spapr: Fix leak of CPU machine specific data
[qemu/ar7.git] / target / mips / translate.c
blobf449758606db2fe81d92c11fd9038408c8b52eb8
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 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg/tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "hw/semihosting/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
41 #include "qemu/qemu-print.h"
43 #define MIPS_DEBUG_DISAS 0
45 /* MIPS major opcodes */
46 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
48 enum {
49 /* indirect opcode tables */
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
58 /* arithmetic with immediate */
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
63 /* logic with immediate */
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
68 /* arithmetic with immediate */
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
71 /* Jump and branches */
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
82 OPC_JALX = (0x1D << 26),
83 OPC_DAUI = (0x1D << 26),
84 /* Load and stores */
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
91 OPC_LWPC = OPC_LW | 0x5,
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
106 OPC_LDPC = OPC_LD | 0x5,
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
110 /* Floating point load/store */
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
148 /* Cache and prefetch */
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
155 /* PC-relative address computation / loads */
156 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
158 enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
172 /* MIPS special opcodes */
173 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
175 enum {
176 /* Shifts */
177 OPC_SLL = 0x00 | OPC_SPECIAL,
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
182 OPC_ROTR = OPC_SRL | (1 << 21),
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
186 OPC_ROTRV = OPC_SRLV | (1 << 6),
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
194 OPC_DROTR = OPC_DSRL | (1 << 21),
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
200 /* Multiplication / division */
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
210 /* 2 registers arithmetic / logic */
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
225 /* Jumps */
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
228 /* Traps */
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
235 /* HI / LO registers load & stores */
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
240 /* Conditional moves */
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
249 /* Special */
250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
266 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
268 enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
297 /* Multiplication variants of the vr54xx. */
298 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
300 enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
317 /* REGIMM (rt field) opcodes */
318 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
320 enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
342 /* Special2 opcodes */
343 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
345 enum {
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
365 /* Misc */
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
370 /* Special */
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
374 /* Special3 opcodes */
375 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
377 enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
391 OPC_GINV = 0x3D | OPC_SPECIAL3,
393 /* Loongson 2E */
394 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
395 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
396 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
397 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
398 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
399 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
400 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
401 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
402 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
403 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
404 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
405 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
407 /* MIPS DSP Load */
408 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
409 /* MIPS DSP Arithmetic */
410 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
411 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
412 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
413 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
414 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
415 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
417 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
418 /* MIPS DSP GPR-Based Shift Sub-class */
419 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
420 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
421 /* MIPS DSP Multiply Sub-class insns */
422 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
423 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
424 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
425 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
426 /* DSP Bit/Manipulation Sub-class */
427 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
428 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
429 /* MIPS DSP Append Sub-class */
430 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
431 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
432 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
433 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
434 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
436 /* EVA */
437 OPC_LWLE = 0x19 | OPC_SPECIAL3,
438 OPC_LWRE = 0x1A | OPC_SPECIAL3,
439 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
440 OPC_SBE = 0x1C | OPC_SPECIAL3,
441 OPC_SHE = 0x1D | OPC_SPECIAL3,
442 OPC_SCE = 0x1E | OPC_SPECIAL3,
443 OPC_SWE = 0x1F | OPC_SPECIAL3,
444 OPC_SWLE = 0x21 | OPC_SPECIAL3,
445 OPC_SWRE = 0x22 | OPC_SPECIAL3,
446 OPC_PREFE = 0x23 | OPC_SPECIAL3,
447 OPC_LBUE = 0x28 | OPC_SPECIAL3,
448 OPC_LHUE = 0x29 | OPC_SPECIAL3,
449 OPC_LBE = 0x2C | OPC_SPECIAL3,
450 OPC_LHE = 0x2D | OPC_SPECIAL3,
451 OPC_LLE = 0x2E | OPC_SPECIAL3,
452 OPC_LWE = 0x2F | OPC_SPECIAL3,
454 /* R6 */
455 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
456 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
457 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
458 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
459 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
460 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
463 /* Loongson EXT load/store quad word opcodes */
464 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
465 enum {
466 OPC_GSLQ = 0x0020 | OPC_LWC2,
467 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
468 OPC_GSSHFL = OPC_LWC2,
469 OPC_GSSQ = 0x0020 | OPC_SWC2,
470 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
471 OPC_GSSHFS = OPC_SWC2,
474 /* Loongson EXT shifted load/store opcodes */
475 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
476 enum {
477 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
478 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
479 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
480 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
481 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
482 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
483 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
484 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
487 /* Loongson EXT LDC2/SDC2 opcodes */
488 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
490 enum {
491 OPC_GSLBX = 0x0 | OPC_LDC2,
492 OPC_GSLHX = 0x1 | OPC_LDC2,
493 OPC_GSLWX = 0x2 | OPC_LDC2,
494 OPC_GSLDX = 0x3 | OPC_LDC2,
495 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
496 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
497 OPC_GSSBX = 0x0 | OPC_SDC2,
498 OPC_GSSHX = 0x1 | OPC_SDC2,
499 OPC_GSSWX = 0x2 | OPC_SDC2,
500 OPC_GSSDX = 0x3 | OPC_SDC2,
501 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
502 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
505 /* BSHFL opcodes */
506 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
508 enum {
509 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
510 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
511 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
512 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
513 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
514 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
515 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
516 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
519 /* DBSHFL opcodes */
520 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
522 enum {
523 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
524 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
525 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
526 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
527 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
528 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
529 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
530 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
531 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
532 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
533 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
536 /* MIPS DSP REGIMM opcodes */
537 enum {
538 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
539 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
542 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
543 /* MIPS DSP Load */
544 enum {
545 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
546 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
547 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
548 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
551 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
552 enum {
553 /* MIPS DSP Arithmetic Sub-class */
554 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
555 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
558 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
559 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
560 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
561 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
562 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
563 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
564 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
565 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
566 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
567 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
568 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
569 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
570 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
571 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
572 /* MIPS DSP Multiply Sub-class insns */
573 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
574 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
575 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
576 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
577 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
578 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
581 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
582 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
589 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
590 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
591 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
592 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
593 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
594 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
595 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
596 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
597 /* MIPS DSP Multiply Sub-class insns */
598 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
599 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
600 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
601 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
604 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
605 enum {
606 /* MIPS DSP Arithmetic Sub-class */
607 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
619 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
620 /* DSP Bit/Manipulation Sub-class */
621 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
622 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
623 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
624 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
625 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
628 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
629 enum {
630 /* MIPS DSP Arithmetic Sub-class */
631 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
638 /* DSP Compare-Pick Sub-class */
639 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
647 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
648 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
649 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
650 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
651 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
652 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
653 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
656 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* MIPS DSP GPR-Based Shift Sub-class */
659 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
674 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
675 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
676 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
677 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
678 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
679 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
680 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
683 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
684 enum {
685 /* MIPS DSP Multiply Sub-class insns */
686 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
696 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
700 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
701 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
702 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
703 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
704 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
705 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
706 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
707 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
710 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
711 enum {
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
716 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
717 enum {
718 /* MIPS DSP Append Sub-class */
719 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
720 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
721 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
724 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
725 enum {
726 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
727 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
732 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
733 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
734 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
735 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
736 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
737 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
738 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
739 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
740 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
741 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
742 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
743 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
746 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
747 enum {
748 /* MIPS DSP Arithmetic Sub-class */
749 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
766 /* DSP Bit/Manipulation Sub-class */
767 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
768 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
769 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
770 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
771 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
772 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
775 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
776 enum {
777 /* MIPS DSP Multiply Sub-class insns */
778 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
779 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
780 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
781 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
782 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
788 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
789 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
790 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
791 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
792 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
793 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
794 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
798 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
799 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
800 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
801 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
802 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
803 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
804 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
807 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
808 enum {
809 /* DSP Compare-Pick Sub-class */
810 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
829 /* MIPS DSP Arithmetic Sub-class */
830 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
831 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
832 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
833 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
834 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
835 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
836 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
837 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
840 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
841 enum {
842 /* DSP Append Sub-class */
843 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
844 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
845 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
846 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
849 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
850 enum {
851 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
852 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
853 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
865 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
866 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
867 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
868 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
869 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
870 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
871 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
872 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
875 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
876 enum {
877 /* DSP Bit/Manipulation Sub-class */
878 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
881 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
882 enum {
883 /* MIPS DSP Multiply Sub-class insns */
884 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
903 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
904 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
905 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
906 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
907 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
908 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
909 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
912 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
913 enum {
914 /* MIPS DSP GPR-Based Shift Sub-class */
915 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
934 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
935 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
936 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
937 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
938 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
939 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
940 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
943 /* Coprocessor 0 (rs field) */
944 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
946 enum {
947 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
948 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
949 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
950 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
951 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
952 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
953 OPC_MFTR = (0x08 << 21) | OPC_CP0,
954 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
955 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
956 OPC_MTTR = (0x0C << 21) | OPC_CP0,
957 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
958 OPC_C0 = (0x10 << 21) | OPC_CP0,
959 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
960 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
961 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
962 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
963 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
964 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
965 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
966 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
967 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
968 OPC_C0_A = (0x1A << 21) | OPC_CP0,
969 OPC_C0_B = (0x1B << 21) | OPC_CP0,
970 OPC_C0_C = (0x1C << 21) | OPC_CP0,
971 OPC_C0_D = (0x1D << 21) | OPC_CP0,
972 OPC_C0_E = (0x1E << 21) | OPC_CP0,
973 OPC_C0_F = (0x1F << 21) | OPC_CP0,
976 /* MFMC0 opcodes */
977 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
979 enum {
980 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
981 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
982 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
983 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
984 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
985 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
986 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
987 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
990 /* Coprocessor 0 (with rs == C0) */
991 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
993 enum {
994 OPC_TLBR = 0x01 | OPC_C0,
995 OPC_TLBWI = 0x02 | OPC_C0,
996 OPC_TLBINV = 0x03 | OPC_C0,
997 OPC_TLBINVF = 0x04 | OPC_C0,
998 OPC_TLBWR = 0x06 | OPC_C0,
999 OPC_TLBP = 0x08 | OPC_C0,
1000 OPC_RFE = 0x10 | OPC_C0,
1001 OPC_ERET = 0x18 | OPC_C0,
1002 OPC_DERET = 0x1F | OPC_C0,
1003 OPC_WAIT = 0x20 | OPC_C0,
1006 /* Coprocessor 1 (rs field) */
1007 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1009 /* Values for the fmt field in FP instructions */
1010 enum {
1011 /* 0 - 15 are reserved */
1012 FMT_S = 16, /* single fp */
1013 FMT_D = 17, /* double fp */
1014 FMT_E = 18, /* extended fp */
1015 FMT_Q = 19, /* quad fp */
1016 FMT_W = 20, /* 32-bit fixed */
1017 FMT_L = 21, /* 64-bit fixed */
1018 FMT_PS = 22, /* paired single fp */
1019 /* 23 - 31 are reserved */
1022 enum {
1023 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
1024 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
1025 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1026 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1027 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
1028 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
1029 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1030 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1031 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1032 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
1033 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1034 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
1035 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
1036 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
1037 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
1038 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
1039 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
1040 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
1041 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1042 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1043 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1044 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1045 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1046 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1047 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1048 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1049 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1050 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1051 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1052 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1055 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1056 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1058 enum {
1059 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1060 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1061 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1062 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1065 enum {
1066 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1067 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1070 enum {
1071 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1072 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1075 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1077 enum {
1078 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1079 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1080 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1081 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1082 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1083 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1084 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1085 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1086 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1087 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1088 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1091 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1093 enum {
1094 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1095 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1096 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1097 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1098 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1099 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1100 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1101 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1103 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1104 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1105 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1106 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1107 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1108 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1109 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1110 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1112 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1113 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1114 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1115 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1116 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1117 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1118 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1119 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1121 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1122 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1123 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1124 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1125 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1126 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1127 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1128 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1130 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1131 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1132 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1133 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1134 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1135 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1137 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1138 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1139 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1140 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1141 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1142 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1144 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1145 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1146 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1147 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1148 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1149 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1151 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1152 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1153 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1154 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1155 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1156 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1158 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1159 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1160 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1161 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1162 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1163 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1165 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1166 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1167 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1168 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1169 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1170 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1172 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1173 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1174 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1175 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1176 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1177 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1179 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1180 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1181 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1182 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1183 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1184 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1188 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1190 enum {
1191 OPC_LWXC1 = 0x00 | OPC_CP3,
1192 OPC_LDXC1 = 0x01 | OPC_CP3,
1193 OPC_LUXC1 = 0x05 | OPC_CP3,
1194 OPC_SWXC1 = 0x08 | OPC_CP3,
1195 OPC_SDXC1 = 0x09 | OPC_CP3,
1196 OPC_SUXC1 = 0x0D | OPC_CP3,
1197 OPC_PREFX = 0x0F | OPC_CP3,
1198 OPC_ALNV_PS = 0x1E | OPC_CP3,
1199 OPC_MADD_S = 0x20 | OPC_CP3,
1200 OPC_MADD_D = 0x21 | OPC_CP3,
1201 OPC_MADD_PS = 0x26 | OPC_CP3,
1202 OPC_MSUB_S = 0x28 | OPC_CP3,
1203 OPC_MSUB_D = 0x29 | OPC_CP3,
1204 OPC_MSUB_PS = 0x2E | OPC_CP3,
1205 OPC_NMADD_S = 0x30 | OPC_CP3,
1206 OPC_NMADD_D = 0x31 | OPC_CP3,
1207 OPC_NMADD_PS = 0x36 | OPC_CP3,
1208 OPC_NMSUB_S = 0x38 | OPC_CP3,
1209 OPC_NMSUB_D = 0x39 | OPC_CP3,
1210 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1213 /* MSA Opcodes */
1214 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1215 enum {
1216 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1217 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1218 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1219 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1220 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1221 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1222 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1223 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1224 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1225 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1226 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1227 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1228 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1229 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1230 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1231 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1232 OPC_MSA_ELM = 0x19 | OPC_MSA,
1233 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1234 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1235 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1236 OPC_MSA_VEC = 0x1E | OPC_MSA,
1238 /* MI10 instruction */
1239 OPC_LD_B = (0x20) | OPC_MSA,
1240 OPC_LD_H = (0x21) | OPC_MSA,
1241 OPC_LD_W = (0x22) | OPC_MSA,
1242 OPC_LD_D = (0x23) | OPC_MSA,
1243 OPC_ST_B = (0x24) | OPC_MSA,
1244 OPC_ST_H = (0x25) | OPC_MSA,
1245 OPC_ST_W = (0x26) | OPC_MSA,
1246 OPC_ST_D = (0x27) | OPC_MSA,
1249 enum {
1250 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1251 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1252 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1253 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1254 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1255 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1256 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1257 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1258 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1259 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1260 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1261 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1262 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1264 /* I8 instruction */
1265 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1266 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1267 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1268 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1269 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1270 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1271 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1272 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1273 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1274 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1276 /* VEC/2R/2RF instruction */
1277 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1278 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1279 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1280 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1281 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1282 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1283 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1285 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1286 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1288 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1289 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1290 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1291 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1292 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1294 /* 2RF instruction df(bit 16) = _w, _d */
1295 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1296 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1297 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1298 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1299 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1300 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1301 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1302 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1303 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1304 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1305 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1306 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1307 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1308 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1309 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1310 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1312 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1313 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1314 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1315 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1316 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1317 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1318 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1319 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1320 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1321 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1322 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1323 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1324 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1325 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1326 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1327 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1328 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1329 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1330 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1331 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1332 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1333 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1334 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1335 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1336 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1337 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1338 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1339 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1340 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1341 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1342 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1343 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1344 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1345 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1346 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1347 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1348 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1349 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1350 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1351 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1352 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1353 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1354 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1355 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1356 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1357 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1358 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1359 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1360 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1361 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1362 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1363 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1364 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1365 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1366 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1367 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1368 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1369 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1370 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1371 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1372 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1373 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1374 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1375 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1377 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1378 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1379 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1380 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1381 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1382 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1383 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1384 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1385 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1386 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1388 /* 3RF instruction _df(bit 21) = _w, _d */
1389 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1390 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1391 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1392 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1393 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1394 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1395 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1396 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1397 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1398 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1399 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1400 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1401 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1402 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1403 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1404 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1405 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1406 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1407 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1408 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1409 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1410 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1411 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1412 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1413 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1414 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1415 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1416 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1417 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1418 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1419 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1420 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1421 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1422 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1423 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1424 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1425 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1426 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1427 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1428 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1429 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1431 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1432 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1433 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1434 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1435 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1436 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1437 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1438 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1439 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1440 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1441 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1442 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1443 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1449 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1450 * ============================================
1453 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1454 * instructions set. It is designed to fit the needs of signal, graphical and
1455 * video processing applications. MXU instruction set is used in Xburst family
1456 * of microprocessors by Ingenic.
1458 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1459 * the control register.
1462 * The notation used in MXU assembler mnemonics
1463 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1465 * Register operands:
1467 * XRa, XRb, XRc, XRd - MXU registers
1468 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1470 * Non-register operands:
1472 * aptn1 - 1-bit accumulate add/subtract pattern
1473 * aptn2 - 2-bit accumulate add/subtract pattern
1474 * eptn2 - 2-bit execute add/subtract pattern
1475 * optn2 - 2-bit operand pattern
1476 * optn3 - 3-bit operand pattern
1477 * sft4 - 4-bit shift amount
1478 * strd2 - 2-bit stride amount
1480 * Prefixes:
1482 * Level of parallelism: Operand size:
1483 * S - single operation at a time 32 - word
1484 * D - two operations in parallel 16 - half word
1485 * Q - four operations in parallel 8 - byte
1487 * Operations:
1489 * ADD - Add or subtract
1490 * ADDC - Add with carry-in
1491 * ACC - Accumulate
1492 * ASUM - Sum together then accumulate (add or subtract)
1493 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1494 * AVG - Average between 2 operands
1495 * ABD - Absolute difference
1496 * ALN - Align data
1497 * AND - Logical bitwise 'and' operation
1498 * CPS - Copy sign
1499 * EXTR - Extract bits
1500 * I2M - Move from GPR register to MXU register
1501 * LDD - Load data from memory to XRF
1502 * LDI - Load data from memory to XRF (and increase the address base)
1503 * LUI - Load unsigned immediate
1504 * MUL - Multiply
1505 * MULU - Unsigned multiply
1506 * MADD - 64-bit operand add 32x32 product
1507 * MSUB - 64-bit operand subtract 32x32 product
1508 * MAC - Multiply and accumulate (add or subtract)
1509 * MAD - Multiply and add or subtract
1510 * MAX - Maximum between 2 operands
1511 * MIN - Minimum between 2 operands
1512 * M2I - Move from MXU register to GPR register
1513 * MOVZ - Move if zero
1514 * MOVN - Move if non-zero
1515 * NOR - Logical bitwise 'nor' operation
1516 * OR - Logical bitwise 'or' operation
1517 * STD - Store data from XRF to memory
1518 * SDI - Store data from XRF to memory (and increase the address base)
1519 * SLT - Set of less than comparison
1520 * SAD - Sum of absolute differences
1521 * SLL - Logical shift left
1522 * SLR - Logical shift right
1523 * SAR - Arithmetic shift right
1524 * SAT - Saturation
1525 * SFL - Shuffle
1526 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1527 * XOR - Logical bitwise 'exclusive or' operation
1529 * Suffixes:
1531 * E - Expand results
1532 * F - Fixed point multiplication
1533 * L - Low part result
1534 * R - Doing rounding
1535 * V - Variable instead of immediate
1536 * W - Combine above L and V
1539 * The list of MXU instructions grouped by functionality
1540 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1542 * Load/Store instructions Multiplication instructions
1543 * ----------------------- ---------------------------
1545 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1546 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1547 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1548 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1549 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1550 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1551 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1552 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1553 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1554 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1555 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1556 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1557 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1558 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1559 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1560 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1561 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1562 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1563 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1564 * S16SDI XRa, Rb, s10, eptn2
1565 * S8LDD XRa, Rb, s8, eptn3
1566 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1567 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1568 * S8SDI XRa, Rb, s8, eptn3
1569 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1570 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1571 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1572 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1573 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1574 * S32CPS XRa, XRb, XRc
1575 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1576 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1577 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1578 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1579 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1580 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1581 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1582 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1583 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1584 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1585 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1586 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1587 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1588 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1589 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1590 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1591 * Q8SLT XRa, XRb, XRc
1592 * Q8SLTU XRa, XRb, XRc
1593 * Q8MOVZ XRa, XRb, XRc Shift instructions
1594 * Q8MOVN XRa, XRb, XRc ------------------
1596 * D32SLL XRa, XRb, XRc, XRd, sft4
1597 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1598 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1599 * D32SARL XRa, XRb, XRc, sft4
1600 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1601 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1602 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1603 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1604 * Q16SLL XRa, XRb, XRc, XRd, sft4
1605 * Q16SLR XRa, XRb, XRc, XRd, sft4
1606 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1607 * ------------------------- Q16SLLV XRa, XRb, Rb
1608 * Q16SLRV XRa, XRb, Rb
1609 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1610 * S32ALN XRa, XRb, XRc, Rb
1611 * S32ALNI XRa, XRb, XRc, s3
1612 * S32LUI XRa, s8, optn3 Move instructions
1613 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1614 * S32EXTRV XRa, XRb, Rs, Rt
1615 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1616 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1619 * The opcode organization of MXU instructions
1620 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1622 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1623 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1624 * other bits up to the instruction level is as follows:
1626 * bits
1627 * 05..00
1629 * ┌─ 000000 ─ OPC_MXU_S32MADD
1630 * ├─ 000001 ─ OPC_MXU_S32MADDU
1631 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1632 * │
1633 * │ 20..18
1634 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1635 * │ ├─ 001 ─ OPC_MXU_S32MIN
1636 * │ ├─ 010 ─ OPC_MXU_D16MAX
1637 * │ ├─ 011 ─ OPC_MXU_D16MIN
1638 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1639 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1640 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1641 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1642 * ├─ 000100 ─ OPC_MXU_S32MSUB
1643 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1644 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1645 * │ ├─ 001 ─ OPC_MXU_D16SLT
1646 * │ ├─ 010 ─ OPC_MXU_D16AVG
1647 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1648 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1649 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1650 * │ └─ 111 ─ OPC_MXU_Q8ADD
1651 * │
1652 * │ 20..18
1653 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1654 * │ ├─ 010 ─ OPC_MXU_D16CPS
1655 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1656 * │ └─ 110 ─ OPC_MXU_Q16SAT
1657 * ├─ 001000 ─ OPC_MXU_D16MUL
1658 * │ 25..24
1659 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1660 * │ └─ 01 ─ OPC_MXU_D16MULE
1661 * ├─ 001010 ─ OPC_MXU_D16MAC
1662 * ├─ 001011 ─ OPC_MXU_D16MACF
1663 * ├─ 001100 ─ OPC_MXU_D16MADL
1664 * ├─ 001101 ─ OPC_MXU_S16MAD
1665 * ├─ 001110 ─ OPC_MXU_Q16ADD
1666 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1667 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1668 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1669 * │
1670 * │ 23
1671 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1672 * │ └─ 1 ─ OPC_MXU_S32STDR
1673 * │
1674 * │ 13..10
1675 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1676 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1677 * │
1678 * │ 13..10
1679 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1680 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1681 * │
1682 * │ 23
1683 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1684 * │ └─ 1 ─ OPC_MXU_S32LDIR
1685 * │
1686 * │ 23
1687 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1688 * │ └─ 1 ─ OPC_MXU_S32SDIR
1689 * │
1690 * │ 13..10
1691 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1692 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1693 * │
1694 * │ 13..10
1695 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1696 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1697 * ├─ 011000 ─ OPC_MXU_D32ADD
1698 * │ 23..22
1699 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1700 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1701 * │ └─ 10 ─ OPC_MXU_D32ASUM
1702 * ├─ 011010 ─ <not assigned>
1703 * │ 23..22
1704 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1705 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1706 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1707 * │
1708 * │ 23..22
1709 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1710 * │ ├─ 01 ─ OPC_MXU_D8SUM
1711 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1712 * ├─ 011110 ─ <not assigned>
1713 * ├─ 011111 ─ <not assigned>
1714 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1715 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1716 * ├─ 100010 ─ OPC_MXU_S8LDD
1717 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1718 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1719 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1720 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1721 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1722 * │
1723 * │ 20..18
1724 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1725 * │ ├─ 001 ─ OPC_MXU_S32ALN
1726 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1727 * │ ├─ 011 ─ OPC_MXU_S32LUI
1728 * │ ├─ 100 ─ OPC_MXU_S32NOR
1729 * │ ├─ 101 ─ OPC_MXU_S32AND
1730 * │ ├─ 110 ─ OPC_MXU_S32OR
1731 * │ └─ 111 ─ OPC_MXU_S32XOR
1732 * │
1733 * │ 7..5
1734 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1735 * │ ├─ 001 ─ OPC_MXU_LXH
1736 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1737 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1738 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1739 * ├─ 101100 ─ OPC_MXU_S16LDI
1740 * ├─ 101101 ─ OPC_MXU_S16SDI
1741 * ├─ 101110 ─ OPC_MXU_S32M2I
1742 * ├─ 101111 ─ OPC_MXU_S32I2M
1743 * ├─ 110000 ─ OPC_MXU_D32SLL
1744 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1745 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1746 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1747 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1748 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1749 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1750 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1751 * │
1752 * ├─ 110111 ─ OPC_MXU_Q16SAR
1753 * │ 23..22
1754 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1755 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1756 * │
1757 * │ 20..18
1758 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1759 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1760 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1761 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1762 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1763 * │ └─ 101 ─ OPC_MXU_S32MOVN
1764 * │
1765 * │ 23..22
1766 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1767 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1768 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1769 * ├─ 111100 ─ OPC_MXU_Q8MADL
1770 * ├─ 111101 ─ OPC_MXU_S32SFL
1771 * ├─ 111110 ─ OPC_MXU_Q8SAD
1772 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1775 * Compiled after:
1777 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1778 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1781 enum {
1782 OPC_MXU_S32MADD = 0x00,
1783 OPC_MXU_S32MADDU = 0x01,
1784 OPC__MXU_MUL = 0x02,
1785 OPC_MXU__POOL00 = 0x03,
1786 OPC_MXU_S32MSUB = 0x04,
1787 OPC_MXU_S32MSUBU = 0x05,
1788 OPC_MXU__POOL01 = 0x06,
1789 OPC_MXU__POOL02 = 0x07,
1790 OPC_MXU_D16MUL = 0x08,
1791 OPC_MXU__POOL03 = 0x09,
1792 OPC_MXU_D16MAC = 0x0A,
1793 OPC_MXU_D16MACF = 0x0B,
1794 OPC_MXU_D16MADL = 0x0C,
1795 OPC_MXU_S16MAD = 0x0D,
1796 OPC_MXU_Q16ADD = 0x0E,
1797 OPC_MXU_D16MACE = 0x0F,
1798 OPC_MXU__POOL04 = 0x10,
1799 OPC_MXU__POOL05 = 0x11,
1800 OPC_MXU__POOL06 = 0x12,
1801 OPC_MXU__POOL07 = 0x13,
1802 OPC_MXU__POOL08 = 0x14,
1803 OPC_MXU__POOL09 = 0x15,
1804 OPC_MXU__POOL10 = 0x16,
1805 OPC_MXU__POOL11 = 0x17,
1806 OPC_MXU_D32ADD = 0x18,
1807 OPC_MXU__POOL12 = 0x19,
1808 /* not assigned 0x1A */
1809 OPC_MXU__POOL13 = 0x1B,
1810 OPC_MXU__POOL14 = 0x1C,
1811 OPC_MXU_Q8ACCE = 0x1D,
1812 /* not assigned 0x1E */
1813 /* not assigned 0x1F */
1814 /* not assigned 0x20 */
1815 /* not assigned 0x21 */
1816 OPC_MXU_S8LDD = 0x22,
1817 OPC_MXU_S8STD = 0x23,
1818 OPC_MXU_S8LDI = 0x24,
1819 OPC_MXU_S8SDI = 0x25,
1820 OPC_MXU__POOL15 = 0x26,
1821 OPC_MXU__POOL16 = 0x27,
1822 OPC_MXU__POOL17 = 0x28,
1823 /* not assigned 0x29 */
1824 OPC_MXU_S16LDD = 0x2A,
1825 OPC_MXU_S16STD = 0x2B,
1826 OPC_MXU_S16LDI = 0x2C,
1827 OPC_MXU_S16SDI = 0x2D,
1828 OPC_MXU_S32M2I = 0x2E,
1829 OPC_MXU_S32I2M = 0x2F,
1830 OPC_MXU_D32SLL = 0x30,
1831 OPC_MXU_D32SLR = 0x31,
1832 OPC_MXU_D32SARL = 0x32,
1833 OPC_MXU_D32SAR = 0x33,
1834 OPC_MXU_Q16SLL = 0x34,
1835 OPC_MXU_Q16SLR = 0x35,
1836 OPC_MXU__POOL18 = 0x36,
1837 OPC_MXU_Q16SAR = 0x37,
1838 OPC_MXU__POOL19 = 0x38,
1839 OPC_MXU__POOL20 = 0x39,
1840 OPC_MXU__POOL21 = 0x3A,
1841 OPC_MXU_Q16SCOP = 0x3B,
1842 OPC_MXU_Q8MADL = 0x3C,
1843 OPC_MXU_S32SFL = 0x3D,
1844 OPC_MXU_Q8SAD = 0x3E,
1845 /* not assigned 0x3F */
1850 * MXU pool 00
1852 enum {
1853 OPC_MXU_S32MAX = 0x00,
1854 OPC_MXU_S32MIN = 0x01,
1855 OPC_MXU_D16MAX = 0x02,
1856 OPC_MXU_D16MIN = 0x03,
1857 OPC_MXU_Q8MAX = 0x04,
1858 OPC_MXU_Q8MIN = 0x05,
1859 OPC_MXU_Q8SLT = 0x06,
1860 OPC_MXU_Q8SLTU = 0x07,
1864 * MXU pool 01
1866 enum {
1867 OPC_MXU_S32SLT = 0x00,
1868 OPC_MXU_D16SLT = 0x01,
1869 OPC_MXU_D16AVG = 0x02,
1870 OPC_MXU_D16AVGR = 0x03,
1871 OPC_MXU_Q8AVG = 0x04,
1872 OPC_MXU_Q8AVGR = 0x05,
1873 OPC_MXU_Q8ADD = 0x07,
1877 * MXU pool 02
1879 enum {
1880 OPC_MXU_S32CPS = 0x00,
1881 OPC_MXU_D16CPS = 0x02,
1882 OPC_MXU_Q8ABD = 0x04,
1883 OPC_MXU_Q16SAT = 0x06,
1887 * MXU pool 03
1889 enum {
1890 OPC_MXU_D16MULF = 0x00,
1891 OPC_MXU_D16MULE = 0x01,
1895 * MXU pool 04
1897 enum {
1898 OPC_MXU_S32LDD = 0x00,
1899 OPC_MXU_S32LDDR = 0x01,
1903 * MXU pool 05
1905 enum {
1906 OPC_MXU_S32STD = 0x00,
1907 OPC_MXU_S32STDR = 0x01,
1911 * MXU pool 06
1913 enum {
1914 OPC_MXU_S32LDDV = 0x00,
1915 OPC_MXU_S32LDDVR = 0x01,
1919 * MXU pool 07
1921 enum {
1922 OPC_MXU_S32STDV = 0x00,
1923 OPC_MXU_S32STDVR = 0x01,
1927 * MXU pool 08
1929 enum {
1930 OPC_MXU_S32LDI = 0x00,
1931 OPC_MXU_S32LDIR = 0x01,
1935 * MXU pool 09
1937 enum {
1938 OPC_MXU_S32SDI = 0x00,
1939 OPC_MXU_S32SDIR = 0x01,
1943 * MXU pool 10
1945 enum {
1946 OPC_MXU_S32LDIV = 0x00,
1947 OPC_MXU_S32LDIVR = 0x01,
1951 * MXU pool 11
1953 enum {
1954 OPC_MXU_S32SDIV = 0x00,
1955 OPC_MXU_S32SDIVR = 0x01,
1959 * MXU pool 12
1961 enum {
1962 OPC_MXU_D32ACC = 0x00,
1963 OPC_MXU_D32ACCM = 0x01,
1964 OPC_MXU_D32ASUM = 0x02,
1968 * MXU pool 13
1970 enum {
1971 OPC_MXU_Q16ACC = 0x00,
1972 OPC_MXU_Q16ACCM = 0x01,
1973 OPC_MXU_Q16ASUM = 0x02,
1977 * MXU pool 14
1979 enum {
1980 OPC_MXU_Q8ADDE = 0x00,
1981 OPC_MXU_D8SUM = 0x01,
1982 OPC_MXU_D8SUMC = 0x02,
1986 * MXU pool 15
1988 enum {
1989 OPC_MXU_S32MUL = 0x00,
1990 OPC_MXU_S32MULU = 0x01,
1991 OPC_MXU_S32EXTR = 0x02,
1992 OPC_MXU_S32EXTRV = 0x03,
1996 * MXU pool 16
1998 enum {
1999 OPC_MXU_D32SARW = 0x00,
2000 OPC_MXU_S32ALN = 0x01,
2001 OPC_MXU_S32ALNI = 0x02,
2002 OPC_MXU_S32LUI = 0x03,
2003 OPC_MXU_S32NOR = 0x04,
2004 OPC_MXU_S32AND = 0x05,
2005 OPC_MXU_S32OR = 0x06,
2006 OPC_MXU_S32XOR = 0x07,
2010 * MXU pool 17
2012 enum {
2013 OPC_MXU_LXB = 0x00,
2014 OPC_MXU_LXH = 0x01,
2015 OPC_MXU_LXW = 0x03,
2016 OPC_MXU_LXBU = 0x04,
2017 OPC_MXU_LXHU = 0x05,
2021 * MXU pool 18
2023 enum {
2024 OPC_MXU_D32SLLV = 0x00,
2025 OPC_MXU_D32SLRV = 0x01,
2026 OPC_MXU_D32SARV = 0x03,
2027 OPC_MXU_Q16SLLV = 0x04,
2028 OPC_MXU_Q16SLRV = 0x05,
2029 OPC_MXU_Q16SARV = 0x07,
2033 * MXU pool 19
2035 enum {
2036 OPC_MXU_Q8MUL = 0x00,
2037 OPC_MXU_Q8MULSU = 0x01,
2041 * MXU pool 20
2043 enum {
2044 OPC_MXU_Q8MOVZ = 0x00,
2045 OPC_MXU_Q8MOVN = 0x01,
2046 OPC_MXU_D16MOVZ = 0x02,
2047 OPC_MXU_D16MOVN = 0x03,
2048 OPC_MXU_S32MOVZ = 0x04,
2049 OPC_MXU_S32MOVN = 0x05,
2053 * MXU pool 21
2055 enum {
2056 OPC_MXU_Q8MAC = 0x00,
2057 OPC_MXU_Q8MACSU = 0x01,
2061 * Overview of the TX79-specific instruction set
2062 * =============================================
2064 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2065 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2066 * instructions and certain multimedia instructions (MMIs). These MMIs
2067 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2068 * or sixteen 8-bit paths.
2070 * Reference:
2072 * The Toshiba TX System RISC TX79 Core Architecture manual,
2073 * https://wiki.qemu.org/File:C790.pdf
2075 * Three-Operand Multiply and Multiply-Add (4 instructions)
2076 * --------------------------------------------------------
2077 * MADD [rd,] rs, rt Multiply/Add
2078 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2079 * MULT [rd,] rs, rt Multiply (3-operand)
2080 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2082 * Multiply Instructions for Pipeline 1 (10 instructions)
2083 * ------------------------------------------------------
2084 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2085 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2086 * DIV1 rs, rt Divide Pipeline 1
2087 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2088 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2089 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2090 * MFHI1 rd Move From HI1 Register
2091 * MFLO1 rd Move From LO1 Register
2092 * MTHI1 rs Move To HI1 Register
2093 * MTLO1 rs Move To LO1 Register
2095 * Arithmetic (19 instructions)
2096 * ----------------------------
2097 * PADDB rd, rs, rt Parallel Add Byte
2098 * PSUBB rd, rs, rt Parallel Subtract Byte
2099 * PADDH rd, rs, rt Parallel Add Halfword
2100 * PSUBH rd, rs, rt Parallel Subtract Halfword
2101 * PADDW rd, rs, rt Parallel Add Word
2102 * PSUBW rd, rs, rt Parallel Subtract Word
2103 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2104 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2105 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2106 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2107 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2108 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2109 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2110 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2111 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2112 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2113 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2114 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2115 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2117 * Min/Max (4 instructions)
2118 * ------------------------
2119 * PMAXH rd, rs, rt Parallel Maximum Halfword
2120 * PMINH rd, rs, rt Parallel Minimum Halfword
2121 * PMAXW rd, rs, rt Parallel Maximum Word
2122 * PMINW rd, rs, rt Parallel Minimum Word
2124 * Absolute (2 instructions)
2125 * -------------------------
2126 * PABSH rd, rt Parallel Absolute Halfword
2127 * PABSW rd, rt Parallel Absolute Word
2129 * Logical (4 instructions)
2130 * ------------------------
2131 * PAND rd, rs, rt Parallel AND
2132 * POR rd, rs, rt Parallel OR
2133 * PXOR rd, rs, rt Parallel XOR
2134 * PNOR rd, rs, rt Parallel NOR
2136 * Shift (9 instructions)
2137 * ----------------------
2138 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2139 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2140 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2141 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2142 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2143 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2144 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2145 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2146 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2148 * Compare (6 instructions)
2149 * ------------------------
2150 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2151 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2152 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2153 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2154 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2155 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2157 * LZC (1 instruction)
2158 * -------------------
2159 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2161 * Quadword Load and Store (2 instructions)
2162 * ----------------------------------------
2163 * LQ rt, offset(base) Load Quadword
2164 * SQ rt, offset(base) Store Quadword
2166 * Multiply and Divide (19 instructions)
2167 * -------------------------------------
2168 * PMULTW rd, rs, rt Parallel Multiply Word
2169 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2170 * PDIVW rs, rt Parallel Divide Word
2171 * PDIVUW rs, rt Parallel Divide Unsigned Word
2172 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2173 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2174 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2175 * PMULTH rd, rs, rt Parallel Multiply Halfword
2176 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2177 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2178 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2179 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2180 * PDIVBW rs, rt Parallel Divide Broadcast Word
2181 * PMFHI rd Parallel Move From HI Register
2182 * PMFLO rd Parallel Move From LO Register
2183 * PMTHI rs Parallel Move To HI Register
2184 * PMTLO rs Parallel Move To LO Register
2185 * PMFHL rd Parallel Move From HI/LO Register
2186 * PMTHL rs Parallel Move To HI/LO Register
2188 * Pack/Extend (11 instructions)
2189 * -----------------------------
2190 * PPAC5 rd, rt Parallel Pack to 5 bits
2191 * PPACB rd, rs, rt Parallel Pack to Byte
2192 * PPACH rd, rs, rt Parallel Pack to Halfword
2193 * PPACW rd, rs, rt Parallel Pack to Word
2194 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2195 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2196 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2197 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2198 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2199 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2200 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2202 * Others (16 instructions)
2203 * ------------------------
2204 * PCPYH rd, rt Parallel Copy Halfword
2205 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2206 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2207 * PREVH rd, rt Parallel Reverse Halfword
2208 * PINTH rd, rs, rt Parallel Interleave Halfword
2209 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2210 * PEXEH rd, rt Parallel Exchange Even Halfword
2211 * PEXCH rd, rt Parallel Exchange Center Halfword
2212 * PEXEW rd, rt Parallel Exchange Even Word
2213 * PEXCW rd, rt Parallel Exchange Center Word
2214 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2215 * MFSA rd Move from Shift Amount Register
2216 * MTSA rs Move to Shift Amount Register
2217 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2218 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2219 * PROT3W rd, rt Parallel Rotate 3 Words
2221 * MMI (MultiMedia Instruction) encodings
2222 * ======================================
2224 * MMI instructions encoding table keys:
2226 * * This code is reserved for future use. An attempt to execute it
2227 * causes a Reserved Instruction exception.
2228 * % This code indicates an instruction class. The instruction word
2229 * must be further decoded by examining additional tables that show
2230 * the values for other instruction fields.
2231 * # This code is reserved for the unsupported instructions DMULT,
2232 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2233 * to execute it causes a Reserved Instruction exception.
2235 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2237 * 31 26 0
2238 * +--------+----------------------------------------+
2239 * | opcode | |
2240 * +--------+----------------------------------------+
2242 * opcode bits 28..26
2243 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2244 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2245 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2246 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2247 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2248 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2249 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2250 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2251 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2252 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2253 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2256 enum {
2257 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2258 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2259 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2263 * MMI instructions with opcode field = MMI:
2265 * 31 26 5 0
2266 * +--------+-------------------------------+--------+
2267 * | MMI | |function|
2268 * +--------+-------------------------------+--------+
2270 * function bits 2..0
2271 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2272 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2273 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2274 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2275 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2276 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2277 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2278 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2279 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2280 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2281 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2284 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2285 enum {
2286 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2287 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2288 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2289 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2290 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2291 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2292 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2293 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2294 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2295 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2296 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2297 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2298 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2299 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2300 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2301 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2302 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2303 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2304 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2305 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2306 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2307 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2308 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2309 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2310 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2314 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2316 * 31 26 10 6 5 0
2317 * +--------+----------------------+--------+--------+
2318 * | MMI | |function| MMI0 |
2319 * +--------+----------------------+--------+--------+
2321 * function bits 7..6
2322 * bits | 0 | 1 | 2 | 3
2323 * 10..8 | 00 | 01 | 10 | 11
2324 * -------+-------+-------+-------+-------
2325 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2326 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2327 * 2 010 | PADDB | PSUBB | PCGTB | *
2328 * 3 011 | * | * | * | *
2329 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2330 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2331 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2332 * 7 111 | * | * | PEXT5 | PPAC5
2335 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2336 enum {
2337 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2338 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2339 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2340 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2341 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2342 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2343 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2344 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2345 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2346 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2347 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2348 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2349 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2350 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2351 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2352 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2353 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2354 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2355 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2356 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2357 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2358 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2359 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2360 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2361 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2365 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2367 * 31 26 10 6 5 0
2368 * +--------+----------------------+--------+--------+
2369 * | MMI | |function| MMI1 |
2370 * +--------+----------------------+--------+--------+
2372 * function bits 7..6
2373 * bits | 0 | 1 | 2 | 3
2374 * 10..8 | 00 | 01 | 10 | 11
2375 * -------+-------+-------+-------+-------
2376 * 0 000 | * | PABSW | PCEQW | PMINW
2377 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2378 * 2 010 | * | * | PCEQB | *
2379 * 3 011 | * | * | * | *
2380 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2381 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2382 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2383 * 7 111 | * | * | * | *
2386 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2387 enum {
2388 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2389 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2390 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2391 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2392 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2393 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2394 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2395 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2396 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2397 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2398 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2399 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2400 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2401 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2402 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2403 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2404 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2405 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2409 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2411 * 31 26 10 6 5 0
2412 * +--------+----------------------+--------+--------+
2413 * | MMI | |function| MMI2 |
2414 * +--------+----------------------+--------+--------+
2416 * function bits 7..6
2417 * bits | 0 | 1 | 2 | 3
2418 * 10..8 | 00 | 01 | 10 | 11
2419 * -------+-------+-------+-------+-------
2420 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2421 * 1 001 | PMSUBW| * | * | *
2422 * 2 010 | PMFHI | PMFLO | PINTH | *
2423 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2424 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2425 * 5 101 | PMSUBH| PHMSBH| * | *
2426 * 6 110 | * | * | PEXEH | PREVH
2427 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2430 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2431 enum {
2432 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2433 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2434 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2435 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2436 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2437 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2438 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2439 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2440 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2441 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2442 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2443 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2444 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2445 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2446 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2447 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2448 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2449 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2450 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2451 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2452 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2453 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2457 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2459 * 31 26 10 6 5 0
2460 * +--------+----------------------+--------+--------+
2461 * | MMI | |function| MMI3 |
2462 * +--------+----------------------+--------+--------+
2464 * function bits 7..6
2465 * bits | 0 | 1 | 2 | 3
2466 * 10..8 | 00 | 01 | 10 | 11
2467 * -------+-------+-------+-------+-------
2468 * 0 000 |PMADDUW| * | * | PSRAVW
2469 * 1 001 | * | * | * | *
2470 * 2 010 | PMTHI | PMTLO | PINTEH| *
2471 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2472 * 4 100 | * | * | POR | PNOR
2473 * 5 101 | * | * | * | *
2474 * 6 110 | * | * | PEXCH | PCPYH
2475 * 7 111 | * | * | PEXCW | *
2478 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2479 enum {
2480 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2481 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2482 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2483 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2484 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2485 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2486 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2487 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2488 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2489 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2490 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2491 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2492 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2495 /* global register indices */
2496 static TCGv cpu_gpr[32], cpu_PC;
2497 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2498 static TCGv cpu_dspctrl, btarget, bcond;
2499 static TCGv cpu_lladdr, cpu_llval;
2500 static TCGv_i32 hflags;
2501 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2502 static TCGv_i64 fpu_f64[32];
2503 static TCGv_i64 msa_wr_d[64];
2505 #if defined(TARGET_MIPS64)
2506 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2507 static TCGv_i64 cpu_mmr[32];
2508 #endif
2510 #if !defined(TARGET_MIPS64)
2511 /* MXU registers */
2512 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2513 static TCGv mxu_CR;
2514 #endif
2516 #include "exec/gen-icount.h"
2518 #define gen_helper_0e0i(name, arg) do { \
2519 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2520 gen_helper_##name(cpu_env, helper_tmp); \
2521 tcg_temp_free_i32(helper_tmp); \
2522 } while (0)
2524 #define gen_helper_0e1i(name, arg1, arg2) do { \
2525 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2526 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2527 tcg_temp_free_i32(helper_tmp); \
2528 } while (0)
2530 #define gen_helper_1e0i(name, ret, arg1) do { \
2531 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2532 gen_helper_##name(ret, cpu_env, helper_tmp); \
2533 tcg_temp_free_i32(helper_tmp); \
2534 } while (0)
2536 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2537 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2538 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2539 tcg_temp_free_i32(helper_tmp); \
2540 } while (0)
2542 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2543 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2544 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2545 tcg_temp_free_i32(helper_tmp); \
2546 } while (0)
2548 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2549 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2550 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2551 tcg_temp_free_i32(helper_tmp); \
2552 } while (0)
2554 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2555 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2556 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2557 tcg_temp_free_i32(helper_tmp); \
2558 } while (0)
2560 typedef struct DisasContext {
2561 DisasContextBase base;
2562 target_ulong saved_pc;
2563 target_ulong page_start;
2564 uint32_t opcode;
2565 uint64_t insn_flags;
2566 int32_t CP0_Config1;
2567 int32_t CP0_Config2;
2568 int32_t CP0_Config3;
2569 int32_t CP0_Config5;
2570 /* Routine used to access memory */
2571 int mem_idx;
2572 MemOp default_tcg_memop_mask;
2573 uint32_t hflags, saved_hflags;
2574 target_ulong btarget;
2575 bool ulri;
2576 int kscrexist;
2577 bool rxi;
2578 int ie;
2579 bool bi;
2580 bool bp;
2581 uint64_t PAMask;
2582 bool mvh;
2583 bool eva;
2584 bool sc;
2585 int CP0_LLAddr_shift;
2586 bool ps;
2587 bool vp;
2588 bool cmgcr;
2589 bool mrp;
2590 bool nan2008;
2591 bool abs2008;
2592 bool saar;
2593 bool mi;
2594 int gi;
2595 } DisasContext;
2597 #define DISAS_STOP DISAS_TARGET_0
2598 #define DISAS_EXIT DISAS_TARGET_1
2600 static const char * const regnames[] = {
2601 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2602 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2603 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2604 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2607 static const char * const regnames_HI[] = {
2608 "HI0", "HI1", "HI2", "HI3",
2611 static const char * const regnames_LO[] = {
2612 "LO0", "LO1", "LO2", "LO3",
2615 static const char * const fregnames[] = {
2616 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2617 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2618 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2619 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2622 static const char * const msaregnames[] = {
2623 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2624 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2625 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2626 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2627 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2628 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2629 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2630 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2631 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2632 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2633 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2634 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2635 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2636 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2637 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2638 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2641 #if !defined(TARGET_MIPS64)
2642 static const char * const mxuregnames[] = {
2643 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2644 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2646 #endif
2648 #define LOG_DISAS(...) \
2649 do { \
2650 if (MIPS_DEBUG_DISAS) { \
2651 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2653 } while (0)
2655 #define MIPS_INVAL(op) \
2656 do { \
2657 if (MIPS_DEBUG_DISAS) { \
2658 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2659 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2660 ctx->base.pc_next, ctx->opcode, op, \
2661 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2662 ((ctx->opcode >> 16) & 0x1F)); \
2664 } while (0)
2666 /* General purpose registers moves. */
2667 static inline void gen_load_gpr(TCGv t, int reg)
2669 if (reg == 0) {
2670 tcg_gen_movi_tl(t, 0);
2671 } else {
2672 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2676 static inline void gen_store_gpr(TCGv t, int reg)
2678 if (reg != 0) {
2679 tcg_gen_mov_tl(cpu_gpr[reg], t);
2683 /* Moves to/from shadow registers. */
2684 static inline void gen_load_srsgpr(int from, int to)
2686 TCGv t0 = tcg_temp_new();
2688 if (from == 0) {
2689 tcg_gen_movi_tl(t0, 0);
2690 } else {
2691 TCGv_i32 t2 = tcg_temp_new_i32();
2692 TCGv_ptr addr = tcg_temp_new_ptr();
2694 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2695 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2696 tcg_gen_andi_i32(t2, t2, 0xf);
2697 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2698 tcg_gen_ext_i32_ptr(addr, t2);
2699 tcg_gen_add_ptr(addr, cpu_env, addr);
2701 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2702 tcg_temp_free_ptr(addr);
2703 tcg_temp_free_i32(t2);
2705 gen_store_gpr(t0, to);
2706 tcg_temp_free(t0);
2709 static inline void gen_store_srsgpr(int from, int to)
2711 if (to != 0) {
2712 TCGv t0 = tcg_temp_new();
2713 TCGv_i32 t2 = tcg_temp_new_i32();
2714 TCGv_ptr addr = tcg_temp_new_ptr();
2716 gen_load_gpr(t0, from);
2717 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2718 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2719 tcg_gen_andi_i32(t2, t2, 0xf);
2720 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2721 tcg_gen_ext_i32_ptr(addr, t2);
2722 tcg_gen_add_ptr(addr, cpu_env, addr);
2724 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2725 tcg_temp_free_ptr(addr);
2726 tcg_temp_free_i32(t2);
2727 tcg_temp_free(t0);
2731 #if !defined(TARGET_MIPS64)
2732 /* MXU General purpose registers moves. */
2733 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2735 if (reg == 0) {
2736 tcg_gen_movi_tl(t, 0);
2737 } else if (reg <= 15) {
2738 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2742 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2744 if (reg > 0 && reg <= 15) {
2745 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2749 /* MXU control register moves. */
2750 static inline void gen_load_mxu_cr(TCGv t)
2752 tcg_gen_mov_tl(t, mxu_CR);
2755 static inline void gen_store_mxu_cr(TCGv t)
2757 /* TODO: Add handling of RW rules for MXU_CR. */
2758 tcg_gen_mov_tl(mxu_CR, t);
2760 #endif
2763 /* Tests */
2764 static inline void gen_save_pc(target_ulong pc)
2766 tcg_gen_movi_tl(cpu_PC, pc);
2769 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2771 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2772 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2773 gen_save_pc(ctx->base.pc_next);
2774 ctx->saved_pc = ctx->base.pc_next;
2776 if (ctx->hflags != ctx->saved_hflags) {
2777 tcg_gen_movi_i32(hflags, ctx->hflags);
2778 ctx->saved_hflags = ctx->hflags;
2779 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2780 case MIPS_HFLAG_BR:
2781 break;
2782 case MIPS_HFLAG_BC:
2783 case MIPS_HFLAG_BL:
2784 case MIPS_HFLAG_B:
2785 tcg_gen_movi_tl(btarget, ctx->btarget);
2786 break;
2791 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2793 ctx->saved_hflags = ctx->hflags;
2794 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2795 case MIPS_HFLAG_BR:
2796 break;
2797 case MIPS_HFLAG_BC:
2798 case MIPS_HFLAG_BL:
2799 case MIPS_HFLAG_B:
2800 ctx->btarget = env->btarget;
2801 break;
2805 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2807 TCGv_i32 texcp = tcg_const_i32(excp);
2808 TCGv_i32 terr = tcg_const_i32(err);
2809 save_cpu_state(ctx, 1);
2810 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2811 tcg_temp_free_i32(terr);
2812 tcg_temp_free_i32(texcp);
2813 ctx->base.is_jmp = DISAS_NORETURN;
2816 static inline void generate_exception(DisasContext *ctx, int excp)
2818 gen_helper_0e0i(raise_exception, excp);
2821 static inline void generate_exception_end(DisasContext *ctx, int excp)
2823 generate_exception_err(ctx, excp, 0);
2826 /* Floating point register moves. */
2827 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2829 if (ctx->hflags & MIPS_HFLAG_FRE) {
2830 generate_exception(ctx, EXCP_RI);
2832 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2835 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2837 TCGv_i64 t64;
2838 if (ctx->hflags & MIPS_HFLAG_FRE) {
2839 generate_exception(ctx, EXCP_RI);
2841 t64 = tcg_temp_new_i64();
2842 tcg_gen_extu_i32_i64(t64, t);
2843 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2844 tcg_temp_free_i64(t64);
2847 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2849 if (ctx->hflags & MIPS_HFLAG_F64) {
2850 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2851 } else {
2852 gen_load_fpr32(ctx, t, reg | 1);
2856 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2858 if (ctx->hflags & MIPS_HFLAG_F64) {
2859 TCGv_i64 t64 = tcg_temp_new_i64();
2860 tcg_gen_extu_i32_i64(t64, t);
2861 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2862 tcg_temp_free_i64(t64);
2863 } else {
2864 gen_store_fpr32(ctx, t, reg | 1);
2868 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2870 if (ctx->hflags & MIPS_HFLAG_F64) {
2871 tcg_gen_mov_i64(t, fpu_f64[reg]);
2872 } else {
2873 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2877 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2879 if (ctx->hflags & MIPS_HFLAG_F64) {
2880 tcg_gen_mov_i64(fpu_f64[reg], t);
2881 } else {
2882 TCGv_i64 t0;
2883 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2884 t0 = tcg_temp_new_i64();
2885 tcg_gen_shri_i64(t0, t, 32);
2886 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2887 tcg_temp_free_i64(t0);
2891 static inline int get_fp_bit(int cc)
2893 if (cc) {
2894 return 24 + cc;
2895 } else {
2896 return 23;
2900 /* Addresses computation */
2901 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2902 TCGv arg1)
2904 tcg_gen_add_tl(ret, arg0, arg1);
2906 #if defined(TARGET_MIPS64)
2907 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2908 tcg_gen_ext32s_i64(ret, ret);
2910 #endif
2913 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2914 target_long ofs)
2916 tcg_gen_addi_tl(ret, base, ofs);
2918 #if defined(TARGET_MIPS64)
2919 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2920 tcg_gen_ext32s_i64(ret, ret);
2922 #endif
2925 /* Addresses computation (translation time) */
2926 static target_long addr_add(DisasContext *ctx, target_long base,
2927 target_long offset)
2929 target_long sum = base + offset;
2931 #if defined(TARGET_MIPS64)
2932 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2933 sum = (int32_t)sum;
2935 #endif
2936 return sum;
2939 /* Sign-extract the low 32-bits to a target_long. */
2940 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2942 #if defined(TARGET_MIPS64)
2943 tcg_gen_ext32s_i64(ret, arg);
2944 #else
2945 tcg_gen_extrl_i64_i32(ret, arg);
2946 #endif
2949 /* Sign-extract the high 32-bits to a target_long. */
2950 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2952 #if defined(TARGET_MIPS64)
2953 tcg_gen_sari_i64(ret, arg, 32);
2954 #else
2955 tcg_gen_extrh_i64_i32(ret, arg);
2956 #endif
2959 static inline void check_cp0_enabled(DisasContext *ctx)
2961 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2962 generate_exception_err(ctx, EXCP_CpU, 0);
2966 static inline void check_cp1_enabled(DisasContext *ctx)
2968 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2969 generate_exception_err(ctx, EXCP_CpU, 1);
2974 * Verify that the processor is running with COP1X instructions enabled.
2975 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2976 * opcode tables.
2978 static inline void check_cop1x(DisasContext *ctx)
2980 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2981 generate_exception_end(ctx, EXCP_RI);
2986 * Verify that the processor is running with 64-bit floating-point
2987 * operations enabled.
2989 static inline void check_cp1_64bitmode(DisasContext *ctx)
2991 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2992 generate_exception_end(ctx, EXCP_RI);
2997 * Verify if floating point register is valid; an operation is not defined
2998 * if bit 0 of any register specification is set and the FR bit in the
2999 * Status register equals zero, since the register numbers specify an
3000 * even-odd pair of adjacent coprocessor general registers. When the FR bit
3001 * in the Status register equals one, both even and odd register numbers
3002 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
3004 * Multiple 64 bit wide registers can be checked by calling
3005 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
3007 static inline void check_cp1_registers(DisasContext *ctx, int regs)
3009 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
3010 generate_exception_end(ctx, EXCP_RI);
3015 * Verify that the processor is running with DSP instructions enabled.
3016 * This is enabled by CP0 Status register MX(24) bit.
3018 static inline void check_dsp(DisasContext *ctx)
3020 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
3021 if (ctx->insn_flags & ASE_DSP) {
3022 generate_exception_end(ctx, EXCP_DSPDIS);
3023 } else {
3024 generate_exception_end(ctx, EXCP_RI);
3029 static inline void check_dsp_r2(DisasContext *ctx)
3031 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
3032 if (ctx->insn_flags & ASE_DSP) {
3033 generate_exception_end(ctx, EXCP_DSPDIS);
3034 } else {
3035 generate_exception_end(ctx, EXCP_RI);
3040 static inline void check_dsp_r3(DisasContext *ctx)
3042 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
3043 if (ctx->insn_flags & ASE_DSP) {
3044 generate_exception_end(ctx, EXCP_DSPDIS);
3045 } else {
3046 generate_exception_end(ctx, EXCP_RI);
3052 * This code generates a "reserved instruction" exception if the
3053 * CPU does not support the instruction set corresponding to flags.
3055 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3057 if (unlikely(!(ctx->insn_flags & flags))) {
3058 generate_exception_end(ctx, EXCP_RI);
3063 * This code generates a "reserved instruction" exception if the
3064 * CPU has corresponding flag set which indicates that the instruction
3065 * has been removed.
3067 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3069 if (unlikely(ctx->insn_flags & flags)) {
3070 generate_exception_end(ctx, EXCP_RI);
3075 * The Linux kernel traps certain reserved instruction exceptions to
3076 * emulate the corresponding instructions. QEMU is the kernel in user
3077 * mode, so those traps are emulated by accepting the instructions.
3079 * A reserved instruction exception is generated for flagged CPUs if
3080 * QEMU runs in system mode.
3082 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3084 #ifndef CONFIG_USER_ONLY
3085 check_insn_opc_removed(ctx, flags);
3086 #endif
3090 * This code generates a "reserved instruction" exception if the
3091 * CPU does not support 64-bit paired-single (PS) floating point data type.
3093 static inline void check_ps(DisasContext *ctx)
3095 if (unlikely(!ctx->ps)) {
3096 generate_exception(ctx, EXCP_RI);
3098 check_cp1_64bitmode(ctx);
3101 #ifdef TARGET_MIPS64
3103 * This code generates a "reserved instruction" exception if 64-bit
3104 * instructions are not enabled.
3106 static inline void check_mips_64(DisasContext *ctx)
3108 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3109 generate_exception_end(ctx, EXCP_RI);
3112 #endif
3114 #ifndef CONFIG_USER_ONLY
3115 static inline void check_mvh(DisasContext *ctx)
3117 if (unlikely(!ctx->mvh)) {
3118 generate_exception(ctx, EXCP_RI);
3121 #endif
3124 * This code generates a "reserved instruction" exception if the
3125 * Config5 XNP bit is set.
3127 static inline void check_xnp(DisasContext *ctx)
3129 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3130 generate_exception_end(ctx, EXCP_RI);
3134 #ifndef CONFIG_USER_ONLY
3136 * This code generates a "reserved instruction" exception if the
3137 * Config3 PW bit is NOT set.
3139 static inline void check_pw(DisasContext *ctx)
3141 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3142 generate_exception_end(ctx, EXCP_RI);
3145 #endif
3148 * This code generates a "reserved instruction" exception if the
3149 * Config3 MT bit is NOT set.
3151 static inline void check_mt(DisasContext *ctx)
3153 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3154 generate_exception_end(ctx, EXCP_RI);
3158 #ifndef CONFIG_USER_ONLY
3160 * This code generates a "coprocessor unusable" exception if CP0 is not
3161 * available, and, if that is not the case, generates a "reserved instruction"
3162 * exception if the Config5 MT bit is NOT set. This is needed for availability
3163 * control of some of MT ASE instructions.
3165 static inline void check_cp0_mt(DisasContext *ctx)
3167 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3168 generate_exception_err(ctx, EXCP_CpU, 0);
3169 } else {
3170 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3171 generate_exception_err(ctx, EXCP_RI, 0);
3175 #endif
3178 * This code generates a "reserved instruction" exception if the
3179 * Config5 NMS bit is set.
3181 static inline void check_nms(DisasContext *ctx)
3183 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3184 generate_exception_end(ctx, EXCP_RI);
3189 * This code generates a "reserved instruction" exception if the
3190 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3191 * Config2 TL, and Config5 L2C are unset.
3193 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3195 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3196 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3197 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3198 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3199 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3200 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3201 generate_exception_end(ctx, EXCP_RI);
3206 * This code generates a "reserved instruction" exception if the
3207 * Config5 EVA bit is NOT set.
3209 static inline void check_eva(DisasContext *ctx)
3211 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3212 generate_exception_end(ctx, EXCP_RI);
3218 * Define small wrappers for gen_load_fpr* so that we have a uniform
3219 * calling interface for 32 and 64-bit FPRs. No sense in changing
3220 * all callers for gen_load_fpr32 when we need the CTX parameter for
3221 * this one use.
3223 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3224 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3225 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3226 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3227 int ft, int fs, int cc) \
3229 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3230 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3231 switch (ifmt) { \
3232 case FMT_PS: \
3233 check_ps(ctx); \
3234 break; \
3235 case FMT_D: \
3236 if (abs) { \
3237 check_cop1x(ctx); \
3239 check_cp1_registers(ctx, fs | ft); \
3240 break; \
3241 case FMT_S: \
3242 if (abs) { \
3243 check_cop1x(ctx); \
3245 break; \
3247 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3248 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3249 switch (n) { \
3250 case 0: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3252 break; \
3253 case 1: \
3254 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3255 break; \
3256 case 2: \
3257 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3258 break; \
3259 case 3: \
3260 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3261 break; \
3262 case 4: \
3263 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3264 break; \
3265 case 5: \
3266 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3267 break; \
3268 case 6: \
3269 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3270 break; \
3271 case 7: \
3272 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3273 break; \
3274 case 8: \
3275 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3276 break; \
3277 case 9: \
3278 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3279 break; \
3280 case 10: \
3281 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3282 break; \
3283 case 11: \
3284 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3285 break; \
3286 case 12: \
3287 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3288 break; \
3289 case 13: \
3290 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3291 break; \
3292 case 14: \
3293 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3294 break; \
3295 case 15: \
3296 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3297 break; \
3298 default: \
3299 abort(); \
3301 tcg_temp_free_i##bits(fp0); \
3302 tcg_temp_free_i##bits(fp1); \
3305 FOP_CONDS(, 0, d, FMT_D, 64)
3306 FOP_CONDS(abs, 1, d, FMT_D, 64)
3307 FOP_CONDS(, 0, s, FMT_S, 32)
3308 FOP_CONDS(abs, 1, s, FMT_S, 32)
3309 FOP_CONDS(, 0, ps, FMT_PS, 64)
3310 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3311 #undef FOP_CONDS
3313 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3314 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3315 int ft, int fs, int fd) \
3317 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3318 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3319 if (ifmt == FMT_D) { \
3320 check_cp1_registers(ctx, fs | ft | fd); \
3322 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3323 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3324 switch (n) { \
3325 case 0: \
3326 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 1: \
3329 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 2: \
3332 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 3: \
3335 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 4: \
3338 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 5: \
3341 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 6: \
3344 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 case 7: \
3347 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3348 break; \
3349 case 8: \
3350 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3351 break; \
3352 case 9: \
3353 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3354 break; \
3355 case 10: \
3356 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3357 break; \
3358 case 11: \
3359 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3360 break; \
3361 case 12: \
3362 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3363 break; \
3364 case 13: \
3365 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3366 break; \
3367 case 14: \
3368 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3369 break; \
3370 case 15: \
3371 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3372 break; \
3373 case 17: \
3374 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3375 break; \
3376 case 18: \
3377 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3378 break; \
3379 case 19: \
3380 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3381 break; \
3382 case 25: \
3383 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3384 break; \
3385 case 26: \
3386 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3387 break; \
3388 case 27: \
3389 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3390 break; \
3391 default: \
3392 abort(); \
3394 STORE; \
3395 tcg_temp_free_i ## bits(fp0); \
3396 tcg_temp_free_i ## bits(fp1); \
3399 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3400 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3401 #undef FOP_CONDNS
3402 #undef gen_ldcmp_fpr32
3403 #undef gen_ldcmp_fpr64
3405 /* load/store instructions. */
3406 #ifdef CONFIG_USER_ONLY
3407 #define OP_LD_ATOMIC(insn, fname) \
3408 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3409 DisasContext *ctx) \
3411 TCGv t0 = tcg_temp_new(); \
3412 tcg_gen_mov_tl(t0, arg1); \
3413 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3414 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3415 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3416 tcg_temp_free(t0); \
3418 #else
3419 #define OP_LD_ATOMIC(insn, fname) \
3420 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3421 DisasContext *ctx) \
3423 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3425 #endif
3426 OP_LD_ATOMIC(ll, ld32s);
3427 #if defined(TARGET_MIPS64)
3428 OP_LD_ATOMIC(lld, ld64);
3429 #endif
3430 #undef OP_LD_ATOMIC
3432 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3433 int base, int offset)
3435 if (base == 0) {
3436 tcg_gen_movi_tl(addr, offset);
3437 } else if (offset == 0) {
3438 gen_load_gpr(addr, base);
3439 } else {
3440 tcg_gen_movi_tl(addr, offset);
3441 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3445 static target_ulong pc_relative_pc(DisasContext *ctx)
3447 target_ulong pc = ctx->base.pc_next;
3449 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3450 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3452 pc -= branch_bytes;
3455 pc &= ~(target_ulong)3;
3456 return pc;
3459 /* Load */
3460 static void gen_ld(DisasContext *ctx, uint32_t opc,
3461 int rt, int base, int offset)
3463 TCGv t0, t1, t2;
3464 int mem_idx = ctx->mem_idx;
3466 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3467 INSN_LOONGSON3A)) {
3469 * Loongson CPU uses a load to zero register for prefetch.
3470 * We emulate it as a NOP. On other CPU we must perform the
3471 * actual memory access.
3473 return;
3476 t0 = tcg_temp_new();
3477 gen_base_offset_addr(ctx, t0, base, offset);
3479 switch (opc) {
3480 #if defined(TARGET_MIPS64)
3481 case OPC_LWU:
3482 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3483 ctx->default_tcg_memop_mask);
3484 gen_store_gpr(t0, rt);
3485 break;
3486 case OPC_LD:
3487 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3488 ctx->default_tcg_memop_mask);
3489 gen_store_gpr(t0, rt);
3490 break;
3491 case OPC_LLD:
3492 case R6_OPC_LLD:
3493 op_ld_lld(t0, t0, mem_idx, ctx);
3494 gen_store_gpr(t0, rt);
3495 break;
3496 case OPC_LDL:
3497 t1 = tcg_temp_new();
3499 * Do a byte access to possibly trigger a page
3500 * fault with the unaligned address.
3502 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3503 tcg_gen_andi_tl(t1, t0, 7);
3504 #ifndef TARGET_WORDS_BIGENDIAN
3505 tcg_gen_xori_tl(t1, t1, 7);
3506 #endif
3507 tcg_gen_shli_tl(t1, t1, 3);
3508 tcg_gen_andi_tl(t0, t0, ~7);
3509 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3510 tcg_gen_shl_tl(t0, t0, t1);
3511 t2 = tcg_const_tl(-1);
3512 tcg_gen_shl_tl(t2, t2, t1);
3513 gen_load_gpr(t1, rt);
3514 tcg_gen_andc_tl(t1, t1, t2);
3515 tcg_temp_free(t2);
3516 tcg_gen_or_tl(t0, t0, t1);
3517 tcg_temp_free(t1);
3518 gen_store_gpr(t0, rt);
3519 break;
3520 case OPC_LDR:
3521 t1 = tcg_temp_new();
3523 * Do a byte access to possibly trigger a page
3524 * fault with the unaligned address.
3526 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3527 tcg_gen_andi_tl(t1, t0, 7);
3528 #ifdef TARGET_WORDS_BIGENDIAN
3529 tcg_gen_xori_tl(t1, t1, 7);
3530 #endif
3531 tcg_gen_shli_tl(t1, t1, 3);
3532 tcg_gen_andi_tl(t0, t0, ~7);
3533 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3534 tcg_gen_shr_tl(t0, t0, t1);
3535 tcg_gen_xori_tl(t1, t1, 63);
3536 t2 = tcg_const_tl(0xfffffffffffffffeull);
3537 tcg_gen_shl_tl(t2, t2, t1);
3538 gen_load_gpr(t1, rt);
3539 tcg_gen_and_tl(t1, t1, t2);
3540 tcg_temp_free(t2);
3541 tcg_gen_or_tl(t0, t0, t1);
3542 tcg_temp_free(t1);
3543 gen_store_gpr(t0, rt);
3544 break;
3545 case OPC_LDPC:
3546 t1 = tcg_const_tl(pc_relative_pc(ctx));
3547 gen_op_addr_add(ctx, t0, t0, t1);
3548 tcg_temp_free(t1);
3549 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3550 gen_store_gpr(t0, rt);
3551 break;
3552 #endif
3553 case OPC_LWPC:
3554 t1 = tcg_const_tl(pc_relative_pc(ctx));
3555 gen_op_addr_add(ctx, t0, t0, t1);
3556 tcg_temp_free(t1);
3557 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3558 gen_store_gpr(t0, rt);
3559 break;
3560 case OPC_LWE:
3561 mem_idx = MIPS_HFLAG_UM;
3562 /* fall through */
3563 case OPC_LW:
3564 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3565 ctx->default_tcg_memop_mask);
3566 gen_store_gpr(t0, rt);
3567 break;
3568 case OPC_LHE:
3569 mem_idx = MIPS_HFLAG_UM;
3570 /* fall through */
3571 case OPC_LH:
3572 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3573 ctx->default_tcg_memop_mask);
3574 gen_store_gpr(t0, rt);
3575 break;
3576 case OPC_LHUE:
3577 mem_idx = MIPS_HFLAG_UM;
3578 /* fall through */
3579 case OPC_LHU:
3580 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3581 ctx->default_tcg_memop_mask);
3582 gen_store_gpr(t0, rt);
3583 break;
3584 case OPC_LBE:
3585 mem_idx = MIPS_HFLAG_UM;
3586 /* fall through */
3587 case OPC_LB:
3588 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3589 gen_store_gpr(t0, rt);
3590 break;
3591 case OPC_LBUE:
3592 mem_idx = MIPS_HFLAG_UM;
3593 /* fall through */
3594 case OPC_LBU:
3595 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3596 gen_store_gpr(t0, rt);
3597 break;
3598 case OPC_LWLE:
3599 mem_idx = MIPS_HFLAG_UM;
3600 /* fall through */
3601 case OPC_LWL:
3602 t1 = tcg_temp_new();
3604 * Do a byte access to possibly trigger a page
3605 * fault with the unaligned address.
3607 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3608 tcg_gen_andi_tl(t1, t0, 3);
3609 #ifndef TARGET_WORDS_BIGENDIAN
3610 tcg_gen_xori_tl(t1, t1, 3);
3611 #endif
3612 tcg_gen_shli_tl(t1, t1, 3);
3613 tcg_gen_andi_tl(t0, t0, ~3);
3614 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3615 tcg_gen_shl_tl(t0, t0, t1);
3616 t2 = tcg_const_tl(-1);
3617 tcg_gen_shl_tl(t2, t2, t1);
3618 gen_load_gpr(t1, rt);
3619 tcg_gen_andc_tl(t1, t1, t2);
3620 tcg_temp_free(t2);
3621 tcg_gen_or_tl(t0, t0, t1);
3622 tcg_temp_free(t1);
3623 tcg_gen_ext32s_tl(t0, t0);
3624 gen_store_gpr(t0, rt);
3625 break;
3626 case OPC_LWRE:
3627 mem_idx = MIPS_HFLAG_UM;
3628 /* fall through */
3629 case OPC_LWR:
3630 t1 = tcg_temp_new();
3632 * Do a byte access to possibly trigger a page
3633 * fault with the unaligned address.
3635 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3636 tcg_gen_andi_tl(t1, t0, 3);
3637 #ifdef TARGET_WORDS_BIGENDIAN
3638 tcg_gen_xori_tl(t1, t1, 3);
3639 #endif
3640 tcg_gen_shli_tl(t1, t1, 3);
3641 tcg_gen_andi_tl(t0, t0, ~3);
3642 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3643 tcg_gen_shr_tl(t0, t0, t1);
3644 tcg_gen_xori_tl(t1, t1, 31);
3645 t2 = tcg_const_tl(0xfffffffeull);
3646 tcg_gen_shl_tl(t2, t2, t1);
3647 gen_load_gpr(t1, rt);
3648 tcg_gen_and_tl(t1, t1, t2);
3649 tcg_temp_free(t2);
3650 tcg_gen_or_tl(t0, t0, t1);
3651 tcg_temp_free(t1);
3652 tcg_gen_ext32s_tl(t0, t0);
3653 gen_store_gpr(t0, rt);
3654 break;
3655 case OPC_LLE:
3656 mem_idx = MIPS_HFLAG_UM;
3657 /* fall through */
3658 case OPC_LL:
3659 case R6_OPC_LL:
3660 op_ld_ll(t0, t0, mem_idx, ctx);
3661 gen_store_gpr(t0, rt);
3662 break;
3664 tcg_temp_free(t0);
3667 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3668 uint32_t reg1, uint32_t reg2)
3670 TCGv taddr = tcg_temp_new();
3671 TCGv_i64 tval = tcg_temp_new_i64();
3672 TCGv tmp1 = tcg_temp_new();
3673 TCGv tmp2 = tcg_temp_new();
3675 gen_base_offset_addr(ctx, taddr, base, offset);
3676 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3677 #ifdef TARGET_WORDS_BIGENDIAN
3678 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3679 #else
3680 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3681 #endif
3682 gen_store_gpr(tmp1, reg1);
3683 tcg_temp_free(tmp1);
3684 gen_store_gpr(tmp2, reg2);
3685 tcg_temp_free(tmp2);
3686 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3687 tcg_temp_free_i64(tval);
3688 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3689 tcg_temp_free(taddr);
3692 /* Store */
3693 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3694 int base, int offset)
3696 TCGv t0 = tcg_temp_new();
3697 TCGv t1 = tcg_temp_new();
3698 int mem_idx = ctx->mem_idx;
3700 gen_base_offset_addr(ctx, t0, base, offset);
3701 gen_load_gpr(t1, rt);
3702 switch (opc) {
3703 #if defined(TARGET_MIPS64)
3704 case OPC_SD:
3705 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3706 ctx->default_tcg_memop_mask);
3707 break;
3708 case OPC_SDL:
3709 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3710 break;
3711 case OPC_SDR:
3712 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3713 break;
3714 #endif
3715 case OPC_SWE:
3716 mem_idx = MIPS_HFLAG_UM;
3717 /* fall through */
3718 case OPC_SW:
3719 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3720 ctx->default_tcg_memop_mask);
3721 break;
3722 case OPC_SHE:
3723 mem_idx = MIPS_HFLAG_UM;
3724 /* fall through */
3725 case OPC_SH:
3726 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3727 ctx->default_tcg_memop_mask);
3728 break;
3729 case OPC_SBE:
3730 mem_idx = MIPS_HFLAG_UM;
3731 /* fall through */
3732 case OPC_SB:
3733 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3734 break;
3735 case OPC_SWLE:
3736 mem_idx = MIPS_HFLAG_UM;
3737 /* fall through */
3738 case OPC_SWL:
3739 gen_helper_0e2i(swl, t1, t0, mem_idx);
3740 break;
3741 case OPC_SWRE:
3742 mem_idx = MIPS_HFLAG_UM;
3743 /* fall through */
3744 case OPC_SWR:
3745 gen_helper_0e2i(swr, t1, t0, mem_idx);
3746 break;
3748 tcg_temp_free(t0);
3749 tcg_temp_free(t1);
3753 /* Store conditional */
3754 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3755 MemOp tcg_mo, bool eva)
3757 TCGv addr, t0, val;
3758 TCGLabel *l1 = gen_new_label();
3759 TCGLabel *done = gen_new_label();
3761 t0 = tcg_temp_new();
3762 addr = tcg_temp_new();
3763 /* compare the address against that of the preceding LL */
3764 gen_base_offset_addr(ctx, addr, base, offset);
3765 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3766 tcg_temp_free(addr);
3767 tcg_gen_movi_tl(t0, 0);
3768 gen_store_gpr(t0, rt);
3769 tcg_gen_br(done);
3771 gen_set_label(l1);
3772 /* generate cmpxchg */
3773 val = tcg_temp_new();
3774 gen_load_gpr(val, rt);
3775 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3776 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3777 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3778 gen_store_gpr(t0, rt);
3779 tcg_temp_free(val);
3781 gen_set_label(done);
3782 tcg_temp_free(t0);
3786 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3787 uint32_t reg1, uint32_t reg2, bool eva)
3789 TCGv taddr = tcg_temp_local_new();
3790 TCGv lladdr = tcg_temp_local_new();
3791 TCGv_i64 tval = tcg_temp_new_i64();
3792 TCGv_i64 llval = tcg_temp_new_i64();
3793 TCGv_i64 val = tcg_temp_new_i64();
3794 TCGv tmp1 = tcg_temp_new();
3795 TCGv tmp2 = tcg_temp_new();
3796 TCGLabel *lab_fail = gen_new_label();
3797 TCGLabel *lab_done = gen_new_label();
3799 gen_base_offset_addr(ctx, taddr, base, offset);
3801 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3802 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3804 gen_load_gpr(tmp1, reg1);
3805 gen_load_gpr(tmp2, reg2);
3807 #ifdef TARGET_WORDS_BIGENDIAN
3808 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3809 #else
3810 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3811 #endif
3813 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3814 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3815 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3816 if (reg1 != 0) {
3817 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3819 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3821 gen_set_label(lab_fail);
3823 if (reg1 != 0) {
3824 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3826 gen_set_label(lab_done);
3827 tcg_gen_movi_tl(lladdr, -1);
3828 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3831 /* Load and store */
3832 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3833 TCGv t0)
3836 * Don't do NOP if destination is zero: we must perform the actual
3837 * memory access.
3839 switch (opc) {
3840 case OPC_LWC1:
3842 TCGv_i32 fp0 = tcg_temp_new_i32();
3843 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3844 ctx->default_tcg_memop_mask);
3845 gen_store_fpr32(ctx, fp0, ft);
3846 tcg_temp_free_i32(fp0);
3848 break;
3849 case OPC_SWC1:
3851 TCGv_i32 fp0 = tcg_temp_new_i32();
3852 gen_load_fpr32(ctx, fp0, ft);
3853 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3854 ctx->default_tcg_memop_mask);
3855 tcg_temp_free_i32(fp0);
3857 break;
3858 case OPC_LDC1:
3860 TCGv_i64 fp0 = tcg_temp_new_i64();
3861 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3862 ctx->default_tcg_memop_mask);
3863 gen_store_fpr64(ctx, fp0, ft);
3864 tcg_temp_free_i64(fp0);
3866 break;
3867 case OPC_SDC1:
3869 TCGv_i64 fp0 = tcg_temp_new_i64();
3870 gen_load_fpr64(ctx, fp0, ft);
3871 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3872 ctx->default_tcg_memop_mask);
3873 tcg_temp_free_i64(fp0);
3875 break;
3876 default:
3877 MIPS_INVAL("flt_ldst");
3878 generate_exception_end(ctx, EXCP_RI);
3879 break;
3883 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3884 int rs, int16_t imm)
3886 TCGv t0 = tcg_temp_new();
3888 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3889 check_cp1_enabled(ctx);
3890 switch (op) {
3891 case OPC_LDC1:
3892 case OPC_SDC1:
3893 check_insn(ctx, ISA_MIPS2);
3894 /* Fallthrough */
3895 default:
3896 gen_base_offset_addr(ctx, t0, rs, imm);
3897 gen_flt_ldst(ctx, op, rt, t0);
3899 } else {
3900 generate_exception_err(ctx, EXCP_CpU, 1);
3902 tcg_temp_free(t0);
3905 /* Arithmetic with immediate operand */
3906 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3907 int rt, int rs, int imm)
3909 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3911 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3913 * If no destination, treat it as a NOP.
3914 * For addi, we must generate the overflow exception when needed.
3916 return;
3918 switch (opc) {
3919 case OPC_ADDI:
3921 TCGv t0 = tcg_temp_local_new();
3922 TCGv t1 = tcg_temp_new();
3923 TCGv t2 = tcg_temp_new();
3924 TCGLabel *l1 = gen_new_label();
3926 gen_load_gpr(t1, rs);
3927 tcg_gen_addi_tl(t0, t1, uimm);
3928 tcg_gen_ext32s_tl(t0, t0);
3930 tcg_gen_xori_tl(t1, t1, ~uimm);
3931 tcg_gen_xori_tl(t2, t0, uimm);
3932 tcg_gen_and_tl(t1, t1, t2);
3933 tcg_temp_free(t2);
3934 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3935 tcg_temp_free(t1);
3936 /* operands of same sign, result different sign */
3937 generate_exception(ctx, EXCP_OVERFLOW);
3938 gen_set_label(l1);
3939 tcg_gen_ext32s_tl(t0, t0);
3940 gen_store_gpr(t0, rt);
3941 tcg_temp_free(t0);
3943 break;
3944 case OPC_ADDIU:
3945 if (rs != 0) {
3946 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3947 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3948 } else {
3949 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3951 break;
3952 #if defined(TARGET_MIPS64)
3953 case OPC_DADDI:
3955 TCGv t0 = tcg_temp_local_new();
3956 TCGv t1 = tcg_temp_new();
3957 TCGv t2 = tcg_temp_new();
3958 TCGLabel *l1 = gen_new_label();
3960 gen_load_gpr(t1, rs);
3961 tcg_gen_addi_tl(t0, t1, uimm);
3963 tcg_gen_xori_tl(t1, t1, ~uimm);
3964 tcg_gen_xori_tl(t2, t0, uimm);
3965 tcg_gen_and_tl(t1, t1, t2);
3966 tcg_temp_free(t2);
3967 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3968 tcg_temp_free(t1);
3969 /* operands of same sign, result different sign */
3970 generate_exception(ctx, EXCP_OVERFLOW);
3971 gen_set_label(l1);
3972 gen_store_gpr(t0, rt);
3973 tcg_temp_free(t0);
3975 break;
3976 case OPC_DADDIU:
3977 if (rs != 0) {
3978 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3979 } else {
3980 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3982 break;
3983 #endif
3987 /* Logic with immediate operand */
3988 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3989 int rt, int rs, int16_t imm)
3991 target_ulong uimm;
3993 if (rt == 0) {
3994 /* If no destination, treat it as a NOP. */
3995 return;
3997 uimm = (uint16_t)imm;
3998 switch (opc) {
3999 case OPC_ANDI:
4000 if (likely(rs != 0)) {
4001 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
4002 } else {
4003 tcg_gen_movi_tl(cpu_gpr[rt], 0);
4005 break;
4006 case OPC_ORI:
4007 if (rs != 0) {
4008 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
4009 } else {
4010 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
4012 break;
4013 case OPC_XORI:
4014 if (likely(rs != 0)) {
4015 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
4016 } else {
4017 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
4019 break;
4020 case OPC_LUI:
4021 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
4022 /* OPC_AUI */
4023 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
4024 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
4025 } else {
4026 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
4028 break;
4030 default:
4031 break;
4035 /* Set on less than with immediate operand */
4036 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
4037 int rt, int rs, int16_t imm)
4039 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
4040 TCGv t0;
4042 if (rt == 0) {
4043 /* If no destination, treat it as a NOP. */
4044 return;
4046 t0 = tcg_temp_new();
4047 gen_load_gpr(t0, rs);
4048 switch (opc) {
4049 case OPC_SLTI:
4050 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4051 break;
4052 case OPC_SLTIU:
4053 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4054 break;
4056 tcg_temp_free(t0);
4059 /* Shifts with immediate operand */
4060 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4061 int rt, int rs, int16_t imm)
4063 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4064 TCGv t0;
4066 if (rt == 0) {
4067 /* If no destination, treat it as a NOP. */
4068 return;
4071 t0 = tcg_temp_new();
4072 gen_load_gpr(t0, rs);
4073 switch (opc) {
4074 case OPC_SLL:
4075 tcg_gen_shli_tl(t0, t0, uimm);
4076 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4077 break;
4078 case OPC_SRA:
4079 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4080 break;
4081 case OPC_SRL:
4082 if (uimm != 0) {
4083 tcg_gen_ext32u_tl(t0, t0);
4084 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4085 } else {
4086 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4088 break;
4089 case OPC_ROTR:
4090 if (uimm != 0) {
4091 TCGv_i32 t1 = tcg_temp_new_i32();
4093 tcg_gen_trunc_tl_i32(t1, t0);
4094 tcg_gen_rotri_i32(t1, t1, uimm);
4095 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4096 tcg_temp_free_i32(t1);
4097 } else {
4098 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4100 break;
4101 #if defined(TARGET_MIPS64)
4102 case OPC_DSLL:
4103 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4104 break;
4105 case OPC_DSRA:
4106 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4107 break;
4108 case OPC_DSRL:
4109 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4110 break;
4111 case OPC_DROTR:
4112 if (uimm != 0) {
4113 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4114 } else {
4115 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4117 break;
4118 case OPC_DSLL32:
4119 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4120 break;
4121 case OPC_DSRA32:
4122 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4123 break;
4124 case OPC_DSRL32:
4125 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4126 break;
4127 case OPC_DROTR32:
4128 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4129 break;
4130 #endif
4132 tcg_temp_free(t0);
4135 /* Arithmetic */
4136 static void gen_arith(DisasContext *ctx, uint32_t opc,
4137 int rd, int rs, int rt)
4139 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4140 && opc != OPC_DADD && opc != OPC_DSUB) {
4142 * If no destination, treat it as a NOP.
4143 * For add & sub, we must generate the overflow exception when needed.
4145 return;
4148 switch (opc) {
4149 case OPC_ADD:
4151 TCGv t0 = tcg_temp_local_new();
4152 TCGv t1 = tcg_temp_new();
4153 TCGv t2 = tcg_temp_new();
4154 TCGLabel *l1 = gen_new_label();
4156 gen_load_gpr(t1, rs);
4157 gen_load_gpr(t2, rt);
4158 tcg_gen_add_tl(t0, t1, t2);
4159 tcg_gen_ext32s_tl(t0, t0);
4160 tcg_gen_xor_tl(t1, t1, t2);
4161 tcg_gen_xor_tl(t2, t0, t2);
4162 tcg_gen_andc_tl(t1, t2, t1);
4163 tcg_temp_free(t2);
4164 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4165 tcg_temp_free(t1);
4166 /* operands of same sign, result different sign */
4167 generate_exception(ctx, EXCP_OVERFLOW);
4168 gen_set_label(l1);
4169 gen_store_gpr(t0, rd);
4170 tcg_temp_free(t0);
4172 break;
4173 case OPC_ADDU:
4174 if (rs != 0 && rt != 0) {
4175 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4176 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4177 } else if (rs == 0 && rt != 0) {
4178 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4179 } else if (rs != 0 && rt == 0) {
4180 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4181 } else {
4182 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4184 break;
4185 case OPC_SUB:
4187 TCGv t0 = tcg_temp_local_new();
4188 TCGv t1 = tcg_temp_new();
4189 TCGv t2 = tcg_temp_new();
4190 TCGLabel *l1 = gen_new_label();
4192 gen_load_gpr(t1, rs);
4193 gen_load_gpr(t2, rt);
4194 tcg_gen_sub_tl(t0, t1, t2);
4195 tcg_gen_ext32s_tl(t0, t0);
4196 tcg_gen_xor_tl(t2, t1, t2);
4197 tcg_gen_xor_tl(t1, t0, t1);
4198 tcg_gen_and_tl(t1, t1, t2);
4199 tcg_temp_free(t2);
4200 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4201 tcg_temp_free(t1);
4203 * operands of different sign, first operand and the result
4204 * of different sign
4206 generate_exception(ctx, EXCP_OVERFLOW);
4207 gen_set_label(l1);
4208 gen_store_gpr(t0, rd);
4209 tcg_temp_free(t0);
4211 break;
4212 case OPC_SUBU:
4213 if (rs != 0 && rt != 0) {
4214 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4215 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4216 } else if (rs == 0 && rt != 0) {
4217 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4218 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4219 } else if (rs != 0 && rt == 0) {
4220 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4221 } else {
4222 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4224 break;
4225 #if defined(TARGET_MIPS64)
4226 case OPC_DADD:
4228 TCGv t0 = tcg_temp_local_new();
4229 TCGv t1 = tcg_temp_new();
4230 TCGv t2 = tcg_temp_new();
4231 TCGLabel *l1 = gen_new_label();
4233 gen_load_gpr(t1, rs);
4234 gen_load_gpr(t2, rt);
4235 tcg_gen_add_tl(t0, t1, t2);
4236 tcg_gen_xor_tl(t1, t1, t2);
4237 tcg_gen_xor_tl(t2, t0, t2);
4238 tcg_gen_andc_tl(t1, t2, t1);
4239 tcg_temp_free(t2);
4240 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4241 tcg_temp_free(t1);
4242 /* operands of same sign, result different sign */
4243 generate_exception(ctx, EXCP_OVERFLOW);
4244 gen_set_label(l1);
4245 gen_store_gpr(t0, rd);
4246 tcg_temp_free(t0);
4248 break;
4249 case OPC_DADDU:
4250 if (rs != 0 && rt != 0) {
4251 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4252 } else if (rs == 0 && rt != 0) {
4253 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4254 } else if (rs != 0 && rt == 0) {
4255 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4256 } else {
4257 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4259 break;
4260 case OPC_DSUB:
4262 TCGv t0 = tcg_temp_local_new();
4263 TCGv t1 = tcg_temp_new();
4264 TCGv t2 = tcg_temp_new();
4265 TCGLabel *l1 = gen_new_label();
4267 gen_load_gpr(t1, rs);
4268 gen_load_gpr(t2, rt);
4269 tcg_gen_sub_tl(t0, t1, t2);
4270 tcg_gen_xor_tl(t2, t1, t2);
4271 tcg_gen_xor_tl(t1, t0, t1);
4272 tcg_gen_and_tl(t1, t1, t2);
4273 tcg_temp_free(t2);
4274 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4275 tcg_temp_free(t1);
4277 * Operands of different sign, first operand and result different
4278 * sign.
4280 generate_exception(ctx, EXCP_OVERFLOW);
4281 gen_set_label(l1);
4282 gen_store_gpr(t0, rd);
4283 tcg_temp_free(t0);
4285 break;
4286 case OPC_DSUBU:
4287 if (rs != 0 && rt != 0) {
4288 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4289 } else if (rs == 0 && rt != 0) {
4290 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4291 } else if (rs != 0 && rt == 0) {
4292 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4293 } else {
4294 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4296 break;
4297 #endif
4298 case OPC_MUL:
4299 if (likely(rs != 0 && rt != 0)) {
4300 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4301 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4302 } else {
4303 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4305 break;
4309 /* Conditional move */
4310 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4311 int rd, int rs, int rt)
4313 TCGv t0, t1, t2;
4315 if (rd == 0) {
4316 /* If no destination, treat it as a NOP. */
4317 return;
4320 t0 = tcg_temp_new();
4321 gen_load_gpr(t0, rt);
4322 t1 = tcg_const_tl(0);
4323 t2 = tcg_temp_new();
4324 gen_load_gpr(t2, rs);
4325 switch (opc) {
4326 case OPC_MOVN:
4327 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4328 break;
4329 case OPC_MOVZ:
4330 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4331 break;
4332 case OPC_SELNEZ:
4333 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4334 break;
4335 case OPC_SELEQZ:
4336 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4337 break;
4339 tcg_temp_free(t2);
4340 tcg_temp_free(t1);
4341 tcg_temp_free(t0);
4344 /* Logic */
4345 static void gen_logic(DisasContext *ctx, uint32_t opc,
4346 int rd, int rs, int rt)
4348 if (rd == 0) {
4349 /* If no destination, treat it as a NOP. */
4350 return;
4353 switch (opc) {
4354 case OPC_AND:
4355 if (likely(rs != 0 && rt != 0)) {
4356 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4357 } else {
4358 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4360 break;
4361 case OPC_NOR:
4362 if (rs != 0 && rt != 0) {
4363 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4364 } else if (rs == 0 && rt != 0) {
4365 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4366 } else if (rs != 0 && rt == 0) {
4367 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4368 } else {
4369 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4371 break;
4372 case OPC_OR:
4373 if (likely(rs != 0 && rt != 0)) {
4374 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4375 } else if (rs == 0 && rt != 0) {
4376 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4377 } else if (rs != 0 && rt == 0) {
4378 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4379 } else {
4380 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4382 break;
4383 case OPC_XOR:
4384 if (likely(rs != 0 && rt != 0)) {
4385 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4386 } else if (rs == 0 && rt != 0) {
4387 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4388 } else if (rs != 0 && rt == 0) {
4389 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4390 } else {
4391 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4393 break;
4397 /* Set on lower than */
4398 static void gen_slt(DisasContext *ctx, uint32_t opc,
4399 int rd, int rs, int rt)
4401 TCGv t0, t1;
4403 if (rd == 0) {
4404 /* If no destination, treat it as a NOP. */
4405 return;
4408 t0 = tcg_temp_new();
4409 t1 = tcg_temp_new();
4410 gen_load_gpr(t0, rs);
4411 gen_load_gpr(t1, rt);
4412 switch (opc) {
4413 case OPC_SLT:
4414 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4415 break;
4416 case OPC_SLTU:
4417 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4418 break;
4420 tcg_temp_free(t0);
4421 tcg_temp_free(t1);
4424 /* Shifts */
4425 static void gen_shift(DisasContext *ctx, uint32_t opc,
4426 int rd, int rs, int rt)
4428 TCGv t0, t1;
4430 if (rd == 0) {
4432 * If no destination, treat it as a NOP.
4433 * For add & sub, we must generate the overflow exception when needed.
4435 return;
4438 t0 = tcg_temp_new();
4439 t1 = tcg_temp_new();
4440 gen_load_gpr(t0, rs);
4441 gen_load_gpr(t1, rt);
4442 switch (opc) {
4443 case OPC_SLLV:
4444 tcg_gen_andi_tl(t0, t0, 0x1f);
4445 tcg_gen_shl_tl(t0, t1, t0);
4446 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4447 break;
4448 case OPC_SRAV:
4449 tcg_gen_andi_tl(t0, t0, 0x1f);
4450 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4451 break;
4452 case OPC_SRLV:
4453 tcg_gen_ext32u_tl(t1, t1);
4454 tcg_gen_andi_tl(t0, t0, 0x1f);
4455 tcg_gen_shr_tl(t0, t1, t0);
4456 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4457 break;
4458 case OPC_ROTRV:
4460 TCGv_i32 t2 = tcg_temp_new_i32();
4461 TCGv_i32 t3 = tcg_temp_new_i32();
4463 tcg_gen_trunc_tl_i32(t2, t0);
4464 tcg_gen_trunc_tl_i32(t3, t1);
4465 tcg_gen_andi_i32(t2, t2, 0x1f);
4466 tcg_gen_rotr_i32(t2, t3, t2);
4467 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4468 tcg_temp_free_i32(t2);
4469 tcg_temp_free_i32(t3);
4471 break;
4472 #if defined(TARGET_MIPS64)
4473 case OPC_DSLLV:
4474 tcg_gen_andi_tl(t0, t0, 0x3f);
4475 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4476 break;
4477 case OPC_DSRAV:
4478 tcg_gen_andi_tl(t0, t0, 0x3f);
4479 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4480 break;
4481 case OPC_DSRLV:
4482 tcg_gen_andi_tl(t0, t0, 0x3f);
4483 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4484 break;
4485 case OPC_DROTRV:
4486 tcg_gen_andi_tl(t0, t0, 0x3f);
4487 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4488 break;
4489 #endif
4491 tcg_temp_free(t0);
4492 tcg_temp_free(t1);
4495 #if defined(TARGET_MIPS64)
4496 /* Copy GPR to and from TX79 HI1/LO1 register. */
4497 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4499 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4500 /* Treat as NOP. */
4501 return;
4504 switch (opc) {
4505 case MMI_OPC_MFHI1:
4506 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4507 break;
4508 case MMI_OPC_MFLO1:
4509 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4510 break;
4511 case MMI_OPC_MTHI1:
4512 if (reg != 0) {
4513 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4514 } else {
4515 tcg_gen_movi_tl(cpu_HI[1], 0);
4517 break;
4518 case MMI_OPC_MTLO1:
4519 if (reg != 0) {
4520 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4521 } else {
4522 tcg_gen_movi_tl(cpu_LO[1], 0);
4524 break;
4525 default:
4526 MIPS_INVAL("mfthilo1 TX79");
4527 generate_exception_end(ctx, EXCP_RI);
4528 break;
4531 #endif
4533 /* Arithmetic on HI/LO registers */
4534 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4536 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4537 /* Treat as NOP. */
4538 return;
4541 if (acc != 0) {
4542 check_dsp(ctx);
4545 switch (opc) {
4546 case OPC_MFHI:
4547 #if defined(TARGET_MIPS64)
4548 if (acc != 0) {
4549 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4550 } else
4551 #endif
4553 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4555 break;
4556 case OPC_MFLO:
4557 #if defined(TARGET_MIPS64)
4558 if (acc != 0) {
4559 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4560 } else
4561 #endif
4563 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4565 break;
4566 case OPC_MTHI:
4567 if (reg != 0) {
4568 #if defined(TARGET_MIPS64)
4569 if (acc != 0) {
4570 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4571 } else
4572 #endif
4574 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4576 } else {
4577 tcg_gen_movi_tl(cpu_HI[acc], 0);
4579 break;
4580 case OPC_MTLO:
4581 if (reg != 0) {
4582 #if defined(TARGET_MIPS64)
4583 if (acc != 0) {
4584 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4585 } else
4586 #endif
4588 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4590 } else {
4591 tcg_gen_movi_tl(cpu_LO[acc], 0);
4593 break;
4597 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4598 MemOp memop)
4600 TCGv t0 = tcg_const_tl(addr);
4601 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4602 gen_store_gpr(t0, reg);
4603 tcg_temp_free(t0);
4606 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4607 int rs)
4609 target_long offset;
4610 target_long addr;
4612 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4613 case OPC_ADDIUPC:
4614 if (rs != 0) {
4615 offset = sextract32(ctx->opcode << 2, 0, 21);
4616 addr = addr_add(ctx, pc, offset);
4617 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4619 break;
4620 case R6_OPC_LWPC:
4621 offset = sextract32(ctx->opcode << 2, 0, 21);
4622 addr = addr_add(ctx, pc, offset);
4623 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4624 break;
4625 #if defined(TARGET_MIPS64)
4626 case OPC_LWUPC:
4627 check_mips_64(ctx);
4628 offset = sextract32(ctx->opcode << 2, 0, 21);
4629 addr = addr_add(ctx, pc, offset);
4630 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4631 break;
4632 #endif
4633 default:
4634 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4635 case OPC_AUIPC:
4636 if (rs != 0) {
4637 offset = sextract32(ctx->opcode, 0, 16) << 16;
4638 addr = addr_add(ctx, pc, offset);
4639 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4641 break;
4642 case OPC_ALUIPC:
4643 if (rs != 0) {
4644 offset = sextract32(ctx->opcode, 0, 16) << 16;
4645 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4646 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4648 break;
4649 #if defined(TARGET_MIPS64)
4650 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4651 case R6_OPC_LDPC + (1 << 16):
4652 case R6_OPC_LDPC + (2 << 16):
4653 case R6_OPC_LDPC + (3 << 16):
4654 check_mips_64(ctx);
4655 offset = sextract32(ctx->opcode << 3, 0, 21);
4656 addr = addr_add(ctx, (pc & ~0x7), offset);
4657 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4658 break;
4659 #endif
4660 default:
4661 MIPS_INVAL("OPC_PCREL");
4662 generate_exception_end(ctx, EXCP_RI);
4663 break;
4665 break;
4669 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4671 TCGv t0, t1;
4673 if (rd == 0) {
4674 /* Treat as NOP. */
4675 return;
4678 t0 = tcg_temp_new();
4679 t1 = tcg_temp_new();
4681 gen_load_gpr(t0, rs);
4682 gen_load_gpr(t1, rt);
4684 switch (opc) {
4685 case R6_OPC_DIV:
4687 TCGv t2 = tcg_temp_new();
4688 TCGv t3 = tcg_temp_new();
4689 tcg_gen_ext32s_tl(t0, t0);
4690 tcg_gen_ext32s_tl(t1, t1);
4691 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4692 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4693 tcg_gen_and_tl(t2, t2, t3);
4694 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4695 tcg_gen_or_tl(t2, t2, t3);
4696 tcg_gen_movi_tl(t3, 0);
4697 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4698 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4699 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4700 tcg_temp_free(t3);
4701 tcg_temp_free(t2);
4703 break;
4704 case R6_OPC_MOD:
4706 TCGv t2 = tcg_temp_new();
4707 TCGv t3 = tcg_temp_new();
4708 tcg_gen_ext32s_tl(t0, t0);
4709 tcg_gen_ext32s_tl(t1, t1);
4710 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4711 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4712 tcg_gen_and_tl(t2, t2, t3);
4713 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4714 tcg_gen_or_tl(t2, t2, t3);
4715 tcg_gen_movi_tl(t3, 0);
4716 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4717 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4718 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4719 tcg_temp_free(t3);
4720 tcg_temp_free(t2);
4722 break;
4723 case R6_OPC_DIVU:
4725 TCGv t2 = tcg_const_tl(0);
4726 TCGv t3 = tcg_const_tl(1);
4727 tcg_gen_ext32u_tl(t0, t0);
4728 tcg_gen_ext32u_tl(t1, t1);
4729 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4730 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4731 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4732 tcg_temp_free(t3);
4733 tcg_temp_free(t2);
4735 break;
4736 case R6_OPC_MODU:
4738 TCGv t2 = tcg_const_tl(0);
4739 TCGv t3 = tcg_const_tl(1);
4740 tcg_gen_ext32u_tl(t0, t0);
4741 tcg_gen_ext32u_tl(t1, t1);
4742 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4743 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4744 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4745 tcg_temp_free(t3);
4746 tcg_temp_free(t2);
4748 break;
4749 case R6_OPC_MUL:
4751 TCGv_i32 t2 = tcg_temp_new_i32();
4752 TCGv_i32 t3 = tcg_temp_new_i32();
4753 tcg_gen_trunc_tl_i32(t2, t0);
4754 tcg_gen_trunc_tl_i32(t3, t1);
4755 tcg_gen_mul_i32(t2, t2, t3);
4756 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4757 tcg_temp_free_i32(t2);
4758 tcg_temp_free_i32(t3);
4760 break;
4761 case R6_OPC_MUH:
4763 TCGv_i32 t2 = tcg_temp_new_i32();
4764 TCGv_i32 t3 = tcg_temp_new_i32();
4765 tcg_gen_trunc_tl_i32(t2, t0);
4766 tcg_gen_trunc_tl_i32(t3, t1);
4767 tcg_gen_muls2_i32(t2, t3, t2, t3);
4768 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4769 tcg_temp_free_i32(t2);
4770 tcg_temp_free_i32(t3);
4772 break;
4773 case R6_OPC_MULU:
4775 TCGv_i32 t2 = tcg_temp_new_i32();
4776 TCGv_i32 t3 = tcg_temp_new_i32();
4777 tcg_gen_trunc_tl_i32(t2, t0);
4778 tcg_gen_trunc_tl_i32(t3, t1);
4779 tcg_gen_mul_i32(t2, t2, t3);
4780 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4781 tcg_temp_free_i32(t2);
4782 tcg_temp_free_i32(t3);
4784 break;
4785 case R6_OPC_MUHU:
4787 TCGv_i32 t2 = tcg_temp_new_i32();
4788 TCGv_i32 t3 = tcg_temp_new_i32();
4789 tcg_gen_trunc_tl_i32(t2, t0);
4790 tcg_gen_trunc_tl_i32(t3, t1);
4791 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4792 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4793 tcg_temp_free_i32(t2);
4794 tcg_temp_free_i32(t3);
4796 break;
4797 #if defined(TARGET_MIPS64)
4798 case R6_OPC_DDIV:
4800 TCGv t2 = tcg_temp_new();
4801 TCGv t3 = tcg_temp_new();
4802 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4803 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4804 tcg_gen_and_tl(t2, t2, t3);
4805 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4806 tcg_gen_or_tl(t2, t2, t3);
4807 tcg_gen_movi_tl(t3, 0);
4808 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4809 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4810 tcg_temp_free(t3);
4811 tcg_temp_free(t2);
4813 break;
4814 case R6_OPC_DMOD:
4816 TCGv t2 = tcg_temp_new();
4817 TCGv t3 = tcg_temp_new();
4818 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4819 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4820 tcg_gen_and_tl(t2, t2, t3);
4821 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4822 tcg_gen_or_tl(t2, t2, t3);
4823 tcg_gen_movi_tl(t3, 0);
4824 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4825 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4826 tcg_temp_free(t3);
4827 tcg_temp_free(t2);
4829 break;
4830 case R6_OPC_DDIVU:
4832 TCGv t2 = tcg_const_tl(0);
4833 TCGv t3 = tcg_const_tl(1);
4834 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4835 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4836 tcg_temp_free(t3);
4837 tcg_temp_free(t2);
4839 break;
4840 case R6_OPC_DMODU:
4842 TCGv t2 = tcg_const_tl(0);
4843 TCGv t3 = tcg_const_tl(1);
4844 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4845 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4846 tcg_temp_free(t3);
4847 tcg_temp_free(t2);
4849 break;
4850 case R6_OPC_DMUL:
4851 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4852 break;
4853 case R6_OPC_DMUH:
4855 TCGv t2 = tcg_temp_new();
4856 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4857 tcg_temp_free(t2);
4859 break;
4860 case R6_OPC_DMULU:
4861 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4862 break;
4863 case R6_OPC_DMUHU:
4865 TCGv t2 = tcg_temp_new();
4866 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4867 tcg_temp_free(t2);
4869 break;
4870 #endif
4871 default:
4872 MIPS_INVAL("r6 mul/div");
4873 generate_exception_end(ctx, EXCP_RI);
4874 goto out;
4876 out:
4877 tcg_temp_free(t0);
4878 tcg_temp_free(t1);
4881 #if defined(TARGET_MIPS64)
4882 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4884 TCGv t0, t1;
4886 t0 = tcg_temp_new();
4887 t1 = tcg_temp_new();
4889 gen_load_gpr(t0, rs);
4890 gen_load_gpr(t1, rt);
4892 switch (opc) {
4893 case MMI_OPC_DIV1:
4895 TCGv t2 = tcg_temp_new();
4896 TCGv t3 = tcg_temp_new();
4897 tcg_gen_ext32s_tl(t0, t0);
4898 tcg_gen_ext32s_tl(t1, t1);
4899 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4900 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4901 tcg_gen_and_tl(t2, t2, t3);
4902 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4903 tcg_gen_or_tl(t2, t2, t3);
4904 tcg_gen_movi_tl(t3, 0);
4905 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4906 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4907 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4908 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4909 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4910 tcg_temp_free(t3);
4911 tcg_temp_free(t2);
4913 break;
4914 case MMI_OPC_DIVU1:
4916 TCGv t2 = tcg_const_tl(0);
4917 TCGv t3 = tcg_const_tl(1);
4918 tcg_gen_ext32u_tl(t0, t0);
4919 tcg_gen_ext32u_tl(t1, t1);
4920 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4921 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4922 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4923 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4924 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4925 tcg_temp_free(t3);
4926 tcg_temp_free(t2);
4928 break;
4929 default:
4930 MIPS_INVAL("div1 TX79");
4931 generate_exception_end(ctx, EXCP_RI);
4932 goto out;
4934 out:
4935 tcg_temp_free(t0);
4936 tcg_temp_free(t1);
4938 #endif
4940 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4941 int acc, int rs, int rt)
4943 TCGv t0, t1;
4945 t0 = tcg_temp_new();
4946 t1 = tcg_temp_new();
4948 gen_load_gpr(t0, rs);
4949 gen_load_gpr(t1, rt);
4951 if (acc != 0) {
4952 check_dsp(ctx);
4955 switch (opc) {
4956 case OPC_DIV:
4958 TCGv t2 = tcg_temp_new();
4959 TCGv t3 = tcg_temp_new();
4960 tcg_gen_ext32s_tl(t0, t0);
4961 tcg_gen_ext32s_tl(t1, t1);
4962 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4963 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4964 tcg_gen_and_tl(t2, t2, t3);
4965 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4966 tcg_gen_or_tl(t2, t2, t3);
4967 tcg_gen_movi_tl(t3, 0);
4968 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4969 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4970 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4971 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4972 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4973 tcg_temp_free(t3);
4974 tcg_temp_free(t2);
4976 break;
4977 case OPC_DIVU:
4979 TCGv t2 = tcg_const_tl(0);
4980 TCGv t3 = tcg_const_tl(1);
4981 tcg_gen_ext32u_tl(t0, t0);
4982 tcg_gen_ext32u_tl(t1, t1);
4983 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4984 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4985 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4986 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4987 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4988 tcg_temp_free(t3);
4989 tcg_temp_free(t2);
4991 break;
4992 case OPC_MULT:
4994 TCGv_i32 t2 = tcg_temp_new_i32();
4995 TCGv_i32 t3 = tcg_temp_new_i32();
4996 tcg_gen_trunc_tl_i32(t2, t0);
4997 tcg_gen_trunc_tl_i32(t3, t1);
4998 tcg_gen_muls2_i32(t2, t3, t2, t3);
4999 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5000 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5001 tcg_temp_free_i32(t2);
5002 tcg_temp_free_i32(t3);
5004 break;
5005 case OPC_MULTU:
5007 TCGv_i32 t2 = tcg_temp_new_i32();
5008 TCGv_i32 t3 = tcg_temp_new_i32();
5009 tcg_gen_trunc_tl_i32(t2, t0);
5010 tcg_gen_trunc_tl_i32(t3, t1);
5011 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5012 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5013 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5014 tcg_temp_free_i32(t2);
5015 tcg_temp_free_i32(t3);
5017 break;
5018 #if defined(TARGET_MIPS64)
5019 case OPC_DDIV:
5021 TCGv t2 = tcg_temp_new();
5022 TCGv t3 = tcg_temp_new();
5023 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
5024 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
5025 tcg_gen_and_tl(t2, t2, t3);
5026 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
5027 tcg_gen_or_tl(t2, t2, t3);
5028 tcg_gen_movi_tl(t3, 0);
5029 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
5030 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
5031 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
5032 tcg_temp_free(t3);
5033 tcg_temp_free(t2);
5035 break;
5036 case OPC_DDIVU:
5038 TCGv t2 = tcg_const_tl(0);
5039 TCGv t3 = tcg_const_tl(1);
5040 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
5041 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
5042 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
5043 tcg_temp_free(t3);
5044 tcg_temp_free(t2);
5046 break;
5047 case OPC_DMULT:
5048 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5049 break;
5050 case OPC_DMULTU:
5051 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5052 break;
5053 #endif
5054 case OPC_MADD:
5056 TCGv_i64 t2 = tcg_temp_new_i64();
5057 TCGv_i64 t3 = tcg_temp_new_i64();
5059 tcg_gen_ext_tl_i64(t2, t0);
5060 tcg_gen_ext_tl_i64(t3, t1);
5061 tcg_gen_mul_i64(t2, t2, t3);
5062 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5063 tcg_gen_add_i64(t2, t2, t3);
5064 tcg_temp_free_i64(t3);
5065 gen_move_low32(cpu_LO[acc], t2);
5066 gen_move_high32(cpu_HI[acc], t2);
5067 tcg_temp_free_i64(t2);
5069 break;
5070 case OPC_MADDU:
5072 TCGv_i64 t2 = tcg_temp_new_i64();
5073 TCGv_i64 t3 = tcg_temp_new_i64();
5075 tcg_gen_ext32u_tl(t0, t0);
5076 tcg_gen_ext32u_tl(t1, t1);
5077 tcg_gen_extu_tl_i64(t2, t0);
5078 tcg_gen_extu_tl_i64(t3, t1);
5079 tcg_gen_mul_i64(t2, t2, t3);
5080 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5081 tcg_gen_add_i64(t2, t2, t3);
5082 tcg_temp_free_i64(t3);
5083 gen_move_low32(cpu_LO[acc], t2);
5084 gen_move_high32(cpu_HI[acc], t2);
5085 tcg_temp_free_i64(t2);
5087 break;
5088 case OPC_MSUB:
5090 TCGv_i64 t2 = tcg_temp_new_i64();
5091 TCGv_i64 t3 = tcg_temp_new_i64();
5093 tcg_gen_ext_tl_i64(t2, t0);
5094 tcg_gen_ext_tl_i64(t3, t1);
5095 tcg_gen_mul_i64(t2, t2, t3);
5096 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5097 tcg_gen_sub_i64(t2, t3, t2);
5098 tcg_temp_free_i64(t3);
5099 gen_move_low32(cpu_LO[acc], t2);
5100 gen_move_high32(cpu_HI[acc], t2);
5101 tcg_temp_free_i64(t2);
5103 break;
5104 case OPC_MSUBU:
5106 TCGv_i64 t2 = tcg_temp_new_i64();
5107 TCGv_i64 t3 = tcg_temp_new_i64();
5109 tcg_gen_ext32u_tl(t0, t0);
5110 tcg_gen_ext32u_tl(t1, t1);
5111 tcg_gen_extu_tl_i64(t2, t0);
5112 tcg_gen_extu_tl_i64(t3, t1);
5113 tcg_gen_mul_i64(t2, t2, t3);
5114 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5115 tcg_gen_sub_i64(t2, t3, t2);
5116 tcg_temp_free_i64(t3);
5117 gen_move_low32(cpu_LO[acc], t2);
5118 gen_move_high32(cpu_HI[acc], t2);
5119 tcg_temp_free_i64(t2);
5121 break;
5122 default:
5123 MIPS_INVAL("mul/div");
5124 generate_exception_end(ctx, EXCP_RI);
5125 goto out;
5127 out:
5128 tcg_temp_free(t0);
5129 tcg_temp_free(t1);
5133 * These MULT[U] and MADD[U] instructions implemented in for example
5134 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5135 * architectures are special three-operand variants with the syntax
5137 * MULT[U][1] rd, rs, rt
5139 * such that
5141 * (rd, LO, HI) <- rs * rt
5143 * and
5145 * MADD[U][1] rd, rs, rt
5147 * such that
5149 * (rd, LO, HI) <- (LO, HI) + rs * rt
5151 * where the low-order 32-bits of the result is placed into both the
5152 * GPR rd and the special register LO. The high-order 32-bits of the
5153 * result is placed into the special register HI.
5155 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5156 * which is the zero register that always reads as 0.
5158 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5159 int rd, int rs, int rt)
5161 TCGv t0 = tcg_temp_new();
5162 TCGv t1 = tcg_temp_new();
5163 int acc = 0;
5165 gen_load_gpr(t0, rs);
5166 gen_load_gpr(t1, rt);
5168 switch (opc) {
5169 case MMI_OPC_MULT1:
5170 acc = 1;
5171 /* Fall through */
5172 case OPC_MULT:
5174 TCGv_i32 t2 = tcg_temp_new_i32();
5175 TCGv_i32 t3 = tcg_temp_new_i32();
5176 tcg_gen_trunc_tl_i32(t2, t0);
5177 tcg_gen_trunc_tl_i32(t3, t1);
5178 tcg_gen_muls2_i32(t2, t3, t2, t3);
5179 if (rd) {
5180 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5182 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5183 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5184 tcg_temp_free_i32(t2);
5185 tcg_temp_free_i32(t3);
5187 break;
5188 case MMI_OPC_MULTU1:
5189 acc = 1;
5190 /* Fall through */
5191 case OPC_MULTU:
5193 TCGv_i32 t2 = tcg_temp_new_i32();
5194 TCGv_i32 t3 = tcg_temp_new_i32();
5195 tcg_gen_trunc_tl_i32(t2, t0);
5196 tcg_gen_trunc_tl_i32(t3, t1);
5197 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5198 if (rd) {
5199 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5201 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5202 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5203 tcg_temp_free_i32(t2);
5204 tcg_temp_free_i32(t3);
5206 break;
5207 case MMI_OPC_MADD1:
5208 acc = 1;
5209 /* Fall through */
5210 case MMI_OPC_MADD:
5212 TCGv_i64 t2 = tcg_temp_new_i64();
5213 TCGv_i64 t3 = tcg_temp_new_i64();
5215 tcg_gen_ext_tl_i64(t2, t0);
5216 tcg_gen_ext_tl_i64(t3, t1);
5217 tcg_gen_mul_i64(t2, t2, t3);
5218 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5219 tcg_gen_add_i64(t2, t2, t3);
5220 tcg_temp_free_i64(t3);
5221 gen_move_low32(cpu_LO[acc], t2);
5222 gen_move_high32(cpu_HI[acc], t2);
5223 if (rd) {
5224 gen_move_low32(cpu_gpr[rd], t2);
5226 tcg_temp_free_i64(t2);
5228 break;
5229 case MMI_OPC_MADDU1:
5230 acc = 1;
5231 /* Fall through */
5232 case MMI_OPC_MADDU:
5234 TCGv_i64 t2 = tcg_temp_new_i64();
5235 TCGv_i64 t3 = tcg_temp_new_i64();
5237 tcg_gen_ext32u_tl(t0, t0);
5238 tcg_gen_ext32u_tl(t1, t1);
5239 tcg_gen_extu_tl_i64(t2, t0);
5240 tcg_gen_extu_tl_i64(t3, t1);
5241 tcg_gen_mul_i64(t2, t2, t3);
5242 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5243 tcg_gen_add_i64(t2, t2, t3);
5244 tcg_temp_free_i64(t3);
5245 gen_move_low32(cpu_LO[acc], t2);
5246 gen_move_high32(cpu_HI[acc], t2);
5247 if (rd) {
5248 gen_move_low32(cpu_gpr[rd], t2);
5250 tcg_temp_free_i64(t2);
5252 break;
5253 default:
5254 MIPS_INVAL("mul/madd TXx9");
5255 generate_exception_end(ctx, EXCP_RI);
5256 goto out;
5259 out:
5260 tcg_temp_free(t0);
5261 tcg_temp_free(t1);
5264 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5265 int rd, int rs, int rt)
5267 TCGv t0 = tcg_temp_new();
5268 TCGv t1 = tcg_temp_new();
5270 gen_load_gpr(t0, rs);
5271 gen_load_gpr(t1, rt);
5273 switch (opc) {
5274 case OPC_VR54XX_MULS:
5275 gen_helper_muls(t0, cpu_env, t0, t1);
5276 break;
5277 case OPC_VR54XX_MULSU:
5278 gen_helper_mulsu(t0, cpu_env, t0, t1);
5279 break;
5280 case OPC_VR54XX_MACC:
5281 gen_helper_macc(t0, cpu_env, t0, t1);
5282 break;
5283 case OPC_VR54XX_MACCU:
5284 gen_helper_maccu(t0, cpu_env, t0, t1);
5285 break;
5286 case OPC_VR54XX_MSAC:
5287 gen_helper_msac(t0, cpu_env, t0, t1);
5288 break;
5289 case OPC_VR54XX_MSACU:
5290 gen_helper_msacu(t0, cpu_env, t0, t1);
5291 break;
5292 case OPC_VR54XX_MULHI:
5293 gen_helper_mulhi(t0, cpu_env, t0, t1);
5294 break;
5295 case OPC_VR54XX_MULHIU:
5296 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5297 break;
5298 case OPC_VR54XX_MULSHI:
5299 gen_helper_mulshi(t0, cpu_env, t0, t1);
5300 break;
5301 case OPC_VR54XX_MULSHIU:
5302 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5303 break;
5304 case OPC_VR54XX_MACCHI:
5305 gen_helper_macchi(t0, cpu_env, t0, t1);
5306 break;
5307 case OPC_VR54XX_MACCHIU:
5308 gen_helper_macchiu(t0, cpu_env, t0, t1);
5309 break;
5310 case OPC_VR54XX_MSACHI:
5311 gen_helper_msachi(t0, cpu_env, t0, t1);
5312 break;
5313 case OPC_VR54XX_MSACHIU:
5314 gen_helper_msachiu(t0, cpu_env, t0, t1);
5315 break;
5316 default:
5317 MIPS_INVAL("mul vr54xx");
5318 generate_exception_end(ctx, EXCP_RI);
5319 goto out;
5321 gen_store_gpr(t0, rd);
5323 out:
5324 tcg_temp_free(t0);
5325 tcg_temp_free(t1);
5328 static void gen_cl(DisasContext *ctx, uint32_t opc,
5329 int rd, int rs)
5331 TCGv t0;
5333 if (rd == 0) {
5334 /* Treat as NOP. */
5335 return;
5337 t0 = cpu_gpr[rd];
5338 gen_load_gpr(t0, rs);
5340 switch (opc) {
5341 case OPC_CLO:
5342 case R6_OPC_CLO:
5343 #if defined(TARGET_MIPS64)
5344 case OPC_DCLO:
5345 case R6_OPC_DCLO:
5346 #endif
5347 tcg_gen_not_tl(t0, t0);
5348 break;
5351 switch (opc) {
5352 case OPC_CLO:
5353 case R6_OPC_CLO:
5354 case OPC_CLZ:
5355 case R6_OPC_CLZ:
5356 tcg_gen_ext32u_tl(t0, t0);
5357 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5358 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5359 break;
5360 #if defined(TARGET_MIPS64)
5361 case OPC_DCLO:
5362 case R6_OPC_DCLO:
5363 case OPC_DCLZ:
5364 case R6_OPC_DCLZ:
5365 tcg_gen_clzi_i64(t0, t0, 64);
5366 break;
5367 #endif
5371 /* Godson integer instructions */
5372 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5373 int rd, int rs, int rt)
5375 TCGv t0, t1;
5377 if (rd == 0) {
5378 /* Treat as NOP. */
5379 return;
5382 switch (opc) {
5383 case OPC_MULT_G_2E:
5384 case OPC_MULT_G_2F:
5385 case OPC_MULTU_G_2E:
5386 case OPC_MULTU_G_2F:
5387 #if defined(TARGET_MIPS64)
5388 case OPC_DMULT_G_2E:
5389 case OPC_DMULT_G_2F:
5390 case OPC_DMULTU_G_2E:
5391 case OPC_DMULTU_G_2F:
5392 #endif
5393 t0 = tcg_temp_new();
5394 t1 = tcg_temp_new();
5395 break;
5396 default:
5397 t0 = tcg_temp_local_new();
5398 t1 = tcg_temp_local_new();
5399 break;
5402 gen_load_gpr(t0, rs);
5403 gen_load_gpr(t1, rt);
5405 switch (opc) {
5406 case OPC_MULT_G_2E:
5407 case OPC_MULT_G_2F:
5408 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5409 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5410 break;
5411 case OPC_MULTU_G_2E:
5412 case OPC_MULTU_G_2F:
5413 tcg_gen_ext32u_tl(t0, t0);
5414 tcg_gen_ext32u_tl(t1, t1);
5415 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5416 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5417 break;
5418 case OPC_DIV_G_2E:
5419 case OPC_DIV_G_2F:
5421 TCGLabel *l1 = gen_new_label();
5422 TCGLabel *l2 = gen_new_label();
5423 TCGLabel *l3 = gen_new_label();
5424 tcg_gen_ext32s_tl(t0, t0);
5425 tcg_gen_ext32s_tl(t1, t1);
5426 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5427 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5428 tcg_gen_br(l3);
5429 gen_set_label(l1);
5430 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5431 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5432 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5433 tcg_gen_br(l3);
5434 gen_set_label(l2);
5435 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5436 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5437 gen_set_label(l3);
5439 break;
5440 case OPC_DIVU_G_2E:
5441 case OPC_DIVU_G_2F:
5443 TCGLabel *l1 = gen_new_label();
5444 TCGLabel *l2 = gen_new_label();
5445 tcg_gen_ext32u_tl(t0, t0);
5446 tcg_gen_ext32u_tl(t1, t1);
5447 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5448 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5449 tcg_gen_br(l2);
5450 gen_set_label(l1);
5451 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5452 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5453 gen_set_label(l2);
5455 break;
5456 case OPC_MOD_G_2E:
5457 case OPC_MOD_G_2F:
5459 TCGLabel *l1 = gen_new_label();
5460 TCGLabel *l2 = gen_new_label();
5461 TCGLabel *l3 = gen_new_label();
5462 tcg_gen_ext32u_tl(t0, t0);
5463 tcg_gen_ext32u_tl(t1, t1);
5464 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5466 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5467 gen_set_label(l1);
5468 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5469 tcg_gen_br(l3);
5470 gen_set_label(l2);
5471 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5472 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5473 gen_set_label(l3);
5475 break;
5476 case OPC_MODU_G_2E:
5477 case OPC_MODU_G_2F:
5479 TCGLabel *l1 = gen_new_label();
5480 TCGLabel *l2 = gen_new_label();
5481 tcg_gen_ext32u_tl(t0, t0);
5482 tcg_gen_ext32u_tl(t1, t1);
5483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5484 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5485 tcg_gen_br(l2);
5486 gen_set_label(l1);
5487 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5488 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5489 gen_set_label(l2);
5491 break;
5492 #if defined(TARGET_MIPS64)
5493 case OPC_DMULT_G_2E:
5494 case OPC_DMULT_G_2F:
5495 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5496 break;
5497 case OPC_DMULTU_G_2E:
5498 case OPC_DMULTU_G_2F:
5499 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5500 break;
5501 case OPC_DDIV_G_2E:
5502 case OPC_DDIV_G_2F:
5504 TCGLabel *l1 = gen_new_label();
5505 TCGLabel *l2 = gen_new_label();
5506 TCGLabel *l3 = gen_new_label();
5507 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5508 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5509 tcg_gen_br(l3);
5510 gen_set_label(l1);
5511 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5512 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5513 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5514 tcg_gen_br(l3);
5515 gen_set_label(l2);
5516 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5517 gen_set_label(l3);
5519 break;
5520 case OPC_DDIVU_G_2E:
5521 case OPC_DDIVU_G_2F:
5523 TCGLabel *l1 = gen_new_label();
5524 TCGLabel *l2 = gen_new_label();
5525 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5526 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5527 tcg_gen_br(l2);
5528 gen_set_label(l1);
5529 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5530 gen_set_label(l2);
5532 break;
5533 case OPC_DMOD_G_2E:
5534 case OPC_DMOD_G_2F:
5536 TCGLabel *l1 = gen_new_label();
5537 TCGLabel *l2 = gen_new_label();
5538 TCGLabel *l3 = gen_new_label();
5539 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5540 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5541 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5542 gen_set_label(l1);
5543 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5544 tcg_gen_br(l3);
5545 gen_set_label(l2);
5546 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5547 gen_set_label(l3);
5549 break;
5550 case OPC_DMODU_G_2E:
5551 case OPC_DMODU_G_2F:
5553 TCGLabel *l1 = gen_new_label();
5554 TCGLabel *l2 = gen_new_label();
5555 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5556 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5557 tcg_gen_br(l2);
5558 gen_set_label(l1);
5559 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5560 gen_set_label(l2);
5562 break;
5563 #endif
5566 tcg_temp_free(t0);
5567 tcg_temp_free(t1);
5570 /* Loongson multimedia instructions */
5571 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5573 uint32_t opc, shift_max;
5574 TCGv_i64 t0, t1;
5575 TCGCond cond;
5577 opc = MASK_LMMI(ctx->opcode);
5578 switch (opc) {
5579 case OPC_ADD_CP2:
5580 case OPC_SUB_CP2:
5581 case OPC_DADD_CP2:
5582 case OPC_DSUB_CP2:
5583 t0 = tcg_temp_local_new_i64();
5584 t1 = tcg_temp_local_new_i64();
5585 break;
5586 default:
5587 t0 = tcg_temp_new_i64();
5588 t1 = tcg_temp_new_i64();
5589 break;
5592 check_cp1_enabled(ctx);
5593 gen_load_fpr64(ctx, t0, rs);
5594 gen_load_fpr64(ctx, t1, rt);
5596 switch (opc) {
5597 case OPC_PADDSH:
5598 gen_helper_paddsh(t0, t0, t1);
5599 break;
5600 case OPC_PADDUSH:
5601 gen_helper_paddush(t0, t0, t1);
5602 break;
5603 case OPC_PADDH:
5604 gen_helper_paddh(t0, t0, t1);
5605 break;
5606 case OPC_PADDW:
5607 gen_helper_paddw(t0, t0, t1);
5608 break;
5609 case OPC_PADDSB:
5610 gen_helper_paddsb(t0, t0, t1);
5611 break;
5612 case OPC_PADDUSB:
5613 gen_helper_paddusb(t0, t0, t1);
5614 break;
5615 case OPC_PADDB:
5616 gen_helper_paddb(t0, t0, t1);
5617 break;
5619 case OPC_PSUBSH:
5620 gen_helper_psubsh(t0, t0, t1);
5621 break;
5622 case OPC_PSUBUSH:
5623 gen_helper_psubush(t0, t0, t1);
5624 break;
5625 case OPC_PSUBH:
5626 gen_helper_psubh(t0, t0, t1);
5627 break;
5628 case OPC_PSUBW:
5629 gen_helper_psubw(t0, t0, t1);
5630 break;
5631 case OPC_PSUBSB:
5632 gen_helper_psubsb(t0, t0, t1);
5633 break;
5634 case OPC_PSUBUSB:
5635 gen_helper_psubusb(t0, t0, t1);
5636 break;
5637 case OPC_PSUBB:
5638 gen_helper_psubb(t0, t0, t1);
5639 break;
5641 case OPC_PSHUFH:
5642 gen_helper_pshufh(t0, t0, t1);
5643 break;
5644 case OPC_PACKSSWH:
5645 gen_helper_packsswh(t0, t0, t1);
5646 break;
5647 case OPC_PACKSSHB:
5648 gen_helper_packsshb(t0, t0, t1);
5649 break;
5650 case OPC_PACKUSHB:
5651 gen_helper_packushb(t0, t0, t1);
5652 break;
5654 case OPC_PUNPCKLHW:
5655 gen_helper_punpcklhw(t0, t0, t1);
5656 break;
5657 case OPC_PUNPCKHHW:
5658 gen_helper_punpckhhw(t0, t0, t1);
5659 break;
5660 case OPC_PUNPCKLBH:
5661 gen_helper_punpcklbh(t0, t0, t1);
5662 break;
5663 case OPC_PUNPCKHBH:
5664 gen_helper_punpckhbh(t0, t0, t1);
5665 break;
5666 case OPC_PUNPCKLWD:
5667 gen_helper_punpcklwd(t0, t0, t1);
5668 break;
5669 case OPC_PUNPCKHWD:
5670 gen_helper_punpckhwd(t0, t0, t1);
5671 break;
5673 case OPC_PAVGH:
5674 gen_helper_pavgh(t0, t0, t1);
5675 break;
5676 case OPC_PAVGB:
5677 gen_helper_pavgb(t0, t0, t1);
5678 break;
5679 case OPC_PMAXSH:
5680 gen_helper_pmaxsh(t0, t0, t1);
5681 break;
5682 case OPC_PMINSH:
5683 gen_helper_pminsh(t0, t0, t1);
5684 break;
5685 case OPC_PMAXUB:
5686 gen_helper_pmaxub(t0, t0, t1);
5687 break;
5688 case OPC_PMINUB:
5689 gen_helper_pminub(t0, t0, t1);
5690 break;
5692 case OPC_PCMPEQW:
5693 gen_helper_pcmpeqw(t0, t0, t1);
5694 break;
5695 case OPC_PCMPGTW:
5696 gen_helper_pcmpgtw(t0, t0, t1);
5697 break;
5698 case OPC_PCMPEQH:
5699 gen_helper_pcmpeqh(t0, t0, t1);
5700 break;
5701 case OPC_PCMPGTH:
5702 gen_helper_pcmpgth(t0, t0, t1);
5703 break;
5704 case OPC_PCMPEQB:
5705 gen_helper_pcmpeqb(t0, t0, t1);
5706 break;
5707 case OPC_PCMPGTB:
5708 gen_helper_pcmpgtb(t0, t0, t1);
5709 break;
5711 case OPC_PSLLW:
5712 gen_helper_psllw(t0, t0, t1);
5713 break;
5714 case OPC_PSLLH:
5715 gen_helper_psllh(t0, t0, t1);
5716 break;
5717 case OPC_PSRLW:
5718 gen_helper_psrlw(t0, t0, t1);
5719 break;
5720 case OPC_PSRLH:
5721 gen_helper_psrlh(t0, t0, t1);
5722 break;
5723 case OPC_PSRAW:
5724 gen_helper_psraw(t0, t0, t1);
5725 break;
5726 case OPC_PSRAH:
5727 gen_helper_psrah(t0, t0, t1);
5728 break;
5730 case OPC_PMULLH:
5731 gen_helper_pmullh(t0, t0, t1);
5732 break;
5733 case OPC_PMULHH:
5734 gen_helper_pmulhh(t0, t0, t1);
5735 break;
5736 case OPC_PMULHUH:
5737 gen_helper_pmulhuh(t0, t0, t1);
5738 break;
5739 case OPC_PMADDHW:
5740 gen_helper_pmaddhw(t0, t0, t1);
5741 break;
5743 case OPC_PASUBUB:
5744 gen_helper_pasubub(t0, t0, t1);
5745 break;
5746 case OPC_BIADD:
5747 gen_helper_biadd(t0, t0);
5748 break;
5749 case OPC_PMOVMSKB:
5750 gen_helper_pmovmskb(t0, t0);
5751 break;
5753 case OPC_PADDD:
5754 tcg_gen_add_i64(t0, t0, t1);
5755 break;
5756 case OPC_PSUBD:
5757 tcg_gen_sub_i64(t0, t0, t1);
5758 break;
5759 case OPC_XOR_CP2:
5760 tcg_gen_xor_i64(t0, t0, t1);
5761 break;
5762 case OPC_NOR_CP2:
5763 tcg_gen_nor_i64(t0, t0, t1);
5764 break;
5765 case OPC_AND_CP2:
5766 tcg_gen_and_i64(t0, t0, t1);
5767 break;
5768 case OPC_OR_CP2:
5769 tcg_gen_or_i64(t0, t0, t1);
5770 break;
5772 case OPC_PANDN:
5773 tcg_gen_andc_i64(t0, t1, t0);
5774 break;
5776 case OPC_PINSRH_0:
5777 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5778 break;
5779 case OPC_PINSRH_1:
5780 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5781 break;
5782 case OPC_PINSRH_2:
5783 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5784 break;
5785 case OPC_PINSRH_3:
5786 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5787 break;
5789 case OPC_PEXTRH:
5790 tcg_gen_andi_i64(t1, t1, 3);
5791 tcg_gen_shli_i64(t1, t1, 4);
5792 tcg_gen_shr_i64(t0, t0, t1);
5793 tcg_gen_ext16u_i64(t0, t0);
5794 break;
5796 case OPC_ADDU_CP2:
5797 tcg_gen_add_i64(t0, t0, t1);
5798 tcg_gen_ext32s_i64(t0, t0);
5799 break;
5800 case OPC_SUBU_CP2:
5801 tcg_gen_sub_i64(t0, t0, t1);
5802 tcg_gen_ext32s_i64(t0, t0);
5803 break;
5805 case OPC_SLL_CP2:
5806 shift_max = 32;
5807 goto do_shift;
5808 case OPC_SRL_CP2:
5809 shift_max = 32;
5810 goto do_shift;
5811 case OPC_SRA_CP2:
5812 shift_max = 32;
5813 goto do_shift;
5814 case OPC_DSLL_CP2:
5815 shift_max = 64;
5816 goto do_shift;
5817 case OPC_DSRL_CP2:
5818 shift_max = 64;
5819 goto do_shift;
5820 case OPC_DSRA_CP2:
5821 shift_max = 64;
5822 goto do_shift;
5823 do_shift:
5824 /* Make sure shift count isn't TCG undefined behaviour. */
5825 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5827 switch (opc) {
5828 case OPC_SLL_CP2:
5829 case OPC_DSLL_CP2:
5830 tcg_gen_shl_i64(t0, t0, t1);
5831 break;
5832 case OPC_SRA_CP2:
5833 case OPC_DSRA_CP2:
5835 * Since SRA is UndefinedResult without sign-extended inputs,
5836 * we can treat SRA and DSRA the same.
5838 tcg_gen_sar_i64(t0, t0, t1);
5839 break;
5840 case OPC_SRL_CP2:
5841 /* We want to shift in zeros for SRL; zero-extend first. */
5842 tcg_gen_ext32u_i64(t0, t0);
5843 /* FALLTHRU */
5844 case OPC_DSRL_CP2:
5845 tcg_gen_shr_i64(t0, t0, t1);
5846 break;
5849 if (shift_max == 32) {
5850 tcg_gen_ext32s_i64(t0, t0);
5853 /* Shifts larger than MAX produce zero. */
5854 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5855 tcg_gen_neg_i64(t1, t1);
5856 tcg_gen_and_i64(t0, t0, t1);
5857 break;
5859 case OPC_ADD_CP2:
5860 case OPC_DADD_CP2:
5862 TCGv_i64 t2 = tcg_temp_new_i64();
5863 TCGLabel *lab = gen_new_label();
5865 tcg_gen_mov_i64(t2, t0);
5866 tcg_gen_add_i64(t0, t1, t2);
5867 if (opc == OPC_ADD_CP2) {
5868 tcg_gen_ext32s_i64(t0, t0);
5870 tcg_gen_xor_i64(t1, t1, t2);
5871 tcg_gen_xor_i64(t2, t2, t0);
5872 tcg_gen_andc_i64(t1, t2, t1);
5873 tcg_temp_free_i64(t2);
5874 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5875 generate_exception(ctx, EXCP_OVERFLOW);
5876 gen_set_label(lab);
5877 break;
5880 case OPC_SUB_CP2:
5881 case OPC_DSUB_CP2:
5883 TCGv_i64 t2 = tcg_temp_new_i64();
5884 TCGLabel *lab = gen_new_label();
5886 tcg_gen_mov_i64(t2, t0);
5887 tcg_gen_sub_i64(t0, t1, t2);
5888 if (opc == OPC_SUB_CP2) {
5889 tcg_gen_ext32s_i64(t0, t0);
5891 tcg_gen_xor_i64(t1, t1, t2);
5892 tcg_gen_xor_i64(t2, t2, t0);
5893 tcg_gen_and_i64(t1, t1, t2);
5894 tcg_temp_free_i64(t2);
5895 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5896 generate_exception(ctx, EXCP_OVERFLOW);
5897 gen_set_label(lab);
5898 break;
5901 case OPC_PMULUW:
5902 tcg_gen_ext32u_i64(t0, t0);
5903 tcg_gen_ext32u_i64(t1, t1);
5904 tcg_gen_mul_i64(t0, t0, t1);
5905 break;
5907 case OPC_SEQU_CP2:
5908 case OPC_SEQ_CP2:
5909 cond = TCG_COND_EQ;
5910 goto do_cc_cond;
5911 break;
5912 case OPC_SLTU_CP2:
5913 cond = TCG_COND_LTU;
5914 goto do_cc_cond;
5915 break;
5916 case OPC_SLT_CP2:
5917 cond = TCG_COND_LT;
5918 goto do_cc_cond;
5919 break;
5920 case OPC_SLEU_CP2:
5921 cond = TCG_COND_LEU;
5922 goto do_cc_cond;
5923 break;
5924 case OPC_SLE_CP2:
5925 cond = TCG_COND_LE;
5926 do_cc_cond:
5928 int cc = (ctx->opcode >> 8) & 0x7;
5929 TCGv_i64 t64 = tcg_temp_new_i64();
5930 TCGv_i32 t32 = tcg_temp_new_i32();
5932 tcg_gen_setcond_i64(cond, t64, t0, t1);
5933 tcg_gen_extrl_i64_i32(t32, t64);
5934 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5935 get_fp_bit(cc), 1);
5937 tcg_temp_free_i32(t32);
5938 tcg_temp_free_i64(t64);
5940 goto no_rd;
5941 break;
5942 default:
5943 MIPS_INVAL("loongson_cp2");
5944 generate_exception_end(ctx, EXCP_RI);
5945 return;
5948 gen_store_fpr64(ctx, t0, rd);
5950 no_rd:
5951 tcg_temp_free_i64(t0);
5952 tcg_temp_free_i64(t1);
5955 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5956 int rs, int rd)
5958 TCGv t0, t1, t2;
5959 TCGv_i32 fp0;
5960 #if defined(TARGET_MIPS64)
5961 int lsq_rt1 = ctx->opcode & 0x1f;
5962 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5963 #endif
5964 int shf_offset = sextract32(ctx->opcode, 6, 8);
5966 t0 = tcg_temp_new();
5968 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5969 #if defined(TARGET_MIPS64)
5970 case OPC_GSLQ:
5971 t1 = tcg_temp_new();
5972 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5973 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5974 ctx->default_tcg_memop_mask);
5975 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5976 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5977 ctx->default_tcg_memop_mask);
5978 gen_store_gpr(t1, rt);
5979 gen_store_gpr(t0, lsq_rt1);
5980 tcg_temp_free(t1);
5981 break;
5982 case OPC_GSLQC1:
5983 check_cp1_enabled(ctx);
5984 t1 = tcg_temp_new();
5985 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5986 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5987 ctx->default_tcg_memop_mask);
5988 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5989 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5990 ctx->default_tcg_memop_mask);
5991 gen_store_fpr64(ctx, t1, rt);
5992 gen_store_fpr64(ctx, t0, lsq_rt1);
5993 tcg_temp_free(t1);
5994 break;
5995 case OPC_GSSQ:
5996 t1 = tcg_temp_new();
5997 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5998 gen_load_gpr(t1, rt);
5999 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6000 ctx->default_tcg_memop_mask);
6001 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
6002 gen_load_gpr(t1, lsq_rt1);
6003 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6004 ctx->default_tcg_memop_mask);
6005 tcg_temp_free(t1);
6006 break;
6007 case OPC_GSSQC1:
6008 check_cp1_enabled(ctx);
6009 t1 = tcg_temp_new();
6010 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
6011 gen_load_fpr64(ctx, t1, rt);
6012 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6013 ctx->default_tcg_memop_mask);
6014 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
6015 gen_load_fpr64(ctx, t1, lsq_rt1);
6016 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6017 ctx->default_tcg_memop_mask);
6018 tcg_temp_free(t1);
6019 break;
6020 #endif
6021 case OPC_GSSHFL:
6022 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6023 case OPC_GSLWLC1:
6024 check_cp1_enabled(ctx);
6025 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6026 t1 = tcg_temp_new();
6027 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6028 tcg_gen_andi_tl(t1, t0, 3);
6029 #ifndef TARGET_WORDS_BIGENDIAN
6030 tcg_gen_xori_tl(t1, t1, 3);
6031 #endif
6032 tcg_gen_shli_tl(t1, t1, 3);
6033 tcg_gen_andi_tl(t0, t0, ~3);
6034 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6035 tcg_gen_shl_tl(t0, t0, t1);
6036 t2 = tcg_const_tl(-1);
6037 tcg_gen_shl_tl(t2, t2, t1);
6038 fp0 = tcg_temp_new_i32();
6039 gen_load_fpr32(ctx, fp0, rt);
6040 tcg_gen_ext_i32_tl(t1, fp0);
6041 tcg_gen_andc_tl(t1, t1, t2);
6042 tcg_temp_free(t2);
6043 tcg_gen_or_tl(t0, t0, t1);
6044 tcg_temp_free(t1);
6045 #if defined(TARGET_MIPS64)
6046 tcg_gen_extrl_i64_i32(fp0, t0);
6047 #else
6048 tcg_gen_ext32s_tl(fp0, t0);
6049 #endif
6050 gen_store_fpr32(ctx, fp0, rt);
6051 tcg_temp_free_i32(fp0);
6052 break;
6053 case OPC_GSLWRC1:
6054 check_cp1_enabled(ctx);
6055 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6056 t1 = tcg_temp_new();
6057 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6058 tcg_gen_andi_tl(t1, t0, 3);
6059 #ifdef TARGET_WORDS_BIGENDIAN
6060 tcg_gen_xori_tl(t1, t1, 3);
6061 #endif
6062 tcg_gen_shli_tl(t1, t1, 3);
6063 tcg_gen_andi_tl(t0, t0, ~3);
6064 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6065 tcg_gen_shr_tl(t0, t0, t1);
6066 tcg_gen_xori_tl(t1, t1, 31);
6067 t2 = tcg_const_tl(0xfffffffeull);
6068 tcg_gen_shl_tl(t2, t2, t1);
6069 fp0 = tcg_temp_new_i32();
6070 gen_load_fpr32(ctx, fp0, rt);
6071 tcg_gen_ext_i32_tl(t1, fp0);
6072 tcg_gen_and_tl(t1, t1, t2);
6073 tcg_temp_free(t2);
6074 tcg_gen_or_tl(t0, t0, t1);
6075 tcg_temp_free(t1);
6076 #if defined(TARGET_MIPS64)
6077 tcg_gen_extrl_i64_i32(fp0, t0);
6078 #else
6079 tcg_gen_ext32s_tl(fp0, t0);
6080 #endif
6081 gen_store_fpr32(ctx, fp0, rt);
6082 tcg_temp_free_i32(fp0);
6083 break;
6084 #if defined(TARGET_MIPS64)
6085 case OPC_GSLDLC1:
6086 check_cp1_enabled(ctx);
6087 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6088 t1 = tcg_temp_new();
6089 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6090 tcg_gen_andi_tl(t1, t0, 7);
6091 #ifndef TARGET_WORDS_BIGENDIAN
6092 tcg_gen_xori_tl(t1, t1, 7);
6093 #endif
6094 tcg_gen_shli_tl(t1, t1, 3);
6095 tcg_gen_andi_tl(t0, t0, ~7);
6096 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6097 tcg_gen_shl_tl(t0, t0, t1);
6098 t2 = tcg_const_tl(-1);
6099 tcg_gen_shl_tl(t2, t2, t1);
6100 gen_load_fpr64(ctx, t1, rt);
6101 tcg_gen_andc_tl(t1, t1, t2);
6102 tcg_temp_free(t2);
6103 tcg_gen_or_tl(t0, t0, t1);
6104 tcg_temp_free(t1);
6105 gen_store_fpr64(ctx, t0, rt);
6106 break;
6107 case OPC_GSLDRC1:
6108 check_cp1_enabled(ctx);
6109 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6110 t1 = tcg_temp_new();
6111 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6112 tcg_gen_andi_tl(t1, t0, 7);
6113 #ifdef TARGET_WORDS_BIGENDIAN
6114 tcg_gen_xori_tl(t1, t1, 7);
6115 #endif
6116 tcg_gen_shli_tl(t1, t1, 3);
6117 tcg_gen_andi_tl(t0, t0, ~7);
6118 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6119 tcg_gen_shr_tl(t0, t0, t1);
6120 tcg_gen_xori_tl(t1, t1, 63);
6121 t2 = tcg_const_tl(0xfffffffffffffffeull);
6122 tcg_gen_shl_tl(t2, t2, t1);
6123 gen_load_fpr64(ctx, t1, rt);
6124 tcg_gen_and_tl(t1, t1, t2);
6125 tcg_temp_free(t2);
6126 tcg_gen_or_tl(t0, t0, t1);
6127 tcg_temp_free(t1);
6128 gen_store_fpr64(ctx, t0, rt);
6129 break;
6130 #endif
6131 default:
6132 MIPS_INVAL("loongson_gsshfl");
6133 generate_exception_end(ctx, EXCP_RI);
6134 break;
6136 break;
6137 case OPC_GSSHFS:
6138 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6139 case OPC_GSSWLC1:
6140 check_cp1_enabled(ctx);
6141 t1 = tcg_temp_new();
6142 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6143 fp0 = tcg_temp_new_i32();
6144 gen_load_fpr32(ctx, fp0, rt);
6145 tcg_gen_ext_i32_tl(t1, fp0);
6146 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
6147 tcg_temp_free_i32(fp0);
6148 tcg_temp_free(t1);
6149 break;
6150 case OPC_GSSWRC1:
6151 check_cp1_enabled(ctx);
6152 t1 = tcg_temp_new();
6153 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6154 fp0 = tcg_temp_new_i32();
6155 gen_load_fpr32(ctx, fp0, rt);
6156 tcg_gen_ext_i32_tl(t1, fp0);
6157 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
6158 tcg_temp_free_i32(fp0);
6159 tcg_temp_free(t1);
6160 break;
6161 #if defined(TARGET_MIPS64)
6162 case OPC_GSSDLC1:
6163 check_cp1_enabled(ctx);
6164 t1 = tcg_temp_new();
6165 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6166 gen_load_fpr64(ctx, t1, rt);
6167 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
6168 tcg_temp_free(t1);
6169 break;
6170 case OPC_GSSDRC1:
6171 check_cp1_enabled(ctx);
6172 t1 = tcg_temp_new();
6173 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6174 gen_load_fpr64(ctx, t1, rt);
6175 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
6176 tcg_temp_free(t1);
6177 break;
6178 #endif
6179 default:
6180 MIPS_INVAL("loongson_gsshfs");
6181 generate_exception_end(ctx, EXCP_RI);
6182 break;
6184 break;
6185 default:
6186 MIPS_INVAL("loongson_gslsq");
6187 generate_exception_end(ctx, EXCP_RI);
6188 break;
6190 tcg_temp_free(t0);
6193 /* Loongson EXT LDC2/SDC2 */
6194 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
6195 int rs, int rd)
6197 int offset = sextract32(ctx->opcode, 3, 8);
6198 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
6199 TCGv t0, t1;
6200 TCGv_i32 fp0;
6202 /* Pre-conditions */
6203 switch (opc) {
6204 case OPC_GSLBX:
6205 case OPC_GSLHX:
6206 case OPC_GSLWX:
6207 case OPC_GSLDX:
6208 /* prefetch, implement as NOP */
6209 if (rt == 0) {
6210 return;
6212 break;
6213 case OPC_GSSBX:
6214 case OPC_GSSHX:
6215 case OPC_GSSWX:
6216 case OPC_GSSDX:
6217 break;
6218 case OPC_GSLWXC1:
6219 #if defined(TARGET_MIPS64)
6220 case OPC_GSLDXC1:
6221 #endif
6222 check_cp1_enabled(ctx);
6223 /* prefetch, implement as NOP */
6224 if (rt == 0) {
6225 return;
6227 break;
6228 case OPC_GSSWXC1:
6229 #if defined(TARGET_MIPS64)
6230 case OPC_GSSDXC1:
6231 #endif
6232 check_cp1_enabled(ctx);
6233 break;
6234 default:
6235 MIPS_INVAL("loongson_lsdc2");
6236 generate_exception_end(ctx, EXCP_RI);
6237 return;
6238 break;
6241 t0 = tcg_temp_new();
6243 gen_base_offset_addr(ctx, t0, rs, offset);
6244 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6246 switch (opc) {
6247 case OPC_GSLBX:
6248 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
6249 gen_store_gpr(t0, rt);
6250 break;
6251 case OPC_GSLHX:
6252 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
6253 ctx->default_tcg_memop_mask);
6254 gen_store_gpr(t0, rt);
6255 break;
6256 case OPC_GSLWX:
6257 gen_base_offset_addr(ctx, t0, rs, offset);
6258 if (rd) {
6259 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6261 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
6262 ctx->default_tcg_memop_mask);
6263 gen_store_gpr(t0, rt);
6264 break;
6265 #if defined(TARGET_MIPS64)
6266 case OPC_GSLDX:
6267 gen_base_offset_addr(ctx, t0, rs, offset);
6268 if (rd) {
6269 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6271 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6272 ctx->default_tcg_memop_mask);
6273 gen_store_gpr(t0, rt);
6274 break;
6275 #endif
6276 case OPC_GSLWXC1:
6277 check_cp1_enabled(ctx);
6278 gen_base_offset_addr(ctx, t0, rs, offset);
6279 if (rd) {
6280 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6282 fp0 = tcg_temp_new_i32();
6283 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
6284 ctx->default_tcg_memop_mask);
6285 gen_store_fpr32(ctx, fp0, rt);
6286 tcg_temp_free_i32(fp0);
6287 break;
6288 #if defined(TARGET_MIPS64)
6289 case OPC_GSLDXC1:
6290 check_cp1_enabled(ctx);
6291 gen_base_offset_addr(ctx, t0, rs, offset);
6292 if (rd) {
6293 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6295 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6296 ctx->default_tcg_memop_mask);
6297 gen_store_fpr64(ctx, t0, rt);
6298 break;
6299 #endif
6300 case OPC_GSSBX:
6301 t1 = tcg_temp_new();
6302 gen_load_gpr(t1, rt);
6303 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
6304 tcg_temp_free(t1);
6305 break;
6306 case OPC_GSSHX:
6307 t1 = tcg_temp_new();
6308 gen_load_gpr(t1, rt);
6309 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
6310 ctx->default_tcg_memop_mask);
6311 tcg_temp_free(t1);
6312 break;
6313 case OPC_GSSWX:
6314 t1 = tcg_temp_new();
6315 gen_load_gpr(t1, rt);
6316 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
6317 ctx->default_tcg_memop_mask);
6318 tcg_temp_free(t1);
6319 break;
6320 #if defined(TARGET_MIPS64)
6321 case OPC_GSSDX:
6322 t1 = tcg_temp_new();
6323 gen_load_gpr(t1, rt);
6324 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6325 ctx->default_tcg_memop_mask);
6326 tcg_temp_free(t1);
6327 break;
6328 #endif
6329 case OPC_GSSWXC1:
6330 fp0 = tcg_temp_new_i32();
6331 gen_load_fpr32(ctx, fp0, rt);
6332 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
6333 ctx->default_tcg_memop_mask);
6334 tcg_temp_free_i32(fp0);
6335 break;
6336 #if defined(TARGET_MIPS64)
6337 case OPC_GSSDXC1:
6338 t1 = tcg_temp_new();
6339 gen_load_fpr64(ctx, t1, rt);
6340 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
6341 ctx->default_tcg_memop_mask);
6342 tcg_temp_free(t1);
6343 break;
6344 #endif
6345 default:
6346 break;
6349 tcg_temp_free(t0);
6352 /* Traps */
6353 static void gen_trap(DisasContext *ctx, uint32_t opc,
6354 int rs, int rt, int16_t imm)
6356 int cond;
6357 TCGv t0 = tcg_temp_new();
6358 TCGv t1 = tcg_temp_new();
6360 cond = 0;
6361 /* Load needed operands */
6362 switch (opc) {
6363 case OPC_TEQ:
6364 case OPC_TGE:
6365 case OPC_TGEU:
6366 case OPC_TLT:
6367 case OPC_TLTU:
6368 case OPC_TNE:
6369 /* Compare two registers */
6370 if (rs != rt) {
6371 gen_load_gpr(t0, rs);
6372 gen_load_gpr(t1, rt);
6373 cond = 1;
6375 break;
6376 case OPC_TEQI:
6377 case OPC_TGEI:
6378 case OPC_TGEIU:
6379 case OPC_TLTI:
6380 case OPC_TLTIU:
6381 case OPC_TNEI:
6382 /* Compare register to immediate */
6383 if (rs != 0 || imm != 0) {
6384 gen_load_gpr(t0, rs);
6385 tcg_gen_movi_tl(t1, (int32_t)imm);
6386 cond = 1;
6388 break;
6390 if (cond == 0) {
6391 switch (opc) {
6392 case OPC_TEQ: /* rs == rs */
6393 case OPC_TEQI: /* r0 == 0 */
6394 case OPC_TGE: /* rs >= rs */
6395 case OPC_TGEI: /* r0 >= 0 */
6396 case OPC_TGEU: /* rs >= rs unsigned */
6397 case OPC_TGEIU: /* r0 >= 0 unsigned */
6398 /* Always trap */
6399 generate_exception_end(ctx, EXCP_TRAP);
6400 break;
6401 case OPC_TLT: /* rs < rs */
6402 case OPC_TLTI: /* r0 < 0 */
6403 case OPC_TLTU: /* rs < rs unsigned */
6404 case OPC_TLTIU: /* r0 < 0 unsigned */
6405 case OPC_TNE: /* rs != rs */
6406 case OPC_TNEI: /* r0 != 0 */
6407 /* Never trap: treat as NOP. */
6408 break;
6410 } else {
6411 TCGLabel *l1 = gen_new_label();
6413 switch (opc) {
6414 case OPC_TEQ:
6415 case OPC_TEQI:
6416 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6417 break;
6418 case OPC_TGE:
6419 case OPC_TGEI:
6420 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6421 break;
6422 case OPC_TGEU:
6423 case OPC_TGEIU:
6424 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6425 break;
6426 case OPC_TLT:
6427 case OPC_TLTI:
6428 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6429 break;
6430 case OPC_TLTU:
6431 case OPC_TLTIU:
6432 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6433 break;
6434 case OPC_TNE:
6435 case OPC_TNEI:
6436 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6437 break;
6439 generate_exception(ctx, EXCP_TRAP);
6440 gen_set_label(l1);
6442 tcg_temp_free(t0);
6443 tcg_temp_free(t1);
6446 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6448 if (unlikely(ctx->base.singlestep_enabled)) {
6449 return false;
6452 #ifndef CONFIG_USER_ONLY
6453 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6454 #else
6455 return true;
6456 #endif
6459 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6461 if (use_goto_tb(ctx, dest)) {
6462 tcg_gen_goto_tb(n);
6463 gen_save_pc(dest);
6464 tcg_gen_exit_tb(ctx->base.tb, n);
6465 } else {
6466 gen_save_pc(dest);
6467 if (ctx->base.singlestep_enabled) {
6468 save_cpu_state(ctx, 0);
6469 gen_helper_raise_exception_debug(cpu_env);
6471 tcg_gen_lookup_and_goto_ptr();
6475 /* Branches (before delay slot) */
6476 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6477 int insn_bytes,
6478 int rs, int rt, int32_t offset,
6479 int delayslot_size)
6481 target_ulong btgt = -1;
6482 int blink = 0;
6483 int bcond_compute = 0;
6484 TCGv t0 = tcg_temp_new();
6485 TCGv t1 = tcg_temp_new();
6487 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6488 #ifdef MIPS_DEBUG_DISAS
6489 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6490 TARGET_FMT_lx "\n", ctx->base.pc_next);
6491 #endif
6492 generate_exception_end(ctx, EXCP_RI);
6493 goto out;
6496 /* Load needed operands */
6497 switch (opc) {
6498 case OPC_BEQ:
6499 case OPC_BEQL:
6500 case OPC_BNE:
6501 case OPC_BNEL:
6502 /* Compare two registers */
6503 if (rs != rt) {
6504 gen_load_gpr(t0, rs);
6505 gen_load_gpr(t1, rt);
6506 bcond_compute = 1;
6508 btgt = ctx->base.pc_next + insn_bytes + offset;
6509 break;
6510 case OPC_BGEZ:
6511 case OPC_BGEZAL:
6512 case OPC_BGEZALL:
6513 case OPC_BGEZL:
6514 case OPC_BGTZ:
6515 case OPC_BGTZL:
6516 case OPC_BLEZ:
6517 case OPC_BLEZL:
6518 case OPC_BLTZ:
6519 case OPC_BLTZAL:
6520 case OPC_BLTZALL:
6521 case OPC_BLTZL:
6522 /* Compare to zero */
6523 if (rs != 0) {
6524 gen_load_gpr(t0, rs);
6525 bcond_compute = 1;
6527 btgt = ctx->base.pc_next + insn_bytes + offset;
6528 break;
6529 case OPC_BPOSGE32:
6530 #if defined(TARGET_MIPS64)
6531 case OPC_BPOSGE64:
6532 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6533 #else
6534 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6535 #endif
6536 bcond_compute = 1;
6537 btgt = ctx->base.pc_next + insn_bytes + offset;
6538 break;
6539 case OPC_J:
6540 case OPC_JAL:
6541 case OPC_JALX:
6542 /* Jump to immediate */
6543 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6544 (uint32_t)offset;
6545 break;
6546 case OPC_JR:
6547 case OPC_JALR:
6548 /* Jump to register */
6549 if (offset != 0 && offset != 16) {
6551 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6552 * others are reserved.
6554 MIPS_INVAL("jump hint");
6555 generate_exception_end(ctx, EXCP_RI);
6556 goto out;
6558 gen_load_gpr(btarget, rs);
6559 break;
6560 default:
6561 MIPS_INVAL("branch/jump");
6562 generate_exception_end(ctx, EXCP_RI);
6563 goto out;
6565 if (bcond_compute == 0) {
6566 /* No condition to be computed */
6567 switch (opc) {
6568 case OPC_BEQ: /* rx == rx */
6569 case OPC_BEQL: /* rx == rx likely */
6570 case OPC_BGEZ: /* 0 >= 0 */
6571 case OPC_BGEZL: /* 0 >= 0 likely */
6572 case OPC_BLEZ: /* 0 <= 0 */
6573 case OPC_BLEZL: /* 0 <= 0 likely */
6574 /* Always take */
6575 ctx->hflags |= MIPS_HFLAG_B;
6576 break;
6577 case OPC_BGEZAL: /* 0 >= 0 */
6578 case OPC_BGEZALL: /* 0 >= 0 likely */
6579 /* Always take and link */
6580 blink = 31;
6581 ctx->hflags |= MIPS_HFLAG_B;
6582 break;
6583 case OPC_BNE: /* rx != rx */
6584 case OPC_BGTZ: /* 0 > 0 */
6585 case OPC_BLTZ: /* 0 < 0 */
6586 /* Treat as NOP. */
6587 goto out;
6588 case OPC_BLTZAL: /* 0 < 0 */
6590 * Handle as an unconditional branch to get correct delay
6591 * slot checking.
6593 blink = 31;
6594 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6595 ctx->hflags |= MIPS_HFLAG_B;
6596 break;
6597 case OPC_BLTZALL: /* 0 < 0 likely */
6598 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6599 /* Skip the instruction in the delay slot */
6600 ctx->base.pc_next += 4;
6601 goto out;
6602 case OPC_BNEL: /* rx != rx likely */
6603 case OPC_BGTZL: /* 0 > 0 likely */
6604 case OPC_BLTZL: /* 0 < 0 likely */
6605 /* Skip the instruction in the delay slot */
6606 ctx->base.pc_next += 4;
6607 goto out;
6608 case OPC_J:
6609 ctx->hflags |= MIPS_HFLAG_B;
6610 break;
6611 case OPC_JALX:
6612 ctx->hflags |= MIPS_HFLAG_BX;
6613 /* Fallthrough */
6614 case OPC_JAL:
6615 blink = 31;
6616 ctx->hflags |= MIPS_HFLAG_B;
6617 break;
6618 case OPC_JR:
6619 ctx->hflags |= MIPS_HFLAG_BR;
6620 break;
6621 case OPC_JALR:
6622 blink = rt;
6623 ctx->hflags |= MIPS_HFLAG_BR;
6624 break;
6625 default:
6626 MIPS_INVAL("branch/jump");
6627 generate_exception_end(ctx, EXCP_RI);
6628 goto out;
6630 } else {
6631 switch (opc) {
6632 case OPC_BEQ:
6633 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6634 goto not_likely;
6635 case OPC_BEQL:
6636 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6637 goto likely;
6638 case OPC_BNE:
6639 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6640 goto not_likely;
6641 case OPC_BNEL:
6642 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6643 goto likely;
6644 case OPC_BGEZ:
6645 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6646 goto not_likely;
6647 case OPC_BGEZL:
6648 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6649 goto likely;
6650 case OPC_BGEZAL:
6651 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6652 blink = 31;
6653 goto not_likely;
6654 case OPC_BGEZALL:
6655 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6656 blink = 31;
6657 goto likely;
6658 case OPC_BGTZ:
6659 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6660 goto not_likely;
6661 case OPC_BGTZL:
6662 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6663 goto likely;
6664 case OPC_BLEZ:
6665 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6666 goto not_likely;
6667 case OPC_BLEZL:
6668 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6669 goto likely;
6670 case OPC_BLTZ:
6671 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6672 goto not_likely;
6673 case OPC_BLTZL:
6674 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6675 goto likely;
6676 case OPC_BPOSGE32:
6677 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6678 goto not_likely;
6679 #if defined(TARGET_MIPS64)
6680 case OPC_BPOSGE64:
6681 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6682 goto not_likely;
6683 #endif
6684 case OPC_BLTZAL:
6685 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6686 blink = 31;
6687 not_likely:
6688 ctx->hflags |= MIPS_HFLAG_BC;
6689 break;
6690 case OPC_BLTZALL:
6691 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6692 blink = 31;
6693 likely:
6694 ctx->hflags |= MIPS_HFLAG_BL;
6695 break;
6696 default:
6697 MIPS_INVAL("conditional branch/jump");
6698 generate_exception_end(ctx, EXCP_RI);
6699 goto out;
6703 ctx->btarget = btgt;
6705 switch (delayslot_size) {
6706 case 2:
6707 ctx->hflags |= MIPS_HFLAG_BDS16;
6708 break;
6709 case 4:
6710 ctx->hflags |= MIPS_HFLAG_BDS32;
6711 break;
6714 if (blink > 0) {
6715 int post_delay = insn_bytes + delayslot_size;
6716 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6718 tcg_gen_movi_tl(cpu_gpr[blink],
6719 ctx->base.pc_next + post_delay + lowbit);
6722 out:
6723 if (insn_bytes == 2) {
6724 ctx->hflags |= MIPS_HFLAG_B16;
6726 tcg_temp_free(t0);
6727 tcg_temp_free(t1);
6731 /* nanoMIPS Branches */
6732 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6733 int insn_bytes,
6734 int rs, int rt, int32_t offset)
6736 target_ulong btgt = -1;
6737 int bcond_compute = 0;
6738 TCGv t0 = tcg_temp_new();
6739 TCGv t1 = tcg_temp_new();
6741 /* Load needed operands */
6742 switch (opc) {
6743 case OPC_BEQ:
6744 case OPC_BNE:
6745 /* Compare two registers */
6746 if (rs != rt) {
6747 gen_load_gpr(t0, rs);
6748 gen_load_gpr(t1, rt);
6749 bcond_compute = 1;
6751 btgt = ctx->base.pc_next + insn_bytes + offset;
6752 break;
6753 case OPC_BGEZAL:
6754 /* Compare to zero */
6755 if (rs != 0) {
6756 gen_load_gpr(t0, rs);
6757 bcond_compute = 1;
6759 btgt = ctx->base.pc_next + insn_bytes + offset;
6760 break;
6761 case OPC_BPOSGE32:
6762 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6763 bcond_compute = 1;
6764 btgt = ctx->base.pc_next + insn_bytes + offset;
6765 break;
6766 case OPC_JR:
6767 case OPC_JALR:
6768 /* Jump to register */
6769 if (offset != 0 && offset != 16) {
6771 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6772 * others are reserved.
6774 MIPS_INVAL("jump hint");
6775 generate_exception_end(ctx, EXCP_RI);
6776 goto out;
6778 gen_load_gpr(btarget, rs);
6779 break;
6780 default:
6781 MIPS_INVAL("branch/jump");
6782 generate_exception_end(ctx, EXCP_RI);
6783 goto out;
6785 if (bcond_compute == 0) {
6786 /* No condition to be computed */
6787 switch (opc) {
6788 case OPC_BEQ: /* rx == rx */
6789 /* Always take */
6790 ctx->hflags |= MIPS_HFLAG_B;
6791 break;
6792 case OPC_BGEZAL: /* 0 >= 0 */
6793 /* Always take and link */
6794 tcg_gen_movi_tl(cpu_gpr[31],
6795 ctx->base.pc_next + insn_bytes);
6796 ctx->hflags |= MIPS_HFLAG_B;
6797 break;
6798 case OPC_BNE: /* rx != rx */
6799 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6800 /* Skip the instruction in the delay slot */
6801 ctx->base.pc_next += 4;
6802 goto out;
6803 case OPC_JR:
6804 ctx->hflags |= MIPS_HFLAG_BR;
6805 break;
6806 case OPC_JALR:
6807 if (rt > 0) {
6808 tcg_gen_movi_tl(cpu_gpr[rt],
6809 ctx->base.pc_next + insn_bytes);
6811 ctx->hflags |= MIPS_HFLAG_BR;
6812 break;
6813 default:
6814 MIPS_INVAL("branch/jump");
6815 generate_exception_end(ctx, EXCP_RI);
6816 goto out;
6818 } else {
6819 switch (opc) {
6820 case OPC_BEQ:
6821 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6822 goto not_likely;
6823 case OPC_BNE:
6824 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6825 goto not_likely;
6826 case OPC_BGEZAL:
6827 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6828 tcg_gen_movi_tl(cpu_gpr[31],
6829 ctx->base.pc_next + insn_bytes);
6830 goto not_likely;
6831 case OPC_BPOSGE32:
6832 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6833 not_likely:
6834 ctx->hflags |= MIPS_HFLAG_BC;
6835 break;
6836 default:
6837 MIPS_INVAL("conditional branch/jump");
6838 generate_exception_end(ctx, EXCP_RI);
6839 goto out;
6843 ctx->btarget = btgt;
6845 out:
6846 if (insn_bytes == 2) {
6847 ctx->hflags |= MIPS_HFLAG_B16;
6849 tcg_temp_free(t0);
6850 tcg_temp_free(t1);
6854 /* special3 bitfield operations */
6855 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6856 int rs, int lsb, int msb)
6858 TCGv t0 = tcg_temp_new();
6859 TCGv t1 = tcg_temp_new();
6861 gen_load_gpr(t1, rs);
6862 switch (opc) {
6863 case OPC_EXT:
6864 if (lsb + msb > 31) {
6865 goto fail;
6867 if (msb != 31) {
6868 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6869 } else {
6871 * The two checks together imply that lsb == 0,
6872 * so this is a simple sign-extension.
6874 tcg_gen_ext32s_tl(t0, t1);
6876 break;
6877 #if defined(TARGET_MIPS64)
6878 case OPC_DEXTU:
6879 lsb += 32;
6880 goto do_dext;
6881 case OPC_DEXTM:
6882 msb += 32;
6883 goto do_dext;
6884 case OPC_DEXT:
6885 do_dext:
6886 if (lsb + msb > 63) {
6887 goto fail;
6889 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6890 break;
6891 #endif
6892 case OPC_INS:
6893 if (lsb > msb) {
6894 goto fail;
6896 gen_load_gpr(t0, rt);
6897 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6898 tcg_gen_ext32s_tl(t0, t0);
6899 break;
6900 #if defined(TARGET_MIPS64)
6901 case OPC_DINSU:
6902 lsb += 32;
6903 /* FALLTHRU */
6904 case OPC_DINSM:
6905 msb += 32;
6906 /* FALLTHRU */
6907 case OPC_DINS:
6908 if (lsb > msb) {
6909 goto fail;
6911 gen_load_gpr(t0, rt);
6912 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6913 break;
6914 #endif
6915 default:
6916 fail:
6917 MIPS_INVAL("bitops");
6918 generate_exception_end(ctx, EXCP_RI);
6919 tcg_temp_free(t0);
6920 tcg_temp_free(t1);
6921 return;
6923 gen_store_gpr(t0, rt);
6924 tcg_temp_free(t0);
6925 tcg_temp_free(t1);
6928 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6930 TCGv t0;
6932 if (rd == 0) {
6933 /* If no destination, treat it as a NOP. */
6934 return;
6937 t0 = tcg_temp_new();
6938 gen_load_gpr(t0, rt);
6939 switch (op2) {
6940 case OPC_WSBH:
6942 TCGv t1 = tcg_temp_new();
6943 TCGv t2 = tcg_const_tl(0x00FF00FF);
6945 tcg_gen_shri_tl(t1, t0, 8);
6946 tcg_gen_and_tl(t1, t1, t2);
6947 tcg_gen_and_tl(t0, t0, t2);
6948 tcg_gen_shli_tl(t0, t0, 8);
6949 tcg_gen_or_tl(t0, t0, t1);
6950 tcg_temp_free(t2);
6951 tcg_temp_free(t1);
6952 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6954 break;
6955 case OPC_SEB:
6956 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6957 break;
6958 case OPC_SEH:
6959 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6960 break;
6961 #if defined(TARGET_MIPS64)
6962 case OPC_DSBH:
6964 TCGv t1 = tcg_temp_new();
6965 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6967 tcg_gen_shri_tl(t1, t0, 8);
6968 tcg_gen_and_tl(t1, t1, t2);
6969 tcg_gen_and_tl(t0, t0, t2);
6970 tcg_gen_shli_tl(t0, t0, 8);
6971 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6972 tcg_temp_free(t2);
6973 tcg_temp_free(t1);
6975 break;
6976 case OPC_DSHD:
6978 TCGv t1 = tcg_temp_new();
6979 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6981 tcg_gen_shri_tl(t1, t0, 16);
6982 tcg_gen_and_tl(t1, t1, t2);
6983 tcg_gen_and_tl(t0, t0, t2);
6984 tcg_gen_shli_tl(t0, t0, 16);
6985 tcg_gen_or_tl(t0, t0, t1);
6986 tcg_gen_shri_tl(t1, t0, 32);
6987 tcg_gen_shli_tl(t0, t0, 32);
6988 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6989 tcg_temp_free(t2);
6990 tcg_temp_free(t1);
6992 break;
6993 #endif
6994 default:
6995 MIPS_INVAL("bsfhl");
6996 generate_exception_end(ctx, EXCP_RI);
6997 tcg_temp_free(t0);
6998 return;
7000 tcg_temp_free(t0);
7003 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
7004 int imm2)
7006 TCGv t0;
7007 TCGv t1;
7008 if (rd == 0) {
7009 /* Treat as NOP. */
7010 return;
7012 t0 = tcg_temp_new();
7013 t1 = tcg_temp_new();
7014 gen_load_gpr(t0, rs);
7015 gen_load_gpr(t1, rt);
7016 tcg_gen_shli_tl(t0, t0, imm2 + 1);
7017 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
7018 if (opc == OPC_LSA) {
7019 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
7022 tcg_temp_free(t1);
7023 tcg_temp_free(t0);
7025 return;
7028 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
7029 int rt, int bits)
7031 TCGv t0;
7032 if (rd == 0) {
7033 /* Treat as NOP. */
7034 return;
7036 t0 = tcg_temp_new();
7037 if (bits == 0 || bits == wordsz) {
7038 if (bits == 0) {
7039 gen_load_gpr(t0, rt);
7040 } else {
7041 gen_load_gpr(t0, rs);
7043 switch (wordsz) {
7044 case 32:
7045 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
7046 break;
7047 #if defined(TARGET_MIPS64)
7048 case 64:
7049 tcg_gen_mov_tl(cpu_gpr[rd], t0);
7050 break;
7051 #endif
7053 } else {
7054 TCGv t1 = tcg_temp_new();
7055 gen_load_gpr(t0, rt);
7056 gen_load_gpr(t1, rs);
7057 switch (wordsz) {
7058 case 32:
7060 TCGv_i64 t2 = tcg_temp_new_i64();
7061 tcg_gen_concat_tl_i64(t2, t1, t0);
7062 tcg_gen_shri_i64(t2, t2, 32 - bits);
7063 gen_move_low32(cpu_gpr[rd], t2);
7064 tcg_temp_free_i64(t2);
7066 break;
7067 #if defined(TARGET_MIPS64)
7068 case 64:
7069 tcg_gen_shli_tl(t0, t0, bits);
7070 tcg_gen_shri_tl(t1, t1, 64 - bits);
7071 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
7072 break;
7073 #endif
7075 tcg_temp_free(t1);
7078 tcg_temp_free(t0);
7081 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7082 int bp)
7084 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
7087 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7088 int shift)
7090 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
7093 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
7095 TCGv t0;
7096 if (rd == 0) {
7097 /* Treat as NOP. */
7098 return;
7100 t0 = tcg_temp_new();
7101 gen_load_gpr(t0, rt);
7102 switch (opc) {
7103 case OPC_BITSWAP:
7104 gen_helper_bitswap(cpu_gpr[rd], t0);
7105 break;
7106 #if defined(TARGET_MIPS64)
7107 case OPC_DBITSWAP:
7108 gen_helper_dbitswap(cpu_gpr[rd], t0);
7109 break;
7110 #endif
7112 tcg_temp_free(t0);
7115 #ifndef CONFIG_USER_ONLY
7116 /* CP0 (MMU and control) */
7117 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
7119 TCGv_i64 t0 = tcg_temp_new_i64();
7120 TCGv_i64 t1 = tcg_temp_new_i64();
7122 tcg_gen_ext_tl_i64(t0, arg);
7123 tcg_gen_ld_i64(t1, cpu_env, off);
7124 #if defined(TARGET_MIPS64)
7125 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
7126 #else
7127 tcg_gen_concat32_i64(t1, t1, t0);
7128 #endif
7129 tcg_gen_st_i64(t1, cpu_env, off);
7130 tcg_temp_free_i64(t1);
7131 tcg_temp_free_i64(t0);
7134 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
7136 TCGv_i64 t0 = tcg_temp_new_i64();
7137 TCGv_i64 t1 = tcg_temp_new_i64();
7139 tcg_gen_ext_tl_i64(t0, arg);
7140 tcg_gen_ld_i64(t1, cpu_env, off);
7141 tcg_gen_concat32_i64(t1, t1, t0);
7142 tcg_gen_st_i64(t1, cpu_env, off);
7143 tcg_temp_free_i64(t1);
7144 tcg_temp_free_i64(t0);
7147 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
7149 TCGv_i64 t0 = tcg_temp_new_i64();
7151 tcg_gen_ld_i64(t0, cpu_env, off);
7152 #if defined(TARGET_MIPS64)
7153 tcg_gen_shri_i64(t0, t0, 30);
7154 #else
7155 tcg_gen_shri_i64(t0, t0, 32);
7156 #endif
7157 gen_move_low32(arg, t0);
7158 tcg_temp_free_i64(t0);
7161 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
7163 TCGv_i64 t0 = tcg_temp_new_i64();
7165 tcg_gen_ld_i64(t0, cpu_env, off);
7166 tcg_gen_shri_i64(t0, t0, 32 + shift);
7167 gen_move_low32(arg, t0);
7168 tcg_temp_free_i64(t0);
7171 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
7173 TCGv_i32 t0 = tcg_temp_new_i32();
7175 tcg_gen_ld_i32(t0, cpu_env, off);
7176 tcg_gen_ext_i32_tl(arg, t0);
7177 tcg_temp_free_i32(t0);
7180 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
7182 tcg_gen_ld_tl(arg, cpu_env, off);
7183 tcg_gen_ext32s_tl(arg, arg);
7186 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
7188 TCGv_i32 t0 = tcg_temp_new_i32();
7190 tcg_gen_trunc_tl_i32(t0, arg);
7191 tcg_gen_st_i32(t0, cpu_env, off);
7192 tcg_temp_free_i32(t0);
7195 #define CP0_CHECK(c) \
7196 do { \
7197 if (!(c)) { \
7198 goto cp0_unimplemented; \
7200 } while (0)
7202 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7204 const char *register_name = "invalid";
7206 switch (reg) {
7207 case CP0_REGISTER_02:
7208 switch (sel) {
7209 case 0:
7210 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7211 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7212 register_name = "EntryLo0";
7213 break;
7214 default:
7215 goto cp0_unimplemented;
7217 break;
7218 case CP0_REGISTER_03:
7219 switch (sel) {
7220 case CP0_REG03__ENTRYLO1:
7221 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7222 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7223 register_name = "EntryLo1";
7224 break;
7225 default:
7226 goto cp0_unimplemented;
7228 break;
7229 case CP0_REGISTER_09:
7230 switch (sel) {
7231 case CP0_REG09__SAAR:
7232 CP0_CHECK(ctx->saar);
7233 gen_helper_mfhc0_saar(arg, cpu_env);
7234 register_name = "SAAR";
7235 break;
7236 default:
7237 goto cp0_unimplemented;
7239 break;
7240 case CP0_REGISTER_17:
7241 switch (sel) {
7242 case CP0_REG17__LLADDR:
7243 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
7244 ctx->CP0_LLAddr_shift);
7245 register_name = "LLAddr";
7246 break;
7247 case CP0_REG17__MAAR:
7248 CP0_CHECK(ctx->mrp);
7249 gen_helper_mfhc0_maar(arg, cpu_env);
7250 register_name = "MAAR";
7251 break;
7252 default:
7253 goto cp0_unimplemented;
7255 break;
7256 case CP0_REGISTER_19:
7257 switch (sel) {
7258 case CP0_REG19__WATCHHI0:
7259 case CP0_REG19__WATCHHI1:
7260 case CP0_REG19__WATCHHI2:
7261 case CP0_REG19__WATCHHI3:
7262 case CP0_REG19__WATCHHI4:
7263 case CP0_REG19__WATCHHI5:
7264 case CP0_REG19__WATCHHI6:
7265 case CP0_REG19__WATCHHI7:
7266 /* upper 32 bits are only available when Config5MI != 0 */
7267 CP0_CHECK(ctx->mi);
7268 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
7269 register_name = "WatchHi";
7270 break;
7271 default:
7272 goto cp0_unimplemented;
7274 break;
7275 case CP0_REGISTER_28:
7276 switch (sel) {
7277 case 0:
7278 case 2:
7279 case 4:
7280 case 6:
7281 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
7282 register_name = "TagLo";
7283 break;
7284 default:
7285 goto cp0_unimplemented;
7287 break;
7288 default:
7289 goto cp0_unimplemented;
7291 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
7292 return;
7294 cp0_unimplemented:
7295 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
7296 register_name, reg, sel);
7297 tcg_gen_movi_tl(arg, 0);
7300 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7302 const char *register_name = "invalid";
7303 uint64_t mask = ctx->PAMask >> 36;
7305 switch (reg) {
7306 case CP0_REGISTER_02:
7307 switch (sel) {
7308 case 0:
7309 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7310 tcg_gen_andi_tl(arg, arg, mask);
7311 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7312 register_name = "EntryLo0";
7313 break;
7314 default:
7315 goto cp0_unimplemented;
7317 break;
7318 case CP0_REGISTER_03:
7319 switch (sel) {
7320 case CP0_REG03__ENTRYLO1:
7321 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7322 tcg_gen_andi_tl(arg, arg, mask);
7323 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7324 register_name = "EntryLo1";
7325 break;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case CP0_REGISTER_09:
7331 switch (sel) {
7332 case CP0_REG09__SAAR:
7333 CP0_CHECK(ctx->saar);
7334 gen_helper_mthc0_saar(cpu_env, arg);
7335 register_name = "SAAR";
7336 break;
7337 default:
7338 goto cp0_unimplemented;
7340 break;
7341 case CP0_REGISTER_17:
7342 switch (sel) {
7343 case CP0_REG17__LLADDR:
7345 * LLAddr is read-only (the only exception is bit 0 if LLB is
7346 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
7347 * relevant for modern MIPS cores supporting MTHC0, therefore
7348 * treating MTHC0 to LLAddr as NOP.
7350 register_name = "LLAddr";
7351 break;
7352 case CP0_REG17__MAAR:
7353 CP0_CHECK(ctx->mrp);
7354 gen_helper_mthc0_maar(cpu_env, arg);
7355 register_name = "MAAR";
7356 break;
7357 default:
7358 goto cp0_unimplemented;
7360 break;
7361 case CP0_REGISTER_19:
7362 switch (sel) {
7363 case CP0_REG19__WATCHHI0:
7364 case CP0_REG19__WATCHHI1:
7365 case CP0_REG19__WATCHHI2:
7366 case CP0_REG19__WATCHHI3:
7367 case CP0_REG19__WATCHHI4:
7368 case CP0_REG19__WATCHHI5:
7369 case CP0_REG19__WATCHHI6:
7370 case CP0_REG19__WATCHHI7:
7371 /* upper 32 bits are only available when Config5MI != 0 */
7372 CP0_CHECK(ctx->mi);
7373 gen_helper_0e1i(mthc0_watchhi, arg, sel);
7374 register_name = "WatchHi";
7375 break;
7376 default:
7377 goto cp0_unimplemented;
7379 break;
7380 case CP0_REGISTER_28:
7381 switch (sel) {
7382 case 0:
7383 case 2:
7384 case 4:
7385 case 6:
7386 tcg_gen_andi_tl(arg, arg, mask);
7387 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
7388 register_name = "TagLo";
7389 break;
7390 default:
7391 goto cp0_unimplemented;
7393 break;
7394 default:
7395 goto cp0_unimplemented;
7397 trace_mips_translate_c0("mthc0", register_name, reg, sel);
7399 cp0_unimplemented:
7400 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
7401 register_name, reg, sel);
7404 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
7406 if (ctx->insn_flags & ISA_MIPS32R6) {
7407 tcg_gen_movi_tl(arg, 0);
7408 } else {
7409 tcg_gen_movi_tl(arg, ~0);
7413 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7415 const char *register_name = "invalid";
7417 if (sel != 0) {
7418 check_insn(ctx, ISA_MIPS32);
7421 switch (reg) {
7422 case CP0_REGISTER_00:
7423 switch (sel) {
7424 case CP0_REG00__INDEX:
7425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7426 register_name = "Index";
7427 break;
7428 case CP0_REG00__MVPCONTROL:
7429 CP0_CHECK(ctx->insn_flags & ASE_MT);
7430 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7431 register_name = "MVPControl";
7432 break;
7433 case CP0_REG00__MVPCONF0:
7434 CP0_CHECK(ctx->insn_flags & ASE_MT);
7435 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7436 register_name = "MVPConf0";
7437 break;
7438 case CP0_REG00__MVPCONF1:
7439 CP0_CHECK(ctx->insn_flags & ASE_MT);
7440 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7441 register_name = "MVPConf1";
7442 break;
7443 case CP0_REG00__VPCONTROL:
7444 CP0_CHECK(ctx->vp);
7445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7446 register_name = "VPControl";
7447 break;
7448 default:
7449 goto cp0_unimplemented;
7451 break;
7452 case CP0_REGISTER_01:
7453 switch (sel) {
7454 case CP0_REG01__RANDOM:
7455 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7456 gen_helper_mfc0_random(arg, cpu_env);
7457 register_name = "Random";
7458 break;
7459 case CP0_REG01__VPECONTROL:
7460 CP0_CHECK(ctx->insn_flags & ASE_MT);
7461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7462 register_name = "VPEControl";
7463 break;
7464 case CP0_REG01__VPECONF0:
7465 CP0_CHECK(ctx->insn_flags & ASE_MT);
7466 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7467 register_name = "VPEConf0";
7468 break;
7469 case CP0_REG01__VPECONF1:
7470 CP0_CHECK(ctx->insn_flags & ASE_MT);
7471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7472 register_name = "VPEConf1";
7473 break;
7474 case CP0_REG01__YQMASK:
7475 CP0_CHECK(ctx->insn_flags & ASE_MT);
7476 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7477 register_name = "YQMask";
7478 break;
7479 case CP0_REG01__VPESCHEDULE:
7480 CP0_CHECK(ctx->insn_flags & ASE_MT);
7481 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7482 register_name = "VPESchedule";
7483 break;
7484 case CP0_REG01__VPESCHEFBACK:
7485 CP0_CHECK(ctx->insn_flags & ASE_MT);
7486 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7487 register_name = "VPEScheFBack";
7488 break;
7489 case CP0_REG01__VPEOPT:
7490 CP0_CHECK(ctx->insn_flags & ASE_MT);
7491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7492 register_name = "VPEOpt";
7493 break;
7494 default:
7495 goto cp0_unimplemented;
7497 break;
7498 case CP0_REGISTER_02:
7499 switch (sel) {
7500 case CP0_REG02__ENTRYLO0:
7502 TCGv_i64 tmp = tcg_temp_new_i64();
7503 tcg_gen_ld_i64(tmp, cpu_env,
7504 offsetof(CPUMIPSState, CP0_EntryLo0));
7505 #if defined(TARGET_MIPS64)
7506 if (ctx->rxi) {
7507 /* Move RI/XI fields to bits 31:30 */
7508 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7509 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7511 #endif
7512 gen_move_low32(arg, tmp);
7513 tcg_temp_free_i64(tmp);
7515 register_name = "EntryLo0";
7516 break;
7517 case CP0_REG02__TCSTATUS:
7518 CP0_CHECK(ctx->insn_flags & ASE_MT);
7519 gen_helper_mfc0_tcstatus(arg, cpu_env);
7520 register_name = "TCStatus";
7521 break;
7522 case CP0_REG02__TCBIND:
7523 CP0_CHECK(ctx->insn_flags & ASE_MT);
7524 gen_helper_mfc0_tcbind(arg, cpu_env);
7525 register_name = "TCBind";
7526 break;
7527 case CP0_REG02__TCRESTART:
7528 CP0_CHECK(ctx->insn_flags & ASE_MT);
7529 gen_helper_mfc0_tcrestart(arg, cpu_env);
7530 register_name = "TCRestart";
7531 break;
7532 case CP0_REG02__TCHALT:
7533 CP0_CHECK(ctx->insn_flags & ASE_MT);
7534 gen_helper_mfc0_tchalt(arg, cpu_env);
7535 register_name = "TCHalt";
7536 break;
7537 case CP0_REG02__TCCONTEXT:
7538 CP0_CHECK(ctx->insn_flags & ASE_MT);
7539 gen_helper_mfc0_tccontext(arg, cpu_env);
7540 register_name = "TCContext";
7541 break;
7542 case CP0_REG02__TCSCHEDULE:
7543 CP0_CHECK(ctx->insn_flags & ASE_MT);
7544 gen_helper_mfc0_tcschedule(arg, cpu_env);
7545 register_name = "TCSchedule";
7546 break;
7547 case CP0_REG02__TCSCHEFBACK:
7548 CP0_CHECK(ctx->insn_flags & ASE_MT);
7549 gen_helper_mfc0_tcschefback(arg, cpu_env);
7550 register_name = "TCScheFBack";
7551 break;
7552 default:
7553 goto cp0_unimplemented;
7555 break;
7556 case CP0_REGISTER_03:
7557 switch (sel) {
7558 case CP0_REG03__ENTRYLO1:
7560 TCGv_i64 tmp = tcg_temp_new_i64();
7561 tcg_gen_ld_i64(tmp, cpu_env,
7562 offsetof(CPUMIPSState, CP0_EntryLo1));
7563 #if defined(TARGET_MIPS64)
7564 if (ctx->rxi) {
7565 /* Move RI/XI fields to bits 31:30 */
7566 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7567 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7569 #endif
7570 gen_move_low32(arg, tmp);
7571 tcg_temp_free_i64(tmp);
7573 register_name = "EntryLo1";
7574 break;
7575 case CP0_REG03__GLOBALNUM:
7576 CP0_CHECK(ctx->vp);
7577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7578 register_name = "GlobalNumber";
7579 break;
7580 default:
7581 goto cp0_unimplemented;
7583 break;
7584 case CP0_REGISTER_04:
7585 switch (sel) {
7586 case CP0_REG04__CONTEXT:
7587 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7588 tcg_gen_ext32s_tl(arg, arg);
7589 register_name = "Context";
7590 break;
7591 case CP0_REG04__CONTEXTCONFIG:
7592 /* SmartMIPS ASE */
7593 /* gen_helper_mfc0_contextconfig(arg); */
7594 register_name = "ContextConfig";
7595 goto cp0_unimplemented;
7596 case CP0_REG04__USERLOCAL:
7597 CP0_CHECK(ctx->ulri);
7598 tcg_gen_ld_tl(arg, cpu_env,
7599 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7600 tcg_gen_ext32s_tl(arg, arg);
7601 register_name = "UserLocal";
7602 break;
7603 case CP0_REG04__MMID:
7604 CP0_CHECK(ctx->mi);
7605 gen_helper_mtc0_memorymapid(cpu_env, arg);
7606 register_name = "MMID";
7607 break;
7608 default:
7609 goto cp0_unimplemented;
7611 break;
7612 case CP0_REGISTER_05:
7613 switch (sel) {
7614 case CP0_REG05__PAGEMASK:
7615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7616 register_name = "PageMask";
7617 break;
7618 case CP0_REG05__PAGEGRAIN:
7619 check_insn(ctx, ISA_MIPS32R2);
7620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7621 register_name = "PageGrain";
7622 break;
7623 case CP0_REG05__SEGCTL0:
7624 CP0_CHECK(ctx->sc);
7625 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7626 tcg_gen_ext32s_tl(arg, arg);
7627 register_name = "SegCtl0";
7628 break;
7629 case CP0_REG05__SEGCTL1:
7630 CP0_CHECK(ctx->sc);
7631 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7632 tcg_gen_ext32s_tl(arg, arg);
7633 register_name = "SegCtl1";
7634 break;
7635 case CP0_REG05__SEGCTL2:
7636 CP0_CHECK(ctx->sc);
7637 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7638 tcg_gen_ext32s_tl(arg, arg);
7639 register_name = "SegCtl2";
7640 break;
7641 case CP0_REG05__PWBASE:
7642 check_pw(ctx);
7643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7644 register_name = "PWBase";
7645 break;
7646 case CP0_REG05__PWFIELD:
7647 check_pw(ctx);
7648 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7649 register_name = "PWField";
7650 break;
7651 case CP0_REG05__PWSIZE:
7652 check_pw(ctx);
7653 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7654 register_name = "PWSize";
7655 break;
7656 default:
7657 goto cp0_unimplemented;
7659 break;
7660 case CP0_REGISTER_06:
7661 switch (sel) {
7662 case CP0_REG06__WIRED:
7663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7664 register_name = "Wired";
7665 break;
7666 case CP0_REG06__SRSCONF0:
7667 check_insn(ctx, ISA_MIPS32R2);
7668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7669 register_name = "SRSConf0";
7670 break;
7671 case CP0_REG06__SRSCONF1:
7672 check_insn(ctx, ISA_MIPS32R2);
7673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7674 register_name = "SRSConf1";
7675 break;
7676 case CP0_REG06__SRSCONF2:
7677 check_insn(ctx, ISA_MIPS32R2);
7678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7679 register_name = "SRSConf2";
7680 break;
7681 case CP0_REG06__SRSCONF3:
7682 check_insn(ctx, ISA_MIPS32R2);
7683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7684 register_name = "SRSConf3";
7685 break;
7686 case CP0_REG06__SRSCONF4:
7687 check_insn(ctx, ISA_MIPS32R2);
7688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7689 register_name = "SRSConf4";
7690 break;
7691 case CP0_REG06__PWCTL:
7692 check_pw(ctx);
7693 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7694 register_name = "PWCtl";
7695 break;
7696 default:
7697 goto cp0_unimplemented;
7699 break;
7700 case CP0_REGISTER_07:
7701 switch (sel) {
7702 case CP0_REG07__HWRENA:
7703 check_insn(ctx, ISA_MIPS32R2);
7704 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7705 register_name = "HWREna";
7706 break;
7707 default:
7708 goto cp0_unimplemented;
7710 break;
7711 case CP0_REGISTER_08:
7712 switch (sel) {
7713 case CP0_REG08__BADVADDR:
7714 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7715 tcg_gen_ext32s_tl(arg, arg);
7716 register_name = "BadVAddr";
7717 break;
7718 case CP0_REG08__BADINSTR:
7719 CP0_CHECK(ctx->bi);
7720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7721 register_name = "BadInstr";
7722 break;
7723 case CP0_REG08__BADINSTRP:
7724 CP0_CHECK(ctx->bp);
7725 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7726 register_name = "BadInstrP";
7727 break;
7728 case CP0_REG08__BADINSTRX:
7729 CP0_CHECK(ctx->bi);
7730 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7731 tcg_gen_andi_tl(arg, arg, ~0xffff);
7732 register_name = "BadInstrX";
7733 break;
7734 default:
7735 goto cp0_unimplemented;
7737 break;
7738 case CP0_REGISTER_09:
7739 switch (sel) {
7740 case CP0_REG09__COUNT:
7741 /* Mark as an IO operation because we read the time. */
7742 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7743 gen_io_start();
7745 gen_helper_mfc0_count(arg, cpu_env);
7747 * Break the TB to be able to take timer interrupts immediately
7748 * after reading count. DISAS_STOP isn't sufficient, we need to
7749 * ensure we break completely out of translated code.
7751 gen_save_pc(ctx->base.pc_next + 4);
7752 ctx->base.is_jmp = DISAS_EXIT;
7753 register_name = "Count";
7754 break;
7755 case CP0_REG09__SAARI:
7756 CP0_CHECK(ctx->saar);
7757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7758 register_name = "SAARI";
7759 break;
7760 case CP0_REG09__SAAR:
7761 CP0_CHECK(ctx->saar);
7762 gen_helper_mfc0_saar(arg, cpu_env);
7763 register_name = "SAAR";
7764 break;
7765 default:
7766 goto cp0_unimplemented;
7768 break;
7769 case CP0_REGISTER_10:
7770 switch (sel) {
7771 case CP0_REG10__ENTRYHI:
7772 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7773 tcg_gen_ext32s_tl(arg, arg);
7774 register_name = "EntryHi";
7775 break;
7776 default:
7777 goto cp0_unimplemented;
7779 break;
7780 case CP0_REGISTER_11:
7781 switch (sel) {
7782 case CP0_REG11__COMPARE:
7783 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7784 register_name = "Compare";
7785 break;
7786 /* 6,7 are implementation dependent */
7787 default:
7788 goto cp0_unimplemented;
7790 break;
7791 case CP0_REGISTER_12:
7792 switch (sel) {
7793 case CP0_REG12__STATUS:
7794 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7795 register_name = "Status";
7796 break;
7797 case CP0_REG12__INTCTL:
7798 check_insn(ctx, ISA_MIPS32R2);
7799 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7800 register_name = "IntCtl";
7801 break;
7802 case CP0_REG12__SRSCTL:
7803 check_insn(ctx, ISA_MIPS32R2);
7804 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7805 register_name = "SRSCtl";
7806 break;
7807 case CP0_REG12__SRSMAP:
7808 check_insn(ctx, ISA_MIPS32R2);
7809 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7810 register_name = "SRSMap";
7811 break;
7812 default:
7813 goto cp0_unimplemented;
7815 break;
7816 case CP0_REGISTER_13:
7817 switch (sel) {
7818 case CP0_REG13__CAUSE:
7819 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7820 register_name = "Cause";
7821 break;
7822 default:
7823 goto cp0_unimplemented;
7825 break;
7826 case CP0_REGISTER_14:
7827 switch (sel) {
7828 case CP0_REG14__EPC:
7829 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7830 tcg_gen_ext32s_tl(arg, arg);
7831 register_name = "EPC";
7832 break;
7833 default:
7834 goto cp0_unimplemented;
7836 break;
7837 case CP0_REGISTER_15:
7838 switch (sel) {
7839 case CP0_REG15__PRID:
7840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7841 register_name = "PRid";
7842 break;
7843 case CP0_REG15__EBASE:
7844 check_insn(ctx, ISA_MIPS32R2);
7845 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7846 tcg_gen_ext32s_tl(arg, arg);
7847 register_name = "EBase";
7848 break;
7849 case CP0_REG15__CMGCRBASE:
7850 check_insn(ctx, ISA_MIPS32R2);
7851 CP0_CHECK(ctx->cmgcr);
7852 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7853 tcg_gen_ext32s_tl(arg, arg);
7854 register_name = "CMGCRBase";
7855 break;
7856 default:
7857 goto cp0_unimplemented;
7859 break;
7860 case CP0_REGISTER_16:
7861 switch (sel) {
7862 case CP0_REG16__CONFIG:
7863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7864 register_name = "Config";
7865 break;
7866 case CP0_REG16__CONFIG1:
7867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7868 register_name = "Config1";
7869 break;
7870 case CP0_REG16__CONFIG2:
7871 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7872 register_name = "Config2";
7873 break;
7874 case CP0_REG16__CONFIG3:
7875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7876 register_name = "Config3";
7877 break;
7878 case CP0_REG16__CONFIG4:
7879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7880 register_name = "Config4";
7881 break;
7882 case CP0_REG16__CONFIG5:
7883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7884 register_name = "Config5";
7885 break;
7886 /* 6,7 are implementation dependent */
7887 case CP0_REG16__CONFIG6:
7888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7889 register_name = "Config6";
7890 break;
7891 case CP0_REG16__CONFIG7:
7892 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7893 register_name = "Config7";
7894 break;
7895 default:
7896 goto cp0_unimplemented;
7898 break;
7899 case CP0_REGISTER_17:
7900 switch (sel) {
7901 case CP0_REG17__LLADDR:
7902 gen_helper_mfc0_lladdr(arg, cpu_env);
7903 register_name = "LLAddr";
7904 break;
7905 case CP0_REG17__MAAR:
7906 CP0_CHECK(ctx->mrp);
7907 gen_helper_mfc0_maar(arg, cpu_env);
7908 register_name = "MAAR";
7909 break;
7910 case CP0_REG17__MAARI:
7911 CP0_CHECK(ctx->mrp);
7912 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7913 register_name = "MAARI";
7914 break;
7915 default:
7916 goto cp0_unimplemented;
7918 break;
7919 case CP0_REGISTER_18:
7920 switch (sel) {
7921 case CP0_REG18__WATCHLO0:
7922 case CP0_REG18__WATCHLO1:
7923 case CP0_REG18__WATCHLO2:
7924 case CP0_REG18__WATCHLO3:
7925 case CP0_REG18__WATCHLO4:
7926 case CP0_REG18__WATCHLO5:
7927 case CP0_REG18__WATCHLO6:
7928 case CP0_REG18__WATCHLO7:
7929 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7930 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7931 register_name = "WatchLo";
7932 break;
7933 default:
7934 goto cp0_unimplemented;
7936 break;
7937 case CP0_REGISTER_19:
7938 switch (sel) {
7939 case CP0_REG19__WATCHHI0:
7940 case CP0_REG19__WATCHHI1:
7941 case CP0_REG19__WATCHHI2:
7942 case CP0_REG19__WATCHHI3:
7943 case CP0_REG19__WATCHHI4:
7944 case CP0_REG19__WATCHHI5:
7945 case CP0_REG19__WATCHHI6:
7946 case CP0_REG19__WATCHHI7:
7947 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7948 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7949 register_name = "WatchHi";
7950 break;
7951 default:
7952 goto cp0_unimplemented;
7954 break;
7955 case CP0_REGISTER_20:
7956 switch (sel) {
7957 case CP0_REG20__XCONTEXT:
7958 #if defined(TARGET_MIPS64)
7959 check_insn(ctx, ISA_MIPS3);
7960 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7961 tcg_gen_ext32s_tl(arg, arg);
7962 register_name = "XContext";
7963 break;
7964 #endif
7965 default:
7966 goto cp0_unimplemented;
7968 break;
7969 case CP0_REGISTER_21:
7970 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7971 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7972 switch (sel) {
7973 case 0:
7974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7975 register_name = "Framemask";
7976 break;
7977 default:
7978 goto cp0_unimplemented;
7980 break;
7981 case CP0_REGISTER_22:
7982 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7983 register_name = "'Diagnostic"; /* implementation dependent */
7984 break;
7985 case CP0_REGISTER_23:
7986 switch (sel) {
7987 case CP0_REG23__DEBUG:
7988 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7989 register_name = "Debug";
7990 break;
7991 case CP0_REG23__TRACECONTROL:
7992 /* PDtrace support */
7993 /* gen_helper_mfc0_tracecontrol(arg); */
7994 register_name = "TraceControl";
7995 goto cp0_unimplemented;
7996 case CP0_REG23__TRACECONTROL2:
7997 /* PDtrace support */
7998 /* gen_helper_mfc0_tracecontrol2(arg); */
7999 register_name = "TraceControl2";
8000 goto cp0_unimplemented;
8001 case CP0_REG23__USERTRACEDATA1:
8002 /* PDtrace support */
8003 /* gen_helper_mfc0_usertracedata1(arg);*/
8004 register_name = "UserTraceData1";
8005 goto cp0_unimplemented;
8006 case CP0_REG23__TRACEIBPC:
8007 /* PDtrace support */
8008 /* gen_helper_mfc0_traceibpc(arg); */
8009 register_name = "TraceIBPC";
8010 goto cp0_unimplemented;
8011 case CP0_REG23__TRACEDBPC:
8012 /* PDtrace support */
8013 /* gen_helper_mfc0_tracedbpc(arg); */
8014 register_name = "TraceDBPC";
8015 goto cp0_unimplemented;
8016 default:
8017 goto cp0_unimplemented;
8019 break;
8020 case CP0_REGISTER_24:
8021 switch (sel) {
8022 case CP0_REG24__DEPC:
8023 /* EJTAG support */
8024 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8025 tcg_gen_ext32s_tl(arg, arg);
8026 register_name = "DEPC";
8027 break;
8028 default:
8029 goto cp0_unimplemented;
8031 break;
8032 case CP0_REGISTER_25:
8033 switch (sel) {
8034 case CP0_REG25__PERFCTL0:
8035 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8036 register_name = "Performance0";
8037 break;
8038 case CP0_REG25__PERFCNT0:
8039 /* gen_helper_mfc0_performance1(arg); */
8040 register_name = "Performance1";
8041 goto cp0_unimplemented;
8042 case CP0_REG25__PERFCTL1:
8043 /* gen_helper_mfc0_performance2(arg); */
8044 register_name = "Performance2";
8045 goto cp0_unimplemented;
8046 case CP0_REG25__PERFCNT1:
8047 /* gen_helper_mfc0_performance3(arg); */
8048 register_name = "Performance3";
8049 goto cp0_unimplemented;
8050 case CP0_REG25__PERFCTL2:
8051 /* gen_helper_mfc0_performance4(arg); */
8052 register_name = "Performance4";
8053 goto cp0_unimplemented;
8054 case CP0_REG25__PERFCNT2:
8055 /* gen_helper_mfc0_performance5(arg); */
8056 register_name = "Performance5";
8057 goto cp0_unimplemented;
8058 case CP0_REG25__PERFCTL3:
8059 /* gen_helper_mfc0_performance6(arg); */
8060 register_name = "Performance6";
8061 goto cp0_unimplemented;
8062 case CP0_REG25__PERFCNT3:
8063 /* gen_helper_mfc0_performance7(arg); */
8064 register_name = "Performance7";
8065 goto cp0_unimplemented;
8066 default:
8067 goto cp0_unimplemented;
8069 break;
8070 case CP0_REGISTER_26:
8071 switch (sel) {
8072 case CP0_REG26__ERRCTL:
8073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8074 register_name = "ErrCtl";
8075 break;
8076 default:
8077 goto cp0_unimplemented;
8079 break;
8080 case CP0_REGISTER_27:
8081 switch (sel) {
8082 case CP0_REG27__CACHERR:
8083 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8084 register_name = "CacheErr";
8085 break;
8086 default:
8087 goto cp0_unimplemented;
8089 break;
8090 case CP0_REGISTER_28:
8091 switch (sel) {
8092 case CP0_REG28__TAGLO:
8093 case CP0_REG28__TAGLO1:
8094 case CP0_REG28__TAGLO2:
8095 case CP0_REG28__TAGLO3:
8097 TCGv_i64 tmp = tcg_temp_new_i64();
8098 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
8099 gen_move_low32(arg, tmp);
8100 tcg_temp_free_i64(tmp);
8102 register_name = "TagLo";
8103 break;
8104 case CP0_REG28__DATALO:
8105 case CP0_REG28__DATALO1:
8106 case CP0_REG28__DATALO2:
8107 case CP0_REG28__DATALO3:
8108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8109 register_name = "DataLo";
8110 break;
8111 default:
8112 goto cp0_unimplemented;
8114 break;
8115 case CP0_REGISTER_29:
8116 switch (sel) {
8117 case CP0_REG29__TAGHI:
8118 case CP0_REG29__TAGHI1:
8119 case CP0_REG29__TAGHI2:
8120 case CP0_REG29__TAGHI3:
8121 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8122 register_name = "TagHi";
8123 break;
8124 case CP0_REG29__DATAHI:
8125 case CP0_REG29__DATAHI1:
8126 case CP0_REG29__DATAHI2:
8127 case CP0_REG29__DATAHI3:
8128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8129 register_name = "DataHi";
8130 break;
8131 default:
8132 goto cp0_unimplemented;
8134 break;
8135 case CP0_REGISTER_30:
8136 switch (sel) {
8137 case CP0_REG30__ERROREPC:
8138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8139 tcg_gen_ext32s_tl(arg, arg);
8140 register_name = "ErrorEPC";
8141 break;
8142 default:
8143 goto cp0_unimplemented;
8145 break;
8146 case CP0_REGISTER_31:
8147 switch (sel) {
8148 case CP0_REG31__DESAVE:
8149 /* EJTAG support */
8150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8151 register_name = "DESAVE";
8152 break;
8153 case CP0_REG31__KSCRATCH1:
8154 case CP0_REG31__KSCRATCH2:
8155 case CP0_REG31__KSCRATCH3:
8156 case CP0_REG31__KSCRATCH4:
8157 case CP0_REG31__KSCRATCH5:
8158 case CP0_REG31__KSCRATCH6:
8159 CP0_CHECK(ctx->kscrexist & (1 << sel));
8160 tcg_gen_ld_tl(arg, cpu_env,
8161 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8162 tcg_gen_ext32s_tl(arg, arg);
8163 register_name = "KScratch";
8164 break;
8165 default:
8166 goto cp0_unimplemented;
8168 break;
8169 default:
8170 goto cp0_unimplemented;
8172 trace_mips_translate_c0("mfc0", register_name, reg, sel);
8173 return;
8175 cp0_unimplemented:
8176 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
8177 register_name, reg, sel);
8178 gen_mfc0_unimplemented(ctx, arg);
8181 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8183 const char *register_name = "invalid";
8185 if (sel != 0) {
8186 check_insn(ctx, ISA_MIPS32);
8189 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8190 gen_io_start();
8193 switch (reg) {
8194 case CP0_REGISTER_00:
8195 switch (sel) {
8196 case CP0_REG00__INDEX:
8197 gen_helper_mtc0_index(cpu_env, arg);
8198 register_name = "Index";
8199 break;
8200 case CP0_REG00__MVPCONTROL:
8201 CP0_CHECK(ctx->insn_flags & ASE_MT);
8202 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8203 register_name = "MVPControl";
8204 break;
8205 case CP0_REG00__MVPCONF0:
8206 CP0_CHECK(ctx->insn_flags & ASE_MT);
8207 /* ignored */
8208 register_name = "MVPConf0";
8209 break;
8210 case CP0_REG00__MVPCONF1:
8211 CP0_CHECK(ctx->insn_flags & ASE_MT);
8212 /* ignored */
8213 register_name = "MVPConf1";
8214 break;
8215 case CP0_REG00__VPCONTROL:
8216 CP0_CHECK(ctx->vp);
8217 /* ignored */
8218 register_name = "VPControl";
8219 break;
8220 default:
8221 goto cp0_unimplemented;
8223 break;
8224 case CP0_REGISTER_01:
8225 switch (sel) {
8226 case CP0_REG01__RANDOM:
8227 /* ignored */
8228 register_name = "Random";
8229 break;
8230 case CP0_REG01__VPECONTROL:
8231 CP0_CHECK(ctx->insn_flags & ASE_MT);
8232 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8233 register_name = "VPEControl";
8234 break;
8235 case CP0_REG01__VPECONF0:
8236 CP0_CHECK(ctx->insn_flags & ASE_MT);
8237 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8238 register_name = "VPEConf0";
8239 break;
8240 case CP0_REG01__VPECONF1:
8241 CP0_CHECK(ctx->insn_flags & ASE_MT);
8242 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8243 register_name = "VPEConf1";
8244 break;
8245 case CP0_REG01__YQMASK:
8246 CP0_CHECK(ctx->insn_flags & ASE_MT);
8247 gen_helper_mtc0_yqmask(cpu_env, arg);
8248 register_name = "YQMask";
8249 break;
8250 case CP0_REG01__VPESCHEDULE:
8251 CP0_CHECK(ctx->insn_flags & ASE_MT);
8252 tcg_gen_st_tl(arg, cpu_env,
8253 offsetof(CPUMIPSState, CP0_VPESchedule));
8254 register_name = "VPESchedule";
8255 break;
8256 case CP0_REG01__VPESCHEFBACK:
8257 CP0_CHECK(ctx->insn_flags & ASE_MT);
8258 tcg_gen_st_tl(arg, cpu_env,
8259 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8260 register_name = "VPEScheFBack";
8261 break;
8262 case CP0_REG01__VPEOPT:
8263 CP0_CHECK(ctx->insn_flags & ASE_MT);
8264 gen_helper_mtc0_vpeopt(cpu_env, arg);
8265 register_name = "VPEOpt";
8266 break;
8267 default:
8268 goto cp0_unimplemented;
8270 break;
8271 case CP0_REGISTER_02:
8272 switch (sel) {
8273 case CP0_REG02__ENTRYLO0:
8274 gen_helper_mtc0_entrylo0(cpu_env, arg);
8275 register_name = "EntryLo0";
8276 break;
8277 case CP0_REG02__TCSTATUS:
8278 CP0_CHECK(ctx->insn_flags & ASE_MT);
8279 gen_helper_mtc0_tcstatus(cpu_env, arg);
8280 register_name = "TCStatus";
8281 break;
8282 case CP0_REG02__TCBIND:
8283 CP0_CHECK(ctx->insn_flags & ASE_MT);
8284 gen_helper_mtc0_tcbind(cpu_env, arg);
8285 register_name = "TCBind";
8286 break;
8287 case CP0_REG02__TCRESTART:
8288 CP0_CHECK(ctx->insn_flags & ASE_MT);
8289 gen_helper_mtc0_tcrestart(cpu_env, arg);
8290 register_name = "TCRestart";
8291 break;
8292 case CP0_REG02__TCHALT:
8293 CP0_CHECK(ctx->insn_flags & ASE_MT);
8294 gen_helper_mtc0_tchalt(cpu_env, arg);
8295 register_name = "TCHalt";
8296 break;
8297 case CP0_REG02__TCCONTEXT:
8298 CP0_CHECK(ctx->insn_flags & ASE_MT);
8299 gen_helper_mtc0_tccontext(cpu_env, arg);
8300 register_name = "TCContext";
8301 break;
8302 case CP0_REG02__TCSCHEDULE:
8303 CP0_CHECK(ctx->insn_flags & ASE_MT);
8304 gen_helper_mtc0_tcschedule(cpu_env, arg);
8305 register_name = "TCSchedule";
8306 break;
8307 case CP0_REG02__TCSCHEFBACK:
8308 CP0_CHECK(ctx->insn_flags & ASE_MT);
8309 gen_helper_mtc0_tcschefback(cpu_env, arg);
8310 register_name = "TCScheFBack";
8311 break;
8312 default:
8313 goto cp0_unimplemented;
8315 break;
8316 case CP0_REGISTER_03:
8317 switch (sel) {
8318 case CP0_REG03__ENTRYLO1:
8319 gen_helper_mtc0_entrylo1(cpu_env, arg);
8320 register_name = "EntryLo1";
8321 break;
8322 case CP0_REG03__GLOBALNUM:
8323 CP0_CHECK(ctx->vp);
8324 /* ignored */
8325 register_name = "GlobalNumber";
8326 break;
8327 default:
8328 goto cp0_unimplemented;
8330 break;
8331 case CP0_REGISTER_04:
8332 switch (sel) {
8333 case CP0_REG04__CONTEXT:
8334 gen_helper_mtc0_context(cpu_env, arg);
8335 register_name = "Context";
8336 break;
8337 case CP0_REG04__CONTEXTCONFIG:
8338 /* SmartMIPS ASE */
8339 /* gen_helper_mtc0_contextconfig(arg); */
8340 register_name = "ContextConfig";
8341 goto cp0_unimplemented;
8342 case CP0_REG04__USERLOCAL:
8343 CP0_CHECK(ctx->ulri);
8344 tcg_gen_st_tl(arg, cpu_env,
8345 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8346 register_name = "UserLocal";
8347 break;
8348 case CP0_REG04__MMID:
8349 CP0_CHECK(ctx->mi);
8350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8351 register_name = "MMID";
8352 break;
8353 default:
8354 goto cp0_unimplemented;
8356 break;
8357 case CP0_REGISTER_05:
8358 switch (sel) {
8359 case CP0_REG05__PAGEMASK:
8360 gen_helper_mtc0_pagemask(cpu_env, arg);
8361 register_name = "PageMask";
8362 break;
8363 case CP0_REG05__PAGEGRAIN:
8364 check_insn(ctx, ISA_MIPS32R2);
8365 gen_helper_mtc0_pagegrain(cpu_env, arg);
8366 register_name = "PageGrain";
8367 ctx->base.is_jmp = DISAS_STOP;
8368 break;
8369 case CP0_REG05__SEGCTL0:
8370 CP0_CHECK(ctx->sc);
8371 gen_helper_mtc0_segctl0(cpu_env, arg);
8372 register_name = "SegCtl0";
8373 break;
8374 case CP0_REG05__SEGCTL1:
8375 CP0_CHECK(ctx->sc);
8376 gen_helper_mtc0_segctl1(cpu_env, arg);
8377 register_name = "SegCtl1";
8378 break;
8379 case CP0_REG05__SEGCTL2:
8380 CP0_CHECK(ctx->sc);
8381 gen_helper_mtc0_segctl2(cpu_env, arg);
8382 register_name = "SegCtl2";
8383 break;
8384 case CP0_REG05__PWBASE:
8385 check_pw(ctx);
8386 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
8387 register_name = "PWBase";
8388 break;
8389 case CP0_REG05__PWFIELD:
8390 check_pw(ctx);
8391 gen_helper_mtc0_pwfield(cpu_env, arg);
8392 register_name = "PWField";
8393 break;
8394 case CP0_REG05__PWSIZE:
8395 check_pw(ctx);
8396 gen_helper_mtc0_pwsize(cpu_env, arg);
8397 register_name = "PWSize";
8398 break;
8399 default:
8400 goto cp0_unimplemented;
8402 break;
8403 case CP0_REGISTER_06:
8404 switch (sel) {
8405 case CP0_REG06__WIRED:
8406 gen_helper_mtc0_wired(cpu_env, arg);
8407 register_name = "Wired";
8408 break;
8409 case CP0_REG06__SRSCONF0:
8410 check_insn(ctx, ISA_MIPS32R2);
8411 gen_helper_mtc0_srsconf0(cpu_env, arg);
8412 register_name = "SRSConf0";
8413 break;
8414 case CP0_REG06__SRSCONF1:
8415 check_insn(ctx, ISA_MIPS32R2);
8416 gen_helper_mtc0_srsconf1(cpu_env, arg);
8417 register_name = "SRSConf1";
8418 break;
8419 case CP0_REG06__SRSCONF2:
8420 check_insn(ctx, ISA_MIPS32R2);
8421 gen_helper_mtc0_srsconf2(cpu_env, arg);
8422 register_name = "SRSConf2";
8423 break;
8424 case CP0_REG06__SRSCONF3:
8425 check_insn(ctx, ISA_MIPS32R2);
8426 gen_helper_mtc0_srsconf3(cpu_env, arg);
8427 register_name = "SRSConf3";
8428 break;
8429 case CP0_REG06__SRSCONF4:
8430 check_insn(ctx, ISA_MIPS32R2);
8431 gen_helper_mtc0_srsconf4(cpu_env, arg);
8432 register_name = "SRSConf4";
8433 break;
8434 case CP0_REG06__PWCTL:
8435 check_pw(ctx);
8436 gen_helper_mtc0_pwctl(cpu_env, arg);
8437 register_name = "PWCtl";
8438 break;
8439 default:
8440 goto cp0_unimplemented;
8442 break;
8443 case CP0_REGISTER_07:
8444 switch (sel) {
8445 case CP0_REG07__HWRENA:
8446 check_insn(ctx, ISA_MIPS32R2);
8447 gen_helper_mtc0_hwrena(cpu_env, arg);
8448 ctx->base.is_jmp = DISAS_STOP;
8449 register_name = "HWREna";
8450 break;
8451 default:
8452 goto cp0_unimplemented;
8454 break;
8455 case CP0_REGISTER_08:
8456 switch (sel) {
8457 case CP0_REG08__BADVADDR:
8458 /* ignored */
8459 register_name = "BadVAddr";
8460 break;
8461 case CP0_REG08__BADINSTR:
8462 /* ignored */
8463 register_name = "BadInstr";
8464 break;
8465 case CP0_REG08__BADINSTRP:
8466 /* ignored */
8467 register_name = "BadInstrP";
8468 break;
8469 case CP0_REG08__BADINSTRX:
8470 /* ignored */
8471 register_name = "BadInstrX";
8472 break;
8473 default:
8474 goto cp0_unimplemented;
8476 break;
8477 case CP0_REGISTER_09:
8478 switch (sel) {
8479 case CP0_REG09__COUNT:
8480 gen_helper_mtc0_count(cpu_env, arg);
8481 register_name = "Count";
8482 break;
8483 case CP0_REG09__SAARI:
8484 CP0_CHECK(ctx->saar);
8485 gen_helper_mtc0_saari(cpu_env, arg);
8486 register_name = "SAARI";
8487 break;
8488 case CP0_REG09__SAAR:
8489 CP0_CHECK(ctx->saar);
8490 gen_helper_mtc0_saar(cpu_env, arg);
8491 register_name = "SAAR";
8492 break;
8493 default:
8494 goto cp0_unimplemented;
8496 break;
8497 case CP0_REGISTER_10:
8498 switch (sel) {
8499 case CP0_REG10__ENTRYHI:
8500 gen_helper_mtc0_entryhi(cpu_env, arg);
8501 register_name = "EntryHi";
8502 break;
8503 default:
8504 goto cp0_unimplemented;
8506 break;
8507 case CP0_REGISTER_11:
8508 switch (sel) {
8509 case CP0_REG11__COMPARE:
8510 gen_helper_mtc0_compare(cpu_env, arg);
8511 register_name = "Compare";
8512 break;
8513 /* 6,7 are implementation dependent */
8514 default:
8515 goto cp0_unimplemented;
8517 break;
8518 case CP0_REGISTER_12:
8519 switch (sel) {
8520 case CP0_REG12__STATUS:
8521 save_cpu_state(ctx, 1);
8522 gen_helper_mtc0_status(cpu_env, arg);
8523 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8524 gen_save_pc(ctx->base.pc_next + 4);
8525 ctx->base.is_jmp = DISAS_EXIT;
8526 register_name = "Status";
8527 break;
8528 case CP0_REG12__INTCTL:
8529 check_insn(ctx, ISA_MIPS32R2);
8530 gen_helper_mtc0_intctl(cpu_env, arg);
8531 /* Stop translation as we may have switched the execution mode */
8532 ctx->base.is_jmp = DISAS_STOP;
8533 register_name = "IntCtl";
8534 break;
8535 case CP0_REG12__SRSCTL:
8536 check_insn(ctx, ISA_MIPS32R2);
8537 gen_helper_mtc0_srsctl(cpu_env, arg);
8538 /* Stop translation as we may have switched the execution mode */
8539 ctx->base.is_jmp = DISAS_STOP;
8540 register_name = "SRSCtl";
8541 break;
8542 case CP0_REG12__SRSMAP:
8543 check_insn(ctx, ISA_MIPS32R2);
8544 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8545 /* Stop translation as we may have switched the execution mode */
8546 ctx->base.is_jmp = DISAS_STOP;
8547 register_name = "SRSMap";
8548 break;
8549 default:
8550 goto cp0_unimplemented;
8552 break;
8553 case CP0_REGISTER_13:
8554 switch (sel) {
8555 case CP0_REG13__CAUSE:
8556 save_cpu_state(ctx, 1);
8557 gen_helper_mtc0_cause(cpu_env, arg);
8559 * Stop translation as we may have triggered an interrupt.
8560 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8561 * translated code to check for pending interrupts.
8563 gen_save_pc(ctx->base.pc_next + 4);
8564 ctx->base.is_jmp = DISAS_EXIT;
8565 register_name = "Cause";
8566 break;
8567 default:
8568 goto cp0_unimplemented;
8570 break;
8571 case CP0_REGISTER_14:
8572 switch (sel) {
8573 case CP0_REG14__EPC:
8574 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8575 register_name = "EPC";
8576 break;
8577 default:
8578 goto cp0_unimplemented;
8580 break;
8581 case CP0_REGISTER_15:
8582 switch (sel) {
8583 case CP0_REG15__PRID:
8584 /* ignored */
8585 register_name = "PRid";
8586 break;
8587 case CP0_REG15__EBASE:
8588 check_insn(ctx, ISA_MIPS32R2);
8589 gen_helper_mtc0_ebase(cpu_env, arg);
8590 register_name = "EBase";
8591 break;
8592 default:
8593 goto cp0_unimplemented;
8595 break;
8596 case CP0_REGISTER_16:
8597 switch (sel) {
8598 case CP0_REG16__CONFIG:
8599 gen_helper_mtc0_config0(cpu_env, arg);
8600 register_name = "Config";
8601 /* Stop translation as we may have switched the execution mode */
8602 ctx->base.is_jmp = DISAS_STOP;
8603 break;
8604 case CP0_REG16__CONFIG1:
8605 /* ignored, read only */
8606 register_name = "Config1";
8607 break;
8608 case CP0_REG16__CONFIG2:
8609 gen_helper_mtc0_config2(cpu_env, arg);
8610 register_name = "Config2";
8611 /* Stop translation as we may have switched the execution mode */
8612 ctx->base.is_jmp = DISAS_STOP;
8613 break;
8614 case CP0_REG16__CONFIG3:
8615 gen_helper_mtc0_config3(cpu_env, arg);
8616 register_name = "Config3";
8617 /* Stop translation as we may have switched the execution mode */
8618 ctx->base.is_jmp = DISAS_STOP;
8619 break;
8620 case CP0_REG16__CONFIG4:
8621 gen_helper_mtc0_config4(cpu_env, arg);
8622 register_name = "Config4";
8623 ctx->base.is_jmp = DISAS_STOP;
8624 break;
8625 case CP0_REG16__CONFIG5:
8626 gen_helper_mtc0_config5(cpu_env, arg);
8627 register_name = "Config5";
8628 /* Stop translation as we may have switched the execution mode */
8629 ctx->base.is_jmp = DISAS_STOP;
8630 break;
8631 /* 6,7 are implementation dependent */
8632 case CP0_REG16__CONFIG6:
8633 /* ignored */
8634 register_name = "Config6";
8635 break;
8636 case CP0_REG16__CONFIG7:
8637 /* ignored */
8638 register_name = "Config7";
8639 break;
8640 default:
8641 register_name = "Invalid config selector";
8642 goto cp0_unimplemented;
8644 break;
8645 case CP0_REGISTER_17:
8646 switch (sel) {
8647 case CP0_REG17__LLADDR:
8648 gen_helper_mtc0_lladdr(cpu_env, arg);
8649 register_name = "LLAddr";
8650 break;
8651 case CP0_REG17__MAAR:
8652 CP0_CHECK(ctx->mrp);
8653 gen_helper_mtc0_maar(cpu_env, arg);
8654 register_name = "MAAR";
8655 break;
8656 case CP0_REG17__MAARI:
8657 CP0_CHECK(ctx->mrp);
8658 gen_helper_mtc0_maari(cpu_env, arg);
8659 register_name = "MAARI";
8660 break;
8661 default:
8662 goto cp0_unimplemented;
8664 break;
8665 case CP0_REGISTER_18:
8666 switch (sel) {
8667 case CP0_REG18__WATCHLO0:
8668 case CP0_REG18__WATCHLO1:
8669 case CP0_REG18__WATCHLO2:
8670 case CP0_REG18__WATCHLO3:
8671 case CP0_REG18__WATCHLO4:
8672 case CP0_REG18__WATCHLO5:
8673 case CP0_REG18__WATCHLO6:
8674 case CP0_REG18__WATCHLO7:
8675 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8676 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8677 register_name = "WatchLo";
8678 break;
8679 default:
8680 goto cp0_unimplemented;
8682 break;
8683 case CP0_REGISTER_19:
8684 switch (sel) {
8685 case CP0_REG19__WATCHHI0:
8686 case CP0_REG19__WATCHHI1:
8687 case CP0_REG19__WATCHHI2:
8688 case CP0_REG19__WATCHHI3:
8689 case CP0_REG19__WATCHHI4:
8690 case CP0_REG19__WATCHHI5:
8691 case CP0_REG19__WATCHHI6:
8692 case CP0_REG19__WATCHHI7:
8693 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8694 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8695 register_name = "WatchHi";
8696 break;
8697 default:
8698 goto cp0_unimplemented;
8700 break;
8701 case CP0_REGISTER_20:
8702 switch (sel) {
8703 case CP0_REG20__XCONTEXT:
8704 #if defined(TARGET_MIPS64)
8705 check_insn(ctx, ISA_MIPS3);
8706 gen_helper_mtc0_xcontext(cpu_env, arg);
8707 register_name = "XContext";
8708 break;
8709 #endif
8710 default:
8711 goto cp0_unimplemented;
8713 break;
8714 case CP0_REGISTER_21:
8715 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8716 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8717 switch (sel) {
8718 case 0:
8719 gen_helper_mtc0_framemask(cpu_env, arg);
8720 register_name = "Framemask";
8721 break;
8722 default:
8723 goto cp0_unimplemented;
8725 break;
8726 case CP0_REGISTER_22:
8727 /* ignored */
8728 register_name = "Diagnostic"; /* implementation dependent */
8729 break;
8730 case CP0_REGISTER_23:
8731 switch (sel) {
8732 case CP0_REG23__DEBUG:
8733 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8734 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8735 gen_save_pc(ctx->base.pc_next + 4);
8736 ctx->base.is_jmp = DISAS_EXIT;
8737 register_name = "Debug";
8738 break;
8739 case CP0_REG23__TRACECONTROL:
8740 /* PDtrace support */
8741 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8742 register_name = "TraceControl";
8743 /* Stop translation as we may have switched the execution mode */
8744 ctx->base.is_jmp = DISAS_STOP;
8745 goto cp0_unimplemented;
8746 case CP0_REG23__TRACECONTROL2:
8747 /* PDtrace support */
8748 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8749 register_name = "TraceControl2";
8750 /* Stop translation as we may have switched the execution mode */
8751 ctx->base.is_jmp = DISAS_STOP;
8752 goto cp0_unimplemented;
8753 case CP0_REG23__USERTRACEDATA1:
8754 /* Stop translation as we may have switched the execution mode */
8755 ctx->base.is_jmp = DISAS_STOP;
8756 /* PDtrace support */
8757 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8758 register_name = "UserTraceData";
8759 /* Stop translation as we may have switched the execution mode */
8760 ctx->base.is_jmp = DISAS_STOP;
8761 goto cp0_unimplemented;
8762 case CP0_REG23__TRACEIBPC:
8763 /* PDtrace support */
8764 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8765 /* Stop translation as we may have switched the execution mode */
8766 ctx->base.is_jmp = DISAS_STOP;
8767 register_name = "TraceIBPC";
8768 goto cp0_unimplemented;
8769 case CP0_REG23__TRACEDBPC:
8770 /* PDtrace support */
8771 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8772 /* Stop translation as we may have switched the execution mode */
8773 ctx->base.is_jmp = DISAS_STOP;
8774 register_name = "TraceDBPC";
8775 goto cp0_unimplemented;
8776 default:
8777 goto cp0_unimplemented;
8779 break;
8780 case CP0_REGISTER_24:
8781 switch (sel) {
8782 case CP0_REG24__DEPC:
8783 /* EJTAG support */
8784 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8785 register_name = "DEPC";
8786 break;
8787 default:
8788 goto cp0_unimplemented;
8790 break;
8791 case CP0_REGISTER_25:
8792 switch (sel) {
8793 case CP0_REG25__PERFCTL0:
8794 gen_helper_mtc0_performance0(cpu_env, arg);
8795 register_name = "Performance0";
8796 break;
8797 case CP0_REG25__PERFCNT0:
8798 /* gen_helper_mtc0_performance1(arg); */
8799 register_name = "Performance1";
8800 goto cp0_unimplemented;
8801 case CP0_REG25__PERFCTL1:
8802 /* gen_helper_mtc0_performance2(arg); */
8803 register_name = "Performance2";
8804 goto cp0_unimplemented;
8805 case CP0_REG25__PERFCNT1:
8806 /* gen_helper_mtc0_performance3(arg); */
8807 register_name = "Performance3";
8808 goto cp0_unimplemented;
8809 case CP0_REG25__PERFCTL2:
8810 /* gen_helper_mtc0_performance4(arg); */
8811 register_name = "Performance4";
8812 goto cp0_unimplemented;
8813 case CP0_REG25__PERFCNT2:
8814 /* gen_helper_mtc0_performance5(arg); */
8815 register_name = "Performance5";
8816 goto cp0_unimplemented;
8817 case CP0_REG25__PERFCTL3:
8818 /* gen_helper_mtc0_performance6(arg); */
8819 register_name = "Performance6";
8820 goto cp0_unimplemented;
8821 case CP0_REG25__PERFCNT3:
8822 /* gen_helper_mtc0_performance7(arg); */
8823 register_name = "Performance7";
8824 goto cp0_unimplemented;
8825 default:
8826 goto cp0_unimplemented;
8828 break;
8829 case CP0_REGISTER_26:
8830 switch (sel) {
8831 case CP0_REG26__ERRCTL:
8832 gen_helper_mtc0_errctl(cpu_env, arg);
8833 ctx->base.is_jmp = DISAS_STOP;
8834 register_name = "ErrCtl";
8835 break;
8836 default:
8837 goto cp0_unimplemented;
8839 break;
8840 case CP0_REGISTER_27:
8841 switch (sel) {
8842 case CP0_REG27__CACHERR:
8843 /* ignored */
8844 register_name = "CacheErr";
8845 break;
8846 default:
8847 goto cp0_unimplemented;
8849 break;
8850 case CP0_REGISTER_28:
8851 switch (sel) {
8852 case CP0_REG28__TAGLO:
8853 case CP0_REG28__TAGLO1:
8854 case CP0_REG28__TAGLO2:
8855 case CP0_REG28__TAGLO3:
8856 gen_helper_mtc0_taglo(cpu_env, arg);
8857 register_name = "TagLo";
8858 break;
8859 case CP0_REG28__DATALO:
8860 case CP0_REG28__DATALO1:
8861 case CP0_REG28__DATALO2:
8862 case CP0_REG28__DATALO3:
8863 gen_helper_mtc0_datalo(cpu_env, arg);
8864 register_name = "DataLo";
8865 break;
8866 default:
8867 goto cp0_unimplemented;
8869 break;
8870 case CP0_REGISTER_29:
8871 switch (sel) {
8872 case CP0_REG29__TAGHI:
8873 case CP0_REG29__TAGHI1:
8874 case CP0_REG29__TAGHI2:
8875 case CP0_REG29__TAGHI3:
8876 gen_helper_mtc0_taghi(cpu_env, arg);
8877 register_name = "TagHi";
8878 break;
8879 case CP0_REG29__DATAHI:
8880 case CP0_REG29__DATAHI1:
8881 case CP0_REG29__DATAHI2:
8882 case CP0_REG29__DATAHI3:
8883 gen_helper_mtc0_datahi(cpu_env, arg);
8884 register_name = "DataHi";
8885 break;
8886 default:
8887 register_name = "invalid sel";
8888 goto cp0_unimplemented;
8890 break;
8891 case CP0_REGISTER_30:
8892 switch (sel) {
8893 case CP0_REG30__ERROREPC:
8894 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8895 register_name = "ErrorEPC";
8896 break;
8897 default:
8898 goto cp0_unimplemented;
8900 break;
8901 case CP0_REGISTER_31:
8902 switch (sel) {
8903 case CP0_REG31__DESAVE:
8904 /* EJTAG support */
8905 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8906 register_name = "DESAVE";
8907 break;
8908 case CP0_REG31__KSCRATCH1:
8909 case CP0_REG31__KSCRATCH2:
8910 case CP0_REG31__KSCRATCH3:
8911 case CP0_REG31__KSCRATCH4:
8912 case CP0_REG31__KSCRATCH5:
8913 case CP0_REG31__KSCRATCH6:
8914 CP0_CHECK(ctx->kscrexist & (1 << sel));
8915 tcg_gen_st_tl(arg, cpu_env,
8916 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8917 register_name = "KScratch";
8918 break;
8919 default:
8920 goto cp0_unimplemented;
8922 break;
8923 default:
8924 goto cp0_unimplemented;
8926 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8928 /* For simplicity assume that all writes can cause interrupts. */
8929 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8931 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8932 * translated code to check for pending interrupts.
8934 gen_save_pc(ctx->base.pc_next + 4);
8935 ctx->base.is_jmp = DISAS_EXIT;
8937 return;
8939 cp0_unimplemented:
8940 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8941 register_name, reg, sel);
8944 #if defined(TARGET_MIPS64)
8945 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8947 const char *register_name = "invalid";
8949 if (sel != 0) {
8950 check_insn(ctx, ISA_MIPS64);
8953 switch (reg) {
8954 case CP0_REGISTER_00:
8955 switch (sel) {
8956 case CP0_REG00__INDEX:
8957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8958 register_name = "Index";
8959 break;
8960 case CP0_REG00__MVPCONTROL:
8961 CP0_CHECK(ctx->insn_flags & ASE_MT);
8962 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8963 register_name = "MVPControl";
8964 break;
8965 case CP0_REG00__MVPCONF0:
8966 CP0_CHECK(ctx->insn_flags & ASE_MT);
8967 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8968 register_name = "MVPConf0";
8969 break;
8970 case CP0_REG00__MVPCONF1:
8971 CP0_CHECK(ctx->insn_flags & ASE_MT);
8972 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8973 register_name = "MVPConf1";
8974 break;
8975 case CP0_REG00__VPCONTROL:
8976 CP0_CHECK(ctx->vp);
8977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8978 register_name = "VPControl";
8979 break;
8980 default:
8981 goto cp0_unimplemented;
8983 break;
8984 case CP0_REGISTER_01:
8985 switch (sel) {
8986 case CP0_REG01__RANDOM:
8987 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8988 gen_helper_mfc0_random(arg, cpu_env);
8989 register_name = "Random";
8990 break;
8991 case CP0_REG01__VPECONTROL:
8992 CP0_CHECK(ctx->insn_flags & ASE_MT);
8993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8994 register_name = "VPEControl";
8995 break;
8996 case CP0_REG01__VPECONF0:
8997 CP0_CHECK(ctx->insn_flags & ASE_MT);
8998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8999 register_name = "VPEConf0";
9000 break;
9001 case CP0_REG01__VPECONF1:
9002 CP0_CHECK(ctx->insn_flags & ASE_MT);
9003 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9004 register_name = "VPEConf1";
9005 break;
9006 case CP0_REG01__YQMASK:
9007 CP0_CHECK(ctx->insn_flags & ASE_MT);
9008 tcg_gen_ld_tl(arg, cpu_env,
9009 offsetof(CPUMIPSState, CP0_YQMask));
9010 register_name = "YQMask";
9011 break;
9012 case CP0_REG01__VPESCHEDULE:
9013 CP0_CHECK(ctx->insn_flags & ASE_MT);
9014 tcg_gen_ld_tl(arg, cpu_env,
9015 offsetof(CPUMIPSState, CP0_VPESchedule));
9016 register_name = "VPESchedule";
9017 break;
9018 case CP0_REG01__VPESCHEFBACK:
9019 CP0_CHECK(ctx->insn_flags & ASE_MT);
9020 tcg_gen_ld_tl(arg, cpu_env,
9021 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9022 register_name = "VPEScheFBack";
9023 break;
9024 case CP0_REG01__VPEOPT:
9025 CP0_CHECK(ctx->insn_flags & ASE_MT);
9026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9027 register_name = "VPEOpt";
9028 break;
9029 default:
9030 goto cp0_unimplemented;
9032 break;
9033 case CP0_REGISTER_02:
9034 switch (sel) {
9035 case CP0_REG02__ENTRYLO0:
9036 tcg_gen_ld_tl(arg, cpu_env,
9037 offsetof(CPUMIPSState, CP0_EntryLo0));
9038 register_name = "EntryLo0";
9039 break;
9040 case CP0_REG02__TCSTATUS:
9041 CP0_CHECK(ctx->insn_flags & ASE_MT);
9042 gen_helper_mfc0_tcstatus(arg, cpu_env);
9043 register_name = "TCStatus";
9044 break;
9045 case CP0_REG02__TCBIND:
9046 CP0_CHECK(ctx->insn_flags & ASE_MT);
9047 gen_helper_mfc0_tcbind(arg, cpu_env);
9048 register_name = "TCBind";
9049 break;
9050 case CP0_REG02__TCRESTART:
9051 CP0_CHECK(ctx->insn_flags & ASE_MT);
9052 gen_helper_dmfc0_tcrestart(arg, cpu_env);
9053 register_name = "TCRestart";
9054 break;
9055 case CP0_REG02__TCHALT:
9056 CP0_CHECK(ctx->insn_flags & ASE_MT);
9057 gen_helper_dmfc0_tchalt(arg, cpu_env);
9058 register_name = "TCHalt";
9059 break;
9060 case CP0_REG02__TCCONTEXT:
9061 CP0_CHECK(ctx->insn_flags & ASE_MT);
9062 gen_helper_dmfc0_tccontext(arg, cpu_env);
9063 register_name = "TCContext";
9064 break;
9065 case CP0_REG02__TCSCHEDULE:
9066 CP0_CHECK(ctx->insn_flags & ASE_MT);
9067 gen_helper_dmfc0_tcschedule(arg, cpu_env);
9068 register_name = "TCSchedule";
9069 break;
9070 case CP0_REG02__TCSCHEFBACK:
9071 CP0_CHECK(ctx->insn_flags & ASE_MT);
9072 gen_helper_dmfc0_tcschefback(arg, cpu_env);
9073 register_name = "TCScheFBack";
9074 break;
9075 default:
9076 goto cp0_unimplemented;
9078 break;
9079 case CP0_REGISTER_03:
9080 switch (sel) {
9081 case CP0_REG03__ENTRYLO1:
9082 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
9083 register_name = "EntryLo1";
9084 break;
9085 case CP0_REG03__GLOBALNUM:
9086 CP0_CHECK(ctx->vp);
9087 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
9088 register_name = "GlobalNumber";
9089 break;
9090 default:
9091 goto cp0_unimplemented;
9093 break;
9094 case CP0_REGISTER_04:
9095 switch (sel) {
9096 case CP0_REG04__CONTEXT:
9097 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
9098 register_name = "Context";
9099 break;
9100 case CP0_REG04__CONTEXTCONFIG:
9101 /* SmartMIPS ASE */
9102 /* gen_helper_dmfc0_contextconfig(arg); */
9103 register_name = "ContextConfig";
9104 goto cp0_unimplemented;
9105 case CP0_REG04__USERLOCAL:
9106 CP0_CHECK(ctx->ulri);
9107 tcg_gen_ld_tl(arg, cpu_env,
9108 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9109 register_name = "UserLocal";
9110 break;
9111 case CP0_REG04__MMID:
9112 CP0_CHECK(ctx->mi);
9113 gen_helper_mtc0_memorymapid(cpu_env, arg);
9114 register_name = "MMID";
9115 break;
9116 default:
9117 goto cp0_unimplemented;
9119 break;
9120 case CP0_REGISTER_05:
9121 switch (sel) {
9122 case CP0_REG05__PAGEMASK:
9123 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
9124 register_name = "PageMask";
9125 break;
9126 case CP0_REG05__PAGEGRAIN:
9127 check_insn(ctx, ISA_MIPS32R2);
9128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
9129 register_name = "PageGrain";
9130 break;
9131 case CP0_REG05__SEGCTL0:
9132 CP0_CHECK(ctx->sc);
9133 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
9134 register_name = "SegCtl0";
9135 break;
9136 case CP0_REG05__SEGCTL1:
9137 CP0_CHECK(ctx->sc);
9138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
9139 register_name = "SegCtl1";
9140 break;
9141 case CP0_REG05__SEGCTL2:
9142 CP0_CHECK(ctx->sc);
9143 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
9144 register_name = "SegCtl2";
9145 break;
9146 case CP0_REG05__PWBASE:
9147 check_pw(ctx);
9148 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9149 register_name = "PWBase";
9150 break;
9151 case CP0_REG05__PWFIELD:
9152 check_pw(ctx);
9153 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
9154 register_name = "PWField";
9155 break;
9156 case CP0_REG05__PWSIZE:
9157 check_pw(ctx);
9158 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
9159 register_name = "PWSize";
9160 break;
9161 default:
9162 goto cp0_unimplemented;
9164 break;
9165 case CP0_REGISTER_06:
9166 switch (sel) {
9167 case CP0_REG06__WIRED:
9168 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
9169 register_name = "Wired";
9170 break;
9171 case CP0_REG06__SRSCONF0:
9172 check_insn(ctx, ISA_MIPS32R2);
9173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
9174 register_name = "SRSConf0";
9175 break;
9176 case CP0_REG06__SRSCONF1:
9177 check_insn(ctx, ISA_MIPS32R2);
9178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
9179 register_name = "SRSConf1";
9180 break;
9181 case CP0_REG06__SRSCONF2:
9182 check_insn(ctx, ISA_MIPS32R2);
9183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
9184 register_name = "SRSConf2";
9185 break;
9186 case CP0_REG06__SRSCONF3:
9187 check_insn(ctx, ISA_MIPS32R2);
9188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
9189 register_name = "SRSConf3";
9190 break;
9191 case CP0_REG06__SRSCONF4:
9192 check_insn(ctx, ISA_MIPS32R2);
9193 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
9194 register_name = "SRSConf4";
9195 break;
9196 case CP0_REG06__PWCTL:
9197 check_pw(ctx);
9198 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
9199 register_name = "PWCtl";
9200 break;
9201 default:
9202 goto cp0_unimplemented;
9204 break;
9205 case CP0_REGISTER_07:
9206 switch (sel) {
9207 case CP0_REG07__HWRENA:
9208 check_insn(ctx, ISA_MIPS32R2);
9209 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
9210 register_name = "HWREna";
9211 break;
9212 default:
9213 goto cp0_unimplemented;
9215 break;
9216 case CP0_REGISTER_08:
9217 switch (sel) {
9218 case CP0_REG08__BADVADDR:
9219 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
9220 register_name = "BadVAddr";
9221 break;
9222 case CP0_REG08__BADINSTR:
9223 CP0_CHECK(ctx->bi);
9224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
9225 register_name = "BadInstr";
9226 break;
9227 case CP0_REG08__BADINSTRP:
9228 CP0_CHECK(ctx->bp);
9229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
9230 register_name = "BadInstrP";
9231 break;
9232 case CP0_REG08__BADINSTRX:
9233 CP0_CHECK(ctx->bi);
9234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
9235 tcg_gen_andi_tl(arg, arg, ~0xffff);
9236 register_name = "BadInstrX";
9237 break;
9238 default:
9239 goto cp0_unimplemented;
9241 break;
9242 case CP0_REGISTER_09:
9243 switch (sel) {
9244 case CP0_REG09__COUNT:
9245 /* Mark as an IO operation because we read the time. */
9246 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9247 gen_io_start();
9249 gen_helper_mfc0_count(arg, cpu_env);
9251 * Break the TB to be able to take timer interrupts immediately
9252 * after reading count. DISAS_STOP isn't sufficient, we need to
9253 * ensure we break completely out of translated code.
9255 gen_save_pc(ctx->base.pc_next + 4);
9256 ctx->base.is_jmp = DISAS_EXIT;
9257 register_name = "Count";
9258 break;
9259 case CP0_REG09__SAARI:
9260 CP0_CHECK(ctx->saar);
9261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
9262 register_name = "SAARI";
9263 break;
9264 case CP0_REG09__SAAR:
9265 CP0_CHECK(ctx->saar);
9266 gen_helper_dmfc0_saar(arg, cpu_env);
9267 register_name = "SAAR";
9268 break;
9269 default:
9270 goto cp0_unimplemented;
9272 break;
9273 case CP0_REGISTER_10:
9274 switch (sel) {
9275 case CP0_REG10__ENTRYHI:
9276 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
9277 register_name = "EntryHi";
9278 break;
9279 default:
9280 goto cp0_unimplemented;
9282 break;
9283 case CP0_REGISTER_11:
9284 switch (sel) {
9285 case CP0_REG11__COMPARE:
9286 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
9287 register_name = "Compare";
9288 break;
9289 /* 6,7 are implementation dependent */
9290 default:
9291 goto cp0_unimplemented;
9293 break;
9294 case CP0_REGISTER_12:
9295 switch (sel) {
9296 case CP0_REG12__STATUS:
9297 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
9298 register_name = "Status";
9299 break;
9300 case CP0_REG12__INTCTL:
9301 check_insn(ctx, ISA_MIPS32R2);
9302 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
9303 register_name = "IntCtl";
9304 break;
9305 case CP0_REG12__SRSCTL:
9306 check_insn(ctx, ISA_MIPS32R2);
9307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
9308 register_name = "SRSCtl";
9309 break;
9310 case CP0_REG12__SRSMAP:
9311 check_insn(ctx, ISA_MIPS32R2);
9312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9313 register_name = "SRSMap";
9314 break;
9315 default:
9316 goto cp0_unimplemented;
9318 break;
9319 case CP0_REGISTER_13:
9320 switch (sel) {
9321 case CP0_REG13__CAUSE:
9322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
9323 register_name = "Cause";
9324 break;
9325 default:
9326 goto cp0_unimplemented;
9328 break;
9329 case CP0_REGISTER_14:
9330 switch (sel) {
9331 case CP0_REG14__EPC:
9332 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9333 register_name = "EPC";
9334 break;
9335 default:
9336 goto cp0_unimplemented;
9338 break;
9339 case CP0_REGISTER_15:
9340 switch (sel) {
9341 case CP0_REG15__PRID:
9342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
9343 register_name = "PRid";
9344 break;
9345 case CP0_REG15__EBASE:
9346 check_insn(ctx, ISA_MIPS32R2);
9347 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
9348 register_name = "EBase";
9349 break;
9350 case CP0_REG15__CMGCRBASE:
9351 check_insn(ctx, ISA_MIPS32R2);
9352 CP0_CHECK(ctx->cmgcr);
9353 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
9354 register_name = "CMGCRBase";
9355 break;
9356 default:
9357 goto cp0_unimplemented;
9359 break;
9360 case CP0_REGISTER_16:
9361 switch (sel) {
9362 case CP0_REG16__CONFIG:
9363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9364 register_name = "Config";
9365 break;
9366 case CP0_REG16__CONFIG1:
9367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9368 register_name = "Config1";
9369 break;
9370 case CP0_REG16__CONFIG2:
9371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9372 register_name = "Config2";
9373 break;
9374 case CP0_REG16__CONFIG3:
9375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9376 register_name = "Config3";
9377 break;
9378 case CP0_REG16__CONFIG4:
9379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
9380 register_name = "Config4";
9381 break;
9382 case CP0_REG16__CONFIG5:
9383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
9384 register_name = "Config5";
9385 break;
9386 /* 6,7 are implementation dependent */
9387 case CP0_REG16__CONFIG6:
9388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
9389 register_name = "Config6";
9390 break;
9391 case CP0_REG16__CONFIG7:
9392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
9393 register_name = "Config7";
9394 break;
9395 default:
9396 goto cp0_unimplemented;
9398 break;
9399 case CP0_REGISTER_17:
9400 switch (sel) {
9401 case CP0_REG17__LLADDR:
9402 gen_helper_dmfc0_lladdr(arg, cpu_env);
9403 register_name = "LLAddr";
9404 break;
9405 case CP0_REG17__MAAR:
9406 CP0_CHECK(ctx->mrp);
9407 gen_helper_dmfc0_maar(arg, cpu_env);
9408 register_name = "MAAR";
9409 break;
9410 case CP0_REG17__MAARI:
9411 CP0_CHECK(ctx->mrp);
9412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9413 register_name = "MAARI";
9414 break;
9415 default:
9416 goto cp0_unimplemented;
9418 break;
9419 case CP0_REGISTER_18:
9420 switch (sel) {
9421 case CP0_REG18__WATCHLO0:
9422 case CP0_REG18__WATCHLO1:
9423 case CP0_REG18__WATCHLO2:
9424 case CP0_REG18__WATCHLO3:
9425 case CP0_REG18__WATCHLO4:
9426 case CP0_REG18__WATCHLO5:
9427 case CP0_REG18__WATCHLO6:
9428 case CP0_REG18__WATCHLO7:
9429 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9430 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9431 register_name = "WatchLo";
9432 break;
9433 default:
9434 goto cp0_unimplemented;
9436 break;
9437 case CP0_REGISTER_19:
9438 switch (sel) {
9439 case CP0_REG19__WATCHHI0:
9440 case CP0_REG19__WATCHHI1:
9441 case CP0_REG19__WATCHHI2:
9442 case CP0_REG19__WATCHHI3:
9443 case CP0_REG19__WATCHHI4:
9444 case CP0_REG19__WATCHHI5:
9445 case CP0_REG19__WATCHHI6:
9446 case CP0_REG19__WATCHHI7:
9447 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9448 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9449 register_name = "WatchHi";
9450 break;
9451 default:
9452 goto cp0_unimplemented;
9454 break;
9455 case CP0_REGISTER_20:
9456 switch (sel) {
9457 case CP0_REG20__XCONTEXT:
9458 check_insn(ctx, ISA_MIPS3);
9459 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9460 register_name = "XContext";
9461 break;
9462 default:
9463 goto cp0_unimplemented;
9465 break;
9466 case CP0_REGISTER_21:
9467 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9468 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9469 switch (sel) {
9470 case 0:
9471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9472 register_name = "Framemask";
9473 break;
9474 default:
9475 goto cp0_unimplemented;
9477 break;
9478 case CP0_REGISTER_22:
9479 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9480 register_name = "'Diagnostic"; /* implementation dependent */
9481 break;
9482 case CP0_REGISTER_23:
9483 switch (sel) {
9484 case CP0_REG23__DEBUG:
9485 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9486 register_name = "Debug";
9487 break;
9488 case CP0_REG23__TRACECONTROL:
9489 /* PDtrace support */
9490 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9491 register_name = "TraceControl";
9492 goto cp0_unimplemented;
9493 case CP0_REG23__TRACECONTROL2:
9494 /* PDtrace support */
9495 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9496 register_name = "TraceControl2";
9497 goto cp0_unimplemented;
9498 case CP0_REG23__USERTRACEDATA1:
9499 /* PDtrace support */
9500 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9501 register_name = "UserTraceData1";
9502 goto cp0_unimplemented;
9503 case CP0_REG23__TRACEIBPC:
9504 /* PDtrace support */
9505 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9506 register_name = "TraceIBPC";
9507 goto cp0_unimplemented;
9508 case CP0_REG23__TRACEDBPC:
9509 /* PDtrace support */
9510 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9511 register_name = "TraceDBPC";
9512 goto cp0_unimplemented;
9513 default:
9514 goto cp0_unimplemented;
9516 break;
9517 case CP0_REGISTER_24:
9518 switch (sel) {
9519 case CP0_REG24__DEPC:
9520 /* EJTAG support */
9521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9522 register_name = "DEPC";
9523 break;
9524 default:
9525 goto cp0_unimplemented;
9527 break;
9528 case CP0_REGISTER_25:
9529 switch (sel) {
9530 case CP0_REG25__PERFCTL0:
9531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9532 register_name = "Performance0";
9533 break;
9534 case CP0_REG25__PERFCNT0:
9535 /* gen_helper_dmfc0_performance1(arg); */
9536 register_name = "Performance1";
9537 goto cp0_unimplemented;
9538 case CP0_REG25__PERFCTL1:
9539 /* gen_helper_dmfc0_performance2(arg); */
9540 register_name = "Performance2";
9541 goto cp0_unimplemented;
9542 case CP0_REG25__PERFCNT1:
9543 /* gen_helper_dmfc0_performance3(arg); */
9544 register_name = "Performance3";
9545 goto cp0_unimplemented;
9546 case CP0_REG25__PERFCTL2:
9547 /* gen_helper_dmfc0_performance4(arg); */
9548 register_name = "Performance4";
9549 goto cp0_unimplemented;
9550 case CP0_REG25__PERFCNT2:
9551 /* gen_helper_dmfc0_performance5(arg); */
9552 register_name = "Performance5";
9553 goto cp0_unimplemented;
9554 case CP0_REG25__PERFCTL3:
9555 /* gen_helper_dmfc0_performance6(arg); */
9556 register_name = "Performance6";
9557 goto cp0_unimplemented;
9558 case CP0_REG25__PERFCNT3:
9559 /* gen_helper_dmfc0_performance7(arg); */
9560 register_name = "Performance7";
9561 goto cp0_unimplemented;
9562 default:
9563 goto cp0_unimplemented;
9565 break;
9566 case CP0_REGISTER_26:
9567 switch (sel) {
9568 case CP0_REG26__ERRCTL:
9569 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9570 register_name = "ErrCtl";
9571 break;
9572 default:
9573 goto cp0_unimplemented;
9575 break;
9576 case CP0_REGISTER_27:
9577 switch (sel) {
9578 /* ignored */
9579 case CP0_REG27__CACHERR:
9580 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9581 register_name = "CacheErr";
9582 break;
9583 default:
9584 goto cp0_unimplemented;
9586 break;
9587 case CP0_REGISTER_28:
9588 switch (sel) {
9589 case CP0_REG28__TAGLO:
9590 case CP0_REG28__TAGLO1:
9591 case CP0_REG28__TAGLO2:
9592 case CP0_REG28__TAGLO3:
9593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9594 register_name = "TagLo";
9595 break;
9596 case CP0_REG28__DATALO:
9597 case CP0_REG28__DATALO1:
9598 case CP0_REG28__DATALO2:
9599 case CP0_REG28__DATALO3:
9600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9601 register_name = "DataLo";
9602 break;
9603 default:
9604 goto cp0_unimplemented;
9606 break;
9607 case CP0_REGISTER_29:
9608 switch (sel) {
9609 case CP0_REG29__TAGHI:
9610 case CP0_REG29__TAGHI1:
9611 case CP0_REG29__TAGHI2:
9612 case CP0_REG29__TAGHI3:
9613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9614 register_name = "TagHi";
9615 break;
9616 case CP0_REG29__DATAHI:
9617 case CP0_REG29__DATAHI1:
9618 case CP0_REG29__DATAHI2:
9619 case CP0_REG29__DATAHI3:
9620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9621 register_name = "DataHi";
9622 break;
9623 default:
9624 goto cp0_unimplemented;
9626 break;
9627 case CP0_REGISTER_30:
9628 switch (sel) {
9629 case CP0_REG30__ERROREPC:
9630 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9631 register_name = "ErrorEPC";
9632 break;
9633 default:
9634 goto cp0_unimplemented;
9636 break;
9637 case CP0_REGISTER_31:
9638 switch (sel) {
9639 case CP0_REG31__DESAVE:
9640 /* EJTAG support */
9641 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9642 register_name = "DESAVE";
9643 break;
9644 case CP0_REG31__KSCRATCH1:
9645 case CP0_REG31__KSCRATCH2:
9646 case CP0_REG31__KSCRATCH3:
9647 case CP0_REG31__KSCRATCH4:
9648 case CP0_REG31__KSCRATCH5:
9649 case CP0_REG31__KSCRATCH6:
9650 CP0_CHECK(ctx->kscrexist & (1 << sel));
9651 tcg_gen_ld_tl(arg, cpu_env,
9652 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9653 register_name = "KScratch";
9654 break;
9655 default:
9656 goto cp0_unimplemented;
9658 break;
9659 default:
9660 goto cp0_unimplemented;
9662 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9663 return;
9665 cp0_unimplemented:
9666 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9667 register_name, reg, sel);
9668 gen_mfc0_unimplemented(ctx, arg);
9671 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9673 const char *register_name = "invalid";
9675 if (sel != 0) {
9676 check_insn(ctx, ISA_MIPS64);
9679 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9680 gen_io_start();
9683 switch (reg) {
9684 case CP0_REGISTER_00:
9685 switch (sel) {
9686 case CP0_REG00__INDEX:
9687 gen_helper_mtc0_index(cpu_env, arg);
9688 register_name = "Index";
9689 break;
9690 case CP0_REG00__MVPCONTROL:
9691 CP0_CHECK(ctx->insn_flags & ASE_MT);
9692 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9693 register_name = "MVPControl";
9694 break;
9695 case CP0_REG00__MVPCONF0:
9696 CP0_CHECK(ctx->insn_flags & ASE_MT);
9697 /* ignored */
9698 register_name = "MVPConf0";
9699 break;
9700 case CP0_REG00__MVPCONF1:
9701 CP0_CHECK(ctx->insn_flags & ASE_MT);
9702 /* ignored */
9703 register_name = "MVPConf1";
9704 break;
9705 case CP0_REG00__VPCONTROL:
9706 CP0_CHECK(ctx->vp);
9707 /* ignored */
9708 register_name = "VPControl";
9709 break;
9710 default:
9711 goto cp0_unimplemented;
9713 break;
9714 case CP0_REGISTER_01:
9715 switch (sel) {
9716 case CP0_REG01__RANDOM:
9717 /* ignored */
9718 register_name = "Random";
9719 break;
9720 case CP0_REG01__VPECONTROL:
9721 CP0_CHECK(ctx->insn_flags & ASE_MT);
9722 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9723 register_name = "VPEControl";
9724 break;
9725 case CP0_REG01__VPECONF0:
9726 CP0_CHECK(ctx->insn_flags & ASE_MT);
9727 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9728 register_name = "VPEConf0";
9729 break;
9730 case CP0_REG01__VPECONF1:
9731 CP0_CHECK(ctx->insn_flags & ASE_MT);
9732 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9733 register_name = "VPEConf1";
9734 break;
9735 case CP0_REG01__YQMASK:
9736 CP0_CHECK(ctx->insn_flags & ASE_MT);
9737 gen_helper_mtc0_yqmask(cpu_env, arg);
9738 register_name = "YQMask";
9739 break;
9740 case CP0_REG01__VPESCHEDULE:
9741 CP0_CHECK(ctx->insn_flags & ASE_MT);
9742 tcg_gen_st_tl(arg, cpu_env,
9743 offsetof(CPUMIPSState, CP0_VPESchedule));
9744 register_name = "VPESchedule";
9745 break;
9746 case CP0_REG01__VPESCHEFBACK:
9747 CP0_CHECK(ctx->insn_flags & ASE_MT);
9748 tcg_gen_st_tl(arg, cpu_env,
9749 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9750 register_name = "VPEScheFBack";
9751 break;
9752 case CP0_REG01__VPEOPT:
9753 CP0_CHECK(ctx->insn_flags & ASE_MT);
9754 gen_helper_mtc0_vpeopt(cpu_env, arg);
9755 register_name = "VPEOpt";
9756 break;
9757 default:
9758 goto cp0_unimplemented;
9760 break;
9761 case CP0_REGISTER_02:
9762 switch (sel) {
9763 case CP0_REG02__ENTRYLO0:
9764 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9765 register_name = "EntryLo0";
9766 break;
9767 case CP0_REG02__TCSTATUS:
9768 CP0_CHECK(ctx->insn_flags & ASE_MT);
9769 gen_helper_mtc0_tcstatus(cpu_env, arg);
9770 register_name = "TCStatus";
9771 break;
9772 case CP0_REG02__TCBIND:
9773 CP0_CHECK(ctx->insn_flags & ASE_MT);
9774 gen_helper_mtc0_tcbind(cpu_env, arg);
9775 register_name = "TCBind";
9776 break;
9777 case CP0_REG02__TCRESTART:
9778 CP0_CHECK(ctx->insn_flags & ASE_MT);
9779 gen_helper_mtc0_tcrestart(cpu_env, arg);
9780 register_name = "TCRestart";
9781 break;
9782 case CP0_REG02__TCHALT:
9783 CP0_CHECK(ctx->insn_flags & ASE_MT);
9784 gen_helper_mtc0_tchalt(cpu_env, arg);
9785 register_name = "TCHalt";
9786 break;
9787 case CP0_REG02__TCCONTEXT:
9788 CP0_CHECK(ctx->insn_flags & ASE_MT);
9789 gen_helper_mtc0_tccontext(cpu_env, arg);
9790 register_name = "TCContext";
9791 break;
9792 case CP0_REG02__TCSCHEDULE:
9793 CP0_CHECK(ctx->insn_flags & ASE_MT);
9794 gen_helper_mtc0_tcschedule(cpu_env, arg);
9795 register_name = "TCSchedule";
9796 break;
9797 case CP0_REG02__TCSCHEFBACK:
9798 CP0_CHECK(ctx->insn_flags & ASE_MT);
9799 gen_helper_mtc0_tcschefback(cpu_env, arg);
9800 register_name = "TCScheFBack";
9801 break;
9802 default:
9803 goto cp0_unimplemented;
9805 break;
9806 case CP0_REGISTER_03:
9807 switch (sel) {
9808 case CP0_REG03__ENTRYLO1:
9809 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9810 register_name = "EntryLo1";
9811 break;
9812 case CP0_REG03__GLOBALNUM:
9813 CP0_CHECK(ctx->vp);
9814 /* ignored */
9815 register_name = "GlobalNumber";
9816 break;
9817 default:
9818 goto cp0_unimplemented;
9820 break;
9821 case CP0_REGISTER_04:
9822 switch (sel) {
9823 case CP0_REG04__CONTEXT:
9824 gen_helper_mtc0_context(cpu_env, arg);
9825 register_name = "Context";
9826 break;
9827 case CP0_REG04__CONTEXTCONFIG:
9828 /* SmartMIPS ASE */
9829 /* gen_helper_dmtc0_contextconfig(arg); */
9830 register_name = "ContextConfig";
9831 goto cp0_unimplemented;
9832 case CP0_REG04__USERLOCAL:
9833 CP0_CHECK(ctx->ulri);
9834 tcg_gen_st_tl(arg, cpu_env,
9835 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9836 register_name = "UserLocal";
9837 break;
9838 case CP0_REG04__MMID:
9839 CP0_CHECK(ctx->mi);
9840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9841 register_name = "MMID";
9842 break;
9843 default:
9844 goto cp0_unimplemented;
9846 break;
9847 case CP0_REGISTER_05:
9848 switch (sel) {
9849 case CP0_REG05__PAGEMASK:
9850 gen_helper_mtc0_pagemask(cpu_env, arg);
9851 register_name = "PageMask";
9852 break;
9853 case CP0_REG05__PAGEGRAIN:
9854 check_insn(ctx, ISA_MIPS32R2);
9855 gen_helper_mtc0_pagegrain(cpu_env, arg);
9856 register_name = "PageGrain";
9857 break;
9858 case CP0_REG05__SEGCTL0:
9859 CP0_CHECK(ctx->sc);
9860 gen_helper_mtc0_segctl0(cpu_env, arg);
9861 register_name = "SegCtl0";
9862 break;
9863 case CP0_REG05__SEGCTL1:
9864 CP0_CHECK(ctx->sc);
9865 gen_helper_mtc0_segctl1(cpu_env, arg);
9866 register_name = "SegCtl1";
9867 break;
9868 case CP0_REG05__SEGCTL2:
9869 CP0_CHECK(ctx->sc);
9870 gen_helper_mtc0_segctl2(cpu_env, arg);
9871 register_name = "SegCtl2";
9872 break;
9873 case CP0_REG05__PWBASE:
9874 check_pw(ctx);
9875 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9876 register_name = "PWBase";
9877 break;
9878 case CP0_REG05__PWFIELD:
9879 check_pw(ctx);
9880 gen_helper_mtc0_pwfield(cpu_env, arg);
9881 register_name = "PWField";
9882 break;
9883 case CP0_REG05__PWSIZE:
9884 check_pw(ctx);
9885 gen_helper_mtc0_pwsize(cpu_env, arg);
9886 register_name = "PWSize";
9887 break;
9888 default:
9889 goto cp0_unimplemented;
9891 break;
9892 case CP0_REGISTER_06:
9893 switch (sel) {
9894 case CP0_REG06__WIRED:
9895 gen_helper_mtc0_wired(cpu_env, arg);
9896 register_name = "Wired";
9897 break;
9898 case CP0_REG06__SRSCONF0:
9899 check_insn(ctx, ISA_MIPS32R2);
9900 gen_helper_mtc0_srsconf0(cpu_env, arg);
9901 register_name = "SRSConf0";
9902 break;
9903 case CP0_REG06__SRSCONF1:
9904 check_insn(ctx, ISA_MIPS32R2);
9905 gen_helper_mtc0_srsconf1(cpu_env, arg);
9906 register_name = "SRSConf1";
9907 break;
9908 case CP0_REG06__SRSCONF2:
9909 check_insn(ctx, ISA_MIPS32R2);
9910 gen_helper_mtc0_srsconf2(cpu_env, arg);
9911 register_name = "SRSConf2";
9912 break;
9913 case CP0_REG06__SRSCONF3:
9914 check_insn(ctx, ISA_MIPS32R2);
9915 gen_helper_mtc0_srsconf3(cpu_env, arg);
9916 register_name = "SRSConf3";
9917 break;
9918 case CP0_REG06__SRSCONF4:
9919 check_insn(ctx, ISA_MIPS32R2);
9920 gen_helper_mtc0_srsconf4(cpu_env, arg);
9921 register_name = "SRSConf4";
9922 break;
9923 case CP0_REG06__PWCTL:
9924 check_pw(ctx);
9925 gen_helper_mtc0_pwctl(cpu_env, arg);
9926 register_name = "PWCtl";
9927 break;
9928 default:
9929 goto cp0_unimplemented;
9931 break;
9932 case CP0_REGISTER_07:
9933 switch (sel) {
9934 case CP0_REG07__HWRENA:
9935 check_insn(ctx, ISA_MIPS32R2);
9936 gen_helper_mtc0_hwrena(cpu_env, arg);
9937 ctx->base.is_jmp = DISAS_STOP;
9938 register_name = "HWREna";
9939 break;
9940 default:
9941 goto cp0_unimplemented;
9943 break;
9944 case CP0_REGISTER_08:
9945 switch (sel) {
9946 case CP0_REG08__BADVADDR:
9947 /* ignored */
9948 register_name = "BadVAddr";
9949 break;
9950 case CP0_REG08__BADINSTR:
9951 /* ignored */
9952 register_name = "BadInstr";
9953 break;
9954 case CP0_REG08__BADINSTRP:
9955 /* ignored */
9956 register_name = "BadInstrP";
9957 break;
9958 case CP0_REG08__BADINSTRX:
9959 /* ignored */
9960 register_name = "BadInstrX";
9961 break;
9962 default:
9963 goto cp0_unimplemented;
9965 break;
9966 case CP0_REGISTER_09:
9967 switch (sel) {
9968 case CP0_REG09__COUNT:
9969 gen_helper_mtc0_count(cpu_env, arg);
9970 register_name = "Count";
9971 break;
9972 case CP0_REG09__SAARI:
9973 CP0_CHECK(ctx->saar);
9974 gen_helper_mtc0_saari(cpu_env, arg);
9975 register_name = "SAARI";
9976 break;
9977 case CP0_REG09__SAAR:
9978 CP0_CHECK(ctx->saar);
9979 gen_helper_mtc0_saar(cpu_env, arg);
9980 register_name = "SAAR";
9981 break;
9982 default:
9983 goto cp0_unimplemented;
9985 /* Stop translation as we may have switched the execution mode */
9986 ctx->base.is_jmp = DISAS_STOP;
9987 break;
9988 case CP0_REGISTER_10:
9989 switch (sel) {
9990 case CP0_REG10__ENTRYHI:
9991 gen_helper_mtc0_entryhi(cpu_env, arg);
9992 register_name = "EntryHi";
9993 break;
9994 default:
9995 goto cp0_unimplemented;
9997 break;
9998 case CP0_REGISTER_11:
9999 switch (sel) {
10000 case CP0_REG11__COMPARE:
10001 gen_helper_mtc0_compare(cpu_env, arg);
10002 register_name = "Compare";
10003 break;
10004 /* 6,7 are implementation dependent */
10005 default:
10006 goto cp0_unimplemented;
10008 /* Stop translation as we may have switched the execution mode */
10009 ctx->base.is_jmp = DISAS_STOP;
10010 break;
10011 case CP0_REGISTER_12:
10012 switch (sel) {
10013 case CP0_REG12__STATUS:
10014 save_cpu_state(ctx, 1);
10015 gen_helper_mtc0_status(cpu_env, arg);
10016 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10017 gen_save_pc(ctx->base.pc_next + 4);
10018 ctx->base.is_jmp = DISAS_EXIT;
10019 register_name = "Status";
10020 break;
10021 case CP0_REG12__INTCTL:
10022 check_insn(ctx, ISA_MIPS32R2);
10023 gen_helper_mtc0_intctl(cpu_env, arg);
10024 /* Stop translation as we may have switched the execution mode */
10025 ctx->base.is_jmp = DISAS_STOP;
10026 register_name = "IntCtl";
10027 break;
10028 case CP0_REG12__SRSCTL:
10029 check_insn(ctx, ISA_MIPS32R2);
10030 gen_helper_mtc0_srsctl(cpu_env, arg);
10031 /* Stop translation as we may have switched the execution mode */
10032 ctx->base.is_jmp = DISAS_STOP;
10033 register_name = "SRSCtl";
10034 break;
10035 case CP0_REG12__SRSMAP:
10036 check_insn(ctx, ISA_MIPS32R2);
10037 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
10038 /* Stop translation as we may have switched the execution mode */
10039 ctx->base.is_jmp = DISAS_STOP;
10040 register_name = "SRSMap";
10041 break;
10042 default:
10043 goto cp0_unimplemented;
10045 break;
10046 case CP0_REGISTER_13:
10047 switch (sel) {
10048 case CP0_REG13__CAUSE:
10049 save_cpu_state(ctx, 1);
10050 gen_helper_mtc0_cause(cpu_env, arg);
10052 * Stop translation as we may have triggered an interrupt.
10053 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10054 * translated code to check for pending interrupts.
10056 gen_save_pc(ctx->base.pc_next + 4);
10057 ctx->base.is_jmp = DISAS_EXIT;
10058 register_name = "Cause";
10059 break;
10060 default:
10061 goto cp0_unimplemented;
10063 break;
10064 case CP0_REGISTER_14:
10065 switch (sel) {
10066 case CP0_REG14__EPC:
10067 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
10068 register_name = "EPC";
10069 break;
10070 default:
10071 goto cp0_unimplemented;
10073 break;
10074 case CP0_REGISTER_15:
10075 switch (sel) {
10076 case CP0_REG15__PRID:
10077 /* ignored */
10078 register_name = "PRid";
10079 break;
10080 case CP0_REG15__EBASE:
10081 check_insn(ctx, ISA_MIPS32R2);
10082 gen_helper_mtc0_ebase(cpu_env, arg);
10083 register_name = "EBase";
10084 break;
10085 default:
10086 goto cp0_unimplemented;
10088 break;
10089 case CP0_REGISTER_16:
10090 switch (sel) {
10091 case CP0_REG16__CONFIG:
10092 gen_helper_mtc0_config0(cpu_env, arg);
10093 register_name = "Config";
10094 /* Stop translation as we may have switched the execution mode */
10095 ctx->base.is_jmp = DISAS_STOP;
10096 break;
10097 case CP0_REG16__CONFIG1:
10098 /* ignored, read only */
10099 register_name = "Config1";
10100 break;
10101 case CP0_REG16__CONFIG2:
10102 gen_helper_mtc0_config2(cpu_env, arg);
10103 register_name = "Config2";
10104 /* Stop translation as we may have switched the execution mode */
10105 ctx->base.is_jmp = DISAS_STOP;
10106 break;
10107 case CP0_REG16__CONFIG3:
10108 gen_helper_mtc0_config3(cpu_env, arg);
10109 register_name = "Config3";
10110 /* Stop translation as we may have switched the execution mode */
10111 ctx->base.is_jmp = DISAS_STOP;
10112 break;
10113 case CP0_REG16__CONFIG4:
10114 /* currently ignored */
10115 register_name = "Config4";
10116 break;
10117 case CP0_REG16__CONFIG5:
10118 gen_helper_mtc0_config5(cpu_env, arg);
10119 register_name = "Config5";
10120 /* Stop translation as we may have switched the execution mode */
10121 ctx->base.is_jmp = DISAS_STOP;
10122 break;
10123 /* 6,7 are implementation dependent */
10124 default:
10125 register_name = "Invalid config selector";
10126 goto cp0_unimplemented;
10128 break;
10129 case CP0_REGISTER_17:
10130 switch (sel) {
10131 case CP0_REG17__LLADDR:
10132 gen_helper_mtc0_lladdr(cpu_env, arg);
10133 register_name = "LLAddr";
10134 break;
10135 case CP0_REG17__MAAR:
10136 CP0_CHECK(ctx->mrp);
10137 gen_helper_mtc0_maar(cpu_env, arg);
10138 register_name = "MAAR";
10139 break;
10140 case CP0_REG17__MAARI:
10141 CP0_CHECK(ctx->mrp);
10142 gen_helper_mtc0_maari(cpu_env, arg);
10143 register_name = "MAARI";
10144 break;
10145 default:
10146 goto cp0_unimplemented;
10148 break;
10149 case CP0_REGISTER_18:
10150 switch (sel) {
10151 case CP0_REG18__WATCHLO0:
10152 case CP0_REG18__WATCHLO1:
10153 case CP0_REG18__WATCHLO2:
10154 case CP0_REG18__WATCHLO3:
10155 case CP0_REG18__WATCHLO4:
10156 case CP0_REG18__WATCHLO5:
10157 case CP0_REG18__WATCHLO6:
10158 case CP0_REG18__WATCHLO7:
10159 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10160 gen_helper_0e1i(mtc0_watchlo, arg, sel);
10161 register_name = "WatchLo";
10162 break;
10163 default:
10164 goto cp0_unimplemented;
10166 break;
10167 case CP0_REGISTER_19:
10168 switch (sel) {
10169 case CP0_REG19__WATCHHI0:
10170 case CP0_REG19__WATCHHI1:
10171 case CP0_REG19__WATCHHI2:
10172 case CP0_REG19__WATCHHI3:
10173 case CP0_REG19__WATCHHI4:
10174 case CP0_REG19__WATCHHI5:
10175 case CP0_REG19__WATCHHI6:
10176 case CP0_REG19__WATCHHI7:
10177 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10178 gen_helper_0e1i(mtc0_watchhi, arg, sel);
10179 register_name = "WatchHi";
10180 break;
10181 default:
10182 goto cp0_unimplemented;
10184 break;
10185 case CP0_REGISTER_20:
10186 switch (sel) {
10187 case CP0_REG20__XCONTEXT:
10188 check_insn(ctx, ISA_MIPS3);
10189 gen_helper_mtc0_xcontext(cpu_env, arg);
10190 register_name = "XContext";
10191 break;
10192 default:
10193 goto cp0_unimplemented;
10195 break;
10196 case CP0_REGISTER_21:
10197 /* Officially reserved, but sel 0 is used for R1x000 framemask */
10198 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
10199 switch (sel) {
10200 case 0:
10201 gen_helper_mtc0_framemask(cpu_env, arg);
10202 register_name = "Framemask";
10203 break;
10204 default:
10205 goto cp0_unimplemented;
10207 break;
10208 case CP0_REGISTER_22:
10209 /* ignored */
10210 register_name = "Diagnostic"; /* implementation dependent */
10211 break;
10212 case CP0_REGISTER_23:
10213 switch (sel) {
10214 case CP0_REG23__DEBUG:
10215 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
10216 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10217 gen_save_pc(ctx->base.pc_next + 4);
10218 ctx->base.is_jmp = DISAS_EXIT;
10219 register_name = "Debug";
10220 break;
10221 case CP0_REG23__TRACECONTROL:
10222 /* PDtrace support */
10223 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
10224 /* Stop translation as we may have switched the execution mode */
10225 ctx->base.is_jmp = DISAS_STOP;
10226 register_name = "TraceControl";
10227 goto cp0_unimplemented;
10228 case CP0_REG23__TRACECONTROL2:
10229 /* PDtrace support */
10230 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
10231 /* Stop translation as we may have switched the execution mode */
10232 ctx->base.is_jmp = DISAS_STOP;
10233 register_name = "TraceControl2";
10234 goto cp0_unimplemented;
10235 case CP0_REG23__USERTRACEDATA1:
10236 /* PDtrace support */
10237 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
10238 /* Stop translation as we may have switched the execution mode */
10239 ctx->base.is_jmp = DISAS_STOP;
10240 register_name = "UserTraceData1";
10241 goto cp0_unimplemented;
10242 case CP0_REG23__TRACEIBPC:
10243 /* PDtrace support */
10244 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
10245 /* Stop translation as we may have switched the execution mode */
10246 ctx->base.is_jmp = DISAS_STOP;
10247 register_name = "TraceIBPC";
10248 goto cp0_unimplemented;
10249 case CP0_REG23__TRACEDBPC:
10250 /* PDtrace support */
10251 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
10252 /* Stop translation as we may have switched the execution mode */
10253 ctx->base.is_jmp = DISAS_STOP;
10254 register_name = "TraceDBPC";
10255 goto cp0_unimplemented;
10256 default:
10257 goto cp0_unimplemented;
10259 break;
10260 case CP0_REGISTER_24:
10261 switch (sel) {
10262 case CP0_REG24__DEPC:
10263 /* EJTAG support */
10264 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
10265 register_name = "DEPC";
10266 break;
10267 default:
10268 goto cp0_unimplemented;
10270 break;
10271 case CP0_REGISTER_25:
10272 switch (sel) {
10273 case CP0_REG25__PERFCTL0:
10274 gen_helper_mtc0_performance0(cpu_env, arg);
10275 register_name = "Performance0";
10276 break;
10277 case CP0_REG25__PERFCNT0:
10278 /* gen_helper_mtc0_performance1(cpu_env, arg); */
10279 register_name = "Performance1";
10280 goto cp0_unimplemented;
10281 case CP0_REG25__PERFCTL1:
10282 /* gen_helper_mtc0_performance2(cpu_env, arg); */
10283 register_name = "Performance2";
10284 goto cp0_unimplemented;
10285 case CP0_REG25__PERFCNT1:
10286 /* gen_helper_mtc0_performance3(cpu_env, arg); */
10287 register_name = "Performance3";
10288 goto cp0_unimplemented;
10289 case CP0_REG25__PERFCTL2:
10290 /* gen_helper_mtc0_performance4(cpu_env, arg); */
10291 register_name = "Performance4";
10292 goto cp0_unimplemented;
10293 case CP0_REG25__PERFCNT2:
10294 /* gen_helper_mtc0_performance5(cpu_env, arg); */
10295 register_name = "Performance5";
10296 goto cp0_unimplemented;
10297 case CP0_REG25__PERFCTL3:
10298 /* gen_helper_mtc0_performance6(cpu_env, arg); */
10299 register_name = "Performance6";
10300 goto cp0_unimplemented;
10301 case CP0_REG25__PERFCNT3:
10302 /* gen_helper_mtc0_performance7(cpu_env, arg); */
10303 register_name = "Performance7";
10304 goto cp0_unimplemented;
10305 default:
10306 goto cp0_unimplemented;
10308 break;
10309 case CP0_REGISTER_26:
10310 switch (sel) {
10311 case CP0_REG26__ERRCTL:
10312 gen_helper_mtc0_errctl(cpu_env, arg);
10313 ctx->base.is_jmp = DISAS_STOP;
10314 register_name = "ErrCtl";
10315 break;
10316 default:
10317 goto cp0_unimplemented;
10319 break;
10320 case CP0_REGISTER_27:
10321 switch (sel) {
10322 case CP0_REG27__CACHERR:
10323 /* ignored */
10324 register_name = "CacheErr";
10325 break;
10326 default:
10327 goto cp0_unimplemented;
10329 break;
10330 case CP0_REGISTER_28:
10331 switch (sel) {
10332 case CP0_REG28__TAGLO:
10333 case CP0_REG28__TAGLO1:
10334 case CP0_REG28__TAGLO2:
10335 case CP0_REG28__TAGLO3:
10336 gen_helper_mtc0_taglo(cpu_env, arg);
10337 register_name = "TagLo";
10338 break;
10339 case CP0_REG28__DATALO:
10340 case CP0_REG28__DATALO1:
10341 case CP0_REG28__DATALO2:
10342 case CP0_REG28__DATALO3:
10343 gen_helper_mtc0_datalo(cpu_env, arg);
10344 register_name = "DataLo";
10345 break;
10346 default:
10347 goto cp0_unimplemented;
10349 break;
10350 case CP0_REGISTER_29:
10351 switch (sel) {
10352 case CP0_REG29__TAGHI:
10353 case CP0_REG29__TAGHI1:
10354 case CP0_REG29__TAGHI2:
10355 case CP0_REG29__TAGHI3:
10356 gen_helper_mtc0_taghi(cpu_env, arg);
10357 register_name = "TagHi";
10358 break;
10359 case CP0_REG29__DATAHI:
10360 case CP0_REG29__DATAHI1:
10361 case CP0_REG29__DATAHI2:
10362 case CP0_REG29__DATAHI3:
10363 gen_helper_mtc0_datahi(cpu_env, arg);
10364 register_name = "DataHi";
10365 break;
10366 default:
10367 register_name = "invalid sel";
10368 goto cp0_unimplemented;
10370 break;
10371 case CP0_REGISTER_30:
10372 switch (sel) {
10373 case CP0_REG30__ERROREPC:
10374 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
10375 register_name = "ErrorEPC";
10376 break;
10377 default:
10378 goto cp0_unimplemented;
10380 break;
10381 case CP0_REGISTER_31:
10382 switch (sel) {
10383 case CP0_REG31__DESAVE:
10384 /* EJTAG support */
10385 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
10386 register_name = "DESAVE";
10387 break;
10388 case CP0_REG31__KSCRATCH1:
10389 case CP0_REG31__KSCRATCH2:
10390 case CP0_REG31__KSCRATCH3:
10391 case CP0_REG31__KSCRATCH4:
10392 case CP0_REG31__KSCRATCH5:
10393 case CP0_REG31__KSCRATCH6:
10394 CP0_CHECK(ctx->kscrexist & (1 << sel));
10395 tcg_gen_st_tl(arg, cpu_env,
10396 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
10397 register_name = "KScratch";
10398 break;
10399 default:
10400 goto cp0_unimplemented;
10402 break;
10403 default:
10404 goto cp0_unimplemented;
10406 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
10408 /* For simplicity assume that all writes can cause interrupts. */
10409 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
10411 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10412 * translated code to check for pending interrupts.
10414 gen_save_pc(ctx->base.pc_next + 4);
10415 ctx->base.is_jmp = DISAS_EXIT;
10417 return;
10419 cp0_unimplemented:
10420 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10421 register_name, reg, sel);
10423 #endif /* TARGET_MIPS64 */
10425 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10426 int u, int sel, int h)
10428 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10429 TCGv t0 = tcg_temp_local_new();
10431 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10432 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10433 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10434 tcg_gen_movi_tl(t0, -1);
10435 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10436 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10437 tcg_gen_movi_tl(t0, -1);
10438 } else if (u == 0) {
10439 switch (rt) {
10440 case 1:
10441 switch (sel) {
10442 case 1:
10443 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10444 break;
10445 case 2:
10446 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10447 break;
10448 default:
10449 goto die;
10450 break;
10452 break;
10453 case 2:
10454 switch (sel) {
10455 case 1:
10456 gen_helper_mftc0_tcstatus(t0, cpu_env);
10457 break;
10458 case 2:
10459 gen_helper_mftc0_tcbind(t0, cpu_env);
10460 break;
10461 case 3:
10462 gen_helper_mftc0_tcrestart(t0, cpu_env);
10463 break;
10464 case 4:
10465 gen_helper_mftc0_tchalt(t0, cpu_env);
10466 break;
10467 case 5:
10468 gen_helper_mftc0_tccontext(t0, cpu_env);
10469 break;
10470 case 6:
10471 gen_helper_mftc0_tcschedule(t0, cpu_env);
10472 break;
10473 case 7:
10474 gen_helper_mftc0_tcschefback(t0, cpu_env);
10475 break;
10476 default:
10477 gen_mfc0(ctx, t0, rt, sel);
10478 break;
10480 break;
10481 case 10:
10482 switch (sel) {
10483 case 0:
10484 gen_helper_mftc0_entryhi(t0, cpu_env);
10485 break;
10486 default:
10487 gen_mfc0(ctx, t0, rt, sel);
10488 break;
10490 break;
10491 case 12:
10492 switch (sel) {
10493 case 0:
10494 gen_helper_mftc0_status(t0, cpu_env);
10495 break;
10496 default:
10497 gen_mfc0(ctx, t0, rt, sel);
10498 break;
10500 break;
10501 case 13:
10502 switch (sel) {
10503 case 0:
10504 gen_helper_mftc0_cause(t0, cpu_env);
10505 break;
10506 default:
10507 goto die;
10508 break;
10510 break;
10511 case 14:
10512 switch (sel) {
10513 case 0:
10514 gen_helper_mftc0_epc(t0, cpu_env);
10515 break;
10516 default:
10517 goto die;
10518 break;
10520 break;
10521 case 15:
10522 switch (sel) {
10523 case 1:
10524 gen_helper_mftc0_ebase(t0, cpu_env);
10525 break;
10526 default:
10527 goto die;
10528 break;
10530 break;
10531 case 16:
10532 switch (sel) {
10533 case 0:
10534 case 1:
10535 case 2:
10536 case 3:
10537 case 4:
10538 case 5:
10539 case 6:
10540 case 7:
10541 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10542 break;
10543 default:
10544 goto die;
10545 break;
10547 break;
10548 case 23:
10549 switch (sel) {
10550 case 0:
10551 gen_helper_mftc0_debug(t0, cpu_env);
10552 break;
10553 default:
10554 gen_mfc0(ctx, t0, rt, sel);
10555 break;
10557 break;
10558 default:
10559 gen_mfc0(ctx, t0, rt, sel);
10561 } else {
10562 switch (sel) {
10563 /* GPR registers. */
10564 case 0:
10565 gen_helper_1e0i(mftgpr, t0, rt);
10566 break;
10567 /* Auxiliary CPU registers */
10568 case 1:
10569 switch (rt) {
10570 case 0:
10571 gen_helper_1e0i(mftlo, t0, 0);
10572 break;
10573 case 1:
10574 gen_helper_1e0i(mfthi, t0, 0);
10575 break;
10576 case 2:
10577 gen_helper_1e0i(mftacx, t0, 0);
10578 break;
10579 case 4:
10580 gen_helper_1e0i(mftlo, t0, 1);
10581 break;
10582 case 5:
10583 gen_helper_1e0i(mfthi, t0, 1);
10584 break;
10585 case 6:
10586 gen_helper_1e0i(mftacx, t0, 1);
10587 break;
10588 case 8:
10589 gen_helper_1e0i(mftlo, t0, 2);
10590 break;
10591 case 9:
10592 gen_helper_1e0i(mfthi, t0, 2);
10593 break;
10594 case 10:
10595 gen_helper_1e0i(mftacx, t0, 2);
10596 break;
10597 case 12:
10598 gen_helper_1e0i(mftlo, t0, 3);
10599 break;
10600 case 13:
10601 gen_helper_1e0i(mfthi, t0, 3);
10602 break;
10603 case 14:
10604 gen_helper_1e0i(mftacx, t0, 3);
10605 break;
10606 case 16:
10607 gen_helper_mftdsp(t0, cpu_env);
10608 break;
10609 default:
10610 goto die;
10612 break;
10613 /* Floating point (COP1). */
10614 case 2:
10615 /* XXX: For now we support only a single FPU context. */
10616 if (h == 0) {
10617 TCGv_i32 fp0 = tcg_temp_new_i32();
10619 gen_load_fpr32(ctx, fp0, rt);
10620 tcg_gen_ext_i32_tl(t0, fp0);
10621 tcg_temp_free_i32(fp0);
10622 } else {
10623 TCGv_i32 fp0 = tcg_temp_new_i32();
10625 gen_load_fpr32h(ctx, fp0, rt);
10626 tcg_gen_ext_i32_tl(t0, fp0);
10627 tcg_temp_free_i32(fp0);
10629 break;
10630 case 3:
10631 /* XXX: For now we support only a single FPU context. */
10632 gen_helper_1e0i(cfc1, t0, rt);
10633 break;
10634 /* COP2: Not implemented. */
10635 case 4:
10636 case 5:
10637 /* fall through */
10638 default:
10639 goto die;
10642 trace_mips_translate_tr("mftr", rt, u, sel, h);
10643 gen_store_gpr(t0, rd);
10644 tcg_temp_free(t0);
10645 return;
10647 die:
10648 tcg_temp_free(t0);
10649 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10650 generate_exception_end(ctx, EXCP_RI);
10653 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10654 int u, int sel, int h)
10656 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10657 TCGv t0 = tcg_temp_local_new();
10659 gen_load_gpr(t0, rt);
10660 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10661 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10662 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10663 /* NOP */
10665 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10666 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10667 /* NOP */
10669 } else if (u == 0) {
10670 switch (rd) {
10671 case 1:
10672 switch (sel) {
10673 case 1:
10674 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10675 break;
10676 case 2:
10677 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10678 break;
10679 default:
10680 goto die;
10681 break;
10683 break;
10684 case 2:
10685 switch (sel) {
10686 case 1:
10687 gen_helper_mttc0_tcstatus(cpu_env, t0);
10688 break;
10689 case 2:
10690 gen_helper_mttc0_tcbind(cpu_env, t0);
10691 break;
10692 case 3:
10693 gen_helper_mttc0_tcrestart(cpu_env, t0);
10694 break;
10695 case 4:
10696 gen_helper_mttc0_tchalt(cpu_env, t0);
10697 break;
10698 case 5:
10699 gen_helper_mttc0_tccontext(cpu_env, t0);
10700 break;
10701 case 6:
10702 gen_helper_mttc0_tcschedule(cpu_env, t0);
10703 break;
10704 case 7:
10705 gen_helper_mttc0_tcschefback(cpu_env, t0);
10706 break;
10707 default:
10708 gen_mtc0(ctx, t0, rd, sel);
10709 break;
10711 break;
10712 case 10:
10713 switch (sel) {
10714 case 0:
10715 gen_helper_mttc0_entryhi(cpu_env, t0);
10716 break;
10717 default:
10718 gen_mtc0(ctx, t0, rd, sel);
10719 break;
10721 break;
10722 case 12:
10723 switch (sel) {
10724 case 0:
10725 gen_helper_mttc0_status(cpu_env, t0);
10726 break;
10727 default:
10728 gen_mtc0(ctx, t0, rd, sel);
10729 break;
10731 break;
10732 case 13:
10733 switch (sel) {
10734 case 0:
10735 gen_helper_mttc0_cause(cpu_env, t0);
10736 break;
10737 default:
10738 goto die;
10739 break;
10741 break;
10742 case 15:
10743 switch (sel) {
10744 case 1:
10745 gen_helper_mttc0_ebase(cpu_env, t0);
10746 break;
10747 default:
10748 goto die;
10749 break;
10751 break;
10752 case 23:
10753 switch (sel) {
10754 case 0:
10755 gen_helper_mttc0_debug(cpu_env, t0);
10756 break;
10757 default:
10758 gen_mtc0(ctx, t0, rd, sel);
10759 break;
10761 break;
10762 default:
10763 gen_mtc0(ctx, t0, rd, sel);
10765 } else {
10766 switch (sel) {
10767 /* GPR registers. */
10768 case 0:
10769 gen_helper_0e1i(mttgpr, t0, rd);
10770 break;
10771 /* Auxiliary CPU registers */
10772 case 1:
10773 switch (rd) {
10774 case 0:
10775 gen_helper_0e1i(mttlo, t0, 0);
10776 break;
10777 case 1:
10778 gen_helper_0e1i(mtthi, t0, 0);
10779 break;
10780 case 2:
10781 gen_helper_0e1i(mttacx, t0, 0);
10782 break;
10783 case 4:
10784 gen_helper_0e1i(mttlo, t0, 1);
10785 break;
10786 case 5:
10787 gen_helper_0e1i(mtthi, t0, 1);
10788 break;
10789 case 6:
10790 gen_helper_0e1i(mttacx, t0, 1);
10791 break;
10792 case 8:
10793 gen_helper_0e1i(mttlo, t0, 2);
10794 break;
10795 case 9:
10796 gen_helper_0e1i(mtthi, t0, 2);
10797 break;
10798 case 10:
10799 gen_helper_0e1i(mttacx, t0, 2);
10800 break;
10801 case 12:
10802 gen_helper_0e1i(mttlo, t0, 3);
10803 break;
10804 case 13:
10805 gen_helper_0e1i(mtthi, t0, 3);
10806 break;
10807 case 14:
10808 gen_helper_0e1i(mttacx, t0, 3);
10809 break;
10810 case 16:
10811 gen_helper_mttdsp(cpu_env, t0);
10812 break;
10813 default:
10814 goto die;
10816 break;
10817 /* Floating point (COP1). */
10818 case 2:
10819 /* XXX: For now we support only a single FPU context. */
10820 if (h == 0) {
10821 TCGv_i32 fp0 = tcg_temp_new_i32();
10823 tcg_gen_trunc_tl_i32(fp0, t0);
10824 gen_store_fpr32(ctx, fp0, rd);
10825 tcg_temp_free_i32(fp0);
10826 } else {
10827 TCGv_i32 fp0 = tcg_temp_new_i32();
10829 tcg_gen_trunc_tl_i32(fp0, t0);
10830 gen_store_fpr32h(ctx, fp0, rd);
10831 tcg_temp_free_i32(fp0);
10833 break;
10834 case 3:
10835 /* XXX: For now we support only a single FPU context. */
10837 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10839 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10840 tcg_temp_free_i32(fs_tmp);
10842 /* Stop translation as we may have changed hflags */
10843 ctx->base.is_jmp = DISAS_STOP;
10844 break;
10845 /* COP2: Not implemented. */
10846 case 4:
10847 case 5:
10848 /* fall through */
10849 default:
10850 goto die;
10853 trace_mips_translate_tr("mttr", rd, u, sel, h);
10854 tcg_temp_free(t0);
10855 return;
10857 die:
10858 tcg_temp_free(t0);
10859 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10860 generate_exception_end(ctx, EXCP_RI);
10863 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10864 int rt, int rd)
10866 const char *opn = "ldst";
10868 check_cp0_enabled(ctx);
10869 switch (opc) {
10870 case OPC_MFC0:
10871 if (rt == 0) {
10872 /* Treat as NOP. */
10873 return;
10875 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10876 opn = "mfc0";
10877 break;
10878 case OPC_MTC0:
10880 TCGv t0 = tcg_temp_new();
10882 gen_load_gpr(t0, rt);
10883 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10884 tcg_temp_free(t0);
10886 opn = "mtc0";
10887 break;
10888 #if defined(TARGET_MIPS64)
10889 case OPC_DMFC0:
10890 check_insn(ctx, ISA_MIPS3);
10891 if (rt == 0) {
10892 /* Treat as NOP. */
10893 return;
10895 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10896 opn = "dmfc0";
10897 break;
10898 case OPC_DMTC0:
10899 check_insn(ctx, ISA_MIPS3);
10901 TCGv t0 = tcg_temp_new();
10903 gen_load_gpr(t0, rt);
10904 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10905 tcg_temp_free(t0);
10907 opn = "dmtc0";
10908 break;
10909 #endif
10910 case OPC_MFHC0:
10911 check_mvh(ctx);
10912 if (rt == 0) {
10913 /* Treat as NOP. */
10914 return;
10916 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10917 opn = "mfhc0";
10918 break;
10919 case OPC_MTHC0:
10920 check_mvh(ctx);
10922 TCGv t0 = tcg_temp_new();
10923 gen_load_gpr(t0, rt);
10924 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10925 tcg_temp_free(t0);
10927 opn = "mthc0";
10928 break;
10929 case OPC_MFTR:
10930 check_cp0_enabled(ctx);
10931 if (rd == 0) {
10932 /* Treat as NOP. */
10933 return;
10935 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10936 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10937 opn = "mftr";
10938 break;
10939 case OPC_MTTR:
10940 check_cp0_enabled(ctx);
10941 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10942 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10943 opn = "mttr";
10944 break;
10945 case OPC_TLBWI:
10946 opn = "tlbwi";
10947 if (!env->tlb->helper_tlbwi) {
10948 goto die;
10950 gen_helper_tlbwi(cpu_env);
10951 break;
10952 case OPC_TLBINV:
10953 opn = "tlbinv";
10954 if (ctx->ie >= 2) {
10955 if (!env->tlb->helper_tlbinv) {
10956 goto die;
10958 gen_helper_tlbinv(cpu_env);
10959 } /* treat as nop if TLBINV not supported */
10960 break;
10961 case OPC_TLBINVF:
10962 opn = "tlbinvf";
10963 if (ctx->ie >= 2) {
10964 if (!env->tlb->helper_tlbinvf) {
10965 goto die;
10967 gen_helper_tlbinvf(cpu_env);
10968 } /* treat as nop if TLBINV not supported */
10969 break;
10970 case OPC_TLBWR:
10971 opn = "tlbwr";
10972 if (!env->tlb->helper_tlbwr) {
10973 goto die;
10975 gen_helper_tlbwr(cpu_env);
10976 break;
10977 case OPC_TLBP:
10978 opn = "tlbp";
10979 if (!env->tlb->helper_tlbp) {
10980 goto die;
10982 gen_helper_tlbp(cpu_env);
10983 break;
10984 case OPC_TLBR:
10985 opn = "tlbr";
10986 if (!env->tlb->helper_tlbr) {
10987 goto die;
10989 gen_helper_tlbr(cpu_env);
10990 break;
10991 case OPC_ERET: /* OPC_ERETNC */
10992 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10993 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10994 goto die;
10995 } else {
10996 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10997 if (ctx->opcode & (1 << bit_shift)) {
10998 /* OPC_ERETNC */
10999 opn = "eretnc";
11000 check_insn(ctx, ISA_MIPS32R5);
11001 gen_helper_eretnc(cpu_env);
11002 } else {
11003 /* OPC_ERET */
11004 opn = "eret";
11005 check_insn(ctx, ISA_MIPS2);
11006 gen_helper_eret(cpu_env);
11008 ctx->base.is_jmp = DISAS_EXIT;
11010 break;
11011 case OPC_DERET:
11012 opn = "deret";
11013 check_insn(ctx, ISA_MIPS32);
11014 if ((ctx->insn_flags & ISA_MIPS32R6) &&
11015 (ctx->hflags & MIPS_HFLAG_BMASK)) {
11016 goto die;
11018 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11019 MIPS_INVAL(opn);
11020 generate_exception_end(ctx, EXCP_RI);
11021 } else {
11022 gen_helper_deret(cpu_env);
11023 ctx->base.is_jmp = DISAS_EXIT;
11025 break;
11026 case OPC_WAIT:
11027 opn = "wait";
11028 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
11029 if ((ctx->insn_flags & ISA_MIPS32R6) &&
11030 (ctx->hflags & MIPS_HFLAG_BMASK)) {
11031 goto die;
11033 /* If we get an exception, we want to restart at next instruction */
11034 ctx->base.pc_next += 4;
11035 save_cpu_state(ctx, 1);
11036 ctx->base.pc_next -= 4;
11037 gen_helper_wait(cpu_env);
11038 ctx->base.is_jmp = DISAS_NORETURN;
11039 break;
11040 default:
11041 die:
11042 MIPS_INVAL(opn);
11043 generate_exception_end(ctx, EXCP_RI);
11044 return;
11046 (void)opn; /* avoid a compiler warning */
11048 #endif /* !CONFIG_USER_ONLY */
11050 /* CP1 Branches (before delay slot) */
11051 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
11052 int32_t cc, int32_t offset)
11054 target_ulong btarget;
11055 TCGv_i32 t0 = tcg_temp_new_i32();
11057 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11058 generate_exception_end(ctx, EXCP_RI);
11059 goto out;
11062 if (cc != 0) {
11063 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
11066 btarget = ctx->base.pc_next + 4 + offset;
11068 switch (op) {
11069 case OPC_BC1F:
11070 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11071 tcg_gen_not_i32(t0, t0);
11072 tcg_gen_andi_i32(t0, t0, 1);
11073 tcg_gen_extu_i32_tl(bcond, t0);
11074 goto not_likely;
11075 case OPC_BC1FL:
11076 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11077 tcg_gen_not_i32(t0, t0);
11078 tcg_gen_andi_i32(t0, t0, 1);
11079 tcg_gen_extu_i32_tl(bcond, t0);
11080 goto likely;
11081 case OPC_BC1T:
11082 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11083 tcg_gen_andi_i32(t0, t0, 1);
11084 tcg_gen_extu_i32_tl(bcond, t0);
11085 goto not_likely;
11086 case OPC_BC1TL:
11087 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11088 tcg_gen_andi_i32(t0, t0, 1);
11089 tcg_gen_extu_i32_tl(bcond, t0);
11090 likely:
11091 ctx->hflags |= MIPS_HFLAG_BL;
11092 break;
11093 case OPC_BC1FANY2:
11095 TCGv_i32 t1 = tcg_temp_new_i32();
11096 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11097 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11098 tcg_gen_nand_i32(t0, t0, t1);
11099 tcg_temp_free_i32(t1);
11100 tcg_gen_andi_i32(t0, t0, 1);
11101 tcg_gen_extu_i32_tl(bcond, t0);
11103 goto not_likely;
11104 case OPC_BC1TANY2:
11106 TCGv_i32 t1 = tcg_temp_new_i32();
11107 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11108 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11109 tcg_gen_or_i32(t0, t0, t1);
11110 tcg_temp_free_i32(t1);
11111 tcg_gen_andi_i32(t0, t0, 1);
11112 tcg_gen_extu_i32_tl(bcond, t0);
11114 goto not_likely;
11115 case OPC_BC1FANY4:
11117 TCGv_i32 t1 = tcg_temp_new_i32();
11118 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11119 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11120 tcg_gen_and_i32(t0, t0, t1);
11121 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11122 tcg_gen_and_i32(t0, t0, t1);
11123 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11124 tcg_gen_nand_i32(t0, t0, t1);
11125 tcg_temp_free_i32(t1);
11126 tcg_gen_andi_i32(t0, t0, 1);
11127 tcg_gen_extu_i32_tl(bcond, t0);
11129 goto not_likely;
11130 case OPC_BC1TANY4:
11132 TCGv_i32 t1 = tcg_temp_new_i32();
11133 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11134 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11135 tcg_gen_or_i32(t0, t0, t1);
11136 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11137 tcg_gen_or_i32(t0, t0, t1);
11138 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11139 tcg_gen_or_i32(t0, t0, t1);
11140 tcg_temp_free_i32(t1);
11141 tcg_gen_andi_i32(t0, t0, 1);
11142 tcg_gen_extu_i32_tl(bcond, t0);
11144 not_likely:
11145 ctx->hflags |= MIPS_HFLAG_BC;
11146 break;
11147 default:
11148 MIPS_INVAL("cp1 cond branch");
11149 generate_exception_end(ctx, EXCP_RI);
11150 goto out;
11152 ctx->btarget = btarget;
11153 ctx->hflags |= MIPS_HFLAG_BDS32;
11154 out:
11155 tcg_temp_free_i32(t0);
11158 /* R6 CP1 Branches */
11159 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
11160 int32_t ft, int32_t offset,
11161 int delayslot_size)
11163 target_ulong btarget;
11164 TCGv_i64 t0 = tcg_temp_new_i64();
11166 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11167 #ifdef MIPS_DEBUG_DISAS
11168 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11169 "\n", ctx->base.pc_next);
11170 #endif
11171 generate_exception_end(ctx, EXCP_RI);
11172 goto out;
11175 gen_load_fpr64(ctx, t0, ft);
11176 tcg_gen_andi_i64(t0, t0, 1);
11178 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11180 switch (op) {
11181 case OPC_BC1EQZ:
11182 tcg_gen_xori_i64(t0, t0, 1);
11183 ctx->hflags |= MIPS_HFLAG_BC;
11184 break;
11185 case OPC_BC1NEZ:
11186 /* t0 already set */
11187 ctx->hflags |= MIPS_HFLAG_BC;
11188 break;
11189 default:
11190 MIPS_INVAL("cp1 cond branch");
11191 generate_exception_end(ctx, EXCP_RI);
11192 goto out;
11195 tcg_gen_trunc_i64_tl(bcond, t0);
11197 ctx->btarget = btarget;
11199 switch (delayslot_size) {
11200 case 2:
11201 ctx->hflags |= MIPS_HFLAG_BDS16;
11202 break;
11203 case 4:
11204 ctx->hflags |= MIPS_HFLAG_BDS32;
11205 break;
11208 out:
11209 tcg_temp_free_i64(t0);
11212 /* Coprocessor 1 (FPU) */
11214 #define FOP(func, fmt) (((fmt) << 21) | (func))
11216 enum fopcode {
11217 OPC_ADD_S = FOP(0, FMT_S),
11218 OPC_SUB_S = FOP(1, FMT_S),
11219 OPC_MUL_S = FOP(2, FMT_S),
11220 OPC_DIV_S = FOP(3, FMT_S),
11221 OPC_SQRT_S = FOP(4, FMT_S),
11222 OPC_ABS_S = FOP(5, FMT_S),
11223 OPC_MOV_S = FOP(6, FMT_S),
11224 OPC_NEG_S = FOP(7, FMT_S),
11225 OPC_ROUND_L_S = FOP(8, FMT_S),
11226 OPC_TRUNC_L_S = FOP(9, FMT_S),
11227 OPC_CEIL_L_S = FOP(10, FMT_S),
11228 OPC_FLOOR_L_S = FOP(11, FMT_S),
11229 OPC_ROUND_W_S = FOP(12, FMT_S),
11230 OPC_TRUNC_W_S = FOP(13, FMT_S),
11231 OPC_CEIL_W_S = FOP(14, FMT_S),
11232 OPC_FLOOR_W_S = FOP(15, FMT_S),
11233 OPC_SEL_S = FOP(16, FMT_S),
11234 OPC_MOVCF_S = FOP(17, FMT_S),
11235 OPC_MOVZ_S = FOP(18, FMT_S),
11236 OPC_MOVN_S = FOP(19, FMT_S),
11237 OPC_SELEQZ_S = FOP(20, FMT_S),
11238 OPC_RECIP_S = FOP(21, FMT_S),
11239 OPC_RSQRT_S = FOP(22, FMT_S),
11240 OPC_SELNEZ_S = FOP(23, FMT_S),
11241 OPC_MADDF_S = FOP(24, FMT_S),
11242 OPC_MSUBF_S = FOP(25, FMT_S),
11243 OPC_RINT_S = FOP(26, FMT_S),
11244 OPC_CLASS_S = FOP(27, FMT_S),
11245 OPC_MIN_S = FOP(28, FMT_S),
11246 OPC_RECIP2_S = FOP(28, FMT_S),
11247 OPC_MINA_S = FOP(29, FMT_S),
11248 OPC_RECIP1_S = FOP(29, FMT_S),
11249 OPC_MAX_S = FOP(30, FMT_S),
11250 OPC_RSQRT1_S = FOP(30, FMT_S),
11251 OPC_MAXA_S = FOP(31, FMT_S),
11252 OPC_RSQRT2_S = FOP(31, FMT_S),
11253 OPC_CVT_D_S = FOP(33, FMT_S),
11254 OPC_CVT_W_S = FOP(36, FMT_S),
11255 OPC_CVT_L_S = FOP(37, FMT_S),
11256 OPC_CVT_PS_S = FOP(38, FMT_S),
11257 OPC_CMP_F_S = FOP(48, FMT_S),
11258 OPC_CMP_UN_S = FOP(49, FMT_S),
11259 OPC_CMP_EQ_S = FOP(50, FMT_S),
11260 OPC_CMP_UEQ_S = FOP(51, FMT_S),
11261 OPC_CMP_OLT_S = FOP(52, FMT_S),
11262 OPC_CMP_ULT_S = FOP(53, FMT_S),
11263 OPC_CMP_OLE_S = FOP(54, FMT_S),
11264 OPC_CMP_ULE_S = FOP(55, FMT_S),
11265 OPC_CMP_SF_S = FOP(56, FMT_S),
11266 OPC_CMP_NGLE_S = FOP(57, FMT_S),
11267 OPC_CMP_SEQ_S = FOP(58, FMT_S),
11268 OPC_CMP_NGL_S = FOP(59, FMT_S),
11269 OPC_CMP_LT_S = FOP(60, FMT_S),
11270 OPC_CMP_NGE_S = FOP(61, FMT_S),
11271 OPC_CMP_LE_S = FOP(62, FMT_S),
11272 OPC_CMP_NGT_S = FOP(63, FMT_S),
11274 OPC_ADD_D = FOP(0, FMT_D),
11275 OPC_SUB_D = FOP(1, FMT_D),
11276 OPC_MUL_D = FOP(2, FMT_D),
11277 OPC_DIV_D = FOP(3, FMT_D),
11278 OPC_SQRT_D = FOP(4, FMT_D),
11279 OPC_ABS_D = FOP(5, FMT_D),
11280 OPC_MOV_D = FOP(6, FMT_D),
11281 OPC_NEG_D = FOP(7, FMT_D),
11282 OPC_ROUND_L_D = FOP(8, FMT_D),
11283 OPC_TRUNC_L_D = FOP(9, FMT_D),
11284 OPC_CEIL_L_D = FOP(10, FMT_D),
11285 OPC_FLOOR_L_D = FOP(11, FMT_D),
11286 OPC_ROUND_W_D = FOP(12, FMT_D),
11287 OPC_TRUNC_W_D = FOP(13, FMT_D),
11288 OPC_CEIL_W_D = FOP(14, FMT_D),
11289 OPC_FLOOR_W_D = FOP(15, FMT_D),
11290 OPC_SEL_D = FOP(16, FMT_D),
11291 OPC_MOVCF_D = FOP(17, FMT_D),
11292 OPC_MOVZ_D = FOP(18, FMT_D),
11293 OPC_MOVN_D = FOP(19, FMT_D),
11294 OPC_SELEQZ_D = FOP(20, FMT_D),
11295 OPC_RECIP_D = FOP(21, FMT_D),
11296 OPC_RSQRT_D = FOP(22, FMT_D),
11297 OPC_SELNEZ_D = FOP(23, FMT_D),
11298 OPC_MADDF_D = FOP(24, FMT_D),
11299 OPC_MSUBF_D = FOP(25, FMT_D),
11300 OPC_RINT_D = FOP(26, FMT_D),
11301 OPC_CLASS_D = FOP(27, FMT_D),
11302 OPC_MIN_D = FOP(28, FMT_D),
11303 OPC_RECIP2_D = FOP(28, FMT_D),
11304 OPC_MINA_D = FOP(29, FMT_D),
11305 OPC_RECIP1_D = FOP(29, FMT_D),
11306 OPC_MAX_D = FOP(30, FMT_D),
11307 OPC_RSQRT1_D = FOP(30, FMT_D),
11308 OPC_MAXA_D = FOP(31, FMT_D),
11309 OPC_RSQRT2_D = FOP(31, FMT_D),
11310 OPC_CVT_S_D = FOP(32, FMT_D),
11311 OPC_CVT_W_D = FOP(36, FMT_D),
11312 OPC_CVT_L_D = FOP(37, FMT_D),
11313 OPC_CMP_F_D = FOP(48, FMT_D),
11314 OPC_CMP_UN_D = FOP(49, FMT_D),
11315 OPC_CMP_EQ_D = FOP(50, FMT_D),
11316 OPC_CMP_UEQ_D = FOP(51, FMT_D),
11317 OPC_CMP_OLT_D = FOP(52, FMT_D),
11318 OPC_CMP_ULT_D = FOP(53, FMT_D),
11319 OPC_CMP_OLE_D = FOP(54, FMT_D),
11320 OPC_CMP_ULE_D = FOP(55, FMT_D),
11321 OPC_CMP_SF_D = FOP(56, FMT_D),
11322 OPC_CMP_NGLE_D = FOP(57, FMT_D),
11323 OPC_CMP_SEQ_D = FOP(58, FMT_D),
11324 OPC_CMP_NGL_D = FOP(59, FMT_D),
11325 OPC_CMP_LT_D = FOP(60, FMT_D),
11326 OPC_CMP_NGE_D = FOP(61, FMT_D),
11327 OPC_CMP_LE_D = FOP(62, FMT_D),
11328 OPC_CMP_NGT_D = FOP(63, FMT_D),
11330 OPC_CVT_S_W = FOP(32, FMT_W),
11331 OPC_CVT_D_W = FOP(33, FMT_W),
11332 OPC_CVT_S_L = FOP(32, FMT_L),
11333 OPC_CVT_D_L = FOP(33, FMT_L),
11334 OPC_CVT_PS_PW = FOP(38, FMT_W),
11336 OPC_ADD_PS = FOP(0, FMT_PS),
11337 OPC_SUB_PS = FOP(1, FMT_PS),
11338 OPC_MUL_PS = FOP(2, FMT_PS),
11339 OPC_DIV_PS = FOP(3, FMT_PS),
11340 OPC_ABS_PS = FOP(5, FMT_PS),
11341 OPC_MOV_PS = FOP(6, FMT_PS),
11342 OPC_NEG_PS = FOP(7, FMT_PS),
11343 OPC_MOVCF_PS = FOP(17, FMT_PS),
11344 OPC_MOVZ_PS = FOP(18, FMT_PS),
11345 OPC_MOVN_PS = FOP(19, FMT_PS),
11346 OPC_ADDR_PS = FOP(24, FMT_PS),
11347 OPC_MULR_PS = FOP(26, FMT_PS),
11348 OPC_RECIP2_PS = FOP(28, FMT_PS),
11349 OPC_RECIP1_PS = FOP(29, FMT_PS),
11350 OPC_RSQRT1_PS = FOP(30, FMT_PS),
11351 OPC_RSQRT2_PS = FOP(31, FMT_PS),
11353 OPC_CVT_S_PU = FOP(32, FMT_PS),
11354 OPC_CVT_PW_PS = FOP(36, FMT_PS),
11355 OPC_CVT_S_PL = FOP(40, FMT_PS),
11356 OPC_PLL_PS = FOP(44, FMT_PS),
11357 OPC_PLU_PS = FOP(45, FMT_PS),
11358 OPC_PUL_PS = FOP(46, FMT_PS),
11359 OPC_PUU_PS = FOP(47, FMT_PS),
11360 OPC_CMP_F_PS = FOP(48, FMT_PS),
11361 OPC_CMP_UN_PS = FOP(49, FMT_PS),
11362 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
11363 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
11364 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
11365 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
11366 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
11367 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
11368 OPC_CMP_SF_PS = FOP(56, FMT_PS),
11369 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
11370 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
11371 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
11372 OPC_CMP_LT_PS = FOP(60, FMT_PS),
11373 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
11374 OPC_CMP_LE_PS = FOP(62, FMT_PS),
11375 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
11378 enum r6_f_cmp_op {
11379 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
11380 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
11381 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
11382 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
11383 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
11384 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
11385 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
11386 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
11387 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
11388 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
11389 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
11390 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
11391 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
11392 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
11393 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
11394 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
11395 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
11396 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
11397 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
11398 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
11399 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
11400 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
11402 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
11403 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
11404 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
11405 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
11406 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
11407 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11408 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11409 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11410 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11411 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11412 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11413 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11414 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11415 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11416 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11417 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11418 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11419 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11420 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11421 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11422 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11423 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11426 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11428 TCGv t0 = tcg_temp_new();
11430 switch (opc) {
11431 case OPC_MFC1:
11433 TCGv_i32 fp0 = tcg_temp_new_i32();
11435 gen_load_fpr32(ctx, fp0, fs);
11436 tcg_gen_ext_i32_tl(t0, fp0);
11437 tcg_temp_free_i32(fp0);
11439 gen_store_gpr(t0, rt);
11440 break;
11441 case OPC_MTC1:
11442 gen_load_gpr(t0, rt);
11444 TCGv_i32 fp0 = tcg_temp_new_i32();
11446 tcg_gen_trunc_tl_i32(fp0, t0);
11447 gen_store_fpr32(ctx, fp0, fs);
11448 tcg_temp_free_i32(fp0);
11450 break;
11451 case OPC_CFC1:
11452 gen_helper_1e0i(cfc1, t0, fs);
11453 gen_store_gpr(t0, rt);
11454 break;
11455 case OPC_CTC1:
11456 gen_load_gpr(t0, rt);
11457 save_cpu_state(ctx, 0);
11459 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11461 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11462 tcg_temp_free_i32(fs_tmp);
11464 /* Stop translation as we may have changed hflags */
11465 ctx->base.is_jmp = DISAS_STOP;
11466 break;
11467 #if defined(TARGET_MIPS64)
11468 case OPC_DMFC1:
11469 gen_load_fpr64(ctx, t0, fs);
11470 gen_store_gpr(t0, rt);
11471 break;
11472 case OPC_DMTC1:
11473 gen_load_gpr(t0, rt);
11474 gen_store_fpr64(ctx, t0, fs);
11475 break;
11476 #endif
11477 case OPC_MFHC1:
11479 TCGv_i32 fp0 = tcg_temp_new_i32();
11481 gen_load_fpr32h(ctx, fp0, fs);
11482 tcg_gen_ext_i32_tl(t0, fp0);
11483 tcg_temp_free_i32(fp0);
11485 gen_store_gpr(t0, rt);
11486 break;
11487 case OPC_MTHC1:
11488 gen_load_gpr(t0, rt);
11490 TCGv_i32 fp0 = tcg_temp_new_i32();
11492 tcg_gen_trunc_tl_i32(fp0, t0);
11493 gen_store_fpr32h(ctx, fp0, fs);
11494 tcg_temp_free_i32(fp0);
11496 break;
11497 default:
11498 MIPS_INVAL("cp1 move");
11499 generate_exception_end(ctx, EXCP_RI);
11500 goto out;
11503 out:
11504 tcg_temp_free(t0);
11507 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11509 TCGLabel *l1;
11510 TCGCond cond;
11511 TCGv_i32 t0;
11513 if (rd == 0) {
11514 /* Treat as NOP. */
11515 return;
11518 if (tf) {
11519 cond = TCG_COND_EQ;
11520 } else {
11521 cond = TCG_COND_NE;
11524 l1 = gen_new_label();
11525 t0 = tcg_temp_new_i32();
11526 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11527 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11528 tcg_temp_free_i32(t0);
11529 if (rs == 0) {
11530 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11531 } else {
11532 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11534 gen_set_label(l1);
11537 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11538 int tf)
11540 int cond;
11541 TCGv_i32 t0 = tcg_temp_new_i32();
11542 TCGLabel *l1 = gen_new_label();
11544 if (tf) {
11545 cond = TCG_COND_EQ;
11546 } else {
11547 cond = TCG_COND_NE;
11550 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11551 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11552 gen_load_fpr32(ctx, t0, fs);
11553 gen_store_fpr32(ctx, t0, fd);
11554 gen_set_label(l1);
11555 tcg_temp_free_i32(t0);
11558 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11559 int tf)
11561 int cond;
11562 TCGv_i32 t0 = tcg_temp_new_i32();
11563 TCGv_i64 fp0;
11564 TCGLabel *l1 = gen_new_label();
11566 if (tf) {
11567 cond = TCG_COND_EQ;
11568 } else {
11569 cond = TCG_COND_NE;
11572 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11573 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11574 tcg_temp_free_i32(t0);
11575 fp0 = tcg_temp_new_i64();
11576 gen_load_fpr64(ctx, fp0, fs);
11577 gen_store_fpr64(ctx, fp0, fd);
11578 tcg_temp_free_i64(fp0);
11579 gen_set_label(l1);
11582 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11583 int cc, int tf)
11585 int cond;
11586 TCGv_i32 t0 = tcg_temp_new_i32();
11587 TCGLabel *l1 = gen_new_label();
11588 TCGLabel *l2 = gen_new_label();
11590 if (tf) {
11591 cond = TCG_COND_EQ;
11592 } else {
11593 cond = TCG_COND_NE;
11596 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11597 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11598 gen_load_fpr32(ctx, t0, fs);
11599 gen_store_fpr32(ctx, t0, fd);
11600 gen_set_label(l1);
11602 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11603 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11604 gen_load_fpr32h(ctx, t0, fs);
11605 gen_store_fpr32h(ctx, t0, fd);
11606 tcg_temp_free_i32(t0);
11607 gen_set_label(l2);
11610 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11611 int fs)
11613 TCGv_i32 t1 = tcg_const_i32(0);
11614 TCGv_i32 fp0 = tcg_temp_new_i32();
11615 TCGv_i32 fp1 = tcg_temp_new_i32();
11616 TCGv_i32 fp2 = tcg_temp_new_i32();
11617 gen_load_fpr32(ctx, fp0, fd);
11618 gen_load_fpr32(ctx, fp1, ft);
11619 gen_load_fpr32(ctx, fp2, fs);
11621 switch (op1) {
11622 case OPC_SEL_S:
11623 tcg_gen_andi_i32(fp0, fp0, 1);
11624 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11625 break;
11626 case OPC_SELEQZ_S:
11627 tcg_gen_andi_i32(fp1, fp1, 1);
11628 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11629 break;
11630 case OPC_SELNEZ_S:
11631 tcg_gen_andi_i32(fp1, fp1, 1);
11632 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11633 break;
11634 default:
11635 MIPS_INVAL("gen_sel_s");
11636 generate_exception_end(ctx, EXCP_RI);
11637 break;
11640 gen_store_fpr32(ctx, fp0, fd);
11641 tcg_temp_free_i32(fp2);
11642 tcg_temp_free_i32(fp1);
11643 tcg_temp_free_i32(fp0);
11644 tcg_temp_free_i32(t1);
11647 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11648 int fs)
11650 TCGv_i64 t1 = tcg_const_i64(0);
11651 TCGv_i64 fp0 = tcg_temp_new_i64();
11652 TCGv_i64 fp1 = tcg_temp_new_i64();
11653 TCGv_i64 fp2 = tcg_temp_new_i64();
11654 gen_load_fpr64(ctx, fp0, fd);
11655 gen_load_fpr64(ctx, fp1, ft);
11656 gen_load_fpr64(ctx, fp2, fs);
11658 switch (op1) {
11659 case OPC_SEL_D:
11660 tcg_gen_andi_i64(fp0, fp0, 1);
11661 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11662 break;
11663 case OPC_SELEQZ_D:
11664 tcg_gen_andi_i64(fp1, fp1, 1);
11665 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11666 break;
11667 case OPC_SELNEZ_D:
11668 tcg_gen_andi_i64(fp1, fp1, 1);
11669 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11670 break;
11671 default:
11672 MIPS_INVAL("gen_sel_d");
11673 generate_exception_end(ctx, EXCP_RI);
11674 break;
11677 gen_store_fpr64(ctx, fp0, fd);
11678 tcg_temp_free_i64(fp2);
11679 tcg_temp_free_i64(fp1);
11680 tcg_temp_free_i64(fp0);
11681 tcg_temp_free_i64(t1);
11684 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11685 int ft, int fs, int fd, int cc)
11687 uint32_t func = ctx->opcode & 0x3f;
11688 switch (op1) {
11689 case OPC_ADD_S:
11691 TCGv_i32 fp0 = tcg_temp_new_i32();
11692 TCGv_i32 fp1 = tcg_temp_new_i32();
11694 gen_load_fpr32(ctx, fp0, fs);
11695 gen_load_fpr32(ctx, fp1, ft);
11696 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11697 tcg_temp_free_i32(fp1);
11698 gen_store_fpr32(ctx, fp0, fd);
11699 tcg_temp_free_i32(fp0);
11701 break;
11702 case OPC_SUB_S:
11704 TCGv_i32 fp0 = tcg_temp_new_i32();
11705 TCGv_i32 fp1 = tcg_temp_new_i32();
11707 gen_load_fpr32(ctx, fp0, fs);
11708 gen_load_fpr32(ctx, fp1, ft);
11709 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11710 tcg_temp_free_i32(fp1);
11711 gen_store_fpr32(ctx, fp0, fd);
11712 tcg_temp_free_i32(fp0);
11714 break;
11715 case OPC_MUL_S:
11717 TCGv_i32 fp0 = tcg_temp_new_i32();
11718 TCGv_i32 fp1 = tcg_temp_new_i32();
11720 gen_load_fpr32(ctx, fp0, fs);
11721 gen_load_fpr32(ctx, fp1, ft);
11722 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11723 tcg_temp_free_i32(fp1);
11724 gen_store_fpr32(ctx, fp0, fd);
11725 tcg_temp_free_i32(fp0);
11727 break;
11728 case OPC_DIV_S:
11730 TCGv_i32 fp0 = tcg_temp_new_i32();
11731 TCGv_i32 fp1 = tcg_temp_new_i32();
11733 gen_load_fpr32(ctx, fp0, fs);
11734 gen_load_fpr32(ctx, fp1, ft);
11735 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11736 tcg_temp_free_i32(fp1);
11737 gen_store_fpr32(ctx, fp0, fd);
11738 tcg_temp_free_i32(fp0);
11740 break;
11741 case OPC_SQRT_S:
11743 TCGv_i32 fp0 = tcg_temp_new_i32();
11745 gen_load_fpr32(ctx, fp0, fs);
11746 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11747 gen_store_fpr32(ctx, fp0, fd);
11748 tcg_temp_free_i32(fp0);
11750 break;
11751 case OPC_ABS_S:
11753 TCGv_i32 fp0 = tcg_temp_new_i32();
11755 gen_load_fpr32(ctx, fp0, fs);
11756 if (ctx->abs2008) {
11757 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11758 } else {
11759 gen_helper_float_abs_s(fp0, fp0);
11761 gen_store_fpr32(ctx, fp0, fd);
11762 tcg_temp_free_i32(fp0);
11764 break;
11765 case OPC_MOV_S:
11767 TCGv_i32 fp0 = tcg_temp_new_i32();
11769 gen_load_fpr32(ctx, fp0, fs);
11770 gen_store_fpr32(ctx, fp0, fd);
11771 tcg_temp_free_i32(fp0);
11773 break;
11774 case OPC_NEG_S:
11776 TCGv_i32 fp0 = tcg_temp_new_i32();
11778 gen_load_fpr32(ctx, fp0, fs);
11779 if (ctx->abs2008) {
11780 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11781 } else {
11782 gen_helper_float_chs_s(fp0, fp0);
11784 gen_store_fpr32(ctx, fp0, fd);
11785 tcg_temp_free_i32(fp0);
11787 break;
11788 case OPC_ROUND_L_S:
11789 check_cp1_64bitmode(ctx);
11791 TCGv_i32 fp32 = tcg_temp_new_i32();
11792 TCGv_i64 fp64 = tcg_temp_new_i64();
11794 gen_load_fpr32(ctx, fp32, fs);
11795 if (ctx->nan2008) {
11796 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11797 } else {
11798 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11800 tcg_temp_free_i32(fp32);
11801 gen_store_fpr64(ctx, fp64, fd);
11802 tcg_temp_free_i64(fp64);
11804 break;
11805 case OPC_TRUNC_L_S:
11806 check_cp1_64bitmode(ctx);
11808 TCGv_i32 fp32 = tcg_temp_new_i32();
11809 TCGv_i64 fp64 = tcg_temp_new_i64();
11811 gen_load_fpr32(ctx, fp32, fs);
11812 if (ctx->nan2008) {
11813 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11814 } else {
11815 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11817 tcg_temp_free_i32(fp32);
11818 gen_store_fpr64(ctx, fp64, fd);
11819 tcg_temp_free_i64(fp64);
11821 break;
11822 case OPC_CEIL_L_S:
11823 check_cp1_64bitmode(ctx);
11825 TCGv_i32 fp32 = tcg_temp_new_i32();
11826 TCGv_i64 fp64 = tcg_temp_new_i64();
11828 gen_load_fpr32(ctx, fp32, fs);
11829 if (ctx->nan2008) {
11830 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11831 } else {
11832 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11834 tcg_temp_free_i32(fp32);
11835 gen_store_fpr64(ctx, fp64, fd);
11836 tcg_temp_free_i64(fp64);
11838 break;
11839 case OPC_FLOOR_L_S:
11840 check_cp1_64bitmode(ctx);
11842 TCGv_i32 fp32 = tcg_temp_new_i32();
11843 TCGv_i64 fp64 = tcg_temp_new_i64();
11845 gen_load_fpr32(ctx, fp32, fs);
11846 if (ctx->nan2008) {
11847 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11848 } else {
11849 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11851 tcg_temp_free_i32(fp32);
11852 gen_store_fpr64(ctx, fp64, fd);
11853 tcg_temp_free_i64(fp64);
11855 break;
11856 case OPC_ROUND_W_S:
11858 TCGv_i32 fp0 = tcg_temp_new_i32();
11860 gen_load_fpr32(ctx, fp0, fs);
11861 if (ctx->nan2008) {
11862 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11863 } else {
11864 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11866 gen_store_fpr32(ctx, fp0, fd);
11867 tcg_temp_free_i32(fp0);
11869 break;
11870 case OPC_TRUNC_W_S:
11872 TCGv_i32 fp0 = tcg_temp_new_i32();
11874 gen_load_fpr32(ctx, fp0, fs);
11875 if (ctx->nan2008) {
11876 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11877 } else {
11878 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11880 gen_store_fpr32(ctx, fp0, fd);
11881 tcg_temp_free_i32(fp0);
11883 break;
11884 case OPC_CEIL_W_S:
11886 TCGv_i32 fp0 = tcg_temp_new_i32();
11888 gen_load_fpr32(ctx, fp0, fs);
11889 if (ctx->nan2008) {
11890 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11891 } else {
11892 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11894 gen_store_fpr32(ctx, fp0, fd);
11895 tcg_temp_free_i32(fp0);
11897 break;
11898 case OPC_FLOOR_W_S:
11900 TCGv_i32 fp0 = tcg_temp_new_i32();
11902 gen_load_fpr32(ctx, fp0, fs);
11903 if (ctx->nan2008) {
11904 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11905 } else {
11906 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11908 gen_store_fpr32(ctx, fp0, fd);
11909 tcg_temp_free_i32(fp0);
11911 break;
11912 case OPC_SEL_S:
11913 check_insn(ctx, ISA_MIPS32R6);
11914 gen_sel_s(ctx, op1, fd, ft, fs);
11915 break;
11916 case OPC_SELEQZ_S:
11917 check_insn(ctx, ISA_MIPS32R6);
11918 gen_sel_s(ctx, op1, fd, ft, fs);
11919 break;
11920 case OPC_SELNEZ_S:
11921 check_insn(ctx, ISA_MIPS32R6);
11922 gen_sel_s(ctx, op1, fd, ft, fs);
11923 break;
11924 case OPC_MOVCF_S:
11925 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11926 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11927 break;
11928 case OPC_MOVZ_S:
11929 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11931 TCGLabel *l1 = gen_new_label();
11932 TCGv_i32 fp0;
11934 if (ft != 0) {
11935 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11937 fp0 = tcg_temp_new_i32();
11938 gen_load_fpr32(ctx, fp0, fs);
11939 gen_store_fpr32(ctx, fp0, fd);
11940 tcg_temp_free_i32(fp0);
11941 gen_set_label(l1);
11943 break;
11944 case OPC_MOVN_S:
11945 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11947 TCGLabel *l1 = gen_new_label();
11948 TCGv_i32 fp0;
11950 if (ft != 0) {
11951 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11952 fp0 = tcg_temp_new_i32();
11953 gen_load_fpr32(ctx, fp0, fs);
11954 gen_store_fpr32(ctx, fp0, fd);
11955 tcg_temp_free_i32(fp0);
11956 gen_set_label(l1);
11959 break;
11960 case OPC_RECIP_S:
11962 TCGv_i32 fp0 = tcg_temp_new_i32();
11964 gen_load_fpr32(ctx, fp0, fs);
11965 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11966 gen_store_fpr32(ctx, fp0, fd);
11967 tcg_temp_free_i32(fp0);
11969 break;
11970 case OPC_RSQRT_S:
11972 TCGv_i32 fp0 = tcg_temp_new_i32();
11974 gen_load_fpr32(ctx, fp0, fs);
11975 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11976 gen_store_fpr32(ctx, fp0, fd);
11977 tcg_temp_free_i32(fp0);
11979 break;
11980 case OPC_MADDF_S:
11981 check_insn(ctx, ISA_MIPS32R6);
11983 TCGv_i32 fp0 = tcg_temp_new_i32();
11984 TCGv_i32 fp1 = tcg_temp_new_i32();
11985 TCGv_i32 fp2 = tcg_temp_new_i32();
11986 gen_load_fpr32(ctx, fp0, fs);
11987 gen_load_fpr32(ctx, fp1, ft);
11988 gen_load_fpr32(ctx, fp2, fd);
11989 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11990 gen_store_fpr32(ctx, fp2, fd);
11991 tcg_temp_free_i32(fp2);
11992 tcg_temp_free_i32(fp1);
11993 tcg_temp_free_i32(fp0);
11995 break;
11996 case OPC_MSUBF_S:
11997 check_insn(ctx, ISA_MIPS32R6);
11999 TCGv_i32 fp0 = tcg_temp_new_i32();
12000 TCGv_i32 fp1 = tcg_temp_new_i32();
12001 TCGv_i32 fp2 = tcg_temp_new_i32();
12002 gen_load_fpr32(ctx, fp0, fs);
12003 gen_load_fpr32(ctx, fp1, ft);
12004 gen_load_fpr32(ctx, fp2, fd);
12005 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
12006 gen_store_fpr32(ctx, fp2, fd);
12007 tcg_temp_free_i32(fp2);
12008 tcg_temp_free_i32(fp1);
12009 tcg_temp_free_i32(fp0);
12011 break;
12012 case OPC_RINT_S:
12013 check_insn(ctx, ISA_MIPS32R6);
12015 TCGv_i32 fp0 = tcg_temp_new_i32();
12016 gen_load_fpr32(ctx, fp0, fs);
12017 gen_helper_float_rint_s(fp0, cpu_env, fp0);
12018 gen_store_fpr32(ctx, fp0, fd);
12019 tcg_temp_free_i32(fp0);
12021 break;
12022 case OPC_CLASS_S:
12023 check_insn(ctx, ISA_MIPS32R6);
12025 TCGv_i32 fp0 = tcg_temp_new_i32();
12026 gen_load_fpr32(ctx, fp0, fs);
12027 gen_helper_float_class_s(fp0, cpu_env, fp0);
12028 gen_store_fpr32(ctx, fp0, fd);
12029 tcg_temp_free_i32(fp0);
12031 break;
12032 case OPC_MIN_S: /* OPC_RECIP2_S */
12033 if (ctx->insn_flags & ISA_MIPS32R6) {
12034 /* OPC_MIN_S */
12035 TCGv_i32 fp0 = tcg_temp_new_i32();
12036 TCGv_i32 fp1 = tcg_temp_new_i32();
12037 TCGv_i32 fp2 = tcg_temp_new_i32();
12038 gen_load_fpr32(ctx, fp0, fs);
12039 gen_load_fpr32(ctx, fp1, ft);
12040 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
12041 gen_store_fpr32(ctx, fp2, fd);
12042 tcg_temp_free_i32(fp2);
12043 tcg_temp_free_i32(fp1);
12044 tcg_temp_free_i32(fp0);
12045 } else {
12046 /* OPC_RECIP2_S */
12047 check_cp1_64bitmode(ctx);
12049 TCGv_i32 fp0 = tcg_temp_new_i32();
12050 TCGv_i32 fp1 = tcg_temp_new_i32();
12052 gen_load_fpr32(ctx, fp0, fs);
12053 gen_load_fpr32(ctx, fp1, ft);
12054 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
12055 tcg_temp_free_i32(fp1);
12056 gen_store_fpr32(ctx, fp0, fd);
12057 tcg_temp_free_i32(fp0);
12060 break;
12061 case OPC_MINA_S: /* OPC_RECIP1_S */
12062 if (ctx->insn_flags & ISA_MIPS32R6) {
12063 /* OPC_MINA_S */
12064 TCGv_i32 fp0 = tcg_temp_new_i32();
12065 TCGv_i32 fp1 = tcg_temp_new_i32();
12066 TCGv_i32 fp2 = tcg_temp_new_i32();
12067 gen_load_fpr32(ctx, fp0, fs);
12068 gen_load_fpr32(ctx, fp1, ft);
12069 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
12070 gen_store_fpr32(ctx, fp2, fd);
12071 tcg_temp_free_i32(fp2);
12072 tcg_temp_free_i32(fp1);
12073 tcg_temp_free_i32(fp0);
12074 } else {
12075 /* OPC_RECIP1_S */
12076 check_cp1_64bitmode(ctx);
12078 TCGv_i32 fp0 = tcg_temp_new_i32();
12080 gen_load_fpr32(ctx, fp0, fs);
12081 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
12082 gen_store_fpr32(ctx, fp0, fd);
12083 tcg_temp_free_i32(fp0);
12086 break;
12087 case OPC_MAX_S: /* OPC_RSQRT1_S */
12088 if (ctx->insn_flags & ISA_MIPS32R6) {
12089 /* OPC_MAX_S */
12090 TCGv_i32 fp0 = tcg_temp_new_i32();
12091 TCGv_i32 fp1 = tcg_temp_new_i32();
12092 gen_load_fpr32(ctx, fp0, fs);
12093 gen_load_fpr32(ctx, fp1, ft);
12094 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
12095 gen_store_fpr32(ctx, fp1, fd);
12096 tcg_temp_free_i32(fp1);
12097 tcg_temp_free_i32(fp0);
12098 } else {
12099 /* OPC_RSQRT1_S */
12100 check_cp1_64bitmode(ctx);
12102 TCGv_i32 fp0 = tcg_temp_new_i32();
12104 gen_load_fpr32(ctx, fp0, fs);
12105 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
12106 gen_store_fpr32(ctx, fp0, fd);
12107 tcg_temp_free_i32(fp0);
12110 break;
12111 case OPC_MAXA_S: /* OPC_RSQRT2_S */
12112 if (ctx->insn_flags & ISA_MIPS32R6) {
12113 /* OPC_MAXA_S */
12114 TCGv_i32 fp0 = tcg_temp_new_i32();
12115 TCGv_i32 fp1 = tcg_temp_new_i32();
12116 gen_load_fpr32(ctx, fp0, fs);
12117 gen_load_fpr32(ctx, fp1, ft);
12118 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
12119 gen_store_fpr32(ctx, fp1, fd);
12120 tcg_temp_free_i32(fp1);
12121 tcg_temp_free_i32(fp0);
12122 } else {
12123 /* OPC_RSQRT2_S */
12124 check_cp1_64bitmode(ctx);
12126 TCGv_i32 fp0 = tcg_temp_new_i32();
12127 TCGv_i32 fp1 = tcg_temp_new_i32();
12129 gen_load_fpr32(ctx, fp0, fs);
12130 gen_load_fpr32(ctx, fp1, ft);
12131 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
12132 tcg_temp_free_i32(fp1);
12133 gen_store_fpr32(ctx, fp0, fd);
12134 tcg_temp_free_i32(fp0);
12137 break;
12138 case OPC_CVT_D_S:
12139 check_cp1_registers(ctx, fd);
12141 TCGv_i32 fp32 = tcg_temp_new_i32();
12142 TCGv_i64 fp64 = tcg_temp_new_i64();
12144 gen_load_fpr32(ctx, fp32, fs);
12145 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
12146 tcg_temp_free_i32(fp32);
12147 gen_store_fpr64(ctx, fp64, fd);
12148 tcg_temp_free_i64(fp64);
12150 break;
12151 case OPC_CVT_W_S:
12153 TCGv_i32 fp0 = tcg_temp_new_i32();
12155 gen_load_fpr32(ctx, fp0, fs);
12156 if (ctx->nan2008) {
12157 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
12158 } else {
12159 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
12161 gen_store_fpr32(ctx, fp0, fd);
12162 tcg_temp_free_i32(fp0);
12164 break;
12165 case OPC_CVT_L_S:
12166 check_cp1_64bitmode(ctx);
12168 TCGv_i32 fp32 = tcg_temp_new_i32();
12169 TCGv_i64 fp64 = tcg_temp_new_i64();
12171 gen_load_fpr32(ctx, fp32, fs);
12172 if (ctx->nan2008) {
12173 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
12174 } else {
12175 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
12177 tcg_temp_free_i32(fp32);
12178 gen_store_fpr64(ctx, fp64, fd);
12179 tcg_temp_free_i64(fp64);
12181 break;
12182 case OPC_CVT_PS_S:
12183 check_ps(ctx);
12185 TCGv_i64 fp64 = tcg_temp_new_i64();
12186 TCGv_i32 fp32_0 = tcg_temp_new_i32();
12187 TCGv_i32 fp32_1 = tcg_temp_new_i32();
12189 gen_load_fpr32(ctx, fp32_0, fs);
12190 gen_load_fpr32(ctx, fp32_1, ft);
12191 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
12192 tcg_temp_free_i32(fp32_1);
12193 tcg_temp_free_i32(fp32_0);
12194 gen_store_fpr64(ctx, fp64, fd);
12195 tcg_temp_free_i64(fp64);
12197 break;
12198 case OPC_CMP_F_S:
12199 case OPC_CMP_UN_S:
12200 case OPC_CMP_EQ_S:
12201 case OPC_CMP_UEQ_S:
12202 case OPC_CMP_OLT_S:
12203 case OPC_CMP_ULT_S:
12204 case OPC_CMP_OLE_S:
12205 case OPC_CMP_ULE_S:
12206 case OPC_CMP_SF_S:
12207 case OPC_CMP_NGLE_S:
12208 case OPC_CMP_SEQ_S:
12209 case OPC_CMP_NGL_S:
12210 case OPC_CMP_LT_S:
12211 case OPC_CMP_NGE_S:
12212 case OPC_CMP_LE_S:
12213 case OPC_CMP_NGT_S:
12214 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12215 if (ctx->opcode & (1 << 6)) {
12216 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
12217 } else {
12218 gen_cmp_s(ctx, func - 48, ft, fs, cc);
12220 break;
12221 case OPC_ADD_D:
12222 check_cp1_registers(ctx, fs | ft | fd);
12224 TCGv_i64 fp0 = tcg_temp_new_i64();
12225 TCGv_i64 fp1 = tcg_temp_new_i64();
12227 gen_load_fpr64(ctx, fp0, fs);
12228 gen_load_fpr64(ctx, fp1, ft);
12229 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
12230 tcg_temp_free_i64(fp1);
12231 gen_store_fpr64(ctx, fp0, fd);
12232 tcg_temp_free_i64(fp0);
12234 break;
12235 case OPC_SUB_D:
12236 check_cp1_registers(ctx, fs | ft | fd);
12238 TCGv_i64 fp0 = tcg_temp_new_i64();
12239 TCGv_i64 fp1 = tcg_temp_new_i64();
12241 gen_load_fpr64(ctx, fp0, fs);
12242 gen_load_fpr64(ctx, fp1, ft);
12243 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
12244 tcg_temp_free_i64(fp1);
12245 gen_store_fpr64(ctx, fp0, fd);
12246 tcg_temp_free_i64(fp0);
12248 break;
12249 case OPC_MUL_D:
12250 check_cp1_registers(ctx, fs | ft | fd);
12252 TCGv_i64 fp0 = tcg_temp_new_i64();
12253 TCGv_i64 fp1 = tcg_temp_new_i64();
12255 gen_load_fpr64(ctx, fp0, fs);
12256 gen_load_fpr64(ctx, fp1, ft);
12257 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
12258 tcg_temp_free_i64(fp1);
12259 gen_store_fpr64(ctx, fp0, fd);
12260 tcg_temp_free_i64(fp0);
12262 break;
12263 case OPC_DIV_D:
12264 check_cp1_registers(ctx, fs | ft | fd);
12266 TCGv_i64 fp0 = tcg_temp_new_i64();
12267 TCGv_i64 fp1 = tcg_temp_new_i64();
12269 gen_load_fpr64(ctx, fp0, fs);
12270 gen_load_fpr64(ctx, fp1, ft);
12271 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
12272 tcg_temp_free_i64(fp1);
12273 gen_store_fpr64(ctx, fp0, fd);
12274 tcg_temp_free_i64(fp0);
12276 break;
12277 case OPC_SQRT_D:
12278 check_cp1_registers(ctx, fs | fd);
12280 TCGv_i64 fp0 = tcg_temp_new_i64();
12282 gen_load_fpr64(ctx, fp0, fs);
12283 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
12284 gen_store_fpr64(ctx, fp0, fd);
12285 tcg_temp_free_i64(fp0);
12287 break;
12288 case OPC_ABS_D:
12289 check_cp1_registers(ctx, fs | fd);
12291 TCGv_i64 fp0 = tcg_temp_new_i64();
12293 gen_load_fpr64(ctx, fp0, fs);
12294 if (ctx->abs2008) {
12295 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
12296 } else {
12297 gen_helper_float_abs_d(fp0, fp0);
12299 gen_store_fpr64(ctx, fp0, fd);
12300 tcg_temp_free_i64(fp0);
12302 break;
12303 case OPC_MOV_D:
12304 check_cp1_registers(ctx, fs | fd);
12306 TCGv_i64 fp0 = tcg_temp_new_i64();
12308 gen_load_fpr64(ctx, fp0, fs);
12309 gen_store_fpr64(ctx, fp0, fd);
12310 tcg_temp_free_i64(fp0);
12312 break;
12313 case OPC_NEG_D:
12314 check_cp1_registers(ctx, fs | fd);
12316 TCGv_i64 fp0 = tcg_temp_new_i64();
12318 gen_load_fpr64(ctx, fp0, fs);
12319 if (ctx->abs2008) {
12320 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
12321 } else {
12322 gen_helper_float_chs_d(fp0, fp0);
12324 gen_store_fpr64(ctx, fp0, fd);
12325 tcg_temp_free_i64(fp0);
12327 break;
12328 case OPC_ROUND_L_D:
12329 check_cp1_64bitmode(ctx);
12331 TCGv_i64 fp0 = tcg_temp_new_i64();
12333 gen_load_fpr64(ctx, fp0, fs);
12334 if (ctx->nan2008) {
12335 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
12336 } else {
12337 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
12339 gen_store_fpr64(ctx, fp0, fd);
12340 tcg_temp_free_i64(fp0);
12342 break;
12343 case OPC_TRUNC_L_D:
12344 check_cp1_64bitmode(ctx);
12346 TCGv_i64 fp0 = tcg_temp_new_i64();
12348 gen_load_fpr64(ctx, fp0, fs);
12349 if (ctx->nan2008) {
12350 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
12351 } else {
12352 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
12354 gen_store_fpr64(ctx, fp0, fd);
12355 tcg_temp_free_i64(fp0);
12357 break;
12358 case OPC_CEIL_L_D:
12359 check_cp1_64bitmode(ctx);
12361 TCGv_i64 fp0 = tcg_temp_new_i64();
12363 gen_load_fpr64(ctx, fp0, fs);
12364 if (ctx->nan2008) {
12365 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
12366 } else {
12367 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
12369 gen_store_fpr64(ctx, fp0, fd);
12370 tcg_temp_free_i64(fp0);
12372 break;
12373 case OPC_FLOOR_L_D:
12374 check_cp1_64bitmode(ctx);
12376 TCGv_i64 fp0 = tcg_temp_new_i64();
12378 gen_load_fpr64(ctx, fp0, fs);
12379 if (ctx->nan2008) {
12380 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
12381 } else {
12382 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
12384 gen_store_fpr64(ctx, fp0, fd);
12385 tcg_temp_free_i64(fp0);
12387 break;
12388 case OPC_ROUND_W_D:
12389 check_cp1_registers(ctx, fs);
12391 TCGv_i32 fp32 = tcg_temp_new_i32();
12392 TCGv_i64 fp64 = tcg_temp_new_i64();
12394 gen_load_fpr64(ctx, fp64, fs);
12395 if (ctx->nan2008) {
12396 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
12397 } else {
12398 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
12400 tcg_temp_free_i64(fp64);
12401 gen_store_fpr32(ctx, fp32, fd);
12402 tcg_temp_free_i32(fp32);
12404 break;
12405 case OPC_TRUNC_W_D:
12406 check_cp1_registers(ctx, fs);
12408 TCGv_i32 fp32 = tcg_temp_new_i32();
12409 TCGv_i64 fp64 = tcg_temp_new_i64();
12411 gen_load_fpr64(ctx, fp64, fs);
12412 if (ctx->nan2008) {
12413 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12414 } else {
12415 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12417 tcg_temp_free_i64(fp64);
12418 gen_store_fpr32(ctx, fp32, fd);
12419 tcg_temp_free_i32(fp32);
12421 break;
12422 case OPC_CEIL_W_D:
12423 check_cp1_registers(ctx, fs);
12425 TCGv_i32 fp32 = tcg_temp_new_i32();
12426 TCGv_i64 fp64 = tcg_temp_new_i64();
12428 gen_load_fpr64(ctx, fp64, fs);
12429 if (ctx->nan2008) {
12430 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12431 } else {
12432 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12434 tcg_temp_free_i64(fp64);
12435 gen_store_fpr32(ctx, fp32, fd);
12436 tcg_temp_free_i32(fp32);
12438 break;
12439 case OPC_FLOOR_W_D:
12440 check_cp1_registers(ctx, fs);
12442 TCGv_i32 fp32 = tcg_temp_new_i32();
12443 TCGv_i64 fp64 = tcg_temp_new_i64();
12445 gen_load_fpr64(ctx, fp64, fs);
12446 if (ctx->nan2008) {
12447 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12448 } else {
12449 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12451 tcg_temp_free_i64(fp64);
12452 gen_store_fpr32(ctx, fp32, fd);
12453 tcg_temp_free_i32(fp32);
12455 break;
12456 case OPC_SEL_D:
12457 check_insn(ctx, ISA_MIPS32R6);
12458 gen_sel_d(ctx, op1, fd, ft, fs);
12459 break;
12460 case OPC_SELEQZ_D:
12461 check_insn(ctx, ISA_MIPS32R6);
12462 gen_sel_d(ctx, op1, fd, ft, fs);
12463 break;
12464 case OPC_SELNEZ_D:
12465 check_insn(ctx, ISA_MIPS32R6);
12466 gen_sel_d(ctx, op1, fd, ft, fs);
12467 break;
12468 case OPC_MOVCF_D:
12469 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12470 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12471 break;
12472 case OPC_MOVZ_D:
12473 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12475 TCGLabel *l1 = gen_new_label();
12476 TCGv_i64 fp0;
12478 if (ft != 0) {
12479 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12481 fp0 = tcg_temp_new_i64();
12482 gen_load_fpr64(ctx, fp0, fs);
12483 gen_store_fpr64(ctx, fp0, fd);
12484 tcg_temp_free_i64(fp0);
12485 gen_set_label(l1);
12487 break;
12488 case OPC_MOVN_D:
12489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12491 TCGLabel *l1 = gen_new_label();
12492 TCGv_i64 fp0;
12494 if (ft != 0) {
12495 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12496 fp0 = tcg_temp_new_i64();
12497 gen_load_fpr64(ctx, fp0, fs);
12498 gen_store_fpr64(ctx, fp0, fd);
12499 tcg_temp_free_i64(fp0);
12500 gen_set_label(l1);
12503 break;
12504 case OPC_RECIP_D:
12505 check_cp1_registers(ctx, fs | fd);
12507 TCGv_i64 fp0 = tcg_temp_new_i64();
12509 gen_load_fpr64(ctx, fp0, fs);
12510 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12511 gen_store_fpr64(ctx, fp0, fd);
12512 tcg_temp_free_i64(fp0);
12514 break;
12515 case OPC_RSQRT_D:
12516 check_cp1_registers(ctx, fs | fd);
12518 TCGv_i64 fp0 = tcg_temp_new_i64();
12520 gen_load_fpr64(ctx, fp0, fs);
12521 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12522 gen_store_fpr64(ctx, fp0, fd);
12523 tcg_temp_free_i64(fp0);
12525 break;
12526 case OPC_MADDF_D:
12527 check_insn(ctx, ISA_MIPS32R6);
12529 TCGv_i64 fp0 = tcg_temp_new_i64();
12530 TCGv_i64 fp1 = tcg_temp_new_i64();
12531 TCGv_i64 fp2 = tcg_temp_new_i64();
12532 gen_load_fpr64(ctx, fp0, fs);
12533 gen_load_fpr64(ctx, fp1, ft);
12534 gen_load_fpr64(ctx, fp2, fd);
12535 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12536 gen_store_fpr64(ctx, fp2, fd);
12537 tcg_temp_free_i64(fp2);
12538 tcg_temp_free_i64(fp1);
12539 tcg_temp_free_i64(fp0);
12541 break;
12542 case OPC_MSUBF_D:
12543 check_insn(ctx, ISA_MIPS32R6);
12545 TCGv_i64 fp0 = tcg_temp_new_i64();
12546 TCGv_i64 fp1 = tcg_temp_new_i64();
12547 TCGv_i64 fp2 = tcg_temp_new_i64();
12548 gen_load_fpr64(ctx, fp0, fs);
12549 gen_load_fpr64(ctx, fp1, ft);
12550 gen_load_fpr64(ctx, fp2, fd);
12551 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12552 gen_store_fpr64(ctx, fp2, fd);
12553 tcg_temp_free_i64(fp2);
12554 tcg_temp_free_i64(fp1);
12555 tcg_temp_free_i64(fp0);
12557 break;
12558 case OPC_RINT_D:
12559 check_insn(ctx, ISA_MIPS32R6);
12561 TCGv_i64 fp0 = tcg_temp_new_i64();
12562 gen_load_fpr64(ctx, fp0, fs);
12563 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12564 gen_store_fpr64(ctx, fp0, fd);
12565 tcg_temp_free_i64(fp0);
12567 break;
12568 case OPC_CLASS_D:
12569 check_insn(ctx, ISA_MIPS32R6);
12571 TCGv_i64 fp0 = tcg_temp_new_i64();
12572 gen_load_fpr64(ctx, fp0, fs);
12573 gen_helper_float_class_d(fp0, cpu_env, fp0);
12574 gen_store_fpr64(ctx, fp0, fd);
12575 tcg_temp_free_i64(fp0);
12577 break;
12578 case OPC_MIN_D: /* OPC_RECIP2_D */
12579 if (ctx->insn_flags & ISA_MIPS32R6) {
12580 /* OPC_MIN_D */
12581 TCGv_i64 fp0 = tcg_temp_new_i64();
12582 TCGv_i64 fp1 = tcg_temp_new_i64();
12583 gen_load_fpr64(ctx, fp0, fs);
12584 gen_load_fpr64(ctx, fp1, ft);
12585 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12586 gen_store_fpr64(ctx, fp1, fd);
12587 tcg_temp_free_i64(fp1);
12588 tcg_temp_free_i64(fp0);
12589 } else {
12590 /* OPC_RECIP2_D */
12591 check_cp1_64bitmode(ctx);
12593 TCGv_i64 fp0 = tcg_temp_new_i64();
12594 TCGv_i64 fp1 = tcg_temp_new_i64();
12596 gen_load_fpr64(ctx, fp0, fs);
12597 gen_load_fpr64(ctx, fp1, ft);
12598 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12599 tcg_temp_free_i64(fp1);
12600 gen_store_fpr64(ctx, fp0, fd);
12601 tcg_temp_free_i64(fp0);
12604 break;
12605 case OPC_MINA_D: /* OPC_RECIP1_D */
12606 if (ctx->insn_flags & ISA_MIPS32R6) {
12607 /* OPC_MINA_D */
12608 TCGv_i64 fp0 = tcg_temp_new_i64();
12609 TCGv_i64 fp1 = tcg_temp_new_i64();
12610 gen_load_fpr64(ctx, fp0, fs);
12611 gen_load_fpr64(ctx, fp1, ft);
12612 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12613 gen_store_fpr64(ctx, fp1, fd);
12614 tcg_temp_free_i64(fp1);
12615 tcg_temp_free_i64(fp0);
12616 } else {
12617 /* OPC_RECIP1_D */
12618 check_cp1_64bitmode(ctx);
12620 TCGv_i64 fp0 = tcg_temp_new_i64();
12622 gen_load_fpr64(ctx, fp0, fs);
12623 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12624 gen_store_fpr64(ctx, fp0, fd);
12625 tcg_temp_free_i64(fp0);
12628 break;
12629 case OPC_MAX_D: /* OPC_RSQRT1_D */
12630 if (ctx->insn_flags & ISA_MIPS32R6) {
12631 /* OPC_MAX_D */
12632 TCGv_i64 fp0 = tcg_temp_new_i64();
12633 TCGv_i64 fp1 = tcg_temp_new_i64();
12634 gen_load_fpr64(ctx, fp0, fs);
12635 gen_load_fpr64(ctx, fp1, ft);
12636 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12637 gen_store_fpr64(ctx, fp1, fd);
12638 tcg_temp_free_i64(fp1);
12639 tcg_temp_free_i64(fp0);
12640 } else {
12641 /* OPC_RSQRT1_D */
12642 check_cp1_64bitmode(ctx);
12644 TCGv_i64 fp0 = tcg_temp_new_i64();
12646 gen_load_fpr64(ctx, fp0, fs);
12647 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12648 gen_store_fpr64(ctx, fp0, fd);
12649 tcg_temp_free_i64(fp0);
12652 break;
12653 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12654 if (ctx->insn_flags & ISA_MIPS32R6) {
12655 /* OPC_MAXA_D */
12656 TCGv_i64 fp0 = tcg_temp_new_i64();
12657 TCGv_i64 fp1 = tcg_temp_new_i64();
12658 gen_load_fpr64(ctx, fp0, fs);
12659 gen_load_fpr64(ctx, fp1, ft);
12660 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12661 gen_store_fpr64(ctx, fp1, fd);
12662 tcg_temp_free_i64(fp1);
12663 tcg_temp_free_i64(fp0);
12664 } else {
12665 /* OPC_RSQRT2_D */
12666 check_cp1_64bitmode(ctx);
12668 TCGv_i64 fp0 = tcg_temp_new_i64();
12669 TCGv_i64 fp1 = tcg_temp_new_i64();
12671 gen_load_fpr64(ctx, fp0, fs);
12672 gen_load_fpr64(ctx, fp1, ft);
12673 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12674 tcg_temp_free_i64(fp1);
12675 gen_store_fpr64(ctx, fp0, fd);
12676 tcg_temp_free_i64(fp0);
12679 break;
12680 case OPC_CMP_F_D:
12681 case OPC_CMP_UN_D:
12682 case OPC_CMP_EQ_D:
12683 case OPC_CMP_UEQ_D:
12684 case OPC_CMP_OLT_D:
12685 case OPC_CMP_ULT_D:
12686 case OPC_CMP_OLE_D:
12687 case OPC_CMP_ULE_D:
12688 case OPC_CMP_SF_D:
12689 case OPC_CMP_NGLE_D:
12690 case OPC_CMP_SEQ_D:
12691 case OPC_CMP_NGL_D:
12692 case OPC_CMP_LT_D:
12693 case OPC_CMP_NGE_D:
12694 case OPC_CMP_LE_D:
12695 case OPC_CMP_NGT_D:
12696 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12697 if (ctx->opcode & (1 << 6)) {
12698 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12699 } else {
12700 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12702 break;
12703 case OPC_CVT_S_D:
12704 check_cp1_registers(ctx, fs);
12706 TCGv_i32 fp32 = tcg_temp_new_i32();
12707 TCGv_i64 fp64 = tcg_temp_new_i64();
12709 gen_load_fpr64(ctx, fp64, fs);
12710 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12711 tcg_temp_free_i64(fp64);
12712 gen_store_fpr32(ctx, fp32, fd);
12713 tcg_temp_free_i32(fp32);
12715 break;
12716 case OPC_CVT_W_D:
12717 check_cp1_registers(ctx, fs);
12719 TCGv_i32 fp32 = tcg_temp_new_i32();
12720 TCGv_i64 fp64 = tcg_temp_new_i64();
12722 gen_load_fpr64(ctx, fp64, fs);
12723 if (ctx->nan2008) {
12724 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12725 } else {
12726 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12728 tcg_temp_free_i64(fp64);
12729 gen_store_fpr32(ctx, fp32, fd);
12730 tcg_temp_free_i32(fp32);
12732 break;
12733 case OPC_CVT_L_D:
12734 check_cp1_64bitmode(ctx);
12736 TCGv_i64 fp0 = tcg_temp_new_i64();
12738 gen_load_fpr64(ctx, fp0, fs);
12739 if (ctx->nan2008) {
12740 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12741 } else {
12742 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12744 gen_store_fpr64(ctx, fp0, fd);
12745 tcg_temp_free_i64(fp0);
12747 break;
12748 case OPC_CVT_S_W:
12750 TCGv_i32 fp0 = tcg_temp_new_i32();
12752 gen_load_fpr32(ctx, fp0, fs);
12753 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12754 gen_store_fpr32(ctx, fp0, fd);
12755 tcg_temp_free_i32(fp0);
12757 break;
12758 case OPC_CVT_D_W:
12759 check_cp1_registers(ctx, fd);
12761 TCGv_i32 fp32 = tcg_temp_new_i32();
12762 TCGv_i64 fp64 = tcg_temp_new_i64();
12764 gen_load_fpr32(ctx, fp32, fs);
12765 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12766 tcg_temp_free_i32(fp32);
12767 gen_store_fpr64(ctx, fp64, fd);
12768 tcg_temp_free_i64(fp64);
12770 break;
12771 case OPC_CVT_S_L:
12772 check_cp1_64bitmode(ctx);
12774 TCGv_i32 fp32 = tcg_temp_new_i32();
12775 TCGv_i64 fp64 = tcg_temp_new_i64();
12777 gen_load_fpr64(ctx, fp64, fs);
12778 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12779 tcg_temp_free_i64(fp64);
12780 gen_store_fpr32(ctx, fp32, fd);
12781 tcg_temp_free_i32(fp32);
12783 break;
12784 case OPC_CVT_D_L:
12785 check_cp1_64bitmode(ctx);
12787 TCGv_i64 fp0 = tcg_temp_new_i64();
12789 gen_load_fpr64(ctx, fp0, fs);
12790 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12791 gen_store_fpr64(ctx, fp0, fd);
12792 tcg_temp_free_i64(fp0);
12794 break;
12795 case OPC_CVT_PS_PW:
12796 check_ps(ctx);
12798 TCGv_i64 fp0 = tcg_temp_new_i64();
12800 gen_load_fpr64(ctx, fp0, fs);
12801 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12802 gen_store_fpr64(ctx, fp0, fd);
12803 tcg_temp_free_i64(fp0);
12805 break;
12806 case OPC_ADD_PS:
12807 check_ps(ctx);
12809 TCGv_i64 fp0 = tcg_temp_new_i64();
12810 TCGv_i64 fp1 = tcg_temp_new_i64();
12812 gen_load_fpr64(ctx, fp0, fs);
12813 gen_load_fpr64(ctx, fp1, ft);
12814 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12815 tcg_temp_free_i64(fp1);
12816 gen_store_fpr64(ctx, fp0, fd);
12817 tcg_temp_free_i64(fp0);
12819 break;
12820 case OPC_SUB_PS:
12821 check_ps(ctx);
12823 TCGv_i64 fp0 = tcg_temp_new_i64();
12824 TCGv_i64 fp1 = tcg_temp_new_i64();
12826 gen_load_fpr64(ctx, fp0, fs);
12827 gen_load_fpr64(ctx, fp1, ft);
12828 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12829 tcg_temp_free_i64(fp1);
12830 gen_store_fpr64(ctx, fp0, fd);
12831 tcg_temp_free_i64(fp0);
12833 break;
12834 case OPC_MUL_PS:
12835 check_ps(ctx);
12837 TCGv_i64 fp0 = tcg_temp_new_i64();
12838 TCGv_i64 fp1 = tcg_temp_new_i64();
12840 gen_load_fpr64(ctx, fp0, fs);
12841 gen_load_fpr64(ctx, fp1, ft);
12842 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12843 tcg_temp_free_i64(fp1);
12844 gen_store_fpr64(ctx, fp0, fd);
12845 tcg_temp_free_i64(fp0);
12847 break;
12848 case OPC_ABS_PS:
12849 check_ps(ctx);
12851 TCGv_i64 fp0 = tcg_temp_new_i64();
12853 gen_load_fpr64(ctx, fp0, fs);
12854 gen_helper_float_abs_ps(fp0, fp0);
12855 gen_store_fpr64(ctx, fp0, fd);
12856 tcg_temp_free_i64(fp0);
12858 break;
12859 case OPC_MOV_PS:
12860 check_ps(ctx);
12862 TCGv_i64 fp0 = tcg_temp_new_i64();
12864 gen_load_fpr64(ctx, fp0, fs);
12865 gen_store_fpr64(ctx, fp0, fd);
12866 tcg_temp_free_i64(fp0);
12868 break;
12869 case OPC_NEG_PS:
12870 check_ps(ctx);
12872 TCGv_i64 fp0 = tcg_temp_new_i64();
12874 gen_load_fpr64(ctx, fp0, fs);
12875 gen_helper_float_chs_ps(fp0, fp0);
12876 gen_store_fpr64(ctx, fp0, fd);
12877 tcg_temp_free_i64(fp0);
12879 break;
12880 case OPC_MOVCF_PS:
12881 check_ps(ctx);
12882 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12883 break;
12884 case OPC_MOVZ_PS:
12885 check_ps(ctx);
12887 TCGLabel *l1 = gen_new_label();
12888 TCGv_i64 fp0;
12890 if (ft != 0) {
12891 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12893 fp0 = tcg_temp_new_i64();
12894 gen_load_fpr64(ctx, fp0, fs);
12895 gen_store_fpr64(ctx, fp0, fd);
12896 tcg_temp_free_i64(fp0);
12897 gen_set_label(l1);
12899 break;
12900 case OPC_MOVN_PS:
12901 check_ps(ctx);
12903 TCGLabel *l1 = gen_new_label();
12904 TCGv_i64 fp0;
12906 if (ft != 0) {
12907 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12908 fp0 = tcg_temp_new_i64();
12909 gen_load_fpr64(ctx, fp0, fs);
12910 gen_store_fpr64(ctx, fp0, fd);
12911 tcg_temp_free_i64(fp0);
12912 gen_set_label(l1);
12915 break;
12916 case OPC_ADDR_PS:
12917 check_ps(ctx);
12919 TCGv_i64 fp0 = tcg_temp_new_i64();
12920 TCGv_i64 fp1 = tcg_temp_new_i64();
12922 gen_load_fpr64(ctx, fp0, ft);
12923 gen_load_fpr64(ctx, fp1, fs);
12924 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12925 tcg_temp_free_i64(fp1);
12926 gen_store_fpr64(ctx, fp0, fd);
12927 tcg_temp_free_i64(fp0);
12929 break;
12930 case OPC_MULR_PS:
12931 check_ps(ctx);
12933 TCGv_i64 fp0 = tcg_temp_new_i64();
12934 TCGv_i64 fp1 = tcg_temp_new_i64();
12936 gen_load_fpr64(ctx, fp0, ft);
12937 gen_load_fpr64(ctx, fp1, fs);
12938 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12939 tcg_temp_free_i64(fp1);
12940 gen_store_fpr64(ctx, fp0, fd);
12941 tcg_temp_free_i64(fp0);
12943 break;
12944 case OPC_RECIP2_PS:
12945 check_ps(ctx);
12947 TCGv_i64 fp0 = tcg_temp_new_i64();
12948 TCGv_i64 fp1 = tcg_temp_new_i64();
12950 gen_load_fpr64(ctx, fp0, fs);
12951 gen_load_fpr64(ctx, fp1, ft);
12952 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12953 tcg_temp_free_i64(fp1);
12954 gen_store_fpr64(ctx, fp0, fd);
12955 tcg_temp_free_i64(fp0);
12957 break;
12958 case OPC_RECIP1_PS:
12959 check_ps(ctx);
12961 TCGv_i64 fp0 = tcg_temp_new_i64();
12963 gen_load_fpr64(ctx, fp0, fs);
12964 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12965 gen_store_fpr64(ctx, fp0, fd);
12966 tcg_temp_free_i64(fp0);
12968 break;
12969 case OPC_RSQRT1_PS:
12970 check_ps(ctx);
12972 TCGv_i64 fp0 = tcg_temp_new_i64();
12974 gen_load_fpr64(ctx, fp0, fs);
12975 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12976 gen_store_fpr64(ctx, fp0, fd);
12977 tcg_temp_free_i64(fp0);
12979 break;
12980 case OPC_RSQRT2_PS:
12981 check_ps(ctx);
12983 TCGv_i64 fp0 = tcg_temp_new_i64();
12984 TCGv_i64 fp1 = tcg_temp_new_i64();
12986 gen_load_fpr64(ctx, fp0, fs);
12987 gen_load_fpr64(ctx, fp1, ft);
12988 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12989 tcg_temp_free_i64(fp1);
12990 gen_store_fpr64(ctx, fp0, fd);
12991 tcg_temp_free_i64(fp0);
12993 break;
12994 case OPC_CVT_S_PU:
12995 check_cp1_64bitmode(ctx);
12997 TCGv_i32 fp0 = tcg_temp_new_i32();
12999 gen_load_fpr32h(ctx, fp0, fs);
13000 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
13001 gen_store_fpr32(ctx, fp0, fd);
13002 tcg_temp_free_i32(fp0);
13004 break;
13005 case OPC_CVT_PW_PS:
13006 check_ps(ctx);
13008 TCGv_i64 fp0 = tcg_temp_new_i64();
13010 gen_load_fpr64(ctx, fp0, fs);
13011 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
13012 gen_store_fpr64(ctx, fp0, fd);
13013 tcg_temp_free_i64(fp0);
13015 break;
13016 case OPC_CVT_S_PL:
13017 check_cp1_64bitmode(ctx);
13019 TCGv_i32 fp0 = tcg_temp_new_i32();
13021 gen_load_fpr32(ctx, fp0, fs);
13022 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
13023 gen_store_fpr32(ctx, fp0, fd);
13024 tcg_temp_free_i32(fp0);
13026 break;
13027 case OPC_PLL_PS:
13028 check_ps(ctx);
13030 TCGv_i32 fp0 = tcg_temp_new_i32();
13031 TCGv_i32 fp1 = tcg_temp_new_i32();
13033 gen_load_fpr32(ctx, fp0, fs);
13034 gen_load_fpr32(ctx, fp1, ft);
13035 gen_store_fpr32h(ctx, fp0, fd);
13036 gen_store_fpr32(ctx, fp1, fd);
13037 tcg_temp_free_i32(fp0);
13038 tcg_temp_free_i32(fp1);
13040 break;
13041 case OPC_PLU_PS:
13042 check_ps(ctx);
13044 TCGv_i32 fp0 = tcg_temp_new_i32();
13045 TCGv_i32 fp1 = tcg_temp_new_i32();
13047 gen_load_fpr32(ctx, fp0, fs);
13048 gen_load_fpr32h(ctx, fp1, ft);
13049 gen_store_fpr32(ctx, fp1, fd);
13050 gen_store_fpr32h(ctx, fp0, fd);
13051 tcg_temp_free_i32(fp0);
13052 tcg_temp_free_i32(fp1);
13054 break;
13055 case OPC_PUL_PS:
13056 check_ps(ctx);
13058 TCGv_i32 fp0 = tcg_temp_new_i32();
13059 TCGv_i32 fp1 = tcg_temp_new_i32();
13061 gen_load_fpr32h(ctx, fp0, fs);
13062 gen_load_fpr32(ctx, fp1, ft);
13063 gen_store_fpr32(ctx, fp1, fd);
13064 gen_store_fpr32h(ctx, fp0, fd);
13065 tcg_temp_free_i32(fp0);
13066 tcg_temp_free_i32(fp1);
13068 break;
13069 case OPC_PUU_PS:
13070 check_ps(ctx);
13072 TCGv_i32 fp0 = tcg_temp_new_i32();
13073 TCGv_i32 fp1 = tcg_temp_new_i32();
13075 gen_load_fpr32h(ctx, fp0, fs);
13076 gen_load_fpr32h(ctx, fp1, ft);
13077 gen_store_fpr32(ctx, fp1, fd);
13078 gen_store_fpr32h(ctx, fp0, fd);
13079 tcg_temp_free_i32(fp0);
13080 tcg_temp_free_i32(fp1);
13082 break;
13083 case OPC_CMP_F_PS:
13084 case OPC_CMP_UN_PS:
13085 case OPC_CMP_EQ_PS:
13086 case OPC_CMP_UEQ_PS:
13087 case OPC_CMP_OLT_PS:
13088 case OPC_CMP_ULT_PS:
13089 case OPC_CMP_OLE_PS:
13090 case OPC_CMP_ULE_PS:
13091 case OPC_CMP_SF_PS:
13092 case OPC_CMP_NGLE_PS:
13093 case OPC_CMP_SEQ_PS:
13094 case OPC_CMP_NGL_PS:
13095 case OPC_CMP_LT_PS:
13096 case OPC_CMP_NGE_PS:
13097 case OPC_CMP_LE_PS:
13098 case OPC_CMP_NGT_PS:
13099 if (ctx->opcode & (1 << 6)) {
13100 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
13101 } else {
13102 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
13104 break;
13105 default:
13106 MIPS_INVAL("farith");
13107 generate_exception_end(ctx, EXCP_RI);
13108 return;
13112 /* Coprocessor 3 (FPU) */
13113 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
13114 int fd, int fs, int base, int index)
13116 TCGv t0 = tcg_temp_new();
13118 if (base == 0) {
13119 gen_load_gpr(t0, index);
13120 } else if (index == 0) {
13121 gen_load_gpr(t0, base);
13122 } else {
13123 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
13126 * Don't do NOP if destination is zero: we must perform the actual
13127 * memory access.
13129 switch (opc) {
13130 case OPC_LWXC1:
13131 check_cop1x(ctx);
13133 TCGv_i32 fp0 = tcg_temp_new_i32();
13135 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13136 tcg_gen_trunc_tl_i32(fp0, t0);
13137 gen_store_fpr32(ctx, fp0, fd);
13138 tcg_temp_free_i32(fp0);
13140 break;
13141 case OPC_LDXC1:
13142 check_cop1x(ctx);
13143 check_cp1_registers(ctx, fd);
13145 TCGv_i64 fp0 = tcg_temp_new_i64();
13146 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13147 gen_store_fpr64(ctx, fp0, fd);
13148 tcg_temp_free_i64(fp0);
13150 break;
13151 case OPC_LUXC1:
13152 check_cp1_64bitmode(ctx);
13153 tcg_gen_andi_tl(t0, t0, ~0x7);
13155 TCGv_i64 fp0 = tcg_temp_new_i64();
13157 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13158 gen_store_fpr64(ctx, fp0, fd);
13159 tcg_temp_free_i64(fp0);
13161 break;
13162 case OPC_SWXC1:
13163 check_cop1x(ctx);
13165 TCGv_i32 fp0 = tcg_temp_new_i32();
13166 gen_load_fpr32(ctx, fp0, fs);
13167 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
13168 tcg_temp_free_i32(fp0);
13170 break;
13171 case OPC_SDXC1:
13172 check_cop1x(ctx);
13173 check_cp1_registers(ctx, fs);
13175 TCGv_i64 fp0 = tcg_temp_new_i64();
13176 gen_load_fpr64(ctx, fp0, fs);
13177 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13178 tcg_temp_free_i64(fp0);
13180 break;
13181 case OPC_SUXC1:
13182 check_cp1_64bitmode(ctx);
13183 tcg_gen_andi_tl(t0, t0, ~0x7);
13185 TCGv_i64 fp0 = tcg_temp_new_i64();
13186 gen_load_fpr64(ctx, fp0, fs);
13187 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13188 tcg_temp_free_i64(fp0);
13190 break;
13192 tcg_temp_free(t0);
13195 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
13196 int fd, int fr, int fs, int ft)
13198 switch (opc) {
13199 case OPC_ALNV_PS:
13200 check_ps(ctx);
13202 TCGv t0 = tcg_temp_local_new();
13203 TCGv_i32 fp = tcg_temp_new_i32();
13204 TCGv_i32 fph = tcg_temp_new_i32();
13205 TCGLabel *l1 = gen_new_label();
13206 TCGLabel *l2 = gen_new_label();
13208 gen_load_gpr(t0, fr);
13209 tcg_gen_andi_tl(t0, t0, 0x7);
13211 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
13212 gen_load_fpr32(ctx, fp, fs);
13213 gen_load_fpr32h(ctx, fph, fs);
13214 gen_store_fpr32(ctx, fp, fd);
13215 gen_store_fpr32h(ctx, fph, fd);
13216 tcg_gen_br(l2);
13217 gen_set_label(l1);
13218 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
13219 tcg_temp_free(t0);
13220 #ifdef TARGET_WORDS_BIGENDIAN
13221 gen_load_fpr32(ctx, fp, fs);
13222 gen_load_fpr32h(ctx, fph, ft);
13223 gen_store_fpr32h(ctx, fp, fd);
13224 gen_store_fpr32(ctx, fph, fd);
13225 #else
13226 gen_load_fpr32h(ctx, fph, fs);
13227 gen_load_fpr32(ctx, fp, ft);
13228 gen_store_fpr32(ctx, fph, fd);
13229 gen_store_fpr32h(ctx, fp, fd);
13230 #endif
13231 gen_set_label(l2);
13232 tcg_temp_free_i32(fp);
13233 tcg_temp_free_i32(fph);
13235 break;
13236 case OPC_MADD_S:
13237 check_cop1x(ctx);
13239 TCGv_i32 fp0 = tcg_temp_new_i32();
13240 TCGv_i32 fp1 = tcg_temp_new_i32();
13241 TCGv_i32 fp2 = tcg_temp_new_i32();
13243 gen_load_fpr32(ctx, fp0, fs);
13244 gen_load_fpr32(ctx, fp1, ft);
13245 gen_load_fpr32(ctx, fp2, fr);
13246 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
13247 tcg_temp_free_i32(fp0);
13248 tcg_temp_free_i32(fp1);
13249 gen_store_fpr32(ctx, fp2, fd);
13250 tcg_temp_free_i32(fp2);
13252 break;
13253 case OPC_MADD_D:
13254 check_cop1x(ctx);
13255 check_cp1_registers(ctx, fd | fs | ft | fr);
13257 TCGv_i64 fp0 = tcg_temp_new_i64();
13258 TCGv_i64 fp1 = tcg_temp_new_i64();
13259 TCGv_i64 fp2 = tcg_temp_new_i64();
13261 gen_load_fpr64(ctx, fp0, fs);
13262 gen_load_fpr64(ctx, fp1, ft);
13263 gen_load_fpr64(ctx, fp2, fr);
13264 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
13265 tcg_temp_free_i64(fp0);
13266 tcg_temp_free_i64(fp1);
13267 gen_store_fpr64(ctx, fp2, fd);
13268 tcg_temp_free_i64(fp2);
13270 break;
13271 case OPC_MADD_PS:
13272 check_ps(ctx);
13274 TCGv_i64 fp0 = tcg_temp_new_i64();
13275 TCGv_i64 fp1 = tcg_temp_new_i64();
13276 TCGv_i64 fp2 = tcg_temp_new_i64();
13278 gen_load_fpr64(ctx, fp0, fs);
13279 gen_load_fpr64(ctx, fp1, ft);
13280 gen_load_fpr64(ctx, fp2, fr);
13281 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
13282 tcg_temp_free_i64(fp0);
13283 tcg_temp_free_i64(fp1);
13284 gen_store_fpr64(ctx, fp2, fd);
13285 tcg_temp_free_i64(fp2);
13287 break;
13288 case OPC_MSUB_S:
13289 check_cop1x(ctx);
13291 TCGv_i32 fp0 = tcg_temp_new_i32();
13292 TCGv_i32 fp1 = tcg_temp_new_i32();
13293 TCGv_i32 fp2 = tcg_temp_new_i32();
13295 gen_load_fpr32(ctx, fp0, fs);
13296 gen_load_fpr32(ctx, fp1, ft);
13297 gen_load_fpr32(ctx, fp2, fr);
13298 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
13299 tcg_temp_free_i32(fp0);
13300 tcg_temp_free_i32(fp1);
13301 gen_store_fpr32(ctx, fp2, fd);
13302 tcg_temp_free_i32(fp2);
13304 break;
13305 case OPC_MSUB_D:
13306 check_cop1x(ctx);
13307 check_cp1_registers(ctx, fd | fs | ft | fr);
13309 TCGv_i64 fp0 = tcg_temp_new_i64();
13310 TCGv_i64 fp1 = tcg_temp_new_i64();
13311 TCGv_i64 fp2 = tcg_temp_new_i64();
13313 gen_load_fpr64(ctx, fp0, fs);
13314 gen_load_fpr64(ctx, fp1, ft);
13315 gen_load_fpr64(ctx, fp2, fr);
13316 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
13317 tcg_temp_free_i64(fp0);
13318 tcg_temp_free_i64(fp1);
13319 gen_store_fpr64(ctx, fp2, fd);
13320 tcg_temp_free_i64(fp2);
13322 break;
13323 case OPC_MSUB_PS:
13324 check_ps(ctx);
13326 TCGv_i64 fp0 = tcg_temp_new_i64();
13327 TCGv_i64 fp1 = tcg_temp_new_i64();
13328 TCGv_i64 fp2 = tcg_temp_new_i64();
13330 gen_load_fpr64(ctx, fp0, fs);
13331 gen_load_fpr64(ctx, fp1, ft);
13332 gen_load_fpr64(ctx, fp2, fr);
13333 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
13334 tcg_temp_free_i64(fp0);
13335 tcg_temp_free_i64(fp1);
13336 gen_store_fpr64(ctx, fp2, fd);
13337 tcg_temp_free_i64(fp2);
13339 break;
13340 case OPC_NMADD_S:
13341 check_cop1x(ctx);
13343 TCGv_i32 fp0 = tcg_temp_new_i32();
13344 TCGv_i32 fp1 = tcg_temp_new_i32();
13345 TCGv_i32 fp2 = tcg_temp_new_i32();
13347 gen_load_fpr32(ctx, fp0, fs);
13348 gen_load_fpr32(ctx, fp1, ft);
13349 gen_load_fpr32(ctx, fp2, fr);
13350 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
13351 tcg_temp_free_i32(fp0);
13352 tcg_temp_free_i32(fp1);
13353 gen_store_fpr32(ctx, fp2, fd);
13354 tcg_temp_free_i32(fp2);
13356 break;
13357 case OPC_NMADD_D:
13358 check_cop1x(ctx);
13359 check_cp1_registers(ctx, fd | fs | ft | fr);
13361 TCGv_i64 fp0 = tcg_temp_new_i64();
13362 TCGv_i64 fp1 = tcg_temp_new_i64();
13363 TCGv_i64 fp2 = tcg_temp_new_i64();
13365 gen_load_fpr64(ctx, fp0, fs);
13366 gen_load_fpr64(ctx, fp1, ft);
13367 gen_load_fpr64(ctx, fp2, fr);
13368 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
13369 tcg_temp_free_i64(fp0);
13370 tcg_temp_free_i64(fp1);
13371 gen_store_fpr64(ctx, fp2, fd);
13372 tcg_temp_free_i64(fp2);
13374 break;
13375 case OPC_NMADD_PS:
13376 check_ps(ctx);
13378 TCGv_i64 fp0 = tcg_temp_new_i64();
13379 TCGv_i64 fp1 = tcg_temp_new_i64();
13380 TCGv_i64 fp2 = tcg_temp_new_i64();
13382 gen_load_fpr64(ctx, fp0, fs);
13383 gen_load_fpr64(ctx, fp1, ft);
13384 gen_load_fpr64(ctx, fp2, fr);
13385 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
13386 tcg_temp_free_i64(fp0);
13387 tcg_temp_free_i64(fp1);
13388 gen_store_fpr64(ctx, fp2, fd);
13389 tcg_temp_free_i64(fp2);
13391 break;
13392 case OPC_NMSUB_S:
13393 check_cop1x(ctx);
13395 TCGv_i32 fp0 = tcg_temp_new_i32();
13396 TCGv_i32 fp1 = tcg_temp_new_i32();
13397 TCGv_i32 fp2 = tcg_temp_new_i32();
13399 gen_load_fpr32(ctx, fp0, fs);
13400 gen_load_fpr32(ctx, fp1, ft);
13401 gen_load_fpr32(ctx, fp2, fr);
13402 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
13403 tcg_temp_free_i32(fp0);
13404 tcg_temp_free_i32(fp1);
13405 gen_store_fpr32(ctx, fp2, fd);
13406 tcg_temp_free_i32(fp2);
13408 break;
13409 case OPC_NMSUB_D:
13410 check_cop1x(ctx);
13411 check_cp1_registers(ctx, fd | fs | ft | fr);
13413 TCGv_i64 fp0 = tcg_temp_new_i64();
13414 TCGv_i64 fp1 = tcg_temp_new_i64();
13415 TCGv_i64 fp2 = tcg_temp_new_i64();
13417 gen_load_fpr64(ctx, fp0, fs);
13418 gen_load_fpr64(ctx, fp1, ft);
13419 gen_load_fpr64(ctx, fp2, fr);
13420 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13421 tcg_temp_free_i64(fp0);
13422 tcg_temp_free_i64(fp1);
13423 gen_store_fpr64(ctx, fp2, fd);
13424 tcg_temp_free_i64(fp2);
13426 break;
13427 case OPC_NMSUB_PS:
13428 check_ps(ctx);
13430 TCGv_i64 fp0 = tcg_temp_new_i64();
13431 TCGv_i64 fp1 = tcg_temp_new_i64();
13432 TCGv_i64 fp2 = tcg_temp_new_i64();
13434 gen_load_fpr64(ctx, fp0, fs);
13435 gen_load_fpr64(ctx, fp1, ft);
13436 gen_load_fpr64(ctx, fp2, fr);
13437 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13438 tcg_temp_free_i64(fp0);
13439 tcg_temp_free_i64(fp1);
13440 gen_store_fpr64(ctx, fp2, fd);
13441 tcg_temp_free_i64(fp2);
13443 break;
13444 default:
13445 MIPS_INVAL("flt3_arith");
13446 generate_exception_end(ctx, EXCP_RI);
13447 return;
13451 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13453 TCGv t0;
13455 #if !defined(CONFIG_USER_ONLY)
13457 * The Linux kernel will emulate rdhwr if it's not supported natively.
13458 * Therefore only check the ISA in system mode.
13460 check_insn(ctx, ISA_MIPS32R2);
13461 #endif
13462 t0 = tcg_temp_new();
13464 switch (rd) {
13465 case 0:
13466 gen_helper_rdhwr_cpunum(t0, cpu_env);
13467 gen_store_gpr(t0, rt);
13468 break;
13469 case 1:
13470 gen_helper_rdhwr_synci_step(t0, cpu_env);
13471 gen_store_gpr(t0, rt);
13472 break;
13473 case 2:
13474 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13475 gen_io_start();
13477 gen_helper_rdhwr_cc(t0, cpu_env);
13478 gen_store_gpr(t0, rt);
13480 * Break the TB to be able to take timer interrupts immediately
13481 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13482 * we break completely out of translated code.
13484 gen_save_pc(ctx->base.pc_next + 4);
13485 ctx->base.is_jmp = DISAS_EXIT;
13486 break;
13487 case 3:
13488 gen_helper_rdhwr_ccres(t0, cpu_env);
13489 gen_store_gpr(t0, rt);
13490 break;
13491 case 4:
13492 check_insn(ctx, ISA_MIPS32R6);
13493 if (sel != 0) {
13495 * Performance counter registers are not implemented other than
13496 * control register 0.
13498 generate_exception(ctx, EXCP_RI);
13500 gen_helper_rdhwr_performance(t0, cpu_env);
13501 gen_store_gpr(t0, rt);
13502 break;
13503 case 5:
13504 check_insn(ctx, ISA_MIPS32R6);
13505 gen_helper_rdhwr_xnp(t0, cpu_env);
13506 gen_store_gpr(t0, rt);
13507 break;
13508 case 29:
13509 #if defined(CONFIG_USER_ONLY)
13510 tcg_gen_ld_tl(t0, cpu_env,
13511 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13512 gen_store_gpr(t0, rt);
13513 break;
13514 #else
13515 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13516 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13517 tcg_gen_ld_tl(t0, cpu_env,
13518 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13519 gen_store_gpr(t0, rt);
13520 } else {
13521 generate_exception_end(ctx, EXCP_RI);
13523 break;
13524 #endif
13525 default: /* Invalid */
13526 MIPS_INVAL("rdhwr");
13527 generate_exception_end(ctx, EXCP_RI);
13528 break;
13530 tcg_temp_free(t0);
13533 static inline void clear_branch_hflags(DisasContext *ctx)
13535 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13536 if (ctx->base.is_jmp == DISAS_NEXT) {
13537 save_cpu_state(ctx, 0);
13538 } else {
13540 * It is not safe to save ctx->hflags as hflags may be changed
13541 * in execution time by the instruction in delay / forbidden slot.
13543 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13547 static void gen_branch(DisasContext *ctx, int insn_bytes)
13549 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13550 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13551 /* Branches completion */
13552 clear_branch_hflags(ctx);
13553 ctx->base.is_jmp = DISAS_NORETURN;
13554 /* FIXME: Need to clear can_do_io. */
13555 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13556 case MIPS_HFLAG_FBNSLOT:
13557 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13558 break;
13559 case MIPS_HFLAG_B:
13560 /* unconditional branch */
13561 if (proc_hflags & MIPS_HFLAG_BX) {
13562 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13564 gen_goto_tb(ctx, 0, ctx->btarget);
13565 break;
13566 case MIPS_HFLAG_BL:
13567 /* blikely taken case */
13568 gen_goto_tb(ctx, 0, ctx->btarget);
13569 break;
13570 case MIPS_HFLAG_BC:
13571 /* Conditional branch */
13573 TCGLabel *l1 = gen_new_label();
13575 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13576 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13577 gen_set_label(l1);
13578 gen_goto_tb(ctx, 0, ctx->btarget);
13580 break;
13581 case MIPS_HFLAG_BR:
13582 /* unconditional branch to register */
13583 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13584 TCGv t0 = tcg_temp_new();
13585 TCGv_i32 t1 = tcg_temp_new_i32();
13587 tcg_gen_andi_tl(t0, btarget, 0x1);
13588 tcg_gen_trunc_tl_i32(t1, t0);
13589 tcg_temp_free(t0);
13590 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13591 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13592 tcg_gen_or_i32(hflags, hflags, t1);
13593 tcg_temp_free_i32(t1);
13595 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13596 } else {
13597 tcg_gen_mov_tl(cpu_PC, btarget);
13599 if (ctx->base.singlestep_enabled) {
13600 save_cpu_state(ctx, 0);
13601 gen_helper_raise_exception_debug(cpu_env);
13603 tcg_gen_lookup_and_goto_ptr();
13604 break;
13605 default:
13606 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13607 abort();
13612 /* Compact Branches */
13613 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13614 int rs, int rt, int32_t offset)
13616 int bcond_compute = 0;
13617 TCGv t0 = tcg_temp_new();
13618 TCGv t1 = tcg_temp_new();
13619 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13621 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13622 #ifdef MIPS_DEBUG_DISAS
13623 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13624 "\n", ctx->base.pc_next);
13625 #endif
13626 generate_exception_end(ctx, EXCP_RI);
13627 goto out;
13630 /* Load needed operands and calculate btarget */
13631 switch (opc) {
13632 /* compact branch */
13633 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13634 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13635 gen_load_gpr(t0, rs);
13636 gen_load_gpr(t1, rt);
13637 bcond_compute = 1;
13638 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13639 if (rs <= rt && rs == 0) {
13640 /* OPC_BEQZALC, OPC_BNEZALC */
13641 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13643 break;
13644 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13645 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13646 gen_load_gpr(t0, rs);
13647 gen_load_gpr(t1, rt);
13648 bcond_compute = 1;
13649 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13650 break;
13651 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13652 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13653 if (rs == 0 || rs == rt) {
13654 /* OPC_BLEZALC, OPC_BGEZALC */
13655 /* OPC_BGTZALC, OPC_BLTZALC */
13656 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13658 gen_load_gpr(t0, rs);
13659 gen_load_gpr(t1, rt);
13660 bcond_compute = 1;
13661 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13662 break;
13663 case OPC_BC:
13664 case OPC_BALC:
13665 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13666 break;
13667 case OPC_BEQZC:
13668 case OPC_BNEZC:
13669 if (rs != 0) {
13670 /* OPC_BEQZC, OPC_BNEZC */
13671 gen_load_gpr(t0, rs);
13672 bcond_compute = 1;
13673 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13674 } else {
13675 /* OPC_JIC, OPC_JIALC */
13676 TCGv tbase = tcg_temp_new();
13677 TCGv toffset = tcg_temp_new();
13679 gen_load_gpr(tbase, rt);
13680 tcg_gen_movi_tl(toffset, offset);
13681 gen_op_addr_add(ctx, btarget, tbase, toffset);
13682 tcg_temp_free(tbase);
13683 tcg_temp_free(toffset);
13685 break;
13686 default:
13687 MIPS_INVAL("Compact branch/jump");
13688 generate_exception_end(ctx, EXCP_RI);
13689 goto out;
13692 if (bcond_compute == 0) {
13693 /* Uncoditional compact branch */
13694 switch (opc) {
13695 case OPC_JIALC:
13696 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13697 /* Fallthrough */
13698 case OPC_JIC:
13699 ctx->hflags |= MIPS_HFLAG_BR;
13700 break;
13701 case OPC_BALC:
13702 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13703 /* Fallthrough */
13704 case OPC_BC:
13705 ctx->hflags |= MIPS_HFLAG_B;
13706 break;
13707 default:
13708 MIPS_INVAL("Compact branch/jump");
13709 generate_exception_end(ctx, EXCP_RI);
13710 goto out;
13713 /* Generating branch here as compact branches don't have delay slot */
13714 gen_branch(ctx, 4);
13715 } else {
13716 /* Conditional compact branch */
13717 TCGLabel *fs = gen_new_label();
13718 save_cpu_state(ctx, 0);
13720 switch (opc) {
13721 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13722 if (rs == 0 && rt != 0) {
13723 /* OPC_BLEZALC */
13724 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13725 } else if (rs != 0 && rt != 0 && rs == rt) {
13726 /* OPC_BGEZALC */
13727 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13728 } else {
13729 /* OPC_BGEUC */
13730 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13732 break;
13733 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13734 if (rs == 0 && rt != 0) {
13735 /* OPC_BGTZALC */
13736 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13737 } else if (rs != 0 && rt != 0 && rs == rt) {
13738 /* OPC_BLTZALC */
13739 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13740 } else {
13741 /* OPC_BLTUC */
13742 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13744 break;
13745 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13746 if (rs == 0 && rt != 0) {
13747 /* OPC_BLEZC */
13748 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13749 } else if (rs != 0 && rt != 0 && rs == rt) {
13750 /* OPC_BGEZC */
13751 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13752 } else {
13753 /* OPC_BGEC */
13754 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13756 break;
13757 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13758 if (rs == 0 && rt != 0) {
13759 /* OPC_BGTZC */
13760 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13761 } else if (rs != 0 && rt != 0 && rs == rt) {
13762 /* OPC_BLTZC */
13763 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13764 } else {
13765 /* OPC_BLTC */
13766 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13768 break;
13769 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13770 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13771 if (rs >= rt) {
13772 /* OPC_BOVC, OPC_BNVC */
13773 TCGv t2 = tcg_temp_new();
13774 TCGv t3 = tcg_temp_new();
13775 TCGv t4 = tcg_temp_new();
13776 TCGv input_overflow = tcg_temp_new();
13778 gen_load_gpr(t0, rs);
13779 gen_load_gpr(t1, rt);
13780 tcg_gen_ext32s_tl(t2, t0);
13781 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13782 tcg_gen_ext32s_tl(t3, t1);
13783 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13784 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13786 tcg_gen_add_tl(t4, t2, t3);
13787 tcg_gen_ext32s_tl(t4, t4);
13788 tcg_gen_xor_tl(t2, t2, t3);
13789 tcg_gen_xor_tl(t3, t4, t3);
13790 tcg_gen_andc_tl(t2, t3, t2);
13791 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13792 tcg_gen_or_tl(t4, t4, input_overflow);
13793 if (opc == OPC_BOVC) {
13794 /* OPC_BOVC */
13795 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13796 } else {
13797 /* OPC_BNVC */
13798 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13800 tcg_temp_free(input_overflow);
13801 tcg_temp_free(t4);
13802 tcg_temp_free(t3);
13803 tcg_temp_free(t2);
13804 } else if (rs < rt && rs == 0) {
13805 /* OPC_BEQZALC, OPC_BNEZALC */
13806 if (opc == OPC_BEQZALC) {
13807 /* OPC_BEQZALC */
13808 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13809 } else {
13810 /* OPC_BNEZALC */
13811 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13813 } else {
13814 /* OPC_BEQC, OPC_BNEC */
13815 if (opc == OPC_BEQC) {
13816 /* OPC_BEQC */
13817 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13818 } else {
13819 /* OPC_BNEC */
13820 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13823 break;
13824 case OPC_BEQZC:
13825 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13826 break;
13827 case OPC_BNEZC:
13828 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13829 break;
13830 default:
13831 MIPS_INVAL("Compact conditional branch/jump");
13832 generate_exception_end(ctx, EXCP_RI);
13833 goto out;
13836 /* Generating branch here as compact branches don't have delay slot */
13837 gen_goto_tb(ctx, 1, ctx->btarget);
13838 gen_set_label(fs);
13840 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13843 out:
13844 tcg_temp_free(t0);
13845 tcg_temp_free(t1);
13848 /* ISA extensions (ASEs) */
13849 /* MIPS16 extension to MIPS32 */
13851 /* MIPS16 major opcodes */
13852 enum {
13853 M16_OPC_ADDIUSP = 0x00,
13854 M16_OPC_ADDIUPC = 0x01,
13855 M16_OPC_B = 0x02,
13856 M16_OPC_JAL = 0x03,
13857 M16_OPC_BEQZ = 0x04,
13858 M16_OPC_BNEQZ = 0x05,
13859 M16_OPC_SHIFT = 0x06,
13860 M16_OPC_LD = 0x07,
13861 M16_OPC_RRIA = 0x08,
13862 M16_OPC_ADDIU8 = 0x09,
13863 M16_OPC_SLTI = 0x0a,
13864 M16_OPC_SLTIU = 0x0b,
13865 M16_OPC_I8 = 0x0c,
13866 M16_OPC_LI = 0x0d,
13867 M16_OPC_CMPI = 0x0e,
13868 M16_OPC_SD = 0x0f,
13869 M16_OPC_LB = 0x10,
13870 M16_OPC_LH = 0x11,
13871 M16_OPC_LWSP = 0x12,
13872 M16_OPC_LW = 0x13,
13873 M16_OPC_LBU = 0x14,
13874 M16_OPC_LHU = 0x15,
13875 M16_OPC_LWPC = 0x16,
13876 M16_OPC_LWU = 0x17,
13877 M16_OPC_SB = 0x18,
13878 M16_OPC_SH = 0x19,
13879 M16_OPC_SWSP = 0x1a,
13880 M16_OPC_SW = 0x1b,
13881 M16_OPC_RRR = 0x1c,
13882 M16_OPC_RR = 0x1d,
13883 M16_OPC_EXTEND = 0x1e,
13884 M16_OPC_I64 = 0x1f
13887 /* I8 funct field */
13888 enum {
13889 I8_BTEQZ = 0x0,
13890 I8_BTNEZ = 0x1,
13891 I8_SWRASP = 0x2,
13892 I8_ADJSP = 0x3,
13893 I8_SVRS = 0x4,
13894 I8_MOV32R = 0x5,
13895 I8_MOVR32 = 0x7
13898 /* RRR f field */
13899 enum {
13900 RRR_DADDU = 0x0,
13901 RRR_ADDU = 0x1,
13902 RRR_DSUBU = 0x2,
13903 RRR_SUBU = 0x3
13906 /* RR funct field */
13907 enum {
13908 RR_JR = 0x00,
13909 RR_SDBBP = 0x01,
13910 RR_SLT = 0x02,
13911 RR_SLTU = 0x03,
13912 RR_SLLV = 0x04,
13913 RR_BREAK = 0x05,
13914 RR_SRLV = 0x06,
13915 RR_SRAV = 0x07,
13916 RR_DSRL = 0x08,
13917 RR_CMP = 0x0a,
13918 RR_NEG = 0x0b,
13919 RR_AND = 0x0c,
13920 RR_OR = 0x0d,
13921 RR_XOR = 0x0e,
13922 RR_NOT = 0x0f,
13923 RR_MFHI = 0x10,
13924 RR_CNVT = 0x11,
13925 RR_MFLO = 0x12,
13926 RR_DSRA = 0x13,
13927 RR_DSLLV = 0x14,
13928 RR_DSRLV = 0x16,
13929 RR_DSRAV = 0x17,
13930 RR_MULT = 0x18,
13931 RR_MULTU = 0x19,
13932 RR_DIV = 0x1a,
13933 RR_DIVU = 0x1b,
13934 RR_DMULT = 0x1c,
13935 RR_DMULTU = 0x1d,
13936 RR_DDIV = 0x1e,
13937 RR_DDIVU = 0x1f
13940 /* I64 funct field */
13941 enum {
13942 I64_LDSP = 0x0,
13943 I64_SDSP = 0x1,
13944 I64_SDRASP = 0x2,
13945 I64_DADJSP = 0x3,
13946 I64_LDPC = 0x4,
13947 I64_DADDIU5 = 0x5,
13948 I64_DADDIUPC = 0x6,
13949 I64_DADDIUSP = 0x7
13952 /* RR ry field for CNVT */
13953 enum {
13954 RR_RY_CNVT_ZEB = 0x0,
13955 RR_RY_CNVT_ZEH = 0x1,
13956 RR_RY_CNVT_ZEW = 0x2,
13957 RR_RY_CNVT_SEB = 0x4,
13958 RR_RY_CNVT_SEH = 0x5,
13959 RR_RY_CNVT_SEW = 0x6,
13962 static int xlat(int r)
13964 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13966 return map[r];
13969 static void gen_mips16_save(DisasContext *ctx,
13970 int xsregs, int aregs,
13971 int do_ra, int do_s0, int do_s1,
13972 int framesize)
13974 TCGv t0 = tcg_temp_new();
13975 TCGv t1 = tcg_temp_new();
13976 TCGv t2 = tcg_temp_new();
13977 int args, astatic;
13979 switch (aregs) {
13980 case 0:
13981 case 1:
13982 case 2:
13983 case 3:
13984 case 11:
13985 args = 0;
13986 break;
13987 case 4:
13988 case 5:
13989 case 6:
13990 case 7:
13991 args = 1;
13992 break;
13993 case 8:
13994 case 9:
13995 case 10:
13996 args = 2;
13997 break;
13998 case 12:
13999 case 13:
14000 args = 3;
14001 break;
14002 case 14:
14003 args = 4;
14004 break;
14005 default:
14006 generate_exception_end(ctx, EXCP_RI);
14007 return;
14010 switch (args) {
14011 case 4:
14012 gen_base_offset_addr(ctx, t0, 29, 12);
14013 gen_load_gpr(t1, 7);
14014 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14015 /* Fall through */
14016 case 3:
14017 gen_base_offset_addr(ctx, t0, 29, 8);
14018 gen_load_gpr(t1, 6);
14019 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14020 /* Fall through */
14021 case 2:
14022 gen_base_offset_addr(ctx, t0, 29, 4);
14023 gen_load_gpr(t1, 5);
14024 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14025 /* Fall through */
14026 case 1:
14027 gen_base_offset_addr(ctx, t0, 29, 0);
14028 gen_load_gpr(t1, 4);
14029 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14032 gen_load_gpr(t0, 29);
14034 #define DECR_AND_STORE(reg) do { \
14035 tcg_gen_movi_tl(t2, -4); \
14036 gen_op_addr_add(ctx, t0, t0, t2); \
14037 gen_load_gpr(t1, reg); \
14038 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
14039 } while (0)
14041 if (do_ra) {
14042 DECR_AND_STORE(31);
14045 switch (xsregs) {
14046 case 7:
14047 DECR_AND_STORE(30);
14048 /* Fall through */
14049 case 6:
14050 DECR_AND_STORE(23);
14051 /* Fall through */
14052 case 5:
14053 DECR_AND_STORE(22);
14054 /* Fall through */
14055 case 4:
14056 DECR_AND_STORE(21);
14057 /* Fall through */
14058 case 3:
14059 DECR_AND_STORE(20);
14060 /* Fall through */
14061 case 2:
14062 DECR_AND_STORE(19);
14063 /* Fall through */
14064 case 1:
14065 DECR_AND_STORE(18);
14068 if (do_s1) {
14069 DECR_AND_STORE(17);
14071 if (do_s0) {
14072 DECR_AND_STORE(16);
14075 switch (aregs) {
14076 case 0:
14077 case 4:
14078 case 8:
14079 case 12:
14080 case 14:
14081 astatic = 0;
14082 break;
14083 case 1:
14084 case 5:
14085 case 9:
14086 case 13:
14087 astatic = 1;
14088 break;
14089 case 2:
14090 case 6:
14091 case 10:
14092 astatic = 2;
14093 break;
14094 case 3:
14095 case 7:
14096 astatic = 3;
14097 break;
14098 case 11:
14099 astatic = 4;
14100 break;
14101 default:
14102 generate_exception_end(ctx, EXCP_RI);
14103 return;
14106 if (astatic > 0) {
14107 DECR_AND_STORE(7);
14108 if (astatic > 1) {
14109 DECR_AND_STORE(6);
14110 if (astatic > 2) {
14111 DECR_AND_STORE(5);
14112 if (astatic > 3) {
14113 DECR_AND_STORE(4);
14118 #undef DECR_AND_STORE
14120 tcg_gen_movi_tl(t2, -framesize);
14121 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14122 tcg_temp_free(t0);
14123 tcg_temp_free(t1);
14124 tcg_temp_free(t2);
14127 static void gen_mips16_restore(DisasContext *ctx,
14128 int xsregs, int aregs,
14129 int do_ra, int do_s0, int do_s1,
14130 int framesize)
14132 int astatic;
14133 TCGv t0 = tcg_temp_new();
14134 TCGv t1 = tcg_temp_new();
14135 TCGv t2 = tcg_temp_new();
14137 tcg_gen_movi_tl(t2, framesize);
14138 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
14140 #define DECR_AND_LOAD(reg) do { \
14141 tcg_gen_movi_tl(t2, -4); \
14142 gen_op_addr_add(ctx, t0, t0, t2); \
14143 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
14144 gen_store_gpr(t1, reg); \
14145 } while (0)
14147 if (do_ra) {
14148 DECR_AND_LOAD(31);
14151 switch (xsregs) {
14152 case 7:
14153 DECR_AND_LOAD(30);
14154 /* Fall through */
14155 case 6:
14156 DECR_AND_LOAD(23);
14157 /* Fall through */
14158 case 5:
14159 DECR_AND_LOAD(22);
14160 /* Fall through */
14161 case 4:
14162 DECR_AND_LOAD(21);
14163 /* Fall through */
14164 case 3:
14165 DECR_AND_LOAD(20);
14166 /* Fall through */
14167 case 2:
14168 DECR_AND_LOAD(19);
14169 /* Fall through */
14170 case 1:
14171 DECR_AND_LOAD(18);
14174 if (do_s1) {
14175 DECR_AND_LOAD(17);
14177 if (do_s0) {
14178 DECR_AND_LOAD(16);
14181 switch (aregs) {
14182 case 0:
14183 case 4:
14184 case 8:
14185 case 12:
14186 case 14:
14187 astatic = 0;
14188 break;
14189 case 1:
14190 case 5:
14191 case 9:
14192 case 13:
14193 astatic = 1;
14194 break;
14195 case 2:
14196 case 6:
14197 case 10:
14198 astatic = 2;
14199 break;
14200 case 3:
14201 case 7:
14202 astatic = 3;
14203 break;
14204 case 11:
14205 astatic = 4;
14206 break;
14207 default:
14208 generate_exception_end(ctx, EXCP_RI);
14209 return;
14212 if (astatic > 0) {
14213 DECR_AND_LOAD(7);
14214 if (astatic > 1) {
14215 DECR_AND_LOAD(6);
14216 if (astatic > 2) {
14217 DECR_AND_LOAD(5);
14218 if (astatic > 3) {
14219 DECR_AND_LOAD(4);
14224 #undef DECR_AND_LOAD
14226 tcg_gen_movi_tl(t2, framesize);
14227 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14228 tcg_temp_free(t0);
14229 tcg_temp_free(t1);
14230 tcg_temp_free(t2);
14233 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
14234 int is_64_bit, int extended)
14236 TCGv t0;
14238 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14239 generate_exception_end(ctx, EXCP_RI);
14240 return;
14243 t0 = tcg_temp_new();
14245 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
14246 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
14247 if (!is_64_bit) {
14248 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14251 tcg_temp_free(t0);
14254 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
14255 int16_t offset)
14257 TCGv_i32 t0 = tcg_const_i32(op);
14258 TCGv t1 = tcg_temp_new();
14259 gen_base_offset_addr(ctx, t1, base, offset);
14260 gen_helper_cache(cpu_env, t1, t0);
14263 #if defined(TARGET_MIPS64)
14264 static void decode_i64_mips16(DisasContext *ctx,
14265 int ry, int funct, int16_t offset,
14266 int extended)
14268 switch (funct) {
14269 case I64_LDSP:
14270 check_insn(ctx, ISA_MIPS3);
14271 check_mips_64(ctx);
14272 offset = extended ? offset : offset << 3;
14273 gen_ld(ctx, OPC_LD, ry, 29, offset);
14274 break;
14275 case I64_SDSP:
14276 check_insn(ctx, ISA_MIPS3);
14277 check_mips_64(ctx);
14278 offset = extended ? offset : offset << 3;
14279 gen_st(ctx, OPC_SD, ry, 29, offset);
14280 break;
14281 case I64_SDRASP:
14282 check_insn(ctx, ISA_MIPS3);
14283 check_mips_64(ctx);
14284 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
14285 gen_st(ctx, OPC_SD, 31, 29, offset);
14286 break;
14287 case I64_DADJSP:
14288 check_insn(ctx, ISA_MIPS3);
14289 check_mips_64(ctx);
14290 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
14291 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
14292 break;
14293 case I64_LDPC:
14294 check_insn(ctx, ISA_MIPS3);
14295 check_mips_64(ctx);
14296 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14297 generate_exception_end(ctx, EXCP_RI);
14298 } else {
14299 offset = extended ? offset : offset << 3;
14300 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
14302 break;
14303 case I64_DADDIU5:
14304 check_insn(ctx, ISA_MIPS3);
14305 check_mips_64(ctx);
14306 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
14307 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
14308 break;
14309 case I64_DADDIUPC:
14310 check_insn(ctx, ISA_MIPS3);
14311 check_mips_64(ctx);
14312 offset = extended ? offset : offset << 2;
14313 gen_addiupc(ctx, ry, offset, 1, extended);
14314 break;
14315 case I64_DADDIUSP:
14316 check_insn(ctx, ISA_MIPS3);
14317 check_mips_64(ctx);
14318 offset = extended ? offset : offset << 2;
14319 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
14320 break;
14323 #endif
14325 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14327 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
14328 int op, rx, ry, funct, sa;
14329 int16_t imm, offset;
14331 ctx->opcode = (ctx->opcode << 16) | extend;
14332 op = (ctx->opcode >> 11) & 0x1f;
14333 sa = (ctx->opcode >> 22) & 0x1f;
14334 funct = (ctx->opcode >> 8) & 0x7;
14335 rx = xlat((ctx->opcode >> 8) & 0x7);
14336 ry = xlat((ctx->opcode >> 5) & 0x7);
14337 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
14338 | ((ctx->opcode >> 21) & 0x3f) << 5
14339 | (ctx->opcode & 0x1f));
14342 * The extended opcodes cleverly reuse the opcodes from their 16-bit
14343 * counterparts.
14345 switch (op) {
14346 case M16_OPC_ADDIUSP:
14347 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14348 break;
14349 case M16_OPC_ADDIUPC:
14350 gen_addiupc(ctx, rx, imm, 0, 1);
14351 break;
14352 case M16_OPC_B:
14353 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
14354 /* No delay slot, so just process as a normal instruction */
14355 break;
14356 case M16_OPC_BEQZ:
14357 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
14358 /* No delay slot, so just process as a normal instruction */
14359 break;
14360 case M16_OPC_BNEQZ:
14361 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
14362 /* No delay slot, so just process as a normal instruction */
14363 break;
14364 case M16_OPC_SHIFT:
14365 switch (ctx->opcode & 0x3) {
14366 case 0x0:
14367 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14368 break;
14369 case 0x1:
14370 #if defined(TARGET_MIPS64)
14371 check_mips_64(ctx);
14372 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14373 #else
14374 generate_exception_end(ctx, EXCP_RI);
14375 #endif
14376 break;
14377 case 0x2:
14378 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14379 break;
14380 case 0x3:
14381 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14382 break;
14384 break;
14385 #if defined(TARGET_MIPS64)
14386 case M16_OPC_LD:
14387 check_insn(ctx, ISA_MIPS3);
14388 check_mips_64(ctx);
14389 gen_ld(ctx, OPC_LD, ry, rx, offset);
14390 break;
14391 #endif
14392 case M16_OPC_RRIA:
14393 imm = ctx->opcode & 0xf;
14394 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
14395 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
14396 imm = (int16_t) (imm << 1) >> 1;
14397 if ((ctx->opcode >> 4) & 0x1) {
14398 #if defined(TARGET_MIPS64)
14399 check_mips_64(ctx);
14400 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14401 #else
14402 generate_exception_end(ctx, EXCP_RI);
14403 #endif
14404 } else {
14405 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14407 break;
14408 case M16_OPC_ADDIU8:
14409 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14410 break;
14411 case M16_OPC_SLTI:
14412 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14413 break;
14414 case M16_OPC_SLTIU:
14415 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14416 break;
14417 case M16_OPC_I8:
14418 switch (funct) {
14419 case I8_BTEQZ:
14420 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14421 break;
14422 case I8_BTNEZ:
14423 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14424 break;
14425 case I8_SWRASP:
14426 gen_st(ctx, OPC_SW, 31, 29, imm);
14427 break;
14428 case I8_ADJSP:
14429 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14430 break;
14431 case I8_SVRS:
14432 check_insn(ctx, ISA_MIPS32);
14434 int xsregs = (ctx->opcode >> 24) & 0x7;
14435 int aregs = (ctx->opcode >> 16) & 0xf;
14436 int do_ra = (ctx->opcode >> 6) & 0x1;
14437 int do_s0 = (ctx->opcode >> 5) & 0x1;
14438 int do_s1 = (ctx->opcode >> 4) & 0x1;
14439 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14440 | (ctx->opcode & 0xf)) << 3;
14442 if (ctx->opcode & (1 << 7)) {
14443 gen_mips16_save(ctx, xsregs, aregs,
14444 do_ra, do_s0, do_s1,
14445 framesize);
14446 } else {
14447 gen_mips16_restore(ctx, xsregs, aregs,
14448 do_ra, do_s0, do_s1,
14449 framesize);
14452 break;
14453 default:
14454 generate_exception_end(ctx, EXCP_RI);
14455 break;
14457 break;
14458 case M16_OPC_LI:
14459 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14460 break;
14461 case M16_OPC_CMPI:
14462 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14463 break;
14464 #if defined(TARGET_MIPS64)
14465 case M16_OPC_SD:
14466 check_insn(ctx, ISA_MIPS3);
14467 check_mips_64(ctx);
14468 gen_st(ctx, OPC_SD, ry, rx, offset);
14469 break;
14470 #endif
14471 case M16_OPC_LB:
14472 gen_ld(ctx, OPC_LB, ry, rx, offset);
14473 break;
14474 case M16_OPC_LH:
14475 gen_ld(ctx, OPC_LH, ry, rx, offset);
14476 break;
14477 case M16_OPC_LWSP:
14478 gen_ld(ctx, OPC_LW, rx, 29, offset);
14479 break;
14480 case M16_OPC_LW:
14481 gen_ld(ctx, OPC_LW, ry, rx, offset);
14482 break;
14483 case M16_OPC_LBU:
14484 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14485 break;
14486 case M16_OPC_LHU:
14487 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14488 break;
14489 case M16_OPC_LWPC:
14490 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14491 break;
14492 #if defined(TARGET_MIPS64)
14493 case M16_OPC_LWU:
14494 check_insn(ctx, ISA_MIPS3);
14495 check_mips_64(ctx);
14496 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14497 break;
14498 #endif
14499 case M16_OPC_SB:
14500 gen_st(ctx, OPC_SB, ry, rx, offset);
14501 break;
14502 case M16_OPC_SH:
14503 gen_st(ctx, OPC_SH, ry, rx, offset);
14504 break;
14505 case M16_OPC_SWSP:
14506 gen_st(ctx, OPC_SW, rx, 29, offset);
14507 break;
14508 case M16_OPC_SW:
14509 gen_st(ctx, OPC_SW, ry, rx, offset);
14510 break;
14511 #if defined(TARGET_MIPS64)
14512 case M16_OPC_I64:
14513 decode_i64_mips16(ctx, ry, funct, offset, 1);
14514 break;
14515 #endif
14516 default:
14517 generate_exception_end(ctx, EXCP_RI);
14518 break;
14521 return 4;
14524 static inline bool is_uhi(int sdbbp_code)
14526 #ifdef CONFIG_USER_ONLY
14527 return false;
14528 #else
14529 return semihosting_enabled() && sdbbp_code == 1;
14530 #endif
14533 #ifdef CONFIG_USER_ONLY
14534 /* The above should dead-code away any calls to this..*/
14535 static inline void gen_helper_do_semihosting(void *env)
14537 g_assert_not_reached();
14539 #endif
14541 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14543 int rx, ry;
14544 int sa;
14545 int op, cnvt_op, op1, offset;
14546 int funct;
14547 int n_bytes;
14549 op = (ctx->opcode >> 11) & 0x1f;
14550 sa = (ctx->opcode >> 2) & 0x7;
14551 sa = sa == 0 ? 8 : sa;
14552 rx = xlat((ctx->opcode >> 8) & 0x7);
14553 cnvt_op = (ctx->opcode >> 5) & 0x7;
14554 ry = xlat((ctx->opcode >> 5) & 0x7);
14555 op1 = offset = ctx->opcode & 0x1f;
14557 n_bytes = 2;
14559 switch (op) {
14560 case M16_OPC_ADDIUSP:
14562 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14564 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14566 break;
14567 case M16_OPC_ADDIUPC:
14568 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14569 break;
14570 case M16_OPC_B:
14571 offset = (ctx->opcode & 0x7ff) << 1;
14572 offset = (int16_t)(offset << 4) >> 4;
14573 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14574 /* No delay slot, so just process as a normal instruction */
14575 break;
14576 case M16_OPC_JAL:
14577 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14578 offset = (((ctx->opcode & 0x1f) << 21)
14579 | ((ctx->opcode >> 5) & 0x1f) << 16
14580 | offset) << 2;
14581 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14582 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14583 n_bytes = 4;
14584 break;
14585 case M16_OPC_BEQZ:
14586 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14587 ((int8_t)ctx->opcode) << 1, 0);
14588 /* No delay slot, so just process as a normal instruction */
14589 break;
14590 case M16_OPC_BNEQZ:
14591 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14592 ((int8_t)ctx->opcode) << 1, 0);
14593 /* No delay slot, so just process as a normal instruction */
14594 break;
14595 case M16_OPC_SHIFT:
14596 switch (ctx->opcode & 0x3) {
14597 case 0x0:
14598 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14599 break;
14600 case 0x1:
14601 #if defined(TARGET_MIPS64)
14602 check_insn(ctx, ISA_MIPS3);
14603 check_mips_64(ctx);
14604 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14605 #else
14606 generate_exception_end(ctx, EXCP_RI);
14607 #endif
14608 break;
14609 case 0x2:
14610 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14611 break;
14612 case 0x3:
14613 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14614 break;
14616 break;
14617 #if defined(TARGET_MIPS64)
14618 case M16_OPC_LD:
14619 check_insn(ctx, ISA_MIPS3);
14620 check_mips_64(ctx);
14621 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14622 break;
14623 #endif
14624 case M16_OPC_RRIA:
14626 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14628 if ((ctx->opcode >> 4) & 1) {
14629 #if defined(TARGET_MIPS64)
14630 check_insn(ctx, ISA_MIPS3);
14631 check_mips_64(ctx);
14632 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14633 #else
14634 generate_exception_end(ctx, EXCP_RI);
14635 #endif
14636 } else {
14637 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14640 break;
14641 case M16_OPC_ADDIU8:
14643 int16_t imm = (int8_t) ctx->opcode;
14645 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14647 break;
14648 case M16_OPC_SLTI:
14650 int16_t imm = (uint8_t) ctx->opcode;
14651 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14653 break;
14654 case M16_OPC_SLTIU:
14656 int16_t imm = (uint8_t) ctx->opcode;
14657 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14659 break;
14660 case M16_OPC_I8:
14662 int reg32;
14664 funct = (ctx->opcode >> 8) & 0x7;
14665 switch (funct) {
14666 case I8_BTEQZ:
14667 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14668 ((int8_t)ctx->opcode) << 1, 0);
14669 break;
14670 case I8_BTNEZ:
14671 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14672 ((int8_t)ctx->opcode) << 1, 0);
14673 break;
14674 case I8_SWRASP:
14675 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14676 break;
14677 case I8_ADJSP:
14678 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14679 ((int8_t)ctx->opcode) << 3);
14680 break;
14681 case I8_SVRS:
14682 check_insn(ctx, ISA_MIPS32);
14684 int do_ra = ctx->opcode & (1 << 6);
14685 int do_s0 = ctx->opcode & (1 << 5);
14686 int do_s1 = ctx->opcode & (1 << 4);
14687 int framesize = ctx->opcode & 0xf;
14689 if (framesize == 0) {
14690 framesize = 128;
14691 } else {
14692 framesize = framesize << 3;
14695 if (ctx->opcode & (1 << 7)) {
14696 gen_mips16_save(ctx, 0, 0,
14697 do_ra, do_s0, do_s1, framesize);
14698 } else {
14699 gen_mips16_restore(ctx, 0, 0,
14700 do_ra, do_s0, do_s1, framesize);
14703 break;
14704 case I8_MOV32R:
14706 int rz = xlat(ctx->opcode & 0x7);
14708 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14709 ((ctx->opcode >> 5) & 0x7);
14710 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14712 break;
14713 case I8_MOVR32:
14714 reg32 = ctx->opcode & 0x1f;
14715 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14716 break;
14717 default:
14718 generate_exception_end(ctx, EXCP_RI);
14719 break;
14722 break;
14723 case M16_OPC_LI:
14725 int16_t imm = (uint8_t) ctx->opcode;
14727 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14729 break;
14730 case M16_OPC_CMPI:
14732 int16_t imm = (uint8_t) ctx->opcode;
14733 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14735 break;
14736 #if defined(TARGET_MIPS64)
14737 case M16_OPC_SD:
14738 check_insn(ctx, ISA_MIPS3);
14739 check_mips_64(ctx);
14740 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14741 break;
14742 #endif
14743 case M16_OPC_LB:
14744 gen_ld(ctx, OPC_LB, ry, rx, offset);
14745 break;
14746 case M16_OPC_LH:
14747 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14748 break;
14749 case M16_OPC_LWSP:
14750 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14751 break;
14752 case M16_OPC_LW:
14753 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14754 break;
14755 case M16_OPC_LBU:
14756 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14757 break;
14758 case M16_OPC_LHU:
14759 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14760 break;
14761 case M16_OPC_LWPC:
14762 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14763 break;
14764 #if defined(TARGET_MIPS64)
14765 case M16_OPC_LWU:
14766 check_insn(ctx, ISA_MIPS3);
14767 check_mips_64(ctx);
14768 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14769 break;
14770 #endif
14771 case M16_OPC_SB:
14772 gen_st(ctx, OPC_SB, ry, rx, offset);
14773 break;
14774 case M16_OPC_SH:
14775 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14776 break;
14777 case M16_OPC_SWSP:
14778 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14779 break;
14780 case M16_OPC_SW:
14781 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14782 break;
14783 case M16_OPC_RRR:
14785 int rz = xlat((ctx->opcode >> 2) & 0x7);
14786 int mips32_op;
14788 switch (ctx->opcode & 0x3) {
14789 case RRR_ADDU:
14790 mips32_op = OPC_ADDU;
14791 break;
14792 case RRR_SUBU:
14793 mips32_op = OPC_SUBU;
14794 break;
14795 #if defined(TARGET_MIPS64)
14796 case RRR_DADDU:
14797 mips32_op = OPC_DADDU;
14798 check_insn(ctx, ISA_MIPS3);
14799 check_mips_64(ctx);
14800 break;
14801 case RRR_DSUBU:
14802 mips32_op = OPC_DSUBU;
14803 check_insn(ctx, ISA_MIPS3);
14804 check_mips_64(ctx);
14805 break;
14806 #endif
14807 default:
14808 generate_exception_end(ctx, EXCP_RI);
14809 goto done;
14812 gen_arith(ctx, mips32_op, rz, rx, ry);
14813 done:
14816 break;
14817 case M16_OPC_RR:
14818 switch (op1) {
14819 case RR_JR:
14821 int nd = (ctx->opcode >> 7) & 0x1;
14822 int link = (ctx->opcode >> 6) & 0x1;
14823 int ra = (ctx->opcode >> 5) & 0x1;
14825 if (nd) {
14826 check_insn(ctx, ISA_MIPS32);
14829 if (link) {
14830 op = OPC_JALR;
14831 } else {
14832 op = OPC_JR;
14835 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14836 (nd ? 0 : 2));
14838 break;
14839 case RR_SDBBP:
14840 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14841 gen_helper_do_semihosting(cpu_env);
14842 } else {
14844 * XXX: not clear which exception should be raised
14845 * when in debug mode...
14847 check_insn(ctx, ISA_MIPS32);
14848 generate_exception_end(ctx, EXCP_DBp);
14850 break;
14851 case RR_SLT:
14852 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14853 break;
14854 case RR_SLTU:
14855 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14856 break;
14857 case RR_BREAK:
14858 generate_exception_end(ctx, EXCP_BREAK);
14859 break;
14860 case RR_SLLV:
14861 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14862 break;
14863 case RR_SRLV:
14864 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14865 break;
14866 case RR_SRAV:
14867 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14868 break;
14869 #if defined(TARGET_MIPS64)
14870 case RR_DSRL:
14871 check_insn(ctx, ISA_MIPS3);
14872 check_mips_64(ctx);
14873 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14874 break;
14875 #endif
14876 case RR_CMP:
14877 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14878 break;
14879 case RR_NEG:
14880 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14881 break;
14882 case RR_AND:
14883 gen_logic(ctx, OPC_AND, rx, rx, ry);
14884 break;
14885 case RR_OR:
14886 gen_logic(ctx, OPC_OR, rx, rx, ry);
14887 break;
14888 case RR_XOR:
14889 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14890 break;
14891 case RR_NOT:
14892 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14893 break;
14894 case RR_MFHI:
14895 gen_HILO(ctx, OPC_MFHI, 0, rx);
14896 break;
14897 case RR_CNVT:
14898 check_insn(ctx, ISA_MIPS32);
14899 switch (cnvt_op) {
14900 case RR_RY_CNVT_ZEB:
14901 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14902 break;
14903 case RR_RY_CNVT_ZEH:
14904 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14905 break;
14906 case RR_RY_CNVT_SEB:
14907 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14908 break;
14909 case RR_RY_CNVT_SEH:
14910 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14911 break;
14912 #if defined(TARGET_MIPS64)
14913 case RR_RY_CNVT_ZEW:
14914 check_insn(ctx, ISA_MIPS64);
14915 check_mips_64(ctx);
14916 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14917 break;
14918 case RR_RY_CNVT_SEW:
14919 check_insn(ctx, ISA_MIPS64);
14920 check_mips_64(ctx);
14921 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14922 break;
14923 #endif
14924 default:
14925 generate_exception_end(ctx, EXCP_RI);
14926 break;
14928 break;
14929 case RR_MFLO:
14930 gen_HILO(ctx, OPC_MFLO, 0, rx);
14931 break;
14932 #if defined(TARGET_MIPS64)
14933 case RR_DSRA:
14934 check_insn(ctx, ISA_MIPS3);
14935 check_mips_64(ctx);
14936 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14937 break;
14938 case RR_DSLLV:
14939 check_insn(ctx, ISA_MIPS3);
14940 check_mips_64(ctx);
14941 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14942 break;
14943 case RR_DSRLV:
14944 check_insn(ctx, ISA_MIPS3);
14945 check_mips_64(ctx);
14946 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14947 break;
14948 case RR_DSRAV:
14949 check_insn(ctx, ISA_MIPS3);
14950 check_mips_64(ctx);
14951 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14952 break;
14953 #endif
14954 case RR_MULT:
14955 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14956 break;
14957 case RR_MULTU:
14958 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14959 break;
14960 case RR_DIV:
14961 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14962 break;
14963 case RR_DIVU:
14964 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14965 break;
14966 #if defined(TARGET_MIPS64)
14967 case RR_DMULT:
14968 check_insn(ctx, ISA_MIPS3);
14969 check_mips_64(ctx);
14970 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14971 break;
14972 case RR_DMULTU:
14973 check_insn(ctx, ISA_MIPS3);
14974 check_mips_64(ctx);
14975 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14976 break;
14977 case RR_DDIV:
14978 check_insn(ctx, ISA_MIPS3);
14979 check_mips_64(ctx);
14980 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14981 break;
14982 case RR_DDIVU:
14983 check_insn(ctx, ISA_MIPS3);
14984 check_mips_64(ctx);
14985 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14986 break;
14987 #endif
14988 default:
14989 generate_exception_end(ctx, EXCP_RI);
14990 break;
14992 break;
14993 case M16_OPC_EXTEND:
14994 decode_extended_mips16_opc(env, ctx);
14995 n_bytes = 4;
14996 break;
14997 #if defined(TARGET_MIPS64)
14998 case M16_OPC_I64:
14999 funct = (ctx->opcode >> 8) & 0x7;
15000 decode_i64_mips16(ctx, ry, funct, offset, 0);
15001 break;
15002 #endif
15003 default:
15004 generate_exception_end(ctx, EXCP_RI);
15005 break;
15008 return n_bytes;
15011 /* microMIPS extension to MIPS32/MIPS64 */
15014 * microMIPS32/microMIPS64 major opcodes
15016 * 1. MIPS Architecture for Programmers Volume II-B:
15017 * The microMIPS32 Instruction Set (Revision 3.05)
15019 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
15021 * 2. MIPS Architecture For Programmers Volume II-A:
15022 * The MIPS64 Instruction Set (Revision 3.51)
15025 enum {
15026 POOL32A = 0x00,
15027 POOL16A = 0x01,
15028 LBU16 = 0x02,
15029 MOVE16 = 0x03,
15030 ADDI32 = 0x04,
15031 R6_LUI = 0x04,
15032 AUI = 0x04,
15033 LBU32 = 0x05,
15034 SB32 = 0x06,
15035 LB32 = 0x07,
15037 POOL32B = 0x08,
15038 POOL16B = 0x09,
15039 LHU16 = 0x0a,
15040 ANDI16 = 0x0b,
15041 ADDIU32 = 0x0c,
15042 LHU32 = 0x0d,
15043 SH32 = 0x0e,
15044 LH32 = 0x0f,
15046 POOL32I = 0x10,
15047 POOL16C = 0x11,
15048 LWSP16 = 0x12,
15049 POOL16D = 0x13,
15050 ORI32 = 0x14,
15051 POOL32F = 0x15,
15052 POOL32S = 0x16, /* MIPS64 */
15053 DADDIU32 = 0x17, /* MIPS64 */
15055 POOL32C = 0x18,
15056 LWGP16 = 0x19,
15057 LW16 = 0x1a,
15058 POOL16E = 0x1b,
15059 XORI32 = 0x1c,
15060 JALS32 = 0x1d,
15061 BOVC = 0x1d,
15062 BEQC = 0x1d,
15063 BEQZALC = 0x1d,
15064 ADDIUPC = 0x1e,
15065 PCREL = 0x1e,
15066 BNVC = 0x1f,
15067 BNEC = 0x1f,
15068 BNEZALC = 0x1f,
15070 R6_BEQZC = 0x20,
15071 JIC = 0x20,
15072 POOL16F = 0x21,
15073 SB16 = 0x22,
15074 BEQZ16 = 0x23,
15075 BEQZC16 = 0x23,
15076 SLTI32 = 0x24,
15077 BEQ32 = 0x25,
15078 BC = 0x25,
15079 SWC132 = 0x26,
15080 LWC132 = 0x27,
15082 /* 0x29 is reserved */
15083 RES_29 = 0x29,
15084 R6_BNEZC = 0x28,
15085 JIALC = 0x28,
15086 SH16 = 0x2a,
15087 BNEZ16 = 0x2b,
15088 BNEZC16 = 0x2b,
15089 SLTIU32 = 0x2c,
15090 BNE32 = 0x2d,
15091 BALC = 0x2d,
15092 SDC132 = 0x2e,
15093 LDC132 = 0x2f,
15095 /* 0x31 is reserved */
15096 RES_31 = 0x31,
15097 BLEZALC = 0x30,
15098 BGEZALC = 0x30,
15099 BGEUC = 0x30,
15100 SWSP16 = 0x32,
15101 B16 = 0x33,
15102 BC16 = 0x33,
15103 ANDI32 = 0x34,
15104 J32 = 0x35,
15105 BGTZC = 0x35,
15106 BLTZC = 0x35,
15107 BLTC = 0x35,
15108 SD32 = 0x36, /* MIPS64 */
15109 LD32 = 0x37, /* MIPS64 */
15111 /* 0x39 is reserved */
15112 RES_39 = 0x39,
15113 BGTZALC = 0x38,
15114 BLTZALC = 0x38,
15115 BLTUC = 0x38,
15116 SW16 = 0x3a,
15117 LI16 = 0x3b,
15118 JALX32 = 0x3c,
15119 JAL32 = 0x3d,
15120 BLEZC = 0x3d,
15121 BGEZC = 0x3d,
15122 BGEC = 0x3d,
15123 SW32 = 0x3e,
15124 LW32 = 0x3f
15127 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
15128 enum {
15129 ADDIUPC_00 = 0x00,
15130 ADDIUPC_01 = 0x01,
15131 ADDIUPC_02 = 0x02,
15132 ADDIUPC_03 = 0x03,
15133 ADDIUPC_04 = 0x04,
15134 ADDIUPC_05 = 0x05,
15135 ADDIUPC_06 = 0x06,
15136 ADDIUPC_07 = 0x07,
15137 AUIPC = 0x1e,
15138 ALUIPC = 0x1f,
15139 LWPC_08 = 0x08,
15140 LWPC_09 = 0x09,
15141 LWPC_0A = 0x0A,
15142 LWPC_0B = 0x0B,
15143 LWPC_0C = 0x0C,
15144 LWPC_0D = 0x0D,
15145 LWPC_0E = 0x0E,
15146 LWPC_0F = 0x0F,
15149 /* POOL32A encoding of minor opcode field */
15151 enum {
15153 * These opcodes are distinguished only by bits 9..6; those bits are
15154 * what are recorded below.
15156 SLL32 = 0x0,
15157 SRL32 = 0x1,
15158 SRA = 0x2,
15159 ROTR = 0x3,
15160 SELEQZ = 0x5,
15161 SELNEZ = 0x6,
15162 R6_RDHWR = 0x7,
15164 SLLV = 0x0,
15165 SRLV = 0x1,
15166 SRAV = 0x2,
15167 ROTRV = 0x3,
15168 ADD = 0x4,
15169 ADDU32 = 0x5,
15170 SUB = 0x6,
15171 SUBU32 = 0x7,
15172 MUL = 0x8,
15173 AND = 0x9,
15174 OR32 = 0xa,
15175 NOR = 0xb,
15176 XOR32 = 0xc,
15177 SLT = 0xd,
15178 SLTU = 0xe,
15180 MOVN = 0x0,
15181 R6_MUL = 0x0,
15182 MOVZ = 0x1,
15183 MUH = 0x1,
15184 MULU = 0x2,
15185 MUHU = 0x3,
15186 LWXS = 0x4,
15187 R6_DIV = 0x4,
15188 MOD = 0x5,
15189 R6_DIVU = 0x6,
15190 MODU = 0x7,
15192 /* The following can be distinguished by their lower 6 bits. */
15193 BREAK32 = 0x07,
15194 INS = 0x0c,
15195 LSA = 0x0f,
15196 ALIGN = 0x1f,
15197 EXT = 0x2c,
15198 POOL32AXF = 0x3c,
15199 SIGRIE = 0x3f
15202 /* POOL32AXF encoding of minor opcode field extension */
15205 * 1. MIPS Architecture for Programmers Volume II-B:
15206 * The microMIPS32 Instruction Set (Revision 3.05)
15208 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
15210 * 2. MIPS Architecture for Programmers VolumeIV-e:
15211 * The MIPS DSP Application-Specific Extension
15212 * to the microMIPS32 Architecture (Revision 2.34)
15214 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
15217 enum {
15218 /* bits 11..6 */
15219 TEQ = 0x00,
15220 TGE = 0x08,
15221 TGEU = 0x10,
15222 TLT = 0x20,
15223 TLTU = 0x28,
15224 TNE = 0x30,
15226 MFC0 = 0x03,
15227 MTC0 = 0x0b,
15229 /* begin of microMIPS32 DSP */
15231 /* bits 13..12 for 0x01 */
15232 MFHI_ACC = 0x0,
15233 MFLO_ACC = 0x1,
15234 MTHI_ACC = 0x2,
15235 MTLO_ACC = 0x3,
15237 /* bits 13..12 for 0x2a */
15238 MADD_ACC = 0x0,
15239 MADDU_ACC = 0x1,
15240 MSUB_ACC = 0x2,
15241 MSUBU_ACC = 0x3,
15243 /* bits 13..12 for 0x32 */
15244 MULT_ACC = 0x0,
15245 MULTU_ACC = 0x1,
15247 /* end of microMIPS32 DSP */
15249 /* bits 15..12 for 0x2c */
15250 BITSWAP = 0x0,
15251 SEB = 0x2,
15252 SEH = 0x3,
15253 CLO = 0x4,
15254 CLZ = 0x5,
15255 RDHWR = 0x6,
15256 WSBH = 0x7,
15257 MULT = 0x8,
15258 MULTU = 0x9,
15259 DIV = 0xa,
15260 DIVU = 0xb,
15261 MADD = 0xc,
15262 MADDU = 0xd,
15263 MSUB = 0xe,
15264 MSUBU = 0xf,
15266 /* bits 15..12 for 0x34 */
15267 MFC2 = 0x4,
15268 MTC2 = 0x5,
15269 MFHC2 = 0x8,
15270 MTHC2 = 0x9,
15271 CFC2 = 0xc,
15272 CTC2 = 0xd,
15274 /* bits 15..12 for 0x3c */
15275 JALR = 0x0,
15276 JR = 0x0, /* alias */
15277 JALRC = 0x0,
15278 JRC = 0x0,
15279 JALR_HB = 0x1,
15280 JALRC_HB = 0x1,
15281 JALRS = 0x4,
15282 JALRS_HB = 0x5,
15284 /* bits 15..12 for 0x05 */
15285 RDPGPR = 0xe,
15286 WRPGPR = 0xf,
15288 /* bits 15..12 for 0x0d */
15289 TLBP = 0x0,
15290 TLBR = 0x1,
15291 TLBWI = 0x2,
15292 TLBWR = 0x3,
15293 TLBINV = 0x4,
15294 TLBINVF = 0x5,
15295 WAIT = 0x9,
15296 IRET = 0xd,
15297 DERET = 0xe,
15298 ERET = 0xf,
15300 /* bits 15..12 for 0x15 */
15301 DMT = 0x0,
15302 DVPE = 0x1,
15303 EMT = 0x2,
15304 EVPE = 0x3,
15306 /* bits 15..12 for 0x1d */
15307 DI = 0x4,
15308 EI = 0x5,
15310 /* bits 15..12 for 0x2d */
15311 SYNC = 0x6,
15312 SYSCALL = 0x8,
15313 SDBBP = 0xd,
15315 /* bits 15..12 for 0x35 */
15316 MFHI32 = 0x0,
15317 MFLO32 = 0x1,
15318 MTHI32 = 0x2,
15319 MTLO32 = 0x3,
15322 /* POOL32B encoding of minor opcode field (bits 15..12) */
15324 enum {
15325 LWC2 = 0x0,
15326 LWP = 0x1,
15327 LDP = 0x4,
15328 LWM32 = 0x5,
15329 CACHE = 0x6,
15330 LDM = 0x7,
15331 SWC2 = 0x8,
15332 SWP = 0x9,
15333 SDP = 0xc,
15334 SWM32 = 0xd,
15335 SDM = 0xf
15338 /* POOL32C encoding of minor opcode field (bits 15..12) */
15340 enum {
15341 LWL = 0x0,
15342 SWL = 0x8,
15343 LWR = 0x1,
15344 SWR = 0x9,
15345 PREF = 0x2,
15346 ST_EVA = 0xa,
15347 LL = 0x3,
15348 SC = 0xb,
15349 LDL = 0x4,
15350 SDL = 0xc,
15351 LDR = 0x5,
15352 SDR = 0xd,
15353 LD_EVA = 0x6,
15354 LWU = 0xe,
15355 LLD = 0x7,
15356 SCD = 0xf
15359 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
15361 enum {
15362 LBUE = 0x0,
15363 LHUE = 0x1,
15364 LWLE = 0x2,
15365 LWRE = 0x3,
15366 LBE = 0x4,
15367 LHE = 0x5,
15368 LLE = 0x6,
15369 LWE = 0x7,
15372 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
15374 enum {
15375 SWLE = 0x0,
15376 SWRE = 0x1,
15377 PREFE = 0x2,
15378 CACHEE = 0x3,
15379 SBE = 0x4,
15380 SHE = 0x5,
15381 SCE = 0x6,
15382 SWE = 0x7,
15385 /* POOL32F encoding of minor opcode field (bits 5..0) */
15387 enum {
15388 /* These are the bit 7..6 values */
15389 ADD_FMT = 0x0,
15391 SUB_FMT = 0x1,
15393 MUL_FMT = 0x2,
15395 DIV_FMT = 0x3,
15397 /* These are the bit 8..6 values */
15398 MOVN_FMT = 0x0,
15399 RSQRT2_FMT = 0x0,
15400 MOVF_FMT = 0x0,
15401 RINT_FMT = 0x0,
15402 SELNEZ_FMT = 0x0,
15404 MOVZ_FMT = 0x1,
15405 LWXC1 = 0x1,
15406 MOVT_FMT = 0x1,
15407 CLASS_FMT = 0x1,
15408 SELEQZ_FMT = 0x1,
15410 PLL_PS = 0x2,
15411 SWXC1 = 0x2,
15412 SEL_FMT = 0x2,
15414 PLU_PS = 0x3,
15415 LDXC1 = 0x3,
15417 MOVN_FMT_04 = 0x4,
15418 PUL_PS = 0x4,
15419 SDXC1 = 0x4,
15420 RECIP2_FMT = 0x4,
15422 MOVZ_FMT_05 = 0x05,
15423 PUU_PS = 0x5,
15424 LUXC1 = 0x5,
15426 CVT_PS_S = 0x6,
15427 SUXC1 = 0x6,
15428 ADDR_PS = 0x6,
15429 PREFX = 0x6,
15430 MADDF_FMT = 0x6,
15432 MULR_PS = 0x7,
15433 MSUBF_FMT = 0x7,
15435 MADD_S = 0x01,
15436 MADD_D = 0x09,
15437 MADD_PS = 0x11,
15438 ALNV_PS = 0x19,
15439 MSUB_S = 0x21,
15440 MSUB_D = 0x29,
15441 MSUB_PS = 0x31,
15443 NMADD_S = 0x02,
15444 NMADD_D = 0x0a,
15445 NMADD_PS = 0x12,
15446 NMSUB_S = 0x22,
15447 NMSUB_D = 0x2a,
15448 NMSUB_PS = 0x32,
15450 MIN_FMT = 0x3,
15451 MAX_FMT = 0xb,
15452 MINA_FMT = 0x23,
15453 MAXA_FMT = 0x2b,
15454 POOL32FXF = 0x3b,
15456 CABS_COND_FMT = 0x1c, /* MIPS3D */
15457 C_COND_FMT = 0x3c,
15459 CMP_CONDN_S = 0x5,
15460 CMP_CONDN_D = 0x15
15463 /* POOL32Fxf encoding of minor opcode extension field */
15465 enum {
15466 CVT_L = 0x04,
15467 RSQRT_FMT = 0x08,
15468 FLOOR_L = 0x0c,
15469 CVT_PW_PS = 0x1c,
15470 CVT_W = 0x24,
15471 SQRT_FMT = 0x28,
15472 FLOOR_W = 0x2c,
15473 CVT_PS_PW = 0x3c,
15474 CFC1 = 0x40,
15475 RECIP_FMT = 0x48,
15476 CEIL_L = 0x4c,
15477 CTC1 = 0x60,
15478 CEIL_W = 0x6c,
15479 MFC1 = 0x80,
15480 CVT_S_PL = 0x84,
15481 TRUNC_L = 0x8c,
15482 MTC1 = 0xa0,
15483 CVT_S_PU = 0xa4,
15484 TRUNC_W = 0xac,
15485 MFHC1 = 0xc0,
15486 ROUND_L = 0xcc,
15487 MTHC1 = 0xe0,
15488 ROUND_W = 0xec,
15490 MOV_FMT = 0x01,
15491 MOVF = 0x05,
15492 ABS_FMT = 0x0d,
15493 RSQRT1_FMT = 0x1d,
15494 MOVT = 0x25,
15495 NEG_FMT = 0x2d,
15496 CVT_D = 0x4d,
15497 RECIP1_FMT = 0x5d,
15498 CVT_S = 0x6d
15501 /* POOL32I encoding of minor opcode field (bits 25..21) */
15503 enum {
15504 BLTZ = 0x00,
15505 BLTZAL = 0x01,
15506 BGEZ = 0x02,
15507 BGEZAL = 0x03,
15508 BLEZ = 0x04,
15509 BNEZC = 0x05,
15510 BGTZ = 0x06,
15511 BEQZC = 0x07,
15512 TLTI = 0x08,
15513 BC1EQZC = 0x08,
15514 TGEI = 0x09,
15515 BC1NEZC = 0x09,
15516 TLTIU = 0x0a,
15517 BC2EQZC = 0x0a,
15518 TGEIU = 0x0b,
15519 BC2NEZC = 0x0a,
15520 TNEI = 0x0c,
15521 R6_SYNCI = 0x0c,
15522 LUI = 0x0d,
15523 TEQI = 0x0e,
15524 SYNCI = 0x10,
15525 BLTZALS = 0x11,
15526 BGEZALS = 0x13,
15527 BC2F = 0x14,
15528 BC2T = 0x15,
15529 BPOSGE64 = 0x1a,
15530 BPOSGE32 = 0x1b,
15531 /* These overlap and are distinguished by bit16 of the instruction */
15532 BC1F = 0x1c,
15533 BC1T = 0x1d,
15534 BC1ANY2F = 0x1c,
15535 BC1ANY2T = 0x1d,
15536 BC1ANY4F = 0x1e,
15537 BC1ANY4T = 0x1f
15540 /* POOL16A encoding of minor opcode field */
15542 enum {
15543 ADDU16 = 0x0,
15544 SUBU16 = 0x1
15547 /* POOL16B encoding of minor opcode field */
15549 enum {
15550 SLL16 = 0x0,
15551 SRL16 = 0x1
15554 /* POOL16C encoding of minor opcode field */
15556 enum {
15557 NOT16 = 0x00,
15558 XOR16 = 0x04,
15559 AND16 = 0x08,
15560 OR16 = 0x0c,
15561 LWM16 = 0x10,
15562 SWM16 = 0x14,
15563 JR16 = 0x18,
15564 JRC16 = 0x1a,
15565 JALR16 = 0x1c,
15566 JALR16S = 0x1e,
15567 MFHI16 = 0x20,
15568 MFLO16 = 0x24,
15569 BREAK16 = 0x28,
15570 SDBBP16 = 0x2c,
15571 JRADDIUSP = 0x30
15574 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15576 enum {
15577 R6_NOT16 = 0x00,
15578 R6_AND16 = 0x01,
15579 R6_LWM16 = 0x02,
15580 R6_JRC16 = 0x03,
15581 MOVEP = 0x04,
15582 MOVEP_05 = 0x05,
15583 MOVEP_06 = 0x06,
15584 MOVEP_07 = 0x07,
15585 R6_XOR16 = 0x08,
15586 R6_OR16 = 0x09,
15587 R6_SWM16 = 0x0a,
15588 JALRC16 = 0x0b,
15589 MOVEP_0C = 0x0c,
15590 MOVEP_0D = 0x0d,
15591 MOVEP_0E = 0x0e,
15592 MOVEP_0F = 0x0f,
15593 JRCADDIUSP = 0x13,
15594 R6_BREAK16 = 0x1b,
15595 R6_SDBBP16 = 0x3b
15598 /* POOL16D encoding of minor opcode field */
15600 enum {
15601 ADDIUS5 = 0x0,
15602 ADDIUSP = 0x1
15605 /* POOL16E encoding of minor opcode field */
15607 enum {
15608 ADDIUR2 = 0x0,
15609 ADDIUR1SP = 0x1
15612 static int mmreg(int r)
15614 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15616 return map[r];
15619 /* Used for 16-bit store instructions. */
15620 static int mmreg2(int r)
15622 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15624 return map[r];
15627 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15628 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15629 #define uMIPS_RS2(op) uMIPS_RS(op)
15630 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15631 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15632 #define uMIPS_RS5(op) (op & 0x1f)
15634 /* Signed immediate */
15635 #define SIMM(op, start, width) \
15636 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15637 << (32 - width)) \
15638 >> (32 - width))
15639 /* Zero-extended immediate */
15640 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15642 static void gen_addiur1sp(DisasContext *ctx)
15644 int rd = mmreg(uMIPS_RD(ctx->opcode));
15646 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15649 static void gen_addiur2(DisasContext *ctx)
15651 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15652 int rd = mmreg(uMIPS_RD(ctx->opcode));
15653 int rs = mmreg(uMIPS_RS(ctx->opcode));
15655 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15658 static void gen_addiusp(DisasContext *ctx)
15660 int encoded = ZIMM(ctx->opcode, 1, 9);
15661 int decoded;
15663 if (encoded <= 1) {
15664 decoded = 256 + encoded;
15665 } else if (encoded <= 255) {
15666 decoded = encoded;
15667 } else if (encoded <= 509) {
15668 decoded = encoded - 512;
15669 } else {
15670 decoded = encoded - 768;
15673 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15676 static void gen_addius5(DisasContext *ctx)
15678 int imm = SIMM(ctx->opcode, 1, 4);
15679 int rd = (ctx->opcode >> 5) & 0x1f;
15681 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15684 static void gen_andi16(DisasContext *ctx)
15686 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15687 31, 32, 63, 64, 255, 32768, 65535 };
15688 int rd = mmreg(uMIPS_RD(ctx->opcode));
15689 int rs = mmreg(uMIPS_RS(ctx->opcode));
15690 int encoded = ZIMM(ctx->opcode, 0, 4);
15692 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15695 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15696 int base, int16_t offset)
15698 TCGv t0, t1;
15699 TCGv_i32 t2;
15701 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15702 generate_exception_end(ctx, EXCP_RI);
15703 return;
15706 t0 = tcg_temp_new();
15708 gen_base_offset_addr(ctx, t0, base, offset);
15710 t1 = tcg_const_tl(reglist);
15711 t2 = tcg_const_i32(ctx->mem_idx);
15713 save_cpu_state(ctx, 1);
15714 switch (opc) {
15715 case LWM32:
15716 gen_helper_lwm(cpu_env, t0, t1, t2);
15717 break;
15718 case SWM32:
15719 gen_helper_swm(cpu_env, t0, t1, t2);
15720 break;
15721 #ifdef TARGET_MIPS64
15722 case LDM:
15723 gen_helper_ldm(cpu_env, t0, t1, t2);
15724 break;
15725 case SDM:
15726 gen_helper_sdm(cpu_env, t0, t1, t2);
15727 break;
15728 #endif
15730 tcg_temp_free(t0);
15731 tcg_temp_free(t1);
15732 tcg_temp_free_i32(t2);
15736 static void gen_pool16c_insn(DisasContext *ctx)
15738 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15739 int rs = mmreg(ctx->opcode & 0x7);
15741 switch (((ctx->opcode) >> 4) & 0x3f) {
15742 case NOT16 + 0:
15743 case NOT16 + 1:
15744 case NOT16 + 2:
15745 case NOT16 + 3:
15746 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15747 break;
15748 case XOR16 + 0:
15749 case XOR16 + 1:
15750 case XOR16 + 2:
15751 case XOR16 + 3:
15752 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15753 break;
15754 case AND16 + 0:
15755 case AND16 + 1:
15756 case AND16 + 2:
15757 case AND16 + 3:
15758 gen_logic(ctx, OPC_AND, rd, rd, rs);
15759 break;
15760 case OR16 + 0:
15761 case OR16 + 1:
15762 case OR16 + 2:
15763 case OR16 + 3:
15764 gen_logic(ctx, OPC_OR, rd, rd, rs);
15765 break;
15766 case LWM16 + 0:
15767 case LWM16 + 1:
15768 case LWM16 + 2:
15769 case LWM16 + 3:
15771 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15772 int offset = ZIMM(ctx->opcode, 0, 4);
15774 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15775 29, offset << 2);
15777 break;
15778 case SWM16 + 0:
15779 case SWM16 + 1:
15780 case SWM16 + 2:
15781 case SWM16 + 3:
15783 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15784 int offset = ZIMM(ctx->opcode, 0, 4);
15786 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15787 29, offset << 2);
15789 break;
15790 case JR16 + 0:
15791 case JR16 + 1:
15793 int reg = ctx->opcode & 0x1f;
15795 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15797 break;
15798 case JRC16 + 0:
15799 case JRC16 + 1:
15801 int reg = ctx->opcode & 0x1f;
15802 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15804 * Let normal delay slot handling in our caller take us
15805 * to the branch target.
15808 break;
15809 case JALR16 + 0:
15810 case JALR16 + 1:
15811 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15812 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15813 break;
15814 case JALR16S + 0:
15815 case JALR16S + 1:
15816 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15817 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15818 break;
15819 case MFHI16 + 0:
15820 case MFHI16 + 1:
15821 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15822 break;
15823 case MFLO16 + 0:
15824 case MFLO16 + 1:
15825 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15826 break;
15827 case BREAK16:
15828 generate_exception_end(ctx, EXCP_BREAK);
15829 break;
15830 case SDBBP16:
15831 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15832 gen_helper_do_semihosting(cpu_env);
15833 } else {
15835 * XXX: not clear which exception should be raised
15836 * when in debug mode...
15838 check_insn(ctx, ISA_MIPS32);
15839 generate_exception_end(ctx, EXCP_DBp);
15841 break;
15842 case JRADDIUSP + 0:
15843 case JRADDIUSP + 1:
15845 int imm = ZIMM(ctx->opcode, 0, 5);
15846 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15847 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15849 * Let normal delay slot handling in our caller take us
15850 * to the branch target.
15853 break;
15854 default:
15855 generate_exception_end(ctx, EXCP_RI);
15856 break;
15860 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15861 int enc_rs)
15863 int rd, rs, re, rt;
15864 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15865 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15866 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15867 rd = rd_enc[enc_dest];
15868 re = re_enc[enc_dest];
15869 rs = rs_rt_enc[enc_rs];
15870 rt = rs_rt_enc[enc_rt];
15871 if (rs) {
15872 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15873 } else {
15874 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15876 if (rt) {
15877 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15878 } else {
15879 tcg_gen_movi_tl(cpu_gpr[re], 0);
15883 static void gen_pool16c_r6_insn(DisasContext *ctx)
15885 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15886 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15888 switch (ctx->opcode & 0xf) {
15889 case R6_NOT16:
15890 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15891 break;
15892 case R6_AND16:
15893 gen_logic(ctx, OPC_AND, rt, rt, rs);
15894 break;
15895 case R6_LWM16:
15897 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15898 int offset = extract32(ctx->opcode, 4, 4);
15899 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15901 break;
15902 case R6_JRC16: /* JRCADDIUSP */
15903 if ((ctx->opcode >> 4) & 1) {
15904 /* JRCADDIUSP */
15905 int imm = extract32(ctx->opcode, 5, 5);
15906 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15907 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15908 } else {
15909 /* JRC16 */
15910 rs = extract32(ctx->opcode, 5, 5);
15911 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15913 break;
15914 case MOVEP:
15915 case MOVEP_05:
15916 case MOVEP_06:
15917 case MOVEP_07:
15918 case MOVEP_0C:
15919 case MOVEP_0D:
15920 case MOVEP_0E:
15921 case MOVEP_0F:
15923 int enc_dest = uMIPS_RD(ctx->opcode);
15924 int enc_rt = uMIPS_RS2(ctx->opcode);
15925 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15926 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15928 break;
15929 case R6_XOR16:
15930 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15931 break;
15932 case R6_OR16:
15933 gen_logic(ctx, OPC_OR, rt, rt, rs);
15934 break;
15935 case R6_SWM16:
15937 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15938 int offset = extract32(ctx->opcode, 4, 4);
15939 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15941 break;
15942 case JALRC16: /* BREAK16, SDBBP16 */
15943 switch (ctx->opcode & 0x3f) {
15944 case JALRC16:
15945 case JALRC16 + 0x20:
15946 /* JALRC16 */
15947 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15948 31, 0, 0);
15949 break;
15950 case R6_BREAK16:
15951 /* BREAK16 */
15952 generate_exception(ctx, EXCP_BREAK);
15953 break;
15954 case R6_SDBBP16:
15955 /* SDBBP16 */
15956 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15957 gen_helper_do_semihosting(cpu_env);
15958 } else {
15959 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15960 generate_exception(ctx, EXCP_RI);
15961 } else {
15962 generate_exception(ctx, EXCP_DBp);
15965 break;
15967 break;
15968 default:
15969 generate_exception(ctx, EXCP_RI);
15970 break;
15974 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15976 TCGv t0 = tcg_temp_new();
15977 TCGv t1 = tcg_temp_new();
15979 gen_load_gpr(t0, base);
15981 if (index != 0) {
15982 gen_load_gpr(t1, index);
15983 tcg_gen_shli_tl(t1, t1, 2);
15984 gen_op_addr_add(ctx, t0, t1, t0);
15987 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15988 gen_store_gpr(t1, rd);
15990 tcg_temp_free(t0);
15991 tcg_temp_free(t1);
15994 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15995 int base, int16_t offset)
15997 TCGv t0, t1;
15999 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
16000 generate_exception_end(ctx, EXCP_RI);
16001 return;
16004 t0 = tcg_temp_new();
16005 t1 = tcg_temp_new();
16007 gen_base_offset_addr(ctx, t0, base, offset);
16009 switch (opc) {
16010 case LWP:
16011 if (rd == base) {
16012 generate_exception_end(ctx, EXCP_RI);
16013 return;
16015 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
16016 gen_store_gpr(t1, rd);
16017 tcg_gen_movi_tl(t1, 4);
16018 gen_op_addr_add(ctx, t0, t0, t1);
16019 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
16020 gen_store_gpr(t1, rd + 1);
16021 break;
16022 case SWP:
16023 gen_load_gpr(t1, rd);
16024 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
16025 tcg_gen_movi_tl(t1, 4);
16026 gen_op_addr_add(ctx, t0, t0, t1);
16027 gen_load_gpr(t1, rd + 1);
16028 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
16029 break;
16030 #ifdef TARGET_MIPS64
16031 case LDP:
16032 if (rd == base) {
16033 generate_exception_end(ctx, EXCP_RI);
16034 return;
16036 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16037 gen_store_gpr(t1, rd);
16038 tcg_gen_movi_tl(t1, 8);
16039 gen_op_addr_add(ctx, t0, t0, t1);
16040 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16041 gen_store_gpr(t1, rd + 1);
16042 break;
16043 case SDP:
16044 gen_load_gpr(t1, rd);
16045 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16046 tcg_gen_movi_tl(t1, 8);
16047 gen_op_addr_add(ctx, t0, t0, t1);
16048 gen_load_gpr(t1, rd + 1);
16049 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16050 break;
16051 #endif
16053 tcg_temp_free(t0);
16054 tcg_temp_free(t1);
16057 static void gen_sync(int stype)
16059 TCGBar tcg_mo = TCG_BAR_SC;
16061 switch (stype) {
16062 case 0x4: /* SYNC_WMB */
16063 tcg_mo |= TCG_MO_ST_ST;
16064 break;
16065 case 0x10: /* SYNC_MB */
16066 tcg_mo |= TCG_MO_ALL;
16067 break;
16068 case 0x11: /* SYNC_ACQUIRE */
16069 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
16070 break;
16071 case 0x12: /* SYNC_RELEASE */
16072 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
16073 break;
16074 case 0x13: /* SYNC_RMB */
16075 tcg_mo |= TCG_MO_LD_LD;
16076 break;
16077 default:
16078 tcg_mo |= TCG_MO_ALL;
16079 break;
16082 tcg_gen_mb(tcg_mo);
16085 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
16087 int extension = (ctx->opcode >> 6) & 0x3f;
16088 int minor = (ctx->opcode >> 12) & 0xf;
16089 uint32_t mips32_op;
16091 switch (extension) {
16092 case TEQ:
16093 mips32_op = OPC_TEQ;
16094 goto do_trap;
16095 case TGE:
16096 mips32_op = OPC_TGE;
16097 goto do_trap;
16098 case TGEU:
16099 mips32_op = OPC_TGEU;
16100 goto do_trap;
16101 case TLT:
16102 mips32_op = OPC_TLT;
16103 goto do_trap;
16104 case TLTU:
16105 mips32_op = OPC_TLTU;
16106 goto do_trap;
16107 case TNE:
16108 mips32_op = OPC_TNE;
16109 do_trap:
16110 gen_trap(ctx, mips32_op, rs, rt, -1);
16111 break;
16112 #ifndef CONFIG_USER_ONLY
16113 case MFC0:
16114 case MFC0 + 32:
16115 check_cp0_enabled(ctx);
16116 if (rt == 0) {
16117 /* Treat as NOP. */
16118 break;
16120 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
16121 break;
16122 case MTC0:
16123 case MTC0 + 32:
16124 check_cp0_enabled(ctx);
16126 TCGv t0 = tcg_temp_new();
16128 gen_load_gpr(t0, rt);
16129 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
16130 tcg_temp_free(t0);
16132 break;
16133 #endif
16134 case 0x2a:
16135 switch (minor & 3) {
16136 case MADD_ACC:
16137 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
16138 break;
16139 case MADDU_ACC:
16140 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
16141 break;
16142 case MSUB_ACC:
16143 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
16144 break;
16145 case MSUBU_ACC:
16146 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
16147 break;
16148 default:
16149 goto pool32axf_invalid;
16151 break;
16152 case 0x32:
16153 switch (minor & 3) {
16154 case MULT_ACC:
16155 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
16156 break;
16157 case MULTU_ACC:
16158 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
16159 break;
16160 default:
16161 goto pool32axf_invalid;
16163 break;
16164 case 0x2c:
16165 switch (minor) {
16166 case BITSWAP:
16167 check_insn(ctx, ISA_MIPS32R6);
16168 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
16169 break;
16170 case SEB:
16171 gen_bshfl(ctx, OPC_SEB, rs, rt);
16172 break;
16173 case SEH:
16174 gen_bshfl(ctx, OPC_SEH, rs, rt);
16175 break;
16176 case CLO:
16177 mips32_op = OPC_CLO;
16178 goto do_cl;
16179 case CLZ:
16180 mips32_op = OPC_CLZ;
16181 do_cl:
16182 check_insn(ctx, ISA_MIPS32);
16183 gen_cl(ctx, mips32_op, rt, rs);
16184 break;
16185 case RDHWR:
16186 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16187 gen_rdhwr(ctx, rt, rs, 0);
16188 break;
16189 case WSBH:
16190 gen_bshfl(ctx, OPC_WSBH, rs, rt);
16191 break;
16192 case MULT:
16193 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16194 mips32_op = OPC_MULT;
16195 goto do_mul;
16196 case MULTU:
16197 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16198 mips32_op = OPC_MULTU;
16199 goto do_mul;
16200 case DIV:
16201 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16202 mips32_op = OPC_DIV;
16203 goto do_div;
16204 case DIVU:
16205 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16206 mips32_op = OPC_DIVU;
16207 goto do_div;
16208 do_div:
16209 check_insn(ctx, ISA_MIPS32);
16210 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16211 break;
16212 case MADD:
16213 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16214 mips32_op = OPC_MADD;
16215 goto do_mul;
16216 case MADDU:
16217 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16218 mips32_op = OPC_MADDU;
16219 goto do_mul;
16220 case MSUB:
16221 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16222 mips32_op = OPC_MSUB;
16223 goto do_mul;
16224 case MSUBU:
16225 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16226 mips32_op = OPC_MSUBU;
16227 do_mul:
16228 check_insn(ctx, ISA_MIPS32);
16229 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16230 break;
16231 default:
16232 goto pool32axf_invalid;
16234 break;
16235 case 0x34:
16236 switch (minor) {
16237 case MFC2:
16238 case MTC2:
16239 case MFHC2:
16240 case MTHC2:
16241 case CFC2:
16242 case CTC2:
16243 generate_exception_err(ctx, EXCP_CpU, 2);
16244 break;
16245 default:
16246 goto pool32axf_invalid;
16248 break;
16249 case 0x3c:
16250 switch (minor) {
16251 case JALR: /* JALRC */
16252 case JALR_HB: /* JALRC_HB */
16253 if (ctx->insn_flags & ISA_MIPS32R6) {
16254 /* JALRC, JALRC_HB */
16255 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
16256 } else {
16257 /* JALR, JALR_HB */
16258 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
16259 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16261 break;
16262 case JALRS:
16263 case JALRS_HB:
16264 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16265 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
16266 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16267 break;
16268 default:
16269 goto pool32axf_invalid;
16271 break;
16272 case 0x05:
16273 switch (minor) {
16274 case RDPGPR:
16275 check_cp0_enabled(ctx);
16276 check_insn(ctx, ISA_MIPS32R2);
16277 gen_load_srsgpr(rs, rt);
16278 break;
16279 case WRPGPR:
16280 check_cp0_enabled(ctx);
16281 check_insn(ctx, ISA_MIPS32R2);
16282 gen_store_srsgpr(rs, rt);
16283 break;
16284 default:
16285 goto pool32axf_invalid;
16287 break;
16288 #ifndef CONFIG_USER_ONLY
16289 case 0x0d:
16290 switch (minor) {
16291 case TLBP:
16292 mips32_op = OPC_TLBP;
16293 goto do_cp0;
16294 case TLBR:
16295 mips32_op = OPC_TLBR;
16296 goto do_cp0;
16297 case TLBWI:
16298 mips32_op = OPC_TLBWI;
16299 goto do_cp0;
16300 case TLBWR:
16301 mips32_op = OPC_TLBWR;
16302 goto do_cp0;
16303 case TLBINV:
16304 mips32_op = OPC_TLBINV;
16305 goto do_cp0;
16306 case TLBINVF:
16307 mips32_op = OPC_TLBINVF;
16308 goto do_cp0;
16309 case WAIT:
16310 mips32_op = OPC_WAIT;
16311 goto do_cp0;
16312 case DERET:
16313 mips32_op = OPC_DERET;
16314 goto do_cp0;
16315 case ERET:
16316 mips32_op = OPC_ERET;
16317 do_cp0:
16318 gen_cp0(env, ctx, mips32_op, rt, rs);
16319 break;
16320 default:
16321 goto pool32axf_invalid;
16323 break;
16324 case 0x1d:
16325 switch (minor) {
16326 case DI:
16327 check_cp0_enabled(ctx);
16329 TCGv t0 = tcg_temp_new();
16331 save_cpu_state(ctx, 1);
16332 gen_helper_di(t0, cpu_env);
16333 gen_store_gpr(t0, rs);
16335 * Stop translation as we may have switched the execution
16336 * mode.
16338 ctx->base.is_jmp = DISAS_STOP;
16339 tcg_temp_free(t0);
16341 break;
16342 case EI:
16343 check_cp0_enabled(ctx);
16345 TCGv t0 = tcg_temp_new();
16347 save_cpu_state(ctx, 1);
16348 gen_helper_ei(t0, cpu_env);
16349 gen_store_gpr(t0, rs);
16351 * DISAS_STOP isn't sufficient, we need to ensure we break out
16352 * of translated code to check for pending interrupts.
16354 gen_save_pc(ctx->base.pc_next + 4);
16355 ctx->base.is_jmp = DISAS_EXIT;
16356 tcg_temp_free(t0);
16358 break;
16359 default:
16360 goto pool32axf_invalid;
16362 break;
16363 #endif
16364 case 0x2d:
16365 switch (minor) {
16366 case SYNC:
16367 gen_sync(extract32(ctx->opcode, 16, 5));
16368 break;
16369 case SYSCALL:
16370 generate_exception_end(ctx, EXCP_SYSCALL);
16371 break;
16372 case SDBBP:
16373 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
16374 gen_helper_do_semihosting(cpu_env);
16375 } else {
16376 check_insn(ctx, ISA_MIPS32);
16377 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16378 generate_exception_end(ctx, EXCP_RI);
16379 } else {
16380 generate_exception_end(ctx, EXCP_DBp);
16383 break;
16384 default:
16385 goto pool32axf_invalid;
16387 break;
16388 case 0x01:
16389 switch (minor & 3) {
16390 case MFHI_ACC:
16391 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
16392 break;
16393 case MFLO_ACC:
16394 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
16395 break;
16396 case MTHI_ACC:
16397 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
16398 break;
16399 case MTLO_ACC:
16400 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
16401 break;
16402 default:
16403 goto pool32axf_invalid;
16405 break;
16406 case 0x35:
16407 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16408 switch (minor) {
16409 case MFHI32:
16410 gen_HILO(ctx, OPC_MFHI, 0, rs);
16411 break;
16412 case MFLO32:
16413 gen_HILO(ctx, OPC_MFLO, 0, rs);
16414 break;
16415 case MTHI32:
16416 gen_HILO(ctx, OPC_MTHI, 0, rs);
16417 break;
16418 case MTLO32:
16419 gen_HILO(ctx, OPC_MTLO, 0, rs);
16420 break;
16421 default:
16422 goto pool32axf_invalid;
16424 break;
16425 default:
16426 pool32axf_invalid:
16427 MIPS_INVAL("pool32axf");
16428 generate_exception_end(ctx, EXCP_RI);
16429 break;
16434 * Values for microMIPS fmt field. Variable-width, depending on which
16435 * formats the instruction supports.
16437 enum {
16438 FMT_SD_S = 0,
16439 FMT_SD_D = 1,
16441 FMT_SDPS_S = 0,
16442 FMT_SDPS_D = 1,
16443 FMT_SDPS_PS = 2,
16445 FMT_SWL_S = 0,
16446 FMT_SWL_W = 1,
16447 FMT_SWL_L = 2,
16449 FMT_DWL_D = 0,
16450 FMT_DWL_W = 1,
16451 FMT_DWL_L = 2
16454 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16456 int extension = (ctx->opcode >> 6) & 0x3ff;
16457 uint32_t mips32_op;
16459 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16460 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16461 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16463 switch (extension) {
16464 case FLOAT_1BIT_FMT(CFC1, 0):
16465 mips32_op = OPC_CFC1;
16466 goto do_cp1;
16467 case FLOAT_1BIT_FMT(CTC1, 0):
16468 mips32_op = OPC_CTC1;
16469 goto do_cp1;
16470 case FLOAT_1BIT_FMT(MFC1, 0):
16471 mips32_op = OPC_MFC1;
16472 goto do_cp1;
16473 case FLOAT_1BIT_FMT(MTC1, 0):
16474 mips32_op = OPC_MTC1;
16475 goto do_cp1;
16476 case FLOAT_1BIT_FMT(MFHC1, 0):
16477 mips32_op = OPC_MFHC1;
16478 goto do_cp1;
16479 case FLOAT_1BIT_FMT(MTHC1, 0):
16480 mips32_op = OPC_MTHC1;
16481 do_cp1:
16482 gen_cp1(ctx, mips32_op, rt, rs);
16483 break;
16485 /* Reciprocal square root */
16486 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16487 mips32_op = OPC_RSQRT_S;
16488 goto do_unaryfp;
16489 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16490 mips32_op = OPC_RSQRT_D;
16491 goto do_unaryfp;
16493 /* Square root */
16494 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16495 mips32_op = OPC_SQRT_S;
16496 goto do_unaryfp;
16497 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16498 mips32_op = OPC_SQRT_D;
16499 goto do_unaryfp;
16501 /* Reciprocal */
16502 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16503 mips32_op = OPC_RECIP_S;
16504 goto do_unaryfp;
16505 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16506 mips32_op = OPC_RECIP_D;
16507 goto do_unaryfp;
16509 /* Floor */
16510 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16511 mips32_op = OPC_FLOOR_L_S;
16512 goto do_unaryfp;
16513 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16514 mips32_op = OPC_FLOOR_L_D;
16515 goto do_unaryfp;
16516 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16517 mips32_op = OPC_FLOOR_W_S;
16518 goto do_unaryfp;
16519 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16520 mips32_op = OPC_FLOOR_W_D;
16521 goto do_unaryfp;
16523 /* Ceiling */
16524 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16525 mips32_op = OPC_CEIL_L_S;
16526 goto do_unaryfp;
16527 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16528 mips32_op = OPC_CEIL_L_D;
16529 goto do_unaryfp;
16530 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16531 mips32_op = OPC_CEIL_W_S;
16532 goto do_unaryfp;
16533 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16534 mips32_op = OPC_CEIL_W_D;
16535 goto do_unaryfp;
16537 /* Truncation */
16538 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16539 mips32_op = OPC_TRUNC_L_S;
16540 goto do_unaryfp;
16541 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16542 mips32_op = OPC_TRUNC_L_D;
16543 goto do_unaryfp;
16544 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16545 mips32_op = OPC_TRUNC_W_S;
16546 goto do_unaryfp;
16547 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16548 mips32_op = OPC_TRUNC_W_D;
16549 goto do_unaryfp;
16551 /* Round */
16552 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16553 mips32_op = OPC_ROUND_L_S;
16554 goto do_unaryfp;
16555 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16556 mips32_op = OPC_ROUND_L_D;
16557 goto do_unaryfp;
16558 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16559 mips32_op = OPC_ROUND_W_S;
16560 goto do_unaryfp;
16561 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16562 mips32_op = OPC_ROUND_W_D;
16563 goto do_unaryfp;
16565 /* Integer to floating-point conversion */
16566 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16567 mips32_op = OPC_CVT_L_S;
16568 goto do_unaryfp;
16569 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16570 mips32_op = OPC_CVT_L_D;
16571 goto do_unaryfp;
16572 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16573 mips32_op = OPC_CVT_W_S;
16574 goto do_unaryfp;
16575 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16576 mips32_op = OPC_CVT_W_D;
16577 goto do_unaryfp;
16579 /* Paired-foo conversions */
16580 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16581 mips32_op = OPC_CVT_S_PL;
16582 goto do_unaryfp;
16583 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16584 mips32_op = OPC_CVT_S_PU;
16585 goto do_unaryfp;
16586 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16587 mips32_op = OPC_CVT_PW_PS;
16588 goto do_unaryfp;
16589 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16590 mips32_op = OPC_CVT_PS_PW;
16591 goto do_unaryfp;
16593 /* Floating-point moves */
16594 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16595 mips32_op = OPC_MOV_S;
16596 goto do_unaryfp;
16597 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16598 mips32_op = OPC_MOV_D;
16599 goto do_unaryfp;
16600 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16601 mips32_op = OPC_MOV_PS;
16602 goto do_unaryfp;
16604 /* Absolute value */
16605 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16606 mips32_op = OPC_ABS_S;
16607 goto do_unaryfp;
16608 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16609 mips32_op = OPC_ABS_D;
16610 goto do_unaryfp;
16611 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16612 mips32_op = OPC_ABS_PS;
16613 goto do_unaryfp;
16615 /* Negation */
16616 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16617 mips32_op = OPC_NEG_S;
16618 goto do_unaryfp;
16619 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16620 mips32_op = OPC_NEG_D;
16621 goto do_unaryfp;
16622 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16623 mips32_op = OPC_NEG_PS;
16624 goto do_unaryfp;
16626 /* Reciprocal square root step */
16627 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16628 mips32_op = OPC_RSQRT1_S;
16629 goto do_unaryfp;
16630 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16631 mips32_op = OPC_RSQRT1_D;
16632 goto do_unaryfp;
16633 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16634 mips32_op = OPC_RSQRT1_PS;
16635 goto do_unaryfp;
16637 /* Reciprocal step */
16638 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16639 mips32_op = OPC_RECIP1_S;
16640 goto do_unaryfp;
16641 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16642 mips32_op = OPC_RECIP1_S;
16643 goto do_unaryfp;
16644 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16645 mips32_op = OPC_RECIP1_PS;
16646 goto do_unaryfp;
16648 /* Conversions from double */
16649 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16650 mips32_op = OPC_CVT_D_S;
16651 goto do_unaryfp;
16652 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16653 mips32_op = OPC_CVT_D_W;
16654 goto do_unaryfp;
16655 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16656 mips32_op = OPC_CVT_D_L;
16657 goto do_unaryfp;
16659 /* Conversions from single */
16660 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16661 mips32_op = OPC_CVT_S_D;
16662 goto do_unaryfp;
16663 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16664 mips32_op = OPC_CVT_S_W;
16665 goto do_unaryfp;
16666 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16667 mips32_op = OPC_CVT_S_L;
16668 do_unaryfp:
16669 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16670 break;
16672 /* Conditional moves on floating-point codes */
16673 case COND_FLOAT_MOV(MOVT, 0):
16674 case COND_FLOAT_MOV(MOVT, 1):
16675 case COND_FLOAT_MOV(MOVT, 2):
16676 case COND_FLOAT_MOV(MOVT, 3):
16677 case COND_FLOAT_MOV(MOVT, 4):
16678 case COND_FLOAT_MOV(MOVT, 5):
16679 case COND_FLOAT_MOV(MOVT, 6):
16680 case COND_FLOAT_MOV(MOVT, 7):
16681 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16682 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16683 break;
16684 case COND_FLOAT_MOV(MOVF, 0):
16685 case COND_FLOAT_MOV(MOVF, 1):
16686 case COND_FLOAT_MOV(MOVF, 2):
16687 case COND_FLOAT_MOV(MOVF, 3):
16688 case COND_FLOAT_MOV(MOVF, 4):
16689 case COND_FLOAT_MOV(MOVF, 5):
16690 case COND_FLOAT_MOV(MOVF, 6):
16691 case COND_FLOAT_MOV(MOVF, 7):
16692 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16693 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16694 break;
16695 default:
16696 MIPS_INVAL("pool32fxf");
16697 generate_exception_end(ctx, EXCP_RI);
16698 break;
16702 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16704 int32_t offset;
16705 uint16_t insn;
16706 int rt, rs, rd, rr;
16707 int16_t imm;
16708 uint32_t op, minor, minor2, mips32_op;
16709 uint32_t cond, fmt, cc;
16711 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16712 ctx->opcode = (ctx->opcode << 16) | insn;
16714 rt = (ctx->opcode >> 21) & 0x1f;
16715 rs = (ctx->opcode >> 16) & 0x1f;
16716 rd = (ctx->opcode >> 11) & 0x1f;
16717 rr = (ctx->opcode >> 6) & 0x1f;
16718 imm = (int16_t) ctx->opcode;
16720 op = (ctx->opcode >> 26) & 0x3f;
16721 switch (op) {
16722 case POOL32A:
16723 minor = ctx->opcode & 0x3f;
16724 switch (minor) {
16725 case 0x00:
16726 minor = (ctx->opcode >> 6) & 0xf;
16727 switch (minor) {
16728 case SLL32:
16729 mips32_op = OPC_SLL;
16730 goto do_shifti;
16731 case SRA:
16732 mips32_op = OPC_SRA;
16733 goto do_shifti;
16734 case SRL32:
16735 mips32_op = OPC_SRL;
16736 goto do_shifti;
16737 case ROTR:
16738 mips32_op = OPC_ROTR;
16739 do_shifti:
16740 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16741 break;
16742 case SELEQZ:
16743 check_insn(ctx, ISA_MIPS32R6);
16744 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16745 break;
16746 case SELNEZ:
16747 check_insn(ctx, ISA_MIPS32R6);
16748 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16749 break;
16750 case R6_RDHWR:
16751 check_insn(ctx, ISA_MIPS32R6);
16752 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16753 break;
16754 default:
16755 goto pool32a_invalid;
16757 break;
16758 case 0x10:
16759 minor = (ctx->opcode >> 6) & 0xf;
16760 switch (minor) {
16761 /* Arithmetic */
16762 case ADD:
16763 mips32_op = OPC_ADD;
16764 goto do_arith;
16765 case ADDU32:
16766 mips32_op = OPC_ADDU;
16767 goto do_arith;
16768 case SUB:
16769 mips32_op = OPC_SUB;
16770 goto do_arith;
16771 case SUBU32:
16772 mips32_op = OPC_SUBU;
16773 goto do_arith;
16774 case MUL:
16775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16776 mips32_op = OPC_MUL;
16777 do_arith:
16778 gen_arith(ctx, mips32_op, rd, rs, rt);
16779 break;
16780 /* Shifts */
16781 case SLLV:
16782 mips32_op = OPC_SLLV;
16783 goto do_shift;
16784 case SRLV:
16785 mips32_op = OPC_SRLV;
16786 goto do_shift;
16787 case SRAV:
16788 mips32_op = OPC_SRAV;
16789 goto do_shift;
16790 case ROTRV:
16791 mips32_op = OPC_ROTRV;
16792 do_shift:
16793 gen_shift(ctx, mips32_op, rd, rs, rt);
16794 break;
16795 /* Logical operations */
16796 case AND:
16797 mips32_op = OPC_AND;
16798 goto do_logic;
16799 case OR32:
16800 mips32_op = OPC_OR;
16801 goto do_logic;
16802 case NOR:
16803 mips32_op = OPC_NOR;
16804 goto do_logic;
16805 case XOR32:
16806 mips32_op = OPC_XOR;
16807 do_logic:
16808 gen_logic(ctx, mips32_op, rd, rs, rt);
16809 break;
16810 /* Set less than */
16811 case SLT:
16812 mips32_op = OPC_SLT;
16813 goto do_slt;
16814 case SLTU:
16815 mips32_op = OPC_SLTU;
16816 do_slt:
16817 gen_slt(ctx, mips32_op, rd, rs, rt);
16818 break;
16819 default:
16820 goto pool32a_invalid;
16822 break;
16823 case 0x18:
16824 minor = (ctx->opcode >> 6) & 0xf;
16825 switch (minor) {
16826 /* Conditional moves */
16827 case MOVN: /* MUL */
16828 if (ctx->insn_flags & ISA_MIPS32R6) {
16829 /* MUL */
16830 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16831 } else {
16832 /* MOVN */
16833 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16835 break;
16836 case MOVZ: /* MUH */
16837 if (ctx->insn_flags & ISA_MIPS32R6) {
16838 /* MUH */
16839 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16840 } else {
16841 /* MOVZ */
16842 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16844 break;
16845 case MULU:
16846 check_insn(ctx, ISA_MIPS32R6);
16847 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16848 break;
16849 case MUHU:
16850 check_insn(ctx, ISA_MIPS32R6);
16851 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16852 break;
16853 case LWXS: /* DIV */
16854 if (ctx->insn_flags & ISA_MIPS32R6) {
16855 /* DIV */
16856 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16857 } else {
16858 /* LWXS */
16859 gen_ldxs(ctx, rs, rt, rd);
16861 break;
16862 case MOD:
16863 check_insn(ctx, ISA_MIPS32R6);
16864 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16865 break;
16866 case R6_DIVU:
16867 check_insn(ctx, ISA_MIPS32R6);
16868 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16869 break;
16870 case MODU:
16871 check_insn(ctx, ISA_MIPS32R6);
16872 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16873 break;
16874 default:
16875 goto pool32a_invalid;
16877 break;
16878 case INS:
16879 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16880 return;
16881 case LSA:
16882 check_insn(ctx, ISA_MIPS32R6);
16883 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16884 extract32(ctx->opcode, 9, 2));
16885 break;
16886 case ALIGN:
16887 check_insn(ctx, ISA_MIPS32R6);
16888 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16889 break;
16890 case EXT:
16891 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16892 return;
16893 case POOL32AXF:
16894 gen_pool32axf(env, ctx, rt, rs);
16895 break;
16896 case BREAK32:
16897 generate_exception_end(ctx, EXCP_BREAK);
16898 break;
16899 case SIGRIE:
16900 check_insn(ctx, ISA_MIPS32R6);
16901 generate_exception_end(ctx, EXCP_RI);
16902 break;
16903 default:
16904 pool32a_invalid:
16905 MIPS_INVAL("pool32a");
16906 generate_exception_end(ctx, EXCP_RI);
16907 break;
16909 break;
16910 case POOL32B:
16911 minor = (ctx->opcode >> 12) & 0xf;
16912 switch (minor) {
16913 case CACHE:
16914 check_cp0_enabled(ctx);
16915 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16916 gen_cache_operation(ctx, rt, rs, imm);
16918 break;
16919 case LWC2:
16920 case SWC2:
16921 /* COP2: Not implemented. */
16922 generate_exception_err(ctx, EXCP_CpU, 2);
16923 break;
16924 #ifdef TARGET_MIPS64
16925 case LDP:
16926 case SDP:
16927 check_insn(ctx, ISA_MIPS3);
16928 check_mips_64(ctx);
16929 #endif
16930 /* fall through */
16931 case LWP:
16932 case SWP:
16933 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16934 break;
16935 #ifdef TARGET_MIPS64
16936 case LDM:
16937 case SDM:
16938 check_insn(ctx, ISA_MIPS3);
16939 check_mips_64(ctx);
16940 #endif
16941 /* fall through */
16942 case LWM32:
16943 case SWM32:
16944 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16945 break;
16946 default:
16947 MIPS_INVAL("pool32b");
16948 generate_exception_end(ctx, EXCP_RI);
16949 break;
16951 break;
16952 case POOL32F:
16953 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16954 minor = ctx->opcode & 0x3f;
16955 check_cp1_enabled(ctx);
16956 switch (minor) {
16957 case ALNV_PS:
16958 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16959 mips32_op = OPC_ALNV_PS;
16960 goto do_madd;
16961 case MADD_S:
16962 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16963 mips32_op = OPC_MADD_S;
16964 goto do_madd;
16965 case MADD_D:
16966 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16967 mips32_op = OPC_MADD_D;
16968 goto do_madd;
16969 case MADD_PS:
16970 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16971 mips32_op = OPC_MADD_PS;
16972 goto do_madd;
16973 case MSUB_S:
16974 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16975 mips32_op = OPC_MSUB_S;
16976 goto do_madd;
16977 case MSUB_D:
16978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16979 mips32_op = OPC_MSUB_D;
16980 goto do_madd;
16981 case MSUB_PS:
16982 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16983 mips32_op = OPC_MSUB_PS;
16984 goto do_madd;
16985 case NMADD_S:
16986 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16987 mips32_op = OPC_NMADD_S;
16988 goto do_madd;
16989 case NMADD_D:
16990 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16991 mips32_op = OPC_NMADD_D;
16992 goto do_madd;
16993 case NMADD_PS:
16994 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16995 mips32_op = OPC_NMADD_PS;
16996 goto do_madd;
16997 case NMSUB_S:
16998 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16999 mips32_op = OPC_NMSUB_S;
17000 goto do_madd;
17001 case NMSUB_D:
17002 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17003 mips32_op = OPC_NMSUB_D;
17004 goto do_madd;
17005 case NMSUB_PS:
17006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17007 mips32_op = OPC_NMSUB_PS;
17008 do_madd:
17009 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
17010 break;
17011 case CABS_COND_FMT:
17012 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17013 cond = (ctx->opcode >> 6) & 0xf;
17014 cc = (ctx->opcode >> 13) & 0x7;
17015 fmt = (ctx->opcode >> 10) & 0x3;
17016 switch (fmt) {
17017 case 0x0:
17018 gen_cmpabs_s(ctx, cond, rt, rs, cc);
17019 break;
17020 case 0x1:
17021 gen_cmpabs_d(ctx, cond, rt, rs, cc);
17022 break;
17023 case 0x2:
17024 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
17025 break;
17026 default:
17027 goto pool32f_invalid;
17029 break;
17030 case C_COND_FMT:
17031 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17032 cond = (ctx->opcode >> 6) & 0xf;
17033 cc = (ctx->opcode >> 13) & 0x7;
17034 fmt = (ctx->opcode >> 10) & 0x3;
17035 switch (fmt) {
17036 case 0x0:
17037 gen_cmp_s(ctx, cond, rt, rs, cc);
17038 break;
17039 case 0x1:
17040 gen_cmp_d(ctx, cond, rt, rs, cc);
17041 break;
17042 case 0x2:
17043 gen_cmp_ps(ctx, cond, rt, rs, cc);
17044 break;
17045 default:
17046 goto pool32f_invalid;
17048 break;
17049 case CMP_CONDN_S:
17050 check_insn(ctx, ISA_MIPS32R6);
17051 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
17052 break;
17053 case CMP_CONDN_D:
17054 check_insn(ctx, ISA_MIPS32R6);
17055 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
17056 break;
17057 case POOL32FXF:
17058 gen_pool32fxf(ctx, rt, rs);
17059 break;
17060 case 0x00:
17061 /* PLL foo */
17062 switch ((ctx->opcode >> 6) & 0x7) {
17063 case PLL_PS:
17064 mips32_op = OPC_PLL_PS;
17065 goto do_ps;
17066 case PLU_PS:
17067 mips32_op = OPC_PLU_PS;
17068 goto do_ps;
17069 case PUL_PS:
17070 mips32_op = OPC_PUL_PS;
17071 goto do_ps;
17072 case PUU_PS:
17073 mips32_op = OPC_PUU_PS;
17074 goto do_ps;
17075 case CVT_PS_S:
17076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17077 mips32_op = OPC_CVT_PS_S;
17078 do_ps:
17079 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17080 break;
17081 default:
17082 goto pool32f_invalid;
17084 break;
17085 case MIN_FMT:
17086 check_insn(ctx, ISA_MIPS32R6);
17087 switch ((ctx->opcode >> 9) & 0x3) {
17088 case FMT_SDPS_S:
17089 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
17090 break;
17091 case FMT_SDPS_D:
17092 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
17093 break;
17094 default:
17095 goto pool32f_invalid;
17097 break;
17098 case 0x08:
17099 /* [LS][WDU]XC1 */
17100 switch ((ctx->opcode >> 6) & 0x7) {
17101 case LWXC1:
17102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17103 mips32_op = OPC_LWXC1;
17104 goto do_ldst_cp1;
17105 case SWXC1:
17106 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17107 mips32_op = OPC_SWXC1;
17108 goto do_ldst_cp1;
17109 case LDXC1:
17110 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17111 mips32_op = OPC_LDXC1;
17112 goto do_ldst_cp1;
17113 case SDXC1:
17114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17115 mips32_op = OPC_SDXC1;
17116 goto do_ldst_cp1;
17117 case LUXC1:
17118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17119 mips32_op = OPC_LUXC1;
17120 goto do_ldst_cp1;
17121 case SUXC1:
17122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17123 mips32_op = OPC_SUXC1;
17124 do_ldst_cp1:
17125 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
17126 break;
17127 default:
17128 goto pool32f_invalid;
17130 break;
17131 case MAX_FMT:
17132 check_insn(ctx, ISA_MIPS32R6);
17133 switch ((ctx->opcode >> 9) & 0x3) {
17134 case FMT_SDPS_S:
17135 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17136 break;
17137 case FMT_SDPS_D:
17138 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17139 break;
17140 default:
17141 goto pool32f_invalid;
17143 break;
17144 case 0x18:
17145 /* 3D insns */
17146 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17147 fmt = (ctx->opcode >> 9) & 0x3;
17148 switch ((ctx->opcode >> 6) & 0x7) {
17149 case RSQRT2_FMT:
17150 switch (fmt) {
17151 case FMT_SDPS_S:
17152 mips32_op = OPC_RSQRT2_S;
17153 goto do_3d;
17154 case FMT_SDPS_D:
17155 mips32_op = OPC_RSQRT2_D;
17156 goto do_3d;
17157 case FMT_SDPS_PS:
17158 mips32_op = OPC_RSQRT2_PS;
17159 goto do_3d;
17160 default:
17161 goto pool32f_invalid;
17163 break;
17164 case RECIP2_FMT:
17165 switch (fmt) {
17166 case FMT_SDPS_S:
17167 mips32_op = OPC_RECIP2_S;
17168 goto do_3d;
17169 case FMT_SDPS_D:
17170 mips32_op = OPC_RECIP2_D;
17171 goto do_3d;
17172 case FMT_SDPS_PS:
17173 mips32_op = OPC_RECIP2_PS;
17174 goto do_3d;
17175 default:
17176 goto pool32f_invalid;
17178 break;
17179 case ADDR_PS:
17180 mips32_op = OPC_ADDR_PS;
17181 goto do_3d;
17182 case MULR_PS:
17183 mips32_op = OPC_MULR_PS;
17184 do_3d:
17185 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17186 break;
17187 default:
17188 goto pool32f_invalid;
17190 break;
17191 case 0x20:
17192 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
17193 cc = (ctx->opcode >> 13) & 0x7;
17194 fmt = (ctx->opcode >> 9) & 0x3;
17195 switch ((ctx->opcode >> 6) & 0x7) {
17196 case MOVF_FMT: /* RINT_FMT */
17197 if (ctx->insn_flags & ISA_MIPS32R6) {
17198 /* RINT_FMT */
17199 switch (fmt) {
17200 case FMT_SDPS_S:
17201 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17202 break;
17203 case FMT_SDPS_D:
17204 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17205 break;
17206 default:
17207 goto pool32f_invalid;
17209 } else {
17210 /* MOVF_FMT */
17211 switch (fmt) {
17212 case FMT_SDPS_S:
17213 gen_movcf_s(ctx, rs, rt, cc, 0);
17214 break;
17215 case FMT_SDPS_D:
17216 gen_movcf_d(ctx, rs, rt, cc, 0);
17217 break;
17218 case FMT_SDPS_PS:
17219 check_ps(ctx);
17220 gen_movcf_ps(ctx, rs, rt, cc, 0);
17221 break;
17222 default:
17223 goto pool32f_invalid;
17226 break;
17227 case MOVT_FMT: /* CLASS_FMT */
17228 if (ctx->insn_flags & ISA_MIPS32R6) {
17229 /* CLASS_FMT */
17230 switch (fmt) {
17231 case FMT_SDPS_S:
17232 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17233 break;
17234 case FMT_SDPS_D:
17235 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17236 break;
17237 default:
17238 goto pool32f_invalid;
17240 } else {
17241 /* MOVT_FMT */
17242 switch (fmt) {
17243 case FMT_SDPS_S:
17244 gen_movcf_s(ctx, rs, rt, cc, 1);
17245 break;
17246 case FMT_SDPS_D:
17247 gen_movcf_d(ctx, rs, rt, cc, 1);
17248 break;
17249 case FMT_SDPS_PS:
17250 check_ps(ctx);
17251 gen_movcf_ps(ctx, rs, rt, cc, 1);
17252 break;
17253 default:
17254 goto pool32f_invalid;
17257 break;
17258 case PREFX:
17259 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17260 break;
17261 default:
17262 goto pool32f_invalid;
17264 break;
17265 #define FINSN_3ARG_SDPS(prfx) \
17266 switch ((ctx->opcode >> 8) & 0x3) { \
17267 case FMT_SDPS_S: \
17268 mips32_op = OPC_##prfx##_S; \
17269 goto do_fpop; \
17270 case FMT_SDPS_D: \
17271 mips32_op = OPC_##prfx##_D; \
17272 goto do_fpop; \
17273 case FMT_SDPS_PS: \
17274 check_ps(ctx); \
17275 mips32_op = OPC_##prfx##_PS; \
17276 goto do_fpop; \
17277 default: \
17278 goto pool32f_invalid; \
17280 case MINA_FMT:
17281 check_insn(ctx, ISA_MIPS32R6);
17282 switch ((ctx->opcode >> 9) & 0x3) {
17283 case FMT_SDPS_S:
17284 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17285 break;
17286 case FMT_SDPS_D:
17287 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17288 break;
17289 default:
17290 goto pool32f_invalid;
17292 break;
17293 case MAXA_FMT:
17294 check_insn(ctx, ISA_MIPS32R6);
17295 switch ((ctx->opcode >> 9) & 0x3) {
17296 case FMT_SDPS_S:
17297 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17298 break;
17299 case FMT_SDPS_D:
17300 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17301 break;
17302 default:
17303 goto pool32f_invalid;
17305 break;
17306 case 0x30:
17307 /* regular FP ops */
17308 switch ((ctx->opcode >> 6) & 0x3) {
17309 case ADD_FMT:
17310 FINSN_3ARG_SDPS(ADD);
17311 break;
17312 case SUB_FMT:
17313 FINSN_3ARG_SDPS(SUB);
17314 break;
17315 case MUL_FMT:
17316 FINSN_3ARG_SDPS(MUL);
17317 break;
17318 case DIV_FMT:
17319 fmt = (ctx->opcode >> 8) & 0x3;
17320 if (fmt == 1) {
17321 mips32_op = OPC_DIV_D;
17322 } else if (fmt == 0) {
17323 mips32_op = OPC_DIV_S;
17324 } else {
17325 goto pool32f_invalid;
17327 goto do_fpop;
17328 default:
17329 goto pool32f_invalid;
17331 break;
17332 case 0x38:
17333 /* cmovs */
17334 switch ((ctx->opcode >> 6) & 0x7) {
17335 case MOVN_FMT: /* SELEQZ_FMT */
17336 if (ctx->insn_flags & ISA_MIPS32R6) {
17337 /* SELEQZ_FMT */
17338 switch ((ctx->opcode >> 9) & 0x3) {
17339 case FMT_SDPS_S:
17340 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
17341 break;
17342 case FMT_SDPS_D:
17343 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
17344 break;
17345 default:
17346 goto pool32f_invalid;
17348 } else {
17349 /* MOVN_FMT */
17350 FINSN_3ARG_SDPS(MOVN);
17352 break;
17353 case MOVN_FMT_04:
17354 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17355 FINSN_3ARG_SDPS(MOVN);
17356 break;
17357 case MOVZ_FMT: /* SELNEZ_FMT */
17358 if (ctx->insn_flags & ISA_MIPS32R6) {
17359 /* SELNEZ_FMT */
17360 switch ((ctx->opcode >> 9) & 0x3) {
17361 case FMT_SDPS_S:
17362 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
17363 break;
17364 case FMT_SDPS_D:
17365 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
17366 break;
17367 default:
17368 goto pool32f_invalid;
17370 } else {
17371 /* MOVZ_FMT */
17372 FINSN_3ARG_SDPS(MOVZ);
17374 break;
17375 case MOVZ_FMT_05:
17376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17377 FINSN_3ARG_SDPS(MOVZ);
17378 break;
17379 case SEL_FMT:
17380 check_insn(ctx, ISA_MIPS32R6);
17381 switch ((ctx->opcode >> 9) & 0x3) {
17382 case FMT_SDPS_S:
17383 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17384 break;
17385 case FMT_SDPS_D:
17386 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17387 break;
17388 default:
17389 goto pool32f_invalid;
17391 break;
17392 case MADDF_FMT:
17393 check_insn(ctx, ISA_MIPS32R6);
17394 switch ((ctx->opcode >> 9) & 0x3) {
17395 case FMT_SDPS_S:
17396 mips32_op = OPC_MADDF_S;
17397 goto do_fpop;
17398 case FMT_SDPS_D:
17399 mips32_op = OPC_MADDF_D;
17400 goto do_fpop;
17401 default:
17402 goto pool32f_invalid;
17404 break;
17405 case MSUBF_FMT:
17406 check_insn(ctx, ISA_MIPS32R6);
17407 switch ((ctx->opcode >> 9) & 0x3) {
17408 case FMT_SDPS_S:
17409 mips32_op = OPC_MSUBF_S;
17410 goto do_fpop;
17411 case FMT_SDPS_D:
17412 mips32_op = OPC_MSUBF_D;
17413 goto do_fpop;
17414 default:
17415 goto pool32f_invalid;
17417 break;
17418 default:
17419 goto pool32f_invalid;
17421 break;
17422 do_fpop:
17423 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17424 break;
17425 default:
17426 pool32f_invalid:
17427 MIPS_INVAL("pool32f");
17428 generate_exception_end(ctx, EXCP_RI);
17429 break;
17431 } else {
17432 generate_exception_err(ctx, EXCP_CpU, 1);
17434 break;
17435 case POOL32I:
17436 minor = (ctx->opcode >> 21) & 0x1f;
17437 switch (minor) {
17438 case BLTZ:
17439 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17440 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17441 break;
17442 case BLTZAL:
17443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17444 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17445 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17446 break;
17447 case BLTZALS:
17448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17449 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17450 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17451 break;
17452 case BGEZ:
17453 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17454 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17455 break;
17456 case BGEZAL:
17457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17458 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17459 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17460 break;
17461 case BGEZALS:
17462 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17463 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17464 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17465 break;
17466 case BLEZ:
17467 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17468 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17469 break;
17470 case BGTZ:
17471 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17472 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17473 break;
17475 /* Traps */
17476 case TLTI: /* BC1EQZC */
17477 if (ctx->insn_flags & ISA_MIPS32R6) {
17478 /* BC1EQZC */
17479 check_cp1_enabled(ctx);
17480 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17481 } else {
17482 /* TLTI */
17483 mips32_op = OPC_TLTI;
17484 goto do_trapi;
17486 break;
17487 case TGEI: /* BC1NEZC */
17488 if (ctx->insn_flags & ISA_MIPS32R6) {
17489 /* BC1NEZC */
17490 check_cp1_enabled(ctx);
17491 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17492 } else {
17493 /* TGEI */
17494 mips32_op = OPC_TGEI;
17495 goto do_trapi;
17497 break;
17498 case TLTIU:
17499 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17500 mips32_op = OPC_TLTIU;
17501 goto do_trapi;
17502 case TGEIU:
17503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17504 mips32_op = OPC_TGEIU;
17505 goto do_trapi;
17506 case TNEI: /* SYNCI */
17507 if (ctx->insn_flags & ISA_MIPS32R6) {
17508 /* SYNCI */
17510 * Break the TB to be able to sync copied instructions
17511 * immediately.
17513 ctx->base.is_jmp = DISAS_STOP;
17514 } else {
17515 /* TNEI */
17516 mips32_op = OPC_TNEI;
17517 goto do_trapi;
17519 break;
17520 case TEQI:
17521 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17522 mips32_op = OPC_TEQI;
17523 do_trapi:
17524 gen_trap(ctx, mips32_op, rs, -1, imm);
17525 break;
17527 case BNEZC:
17528 case BEQZC:
17529 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17530 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17531 4, rs, 0, imm << 1, 0);
17533 * Compact branches don't have a delay slot, so just let
17534 * the normal delay slot handling take us to the branch
17535 * target.
17537 break;
17538 case LUI:
17539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17540 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17541 break;
17542 case SYNCI:
17543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17545 * Break the TB to be able to sync copied instructions
17546 * immediately.
17548 ctx->base.is_jmp = DISAS_STOP;
17549 break;
17550 case BC2F:
17551 case BC2T:
17552 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17553 /* COP2: Not implemented. */
17554 generate_exception_err(ctx, EXCP_CpU, 2);
17555 break;
17556 case BC1F:
17557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17558 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17559 goto do_cp1branch;
17560 case BC1T:
17561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17562 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17563 goto do_cp1branch;
17564 case BC1ANY4F:
17565 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17566 mips32_op = OPC_BC1FANY4;
17567 goto do_cp1mips3d;
17568 case BC1ANY4T:
17569 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17570 mips32_op = OPC_BC1TANY4;
17571 do_cp1mips3d:
17572 check_cop1x(ctx);
17573 check_insn(ctx, ASE_MIPS3D);
17574 /* Fall through */
17575 do_cp1branch:
17576 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17577 check_cp1_enabled(ctx);
17578 gen_compute_branch1(ctx, mips32_op,
17579 (ctx->opcode >> 18) & 0x7, imm << 1);
17580 } else {
17581 generate_exception_err(ctx, EXCP_CpU, 1);
17583 break;
17584 case BPOSGE64:
17585 case BPOSGE32:
17586 /* MIPS DSP: not implemented */
17587 /* Fall through */
17588 default:
17589 MIPS_INVAL("pool32i");
17590 generate_exception_end(ctx, EXCP_RI);
17591 break;
17593 break;
17594 case POOL32C:
17595 minor = (ctx->opcode >> 12) & 0xf;
17596 offset = sextract32(ctx->opcode, 0,
17597 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
17598 switch (minor) {
17599 case LWL:
17600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17601 mips32_op = OPC_LWL;
17602 goto do_ld_lr;
17603 case SWL:
17604 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17605 mips32_op = OPC_SWL;
17606 goto do_st_lr;
17607 case LWR:
17608 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17609 mips32_op = OPC_LWR;
17610 goto do_ld_lr;
17611 case SWR:
17612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17613 mips32_op = OPC_SWR;
17614 goto do_st_lr;
17615 #if defined(TARGET_MIPS64)
17616 case LDL:
17617 check_insn(ctx, ISA_MIPS3);
17618 check_mips_64(ctx);
17619 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17620 mips32_op = OPC_LDL;
17621 goto do_ld_lr;
17622 case SDL:
17623 check_insn(ctx, ISA_MIPS3);
17624 check_mips_64(ctx);
17625 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17626 mips32_op = OPC_SDL;
17627 goto do_st_lr;
17628 case LDR:
17629 check_insn(ctx, ISA_MIPS3);
17630 check_mips_64(ctx);
17631 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17632 mips32_op = OPC_LDR;
17633 goto do_ld_lr;
17634 case SDR:
17635 check_insn(ctx, ISA_MIPS3);
17636 check_mips_64(ctx);
17637 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17638 mips32_op = OPC_SDR;
17639 goto do_st_lr;
17640 case LWU:
17641 check_insn(ctx, ISA_MIPS3);
17642 check_mips_64(ctx);
17643 mips32_op = OPC_LWU;
17644 goto do_ld_lr;
17645 case LLD:
17646 check_insn(ctx, ISA_MIPS3);
17647 check_mips_64(ctx);
17648 mips32_op = OPC_LLD;
17649 goto do_ld_lr;
17650 #endif
17651 case LL:
17652 mips32_op = OPC_LL;
17653 goto do_ld_lr;
17654 do_ld_lr:
17655 gen_ld(ctx, mips32_op, rt, rs, offset);
17656 break;
17657 do_st_lr:
17658 gen_st(ctx, mips32_op, rt, rs, offset);
17659 break;
17660 case SC:
17661 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17662 break;
17663 #if defined(TARGET_MIPS64)
17664 case SCD:
17665 check_insn(ctx, ISA_MIPS3);
17666 check_mips_64(ctx);
17667 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17668 break;
17669 #endif
17670 case LD_EVA:
17671 if (!ctx->eva) {
17672 MIPS_INVAL("pool32c ld-eva");
17673 generate_exception_end(ctx, EXCP_RI);
17674 break;
17676 check_cp0_enabled(ctx);
17678 minor2 = (ctx->opcode >> 9) & 0x7;
17679 offset = sextract32(ctx->opcode, 0, 9);
17680 switch (minor2) {
17681 case LBUE:
17682 mips32_op = OPC_LBUE;
17683 goto do_ld_lr;
17684 case LHUE:
17685 mips32_op = OPC_LHUE;
17686 goto do_ld_lr;
17687 case LWLE:
17688 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17689 mips32_op = OPC_LWLE;
17690 goto do_ld_lr;
17691 case LWRE:
17692 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17693 mips32_op = OPC_LWRE;
17694 goto do_ld_lr;
17695 case LBE:
17696 mips32_op = OPC_LBE;
17697 goto do_ld_lr;
17698 case LHE:
17699 mips32_op = OPC_LHE;
17700 goto do_ld_lr;
17701 case LLE:
17702 mips32_op = OPC_LLE;
17703 goto do_ld_lr;
17704 case LWE:
17705 mips32_op = OPC_LWE;
17706 goto do_ld_lr;
17708 break;
17709 case ST_EVA:
17710 if (!ctx->eva) {
17711 MIPS_INVAL("pool32c st-eva");
17712 generate_exception_end(ctx, EXCP_RI);
17713 break;
17715 check_cp0_enabled(ctx);
17717 minor2 = (ctx->opcode >> 9) & 0x7;
17718 offset = sextract32(ctx->opcode, 0, 9);
17719 switch (minor2) {
17720 case SWLE:
17721 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17722 mips32_op = OPC_SWLE;
17723 goto do_st_lr;
17724 case SWRE:
17725 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17726 mips32_op = OPC_SWRE;
17727 goto do_st_lr;
17728 case PREFE:
17729 /* Treat as no-op */
17730 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17731 /* hint codes 24-31 are reserved and signal RI */
17732 generate_exception(ctx, EXCP_RI);
17734 break;
17735 case CACHEE:
17736 /* Treat as no-op */
17737 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17738 gen_cache_operation(ctx, rt, rs, offset);
17740 break;
17741 case SBE:
17742 mips32_op = OPC_SBE;
17743 goto do_st_lr;
17744 case SHE:
17745 mips32_op = OPC_SHE;
17746 goto do_st_lr;
17747 case SCE:
17748 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17749 break;
17750 case SWE:
17751 mips32_op = OPC_SWE;
17752 goto do_st_lr;
17754 break;
17755 case PREF:
17756 /* Treat as no-op */
17757 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17758 /* hint codes 24-31 are reserved and signal RI */
17759 generate_exception(ctx, EXCP_RI);
17761 break;
17762 default:
17763 MIPS_INVAL("pool32c");
17764 generate_exception_end(ctx, EXCP_RI);
17765 break;
17767 break;
17768 case ADDI32: /* AUI, LUI */
17769 if (ctx->insn_flags & ISA_MIPS32R6) {
17770 /* AUI, LUI */
17771 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17772 } else {
17773 /* ADDI32 */
17774 mips32_op = OPC_ADDI;
17775 goto do_addi;
17777 break;
17778 case ADDIU32:
17779 mips32_op = OPC_ADDIU;
17780 do_addi:
17781 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17782 break;
17784 /* Logical operations */
17785 case ORI32:
17786 mips32_op = OPC_ORI;
17787 goto do_logici;
17788 case XORI32:
17789 mips32_op = OPC_XORI;
17790 goto do_logici;
17791 case ANDI32:
17792 mips32_op = OPC_ANDI;
17793 do_logici:
17794 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17795 break;
17797 /* Set less than immediate */
17798 case SLTI32:
17799 mips32_op = OPC_SLTI;
17800 goto do_slti;
17801 case SLTIU32:
17802 mips32_op = OPC_SLTIU;
17803 do_slti:
17804 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17805 break;
17806 case JALX32:
17807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17808 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17809 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17810 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17811 break;
17812 case JALS32: /* BOVC, BEQC, BEQZALC */
17813 if (ctx->insn_flags & ISA_MIPS32R6) {
17814 if (rs >= rt) {
17815 /* BOVC */
17816 mips32_op = OPC_BOVC;
17817 } else if (rs < rt && rs == 0) {
17818 /* BEQZALC */
17819 mips32_op = OPC_BEQZALC;
17820 } else {
17821 /* BEQC */
17822 mips32_op = OPC_BEQC;
17824 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17825 } else {
17826 /* JALS32 */
17827 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17828 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17829 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17831 break;
17832 case BEQ32: /* BC */
17833 if (ctx->insn_flags & ISA_MIPS32R6) {
17834 /* BC */
17835 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17836 sextract32(ctx->opcode << 1, 0, 27));
17837 } else {
17838 /* BEQ32 */
17839 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17841 break;
17842 case BNE32: /* BALC */
17843 if (ctx->insn_flags & ISA_MIPS32R6) {
17844 /* BALC */
17845 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17846 sextract32(ctx->opcode << 1, 0, 27));
17847 } else {
17848 /* BNE32 */
17849 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17851 break;
17852 case J32: /* BGTZC, BLTZC, BLTC */
17853 if (ctx->insn_flags & ISA_MIPS32R6) {
17854 if (rs == 0 && rt != 0) {
17855 /* BGTZC */
17856 mips32_op = OPC_BGTZC;
17857 } else if (rs != 0 && rt != 0 && rs == rt) {
17858 /* BLTZC */
17859 mips32_op = OPC_BLTZC;
17860 } else {
17861 /* BLTC */
17862 mips32_op = OPC_BLTC;
17864 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17865 } else {
17866 /* J32 */
17867 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17868 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17870 break;
17871 case JAL32: /* BLEZC, BGEZC, BGEC */
17872 if (ctx->insn_flags & ISA_MIPS32R6) {
17873 if (rs == 0 && rt != 0) {
17874 /* BLEZC */
17875 mips32_op = OPC_BLEZC;
17876 } else if (rs != 0 && rt != 0 && rs == rt) {
17877 /* BGEZC */
17878 mips32_op = OPC_BGEZC;
17879 } else {
17880 /* BGEC */
17881 mips32_op = OPC_BGEC;
17883 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17884 } else {
17885 /* JAL32 */
17886 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17887 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17888 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17890 break;
17891 /* Floating point (COP1) */
17892 case LWC132:
17893 mips32_op = OPC_LWC1;
17894 goto do_cop1;
17895 case LDC132:
17896 mips32_op = OPC_LDC1;
17897 goto do_cop1;
17898 case SWC132:
17899 mips32_op = OPC_SWC1;
17900 goto do_cop1;
17901 case SDC132:
17902 mips32_op = OPC_SDC1;
17903 do_cop1:
17904 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17905 break;
17906 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17907 if (ctx->insn_flags & ISA_MIPS32R6) {
17908 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17909 switch ((ctx->opcode >> 16) & 0x1f) {
17910 case ADDIUPC_00:
17911 case ADDIUPC_01:
17912 case ADDIUPC_02:
17913 case ADDIUPC_03:
17914 case ADDIUPC_04:
17915 case ADDIUPC_05:
17916 case ADDIUPC_06:
17917 case ADDIUPC_07:
17918 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17919 break;
17920 case AUIPC:
17921 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17922 break;
17923 case ALUIPC:
17924 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17925 break;
17926 case LWPC_08:
17927 case LWPC_09:
17928 case LWPC_0A:
17929 case LWPC_0B:
17930 case LWPC_0C:
17931 case LWPC_0D:
17932 case LWPC_0E:
17933 case LWPC_0F:
17934 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17935 break;
17936 default:
17937 generate_exception(ctx, EXCP_RI);
17938 break;
17940 } else {
17941 /* ADDIUPC */
17942 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17943 offset = SIMM(ctx->opcode, 0, 23) << 2;
17945 gen_addiupc(ctx, reg, offset, 0, 0);
17947 break;
17948 case BNVC: /* BNEC, BNEZALC */
17949 check_insn(ctx, ISA_MIPS32R6);
17950 if (rs >= rt) {
17951 /* BNVC */
17952 mips32_op = OPC_BNVC;
17953 } else if (rs < rt && rs == 0) {
17954 /* BNEZALC */
17955 mips32_op = OPC_BNEZALC;
17956 } else {
17957 /* BNEC */
17958 mips32_op = OPC_BNEC;
17960 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17961 break;
17962 case R6_BNEZC: /* JIALC */
17963 check_insn(ctx, ISA_MIPS32R6);
17964 if (rt != 0) {
17965 /* BNEZC */
17966 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17967 sextract32(ctx->opcode << 1, 0, 22));
17968 } else {
17969 /* JIALC */
17970 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17972 break;
17973 case R6_BEQZC: /* JIC */
17974 check_insn(ctx, ISA_MIPS32R6);
17975 if (rt != 0) {
17976 /* BEQZC */
17977 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17978 sextract32(ctx->opcode << 1, 0, 22));
17979 } else {
17980 /* JIC */
17981 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17983 break;
17984 case BLEZALC: /* BGEZALC, BGEUC */
17985 check_insn(ctx, ISA_MIPS32R6);
17986 if (rs == 0 && rt != 0) {
17987 /* BLEZALC */
17988 mips32_op = OPC_BLEZALC;
17989 } else if (rs != 0 && rt != 0 && rs == rt) {
17990 /* BGEZALC */
17991 mips32_op = OPC_BGEZALC;
17992 } else {
17993 /* BGEUC */
17994 mips32_op = OPC_BGEUC;
17996 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17997 break;
17998 case BGTZALC: /* BLTZALC, BLTUC */
17999 check_insn(ctx, ISA_MIPS32R6);
18000 if (rs == 0 && rt != 0) {
18001 /* BGTZALC */
18002 mips32_op = OPC_BGTZALC;
18003 } else if (rs != 0 && rt != 0 && rs == rt) {
18004 /* BLTZALC */
18005 mips32_op = OPC_BLTZALC;
18006 } else {
18007 /* BLTUC */
18008 mips32_op = OPC_BLTUC;
18010 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
18011 break;
18012 /* Loads and stores */
18013 case LB32:
18014 mips32_op = OPC_LB;
18015 goto do_ld;
18016 case LBU32:
18017 mips32_op = OPC_LBU;
18018 goto do_ld;
18019 case LH32:
18020 mips32_op = OPC_LH;
18021 goto do_ld;
18022 case LHU32:
18023 mips32_op = OPC_LHU;
18024 goto do_ld;
18025 case LW32:
18026 mips32_op = OPC_LW;
18027 goto do_ld;
18028 #ifdef TARGET_MIPS64
18029 case LD32:
18030 check_insn(ctx, ISA_MIPS3);
18031 check_mips_64(ctx);
18032 mips32_op = OPC_LD;
18033 goto do_ld;
18034 case SD32:
18035 check_insn(ctx, ISA_MIPS3);
18036 check_mips_64(ctx);
18037 mips32_op = OPC_SD;
18038 goto do_st;
18039 #endif
18040 case SB32:
18041 mips32_op = OPC_SB;
18042 goto do_st;
18043 case SH32:
18044 mips32_op = OPC_SH;
18045 goto do_st;
18046 case SW32:
18047 mips32_op = OPC_SW;
18048 goto do_st;
18049 do_ld:
18050 gen_ld(ctx, mips32_op, rt, rs, imm);
18051 break;
18052 do_st:
18053 gen_st(ctx, mips32_op, rt, rs, imm);
18054 break;
18055 default:
18056 generate_exception_end(ctx, EXCP_RI);
18057 break;
18061 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
18063 uint32_t op;
18065 /* make sure instructions are on a halfword boundary */
18066 if (ctx->base.pc_next & 0x1) {
18067 env->CP0_BadVAddr = ctx->base.pc_next;
18068 generate_exception_end(ctx, EXCP_AdEL);
18069 return 2;
18072 op = (ctx->opcode >> 10) & 0x3f;
18073 /* Enforce properly-sized instructions in a delay slot */
18074 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
18075 switch (op & 0x7) { /* MSB-3..MSB-5 */
18076 case 0:
18077 /* POOL32A, POOL32B, POOL32I, POOL32C */
18078 case 4:
18079 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
18080 case 5:
18081 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
18082 case 6:
18083 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
18084 case 7:
18085 /* LB32, LH32, LWC132, LDC132, LW32 */
18086 if (ctx->hflags & MIPS_HFLAG_BDS16) {
18087 generate_exception_end(ctx, EXCP_RI);
18088 return 2;
18090 break;
18091 case 1:
18092 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
18093 case 2:
18094 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
18095 case 3:
18096 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
18097 if (ctx->hflags & MIPS_HFLAG_BDS32) {
18098 generate_exception_end(ctx, EXCP_RI);
18099 return 2;
18101 break;
18105 switch (op) {
18106 case POOL16A:
18108 int rd = mmreg(uMIPS_RD(ctx->opcode));
18109 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
18110 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
18111 uint32_t opc = 0;
18113 switch (ctx->opcode & 0x1) {
18114 case ADDU16:
18115 opc = OPC_ADDU;
18116 break;
18117 case SUBU16:
18118 opc = OPC_SUBU;
18119 break;
18121 if (ctx->insn_flags & ISA_MIPS32R6) {
18123 * In the Release 6, the register number location in
18124 * the instruction encoding has changed.
18126 gen_arith(ctx, opc, rs1, rd, rs2);
18127 } else {
18128 gen_arith(ctx, opc, rd, rs1, rs2);
18131 break;
18132 case POOL16B:
18134 int rd = mmreg(uMIPS_RD(ctx->opcode));
18135 int rs = mmreg(uMIPS_RS(ctx->opcode));
18136 int amount = (ctx->opcode >> 1) & 0x7;
18137 uint32_t opc = 0;
18138 amount = amount == 0 ? 8 : amount;
18140 switch (ctx->opcode & 0x1) {
18141 case SLL16:
18142 opc = OPC_SLL;
18143 break;
18144 case SRL16:
18145 opc = OPC_SRL;
18146 break;
18149 gen_shift_imm(ctx, opc, rd, rs, amount);
18151 break;
18152 case POOL16C:
18153 if (ctx->insn_flags & ISA_MIPS32R6) {
18154 gen_pool16c_r6_insn(ctx);
18155 } else {
18156 gen_pool16c_insn(ctx);
18158 break;
18159 case LWGP16:
18161 int rd = mmreg(uMIPS_RD(ctx->opcode));
18162 int rb = 28; /* GP */
18163 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
18165 gen_ld(ctx, OPC_LW, rd, rb, offset);
18167 break;
18168 case POOL16F:
18169 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18170 if (ctx->opcode & 1) {
18171 generate_exception_end(ctx, EXCP_RI);
18172 } else {
18173 /* MOVEP */
18174 int enc_dest = uMIPS_RD(ctx->opcode);
18175 int enc_rt = uMIPS_RS2(ctx->opcode);
18176 int enc_rs = uMIPS_RS1(ctx->opcode);
18177 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
18179 break;
18180 case LBU16:
18182 int rd = mmreg(uMIPS_RD(ctx->opcode));
18183 int rb = mmreg(uMIPS_RS(ctx->opcode));
18184 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18185 offset = (offset == 0xf ? -1 : offset);
18187 gen_ld(ctx, OPC_LBU, rd, rb, offset);
18189 break;
18190 case LHU16:
18192 int rd = mmreg(uMIPS_RD(ctx->opcode));
18193 int rb = mmreg(uMIPS_RS(ctx->opcode));
18194 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18196 gen_ld(ctx, OPC_LHU, rd, rb, offset);
18198 break;
18199 case LWSP16:
18201 int rd = (ctx->opcode >> 5) & 0x1f;
18202 int rb = 29; /* SP */
18203 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18205 gen_ld(ctx, OPC_LW, rd, rb, offset);
18207 break;
18208 case LW16:
18210 int rd = mmreg(uMIPS_RD(ctx->opcode));
18211 int rb = mmreg(uMIPS_RS(ctx->opcode));
18212 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18214 gen_ld(ctx, OPC_LW, rd, rb, offset);
18216 break;
18217 case SB16:
18219 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18220 int rb = mmreg(uMIPS_RS(ctx->opcode));
18221 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18223 gen_st(ctx, OPC_SB, rd, rb, offset);
18225 break;
18226 case SH16:
18228 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18229 int rb = mmreg(uMIPS_RS(ctx->opcode));
18230 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18232 gen_st(ctx, OPC_SH, rd, rb, offset);
18234 break;
18235 case SWSP16:
18237 int rd = (ctx->opcode >> 5) & 0x1f;
18238 int rb = 29; /* SP */
18239 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18241 gen_st(ctx, OPC_SW, rd, rb, offset);
18243 break;
18244 case SW16:
18246 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18247 int rb = mmreg(uMIPS_RS(ctx->opcode));
18248 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18250 gen_st(ctx, OPC_SW, rd, rb, offset);
18252 break;
18253 case MOVE16:
18255 int rd = uMIPS_RD5(ctx->opcode);
18256 int rs = uMIPS_RS5(ctx->opcode);
18258 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
18260 break;
18261 case ANDI16:
18262 gen_andi16(ctx);
18263 break;
18264 case POOL16D:
18265 switch (ctx->opcode & 0x1) {
18266 case ADDIUS5:
18267 gen_addius5(ctx);
18268 break;
18269 case ADDIUSP:
18270 gen_addiusp(ctx);
18271 break;
18273 break;
18274 case POOL16E:
18275 switch (ctx->opcode & 0x1) {
18276 case ADDIUR2:
18277 gen_addiur2(ctx);
18278 break;
18279 case ADDIUR1SP:
18280 gen_addiur1sp(ctx);
18281 break;
18283 break;
18284 case B16: /* BC16 */
18285 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
18286 sextract32(ctx->opcode, 0, 10) << 1,
18287 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
18288 break;
18289 case BNEZ16: /* BNEZC16 */
18290 case BEQZ16: /* BEQZC16 */
18291 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
18292 mmreg(uMIPS_RD(ctx->opcode)),
18293 0, sextract32(ctx->opcode, 0, 7) << 1,
18294 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
18296 break;
18297 case LI16:
18299 int reg = mmreg(uMIPS_RD(ctx->opcode));
18300 int imm = ZIMM(ctx->opcode, 0, 7);
18302 imm = (imm == 0x7f ? -1 : imm);
18303 tcg_gen_movi_tl(cpu_gpr[reg], imm);
18305 break;
18306 case RES_29:
18307 case RES_31:
18308 case RES_39:
18309 generate_exception_end(ctx, EXCP_RI);
18310 break;
18311 default:
18312 decode_micromips32_opc(env, ctx);
18313 return 4;
18316 return 2;
18321 * nanoMIPS opcodes
18325 /* MAJOR, P16, and P32 pools opcodes */
18326 enum {
18327 NM_P_ADDIU = 0x00,
18328 NM_ADDIUPC = 0x01,
18329 NM_MOVE_BALC = 0x02,
18330 NM_P16_MV = 0x04,
18331 NM_LW16 = 0x05,
18332 NM_BC16 = 0x06,
18333 NM_P16_SR = 0x07,
18335 NM_POOL32A = 0x08,
18336 NM_P_BAL = 0x0a,
18337 NM_P16_SHIFT = 0x0c,
18338 NM_LWSP16 = 0x0d,
18339 NM_BALC16 = 0x0e,
18340 NM_P16_4X4 = 0x0f,
18342 NM_P_GP_W = 0x10,
18343 NM_P_GP_BH = 0x11,
18344 NM_P_J = 0x12,
18345 NM_P16C = 0x14,
18346 NM_LWGP16 = 0x15,
18347 NM_P16_LB = 0x17,
18349 NM_P48I = 0x18,
18350 NM_P16_A1 = 0x1c,
18351 NM_LW4X4 = 0x1d,
18352 NM_P16_LH = 0x1f,
18354 NM_P_U12 = 0x20,
18355 NM_P_LS_U12 = 0x21,
18356 NM_P_BR1 = 0x22,
18357 NM_P16_A2 = 0x24,
18358 NM_SW16 = 0x25,
18359 NM_BEQZC16 = 0x26,
18361 NM_POOL32F = 0x28,
18362 NM_P_LS_S9 = 0x29,
18363 NM_P_BR2 = 0x2a,
18365 NM_P16_ADDU = 0x2c,
18366 NM_SWSP16 = 0x2d,
18367 NM_BNEZC16 = 0x2e,
18368 NM_MOVEP = 0x2f,
18370 NM_POOL32S = 0x30,
18371 NM_P_BRI = 0x32,
18372 NM_LI16 = 0x34,
18373 NM_SWGP16 = 0x35,
18374 NM_P16_BR = 0x36,
18376 NM_P_LUI = 0x38,
18377 NM_ANDI16 = 0x3c,
18378 NM_SW4X4 = 0x3d,
18379 NM_MOVEPREV = 0x3f,
18382 /* POOL32A instruction pool */
18383 enum {
18384 NM_POOL32A0 = 0x00,
18385 NM_SPECIAL2 = 0x01,
18386 NM_COP2_1 = 0x02,
18387 NM_UDI = 0x03,
18388 NM_POOL32A5 = 0x05,
18389 NM_POOL32A7 = 0x07,
18392 /* P.GP.W instruction pool */
18393 enum {
18394 NM_ADDIUGP_W = 0x00,
18395 NM_LWGP = 0x02,
18396 NM_SWGP = 0x03,
18399 /* P48I instruction pool */
18400 enum {
18401 NM_LI48 = 0x00,
18402 NM_ADDIU48 = 0x01,
18403 NM_ADDIUGP48 = 0x02,
18404 NM_ADDIUPC48 = 0x03,
18405 NM_LWPC48 = 0x0b,
18406 NM_SWPC48 = 0x0f,
18409 /* P.U12 instruction pool */
18410 enum {
18411 NM_ORI = 0x00,
18412 NM_XORI = 0x01,
18413 NM_ANDI = 0x02,
18414 NM_P_SR = 0x03,
18415 NM_SLTI = 0x04,
18416 NM_SLTIU = 0x05,
18417 NM_SEQI = 0x06,
18418 NM_ADDIUNEG = 0x08,
18419 NM_P_SHIFT = 0x0c,
18420 NM_P_ROTX = 0x0d,
18421 NM_P_INS = 0x0e,
18422 NM_P_EXT = 0x0f,
18425 /* POOL32F instruction pool */
18426 enum {
18427 NM_POOL32F_0 = 0x00,
18428 NM_POOL32F_3 = 0x03,
18429 NM_POOL32F_5 = 0x05,
18432 /* POOL32S instruction pool */
18433 enum {
18434 NM_POOL32S_0 = 0x00,
18435 NM_POOL32S_4 = 0x04,
18438 /* P.LUI instruction pool */
18439 enum {
18440 NM_LUI = 0x00,
18441 NM_ALUIPC = 0x01,
18444 /* P.GP.BH instruction pool */
18445 enum {
18446 NM_LBGP = 0x00,
18447 NM_SBGP = 0x01,
18448 NM_LBUGP = 0x02,
18449 NM_ADDIUGP_B = 0x03,
18450 NM_P_GP_LH = 0x04,
18451 NM_P_GP_SH = 0x05,
18452 NM_P_GP_CP1 = 0x06,
18455 /* P.LS.U12 instruction pool */
18456 enum {
18457 NM_LB = 0x00,
18458 NM_SB = 0x01,
18459 NM_LBU = 0x02,
18460 NM_P_PREFU12 = 0x03,
18461 NM_LH = 0x04,
18462 NM_SH = 0x05,
18463 NM_LHU = 0x06,
18464 NM_LWU = 0x07,
18465 NM_LW = 0x08,
18466 NM_SW = 0x09,
18467 NM_LWC1 = 0x0a,
18468 NM_SWC1 = 0x0b,
18469 NM_LDC1 = 0x0e,
18470 NM_SDC1 = 0x0f,
18473 /* P.LS.S9 instruction pool */
18474 enum {
18475 NM_P_LS_S0 = 0x00,
18476 NM_P_LS_S1 = 0x01,
18477 NM_P_LS_E0 = 0x02,
18478 NM_P_LS_WM = 0x04,
18479 NM_P_LS_UAWM = 0x05,
18482 /* P.BAL instruction pool */
18483 enum {
18484 NM_BC = 0x00,
18485 NM_BALC = 0x01,
18488 /* P.J instruction pool */
18489 enum {
18490 NM_JALRC = 0x00,
18491 NM_JALRC_HB = 0x01,
18492 NM_P_BALRSC = 0x08,
18495 /* P.BR1 instruction pool */
18496 enum {
18497 NM_BEQC = 0x00,
18498 NM_P_BR3A = 0x01,
18499 NM_BGEC = 0x02,
18500 NM_BGEUC = 0x03,
18503 /* P.BR2 instruction pool */
18504 enum {
18505 NM_BNEC = 0x00,
18506 NM_BLTC = 0x02,
18507 NM_BLTUC = 0x03,
18510 /* P.BRI instruction pool */
18511 enum {
18512 NM_BEQIC = 0x00,
18513 NM_BBEQZC = 0x01,
18514 NM_BGEIC = 0x02,
18515 NM_BGEIUC = 0x03,
18516 NM_BNEIC = 0x04,
18517 NM_BBNEZC = 0x05,
18518 NM_BLTIC = 0x06,
18519 NM_BLTIUC = 0x07,
18522 /* P16.SHIFT instruction pool */
18523 enum {
18524 NM_SLL16 = 0x00,
18525 NM_SRL16 = 0x01,
18528 /* POOL16C instruction pool */
18529 enum {
18530 NM_POOL16C_0 = 0x00,
18531 NM_LWXS16 = 0x01,
18534 /* P16.A1 instruction pool */
18535 enum {
18536 NM_ADDIUR1SP = 0x01,
18539 /* P16.A2 instruction pool */
18540 enum {
18541 NM_ADDIUR2 = 0x00,
18542 NM_P_ADDIURS5 = 0x01,
18545 /* P16.ADDU instruction pool */
18546 enum {
18547 NM_ADDU16 = 0x00,
18548 NM_SUBU16 = 0x01,
18551 /* P16.SR instruction pool */
18552 enum {
18553 NM_SAVE16 = 0x00,
18554 NM_RESTORE_JRC16 = 0x01,
18557 /* P16.4X4 instruction pool */
18558 enum {
18559 NM_ADDU4X4 = 0x00,
18560 NM_MUL4X4 = 0x01,
18563 /* P16.LB instruction pool */
18564 enum {
18565 NM_LB16 = 0x00,
18566 NM_SB16 = 0x01,
18567 NM_LBU16 = 0x02,
18570 /* P16.LH instruction pool */
18571 enum {
18572 NM_LH16 = 0x00,
18573 NM_SH16 = 0x01,
18574 NM_LHU16 = 0x02,
18577 /* P.RI instruction pool */
18578 enum {
18579 NM_SIGRIE = 0x00,
18580 NM_P_SYSCALL = 0x01,
18581 NM_BREAK = 0x02,
18582 NM_SDBBP = 0x03,
18585 /* POOL32A0 instruction pool */
18586 enum {
18587 NM_P_TRAP = 0x00,
18588 NM_SEB = 0x01,
18589 NM_SLLV = 0x02,
18590 NM_MUL = 0x03,
18591 NM_MFC0 = 0x06,
18592 NM_MFHC0 = 0x07,
18593 NM_SEH = 0x09,
18594 NM_SRLV = 0x0a,
18595 NM_MUH = 0x0b,
18596 NM_MTC0 = 0x0e,
18597 NM_MTHC0 = 0x0f,
18598 NM_SRAV = 0x12,
18599 NM_MULU = 0x13,
18600 NM_ROTRV = 0x1a,
18601 NM_MUHU = 0x1b,
18602 NM_ADD = 0x22,
18603 NM_DIV = 0x23,
18604 NM_ADDU = 0x2a,
18605 NM_MOD = 0x2b,
18606 NM_SUB = 0x32,
18607 NM_DIVU = 0x33,
18608 NM_RDHWR = 0x38,
18609 NM_SUBU = 0x3a,
18610 NM_MODU = 0x3b,
18611 NM_P_CMOVE = 0x42,
18612 NM_FORK = 0x45,
18613 NM_MFTR = 0x46,
18614 NM_MFHTR = 0x47,
18615 NM_AND = 0x4a,
18616 NM_YIELD = 0x4d,
18617 NM_MTTR = 0x4e,
18618 NM_MTHTR = 0x4f,
18619 NM_OR = 0x52,
18620 NM_D_E_MT_VPE = 0x56,
18621 NM_NOR = 0x5a,
18622 NM_XOR = 0x62,
18623 NM_SLT = 0x6a,
18624 NM_P_SLTU = 0x72,
18625 NM_SOV = 0x7a,
18628 /* CRC32 instruction pool */
18629 enum {
18630 NM_CRC32B = 0x00,
18631 NM_CRC32H = 0x01,
18632 NM_CRC32W = 0x02,
18633 NM_CRC32CB = 0x04,
18634 NM_CRC32CH = 0x05,
18635 NM_CRC32CW = 0x06,
18638 /* POOL32A5 instruction pool */
18639 enum {
18640 NM_CMP_EQ_PH = 0x00,
18641 NM_CMP_LT_PH = 0x08,
18642 NM_CMP_LE_PH = 0x10,
18643 NM_CMPGU_EQ_QB = 0x18,
18644 NM_CMPGU_LT_QB = 0x20,
18645 NM_CMPGU_LE_QB = 0x28,
18646 NM_CMPGDU_EQ_QB = 0x30,
18647 NM_CMPGDU_LT_QB = 0x38,
18648 NM_CMPGDU_LE_QB = 0x40,
18649 NM_CMPU_EQ_QB = 0x48,
18650 NM_CMPU_LT_QB = 0x50,
18651 NM_CMPU_LE_QB = 0x58,
18652 NM_ADDQ_S_W = 0x60,
18653 NM_SUBQ_S_W = 0x68,
18654 NM_ADDSC = 0x70,
18655 NM_ADDWC = 0x78,
18657 NM_ADDQ_S_PH = 0x01,
18658 NM_ADDQH_R_PH = 0x09,
18659 NM_ADDQH_R_W = 0x11,
18660 NM_ADDU_S_QB = 0x19,
18661 NM_ADDU_S_PH = 0x21,
18662 NM_ADDUH_R_QB = 0x29,
18663 NM_SHRAV_R_PH = 0x31,
18664 NM_SHRAV_R_QB = 0x39,
18665 NM_SUBQ_S_PH = 0x41,
18666 NM_SUBQH_R_PH = 0x49,
18667 NM_SUBQH_R_W = 0x51,
18668 NM_SUBU_S_QB = 0x59,
18669 NM_SUBU_S_PH = 0x61,
18670 NM_SUBUH_R_QB = 0x69,
18671 NM_SHLLV_S_PH = 0x71,
18672 NM_PRECR_SRA_R_PH_W = 0x79,
18674 NM_MULEU_S_PH_QBL = 0x12,
18675 NM_MULEU_S_PH_QBR = 0x1a,
18676 NM_MULQ_RS_PH = 0x22,
18677 NM_MULQ_S_PH = 0x2a,
18678 NM_MULQ_RS_W = 0x32,
18679 NM_MULQ_S_W = 0x3a,
18680 NM_APPEND = 0x42,
18681 NM_MODSUB = 0x52,
18682 NM_SHRAV_R_W = 0x5a,
18683 NM_SHRLV_PH = 0x62,
18684 NM_SHRLV_QB = 0x6a,
18685 NM_SHLLV_QB = 0x72,
18686 NM_SHLLV_S_W = 0x7a,
18688 NM_SHILO = 0x03,
18690 NM_MULEQ_S_W_PHL = 0x04,
18691 NM_MULEQ_S_W_PHR = 0x0c,
18693 NM_MUL_S_PH = 0x05,
18694 NM_PRECR_QB_PH = 0x0d,
18695 NM_PRECRQ_QB_PH = 0x15,
18696 NM_PRECRQ_PH_W = 0x1d,
18697 NM_PRECRQ_RS_PH_W = 0x25,
18698 NM_PRECRQU_S_QB_PH = 0x2d,
18699 NM_PACKRL_PH = 0x35,
18700 NM_PICK_QB = 0x3d,
18701 NM_PICK_PH = 0x45,
18703 NM_SHRA_R_W = 0x5e,
18704 NM_SHRA_R_PH = 0x66,
18705 NM_SHLL_S_PH = 0x76,
18706 NM_SHLL_S_W = 0x7e,
18708 NM_REPL_PH = 0x07
18711 /* POOL32A7 instruction pool */
18712 enum {
18713 NM_P_LSX = 0x00,
18714 NM_LSA = 0x01,
18715 NM_EXTW = 0x03,
18716 NM_POOL32AXF = 0x07,
18719 /* P.SR instruction pool */
18720 enum {
18721 NM_PP_SR = 0x00,
18722 NM_P_SR_F = 0x01,
18725 /* P.SHIFT instruction pool */
18726 enum {
18727 NM_P_SLL = 0x00,
18728 NM_SRL = 0x02,
18729 NM_SRA = 0x04,
18730 NM_ROTR = 0x06,
18733 /* P.ROTX instruction pool */
18734 enum {
18735 NM_ROTX = 0x00,
18738 /* P.INS instruction pool */
18739 enum {
18740 NM_INS = 0x00,
18743 /* P.EXT instruction pool */
18744 enum {
18745 NM_EXT = 0x00,
18748 /* POOL32F_0 (fmt) instruction pool */
18749 enum {
18750 NM_RINT_S = 0x04,
18751 NM_RINT_D = 0x44,
18752 NM_ADD_S = 0x06,
18753 NM_SELEQZ_S = 0x07,
18754 NM_SELEQZ_D = 0x47,
18755 NM_CLASS_S = 0x0c,
18756 NM_CLASS_D = 0x4c,
18757 NM_SUB_S = 0x0e,
18758 NM_SELNEZ_S = 0x0f,
18759 NM_SELNEZ_D = 0x4f,
18760 NM_MUL_S = 0x16,
18761 NM_SEL_S = 0x17,
18762 NM_SEL_D = 0x57,
18763 NM_DIV_S = 0x1e,
18764 NM_ADD_D = 0x26,
18765 NM_SUB_D = 0x2e,
18766 NM_MUL_D = 0x36,
18767 NM_MADDF_S = 0x37,
18768 NM_MADDF_D = 0x77,
18769 NM_DIV_D = 0x3e,
18770 NM_MSUBF_S = 0x3f,
18771 NM_MSUBF_D = 0x7f,
18774 /* POOL32F_3 instruction pool */
18775 enum {
18776 NM_MIN_FMT = 0x00,
18777 NM_MAX_FMT = 0x01,
18778 NM_MINA_FMT = 0x04,
18779 NM_MAXA_FMT = 0x05,
18780 NM_POOL32FXF = 0x07,
18783 /* POOL32F_5 instruction pool */
18784 enum {
18785 NM_CMP_CONDN_S = 0x00,
18786 NM_CMP_CONDN_D = 0x02,
18789 /* P.GP.LH instruction pool */
18790 enum {
18791 NM_LHGP = 0x00,
18792 NM_LHUGP = 0x01,
18795 /* P.GP.SH instruction pool */
18796 enum {
18797 NM_SHGP = 0x00,
18800 /* P.GP.CP1 instruction pool */
18801 enum {
18802 NM_LWC1GP = 0x00,
18803 NM_SWC1GP = 0x01,
18804 NM_LDC1GP = 0x02,
18805 NM_SDC1GP = 0x03,
18808 /* P.LS.S0 instruction pool */
18809 enum {
18810 NM_LBS9 = 0x00,
18811 NM_LHS9 = 0x04,
18812 NM_LWS9 = 0x08,
18813 NM_LDS9 = 0x0c,
18815 NM_SBS9 = 0x01,
18816 NM_SHS9 = 0x05,
18817 NM_SWS9 = 0x09,
18818 NM_SDS9 = 0x0d,
18820 NM_LBUS9 = 0x02,
18821 NM_LHUS9 = 0x06,
18822 NM_LWC1S9 = 0x0a,
18823 NM_LDC1S9 = 0x0e,
18825 NM_P_PREFS9 = 0x03,
18826 NM_LWUS9 = 0x07,
18827 NM_SWC1S9 = 0x0b,
18828 NM_SDC1S9 = 0x0f,
18831 /* P.LS.S1 instruction pool */
18832 enum {
18833 NM_ASET_ACLR = 0x02,
18834 NM_UALH = 0x04,
18835 NM_UASH = 0x05,
18836 NM_CACHE = 0x07,
18837 NM_P_LL = 0x0a,
18838 NM_P_SC = 0x0b,
18841 /* P.LS.E0 instruction pool */
18842 enum {
18843 NM_LBE = 0x00,
18844 NM_SBE = 0x01,
18845 NM_LBUE = 0x02,
18846 NM_P_PREFE = 0x03,
18847 NM_LHE = 0x04,
18848 NM_SHE = 0x05,
18849 NM_LHUE = 0x06,
18850 NM_CACHEE = 0x07,
18851 NM_LWE = 0x08,
18852 NM_SWE = 0x09,
18853 NM_P_LLE = 0x0a,
18854 NM_P_SCE = 0x0b,
18857 /* P.PREFE instruction pool */
18858 enum {
18859 NM_SYNCIE = 0x00,
18860 NM_PREFE = 0x01,
18863 /* P.LLE instruction pool */
18864 enum {
18865 NM_LLE = 0x00,
18866 NM_LLWPE = 0x01,
18869 /* P.SCE instruction pool */
18870 enum {
18871 NM_SCE = 0x00,
18872 NM_SCWPE = 0x01,
18875 /* P.LS.WM instruction pool */
18876 enum {
18877 NM_LWM = 0x00,
18878 NM_SWM = 0x01,
18881 /* P.LS.UAWM instruction pool */
18882 enum {
18883 NM_UALWM = 0x00,
18884 NM_UASWM = 0x01,
18887 /* P.BR3A instruction pool */
18888 enum {
18889 NM_BC1EQZC = 0x00,
18890 NM_BC1NEZC = 0x01,
18891 NM_BC2EQZC = 0x02,
18892 NM_BC2NEZC = 0x03,
18893 NM_BPOSGE32C = 0x04,
18896 /* P16.RI instruction pool */
18897 enum {
18898 NM_P16_SYSCALL = 0x01,
18899 NM_BREAK16 = 0x02,
18900 NM_SDBBP16 = 0x03,
18903 /* POOL16C_0 instruction pool */
18904 enum {
18905 NM_POOL16C_00 = 0x00,
18908 /* P16.JRC instruction pool */
18909 enum {
18910 NM_JRC = 0x00,
18911 NM_JALRC16 = 0x01,
18914 /* P.SYSCALL instruction pool */
18915 enum {
18916 NM_SYSCALL = 0x00,
18917 NM_HYPCALL = 0x01,
18920 /* P.TRAP instruction pool */
18921 enum {
18922 NM_TEQ = 0x00,
18923 NM_TNE = 0x01,
18926 /* P.CMOVE instruction pool */
18927 enum {
18928 NM_MOVZ = 0x00,
18929 NM_MOVN = 0x01,
18932 /* POOL32Axf instruction pool */
18933 enum {
18934 NM_POOL32AXF_1 = 0x01,
18935 NM_POOL32AXF_2 = 0x02,
18936 NM_POOL32AXF_4 = 0x04,
18937 NM_POOL32AXF_5 = 0x05,
18938 NM_POOL32AXF_7 = 0x07,
18941 /* POOL32Axf_1 instruction pool */
18942 enum {
18943 NM_POOL32AXF_1_0 = 0x00,
18944 NM_POOL32AXF_1_1 = 0x01,
18945 NM_POOL32AXF_1_3 = 0x03,
18946 NM_POOL32AXF_1_4 = 0x04,
18947 NM_POOL32AXF_1_5 = 0x05,
18948 NM_POOL32AXF_1_7 = 0x07,
18951 /* POOL32Axf_2 instruction pool */
18952 enum {
18953 NM_POOL32AXF_2_0_7 = 0x00,
18954 NM_POOL32AXF_2_8_15 = 0x01,
18955 NM_POOL32AXF_2_16_23 = 0x02,
18956 NM_POOL32AXF_2_24_31 = 0x03,
18959 /* POOL32Axf_7 instruction pool */
18960 enum {
18961 NM_SHRA_R_QB = 0x0,
18962 NM_SHRL_PH = 0x1,
18963 NM_REPL_QB = 0x2,
18966 /* POOL32Axf_1_0 instruction pool */
18967 enum {
18968 NM_MFHI = 0x0,
18969 NM_MFLO = 0x1,
18970 NM_MTHI = 0x2,
18971 NM_MTLO = 0x3,
18974 /* POOL32Axf_1_1 instruction pool */
18975 enum {
18976 NM_MTHLIP = 0x0,
18977 NM_SHILOV = 0x1,
18980 /* POOL32Axf_1_3 instruction pool */
18981 enum {
18982 NM_RDDSP = 0x0,
18983 NM_WRDSP = 0x1,
18984 NM_EXTP = 0x2,
18985 NM_EXTPDP = 0x3,
18988 /* POOL32Axf_1_4 instruction pool */
18989 enum {
18990 NM_SHLL_QB = 0x0,
18991 NM_SHRL_QB = 0x1,
18994 /* POOL32Axf_1_5 instruction pool */
18995 enum {
18996 NM_MAQ_S_W_PHR = 0x0,
18997 NM_MAQ_S_W_PHL = 0x1,
18998 NM_MAQ_SA_W_PHR = 0x2,
18999 NM_MAQ_SA_W_PHL = 0x3,
19002 /* POOL32Axf_1_7 instruction pool */
19003 enum {
19004 NM_EXTR_W = 0x0,
19005 NM_EXTR_R_W = 0x1,
19006 NM_EXTR_RS_W = 0x2,
19007 NM_EXTR_S_H = 0x3,
19010 /* POOL32Axf_2_0_7 instruction pool */
19011 enum {
19012 NM_DPA_W_PH = 0x0,
19013 NM_DPAQ_S_W_PH = 0x1,
19014 NM_DPS_W_PH = 0x2,
19015 NM_DPSQ_S_W_PH = 0x3,
19016 NM_BALIGN = 0x4,
19017 NM_MADD = 0x5,
19018 NM_MULT = 0x6,
19019 NM_EXTRV_W = 0x7,
19022 /* POOL32Axf_2_8_15 instruction pool */
19023 enum {
19024 NM_DPAX_W_PH = 0x0,
19025 NM_DPAQ_SA_L_W = 0x1,
19026 NM_DPSX_W_PH = 0x2,
19027 NM_DPSQ_SA_L_W = 0x3,
19028 NM_MADDU = 0x5,
19029 NM_MULTU = 0x6,
19030 NM_EXTRV_R_W = 0x7,
19033 /* POOL32Axf_2_16_23 instruction pool */
19034 enum {
19035 NM_DPAU_H_QBL = 0x0,
19036 NM_DPAQX_S_W_PH = 0x1,
19037 NM_DPSU_H_QBL = 0x2,
19038 NM_DPSQX_S_W_PH = 0x3,
19039 NM_EXTPV = 0x4,
19040 NM_MSUB = 0x5,
19041 NM_MULSA_W_PH = 0x6,
19042 NM_EXTRV_RS_W = 0x7,
19045 /* POOL32Axf_2_24_31 instruction pool */
19046 enum {
19047 NM_DPAU_H_QBR = 0x0,
19048 NM_DPAQX_SA_W_PH = 0x1,
19049 NM_DPSU_H_QBR = 0x2,
19050 NM_DPSQX_SA_W_PH = 0x3,
19051 NM_EXTPDPV = 0x4,
19052 NM_MSUBU = 0x5,
19053 NM_MULSAQ_S_W_PH = 0x6,
19054 NM_EXTRV_S_H = 0x7,
19057 /* POOL32Axf_{4, 5} instruction pool */
19058 enum {
19059 NM_CLO = 0x25,
19060 NM_CLZ = 0x2d,
19062 NM_TLBP = 0x01,
19063 NM_TLBR = 0x09,
19064 NM_TLBWI = 0x11,
19065 NM_TLBWR = 0x19,
19066 NM_TLBINV = 0x03,
19067 NM_TLBINVF = 0x0b,
19068 NM_DI = 0x23,
19069 NM_EI = 0x2b,
19070 NM_RDPGPR = 0x70,
19071 NM_WRPGPR = 0x78,
19072 NM_WAIT = 0x61,
19073 NM_DERET = 0x71,
19074 NM_ERETX = 0x79,
19076 /* nanoMIPS DSP instructions */
19077 NM_ABSQ_S_QB = 0x00,
19078 NM_ABSQ_S_PH = 0x08,
19079 NM_ABSQ_S_W = 0x10,
19080 NM_PRECEQ_W_PHL = 0x28,
19081 NM_PRECEQ_W_PHR = 0x30,
19082 NM_PRECEQU_PH_QBL = 0x38,
19083 NM_PRECEQU_PH_QBR = 0x48,
19084 NM_PRECEU_PH_QBL = 0x58,
19085 NM_PRECEU_PH_QBR = 0x68,
19086 NM_PRECEQU_PH_QBLA = 0x39,
19087 NM_PRECEQU_PH_QBRA = 0x49,
19088 NM_PRECEU_PH_QBLA = 0x59,
19089 NM_PRECEU_PH_QBRA = 0x69,
19090 NM_REPLV_PH = 0x01,
19091 NM_REPLV_QB = 0x09,
19092 NM_BITREV = 0x18,
19093 NM_INSV = 0x20,
19094 NM_RADDU_W_QB = 0x78,
19096 NM_BITSWAP = 0x05,
19097 NM_WSBH = 0x3d,
19100 /* PP.SR instruction pool */
19101 enum {
19102 NM_SAVE = 0x00,
19103 NM_RESTORE = 0x02,
19104 NM_RESTORE_JRC = 0x03,
19107 /* P.SR.F instruction pool */
19108 enum {
19109 NM_SAVEF = 0x00,
19110 NM_RESTOREF = 0x01,
19113 /* P16.SYSCALL instruction pool */
19114 enum {
19115 NM_SYSCALL16 = 0x00,
19116 NM_HYPCALL16 = 0x01,
19119 /* POOL16C_00 instruction pool */
19120 enum {
19121 NM_NOT16 = 0x00,
19122 NM_XOR16 = 0x01,
19123 NM_AND16 = 0x02,
19124 NM_OR16 = 0x03,
19127 /* PP.LSX and PP.LSXS instruction pool */
19128 enum {
19129 NM_LBX = 0x00,
19130 NM_LHX = 0x04,
19131 NM_LWX = 0x08,
19132 NM_LDX = 0x0c,
19134 NM_SBX = 0x01,
19135 NM_SHX = 0x05,
19136 NM_SWX = 0x09,
19137 NM_SDX = 0x0d,
19139 NM_LBUX = 0x02,
19140 NM_LHUX = 0x06,
19141 NM_LWC1X = 0x0a,
19142 NM_LDC1X = 0x0e,
19144 NM_LWUX = 0x07,
19145 NM_SWC1X = 0x0b,
19146 NM_SDC1X = 0x0f,
19148 NM_LHXS = 0x04,
19149 NM_LWXS = 0x08,
19150 NM_LDXS = 0x0c,
19152 NM_SHXS = 0x05,
19153 NM_SWXS = 0x09,
19154 NM_SDXS = 0x0d,
19156 NM_LHUXS = 0x06,
19157 NM_LWC1XS = 0x0a,
19158 NM_LDC1XS = 0x0e,
19160 NM_LWUXS = 0x07,
19161 NM_SWC1XS = 0x0b,
19162 NM_SDC1XS = 0x0f,
19165 /* ERETx instruction pool */
19166 enum {
19167 NM_ERET = 0x00,
19168 NM_ERETNC = 0x01,
19171 /* POOL32FxF_{0, 1} insturction pool */
19172 enum {
19173 NM_CFC1 = 0x40,
19174 NM_CTC1 = 0x60,
19175 NM_MFC1 = 0x80,
19176 NM_MTC1 = 0xa0,
19177 NM_MFHC1 = 0xc0,
19178 NM_MTHC1 = 0xe0,
19180 NM_CVT_S_PL = 0x84,
19181 NM_CVT_S_PU = 0xa4,
19183 NM_CVT_L_S = 0x004,
19184 NM_CVT_L_D = 0x104,
19185 NM_CVT_W_S = 0x024,
19186 NM_CVT_W_D = 0x124,
19188 NM_RSQRT_S = 0x008,
19189 NM_RSQRT_D = 0x108,
19191 NM_SQRT_S = 0x028,
19192 NM_SQRT_D = 0x128,
19194 NM_RECIP_S = 0x048,
19195 NM_RECIP_D = 0x148,
19197 NM_FLOOR_L_S = 0x00c,
19198 NM_FLOOR_L_D = 0x10c,
19200 NM_FLOOR_W_S = 0x02c,
19201 NM_FLOOR_W_D = 0x12c,
19203 NM_CEIL_L_S = 0x04c,
19204 NM_CEIL_L_D = 0x14c,
19205 NM_CEIL_W_S = 0x06c,
19206 NM_CEIL_W_D = 0x16c,
19207 NM_TRUNC_L_S = 0x08c,
19208 NM_TRUNC_L_D = 0x18c,
19209 NM_TRUNC_W_S = 0x0ac,
19210 NM_TRUNC_W_D = 0x1ac,
19211 NM_ROUND_L_S = 0x0cc,
19212 NM_ROUND_L_D = 0x1cc,
19213 NM_ROUND_W_S = 0x0ec,
19214 NM_ROUND_W_D = 0x1ec,
19216 NM_MOV_S = 0x01,
19217 NM_MOV_D = 0x81,
19218 NM_ABS_S = 0x0d,
19219 NM_ABS_D = 0x8d,
19220 NM_NEG_S = 0x2d,
19221 NM_NEG_D = 0xad,
19222 NM_CVT_D_S = 0x04d,
19223 NM_CVT_D_W = 0x0cd,
19224 NM_CVT_D_L = 0x14d,
19225 NM_CVT_S_D = 0x06d,
19226 NM_CVT_S_W = 0x0ed,
19227 NM_CVT_S_L = 0x16d,
19230 /* P.LL instruction pool */
19231 enum {
19232 NM_LL = 0x00,
19233 NM_LLWP = 0x01,
19236 /* P.SC instruction pool */
19237 enum {
19238 NM_SC = 0x00,
19239 NM_SCWP = 0x01,
19242 /* P.DVP instruction pool */
19243 enum {
19244 NM_DVP = 0x00,
19245 NM_EVP = 0x01,
19251 * nanoMIPS decoding engine
19256 /* extraction utilities */
19258 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
19259 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
19260 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
19261 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
19262 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
19264 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
19265 static inline int decode_gpr_gpr3(int r)
19267 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
19269 return map[r & 0x7];
19272 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
19273 static inline int decode_gpr_gpr3_src_store(int r)
19275 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
19277 return map[r & 0x7];
19280 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
19281 static inline int decode_gpr_gpr4(int r)
19283 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
19284 16, 17, 18, 19, 20, 21, 22, 23 };
19286 return map[r & 0xf];
19289 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
19290 static inline int decode_gpr_gpr4_zero(int r)
19292 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
19293 16, 17, 18, 19, 20, 21, 22, 23 };
19295 return map[r & 0xf];
19299 static void gen_adjust_sp(DisasContext *ctx, int u)
19301 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
19304 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
19305 uint8_t gp, uint16_t u)
19307 int counter = 0;
19308 TCGv va = tcg_temp_new();
19309 TCGv t0 = tcg_temp_new();
19311 while (counter != count) {
19312 bool use_gp = gp && (counter == count - 1);
19313 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19314 int this_offset = -((counter + 1) << 2);
19315 gen_base_offset_addr(ctx, va, 29, this_offset);
19316 gen_load_gpr(t0, this_rt);
19317 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
19318 (MO_TEUL | ctx->default_tcg_memop_mask));
19319 counter++;
19322 /* adjust stack pointer */
19323 gen_adjust_sp(ctx, -u);
19325 tcg_temp_free(t0);
19326 tcg_temp_free(va);
19329 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
19330 uint8_t gp, uint16_t u)
19332 int counter = 0;
19333 TCGv va = tcg_temp_new();
19334 TCGv t0 = tcg_temp_new();
19336 while (counter != count) {
19337 bool use_gp = gp && (counter == count - 1);
19338 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19339 int this_offset = u - ((counter + 1) << 2);
19340 gen_base_offset_addr(ctx, va, 29, this_offset);
19341 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
19342 ctx->default_tcg_memop_mask);
19343 tcg_gen_ext32s_tl(t0, t0);
19344 gen_store_gpr(t0, this_rt);
19345 counter++;
19348 /* adjust stack pointer */
19349 gen_adjust_sp(ctx, u);
19351 tcg_temp_free(t0);
19352 tcg_temp_free(va);
19355 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
19357 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
19358 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
19360 switch (extract32(ctx->opcode, 2, 2)) {
19361 case NM_NOT16:
19362 gen_logic(ctx, OPC_NOR, rt, rs, 0);
19363 break;
19364 case NM_AND16:
19365 gen_logic(ctx, OPC_AND, rt, rt, rs);
19366 break;
19367 case NM_XOR16:
19368 gen_logic(ctx, OPC_XOR, rt, rt, rs);
19369 break;
19370 case NM_OR16:
19371 gen_logic(ctx, OPC_OR, rt, rt, rs);
19372 break;
19376 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19378 int rt = extract32(ctx->opcode, 21, 5);
19379 int rs = extract32(ctx->opcode, 16, 5);
19380 int rd = extract32(ctx->opcode, 11, 5);
19382 switch (extract32(ctx->opcode, 3, 7)) {
19383 case NM_P_TRAP:
19384 switch (extract32(ctx->opcode, 10, 1)) {
19385 case NM_TEQ:
19386 check_nms(ctx);
19387 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
19388 break;
19389 case NM_TNE:
19390 check_nms(ctx);
19391 gen_trap(ctx, OPC_TNE, rs, rt, -1);
19392 break;
19394 break;
19395 case NM_RDHWR:
19396 check_nms(ctx);
19397 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
19398 break;
19399 case NM_SEB:
19400 check_nms(ctx);
19401 gen_bshfl(ctx, OPC_SEB, rs, rt);
19402 break;
19403 case NM_SEH:
19404 gen_bshfl(ctx, OPC_SEH, rs, rt);
19405 break;
19406 case NM_SLLV:
19407 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
19408 break;
19409 case NM_SRLV:
19410 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19411 break;
19412 case NM_SRAV:
19413 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19414 break;
19415 case NM_ROTRV:
19416 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19417 break;
19418 case NM_ADD:
19419 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19420 break;
19421 case NM_ADDU:
19422 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19423 break;
19424 case NM_SUB:
19425 check_nms(ctx);
19426 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19427 break;
19428 case NM_SUBU:
19429 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19430 break;
19431 case NM_P_CMOVE:
19432 switch (extract32(ctx->opcode, 10, 1)) {
19433 case NM_MOVZ:
19434 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19435 break;
19436 case NM_MOVN:
19437 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19438 break;
19440 break;
19441 case NM_AND:
19442 gen_logic(ctx, OPC_AND, rd, rs, rt);
19443 break;
19444 case NM_OR:
19445 gen_logic(ctx, OPC_OR, rd, rs, rt);
19446 break;
19447 case NM_NOR:
19448 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19449 break;
19450 case NM_XOR:
19451 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19452 break;
19453 case NM_SLT:
19454 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19455 break;
19456 case NM_P_SLTU:
19457 if (rd == 0) {
19458 /* P_DVP */
19459 #ifndef CONFIG_USER_ONLY
19460 TCGv t0 = tcg_temp_new();
19461 switch (extract32(ctx->opcode, 10, 1)) {
19462 case NM_DVP:
19463 if (ctx->vp) {
19464 check_cp0_enabled(ctx);
19465 gen_helper_dvp(t0, cpu_env);
19466 gen_store_gpr(t0, rt);
19468 break;
19469 case NM_EVP:
19470 if (ctx->vp) {
19471 check_cp0_enabled(ctx);
19472 gen_helper_evp(t0, cpu_env);
19473 gen_store_gpr(t0, rt);
19475 break;
19477 tcg_temp_free(t0);
19478 #endif
19479 } else {
19480 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19482 break;
19483 case NM_SOV:
19485 TCGv t0 = tcg_temp_new();
19486 TCGv t1 = tcg_temp_new();
19487 TCGv t2 = tcg_temp_new();
19489 gen_load_gpr(t1, rs);
19490 gen_load_gpr(t2, rt);
19491 tcg_gen_add_tl(t0, t1, t2);
19492 tcg_gen_ext32s_tl(t0, t0);
19493 tcg_gen_xor_tl(t1, t1, t2);
19494 tcg_gen_xor_tl(t2, t0, t2);
19495 tcg_gen_andc_tl(t1, t2, t1);
19497 /* operands of same sign, result different sign */
19498 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19499 gen_store_gpr(t0, rd);
19501 tcg_temp_free(t0);
19502 tcg_temp_free(t1);
19503 tcg_temp_free(t2);
19505 break;
19506 case NM_MUL:
19507 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19508 break;
19509 case NM_MUH:
19510 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19511 break;
19512 case NM_MULU:
19513 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19514 break;
19515 case NM_MUHU:
19516 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19517 break;
19518 case NM_DIV:
19519 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19520 break;
19521 case NM_MOD:
19522 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19523 break;
19524 case NM_DIVU:
19525 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19526 break;
19527 case NM_MODU:
19528 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19529 break;
19530 #ifndef CONFIG_USER_ONLY
19531 case NM_MFC0:
19532 check_cp0_enabled(ctx);
19533 if (rt == 0) {
19534 /* Treat as NOP. */
19535 break;
19537 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19538 break;
19539 case NM_MTC0:
19540 check_cp0_enabled(ctx);
19542 TCGv t0 = tcg_temp_new();
19544 gen_load_gpr(t0, rt);
19545 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19546 tcg_temp_free(t0);
19548 break;
19549 case NM_D_E_MT_VPE:
19551 uint8_t sc = extract32(ctx->opcode, 10, 1);
19552 TCGv t0 = tcg_temp_new();
19554 switch (sc) {
19555 case 0:
19556 if (rs == 1) {
19557 /* DMT */
19558 check_cp0_mt(ctx);
19559 gen_helper_dmt(t0);
19560 gen_store_gpr(t0, rt);
19561 } else if (rs == 0) {
19562 /* DVPE */
19563 check_cp0_mt(ctx);
19564 gen_helper_dvpe(t0, cpu_env);
19565 gen_store_gpr(t0, rt);
19566 } else {
19567 generate_exception_end(ctx, EXCP_RI);
19569 break;
19570 case 1:
19571 if (rs == 1) {
19572 /* EMT */
19573 check_cp0_mt(ctx);
19574 gen_helper_emt(t0);
19575 gen_store_gpr(t0, rt);
19576 } else if (rs == 0) {
19577 /* EVPE */
19578 check_cp0_mt(ctx);
19579 gen_helper_evpe(t0, cpu_env);
19580 gen_store_gpr(t0, rt);
19581 } else {
19582 generate_exception_end(ctx, EXCP_RI);
19584 break;
19587 tcg_temp_free(t0);
19589 break;
19590 case NM_FORK:
19591 check_mt(ctx);
19593 TCGv t0 = tcg_temp_new();
19594 TCGv t1 = tcg_temp_new();
19596 gen_load_gpr(t0, rt);
19597 gen_load_gpr(t1, rs);
19598 gen_helper_fork(t0, t1);
19599 tcg_temp_free(t0);
19600 tcg_temp_free(t1);
19602 break;
19603 case NM_MFTR:
19604 case NM_MFHTR:
19605 check_cp0_enabled(ctx);
19606 if (rd == 0) {
19607 /* Treat as NOP. */
19608 return;
19610 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19611 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19612 break;
19613 case NM_MTTR:
19614 case NM_MTHTR:
19615 check_cp0_enabled(ctx);
19616 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19617 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19618 break;
19619 case NM_YIELD:
19620 check_mt(ctx);
19622 TCGv t0 = tcg_temp_new();
19624 gen_load_gpr(t0, rs);
19625 gen_helper_yield(t0, cpu_env, t0);
19626 gen_store_gpr(t0, rt);
19627 tcg_temp_free(t0);
19629 break;
19630 #endif
19631 default:
19632 generate_exception_end(ctx, EXCP_RI);
19633 break;
19637 /* dsp */
19638 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19639 int ret, int v1, int v2)
19641 TCGv_i32 t0;
19642 TCGv v0_t;
19643 TCGv v1_t;
19645 t0 = tcg_temp_new_i32();
19647 v0_t = tcg_temp_new();
19648 v1_t = tcg_temp_new();
19650 tcg_gen_movi_i32(t0, v2 >> 3);
19652 gen_load_gpr(v0_t, ret);
19653 gen_load_gpr(v1_t, v1);
19655 switch (opc) {
19656 case NM_MAQ_S_W_PHR:
19657 check_dsp(ctx);
19658 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19659 break;
19660 case NM_MAQ_S_W_PHL:
19661 check_dsp(ctx);
19662 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19663 break;
19664 case NM_MAQ_SA_W_PHR:
19665 check_dsp(ctx);
19666 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19667 break;
19668 case NM_MAQ_SA_W_PHL:
19669 check_dsp(ctx);
19670 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19671 break;
19672 default:
19673 generate_exception_end(ctx, EXCP_RI);
19674 break;
19677 tcg_temp_free_i32(t0);
19679 tcg_temp_free(v0_t);
19680 tcg_temp_free(v1_t);
19684 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19685 int ret, int v1, int v2)
19687 int16_t imm;
19688 TCGv t0 = tcg_temp_new();
19689 TCGv t1 = tcg_temp_new();
19690 TCGv v0_t = tcg_temp_new();
19692 gen_load_gpr(v0_t, v1);
19694 switch (opc) {
19695 case NM_POOL32AXF_1_0:
19696 check_dsp(ctx);
19697 switch (extract32(ctx->opcode, 12, 2)) {
19698 case NM_MFHI:
19699 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19700 break;
19701 case NM_MFLO:
19702 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19703 break;
19704 case NM_MTHI:
19705 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19706 break;
19707 case NM_MTLO:
19708 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19709 break;
19711 break;
19712 case NM_POOL32AXF_1_1:
19713 check_dsp(ctx);
19714 switch (extract32(ctx->opcode, 12, 2)) {
19715 case NM_MTHLIP:
19716 tcg_gen_movi_tl(t0, v2);
19717 gen_helper_mthlip(t0, v0_t, cpu_env);
19718 break;
19719 case NM_SHILOV:
19720 tcg_gen_movi_tl(t0, v2 >> 3);
19721 gen_helper_shilo(t0, v0_t, cpu_env);
19722 break;
19723 default:
19724 generate_exception_end(ctx, EXCP_RI);
19725 break;
19727 break;
19728 case NM_POOL32AXF_1_3:
19729 check_dsp(ctx);
19730 imm = extract32(ctx->opcode, 14, 7);
19731 switch (extract32(ctx->opcode, 12, 2)) {
19732 case NM_RDDSP:
19733 tcg_gen_movi_tl(t0, imm);
19734 gen_helper_rddsp(t0, t0, cpu_env);
19735 gen_store_gpr(t0, ret);
19736 break;
19737 case NM_WRDSP:
19738 gen_load_gpr(t0, ret);
19739 tcg_gen_movi_tl(t1, imm);
19740 gen_helper_wrdsp(t0, t1, cpu_env);
19741 break;
19742 case NM_EXTP:
19743 tcg_gen_movi_tl(t0, v2 >> 3);
19744 tcg_gen_movi_tl(t1, v1);
19745 gen_helper_extp(t0, t0, t1, cpu_env);
19746 gen_store_gpr(t0, ret);
19747 break;
19748 case NM_EXTPDP:
19749 tcg_gen_movi_tl(t0, v2 >> 3);
19750 tcg_gen_movi_tl(t1, v1);
19751 gen_helper_extpdp(t0, t0, t1, cpu_env);
19752 gen_store_gpr(t0, ret);
19753 break;
19755 break;
19756 case NM_POOL32AXF_1_4:
19757 check_dsp(ctx);
19758 tcg_gen_movi_tl(t0, v2 >> 2);
19759 switch (extract32(ctx->opcode, 12, 1)) {
19760 case NM_SHLL_QB:
19761 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19762 gen_store_gpr(t0, ret);
19763 break;
19764 case NM_SHRL_QB:
19765 gen_helper_shrl_qb(t0, t0, v0_t);
19766 gen_store_gpr(t0, ret);
19767 break;
19769 break;
19770 case NM_POOL32AXF_1_5:
19771 opc = extract32(ctx->opcode, 12, 2);
19772 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19773 break;
19774 case NM_POOL32AXF_1_7:
19775 check_dsp(ctx);
19776 tcg_gen_movi_tl(t0, v2 >> 3);
19777 tcg_gen_movi_tl(t1, v1);
19778 switch (extract32(ctx->opcode, 12, 2)) {
19779 case NM_EXTR_W:
19780 gen_helper_extr_w(t0, t0, t1, cpu_env);
19781 gen_store_gpr(t0, ret);
19782 break;
19783 case NM_EXTR_R_W:
19784 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19785 gen_store_gpr(t0, ret);
19786 break;
19787 case NM_EXTR_RS_W:
19788 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19789 gen_store_gpr(t0, ret);
19790 break;
19791 case NM_EXTR_S_H:
19792 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19793 gen_store_gpr(t0, ret);
19794 break;
19796 break;
19797 default:
19798 generate_exception_end(ctx, EXCP_RI);
19799 break;
19802 tcg_temp_free(t0);
19803 tcg_temp_free(t1);
19804 tcg_temp_free(v0_t);
19807 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19808 TCGv v0, TCGv v1, int rd)
19810 TCGv_i32 t0;
19812 t0 = tcg_temp_new_i32();
19814 tcg_gen_movi_i32(t0, rd >> 3);
19816 switch (opc) {
19817 case NM_POOL32AXF_2_0_7:
19818 switch (extract32(ctx->opcode, 9, 3)) {
19819 case NM_DPA_W_PH:
19820 check_dsp_r2(ctx);
19821 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19822 break;
19823 case NM_DPAQ_S_W_PH:
19824 check_dsp(ctx);
19825 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19826 break;
19827 case NM_DPS_W_PH:
19828 check_dsp_r2(ctx);
19829 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19830 break;
19831 case NM_DPSQ_S_W_PH:
19832 check_dsp(ctx);
19833 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19834 break;
19835 default:
19836 generate_exception_end(ctx, EXCP_RI);
19837 break;
19839 break;
19840 case NM_POOL32AXF_2_8_15:
19841 switch (extract32(ctx->opcode, 9, 3)) {
19842 case NM_DPAX_W_PH:
19843 check_dsp_r2(ctx);
19844 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19845 break;
19846 case NM_DPAQ_SA_L_W:
19847 check_dsp(ctx);
19848 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19849 break;
19850 case NM_DPSX_W_PH:
19851 check_dsp_r2(ctx);
19852 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19853 break;
19854 case NM_DPSQ_SA_L_W:
19855 check_dsp(ctx);
19856 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19857 break;
19858 default:
19859 generate_exception_end(ctx, EXCP_RI);
19860 break;
19862 break;
19863 case NM_POOL32AXF_2_16_23:
19864 switch (extract32(ctx->opcode, 9, 3)) {
19865 case NM_DPAU_H_QBL:
19866 check_dsp(ctx);
19867 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19868 break;
19869 case NM_DPAQX_S_W_PH:
19870 check_dsp_r2(ctx);
19871 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19872 break;
19873 case NM_DPSU_H_QBL:
19874 check_dsp(ctx);
19875 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19876 break;
19877 case NM_DPSQX_S_W_PH:
19878 check_dsp_r2(ctx);
19879 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19880 break;
19881 case NM_MULSA_W_PH:
19882 check_dsp_r2(ctx);
19883 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19884 break;
19885 default:
19886 generate_exception_end(ctx, EXCP_RI);
19887 break;
19889 break;
19890 case NM_POOL32AXF_2_24_31:
19891 switch (extract32(ctx->opcode, 9, 3)) {
19892 case NM_DPAU_H_QBR:
19893 check_dsp(ctx);
19894 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19895 break;
19896 case NM_DPAQX_SA_W_PH:
19897 check_dsp_r2(ctx);
19898 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19899 break;
19900 case NM_DPSU_H_QBR:
19901 check_dsp(ctx);
19902 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19903 break;
19904 case NM_DPSQX_SA_W_PH:
19905 check_dsp_r2(ctx);
19906 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19907 break;
19908 case NM_MULSAQ_S_W_PH:
19909 check_dsp(ctx);
19910 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19911 break;
19912 default:
19913 generate_exception_end(ctx, EXCP_RI);
19914 break;
19916 break;
19917 default:
19918 generate_exception_end(ctx, EXCP_RI);
19919 break;
19922 tcg_temp_free_i32(t0);
19925 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19926 int rt, int rs, int rd)
19928 int ret = rt;
19929 TCGv t0 = tcg_temp_new();
19930 TCGv t1 = tcg_temp_new();
19931 TCGv v0_t = tcg_temp_new();
19932 TCGv v1_t = tcg_temp_new();
19934 gen_load_gpr(v0_t, rt);
19935 gen_load_gpr(v1_t, rs);
19937 switch (opc) {
19938 case NM_POOL32AXF_2_0_7:
19939 switch (extract32(ctx->opcode, 9, 3)) {
19940 case NM_DPA_W_PH:
19941 case NM_DPAQ_S_W_PH:
19942 case NM_DPS_W_PH:
19943 case NM_DPSQ_S_W_PH:
19944 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19945 break;
19946 case NM_BALIGN:
19947 check_dsp_r2(ctx);
19948 if (rt != 0) {
19949 gen_load_gpr(t0, rs);
19950 rd &= 3;
19951 if (rd != 0 && rd != 2) {
19952 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19953 tcg_gen_ext32u_tl(t0, t0);
19954 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19955 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19957 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19959 break;
19960 case NM_MADD:
19961 check_dsp(ctx);
19963 int acc = extract32(ctx->opcode, 14, 2);
19964 TCGv_i64 t2 = tcg_temp_new_i64();
19965 TCGv_i64 t3 = tcg_temp_new_i64();
19967 gen_load_gpr(t0, rt);
19968 gen_load_gpr(t1, rs);
19969 tcg_gen_ext_tl_i64(t2, t0);
19970 tcg_gen_ext_tl_i64(t3, t1);
19971 tcg_gen_mul_i64(t2, t2, t3);
19972 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19973 tcg_gen_add_i64(t2, t2, t3);
19974 tcg_temp_free_i64(t3);
19975 gen_move_low32(cpu_LO[acc], t2);
19976 gen_move_high32(cpu_HI[acc], t2);
19977 tcg_temp_free_i64(t2);
19979 break;
19980 case NM_MULT:
19981 check_dsp(ctx);
19983 int acc = extract32(ctx->opcode, 14, 2);
19984 TCGv_i32 t2 = tcg_temp_new_i32();
19985 TCGv_i32 t3 = tcg_temp_new_i32();
19987 gen_load_gpr(t0, rs);
19988 gen_load_gpr(t1, rt);
19989 tcg_gen_trunc_tl_i32(t2, t0);
19990 tcg_gen_trunc_tl_i32(t3, t1);
19991 tcg_gen_muls2_i32(t2, t3, t2, t3);
19992 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19993 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19994 tcg_temp_free_i32(t2);
19995 tcg_temp_free_i32(t3);
19997 break;
19998 case NM_EXTRV_W:
19999 check_dsp(ctx);
20000 gen_load_gpr(v1_t, rs);
20001 tcg_gen_movi_tl(t0, rd >> 3);
20002 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
20003 gen_store_gpr(t0, ret);
20004 break;
20006 break;
20007 case NM_POOL32AXF_2_8_15:
20008 switch (extract32(ctx->opcode, 9, 3)) {
20009 case NM_DPAX_W_PH:
20010 case NM_DPAQ_SA_L_W:
20011 case NM_DPSX_W_PH:
20012 case NM_DPSQ_SA_L_W:
20013 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20014 break;
20015 case NM_MADDU:
20016 check_dsp(ctx);
20018 int acc = extract32(ctx->opcode, 14, 2);
20019 TCGv_i64 t2 = tcg_temp_new_i64();
20020 TCGv_i64 t3 = tcg_temp_new_i64();
20022 gen_load_gpr(t0, rs);
20023 gen_load_gpr(t1, rt);
20024 tcg_gen_ext32u_tl(t0, t0);
20025 tcg_gen_ext32u_tl(t1, t1);
20026 tcg_gen_extu_tl_i64(t2, t0);
20027 tcg_gen_extu_tl_i64(t3, t1);
20028 tcg_gen_mul_i64(t2, t2, t3);
20029 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20030 tcg_gen_add_i64(t2, t2, t3);
20031 tcg_temp_free_i64(t3);
20032 gen_move_low32(cpu_LO[acc], t2);
20033 gen_move_high32(cpu_HI[acc], t2);
20034 tcg_temp_free_i64(t2);
20036 break;
20037 case NM_MULTU:
20038 check_dsp(ctx);
20040 int acc = extract32(ctx->opcode, 14, 2);
20041 TCGv_i32 t2 = tcg_temp_new_i32();
20042 TCGv_i32 t3 = tcg_temp_new_i32();
20044 gen_load_gpr(t0, rs);
20045 gen_load_gpr(t1, rt);
20046 tcg_gen_trunc_tl_i32(t2, t0);
20047 tcg_gen_trunc_tl_i32(t3, t1);
20048 tcg_gen_mulu2_i32(t2, t3, t2, t3);
20049 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
20050 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
20051 tcg_temp_free_i32(t2);
20052 tcg_temp_free_i32(t3);
20054 break;
20055 case NM_EXTRV_R_W:
20056 check_dsp(ctx);
20057 tcg_gen_movi_tl(t0, rd >> 3);
20058 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
20059 gen_store_gpr(t0, ret);
20060 break;
20061 default:
20062 generate_exception_end(ctx, EXCP_RI);
20063 break;
20065 break;
20066 case NM_POOL32AXF_2_16_23:
20067 switch (extract32(ctx->opcode, 9, 3)) {
20068 case NM_DPAU_H_QBL:
20069 case NM_DPAQX_S_W_PH:
20070 case NM_DPSU_H_QBL:
20071 case NM_DPSQX_S_W_PH:
20072 case NM_MULSA_W_PH:
20073 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20074 break;
20075 case NM_EXTPV:
20076 check_dsp(ctx);
20077 tcg_gen_movi_tl(t0, rd >> 3);
20078 gen_helper_extp(t0, t0, v1_t, cpu_env);
20079 gen_store_gpr(t0, ret);
20080 break;
20081 case NM_MSUB:
20082 check_dsp(ctx);
20084 int acc = extract32(ctx->opcode, 14, 2);
20085 TCGv_i64 t2 = tcg_temp_new_i64();
20086 TCGv_i64 t3 = tcg_temp_new_i64();
20088 gen_load_gpr(t0, rs);
20089 gen_load_gpr(t1, rt);
20090 tcg_gen_ext_tl_i64(t2, t0);
20091 tcg_gen_ext_tl_i64(t3, t1);
20092 tcg_gen_mul_i64(t2, t2, t3);
20093 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20094 tcg_gen_sub_i64(t2, t3, t2);
20095 tcg_temp_free_i64(t3);
20096 gen_move_low32(cpu_LO[acc], t2);
20097 gen_move_high32(cpu_HI[acc], t2);
20098 tcg_temp_free_i64(t2);
20100 break;
20101 case NM_EXTRV_RS_W:
20102 check_dsp(ctx);
20103 tcg_gen_movi_tl(t0, rd >> 3);
20104 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
20105 gen_store_gpr(t0, ret);
20106 break;
20108 break;
20109 case NM_POOL32AXF_2_24_31:
20110 switch (extract32(ctx->opcode, 9, 3)) {
20111 case NM_DPAU_H_QBR:
20112 case NM_DPAQX_SA_W_PH:
20113 case NM_DPSU_H_QBR:
20114 case NM_DPSQX_SA_W_PH:
20115 case NM_MULSAQ_S_W_PH:
20116 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20117 break;
20118 case NM_EXTPDPV:
20119 check_dsp(ctx);
20120 tcg_gen_movi_tl(t0, rd >> 3);
20121 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
20122 gen_store_gpr(t0, ret);
20123 break;
20124 case NM_MSUBU:
20125 check_dsp(ctx);
20127 int acc = extract32(ctx->opcode, 14, 2);
20128 TCGv_i64 t2 = tcg_temp_new_i64();
20129 TCGv_i64 t3 = tcg_temp_new_i64();
20131 gen_load_gpr(t0, rs);
20132 gen_load_gpr(t1, rt);
20133 tcg_gen_ext32u_tl(t0, t0);
20134 tcg_gen_ext32u_tl(t1, t1);
20135 tcg_gen_extu_tl_i64(t2, t0);
20136 tcg_gen_extu_tl_i64(t3, t1);
20137 tcg_gen_mul_i64(t2, t2, t3);
20138 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20139 tcg_gen_sub_i64(t2, t3, t2);
20140 tcg_temp_free_i64(t3);
20141 gen_move_low32(cpu_LO[acc], t2);
20142 gen_move_high32(cpu_HI[acc], t2);
20143 tcg_temp_free_i64(t2);
20145 break;
20146 case NM_EXTRV_S_H:
20147 check_dsp(ctx);
20148 tcg_gen_movi_tl(t0, rd >> 3);
20149 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
20150 gen_store_gpr(t0, ret);
20151 break;
20153 break;
20154 default:
20155 generate_exception_end(ctx, EXCP_RI);
20156 break;
20159 tcg_temp_free(t0);
20160 tcg_temp_free(t1);
20162 tcg_temp_free(v0_t);
20163 tcg_temp_free(v1_t);
20166 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
20167 int rt, int rs)
20169 int ret = rt;
20170 TCGv t0 = tcg_temp_new();
20171 TCGv v0_t = tcg_temp_new();
20173 gen_load_gpr(v0_t, rs);
20175 switch (opc) {
20176 case NM_ABSQ_S_QB:
20177 check_dsp_r2(ctx);
20178 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
20179 gen_store_gpr(v0_t, ret);
20180 break;
20181 case NM_ABSQ_S_PH:
20182 check_dsp(ctx);
20183 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
20184 gen_store_gpr(v0_t, ret);
20185 break;
20186 case NM_ABSQ_S_W:
20187 check_dsp(ctx);
20188 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
20189 gen_store_gpr(v0_t, ret);
20190 break;
20191 case NM_PRECEQ_W_PHL:
20192 check_dsp(ctx);
20193 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
20194 tcg_gen_ext32s_tl(v0_t, v0_t);
20195 gen_store_gpr(v0_t, ret);
20196 break;
20197 case NM_PRECEQ_W_PHR:
20198 check_dsp(ctx);
20199 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
20200 tcg_gen_shli_tl(v0_t, v0_t, 16);
20201 tcg_gen_ext32s_tl(v0_t, v0_t);
20202 gen_store_gpr(v0_t, ret);
20203 break;
20204 case NM_PRECEQU_PH_QBL:
20205 check_dsp(ctx);
20206 gen_helper_precequ_ph_qbl(v0_t, v0_t);
20207 gen_store_gpr(v0_t, ret);
20208 break;
20209 case NM_PRECEQU_PH_QBR:
20210 check_dsp(ctx);
20211 gen_helper_precequ_ph_qbr(v0_t, v0_t);
20212 gen_store_gpr(v0_t, ret);
20213 break;
20214 case NM_PRECEQU_PH_QBLA:
20215 check_dsp(ctx);
20216 gen_helper_precequ_ph_qbla(v0_t, v0_t);
20217 gen_store_gpr(v0_t, ret);
20218 break;
20219 case NM_PRECEQU_PH_QBRA:
20220 check_dsp(ctx);
20221 gen_helper_precequ_ph_qbra(v0_t, v0_t);
20222 gen_store_gpr(v0_t, ret);
20223 break;
20224 case NM_PRECEU_PH_QBL:
20225 check_dsp(ctx);
20226 gen_helper_preceu_ph_qbl(v0_t, v0_t);
20227 gen_store_gpr(v0_t, ret);
20228 break;
20229 case NM_PRECEU_PH_QBR:
20230 check_dsp(ctx);
20231 gen_helper_preceu_ph_qbr(v0_t, v0_t);
20232 gen_store_gpr(v0_t, ret);
20233 break;
20234 case NM_PRECEU_PH_QBLA:
20235 check_dsp(ctx);
20236 gen_helper_preceu_ph_qbla(v0_t, v0_t);
20237 gen_store_gpr(v0_t, ret);
20238 break;
20239 case NM_PRECEU_PH_QBRA:
20240 check_dsp(ctx);
20241 gen_helper_preceu_ph_qbra(v0_t, v0_t);
20242 gen_store_gpr(v0_t, ret);
20243 break;
20244 case NM_REPLV_PH:
20245 check_dsp(ctx);
20246 tcg_gen_ext16u_tl(v0_t, v0_t);
20247 tcg_gen_shli_tl(t0, v0_t, 16);
20248 tcg_gen_or_tl(v0_t, v0_t, t0);
20249 tcg_gen_ext32s_tl(v0_t, v0_t);
20250 gen_store_gpr(v0_t, ret);
20251 break;
20252 case NM_REPLV_QB:
20253 check_dsp(ctx);
20254 tcg_gen_ext8u_tl(v0_t, v0_t);
20255 tcg_gen_shli_tl(t0, v0_t, 8);
20256 tcg_gen_or_tl(v0_t, v0_t, t0);
20257 tcg_gen_shli_tl(t0, v0_t, 16);
20258 tcg_gen_or_tl(v0_t, v0_t, t0);
20259 tcg_gen_ext32s_tl(v0_t, v0_t);
20260 gen_store_gpr(v0_t, ret);
20261 break;
20262 case NM_BITREV:
20263 check_dsp(ctx);
20264 gen_helper_bitrev(v0_t, v0_t);
20265 gen_store_gpr(v0_t, ret);
20266 break;
20267 case NM_INSV:
20268 check_dsp(ctx);
20270 TCGv tv0 = tcg_temp_new();
20272 gen_load_gpr(tv0, rt);
20273 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
20274 gen_store_gpr(v0_t, ret);
20275 tcg_temp_free(tv0);
20277 break;
20278 case NM_RADDU_W_QB:
20279 check_dsp(ctx);
20280 gen_helper_raddu_w_qb(v0_t, v0_t);
20281 gen_store_gpr(v0_t, ret);
20282 break;
20283 case NM_BITSWAP:
20284 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
20285 break;
20286 case NM_CLO:
20287 check_nms(ctx);
20288 gen_cl(ctx, OPC_CLO, ret, rs);
20289 break;
20290 case NM_CLZ:
20291 check_nms(ctx);
20292 gen_cl(ctx, OPC_CLZ, ret, rs);
20293 break;
20294 case NM_WSBH:
20295 gen_bshfl(ctx, OPC_WSBH, ret, rs);
20296 break;
20297 default:
20298 generate_exception_end(ctx, EXCP_RI);
20299 break;
20302 tcg_temp_free(v0_t);
20303 tcg_temp_free(t0);
20306 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
20307 int rt, int rs, int rd)
20309 TCGv t0 = tcg_temp_new();
20310 TCGv rs_t = tcg_temp_new();
20312 gen_load_gpr(rs_t, rs);
20314 switch (opc) {
20315 case NM_SHRA_R_QB:
20316 check_dsp_r2(ctx);
20317 tcg_gen_movi_tl(t0, rd >> 2);
20318 switch (extract32(ctx->opcode, 12, 1)) {
20319 case 0:
20320 /* NM_SHRA_QB */
20321 gen_helper_shra_qb(t0, t0, rs_t);
20322 gen_store_gpr(t0, rt);
20323 break;
20324 case 1:
20325 /* NM_SHRA_R_QB */
20326 gen_helper_shra_r_qb(t0, t0, rs_t);
20327 gen_store_gpr(t0, rt);
20328 break;
20330 break;
20331 case NM_SHRL_PH:
20332 check_dsp_r2(ctx);
20333 tcg_gen_movi_tl(t0, rd >> 1);
20334 gen_helper_shrl_ph(t0, t0, rs_t);
20335 gen_store_gpr(t0, rt);
20336 break;
20337 case NM_REPL_QB:
20338 check_dsp(ctx);
20340 int16_t imm;
20341 target_long result;
20342 imm = extract32(ctx->opcode, 13, 8);
20343 result = (uint32_t)imm << 24 |
20344 (uint32_t)imm << 16 |
20345 (uint32_t)imm << 8 |
20346 (uint32_t)imm;
20347 result = (int32_t)result;
20348 tcg_gen_movi_tl(t0, result);
20349 gen_store_gpr(t0, rt);
20351 break;
20352 default:
20353 generate_exception_end(ctx, EXCP_RI);
20354 break;
20356 tcg_temp_free(t0);
20357 tcg_temp_free(rs_t);
20361 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
20363 int rt = extract32(ctx->opcode, 21, 5);
20364 int rs = extract32(ctx->opcode, 16, 5);
20365 int rd = extract32(ctx->opcode, 11, 5);
20367 switch (extract32(ctx->opcode, 6, 3)) {
20368 case NM_POOL32AXF_1:
20370 int32_t op1 = extract32(ctx->opcode, 9, 3);
20371 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
20373 break;
20374 case NM_POOL32AXF_2:
20376 int32_t op1 = extract32(ctx->opcode, 12, 2);
20377 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
20379 break;
20380 case NM_POOL32AXF_4:
20382 int32_t op1 = extract32(ctx->opcode, 9, 7);
20383 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
20385 break;
20386 case NM_POOL32AXF_5:
20387 switch (extract32(ctx->opcode, 9, 7)) {
20388 #ifndef CONFIG_USER_ONLY
20389 case NM_TLBP:
20390 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
20391 break;
20392 case NM_TLBR:
20393 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
20394 break;
20395 case NM_TLBWI:
20396 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
20397 break;
20398 case NM_TLBWR:
20399 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
20400 break;
20401 case NM_TLBINV:
20402 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
20403 break;
20404 case NM_TLBINVF:
20405 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
20406 break;
20407 case NM_DI:
20408 check_cp0_enabled(ctx);
20410 TCGv t0 = tcg_temp_new();
20412 save_cpu_state(ctx, 1);
20413 gen_helper_di(t0, cpu_env);
20414 gen_store_gpr(t0, rt);
20415 /* Stop translation as we may have switched the execution mode */
20416 ctx->base.is_jmp = DISAS_STOP;
20417 tcg_temp_free(t0);
20419 break;
20420 case NM_EI:
20421 check_cp0_enabled(ctx);
20423 TCGv t0 = tcg_temp_new();
20425 save_cpu_state(ctx, 1);
20426 gen_helper_ei(t0, cpu_env);
20427 gen_store_gpr(t0, rt);
20428 /* Stop translation as we may have switched the execution mode */
20429 ctx->base.is_jmp = DISAS_STOP;
20430 tcg_temp_free(t0);
20432 break;
20433 case NM_RDPGPR:
20434 gen_load_srsgpr(rs, rt);
20435 break;
20436 case NM_WRPGPR:
20437 gen_store_srsgpr(rs, rt);
20438 break;
20439 case NM_WAIT:
20440 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20441 break;
20442 case NM_DERET:
20443 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20444 break;
20445 case NM_ERETX:
20446 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20447 break;
20448 #endif
20449 default:
20450 generate_exception_end(ctx, EXCP_RI);
20451 break;
20453 break;
20454 case NM_POOL32AXF_7:
20456 int32_t op1 = extract32(ctx->opcode, 9, 3);
20457 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20459 break;
20460 default:
20461 generate_exception_end(ctx, EXCP_RI);
20462 break;
20466 /* Immediate Value Compact Branches */
20467 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20468 int rt, int32_t imm, int32_t offset)
20470 TCGCond cond = TCG_COND_ALWAYS;
20471 TCGv t0 = tcg_temp_new();
20472 TCGv t1 = tcg_temp_new();
20474 gen_load_gpr(t0, rt);
20475 tcg_gen_movi_tl(t1, imm);
20476 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20478 /* Load needed operands and calculate btarget */
20479 switch (opc) {
20480 case NM_BEQIC:
20481 if (rt == 0 && imm == 0) {
20482 /* Unconditional branch */
20483 } else if (rt == 0 && imm != 0) {
20484 /* Treat as NOP */
20485 goto out;
20486 } else {
20487 cond = TCG_COND_EQ;
20489 break;
20490 case NM_BBEQZC:
20491 case NM_BBNEZC:
20492 check_nms(ctx);
20493 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20494 generate_exception_end(ctx, EXCP_RI);
20495 goto out;
20496 } else if (rt == 0 && opc == NM_BBEQZC) {
20497 /* Unconditional branch */
20498 } else if (rt == 0 && opc == NM_BBNEZC) {
20499 /* Treat as NOP */
20500 goto out;
20501 } else {
20502 tcg_gen_shri_tl(t0, t0, imm);
20503 tcg_gen_andi_tl(t0, t0, 1);
20504 tcg_gen_movi_tl(t1, 0);
20505 if (opc == NM_BBEQZC) {
20506 cond = TCG_COND_EQ;
20507 } else {
20508 cond = TCG_COND_NE;
20511 break;
20512 case NM_BNEIC:
20513 if (rt == 0 && imm == 0) {
20514 /* Treat as NOP */
20515 goto out;
20516 } else if (rt == 0 && imm != 0) {
20517 /* Unconditional branch */
20518 } else {
20519 cond = TCG_COND_NE;
20521 break;
20522 case NM_BGEIC:
20523 if (rt == 0 && imm == 0) {
20524 /* Unconditional branch */
20525 } else {
20526 cond = TCG_COND_GE;
20528 break;
20529 case NM_BLTIC:
20530 cond = TCG_COND_LT;
20531 break;
20532 case NM_BGEIUC:
20533 if (rt == 0 && imm == 0) {
20534 /* Unconditional branch */
20535 } else {
20536 cond = TCG_COND_GEU;
20538 break;
20539 case NM_BLTIUC:
20540 cond = TCG_COND_LTU;
20541 break;
20542 default:
20543 MIPS_INVAL("Immediate Value Compact branch");
20544 generate_exception_end(ctx, EXCP_RI);
20545 goto out;
20548 /* branch completion */
20549 clear_branch_hflags(ctx);
20550 ctx->base.is_jmp = DISAS_NORETURN;
20552 if (cond == TCG_COND_ALWAYS) {
20553 /* Uncoditional compact branch */
20554 gen_goto_tb(ctx, 0, ctx->btarget);
20555 } else {
20556 /* Conditional compact branch */
20557 TCGLabel *fs = gen_new_label();
20559 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20561 gen_goto_tb(ctx, 1, ctx->btarget);
20562 gen_set_label(fs);
20564 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20567 out:
20568 tcg_temp_free(t0);
20569 tcg_temp_free(t1);
20572 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20573 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20574 int rt)
20576 TCGv t0 = tcg_temp_new();
20577 TCGv t1 = tcg_temp_new();
20579 /* load rs */
20580 gen_load_gpr(t0, rs);
20582 /* link */
20583 if (rt != 0) {
20584 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20587 /* calculate btarget */
20588 tcg_gen_shli_tl(t0, t0, 1);
20589 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20590 gen_op_addr_add(ctx, btarget, t1, t0);
20592 /* branch completion */
20593 clear_branch_hflags(ctx);
20594 ctx->base.is_jmp = DISAS_NORETURN;
20596 /* unconditional branch to register */
20597 tcg_gen_mov_tl(cpu_PC, btarget);
20598 tcg_gen_lookup_and_goto_ptr();
20600 tcg_temp_free(t0);
20601 tcg_temp_free(t1);
20604 /* nanoMIPS Branches */
20605 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20606 int rs, int rt, int32_t offset)
20608 int bcond_compute = 0;
20609 TCGv t0 = tcg_temp_new();
20610 TCGv t1 = tcg_temp_new();
20612 /* Load needed operands and calculate btarget */
20613 switch (opc) {
20614 /* compact branch */
20615 case OPC_BGEC:
20616 case OPC_BLTC:
20617 gen_load_gpr(t0, rs);
20618 gen_load_gpr(t1, rt);
20619 bcond_compute = 1;
20620 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20621 break;
20622 case OPC_BGEUC:
20623 case OPC_BLTUC:
20624 if (rs == 0 || rs == rt) {
20625 /* OPC_BLEZALC, OPC_BGEZALC */
20626 /* OPC_BGTZALC, OPC_BLTZALC */
20627 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20629 gen_load_gpr(t0, rs);
20630 gen_load_gpr(t1, rt);
20631 bcond_compute = 1;
20632 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20633 break;
20634 case OPC_BC:
20635 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20636 break;
20637 case OPC_BEQZC:
20638 if (rs != 0) {
20639 /* OPC_BEQZC, OPC_BNEZC */
20640 gen_load_gpr(t0, rs);
20641 bcond_compute = 1;
20642 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20643 } else {
20644 /* OPC_JIC, OPC_JIALC */
20645 TCGv tbase = tcg_temp_new();
20646 TCGv toffset = tcg_temp_new();
20648 gen_load_gpr(tbase, rt);
20649 tcg_gen_movi_tl(toffset, offset);
20650 gen_op_addr_add(ctx, btarget, tbase, toffset);
20651 tcg_temp_free(tbase);
20652 tcg_temp_free(toffset);
20654 break;
20655 default:
20656 MIPS_INVAL("Compact branch/jump");
20657 generate_exception_end(ctx, EXCP_RI);
20658 goto out;
20661 if (bcond_compute == 0) {
20662 /* Uncoditional compact branch */
20663 switch (opc) {
20664 case OPC_BC:
20665 gen_goto_tb(ctx, 0, ctx->btarget);
20666 break;
20667 default:
20668 MIPS_INVAL("Compact branch/jump");
20669 generate_exception_end(ctx, EXCP_RI);
20670 goto out;
20672 } else {
20673 /* Conditional compact branch */
20674 TCGLabel *fs = gen_new_label();
20676 switch (opc) {
20677 case OPC_BGEUC:
20678 if (rs == 0 && rt != 0) {
20679 /* OPC_BLEZALC */
20680 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20681 } else if (rs != 0 && rt != 0 && rs == rt) {
20682 /* OPC_BGEZALC */
20683 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20684 } else {
20685 /* OPC_BGEUC */
20686 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20688 break;
20689 case OPC_BLTUC:
20690 if (rs == 0 && rt != 0) {
20691 /* OPC_BGTZALC */
20692 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20693 } else if (rs != 0 && rt != 0 && rs == rt) {
20694 /* OPC_BLTZALC */
20695 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20696 } else {
20697 /* OPC_BLTUC */
20698 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20700 break;
20701 case OPC_BGEC:
20702 if (rs == 0 && rt != 0) {
20703 /* OPC_BLEZC */
20704 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20705 } else if (rs != 0 && rt != 0 && rs == rt) {
20706 /* OPC_BGEZC */
20707 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20708 } else {
20709 /* OPC_BGEC */
20710 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20712 break;
20713 case OPC_BLTC:
20714 if (rs == 0 && rt != 0) {
20715 /* OPC_BGTZC */
20716 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20717 } else if (rs != 0 && rt != 0 && rs == rt) {
20718 /* OPC_BLTZC */
20719 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20720 } else {
20721 /* OPC_BLTC */
20722 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20724 break;
20725 case OPC_BEQZC:
20726 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20727 break;
20728 default:
20729 MIPS_INVAL("Compact conditional branch/jump");
20730 generate_exception_end(ctx, EXCP_RI);
20731 goto out;
20734 /* branch completion */
20735 clear_branch_hflags(ctx);
20736 ctx->base.is_jmp = DISAS_NORETURN;
20738 /* Generating branch here as compact branches don't have delay slot */
20739 gen_goto_tb(ctx, 1, ctx->btarget);
20740 gen_set_label(fs);
20742 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20745 out:
20746 tcg_temp_free(t0);
20747 tcg_temp_free(t1);
20751 /* nanoMIPS CP1 Branches */
20752 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20753 int32_t ft, int32_t offset)
20755 target_ulong btarget;
20756 TCGv_i64 t0 = tcg_temp_new_i64();
20758 gen_load_fpr64(ctx, t0, ft);
20759 tcg_gen_andi_i64(t0, t0, 1);
20761 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20763 switch (op) {
20764 case NM_BC1EQZC:
20765 tcg_gen_xori_i64(t0, t0, 1);
20766 ctx->hflags |= MIPS_HFLAG_BC;
20767 break;
20768 case NM_BC1NEZC:
20769 /* t0 already set */
20770 ctx->hflags |= MIPS_HFLAG_BC;
20771 break;
20772 default:
20773 MIPS_INVAL("cp1 cond branch");
20774 generate_exception_end(ctx, EXCP_RI);
20775 goto out;
20778 tcg_gen_trunc_i64_tl(bcond, t0);
20780 ctx->btarget = btarget;
20782 out:
20783 tcg_temp_free_i64(t0);
20787 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20789 TCGv t0, t1;
20790 t0 = tcg_temp_new();
20791 t1 = tcg_temp_new();
20793 gen_load_gpr(t0, rs);
20794 gen_load_gpr(t1, rt);
20796 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20797 /* PP.LSXS instructions require shifting */
20798 switch (extract32(ctx->opcode, 7, 4)) {
20799 case NM_SHXS:
20800 check_nms(ctx);
20801 /* fall through */
20802 case NM_LHXS:
20803 case NM_LHUXS:
20804 tcg_gen_shli_tl(t0, t0, 1);
20805 break;
20806 case NM_SWXS:
20807 check_nms(ctx);
20808 /* fall through */
20809 case NM_LWXS:
20810 case NM_LWC1XS:
20811 case NM_SWC1XS:
20812 tcg_gen_shli_tl(t0, t0, 2);
20813 break;
20814 case NM_LDC1XS:
20815 case NM_SDC1XS:
20816 tcg_gen_shli_tl(t0, t0, 3);
20817 break;
20820 gen_op_addr_add(ctx, t0, t0, t1);
20822 switch (extract32(ctx->opcode, 7, 4)) {
20823 case NM_LBX:
20824 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20825 MO_SB);
20826 gen_store_gpr(t0, rd);
20827 break;
20828 case NM_LHX:
20829 /*case NM_LHXS:*/
20830 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20831 MO_TESW);
20832 gen_store_gpr(t0, rd);
20833 break;
20834 case NM_LWX:
20835 /*case NM_LWXS:*/
20836 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20837 MO_TESL);
20838 gen_store_gpr(t0, rd);
20839 break;
20840 case NM_LBUX:
20841 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20842 MO_UB);
20843 gen_store_gpr(t0, rd);
20844 break;
20845 case NM_LHUX:
20846 /*case NM_LHUXS:*/
20847 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20848 MO_TEUW);
20849 gen_store_gpr(t0, rd);
20850 break;
20851 case NM_SBX:
20852 check_nms(ctx);
20853 gen_load_gpr(t1, rd);
20854 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20855 MO_8);
20856 break;
20857 case NM_SHX:
20858 /*case NM_SHXS:*/
20859 check_nms(ctx);
20860 gen_load_gpr(t1, rd);
20861 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20862 MO_TEUW);
20863 break;
20864 case NM_SWX:
20865 /*case NM_SWXS:*/
20866 check_nms(ctx);
20867 gen_load_gpr(t1, rd);
20868 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20869 MO_TEUL);
20870 break;
20871 case NM_LWC1X:
20872 /*case NM_LWC1XS:*/
20873 case NM_LDC1X:
20874 /*case NM_LDC1XS:*/
20875 case NM_SWC1X:
20876 /*case NM_SWC1XS:*/
20877 case NM_SDC1X:
20878 /*case NM_SDC1XS:*/
20879 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20880 check_cp1_enabled(ctx);
20881 switch (extract32(ctx->opcode, 7, 4)) {
20882 case NM_LWC1X:
20883 /*case NM_LWC1XS:*/
20884 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20885 break;
20886 case NM_LDC1X:
20887 /*case NM_LDC1XS:*/
20888 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20889 break;
20890 case NM_SWC1X:
20891 /*case NM_SWC1XS:*/
20892 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20893 break;
20894 case NM_SDC1X:
20895 /*case NM_SDC1XS:*/
20896 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20897 break;
20899 } else {
20900 generate_exception_err(ctx, EXCP_CpU, 1);
20902 break;
20903 default:
20904 generate_exception_end(ctx, EXCP_RI);
20905 break;
20908 tcg_temp_free(t0);
20909 tcg_temp_free(t1);
20912 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20914 int rt, rs, rd;
20916 rt = extract32(ctx->opcode, 21, 5);
20917 rs = extract32(ctx->opcode, 16, 5);
20918 rd = extract32(ctx->opcode, 11, 5);
20920 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20921 generate_exception_end(ctx, EXCP_RI);
20922 return;
20924 check_cp1_enabled(ctx);
20925 switch (extract32(ctx->opcode, 0, 3)) {
20926 case NM_POOL32F_0:
20927 switch (extract32(ctx->opcode, 3, 7)) {
20928 case NM_RINT_S:
20929 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20930 break;
20931 case NM_RINT_D:
20932 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20933 break;
20934 case NM_CLASS_S:
20935 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20936 break;
20937 case NM_CLASS_D:
20938 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20939 break;
20940 case NM_ADD_S:
20941 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20942 break;
20943 case NM_ADD_D:
20944 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20945 break;
20946 case NM_SUB_S:
20947 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20948 break;
20949 case NM_SUB_D:
20950 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20951 break;
20952 case NM_MUL_S:
20953 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20954 break;
20955 case NM_MUL_D:
20956 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20957 break;
20958 case NM_DIV_S:
20959 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20960 break;
20961 case NM_DIV_D:
20962 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20963 break;
20964 case NM_SELEQZ_S:
20965 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20966 break;
20967 case NM_SELEQZ_D:
20968 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20969 break;
20970 case NM_SELNEZ_S:
20971 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20972 break;
20973 case NM_SELNEZ_D:
20974 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20975 break;
20976 case NM_SEL_S:
20977 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20978 break;
20979 case NM_SEL_D:
20980 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20981 break;
20982 case NM_MADDF_S:
20983 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20984 break;
20985 case NM_MADDF_D:
20986 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20987 break;
20988 case NM_MSUBF_S:
20989 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20990 break;
20991 case NM_MSUBF_D:
20992 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20993 break;
20994 default:
20995 generate_exception_end(ctx, EXCP_RI);
20996 break;
20998 break;
20999 case NM_POOL32F_3:
21000 switch (extract32(ctx->opcode, 3, 3)) {
21001 case NM_MIN_FMT:
21002 switch (extract32(ctx->opcode, 9, 1)) {
21003 case FMT_SDPS_S:
21004 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
21005 break;
21006 case FMT_SDPS_D:
21007 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
21008 break;
21010 break;
21011 case NM_MAX_FMT:
21012 switch (extract32(ctx->opcode, 9, 1)) {
21013 case FMT_SDPS_S:
21014 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
21015 break;
21016 case FMT_SDPS_D:
21017 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
21018 break;
21020 break;
21021 case NM_MINA_FMT:
21022 switch (extract32(ctx->opcode, 9, 1)) {
21023 case FMT_SDPS_S:
21024 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
21025 break;
21026 case FMT_SDPS_D:
21027 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
21028 break;
21030 break;
21031 case NM_MAXA_FMT:
21032 switch (extract32(ctx->opcode, 9, 1)) {
21033 case FMT_SDPS_S:
21034 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
21035 break;
21036 case FMT_SDPS_D:
21037 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
21038 break;
21040 break;
21041 case NM_POOL32FXF:
21042 switch (extract32(ctx->opcode, 6, 8)) {
21043 case NM_CFC1:
21044 gen_cp1(ctx, OPC_CFC1, rt, rs);
21045 break;
21046 case NM_CTC1:
21047 gen_cp1(ctx, OPC_CTC1, rt, rs);
21048 break;
21049 case NM_MFC1:
21050 gen_cp1(ctx, OPC_MFC1, rt, rs);
21051 break;
21052 case NM_MTC1:
21053 gen_cp1(ctx, OPC_MTC1, rt, rs);
21054 break;
21055 case NM_MFHC1:
21056 gen_cp1(ctx, OPC_MFHC1, rt, rs);
21057 break;
21058 case NM_MTHC1:
21059 gen_cp1(ctx, OPC_MTHC1, rt, rs);
21060 break;
21061 case NM_CVT_S_PL:
21062 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
21063 break;
21064 case NM_CVT_S_PU:
21065 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
21066 break;
21067 default:
21068 switch (extract32(ctx->opcode, 6, 9)) {
21069 case NM_CVT_L_S:
21070 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
21071 break;
21072 case NM_CVT_L_D:
21073 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
21074 break;
21075 case NM_CVT_W_S:
21076 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
21077 break;
21078 case NM_CVT_W_D:
21079 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
21080 break;
21081 case NM_RSQRT_S:
21082 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
21083 break;
21084 case NM_RSQRT_D:
21085 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
21086 break;
21087 case NM_SQRT_S:
21088 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
21089 break;
21090 case NM_SQRT_D:
21091 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
21092 break;
21093 case NM_RECIP_S:
21094 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
21095 break;
21096 case NM_RECIP_D:
21097 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
21098 break;
21099 case NM_FLOOR_L_S:
21100 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
21101 break;
21102 case NM_FLOOR_L_D:
21103 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
21104 break;
21105 case NM_FLOOR_W_S:
21106 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
21107 break;
21108 case NM_FLOOR_W_D:
21109 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
21110 break;
21111 case NM_CEIL_L_S:
21112 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
21113 break;
21114 case NM_CEIL_L_D:
21115 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
21116 break;
21117 case NM_CEIL_W_S:
21118 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
21119 break;
21120 case NM_CEIL_W_D:
21121 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
21122 break;
21123 case NM_TRUNC_L_S:
21124 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
21125 break;
21126 case NM_TRUNC_L_D:
21127 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
21128 break;
21129 case NM_TRUNC_W_S:
21130 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
21131 break;
21132 case NM_TRUNC_W_D:
21133 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
21134 break;
21135 case NM_ROUND_L_S:
21136 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
21137 break;
21138 case NM_ROUND_L_D:
21139 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
21140 break;
21141 case NM_ROUND_W_S:
21142 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
21143 break;
21144 case NM_ROUND_W_D:
21145 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
21146 break;
21147 case NM_MOV_S:
21148 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
21149 break;
21150 case NM_MOV_D:
21151 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
21152 break;
21153 case NM_ABS_S:
21154 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
21155 break;
21156 case NM_ABS_D:
21157 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
21158 break;
21159 case NM_NEG_S:
21160 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
21161 break;
21162 case NM_NEG_D:
21163 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
21164 break;
21165 case NM_CVT_D_S:
21166 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
21167 break;
21168 case NM_CVT_D_W:
21169 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
21170 break;
21171 case NM_CVT_D_L:
21172 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
21173 break;
21174 case NM_CVT_S_D:
21175 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
21176 break;
21177 case NM_CVT_S_W:
21178 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
21179 break;
21180 case NM_CVT_S_L:
21181 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
21182 break;
21183 default:
21184 generate_exception_end(ctx, EXCP_RI);
21185 break;
21187 break;
21189 break;
21191 break;
21192 case NM_POOL32F_5:
21193 switch (extract32(ctx->opcode, 3, 3)) {
21194 case NM_CMP_CONDN_S:
21195 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21196 break;
21197 case NM_CMP_CONDN_D:
21198 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21199 break;
21200 default:
21201 generate_exception_end(ctx, EXCP_RI);
21202 break;
21204 break;
21205 default:
21206 generate_exception_end(ctx, EXCP_RI);
21207 break;
21211 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
21212 int rd, int rs, int rt)
21214 int ret = rd;
21215 TCGv t0 = tcg_temp_new();
21216 TCGv v1_t = tcg_temp_new();
21217 TCGv v2_t = tcg_temp_new();
21219 gen_load_gpr(v1_t, rs);
21220 gen_load_gpr(v2_t, rt);
21222 switch (opc) {
21223 case NM_CMP_EQ_PH:
21224 check_dsp(ctx);
21225 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21226 break;
21227 case NM_CMP_LT_PH:
21228 check_dsp(ctx);
21229 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21230 break;
21231 case NM_CMP_LE_PH:
21232 check_dsp(ctx);
21233 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21234 break;
21235 case NM_CMPU_EQ_QB:
21236 check_dsp(ctx);
21237 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21238 break;
21239 case NM_CMPU_LT_QB:
21240 check_dsp(ctx);
21241 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21242 break;
21243 case NM_CMPU_LE_QB:
21244 check_dsp(ctx);
21245 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21246 break;
21247 case NM_CMPGU_EQ_QB:
21248 check_dsp(ctx);
21249 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21250 gen_store_gpr(v1_t, ret);
21251 break;
21252 case NM_CMPGU_LT_QB:
21253 check_dsp(ctx);
21254 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21255 gen_store_gpr(v1_t, ret);
21256 break;
21257 case NM_CMPGU_LE_QB:
21258 check_dsp(ctx);
21259 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21260 gen_store_gpr(v1_t, ret);
21261 break;
21262 case NM_CMPGDU_EQ_QB:
21263 check_dsp_r2(ctx);
21264 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21265 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21266 gen_store_gpr(v1_t, ret);
21267 break;
21268 case NM_CMPGDU_LT_QB:
21269 check_dsp_r2(ctx);
21270 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21271 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21272 gen_store_gpr(v1_t, ret);
21273 break;
21274 case NM_CMPGDU_LE_QB:
21275 check_dsp_r2(ctx);
21276 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21277 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21278 gen_store_gpr(v1_t, ret);
21279 break;
21280 case NM_PACKRL_PH:
21281 check_dsp(ctx);
21282 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
21283 gen_store_gpr(v1_t, ret);
21284 break;
21285 case NM_PICK_QB:
21286 check_dsp(ctx);
21287 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
21288 gen_store_gpr(v1_t, ret);
21289 break;
21290 case NM_PICK_PH:
21291 check_dsp(ctx);
21292 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
21293 gen_store_gpr(v1_t, ret);
21294 break;
21295 case NM_ADDQ_S_W:
21296 check_dsp(ctx);
21297 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
21298 gen_store_gpr(v1_t, ret);
21299 break;
21300 case NM_SUBQ_S_W:
21301 check_dsp(ctx);
21302 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
21303 gen_store_gpr(v1_t, ret);
21304 break;
21305 case NM_ADDSC:
21306 check_dsp(ctx);
21307 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
21308 gen_store_gpr(v1_t, ret);
21309 break;
21310 case NM_ADDWC:
21311 check_dsp(ctx);
21312 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
21313 gen_store_gpr(v1_t, ret);
21314 break;
21315 case NM_ADDQ_S_PH:
21316 check_dsp(ctx);
21317 switch (extract32(ctx->opcode, 10, 1)) {
21318 case 0:
21319 /* ADDQ_PH */
21320 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
21321 gen_store_gpr(v1_t, ret);
21322 break;
21323 case 1:
21324 /* ADDQ_S_PH */
21325 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21326 gen_store_gpr(v1_t, ret);
21327 break;
21329 break;
21330 case NM_ADDQH_R_PH:
21331 check_dsp_r2(ctx);
21332 switch (extract32(ctx->opcode, 10, 1)) {
21333 case 0:
21334 /* ADDQH_PH */
21335 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
21336 gen_store_gpr(v1_t, ret);
21337 break;
21338 case 1:
21339 /* ADDQH_R_PH */
21340 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
21341 gen_store_gpr(v1_t, ret);
21342 break;
21344 break;
21345 case NM_ADDQH_R_W:
21346 check_dsp_r2(ctx);
21347 switch (extract32(ctx->opcode, 10, 1)) {
21348 case 0:
21349 /* ADDQH_W */
21350 gen_helper_addqh_w(v1_t, v1_t, v2_t);
21351 gen_store_gpr(v1_t, ret);
21352 break;
21353 case 1:
21354 /* ADDQH_R_W */
21355 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
21356 gen_store_gpr(v1_t, ret);
21357 break;
21359 break;
21360 case NM_ADDU_S_QB:
21361 check_dsp(ctx);
21362 switch (extract32(ctx->opcode, 10, 1)) {
21363 case 0:
21364 /* ADDU_QB */
21365 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
21366 gen_store_gpr(v1_t, ret);
21367 break;
21368 case 1:
21369 /* ADDU_S_QB */
21370 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21371 gen_store_gpr(v1_t, ret);
21372 break;
21374 break;
21375 case NM_ADDU_S_PH:
21376 check_dsp_r2(ctx);
21377 switch (extract32(ctx->opcode, 10, 1)) {
21378 case 0:
21379 /* ADDU_PH */
21380 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
21381 gen_store_gpr(v1_t, ret);
21382 break;
21383 case 1:
21384 /* ADDU_S_PH */
21385 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21386 gen_store_gpr(v1_t, ret);
21387 break;
21389 break;
21390 case NM_ADDUH_R_QB:
21391 check_dsp_r2(ctx);
21392 switch (extract32(ctx->opcode, 10, 1)) {
21393 case 0:
21394 /* ADDUH_QB */
21395 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
21396 gen_store_gpr(v1_t, ret);
21397 break;
21398 case 1:
21399 /* ADDUH_R_QB */
21400 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
21401 gen_store_gpr(v1_t, ret);
21402 break;
21404 break;
21405 case NM_SHRAV_R_PH:
21406 check_dsp(ctx);
21407 switch (extract32(ctx->opcode, 10, 1)) {
21408 case 0:
21409 /* SHRAV_PH */
21410 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21411 gen_store_gpr(v1_t, ret);
21412 break;
21413 case 1:
21414 /* SHRAV_R_PH */
21415 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21416 gen_store_gpr(v1_t, ret);
21417 break;
21419 break;
21420 case NM_SHRAV_R_QB:
21421 check_dsp_r2(ctx);
21422 switch (extract32(ctx->opcode, 10, 1)) {
21423 case 0:
21424 /* SHRAV_QB */
21425 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21426 gen_store_gpr(v1_t, ret);
21427 break;
21428 case 1:
21429 /* SHRAV_R_QB */
21430 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21431 gen_store_gpr(v1_t, ret);
21432 break;
21434 break;
21435 case NM_SUBQ_S_PH:
21436 check_dsp(ctx);
21437 switch (extract32(ctx->opcode, 10, 1)) {
21438 case 0:
21439 /* SUBQ_PH */
21440 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21441 gen_store_gpr(v1_t, ret);
21442 break;
21443 case 1:
21444 /* SUBQ_S_PH */
21445 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21446 gen_store_gpr(v1_t, ret);
21447 break;
21449 break;
21450 case NM_SUBQH_R_PH:
21451 check_dsp_r2(ctx);
21452 switch (extract32(ctx->opcode, 10, 1)) {
21453 case 0:
21454 /* SUBQH_PH */
21455 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21456 gen_store_gpr(v1_t, ret);
21457 break;
21458 case 1:
21459 /* SUBQH_R_PH */
21460 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21461 gen_store_gpr(v1_t, ret);
21462 break;
21464 break;
21465 case NM_SUBQH_R_W:
21466 check_dsp_r2(ctx);
21467 switch (extract32(ctx->opcode, 10, 1)) {
21468 case 0:
21469 /* SUBQH_W */
21470 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21471 gen_store_gpr(v1_t, ret);
21472 break;
21473 case 1:
21474 /* SUBQH_R_W */
21475 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21476 gen_store_gpr(v1_t, ret);
21477 break;
21479 break;
21480 case NM_SUBU_S_QB:
21481 check_dsp(ctx);
21482 switch (extract32(ctx->opcode, 10, 1)) {
21483 case 0:
21484 /* SUBU_QB */
21485 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21486 gen_store_gpr(v1_t, ret);
21487 break;
21488 case 1:
21489 /* SUBU_S_QB */
21490 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21491 gen_store_gpr(v1_t, ret);
21492 break;
21494 break;
21495 case NM_SUBU_S_PH:
21496 check_dsp_r2(ctx);
21497 switch (extract32(ctx->opcode, 10, 1)) {
21498 case 0:
21499 /* SUBU_PH */
21500 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21501 gen_store_gpr(v1_t, ret);
21502 break;
21503 case 1:
21504 /* SUBU_S_PH */
21505 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21506 gen_store_gpr(v1_t, ret);
21507 break;
21509 break;
21510 case NM_SUBUH_R_QB:
21511 check_dsp_r2(ctx);
21512 switch (extract32(ctx->opcode, 10, 1)) {
21513 case 0:
21514 /* SUBUH_QB */
21515 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21516 gen_store_gpr(v1_t, ret);
21517 break;
21518 case 1:
21519 /* SUBUH_R_QB */
21520 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21521 gen_store_gpr(v1_t, ret);
21522 break;
21524 break;
21525 case NM_SHLLV_S_PH:
21526 check_dsp(ctx);
21527 switch (extract32(ctx->opcode, 10, 1)) {
21528 case 0:
21529 /* SHLLV_PH */
21530 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21531 gen_store_gpr(v1_t, ret);
21532 break;
21533 case 1:
21534 /* SHLLV_S_PH */
21535 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21536 gen_store_gpr(v1_t, ret);
21537 break;
21539 break;
21540 case NM_PRECR_SRA_R_PH_W:
21541 check_dsp_r2(ctx);
21542 switch (extract32(ctx->opcode, 10, 1)) {
21543 case 0:
21544 /* PRECR_SRA_PH_W */
21546 TCGv_i32 sa_t = tcg_const_i32(rd);
21547 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21548 cpu_gpr[rt]);
21549 gen_store_gpr(v1_t, rt);
21550 tcg_temp_free_i32(sa_t);
21552 break;
21553 case 1:
21554 /* PRECR_SRA_R_PH_W */
21556 TCGv_i32 sa_t = tcg_const_i32(rd);
21557 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21558 cpu_gpr[rt]);
21559 gen_store_gpr(v1_t, rt);
21560 tcg_temp_free_i32(sa_t);
21562 break;
21564 break;
21565 case NM_MULEU_S_PH_QBL:
21566 check_dsp(ctx);
21567 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21568 gen_store_gpr(v1_t, ret);
21569 break;
21570 case NM_MULEU_S_PH_QBR:
21571 check_dsp(ctx);
21572 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21573 gen_store_gpr(v1_t, ret);
21574 break;
21575 case NM_MULQ_RS_PH:
21576 check_dsp(ctx);
21577 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21578 gen_store_gpr(v1_t, ret);
21579 break;
21580 case NM_MULQ_S_PH:
21581 check_dsp_r2(ctx);
21582 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21583 gen_store_gpr(v1_t, ret);
21584 break;
21585 case NM_MULQ_RS_W:
21586 check_dsp_r2(ctx);
21587 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21588 gen_store_gpr(v1_t, ret);
21589 break;
21590 case NM_MULQ_S_W:
21591 check_dsp_r2(ctx);
21592 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21593 gen_store_gpr(v1_t, ret);
21594 break;
21595 case NM_APPEND:
21596 check_dsp_r2(ctx);
21597 gen_load_gpr(t0, rs);
21598 if (rd != 0) {
21599 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21601 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21602 break;
21603 case NM_MODSUB:
21604 check_dsp(ctx);
21605 gen_helper_modsub(v1_t, v1_t, v2_t);
21606 gen_store_gpr(v1_t, ret);
21607 break;
21608 case NM_SHRAV_R_W:
21609 check_dsp(ctx);
21610 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21611 gen_store_gpr(v1_t, ret);
21612 break;
21613 case NM_SHRLV_PH:
21614 check_dsp_r2(ctx);
21615 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21616 gen_store_gpr(v1_t, ret);
21617 break;
21618 case NM_SHRLV_QB:
21619 check_dsp(ctx);
21620 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21621 gen_store_gpr(v1_t, ret);
21622 break;
21623 case NM_SHLLV_QB:
21624 check_dsp(ctx);
21625 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21626 gen_store_gpr(v1_t, ret);
21627 break;
21628 case NM_SHLLV_S_W:
21629 check_dsp(ctx);
21630 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21631 gen_store_gpr(v1_t, ret);
21632 break;
21633 case NM_SHILO:
21634 check_dsp(ctx);
21636 TCGv tv0 = tcg_temp_new();
21637 TCGv tv1 = tcg_temp_new();
21638 int16_t imm = extract32(ctx->opcode, 16, 7);
21640 tcg_gen_movi_tl(tv0, rd >> 3);
21641 tcg_gen_movi_tl(tv1, imm);
21642 gen_helper_shilo(tv0, tv1, cpu_env);
21644 break;
21645 case NM_MULEQ_S_W_PHL:
21646 check_dsp(ctx);
21647 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21648 gen_store_gpr(v1_t, ret);
21649 break;
21650 case NM_MULEQ_S_W_PHR:
21651 check_dsp(ctx);
21652 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21653 gen_store_gpr(v1_t, ret);
21654 break;
21655 case NM_MUL_S_PH:
21656 check_dsp_r2(ctx);
21657 switch (extract32(ctx->opcode, 10, 1)) {
21658 case 0:
21659 /* MUL_PH */
21660 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21661 gen_store_gpr(v1_t, ret);
21662 break;
21663 case 1:
21664 /* MUL_S_PH */
21665 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21666 gen_store_gpr(v1_t, ret);
21667 break;
21669 break;
21670 case NM_PRECR_QB_PH:
21671 check_dsp_r2(ctx);
21672 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21673 gen_store_gpr(v1_t, ret);
21674 break;
21675 case NM_PRECRQ_QB_PH:
21676 check_dsp(ctx);
21677 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21678 gen_store_gpr(v1_t, ret);
21679 break;
21680 case NM_PRECRQ_PH_W:
21681 check_dsp(ctx);
21682 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21683 gen_store_gpr(v1_t, ret);
21684 break;
21685 case NM_PRECRQ_RS_PH_W:
21686 check_dsp(ctx);
21687 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21688 gen_store_gpr(v1_t, ret);
21689 break;
21690 case NM_PRECRQU_S_QB_PH:
21691 check_dsp(ctx);
21692 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21693 gen_store_gpr(v1_t, ret);
21694 break;
21695 case NM_SHRA_R_W:
21696 check_dsp(ctx);
21697 tcg_gen_movi_tl(t0, rd);
21698 gen_helper_shra_r_w(v1_t, t0, v1_t);
21699 gen_store_gpr(v1_t, rt);
21700 break;
21701 case NM_SHRA_R_PH:
21702 check_dsp(ctx);
21703 tcg_gen_movi_tl(t0, rd >> 1);
21704 switch (extract32(ctx->opcode, 10, 1)) {
21705 case 0:
21706 /* SHRA_PH */
21707 gen_helper_shra_ph(v1_t, t0, v1_t);
21708 gen_store_gpr(v1_t, rt);
21709 break;
21710 case 1:
21711 /* SHRA_R_PH */
21712 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21713 gen_store_gpr(v1_t, rt);
21714 break;
21716 break;
21717 case NM_SHLL_S_PH:
21718 check_dsp(ctx);
21719 tcg_gen_movi_tl(t0, rd >> 1);
21720 switch (extract32(ctx->opcode, 10, 2)) {
21721 case 0:
21722 /* SHLL_PH */
21723 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21724 gen_store_gpr(v1_t, rt);
21725 break;
21726 case 2:
21727 /* SHLL_S_PH */
21728 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21729 gen_store_gpr(v1_t, rt);
21730 break;
21731 default:
21732 generate_exception_end(ctx, EXCP_RI);
21733 break;
21735 break;
21736 case NM_SHLL_S_W:
21737 check_dsp(ctx);
21738 tcg_gen_movi_tl(t0, rd);
21739 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21740 gen_store_gpr(v1_t, rt);
21741 break;
21742 case NM_REPL_PH:
21743 check_dsp(ctx);
21745 int16_t imm;
21746 imm = sextract32(ctx->opcode, 11, 11);
21747 imm = (int16_t)(imm << 6) >> 6;
21748 if (rt != 0) {
21749 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21752 break;
21753 default:
21754 generate_exception_end(ctx, EXCP_RI);
21755 break;
21759 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21761 uint16_t insn;
21762 uint32_t op;
21763 int rt, rs, rd;
21764 int offset;
21765 int imm;
21767 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21768 ctx->opcode = (ctx->opcode << 16) | insn;
21770 rt = extract32(ctx->opcode, 21, 5);
21771 rs = extract32(ctx->opcode, 16, 5);
21772 rd = extract32(ctx->opcode, 11, 5);
21774 op = extract32(ctx->opcode, 26, 6);
21775 switch (op) {
21776 case NM_P_ADDIU:
21777 if (rt == 0) {
21778 /* P.RI */
21779 switch (extract32(ctx->opcode, 19, 2)) {
21780 case NM_SIGRIE:
21781 default:
21782 generate_exception_end(ctx, EXCP_RI);
21783 break;
21784 case NM_P_SYSCALL:
21785 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21786 generate_exception_end(ctx, EXCP_SYSCALL);
21787 } else {
21788 generate_exception_end(ctx, EXCP_RI);
21790 break;
21791 case NM_BREAK:
21792 generate_exception_end(ctx, EXCP_BREAK);
21793 break;
21794 case NM_SDBBP:
21795 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21796 gen_helper_do_semihosting(cpu_env);
21797 } else {
21798 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21799 generate_exception_end(ctx, EXCP_RI);
21800 } else {
21801 generate_exception_end(ctx, EXCP_DBp);
21804 break;
21806 } else {
21807 /* NM_ADDIU */
21808 imm = extract32(ctx->opcode, 0, 16);
21809 if (rs != 0) {
21810 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21811 } else {
21812 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21814 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21816 break;
21817 case NM_ADDIUPC:
21818 if (rt != 0) {
21819 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21820 extract32(ctx->opcode, 1, 20) << 1;
21821 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21822 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21824 break;
21825 case NM_POOL32A:
21826 switch (ctx->opcode & 0x07) {
21827 case NM_POOL32A0:
21828 gen_pool32a0_nanomips_insn(env, ctx);
21829 break;
21830 case NM_POOL32A5:
21832 int32_t op1 = extract32(ctx->opcode, 3, 7);
21833 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21835 break;
21836 case NM_POOL32A7:
21837 switch (extract32(ctx->opcode, 3, 3)) {
21838 case NM_P_LSX:
21839 gen_p_lsx(ctx, rd, rs, rt);
21840 break;
21841 case NM_LSA:
21843 * In nanoMIPS, the shift field directly encodes the shift
21844 * amount, meaning that the supported shift values are in
21845 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21847 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21848 extract32(ctx->opcode, 9, 2) - 1);
21849 break;
21850 case NM_EXTW:
21851 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21852 break;
21853 case NM_POOL32AXF:
21854 gen_pool32axf_nanomips_insn(env, ctx);
21855 break;
21856 default:
21857 generate_exception_end(ctx, EXCP_RI);
21858 break;
21860 break;
21861 default:
21862 generate_exception_end(ctx, EXCP_RI);
21863 break;
21865 break;
21866 case NM_P_GP_W:
21867 switch (ctx->opcode & 0x03) {
21868 case NM_ADDIUGP_W:
21869 if (rt != 0) {
21870 offset = extract32(ctx->opcode, 0, 21);
21871 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21873 break;
21874 case NM_LWGP:
21875 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21876 break;
21877 case NM_SWGP:
21878 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21879 break;
21880 default:
21881 generate_exception_end(ctx, EXCP_RI);
21882 break;
21884 break;
21885 case NM_P48I:
21887 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21888 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21889 switch (extract32(ctx->opcode, 16, 5)) {
21890 case NM_LI48:
21891 check_nms(ctx);
21892 if (rt != 0) {
21893 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21895 break;
21896 case NM_ADDIU48:
21897 check_nms(ctx);
21898 if (rt != 0) {
21899 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21900 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21902 break;
21903 case NM_ADDIUGP48:
21904 check_nms(ctx);
21905 if (rt != 0) {
21906 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21908 break;
21909 case NM_ADDIUPC48:
21910 check_nms(ctx);
21911 if (rt != 0) {
21912 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21913 addr_off);
21915 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21917 break;
21918 case NM_LWPC48:
21919 check_nms(ctx);
21920 if (rt != 0) {
21921 TCGv t0;
21922 t0 = tcg_temp_new();
21924 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21925 addr_off);
21927 tcg_gen_movi_tl(t0, addr);
21928 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21929 tcg_temp_free(t0);
21931 break;
21932 case NM_SWPC48:
21933 check_nms(ctx);
21935 TCGv t0, t1;
21936 t0 = tcg_temp_new();
21937 t1 = tcg_temp_new();
21939 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21940 addr_off);
21942 tcg_gen_movi_tl(t0, addr);
21943 gen_load_gpr(t1, rt);
21945 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21947 tcg_temp_free(t0);
21948 tcg_temp_free(t1);
21950 break;
21951 default:
21952 generate_exception_end(ctx, EXCP_RI);
21953 break;
21955 return 6;
21957 case NM_P_U12:
21958 switch (extract32(ctx->opcode, 12, 4)) {
21959 case NM_ORI:
21960 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21961 break;
21962 case NM_XORI:
21963 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21964 break;
21965 case NM_ANDI:
21966 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21967 break;
21968 case NM_P_SR:
21969 switch (extract32(ctx->opcode, 20, 1)) {
21970 case NM_PP_SR:
21971 switch (ctx->opcode & 3) {
21972 case NM_SAVE:
21973 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21974 extract32(ctx->opcode, 2, 1),
21975 extract32(ctx->opcode, 3, 9) << 3);
21976 break;
21977 case NM_RESTORE:
21978 case NM_RESTORE_JRC:
21979 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21980 extract32(ctx->opcode, 2, 1),
21981 extract32(ctx->opcode, 3, 9) << 3);
21982 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21983 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21985 break;
21986 default:
21987 generate_exception_end(ctx, EXCP_RI);
21988 break;
21990 break;
21991 case NM_P_SR_F:
21992 generate_exception_end(ctx, EXCP_RI);
21993 break;
21995 break;
21996 case NM_SLTI:
21997 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21998 break;
21999 case NM_SLTIU:
22000 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
22001 break;
22002 case NM_SEQI:
22004 TCGv t0 = tcg_temp_new();
22006 imm = extract32(ctx->opcode, 0, 12);
22007 gen_load_gpr(t0, rs);
22008 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
22009 gen_store_gpr(t0, rt);
22011 tcg_temp_free(t0);
22013 break;
22014 case NM_ADDIUNEG:
22015 imm = (int16_t) extract32(ctx->opcode, 0, 12);
22016 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
22017 break;
22018 case NM_P_SHIFT:
22020 int shift = extract32(ctx->opcode, 0, 5);
22021 switch (extract32(ctx->opcode, 5, 4)) {
22022 case NM_P_SLL:
22023 if (rt == 0 && shift == 0) {
22024 /* NOP */
22025 } else if (rt == 0 && shift == 3) {
22026 /* EHB - treat as NOP */
22027 } else if (rt == 0 && shift == 5) {
22028 /* PAUSE - treat as NOP */
22029 } else if (rt == 0 && shift == 6) {
22030 /* SYNC */
22031 gen_sync(extract32(ctx->opcode, 16, 5));
22032 } else {
22033 /* SLL */
22034 gen_shift_imm(ctx, OPC_SLL, rt, rs,
22035 extract32(ctx->opcode, 0, 5));
22037 break;
22038 case NM_SRL:
22039 gen_shift_imm(ctx, OPC_SRL, rt, rs,
22040 extract32(ctx->opcode, 0, 5));
22041 break;
22042 case NM_SRA:
22043 gen_shift_imm(ctx, OPC_SRA, rt, rs,
22044 extract32(ctx->opcode, 0, 5));
22045 break;
22046 case NM_ROTR:
22047 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
22048 extract32(ctx->opcode, 0, 5));
22049 break;
22052 break;
22053 case NM_P_ROTX:
22054 check_nms(ctx);
22055 if (rt != 0) {
22056 TCGv t0 = tcg_temp_new();
22057 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
22058 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
22059 << 1);
22060 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
22062 gen_load_gpr(t0, rs);
22063 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
22064 tcg_temp_free(t0);
22066 tcg_temp_free_i32(shift);
22067 tcg_temp_free_i32(shiftx);
22068 tcg_temp_free_i32(stripe);
22070 break;
22071 case NM_P_INS:
22072 switch (((ctx->opcode >> 10) & 2) |
22073 (extract32(ctx->opcode, 5, 1))) {
22074 case NM_INS:
22075 check_nms(ctx);
22076 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
22077 extract32(ctx->opcode, 6, 5));
22078 break;
22079 default:
22080 generate_exception_end(ctx, EXCP_RI);
22081 break;
22083 break;
22084 case NM_P_EXT:
22085 switch (((ctx->opcode >> 10) & 2) |
22086 (extract32(ctx->opcode, 5, 1))) {
22087 case NM_EXT:
22088 check_nms(ctx);
22089 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
22090 extract32(ctx->opcode, 6, 5));
22091 break;
22092 default:
22093 generate_exception_end(ctx, EXCP_RI);
22094 break;
22096 break;
22097 default:
22098 generate_exception_end(ctx, EXCP_RI);
22099 break;
22101 break;
22102 case NM_POOL32F:
22103 gen_pool32f_nanomips_insn(ctx);
22104 break;
22105 case NM_POOL32S:
22106 break;
22107 case NM_P_LUI:
22108 switch (extract32(ctx->opcode, 1, 1)) {
22109 case NM_LUI:
22110 if (rt != 0) {
22111 tcg_gen_movi_tl(cpu_gpr[rt],
22112 sextract32(ctx->opcode, 0, 1) << 31 |
22113 extract32(ctx->opcode, 2, 10) << 21 |
22114 extract32(ctx->opcode, 12, 9) << 12);
22116 break;
22117 case NM_ALUIPC:
22118 if (rt != 0) {
22119 offset = sextract32(ctx->opcode, 0, 1) << 31 |
22120 extract32(ctx->opcode, 2, 10) << 21 |
22121 extract32(ctx->opcode, 12, 9) << 12;
22122 target_long addr;
22123 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
22124 tcg_gen_movi_tl(cpu_gpr[rt], addr);
22126 break;
22128 break;
22129 case NM_P_GP_BH:
22131 uint32_t u = extract32(ctx->opcode, 0, 18);
22133 switch (extract32(ctx->opcode, 18, 3)) {
22134 case NM_LBGP:
22135 gen_ld(ctx, OPC_LB, rt, 28, u);
22136 break;
22137 case NM_SBGP:
22138 gen_st(ctx, OPC_SB, rt, 28, u);
22139 break;
22140 case NM_LBUGP:
22141 gen_ld(ctx, OPC_LBU, rt, 28, u);
22142 break;
22143 case NM_ADDIUGP_B:
22144 if (rt != 0) {
22145 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
22147 break;
22148 case NM_P_GP_LH:
22149 u &= ~1;
22150 switch (ctx->opcode & 1) {
22151 case NM_LHGP:
22152 gen_ld(ctx, OPC_LH, rt, 28, u);
22153 break;
22154 case NM_LHUGP:
22155 gen_ld(ctx, OPC_LHU, rt, 28, u);
22156 break;
22158 break;
22159 case NM_P_GP_SH:
22160 u &= ~1;
22161 switch (ctx->opcode & 1) {
22162 case NM_SHGP:
22163 gen_st(ctx, OPC_SH, rt, 28, u);
22164 break;
22165 default:
22166 generate_exception_end(ctx, EXCP_RI);
22167 break;
22169 break;
22170 case NM_P_GP_CP1:
22171 u &= ~0x3;
22172 switch (ctx->opcode & 0x3) {
22173 case NM_LWC1GP:
22174 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
22175 break;
22176 case NM_LDC1GP:
22177 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
22178 break;
22179 case NM_SWC1GP:
22180 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
22181 break;
22182 case NM_SDC1GP:
22183 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
22184 break;
22186 break;
22187 default:
22188 generate_exception_end(ctx, EXCP_RI);
22189 break;
22192 break;
22193 case NM_P_LS_U12:
22195 uint32_t u = extract32(ctx->opcode, 0, 12);
22197 switch (extract32(ctx->opcode, 12, 4)) {
22198 case NM_P_PREFU12:
22199 if (rt == 31) {
22200 /* SYNCI */
22202 * Break the TB to be able to sync copied instructions
22203 * immediately.
22205 ctx->base.is_jmp = DISAS_STOP;
22206 } else {
22207 /* PREF */
22208 /* Treat as NOP. */
22210 break;
22211 case NM_LB:
22212 gen_ld(ctx, OPC_LB, rt, rs, u);
22213 break;
22214 case NM_LH:
22215 gen_ld(ctx, OPC_LH, rt, rs, u);
22216 break;
22217 case NM_LW:
22218 gen_ld(ctx, OPC_LW, rt, rs, u);
22219 break;
22220 case NM_LBU:
22221 gen_ld(ctx, OPC_LBU, rt, rs, u);
22222 break;
22223 case NM_LHU:
22224 gen_ld(ctx, OPC_LHU, rt, rs, u);
22225 break;
22226 case NM_SB:
22227 gen_st(ctx, OPC_SB, rt, rs, u);
22228 break;
22229 case NM_SH:
22230 gen_st(ctx, OPC_SH, rt, rs, u);
22231 break;
22232 case NM_SW:
22233 gen_st(ctx, OPC_SW, rt, rs, u);
22234 break;
22235 case NM_LWC1:
22236 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
22237 break;
22238 case NM_LDC1:
22239 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
22240 break;
22241 case NM_SWC1:
22242 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
22243 break;
22244 case NM_SDC1:
22245 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
22246 break;
22247 default:
22248 generate_exception_end(ctx, EXCP_RI);
22249 break;
22252 break;
22253 case NM_P_LS_S9:
22255 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
22256 extract32(ctx->opcode, 0, 8);
22258 switch (extract32(ctx->opcode, 8, 3)) {
22259 case NM_P_LS_S0:
22260 switch (extract32(ctx->opcode, 11, 4)) {
22261 case NM_LBS9:
22262 gen_ld(ctx, OPC_LB, rt, rs, s);
22263 break;
22264 case NM_LHS9:
22265 gen_ld(ctx, OPC_LH, rt, rs, s);
22266 break;
22267 case NM_LWS9:
22268 gen_ld(ctx, OPC_LW, rt, rs, s);
22269 break;
22270 case NM_LBUS9:
22271 gen_ld(ctx, OPC_LBU, rt, rs, s);
22272 break;
22273 case NM_LHUS9:
22274 gen_ld(ctx, OPC_LHU, rt, rs, s);
22275 break;
22276 case NM_SBS9:
22277 gen_st(ctx, OPC_SB, rt, rs, s);
22278 break;
22279 case NM_SHS9:
22280 gen_st(ctx, OPC_SH, rt, rs, s);
22281 break;
22282 case NM_SWS9:
22283 gen_st(ctx, OPC_SW, rt, rs, s);
22284 break;
22285 case NM_LWC1S9:
22286 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
22287 break;
22288 case NM_LDC1S9:
22289 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
22290 break;
22291 case NM_SWC1S9:
22292 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
22293 break;
22294 case NM_SDC1S9:
22295 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
22296 break;
22297 case NM_P_PREFS9:
22298 if (rt == 31) {
22299 /* SYNCI */
22301 * Break the TB to be able to sync copied instructions
22302 * immediately.
22304 ctx->base.is_jmp = DISAS_STOP;
22305 } else {
22306 /* PREF */
22307 /* Treat as NOP. */
22309 break;
22310 default:
22311 generate_exception_end(ctx, EXCP_RI);
22312 break;
22314 break;
22315 case NM_P_LS_S1:
22316 switch (extract32(ctx->opcode, 11, 4)) {
22317 case NM_UALH:
22318 case NM_UASH:
22319 check_nms(ctx);
22321 TCGv t0 = tcg_temp_new();
22322 TCGv t1 = tcg_temp_new();
22324 gen_base_offset_addr(ctx, t0, rs, s);
22326 switch (extract32(ctx->opcode, 11, 4)) {
22327 case NM_UALH:
22328 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
22329 MO_UNALN);
22330 gen_store_gpr(t0, rt);
22331 break;
22332 case NM_UASH:
22333 gen_load_gpr(t1, rt);
22334 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
22335 MO_UNALN);
22336 break;
22338 tcg_temp_free(t0);
22339 tcg_temp_free(t1);
22341 break;
22342 case NM_P_LL:
22343 switch (ctx->opcode & 0x03) {
22344 case NM_LL:
22345 gen_ld(ctx, OPC_LL, rt, rs, s);
22346 break;
22347 case NM_LLWP:
22348 check_xnp(ctx);
22349 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22350 break;
22352 break;
22353 case NM_P_SC:
22354 switch (ctx->opcode & 0x03) {
22355 case NM_SC:
22356 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
22357 break;
22358 case NM_SCWP:
22359 check_xnp(ctx);
22360 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22361 false);
22362 break;
22364 break;
22365 case NM_CACHE:
22366 check_cp0_enabled(ctx);
22367 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22368 gen_cache_operation(ctx, rt, rs, s);
22370 break;
22372 break;
22373 case NM_P_LS_E0:
22374 switch (extract32(ctx->opcode, 11, 4)) {
22375 case NM_LBE:
22376 check_eva(ctx);
22377 check_cp0_enabled(ctx);
22378 gen_ld(ctx, OPC_LBE, rt, rs, s);
22379 break;
22380 case NM_SBE:
22381 check_eva(ctx);
22382 check_cp0_enabled(ctx);
22383 gen_st(ctx, OPC_SBE, rt, rs, s);
22384 break;
22385 case NM_LBUE:
22386 check_eva(ctx);
22387 check_cp0_enabled(ctx);
22388 gen_ld(ctx, OPC_LBUE, rt, rs, s);
22389 break;
22390 case NM_P_PREFE:
22391 if (rt == 31) {
22392 /* case NM_SYNCIE */
22393 check_eva(ctx);
22394 check_cp0_enabled(ctx);
22396 * Break the TB to be able to sync copied instructions
22397 * immediately.
22399 ctx->base.is_jmp = DISAS_STOP;
22400 } else {
22401 /* case NM_PREFE */
22402 check_eva(ctx);
22403 check_cp0_enabled(ctx);
22404 /* Treat as NOP. */
22406 break;
22407 case NM_LHE:
22408 check_eva(ctx);
22409 check_cp0_enabled(ctx);
22410 gen_ld(ctx, OPC_LHE, rt, rs, s);
22411 break;
22412 case NM_SHE:
22413 check_eva(ctx);
22414 check_cp0_enabled(ctx);
22415 gen_st(ctx, OPC_SHE, rt, rs, s);
22416 break;
22417 case NM_LHUE:
22418 check_eva(ctx);
22419 check_cp0_enabled(ctx);
22420 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22421 break;
22422 case NM_CACHEE:
22423 check_nms_dl_il_sl_tl_l2c(ctx);
22424 gen_cache_operation(ctx, rt, rs, s);
22425 break;
22426 case NM_LWE:
22427 check_eva(ctx);
22428 check_cp0_enabled(ctx);
22429 gen_ld(ctx, OPC_LWE, rt, rs, s);
22430 break;
22431 case NM_SWE:
22432 check_eva(ctx);
22433 check_cp0_enabled(ctx);
22434 gen_st(ctx, OPC_SWE, rt, rs, s);
22435 break;
22436 case NM_P_LLE:
22437 switch (extract32(ctx->opcode, 2, 2)) {
22438 case NM_LLE:
22439 check_xnp(ctx);
22440 check_eva(ctx);
22441 check_cp0_enabled(ctx);
22442 gen_ld(ctx, OPC_LLE, rt, rs, s);
22443 break;
22444 case NM_LLWPE:
22445 check_xnp(ctx);
22446 check_eva(ctx);
22447 check_cp0_enabled(ctx);
22448 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22449 break;
22450 default:
22451 generate_exception_end(ctx, EXCP_RI);
22452 break;
22454 break;
22455 case NM_P_SCE:
22456 switch (extract32(ctx->opcode, 2, 2)) {
22457 case NM_SCE:
22458 check_xnp(ctx);
22459 check_eva(ctx);
22460 check_cp0_enabled(ctx);
22461 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22462 break;
22463 case NM_SCWPE:
22464 check_xnp(ctx);
22465 check_eva(ctx);
22466 check_cp0_enabled(ctx);
22467 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22468 true);
22469 break;
22470 default:
22471 generate_exception_end(ctx, EXCP_RI);
22472 break;
22474 break;
22476 break;
22477 case NM_P_LS_WM:
22478 case NM_P_LS_UAWM:
22479 check_nms(ctx);
22481 int count = extract32(ctx->opcode, 12, 3);
22482 int counter = 0;
22484 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22485 extract32(ctx->opcode, 0, 8);
22486 TCGv va = tcg_temp_new();
22487 TCGv t1 = tcg_temp_new();
22488 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22489 NM_P_LS_UAWM ? MO_UNALN : 0;
22491 count = (count == 0) ? 8 : count;
22492 while (counter != count) {
22493 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22494 int this_offset = offset + (counter << 2);
22496 gen_base_offset_addr(ctx, va, rs, this_offset);
22498 switch (extract32(ctx->opcode, 11, 1)) {
22499 case NM_LWM:
22500 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22501 memop | MO_TESL);
22502 gen_store_gpr(t1, this_rt);
22503 if ((this_rt == rs) &&
22504 (counter != (count - 1))) {
22505 /* UNPREDICTABLE */
22507 break;
22508 case NM_SWM:
22509 this_rt = (rt == 0) ? 0 : this_rt;
22510 gen_load_gpr(t1, this_rt);
22511 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22512 memop | MO_TEUL);
22513 break;
22515 counter++;
22517 tcg_temp_free(va);
22518 tcg_temp_free(t1);
22520 break;
22521 default:
22522 generate_exception_end(ctx, EXCP_RI);
22523 break;
22526 break;
22527 case NM_MOVE_BALC:
22528 check_nms(ctx);
22530 TCGv t0 = tcg_temp_new();
22531 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22532 extract32(ctx->opcode, 1, 20) << 1;
22533 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22534 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22535 extract32(ctx->opcode, 21, 3));
22536 gen_load_gpr(t0, rt);
22537 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22538 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22539 tcg_temp_free(t0);
22541 break;
22542 case NM_P_BAL:
22544 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22545 extract32(ctx->opcode, 1, 24) << 1;
22547 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22548 /* BC */
22549 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22550 } else {
22551 /* BALC */
22552 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22555 break;
22556 case NM_P_J:
22557 switch (extract32(ctx->opcode, 12, 4)) {
22558 case NM_JALRC:
22559 case NM_JALRC_HB:
22560 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22561 break;
22562 case NM_P_BALRSC:
22563 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22564 break;
22565 default:
22566 generate_exception_end(ctx, EXCP_RI);
22567 break;
22569 break;
22570 case NM_P_BR1:
22572 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22573 extract32(ctx->opcode, 1, 13) << 1;
22574 switch (extract32(ctx->opcode, 14, 2)) {
22575 case NM_BEQC:
22576 check_nms(ctx);
22577 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22578 break;
22579 case NM_P_BR3A:
22580 s = sextract32(ctx->opcode, 0, 1) << 14 |
22581 extract32(ctx->opcode, 1, 13) << 1;
22582 check_cp1_enabled(ctx);
22583 switch (extract32(ctx->opcode, 16, 5)) {
22584 case NM_BC1EQZC:
22585 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22586 break;
22587 case NM_BC1NEZC:
22588 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22589 break;
22590 case NM_BPOSGE32C:
22591 check_dsp_r3(ctx);
22593 int32_t imm = extract32(ctx->opcode, 1, 13) |
22594 extract32(ctx->opcode, 0, 1) << 13;
22596 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22597 imm);
22599 break;
22600 default:
22601 generate_exception_end(ctx, EXCP_RI);
22602 break;
22604 break;
22605 case NM_BGEC:
22606 if (rs == rt) {
22607 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22608 } else {
22609 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22611 break;
22612 case NM_BGEUC:
22613 if (rs == rt || rt == 0) {
22614 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22615 } else if (rs == 0) {
22616 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22617 } else {
22618 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22620 break;
22623 break;
22624 case NM_P_BR2:
22626 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22627 extract32(ctx->opcode, 1, 13) << 1;
22628 switch (extract32(ctx->opcode, 14, 2)) {
22629 case NM_BNEC:
22630 check_nms(ctx);
22631 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22632 break;
22633 case NM_BLTC:
22634 if (rs != 0 && rt != 0 && rs == rt) {
22635 /* NOP */
22636 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22637 } else {
22638 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22640 break;
22641 case NM_BLTUC:
22642 if (rs == 0 || rs == rt) {
22643 /* NOP */
22644 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22645 } else {
22646 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22648 break;
22649 default:
22650 generate_exception_end(ctx, EXCP_RI);
22651 break;
22654 break;
22655 case NM_P_BRI:
22657 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22658 extract32(ctx->opcode, 1, 10) << 1;
22659 uint32_t u = extract32(ctx->opcode, 11, 7);
22661 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22662 rt, u, s);
22664 break;
22665 default:
22666 generate_exception_end(ctx, EXCP_RI);
22667 break;
22669 return 4;
22672 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22674 uint32_t op;
22675 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22676 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22677 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22678 int offset;
22679 int imm;
22681 /* make sure instructions are on a halfword boundary */
22682 if (ctx->base.pc_next & 0x1) {
22683 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22684 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22685 tcg_temp_free(tmp);
22686 generate_exception_end(ctx, EXCP_AdEL);
22687 return 2;
22690 op = extract32(ctx->opcode, 10, 6);
22691 switch (op) {
22692 case NM_P16_MV:
22693 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22694 if (rt != 0) {
22695 /* MOVE */
22696 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22697 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22698 } else {
22699 /* P16.RI */
22700 switch (extract32(ctx->opcode, 3, 2)) {
22701 case NM_P16_SYSCALL:
22702 if (extract32(ctx->opcode, 2, 1) == 0) {
22703 generate_exception_end(ctx, EXCP_SYSCALL);
22704 } else {
22705 generate_exception_end(ctx, EXCP_RI);
22707 break;
22708 case NM_BREAK16:
22709 generate_exception_end(ctx, EXCP_BREAK);
22710 break;
22711 case NM_SDBBP16:
22712 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22713 gen_helper_do_semihosting(cpu_env);
22714 } else {
22715 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22716 generate_exception_end(ctx, EXCP_RI);
22717 } else {
22718 generate_exception_end(ctx, EXCP_DBp);
22721 break;
22722 default:
22723 generate_exception_end(ctx, EXCP_RI);
22724 break;
22727 break;
22728 case NM_P16_SHIFT:
22730 int shift = extract32(ctx->opcode, 0, 3);
22731 uint32_t opc = 0;
22732 shift = (shift == 0) ? 8 : shift;
22734 switch (extract32(ctx->opcode, 3, 1)) {
22735 case NM_SLL16:
22736 opc = OPC_SLL;
22737 break;
22738 case NM_SRL16:
22739 opc = OPC_SRL;
22740 break;
22742 gen_shift_imm(ctx, opc, rt, rs, shift);
22744 break;
22745 case NM_P16C:
22746 switch (ctx->opcode & 1) {
22747 case NM_POOL16C_0:
22748 gen_pool16c_nanomips_insn(ctx);
22749 break;
22750 case NM_LWXS16:
22751 gen_ldxs(ctx, rt, rs, rd);
22752 break;
22754 break;
22755 case NM_P16_A1:
22756 switch (extract32(ctx->opcode, 6, 1)) {
22757 case NM_ADDIUR1SP:
22758 imm = extract32(ctx->opcode, 0, 6) << 2;
22759 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22760 break;
22761 default:
22762 generate_exception_end(ctx, EXCP_RI);
22763 break;
22765 break;
22766 case NM_P16_A2:
22767 switch (extract32(ctx->opcode, 3, 1)) {
22768 case NM_ADDIUR2:
22769 imm = extract32(ctx->opcode, 0, 3) << 2;
22770 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22771 break;
22772 case NM_P_ADDIURS5:
22773 rt = extract32(ctx->opcode, 5, 5);
22774 if (rt != 0) {
22775 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22776 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22777 (extract32(ctx->opcode, 0, 3));
22778 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22780 break;
22782 break;
22783 case NM_P16_ADDU:
22784 switch (ctx->opcode & 0x1) {
22785 case NM_ADDU16:
22786 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22787 break;
22788 case NM_SUBU16:
22789 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22790 break;
22792 break;
22793 case NM_P16_4X4:
22794 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22795 extract32(ctx->opcode, 5, 3);
22796 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22797 extract32(ctx->opcode, 0, 3);
22798 rt = decode_gpr_gpr4(rt);
22799 rs = decode_gpr_gpr4(rs);
22800 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22801 (extract32(ctx->opcode, 3, 1))) {
22802 case NM_ADDU4X4:
22803 check_nms(ctx);
22804 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22805 break;
22806 case NM_MUL4X4:
22807 check_nms(ctx);
22808 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22809 break;
22810 default:
22811 generate_exception_end(ctx, EXCP_RI);
22812 break;
22814 break;
22815 case NM_LI16:
22817 int imm = extract32(ctx->opcode, 0, 7);
22818 imm = (imm == 0x7f ? -1 : imm);
22819 if (rt != 0) {
22820 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22823 break;
22824 case NM_ANDI16:
22826 uint32_t u = extract32(ctx->opcode, 0, 4);
22827 u = (u == 12) ? 0xff :
22828 (u == 13) ? 0xffff : u;
22829 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22831 break;
22832 case NM_P16_LB:
22833 offset = extract32(ctx->opcode, 0, 2);
22834 switch (extract32(ctx->opcode, 2, 2)) {
22835 case NM_LB16:
22836 gen_ld(ctx, OPC_LB, rt, rs, offset);
22837 break;
22838 case NM_SB16:
22839 rt = decode_gpr_gpr3_src_store(
22840 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22841 gen_st(ctx, OPC_SB, rt, rs, offset);
22842 break;
22843 case NM_LBU16:
22844 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22845 break;
22846 default:
22847 generate_exception_end(ctx, EXCP_RI);
22848 break;
22850 break;
22851 case NM_P16_LH:
22852 offset = extract32(ctx->opcode, 1, 2) << 1;
22853 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22854 case NM_LH16:
22855 gen_ld(ctx, OPC_LH, rt, rs, offset);
22856 break;
22857 case NM_SH16:
22858 rt = decode_gpr_gpr3_src_store(
22859 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22860 gen_st(ctx, OPC_SH, rt, rs, offset);
22861 break;
22862 case NM_LHU16:
22863 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22864 break;
22865 default:
22866 generate_exception_end(ctx, EXCP_RI);
22867 break;
22869 break;
22870 case NM_LW16:
22871 offset = extract32(ctx->opcode, 0, 4) << 2;
22872 gen_ld(ctx, OPC_LW, rt, rs, offset);
22873 break;
22874 case NM_LWSP16:
22875 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22876 offset = extract32(ctx->opcode, 0, 5) << 2;
22877 gen_ld(ctx, OPC_LW, rt, 29, offset);
22878 break;
22879 case NM_LW4X4:
22880 check_nms(ctx);
22881 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22882 extract32(ctx->opcode, 5, 3);
22883 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22884 extract32(ctx->opcode, 0, 3);
22885 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22886 (extract32(ctx->opcode, 8, 1) << 2);
22887 rt = decode_gpr_gpr4(rt);
22888 rs = decode_gpr_gpr4(rs);
22889 gen_ld(ctx, OPC_LW, rt, rs, offset);
22890 break;
22891 case NM_SW4X4:
22892 check_nms(ctx);
22893 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22894 extract32(ctx->opcode, 5, 3);
22895 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22896 extract32(ctx->opcode, 0, 3);
22897 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22898 (extract32(ctx->opcode, 8, 1) << 2);
22899 rt = decode_gpr_gpr4_zero(rt);
22900 rs = decode_gpr_gpr4(rs);
22901 gen_st(ctx, OPC_SW, rt, rs, offset);
22902 break;
22903 case NM_LWGP16:
22904 offset = extract32(ctx->opcode, 0, 7) << 2;
22905 gen_ld(ctx, OPC_LW, rt, 28, offset);
22906 break;
22907 case NM_SWSP16:
22908 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22909 offset = extract32(ctx->opcode, 0, 5) << 2;
22910 gen_st(ctx, OPC_SW, rt, 29, offset);
22911 break;
22912 case NM_SW16:
22913 rt = decode_gpr_gpr3_src_store(
22914 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22915 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22916 offset = extract32(ctx->opcode, 0, 4) << 2;
22917 gen_st(ctx, OPC_SW, rt, rs, offset);
22918 break;
22919 case NM_SWGP16:
22920 rt = decode_gpr_gpr3_src_store(
22921 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22922 offset = extract32(ctx->opcode, 0, 7) << 2;
22923 gen_st(ctx, OPC_SW, rt, 28, offset);
22924 break;
22925 case NM_BC16:
22926 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22927 (sextract32(ctx->opcode, 0, 1) << 10) |
22928 (extract32(ctx->opcode, 1, 9) << 1));
22929 break;
22930 case NM_BALC16:
22931 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22932 (sextract32(ctx->opcode, 0, 1) << 10) |
22933 (extract32(ctx->opcode, 1, 9) << 1));
22934 break;
22935 case NM_BEQZC16:
22936 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22937 (sextract32(ctx->opcode, 0, 1) << 7) |
22938 (extract32(ctx->opcode, 1, 6) << 1));
22939 break;
22940 case NM_BNEZC16:
22941 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22942 (sextract32(ctx->opcode, 0, 1) << 7) |
22943 (extract32(ctx->opcode, 1, 6) << 1));
22944 break;
22945 case NM_P16_BR:
22946 switch (ctx->opcode & 0xf) {
22947 case 0:
22948 /* P16.JRC */
22949 switch (extract32(ctx->opcode, 4, 1)) {
22950 case NM_JRC:
22951 gen_compute_branch_nm(ctx, OPC_JR, 2,
22952 extract32(ctx->opcode, 5, 5), 0, 0);
22953 break;
22954 case NM_JALRC16:
22955 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22956 extract32(ctx->opcode, 5, 5), 31, 0);
22957 break;
22959 break;
22960 default:
22962 /* P16.BRI */
22963 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22964 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22965 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22966 extract32(ctx->opcode, 0, 4) << 1);
22968 break;
22970 break;
22971 case NM_P16_SR:
22973 int count = extract32(ctx->opcode, 0, 4);
22974 int u = extract32(ctx->opcode, 4, 4) << 4;
22976 rt = 30 + extract32(ctx->opcode, 9, 1);
22977 switch (extract32(ctx->opcode, 8, 1)) {
22978 case NM_SAVE16:
22979 gen_save(ctx, rt, count, 0, u);
22980 break;
22981 case NM_RESTORE_JRC16:
22982 gen_restore(ctx, rt, count, 0, u);
22983 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22984 break;
22987 break;
22988 case NM_MOVEP:
22989 case NM_MOVEPREV:
22990 check_nms(ctx);
22992 static const int gpr2reg1[] = {4, 5, 6, 7};
22993 static const int gpr2reg2[] = {5, 6, 7, 8};
22994 int re;
22995 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22996 extract32(ctx->opcode, 8, 1);
22997 int r1 = gpr2reg1[rd2];
22998 int r2 = gpr2reg2[rd2];
22999 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
23000 extract32(ctx->opcode, 0, 3);
23001 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
23002 extract32(ctx->opcode, 5, 3);
23003 TCGv t0 = tcg_temp_new();
23004 TCGv t1 = tcg_temp_new();
23005 if (op == NM_MOVEP) {
23006 rd = r1;
23007 re = r2;
23008 rs = decode_gpr_gpr4_zero(r3);
23009 rt = decode_gpr_gpr4_zero(r4);
23010 } else {
23011 rd = decode_gpr_gpr4(r3);
23012 re = decode_gpr_gpr4(r4);
23013 rs = r1;
23014 rt = r2;
23016 gen_load_gpr(t0, rs);
23017 gen_load_gpr(t1, rt);
23018 tcg_gen_mov_tl(cpu_gpr[rd], t0);
23019 tcg_gen_mov_tl(cpu_gpr[re], t1);
23020 tcg_temp_free(t0);
23021 tcg_temp_free(t1);
23023 break;
23024 default:
23025 return decode_nanomips_32_48_opc(env, ctx);
23028 return 2;
23032 /* SmartMIPS extension to MIPS32 */
23034 #if defined(TARGET_MIPS64)
23036 /* MDMX extension to MIPS64 */
23038 #endif
23040 /* MIPSDSP functions. */
23041 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
23042 int rd, int base, int offset)
23044 TCGv t0;
23046 check_dsp(ctx);
23047 t0 = tcg_temp_new();
23049 if (base == 0) {
23050 gen_load_gpr(t0, offset);
23051 } else if (offset == 0) {
23052 gen_load_gpr(t0, base);
23053 } else {
23054 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
23057 switch (opc) {
23058 case OPC_LBUX:
23059 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
23060 gen_store_gpr(t0, rd);
23061 break;
23062 case OPC_LHX:
23063 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
23064 gen_store_gpr(t0, rd);
23065 break;
23066 case OPC_LWX:
23067 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
23068 gen_store_gpr(t0, rd);
23069 break;
23070 #if defined(TARGET_MIPS64)
23071 case OPC_LDX:
23072 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
23073 gen_store_gpr(t0, rd);
23074 break;
23075 #endif
23077 tcg_temp_free(t0);
23080 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
23081 int ret, int v1, int v2)
23083 TCGv v1_t;
23084 TCGv v2_t;
23086 if (ret == 0) {
23087 /* Treat as NOP. */
23088 return;
23091 v1_t = tcg_temp_new();
23092 v2_t = tcg_temp_new();
23094 gen_load_gpr(v1_t, v1);
23095 gen_load_gpr(v2_t, v2);
23097 switch (op1) {
23098 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
23099 case OPC_MULT_G_2E:
23100 check_dsp_r2(ctx);
23101 switch (op2) {
23102 case OPC_ADDUH_QB:
23103 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
23104 break;
23105 case OPC_ADDUH_R_QB:
23106 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23107 break;
23108 case OPC_ADDQH_PH:
23109 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
23110 break;
23111 case OPC_ADDQH_R_PH:
23112 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23113 break;
23114 case OPC_ADDQH_W:
23115 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
23116 break;
23117 case OPC_ADDQH_R_W:
23118 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23119 break;
23120 case OPC_SUBUH_QB:
23121 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
23122 break;
23123 case OPC_SUBUH_R_QB:
23124 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23125 break;
23126 case OPC_SUBQH_PH:
23127 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
23128 break;
23129 case OPC_SUBQH_R_PH:
23130 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23131 break;
23132 case OPC_SUBQH_W:
23133 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
23134 break;
23135 case OPC_SUBQH_R_W:
23136 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23137 break;
23139 break;
23140 case OPC_ABSQ_S_PH_DSP:
23141 switch (op2) {
23142 case OPC_ABSQ_S_QB:
23143 check_dsp_r2(ctx);
23144 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
23145 break;
23146 case OPC_ABSQ_S_PH:
23147 check_dsp(ctx);
23148 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
23149 break;
23150 case OPC_ABSQ_S_W:
23151 check_dsp(ctx);
23152 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
23153 break;
23154 case OPC_PRECEQ_W_PHL:
23155 check_dsp(ctx);
23156 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
23157 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23158 break;
23159 case OPC_PRECEQ_W_PHR:
23160 check_dsp(ctx);
23161 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
23162 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
23163 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23164 break;
23165 case OPC_PRECEQU_PH_QBL:
23166 check_dsp(ctx);
23167 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
23168 break;
23169 case OPC_PRECEQU_PH_QBR:
23170 check_dsp(ctx);
23171 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
23172 break;
23173 case OPC_PRECEQU_PH_QBLA:
23174 check_dsp(ctx);
23175 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
23176 break;
23177 case OPC_PRECEQU_PH_QBRA:
23178 check_dsp(ctx);
23179 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
23180 break;
23181 case OPC_PRECEU_PH_QBL:
23182 check_dsp(ctx);
23183 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
23184 break;
23185 case OPC_PRECEU_PH_QBR:
23186 check_dsp(ctx);
23187 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
23188 break;
23189 case OPC_PRECEU_PH_QBLA:
23190 check_dsp(ctx);
23191 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
23192 break;
23193 case OPC_PRECEU_PH_QBRA:
23194 check_dsp(ctx);
23195 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
23196 break;
23198 break;
23199 case OPC_ADDU_QB_DSP:
23200 switch (op2) {
23201 case OPC_ADDQ_PH:
23202 check_dsp(ctx);
23203 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23204 break;
23205 case OPC_ADDQ_S_PH:
23206 check_dsp(ctx);
23207 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23208 break;
23209 case OPC_ADDQ_S_W:
23210 check_dsp(ctx);
23211 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23212 break;
23213 case OPC_ADDU_QB:
23214 check_dsp(ctx);
23215 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23216 break;
23217 case OPC_ADDU_S_QB:
23218 check_dsp(ctx);
23219 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23220 break;
23221 case OPC_ADDU_PH:
23222 check_dsp_r2(ctx);
23223 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23224 break;
23225 case OPC_ADDU_S_PH:
23226 check_dsp_r2(ctx);
23227 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23228 break;
23229 case OPC_SUBQ_PH:
23230 check_dsp(ctx);
23231 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23232 break;
23233 case OPC_SUBQ_S_PH:
23234 check_dsp(ctx);
23235 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23236 break;
23237 case OPC_SUBQ_S_W:
23238 check_dsp(ctx);
23239 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23240 break;
23241 case OPC_SUBU_QB:
23242 check_dsp(ctx);
23243 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23244 break;
23245 case OPC_SUBU_S_QB:
23246 check_dsp(ctx);
23247 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23248 break;
23249 case OPC_SUBU_PH:
23250 check_dsp_r2(ctx);
23251 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23252 break;
23253 case OPC_SUBU_S_PH:
23254 check_dsp_r2(ctx);
23255 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23256 break;
23257 case OPC_ADDSC:
23258 check_dsp(ctx);
23259 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_ADDWC:
23262 check_dsp(ctx);
23263 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23264 break;
23265 case OPC_MODSUB:
23266 check_dsp(ctx);
23267 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
23268 break;
23269 case OPC_RADDU_W_QB:
23270 check_dsp(ctx);
23271 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
23272 break;
23274 break;
23275 case OPC_CMPU_EQ_QB_DSP:
23276 switch (op2) {
23277 case OPC_PRECR_QB_PH:
23278 check_dsp_r2(ctx);
23279 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23280 break;
23281 case OPC_PRECRQ_QB_PH:
23282 check_dsp(ctx);
23283 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23284 break;
23285 case OPC_PRECR_SRA_PH_W:
23286 check_dsp_r2(ctx);
23288 TCGv_i32 sa_t = tcg_const_i32(v2);
23289 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
23290 cpu_gpr[ret]);
23291 tcg_temp_free_i32(sa_t);
23292 break;
23294 case OPC_PRECR_SRA_R_PH_W:
23295 check_dsp_r2(ctx);
23297 TCGv_i32 sa_t = tcg_const_i32(v2);
23298 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
23299 cpu_gpr[ret]);
23300 tcg_temp_free_i32(sa_t);
23301 break;
23303 case OPC_PRECRQ_PH_W:
23304 check_dsp(ctx);
23305 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
23306 break;
23307 case OPC_PRECRQ_RS_PH_W:
23308 check_dsp(ctx);
23309 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23310 break;
23311 case OPC_PRECRQU_S_QB_PH:
23312 check_dsp(ctx);
23313 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23314 break;
23316 break;
23317 #ifdef TARGET_MIPS64
23318 case OPC_ABSQ_S_QH_DSP:
23319 switch (op2) {
23320 case OPC_PRECEQ_L_PWL:
23321 check_dsp(ctx);
23322 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
23323 break;
23324 case OPC_PRECEQ_L_PWR:
23325 check_dsp(ctx);
23326 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
23327 break;
23328 case OPC_PRECEQ_PW_QHL:
23329 check_dsp(ctx);
23330 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
23331 break;
23332 case OPC_PRECEQ_PW_QHR:
23333 check_dsp(ctx);
23334 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
23335 break;
23336 case OPC_PRECEQ_PW_QHLA:
23337 check_dsp(ctx);
23338 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
23339 break;
23340 case OPC_PRECEQ_PW_QHRA:
23341 check_dsp(ctx);
23342 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
23343 break;
23344 case OPC_PRECEQU_QH_OBL:
23345 check_dsp(ctx);
23346 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
23347 break;
23348 case OPC_PRECEQU_QH_OBR:
23349 check_dsp(ctx);
23350 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
23351 break;
23352 case OPC_PRECEQU_QH_OBLA:
23353 check_dsp(ctx);
23354 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
23355 break;
23356 case OPC_PRECEQU_QH_OBRA:
23357 check_dsp(ctx);
23358 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
23359 break;
23360 case OPC_PRECEU_QH_OBL:
23361 check_dsp(ctx);
23362 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
23363 break;
23364 case OPC_PRECEU_QH_OBR:
23365 check_dsp(ctx);
23366 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
23367 break;
23368 case OPC_PRECEU_QH_OBLA:
23369 check_dsp(ctx);
23370 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
23371 break;
23372 case OPC_PRECEU_QH_OBRA:
23373 check_dsp(ctx);
23374 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
23375 break;
23376 case OPC_ABSQ_S_OB:
23377 check_dsp_r2(ctx);
23378 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
23379 break;
23380 case OPC_ABSQ_S_PW:
23381 check_dsp(ctx);
23382 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
23383 break;
23384 case OPC_ABSQ_S_QH:
23385 check_dsp(ctx);
23386 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
23387 break;
23389 break;
23390 case OPC_ADDU_OB_DSP:
23391 switch (op2) {
23392 case OPC_RADDU_L_OB:
23393 check_dsp(ctx);
23394 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
23395 break;
23396 case OPC_SUBQ_PW:
23397 check_dsp(ctx);
23398 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23399 break;
23400 case OPC_SUBQ_S_PW:
23401 check_dsp(ctx);
23402 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23403 break;
23404 case OPC_SUBQ_QH:
23405 check_dsp(ctx);
23406 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23407 break;
23408 case OPC_SUBQ_S_QH:
23409 check_dsp(ctx);
23410 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23411 break;
23412 case OPC_SUBU_OB:
23413 check_dsp(ctx);
23414 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23415 break;
23416 case OPC_SUBU_S_OB:
23417 check_dsp(ctx);
23418 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23419 break;
23420 case OPC_SUBU_QH:
23421 check_dsp_r2(ctx);
23422 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23423 break;
23424 case OPC_SUBU_S_QH:
23425 check_dsp_r2(ctx);
23426 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23427 break;
23428 case OPC_SUBUH_OB:
23429 check_dsp_r2(ctx);
23430 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23431 break;
23432 case OPC_SUBUH_R_OB:
23433 check_dsp_r2(ctx);
23434 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23435 break;
23436 case OPC_ADDQ_PW:
23437 check_dsp(ctx);
23438 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23439 break;
23440 case OPC_ADDQ_S_PW:
23441 check_dsp(ctx);
23442 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23443 break;
23444 case OPC_ADDQ_QH:
23445 check_dsp(ctx);
23446 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23447 break;
23448 case OPC_ADDQ_S_QH:
23449 check_dsp(ctx);
23450 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23451 break;
23452 case OPC_ADDU_OB:
23453 check_dsp(ctx);
23454 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23455 break;
23456 case OPC_ADDU_S_OB:
23457 check_dsp(ctx);
23458 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23459 break;
23460 case OPC_ADDU_QH:
23461 check_dsp_r2(ctx);
23462 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23463 break;
23464 case OPC_ADDU_S_QH:
23465 check_dsp_r2(ctx);
23466 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23467 break;
23468 case OPC_ADDUH_OB:
23469 check_dsp_r2(ctx);
23470 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23471 break;
23472 case OPC_ADDUH_R_OB:
23473 check_dsp_r2(ctx);
23474 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23475 break;
23477 break;
23478 case OPC_CMPU_EQ_OB_DSP:
23479 switch (op2) {
23480 case OPC_PRECR_OB_QH:
23481 check_dsp_r2(ctx);
23482 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23483 break;
23484 case OPC_PRECR_SRA_QH_PW:
23485 check_dsp_r2(ctx);
23487 TCGv_i32 ret_t = tcg_const_i32(ret);
23488 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23489 tcg_temp_free_i32(ret_t);
23490 break;
23492 case OPC_PRECR_SRA_R_QH_PW:
23493 check_dsp_r2(ctx);
23495 TCGv_i32 sa_v = tcg_const_i32(ret);
23496 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23497 tcg_temp_free_i32(sa_v);
23498 break;
23500 case OPC_PRECRQ_OB_QH:
23501 check_dsp(ctx);
23502 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23503 break;
23504 case OPC_PRECRQ_PW_L:
23505 check_dsp(ctx);
23506 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23507 break;
23508 case OPC_PRECRQ_QH_PW:
23509 check_dsp(ctx);
23510 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23511 break;
23512 case OPC_PRECRQ_RS_QH_PW:
23513 check_dsp(ctx);
23514 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23515 break;
23516 case OPC_PRECRQU_S_OB_QH:
23517 check_dsp(ctx);
23518 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23519 break;
23521 break;
23522 #endif
23525 tcg_temp_free(v1_t);
23526 tcg_temp_free(v2_t);
23529 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23530 int ret, int v1, int v2)
23532 uint32_t op2;
23533 TCGv t0;
23534 TCGv v1_t;
23535 TCGv v2_t;
23537 if (ret == 0) {
23538 /* Treat as NOP. */
23539 return;
23542 t0 = tcg_temp_new();
23543 v1_t = tcg_temp_new();
23544 v2_t = tcg_temp_new();
23546 tcg_gen_movi_tl(t0, v1);
23547 gen_load_gpr(v1_t, v1);
23548 gen_load_gpr(v2_t, v2);
23550 switch (opc) {
23551 case OPC_SHLL_QB_DSP:
23553 op2 = MASK_SHLL_QB(ctx->opcode);
23554 switch (op2) {
23555 case OPC_SHLL_QB:
23556 check_dsp(ctx);
23557 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23558 break;
23559 case OPC_SHLLV_QB:
23560 check_dsp(ctx);
23561 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23562 break;
23563 case OPC_SHLL_PH:
23564 check_dsp(ctx);
23565 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23566 break;
23567 case OPC_SHLLV_PH:
23568 check_dsp(ctx);
23569 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23570 break;
23571 case OPC_SHLL_S_PH:
23572 check_dsp(ctx);
23573 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23574 break;
23575 case OPC_SHLLV_S_PH:
23576 check_dsp(ctx);
23577 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23578 break;
23579 case OPC_SHLL_S_W:
23580 check_dsp(ctx);
23581 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23582 break;
23583 case OPC_SHLLV_S_W:
23584 check_dsp(ctx);
23585 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23586 break;
23587 case OPC_SHRL_QB:
23588 check_dsp(ctx);
23589 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23590 break;
23591 case OPC_SHRLV_QB:
23592 check_dsp(ctx);
23593 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23594 break;
23595 case OPC_SHRL_PH:
23596 check_dsp_r2(ctx);
23597 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23598 break;
23599 case OPC_SHRLV_PH:
23600 check_dsp_r2(ctx);
23601 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23602 break;
23603 case OPC_SHRA_QB:
23604 check_dsp_r2(ctx);
23605 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23606 break;
23607 case OPC_SHRA_R_QB:
23608 check_dsp_r2(ctx);
23609 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23610 break;
23611 case OPC_SHRAV_QB:
23612 check_dsp_r2(ctx);
23613 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23614 break;
23615 case OPC_SHRAV_R_QB:
23616 check_dsp_r2(ctx);
23617 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23618 break;
23619 case OPC_SHRA_PH:
23620 check_dsp(ctx);
23621 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23622 break;
23623 case OPC_SHRA_R_PH:
23624 check_dsp(ctx);
23625 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23626 break;
23627 case OPC_SHRAV_PH:
23628 check_dsp(ctx);
23629 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23630 break;
23631 case OPC_SHRAV_R_PH:
23632 check_dsp(ctx);
23633 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23634 break;
23635 case OPC_SHRA_R_W:
23636 check_dsp(ctx);
23637 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23638 break;
23639 case OPC_SHRAV_R_W:
23640 check_dsp(ctx);
23641 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23642 break;
23643 default: /* Invalid */
23644 MIPS_INVAL("MASK SHLL.QB");
23645 generate_exception_end(ctx, EXCP_RI);
23646 break;
23648 break;
23650 #ifdef TARGET_MIPS64
23651 case OPC_SHLL_OB_DSP:
23652 op2 = MASK_SHLL_OB(ctx->opcode);
23653 switch (op2) {
23654 case OPC_SHLL_PW:
23655 check_dsp(ctx);
23656 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23657 break;
23658 case OPC_SHLLV_PW:
23659 check_dsp(ctx);
23660 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23661 break;
23662 case OPC_SHLL_S_PW:
23663 check_dsp(ctx);
23664 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23665 break;
23666 case OPC_SHLLV_S_PW:
23667 check_dsp(ctx);
23668 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23669 break;
23670 case OPC_SHLL_OB:
23671 check_dsp(ctx);
23672 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23673 break;
23674 case OPC_SHLLV_OB:
23675 check_dsp(ctx);
23676 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23677 break;
23678 case OPC_SHLL_QH:
23679 check_dsp(ctx);
23680 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23681 break;
23682 case OPC_SHLLV_QH:
23683 check_dsp(ctx);
23684 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23685 break;
23686 case OPC_SHLL_S_QH:
23687 check_dsp(ctx);
23688 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23689 break;
23690 case OPC_SHLLV_S_QH:
23691 check_dsp(ctx);
23692 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23693 break;
23694 case OPC_SHRA_OB:
23695 check_dsp_r2(ctx);
23696 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23697 break;
23698 case OPC_SHRAV_OB:
23699 check_dsp_r2(ctx);
23700 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23701 break;
23702 case OPC_SHRA_R_OB:
23703 check_dsp_r2(ctx);
23704 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23705 break;
23706 case OPC_SHRAV_R_OB:
23707 check_dsp_r2(ctx);
23708 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23709 break;
23710 case OPC_SHRA_PW:
23711 check_dsp(ctx);
23712 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23713 break;
23714 case OPC_SHRAV_PW:
23715 check_dsp(ctx);
23716 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23717 break;
23718 case OPC_SHRA_R_PW:
23719 check_dsp(ctx);
23720 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23721 break;
23722 case OPC_SHRAV_R_PW:
23723 check_dsp(ctx);
23724 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23725 break;
23726 case OPC_SHRA_QH:
23727 check_dsp(ctx);
23728 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23729 break;
23730 case OPC_SHRAV_QH:
23731 check_dsp(ctx);
23732 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23733 break;
23734 case OPC_SHRA_R_QH:
23735 check_dsp(ctx);
23736 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23737 break;
23738 case OPC_SHRAV_R_QH:
23739 check_dsp(ctx);
23740 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23741 break;
23742 case OPC_SHRL_OB:
23743 check_dsp(ctx);
23744 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23745 break;
23746 case OPC_SHRLV_OB:
23747 check_dsp(ctx);
23748 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23749 break;
23750 case OPC_SHRL_QH:
23751 check_dsp_r2(ctx);
23752 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23753 break;
23754 case OPC_SHRLV_QH:
23755 check_dsp_r2(ctx);
23756 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23757 break;
23758 default: /* Invalid */
23759 MIPS_INVAL("MASK SHLL.OB");
23760 generate_exception_end(ctx, EXCP_RI);
23761 break;
23763 break;
23764 #endif
23767 tcg_temp_free(t0);
23768 tcg_temp_free(v1_t);
23769 tcg_temp_free(v2_t);
23772 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23773 int ret, int v1, int v2, int check_ret)
23775 TCGv_i32 t0;
23776 TCGv v1_t;
23777 TCGv v2_t;
23779 if ((ret == 0) && (check_ret == 1)) {
23780 /* Treat as NOP. */
23781 return;
23784 t0 = tcg_temp_new_i32();
23785 v1_t = tcg_temp_new();
23786 v2_t = tcg_temp_new();
23788 tcg_gen_movi_i32(t0, ret);
23789 gen_load_gpr(v1_t, v1);
23790 gen_load_gpr(v2_t, v2);
23792 switch (op1) {
23794 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23795 * the same mask and op1.
23797 case OPC_MULT_G_2E:
23798 check_dsp_r2(ctx);
23799 switch (op2) {
23800 case OPC_MUL_PH:
23801 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23802 break;
23803 case OPC_MUL_S_PH:
23804 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23805 break;
23806 case OPC_MULQ_S_W:
23807 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23808 break;
23809 case OPC_MULQ_RS_W:
23810 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23811 break;
23813 break;
23814 case OPC_DPA_W_PH_DSP:
23815 switch (op2) {
23816 case OPC_DPAU_H_QBL:
23817 check_dsp(ctx);
23818 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23819 break;
23820 case OPC_DPAU_H_QBR:
23821 check_dsp(ctx);
23822 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23823 break;
23824 case OPC_DPSU_H_QBL:
23825 check_dsp(ctx);
23826 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23827 break;
23828 case OPC_DPSU_H_QBR:
23829 check_dsp(ctx);
23830 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23831 break;
23832 case OPC_DPA_W_PH:
23833 check_dsp_r2(ctx);
23834 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23835 break;
23836 case OPC_DPAX_W_PH:
23837 check_dsp_r2(ctx);
23838 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23839 break;
23840 case OPC_DPAQ_S_W_PH:
23841 check_dsp(ctx);
23842 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23843 break;
23844 case OPC_DPAQX_S_W_PH:
23845 check_dsp_r2(ctx);
23846 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23847 break;
23848 case OPC_DPAQX_SA_W_PH:
23849 check_dsp_r2(ctx);
23850 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23851 break;
23852 case OPC_DPS_W_PH:
23853 check_dsp_r2(ctx);
23854 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23855 break;
23856 case OPC_DPSX_W_PH:
23857 check_dsp_r2(ctx);
23858 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23859 break;
23860 case OPC_DPSQ_S_W_PH:
23861 check_dsp(ctx);
23862 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23863 break;
23864 case OPC_DPSQX_S_W_PH:
23865 check_dsp_r2(ctx);
23866 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23867 break;
23868 case OPC_DPSQX_SA_W_PH:
23869 check_dsp_r2(ctx);
23870 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23871 break;
23872 case OPC_MULSAQ_S_W_PH:
23873 check_dsp(ctx);
23874 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23875 break;
23876 case OPC_DPAQ_SA_L_W:
23877 check_dsp(ctx);
23878 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23879 break;
23880 case OPC_DPSQ_SA_L_W:
23881 check_dsp(ctx);
23882 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23883 break;
23884 case OPC_MAQ_S_W_PHL:
23885 check_dsp(ctx);
23886 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23887 break;
23888 case OPC_MAQ_S_W_PHR:
23889 check_dsp(ctx);
23890 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23891 break;
23892 case OPC_MAQ_SA_W_PHL:
23893 check_dsp(ctx);
23894 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23895 break;
23896 case OPC_MAQ_SA_W_PHR:
23897 check_dsp(ctx);
23898 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23899 break;
23900 case OPC_MULSA_W_PH:
23901 check_dsp_r2(ctx);
23902 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23903 break;
23905 break;
23906 #ifdef TARGET_MIPS64
23907 case OPC_DPAQ_W_QH_DSP:
23909 int ac = ret & 0x03;
23910 tcg_gen_movi_i32(t0, ac);
23912 switch (op2) {
23913 case OPC_DMADD:
23914 check_dsp(ctx);
23915 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23916 break;
23917 case OPC_DMADDU:
23918 check_dsp(ctx);
23919 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23920 break;
23921 case OPC_DMSUB:
23922 check_dsp(ctx);
23923 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23924 break;
23925 case OPC_DMSUBU:
23926 check_dsp(ctx);
23927 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23928 break;
23929 case OPC_DPA_W_QH:
23930 check_dsp_r2(ctx);
23931 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23932 break;
23933 case OPC_DPAQ_S_W_QH:
23934 check_dsp(ctx);
23935 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23936 break;
23937 case OPC_DPAQ_SA_L_PW:
23938 check_dsp(ctx);
23939 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23940 break;
23941 case OPC_DPAU_H_OBL:
23942 check_dsp(ctx);
23943 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23944 break;
23945 case OPC_DPAU_H_OBR:
23946 check_dsp(ctx);
23947 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23948 break;
23949 case OPC_DPS_W_QH:
23950 check_dsp_r2(ctx);
23951 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23952 break;
23953 case OPC_DPSQ_S_W_QH:
23954 check_dsp(ctx);
23955 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23956 break;
23957 case OPC_DPSQ_SA_L_PW:
23958 check_dsp(ctx);
23959 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23960 break;
23961 case OPC_DPSU_H_OBL:
23962 check_dsp(ctx);
23963 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23964 break;
23965 case OPC_DPSU_H_OBR:
23966 check_dsp(ctx);
23967 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23968 break;
23969 case OPC_MAQ_S_L_PWL:
23970 check_dsp(ctx);
23971 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23972 break;
23973 case OPC_MAQ_S_L_PWR:
23974 check_dsp(ctx);
23975 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23976 break;
23977 case OPC_MAQ_S_W_QHLL:
23978 check_dsp(ctx);
23979 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23980 break;
23981 case OPC_MAQ_SA_W_QHLL:
23982 check_dsp(ctx);
23983 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23984 break;
23985 case OPC_MAQ_S_W_QHLR:
23986 check_dsp(ctx);
23987 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23988 break;
23989 case OPC_MAQ_SA_W_QHLR:
23990 check_dsp(ctx);
23991 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23992 break;
23993 case OPC_MAQ_S_W_QHRL:
23994 check_dsp(ctx);
23995 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23996 break;
23997 case OPC_MAQ_SA_W_QHRL:
23998 check_dsp(ctx);
23999 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
24000 break;
24001 case OPC_MAQ_S_W_QHRR:
24002 check_dsp(ctx);
24003 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
24004 break;
24005 case OPC_MAQ_SA_W_QHRR:
24006 check_dsp(ctx);
24007 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
24008 break;
24009 case OPC_MULSAQ_S_L_PW:
24010 check_dsp(ctx);
24011 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
24012 break;
24013 case OPC_MULSAQ_S_W_QH:
24014 check_dsp(ctx);
24015 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
24016 break;
24019 break;
24020 #endif
24021 case OPC_ADDU_QB_DSP:
24022 switch (op2) {
24023 case OPC_MULEU_S_PH_QBL:
24024 check_dsp(ctx);
24025 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24026 break;
24027 case OPC_MULEU_S_PH_QBR:
24028 check_dsp(ctx);
24029 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24030 break;
24031 case OPC_MULQ_RS_PH:
24032 check_dsp(ctx);
24033 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24034 break;
24035 case OPC_MULEQ_S_W_PHL:
24036 check_dsp(ctx);
24037 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24038 break;
24039 case OPC_MULEQ_S_W_PHR:
24040 check_dsp(ctx);
24041 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24042 break;
24043 case OPC_MULQ_S_PH:
24044 check_dsp_r2(ctx);
24045 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24046 break;
24048 break;
24049 #ifdef TARGET_MIPS64
24050 case OPC_ADDU_OB_DSP:
24051 switch (op2) {
24052 case OPC_MULEQ_S_PW_QHL:
24053 check_dsp(ctx);
24054 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24055 break;
24056 case OPC_MULEQ_S_PW_QHR:
24057 check_dsp(ctx);
24058 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24059 break;
24060 case OPC_MULEU_S_QH_OBL:
24061 check_dsp(ctx);
24062 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24063 break;
24064 case OPC_MULEU_S_QH_OBR:
24065 check_dsp(ctx);
24066 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24067 break;
24068 case OPC_MULQ_RS_QH:
24069 check_dsp(ctx);
24070 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24071 break;
24073 break;
24074 #endif
24077 tcg_temp_free_i32(t0);
24078 tcg_temp_free(v1_t);
24079 tcg_temp_free(v2_t);
24082 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24083 int ret, int val)
24085 int16_t imm;
24086 TCGv t0;
24087 TCGv val_t;
24089 if (ret == 0) {
24090 /* Treat as NOP. */
24091 return;
24094 t0 = tcg_temp_new();
24095 val_t = tcg_temp_new();
24096 gen_load_gpr(val_t, val);
24098 switch (op1) {
24099 case OPC_ABSQ_S_PH_DSP:
24100 switch (op2) {
24101 case OPC_BITREV:
24102 check_dsp(ctx);
24103 gen_helper_bitrev(cpu_gpr[ret], val_t);
24104 break;
24105 case OPC_REPL_QB:
24106 check_dsp(ctx);
24108 target_long result;
24109 imm = (ctx->opcode >> 16) & 0xFF;
24110 result = (uint32_t)imm << 24 |
24111 (uint32_t)imm << 16 |
24112 (uint32_t)imm << 8 |
24113 (uint32_t)imm;
24114 result = (int32_t)result;
24115 tcg_gen_movi_tl(cpu_gpr[ret], result);
24117 break;
24118 case OPC_REPLV_QB:
24119 check_dsp(ctx);
24120 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24121 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24122 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24123 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24124 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24125 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24126 break;
24127 case OPC_REPL_PH:
24128 check_dsp(ctx);
24130 imm = (ctx->opcode >> 16) & 0x03FF;
24131 imm = (int16_t)(imm << 6) >> 6;
24132 tcg_gen_movi_tl(cpu_gpr[ret], \
24133 (target_long)((int32_t)imm << 16 | \
24134 (uint16_t)imm));
24136 break;
24137 case OPC_REPLV_PH:
24138 check_dsp(ctx);
24139 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24140 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24141 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24142 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24143 break;
24145 break;
24146 #ifdef TARGET_MIPS64
24147 case OPC_ABSQ_S_QH_DSP:
24148 switch (op2) {
24149 case OPC_REPL_OB:
24150 check_dsp(ctx);
24152 target_long temp;
24154 imm = (ctx->opcode >> 16) & 0xFF;
24155 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
24156 temp = (temp << 16) | temp;
24157 temp = (temp << 32) | temp;
24158 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24159 break;
24161 case OPC_REPL_PW:
24162 check_dsp(ctx);
24164 target_long temp;
24166 imm = (ctx->opcode >> 16) & 0x03FF;
24167 imm = (int16_t)(imm << 6) >> 6;
24168 temp = ((target_long)imm << 32) \
24169 | ((target_long)imm & 0xFFFFFFFF);
24170 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24171 break;
24173 case OPC_REPL_QH:
24174 check_dsp(ctx);
24176 target_long temp;
24178 imm = (ctx->opcode >> 16) & 0x03FF;
24179 imm = (int16_t)(imm << 6) >> 6;
24181 temp = ((uint64_t)(uint16_t)imm << 48) |
24182 ((uint64_t)(uint16_t)imm << 32) |
24183 ((uint64_t)(uint16_t)imm << 16) |
24184 (uint64_t)(uint16_t)imm;
24185 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24186 break;
24188 case OPC_REPLV_OB:
24189 check_dsp(ctx);
24190 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24191 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24192 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24193 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24194 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24195 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24196 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24197 break;
24198 case OPC_REPLV_PW:
24199 check_dsp(ctx);
24200 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
24201 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24202 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24203 break;
24204 case OPC_REPLV_QH:
24205 check_dsp(ctx);
24206 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24207 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24208 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24209 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24210 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24211 break;
24213 break;
24214 #endif
24216 tcg_temp_free(t0);
24217 tcg_temp_free(val_t);
24220 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
24221 uint32_t op1, uint32_t op2,
24222 int ret, int v1, int v2, int check_ret)
24224 TCGv t1;
24225 TCGv v1_t;
24226 TCGv v2_t;
24228 if ((ret == 0) && (check_ret == 1)) {
24229 /* Treat as NOP. */
24230 return;
24233 t1 = tcg_temp_new();
24234 v1_t = tcg_temp_new();
24235 v2_t = tcg_temp_new();
24237 gen_load_gpr(v1_t, v1);
24238 gen_load_gpr(v2_t, v2);
24240 switch (op1) {
24241 case OPC_CMPU_EQ_QB_DSP:
24242 switch (op2) {
24243 case OPC_CMPU_EQ_QB:
24244 check_dsp(ctx);
24245 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
24246 break;
24247 case OPC_CMPU_LT_QB:
24248 check_dsp(ctx);
24249 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
24250 break;
24251 case OPC_CMPU_LE_QB:
24252 check_dsp(ctx);
24253 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
24254 break;
24255 case OPC_CMPGU_EQ_QB:
24256 check_dsp(ctx);
24257 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
24258 break;
24259 case OPC_CMPGU_LT_QB:
24260 check_dsp(ctx);
24261 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
24262 break;
24263 case OPC_CMPGU_LE_QB:
24264 check_dsp(ctx);
24265 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
24266 break;
24267 case OPC_CMPGDU_EQ_QB:
24268 check_dsp_r2(ctx);
24269 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
24270 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24271 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24272 tcg_gen_shli_tl(t1, t1, 24);
24273 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24274 break;
24275 case OPC_CMPGDU_LT_QB:
24276 check_dsp_r2(ctx);
24277 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
24278 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24279 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24280 tcg_gen_shli_tl(t1, t1, 24);
24281 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24282 break;
24283 case OPC_CMPGDU_LE_QB:
24284 check_dsp_r2(ctx);
24285 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
24286 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24287 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24288 tcg_gen_shli_tl(t1, t1, 24);
24289 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24290 break;
24291 case OPC_CMP_EQ_PH:
24292 check_dsp(ctx);
24293 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
24294 break;
24295 case OPC_CMP_LT_PH:
24296 check_dsp(ctx);
24297 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
24298 break;
24299 case OPC_CMP_LE_PH:
24300 check_dsp(ctx);
24301 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
24302 break;
24303 case OPC_PICK_QB:
24304 check_dsp(ctx);
24305 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24306 break;
24307 case OPC_PICK_PH:
24308 check_dsp(ctx);
24309 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24310 break;
24311 case OPC_PACKRL_PH:
24312 check_dsp(ctx);
24313 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
24314 break;
24316 break;
24317 #ifdef TARGET_MIPS64
24318 case OPC_CMPU_EQ_OB_DSP:
24319 switch (op2) {
24320 case OPC_CMP_EQ_PW:
24321 check_dsp(ctx);
24322 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
24323 break;
24324 case OPC_CMP_LT_PW:
24325 check_dsp(ctx);
24326 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
24327 break;
24328 case OPC_CMP_LE_PW:
24329 check_dsp(ctx);
24330 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
24331 break;
24332 case OPC_CMP_EQ_QH:
24333 check_dsp(ctx);
24334 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
24335 break;
24336 case OPC_CMP_LT_QH:
24337 check_dsp(ctx);
24338 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
24339 break;
24340 case OPC_CMP_LE_QH:
24341 check_dsp(ctx);
24342 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
24343 break;
24344 case OPC_CMPGDU_EQ_OB:
24345 check_dsp_r2(ctx);
24346 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24347 break;
24348 case OPC_CMPGDU_LT_OB:
24349 check_dsp_r2(ctx);
24350 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24351 break;
24352 case OPC_CMPGDU_LE_OB:
24353 check_dsp_r2(ctx);
24354 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24355 break;
24356 case OPC_CMPGU_EQ_OB:
24357 check_dsp(ctx);
24358 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
24359 break;
24360 case OPC_CMPGU_LT_OB:
24361 check_dsp(ctx);
24362 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
24363 break;
24364 case OPC_CMPGU_LE_OB:
24365 check_dsp(ctx);
24366 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
24367 break;
24368 case OPC_CMPU_EQ_OB:
24369 check_dsp(ctx);
24370 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
24371 break;
24372 case OPC_CMPU_LT_OB:
24373 check_dsp(ctx);
24374 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
24375 break;
24376 case OPC_CMPU_LE_OB:
24377 check_dsp(ctx);
24378 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
24379 break;
24380 case OPC_PACKRL_PW:
24381 check_dsp(ctx);
24382 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
24383 break;
24384 case OPC_PICK_OB:
24385 check_dsp(ctx);
24386 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24387 break;
24388 case OPC_PICK_PW:
24389 check_dsp(ctx);
24390 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24391 break;
24392 case OPC_PICK_QH:
24393 check_dsp(ctx);
24394 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24395 break;
24397 break;
24398 #endif
24401 tcg_temp_free(t1);
24402 tcg_temp_free(v1_t);
24403 tcg_temp_free(v2_t);
24406 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
24407 uint32_t op1, int rt, int rs, int sa)
24409 TCGv t0;
24411 check_dsp_r2(ctx);
24413 if (rt == 0) {
24414 /* Treat as NOP. */
24415 return;
24418 t0 = tcg_temp_new();
24419 gen_load_gpr(t0, rs);
24421 switch (op1) {
24422 case OPC_APPEND_DSP:
24423 switch (MASK_APPEND(ctx->opcode)) {
24424 case OPC_APPEND:
24425 if (sa != 0) {
24426 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24428 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24429 break;
24430 case OPC_PREPEND:
24431 if (sa != 0) {
24432 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24433 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24434 tcg_gen_shli_tl(t0, t0, 32 - sa);
24435 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24437 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24438 break;
24439 case OPC_BALIGN:
24440 sa &= 3;
24441 if (sa != 0 && sa != 2) {
24442 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24443 tcg_gen_ext32u_tl(t0, t0);
24444 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24445 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24447 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24448 break;
24449 default: /* Invalid */
24450 MIPS_INVAL("MASK APPEND");
24451 generate_exception_end(ctx, EXCP_RI);
24452 break;
24454 break;
24455 #ifdef TARGET_MIPS64
24456 case OPC_DAPPEND_DSP:
24457 switch (MASK_DAPPEND(ctx->opcode)) {
24458 case OPC_DAPPEND:
24459 if (sa != 0) {
24460 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24462 break;
24463 case OPC_PREPENDD:
24464 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24465 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24466 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24467 break;
24468 case OPC_PREPENDW:
24469 if (sa != 0) {
24470 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24471 tcg_gen_shli_tl(t0, t0, 64 - sa);
24472 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24474 break;
24475 case OPC_DBALIGN:
24476 sa &= 7;
24477 if (sa != 0 && sa != 2 && sa != 4) {
24478 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24479 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24480 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24482 break;
24483 default: /* Invalid */
24484 MIPS_INVAL("MASK DAPPEND");
24485 generate_exception_end(ctx, EXCP_RI);
24486 break;
24488 break;
24489 #endif
24491 tcg_temp_free(t0);
24494 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24495 int ret, int v1, int v2, int check_ret)
24498 TCGv t0;
24499 TCGv t1;
24500 TCGv v1_t;
24501 TCGv v2_t;
24502 int16_t imm;
24504 if ((ret == 0) && (check_ret == 1)) {
24505 /* Treat as NOP. */
24506 return;
24509 t0 = tcg_temp_new();
24510 t1 = tcg_temp_new();
24511 v1_t = tcg_temp_new();
24512 v2_t = tcg_temp_new();
24514 gen_load_gpr(v1_t, v1);
24515 gen_load_gpr(v2_t, v2);
24517 switch (op1) {
24518 case OPC_EXTR_W_DSP:
24519 check_dsp(ctx);
24520 switch (op2) {
24521 case OPC_EXTR_W:
24522 tcg_gen_movi_tl(t0, v2);
24523 tcg_gen_movi_tl(t1, v1);
24524 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24525 break;
24526 case OPC_EXTR_R_W:
24527 tcg_gen_movi_tl(t0, v2);
24528 tcg_gen_movi_tl(t1, v1);
24529 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24530 break;
24531 case OPC_EXTR_RS_W:
24532 tcg_gen_movi_tl(t0, v2);
24533 tcg_gen_movi_tl(t1, v1);
24534 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24535 break;
24536 case OPC_EXTR_S_H:
24537 tcg_gen_movi_tl(t0, v2);
24538 tcg_gen_movi_tl(t1, v1);
24539 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24540 break;
24541 case OPC_EXTRV_S_H:
24542 tcg_gen_movi_tl(t0, v2);
24543 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24544 break;
24545 case OPC_EXTRV_W:
24546 tcg_gen_movi_tl(t0, v2);
24547 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24548 break;
24549 case OPC_EXTRV_R_W:
24550 tcg_gen_movi_tl(t0, v2);
24551 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24552 break;
24553 case OPC_EXTRV_RS_W:
24554 tcg_gen_movi_tl(t0, v2);
24555 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24556 break;
24557 case OPC_EXTP:
24558 tcg_gen_movi_tl(t0, v2);
24559 tcg_gen_movi_tl(t1, v1);
24560 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24561 break;
24562 case OPC_EXTPV:
24563 tcg_gen_movi_tl(t0, v2);
24564 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24565 break;
24566 case OPC_EXTPDP:
24567 tcg_gen_movi_tl(t0, v2);
24568 tcg_gen_movi_tl(t1, v1);
24569 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24570 break;
24571 case OPC_EXTPDPV:
24572 tcg_gen_movi_tl(t0, v2);
24573 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24574 break;
24575 case OPC_SHILO:
24576 imm = (ctx->opcode >> 20) & 0x3F;
24577 tcg_gen_movi_tl(t0, ret);
24578 tcg_gen_movi_tl(t1, imm);
24579 gen_helper_shilo(t0, t1, cpu_env);
24580 break;
24581 case OPC_SHILOV:
24582 tcg_gen_movi_tl(t0, ret);
24583 gen_helper_shilo(t0, v1_t, cpu_env);
24584 break;
24585 case OPC_MTHLIP:
24586 tcg_gen_movi_tl(t0, ret);
24587 gen_helper_mthlip(t0, v1_t, cpu_env);
24588 break;
24589 case OPC_WRDSP:
24590 imm = (ctx->opcode >> 11) & 0x3FF;
24591 tcg_gen_movi_tl(t0, imm);
24592 gen_helper_wrdsp(v1_t, t0, cpu_env);
24593 break;
24594 case OPC_RDDSP:
24595 imm = (ctx->opcode >> 16) & 0x03FF;
24596 tcg_gen_movi_tl(t0, imm);
24597 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24598 break;
24600 break;
24601 #ifdef TARGET_MIPS64
24602 case OPC_DEXTR_W_DSP:
24603 check_dsp(ctx);
24604 switch (op2) {
24605 case OPC_DMTHLIP:
24606 tcg_gen_movi_tl(t0, ret);
24607 gen_helper_dmthlip(v1_t, t0, cpu_env);
24608 break;
24609 case OPC_DSHILO:
24611 int shift = (ctx->opcode >> 19) & 0x7F;
24612 int ac = (ctx->opcode >> 11) & 0x03;
24613 tcg_gen_movi_tl(t0, shift);
24614 tcg_gen_movi_tl(t1, ac);
24615 gen_helper_dshilo(t0, t1, cpu_env);
24616 break;
24618 case OPC_DSHILOV:
24620 int ac = (ctx->opcode >> 11) & 0x03;
24621 tcg_gen_movi_tl(t0, ac);
24622 gen_helper_dshilo(v1_t, t0, cpu_env);
24623 break;
24625 case OPC_DEXTP:
24626 tcg_gen_movi_tl(t0, v2);
24627 tcg_gen_movi_tl(t1, v1);
24629 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24630 break;
24631 case OPC_DEXTPV:
24632 tcg_gen_movi_tl(t0, v2);
24633 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24634 break;
24635 case OPC_DEXTPDP:
24636 tcg_gen_movi_tl(t0, v2);
24637 tcg_gen_movi_tl(t1, v1);
24638 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24639 break;
24640 case OPC_DEXTPDPV:
24641 tcg_gen_movi_tl(t0, v2);
24642 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24643 break;
24644 case OPC_DEXTR_L:
24645 tcg_gen_movi_tl(t0, v2);
24646 tcg_gen_movi_tl(t1, v1);
24647 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24648 break;
24649 case OPC_DEXTR_R_L:
24650 tcg_gen_movi_tl(t0, v2);
24651 tcg_gen_movi_tl(t1, v1);
24652 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24653 break;
24654 case OPC_DEXTR_RS_L:
24655 tcg_gen_movi_tl(t0, v2);
24656 tcg_gen_movi_tl(t1, v1);
24657 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24658 break;
24659 case OPC_DEXTR_W:
24660 tcg_gen_movi_tl(t0, v2);
24661 tcg_gen_movi_tl(t1, v1);
24662 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24663 break;
24664 case OPC_DEXTR_R_W:
24665 tcg_gen_movi_tl(t0, v2);
24666 tcg_gen_movi_tl(t1, v1);
24667 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24668 break;
24669 case OPC_DEXTR_RS_W:
24670 tcg_gen_movi_tl(t0, v2);
24671 tcg_gen_movi_tl(t1, v1);
24672 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24673 break;
24674 case OPC_DEXTR_S_H:
24675 tcg_gen_movi_tl(t0, v2);
24676 tcg_gen_movi_tl(t1, v1);
24677 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24678 break;
24679 case OPC_DEXTRV_S_H:
24680 tcg_gen_movi_tl(t0, v2);
24681 tcg_gen_movi_tl(t1, v1);
24682 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24683 break;
24684 case OPC_DEXTRV_L:
24685 tcg_gen_movi_tl(t0, v2);
24686 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24687 break;
24688 case OPC_DEXTRV_R_L:
24689 tcg_gen_movi_tl(t0, v2);
24690 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24691 break;
24692 case OPC_DEXTRV_RS_L:
24693 tcg_gen_movi_tl(t0, v2);
24694 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24695 break;
24696 case OPC_DEXTRV_W:
24697 tcg_gen_movi_tl(t0, v2);
24698 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24699 break;
24700 case OPC_DEXTRV_R_W:
24701 tcg_gen_movi_tl(t0, v2);
24702 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24703 break;
24704 case OPC_DEXTRV_RS_W:
24705 tcg_gen_movi_tl(t0, v2);
24706 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24707 break;
24709 break;
24710 #endif
24713 tcg_temp_free(t0);
24714 tcg_temp_free(t1);
24715 tcg_temp_free(v1_t);
24716 tcg_temp_free(v2_t);
24719 /* End MIPSDSP functions. */
24721 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24723 int rs, rt, rd, sa;
24724 uint32_t op1, op2;
24726 rs = (ctx->opcode >> 21) & 0x1f;
24727 rt = (ctx->opcode >> 16) & 0x1f;
24728 rd = (ctx->opcode >> 11) & 0x1f;
24729 sa = (ctx->opcode >> 6) & 0x1f;
24731 op1 = MASK_SPECIAL(ctx->opcode);
24732 switch (op1) {
24733 case OPC_LSA:
24734 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24735 break;
24736 case OPC_MULT:
24737 case OPC_MULTU:
24738 case OPC_DIV:
24739 case OPC_DIVU:
24740 op2 = MASK_R6_MULDIV(ctx->opcode);
24741 switch (op2) {
24742 case R6_OPC_MUL:
24743 case R6_OPC_MUH:
24744 case R6_OPC_MULU:
24745 case R6_OPC_MUHU:
24746 case R6_OPC_DIV:
24747 case R6_OPC_MOD:
24748 case R6_OPC_DIVU:
24749 case R6_OPC_MODU:
24750 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24751 break;
24752 default:
24753 MIPS_INVAL("special_r6 muldiv");
24754 generate_exception_end(ctx, EXCP_RI);
24755 break;
24757 break;
24758 case OPC_SELEQZ:
24759 case OPC_SELNEZ:
24760 gen_cond_move(ctx, op1, rd, rs, rt);
24761 break;
24762 case R6_OPC_CLO:
24763 case R6_OPC_CLZ:
24764 if (rt == 0 && sa == 1) {
24766 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24767 * We need additionally to check other fields.
24769 gen_cl(ctx, op1, rd, rs);
24770 } else {
24771 generate_exception_end(ctx, EXCP_RI);
24773 break;
24774 case R6_OPC_SDBBP:
24775 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24776 gen_helper_do_semihosting(cpu_env);
24777 } else {
24778 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24779 generate_exception_end(ctx, EXCP_RI);
24780 } else {
24781 generate_exception_end(ctx, EXCP_DBp);
24784 break;
24785 #if defined(TARGET_MIPS64)
24786 case OPC_DLSA:
24787 check_mips_64(ctx);
24788 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24789 break;
24790 case R6_OPC_DCLO:
24791 case R6_OPC_DCLZ:
24792 if (rt == 0 && sa == 1) {
24794 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24795 * We need additionally to check other fields.
24797 check_mips_64(ctx);
24798 gen_cl(ctx, op1, rd, rs);
24799 } else {
24800 generate_exception_end(ctx, EXCP_RI);
24802 break;
24803 case OPC_DMULT:
24804 case OPC_DMULTU:
24805 case OPC_DDIV:
24806 case OPC_DDIVU:
24808 op2 = MASK_R6_MULDIV(ctx->opcode);
24809 switch (op2) {
24810 case R6_OPC_DMUL:
24811 case R6_OPC_DMUH:
24812 case R6_OPC_DMULU:
24813 case R6_OPC_DMUHU:
24814 case R6_OPC_DDIV:
24815 case R6_OPC_DMOD:
24816 case R6_OPC_DDIVU:
24817 case R6_OPC_DMODU:
24818 check_mips_64(ctx);
24819 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24820 break;
24821 default:
24822 MIPS_INVAL("special_r6 muldiv");
24823 generate_exception_end(ctx, EXCP_RI);
24824 break;
24826 break;
24827 #endif
24828 default: /* Invalid */
24829 MIPS_INVAL("special_r6");
24830 generate_exception_end(ctx, EXCP_RI);
24831 break;
24835 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24837 int rs = extract32(ctx->opcode, 21, 5);
24838 int rt = extract32(ctx->opcode, 16, 5);
24839 int rd = extract32(ctx->opcode, 11, 5);
24840 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24842 switch (op1) {
24843 case OPC_MOVN: /* Conditional move */
24844 case OPC_MOVZ:
24845 gen_cond_move(ctx, op1, rd, rs, rt);
24846 break;
24847 case OPC_MFHI: /* Move from HI/LO */
24848 case OPC_MFLO:
24849 gen_HILO(ctx, op1, 0, rd);
24850 break;
24851 case OPC_MTHI:
24852 case OPC_MTLO: /* Move to HI/LO */
24853 gen_HILO(ctx, op1, 0, rs);
24854 break;
24855 case OPC_MULT:
24856 case OPC_MULTU:
24857 gen_mul_txx9(ctx, op1, rd, rs, rt);
24858 break;
24859 case OPC_DIV:
24860 case OPC_DIVU:
24861 gen_muldiv(ctx, op1, 0, rs, rt);
24862 break;
24863 #if defined(TARGET_MIPS64)
24864 case OPC_DMULT:
24865 case OPC_DMULTU:
24866 case OPC_DDIV:
24867 case OPC_DDIVU:
24868 check_insn_opc_user_only(ctx, INSN_R5900);
24869 gen_muldiv(ctx, op1, 0, rs, rt);
24870 break;
24871 #endif
24872 case OPC_JR:
24873 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24874 break;
24875 default: /* Invalid */
24876 MIPS_INVAL("special_tx79");
24877 generate_exception_end(ctx, EXCP_RI);
24878 break;
24882 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24884 int rs, rt, rd, sa;
24885 uint32_t op1;
24887 rs = (ctx->opcode >> 21) & 0x1f;
24888 rt = (ctx->opcode >> 16) & 0x1f;
24889 rd = (ctx->opcode >> 11) & 0x1f;
24890 sa = (ctx->opcode >> 6) & 0x1f;
24892 op1 = MASK_SPECIAL(ctx->opcode);
24893 switch (op1) {
24894 case OPC_MOVN: /* Conditional move */
24895 case OPC_MOVZ:
24896 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24897 INSN_LOONGSON2E | INSN_LOONGSON2F);
24898 gen_cond_move(ctx, op1, rd, rs, rt);
24899 break;
24900 case OPC_MFHI: /* Move from HI/LO */
24901 case OPC_MFLO:
24902 gen_HILO(ctx, op1, rs & 3, rd);
24903 break;
24904 case OPC_MTHI:
24905 case OPC_MTLO: /* Move to HI/LO */
24906 gen_HILO(ctx, op1, rd & 3, rs);
24907 break;
24908 case OPC_MOVCI:
24909 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24910 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24911 check_cp1_enabled(ctx);
24912 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24913 (ctx->opcode >> 16) & 1);
24914 } else {
24915 generate_exception_err(ctx, EXCP_CpU, 1);
24917 break;
24918 case OPC_MULT:
24919 case OPC_MULTU:
24920 if (sa) {
24921 check_insn(ctx, INSN_VR54XX);
24922 op1 = MASK_MUL_VR54XX(ctx->opcode);
24923 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24924 } else {
24925 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24927 break;
24928 case OPC_DIV:
24929 case OPC_DIVU:
24930 gen_muldiv(ctx, op1, 0, rs, rt);
24931 break;
24932 #if defined(TARGET_MIPS64)
24933 case OPC_DMULT:
24934 case OPC_DMULTU:
24935 case OPC_DDIV:
24936 case OPC_DDIVU:
24937 check_insn(ctx, ISA_MIPS3);
24938 check_mips_64(ctx);
24939 gen_muldiv(ctx, op1, 0, rs, rt);
24940 break;
24941 #endif
24942 case OPC_JR:
24943 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24944 break;
24945 case OPC_SPIM:
24946 #ifdef MIPS_STRICT_STANDARD
24947 MIPS_INVAL("SPIM");
24948 generate_exception_end(ctx, EXCP_RI);
24949 #else
24950 /* Implemented as RI exception for now. */
24951 MIPS_INVAL("spim (unofficial)");
24952 generate_exception_end(ctx, EXCP_RI);
24953 #endif
24954 break;
24955 default: /* Invalid */
24956 MIPS_INVAL("special_legacy");
24957 generate_exception_end(ctx, EXCP_RI);
24958 break;
24962 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24964 int rs, rt, rd, sa;
24965 uint32_t op1;
24967 rs = (ctx->opcode >> 21) & 0x1f;
24968 rt = (ctx->opcode >> 16) & 0x1f;
24969 rd = (ctx->opcode >> 11) & 0x1f;
24970 sa = (ctx->opcode >> 6) & 0x1f;
24972 op1 = MASK_SPECIAL(ctx->opcode);
24973 switch (op1) {
24974 case OPC_SLL: /* Shift with immediate */
24975 if (sa == 5 && rd == 0 &&
24976 rs == 0 && rt == 0) { /* PAUSE */
24977 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24978 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24979 generate_exception_end(ctx, EXCP_RI);
24980 break;
24983 /* Fallthrough */
24984 case OPC_SRA:
24985 gen_shift_imm(ctx, op1, rd, rt, sa);
24986 break;
24987 case OPC_SRL:
24988 switch ((ctx->opcode >> 21) & 0x1f) {
24989 case 1:
24990 /* rotr is decoded as srl on non-R2 CPUs */
24991 if (ctx->insn_flags & ISA_MIPS32R2) {
24992 op1 = OPC_ROTR;
24994 /* Fallthrough */
24995 case 0:
24996 gen_shift_imm(ctx, op1, rd, rt, sa);
24997 break;
24998 default:
24999 generate_exception_end(ctx, EXCP_RI);
25000 break;
25002 break;
25003 case OPC_ADD:
25004 case OPC_ADDU:
25005 case OPC_SUB:
25006 case OPC_SUBU:
25007 gen_arith(ctx, op1, rd, rs, rt);
25008 break;
25009 case OPC_SLLV: /* Shifts */
25010 case OPC_SRAV:
25011 gen_shift(ctx, op1, rd, rs, rt);
25012 break;
25013 case OPC_SRLV:
25014 switch ((ctx->opcode >> 6) & 0x1f) {
25015 case 1:
25016 /* rotrv is decoded as srlv on non-R2 CPUs */
25017 if (ctx->insn_flags & ISA_MIPS32R2) {
25018 op1 = OPC_ROTRV;
25020 /* Fallthrough */
25021 case 0:
25022 gen_shift(ctx, op1, rd, rs, rt);
25023 break;
25024 default:
25025 generate_exception_end(ctx, EXCP_RI);
25026 break;
25028 break;
25029 case OPC_SLT: /* Set on less than */
25030 case OPC_SLTU:
25031 gen_slt(ctx, op1, rd, rs, rt);
25032 break;
25033 case OPC_AND: /* Logic*/
25034 case OPC_OR:
25035 case OPC_NOR:
25036 case OPC_XOR:
25037 gen_logic(ctx, op1, rd, rs, rt);
25038 break;
25039 case OPC_JALR:
25040 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
25041 break;
25042 case OPC_TGE: /* Traps */
25043 case OPC_TGEU:
25044 case OPC_TLT:
25045 case OPC_TLTU:
25046 case OPC_TEQ:
25047 case OPC_TNE:
25048 check_insn(ctx, ISA_MIPS2);
25049 gen_trap(ctx, op1, rs, rt, -1);
25050 break;
25051 case OPC_LSA: /* OPC_PMON */
25052 if ((ctx->insn_flags & ISA_MIPS32R6) ||
25053 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25054 decode_opc_special_r6(env, ctx);
25055 } else {
25056 /* Pmon entry point, also R4010 selsl */
25057 #ifdef MIPS_STRICT_STANDARD
25058 MIPS_INVAL("PMON / selsl");
25059 generate_exception_end(ctx, EXCP_RI);
25060 #else
25061 gen_helper_0e0i(pmon, sa);
25062 #endif
25064 break;
25065 case OPC_SYSCALL:
25066 generate_exception_end(ctx, EXCP_SYSCALL);
25067 break;
25068 case OPC_BREAK:
25069 generate_exception_end(ctx, EXCP_BREAK);
25070 break;
25071 case OPC_SYNC:
25072 check_insn(ctx, ISA_MIPS2);
25073 gen_sync(extract32(ctx->opcode, 6, 5));
25074 break;
25076 #if defined(TARGET_MIPS64)
25077 /* MIPS64 specific opcodes */
25078 case OPC_DSLL:
25079 case OPC_DSRA:
25080 case OPC_DSLL32:
25081 case OPC_DSRA32:
25082 check_insn(ctx, ISA_MIPS3);
25083 check_mips_64(ctx);
25084 gen_shift_imm(ctx, op1, rd, rt, sa);
25085 break;
25086 case OPC_DSRL:
25087 switch ((ctx->opcode >> 21) & 0x1f) {
25088 case 1:
25089 /* drotr is decoded as dsrl on non-R2 CPUs */
25090 if (ctx->insn_flags & ISA_MIPS32R2) {
25091 op1 = OPC_DROTR;
25093 /* Fallthrough */
25094 case 0:
25095 check_insn(ctx, ISA_MIPS3);
25096 check_mips_64(ctx);
25097 gen_shift_imm(ctx, op1, rd, rt, sa);
25098 break;
25099 default:
25100 generate_exception_end(ctx, EXCP_RI);
25101 break;
25103 break;
25104 case OPC_DSRL32:
25105 switch ((ctx->opcode >> 21) & 0x1f) {
25106 case 1:
25107 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
25108 if (ctx->insn_flags & ISA_MIPS32R2) {
25109 op1 = OPC_DROTR32;
25111 /* Fallthrough */
25112 case 0:
25113 check_insn(ctx, ISA_MIPS3);
25114 check_mips_64(ctx);
25115 gen_shift_imm(ctx, op1, rd, rt, sa);
25116 break;
25117 default:
25118 generate_exception_end(ctx, EXCP_RI);
25119 break;
25121 break;
25122 case OPC_DADD:
25123 case OPC_DADDU:
25124 case OPC_DSUB:
25125 case OPC_DSUBU:
25126 check_insn(ctx, ISA_MIPS3);
25127 check_mips_64(ctx);
25128 gen_arith(ctx, op1, rd, rs, rt);
25129 break;
25130 case OPC_DSLLV:
25131 case OPC_DSRAV:
25132 check_insn(ctx, ISA_MIPS3);
25133 check_mips_64(ctx);
25134 gen_shift(ctx, op1, rd, rs, rt);
25135 break;
25136 case OPC_DSRLV:
25137 switch ((ctx->opcode >> 6) & 0x1f) {
25138 case 1:
25139 /* drotrv is decoded as dsrlv on non-R2 CPUs */
25140 if (ctx->insn_flags & ISA_MIPS32R2) {
25141 op1 = OPC_DROTRV;
25143 /* Fallthrough */
25144 case 0:
25145 check_insn(ctx, ISA_MIPS3);
25146 check_mips_64(ctx);
25147 gen_shift(ctx, op1, rd, rs, rt);
25148 break;
25149 default:
25150 generate_exception_end(ctx, EXCP_RI);
25151 break;
25153 break;
25154 case OPC_DLSA:
25155 if ((ctx->insn_flags & ISA_MIPS32R6) ||
25156 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25157 decode_opc_special_r6(env, ctx);
25159 break;
25160 #endif
25161 default:
25162 if (ctx->insn_flags & ISA_MIPS32R6) {
25163 decode_opc_special_r6(env, ctx);
25164 } else if (ctx->insn_flags & INSN_R5900) {
25165 decode_opc_special_tx79(env, ctx);
25166 } else {
25167 decode_opc_special_legacy(env, ctx);
25173 #if defined(TARGET_MIPS64)
25177 * MMI (MultiMedia Interface) ASE instructions
25178 * ===========================================
25182 * MMI instructions category: data communication
25183 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25185 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
25186 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
25187 * PCPYUD PEXEH PEXTLW PPACW
25188 * PEXEW PEXTUB
25189 * PEXTUH
25190 * PEXTUW
25194 * PCPYH rd, rt
25196 * Parallel Copy Halfword
25198 * 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
25199 * +-----------+---------+---------+---------+---------+-----------+
25200 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
25201 * +-----------+---------+---------+---------+---------+-----------+
25203 static void gen_mmi_pcpyh(DisasContext *ctx)
25205 uint32_t pd, rt, rd;
25206 uint32_t opcode;
25208 opcode = ctx->opcode;
25210 pd = extract32(opcode, 21, 5);
25211 rt = extract32(opcode, 16, 5);
25212 rd = extract32(opcode, 11, 5);
25214 if (unlikely(pd != 0)) {
25215 generate_exception_end(ctx, EXCP_RI);
25216 } else if (rd == 0) {
25217 /* nop */
25218 } else if (rt == 0) {
25219 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25220 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25221 } else {
25222 TCGv_i64 t0 = tcg_temp_new();
25223 TCGv_i64 t1 = tcg_temp_new();
25224 uint64_t mask = (1ULL << 16) - 1;
25226 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
25227 tcg_gen_movi_i64(t1, 0);
25228 tcg_gen_or_i64(t1, t0, t1);
25229 tcg_gen_shli_i64(t0, t0, 16);
25230 tcg_gen_or_i64(t1, t0, t1);
25231 tcg_gen_shli_i64(t0, t0, 16);
25232 tcg_gen_or_i64(t1, t0, t1);
25233 tcg_gen_shli_i64(t0, t0, 16);
25234 tcg_gen_or_i64(t1, t0, t1);
25236 tcg_gen_mov_i64(cpu_gpr[rd], t1);
25238 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
25239 tcg_gen_movi_i64(t1, 0);
25240 tcg_gen_or_i64(t1, t0, t1);
25241 tcg_gen_shli_i64(t0, t0, 16);
25242 tcg_gen_or_i64(t1, t0, t1);
25243 tcg_gen_shli_i64(t0, t0, 16);
25244 tcg_gen_or_i64(t1, t0, t1);
25245 tcg_gen_shli_i64(t0, t0, 16);
25246 tcg_gen_or_i64(t1, t0, t1);
25248 tcg_gen_mov_i64(cpu_mmr[rd], t1);
25250 tcg_temp_free(t0);
25251 tcg_temp_free(t1);
25256 * PCPYLD rd, rs, rt
25258 * Parallel Copy Lower Doubleword
25260 * 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
25261 * +-----------+---------+---------+---------+---------+-----------+
25262 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
25263 * +-----------+---------+---------+---------+---------+-----------+
25265 static void gen_mmi_pcpyld(DisasContext *ctx)
25267 uint32_t rs, rt, rd;
25268 uint32_t opcode;
25270 opcode = ctx->opcode;
25272 rs = extract32(opcode, 21, 5);
25273 rt = extract32(opcode, 16, 5);
25274 rd = extract32(opcode, 11, 5);
25276 if (rd == 0) {
25277 /* nop */
25278 } else {
25279 if (rs == 0) {
25280 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25281 } else {
25282 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
25284 if (rt == 0) {
25285 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25286 } else {
25287 if (rd != rt) {
25288 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
25295 * PCPYUD rd, rs, rt
25297 * Parallel Copy Upper Doubleword
25299 * 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
25300 * +-----------+---------+---------+---------+---------+-----------+
25301 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
25302 * +-----------+---------+---------+---------+---------+-----------+
25304 static void gen_mmi_pcpyud(DisasContext *ctx)
25306 uint32_t rs, rt, rd;
25307 uint32_t opcode;
25309 opcode = ctx->opcode;
25311 rs = extract32(opcode, 21, 5);
25312 rt = extract32(opcode, 16, 5);
25313 rd = extract32(opcode, 11, 5);
25315 if (rd == 0) {
25316 /* nop */
25317 } else {
25318 if (rs == 0) {
25319 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25320 } else {
25321 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
25323 if (rt == 0) {
25324 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25325 } else {
25326 if (rd != rt) {
25327 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
25333 #endif
25336 #if !defined(TARGET_MIPS64)
25338 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
25339 #define MXU_APTN1_A 0
25340 #define MXU_APTN1_S 1
25342 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
25343 #define MXU_APTN2_AA 0
25344 #define MXU_APTN2_AS 1
25345 #define MXU_APTN2_SA 2
25346 #define MXU_APTN2_SS 3
25348 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
25349 #define MXU_EPTN2_AA 0
25350 #define MXU_EPTN2_AS 1
25351 #define MXU_EPTN2_SA 2
25352 #define MXU_EPTN2_SS 3
25354 /* MXU operand getting pattern 'optn2' */
25355 #define MXU_OPTN2_PTN0 0
25356 #define MXU_OPTN2_PTN1 1
25357 #define MXU_OPTN2_PTN2 2
25358 #define MXU_OPTN2_PTN3 3
25359 /* alternative naming scheme for 'optn2' */
25360 #define MXU_OPTN2_WW 0
25361 #define MXU_OPTN2_LW 1
25362 #define MXU_OPTN2_HW 2
25363 #define MXU_OPTN2_XW 3
25365 /* MXU operand getting pattern 'optn3' */
25366 #define MXU_OPTN3_PTN0 0
25367 #define MXU_OPTN3_PTN1 1
25368 #define MXU_OPTN3_PTN2 2
25369 #define MXU_OPTN3_PTN3 3
25370 #define MXU_OPTN3_PTN4 4
25371 #define MXU_OPTN3_PTN5 5
25372 #define MXU_OPTN3_PTN6 6
25373 #define MXU_OPTN3_PTN7 7
25377 * S32I2M XRa, rb - Register move from GRF to XRF
25379 static void gen_mxu_s32i2m(DisasContext *ctx)
25381 TCGv t0;
25382 uint32_t XRa, Rb;
25384 t0 = tcg_temp_new();
25386 XRa = extract32(ctx->opcode, 6, 5);
25387 Rb = extract32(ctx->opcode, 16, 5);
25389 gen_load_gpr(t0, Rb);
25390 if (XRa <= 15) {
25391 gen_store_mxu_gpr(t0, XRa);
25392 } else if (XRa == 16) {
25393 gen_store_mxu_cr(t0);
25396 tcg_temp_free(t0);
25400 * S32M2I XRa, rb - Register move from XRF to GRF
25402 static void gen_mxu_s32m2i(DisasContext *ctx)
25404 TCGv t0;
25405 uint32_t XRa, Rb;
25407 t0 = tcg_temp_new();
25409 XRa = extract32(ctx->opcode, 6, 5);
25410 Rb = extract32(ctx->opcode, 16, 5);
25412 if (XRa <= 15) {
25413 gen_load_mxu_gpr(t0, XRa);
25414 } else if (XRa == 16) {
25415 gen_load_mxu_cr(t0);
25418 gen_store_gpr(t0, Rb);
25420 tcg_temp_free(t0);
25424 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
25426 static void gen_mxu_s8ldd(DisasContext *ctx)
25428 TCGv t0, t1;
25429 uint32_t XRa, Rb, s8, optn3;
25431 t0 = tcg_temp_new();
25432 t1 = tcg_temp_new();
25434 XRa = extract32(ctx->opcode, 6, 4);
25435 s8 = extract32(ctx->opcode, 10, 8);
25436 optn3 = extract32(ctx->opcode, 18, 3);
25437 Rb = extract32(ctx->opcode, 21, 5);
25439 gen_load_gpr(t0, Rb);
25440 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25442 switch (optn3) {
25443 /* XRa[7:0] = tmp8 */
25444 case MXU_OPTN3_PTN0:
25445 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25446 gen_load_mxu_gpr(t0, XRa);
25447 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25448 break;
25449 /* XRa[15:8] = tmp8 */
25450 case MXU_OPTN3_PTN1:
25451 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25452 gen_load_mxu_gpr(t0, XRa);
25453 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25454 break;
25455 /* XRa[23:16] = tmp8 */
25456 case MXU_OPTN3_PTN2:
25457 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25458 gen_load_mxu_gpr(t0, XRa);
25459 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25460 break;
25461 /* XRa[31:24] = tmp8 */
25462 case MXU_OPTN3_PTN3:
25463 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25464 gen_load_mxu_gpr(t0, XRa);
25465 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25466 break;
25467 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25468 case MXU_OPTN3_PTN4:
25469 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25470 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25471 break;
25472 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25473 case MXU_OPTN3_PTN5:
25474 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25475 tcg_gen_shli_tl(t1, t1, 8);
25476 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25477 break;
25478 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25479 case MXU_OPTN3_PTN6:
25480 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25481 tcg_gen_mov_tl(t0, t1);
25482 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25483 tcg_gen_shli_tl(t1, t1, 16);
25484 tcg_gen_or_tl(t0, t0, t1);
25485 break;
25486 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25487 case MXU_OPTN3_PTN7:
25488 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25489 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25490 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25491 break;
25494 gen_store_mxu_gpr(t0, XRa);
25496 tcg_temp_free(t0);
25497 tcg_temp_free(t1);
25501 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25503 static void gen_mxu_d16mul(DisasContext *ctx)
25505 TCGv t0, t1, t2, t3;
25506 uint32_t XRa, XRb, XRc, XRd, optn2;
25508 t0 = tcg_temp_new();
25509 t1 = tcg_temp_new();
25510 t2 = tcg_temp_new();
25511 t3 = tcg_temp_new();
25513 XRa = extract32(ctx->opcode, 6, 4);
25514 XRb = extract32(ctx->opcode, 10, 4);
25515 XRc = extract32(ctx->opcode, 14, 4);
25516 XRd = extract32(ctx->opcode, 18, 4);
25517 optn2 = extract32(ctx->opcode, 22, 2);
25519 gen_load_mxu_gpr(t1, XRb);
25520 tcg_gen_sextract_tl(t0, t1, 0, 16);
25521 tcg_gen_sextract_tl(t1, t1, 16, 16);
25522 gen_load_mxu_gpr(t3, XRc);
25523 tcg_gen_sextract_tl(t2, t3, 0, 16);
25524 tcg_gen_sextract_tl(t3, t3, 16, 16);
25526 switch (optn2) {
25527 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25528 tcg_gen_mul_tl(t3, t1, t3);
25529 tcg_gen_mul_tl(t2, t0, t2);
25530 break;
25531 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25532 tcg_gen_mul_tl(t3, t0, t3);
25533 tcg_gen_mul_tl(t2, t0, t2);
25534 break;
25535 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25536 tcg_gen_mul_tl(t3, t1, t3);
25537 tcg_gen_mul_tl(t2, t1, t2);
25538 break;
25539 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25540 tcg_gen_mul_tl(t3, t0, t3);
25541 tcg_gen_mul_tl(t2, t1, t2);
25542 break;
25544 gen_store_mxu_gpr(t3, XRa);
25545 gen_store_mxu_gpr(t2, XRd);
25547 tcg_temp_free(t0);
25548 tcg_temp_free(t1);
25549 tcg_temp_free(t2);
25550 tcg_temp_free(t3);
25554 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25555 * and accumulate
25557 static void gen_mxu_d16mac(DisasContext *ctx)
25559 TCGv t0, t1, t2, t3;
25560 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25562 t0 = tcg_temp_new();
25563 t1 = tcg_temp_new();
25564 t2 = tcg_temp_new();
25565 t3 = tcg_temp_new();
25567 XRa = extract32(ctx->opcode, 6, 4);
25568 XRb = extract32(ctx->opcode, 10, 4);
25569 XRc = extract32(ctx->opcode, 14, 4);
25570 XRd = extract32(ctx->opcode, 18, 4);
25571 optn2 = extract32(ctx->opcode, 22, 2);
25572 aptn2 = extract32(ctx->opcode, 24, 2);
25574 gen_load_mxu_gpr(t1, XRb);
25575 tcg_gen_sextract_tl(t0, t1, 0, 16);
25576 tcg_gen_sextract_tl(t1, t1, 16, 16);
25578 gen_load_mxu_gpr(t3, XRc);
25579 tcg_gen_sextract_tl(t2, t3, 0, 16);
25580 tcg_gen_sextract_tl(t3, t3, 16, 16);
25582 switch (optn2) {
25583 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25584 tcg_gen_mul_tl(t3, t1, t3);
25585 tcg_gen_mul_tl(t2, t0, t2);
25586 break;
25587 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25588 tcg_gen_mul_tl(t3, t0, t3);
25589 tcg_gen_mul_tl(t2, t0, t2);
25590 break;
25591 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25592 tcg_gen_mul_tl(t3, t1, t3);
25593 tcg_gen_mul_tl(t2, t1, t2);
25594 break;
25595 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25596 tcg_gen_mul_tl(t3, t0, t3);
25597 tcg_gen_mul_tl(t2, t1, t2);
25598 break;
25600 gen_load_mxu_gpr(t0, XRa);
25601 gen_load_mxu_gpr(t1, XRd);
25603 switch (aptn2) {
25604 case MXU_APTN2_AA:
25605 tcg_gen_add_tl(t3, t0, t3);
25606 tcg_gen_add_tl(t2, t1, t2);
25607 break;
25608 case MXU_APTN2_AS:
25609 tcg_gen_add_tl(t3, t0, t3);
25610 tcg_gen_sub_tl(t2, t1, t2);
25611 break;
25612 case MXU_APTN2_SA:
25613 tcg_gen_sub_tl(t3, t0, t3);
25614 tcg_gen_add_tl(t2, t1, t2);
25615 break;
25616 case MXU_APTN2_SS:
25617 tcg_gen_sub_tl(t3, t0, t3);
25618 tcg_gen_sub_tl(t2, t1, t2);
25619 break;
25621 gen_store_mxu_gpr(t3, XRa);
25622 gen_store_mxu_gpr(t2, XRd);
25624 tcg_temp_free(t0);
25625 tcg_temp_free(t1);
25626 tcg_temp_free(t2);
25627 tcg_temp_free(t3);
25631 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25632 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25634 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25636 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25637 uint32_t XRa, XRb, XRc, XRd, sel;
25639 t0 = tcg_temp_new();
25640 t1 = tcg_temp_new();
25641 t2 = tcg_temp_new();
25642 t3 = tcg_temp_new();
25643 t4 = tcg_temp_new();
25644 t5 = tcg_temp_new();
25645 t6 = tcg_temp_new();
25646 t7 = tcg_temp_new();
25648 XRa = extract32(ctx->opcode, 6, 4);
25649 XRb = extract32(ctx->opcode, 10, 4);
25650 XRc = extract32(ctx->opcode, 14, 4);
25651 XRd = extract32(ctx->opcode, 18, 4);
25652 sel = extract32(ctx->opcode, 22, 2);
25654 gen_load_mxu_gpr(t3, XRb);
25655 gen_load_mxu_gpr(t7, XRc);
25657 if (sel == 0x2) {
25658 /* Q8MULSU */
25659 tcg_gen_ext8s_tl(t0, t3);
25660 tcg_gen_shri_tl(t3, t3, 8);
25661 tcg_gen_ext8s_tl(t1, t3);
25662 tcg_gen_shri_tl(t3, t3, 8);
25663 tcg_gen_ext8s_tl(t2, t3);
25664 tcg_gen_shri_tl(t3, t3, 8);
25665 tcg_gen_ext8s_tl(t3, t3);
25666 } else {
25667 /* Q8MUL */
25668 tcg_gen_ext8u_tl(t0, t3);
25669 tcg_gen_shri_tl(t3, t3, 8);
25670 tcg_gen_ext8u_tl(t1, t3);
25671 tcg_gen_shri_tl(t3, t3, 8);
25672 tcg_gen_ext8u_tl(t2, t3);
25673 tcg_gen_shri_tl(t3, t3, 8);
25674 tcg_gen_ext8u_tl(t3, t3);
25677 tcg_gen_ext8u_tl(t4, t7);
25678 tcg_gen_shri_tl(t7, t7, 8);
25679 tcg_gen_ext8u_tl(t5, t7);
25680 tcg_gen_shri_tl(t7, t7, 8);
25681 tcg_gen_ext8u_tl(t6, t7);
25682 tcg_gen_shri_tl(t7, t7, 8);
25683 tcg_gen_ext8u_tl(t7, t7);
25685 tcg_gen_mul_tl(t0, t0, t4);
25686 tcg_gen_mul_tl(t1, t1, t5);
25687 tcg_gen_mul_tl(t2, t2, t6);
25688 tcg_gen_mul_tl(t3, t3, t7);
25690 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25691 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25692 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25693 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25695 tcg_gen_shli_tl(t1, t1, 16);
25696 tcg_gen_shli_tl(t3, t3, 16);
25698 tcg_gen_or_tl(t0, t0, t1);
25699 tcg_gen_or_tl(t1, t2, t3);
25701 gen_store_mxu_gpr(t0, XRd);
25702 gen_store_mxu_gpr(t1, XRa);
25704 tcg_temp_free(t0);
25705 tcg_temp_free(t1);
25706 tcg_temp_free(t2);
25707 tcg_temp_free(t3);
25708 tcg_temp_free(t4);
25709 tcg_temp_free(t5);
25710 tcg_temp_free(t6);
25711 tcg_temp_free(t7);
25715 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25716 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25718 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25720 TCGv t0, t1;
25721 uint32_t XRa, Rb, s12, sel;
25723 t0 = tcg_temp_new();
25724 t1 = tcg_temp_new();
25726 XRa = extract32(ctx->opcode, 6, 4);
25727 s12 = extract32(ctx->opcode, 10, 10);
25728 sel = extract32(ctx->opcode, 20, 1);
25729 Rb = extract32(ctx->opcode, 21, 5);
25731 gen_load_gpr(t0, Rb);
25733 tcg_gen_movi_tl(t1, s12);
25734 tcg_gen_shli_tl(t1, t1, 2);
25735 if (s12 & 0x200) {
25736 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25738 tcg_gen_add_tl(t1, t0, t1);
25739 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25741 if (sel == 1) {
25742 /* S32LDDR */
25743 tcg_gen_bswap32_tl(t1, t1);
25745 gen_store_mxu_gpr(t1, XRa);
25747 tcg_temp_free(t0);
25748 tcg_temp_free(t1);
25753 * MXU instruction category: logic
25754 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25756 * S32NOR S32AND S32OR S32XOR
25760 * S32NOR XRa, XRb, XRc
25761 * Update XRa with the result of logical bitwise 'nor' operation
25762 * applied to the content of XRb and XRc.
25764 * 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
25765 * +-----------+---------+-----+-------+-------+-------+-----------+
25766 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25767 * +-----------+---------+-----+-------+-------+-------+-----------+
25769 static void gen_mxu_S32NOR(DisasContext *ctx)
25771 uint32_t pad, XRc, XRb, XRa;
25773 pad = extract32(ctx->opcode, 21, 5);
25774 XRc = extract32(ctx->opcode, 14, 4);
25775 XRb = extract32(ctx->opcode, 10, 4);
25776 XRa = extract32(ctx->opcode, 6, 4);
25778 if (unlikely(pad != 0)) {
25779 /* opcode padding incorrect -> do nothing */
25780 } else if (unlikely(XRa == 0)) {
25781 /* destination is zero register -> do nothing */
25782 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25783 /* both operands zero registers -> just set destination to all 1s */
25784 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25785 } else if (unlikely(XRb == 0)) {
25786 /* XRb zero register -> just set destination to the negation of XRc */
25787 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25788 } else if (unlikely(XRc == 0)) {
25789 /* XRa zero register -> just set destination to the negation of XRb */
25790 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25791 } else if (unlikely(XRb == XRc)) {
25792 /* both operands same -> just set destination to the negation of XRb */
25793 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25794 } else {
25795 /* the most general case */
25796 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25801 * S32AND XRa, XRb, XRc
25802 * Update XRa with the result of logical bitwise 'and' operation
25803 * applied to the content of XRb and XRc.
25805 * 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
25806 * +-----------+---------+-----+-------+-------+-------+-----------+
25807 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25808 * +-----------+---------+-----+-------+-------+-------+-----------+
25810 static void gen_mxu_S32AND(DisasContext *ctx)
25812 uint32_t pad, XRc, XRb, XRa;
25814 pad = extract32(ctx->opcode, 21, 5);
25815 XRc = extract32(ctx->opcode, 14, 4);
25816 XRb = extract32(ctx->opcode, 10, 4);
25817 XRa = extract32(ctx->opcode, 6, 4);
25819 if (unlikely(pad != 0)) {
25820 /* opcode padding incorrect -> do nothing */
25821 } else if (unlikely(XRa == 0)) {
25822 /* destination is zero register -> do nothing */
25823 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25824 /* one of operands zero register -> just set destination to all 0s */
25825 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25826 } else if (unlikely(XRb == XRc)) {
25827 /* both operands same -> just set destination to one of them */
25828 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25829 } else {
25830 /* the most general case */
25831 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25836 * S32OR XRa, XRb, XRc
25837 * Update XRa with the result of logical bitwise 'or' operation
25838 * applied to the content of XRb and XRc.
25840 * 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
25841 * +-----------+---------+-----+-------+-------+-------+-----------+
25842 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25843 * +-----------+---------+-----+-------+-------+-------+-----------+
25845 static void gen_mxu_S32OR(DisasContext *ctx)
25847 uint32_t pad, XRc, XRb, XRa;
25849 pad = extract32(ctx->opcode, 21, 5);
25850 XRc = extract32(ctx->opcode, 14, 4);
25851 XRb = extract32(ctx->opcode, 10, 4);
25852 XRa = extract32(ctx->opcode, 6, 4);
25854 if (unlikely(pad != 0)) {
25855 /* opcode padding incorrect -> do nothing */
25856 } else if (unlikely(XRa == 0)) {
25857 /* destination is zero register -> do nothing */
25858 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25859 /* both operands zero registers -> just set destination to all 0s */
25860 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25861 } else if (unlikely(XRb == 0)) {
25862 /* XRb zero register -> just set destination to the content of XRc */
25863 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25864 } else if (unlikely(XRc == 0)) {
25865 /* XRc zero register -> just set destination to the content of XRb */
25866 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25867 } else if (unlikely(XRb == XRc)) {
25868 /* both operands same -> just set destination to one of them */
25869 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25870 } else {
25871 /* the most general case */
25872 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25877 * S32XOR XRa, XRb, XRc
25878 * Update XRa with the result of logical bitwise 'xor' operation
25879 * applied to the content of XRb and XRc.
25881 * 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
25882 * +-----------+---------+-----+-------+-------+-------+-----------+
25883 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25884 * +-----------+---------+-----+-------+-------+-------+-----------+
25886 static void gen_mxu_S32XOR(DisasContext *ctx)
25888 uint32_t pad, XRc, XRb, XRa;
25890 pad = extract32(ctx->opcode, 21, 5);
25891 XRc = extract32(ctx->opcode, 14, 4);
25892 XRb = extract32(ctx->opcode, 10, 4);
25893 XRa = extract32(ctx->opcode, 6, 4);
25895 if (unlikely(pad != 0)) {
25896 /* opcode padding incorrect -> do nothing */
25897 } else if (unlikely(XRa == 0)) {
25898 /* destination is zero register -> do nothing */
25899 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25900 /* both operands zero registers -> just set destination to all 0s */
25901 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25902 } else if (unlikely(XRb == 0)) {
25903 /* XRb zero register -> just set destination to the content of XRc */
25904 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25905 } else if (unlikely(XRc == 0)) {
25906 /* XRc zero register -> just set destination to the content of XRb */
25907 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25908 } else if (unlikely(XRb == XRc)) {
25909 /* both operands same -> just set destination to all 0s */
25910 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25911 } else {
25912 /* the most general case */
25913 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25919 * MXU instruction category max/min
25920 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25922 * S32MAX D16MAX Q8MAX
25923 * S32MIN D16MIN Q8MIN
25927 * S32MAX XRa, XRb, XRc
25928 * Update XRa with the maximum of signed 32-bit integers contained
25929 * in XRb and XRc.
25931 * S32MIN XRa, XRb, XRc
25932 * Update XRa with the minimum of signed 32-bit integers contained
25933 * in XRb and XRc.
25935 * 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
25936 * +-----------+---------+-----+-------+-------+-------+-----------+
25937 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25938 * +-----------+---------+-----+-------+-------+-------+-----------+
25940 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25942 uint32_t pad, opc, XRc, XRb, XRa;
25944 pad = extract32(ctx->opcode, 21, 5);
25945 opc = extract32(ctx->opcode, 18, 3);
25946 XRc = extract32(ctx->opcode, 14, 4);
25947 XRb = extract32(ctx->opcode, 10, 4);
25948 XRa = extract32(ctx->opcode, 6, 4);
25950 if (unlikely(pad != 0)) {
25951 /* opcode padding incorrect -> do nothing */
25952 } else if (unlikely(XRa == 0)) {
25953 /* destination is zero register -> do nothing */
25954 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25955 /* both operands zero registers -> just set destination to zero */
25956 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25957 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25958 /* exactly one operand is zero register - find which one is not...*/
25959 uint32_t XRx = XRb ? XRb : XRc;
25960 /* ...and do max/min operation with one operand 0 */
25961 if (opc == OPC_MXU_S32MAX) {
25962 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25963 } else {
25964 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25966 } else if (unlikely(XRb == XRc)) {
25967 /* both operands same -> just set destination to one of them */
25968 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25969 } else {
25970 /* the most general case */
25971 if (opc == OPC_MXU_S32MAX) {
25972 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25973 mxu_gpr[XRc - 1]);
25974 } else {
25975 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25976 mxu_gpr[XRc - 1]);
25982 * D16MAX
25983 * Update XRa with the 16-bit-wise maximums of signed integers
25984 * contained in XRb and XRc.
25986 * D16MIN
25987 * Update XRa with the 16-bit-wise minimums of signed integers
25988 * contained in XRb and XRc.
25990 * 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
25991 * +-----------+---------+-----+-------+-------+-------+-----------+
25992 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25993 * +-----------+---------+-----+-------+-------+-------+-----------+
25995 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25997 uint32_t pad, opc, XRc, XRb, XRa;
25999 pad = extract32(ctx->opcode, 21, 5);
26000 opc = extract32(ctx->opcode, 18, 3);
26001 XRc = extract32(ctx->opcode, 14, 4);
26002 XRb = extract32(ctx->opcode, 10, 4);
26003 XRa = extract32(ctx->opcode, 6, 4);
26005 if (unlikely(pad != 0)) {
26006 /* opcode padding incorrect -> do nothing */
26007 } else if (unlikely(XRc == 0)) {
26008 /* destination is zero register -> do nothing */
26009 } else if (unlikely((XRb == 0) && (XRa == 0))) {
26010 /* both operands zero registers -> just set destination to zero */
26011 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
26012 } else if (unlikely((XRb == 0) || (XRa == 0))) {
26013 /* exactly one operand is zero register - find which one is not...*/
26014 uint32_t XRx = XRb ? XRb : XRc;
26015 /* ...and do half-word-wise max/min with one operand 0 */
26016 TCGv_i32 t0 = tcg_temp_new();
26017 TCGv_i32 t1 = tcg_const_i32(0);
26019 /* the left half-word first */
26020 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
26021 if (opc == OPC_MXU_D16MAX) {
26022 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26023 } else {
26024 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26027 /* the right half-word */
26028 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
26029 /* move half-words to the leftmost position */
26030 tcg_gen_shli_i32(t0, t0, 16);
26031 /* t0 will be max/min of t0 and t1 */
26032 if (opc == OPC_MXU_D16MAX) {
26033 tcg_gen_smax_i32(t0, t0, t1);
26034 } else {
26035 tcg_gen_smin_i32(t0, t0, t1);
26037 /* return resulting half-words to its original position */
26038 tcg_gen_shri_i32(t0, t0, 16);
26039 /* finally update the destination */
26040 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26042 tcg_temp_free(t1);
26043 tcg_temp_free(t0);
26044 } else if (unlikely(XRb == XRc)) {
26045 /* both operands same -> just set destination to one of them */
26046 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26047 } else {
26048 /* the most general case */
26049 TCGv_i32 t0 = tcg_temp_new();
26050 TCGv_i32 t1 = tcg_temp_new();
26052 /* the left half-word first */
26053 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
26054 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26055 if (opc == OPC_MXU_D16MAX) {
26056 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26057 } else {
26058 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26061 /* the right half-word */
26062 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26063 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
26064 /* move half-words to the leftmost position */
26065 tcg_gen_shli_i32(t0, t0, 16);
26066 tcg_gen_shli_i32(t1, t1, 16);
26067 /* t0 will be max/min of t0 and t1 */
26068 if (opc == OPC_MXU_D16MAX) {
26069 tcg_gen_smax_i32(t0, t0, t1);
26070 } else {
26071 tcg_gen_smin_i32(t0, t0, t1);
26073 /* return resulting half-words to its original position */
26074 tcg_gen_shri_i32(t0, t0, 16);
26075 /* finally update the destination */
26076 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26078 tcg_temp_free(t1);
26079 tcg_temp_free(t0);
26084 * Q8MAX
26085 * Update XRa with the 8-bit-wise maximums of signed integers
26086 * contained in XRb and XRc.
26088 * Q8MIN
26089 * Update XRa with the 8-bit-wise minimums of signed integers
26090 * contained in XRb and XRc.
26092 * 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
26093 * +-----------+---------+-----+-------+-------+-------+-----------+
26094 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
26095 * +-----------+---------+-----+-------+-------+-------+-----------+
26097 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
26099 uint32_t pad, opc, XRc, XRb, XRa;
26101 pad = extract32(ctx->opcode, 21, 5);
26102 opc = extract32(ctx->opcode, 18, 3);
26103 XRc = extract32(ctx->opcode, 14, 4);
26104 XRb = extract32(ctx->opcode, 10, 4);
26105 XRa = extract32(ctx->opcode, 6, 4);
26107 if (unlikely(pad != 0)) {
26108 /* opcode padding incorrect -> do nothing */
26109 } else if (unlikely(XRa == 0)) {
26110 /* destination is zero register -> do nothing */
26111 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26112 /* both operands zero registers -> just set destination to zero */
26113 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26114 } else if (unlikely((XRb == 0) || (XRc == 0))) {
26115 /* exactly one operand is zero register - make it be the first...*/
26116 uint32_t XRx = XRb ? XRb : XRc;
26117 /* ...and do byte-wise max/min with one operand 0 */
26118 TCGv_i32 t0 = tcg_temp_new();
26119 TCGv_i32 t1 = tcg_const_i32(0);
26120 int32_t i;
26122 /* the leftmost byte (byte 3) first */
26123 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
26124 if (opc == OPC_MXU_Q8MAX) {
26125 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26126 } else {
26127 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26130 /* bytes 2, 1, 0 */
26131 for (i = 2; i >= 0; i--) {
26132 /* extract the byte */
26133 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
26134 /* move the byte to the leftmost position */
26135 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26136 /* t0 will be max/min of t0 and t1 */
26137 if (opc == OPC_MXU_Q8MAX) {
26138 tcg_gen_smax_i32(t0, t0, t1);
26139 } else {
26140 tcg_gen_smin_i32(t0, t0, t1);
26142 /* return resulting byte to its original position */
26143 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26144 /* finally update the destination */
26145 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26148 tcg_temp_free(t1);
26149 tcg_temp_free(t0);
26150 } else if (unlikely(XRb == XRc)) {
26151 /* both operands same -> just set destination to one of them */
26152 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26153 } else {
26154 /* the most general case */
26155 TCGv_i32 t0 = tcg_temp_new();
26156 TCGv_i32 t1 = tcg_temp_new();
26157 int32_t i;
26159 /* the leftmost bytes (bytes 3) first */
26160 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
26161 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26162 if (opc == OPC_MXU_Q8MAX) {
26163 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26164 } else {
26165 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26168 /* bytes 2, 1, 0 */
26169 for (i = 2; i >= 0; i--) {
26170 /* extract corresponding bytes */
26171 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
26172 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
26173 /* move the bytes to the leftmost position */
26174 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26175 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
26176 /* t0 will be max/min of t0 and t1 */
26177 if (opc == OPC_MXU_Q8MAX) {
26178 tcg_gen_smax_i32(t0, t0, t1);
26179 } else {
26180 tcg_gen_smin_i32(t0, t0, t1);
26182 /* return resulting byte to its original position */
26183 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26184 /* finally update the destination */
26185 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26188 tcg_temp_free(t1);
26189 tcg_temp_free(t0);
26195 * MXU instruction category: align
26196 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26198 * S32ALN S32ALNI
26202 * S32ALNI XRc, XRb, XRa, optn3
26203 * Arrange bytes from XRb and XRc according to one of five sets of
26204 * rules determined by optn3, and place the result in XRa.
26206 * 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
26207 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26208 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26209 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26212 static void gen_mxu_S32ALNI(DisasContext *ctx)
26214 uint32_t optn3, pad, XRc, XRb, XRa;
26216 optn3 = extract32(ctx->opcode, 23, 3);
26217 pad = extract32(ctx->opcode, 21, 2);
26218 XRc = extract32(ctx->opcode, 14, 4);
26219 XRb = extract32(ctx->opcode, 10, 4);
26220 XRa = extract32(ctx->opcode, 6, 4);
26222 if (unlikely(pad != 0)) {
26223 /* opcode padding incorrect -> do nothing */
26224 } else if (unlikely(XRa == 0)) {
26225 /* destination is zero register -> do nothing */
26226 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26227 /* both operands zero registers -> just set destination to all 0s */
26228 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26229 } else if (unlikely(XRb == 0)) {
26230 /* XRb zero register -> just appropriatelly shift XRc into XRa */
26231 switch (optn3) {
26232 case MXU_OPTN3_PTN0:
26233 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26234 break;
26235 case MXU_OPTN3_PTN1:
26236 case MXU_OPTN3_PTN2:
26237 case MXU_OPTN3_PTN3:
26238 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
26239 8 * (4 - optn3));
26240 break;
26241 case MXU_OPTN3_PTN4:
26242 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26243 break;
26245 } else if (unlikely(XRc == 0)) {
26246 /* XRc zero register -> just appropriatelly shift XRb into XRa */
26247 switch (optn3) {
26248 case MXU_OPTN3_PTN0:
26249 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26250 break;
26251 case MXU_OPTN3_PTN1:
26252 case MXU_OPTN3_PTN2:
26253 case MXU_OPTN3_PTN3:
26254 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26255 break;
26256 case MXU_OPTN3_PTN4:
26257 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26258 break;
26260 } else if (unlikely(XRb == XRc)) {
26261 /* both operands same -> just rotation or moving from any of them */
26262 switch (optn3) {
26263 case MXU_OPTN3_PTN0:
26264 case MXU_OPTN3_PTN4:
26265 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26266 break;
26267 case MXU_OPTN3_PTN1:
26268 case MXU_OPTN3_PTN2:
26269 case MXU_OPTN3_PTN3:
26270 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26271 break;
26273 } else {
26274 /* the most general case */
26275 switch (optn3) {
26276 case MXU_OPTN3_PTN0:
26278 /* */
26279 /* XRb XRc */
26280 /* +---------------+ */
26281 /* | A B C D | E F G H */
26282 /* +-------+-------+ */
26283 /* | */
26284 /* XRa */
26285 /* */
26287 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26289 break;
26290 case MXU_OPTN3_PTN1:
26292 /* */
26293 /* XRb XRc */
26294 /* +-------------------+ */
26295 /* A | B C D E | F G H */
26296 /* +---------+---------+ */
26297 /* | */
26298 /* XRa */
26299 /* */
26301 TCGv_i32 t0 = tcg_temp_new();
26302 TCGv_i32 t1 = tcg_temp_new();
26304 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
26305 tcg_gen_shli_i32(t0, t0, 8);
26307 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26308 tcg_gen_shri_i32(t1, t1, 24);
26310 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26312 tcg_temp_free(t1);
26313 tcg_temp_free(t0);
26315 break;
26316 case MXU_OPTN3_PTN2:
26318 /* */
26319 /* XRb XRc */
26320 /* +-------------------+ */
26321 /* A B | C D E F | G H */
26322 /* +---------+---------+ */
26323 /* | */
26324 /* XRa */
26325 /* */
26327 TCGv_i32 t0 = tcg_temp_new();
26328 TCGv_i32 t1 = tcg_temp_new();
26330 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26331 tcg_gen_shli_i32(t0, t0, 16);
26333 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26334 tcg_gen_shri_i32(t1, t1, 16);
26336 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26338 tcg_temp_free(t1);
26339 tcg_temp_free(t0);
26341 break;
26342 case MXU_OPTN3_PTN3:
26344 /* */
26345 /* XRb XRc */
26346 /* +-------------------+ */
26347 /* A B C | D E F G | H */
26348 /* +---------+---------+ */
26349 /* | */
26350 /* XRa */
26351 /* */
26353 TCGv_i32 t0 = tcg_temp_new();
26354 TCGv_i32 t1 = tcg_temp_new();
26356 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
26357 tcg_gen_shli_i32(t0, t0, 24);
26359 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
26360 tcg_gen_shri_i32(t1, t1, 8);
26362 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26364 tcg_temp_free(t1);
26365 tcg_temp_free(t0);
26367 break;
26368 case MXU_OPTN3_PTN4:
26370 /* */
26371 /* XRb XRc */
26372 /* +---------------+ */
26373 /* A B C D | E F G H | */
26374 /* +-------+-------+ */
26375 /* | */
26376 /* XRa */
26377 /* */
26379 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26381 break;
26388 * Decoding engine for MXU
26389 * =======================
26394 * Decode MXU pool00
26396 * 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
26397 * +-----------+---------+-----+-------+-------+-------+-----------+
26398 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
26399 * +-----------+---------+-----+-------+-------+-------+-----------+
26402 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
26404 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26406 switch (opcode) {
26407 case OPC_MXU_S32MAX:
26408 case OPC_MXU_S32MIN:
26409 gen_mxu_S32MAX_S32MIN(ctx);
26410 break;
26411 case OPC_MXU_D16MAX:
26412 case OPC_MXU_D16MIN:
26413 gen_mxu_D16MAX_D16MIN(ctx);
26414 break;
26415 case OPC_MXU_Q8MAX:
26416 case OPC_MXU_Q8MIN:
26417 gen_mxu_Q8MAX_Q8MIN(ctx);
26418 break;
26419 case OPC_MXU_Q8SLT:
26420 /* TODO: Implement emulation of Q8SLT instruction. */
26421 MIPS_INVAL("OPC_MXU_Q8SLT");
26422 generate_exception_end(ctx, EXCP_RI);
26423 break;
26424 case OPC_MXU_Q8SLTU:
26425 /* TODO: Implement emulation of Q8SLTU instruction. */
26426 MIPS_INVAL("OPC_MXU_Q8SLTU");
26427 generate_exception_end(ctx, EXCP_RI);
26428 break;
26429 default:
26430 MIPS_INVAL("decode_opc_mxu");
26431 generate_exception_end(ctx, EXCP_RI);
26432 break;
26438 * Decode MXU pool01
26440 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26441 * 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
26442 * +-----------+---------+-----+-------+-------+-------+-----------+
26443 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26444 * +-----------+---------+-----+-------+-------+-------+-----------+
26446 * Q8ADD:
26447 * 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
26448 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26449 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26450 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26453 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26455 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26457 switch (opcode) {
26458 case OPC_MXU_S32SLT:
26459 /* TODO: Implement emulation of S32SLT instruction. */
26460 MIPS_INVAL("OPC_MXU_S32SLT");
26461 generate_exception_end(ctx, EXCP_RI);
26462 break;
26463 case OPC_MXU_D16SLT:
26464 /* TODO: Implement emulation of D16SLT instruction. */
26465 MIPS_INVAL("OPC_MXU_D16SLT");
26466 generate_exception_end(ctx, EXCP_RI);
26467 break;
26468 case OPC_MXU_D16AVG:
26469 /* TODO: Implement emulation of D16AVG instruction. */
26470 MIPS_INVAL("OPC_MXU_D16AVG");
26471 generate_exception_end(ctx, EXCP_RI);
26472 break;
26473 case OPC_MXU_D16AVGR:
26474 /* TODO: Implement emulation of D16AVGR instruction. */
26475 MIPS_INVAL("OPC_MXU_D16AVGR");
26476 generate_exception_end(ctx, EXCP_RI);
26477 break;
26478 case OPC_MXU_Q8AVG:
26479 /* TODO: Implement emulation of Q8AVG instruction. */
26480 MIPS_INVAL("OPC_MXU_Q8AVG");
26481 generate_exception_end(ctx, EXCP_RI);
26482 break;
26483 case OPC_MXU_Q8AVGR:
26484 /* TODO: Implement emulation of Q8AVGR instruction. */
26485 MIPS_INVAL("OPC_MXU_Q8AVGR");
26486 generate_exception_end(ctx, EXCP_RI);
26487 break;
26488 case OPC_MXU_Q8ADD:
26489 /* TODO: Implement emulation of Q8ADD instruction. */
26490 MIPS_INVAL("OPC_MXU_Q8ADD");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26493 default:
26494 MIPS_INVAL("decode_opc_mxu");
26495 generate_exception_end(ctx, EXCP_RI);
26496 break;
26502 * Decode MXU pool02
26504 * 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
26505 * +-----------+---------+-----+-------+-------+-------+-----------+
26506 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26507 * +-----------+---------+-----+-------+-------+-------+-----------+
26510 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26512 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26514 switch (opcode) {
26515 case OPC_MXU_S32CPS:
26516 /* TODO: Implement emulation of S32CPS instruction. */
26517 MIPS_INVAL("OPC_MXU_S32CPS");
26518 generate_exception_end(ctx, EXCP_RI);
26519 break;
26520 case OPC_MXU_D16CPS:
26521 /* TODO: Implement emulation of D16CPS instruction. */
26522 MIPS_INVAL("OPC_MXU_D16CPS");
26523 generate_exception_end(ctx, EXCP_RI);
26524 break;
26525 case OPC_MXU_Q8ABD:
26526 /* TODO: Implement emulation of Q8ABD instruction. */
26527 MIPS_INVAL("OPC_MXU_Q8ABD");
26528 generate_exception_end(ctx, EXCP_RI);
26529 break;
26530 case OPC_MXU_Q16SAT:
26531 /* TODO: Implement emulation of Q16SAT instruction. */
26532 MIPS_INVAL("OPC_MXU_Q16SAT");
26533 generate_exception_end(ctx, EXCP_RI);
26534 break;
26535 default:
26536 MIPS_INVAL("decode_opc_mxu");
26537 generate_exception_end(ctx, EXCP_RI);
26538 break;
26544 * Decode MXU pool03
26546 * D16MULF:
26547 * 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
26548 * +-----------+---+---+-------+-------+-------+-------+-----------+
26549 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26550 * +-----------+---+---+-------+-------+-------+-------+-----------+
26552 * D16MULE:
26553 * 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
26554 * +-----------+---+---+-------+-------+-------+-------+-----------+
26555 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26556 * +-----------+---+---+-------+-------+-------+-------+-----------+
26559 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26561 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26563 switch (opcode) {
26564 case OPC_MXU_D16MULF:
26565 /* TODO: Implement emulation of D16MULF instruction. */
26566 MIPS_INVAL("OPC_MXU_D16MULF");
26567 generate_exception_end(ctx, EXCP_RI);
26568 break;
26569 case OPC_MXU_D16MULE:
26570 /* TODO: Implement emulation of D16MULE instruction. */
26571 MIPS_INVAL("OPC_MXU_D16MULE");
26572 generate_exception_end(ctx, EXCP_RI);
26573 break;
26574 default:
26575 MIPS_INVAL("decode_opc_mxu");
26576 generate_exception_end(ctx, EXCP_RI);
26577 break;
26583 * Decode MXU pool04
26585 * 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
26586 * +-----------+---------+-+-------------------+-------+-----------+
26587 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26588 * +-----------+---------+-+-------------------+-------+-----------+
26591 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26593 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26595 switch (opcode) {
26596 case OPC_MXU_S32LDD:
26597 case OPC_MXU_S32LDDR:
26598 gen_mxu_s32ldd_s32lddr(ctx);
26599 break;
26600 default:
26601 MIPS_INVAL("decode_opc_mxu");
26602 generate_exception_end(ctx, EXCP_RI);
26603 break;
26609 * Decode MXU pool05
26611 * 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
26612 * +-----------+---------+-+-------------------+-------+-----------+
26613 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26614 * +-----------+---------+-+-------------------+-------+-----------+
26617 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26619 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26621 switch (opcode) {
26622 case OPC_MXU_S32STD:
26623 /* TODO: Implement emulation of S32STD instruction. */
26624 MIPS_INVAL("OPC_MXU_S32STD");
26625 generate_exception_end(ctx, EXCP_RI);
26626 break;
26627 case OPC_MXU_S32STDR:
26628 /* TODO: Implement emulation of S32STDR instruction. */
26629 MIPS_INVAL("OPC_MXU_S32STDR");
26630 generate_exception_end(ctx, EXCP_RI);
26631 break;
26632 default:
26633 MIPS_INVAL("decode_opc_mxu");
26634 generate_exception_end(ctx, EXCP_RI);
26635 break;
26641 * Decode MXU pool06
26643 * 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
26644 * +-----------+---------+---------+---+-------+-------+-----------+
26645 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26646 * +-----------+---------+---------+---+-------+-------+-----------+
26649 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26651 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26653 switch (opcode) {
26654 case OPC_MXU_S32LDDV:
26655 /* TODO: Implement emulation of S32LDDV instruction. */
26656 MIPS_INVAL("OPC_MXU_S32LDDV");
26657 generate_exception_end(ctx, EXCP_RI);
26658 break;
26659 case OPC_MXU_S32LDDVR:
26660 /* TODO: Implement emulation of S32LDDVR instruction. */
26661 MIPS_INVAL("OPC_MXU_S32LDDVR");
26662 generate_exception_end(ctx, EXCP_RI);
26663 break;
26664 default:
26665 MIPS_INVAL("decode_opc_mxu");
26666 generate_exception_end(ctx, EXCP_RI);
26667 break;
26673 * Decode MXU pool07
26675 * 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
26676 * +-----------+---------+---------+---+-------+-------+-----------+
26677 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26678 * +-----------+---------+---------+---+-------+-------+-----------+
26681 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26683 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26685 switch (opcode) {
26686 case OPC_MXU_S32STDV:
26687 /* TODO: Implement emulation of S32TDV instruction. */
26688 MIPS_INVAL("OPC_MXU_S32TDV");
26689 generate_exception_end(ctx, EXCP_RI);
26690 break;
26691 case OPC_MXU_S32STDVR:
26692 /* TODO: Implement emulation of S32TDVR instruction. */
26693 MIPS_INVAL("OPC_MXU_S32TDVR");
26694 generate_exception_end(ctx, EXCP_RI);
26695 break;
26696 default:
26697 MIPS_INVAL("decode_opc_mxu");
26698 generate_exception_end(ctx, EXCP_RI);
26699 break;
26705 * Decode MXU pool08
26707 * 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
26708 * +-----------+---------+-+-------------------+-------+-----------+
26709 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26710 * +-----------+---------+-+-------------------+-------+-----------+
26713 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26715 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26717 switch (opcode) {
26718 case OPC_MXU_S32LDI:
26719 /* TODO: Implement emulation of S32LDI instruction. */
26720 MIPS_INVAL("OPC_MXU_S32LDI");
26721 generate_exception_end(ctx, EXCP_RI);
26722 break;
26723 case OPC_MXU_S32LDIR:
26724 /* TODO: Implement emulation of S32LDIR instruction. */
26725 MIPS_INVAL("OPC_MXU_S32LDIR");
26726 generate_exception_end(ctx, EXCP_RI);
26727 break;
26728 default:
26729 MIPS_INVAL("decode_opc_mxu");
26730 generate_exception_end(ctx, EXCP_RI);
26731 break;
26737 * Decode MXU pool09
26739 * 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
26740 * +-----------+---------+-+-------------------+-------+-----------+
26741 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26742 * +-----------+---------+-+-------------------+-------+-----------+
26745 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26747 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26749 switch (opcode) {
26750 case OPC_MXU_S32SDI:
26751 /* TODO: Implement emulation of S32SDI instruction. */
26752 MIPS_INVAL("OPC_MXU_S32SDI");
26753 generate_exception_end(ctx, EXCP_RI);
26754 break;
26755 case OPC_MXU_S32SDIR:
26756 /* TODO: Implement emulation of S32SDIR instruction. */
26757 MIPS_INVAL("OPC_MXU_S32SDIR");
26758 generate_exception_end(ctx, EXCP_RI);
26759 break;
26760 default:
26761 MIPS_INVAL("decode_opc_mxu");
26762 generate_exception_end(ctx, EXCP_RI);
26763 break;
26769 * Decode MXU pool10
26771 * 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
26772 * +-----------+---------+---------+---+-------+-------+-----------+
26773 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26774 * +-----------+---------+---------+---+-------+-------+-----------+
26777 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26779 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26781 switch (opcode) {
26782 case OPC_MXU_S32LDIV:
26783 /* TODO: Implement emulation of S32LDIV instruction. */
26784 MIPS_INVAL("OPC_MXU_S32LDIV");
26785 generate_exception_end(ctx, EXCP_RI);
26786 break;
26787 case OPC_MXU_S32LDIVR:
26788 /* TODO: Implement emulation of S32LDIVR instruction. */
26789 MIPS_INVAL("OPC_MXU_S32LDIVR");
26790 generate_exception_end(ctx, EXCP_RI);
26791 break;
26792 default:
26793 MIPS_INVAL("decode_opc_mxu");
26794 generate_exception_end(ctx, EXCP_RI);
26795 break;
26801 * Decode MXU pool11
26803 * 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
26804 * +-----------+---------+---------+---+-------+-------+-----------+
26805 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26806 * +-----------+---------+---------+---+-------+-------+-----------+
26809 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26811 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26813 switch (opcode) {
26814 case OPC_MXU_S32SDIV:
26815 /* TODO: Implement emulation of S32SDIV instruction. */
26816 MIPS_INVAL("OPC_MXU_S32SDIV");
26817 generate_exception_end(ctx, EXCP_RI);
26818 break;
26819 case OPC_MXU_S32SDIVR:
26820 /* TODO: Implement emulation of S32SDIVR instruction. */
26821 MIPS_INVAL("OPC_MXU_S32SDIVR");
26822 generate_exception_end(ctx, EXCP_RI);
26823 break;
26824 default:
26825 MIPS_INVAL("decode_opc_mxu");
26826 generate_exception_end(ctx, EXCP_RI);
26827 break;
26833 * Decode MXU pool12
26835 * 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
26836 * +-----------+---+---+-------+-------+-------+-------+-----------+
26837 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26838 * +-----------+---+---+-------+-------+-------+-------+-----------+
26841 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26843 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26845 switch (opcode) {
26846 case OPC_MXU_D32ACC:
26847 /* TODO: Implement emulation of D32ACC instruction. */
26848 MIPS_INVAL("OPC_MXU_D32ACC");
26849 generate_exception_end(ctx, EXCP_RI);
26850 break;
26851 case OPC_MXU_D32ACCM:
26852 /* TODO: Implement emulation of D32ACCM instruction. */
26853 MIPS_INVAL("OPC_MXU_D32ACCM");
26854 generate_exception_end(ctx, EXCP_RI);
26855 break;
26856 case OPC_MXU_D32ASUM:
26857 /* TODO: Implement emulation of D32ASUM instruction. */
26858 MIPS_INVAL("OPC_MXU_D32ASUM");
26859 generate_exception_end(ctx, EXCP_RI);
26860 break;
26861 default:
26862 MIPS_INVAL("decode_opc_mxu");
26863 generate_exception_end(ctx, EXCP_RI);
26864 break;
26870 * Decode MXU pool13
26872 * 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
26873 * +-----------+---+---+-------+-------+-------+-------+-----------+
26874 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26875 * +-----------+---+---+-------+-------+-------+-------+-----------+
26878 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26880 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26882 switch (opcode) {
26883 case OPC_MXU_Q16ACC:
26884 /* TODO: Implement emulation of Q16ACC instruction. */
26885 MIPS_INVAL("OPC_MXU_Q16ACC");
26886 generate_exception_end(ctx, EXCP_RI);
26887 break;
26888 case OPC_MXU_Q16ACCM:
26889 /* TODO: Implement emulation of Q16ACCM instruction. */
26890 MIPS_INVAL("OPC_MXU_Q16ACCM");
26891 generate_exception_end(ctx, EXCP_RI);
26892 break;
26893 case OPC_MXU_Q16ASUM:
26894 /* TODO: Implement emulation of Q16ASUM instruction. */
26895 MIPS_INVAL("OPC_MXU_Q16ASUM");
26896 generate_exception_end(ctx, EXCP_RI);
26897 break;
26898 default:
26899 MIPS_INVAL("decode_opc_mxu");
26900 generate_exception_end(ctx, EXCP_RI);
26901 break;
26907 * Decode MXU pool14
26909 * Q8ADDE, Q8ACCE:
26910 * 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
26911 * +-----------+---+---+-------+-------+-------+-------+-----------+
26912 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26913 * +-----------+---+---+-------+-------+-------+-------+-----------+
26915 * D8SUM, D8SUMC:
26916 * 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
26917 * +-----------+---+---+-------+-------+-------+-------+-----------+
26918 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26919 * +-----------+---+---+-------+-------+-------+-------+-----------+
26922 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26924 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26926 switch (opcode) {
26927 case OPC_MXU_Q8ADDE:
26928 /* TODO: Implement emulation of Q8ADDE instruction. */
26929 MIPS_INVAL("OPC_MXU_Q8ADDE");
26930 generate_exception_end(ctx, EXCP_RI);
26931 break;
26932 case OPC_MXU_D8SUM:
26933 /* TODO: Implement emulation of D8SUM instruction. */
26934 MIPS_INVAL("OPC_MXU_D8SUM");
26935 generate_exception_end(ctx, EXCP_RI);
26936 break;
26937 case OPC_MXU_D8SUMC:
26938 /* TODO: Implement emulation of D8SUMC instruction. */
26939 MIPS_INVAL("OPC_MXU_D8SUMC");
26940 generate_exception_end(ctx, EXCP_RI);
26941 break;
26942 default:
26943 MIPS_INVAL("decode_opc_mxu");
26944 generate_exception_end(ctx, EXCP_RI);
26945 break;
26951 * Decode MXU pool15
26953 * S32MUL, S32MULU, S32EXTRV:
26954 * 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
26955 * +-----------+---------+---------+---+-------+-------+-----------+
26956 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26957 * +-----------+---------+---------+---+-------+-------+-----------+
26959 * S32EXTR:
26960 * 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
26961 * +-----------+---------+---------+---+-------+-------+-----------+
26962 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26963 * +-----------+---------+---------+---+-------+-------+-----------+
26966 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26968 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26970 switch (opcode) {
26971 case OPC_MXU_S32MUL:
26972 /* TODO: Implement emulation of S32MUL instruction. */
26973 MIPS_INVAL("OPC_MXU_S32MUL");
26974 generate_exception_end(ctx, EXCP_RI);
26975 break;
26976 case OPC_MXU_S32MULU:
26977 /* TODO: Implement emulation of S32MULU instruction. */
26978 MIPS_INVAL("OPC_MXU_S32MULU");
26979 generate_exception_end(ctx, EXCP_RI);
26980 break;
26981 case OPC_MXU_S32EXTR:
26982 /* TODO: Implement emulation of S32EXTR instruction. */
26983 MIPS_INVAL("OPC_MXU_S32EXTR");
26984 generate_exception_end(ctx, EXCP_RI);
26985 break;
26986 case OPC_MXU_S32EXTRV:
26987 /* TODO: Implement emulation of S32EXTRV instruction. */
26988 MIPS_INVAL("OPC_MXU_S32EXTRV");
26989 generate_exception_end(ctx, EXCP_RI);
26990 break;
26991 default:
26992 MIPS_INVAL("decode_opc_mxu");
26993 generate_exception_end(ctx, EXCP_RI);
26994 break;
27000 * Decode MXU pool16
27002 * D32SARW:
27003 * 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
27004 * +-----------+---------+-----+-------+-------+-------+-----------+
27005 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
27006 * +-----------+---------+-----+-------+-------+-------+-----------+
27008 * S32ALN:
27009 * 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
27010 * +-----------+---------+-----+-------+-------+-------+-----------+
27011 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
27012 * +-----------+---------+-----+-------+-------+-------+-----------+
27014 * S32ALNI:
27015 * 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
27016 * +-----------+-----+---+-----+-------+-------+-------+-----------+
27017 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
27018 * +-----------+-----+---+-----+-------+-------+-------+-----------+
27020 * S32LUI:
27021 * 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
27022 * +-----------+-----+---+-----+-------+---------------+-----------+
27023 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
27024 * +-----------+-----+---+-----+-------+---------------+-----------+
27026 * S32NOR, S32AND, S32OR, S32XOR:
27027 * 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
27028 * +-----------+---------+-----+-------+-------+-------+-----------+
27029 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
27030 * +-----------+---------+-----+-------+-------+-------+-----------+
27033 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
27035 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27037 switch (opcode) {
27038 case OPC_MXU_D32SARW:
27039 /* TODO: Implement emulation of D32SARW instruction. */
27040 MIPS_INVAL("OPC_MXU_D32SARW");
27041 generate_exception_end(ctx, EXCP_RI);
27042 break;
27043 case OPC_MXU_S32ALN:
27044 /* TODO: Implement emulation of S32ALN instruction. */
27045 MIPS_INVAL("OPC_MXU_S32ALN");
27046 generate_exception_end(ctx, EXCP_RI);
27047 break;
27048 case OPC_MXU_S32ALNI:
27049 gen_mxu_S32ALNI(ctx);
27050 break;
27051 case OPC_MXU_S32LUI:
27052 /* TODO: Implement emulation of S32LUI instruction. */
27053 MIPS_INVAL("OPC_MXU_S32LUI");
27054 generate_exception_end(ctx, EXCP_RI);
27055 break;
27056 case OPC_MXU_S32NOR:
27057 gen_mxu_S32NOR(ctx);
27058 break;
27059 case OPC_MXU_S32AND:
27060 gen_mxu_S32AND(ctx);
27061 break;
27062 case OPC_MXU_S32OR:
27063 gen_mxu_S32OR(ctx);
27064 break;
27065 case OPC_MXU_S32XOR:
27066 gen_mxu_S32XOR(ctx);
27067 break;
27068 default:
27069 MIPS_INVAL("decode_opc_mxu");
27070 generate_exception_end(ctx, EXCP_RI);
27071 break;
27077 * Decode MXU pool17
27079 * 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
27080 * +-----------+---------+---------+---+---------+-----+-----------+
27081 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
27082 * +-----------+---------+---------+---+---------+-----+-----------+
27085 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
27087 uint32_t opcode = extract32(ctx->opcode, 6, 2);
27089 switch (opcode) {
27090 case OPC_MXU_LXW:
27091 /* TODO: Implement emulation of LXW instruction. */
27092 MIPS_INVAL("OPC_MXU_LXW");
27093 generate_exception_end(ctx, EXCP_RI);
27094 break;
27095 case OPC_MXU_LXH:
27096 /* TODO: Implement emulation of LXH instruction. */
27097 MIPS_INVAL("OPC_MXU_LXH");
27098 generate_exception_end(ctx, EXCP_RI);
27099 break;
27100 case OPC_MXU_LXHU:
27101 /* TODO: Implement emulation of LXHU instruction. */
27102 MIPS_INVAL("OPC_MXU_LXHU");
27103 generate_exception_end(ctx, EXCP_RI);
27104 break;
27105 case OPC_MXU_LXB:
27106 /* TODO: Implement emulation of LXB instruction. */
27107 MIPS_INVAL("OPC_MXU_LXB");
27108 generate_exception_end(ctx, EXCP_RI);
27109 break;
27110 case OPC_MXU_LXBU:
27111 /* TODO: Implement emulation of LXBU instruction. */
27112 MIPS_INVAL("OPC_MXU_LXBU");
27113 generate_exception_end(ctx, EXCP_RI);
27114 break;
27115 default:
27116 MIPS_INVAL("decode_opc_mxu");
27117 generate_exception_end(ctx, EXCP_RI);
27118 break;
27123 * Decode MXU pool18
27125 * 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
27126 * +-----------+---------+-----+-------+-------+-------+-----------+
27127 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
27128 * +-----------+---------+-----+-------+-------+-------+-----------+
27131 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
27133 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27135 switch (opcode) {
27136 case OPC_MXU_D32SLLV:
27137 /* TODO: Implement emulation of D32SLLV instruction. */
27138 MIPS_INVAL("OPC_MXU_D32SLLV");
27139 generate_exception_end(ctx, EXCP_RI);
27140 break;
27141 case OPC_MXU_D32SLRV:
27142 /* TODO: Implement emulation of D32SLRV instruction. */
27143 MIPS_INVAL("OPC_MXU_D32SLRV");
27144 generate_exception_end(ctx, EXCP_RI);
27145 break;
27146 case OPC_MXU_D32SARV:
27147 /* TODO: Implement emulation of D32SARV instruction. */
27148 MIPS_INVAL("OPC_MXU_D32SARV");
27149 generate_exception_end(ctx, EXCP_RI);
27150 break;
27151 case OPC_MXU_Q16SLLV:
27152 /* TODO: Implement emulation of Q16SLLV instruction. */
27153 MIPS_INVAL("OPC_MXU_Q16SLLV");
27154 generate_exception_end(ctx, EXCP_RI);
27155 break;
27156 case OPC_MXU_Q16SLRV:
27157 /* TODO: Implement emulation of Q16SLRV instruction. */
27158 MIPS_INVAL("OPC_MXU_Q16SLRV");
27159 generate_exception_end(ctx, EXCP_RI);
27160 break;
27161 case OPC_MXU_Q16SARV:
27162 /* TODO: Implement emulation of Q16SARV instruction. */
27163 MIPS_INVAL("OPC_MXU_Q16SARV");
27164 generate_exception_end(ctx, EXCP_RI);
27165 break;
27166 default:
27167 MIPS_INVAL("decode_opc_mxu");
27168 generate_exception_end(ctx, EXCP_RI);
27169 break;
27175 * Decode MXU pool19
27177 * 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
27178 * +-----------+---+---+-------+-------+-------+-------+-----------+
27179 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
27180 * +-----------+---+---+-------+-------+-------+-------+-----------+
27183 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
27185 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27187 switch (opcode) {
27188 case OPC_MXU_Q8MUL:
27189 case OPC_MXU_Q8MULSU:
27190 gen_mxu_q8mul_q8mulsu(ctx);
27191 break;
27192 default:
27193 MIPS_INVAL("decode_opc_mxu");
27194 generate_exception_end(ctx, EXCP_RI);
27195 break;
27201 * Decode MXU pool20
27203 * 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
27204 * +-----------+---------+-----+-------+-------+-------+-----------+
27205 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
27206 * +-----------+---------+-----+-------+-------+-------+-----------+
27209 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
27211 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27213 switch (opcode) {
27214 case OPC_MXU_Q8MOVZ:
27215 /* TODO: Implement emulation of Q8MOVZ instruction. */
27216 MIPS_INVAL("OPC_MXU_Q8MOVZ");
27217 generate_exception_end(ctx, EXCP_RI);
27218 break;
27219 case OPC_MXU_Q8MOVN:
27220 /* TODO: Implement emulation of Q8MOVN instruction. */
27221 MIPS_INVAL("OPC_MXU_Q8MOVN");
27222 generate_exception_end(ctx, EXCP_RI);
27223 break;
27224 case OPC_MXU_D16MOVZ:
27225 /* TODO: Implement emulation of D16MOVZ instruction. */
27226 MIPS_INVAL("OPC_MXU_D16MOVZ");
27227 generate_exception_end(ctx, EXCP_RI);
27228 break;
27229 case OPC_MXU_D16MOVN:
27230 /* TODO: Implement emulation of D16MOVN instruction. */
27231 MIPS_INVAL("OPC_MXU_D16MOVN");
27232 generate_exception_end(ctx, EXCP_RI);
27233 break;
27234 case OPC_MXU_S32MOVZ:
27235 /* TODO: Implement emulation of S32MOVZ instruction. */
27236 MIPS_INVAL("OPC_MXU_S32MOVZ");
27237 generate_exception_end(ctx, EXCP_RI);
27238 break;
27239 case OPC_MXU_S32MOVN:
27240 /* TODO: Implement emulation of S32MOVN instruction. */
27241 MIPS_INVAL("OPC_MXU_S32MOVN");
27242 generate_exception_end(ctx, EXCP_RI);
27243 break;
27244 default:
27245 MIPS_INVAL("decode_opc_mxu");
27246 generate_exception_end(ctx, EXCP_RI);
27247 break;
27253 * Decode MXU pool21
27255 * 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
27256 * +-----------+---+---+-------+-------+-------+-------+-----------+
27257 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
27258 * +-----------+---+---+-------+-------+-------+-------+-----------+
27261 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
27263 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27265 switch (opcode) {
27266 case OPC_MXU_Q8MAC:
27267 /* TODO: Implement emulation of Q8MAC instruction. */
27268 MIPS_INVAL("OPC_MXU_Q8MAC");
27269 generate_exception_end(ctx, EXCP_RI);
27270 break;
27271 case OPC_MXU_Q8MACSU:
27272 /* TODO: Implement emulation of Q8MACSU instruction. */
27273 MIPS_INVAL("OPC_MXU_Q8MACSU");
27274 generate_exception_end(ctx, EXCP_RI);
27275 break;
27276 default:
27277 MIPS_INVAL("decode_opc_mxu");
27278 generate_exception_end(ctx, EXCP_RI);
27279 break;
27285 * Main MXU decoding function
27287 * 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
27288 * +-----------+---------------------------------------+-----------+
27289 * | SPECIAL2 | |x x x x x x|
27290 * +-----------+---------------------------------------+-----------+
27293 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
27296 * TODO: Investigate necessity of including handling of
27297 * CLZ, CLO, SDBB in this function, as they belong to
27298 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
27300 uint32_t opcode = extract32(ctx->opcode, 0, 6);
27302 if (opcode == OPC__MXU_MUL) {
27303 uint32_t rs, rt, rd, op1;
27305 rs = extract32(ctx->opcode, 21, 5);
27306 rt = extract32(ctx->opcode, 16, 5);
27307 rd = extract32(ctx->opcode, 11, 5);
27308 op1 = MASK_SPECIAL2(ctx->opcode);
27310 gen_arith(ctx, op1, rd, rs, rt);
27312 return;
27315 if (opcode == OPC_MXU_S32M2I) {
27316 gen_mxu_s32m2i(ctx);
27317 return;
27320 if (opcode == OPC_MXU_S32I2M) {
27321 gen_mxu_s32i2m(ctx);
27322 return;
27326 TCGv t_mxu_cr = tcg_temp_new();
27327 TCGLabel *l_exit = gen_new_label();
27329 gen_load_mxu_cr(t_mxu_cr);
27330 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
27331 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
27333 switch (opcode) {
27334 case OPC_MXU_S32MADD:
27335 /* TODO: Implement emulation of S32MADD instruction. */
27336 MIPS_INVAL("OPC_MXU_S32MADD");
27337 generate_exception_end(ctx, EXCP_RI);
27338 break;
27339 case OPC_MXU_S32MADDU:
27340 /* TODO: Implement emulation of S32MADDU instruction. */
27341 MIPS_INVAL("OPC_MXU_S32MADDU");
27342 generate_exception_end(ctx, EXCP_RI);
27343 break;
27344 case OPC_MXU__POOL00:
27345 decode_opc_mxu__pool00(env, ctx);
27346 break;
27347 case OPC_MXU_S32MSUB:
27348 /* TODO: Implement emulation of S32MSUB instruction. */
27349 MIPS_INVAL("OPC_MXU_S32MSUB");
27350 generate_exception_end(ctx, EXCP_RI);
27351 break;
27352 case OPC_MXU_S32MSUBU:
27353 /* TODO: Implement emulation of S32MSUBU instruction. */
27354 MIPS_INVAL("OPC_MXU_S32MSUBU");
27355 generate_exception_end(ctx, EXCP_RI);
27356 break;
27357 case OPC_MXU__POOL01:
27358 decode_opc_mxu__pool01(env, ctx);
27359 break;
27360 case OPC_MXU__POOL02:
27361 decode_opc_mxu__pool02(env, ctx);
27362 break;
27363 case OPC_MXU_D16MUL:
27364 gen_mxu_d16mul(ctx);
27365 break;
27366 case OPC_MXU__POOL03:
27367 decode_opc_mxu__pool03(env, ctx);
27368 break;
27369 case OPC_MXU_D16MAC:
27370 gen_mxu_d16mac(ctx);
27371 break;
27372 case OPC_MXU_D16MACF:
27373 /* TODO: Implement emulation of D16MACF instruction. */
27374 MIPS_INVAL("OPC_MXU_D16MACF");
27375 generate_exception_end(ctx, EXCP_RI);
27376 break;
27377 case OPC_MXU_D16MADL:
27378 /* TODO: Implement emulation of D16MADL instruction. */
27379 MIPS_INVAL("OPC_MXU_D16MADL");
27380 generate_exception_end(ctx, EXCP_RI);
27381 break;
27382 case OPC_MXU_S16MAD:
27383 /* TODO: Implement emulation of S16MAD instruction. */
27384 MIPS_INVAL("OPC_MXU_S16MAD");
27385 generate_exception_end(ctx, EXCP_RI);
27386 break;
27387 case OPC_MXU_Q16ADD:
27388 /* TODO: Implement emulation of Q16ADD instruction. */
27389 MIPS_INVAL("OPC_MXU_Q16ADD");
27390 generate_exception_end(ctx, EXCP_RI);
27391 break;
27392 case OPC_MXU_D16MACE:
27393 /* TODO: Implement emulation of D16MACE instruction. */
27394 MIPS_INVAL("OPC_MXU_D16MACE");
27395 generate_exception_end(ctx, EXCP_RI);
27396 break;
27397 case OPC_MXU__POOL04:
27398 decode_opc_mxu__pool04(env, ctx);
27399 break;
27400 case OPC_MXU__POOL05:
27401 decode_opc_mxu__pool05(env, ctx);
27402 break;
27403 case OPC_MXU__POOL06:
27404 decode_opc_mxu__pool06(env, ctx);
27405 break;
27406 case OPC_MXU__POOL07:
27407 decode_opc_mxu__pool07(env, ctx);
27408 break;
27409 case OPC_MXU__POOL08:
27410 decode_opc_mxu__pool08(env, ctx);
27411 break;
27412 case OPC_MXU__POOL09:
27413 decode_opc_mxu__pool09(env, ctx);
27414 break;
27415 case OPC_MXU__POOL10:
27416 decode_opc_mxu__pool10(env, ctx);
27417 break;
27418 case OPC_MXU__POOL11:
27419 decode_opc_mxu__pool11(env, ctx);
27420 break;
27421 case OPC_MXU_D32ADD:
27422 /* TODO: Implement emulation of D32ADD instruction. */
27423 MIPS_INVAL("OPC_MXU_D32ADD");
27424 generate_exception_end(ctx, EXCP_RI);
27425 break;
27426 case OPC_MXU__POOL12:
27427 decode_opc_mxu__pool12(env, ctx);
27428 break;
27429 case OPC_MXU__POOL13:
27430 decode_opc_mxu__pool13(env, ctx);
27431 break;
27432 case OPC_MXU__POOL14:
27433 decode_opc_mxu__pool14(env, ctx);
27434 break;
27435 case OPC_MXU_Q8ACCE:
27436 /* TODO: Implement emulation of Q8ACCE instruction. */
27437 MIPS_INVAL("OPC_MXU_Q8ACCE");
27438 generate_exception_end(ctx, EXCP_RI);
27439 break;
27440 case OPC_MXU_S8LDD:
27441 gen_mxu_s8ldd(ctx);
27442 break;
27443 case OPC_MXU_S8STD:
27444 /* TODO: Implement emulation of S8STD instruction. */
27445 MIPS_INVAL("OPC_MXU_S8STD");
27446 generate_exception_end(ctx, EXCP_RI);
27447 break;
27448 case OPC_MXU_S8LDI:
27449 /* TODO: Implement emulation of S8LDI instruction. */
27450 MIPS_INVAL("OPC_MXU_S8LDI");
27451 generate_exception_end(ctx, EXCP_RI);
27452 break;
27453 case OPC_MXU_S8SDI:
27454 /* TODO: Implement emulation of S8SDI instruction. */
27455 MIPS_INVAL("OPC_MXU_S8SDI");
27456 generate_exception_end(ctx, EXCP_RI);
27457 break;
27458 case OPC_MXU__POOL15:
27459 decode_opc_mxu__pool15(env, ctx);
27460 break;
27461 case OPC_MXU__POOL16:
27462 decode_opc_mxu__pool16(env, ctx);
27463 break;
27464 case OPC_MXU__POOL17:
27465 decode_opc_mxu__pool17(env, ctx);
27466 break;
27467 case OPC_MXU_S16LDD:
27468 /* TODO: Implement emulation of S16LDD instruction. */
27469 MIPS_INVAL("OPC_MXU_S16LDD");
27470 generate_exception_end(ctx, EXCP_RI);
27471 break;
27472 case OPC_MXU_S16STD:
27473 /* TODO: Implement emulation of S16STD instruction. */
27474 MIPS_INVAL("OPC_MXU_S16STD");
27475 generate_exception_end(ctx, EXCP_RI);
27476 break;
27477 case OPC_MXU_S16LDI:
27478 /* TODO: Implement emulation of S16LDI instruction. */
27479 MIPS_INVAL("OPC_MXU_S16LDI");
27480 generate_exception_end(ctx, EXCP_RI);
27481 break;
27482 case OPC_MXU_S16SDI:
27483 /* TODO: Implement emulation of S16SDI instruction. */
27484 MIPS_INVAL("OPC_MXU_S16SDI");
27485 generate_exception_end(ctx, EXCP_RI);
27486 break;
27487 case OPC_MXU_D32SLL:
27488 /* TODO: Implement emulation of D32SLL instruction. */
27489 MIPS_INVAL("OPC_MXU_D32SLL");
27490 generate_exception_end(ctx, EXCP_RI);
27491 break;
27492 case OPC_MXU_D32SLR:
27493 /* TODO: Implement emulation of D32SLR instruction. */
27494 MIPS_INVAL("OPC_MXU_D32SLR");
27495 generate_exception_end(ctx, EXCP_RI);
27496 break;
27497 case OPC_MXU_D32SARL:
27498 /* TODO: Implement emulation of D32SARL instruction. */
27499 MIPS_INVAL("OPC_MXU_D32SARL");
27500 generate_exception_end(ctx, EXCP_RI);
27501 break;
27502 case OPC_MXU_D32SAR:
27503 /* TODO: Implement emulation of D32SAR instruction. */
27504 MIPS_INVAL("OPC_MXU_D32SAR");
27505 generate_exception_end(ctx, EXCP_RI);
27506 break;
27507 case OPC_MXU_Q16SLL:
27508 /* TODO: Implement emulation of Q16SLL instruction. */
27509 MIPS_INVAL("OPC_MXU_Q16SLL");
27510 generate_exception_end(ctx, EXCP_RI);
27511 break;
27512 case OPC_MXU_Q16SLR:
27513 /* TODO: Implement emulation of Q16SLR instruction. */
27514 MIPS_INVAL("OPC_MXU_Q16SLR");
27515 generate_exception_end(ctx, EXCP_RI);
27516 break;
27517 case OPC_MXU__POOL18:
27518 decode_opc_mxu__pool18(env, ctx);
27519 break;
27520 case OPC_MXU_Q16SAR:
27521 /* TODO: Implement emulation of Q16SAR instruction. */
27522 MIPS_INVAL("OPC_MXU_Q16SAR");
27523 generate_exception_end(ctx, EXCP_RI);
27524 break;
27525 case OPC_MXU__POOL19:
27526 decode_opc_mxu__pool19(env, ctx);
27527 break;
27528 case OPC_MXU__POOL20:
27529 decode_opc_mxu__pool20(env, ctx);
27530 break;
27531 case OPC_MXU__POOL21:
27532 decode_opc_mxu__pool21(env, ctx);
27533 break;
27534 case OPC_MXU_Q16SCOP:
27535 /* TODO: Implement emulation of Q16SCOP instruction. */
27536 MIPS_INVAL("OPC_MXU_Q16SCOP");
27537 generate_exception_end(ctx, EXCP_RI);
27538 break;
27539 case OPC_MXU_Q8MADL:
27540 /* TODO: Implement emulation of Q8MADL instruction. */
27541 MIPS_INVAL("OPC_MXU_Q8MADL");
27542 generate_exception_end(ctx, EXCP_RI);
27543 break;
27544 case OPC_MXU_S32SFL:
27545 /* TODO: Implement emulation of S32SFL instruction. */
27546 MIPS_INVAL("OPC_MXU_S32SFL");
27547 generate_exception_end(ctx, EXCP_RI);
27548 break;
27549 case OPC_MXU_Q8SAD:
27550 /* TODO: Implement emulation of Q8SAD instruction. */
27551 MIPS_INVAL("OPC_MXU_Q8SAD");
27552 generate_exception_end(ctx, EXCP_RI);
27553 break;
27554 default:
27555 MIPS_INVAL("decode_opc_mxu");
27556 generate_exception_end(ctx, EXCP_RI);
27559 gen_set_label(l_exit);
27560 tcg_temp_free(t_mxu_cr);
27564 #endif /* !defined(TARGET_MIPS64) */
27567 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27569 int rs, rt, rd;
27570 uint32_t op1;
27572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27574 rs = (ctx->opcode >> 21) & 0x1f;
27575 rt = (ctx->opcode >> 16) & 0x1f;
27576 rd = (ctx->opcode >> 11) & 0x1f;
27578 op1 = MASK_SPECIAL2(ctx->opcode);
27579 switch (op1) {
27580 case OPC_MADD: /* Multiply and add/sub */
27581 case OPC_MADDU:
27582 case OPC_MSUB:
27583 case OPC_MSUBU:
27584 check_insn(ctx, ISA_MIPS32);
27585 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27586 break;
27587 case OPC_MUL:
27588 gen_arith(ctx, op1, rd, rs, rt);
27589 break;
27590 case OPC_DIV_G_2F:
27591 case OPC_DIVU_G_2F:
27592 case OPC_MULT_G_2F:
27593 case OPC_MULTU_G_2F:
27594 case OPC_MOD_G_2F:
27595 case OPC_MODU_G_2F:
27596 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27597 gen_loongson_integer(ctx, op1, rd, rs, rt);
27598 break;
27599 case OPC_CLO:
27600 case OPC_CLZ:
27601 check_insn(ctx, ISA_MIPS32);
27602 gen_cl(ctx, op1, rd, rs);
27603 break;
27604 case OPC_SDBBP:
27605 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27606 gen_helper_do_semihosting(cpu_env);
27607 } else {
27609 * XXX: not clear which exception should be raised
27610 * when in debug mode...
27612 check_insn(ctx, ISA_MIPS32);
27613 generate_exception_end(ctx, EXCP_DBp);
27615 break;
27616 #if defined(TARGET_MIPS64)
27617 case OPC_DCLO:
27618 case OPC_DCLZ:
27619 check_insn(ctx, ISA_MIPS64);
27620 check_mips_64(ctx);
27621 gen_cl(ctx, op1, rd, rs);
27622 break;
27623 case OPC_DMULT_G_2F:
27624 case OPC_DMULTU_G_2F:
27625 case OPC_DDIV_G_2F:
27626 case OPC_DDIVU_G_2F:
27627 case OPC_DMOD_G_2F:
27628 case OPC_DMODU_G_2F:
27629 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27630 gen_loongson_integer(ctx, op1, rd, rs, rt);
27631 break;
27632 #endif
27633 default: /* Invalid */
27634 MIPS_INVAL("special2_legacy");
27635 generate_exception_end(ctx, EXCP_RI);
27636 break;
27640 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27642 int rs, rt, rd, sa;
27643 uint32_t op1, op2;
27644 int16_t imm;
27646 rs = (ctx->opcode >> 21) & 0x1f;
27647 rt = (ctx->opcode >> 16) & 0x1f;
27648 rd = (ctx->opcode >> 11) & 0x1f;
27649 sa = (ctx->opcode >> 6) & 0x1f;
27650 imm = (int16_t)ctx->opcode >> 7;
27652 op1 = MASK_SPECIAL3(ctx->opcode);
27653 switch (op1) {
27654 case R6_OPC_PREF:
27655 if (rt >= 24) {
27656 /* hint codes 24-31 are reserved and signal RI */
27657 generate_exception_end(ctx, EXCP_RI);
27659 /* Treat as NOP. */
27660 break;
27661 case R6_OPC_CACHE:
27662 check_cp0_enabled(ctx);
27663 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27664 gen_cache_operation(ctx, rt, rs, imm);
27666 break;
27667 case R6_OPC_SC:
27668 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27669 break;
27670 case R6_OPC_LL:
27671 gen_ld(ctx, op1, rt, rs, imm);
27672 break;
27673 case OPC_BSHFL:
27675 if (rd == 0) {
27676 /* Treat as NOP. */
27677 break;
27679 op2 = MASK_BSHFL(ctx->opcode);
27680 switch (op2) {
27681 case OPC_ALIGN:
27682 case OPC_ALIGN_1:
27683 case OPC_ALIGN_2:
27684 case OPC_ALIGN_3:
27685 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27686 break;
27687 case OPC_BITSWAP:
27688 gen_bitswap(ctx, op2, rd, rt);
27689 break;
27692 break;
27693 #ifndef CONFIG_USER_ONLY
27694 case OPC_GINV:
27695 if (unlikely(ctx->gi <= 1)) {
27696 generate_exception_end(ctx, EXCP_RI);
27698 check_cp0_enabled(ctx);
27699 switch ((ctx->opcode >> 6) & 3) {
27700 case 0: /* GINVI */
27701 /* Treat as NOP. */
27702 break;
27703 case 2: /* GINVT */
27704 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27705 break;
27706 default:
27707 generate_exception_end(ctx, EXCP_RI);
27708 break;
27710 break;
27711 #endif
27712 #if defined(TARGET_MIPS64)
27713 case R6_OPC_SCD:
27714 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27715 break;
27716 case R6_OPC_LLD:
27717 gen_ld(ctx, op1, rt, rs, imm);
27718 break;
27719 case OPC_DBSHFL:
27720 check_mips_64(ctx);
27722 if (rd == 0) {
27723 /* Treat as NOP. */
27724 break;
27726 op2 = MASK_DBSHFL(ctx->opcode);
27727 switch (op2) {
27728 case OPC_DALIGN:
27729 case OPC_DALIGN_1:
27730 case OPC_DALIGN_2:
27731 case OPC_DALIGN_3:
27732 case OPC_DALIGN_4:
27733 case OPC_DALIGN_5:
27734 case OPC_DALIGN_6:
27735 case OPC_DALIGN_7:
27736 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27737 break;
27738 case OPC_DBITSWAP:
27739 gen_bitswap(ctx, op2, rd, rt);
27740 break;
27744 break;
27745 #endif
27746 default: /* Invalid */
27747 MIPS_INVAL("special3_r6");
27748 generate_exception_end(ctx, EXCP_RI);
27749 break;
27753 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27755 int rs, rt, rd;
27756 uint32_t op1, op2;
27758 rs = (ctx->opcode >> 21) & 0x1f;
27759 rt = (ctx->opcode >> 16) & 0x1f;
27760 rd = (ctx->opcode >> 11) & 0x1f;
27762 op1 = MASK_SPECIAL3(ctx->opcode);
27763 switch (op1) {
27764 case OPC_DIV_G_2E:
27765 case OPC_DIVU_G_2E:
27766 case OPC_MOD_G_2E:
27767 case OPC_MODU_G_2E:
27768 case OPC_MULT_G_2E:
27769 case OPC_MULTU_G_2E:
27771 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27772 * the same mask and op1.
27774 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27775 op2 = MASK_ADDUH_QB(ctx->opcode);
27776 switch (op2) {
27777 case OPC_ADDUH_QB:
27778 case OPC_ADDUH_R_QB:
27779 case OPC_ADDQH_PH:
27780 case OPC_ADDQH_R_PH:
27781 case OPC_ADDQH_W:
27782 case OPC_ADDQH_R_W:
27783 case OPC_SUBUH_QB:
27784 case OPC_SUBUH_R_QB:
27785 case OPC_SUBQH_PH:
27786 case OPC_SUBQH_R_PH:
27787 case OPC_SUBQH_W:
27788 case OPC_SUBQH_R_W:
27789 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27790 break;
27791 case OPC_MUL_PH:
27792 case OPC_MUL_S_PH:
27793 case OPC_MULQ_S_W:
27794 case OPC_MULQ_RS_W:
27795 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27796 break;
27797 default:
27798 MIPS_INVAL("MASK ADDUH.QB");
27799 generate_exception_end(ctx, EXCP_RI);
27800 break;
27802 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27803 gen_loongson_integer(ctx, op1, rd, rs, rt);
27804 } else {
27805 generate_exception_end(ctx, EXCP_RI);
27807 break;
27808 case OPC_LX_DSP:
27809 op2 = MASK_LX(ctx->opcode);
27810 switch (op2) {
27811 #if defined(TARGET_MIPS64)
27812 case OPC_LDX:
27813 #endif
27814 case OPC_LBUX:
27815 case OPC_LHX:
27816 case OPC_LWX:
27817 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27818 break;
27819 default: /* Invalid */
27820 MIPS_INVAL("MASK LX");
27821 generate_exception_end(ctx, EXCP_RI);
27822 break;
27824 break;
27825 case OPC_ABSQ_S_PH_DSP:
27826 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27827 switch (op2) {
27828 case OPC_ABSQ_S_QB:
27829 case OPC_ABSQ_S_PH:
27830 case OPC_ABSQ_S_W:
27831 case OPC_PRECEQ_W_PHL:
27832 case OPC_PRECEQ_W_PHR:
27833 case OPC_PRECEQU_PH_QBL:
27834 case OPC_PRECEQU_PH_QBR:
27835 case OPC_PRECEQU_PH_QBLA:
27836 case OPC_PRECEQU_PH_QBRA:
27837 case OPC_PRECEU_PH_QBL:
27838 case OPC_PRECEU_PH_QBR:
27839 case OPC_PRECEU_PH_QBLA:
27840 case OPC_PRECEU_PH_QBRA:
27841 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27842 break;
27843 case OPC_BITREV:
27844 case OPC_REPL_QB:
27845 case OPC_REPLV_QB:
27846 case OPC_REPL_PH:
27847 case OPC_REPLV_PH:
27848 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27849 break;
27850 default:
27851 MIPS_INVAL("MASK ABSQ_S.PH");
27852 generate_exception_end(ctx, EXCP_RI);
27853 break;
27855 break;
27856 case OPC_ADDU_QB_DSP:
27857 op2 = MASK_ADDU_QB(ctx->opcode);
27858 switch (op2) {
27859 case OPC_ADDQ_PH:
27860 case OPC_ADDQ_S_PH:
27861 case OPC_ADDQ_S_W:
27862 case OPC_ADDU_QB:
27863 case OPC_ADDU_S_QB:
27864 case OPC_ADDU_PH:
27865 case OPC_ADDU_S_PH:
27866 case OPC_SUBQ_PH:
27867 case OPC_SUBQ_S_PH:
27868 case OPC_SUBQ_S_W:
27869 case OPC_SUBU_QB:
27870 case OPC_SUBU_S_QB:
27871 case OPC_SUBU_PH:
27872 case OPC_SUBU_S_PH:
27873 case OPC_ADDSC:
27874 case OPC_ADDWC:
27875 case OPC_MODSUB:
27876 case OPC_RADDU_W_QB:
27877 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27878 break;
27879 case OPC_MULEU_S_PH_QBL:
27880 case OPC_MULEU_S_PH_QBR:
27881 case OPC_MULQ_RS_PH:
27882 case OPC_MULEQ_S_W_PHL:
27883 case OPC_MULEQ_S_W_PHR:
27884 case OPC_MULQ_S_PH:
27885 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27886 break;
27887 default: /* Invalid */
27888 MIPS_INVAL("MASK ADDU.QB");
27889 generate_exception_end(ctx, EXCP_RI);
27890 break;
27893 break;
27894 case OPC_CMPU_EQ_QB_DSP:
27895 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27896 switch (op2) {
27897 case OPC_PRECR_SRA_PH_W:
27898 case OPC_PRECR_SRA_R_PH_W:
27899 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27900 break;
27901 case OPC_PRECR_QB_PH:
27902 case OPC_PRECRQ_QB_PH:
27903 case OPC_PRECRQ_PH_W:
27904 case OPC_PRECRQ_RS_PH_W:
27905 case OPC_PRECRQU_S_QB_PH:
27906 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27907 break;
27908 case OPC_CMPU_EQ_QB:
27909 case OPC_CMPU_LT_QB:
27910 case OPC_CMPU_LE_QB:
27911 case OPC_CMP_EQ_PH:
27912 case OPC_CMP_LT_PH:
27913 case OPC_CMP_LE_PH:
27914 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27915 break;
27916 case OPC_CMPGU_EQ_QB:
27917 case OPC_CMPGU_LT_QB:
27918 case OPC_CMPGU_LE_QB:
27919 case OPC_CMPGDU_EQ_QB:
27920 case OPC_CMPGDU_LT_QB:
27921 case OPC_CMPGDU_LE_QB:
27922 case OPC_PICK_QB:
27923 case OPC_PICK_PH:
27924 case OPC_PACKRL_PH:
27925 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27926 break;
27927 default: /* Invalid */
27928 MIPS_INVAL("MASK CMPU.EQ.QB");
27929 generate_exception_end(ctx, EXCP_RI);
27930 break;
27932 break;
27933 case OPC_SHLL_QB_DSP:
27934 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27935 break;
27936 case OPC_DPA_W_PH_DSP:
27937 op2 = MASK_DPA_W_PH(ctx->opcode);
27938 switch (op2) {
27939 case OPC_DPAU_H_QBL:
27940 case OPC_DPAU_H_QBR:
27941 case OPC_DPSU_H_QBL:
27942 case OPC_DPSU_H_QBR:
27943 case OPC_DPA_W_PH:
27944 case OPC_DPAX_W_PH:
27945 case OPC_DPAQ_S_W_PH:
27946 case OPC_DPAQX_S_W_PH:
27947 case OPC_DPAQX_SA_W_PH:
27948 case OPC_DPS_W_PH:
27949 case OPC_DPSX_W_PH:
27950 case OPC_DPSQ_S_W_PH:
27951 case OPC_DPSQX_S_W_PH:
27952 case OPC_DPSQX_SA_W_PH:
27953 case OPC_MULSAQ_S_W_PH:
27954 case OPC_DPAQ_SA_L_W:
27955 case OPC_DPSQ_SA_L_W:
27956 case OPC_MAQ_S_W_PHL:
27957 case OPC_MAQ_S_W_PHR:
27958 case OPC_MAQ_SA_W_PHL:
27959 case OPC_MAQ_SA_W_PHR:
27960 case OPC_MULSA_W_PH:
27961 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27962 break;
27963 default: /* Invalid */
27964 MIPS_INVAL("MASK DPAW.PH");
27965 generate_exception_end(ctx, EXCP_RI);
27966 break;
27968 break;
27969 case OPC_INSV_DSP:
27970 op2 = MASK_INSV(ctx->opcode);
27971 switch (op2) {
27972 case OPC_INSV:
27973 check_dsp(ctx);
27975 TCGv t0, t1;
27977 if (rt == 0) {
27978 break;
27981 t0 = tcg_temp_new();
27982 t1 = tcg_temp_new();
27984 gen_load_gpr(t0, rt);
27985 gen_load_gpr(t1, rs);
27987 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27989 tcg_temp_free(t0);
27990 tcg_temp_free(t1);
27991 break;
27993 default: /* Invalid */
27994 MIPS_INVAL("MASK INSV");
27995 generate_exception_end(ctx, EXCP_RI);
27996 break;
27998 break;
27999 case OPC_APPEND_DSP:
28000 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28001 break;
28002 case OPC_EXTR_W_DSP:
28003 op2 = MASK_EXTR_W(ctx->opcode);
28004 switch (op2) {
28005 case OPC_EXTR_W:
28006 case OPC_EXTR_R_W:
28007 case OPC_EXTR_RS_W:
28008 case OPC_EXTR_S_H:
28009 case OPC_EXTRV_S_H:
28010 case OPC_EXTRV_W:
28011 case OPC_EXTRV_R_W:
28012 case OPC_EXTRV_RS_W:
28013 case OPC_EXTP:
28014 case OPC_EXTPV:
28015 case OPC_EXTPDP:
28016 case OPC_EXTPDPV:
28017 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28018 break;
28019 case OPC_RDDSP:
28020 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
28021 break;
28022 case OPC_SHILO:
28023 case OPC_SHILOV:
28024 case OPC_MTHLIP:
28025 case OPC_WRDSP:
28026 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28027 break;
28028 default: /* Invalid */
28029 MIPS_INVAL("MASK EXTR.W");
28030 generate_exception_end(ctx, EXCP_RI);
28031 break;
28033 break;
28034 #if defined(TARGET_MIPS64)
28035 case OPC_DDIV_G_2E:
28036 case OPC_DDIVU_G_2E:
28037 case OPC_DMULT_G_2E:
28038 case OPC_DMULTU_G_2E:
28039 case OPC_DMOD_G_2E:
28040 case OPC_DMODU_G_2E:
28041 check_insn(ctx, INSN_LOONGSON2E);
28042 gen_loongson_integer(ctx, op1, rd, rs, rt);
28043 break;
28044 case OPC_ABSQ_S_QH_DSP:
28045 op2 = MASK_ABSQ_S_QH(ctx->opcode);
28046 switch (op2) {
28047 case OPC_PRECEQ_L_PWL:
28048 case OPC_PRECEQ_L_PWR:
28049 case OPC_PRECEQ_PW_QHL:
28050 case OPC_PRECEQ_PW_QHR:
28051 case OPC_PRECEQ_PW_QHLA:
28052 case OPC_PRECEQ_PW_QHRA:
28053 case OPC_PRECEQU_QH_OBL:
28054 case OPC_PRECEQU_QH_OBR:
28055 case OPC_PRECEQU_QH_OBLA:
28056 case OPC_PRECEQU_QH_OBRA:
28057 case OPC_PRECEU_QH_OBL:
28058 case OPC_PRECEU_QH_OBR:
28059 case OPC_PRECEU_QH_OBLA:
28060 case OPC_PRECEU_QH_OBRA:
28061 case OPC_ABSQ_S_OB:
28062 case OPC_ABSQ_S_PW:
28063 case OPC_ABSQ_S_QH:
28064 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28065 break;
28066 case OPC_REPL_OB:
28067 case OPC_REPL_PW:
28068 case OPC_REPL_QH:
28069 case OPC_REPLV_OB:
28070 case OPC_REPLV_PW:
28071 case OPC_REPLV_QH:
28072 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
28073 break;
28074 default: /* Invalid */
28075 MIPS_INVAL("MASK ABSQ_S.QH");
28076 generate_exception_end(ctx, EXCP_RI);
28077 break;
28079 break;
28080 case OPC_ADDU_OB_DSP:
28081 op2 = MASK_ADDU_OB(ctx->opcode);
28082 switch (op2) {
28083 case OPC_RADDU_L_OB:
28084 case OPC_SUBQ_PW:
28085 case OPC_SUBQ_S_PW:
28086 case OPC_SUBQ_QH:
28087 case OPC_SUBQ_S_QH:
28088 case OPC_SUBU_OB:
28089 case OPC_SUBU_S_OB:
28090 case OPC_SUBU_QH:
28091 case OPC_SUBU_S_QH:
28092 case OPC_SUBUH_OB:
28093 case OPC_SUBUH_R_OB:
28094 case OPC_ADDQ_PW:
28095 case OPC_ADDQ_S_PW:
28096 case OPC_ADDQ_QH:
28097 case OPC_ADDQ_S_QH:
28098 case OPC_ADDU_OB:
28099 case OPC_ADDU_S_OB:
28100 case OPC_ADDU_QH:
28101 case OPC_ADDU_S_QH:
28102 case OPC_ADDUH_OB:
28103 case OPC_ADDUH_R_OB:
28104 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28105 break;
28106 case OPC_MULEQ_S_PW_QHL:
28107 case OPC_MULEQ_S_PW_QHR:
28108 case OPC_MULEU_S_QH_OBL:
28109 case OPC_MULEU_S_QH_OBR:
28110 case OPC_MULQ_RS_QH:
28111 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
28112 break;
28113 default: /* Invalid */
28114 MIPS_INVAL("MASK ADDU.OB");
28115 generate_exception_end(ctx, EXCP_RI);
28116 break;
28118 break;
28119 case OPC_CMPU_EQ_OB_DSP:
28120 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
28121 switch (op2) {
28122 case OPC_PRECR_SRA_QH_PW:
28123 case OPC_PRECR_SRA_R_QH_PW:
28124 /* Return value is rt. */
28125 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
28126 break;
28127 case OPC_PRECR_OB_QH:
28128 case OPC_PRECRQ_OB_QH:
28129 case OPC_PRECRQ_PW_L:
28130 case OPC_PRECRQ_QH_PW:
28131 case OPC_PRECRQ_RS_QH_PW:
28132 case OPC_PRECRQU_S_OB_QH:
28133 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28134 break;
28135 case OPC_CMPU_EQ_OB:
28136 case OPC_CMPU_LT_OB:
28137 case OPC_CMPU_LE_OB:
28138 case OPC_CMP_EQ_QH:
28139 case OPC_CMP_LT_QH:
28140 case OPC_CMP_LE_QH:
28141 case OPC_CMP_EQ_PW:
28142 case OPC_CMP_LT_PW:
28143 case OPC_CMP_LE_PW:
28144 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
28145 break;
28146 case OPC_CMPGDU_EQ_OB:
28147 case OPC_CMPGDU_LT_OB:
28148 case OPC_CMPGDU_LE_OB:
28149 case OPC_CMPGU_EQ_OB:
28150 case OPC_CMPGU_LT_OB:
28151 case OPC_CMPGU_LE_OB:
28152 case OPC_PACKRL_PW:
28153 case OPC_PICK_OB:
28154 case OPC_PICK_PW:
28155 case OPC_PICK_QH:
28156 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
28157 break;
28158 default: /* Invalid */
28159 MIPS_INVAL("MASK CMPU_EQ.OB");
28160 generate_exception_end(ctx, EXCP_RI);
28161 break;
28163 break;
28164 case OPC_DAPPEND_DSP:
28165 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28166 break;
28167 case OPC_DEXTR_W_DSP:
28168 op2 = MASK_DEXTR_W(ctx->opcode);
28169 switch (op2) {
28170 case OPC_DEXTP:
28171 case OPC_DEXTPDP:
28172 case OPC_DEXTPDPV:
28173 case OPC_DEXTPV:
28174 case OPC_DEXTR_L:
28175 case OPC_DEXTR_R_L:
28176 case OPC_DEXTR_RS_L:
28177 case OPC_DEXTR_W:
28178 case OPC_DEXTR_R_W:
28179 case OPC_DEXTR_RS_W:
28180 case OPC_DEXTR_S_H:
28181 case OPC_DEXTRV_L:
28182 case OPC_DEXTRV_R_L:
28183 case OPC_DEXTRV_RS_L:
28184 case OPC_DEXTRV_S_H:
28185 case OPC_DEXTRV_W:
28186 case OPC_DEXTRV_R_W:
28187 case OPC_DEXTRV_RS_W:
28188 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28189 break;
28190 case OPC_DMTHLIP:
28191 case OPC_DSHILO:
28192 case OPC_DSHILOV:
28193 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28194 break;
28195 default: /* Invalid */
28196 MIPS_INVAL("MASK EXTR.W");
28197 generate_exception_end(ctx, EXCP_RI);
28198 break;
28200 break;
28201 case OPC_DPAQ_W_QH_DSP:
28202 op2 = MASK_DPAQ_W_QH(ctx->opcode);
28203 switch (op2) {
28204 case OPC_DPAU_H_OBL:
28205 case OPC_DPAU_H_OBR:
28206 case OPC_DPSU_H_OBL:
28207 case OPC_DPSU_H_OBR:
28208 case OPC_DPA_W_QH:
28209 case OPC_DPAQ_S_W_QH:
28210 case OPC_DPS_W_QH:
28211 case OPC_DPSQ_S_W_QH:
28212 case OPC_MULSAQ_S_W_QH:
28213 case OPC_DPAQ_SA_L_PW:
28214 case OPC_DPSQ_SA_L_PW:
28215 case OPC_MULSAQ_S_L_PW:
28216 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28217 break;
28218 case OPC_MAQ_S_W_QHLL:
28219 case OPC_MAQ_S_W_QHLR:
28220 case OPC_MAQ_S_W_QHRL:
28221 case OPC_MAQ_S_W_QHRR:
28222 case OPC_MAQ_SA_W_QHLL:
28223 case OPC_MAQ_SA_W_QHLR:
28224 case OPC_MAQ_SA_W_QHRL:
28225 case OPC_MAQ_SA_W_QHRR:
28226 case OPC_MAQ_S_L_PWL:
28227 case OPC_MAQ_S_L_PWR:
28228 case OPC_DMADD:
28229 case OPC_DMADDU:
28230 case OPC_DMSUB:
28231 case OPC_DMSUBU:
28232 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28233 break;
28234 default: /* Invalid */
28235 MIPS_INVAL("MASK DPAQ.W.QH");
28236 generate_exception_end(ctx, EXCP_RI);
28237 break;
28239 break;
28240 case OPC_DINSV_DSP:
28241 op2 = MASK_INSV(ctx->opcode);
28242 switch (op2) {
28243 case OPC_DINSV:
28245 TCGv t0, t1;
28247 if (rt == 0) {
28248 break;
28250 check_dsp(ctx);
28252 t0 = tcg_temp_new();
28253 t1 = tcg_temp_new();
28255 gen_load_gpr(t0, rt);
28256 gen_load_gpr(t1, rs);
28258 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
28260 tcg_temp_free(t0);
28261 tcg_temp_free(t1);
28262 break;
28264 default: /* Invalid */
28265 MIPS_INVAL("MASK DINSV");
28266 generate_exception_end(ctx, EXCP_RI);
28267 break;
28269 break;
28270 case OPC_SHLL_OB_DSP:
28271 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
28272 break;
28273 #endif
28274 default: /* Invalid */
28275 MIPS_INVAL("special3_legacy");
28276 generate_exception_end(ctx, EXCP_RI);
28277 break;
28282 #if defined(TARGET_MIPS64)
28284 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
28286 uint32_t opc = MASK_MMI0(ctx->opcode);
28288 switch (opc) {
28289 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
28290 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
28291 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
28292 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
28293 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
28294 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
28295 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
28296 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
28297 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
28298 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
28299 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
28300 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
28301 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
28302 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
28303 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
28304 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
28305 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
28306 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
28307 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
28308 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
28309 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
28310 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
28311 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
28312 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
28313 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
28314 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
28315 break;
28316 default:
28317 MIPS_INVAL("TX79 MMI class MMI0");
28318 generate_exception_end(ctx, EXCP_RI);
28319 break;
28323 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
28325 uint32_t opc = MASK_MMI1(ctx->opcode);
28327 switch (opc) {
28328 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
28329 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
28330 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
28331 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
28332 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
28333 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
28334 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
28335 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
28336 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
28337 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
28338 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
28339 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
28340 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
28341 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
28342 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
28343 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
28344 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
28345 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
28346 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
28347 break;
28348 default:
28349 MIPS_INVAL("TX79 MMI class MMI1");
28350 generate_exception_end(ctx, EXCP_RI);
28351 break;
28355 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
28357 uint32_t opc = MASK_MMI2(ctx->opcode);
28359 switch (opc) {
28360 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
28361 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
28362 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
28363 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
28364 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
28365 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
28366 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
28367 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
28368 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
28369 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
28370 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
28371 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
28372 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
28373 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
28374 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
28375 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
28376 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
28377 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
28378 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
28379 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
28380 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
28381 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
28382 break;
28383 case MMI_OPC_2_PCPYLD:
28384 gen_mmi_pcpyld(ctx);
28385 break;
28386 default:
28387 MIPS_INVAL("TX79 MMI class MMI2");
28388 generate_exception_end(ctx, EXCP_RI);
28389 break;
28393 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
28395 uint32_t opc = MASK_MMI3(ctx->opcode);
28397 switch (opc) {
28398 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
28399 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
28400 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
28401 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
28402 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
28403 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
28404 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
28405 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
28406 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
28407 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
28408 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
28409 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
28410 break;
28411 case MMI_OPC_3_PCPYH:
28412 gen_mmi_pcpyh(ctx);
28413 break;
28414 case MMI_OPC_3_PCPYUD:
28415 gen_mmi_pcpyud(ctx);
28416 break;
28417 default:
28418 MIPS_INVAL("TX79 MMI class MMI3");
28419 generate_exception_end(ctx, EXCP_RI);
28420 break;
28424 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
28426 uint32_t opc = MASK_MMI(ctx->opcode);
28427 int rs = extract32(ctx->opcode, 21, 5);
28428 int rt = extract32(ctx->opcode, 16, 5);
28429 int rd = extract32(ctx->opcode, 11, 5);
28431 switch (opc) {
28432 case MMI_OPC_CLASS_MMI0:
28433 decode_mmi0(env, ctx);
28434 break;
28435 case MMI_OPC_CLASS_MMI1:
28436 decode_mmi1(env, ctx);
28437 break;
28438 case MMI_OPC_CLASS_MMI2:
28439 decode_mmi2(env, ctx);
28440 break;
28441 case MMI_OPC_CLASS_MMI3:
28442 decode_mmi3(env, ctx);
28443 break;
28444 case MMI_OPC_MULT1:
28445 case MMI_OPC_MULTU1:
28446 case MMI_OPC_MADD:
28447 case MMI_OPC_MADDU:
28448 case MMI_OPC_MADD1:
28449 case MMI_OPC_MADDU1:
28450 gen_mul_txx9(ctx, opc, rd, rs, rt);
28451 break;
28452 case MMI_OPC_DIV1:
28453 case MMI_OPC_DIVU1:
28454 gen_div1_tx79(ctx, opc, rs, rt);
28455 break;
28456 case MMI_OPC_MTLO1:
28457 case MMI_OPC_MTHI1:
28458 gen_HILO1_tx79(ctx, opc, rs);
28459 break;
28460 case MMI_OPC_MFLO1:
28461 case MMI_OPC_MFHI1:
28462 gen_HILO1_tx79(ctx, opc, rd);
28463 break;
28464 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28465 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28466 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28467 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28468 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28469 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28470 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28471 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28472 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28473 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
28474 break;
28475 default:
28476 MIPS_INVAL("TX79 MMI class");
28477 generate_exception_end(ctx, EXCP_RI);
28478 break;
28482 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28484 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
28487 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28489 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
28493 * The TX79-specific instruction Store Quadword
28495 * +--------+-------+-------+------------------------+
28496 * | 011111 | base | rt | offset | SQ
28497 * +--------+-------+-------+------------------------+
28498 * 6 5 5 16
28500 * has the same opcode as the Read Hardware Register instruction
28502 * +--------+-------+-------+-------+-------+--------+
28503 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28504 * +--------+-------+-------+-------+-------+--------+
28505 * 6 5 5 5 5 6
28507 * that is required, trapped and emulated by the Linux kernel. However, all
28508 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28509 * offset is odd. Therefore all valid SQ instructions can execute normally.
28510 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28511 * between SQ and RDHWR, as the Linux kernel does.
28513 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28515 int base = extract32(ctx->opcode, 21, 5);
28516 int rt = extract32(ctx->opcode, 16, 5);
28517 int offset = extract32(ctx->opcode, 0, 16);
28519 #ifdef CONFIG_USER_ONLY
28520 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28521 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28523 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28524 int rd = extract32(ctx->opcode, 11, 5);
28526 gen_rdhwr(ctx, rt, rd, 0);
28527 return;
28529 #endif
28531 gen_mmi_sq(ctx, base, rt, offset);
28534 #endif
28536 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28538 int rs, rt, rd, sa;
28539 uint32_t op1, op2;
28540 int16_t imm;
28542 rs = (ctx->opcode >> 21) & 0x1f;
28543 rt = (ctx->opcode >> 16) & 0x1f;
28544 rd = (ctx->opcode >> 11) & 0x1f;
28545 sa = (ctx->opcode >> 6) & 0x1f;
28546 imm = sextract32(ctx->opcode, 7, 9);
28548 op1 = MASK_SPECIAL3(ctx->opcode);
28551 * EVA loads and stores overlap Loongson 2E instructions decoded by
28552 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28553 * EVA is absent.
28555 if (ctx->eva) {
28556 switch (op1) {
28557 case OPC_LWLE:
28558 case OPC_LWRE:
28559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28560 /* fall through */
28561 case OPC_LBUE:
28562 case OPC_LHUE:
28563 case OPC_LBE:
28564 case OPC_LHE:
28565 case OPC_LLE:
28566 case OPC_LWE:
28567 check_cp0_enabled(ctx);
28568 gen_ld(ctx, op1, rt, rs, imm);
28569 return;
28570 case OPC_SWLE:
28571 case OPC_SWRE:
28572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28573 /* fall through */
28574 case OPC_SBE:
28575 case OPC_SHE:
28576 case OPC_SWE:
28577 check_cp0_enabled(ctx);
28578 gen_st(ctx, op1, rt, rs, imm);
28579 return;
28580 case OPC_SCE:
28581 check_cp0_enabled(ctx);
28582 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28583 return;
28584 case OPC_CACHEE:
28585 check_cp0_enabled(ctx);
28586 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28587 gen_cache_operation(ctx, rt, rs, imm);
28589 /* Treat as NOP. */
28590 return;
28591 case OPC_PREFE:
28592 check_cp0_enabled(ctx);
28593 /* Treat as NOP. */
28594 return;
28598 switch (op1) {
28599 case OPC_EXT:
28600 case OPC_INS:
28601 check_insn(ctx, ISA_MIPS32R2);
28602 gen_bitops(ctx, op1, rt, rs, sa, rd);
28603 break;
28604 case OPC_BSHFL:
28605 op2 = MASK_BSHFL(ctx->opcode);
28606 switch (op2) {
28607 case OPC_ALIGN:
28608 case OPC_ALIGN_1:
28609 case OPC_ALIGN_2:
28610 case OPC_ALIGN_3:
28611 case OPC_BITSWAP:
28612 check_insn(ctx, ISA_MIPS32R6);
28613 decode_opc_special3_r6(env, ctx);
28614 break;
28615 default:
28616 check_insn(ctx, ISA_MIPS32R2);
28617 gen_bshfl(ctx, op2, rt, rd);
28618 break;
28620 break;
28621 #if defined(TARGET_MIPS64)
28622 case OPC_DEXTM:
28623 case OPC_DEXTU:
28624 case OPC_DEXT:
28625 case OPC_DINSM:
28626 case OPC_DINSU:
28627 case OPC_DINS:
28628 check_insn(ctx, ISA_MIPS64R2);
28629 check_mips_64(ctx);
28630 gen_bitops(ctx, op1, rt, rs, sa, rd);
28631 break;
28632 case OPC_DBSHFL:
28633 op2 = MASK_DBSHFL(ctx->opcode);
28634 switch (op2) {
28635 case OPC_DALIGN:
28636 case OPC_DALIGN_1:
28637 case OPC_DALIGN_2:
28638 case OPC_DALIGN_3:
28639 case OPC_DALIGN_4:
28640 case OPC_DALIGN_5:
28641 case OPC_DALIGN_6:
28642 case OPC_DALIGN_7:
28643 case OPC_DBITSWAP:
28644 check_insn(ctx, ISA_MIPS32R6);
28645 decode_opc_special3_r6(env, ctx);
28646 break;
28647 default:
28648 check_insn(ctx, ISA_MIPS64R2);
28649 check_mips_64(ctx);
28650 op2 = MASK_DBSHFL(ctx->opcode);
28651 gen_bshfl(ctx, op2, rt, rd);
28652 break;
28654 break;
28655 #endif
28656 case OPC_RDHWR:
28657 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28658 break;
28659 case OPC_FORK:
28660 check_mt(ctx);
28662 TCGv t0 = tcg_temp_new();
28663 TCGv t1 = tcg_temp_new();
28665 gen_load_gpr(t0, rt);
28666 gen_load_gpr(t1, rs);
28667 gen_helper_fork(t0, t1);
28668 tcg_temp_free(t0);
28669 tcg_temp_free(t1);
28671 break;
28672 case OPC_YIELD:
28673 check_mt(ctx);
28675 TCGv t0 = tcg_temp_new();
28677 gen_load_gpr(t0, rs);
28678 gen_helper_yield(t0, cpu_env, t0);
28679 gen_store_gpr(t0, rd);
28680 tcg_temp_free(t0);
28682 break;
28683 default:
28684 if (ctx->insn_flags & ISA_MIPS32R6) {
28685 decode_opc_special3_r6(env, ctx);
28686 } else {
28687 decode_opc_special3_legacy(env, ctx);
28692 /* MIPS SIMD Architecture (MSA) */
28693 static inline int check_msa_access(DisasContext *ctx)
28695 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28696 !(ctx->hflags & MIPS_HFLAG_F64))) {
28697 generate_exception_end(ctx, EXCP_RI);
28698 return 0;
28701 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28702 if (ctx->insn_flags & ASE_MSA) {
28703 generate_exception_end(ctx, EXCP_MSADIS);
28704 return 0;
28705 } else {
28706 generate_exception_end(ctx, EXCP_RI);
28707 return 0;
28710 return 1;
28713 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28715 /* generates tcg ops to check if any element is 0 */
28716 /* Note this function only works with MSA_WRLEN = 128 */
28717 uint64_t eval_zero_or_big = 0;
28718 uint64_t eval_big = 0;
28719 TCGv_i64 t0 = tcg_temp_new_i64();
28720 TCGv_i64 t1 = tcg_temp_new_i64();
28721 switch (df) {
28722 case DF_BYTE:
28723 eval_zero_or_big = 0x0101010101010101ULL;
28724 eval_big = 0x8080808080808080ULL;
28725 break;
28726 case DF_HALF:
28727 eval_zero_or_big = 0x0001000100010001ULL;
28728 eval_big = 0x8000800080008000ULL;
28729 break;
28730 case DF_WORD:
28731 eval_zero_or_big = 0x0000000100000001ULL;
28732 eval_big = 0x8000000080000000ULL;
28733 break;
28734 case DF_DOUBLE:
28735 eval_zero_or_big = 0x0000000000000001ULL;
28736 eval_big = 0x8000000000000000ULL;
28737 break;
28739 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28740 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28741 tcg_gen_andi_i64(t0, t0, eval_big);
28742 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28743 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28744 tcg_gen_andi_i64(t1, t1, eval_big);
28745 tcg_gen_or_i64(t0, t0, t1);
28746 /* if all bits are zero then all elements are not zero */
28747 /* if some bit is non-zero then some element is zero */
28748 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28749 tcg_gen_trunc_i64_tl(tresult, t0);
28750 tcg_temp_free_i64(t0);
28751 tcg_temp_free_i64(t1);
28754 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28756 uint8_t df = (ctx->opcode >> 21) & 0x3;
28757 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28758 int64_t s16 = (int16_t)ctx->opcode;
28760 check_msa_access(ctx);
28762 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28763 generate_exception_end(ctx, EXCP_RI);
28764 return;
28766 switch (op1) {
28767 case OPC_BZ_V:
28768 case OPC_BNZ_V:
28770 TCGv_i64 t0 = tcg_temp_new_i64();
28771 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28772 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28773 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28774 tcg_gen_trunc_i64_tl(bcond, t0);
28775 tcg_temp_free_i64(t0);
28777 break;
28778 case OPC_BZ_B:
28779 case OPC_BZ_H:
28780 case OPC_BZ_W:
28781 case OPC_BZ_D:
28782 gen_check_zero_element(bcond, df, wt);
28783 break;
28784 case OPC_BNZ_B:
28785 case OPC_BNZ_H:
28786 case OPC_BNZ_W:
28787 case OPC_BNZ_D:
28788 gen_check_zero_element(bcond, df, wt);
28789 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28790 break;
28793 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28795 ctx->hflags |= MIPS_HFLAG_BC;
28796 ctx->hflags |= MIPS_HFLAG_BDS32;
28799 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28801 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28802 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28803 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28804 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28806 TCGv_i32 twd = tcg_const_i32(wd);
28807 TCGv_i32 tws = tcg_const_i32(ws);
28808 TCGv_i32 ti8 = tcg_const_i32(i8);
28810 switch (MASK_MSA_I8(ctx->opcode)) {
28811 case OPC_ANDI_B:
28812 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28813 break;
28814 case OPC_ORI_B:
28815 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28816 break;
28817 case OPC_NORI_B:
28818 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28819 break;
28820 case OPC_XORI_B:
28821 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28822 break;
28823 case OPC_BMNZI_B:
28824 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28825 break;
28826 case OPC_BMZI_B:
28827 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28828 break;
28829 case OPC_BSELI_B:
28830 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28831 break;
28832 case OPC_SHF_B:
28833 case OPC_SHF_H:
28834 case OPC_SHF_W:
28836 uint8_t df = (ctx->opcode >> 24) & 0x3;
28837 if (df == DF_DOUBLE) {
28838 generate_exception_end(ctx, EXCP_RI);
28839 } else {
28840 TCGv_i32 tdf = tcg_const_i32(df);
28841 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28842 tcg_temp_free_i32(tdf);
28845 break;
28846 default:
28847 MIPS_INVAL("MSA instruction");
28848 generate_exception_end(ctx, EXCP_RI);
28849 break;
28852 tcg_temp_free_i32(twd);
28853 tcg_temp_free_i32(tws);
28854 tcg_temp_free_i32(ti8);
28857 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28859 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28860 uint8_t df = (ctx->opcode >> 21) & 0x3;
28861 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28862 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28863 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28864 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28866 TCGv_i32 tdf = tcg_const_i32(df);
28867 TCGv_i32 twd = tcg_const_i32(wd);
28868 TCGv_i32 tws = tcg_const_i32(ws);
28869 TCGv_i32 timm = tcg_temp_new_i32();
28870 tcg_gen_movi_i32(timm, u5);
28872 switch (MASK_MSA_I5(ctx->opcode)) {
28873 case OPC_ADDVI_df:
28874 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28875 break;
28876 case OPC_SUBVI_df:
28877 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28878 break;
28879 case OPC_MAXI_S_df:
28880 tcg_gen_movi_i32(timm, s5);
28881 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28882 break;
28883 case OPC_MAXI_U_df:
28884 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28885 break;
28886 case OPC_MINI_S_df:
28887 tcg_gen_movi_i32(timm, s5);
28888 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28889 break;
28890 case OPC_MINI_U_df:
28891 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28892 break;
28893 case OPC_CEQI_df:
28894 tcg_gen_movi_i32(timm, s5);
28895 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28896 break;
28897 case OPC_CLTI_S_df:
28898 tcg_gen_movi_i32(timm, s5);
28899 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28900 break;
28901 case OPC_CLTI_U_df:
28902 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28903 break;
28904 case OPC_CLEI_S_df:
28905 tcg_gen_movi_i32(timm, s5);
28906 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28907 break;
28908 case OPC_CLEI_U_df:
28909 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28910 break;
28911 case OPC_LDI_df:
28913 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28914 tcg_gen_movi_i32(timm, s10);
28915 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28917 break;
28918 default:
28919 MIPS_INVAL("MSA instruction");
28920 generate_exception_end(ctx, EXCP_RI);
28921 break;
28924 tcg_temp_free_i32(tdf);
28925 tcg_temp_free_i32(twd);
28926 tcg_temp_free_i32(tws);
28927 tcg_temp_free_i32(timm);
28930 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28932 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28933 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28934 uint32_t df = 0, m = 0;
28935 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28936 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28938 TCGv_i32 tdf;
28939 TCGv_i32 tm;
28940 TCGv_i32 twd;
28941 TCGv_i32 tws;
28943 if ((dfm & 0x40) == 0x00) {
28944 m = dfm & 0x3f;
28945 df = DF_DOUBLE;
28946 } else if ((dfm & 0x60) == 0x40) {
28947 m = dfm & 0x1f;
28948 df = DF_WORD;
28949 } else if ((dfm & 0x70) == 0x60) {
28950 m = dfm & 0x0f;
28951 df = DF_HALF;
28952 } else if ((dfm & 0x78) == 0x70) {
28953 m = dfm & 0x7;
28954 df = DF_BYTE;
28955 } else {
28956 generate_exception_end(ctx, EXCP_RI);
28957 return;
28960 tdf = tcg_const_i32(df);
28961 tm = tcg_const_i32(m);
28962 twd = tcg_const_i32(wd);
28963 tws = tcg_const_i32(ws);
28965 switch (MASK_MSA_BIT(ctx->opcode)) {
28966 case OPC_SLLI_df:
28967 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28968 break;
28969 case OPC_SRAI_df:
28970 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28971 break;
28972 case OPC_SRLI_df:
28973 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28974 break;
28975 case OPC_BCLRI_df:
28976 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28977 break;
28978 case OPC_BSETI_df:
28979 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28980 break;
28981 case OPC_BNEGI_df:
28982 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28983 break;
28984 case OPC_BINSLI_df:
28985 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28986 break;
28987 case OPC_BINSRI_df:
28988 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28989 break;
28990 case OPC_SAT_S_df:
28991 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28992 break;
28993 case OPC_SAT_U_df:
28994 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28995 break;
28996 case OPC_SRARI_df:
28997 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28998 break;
28999 case OPC_SRLRI_df:
29000 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
29001 break;
29002 default:
29003 MIPS_INVAL("MSA instruction");
29004 generate_exception_end(ctx, EXCP_RI);
29005 break;
29008 tcg_temp_free_i32(tdf);
29009 tcg_temp_free_i32(tm);
29010 tcg_temp_free_i32(twd);
29011 tcg_temp_free_i32(tws);
29014 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
29016 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
29017 uint8_t df = (ctx->opcode >> 21) & 0x3;
29018 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29019 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29020 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29022 TCGv_i32 tdf = tcg_const_i32(df);
29023 TCGv_i32 twd = tcg_const_i32(wd);
29024 TCGv_i32 tws = tcg_const_i32(ws);
29025 TCGv_i32 twt = tcg_const_i32(wt);
29027 switch (MASK_MSA_3R(ctx->opcode)) {
29028 case OPC_BINSL_df:
29029 switch (df) {
29030 case DF_BYTE:
29031 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
29032 break;
29033 case DF_HALF:
29034 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
29035 break;
29036 case DF_WORD:
29037 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
29038 break;
29039 case DF_DOUBLE:
29040 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
29041 break;
29043 break;
29044 case OPC_BINSR_df:
29045 switch (df) {
29046 case DF_BYTE:
29047 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
29048 break;
29049 case DF_HALF:
29050 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
29051 break;
29052 case DF_WORD:
29053 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
29054 break;
29055 case DF_DOUBLE:
29056 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
29057 break;
29059 break;
29060 case OPC_BCLR_df:
29061 switch (df) {
29062 case DF_BYTE:
29063 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
29064 break;
29065 case DF_HALF:
29066 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
29067 break;
29068 case DF_WORD:
29069 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
29070 break;
29071 case DF_DOUBLE:
29072 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
29073 break;
29075 break;
29076 case OPC_BNEG_df:
29077 switch (df) {
29078 case DF_BYTE:
29079 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
29080 break;
29081 case DF_HALF:
29082 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
29083 break;
29084 case DF_WORD:
29085 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
29086 break;
29087 case DF_DOUBLE:
29088 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
29089 break;
29091 break;
29092 case OPC_BSET_df:
29093 switch (df) {
29094 case DF_BYTE:
29095 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
29096 break;
29097 case DF_HALF:
29098 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
29099 break;
29100 case DF_WORD:
29101 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
29102 break;
29103 case DF_DOUBLE:
29104 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
29105 break;
29107 break;
29108 case OPC_ADD_A_df:
29109 switch (df) {
29110 case DF_BYTE:
29111 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
29112 break;
29113 case DF_HALF:
29114 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
29115 break;
29116 case DF_WORD:
29117 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
29118 break;
29119 case DF_DOUBLE:
29120 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
29121 break;
29123 break;
29124 case OPC_ADDS_A_df:
29125 switch (df) {
29126 case DF_BYTE:
29127 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
29128 break;
29129 case DF_HALF:
29130 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
29131 break;
29132 case DF_WORD:
29133 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
29134 break;
29135 case DF_DOUBLE:
29136 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
29137 break;
29139 break;
29140 case OPC_ADDS_S_df:
29141 switch (df) {
29142 case DF_BYTE:
29143 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
29144 break;
29145 case DF_HALF:
29146 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
29147 break;
29148 case DF_WORD:
29149 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
29150 break;
29151 case DF_DOUBLE:
29152 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
29153 break;
29155 break;
29156 case OPC_ADDS_U_df:
29157 switch (df) {
29158 case DF_BYTE:
29159 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
29160 break;
29161 case DF_HALF:
29162 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
29163 break;
29164 case DF_WORD:
29165 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
29166 break;
29167 case DF_DOUBLE:
29168 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
29169 break;
29171 break;
29172 case OPC_ADDV_df:
29173 switch (df) {
29174 case DF_BYTE:
29175 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
29176 break;
29177 case DF_HALF:
29178 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
29179 break;
29180 case DF_WORD:
29181 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
29182 break;
29183 case DF_DOUBLE:
29184 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
29185 break;
29187 break;
29188 case OPC_AVE_S_df:
29189 switch (df) {
29190 case DF_BYTE:
29191 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
29192 break;
29193 case DF_HALF:
29194 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
29195 break;
29196 case DF_WORD:
29197 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
29198 break;
29199 case DF_DOUBLE:
29200 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
29201 break;
29203 break;
29204 case OPC_AVE_U_df:
29205 switch (df) {
29206 case DF_BYTE:
29207 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
29208 break;
29209 case DF_HALF:
29210 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
29211 break;
29212 case DF_WORD:
29213 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
29214 break;
29215 case DF_DOUBLE:
29216 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
29217 break;
29219 break;
29220 case OPC_AVER_S_df:
29221 switch (df) {
29222 case DF_BYTE:
29223 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
29224 break;
29225 case DF_HALF:
29226 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
29227 break;
29228 case DF_WORD:
29229 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
29230 break;
29231 case DF_DOUBLE:
29232 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
29233 break;
29235 break;
29236 case OPC_AVER_U_df:
29237 switch (df) {
29238 case DF_BYTE:
29239 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
29240 break;
29241 case DF_HALF:
29242 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
29243 break;
29244 case DF_WORD:
29245 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
29246 break;
29247 case DF_DOUBLE:
29248 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
29249 break;
29251 break;
29252 case OPC_CEQ_df:
29253 switch (df) {
29254 case DF_BYTE:
29255 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
29256 break;
29257 case DF_HALF:
29258 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
29259 break;
29260 case DF_WORD:
29261 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
29262 break;
29263 case DF_DOUBLE:
29264 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
29265 break;
29267 break;
29268 case OPC_CLE_S_df:
29269 switch (df) {
29270 case DF_BYTE:
29271 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
29272 break;
29273 case DF_HALF:
29274 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
29275 break;
29276 case DF_WORD:
29277 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
29278 break;
29279 case DF_DOUBLE:
29280 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
29281 break;
29283 break;
29284 case OPC_CLE_U_df:
29285 switch (df) {
29286 case DF_BYTE:
29287 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
29288 break;
29289 case DF_HALF:
29290 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
29291 break;
29292 case DF_WORD:
29293 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
29294 break;
29295 case DF_DOUBLE:
29296 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
29297 break;
29299 break;
29300 case OPC_CLT_S_df:
29301 switch (df) {
29302 case DF_BYTE:
29303 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
29304 break;
29305 case DF_HALF:
29306 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
29307 break;
29308 case DF_WORD:
29309 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
29310 break;
29311 case DF_DOUBLE:
29312 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
29313 break;
29315 break;
29316 case OPC_CLT_U_df:
29317 switch (df) {
29318 case DF_BYTE:
29319 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
29320 break;
29321 case DF_HALF:
29322 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
29323 break;
29324 case DF_WORD:
29325 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
29326 break;
29327 case DF_DOUBLE:
29328 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
29329 break;
29331 break;
29332 case OPC_DIV_S_df:
29333 switch (df) {
29334 case DF_BYTE:
29335 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
29336 break;
29337 case DF_HALF:
29338 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
29339 break;
29340 case DF_WORD:
29341 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
29342 break;
29343 case DF_DOUBLE:
29344 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
29345 break;
29347 break;
29348 case OPC_DIV_U_df:
29349 switch (df) {
29350 case DF_BYTE:
29351 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
29352 break;
29353 case DF_HALF:
29354 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
29355 break;
29356 case DF_WORD:
29357 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
29358 break;
29359 case DF_DOUBLE:
29360 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
29361 break;
29363 break;
29364 case OPC_MAX_A_df:
29365 switch (df) {
29366 case DF_BYTE:
29367 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
29368 break;
29369 case DF_HALF:
29370 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
29371 break;
29372 case DF_WORD:
29373 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
29374 break;
29375 case DF_DOUBLE:
29376 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
29377 break;
29379 break;
29380 case OPC_MAX_S_df:
29381 switch (df) {
29382 case DF_BYTE:
29383 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
29384 break;
29385 case DF_HALF:
29386 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
29387 break;
29388 case DF_WORD:
29389 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
29390 break;
29391 case DF_DOUBLE:
29392 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
29393 break;
29395 break;
29396 case OPC_MAX_U_df:
29397 switch (df) {
29398 case DF_BYTE:
29399 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
29400 break;
29401 case DF_HALF:
29402 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
29403 break;
29404 case DF_WORD:
29405 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
29406 break;
29407 case DF_DOUBLE:
29408 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
29409 break;
29411 break;
29412 case OPC_MIN_A_df:
29413 switch (df) {
29414 case DF_BYTE:
29415 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
29416 break;
29417 case DF_HALF:
29418 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
29419 break;
29420 case DF_WORD:
29421 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
29422 break;
29423 case DF_DOUBLE:
29424 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
29425 break;
29427 break;
29428 case OPC_MIN_S_df:
29429 switch (df) {
29430 case DF_BYTE:
29431 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29432 break;
29433 case DF_HALF:
29434 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29435 break;
29436 case DF_WORD:
29437 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29438 break;
29439 case DF_DOUBLE:
29440 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29441 break;
29443 break;
29444 case OPC_MIN_U_df:
29445 switch (df) {
29446 case DF_BYTE:
29447 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29448 break;
29449 case DF_HALF:
29450 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29451 break;
29452 case DF_WORD:
29453 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29454 break;
29455 case DF_DOUBLE:
29456 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29457 break;
29459 break;
29460 case OPC_MOD_S_df:
29461 switch (df) {
29462 case DF_BYTE:
29463 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29464 break;
29465 case DF_HALF:
29466 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29467 break;
29468 case DF_WORD:
29469 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29470 break;
29471 case DF_DOUBLE:
29472 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29473 break;
29475 break;
29476 case OPC_MOD_U_df:
29477 switch (df) {
29478 case DF_BYTE:
29479 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29480 break;
29481 case DF_HALF:
29482 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29483 break;
29484 case DF_WORD:
29485 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29486 break;
29487 case DF_DOUBLE:
29488 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29489 break;
29491 break;
29492 case OPC_MADDV_df:
29493 switch (df) {
29494 case DF_BYTE:
29495 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29496 break;
29497 case DF_HALF:
29498 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29499 break;
29500 case DF_WORD:
29501 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29502 break;
29503 case DF_DOUBLE:
29504 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29505 break;
29507 break;
29508 case OPC_MSUBV_df:
29509 switch (df) {
29510 case DF_BYTE:
29511 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29512 break;
29513 case DF_HALF:
29514 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29515 break;
29516 case DF_WORD:
29517 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29518 break;
29519 case DF_DOUBLE:
29520 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29521 break;
29523 break;
29524 case OPC_ASUB_S_df:
29525 switch (df) {
29526 case DF_BYTE:
29527 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29528 break;
29529 case DF_HALF:
29530 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29531 break;
29532 case DF_WORD:
29533 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29534 break;
29535 case DF_DOUBLE:
29536 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29537 break;
29539 break;
29540 case OPC_ASUB_U_df:
29541 switch (df) {
29542 case DF_BYTE:
29543 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29544 break;
29545 case DF_HALF:
29546 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29547 break;
29548 case DF_WORD:
29549 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29550 break;
29551 case DF_DOUBLE:
29552 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29553 break;
29555 break;
29556 case OPC_ILVEV_df:
29557 switch (df) {
29558 case DF_BYTE:
29559 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29560 break;
29561 case DF_HALF:
29562 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29563 break;
29564 case DF_WORD:
29565 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29566 break;
29567 case DF_DOUBLE:
29568 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29569 break;
29571 break;
29572 case OPC_ILVOD_df:
29573 switch (df) {
29574 case DF_BYTE:
29575 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29576 break;
29577 case DF_HALF:
29578 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29579 break;
29580 case DF_WORD:
29581 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29582 break;
29583 case DF_DOUBLE:
29584 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29585 break;
29587 break;
29588 case OPC_ILVL_df:
29589 switch (df) {
29590 case DF_BYTE:
29591 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29592 break;
29593 case DF_HALF:
29594 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29595 break;
29596 case DF_WORD:
29597 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29598 break;
29599 case DF_DOUBLE:
29600 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29601 break;
29603 break;
29604 case OPC_ILVR_df:
29605 switch (df) {
29606 case DF_BYTE:
29607 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29608 break;
29609 case DF_HALF:
29610 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29611 break;
29612 case DF_WORD:
29613 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29614 break;
29615 case DF_DOUBLE:
29616 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29617 break;
29619 break;
29620 case OPC_PCKEV_df:
29621 switch (df) {
29622 case DF_BYTE:
29623 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29624 break;
29625 case DF_HALF:
29626 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29627 break;
29628 case DF_WORD:
29629 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29630 break;
29631 case DF_DOUBLE:
29632 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29633 break;
29635 break;
29636 case OPC_PCKOD_df:
29637 switch (df) {
29638 case DF_BYTE:
29639 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29640 break;
29641 case DF_HALF:
29642 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29643 break;
29644 case DF_WORD:
29645 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29646 break;
29647 case DF_DOUBLE:
29648 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29649 break;
29651 break;
29652 case OPC_SLL_df:
29653 switch (df) {
29654 case DF_BYTE:
29655 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29656 break;
29657 case DF_HALF:
29658 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29659 break;
29660 case DF_WORD:
29661 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29662 break;
29663 case DF_DOUBLE:
29664 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29665 break;
29667 break;
29668 case OPC_SRA_df:
29669 switch (df) {
29670 case DF_BYTE:
29671 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29672 break;
29673 case DF_HALF:
29674 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29675 break;
29676 case DF_WORD:
29677 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29678 break;
29679 case DF_DOUBLE:
29680 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29681 break;
29683 break;
29684 case OPC_SRAR_df:
29685 switch (df) {
29686 case DF_BYTE:
29687 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29688 break;
29689 case DF_HALF:
29690 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29691 break;
29692 case DF_WORD:
29693 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29694 break;
29695 case DF_DOUBLE:
29696 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29697 break;
29699 break;
29700 case OPC_SRL_df:
29701 switch (df) {
29702 case DF_BYTE:
29703 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29704 break;
29705 case DF_HALF:
29706 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29707 break;
29708 case DF_WORD:
29709 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29710 break;
29711 case DF_DOUBLE:
29712 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29713 break;
29715 break;
29716 case OPC_SRLR_df:
29717 switch (df) {
29718 case DF_BYTE:
29719 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29720 break;
29721 case DF_HALF:
29722 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29723 break;
29724 case DF_WORD:
29725 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29726 break;
29727 case DF_DOUBLE:
29728 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29729 break;
29731 break;
29732 case OPC_SUBS_S_df:
29733 switch (df) {
29734 case DF_BYTE:
29735 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29736 break;
29737 case DF_HALF:
29738 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29739 break;
29740 case DF_WORD:
29741 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29742 break;
29743 case DF_DOUBLE:
29744 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29745 break;
29747 break;
29748 case OPC_MULV_df:
29749 switch (df) {
29750 case DF_BYTE:
29751 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29752 break;
29753 case DF_HALF:
29754 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29755 break;
29756 case DF_WORD:
29757 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29758 break;
29759 case DF_DOUBLE:
29760 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29761 break;
29763 break;
29764 case OPC_SLD_df:
29765 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29766 break;
29767 case OPC_VSHF_df:
29768 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29769 break;
29770 case OPC_SUBV_df:
29771 switch (df) {
29772 case DF_BYTE:
29773 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29774 break;
29775 case DF_HALF:
29776 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29777 break;
29778 case DF_WORD:
29779 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29780 break;
29781 case DF_DOUBLE:
29782 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29783 break;
29785 break;
29786 case OPC_SUBS_U_df:
29787 switch (df) {
29788 case DF_BYTE:
29789 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29790 break;
29791 case DF_HALF:
29792 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29793 break;
29794 case DF_WORD:
29795 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29796 break;
29797 case DF_DOUBLE:
29798 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29799 break;
29801 break;
29802 case OPC_SPLAT_df:
29803 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29804 break;
29805 case OPC_SUBSUS_U_df:
29806 switch (df) {
29807 case DF_BYTE:
29808 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29809 break;
29810 case DF_HALF:
29811 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29812 break;
29813 case DF_WORD:
29814 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29815 break;
29816 case DF_DOUBLE:
29817 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29818 break;
29820 break;
29821 case OPC_SUBSUU_S_df:
29822 switch (df) {
29823 case DF_BYTE:
29824 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29825 break;
29826 case DF_HALF:
29827 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29828 break;
29829 case DF_WORD:
29830 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29831 break;
29832 case DF_DOUBLE:
29833 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29834 break;
29836 break;
29838 case OPC_DOTP_S_df:
29839 case OPC_DOTP_U_df:
29840 case OPC_DPADD_S_df:
29841 case OPC_DPADD_U_df:
29842 case OPC_DPSUB_S_df:
29843 case OPC_HADD_S_df:
29844 case OPC_DPSUB_U_df:
29845 case OPC_HADD_U_df:
29846 case OPC_HSUB_S_df:
29847 case OPC_HSUB_U_df:
29848 if (df == DF_BYTE) {
29849 generate_exception_end(ctx, EXCP_RI);
29850 break;
29852 switch (MASK_MSA_3R(ctx->opcode)) {
29853 case OPC_HADD_S_df:
29854 switch (df) {
29855 case DF_HALF:
29856 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29857 break;
29858 case DF_WORD:
29859 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29860 break;
29861 case DF_DOUBLE:
29862 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29863 break;
29865 break;
29866 case OPC_HADD_U_df:
29867 switch (df) {
29868 case DF_HALF:
29869 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29870 break;
29871 case DF_WORD:
29872 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29873 break;
29874 case DF_DOUBLE:
29875 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29876 break;
29878 break;
29879 case OPC_HSUB_S_df:
29880 switch (df) {
29881 case DF_HALF:
29882 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29883 break;
29884 case DF_WORD:
29885 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29886 break;
29887 case DF_DOUBLE:
29888 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29889 break;
29891 break;
29892 case OPC_HSUB_U_df:
29893 switch (df) {
29894 case DF_HALF:
29895 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29896 break;
29897 case DF_WORD:
29898 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29899 break;
29900 case DF_DOUBLE:
29901 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29902 break;
29904 break;
29905 case OPC_DOTP_S_df:
29906 switch (df) {
29907 case DF_HALF:
29908 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29909 break;
29910 case DF_WORD:
29911 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29912 break;
29913 case DF_DOUBLE:
29914 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29915 break;
29917 break;
29918 case OPC_DOTP_U_df:
29919 switch (df) {
29920 case DF_HALF:
29921 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29922 break;
29923 case DF_WORD:
29924 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29925 break;
29926 case DF_DOUBLE:
29927 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29928 break;
29930 break;
29931 case OPC_DPADD_S_df:
29932 switch (df) {
29933 case DF_HALF:
29934 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29935 break;
29936 case DF_WORD:
29937 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29938 break;
29939 case DF_DOUBLE:
29940 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29941 break;
29943 break;
29944 case OPC_DPADD_U_df:
29945 switch (df) {
29946 case DF_HALF:
29947 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29948 break;
29949 case DF_WORD:
29950 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29951 break;
29952 case DF_DOUBLE:
29953 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29954 break;
29956 break;
29957 case OPC_DPSUB_S_df:
29958 switch (df) {
29959 case DF_HALF:
29960 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29961 break;
29962 case DF_WORD:
29963 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29964 break;
29965 case DF_DOUBLE:
29966 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29967 break;
29969 break;
29970 case OPC_DPSUB_U_df:
29971 switch (df) {
29972 case DF_HALF:
29973 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29974 break;
29975 case DF_WORD:
29976 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29977 break;
29978 case DF_DOUBLE:
29979 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29980 break;
29982 break;
29984 break;
29985 default:
29986 MIPS_INVAL("MSA instruction");
29987 generate_exception_end(ctx, EXCP_RI);
29988 break;
29990 tcg_temp_free_i32(twd);
29991 tcg_temp_free_i32(tws);
29992 tcg_temp_free_i32(twt);
29993 tcg_temp_free_i32(tdf);
29996 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29998 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29999 uint8_t source = (ctx->opcode >> 11) & 0x1f;
30000 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
30001 TCGv telm = tcg_temp_new();
30002 TCGv_i32 tsr = tcg_const_i32(source);
30003 TCGv_i32 tdt = tcg_const_i32(dest);
30005 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
30006 case OPC_CTCMSA:
30007 gen_load_gpr(telm, source);
30008 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
30009 break;
30010 case OPC_CFCMSA:
30011 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
30012 gen_store_gpr(telm, dest);
30013 break;
30014 case OPC_MOVE_V:
30015 gen_helper_msa_move_v(cpu_env, tdt, tsr);
30016 break;
30017 default:
30018 MIPS_INVAL("MSA instruction");
30019 generate_exception_end(ctx, EXCP_RI);
30020 break;
30023 tcg_temp_free(telm);
30024 tcg_temp_free_i32(tdt);
30025 tcg_temp_free_i32(tsr);
30028 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
30029 uint32_t n)
30031 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30032 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30033 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30035 TCGv_i32 tws = tcg_const_i32(ws);
30036 TCGv_i32 twd = tcg_const_i32(wd);
30037 TCGv_i32 tn = tcg_const_i32(n);
30038 TCGv_i32 tdf = tcg_const_i32(df);
30040 switch (MASK_MSA_ELM(ctx->opcode)) {
30041 case OPC_SLDI_df:
30042 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
30043 break;
30044 case OPC_SPLATI_df:
30045 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
30046 break;
30047 case OPC_INSVE_df:
30048 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
30049 break;
30050 case OPC_COPY_S_df:
30051 case OPC_COPY_U_df:
30052 case OPC_INSERT_df:
30053 #if !defined(TARGET_MIPS64)
30054 /* Double format valid only for MIPS64 */
30055 if (df == DF_DOUBLE) {
30056 generate_exception_end(ctx, EXCP_RI);
30057 break;
30059 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
30060 (df == DF_WORD)) {
30061 generate_exception_end(ctx, EXCP_RI);
30062 break;
30064 #endif
30065 switch (MASK_MSA_ELM(ctx->opcode)) {
30066 case OPC_COPY_S_df:
30067 if (likely(wd != 0)) {
30068 switch (df) {
30069 case DF_BYTE:
30070 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
30071 break;
30072 case DF_HALF:
30073 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
30074 break;
30075 case DF_WORD:
30076 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
30077 break;
30078 #if defined(TARGET_MIPS64)
30079 case DF_DOUBLE:
30080 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
30081 break;
30082 #endif
30083 default:
30084 assert(0);
30087 break;
30088 case OPC_COPY_U_df:
30089 if (likely(wd != 0)) {
30090 switch (df) {
30091 case DF_BYTE:
30092 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
30093 break;
30094 case DF_HALF:
30095 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
30096 break;
30097 #if defined(TARGET_MIPS64)
30098 case DF_WORD:
30099 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
30100 break;
30101 #endif
30102 default:
30103 assert(0);
30106 break;
30107 case OPC_INSERT_df:
30108 switch (df) {
30109 case DF_BYTE:
30110 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
30111 break;
30112 case DF_HALF:
30113 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
30114 break;
30115 case DF_WORD:
30116 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
30117 break;
30118 #if defined(TARGET_MIPS64)
30119 case DF_DOUBLE:
30120 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
30121 break;
30122 #endif
30123 default:
30124 assert(0);
30126 break;
30128 break;
30129 default:
30130 MIPS_INVAL("MSA instruction");
30131 generate_exception_end(ctx, EXCP_RI);
30133 tcg_temp_free_i32(twd);
30134 tcg_temp_free_i32(tws);
30135 tcg_temp_free_i32(tn);
30136 tcg_temp_free_i32(tdf);
30139 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
30141 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
30142 uint32_t df = 0, n = 0;
30144 if ((dfn & 0x30) == 0x00) {
30145 n = dfn & 0x0f;
30146 df = DF_BYTE;
30147 } else if ((dfn & 0x38) == 0x20) {
30148 n = dfn & 0x07;
30149 df = DF_HALF;
30150 } else if ((dfn & 0x3c) == 0x30) {
30151 n = dfn & 0x03;
30152 df = DF_WORD;
30153 } else if ((dfn & 0x3e) == 0x38) {
30154 n = dfn & 0x01;
30155 df = DF_DOUBLE;
30156 } else if (dfn == 0x3E) {
30157 /* CTCMSA, CFCMSA, MOVE.V */
30158 gen_msa_elm_3e(env, ctx);
30159 return;
30160 } else {
30161 generate_exception_end(ctx, EXCP_RI);
30162 return;
30165 gen_msa_elm_df(env, ctx, df, n);
30168 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
30170 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30171 uint8_t df = (ctx->opcode >> 21) & 0x1;
30172 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30173 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30174 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30176 TCGv_i32 twd = tcg_const_i32(wd);
30177 TCGv_i32 tws = tcg_const_i32(ws);
30178 TCGv_i32 twt = tcg_const_i32(wt);
30179 TCGv_i32 tdf = tcg_temp_new_i32();
30181 /* adjust df value for floating-point instruction */
30182 tcg_gen_movi_i32(tdf, df + 2);
30184 switch (MASK_MSA_3RF(ctx->opcode)) {
30185 case OPC_FCAF_df:
30186 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
30187 break;
30188 case OPC_FADD_df:
30189 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
30190 break;
30191 case OPC_FCUN_df:
30192 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
30193 break;
30194 case OPC_FSUB_df:
30195 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
30196 break;
30197 case OPC_FCOR_df:
30198 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
30199 break;
30200 case OPC_FCEQ_df:
30201 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
30202 break;
30203 case OPC_FMUL_df:
30204 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
30205 break;
30206 case OPC_FCUNE_df:
30207 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
30208 break;
30209 case OPC_FCUEQ_df:
30210 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
30211 break;
30212 case OPC_FDIV_df:
30213 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
30214 break;
30215 case OPC_FCNE_df:
30216 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
30217 break;
30218 case OPC_FCLT_df:
30219 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
30220 break;
30221 case OPC_FMADD_df:
30222 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
30223 break;
30224 case OPC_MUL_Q_df:
30225 tcg_gen_movi_i32(tdf, df + 1);
30226 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
30227 break;
30228 case OPC_FCULT_df:
30229 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
30230 break;
30231 case OPC_FMSUB_df:
30232 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
30233 break;
30234 case OPC_MADD_Q_df:
30235 tcg_gen_movi_i32(tdf, df + 1);
30236 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
30237 break;
30238 case OPC_FCLE_df:
30239 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
30240 break;
30241 case OPC_MSUB_Q_df:
30242 tcg_gen_movi_i32(tdf, df + 1);
30243 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
30244 break;
30245 case OPC_FCULE_df:
30246 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
30247 break;
30248 case OPC_FEXP2_df:
30249 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
30250 break;
30251 case OPC_FSAF_df:
30252 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
30253 break;
30254 case OPC_FEXDO_df:
30255 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
30256 break;
30257 case OPC_FSUN_df:
30258 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
30259 break;
30260 case OPC_FSOR_df:
30261 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
30262 break;
30263 case OPC_FSEQ_df:
30264 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
30265 break;
30266 case OPC_FTQ_df:
30267 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
30268 break;
30269 case OPC_FSUNE_df:
30270 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
30271 break;
30272 case OPC_FSUEQ_df:
30273 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
30274 break;
30275 case OPC_FSNE_df:
30276 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
30277 break;
30278 case OPC_FSLT_df:
30279 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
30280 break;
30281 case OPC_FMIN_df:
30282 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
30283 break;
30284 case OPC_MULR_Q_df:
30285 tcg_gen_movi_i32(tdf, df + 1);
30286 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
30287 break;
30288 case OPC_FSULT_df:
30289 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
30290 break;
30291 case OPC_FMIN_A_df:
30292 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
30293 break;
30294 case OPC_MADDR_Q_df:
30295 tcg_gen_movi_i32(tdf, df + 1);
30296 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
30297 break;
30298 case OPC_FSLE_df:
30299 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
30300 break;
30301 case OPC_FMAX_df:
30302 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
30303 break;
30304 case OPC_MSUBR_Q_df:
30305 tcg_gen_movi_i32(tdf, df + 1);
30306 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
30307 break;
30308 case OPC_FSULE_df:
30309 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
30310 break;
30311 case OPC_FMAX_A_df:
30312 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
30313 break;
30314 default:
30315 MIPS_INVAL("MSA instruction");
30316 generate_exception_end(ctx, EXCP_RI);
30317 break;
30320 tcg_temp_free_i32(twd);
30321 tcg_temp_free_i32(tws);
30322 tcg_temp_free_i32(twt);
30323 tcg_temp_free_i32(tdf);
30326 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
30328 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30329 (op & (0x7 << 18)))
30330 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30331 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30332 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30333 uint8_t df = (ctx->opcode >> 16) & 0x3;
30334 TCGv_i32 twd = tcg_const_i32(wd);
30335 TCGv_i32 tws = tcg_const_i32(ws);
30336 TCGv_i32 twt = tcg_const_i32(wt);
30337 TCGv_i32 tdf = tcg_const_i32(df);
30339 switch (MASK_MSA_2R(ctx->opcode)) {
30340 case OPC_FILL_df:
30341 #if !defined(TARGET_MIPS64)
30342 /* Double format valid only for MIPS64 */
30343 if (df == DF_DOUBLE) {
30344 generate_exception_end(ctx, EXCP_RI);
30345 break;
30347 #endif
30348 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
30349 break;
30350 case OPC_NLOC_df:
30351 switch (df) {
30352 case DF_BYTE:
30353 gen_helper_msa_nloc_b(cpu_env, twd, tws);
30354 break;
30355 case DF_HALF:
30356 gen_helper_msa_nloc_h(cpu_env, twd, tws);
30357 break;
30358 case DF_WORD:
30359 gen_helper_msa_nloc_w(cpu_env, twd, tws);
30360 break;
30361 case DF_DOUBLE:
30362 gen_helper_msa_nloc_d(cpu_env, twd, tws);
30363 break;
30365 break;
30366 case OPC_NLZC_df:
30367 switch (df) {
30368 case DF_BYTE:
30369 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
30370 break;
30371 case DF_HALF:
30372 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
30373 break;
30374 case DF_WORD:
30375 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
30376 break;
30377 case DF_DOUBLE:
30378 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
30379 break;
30381 break;
30382 case OPC_PCNT_df:
30383 switch (df) {
30384 case DF_BYTE:
30385 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
30386 break;
30387 case DF_HALF:
30388 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
30389 break;
30390 case DF_WORD:
30391 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
30392 break;
30393 case DF_DOUBLE:
30394 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
30395 break;
30397 break;
30398 default:
30399 MIPS_INVAL("MSA instruction");
30400 generate_exception_end(ctx, EXCP_RI);
30401 break;
30404 tcg_temp_free_i32(twd);
30405 tcg_temp_free_i32(tws);
30406 tcg_temp_free_i32(twt);
30407 tcg_temp_free_i32(tdf);
30410 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
30412 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30413 (op & (0xf << 17)))
30414 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30415 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30416 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30417 uint8_t df = (ctx->opcode >> 16) & 0x1;
30418 TCGv_i32 twd = tcg_const_i32(wd);
30419 TCGv_i32 tws = tcg_const_i32(ws);
30420 TCGv_i32 twt = tcg_const_i32(wt);
30421 /* adjust df value for floating-point instruction */
30422 TCGv_i32 tdf = tcg_const_i32(df + 2);
30424 switch (MASK_MSA_2RF(ctx->opcode)) {
30425 case OPC_FCLASS_df:
30426 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
30427 break;
30428 case OPC_FTRUNC_S_df:
30429 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
30430 break;
30431 case OPC_FTRUNC_U_df:
30432 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30433 break;
30434 case OPC_FSQRT_df:
30435 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30436 break;
30437 case OPC_FRSQRT_df:
30438 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30439 break;
30440 case OPC_FRCP_df:
30441 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30442 break;
30443 case OPC_FRINT_df:
30444 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30445 break;
30446 case OPC_FLOG2_df:
30447 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30448 break;
30449 case OPC_FEXUPL_df:
30450 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30451 break;
30452 case OPC_FEXUPR_df:
30453 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30454 break;
30455 case OPC_FFQL_df:
30456 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30457 break;
30458 case OPC_FFQR_df:
30459 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30460 break;
30461 case OPC_FTINT_S_df:
30462 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30463 break;
30464 case OPC_FTINT_U_df:
30465 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30466 break;
30467 case OPC_FFINT_S_df:
30468 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30469 break;
30470 case OPC_FFINT_U_df:
30471 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30472 break;
30475 tcg_temp_free_i32(twd);
30476 tcg_temp_free_i32(tws);
30477 tcg_temp_free_i32(twt);
30478 tcg_temp_free_i32(tdf);
30481 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30483 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30484 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30485 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30486 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30487 TCGv_i32 twd = tcg_const_i32(wd);
30488 TCGv_i32 tws = tcg_const_i32(ws);
30489 TCGv_i32 twt = tcg_const_i32(wt);
30491 switch (MASK_MSA_VEC(ctx->opcode)) {
30492 case OPC_AND_V:
30493 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30494 break;
30495 case OPC_OR_V:
30496 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30497 break;
30498 case OPC_NOR_V:
30499 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30500 break;
30501 case OPC_XOR_V:
30502 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30503 break;
30504 case OPC_BMNZ_V:
30505 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30506 break;
30507 case OPC_BMZ_V:
30508 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30509 break;
30510 case OPC_BSEL_V:
30511 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30512 break;
30513 default:
30514 MIPS_INVAL("MSA instruction");
30515 generate_exception_end(ctx, EXCP_RI);
30516 break;
30519 tcg_temp_free_i32(twd);
30520 tcg_temp_free_i32(tws);
30521 tcg_temp_free_i32(twt);
30524 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30526 switch (MASK_MSA_VEC(ctx->opcode)) {
30527 case OPC_AND_V:
30528 case OPC_OR_V:
30529 case OPC_NOR_V:
30530 case OPC_XOR_V:
30531 case OPC_BMNZ_V:
30532 case OPC_BMZ_V:
30533 case OPC_BSEL_V:
30534 gen_msa_vec_v(env, ctx);
30535 break;
30536 case OPC_MSA_2R:
30537 gen_msa_2r(env, ctx);
30538 break;
30539 case OPC_MSA_2RF:
30540 gen_msa_2rf(env, ctx);
30541 break;
30542 default:
30543 MIPS_INVAL("MSA instruction");
30544 generate_exception_end(ctx, EXCP_RI);
30545 break;
30549 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30551 uint32_t opcode = ctx->opcode;
30552 check_insn(ctx, ASE_MSA);
30553 check_msa_access(ctx);
30555 switch (MASK_MSA_MINOR(opcode)) {
30556 case OPC_MSA_I8_00:
30557 case OPC_MSA_I8_01:
30558 case OPC_MSA_I8_02:
30559 gen_msa_i8(env, ctx);
30560 break;
30561 case OPC_MSA_I5_06:
30562 case OPC_MSA_I5_07:
30563 gen_msa_i5(env, ctx);
30564 break;
30565 case OPC_MSA_BIT_09:
30566 case OPC_MSA_BIT_0A:
30567 gen_msa_bit(env, ctx);
30568 break;
30569 case OPC_MSA_3R_0D:
30570 case OPC_MSA_3R_0E:
30571 case OPC_MSA_3R_0F:
30572 case OPC_MSA_3R_10:
30573 case OPC_MSA_3R_11:
30574 case OPC_MSA_3R_12:
30575 case OPC_MSA_3R_13:
30576 case OPC_MSA_3R_14:
30577 case OPC_MSA_3R_15:
30578 gen_msa_3r(env, ctx);
30579 break;
30580 case OPC_MSA_ELM:
30581 gen_msa_elm(env, ctx);
30582 break;
30583 case OPC_MSA_3RF_1A:
30584 case OPC_MSA_3RF_1B:
30585 case OPC_MSA_3RF_1C:
30586 gen_msa_3rf(env, ctx);
30587 break;
30588 case OPC_MSA_VEC:
30589 gen_msa_vec(env, ctx);
30590 break;
30591 case OPC_LD_B:
30592 case OPC_LD_H:
30593 case OPC_LD_W:
30594 case OPC_LD_D:
30595 case OPC_ST_B:
30596 case OPC_ST_H:
30597 case OPC_ST_W:
30598 case OPC_ST_D:
30600 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30601 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30602 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30603 uint8_t df = (ctx->opcode >> 0) & 0x3;
30605 TCGv_i32 twd = tcg_const_i32(wd);
30606 TCGv taddr = tcg_temp_new();
30607 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30609 switch (MASK_MSA_MINOR(opcode)) {
30610 case OPC_LD_B:
30611 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30612 break;
30613 case OPC_LD_H:
30614 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30615 break;
30616 case OPC_LD_W:
30617 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30618 break;
30619 case OPC_LD_D:
30620 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30621 break;
30622 case OPC_ST_B:
30623 gen_helper_msa_st_b(cpu_env, twd, taddr);
30624 break;
30625 case OPC_ST_H:
30626 gen_helper_msa_st_h(cpu_env, twd, taddr);
30627 break;
30628 case OPC_ST_W:
30629 gen_helper_msa_st_w(cpu_env, twd, taddr);
30630 break;
30631 case OPC_ST_D:
30632 gen_helper_msa_st_d(cpu_env, twd, taddr);
30633 break;
30636 tcg_temp_free_i32(twd);
30637 tcg_temp_free(taddr);
30639 break;
30640 default:
30641 MIPS_INVAL("MSA instruction");
30642 generate_exception_end(ctx, EXCP_RI);
30643 break;
30648 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30650 int32_t offset;
30651 int rs, rt, rd, sa;
30652 uint32_t op, op1;
30653 int16_t imm;
30655 /* make sure instructions are on a word boundary */
30656 if (ctx->base.pc_next & 0x3) {
30657 env->CP0_BadVAddr = ctx->base.pc_next;
30658 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30659 return;
30662 /* Handle blikely not taken case */
30663 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30664 TCGLabel *l1 = gen_new_label();
30666 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30667 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30668 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30669 gen_set_label(l1);
30672 op = MASK_OP_MAJOR(ctx->opcode);
30673 rs = (ctx->opcode >> 21) & 0x1f;
30674 rt = (ctx->opcode >> 16) & 0x1f;
30675 rd = (ctx->opcode >> 11) & 0x1f;
30676 sa = (ctx->opcode >> 6) & 0x1f;
30677 imm = (int16_t)ctx->opcode;
30678 switch (op) {
30679 case OPC_SPECIAL:
30680 decode_opc_special(env, ctx);
30681 break;
30682 case OPC_SPECIAL2:
30683 #if defined(TARGET_MIPS64)
30684 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30685 decode_mmi(env, ctx);
30686 #else
30687 if (ctx->insn_flags & ASE_MXU) {
30688 decode_opc_mxu(env, ctx);
30689 #endif
30690 } else {
30691 decode_opc_special2_legacy(env, ctx);
30693 break;
30694 case OPC_SPECIAL3:
30695 #if defined(TARGET_MIPS64)
30696 if (ctx->insn_flags & INSN_R5900) {
30697 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30698 } else {
30699 decode_opc_special3(env, ctx);
30701 #else
30702 decode_opc_special3(env, ctx);
30703 #endif
30704 break;
30705 case OPC_REGIMM:
30706 op1 = MASK_REGIMM(ctx->opcode);
30707 switch (op1) {
30708 case OPC_BLTZL: /* REGIMM branches */
30709 case OPC_BGEZL:
30710 case OPC_BLTZALL:
30711 case OPC_BGEZALL:
30712 check_insn(ctx, ISA_MIPS2);
30713 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30714 /* Fallthrough */
30715 case OPC_BLTZ:
30716 case OPC_BGEZ:
30717 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30718 break;
30719 case OPC_BLTZAL:
30720 case OPC_BGEZAL:
30721 if (ctx->insn_flags & ISA_MIPS32R6) {
30722 if (rs == 0) {
30723 /* OPC_NAL, OPC_BAL */
30724 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30725 } else {
30726 generate_exception_end(ctx, EXCP_RI);
30728 } else {
30729 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30731 break;
30732 case OPC_TGEI: /* REGIMM traps */
30733 case OPC_TGEIU:
30734 case OPC_TLTI:
30735 case OPC_TLTIU:
30736 case OPC_TEQI:
30738 case OPC_TNEI:
30739 check_insn(ctx, ISA_MIPS2);
30740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30741 gen_trap(ctx, op1, rs, -1, imm);
30742 break;
30743 case OPC_SIGRIE:
30744 check_insn(ctx, ISA_MIPS32R6);
30745 generate_exception_end(ctx, EXCP_RI);
30746 break;
30747 case OPC_SYNCI:
30748 check_insn(ctx, ISA_MIPS32R2);
30750 * Break the TB to be able to sync copied instructions
30751 * immediately.
30753 ctx->base.is_jmp = DISAS_STOP;
30754 break;
30755 case OPC_BPOSGE32: /* MIPS DSP branch */
30756 #if defined(TARGET_MIPS64)
30757 case OPC_BPOSGE64:
30758 #endif
30759 check_dsp(ctx);
30760 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30761 break;
30762 #if defined(TARGET_MIPS64)
30763 case OPC_DAHI:
30764 check_insn(ctx, ISA_MIPS32R6);
30765 check_mips_64(ctx);
30766 if (rs != 0) {
30767 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30769 break;
30770 case OPC_DATI:
30771 check_insn(ctx, ISA_MIPS32R6);
30772 check_mips_64(ctx);
30773 if (rs != 0) {
30774 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30776 break;
30777 #endif
30778 default: /* Invalid */
30779 MIPS_INVAL("regimm");
30780 generate_exception_end(ctx, EXCP_RI);
30781 break;
30783 break;
30784 case OPC_CP0:
30785 check_cp0_enabled(ctx);
30786 op1 = MASK_CP0(ctx->opcode);
30787 switch (op1) {
30788 case OPC_MFC0:
30789 case OPC_MTC0:
30790 case OPC_MFTR:
30791 case OPC_MTTR:
30792 case OPC_MFHC0:
30793 case OPC_MTHC0:
30794 #if defined(TARGET_MIPS64)
30795 case OPC_DMFC0:
30796 case OPC_DMTC0:
30797 #endif
30798 #ifndef CONFIG_USER_ONLY
30799 gen_cp0(env, ctx, op1, rt, rd);
30800 #endif /* !CONFIG_USER_ONLY */
30801 break;
30802 case OPC_C0:
30803 case OPC_C0_1:
30804 case OPC_C0_2:
30805 case OPC_C0_3:
30806 case OPC_C0_4:
30807 case OPC_C0_5:
30808 case OPC_C0_6:
30809 case OPC_C0_7:
30810 case OPC_C0_8:
30811 case OPC_C0_9:
30812 case OPC_C0_A:
30813 case OPC_C0_B:
30814 case OPC_C0_C:
30815 case OPC_C0_D:
30816 case OPC_C0_E:
30817 case OPC_C0_F:
30818 #ifndef CONFIG_USER_ONLY
30819 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30820 #endif /* !CONFIG_USER_ONLY */
30821 break;
30822 case OPC_MFMC0:
30823 #ifndef CONFIG_USER_ONLY
30825 uint32_t op2;
30826 TCGv t0 = tcg_temp_new();
30828 op2 = MASK_MFMC0(ctx->opcode);
30829 switch (op2) {
30830 case OPC_DMT:
30831 check_cp0_mt(ctx);
30832 gen_helper_dmt(t0);
30833 gen_store_gpr(t0, rt);
30834 break;
30835 case OPC_EMT:
30836 check_cp0_mt(ctx);
30837 gen_helper_emt(t0);
30838 gen_store_gpr(t0, rt);
30839 break;
30840 case OPC_DVPE:
30841 check_cp0_mt(ctx);
30842 gen_helper_dvpe(t0, cpu_env);
30843 gen_store_gpr(t0, rt);
30844 break;
30845 case OPC_EVPE:
30846 check_cp0_mt(ctx);
30847 gen_helper_evpe(t0, cpu_env);
30848 gen_store_gpr(t0, rt);
30849 break;
30850 case OPC_DVP:
30851 check_insn(ctx, ISA_MIPS32R6);
30852 if (ctx->vp) {
30853 gen_helper_dvp(t0, cpu_env);
30854 gen_store_gpr(t0, rt);
30856 break;
30857 case OPC_EVP:
30858 check_insn(ctx, ISA_MIPS32R6);
30859 if (ctx->vp) {
30860 gen_helper_evp(t0, cpu_env);
30861 gen_store_gpr(t0, rt);
30863 break;
30864 case OPC_DI:
30865 check_insn(ctx, ISA_MIPS32R2);
30866 save_cpu_state(ctx, 1);
30867 gen_helper_di(t0, cpu_env);
30868 gen_store_gpr(t0, rt);
30870 * Stop translation as we may have switched
30871 * the execution mode.
30873 ctx->base.is_jmp = DISAS_STOP;
30874 break;
30875 case OPC_EI:
30876 check_insn(ctx, ISA_MIPS32R2);
30877 save_cpu_state(ctx, 1);
30878 gen_helper_ei(t0, cpu_env);
30879 gen_store_gpr(t0, rt);
30881 * DISAS_STOP isn't sufficient, we need to ensure we break
30882 * out of translated code to check for pending interrupts.
30884 gen_save_pc(ctx->base.pc_next + 4);
30885 ctx->base.is_jmp = DISAS_EXIT;
30886 break;
30887 default: /* Invalid */
30888 MIPS_INVAL("mfmc0");
30889 generate_exception_end(ctx, EXCP_RI);
30890 break;
30892 tcg_temp_free(t0);
30894 #endif /* !CONFIG_USER_ONLY */
30895 break;
30896 case OPC_RDPGPR:
30897 check_insn(ctx, ISA_MIPS32R2);
30898 gen_load_srsgpr(rt, rd);
30899 break;
30900 case OPC_WRPGPR:
30901 check_insn(ctx, ISA_MIPS32R2);
30902 gen_store_srsgpr(rt, rd);
30903 break;
30904 default:
30905 MIPS_INVAL("cp0");
30906 generate_exception_end(ctx, EXCP_RI);
30907 break;
30909 break;
30910 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30911 if (ctx->insn_flags & ISA_MIPS32R6) {
30912 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30913 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30914 } else {
30915 /* OPC_ADDI */
30916 /* Arithmetic with immediate opcode */
30917 gen_arith_imm(ctx, op, rt, rs, imm);
30919 break;
30920 case OPC_ADDIU:
30921 gen_arith_imm(ctx, op, rt, rs, imm);
30922 break;
30923 case OPC_SLTI: /* Set on less than with immediate opcode */
30924 case OPC_SLTIU:
30925 gen_slt_imm(ctx, op, rt, rs, imm);
30926 break;
30927 case OPC_ANDI: /* Arithmetic with immediate opcode */
30928 case OPC_LUI: /* OPC_AUI */
30929 case OPC_ORI:
30930 case OPC_XORI:
30931 gen_logic_imm(ctx, op, rt, rs, imm);
30932 break;
30933 case OPC_J: /* Jump */
30934 case OPC_JAL:
30935 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30936 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30937 break;
30938 /* Branch */
30939 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30940 if (ctx->insn_flags & ISA_MIPS32R6) {
30941 if (rt == 0) {
30942 generate_exception_end(ctx, EXCP_RI);
30943 break;
30945 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30946 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30947 } else {
30948 /* OPC_BLEZL */
30949 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30951 break;
30952 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30953 if (ctx->insn_flags & ISA_MIPS32R6) {
30954 if (rt == 0) {
30955 generate_exception_end(ctx, EXCP_RI);
30956 break;
30958 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30959 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30960 } else {
30961 /* OPC_BGTZL */
30962 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30964 break;
30965 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30966 if (rt == 0) {
30967 /* OPC_BLEZ */
30968 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30969 } else {
30970 check_insn(ctx, ISA_MIPS32R6);
30971 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30972 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30974 break;
30975 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30976 if (rt == 0) {
30977 /* OPC_BGTZ */
30978 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30979 } else {
30980 check_insn(ctx, ISA_MIPS32R6);
30981 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30982 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30984 break;
30985 case OPC_BEQL:
30986 case OPC_BNEL:
30987 check_insn(ctx, ISA_MIPS2);
30988 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30989 /* Fallthrough */
30990 case OPC_BEQ:
30991 case OPC_BNE:
30992 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30993 break;
30994 case OPC_LL: /* Load and stores */
30995 check_insn(ctx, ISA_MIPS2);
30996 if (ctx->insn_flags & INSN_R5900) {
30997 check_insn_opc_user_only(ctx, INSN_R5900);
30999 /* Fallthrough */
31000 case OPC_LWL:
31001 case OPC_LWR:
31002 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31003 /* Fallthrough */
31004 case OPC_LB:
31005 case OPC_LH:
31006 case OPC_LW:
31007 case OPC_LWPC:
31008 case OPC_LBU:
31009 case OPC_LHU:
31010 gen_ld(ctx, op, rt, rs, imm);
31011 break;
31012 case OPC_SWL:
31013 case OPC_SWR:
31014 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31015 /* fall through */
31016 case OPC_SB:
31017 case OPC_SH:
31018 case OPC_SW:
31019 gen_st(ctx, op, rt, rs, imm);
31020 break;
31021 case OPC_SC:
31022 check_insn(ctx, ISA_MIPS2);
31023 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31024 if (ctx->insn_flags & INSN_R5900) {
31025 check_insn_opc_user_only(ctx, INSN_R5900);
31027 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
31028 break;
31029 case OPC_CACHE:
31030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31031 check_cp0_enabled(ctx);
31032 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
31033 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
31034 gen_cache_operation(ctx, rt, rs, imm);
31036 /* Treat as NOP. */
31037 break;
31038 case OPC_PREF:
31039 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31040 if (ctx->insn_flags & INSN_R5900) {
31041 /* Treat as NOP. */
31042 } else {
31043 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
31044 /* Treat as NOP. */
31046 break;
31048 /* Floating point (COP1). */
31049 case OPC_LWC1:
31050 case OPC_LDC1:
31051 case OPC_SWC1:
31052 case OPC_SDC1:
31053 gen_cop1_ldst(ctx, op, rt, rs, imm);
31054 break;
31056 case OPC_CP1:
31057 op1 = MASK_CP1(ctx->opcode);
31059 switch (op1) {
31060 case OPC_MFHC1:
31061 case OPC_MTHC1:
31062 check_cp1_enabled(ctx);
31063 check_insn(ctx, ISA_MIPS32R2);
31064 /* fall through */
31065 case OPC_MFC1:
31066 case OPC_CFC1:
31067 case OPC_MTC1:
31068 case OPC_CTC1:
31069 check_cp1_enabled(ctx);
31070 gen_cp1(ctx, op1, rt, rd);
31071 break;
31072 #if defined(TARGET_MIPS64)
31073 case OPC_DMFC1:
31074 case OPC_DMTC1:
31075 check_cp1_enabled(ctx);
31076 check_insn(ctx, ISA_MIPS3);
31077 check_mips_64(ctx);
31078 gen_cp1(ctx, op1, rt, rd);
31079 break;
31080 #endif
31081 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
31082 check_cp1_enabled(ctx);
31083 if (ctx->insn_flags & ISA_MIPS32R6) {
31084 /* OPC_BC1EQZ */
31085 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
31086 rt, imm << 2, 4);
31087 } else {
31088 /* OPC_BC1ANY2 */
31089 check_cop1x(ctx);
31090 check_insn(ctx, ASE_MIPS3D);
31091 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31092 (rt >> 2) & 0x7, imm << 2);
31094 break;
31095 case OPC_BC1NEZ:
31096 check_cp1_enabled(ctx);
31097 check_insn(ctx, ISA_MIPS32R6);
31098 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
31099 rt, imm << 2, 4);
31100 break;
31101 case OPC_BC1ANY4:
31102 check_cp1_enabled(ctx);
31103 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31104 check_cop1x(ctx);
31105 check_insn(ctx, ASE_MIPS3D);
31106 /* fall through */
31107 case OPC_BC1:
31108 check_cp1_enabled(ctx);
31109 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31110 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31111 (rt >> 2) & 0x7, imm << 2);
31112 break;
31113 case OPC_PS_FMT:
31114 check_ps(ctx);
31115 /* fall through */
31116 case OPC_S_FMT:
31117 case OPC_D_FMT:
31118 check_cp1_enabled(ctx);
31119 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31120 (imm >> 8) & 0x7);
31121 break;
31122 case OPC_W_FMT:
31123 case OPC_L_FMT:
31125 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
31126 check_cp1_enabled(ctx);
31127 if (ctx->insn_flags & ISA_MIPS32R6) {
31128 switch (r6_op) {
31129 case R6_OPC_CMP_AF_S:
31130 case R6_OPC_CMP_UN_S:
31131 case R6_OPC_CMP_EQ_S:
31132 case R6_OPC_CMP_UEQ_S:
31133 case R6_OPC_CMP_LT_S:
31134 case R6_OPC_CMP_ULT_S:
31135 case R6_OPC_CMP_LE_S:
31136 case R6_OPC_CMP_ULE_S:
31137 case R6_OPC_CMP_SAF_S:
31138 case R6_OPC_CMP_SUN_S:
31139 case R6_OPC_CMP_SEQ_S:
31140 case R6_OPC_CMP_SEUQ_S:
31141 case R6_OPC_CMP_SLT_S:
31142 case R6_OPC_CMP_SULT_S:
31143 case R6_OPC_CMP_SLE_S:
31144 case R6_OPC_CMP_SULE_S:
31145 case R6_OPC_CMP_OR_S:
31146 case R6_OPC_CMP_UNE_S:
31147 case R6_OPC_CMP_NE_S:
31148 case R6_OPC_CMP_SOR_S:
31149 case R6_OPC_CMP_SUNE_S:
31150 case R6_OPC_CMP_SNE_S:
31151 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31152 break;
31153 case R6_OPC_CMP_AF_D:
31154 case R6_OPC_CMP_UN_D:
31155 case R6_OPC_CMP_EQ_D:
31156 case R6_OPC_CMP_UEQ_D:
31157 case R6_OPC_CMP_LT_D:
31158 case R6_OPC_CMP_ULT_D:
31159 case R6_OPC_CMP_LE_D:
31160 case R6_OPC_CMP_ULE_D:
31161 case R6_OPC_CMP_SAF_D:
31162 case R6_OPC_CMP_SUN_D:
31163 case R6_OPC_CMP_SEQ_D:
31164 case R6_OPC_CMP_SEUQ_D:
31165 case R6_OPC_CMP_SLT_D:
31166 case R6_OPC_CMP_SULT_D:
31167 case R6_OPC_CMP_SLE_D:
31168 case R6_OPC_CMP_SULE_D:
31169 case R6_OPC_CMP_OR_D:
31170 case R6_OPC_CMP_UNE_D:
31171 case R6_OPC_CMP_NE_D:
31172 case R6_OPC_CMP_SOR_D:
31173 case R6_OPC_CMP_SUNE_D:
31174 case R6_OPC_CMP_SNE_D:
31175 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31176 break;
31177 default:
31178 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
31179 rt, rd, sa, (imm >> 8) & 0x7);
31181 break;
31183 } else {
31184 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31185 (imm >> 8) & 0x7);
31187 break;
31189 case OPC_BZ_V:
31190 case OPC_BNZ_V:
31191 case OPC_BZ_B:
31192 case OPC_BZ_H:
31193 case OPC_BZ_W:
31194 case OPC_BZ_D:
31195 case OPC_BNZ_B:
31196 case OPC_BNZ_H:
31197 case OPC_BNZ_W:
31198 case OPC_BNZ_D:
31199 check_insn(ctx, ASE_MSA);
31200 gen_msa_branch(env, ctx, op1);
31201 break;
31202 default:
31203 MIPS_INVAL("cp1");
31204 generate_exception_end(ctx, EXCP_RI);
31205 break;
31207 break;
31209 /* Compact branches [R6] and COP2 [non-R6] */
31210 case OPC_BC: /* OPC_LWC2 */
31211 case OPC_BALC: /* OPC_SWC2 */
31212 if (ctx->insn_flags & ISA_MIPS32R6) {
31213 /* OPC_BC, OPC_BALC */
31214 gen_compute_compact_branch(ctx, op, 0, 0,
31215 sextract32(ctx->opcode << 2, 0, 28));
31216 } else if (ctx->insn_flags & ASE_LEXT) {
31217 gen_loongson_lswc2(ctx, rt, rs, rd);
31218 } else {
31219 /* OPC_LWC2, OPC_SWC2 */
31220 /* COP2: Not implemented. */
31221 generate_exception_err(ctx, EXCP_CpU, 2);
31223 break;
31224 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
31225 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
31226 if (ctx->insn_flags & ISA_MIPS32R6) {
31227 if (rs != 0) {
31228 /* OPC_BEQZC, OPC_BNEZC */
31229 gen_compute_compact_branch(ctx, op, rs, 0,
31230 sextract32(ctx->opcode << 2, 0, 23));
31231 } else {
31232 /* OPC_JIC, OPC_JIALC */
31233 gen_compute_compact_branch(ctx, op, 0, rt, imm);
31235 } else if (ctx->insn_flags & ASE_LEXT) {
31236 gen_loongson_lsdc2(ctx, rt, rs, rd);
31237 } else {
31238 /* OPC_LWC2, OPC_SWC2 */
31239 /* COP2: Not implemented. */
31240 generate_exception_err(ctx, EXCP_CpU, 2);
31242 break;
31243 case OPC_CP2:
31244 check_insn(ctx, ASE_LMMI);
31245 /* Note that these instructions use different fields. */
31246 gen_loongson_multimedia(ctx, sa, rd, rt);
31247 break;
31249 case OPC_CP3:
31250 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31251 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
31252 check_cp1_enabled(ctx);
31253 op1 = MASK_CP3(ctx->opcode);
31254 switch (op1) {
31255 case OPC_LUXC1:
31256 case OPC_SUXC1:
31257 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
31258 /* Fallthrough */
31259 case OPC_LWXC1:
31260 case OPC_LDXC1:
31261 case OPC_SWXC1:
31262 case OPC_SDXC1:
31263 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
31264 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
31265 break;
31266 case OPC_PREFX:
31267 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
31268 /* Treat as NOP. */
31269 break;
31270 case OPC_ALNV_PS:
31271 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
31272 /* Fallthrough */
31273 case OPC_MADD_S:
31274 case OPC_MADD_D:
31275 case OPC_MADD_PS:
31276 case OPC_MSUB_S:
31277 case OPC_MSUB_D:
31278 case OPC_MSUB_PS:
31279 case OPC_NMADD_S:
31280 case OPC_NMADD_D:
31281 case OPC_NMADD_PS:
31282 case OPC_NMSUB_S:
31283 case OPC_NMSUB_D:
31284 case OPC_NMSUB_PS:
31285 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
31286 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
31287 break;
31288 default:
31289 MIPS_INVAL("cp3");
31290 generate_exception_end(ctx, EXCP_RI);
31291 break;
31293 } else {
31294 generate_exception_err(ctx, EXCP_CpU, 1);
31296 break;
31298 #if defined(TARGET_MIPS64)
31299 /* MIPS64 opcodes */
31300 case OPC_LLD:
31301 if (ctx->insn_flags & INSN_R5900) {
31302 check_insn_opc_user_only(ctx, INSN_R5900);
31304 /* fall through */
31305 case OPC_LDL:
31306 case OPC_LDR:
31307 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31308 /* fall through */
31309 case OPC_LWU:
31310 case OPC_LD:
31311 check_insn(ctx, ISA_MIPS3);
31312 check_mips_64(ctx);
31313 gen_ld(ctx, op, rt, rs, imm);
31314 break;
31315 case OPC_SDL:
31316 case OPC_SDR:
31317 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31318 /* fall through */
31319 case OPC_SD:
31320 check_insn(ctx, ISA_MIPS3);
31321 check_mips_64(ctx);
31322 gen_st(ctx, op, rt, rs, imm);
31323 break;
31324 case OPC_SCD:
31325 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31326 check_insn(ctx, ISA_MIPS3);
31327 if (ctx->insn_flags & INSN_R5900) {
31328 check_insn_opc_user_only(ctx, INSN_R5900);
31330 check_mips_64(ctx);
31331 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
31332 break;
31333 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
31334 if (ctx->insn_flags & ISA_MIPS32R6) {
31335 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
31336 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31337 } else {
31338 /* OPC_DADDI */
31339 check_insn(ctx, ISA_MIPS3);
31340 check_mips_64(ctx);
31341 gen_arith_imm(ctx, op, rt, rs, imm);
31343 break;
31344 case OPC_DADDIU:
31345 check_insn(ctx, ISA_MIPS3);
31346 check_mips_64(ctx);
31347 gen_arith_imm(ctx, op, rt, rs, imm);
31348 break;
31349 #else
31350 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
31351 if (ctx->insn_flags & ISA_MIPS32R6) {
31352 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31353 } else {
31354 MIPS_INVAL("major opcode");
31355 generate_exception_end(ctx, EXCP_RI);
31357 break;
31358 #endif
31359 case OPC_DAUI: /* OPC_JALX */
31360 if (ctx->insn_flags & ISA_MIPS32R6) {
31361 #if defined(TARGET_MIPS64)
31362 /* OPC_DAUI */
31363 check_mips_64(ctx);
31364 if (rs == 0) {
31365 generate_exception(ctx, EXCP_RI);
31366 } else if (rt != 0) {
31367 TCGv t0 = tcg_temp_new();
31368 gen_load_gpr(t0, rs);
31369 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
31370 tcg_temp_free(t0);
31372 #else
31373 generate_exception_end(ctx, EXCP_RI);
31374 MIPS_INVAL("major opcode");
31375 #endif
31376 } else {
31377 /* OPC_JALX */
31378 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
31379 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
31380 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
31382 break;
31383 case OPC_MSA: /* OPC_MDMX */
31384 if (ctx->insn_flags & INSN_R5900) {
31385 #if defined(TARGET_MIPS64)
31386 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
31387 #endif
31388 } else {
31389 /* MDMX: Not implemented. */
31390 gen_msa(env, ctx);
31392 break;
31393 case OPC_PCREL:
31394 check_insn(ctx, ISA_MIPS32R6);
31395 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
31396 break;
31397 default: /* Invalid */
31398 MIPS_INVAL("major opcode");
31399 generate_exception_end(ctx, EXCP_RI);
31400 break;
31404 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
31406 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31407 CPUMIPSState *env = cs->env_ptr;
31409 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
31410 ctx->saved_pc = -1;
31411 ctx->insn_flags = env->insn_flags;
31412 ctx->CP0_Config1 = env->CP0_Config1;
31413 ctx->CP0_Config2 = env->CP0_Config2;
31414 ctx->CP0_Config3 = env->CP0_Config3;
31415 ctx->CP0_Config5 = env->CP0_Config5;
31416 ctx->btarget = 0;
31417 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
31418 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
31419 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
31420 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
31421 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
31422 ctx->PAMask = env->PAMask;
31423 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
31424 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
31425 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
31426 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
31427 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
31428 /* Restore delay slot state from the tb context. */
31429 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
31430 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
31431 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
31432 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
31433 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
31434 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31435 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31436 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
31437 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
31438 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
31439 restore_cpu_state(env, ctx);
31440 #ifdef CONFIG_USER_ONLY
31441 ctx->mem_idx = MIPS_HFLAG_UM;
31442 #else
31443 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
31444 #endif
31445 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
31446 MO_UNALN : MO_ALIGN;
31448 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31449 ctx->hflags);
31452 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31456 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31458 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31460 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31461 ctx->btarget);
31464 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31465 const CPUBreakpoint *bp)
31467 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31469 save_cpu_state(ctx, 1);
31470 ctx->base.is_jmp = DISAS_NORETURN;
31471 gen_helper_raise_exception_debug(cpu_env);
31473 * The address covered by the breakpoint must be included in
31474 * [tb->pc, tb->pc + tb->size) in order to for it to be
31475 * properly cleared -- thus we increment the PC here so that
31476 * the logic setting tb->size below does the right thing.
31478 ctx->base.pc_next += 4;
31479 return true;
31482 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31484 CPUMIPSState *env = cs->env_ptr;
31485 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31486 int insn_bytes;
31487 int is_slot;
31489 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
31490 if (ctx->insn_flags & ISA_NANOMIPS32) {
31491 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31492 insn_bytes = decode_nanomips_opc(env, ctx);
31493 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
31494 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31495 insn_bytes = 4;
31496 decode_opc(env, ctx);
31497 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31498 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31499 insn_bytes = decode_micromips_opc(env, ctx);
31500 } else if (ctx->insn_flags & ASE_MIPS16) {
31501 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31502 insn_bytes = decode_mips16_opc(env, ctx);
31503 } else {
31504 generate_exception_end(ctx, EXCP_RI);
31505 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31506 return;
31509 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31510 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31511 MIPS_HFLAG_FBNSLOT))) {
31513 * Force to generate branch as there is neither delay nor
31514 * forbidden slot.
31516 is_slot = 1;
31518 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31519 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
31521 * Force to generate branch as microMIPS R6 doesn't restrict
31522 * branches in the forbidden slot.
31524 is_slot = 1;
31527 if (is_slot) {
31528 gen_branch(ctx, insn_bytes);
31530 ctx->base.pc_next += insn_bytes;
31532 if (ctx->base.is_jmp != DISAS_NEXT) {
31533 return;
31536 * Execute a branch and its delay slot as a single instruction.
31537 * This is what GDB expects and is consistent with what the
31538 * hardware does (e.g. if a delay slot instruction faults, the
31539 * reported PC is the PC of the branch).
31541 if (ctx->base.singlestep_enabled &&
31542 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31543 ctx->base.is_jmp = DISAS_TOO_MANY;
31545 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31546 ctx->base.is_jmp = DISAS_TOO_MANY;
31550 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31552 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31554 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31555 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
31556 gen_helper_raise_exception_debug(cpu_env);
31557 } else {
31558 switch (ctx->base.is_jmp) {
31559 case DISAS_STOP:
31560 gen_save_pc(ctx->base.pc_next);
31561 tcg_gen_lookup_and_goto_ptr();
31562 break;
31563 case DISAS_NEXT:
31564 case DISAS_TOO_MANY:
31565 save_cpu_state(ctx, 0);
31566 gen_goto_tb(ctx, 0, ctx->base.pc_next);
31567 break;
31568 case DISAS_EXIT:
31569 tcg_gen_exit_tb(NULL, 0);
31570 break;
31571 case DISAS_NORETURN:
31572 break;
31573 default:
31574 g_assert_not_reached();
31579 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31581 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31582 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31585 static const TranslatorOps mips_tr_ops = {
31586 .init_disas_context = mips_tr_init_disas_context,
31587 .tb_start = mips_tr_tb_start,
31588 .insn_start = mips_tr_insn_start,
31589 .breakpoint_check = mips_tr_breakpoint_check,
31590 .translate_insn = mips_tr_translate_insn,
31591 .tb_stop = mips_tr_tb_stop,
31592 .disas_log = mips_tr_disas_log,
31595 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31597 DisasContext ctx;
31599 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31602 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31604 int i;
31605 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31607 #define printfpr(fp) \
31608 do { \
31609 if (is_fpu64) \
31610 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31611 " fd:%13g fs:%13g psu: %13g\n", \
31612 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31613 (double)(fp)->fd, \
31614 (double)(fp)->fs[FP_ENDIAN_IDX], \
31615 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31616 else { \
31617 fpr_t tmp; \
31618 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31619 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31620 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31621 " fd:%13g fs:%13g psu:%13g\n", \
31622 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31623 (double)tmp.fd, \
31624 (double)tmp.fs[FP_ENDIAN_IDX], \
31625 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31627 } while (0)
31630 qemu_fprintf(f,
31631 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31632 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31633 get_float_exception_flags(&env->active_fpu.fp_status));
31634 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31635 qemu_fprintf(f, "%3s: ", fregnames[i]);
31636 printfpr(&env->active_fpu.fpr[i]);
31639 #undef printfpr
31642 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31644 MIPSCPU *cpu = MIPS_CPU(cs);
31645 CPUMIPSState *env = &cpu->env;
31646 int i;
31648 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31649 " LO=0x" TARGET_FMT_lx " ds %04x "
31650 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31651 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31652 env->hflags, env->btarget, env->bcond);
31653 for (i = 0; i < 32; i++) {
31654 if ((i & 3) == 0) {
31655 qemu_fprintf(f, "GPR%02d:", i);
31657 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31658 regnames[i], env->active_tc.gpr[i]);
31659 if ((i & 3) == 3) {
31660 qemu_fprintf(f, "\n");
31664 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31665 TARGET_FMT_lx "\n",
31666 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31667 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31668 PRIx64 "\n",
31669 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31670 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31671 env->CP0_Config2, env->CP0_Config3);
31672 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31673 env->CP0_Config4, env->CP0_Config5);
31674 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31675 fpu_dump_state(env, f, flags);
31679 void mips_tcg_init(void)
31681 int i;
31683 cpu_gpr[0] = NULL;
31684 for (i = 1; i < 32; i++)
31685 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31686 offsetof(CPUMIPSState,
31687 active_tc.gpr[i]),
31688 regnames[i]);
31690 for (i = 0; i < 32; i++) {
31691 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31692 msa_wr_d[i * 2] =
31693 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31695 * The scalar floating-point unit (FPU) registers are mapped on
31696 * the MSA vector registers.
31698 fpu_f64[i] = msa_wr_d[i * 2];
31699 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31700 msa_wr_d[i * 2 + 1] =
31701 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31704 cpu_PC = tcg_global_mem_new(cpu_env,
31705 offsetof(CPUMIPSState, active_tc.PC), "PC");
31706 for (i = 0; i < MIPS_DSP_ACC; i++) {
31707 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31708 offsetof(CPUMIPSState, active_tc.HI[i]),
31709 regnames_HI[i]);
31710 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31711 offsetof(CPUMIPSState, active_tc.LO[i]),
31712 regnames_LO[i]);
31714 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31715 offsetof(CPUMIPSState,
31716 active_tc.DSPControl),
31717 "DSPControl");
31718 bcond = tcg_global_mem_new(cpu_env,
31719 offsetof(CPUMIPSState, bcond), "bcond");
31720 btarget = tcg_global_mem_new(cpu_env,
31721 offsetof(CPUMIPSState, btarget), "btarget");
31722 hflags = tcg_global_mem_new_i32(cpu_env,
31723 offsetof(CPUMIPSState, hflags), "hflags");
31725 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31726 offsetof(CPUMIPSState, active_fpu.fcr0),
31727 "fcr0");
31728 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31729 offsetof(CPUMIPSState, active_fpu.fcr31),
31730 "fcr31");
31731 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31732 "lladdr");
31733 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31734 "llval");
31736 #if defined(TARGET_MIPS64)
31737 cpu_mmr[0] = NULL;
31738 for (i = 1; i < 32; i++) {
31739 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31740 offsetof(CPUMIPSState,
31741 active_tc.mmr[i]),
31742 regnames[i]);
31744 #endif
31746 #if !defined(TARGET_MIPS64)
31747 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31748 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31749 offsetof(CPUMIPSState,
31750 active_tc.mxu_gpr[i]),
31751 mxuregnames[i]);
31754 mxu_CR = tcg_global_mem_new(cpu_env,
31755 offsetof(CPUMIPSState, active_tc.mxu_cr),
31756 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31757 #endif
31760 #include "translate_init.c.inc"
31762 void cpu_mips_realize_env(CPUMIPSState *env)
31764 env->exception_base = (int32_t)0xBFC00000;
31766 #ifndef CONFIG_USER_ONLY
31767 mmu_init(env, env->cpu_model);
31768 #endif
31769 fpu_init(env, env->cpu_model);
31770 mvp_init(env, env->cpu_model);
31773 bool cpu_supports_cps_smp(const char *cpu_type)
31775 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31776 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
31779 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
31781 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31782 return (mcc->cpu_def->insn_flags & isa) != 0;
31785 void cpu_set_exception_base(int vp_index, target_ulong address)
31787 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31788 vp->env.exception_base = address;
31791 void cpu_state_reset(CPUMIPSState *env)
31793 CPUState *cs = env_cpu(env);
31795 /* Reset registers to their default values */
31796 env->CP0_PRid = env->cpu_model->CP0_PRid;
31797 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31798 #ifdef TARGET_WORDS_BIGENDIAN
31799 env->CP0_Config0 |= (1 << CP0C0_BE);
31800 #endif
31801 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31802 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31803 env->CP0_Config3 = env->cpu_model->CP0_Config3;
31804 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31805 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
31806 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31807 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
31808 env->CP0_Config6 = env->cpu_model->CP0_Config6;
31809 env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
31810 env->CP0_Config7 = env->cpu_model->CP0_Config7;
31811 env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
31812 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31813 << env->cpu_model->CP0_LLAddr_shift;
31814 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
31815 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31816 env->CCRes = env->cpu_model->CCRes;
31817 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31818 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31819 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31820 env->current_tc = 0;
31821 env->SEGBITS = env->cpu_model->SEGBITS;
31822 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31823 #if defined(TARGET_MIPS64)
31824 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31825 env->SEGMask |= 3ULL << 62;
31827 #endif
31828 env->PABITS = env->cpu_model->PABITS;
31829 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31830 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31831 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31832 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31833 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31834 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31835 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31836 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31837 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31838 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
31839 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31840 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
31841 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
31842 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
31843 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
31844 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
31845 env->msair = env->cpu_model->MSAIR;
31846 env->insn_flags = env->cpu_model->insn_flags;
31848 #if defined(CONFIG_USER_ONLY)
31849 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
31850 # ifdef TARGET_MIPS64
31851 /* Enable 64-bit register mode. */
31852 env->CP0_Status |= (1 << CP0St_PX);
31853 # endif
31854 # ifdef TARGET_ABI_MIPSN64
31855 /* Enable 64-bit address mode. */
31856 env->CP0_Status |= (1 << CP0St_UX);
31857 # endif
31859 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31860 * hardware registers.
31862 env->CP0_HWREna |= 0x0000000F;
31863 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
31864 env->CP0_Status |= (1 << CP0St_CU1);
31866 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31867 env->CP0_Status |= (1 << CP0St_MX);
31869 # if defined(TARGET_MIPS64)
31870 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31871 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31872 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
31873 env->CP0_Status |= (1 << CP0St_FR);
31875 # endif
31876 #else
31877 if (env->hflags & MIPS_HFLAG_BMASK) {
31879 * If the exception was raised from a delay slot,
31880 * come back to the jump.
31882 env->CP0_ErrorEPC = (env->active_tc.PC
31883 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
31884 } else {
31885 env->CP0_ErrorEPC = env->active_tc.PC;
31887 env->active_tc.PC = env->exception_base;
31888 env->CP0_Random = env->tlb->nb_tlb - 1;
31889 env->tlb->tlb_in_use = env->tlb->nb_tlb;
31890 env->CP0_Wired = 0;
31891 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
31892 env->CP0_EBase = (cs->cpu_index & 0x3FF);
31893 if (mips_um_ksegs_enabled()) {
31894 env->CP0_EBase |= 0x40000000;
31895 } else {
31896 env->CP0_EBase |= (int32_t)0x80000000;
31898 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31899 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31901 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
31902 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
31903 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
31905 * Vectored interrupts not implemented, timer on int 7,
31906 * no performance counters.
31908 env->CP0_IntCtl = 0xe0000000;
31910 int i;
31912 for (i = 0; i < 7; i++) {
31913 env->CP0_WatchLo[i] = 0;
31914 env->CP0_WatchHi[i] = 0x80000000;
31916 env->CP0_WatchLo[7] = 0;
31917 env->CP0_WatchHi[7] = 0;
31919 /* Count register increments in debug mode, EJTAG version 1 */
31920 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
31922 cpu_mips_store_count(env, 1);
31924 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31925 int i;
31927 /* Only TC0 on VPE 0 starts as active. */
31928 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
31929 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
31930 env->tcs[i].CP0_TCHalt = 1;
31932 env->active_tc.CP0_TCHalt = 1;
31933 cs->halted = 1;
31935 if (cs->cpu_index == 0) {
31936 /* VPE0 starts up enabled. */
31937 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31938 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31940 /* TC0 starts up unhalted. */
31941 cs->halted = 0;
31942 env->active_tc.CP0_TCHalt = 0;
31943 env->tcs[0].CP0_TCHalt = 0;
31944 /* With thread 0 active. */
31945 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31946 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31951 * Configure default legacy segmentation control. We use this regardless of
31952 * whether segmentation control is presented to the guest.
31954 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31955 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31956 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31957 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31958 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31959 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31960 (2 << CP0SC_C);
31961 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31962 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31963 (3 << CP0SC_C)) << 16;
31964 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31965 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31966 (1 << CP0SC_EU) | (2 << CP0SC_C);
31967 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31968 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31969 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31970 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31971 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
31972 #endif
31973 if ((env->insn_flags & ISA_MIPS32R6) &&
31974 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31975 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31976 env->CP0_Status |= (1 << CP0St_FR);
31979 if (env->insn_flags & ISA_MIPS32R6) {
31980 /* PTW = 1 */
31981 env->CP0_PWSize = 0x40;
31982 /* GDI = 12 */
31983 /* UDI = 12 */
31984 /* MDI = 12 */
31985 /* PRI = 12 */
31986 /* PTEI = 2 */
31987 env->CP0_PWField = 0x0C30C302;
31988 } else {
31989 /* GDI = 0 */
31990 /* UDI = 0 */
31991 /* MDI = 0 */
31992 /* PRI = 0 */
31993 /* PTEI = 2 */
31994 env->CP0_PWField = 0x02;
31997 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31998 /* microMIPS on reset when Config3.ISA is 3 */
31999 env->hflags |= MIPS_HFLAG_M16;
32002 /* MSA */
32003 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
32004 msa_reset(env);
32007 compute_hflags(env);
32008 restore_fp_status(env);
32009 restore_pamask(env);
32010 cs->exception_index = EXCP_NONE;
32012 if (semihosting_get_argc()) {
32013 /* UHI interface can be used to obtain argc and argv */
32014 env->active_tc.gpr[4] = -1;
32018 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
32019 target_ulong *data)
32021 env->active_tc.PC = data[0];
32022 env->hflags &= ~MIPS_HFLAG_BMASK;
32023 env->hflags |= data[1];
32024 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
32025 case MIPS_HFLAG_BR:
32026 break;
32027 case MIPS_HFLAG_BC:
32028 case MIPS_HFLAG_BL:
32029 case MIPS_HFLAG_B:
32030 env->btarget = data[2];
32031 break;