tests/boot_linux_console: Tag Emcraft Smartfusion2 as running 'u-boot'
[qemu/ar7.git] / target / mips / translate.c
blobd745bd2803b4bdf30480658104f4e5763bce3bcb
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 /* BSHFL opcodes */
464 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
466 enum {
467 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
468 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
469 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
470 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
471 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
472 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
473 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
474 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
477 /* DBSHFL opcodes */
478 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
480 enum {
481 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
482 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
483 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
484 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
485 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
486 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
487 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
488 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
489 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
490 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
491 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
494 /* MIPS DSP REGIMM opcodes */
495 enum {
496 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
497 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
500 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
501 /* MIPS DSP Load */
502 enum {
503 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
504 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
505 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
506 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
509 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 /* MIPS DSP Arithmetic Sub-class */
512 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
518 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
525 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
527 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
529 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
530 /* MIPS DSP Multiply Sub-class insns */
531 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
536 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
539 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
540 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
541 enum {
542 /* MIPS DSP Arithmetic Sub-class */
543 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
554 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
555 /* MIPS DSP Multiply Sub-class insns */
556 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
559 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
562 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
563 enum {
564 /* MIPS DSP Arithmetic Sub-class */
565 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
578 /* DSP Bit/Manipulation Sub-class */
579 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
583 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
586 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
587 enum {
588 /* MIPS DSP Arithmetic Sub-class */
589 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
596 /* DSP Compare-Pick Sub-class */
597 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
611 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
614 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
615 enum {
616 /* MIPS DSP GPR-Based Shift Sub-class */
617 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
638 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
641 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
642 enum {
643 /* MIPS DSP Multiply Sub-class insns */
644 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
657 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
660 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
665 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
668 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* DSP Bit/Manipulation Sub-class */
671 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
674 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
675 enum {
676 /* MIPS DSP Append Sub-class */
677 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
678 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
679 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
682 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
683 enum {
684 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
685 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
696 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
698 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
699 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
700 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
701 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
704 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Arithmetic Sub-class */
707 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
724 /* DSP Bit/Manipulation Sub-class */
725 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
730 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
733 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
734 enum {
735 /* MIPS DSP Multiply Sub-class insns */
736 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
740 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
741 /* MIPS DSP Arithmetic Sub-class */
742 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
752 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
762 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
765 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
766 enum {
767 /* DSP Compare-Pick Sub-class */
768 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
787 /* MIPS DSP Arithmetic Sub-class */
788 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
795 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
798 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
799 enum {
800 /* DSP Append Sub-class */
801 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
803 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
804 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
807 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
808 enum {
809 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
810 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
811 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
830 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
833 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
834 enum {
835 /* DSP Bit/Manipulation Sub-class */
836 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
839 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
840 enum {
841 /* MIPS DSP Multiply Sub-class insns */
842 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
867 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
870 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
871 enum {
872 /* MIPS DSP GPR-Based Shift Sub-class */
873 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
898 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
901 /* Coprocessor 0 (rs field) */
902 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
904 enum {
905 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
906 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
907 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
908 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
909 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
910 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
911 OPC_MFTR = (0x08 << 21) | OPC_CP0,
912 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
913 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
914 OPC_MTTR = (0x0C << 21) | OPC_CP0,
915 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
916 OPC_C0 = (0x10 << 21) | OPC_CP0,
917 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
918 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
919 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
920 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
921 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
922 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
923 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
924 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
925 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
926 OPC_C0_A = (0x1A << 21) | OPC_CP0,
927 OPC_C0_B = (0x1B << 21) | OPC_CP0,
928 OPC_C0_C = (0x1C << 21) | OPC_CP0,
929 OPC_C0_D = (0x1D << 21) | OPC_CP0,
930 OPC_C0_E = (0x1E << 21) | OPC_CP0,
931 OPC_C0_F = (0x1F << 21) | OPC_CP0,
934 /* MFMC0 opcodes */
935 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
937 enum {
938 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
940 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
941 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
942 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
943 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
944 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
945 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
948 /* Coprocessor 0 (with rs == C0) */
949 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
951 enum {
952 OPC_TLBR = 0x01 | OPC_C0,
953 OPC_TLBWI = 0x02 | OPC_C0,
954 OPC_TLBINV = 0x03 | OPC_C0,
955 OPC_TLBINVF = 0x04 | OPC_C0,
956 OPC_TLBWR = 0x06 | OPC_C0,
957 OPC_TLBP = 0x08 | OPC_C0,
958 OPC_RFE = 0x10 | OPC_C0,
959 OPC_ERET = 0x18 | OPC_C0,
960 OPC_DERET = 0x1F | OPC_C0,
961 OPC_WAIT = 0x20 | OPC_C0,
964 /* Coprocessor 1 (rs field) */
965 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
967 /* Values for the fmt field in FP instructions */
968 enum {
969 /* 0 - 15 are reserved */
970 FMT_S = 16, /* single fp */
971 FMT_D = 17, /* double fp */
972 FMT_E = 18, /* extended fp */
973 FMT_Q = 19, /* quad fp */
974 FMT_W = 20, /* 32-bit fixed */
975 FMT_L = 21, /* 64-bit fixed */
976 FMT_PS = 22, /* paired single fp */
977 /* 23 - 31 are reserved */
980 enum {
981 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
982 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
983 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
984 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
985 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
986 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
987 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
988 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
989 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
990 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
991 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
992 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
993 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
994 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
995 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
996 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
997 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
998 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
999 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1000 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1001 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1002 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1003 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1004 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1005 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1006 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1007 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1008 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1009 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1010 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1013 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1014 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1016 enum {
1017 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1018 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1019 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1020 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1023 enum {
1024 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1025 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1028 enum {
1029 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1030 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1033 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1035 enum {
1036 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1037 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1038 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1039 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1040 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1041 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1042 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1043 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1044 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1045 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1046 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1049 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1051 enum {
1052 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1059 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1061 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1068 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1070 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1073 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1074 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1075 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1076 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1077 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1079 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1082 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1086 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1088 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1089 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1093 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1095 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1100 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1102 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1107 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1109 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1114 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1116 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1117 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1118 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1119 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1121 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1123 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1124 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1125 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1126 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1128 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1130 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1131 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1133 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1135 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1137 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1138 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1139 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1140 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1141 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1142 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1146 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1148 enum {
1149 OPC_LWXC1 = 0x00 | OPC_CP3,
1150 OPC_LDXC1 = 0x01 | OPC_CP3,
1151 OPC_LUXC1 = 0x05 | OPC_CP3,
1152 OPC_SWXC1 = 0x08 | OPC_CP3,
1153 OPC_SDXC1 = 0x09 | OPC_CP3,
1154 OPC_SUXC1 = 0x0D | OPC_CP3,
1155 OPC_PREFX = 0x0F | OPC_CP3,
1156 OPC_ALNV_PS = 0x1E | OPC_CP3,
1157 OPC_MADD_S = 0x20 | OPC_CP3,
1158 OPC_MADD_D = 0x21 | OPC_CP3,
1159 OPC_MADD_PS = 0x26 | OPC_CP3,
1160 OPC_MSUB_S = 0x28 | OPC_CP3,
1161 OPC_MSUB_D = 0x29 | OPC_CP3,
1162 OPC_MSUB_PS = 0x2E | OPC_CP3,
1163 OPC_NMADD_S = 0x30 | OPC_CP3,
1164 OPC_NMADD_D = 0x31 | OPC_CP3,
1165 OPC_NMADD_PS = 0x36 | OPC_CP3,
1166 OPC_NMSUB_S = 0x38 | OPC_CP3,
1167 OPC_NMSUB_D = 0x39 | OPC_CP3,
1168 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1171 /* MSA Opcodes */
1172 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1173 enum {
1174 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1175 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1176 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1177 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1178 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1179 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1180 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1181 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1182 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1183 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1184 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1185 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1186 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1187 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1188 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1189 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1190 OPC_MSA_ELM = 0x19 | OPC_MSA,
1191 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1192 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1193 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1194 OPC_MSA_VEC = 0x1E | OPC_MSA,
1196 /* MI10 instruction */
1197 OPC_LD_B = (0x20) | OPC_MSA,
1198 OPC_LD_H = (0x21) | OPC_MSA,
1199 OPC_LD_W = (0x22) | OPC_MSA,
1200 OPC_LD_D = (0x23) | OPC_MSA,
1201 OPC_ST_B = (0x24) | OPC_MSA,
1202 OPC_ST_H = (0x25) | OPC_MSA,
1203 OPC_ST_W = (0x26) | OPC_MSA,
1204 OPC_ST_D = (0x27) | OPC_MSA,
1207 enum {
1208 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1209 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1210 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1211 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1212 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1213 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1214 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1215 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1216 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1217 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1218 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1219 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1220 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1222 /* I8 instruction */
1223 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1224 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1225 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1226 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1227 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1228 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1229 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1230 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1231 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1232 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1234 /* VEC/2R/2RF instruction */
1235 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1236 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1237 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1238 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1239 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1240 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1241 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1244 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1246 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1247 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1248 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1249 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1250 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1252 /* 2RF instruction df(bit 16) = _w, _d */
1253 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1255 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1256 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1257 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1258 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1259 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1260 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1262 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1263 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1264 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1266 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1268 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1270 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1271 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1272 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1273 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1274 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1275 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1276 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1277 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1278 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1279 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1280 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1281 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1282 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1283 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1284 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1285 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1286 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1287 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1288 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1289 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1290 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1291 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1292 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1293 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1294 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1295 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1296 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1297 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1298 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1299 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1300 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1301 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1302 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1303 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1304 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1305 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1306 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1307 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1308 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1309 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1310 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1311 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1312 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1313 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1314 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1315 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1316 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1317 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1318 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1319 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1320 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1321 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1322 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1323 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1324 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1325 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1326 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1327 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1328 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1329 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1330 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1331 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1332 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1333 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1335 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1336 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1340 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1342 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1344 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1346 /* 3RF instruction _df(bit 21) = _w, _d */
1347 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1348 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1349 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1351 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1353 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1354 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1355 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1356 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1357 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1358 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1360 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1361 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1362 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1363 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1364 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1365 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1366 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1368 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1369 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1371 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1372 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1373 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1374 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1375 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1376 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1377 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1378 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1379 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1380 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1381 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1382 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1383 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1384 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1385 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1386 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1387 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1389 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1390 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1391 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1392 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1393 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1394 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1395 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1396 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1397 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1398 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1399 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1401 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1407 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1408 * ============================================
1411 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1412 * instructions set. It is designed to fit the needs of signal, graphical and
1413 * video processing applications. MXU instruction set is used in Xburst family
1414 * of microprocessors by Ingenic.
1416 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1417 * the control register.
1420 * The notation used in MXU assembler mnemonics
1421 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1423 * Register operands:
1425 * XRa, XRb, XRc, XRd - MXU registers
1426 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1428 * Non-register operands:
1430 * aptn1 - 1-bit accumulate add/subtract pattern
1431 * aptn2 - 2-bit accumulate add/subtract pattern
1432 * eptn2 - 2-bit execute add/subtract pattern
1433 * optn2 - 2-bit operand pattern
1434 * optn3 - 3-bit operand pattern
1435 * sft4 - 4-bit shift amount
1436 * strd2 - 2-bit stride amount
1438 * Prefixes:
1440 * Level of parallelism: Operand size:
1441 * S - single operation at a time 32 - word
1442 * D - two operations in parallel 16 - half word
1443 * Q - four operations in parallel 8 - byte
1445 * Operations:
1447 * ADD - Add or subtract
1448 * ADDC - Add with carry-in
1449 * ACC - Accumulate
1450 * ASUM - Sum together then accumulate (add or subtract)
1451 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1452 * AVG - Average between 2 operands
1453 * ABD - Absolute difference
1454 * ALN - Align data
1455 * AND - Logical bitwise 'and' operation
1456 * CPS - Copy sign
1457 * EXTR - Extract bits
1458 * I2M - Move from GPR register to MXU register
1459 * LDD - Load data from memory to XRF
1460 * LDI - Load data from memory to XRF (and increase the address base)
1461 * LUI - Load unsigned immediate
1462 * MUL - Multiply
1463 * MULU - Unsigned multiply
1464 * MADD - 64-bit operand add 32x32 product
1465 * MSUB - 64-bit operand subtract 32x32 product
1466 * MAC - Multiply and accumulate (add or subtract)
1467 * MAD - Multiply and add or subtract
1468 * MAX - Maximum between 2 operands
1469 * MIN - Minimum between 2 operands
1470 * M2I - Move from MXU register to GPR register
1471 * MOVZ - Move if zero
1472 * MOVN - Move if non-zero
1473 * NOR - Logical bitwise 'nor' operation
1474 * OR - Logical bitwise 'or' operation
1475 * STD - Store data from XRF to memory
1476 * SDI - Store data from XRF to memory (and increase the address base)
1477 * SLT - Set of less than comparison
1478 * SAD - Sum of absolute differences
1479 * SLL - Logical shift left
1480 * SLR - Logical shift right
1481 * SAR - Arithmetic shift right
1482 * SAT - Saturation
1483 * SFL - Shuffle
1484 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1485 * XOR - Logical bitwise 'exclusive or' operation
1487 * Suffixes:
1489 * E - Expand results
1490 * F - Fixed point multiplication
1491 * L - Low part result
1492 * R - Doing rounding
1493 * V - Variable instead of immediate
1494 * W - Combine above L and V
1497 * The list of MXU instructions grouped by functionality
1498 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1500 * Load/Store instructions Multiplication instructions
1501 * ----------------------- ---------------------------
1503 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1504 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1505 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1506 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1507 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1508 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1509 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1510 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1511 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1512 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1516 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1517 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1518 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1519 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1520 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1521 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1522 * S16SDI XRa, Rb, s10, eptn2
1523 * S8LDD XRa, Rb, s8, eptn3
1524 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1525 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1526 * S8SDI XRa, Rb, s8, eptn3
1527 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1528 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1529 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1530 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1531 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1532 * S32CPS XRa, XRb, XRc
1533 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1534 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1535 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1536 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1537 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1538 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1539 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1540 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1541 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1542 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1543 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1544 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1545 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1546 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1547 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1548 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1549 * Q8SLT XRa, XRb, XRc
1550 * Q8SLTU XRa, XRb, XRc
1551 * Q8MOVZ XRa, XRb, XRc Shift instructions
1552 * Q8MOVN XRa, XRb, XRc ------------------
1554 * D32SLL XRa, XRb, XRc, XRd, sft4
1555 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1556 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1557 * D32SARL XRa, XRb, XRc, sft4
1558 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1559 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1560 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1561 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1562 * Q16SLL XRa, XRb, XRc, XRd, sft4
1563 * Q16SLR XRa, XRb, XRc, XRd, sft4
1564 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1565 * ------------------------- Q16SLLV XRa, XRb, Rb
1566 * Q16SLRV XRa, XRb, Rb
1567 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1568 * S32ALN XRa, XRb, XRc, Rb
1569 * S32ALNI XRa, XRb, XRc, s3
1570 * S32LUI XRa, s8, optn3 Move instructions
1571 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1572 * S32EXTRV XRa, XRb, Rs, Rt
1573 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1574 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1577 * The opcode organization of MXU instructions
1578 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1580 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1581 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1582 * other bits up to the instruction level is as follows:
1584 * bits
1585 * 05..00
1587 * ┌─ 000000 ─ OPC_MXU_S32MADD
1588 * ├─ 000001 ─ OPC_MXU_S32MADDU
1589 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1590 * │
1591 * │ 20..18
1592 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1593 * │ ├─ 001 ─ OPC_MXU_S32MIN
1594 * │ ├─ 010 ─ OPC_MXU_D16MAX
1595 * │ ├─ 011 ─ OPC_MXU_D16MIN
1596 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1597 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1598 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1599 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1600 * ├─ 000100 ─ OPC_MXU_S32MSUB
1601 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1602 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1603 * │ ├─ 001 ─ OPC_MXU_D16SLT
1604 * │ ├─ 010 ─ OPC_MXU_D16AVG
1605 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1606 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1607 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1608 * │ └─ 111 ─ OPC_MXU_Q8ADD
1609 * │
1610 * │ 20..18
1611 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1612 * │ ├─ 010 ─ OPC_MXU_D16CPS
1613 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1614 * │ └─ 110 ─ OPC_MXU_Q16SAT
1615 * ├─ 001000 ─ OPC_MXU_D16MUL
1616 * │ 25..24
1617 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1618 * │ └─ 01 ─ OPC_MXU_D16MULE
1619 * ├─ 001010 ─ OPC_MXU_D16MAC
1620 * ├─ 001011 ─ OPC_MXU_D16MACF
1621 * ├─ 001100 ─ OPC_MXU_D16MADL
1622 * ├─ 001101 ─ OPC_MXU_S16MAD
1623 * ├─ 001110 ─ OPC_MXU_Q16ADD
1624 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1625 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1626 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1627 * │
1628 * │ 23
1629 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1630 * │ └─ 1 ─ OPC_MXU_S32STDR
1631 * │
1632 * │ 13..10
1633 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1634 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1635 * │
1636 * │ 13..10
1637 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1638 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1639 * │
1640 * │ 23
1641 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1642 * │ └─ 1 ─ OPC_MXU_S32LDIR
1643 * │
1644 * │ 23
1645 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1646 * │ └─ 1 ─ OPC_MXU_S32SDIR
1647 * │
1648 * │ 13..10
1649 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1650 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1651 * │
1652 * │ 13..10
1653 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1654 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1655 * ├─ 011000 ─ OPC_MXU_D32ADD
1656 * │ 23..22
1657 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1658 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1659 * │ └─ 10 ─ OPC_MXU_D32ASUM
1660 * ├─ 011010 ─ <not assigned>
1661 * │ 23..22
1662 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1663 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1664 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1665 * │
1666 * │ 23..22
1667 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1668 * │ ├─ 01 ─ OPC_MXU_D8SUM
1669 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1670 * ├─ 011110 ─ <not assigned>
1671 * ├─ 011111 ─ <not assigned>
1672 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1673 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1674 * ├─ 100010 ─ OPC_MXU_S8LDD
1675 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1676 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1677 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1678 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1679 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1680 * │
1681 * │ 20..18
1682 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1683 * │ ├─ 001 ─ OPC_MXU_S32ALN
1684 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1685 * │ ├─ 011 ─ OPC_MXU_S32LUI
1686 * │ ├─ 100 ─ OPC_MXU_S32NOR
1687 * │ ├─ 101 ─ OPC_MXU_S32AND
1688 * │ ├─ 110 ─ OPC_MXU_S32OR
1689 * │ └─ 111 ─ OPC_MXU_S32XOR
1690 * │
1691 * │ 7..5
1692 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1693 * │ ├─ 001 ─ OPC_MXU_LXH
1694 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1695 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1696 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1697 * ├─ 101100 ─ OPC_MXU_S16LDI
1698 * ├─ 101101 ─ OPC_MXU_S16SDI
1699 * ├─ 101110 ─ OPC_MXU_S32M2I
1700 * ├─ 101111 ─ OPC_MXU_S32I2M
1701 * ├─ 110000 ─ OPC_MXU_D32SLL
1702 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1703 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1704 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1705 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1706 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1707 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1708 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1709 * │
1710 * ├─ 110111 ─ OPC_MXU_Q16SAR
1711 * │ 23..22
1712 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1713 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1714 * │
1715 * │ 20..18
1716 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1717 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1718 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1719 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1720 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1721 * │ └─ 101 ─ OPC_MXU_S32MOVN
1722 * │
1723 * │ 23..22
1724 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1725 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1726 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1727 * ├─ 111100 ─ OPC_MXU_Q8MADL
1728 * ├─ 111101 ─ OPC_MXU_S32SFL
1729 * ├─ 111110 ─ OPC_MXU_Q8SAD
1730 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1733 * Compiled after:
1735 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1736 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1739 enum {
1740 OPC_MXU_S32MADD = 0x00,
1741 OPC_MXU_S32MADDU = 0x01,
1742 OPC__MXU_MUL = 0x02,
1743 OPC_MXU__POOL00 = 0x03,
1744 OPC_MXU_S32MSUB = 0x04,
1745 OPC_MXU_S32MSUBU = 0x05,
1746 OPC_MXU__POOL01 = 0x06,
1747 OPC_MXU__POOL02 = 0x07,
1748 OPC_MXU_D16MUL = 0x08,
1749 OPC_MXU__POOL03 = 0x09,
1750 OPC_MXU_D16MAC = 0x0A,
1751 OPC_MXU_D16MACF = 0x0B,
1752 OPC_MXU_D16MADL = 0x0C,
1753 OPC_MXU_S16MAD = 0x0D,
1754 OPC_MXU_Q16ADD = 0x0E,
1755 OPC_MXU_D16MACE = 0x0F,
1756 OPC_MXU__POOL04 = 0x10,
1757 OPC_MXU__POOL05 = 0x11,
1758 OPC_MXU__POOL06 = 0x12,
1759 OPC_MXU__POOL07 = 0x13,
1760 OPC_MXU__POOL08 = 0x14,
1761 OPC_MXU__POOL09 = 0x15,
1762 OPC_MXU__POOL10 = 0x16,
1763 OPC_MXU__POOL11 = 0x17,
1764 OPC_MXU_D32ADD = 0x18,
1765 OPC_MXU__POOL12 = 0x19,
1766 /* not assigned 0x1A */
1767 OPC_MXU__POOL13 = 0x1B,
1768 OPC_MXU__POOL14 = 0x1C,
1769 OPC_MXU_Q8ACCE = 0x1D,
1770 /* not assigned 0x1E */
1771 /* not assigned 0x1F */
1772 /* not assigned 0x20 */
1773 /* not assigned 0x21 */
1774 OPC_MXU_S8LDD = 0x22,
1775 OPC_MXU_S8STD = 0x23,
1776 OPC_MXU_S8LDI = 0x24,
1777 OPC_MXU_S8SDI = 0x25,
1778 OPC_MXU__POOL15 = 0x26,
1779 OPC_MXU__POOL16 = 0x27,
1780 OPC_MXU__POOL17 = 0x28,
1781 /* not assigned 0x29 */
1782 OPC_MXU_S16LDD = 0x2A,
1783 OPC_MXU_S16STD = 0x2B,
1784 OPC_MXU_S16LDI = 0x2C,
1785 OPC_MXU_S16SDI = 0x2D,
1786 OPC_MXU_S32M2I = 0x2E,
1787 OPC_MXU_S32I2M = 0x2F,
1788 OPC_MXU_D32SLL = 0x30,
1789 OPC_MXU_D32SLR = 0x31,
1790 OPC_MXU_D32SARL = 0x32,
1791 OPC_MXU_D32SAR = 0x33,
1792 OPC_MXU_Q16SLL = 0x34,
1793 OPC_MXU_Q16SLR = 0x35,
1794 OPC_MXU__POOL18 = 0x36,
1795 OPC_MXU_Q16SAR = 0x37,
1796 OPC_MXU__POOL19 = 0x38,
1797 OPC_MXU__POOL20 = 0x39,
1798 OPC_MXU__POOL21 = 0x3A,
1799 OPC_MXU_Q16SCOP = 0x3B,
1800 OPC_MXU_Q8MADL = 0x3C,
1801 OPC_MXU_S32SFL = 0x3D,
1802 OPC_MXU_Q8SAD = 0x3E,
1803 /* not assigned 0x3F */
1808 * MXU pool 00
1810 enum {
1811 OPC_MXU_S32MAX = 0x00,
1812 OPC_MXU_S32MIN = 0x01,
1813 OPC_MXU_D16MAX = 0x02,
1814 OPC_MXU_D16MIN = 0x03,
1815 OPC_MXU_Q8MAX = 0x04,
1816 OPC_MXU_Q8MIN = 0x05,
1817 OPC_MXU_Q8SLT = 0x06,
1818 OPC_MXU_Q8SLTU = 0x07,
1822 * MXU pool 01
1824 enum {
1825 OPC_MXU_S32SLT = 0x00,
1826 OPC_MXU_D16SLT = 0x01,
1827 OPC_MXU_D16AVG = 0x02,
1828 OPC_MXU_D16AVGR = 0x03,
1829 OPC_MXU_Q8AVG = 0x04,
1830 OPC_MXU_Q8AVGR = 0x05,
1831 OPC_MXU_Q8ADD = 0x07,
1835 * MXU pool 02
1837 enum {
1838 OPC_MXU_S32CPS = 0x00,
1839 OPC_MXU_D16CPS = 0x02,
1840 OPC_MXU_Q8ABD = 0x04,
1841 OPC_MXU_Q16SAT = 0x06,
1845 * MXU pool 03
1847 enum {
1848 OPC_MXU_D16MULF = 0x00,
1849 OPC_MXU_D16MULE = 0x01,
1853 * MXU pool 04
1855 enum {
1856 OPC_MXU_S32LDD = 0x00,
1857 OPC_MXU_S32LDDR = 0x01,
1861 * MXU pool 05
1863 enum {
1864 OPC_MXU_S32STD = 0x00,
1865 OPC_MXU_S32STDR = 0x01,
1869 * MXU pool 06
1871 enum {
1872 OPC_MXU_S32LDDV = 0x00,
1873 OPC_MXU_S32LDDVR = 0x01,
1877 * MXU pool 07
1879 enum {
1880 OPC_MXU_S32STDV = 0x00,
1881 OPC_MXU_S32STDVR = 0x01,
1885 * MXU pool 08
1887 enum {
1888 OPC_MXU_S32LDI = 0x00,
1889 OPC_MXU_S32LDIR = 0x01,
1893 * MXU pool 09
1895 enum {
1896 OPC_MXU_S32SDI = 0x00,
1897 OPC_MXU_S32SDIR = 0x01,
1901 * MXU pool 10
1903 enum {
1904 OPC_MXU_S32LDIV = 0x00,
1905 OPC_MXU_S32LDIVR = 0x01,
1909 * MXU pool 11
1911 enum {
1912 OPC_MXU_S32SDIV = 0x00,
1913 OPC_MXU_S32SDIVR = 0x01,
1917 * MXU pool 12
1919 enum {
1920 OPC_MXU_D32ACC = 0x00,
1921 OPC_MXU_D32ACCM = 0x01,
1922 OPC_MXU_D32ASUM = 0x02,
1926 * MXU pool 13
1928 enum {
1929 OPC_MXU_Q16ACC = 0x00,
1930 OPC_MXU_Q16ACCM = 0x01,
1931 OPC_MXU_Q16ASUM = 0x02,
1935 * MXU pool 14
1937 enum {
1938 OPC_MXU_Q8ADDE = 0x00,
1939 OPC_MXU_D8SUM = 0x01,
1940 OPC_MXU_D8SUMC = 0x02,
1944 * MXU pool 15
1946 enum {
1947 OPC_MXU_S32MUL = 0x00,
1948 OPC_MXU_S32MULU = 0x01,
1949 OPC_MXU_S32EXTR = 0x02,
1950 OPC_MXU_S32EXTRV = 0x03,
1954 * MXU pool 16
1956 enum {
1957 OPC_MXU_D32SARW = 0x00,
1958 OPC_MXU_S32ALN = 0x01,
1959 OPC_MXU_S32ALNI = 0x02,
1960 OPC_MXU_S32LUI = 0x03,
1961 OPC_MXU_S32NOR = 0x04,
1962 OPC_MXU_S32AND = 0x05,
1963 OPC_MXU_S32OR = 0x06,
1964 OPC_MXU_S32XOR = 0x07,
1968 * MXU pool 17
1970 enum {
1971 OPC_MXU_LXB = 0x00,
1972 OPC_MXU_LXH = 0x01,
1973 OPC_MXU_LXW = 0x03,
1974 OPC_MXU_LXBU = 0x04,
1975 OPC_MXU_LXHU = 0x05,
1979 * MXU pool 18
1981 enum {
1982 OPC_MXU_D32SLLV = 0x00,
1983 OPC_MXU_D32SLRV = 0x01,
1984 OPC_MXU_D32SARV = 0x03,
1985 OPC_MXU_Q16SLLV = 0x04,
1986 OPC_MXU_Q16SLRV = 0x05,
1987 OPC_MXU_Q16SARV = 0x07,
1991 * MXU pool 19
1993 enum {
1994 OPC_MXU_Q8MUL = 0x00,
1995 OPC_MXU_Q8MULSU = 0x01,
1999 * MXU pool 20
2001 enum {
2002 OPC_MXU_Q8MOVZ = 0x00,
2003 OPC_MXU_Q8MOVN = 0x01,
2004 OPC_MXU_D16MOVZ = 0x02,
2005 OPC_MXU_D16MOVN = 0x03,
2006 OPC_MXU_S32MOVZ = 0x04,
2007 OPC_MXU_S32MOVN = 0x05,
2011 * MXU pool 21
2013 enum {
2014 OPC_MXU_Q8MAC = 0x00,
2015 OPC_MXU_Q8MACSU = 0x01,
2019 * Overview of the TX79-specific instruction set
2020 * =============================================
2022 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2023 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2024 * instructions and certain multimedia instructions (MMIs). These MMIs
2025 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2026 * or sixteen 8-bit paths.
2028 * Reference:
2030 * The Toshiba TX System RISC TX79 Core Architecture manual,
2031 * https://wiki.qemu.org/File:C790.pdf
2033 * Three-Operand Multiply and Multiply-Add (4 instructions)
2034 * --------------------------------------------------------
2035 * MADD [rd,] rs, rt Multiply/Add
2036 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2037 * MULT [rd,] rs, rt Multiply (3-operand)
2038 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2040 * Multiply Instructions for Pipeline 1 (10 instructions)
2041 * ------------------------------------------------------
2042 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2043 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2044 * DIV1 rs, rt Divide Pipeline 1
2045 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2046 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2047 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2048 * MFHI1 rd Move From HI1 Register
2049 * MFLO1 rd Move From LO1 Register
2050 * MTHI1 rs Move To HI1 Register
2051 * MTLO1 rs Move To LO1 Register
2053 * Arithmetic (19 instructions)
2054 * ----------------------------
2055 * PADDB rd, rs, rt Parallel Add Byte
2056 * PSUBB rd, rs, rt Parallel Subtract Byte
2057 * PADDH rd, rs, rt Parallel Add Halfword
2058 * PSUBH rd, rs, rt Parallel Subtract Halfword
2059 * PADDW rd, rs, rt Parallel Add Word
2060 * PSUBW rd, rs, rt Parallel Subtract Word
2061 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2062 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2063 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2064 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2065 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2066 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2067 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2068 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2069 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2070 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2071 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2072 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2073 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2075 * Min/Max (4 instructions)
2076 * ------------------------
2077 * PMAXH rd, rs, rt Parallel Maximum Halfword
2078 * PMINH rd, rs, rt Parallel Minimum Halfword
2079 * PMAXW rd, rs, rt Parallel Maximum Word
2080 * PMINW rd, rs, rt Parallel Minimum Word
2082 * Absolute (2 instructions)
2083 * -------------------------
2084 * PABSH rd, rt Parallel Absolute Halfword
2085 * PABSW rd, rt Parallel Absolute Word
2087 * Logical (4 instructions)
2088 * ------------------------
2089 * PAND rd, rs, rt Parallel AND
2090 * POR rd, rs, rt Parallel OR
2091 * PXOR rd, rs, rt Parallel XOR
2092 * PNOR rd, rs, rt Parallel NOR
2094 * Shift (9 instructions)
2095 * ----------------------
2096 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2097 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2098 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2099 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2100 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2101 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2102 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2103 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2104 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2106 * Compare (6 instructions)
2107 * ------------------------
2108 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2109 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2110 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2111 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2112 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2113 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2115 * LZC (1 instruction)
2116 * -------------------
2117 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2119 * Quadword Load and Store (2 instructions)
2120 * ----------------------------------------
2121 * LQ rt, offset(base) Load Quadword
2122 * SQ rt, offset(base) Store Quadword
2124 * Multiply and Divide (19 instructions)
2125 * -------------------------------------
2126 * PMULTW rd, rs, rt Parallel Multiply Word
2127 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2128 * PDIVW rs, rt Parallel Divide Word
2129 * PDIVUW rs, rt Parallel Divide Unsigned Word
2130 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2131 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2132 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2133 * PMULTH rd, rs, rt Parallel Multiply Halfword
2134 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2135 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2136 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2137 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2138 * PDIVBW rs, rt Parallel Divide Broadcast Word
2139 * PMFHI rd Parallel Move From HI Register
2140 * PMFLO rd Parallel Move From LO Register
2141 * PMTHI rs Parallel Move To HI Register
2142 * PMTLO rs Parallel Move To LO Register
2143 * PMFHL rd Parallel Move From HI/LO Register
2144 * PMTHL rs Parallel Move To HI/LO Register
2146 * Pack/Extend (11 instructions)
2147 * -----------------------------
2148 * PPAC5 rd, rt Parallel Pack to 5 bits
2149 * PPACB rd, rs, rt Parallel Pack to Byte
2150 * PPACH rd, rs, rt Parallel Pack to Halfword
2151 * PPACW rd, rs, rt Parallel Pack to Word
2152 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2153 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2154 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2155 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2156 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2157 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2158 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2160 * Others (16 instructions)
2161 * ------------------------
2162 * PCPYH rd, rt Parallel Copy Halfword
2163 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2164 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2165 * PREVH rd, rt Parallel Reverse Halfword
2166 * PINTH rd, rs, rt Parallel Interleave Halfword
2167 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2168 * PEXEH rd, rt Parallel Exchange Even Halfword
2169 * PEXCH rd, rt Parallel Exchange Center Halfword
2170 * PEXEW rd, rt Parallel Exchange Even Word
2171 * PEXCW rd, rt Parallel Exchange Center Word
2172 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2173 * MFSA rd Move from Shift Amount Register
2174 * MTSA rs Move to Shift Amount Register
2175 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2176 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2177 * PROT3W rd, rt Parallel Rotate 3 Words
2179 * MMI (MultiMedia Instruction) encodings
2180 * ======================================
2182 * MMI instructions encoding table keys:
2184 * * This code is reserved for future use. An attempt to execute it
2185 * causes a Reserved Instruction exception.
2186 * % This code indicates an instruction class. The instruction word
2187 * must be further decoded by examining additional tables that show
2188 * the values for other instruction fields.
2189 * # This code is reserved for the unsupported instructions DMULT,
2190 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2191 * to execute it causes a Reserved Instruction exception.
2193 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2195 * 31 26 0
2196 * +--------+----------------------------------------+
2197 * | opcode | |
2198 * +--------+----------------------------------------+
2200 * opcode bits 28..26
2201 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2202 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2203 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2204 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2205 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2206 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2207 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2208 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2209 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2210 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2211 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2214 enum {
2215 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2216 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2217 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2221 * MMI instructions with opcode field = MMI:
2223 * 31 26 5 0
2224 * +--------+-------------------------------+--------+
2225 * | MMI | |function|
2226 * +--------+-------------------------------+--------+
2228 * function bits 2..0
2229 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2230 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2231 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2232 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2233 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2234 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2235 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2236 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2237 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2238 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2239 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2242 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2243 enum {
2244 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2245 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2246 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2249 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2250 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2251 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2252 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2253 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2254 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2255 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2256 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2257 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2268 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2272 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2274 * 31 26 10 6 5 0
2275 * +--------+----------------------+--------+--------+
2276 * | MMI | |function| MMI0 |
2277 * +--------+----------------------+--------+--------+
2279 * function bits 7..6
2280 * bits | 0 | 1 | 2 | 3
2281 * 10..8 | 00 | 01 | 10 | 11
2282 * -------+-------+-------+-------+-------
2283 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2284 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2285 * 2 010 | PADDB | PSUBB | PCGTB | *
2286 * 3 011 | * | * | * | *
2287 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2288 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2289 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2290 * 7 111 | * | * | PEXT5 | PPAC5
2293 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2294 enum {
2295 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2319 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2323 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2325 * 31 26 10 6 5 0
2326 * +--------+----------------------+--------+--------+
2327 * | MMI | |function| MMI1 |
2328 * +--------+----------------------+--------+--------+
2330 * function bits 7..6
2331 * bits | 0 | 1 | 2 | 3
2332 * 10..8 | 00 | 01 | 10 | 11
2333 * -------+-------+-------+-------+-------
2334 * 0 000 | * | PABSW | PCEQW | PMINW
2335 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2336 * 2 010 | * | * | PCEQB | *
2337 * 3 011 | * | * | * | *
2338 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2339 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2340 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2341 * 7 111 | * | * | * | *
2344 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2345 enum {
2346 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2363 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2367 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2369 * 31 26 10 6 5 0
2370 * +--------+----------------------+--------+--------+
2371 * | MMI | |function| MMI2 |
2372 * +--------+----------------------+--------+--------+
2374 * function bits 7..6
2375 * bits | 0 | 1 | 2 | 3
2376 * 10..8 | 00 | 01 | 10 | 11
2377 * -------+-------+-------+-------+-------
2378 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2379 * 1 001 | PMSUBW| * | * | *
2380 * 2 010 | PMFHI | PMFLO | PINTH | *
2381 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2382 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2383 * 5 101 | PMSUBH| PHMSBH| * | *
2384 * 6 110 | * | * | PEXEH | PREVH
2385 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2388 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2389 enum {
2390 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2411 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2415 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2417 * 31 26 10 6 5 0
2418 * +--------+----------------------+--------+--------+
2419 * | MMI | |function| MMI3 |
2420 * +--------+----------------------+--------+--------+
2422 * function bits 7..6
2423 * bits | 0 | 1 | 2 | 3
2424 * 10..8 | 00 | 01 | 10 | 11
2425 * -------+-------+-------+-------+-------
2426 * 0 000 |PMADDUW| * | * | PSRAVW
2427 * 1 001 | * | * | * | *
2428 * 2 010 | PMTHI | PMTLO | PINTEH| *
2429 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2430 * 4 100 | * | * | POR | PNOR
2431 * 5 101 | * | * | * | *
2432 * 6 110 | * | * | PEXCH | PCPYH
2433 * 7 111 | * | * | PEXCW | *
2436 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2437 enum {
2438 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2450 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2453 /* global register indices */
2454 static TCGv cpu_gpr[32], cpu_PC;
2455 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2456 static TCGv cpu_dspctrl, btarget, bcond;
2457 static TCGv cpu_lladdr, cpu_llval;
2458 static TCGv_i32 hflags;
2459 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2460 static TCGv_i64 fpu_f64[32];
2461 static TCGv_i64 msa_wr_d[64];
2463 #if defined(TARGET_MIPS64)
2464 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2465 static TCGv_i64 cpu_mmr[32];
2466 #endif
2468 #if !defined(TARGET_MIPS64)
2469 /* MXU registers */
2470 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2471 static TCGv mxu_CR;
2472 #endif
2474 #include "exec/gen-icount.h"
2476 #define gen_helper_0e0i(name, arg) do { \
2477 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2478 gen_helper_##name(cpu_env, helper_tmp); \
2479 tcg_temp_free_i32(helper_tmp); \
2480 } while (0)
2482 #define gen_helper_0e1i(name, arg1, arg2) do { \
2483 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2484 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2485 tcg_temp_free_i32(helper_tmp); \
2486 } while (0)
2488 #define gen_helper_1e0i(name, ret, arg1) do { \
2489 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2490 gen_helper_##name(ret, cpu_env, helper_tmp); \
2491 tcg_temp_free_i32(helper_tmp); \
2492 } while (0)
2494 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2495 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2496 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2497 tcg_temp_free_i32(helper_tmp); \
2498 } while (0)
2500 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2501 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2502 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2503 tcg_temp_free_i32(helper_tmp); \
2504 } while (0)
2506 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2507 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2508 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2509 tcg_temp_free_i32(helper_tmp); \
2510 } while (0)
2512 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2513 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2514 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2515 tcg_temp_free_i32(helper_tmp); \
2516 } while (0)
2518 typedef struct DisasContext {
2519 DisasContextBase base;
2520 target_ulong saved_pc;
2521 target_ulong page_start;
2522 uint32_t opcode;
2523 uint64_t insn_flags;
2524 int32_t CP0_Config1;
2525 int32_t CP0_Config2;
2526 int32_t CP0_Config3;
2527 int32_t CP0_Config5;
2528 /* Routine used to access memory */
2529 int mem_idx;
2530 MemOp default_tcg_memop_mask;
2531 uint32_t hflags, saved_hflags;
2532 target_ulong btarget;
2533 bool ulri;
2534 int kscrexist;
2535 bool rxi;
2536 int ie;
2537 bool bi;
2538 bool bp;
2539 uint64_t PAMask;
2540 bool mvh;
2541 bool eva;
2542 bool sc;
2543 int CP0_LLAddr_shift;
2544 bool ps;
2545 bool vp;
2546 bool cmgcr;
2547 bool mrp;
2548 bool nan2008;
2549 bool abs2008;
2550 bool saar;
2551 bool mi;
2552 int gi;
2553 } DisasContext;
2555 #define DISAS_STOP DISAS_TARGET_0
2556 #define DISAS_EXIT DISAS_TARGET_1
2558 static const char * const regnames[] = {
2559 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2560 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2561 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2562 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2565 static const char * const regnames_HI[] = {
2566 "HI0", "HI1", "HI2", "HI3",
2569 static const char * const regnames_LO[] = {
2570 "LO0", "LO1", "LO2", "LO3",
2573 static const char * const fregnames[] = {
2574 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2575 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2576 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2577 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2580 static const char * const msaregnames[] = {
2581 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2582 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2583 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2584 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2585 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2586 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2587 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2588 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2589 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2590 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2591 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2592 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2593 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2594 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2595 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2596 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2599 #if !defined(TARGET_MIPS64)
2600 static const char * const mxuregnames[] = {
2601 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2602 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2604 #endif
2606 #define LOG_DISAS(...) \
2607 do { \
2608 if (MIPS_DEBUG_DISAS) { \
2609 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2611 } while (0)
2613 #define MIPS_INVAL(op) \
2614 do { \
2615 if (MIPS_DEBUG_DISAS) { \
2616 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2617 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2618 ctx->base.pc_next, ctx->opcode, op, \
2619 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2620 ((ctx->opcode >> 16) & 0x1F)); \
2622 } while (0)
2624 /* General purpose registers moves. */
2625 static inline void gen_load_gpr(TCGv t, int reg)
2627 if (reg == 0) {
2628 tcg_gen_movi_tl(t, 0);
2629 } else {
2630 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2634 static inline void gen_store_gpr(TCGv t, int reg)
2636 if (reg != 0) {
2637 tcg_gen_mov_tl(cpu_gpr[reg], t);
2641 /* Moves to/from shadow registers. */
2642 static inline void gen_load_srsgpr(int from, int to)
2644 TCGv t0 = tcg_temp_new();
2646 if (from == 0) {
2647 tcg_gen_movi_tl(t0, 0);
2648 } else {
2649 TCGv_i32 t2 = tcg_temp_new_i32();
2650 TCGv_ptr addr = tcg_temp_new_ptr();
2652 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2653 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2654 tcg_gen_andi_i32(t2, t2, 0xf);
2655 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2656 tcg_gen_ext_i32_ptr(addr, t2);
2657 tcg_gen_add_ptr(addr, cpu_env, addr);
2659 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2660 tcg_temp_free_ptr(addr);
2661 tcg_temp_free_i32(t2);
2663 gen_store_gpr(t0, to);
2664 tcg_temp_free(t0);
2667 static inline void gen_store_srsgpr(int from, int to)
2669 if (to != 0) {
2670 TCGv t0 = tcg_temp_new();
2671 TCGv_i32 t2 = tcg_temp_new_i32();
2672 TCGv_ptr addr = tcg_temp_new_ptr();
2674 gen_load_gpr(t0, from);
2675 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2676 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2677 tcg_gen_andi_i32(t2, t2, 0xf);
2678 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2679 tcg_gen_ext_i32_ptr(addr, t2);
2680 tcg_gen_add_ptr(addr, cpu_env, addr);
2682 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2683 tcg_temp_free_ptr(addr);
2684 tcg_temp_free_i32(t2);
2685 tcg_temp_free(t0);
2689 #if !defined(TARGET_MIPS64)
2690 /* MXU General purpose registers moves. */
2691 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2693 if (reg == 0) {
2694 tcg_gen_movi_tl(t, 0);
2695 } else if (reg <= 15) {
2696 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2700 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2702 if (reg > 0 && reg <= 15) {
2703 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2707 /* MXU control register moves. */
2708 static inline void gen_load_mxu_cr(TCGv t)
2710 tcg_gen_mov_tl(t, mxu_CR);
2713 static inline void gen_store_mxu_cr(TCGv t)
2715 /* TODO: Add handling of RW rules for MXU_CR. */
2716 tcg_gen_mov_tl(mxu_CR, t);
2718 #endif
2721 /* Tests */
2722 static inline void gen_save_pc(target_ulong pc)
2724 tcg_gen_movi_tl(cpu_PC, pc);
2727 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2729 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2730 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2731 gen_save_pc(ctx->base.pc_next);
2732 ctx->saved_pc = ctx->base.pc_next;
2734 if (ctx->hflags != ctx->saved_hflags) {
2735 tcg_gen_movi_i32(hflags, ctx->hflags);
2736 ctx->saved_hflags = ctx->hflags;
2737 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2738 case MIPS_HFLAG_BR:
2739 break;
2740 case MIPS_HFLAG_BC:
2741 case MIPS_HFLAG_BL:
2742 case MIPS_HFLAG_B:
2743 tcg_gen_movi_tl(btarget, ctx->btarget);
2744 break;
2749 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2751 ctx->saved_hflags = ctx->hflags;
2752 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2753 case MIPS_HFLAG_BR:
2754 break;
2755 case MIPS_HFLAG_BC:
2756 case MIPS_HFLAG_BL:
2757 case MIPS_HFLAG_B:
2758 ctx->btarget = env->btarget;
2759 break;
2763 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2765 TCGv_i32 texcp = tcg_const_i32(excp);
2766 TCGv_i32 terr = tcg_const_i32(err);
2767 save_cpu_state(ctx, 1);
2768 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2769 tcg_temp_free_i32(terr);
2770 tcg_temp_free_i32(texcp);
2771 ctx->base.is_jmp = DISAS_NORETURN;
2774 static inline void generate_exception(DisasContext *ctx, int excp)
2776 gen_helper_0e0i(raise_exception, excp);
2779 static inline void generate_exception_end(DisasContext *ctx, int excp)
2781 generate_exception_err(ctx, excp, 0);
2784 /* Floating point register moves. */
2785 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2787 if (ctx->hflags & MIPS_HFLAG_FRE) {
2788 generate_exception(ctx, EXCP_RI);
2790 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2793 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2795 TCGv_i64 t64;
2796 if (ctx->hflags & MIPS_HFLAG_FRE) {
2797 generate_exception(ctx, EXCP_RI);
2799 t64 = tcg_temp_new_i64();
2800 tcg_gen_extu_i32_i64(t64, t);
2801 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2802 tcg_temp_free_i64(t64);
2805 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2807 if (ctx->hflags & MIPS_HFLAG_F64) {
2808 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2809 } else {
2810 gen_load_fpr32(ctx, t, reg | 1);
2814 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2816 if (ctx->hflags & MIPS_HFLAG_F64) {
2817 TCGv_i64 t64 = tcg_temp_new_i64();
2818 tcg_gen_extu_i32_i64(t64, t);
2819 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2820 tcg_temp_free_i64(t64);
2821 } else {
2822 gen_store_fpr32(ctx, t, reg | 1);
2826 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2828 if (ctx->hflags & MIPS_HFLAG_F64) {
2829 tcg_gen_mov_i64(t, fpu_f64[reg]);
2830 } else {
2831 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2835 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2837 if (ctx->hflags & MIPS_HFLAG_F64) {
2838 tcg_gen_mov_i64(fpu_f64[reg], t);
2839 } else {
2840 TCGv_i64 t0;
2841 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2842 t0 = tcg_temp_new_i64();
2843 tcg_gen_shri_i64(t0, t, 32);
2844 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2845 tcg_temp_free_i64(t0);
2849 static inline int get_fp_bit(int cc)
2851 if (cc) {
2852 return 24 + cc;
2853 } else {
2854 return 23;
2858 /* Addresses computation */
2859 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2860 TCGv arg1)
2862 tcg_gen_add_tl(ret, arg0, arg1);
2864 #if defined(TARGET_MIPS64)
2865 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2866 tcg_gen_ext32s_i64(ret, ret);
2868 #endif
2871 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2872 target_long ofs)
2874 tcg_gen_addi_tl(ret, base, ofs);
2876 #if defined(TARGET_MIPS64)
2877 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2878 tcg_gen_ext32s_i64(ret, ret);
2880 #endif
2883 /* Addresses computation (translation time) */
2884 static target_long addr_add(DisasContext *ctx, target_long base,
2885 target_long offset)
2887 target_long sum = base + offset;
2889 #if defined(TARGET_MIPS64)
2890 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2891 sum = (int32_t)sum;
2893 #endif
2894 return sum;
2897 /* Sign-extract the low 32-bits to a target_long. */
2898 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2900 #if defined(TARGET_MIPS64)
2901 tcg_gen_ext32s_i64(ret, arg);
2902 #else
2903 tcg_gen_extrl_i64_i32(ret, arg);
2904 #endif
2907 /* Sign-extract the high 32-bits to a target_long. */
2908 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2910 #if defined(TARGET_MIPS64)
2911 tcg_gen_sari_i64(ret, arg, 32);
2912 #else
2913 tcg_gen_extrh_i64_i32(ret, arg);
2914 #endif
2917 static inline void check_cp0_enabled(DisasContext *ctx)
2919 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2920 generate_exception_err(ctx, EXCP_CpU, 0);
2924 static inline void check_cp1_enabled(DisasContext *ctx)
2926 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2927 generate_exception_err(ctx, EXCP_CpU, 1);
2932 * Verify that the processor is running with COP1X instructions enabled.
2933 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2934 * opcode tables.
2936 static inline void check_cop1x(DisasContext *ctx)
2938 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2939 generate_exception_end(ctx, EXCP_RI);
2944 * Verify that the processor is running with 64-bit floating-point
2945 * operations enabled.
2947 static inline void check_cp1_64bitmode(DisasContext *ctx)
2949 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2950 generate_exception_end(ctx, EXCP_RI);
2955 * Verify if floating point register is valid; an operation is not defined
2956 * if bit 0 of any register specification is set and the FR bit in the
2957 * Status register equals zero, since the register numbers specify an
2958 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2959 * in the Status register equals one, both even and odd register numbers
2960 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2962 * Multiple 64 bit wide registers can be checked by calling
2963 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2965 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2967 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2968 generate_exception_end(ctx, EXCP_RI);
2973 * Verify that the processor is running with DSP instructions enabled.
2974 * This is enabled by CP0 Status register MX(24) bit.
2976 static inline void check_dsp(DisasContext *ctx)
2978 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2979 if (ctx->insn_flags & ASE_DSP) {
2980 generate_exception_end(ctx, EXCP_DSPDIS);
2981 } else {
2982 generate_exception_end(ctx, EXCP_RI);
2987 static inline void check_dsp_r2(DisasContext *ctx)
2989 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2990 if (ctx->insn_flags & ASE_DSP) {
2991 generate_exception_end(ctx, EXCP_DSPDIS);
2992 } else {
2993 generate_exception_end(ctx, EXCP_RI);
2998 static inline void check_dsp_r3(DisasContext *ctx)
3000 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
3001 if (ctx->insn_flags & ASE_DSP) {
3002 generate_exception_end(ctx, EXCP_DSPDIS);
3003 } else {
3004 generate_exception_end(ctx, EXCP_RI);
3010 * This code generates a "reserved instruction" exception if the
3011 * CPU does not support the instruction set corresponding to flags.
3013 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3015 if (unlikely(!(ctx->insn_flags & flags))) {
3016 generate_exception_end(ctx, EXCP_RI);
3021 * This code generates a "reserved instruction" exception if the
3022 * CPU has corresponding flag set which indicates that the instruction
3023 * has been removed.
3025 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3027 if (unlikely(ctx->insn_flags & flags)) {
3028 generate_exception_end(ctx, EXCP_RI);
3033 * The Linux kernel traps certain reserved instruction exceptions to
3034 * emulate the corresponding instructions. QEMU is the kernel in user
3035 * mode, so those traps are emulated by accepting the instructions.
3037 * A reserved instruction exception is generated for flagged CPUs if
3038 * QEMU runs in system mode.
3040 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3042 #ifndef CONFIG_USER_ONLY
3043 check_insn_opc_removed(ctx, flags);
3044 #endif
3048 * This code generates a "reserved instruction" exception if the
3049 * CPU does not support 64-bit paired-single (PS) floating point data type.
3051 static inline void check_ps(DisasContext *ctx)
3053 if (unlikely(!ctx->ps)) {
3054 generate_exception(ctx, EXCP_RI);
3056 check_cp1_64bitmode(ctx);
3059 #ifdef TARGET_MIPS64
3061 * This code generates a "reserved instruction" exception if 64-bit
3062 * instructions are not enabled.
3064 static inline void check_mips_64(DisasContext *ctx)
3066 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3067 generate_exception_end(ctx, EXCP_RI);
3070 #endif
3072 #ifndef CONFIG_USER_ONLY
3073 static inline void check_mvh(DisasContext *ctx)
3075 if (unlikely(!ctx->mvh)) {
3076 generate_exception(ctx, EXCP_RI);
3079 #endif
3082 * This code generates a "reserved instruction" exception if the
3083 * Config5 XNP bit is set.
3085 static inline void check_xnp(DisasContext *ctx)
3087 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3088 generate_exception_end(ctx, EXCP_RI);
3092 #ifndef CONFIG_USER_ONLY
3094 * This code generates a "reserved instruction" exception if the
3095 * Config3 PW bit is NOT set.
3097 static inline void check_pw(DisasContext *ctx)
3099 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3100 generate_exception_end(ctx, EXCP_RI);
3103 #endif
3106 * This code generates a "reserved instruction" exception if the
3107 * Config3 MT bit is NOT set.
3109 static inline void check_mt(DisasContext *ctx)
3111 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3112 generate_exception_end(ctx, EXCP_RI);
3116 #ifndef CONFIG_USER_ONLY
3118 * This code generates a "coprocessor unusable" exception if CP0 is not
3119 * available, and, if that is not the case, generates a "reserved instruction"
3120 * exception if the Config5 MT bit is NOT set. This is needed for availability
3121 * control of some of MT ASE instructions.
3123 static inline void check_cp0_mt(DisasContext *ctx)
3125 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3126 generate_exception_err(ctx, EXCP_CpU, 0);
3127 } else {
3128 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3129 generate_exception_err(ctx, EXCP_RI, 0);
3133 #endif
3136 * This code generates a "reserved instruction" exception if the
3137 * Config5 NMS bit is set.
3139 static inline void check_nms(DisasContext *ctx)
3141 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3142 generate_exception_end(ctx, EXCP_RI);
3147 * This code generates a "reserved instruction" exception if the
3148 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3149 * Config2 TL, and Config5 L2C are unset.
3151 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3153 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3154 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3155 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3156 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3157 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3158 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3159 generate_exception_end(ctx, EXCP_RI);
3164 * This code generates a "reserved instruction" exception if the
3165 * Config5 EVA bit is NOT set.
3167 static inline void check_eva(DisasContext *ctx)
3169 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3170 generate_exception_end(ctx, EXCP_RI);
3176 * Define small wrappers for gen_load_fpr* so that we have a uniform
3177 * calling interface for 32 and 64-bit FPRs. No sense in changing
3178 * all callers for gen_load_fpr32 when we need the CTX parameter for
3179 * this one use.
3181 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3182 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3183 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3184 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3185 int ft, int fs, int cc) \
3187 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3188 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3189 switch (ifmt) { \
3190 case FMT_PS: \
3191 check_ps(ctx); \
3192 break; \
3193 case FMT_D: \
3194 if (abs) { \
3195 check_cop1x(ctx); \
3197 check_cp1_registers(ctx, fs | ft); \
3198 break; \
3199 case FMT_S: \
3200 if (abs) { \
3201 check_cop1x(ctx); \
3203 break; \
3205 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3206 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3207 switch (n) { \
3208 case 0: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3210 break; \
3211 case 1: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3213 break; \
3214 case 2: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3216 break; \
3217 case 3: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3219 break; \
3220 case 4: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3222 break; \
3223 case 5: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3225 break; \
3226 case 6: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3228 break; \
3229 case 7: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3231 break; \
3232 case 8: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3234 break; \
3235 case 9: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3237 break; \
3238 case 10: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3240 break; \
3241 case 11: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3243 break; \
3244 case 12: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3246 break; \
3247 case 13: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3249 break; \
3250 case 14: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3252 break; \
3253 case 15: \
3254 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3255 break; \
3256 default: \
3257 abort(); \
3259 tcg_temp_free_i##bits(fp0); \
3260 tcg_temp_free_i##bits(fp1); \
3263 FOP_CONDS(, 0, d, FMT_D, 64)
3264 FOP_CONDS(abs, 1, d, FMT_D, 64)
3265 FOP_CONDS(, 0, s, FMT_S, 32)
3266 FOP_CONDS(abs, 1, s, FMT_S, 32)
3267 FOP_CONDS(, 0, ps, FMT_PS, 64)
3268 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3269 #undef FOP_CONDS
3271 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3272 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3273 int ft, int fs, int fd) \
3275 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3276 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3277 if (ifmt == FMT_D) { \
3278 check_cp1_registers(ctx, fs | ft | fd); \
3280 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3281 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3282 switch (n) { \
3283 case 0: \
3284 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 1: \
3287 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 2: \
3290 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 3: \
3293 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 4: \
3296 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 5: \
3299 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 6: \
3302 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 7: \
3305 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 8: \
3308 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 9: \
3311 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 10: \
3314 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 11: \
3317 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 12: \
3320 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 13: \
3323 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 14: \
3326 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 15: \
3329 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 17: \
3332 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 18: \
3335 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 19: \
3338 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 25: \
3341 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 26: \
3344 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 case 27: \
3347 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3348 break; \
3349 default: \
3350 abort(); \
3352 STORE; \
3353 tcg_temp_free_i ## bits(fp0); \
3354 tcg_temp_free_i ## bits(fp1); \
3357 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3358 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3359 #undef FOP_CONDNS
3360 #undef gen_ldcmp_fpr32
3361 #undef gen_ldcmp_fpr64
3363 /* load/store instructions. */
3364 #ifdef CONFIG_USER_ONLY
3365 #define OP_LD_ATOMIC(insn, fname) \
3366 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3367 DisasContext *ctx) \
3369 TCGv t0 = tcg_temp_new(); \
3370 tcg_gen_mov_tl(t0, arg1); \
3371 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3372 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3373 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3374 tcg_temp_free(t0); \
3376 #else
3377 #define OP_LD_ATOMIC(insn, fname) \
3378 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3379 DisasContext *ctx) \
3381 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3383 #endif
3384 OP_LD_ATOMIC(ll, ld32s);
3385 #if defined(TARGET_MIPS64)
3386 OP_LD_ATOMIC(lld, ld64);
3387 #endif
3388 #undef OP_LD_ATOMIC
3390 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3391 int base, int offset)
3393 if (base == 0) {
3394 tcg_gen_movi_tl(addr, offset);
3395 } else if (offset == 0) {
3396 gen_load_gpr(addr, base);
3397 } else {
3398 tcg_gen_movi_tl(addr, offset);
3399 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3403 static target_ulong pc_relative_pc(DisasContext *ctx)
3405 target_ulong pc = ctx->base.pc_next;
3407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3408 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3410 pc -= branch_bytes;
3413 pc &= ~(target_ulong)3;
3414 return pc;
3417 /* Load */
3418 static void gen_ld(DisasContext *ctx, uint32_t opc,
3419 int rt, int base, int offset)
3421 TCGv t0, t1, t2;
3422 int mem_idx = ctx->mem_idx;
3424 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3426 * Loongson CPU uses a load to zero register for prefetch.
3427 * We emulate it as a NOP. On other CPU we must perform the
3428 * actual memory access.
3430 return;
3433 t0 = tcg_temp_new();
3434 gen_base_offset_addr(ctx, t0, base, offset);
3436 switch (opc) {
3437 #if defined(TARGET_MIPS64)
3438 case OPC_LWU:
3439 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3440 ctx->default_tcg_memop_mask);
3441 gen_store_gpr(t0, rt);
3442 break;
3443 case OPC_LD:
3444 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3445 ctx->default_tcg_memop_mask);
3446 gen_store_gpr(t0, rt);
3447 break;
3448 case OPC_LLD:
3449 case R6_OPC_LLD:
3450 op_ld_lld(t0, t0, mem_idx, ctx);
3451 gen_store_gpr(t0, rt);
3452 break;
3453 case OPC_LDL:
3454 t1 = tcg_temp_new();
3456 * Do a byte access to possibly trigger a page
3457 * fault with the unaligned address.
3459 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3460 tcg_gen_andi_tl(t1, t0, 7);
3461 #ifndef TARGET_WORDS_BIGENDIAN
3462 tcg_gen_xori_tl(t1, t1, 7);
3463 #endif
3464 tcg_gen_shli_tl(t1, t1, 3);
3465 tcg_gen_andi_tl(t0, t0, ~7);
3466 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3467 tcg_gen_shl_tl(t0, t0, t1);
3468 t2 = tcg_const_tl(-1);
3469 tcg_gen_shl_tl(t2, t2, t1);
3470 gen_load_gpr(t1, rt);
3471 tcg_gen_andc_tl(t1, t1, t2);
3472 tcg_temp_free(t2);
3473 tcg_gen_or_tl(t0, t0, t1);
3474 tcg_temp_free(t1);
3475 gen_store_gpr(t0, rt);
3476 break;
3477 case OPC_LDR:
3478 t1 = tcg_temp_new();
3480 * Do a byte access to possibly trigger a page
3481 * fault with the unaligned address.
3483 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3484 tcg_gen_andi_tl(t1, t0, 7);
3485 #ifdef TARGET_WORDS_BIGENDIAN
3486 tcg_gen_xori_tl(t1, t1, 7);
3487 #endif
3488 tcg_gen_shli_tl(t1, t1, 3);
3489 tcg_gen_andi_tl(t0, t0, ~7);
3490 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3491 tcg_gen_shr_tl(t0, t0, t1);
3492 tcg_gen_xori_tl(t1, t1, 63);
3493 t2 = tcg_const_tl(0xfffffffffffffffeull);
3494 tcg_gen_shl_tl(t2, t2, t1);
3495 gen_load_gpr(t1, rt);
3496 tcg_gen_and_tl(t1, t1, t2);
3497 tcg_temp_free(t2);
3498 tcg_gen_or_tl(t0, t0, t1);
3499 tcg_temp_free(t1);
3500 gen_store_gpr(t0, rt);
3501 break;
3502 case OPC_LDPC:
3503 t1 = tcg_const_tl(pc_relative_pc(ctx));
3504 gen_op_addr_add(ctx, t0, t0, t1);
3505 tcg_temp_free(t1);
3506 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3507 gen_store_gpr(t0, rt);
3508 break;
3509 #endif
3510 case OPC_LWPC:
3511 t1 = tcg_const_tl(pc_relative_pc(ctx));
3512 gen_op_addr_add(ctx, t0, t0, t1);
3513 tcg_temp_free(t1);
3514 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3515 gen_store_gpr(t0, rt);
3516 break;
3517 case OPC_LWE:
3518 mem_idx = MIPS_HFLAG_UM;
3519 /* fall through */
3520 case OPC_LW:
3521 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3522 ctx->default_tcg_memop_mask);
3523 gen_store_gpr(t0, rt);
3524 break;
3525 case OPC_LHE:
3526 mem_idx = MIPS_HFLAG_UM;
3527 /* fall through */
3528 case OPC_LH:
3529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3530 ctx->default_tcg_memop_mask);
3531 gen_store_gpr(t0, rt);
3532 break;
3533 case OPC_LHUE:
3534 mem_idx = MIPS_HFLAG_UM;
3535 /* fall through */
3536 case OPC_LHU:
3537 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3538 ctx->default_tcg_memop_mask);
3539 gen_store_gpr(t0, rt);
3540 break;
3541 case OPC_LBE:
3542 mem_idx = MIPS_HFLAG_UM;
3543 /* fall through */
3544 case OPC_LB:
3545 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3546 gen_store_gpr(t0, rt);
3547 break;
3548 case OPC_LBUE:
3549 mem_idx = MIPS_HFLAG_UM;
3550 /* fall through */
3551 case OPC_LBU:
3552 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3553 gen_store_gpr(t0, rt);
3554 break;
3555 case OPC_LWLE:
3556 mem_idx = MIPS_HFLAG_UM;
3557 /* fall through */
3558 case OPC_LWL:
3559 t1 = tcg_temp_new();
3561 * Do a byte access to possibly trigger a page
3562 * fault with the unaligned address.
3564 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3565 tcg_gen_andi_tl(t1, t0, 3);
3566 #ifndef TARGET_WORDS_BIGENDIAN
3567 tcg_gen_xori_tl(t1, t1, 3);
3568 #endif
3569 tcg_gen_shli_tl(t1, t1, 3);
3570 tcg_gen_andi_tl(t0, t0, ~3);
3571 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3572 tcg_gen_shl_tl(t0, t0, t1);
3573 t2 = tcg_const_tl(-1);
3574 tcg_gen_shl_tl(t2, t2, t1);
3575 gen_load_gpr(t1, rt);
3576 tcg_gen_andc_tl(t1, t1, t2);
3577 tcg_temp_free(t2);
3578 tcg_gen_or_tl(t0, t0, t1);
3579 tcg_temp_free(t1);
3580 tcg_gen_ext32s_tl(t0, t0);
3581 gen_store_gpr(t0, rt);
3582 break;
3583 case OPC_LWRE:
3584 mem_idx = MIPS_HFLAG_UM;
3585 /* fall through */
3586 case OPC_LWR:
3587 t1 = tcg_temp_new();
3589 * Do a byte access to possibly trigger a page
3590 * fault with the unaligned address.
3592 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3593 tcg_gen_andi_tl(t1, t0, 3);
3594 #ifdef TARGET_WORDS_BIGENDIAN
3595 tcg_gen_xori_tl(t1, t1, 3);
3596 #endif
3597 tcg_gen_shli_tl(t1, t1, 3);
3598 tcg_gen_andi_tl(t0, t0, ~3);
3599 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3600 tcg_gen_shr_tl(t0, t0, t1);
3601 tcg_gen_xori_tl(t1, t1, 31);
3602 t2 = tcg_const_tl(0xfffffffeull);
3603 tcg_gen_shl_tl(t2, t2, t1);
3604 gen_load_gpr(t1, rt);
3605 tcg_gen_and_tl(t1, t1, t2);
3606 tcg_temp_free(t2);
3607 tcg_gen_or_tl(t0, t0, t1);
3608 tcg_temp_free(t1);
3609 tcg_gen_ext32s_tl(t0, t0);
3610 gen_store_gpr(t0, rt);
3611 break;
3612 case OPC_LLE:
3613 mem_idx = MIPS_HFLAG_UM;
3614 /* fall through */
3615 case OPC_LL:
3616 case R6_OPC_LL:
3617 op_ld_ll(t0, t0, mem_idx, ctx);
3618 gen_store_gpr(t0, rt);
3619 break;
3621 tcg_temp_free(t0);
3624 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3625 uint32_t reg1, uint32_t reg2)
3627 TCGv taddr = tcg_temp_new();
3628 TCGv_i64 tval = tcg_temp_new_i64();
3629 TCGv tmp1 = tcg_temp_new();
3630 TCGv tmp2 = tcg_temp_new();
3632 gen_base_offset_addr(ctx, taddr, base, offset);
3633 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3634 #ifdef TARGET_WORDS_BIGENDIAN
3635 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3636 #else
3637 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3638 #endif
3639 gen_store_gpr(tmp1, reg1);
3640 tcg_temp_free(tmp1);
3641 gen_store_gpr(tmp2, reg2);
3642 tcg_temp_free(tmp2);
3643 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3644 tcg_temp_free_i64(tval);
3645 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3646 tcg_temp_free(taddr);
3649 /* Store */
3650 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3651 int base, int offset)
3653 TCGv t0 = tcg_temp_new();
3654 TCGv t1 = tcg_temp_new();
3655 int mem_idx = ctx->mem_idx;
3657 gen_base_offset_addr(ctx, t0, base, offset);
3658 gen_load_gpr(t1, rt);
3659 switch (opc) {
3660 #if defined(TARGET_MIPS64)
3661 case OPC_SD:
3662 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3663 ctx->default_tcg_memop_mask);
3664 break;
3665 case OPC_SDL:
3666 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3667 break;
3668 case OPC_SDR:
3669 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3670 break;
3671 #endif
3672 case OPC_SWE:
3673 mem_idx = MIPS_HFLAG_UM;
3674 /* fall through */
3675 case OPC_SW:
3676 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3677 ctx->default_tcg_memop_mask);
3678 break;
3679 case OPC_SHE:
3680 mem_idx = MIPS_HFLAG_UM;
3681 /* fall through */
3682 case OPC_SH:
3683 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3684 ctx->default_tcg_memop_mask);
3685 break;
3686 case OPC_SBE:
3687 mem_idx = MIPS_HFLAG_UM;
3688 /* fall through */
3689 case OPC_SB:
3690 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3691 break;
3692 case OPC_SWLE:
3693 mem_idx = MIPS_HFLAG_UM;
3694 /* fall through */
3695 case OPC_SWL:
3696 gen_helper_0e2i(swl, t1, t0, mem_idx);
3697 break;
3698 case OPC_SWRE:
3699 mem_idx = MIPS_HFLAG_UM;
3700 /* fall through */
3701 case OPC_SWR:
3702 gen_helper_0e2i(swr, t1, t0, mem_idx);
3703 break;
3705 tcg_temp_free(t0);
3706 tcg_temp_free(t1);
3710 /* Store conditional */
3711 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3712 MemOp tcg_mo, bool eva)
3714 TCGv addr, t0, val;
3715 TCGLabel *l1 = gen_new_label();
3716 TCGLabel *done = gen_new_label();
3718 t0 = tcg_temp_new();
3719 addr = tcg_temp_new();
3720 /* compare the address against that of the preceeding LL */
3721 gen_base_offset_addr(ctx, addr, base, offset);
3722 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3723 tcg_temp_free(addr);
3724 tcg_gen_movi_tl(t0, 0);
3725 gen_store_gpr(t0, rt);
3726 tcg_gen_br(done);
3728 gen_set_label(l1);
3729 /* generate cmpxchg */
3730 val = tcg_temp_new();
3731 gen_load_gpr(val, rt);
3732 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3733 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3734 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3735 gen_store_gpr(t0, rt);
3736 tcg_temp_free(val);
3738 gen_set_label(done);
3739 tcg_temp_free(t0);
3743 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3744 uint32_t reg1, uint32_t reg2, bool eva)
3746 TCGv taddr = tcg_temp_local_new();
3747 TCGv lladdr = tcg_temp_local_new();
3748 TCGv_i64 tval = tcg_temp_new_i64();
3749 TCGv_i64 llval = tcg_temp_new_i64();
3750 TCGv_i64 val = tcg_temp_new_i64();
3751 TCGv tmp1 = tcg_temp_new();
3752 TCGv tmp2 = tcg_temp_new();
3753 TCGLabel *lab_fail = gen_new_label();
3754 TCGLabel *lab_done = gen_new_label();
3756 gen_base_offset_addr(ctx, taddr, base, offset);
3758 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3759 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3761 gen_load_gpr(tmp1, reg1);
3762 gen_load_gpr(tmp2, reg2);
3764 #ifdef TARGET_WORDS_BIGENDIAN
3765 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3766 #else
3767 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3768 #endif
3770 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3771 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3772 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3773 if (reg1 != 0) {
3774 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3776 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3778 gen_set_label(lab_fail);
3780 if (reg1 != 0) {
3781 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3783 gen_set_label(lab_done);
3784 tcg_gen_movi_tl(lladdr, -1);
3785 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3788 /* Load and store */
3789 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3790 TCGv t0)
3793 * Don't do NOP if destination is zero: we must perform the actual
3794 * memory access.
3796 switch (opc) {
3797 case OPC_LWC1:
3799 TCGv_i32 fp0 = tcg_temp_new_i32();
3800 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3801 ctx->default_tcg_memop_mask);
3802 gen_store_fpr32(ctx, fp0, ft);
3803 tcg_temp_free_i32(fp0);
3805 break;
3806 case OPC_SWC1:
3808 TCGv_i32 fp0 = tcg_temp_new_i32();
3809 gen_load_fpr32(ctx, fp0, ft);
3810 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3811 ctx->default_tcg_memop_mask);
3812 tcg_temp_free_i32(fp0);
3814 break;
3815 case OPC_LDC1:
3817 TCGv_i64 fp0 = tcg_temp_new_i64();
3818 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3819 ctx->default_tcg_memop_mask);
3820 gen_store_fpr64(ctx, fp0, ft);
3821 tcg_temp_free_i64(fp0);
3823 break;
3824 case OPC_SDC1:
3826 TCGv_i64 fp0 = tcg_temp_new_i64();
3827 gen_load_fpr64(ctx, fp0, ft);
3828 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3829 ctx->default_tcg_memop_mask);
3830 tcg_temp_free_i64(fp0);
3832 break;
3833 default:
3834 MIPS_INVAL("flt_ldst");
3835 generate_exception_end(ctx, EXCP_RI);
3836 break;
3840 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3841 int rs, int16_t imm)
3843 TCGv t0 = tcg_temp_new();
3845 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3846 check_cp1_enabled(ctx);
3847 switch (op) {
3848 case OPC_LDC1:
3849 case OPC_SDC1:
3850 check_insn(ctx, ISA_MIPS2);
3851 /* Fallthrough */
3852 default:
3853 gen_base_offset_addr(ctx, t0, rs, imm);
3854 gen_flt_ldst(ctx, op, rt, t0);
3856 } else {
3857 generate_exception_err(ctx, EXCP_CpU, 1);
3859 tcg_temp_free(t0);
3862 /* Arithmetic with immediate operand */
3863 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3864 int rt, int rs, int imm)
3866 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3868 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3870 * If no destination, treat it as a NOP.
3871 * For addi, we must generate the overflow exception when needed.
3873 return;
3875 switch (opc) {
3876 case OPC_ADDI:
3878 TCGv t0 = tcg_temp_local_new();
3879 TCGv t1 = tcg_temp_new();
3880 TCGv t2 = tcg_temp_new();
3881 TCGLabel *l1 = gen_new_label();
3883 gen_load_gpr(t1, rs);
3884 tcg_gen_addi_tl(t0, t1, uimm);
3885 tcg_gen_ext32s_tl(t0, t0);
3887 tcg_gen_xori_tl(t1, t1, ~uimm);
3888 tcg_gen_xori_tl(t2, t0, uimm);
3889 tcg_gen_and_tl(t1, t1, t2);
3890 tcg_temp_free(t2);
3891 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3892 tcg_temp_free(t1);
3893 /* operands of same sign, result different sign */
3894 generate_exception(ctx, EXCP_OVERFLOW);
3895 gen_set_label(l1);
3896 tcg_gen_ext32s_tl(t0, t0);
3897 gen_store_gpr(t0, rt);
3898 tcg_temp_free(t0);
3900 break;
3901 case OPC_ADDIU:
3902 if (rs != 0) {
3903 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3904 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3908 break;
3909 #if defined(TARGET_MIPS64)
3910 case OPC_DADDI:
3912 TCGv t0 = tcg_temp_local_new();
3913 TCGv t1 = tcg_temp_new();
3914 TCGv t2 = tcg_temp_new();
3915 TCGLabel *l1 = gen_new_label();
3917 gen_load_gpr(t1, rs);
3918 tcg_gen_addi_tl(t0, t1, uimm);
3920 tcg_gen_xori_tl(t1, t1, ~uimm);
3921 tcg_gen_xori_tl(t2, t0, uimm);
3922 tcg_gen_and_tl(t1, t1, t2);
3923 tcg_temp_free(t2);
3924 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3925 tcg_temp_free(t1);
3926 /* operands of same sign, result different sign */
3927 generate_exception(ctx, EXCP_OVERFLOW);
3928 gen_set_label(l1);
3929 gen_store_gpr(t0, rt);
3930 tcg_temp_free(t0);
3932 break;
3933 case OPC_DADDIU:
3934 if (rs != 0) {
3935 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3936 } else {
3937 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3939 break;
3940 #endif
3944 /* Logic with immediate operand */
3945 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3946 int rt, int rs, int16_t imm)
3948 target_ulong uimm;
3950 if (rt == 0) {
3951 /* If no destination, treat it as a NOP. */
3952 return;
3954 uimm = (uint16_t)imm;
3955 switch (opc) {
3956 case OPC_ANDI:
3957 if (likely(rs != 0)) {
3958 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3959 } else {
3960 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3962 break;
3963 case OPC_ORI:
3964 if (rs != 0) {
3965 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3966 } else {
3967 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3969 break;
3970 case OPC_XORI:
3971 if (likely(rs != 0)) {
3972 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3973 } else {
3974 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3976 break;
3977 case OPC_LUI:
3978 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3979 /* OPC_AUI */
3980 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3981 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3982 } else {
3983 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3985 break;
3987 default:
3988 break;
3992 /* Set on less than with immediate operand */
3993 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3994 int rt, int rs, int16_t imm)
3996 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3997 TCGv t0;
3999 if (rt == 0) {
4000 /* If no destination, treat it as a NOP. */
4001 return;
4003 t0 = tcg_temp_new();
4004 gen_load_gpr(t0, rs);
4005 switch (opc) {
4006 case OPC_SLTI:
4007 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4008 break;
4009 case OPC_SLTIU:
4010 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4011 break;
4013 tcg_temp_free(t0);
4016 /* Shifts with immediate operand */
4017 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4018 int rt, int rs, int16_t imm)
4020 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4021 TCGv t0;
4023 if (rt == 0) {
4024 /* If no destination, treat it as a NOP. */
4025 return;
4028 t0 = tcg_temp_new();
4029 gen_load_gpr(t0, rs);
4030 switch (opc) {
4031 case OPC_SLL:
4032 tcg_gen_shli_tl(t0, t0, uimm);
4033 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4034 break;
4035 case OPC_SRA:
4036 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4037 break;
4038 case OPC_SRL:
4039 if (uimm != 0) {
4040 tcg_gen_ext32u_tl(t0, t0);
4041 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4042 } else {
4043 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4045 break;
4046 case OPC_ROTR:
4047 if (uimm != 0) {
4048 TCGv_i32 t1 = tcg_temp_new_i32();
4050 tcg_gen_trunc_tl_i32(t1, t0);
4051 tcg_gen_rotri_i32(t1, t1, uimm);
4052 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4053 tcg_temp_free_i32(t1);
4054 } else {
4055 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4057 break;
4058 #if defined(TARGET_MIPS64)
4059 case OPC_DSLL:
4060 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4061 break;
4062 case OPC_DSRA:
4063 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4064 break;
4065 case OPC_DSRL:
4066 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4067 break;
4068 case OPC_DROTR:
4069 if (uimm != 0) {
4070 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4071 } else {
4072 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4074 break;
4075 case OPC_DSLL32:
4076 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4077 break;
4078 case OPC_DSRA32:
4079 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4080 break;
4081 case OPC_DSRL32:
4082 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4083 break;
4084 case OPC_DROTR32:
4085 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4086 break;
4087 #endif
4089 tcg_temp_free(t0);
4092 /* Arithmetic */
4093 static void gen_arith(DisasContext *ctx, uint32_t opc,
4094 int rd, int rs, int rt)
4096 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4097 && opc != OPC_DADD && opc != OPC_DSUB) {
4099 * If no destination, treat it as a NOP.
4100 * For add & sub, we must generate the overflow exception when needed.
4102 return;
4105 switch (opc) {
4106 case OPC_ADD:
4108 TCGv t0 = tcg_temp_local_new();
4109 TCGv t1 = tcg_temp_new();
4110 TCGv t2 = tcg_temp_new();
4111 TCGLabel *l1 = gen_new_label();
4113 gen_load_gpr(t1, rs);
4114 gen_load_gpr(t2, rt);
4115 tcg_gen_add_tl(t0, t1, t2);
4116 tcg_gen_ext32s_tl(t0, t0);
4117 tcg_gen_xor_tl(t1, t1, t2);
4118 tcg_gen_xor_tl(t2, t0, t2);
4119 tcg_gen_andc_tl(t1, t2, t1);
4120 tcg_temp_free(t2);
4121 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4122 tcg_temp_free(t1);
4123 /* operands of same sign, result different sign */
4124 generate_exception(ctx, EXCP_OVERFLOW);
4125 gen_set_label(l1);
4126 gen_store_gpr(t0, rd);
4127 tcg_temp_free(t0);
4129 break;
4130 case OPC_ADDU:
4131 if (rs != 0 && rt != 0) {
4132 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4133 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4134 } else if (rs == 0 && rt != 0) {
4135 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4136 } else if (rs != 0 && rt == 0) {
4137 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4138 } else {
4139 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4141 break;
4142 case OPC_SUB:
4144 TCGv t0 = tcg_temp_local_new();
4145 TCGv t1 = tcg_temp_new();
4146 TCGv t2 = tcg_temp_new();
4147 TCGLabel *l1 = gen_new_label();
4149 gen_load_gpr(t1, rs);
4150 gen_load_gpr(t2, rt);
4151 tcg_gen_sub_tl(t0, t1, t2);
4152 tcg_gen_ext32s_tl(t0, t0);
4153 tcg_gen_xor_tl(t2, t1, t2);
4154 tcg_gen_xor_tl(t1, t0, t1);
4155 tcg_gen_and_tl(t1, t1, t2);
4156 tcg_temp_free(t2);
4157 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4158 tcg_temp_free(t1);
4160 * operands of different sign, first operand and the result
4161 * of different sign
4163 generate_exception(ctx, EXCP_OVERFLOW);
4164 gen_set_label(l1);
4165 gen_store_gpr(t0, rd);
4166 tcg_temp_free(t0);
4168 break;
4169 case OPC_SUBU:
4170 if (rs != 0 && rt != 0) {
4171 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4173 } else if (rs == 0 && rt != 0) {
4174 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4175 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4176 } else if (rs != 0 && rt == 0) {
4177 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4178 } else {
4179 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4181 break;
4182 #if defined(TARGET_MIPS64)
4183 case OPC_DADD:
4185 TCGv t0 = tcg_temp_local_new();
4186 TCGv t1 = tcg_temp_new();
4187 TCGv t2 = tcg_temp_new();
4188 TCGLabel *l1 = gen_new_label();
4190 gen_load_gpr(t1, rs);
4191 gen_load_gpr(t2, rt);
4192 tcg_gen_add_tl(t0, t1, t2);
4193 tcg_gen_xor_tl(t1, t1, t2);
4194 tcg_gen_xor_tl(t2, t0, t2);
4195 tcg_gen_andc_tl(t1, t2, t1);
4196 tcg_temp_free(t2);
4197 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4198 tcg_temp_free(t1);
4199 /* operands of same sign, result different sign */
4200 generate_exception(ctx, EXCP_OVERFLOW);
4201 gen_set_label(l1);
4202 gen_store_gpr(t0, rd);
4203 tcg_temp_free(t0);
4205 break;
4206 case OPC_DADDU:
4207 if (rs != 0 && rt != 0) {
4208 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4209 } else if (rs == 0 && rt != 0) {
4210 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4211 } else if (rs != 0 && rt == 0) {
4212 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4213 } else {
4214 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4216 break;
4217 case OPC_DSUB:
4219 TCGv t0 = tcg_temp_local_new();
4220 TCGv t1 = tcg_temp_new();
4221 TCGv t2 = tcg_temp_new();
4222 TCGLabel *l1 = gen_new_label();
4224 gen_load_gpr(t1, rs);
4225 gen_load_gpr(t2, rt);
4226 tcg_gen_sub_tl(t0, t1, t2);
4227 tcg_gen_xor_tl(t2, t1, t2);
4228 tcg_gen_xor_tl(t1, t0, t1);
4229 tcg_gen_and_tl(t1, t1, t2);
4230 tcg_temp_free(t2);
4231 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4232 tcg_temp_free(t1);
4234 * Operands of different sign, first operand and result different
4235 * sign.
4237 generate_exception(ctx, EXCP_OVERFLOW);
4238 gen_set_label(l1);
4239 gen_store_gpr(t0, rd);
4240 tcg_temp_free(t0);
4242 break;
4243 case OPC_DSUBU:
4244 if (rs != 0 && rt != 0) {
4245 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4246 } else if (rs == 0 && rt != 0) {
4247 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4248 } else if (rs != 0 && rt == 0) {
4249 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4250 } else {
4251 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4253 break;
4254 #endif
4255 case OPC_MUL:
4256 if (likely(rs != 0 && rt != 0)) {
4257 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4258 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4259 } else {
4260 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4262 break;
4266 /* Conditional move */
4267 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4268 int rd, int rs, int rt)
4270 TCGv t0, t1, t2;
4272 if (rd == 0) {
4273 /* If no destination, treat it as a NOP. */
4274 return;
4277 t0 = tcg_temp_new();
4278 gen_load_gpr(t0, rt);
4279 t1 = tcg_const_tl(0);
4280 t2 = tcg_temp_new();
4281 gen_load_gpr(t2, rs);
4282 switch (opc) {
4283 case OPC_MOVN:
4284 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4285 break;
4286 case OPC_MOVZ:
4287 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4288 break;
4289 case OPC_SELNEZ:
4290 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4291 break;
4292 case OPC_SELEQZ:
4293 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4294 break;
4296 tcg_temp_free(t2);
4297 tcg_temp_free(t1);
4298 tcg_temp_free(t0);
4301 /* Logic */
4302 static void gen_logic(DisasContext *ctx, uint32_t opc,
4303 int rd, int rs, int rt)
4305 if (rd == 0) {
4306 /* If no destination, treat it as a NOP. */
4307 return;
4310 switch (opc) {
4311 case OPC_AND:
4312 if (likely(rs != 0 && rt != 0)) {
4313 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4314 } else {
4315 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4317 break;
4318 case OPC_NOR:
4319 if (rs != 0 && rt != 0) {
4320 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4321 } else if (rs == 0 && rt != 0) {
4322 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4323 } else if (rs != 0 && rt == 0) {
4324 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4325 } else {
4326 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4328 break;
4329 case OPC_OR:
4330 if (likely(rs != 0 && rt != 0)) {
4331 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4332 } else if (rs == 0 && rt != 0) {
4333 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4334 } else if (rs != 0 && rt == 0) {
4335 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4336 } else {
4337 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4339 break;
4340 case OPC_XOR:
4341 if (likely(rs != 0 && rt != 0)) {
4342 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4343 } else if (rs == 0 && rt != 0) {
4344 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4345 } else if (rs != 0 && rt == 0) {
4346 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4347 } else {
4348 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4350 break;
4354 /* Set on lower than */
4355 static void gen_slt(DisasContext *ctx, uint32_t opc,
4356 int rd, int rs, int rt)
4358 TCGv t0, t1;
4360 if (rd == 0) {
4361 /* If no destination, treat it as a NOP. */
4362 return;
4365 t0 = tcg_temp_new();
4366 t1 = tcg_temp_new();
4367 gen_load_gpr(t0, rs);
4368 gen_load_gpr(t1, rt);
4369 switch (opc) {
4370 case OPC_SLT:
4371 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4372 break;
4373 case OPC_SLTU:
4374 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4375 break;
4377 tcg_temp_free(t0);
4378 tcg_temp_free(t1);
4381 /* Shifts */
4382 static void gen_shift(DisasContext *ctx, uint32_t opc,
4383 int rd, int rs, int rt)
4385 TCGv t0, t1;
4387 if (rd == 0) {
4389 * If no destination, treat it as a NOP.
4390 * For add & sub, we must generate the overflow exception when needed.
4392 return;
4395 t0 = tcg_temp_new();
4396 t1 = tcg_temp_new();
4397 gen_load_gpr(t0, rs);
4398 gen_load_gpr(t1, rt);
4399 switch (opc) {
4400 case OPC_SLLV:
4401 tcg_gen_andi_tl(t0, t0, 0x1f);
4402 tcg_gen_shl_tl(t0, t1, t0);
4403 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4404 break;
4405 case OPC_SRAV:
4406 tcg_gen_andi_tl(t0, t0, 0x1f);
4407 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4408 break;
4409 case OPC_SRLV:
4410 tcg_gen_ext32u_tl(t1, t1);
4411 tcg_gen_andi_tl(t0, t0, 0x1f);
4412 tcg_gen_shr_tl(t0, t1, t0);
4413 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4414 break;
4415 case OPC_ROTRV:
4417 TCGv_i32 t2 = tcg_temp_new_i32();
4418 TCGv_i32 t3 = tcg_temp_new_i32();
4420 tcg_gen_trunc_tl_i32(t2, t0);
4421 tcg_gen_trunc_tl_i32(t3, t1);
4422 tcg_gen_andi_i32(t2, t2, 0x1f);
4423 tcg_gen_rotr_i32(t2, t3, t2);
4424 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4425 tcg_temp_free_i32(t2);
4426 tcg_temp_free_i32(t3);
4428 break;
4429 #if defined(TARGET_MIPS64)
4430 case OPC_DSLLV:
4431 tcg_gen_andi_tl(t0, t0, 0x3f);
4432 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4433 break;
4434 case OPC_DSRAV:
4435 tcg_gen_andi_tl(t0, t0, 0x3f);
4436 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4437 break;
4438 case OPC_DSRLV:
4439 tcg_gen_andi_tl(t0, t0, 0x3f);
4440 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4441 break;
4442 case OPC_DROTRV:
4443 tcg_gen_andi_tl(t0, t0, 0x3f);
4444 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4445 break;
4446 #endif
4448 tcg_temp_free(t0);
4449 tcg_temp_free(t1);
4452 #if defined(TARGET_MIPS64)
4453 /* Copy GPR to and from TX79 HI1/LO1 register. */
4454 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4456 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4457 /* Treat as NOP. */
4458 return;
4461 switch (opc) {
4462 case MMI_OPC_MFHI1:
4463 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4464 break;
4465 case MMI_OPC_MFLO1:
4466 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4467 break;
4468 case MMI_OPC_MTHI1:
4469 if (reg != 0) {
4470 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4471 } else {
4472 tcg_gen_movi_tl(cpu_HI[1], 0);
4474 break;
4475 case MMI_OPC_MTLO1:
4476 if (reg != 0) {
4477 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4478 } else {
4479 tcg_gen_movi_tl(cpu_LO[1], 0);
4481 break;
4482 default:
4483 MIPS_INVAL("mfthilo1 TX79");
4484 generate_exception_end(ctx, EXCP_RI);
4485 break;
4488 #endif
4490 /* Arithmetic on HI/LO registers */
4491 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4493 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4494 /* Treat as NOP. */
4495 return;
4498 if (acc != 0) {
4499 check_dsp(ctx);
4502 switch (opc) {
4503 case OPC_MFHI:
4504 #if defined(TARGET_MIPS64)
4505 if (acc != 0) {
4506 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4507 } else
4508 #endif
4510 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4512 break;
4513 case OPC_MFLO:
4514 #if defined(TARGET_MIPS64)
4515 if (acc != 0) {
4516 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4517 } else
4518 #endif
4520 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4522 break;
4523 case OPC_MTHI:
4524 if (reg != 0) {
4525 #if defined(TARGET_MIPS64)
4526 if (acc != 0) {
4527 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4528 } else
4529 #endif
4531 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4533 } else {
4534 tcg_gen_movi_tl(cpu_HI[acc], 0);
4536 break;
4537 case OPC_MTLO:
4538 if (reg != 0) {
4539 #if defined(TARGET_MIPS64)
4540 if (acc != 0) {
4541 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4542 } else
4543 #endif
4545 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4547 } else {
4548 tcg_gen_movi_tl(cpu_LO[acc], 0);
4550 break;
4554 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4555 MemOp memop)
4557 TCGv t0 = tcg_const_tl(addr);
4558 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4559 gen_store_gpr(t0, reg);
4560 tcg_temp_free(t0);
4563 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4564 int rs)
4566 target_long offset;
4567 target_long addr;
4569 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4570 case OPC_ADDIUPC:
4571 if (rs != 0) {
4572 offset = sextract32(ctx->opcode << 2, 0, 21);
4573 addr = addr_add(ctx, pc, offset);
4574 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4576 break;
4577 case R6_OPC_LWPC:
4578 offset = sextract32(ctx->opcode << 2, 0, 21);
4579 addr = addr_add(ctx, pc, offset);
4580 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4581 break;
4582 #if defined(TARGET_MIPS64)
4583 case OPC_LWUPC:
4584 check_mips_64(ctx);
4585 offset = sextract32(ctx->opcode << 2, 0, 21);
4586 addr = addr_add(ctx, pc, offset);
4587 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4588 break;
4589 #endif
4590 default:
4591 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4592 case OPC_AUIPC:
4593 if (rs != 0) {
4594 offset = sextract32(ctx->opcode, 0, 16) << 16;
4595 addr = addr_add(ctx, pc, offset);
4596 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4598 break;
4599 case OPC_ALUIPC:
4600 if (rs != 0) {
4601 offset = sextract32(ctx->opcode, 0, 16) << 16;
4602 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4603 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4605 break;
4606 #if defined(TARGET_MIPS64)
4607 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4608 case R6_OPC_LDPC + (1 << 16):
4609 case R6_OPC_LDPC + (2 << 16):
4610 case R6_OPC_LDPC + (3 << 16):
4611 check_mips_64(ctx);
4612 offset = sextract32(ctx->opcode << 3, 0, 21);
4613 addr = addr_add(ctx, (pc & ~0x7), offset);
4614 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4615 break;
4616 #endif
4617 default:
4618 MIPS_INVAL("OPC_PCREL");
4619 generate_exception_end(ctx, EXCP_RI);
4620 break;
4622 break;
4626 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4628 TCGv t0, t1;
4630 if (rd == 0) {
4631 /* Treat as NOP. */
4632 return;
4635 t0 = tcg_temp_new();
4636 t1 = tcg_temp_new();
4638 gen_load_gpr(t0, rs);
4639 gen_load_gpr(t1, rt);
4641 switch (opc) {
4642 case R6_OPC_DIV:
4644 TCGv t2 = tcg_temp_new();
4645 TCGv t3 = tcg_temp_new();
4646 tcg_gen_ext32s_tl(t0, t0);
4647 tcg_gen_ext32s_tl(t1, t1);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4649 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4650 tcg_gen_and_tl(t2, t2, t3);
4651 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4652 tcg_gen_or_tl(t2, t2, t3);
4653 tcg_gen_movi_tl(t3, 0);
4654 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4655 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4656 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4657 tcg_temp_free(t3);
4658 tcg_temp_free(t2);
4660 break;
4661 case R6_OPC_MOD:
4663 TCGv t2 = tcg_temp_new();
4664 TCGv t3 = tcg_temp_new();
4665 tcg_gen_ext32s_tl(t0, t0);
4666 tcg_gen_ext32s_tl(t1, t1);
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4669 tcg_gen_and_tl(t2, t2, t3);
4670 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4671 tcg_gen_or_tl(t2, t2, t3);
4672 tcg_gen_movi_tl(t3, 0);
4673 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4674 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4675 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4676 tcg_temp_free(t3);
4677 tcg_temp_free(t2);
4679 break;
4680 case R6_OPC_DIVU:
4682 TCGv t2 = tcg_const_tl(0);
4683 TCGv t3 = tcg_const_tl(1);
4684 tcg_gen_ext32u_tl(t0, t0);
4685 tcg_gen_ext32u_tl(t1, t1);
4686 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4687 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4688 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4689 tcg_temp_free(t3);
4690 tcg_temp_free(t2);
4692 break;
4693 case R6_OPC_MODU:
4695 TCGv t2 = tcg_const_tl(0);
4696 TCGv t3 = tcg_const_tl(1);
4697 tcg_gen_ext32u_tl(t0, t0);
4698 tcg_gen_ext32u_tl(t1, t1);
4699 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4700 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4701 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4702 tcg_temp_free(t3);
4703 tcg_temp_free(t2);
4705 break;
4706 case R6_OPC_MUL:
4708 TCGv_i32 t2 = tcg_temp_new_i32();
4709 TCGv_i32 t3 = tcg_temp_new_i32();
4710 tcg_gen_trunc_tl_i32(t2, t0);
4711 tcg_gen_trunc_tl_i32(t3, t1);
4712 tcg_gen_mul_i32(t2, t2, t3);
4713 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4714 tcg_temp_free_i32(t2);
4715 tcg_temp_free_i32(t3);
4717 break;
4718 case R6_OPC_MUH:
4720 TCGv_i32 t2 = tcg_temp_new_i32();
4721 TCGv_i32 t3 = tcg_temp_new_i32();
4722 tcg_gen_trunc_tl_i32(t2, t0);
4723 tcg_gen_trunc_tl_i32(t3, t1);
4724 tcg_gen_muls2_i32(t2, t3, t2, t3);
4725 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4726 tcg_temp_free_i32(t2);
4727 tcg_temp_free_i32(t3);
4729 break;
4730 case R6_OPC_MULU:
4732 TCGv_i32 t2 = tcg_temp_new_i32();
4733 TCGv_i32 t3 = tcg_temp_new_i32();
4734 tcg_gen_trunc_tl_i32(t2, t0);
4735 tcg_gen_trunc_tl_i32(t3, t1);
4736 tcg_gen_mul_i32(t2, t2, t3);
4737 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4738 tcg_temp_free_i32(t2);
4739 tcg_temp_free_i32(t3);
4741 break;
4742 case R6_OPC_MUHU:
4744 TCGv_i32 t2 = tcg_temp_new_i32();
4745 TCGv_i32 t3 = tcg_temp_new_i32();
4746 tcg_gen_trunc_tl_i32(t2, t0);
4747 tcg_gen_trunc_tl_i32(t3, t1);
4748 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4749 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4750 tcg_temp_free_i32(t2);
4751 tcg_temp_free_i32(t3);
4753 break;
4754 #if defined(TARGET_MIPS64)
4755 case R6_OPC_DDIV:
4757 TCGv t2 = tcg_temp_new();
4758 TCGv t3 = tcg_temp_new();
4759 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4760 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4761 tcg_gen_and_tl(t2, t2, t3);
4762 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4763 tcg_gen_or_tl(t2, t2, t3);
4764 tcg_gen_movi_tl(t3, 0);
4765 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4766 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4767 tcg_temp_free(t3);
4768 tcg_temp_free(t2);
4770 break;
4771 case R6_OPC_DMOD:
4773 TCGv t2 = tcg_temp_new();
4774 TCGv t3 = tcg_temp_new();
4775 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4776 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4777 tcg_gen_and_tl(t2, t2, t3);
4778 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4779 tcg_gen_or_tl(t2, t2, t3);
4780 tcg_gen_movi_tl(t3, 0);
4781 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4782 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4783 tcg_temp_free(t3);
4784 tcg_temp_free(t2);
4786 break;
4787 case R6_OPC_DDIVU:
4789 TCGv t2 = tcg_const_tl(0);
4790 TCGv t3 = tcg_const_tl(1);
4791 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4792 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4793 tcg_temp_free(t3);
4794 tcg_temp_free(t2);
4796 break;
4797 case R6_OPC_DMODU:
4799 TCGv t2 = tcg_const_tl(0);
4800 TCGv t3 = tcg_const_tl(1);
4801 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4802 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4803 tcg_temp_free(t3);
4804 tcg_temp_free(t2);
4806 break;
4807 case R6_OPC_DMUL:
4808 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4809 break;
4810 case R6_OPC_DMUH:
4812 TCGv t2 = tcg_temp_new();
4813 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4814 tcg_temp_free(t2);
4816 break;
4817 case R6_OPC_DMULU:
4818 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4819 break;
4820 case R6_OPC_DMUHU:
4822 TCGv t2 = tcg_temp_new();
4823 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4824 tcg_temp_free(t2);
4826 break;
4827 #endif
4828 default:
4829 MIPS_INVAL("r6 mul/div");
4830 generate_exception_end(ctx, EXCP_RI);
4831 goto out;
4833 out:
4834 tcg_temp_free(t0);
4835 tcg_temp_free(t1);
4838 #if defined(TARGET_MIPS64)
4839 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4841 TCGv t0, t1;
4843 t0 = tcg_temp_new();
4844 t1 = tcg_temp_new();
4846 gen_load_gpr(t0, rs);
4847 gen_load_gpr(t1, rt);
4849 switch (opc) {
4850 case MMI_OPC_DIV1:
4852 TCGv t2 = tcg_temp_new();
4853 TCGv t3 = tcg_temp_new();
4854 tcg_gen_ext32s_tl(t0, t0);
4855 tcg_gen_ext32s_tl(t1, t1);
4856 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4857 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4858 tcg_gen_and_tl(t2, t2, t3);
4859 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4860 tcg_gen_or_tl(t2, t2, t3);
4861 tcg_gen_movi_tl(t3, 0);
4862 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4863 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4864 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4865 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4866 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4867 tcg_temp_free(t3);
4868 tcg_temp_free(t2);
4870 break;
4871 case MMI_OPC_DIVU1:
4873 TCGv t2 = tcg_const_tl(0);
4874 TCGv t3 = tcg_const_tl(1);
4875 tcg_gen_ext32u_tl(t0, t0);
4876 tcg_gen_ext32u_tl(t1, t1);
4877 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4878 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4879 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4880 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4881 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4882 tcg_temp_free(t3);
4883 tcg_temp_free(t2);
4885 break;
4886 default:
4887 MIPS_INVAL("div1 TX79");
4888 generate_exception_end(ctx, EXCP_RI);
4889 goto out;
4891 out:
4892 tcg_temp_free(t0);
4893 tcg_temp_free(t1);
4895 #endif
4897 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4898 int acc, int rs, int rt)
4900 TCGv t0, t1;
4902 t0 = tcg_temp_new();
4903 t1 = tcg_temp_new();
4905 gen_load_gpr(t0, rs);
4906 gen_load_gpr(t1, rt);
4908 if (acc != 0) {
4909 check_dsp(ctx);
4912 switch (opc) {
4913 case OPC_DIV:
4915 TCGv t2 = tcg_temp_new();
4916 TCGv t3 = tcg_temp_new();
4917 tcg_gen_ext32s_tl(t0, t0);
4918 tcg_gen_ext32s_tl(t1, t1);
4919 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4920 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4921 tcg_gen_and_tl(t2, t2, t3);
4922 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4923 tcg_gen_or_tl(t2, t2, t3);
4924 tcg_gen_movi_tl(t3, 0);
4925 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4926 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4927 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4928 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4929 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4930 tcg_temp_free(t3);
4931 tcg_temp_free(t2);
4933 break;
4934 case OPC_DIVU:
4936 TCGv t2 = tcg_const_tl(0);
4937 TCGv t3 = tcg_const_tl(1);
4938 tcg_gen_ext32u_tl(t0, t0);
4939 tcg_gen_ext32u_tl(t1, t1);
4940 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4941 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4942 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4943 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4944 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4945 tcg_temp_free(t3);
4946 tcg_temp_free(t2);
4948 break;
4949 case OPC_MULT:
4951 TCGv_i32 t2 = tcg_temp_new_i32();
4952 TCGv_i32 t3 = tcg_temp_new_i32();
4953 tcg_gen_trunc_tl_i32(t2, t0);
4954 tcg_gen_trunc_tl_i32(t3, t1);
4955 tcg_gen_muls2_i32(t2, t3, t2, t3);
4956 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4957 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4958 tcg_temp_free_i32(t2);
4959 tcg_temp_free_i32(t3);
4961 break;
4962 case OPC_MULTU:
4964 TCGv_i32 t2 = tcg_temp_new_i32();
4965 TCGv_i32 t3 = tcg_temp_new_i32();
4966 tcg_gen_trunc_tl_i32(t2, t0);
4967 tcg_gen_trunc_tl_i32(t3, t1);
4968 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4969 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4970 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4971 tcg_temp_free_i32(t2);
4972 tcg_temp_free_i32(t3);
4974 break;
4975 #if defined(TARGET_MIPS64)
4976 case OPC_DDIV:
4978 TCGv t2 = tcg_temp_new();
4979 TCGv t3 = tcg_temp_new();
4980 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4981 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4982 tcg_gen_and_tl(t2, t2, t3);
4983 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4984 tcg_gen_or_tl(t2, t2, t3);
4985 tcg_gen_movi_tl(t3, 0);
4986 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4987 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4988 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4989 tcg_temp_free(t3);
4990 tcg_temp_free(t2);
4992 break;
4993 case OPC_DDIVU:
4995 TCGv t2 = tcg_const_tl(0);
4996 TCGv t3 = tcg_const_tl(1);
4997 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4998 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4999 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
5000 tcg_temp_free(t3);
5001 tcg_temp_free(t2);
5003 break;
5004 case OPC_DMULT:
5005 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5006 break;
5007 case OPC_DMULTU:
5008 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5009 break;
5010 #endif
5011 case OPC_MADD:
5013 TCGv_i64 t2 = tcg_temp_new_i64();
5014 TCGv_i64 t3 = tcg_temp_new_i64();
5016 tcg_gen_ext_tl_i64(t2, t0);
5017 tcg_gen_ext_tl_i64(t3, t1);
5018 tcg_gen_mul_i64(t2, t2, t3);
5019 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5020 tcg_gen_add_i64(t2, t2, t3);
5021 tcg_temp_free_i64(t3);
5022 gen_move_low32(cpu_LO[acc], t2);
5023 gen_move_high32(cpu_HI[acc], t2);
5024 tcg_temp_free_i64(t2);
5026 break;
5027 case OPC_MADDU:
5029 TCGv_i64 t2 = tcg_temp_new_i64();
5030 TCGv_i64 t3 = tcg_temp_new_i64();
5032 tcg_gen_ext32u_tl(t0, t0);
5033 tcg_gen_ext32u_tl(t1, t1);
5034 tcg_gen_extu_tl_i64(t2, t0);
5035 tcg_gen_extu_tl_i64(t3, t1);
5036 tcg_gen_mul_i64(t2, t2, t3);
5037 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5038 tcg_gen_add_i64(t2, t2, t3);
5039 tcg_temp_free_i64(t3);
5040 gen_move_low32(cpu_LO[acc], t2);
5041 gen_move_high32(cpu_HI[acc], t2);
5042 tcg_temp_free_i64(t2);
5044 break;
5045 case OPC_MSUB:
5047 TCGv_i64 t2 = tcg_temp_new_i64();
5048 TCGv_i64 t3 = tcg_temp_new_i64();
5050 tcg_gen_ext_tl_i64(t2, t0);
5051 tcg_gen_ext_tl_i64(t3, t1);
5052 tcg_gen_mul_i64(t2, t2, t3);
5053 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5054 tcg_gen_sub_i64(t2, t3, t2);
5055 tcg_temp_free_i64(t3);
5056 gen_move_low32(cpu_LO[acc], t2);
5057 gen_move_high32(cpu_HI[acc], t2);
5058 tcg_temp_free_i64(t2);
5060 break;
5061 case OPC_MSUBU:
5063 TCGv_i64 t2 = tcg_temp_new_i64();
5064 TCGv_i64 t3 = tcg_temp_new_i64();
5066 tcg_gen_ext32u_tl(t0, t0);
5067 tcg_gen_ext32u_tl(t1, t1);
5068 tcg_gen_extu_tl_i64(t2, t0);
5069 tcg_gen_extu_tl_i64(t3, t1);
5070 tcg_gen_mul_i64(t2, t2, t3);
5071 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5072 tcg_gen_sub_i64(t2, t3, t2);
5073 tcg_temp_free_i64(t3);
5074 gen_move_low32(cpu_LO[acc], t2);
5075 gen_move_high32(cpu_HI[acc], t2);
5076 tcg_temp_free_i64(t2);
5078 break;
5079 default:
5080 MIPS_INVAL("mul/div");
5081 generate_exception_end(ctx, EXCP_RI);
5082 goto out;
5084 out:
5085 tcg_temp_free(t0);
5086 tcg_temp_free(t1);
5090 * These MULT[U] and MADD[U] instructions implemented in for example
5091 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5092 * architectures are special three-operand variants with the syntax
5094 * MULT[U][1] rd, rs, rt
5096 * such that
5098 * (rd, LO, HI) <- rs * rt
5100 * and
5102 * MADD[U][1] rd, rs, rt
5104 * such that
5106 * (rd, LO, HI) <- (LO, HI) + rs * rt
5108 * where the low-order 32-bits of the result is placed into both the
5109 * GPR rd and the special register LO. The high-order 32-bits of the
5110 * result is placed into the special register HI.
5112 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5113 * which is the zero register that always reads as 0.
5115 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5116 int rd, int rs, int rt)
5118 TCGv t0 = tcg_temp_new();
5119 TCGv t1 = tcg_temp_new();
5120 int acc = 0;
5122 gen_load_gpr(t0, rs);
5123 gen_load_gpr(t1, rt);
5125 switch (opc) {
5126 case MMI_OPC_MULT1:
5127 acc = 1;
5128 /* Fall through */
5129 case OPC_MULT:
5131 TCGv_i32 t2 = tcg_temp_new_i32();
5132 TCGv_i32 t3 = tcg_temp_new_i32();
5133 tcg_gen_trunc_tl_i32(t2, t0);
5134 tcg_gen_trunc_tl_i32(t3, t1);
5135 tcg_gen_muls2_i32(t2, t3, t2, t3);
5136 if (rd) {
5137 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5139 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5140 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5141 tcg_temp_free_i32(t2);
5142 tcg_temp_free_i32(t3);
5144 break;
5145 case MMI_OPC_MULTU1:
5146 acc = 1;
5147 /* Fall through */
5148 case OPC_MULTU:
5150 TCGv_i32 t2 = tcg_temp_new_i32();
5151 TCGv_i32 t3 = tcg_temp_new_i32();
5152 tcg_gen_trunc_tl_i32(t2, t0);
5153 tcg_gen_trunc_tl_i32(t3, t1);
5154 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5155 if (rd) {
5156 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5158 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5159 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5160 tcg_temp_free_i32(t2);
5161 tcg_temp_free_i32(t3);
5163 break;
5164 case MMI_OPC_MADD1:
5165 acc = 1;
5166 /* Fall through */
5167 case MMI_OPC_MADD:
5169 TCGv_i64 t2 = tcg_temp_new_i64();
5170 TCGv_i64 t3 = tcg_temp_new_i64();
5172 tcg_gen_ext_tl_i64(t2, t0);
5173 tcg_gen_ext_tl_i64(t3, t1);
5174 tcg_gen_mul_i64(t2, t2, t3);
5175 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5176 tcg_gen_add_i64(t2, t2, t3);
5177 tcg_temp_free_i64(t3);
5178 gen_move_low32(cpu_LO[acc], t2);
5179 gen_move_high32(cpu_HI[acc], t2);
5180 if (rd) {
5181 gen_move_low32(cpu_gpr[rd], t2);
5183 tcg_temp_free_i64(t2);
5185 break;
5186 case MMI_OPC_MADDU1:
5187 acc = 1;
5188 /* Fall through */
5189 case MMI_OPC_MADDU:
5191 TCGv_i64 t2 = tcg_temp_new_i64();
5192 TCGv_i64 t3 = tcg_temp_new_i64();
5194 tcg_gen_ext32u_tl(t0, t0);
5195 tcg_gen_ext32u_tl(t1, t1);
5196 tcg_gen_extu_tl_i64(t2, t0);
5197 tcg_gen_extu_tl_i64(t3, t1);
5198 tcg_gen_mul_i64(t2, t2, t3);
5199 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5200 tcg_gen_add_i64(t2, t2, t3);
5201 tcg_temp_free_i64(t3);
5202 gen_move_low32(cpu_LO[acc], t2);
5203 gen_move_high32(cpu_HI[acc], t2);
5204 if (rd) {
5205 gen_move_low32(cpu_gpr[rd], t2);
5207 tcg_temp_free_i64(t2);
5209 break;
5210 default:
5211 MIPS_INVAL("mul/madd TXx9");
5212 generate_exception_end(ctx, EXCP_RI);
5213 goto out;
5216 out:
5217 tcg_temp_free(t0);
5218 tcg_temp_free(t1);
5221 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5222 int rd, int rs, int rt)
5224 TCGv t0 = tcg_temp_new();
5225 TCGv t1 = tcg_temp_new();
5227 gen_load_gpr(t0, rs);
5228 gen_load_gpr(t1, rt);
5230 switch (opc) {
5231 case OPC_VR54XX_MULS:
5232 gen_helper_muls(t0, cpu_env, t0, t1);
5233 break;
5234 case OPC_VR54XX_MULSU:
5235 gen_helper_mulsu(t0, cpu_env, t0, t1);
5236 break;
5237 case OPC_VR54XX_MACC:
5238 gen_helper_macc(t0, cpu_env, t0, t1);
5239 break;
5240 case OPC_VR54XX_MACCU:
5241 gen_helper_maccu(t0, cpu_env, t0, t1);
5242 break;
5243 case OPC_VR54XX_MSAC:
5244 gen_helper_msac(t0, cpu_env, t0, t1);
5245 break;
5246 case OPC_VR54XX_MSACU:
5247 gen_helper_msacu(t0, cpu_env, t0, t1);
5248 break;
5249 case OPC_VR54XX_MULHI:
5250 gen_helper_mulhi(t0, cpu_env, t0, t1);
5251 break;
5252 case OPC_VR54XX_MULHIU:
5253 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5254 break;
5255 case OPC_VR54XX_MULSHI:
5256 gen_helper_mulshi(t0, cpu_env, t0, t1);
5257 break;
5258 case OPC_VR54XX_MULSHIU:
5259 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5260 break;
5261 case OPC_VR54XX_MACCHI:
5262 gen_helper_macchi(t0, cpu_env, t0, t1);
5263 break;
5264 case OPC_VR54XX_MACCHIU:
5265 gen_helper_macchiu(t0, cpu_env, t0, t1);
5266 break;
5267 case OPC_VR54XX_MSACHI:
5268 gen_helper_msachi(t0, cpu_env, t0, t1);
5269 break;
5270 case OPC_VR54XX_MSACHIU:
5271 gen_helper_msachiu(t0, cpu_env, t0, t1);
5272 break;
5273 default:
5274 MIPS_INVAL("mul vr54xx");
5275 generate_exception_end(ctx, EXCP_RI);
5276 goto out;
5278 gen_store_gpr(t0, rd);
5280 out:
5281 tcg_temp_free(t0);
5282 tcg_temp_free(t1);
5285 static void gen_cl(DisasContext *ctx, uint32_t opc,
5286 int rd, int rs)
5288 TCGv t0;
5290 if (rd == 0) {
5291 /* Treat as NOP. */
5292 return;
5294 t0 = cpu_gpr[rd];
5295 gen_load_gpr(t0, rs);
5297 switch (opc) {
5298 case OPC_CLO:
5299 case R6_OPC_CLO:
5300 #if defined(TARGET_MIPS64)
5301 case OPC_DCLO:
5302 case R6_OPC_DCLO:
5303 #endif
5304 tcg_gen_not_tl(t0, t0);
5305 break;
5308 switch (opc) {
5309 case OPC_CLO:
5310 case R6_OPC_CLO:
5311 case OPC_CLZ:
5312 case R6_OPC_CLZ:
5313 tcg_gen_ext32u_tl(t0, t0);
5314 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5315 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5316 break;
5317 #if defined(TARGET_MIPS64)
5318 case OPC_DCLO:
5319 case R6_OPC_DCLO:
5320 case OPC_DCLZ:
5321 case R6_OPC_DCLZ:
5322 tcg_gen_clzi_i64(t0, t0, 64);
5323 break;
5324 #endif
5328 /* Godson integer instructions */
5329 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5330 int rd, int rs, int rt)
5332 TCGv t0, t1;
5334 if (rd == 0) {
5335 /* Treat as NOP. */
5336 return;
5339 switch (opc) {
5340 case OPC_MULT_G_2E:
5341 case OPC_MULT_G_2F:
5342 case OPC_MULTU_G_2E:
5343 case OPC_MULTU_G_2F:
5344 #if defined(TARGET_MIPS64)
5345 case OPC_DMULT_G_2E:
5346 case OPC_DMULT_G_2F:
5347 case OPC_DMULTU_G_2E:
5348 case OPC_DMULTU_G_2F:
5349 #endif
5350 t0 = tcg_temp_new();
5351 t1 = tcg_temp_new();
5352 break;
5353 default:
5354 t0 = tcg_temp_local_new();
5355 t1 = tcg_temp_local_new();
5356 break;
5359 gen_load_gpr(t0, rs);
5360 gen_load_gpr(t1, rt);
5362 switch (opc) {
5363 case OPC_MULT_G_2E:
5364 case OPC_MULT_G_2F:
5365 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5366 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5367 break;
5368 case OPC_MULTU_G_2E:
5369 case OPC_MULTU_G_2F:
5370 tcg_gen_ext32u_tl(t0, t0);
5371 tcg_gen_ext32u_tl(t1, t1);
5372 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5373 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5374 break;
5375 case OPC_DIV_G_2E:
5376 case OPC_DIV_G_2F:
5378 TCGLabel *l1 = gen_new_label();
5379 TCGLabel *l2 = gen_new_label();
5380 TCGLabel *l3 = gen_new_label();
5381 tcg_gen_ext32s_tl(t0, t0);
5382 tcg_gen_ext32s_tl(t1, t1);
5383 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5384 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5385 tcg_gen_br(l3);
5386 gen_set_label(l1);
5387 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5388 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5389 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5390 tcg_gen_br(l3);
5391 gen_set_label(l2);
5392 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5393 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5394 gen_set_label(l3);
5396 break;
5397 case OPC_DIVU_G_2E:
5398 case OPC_DIVU_G_2F:
5400 TCGLabel *l1 = gen_new_label();
5401 TCGLabel *l2 = gen_new_label();
5402 tcg_gen_ext32u_tl(t0, t0);
5403 tcg_gen_ext32u_tl(t1, t1);
5404 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5405 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5406 tcg_gen_br(l2);
5407 gen_set_label(l1);
5408 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5409 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5410 gen_set_label(l2);
5412 break;
5413 case OPC_MOD_G_2E:
5414 case OPC_MOD_G_2F:
5416 TCGLabel *l1 = gen_new_label();
5417 TCGLabel *l2 = gen_new_label();
5418 TCGLabel *l3 = gen_new_label();
5419 tcg_gen_ext32u_tl(t0, t0);
5420 tcg_gen_ext32u_tl(t1, t1);
5421 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5422 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5423 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5424 gen_set_label(l1);
5425 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5426 tcg_gen_br(l3);
5427 gen_set_label(l2);
5428 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5429 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5430 gen_set_label(l3);
5432 break;
5433 case OPC_MODU_G_2E:
5434 case OPC_MODU_G_2F:
5436 TCGLabel *l1 = gen_new_label();
5437 TCGLabel *l2 = gen_new_label();
5438 tcg_gen_ext32u_tl(t0, t0);
5439 tcg_gen_ext32u_tl(t1, t1);
5440 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5441 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5442 tcg_gen_br(l2);
5443 gen_set_label(l1);
5444 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5445 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5446 gen_set_label(l2);
5448 break;
5449 #if defined(TARGET_MIPS64)
5450 case OPC_DMULT_G_2E:
5451 case OPC_DMULT_G_2F:
5452 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5453 break;
5454 case OPC_DMULTU_G_2E:
5455 case OPC_DMULTU_G_2F:
5456 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5457 break;
5458 case OPC_DDIV_G_2E:
5459 case OPC_DDIV_G_2F:
5461 TCGLabel *l1 = gen_new_label();
5462 TCGLabel *l2 = gen_new_label();
5463 TCGLabel *l3 = gen_new_label();
5464 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5465 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5466 tcg_gen_br(l3);
5467 gen_set_label(l1);
5468 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5469 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5470 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5471 tcg_gen_br(l3);
5472 gen_set_label(l2);
5473 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5474 gen_set_label(l3);
5476 break;
5477 case OPC_DDIVU_G_2E:
5478 case OPC_DDIVU_G_2F:
5480 TCGLabel *l1 = gen_new_label();
5481 TCGLabel *l2 = gen_new_label();
5482 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5483 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5484 tcg_gen_br(l2);
5485 gen_set_label(l1);
5486 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5487 gen_set_label(l2);
5489 break;
5490 case OPC_DMOD_G_2E:
5491 case OPC_DMOD_G_2F:
5493 TCGLabel *l1 = gen_new_label();
5494 TCGLabel *l2 = gen_new_label();
5495 TCGLabel *l3 = gen_new_label();
5496 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5497 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5498 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5499 gen_set_label(l1);
5500 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5501 tcg_gen_br(l3);
5502 gen_set_label(l2);
5503 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5504 gen_set_label(l3);
5506 break;
5507 case OPC_DMODU_G_2E:
5508 case OPC_DMODU_G_2F:
5510 TCGLabel *l1 = gen_new_label();
5511 TCGLabel *l2 = gen_new_label();
5512 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5513 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5514 tcg_gen_br(l2);
5515 gen_set_label(l1);
5516 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5517 gen_set_label(l2);
5519 break;
5520 #endif
5523 tcg_temp_free(t0);
5524 tcg_temp_free(t1);
5527 /* Loongson multimedia instructions */
5528 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5530 uint32_t opc, shift_max;
5531 TCGv_i64 t0, t1;
5533 opc = MASK_LMI(ctx->opcode);
5534 switch (opc) {
5535 case OPC_ADD_CP2:
5536 case OPC_SUB_CP2:
5537 case OPC_DADD_CP2:
5538 case OPC_DSUB_CP2:
5539 t0 = tcg_temp_local_new_i64();
5540 t1 = tcg_temp_local_new_i64();
5541 break;
5542 default:
5543 t0 = tcg_temp_new_i64();
5544 t1 = tcg_temp_new_i64();
5545 break;
5548 check_cp1_enabled(ctx);
5549 gen_load_fpr64(ctx, t0, rs);
5550 gen_load_fpr64(ctx, t1, rt);
5552 switch (opc) {
5553 case OPC_PADDSH:
5554 gen_helper_paddsh(t0, t0, t1);
5555 break;
5556 case OPC_PADDUSH:
5557 gen_helper_paddush(t0, t0, t1);
5558 break;
5559 case OPC_PADDH:
5560 gen_helper_paddh(t0, t0, t1);
5561 break;
5562 case OPC_PADDW:
5563 gen_helper_paddw(t0, t0, t1);
5564 break;
5565 case OPC_PADDSB:
5566 gen_helper_paddsb(t0, t0, t1);
5567 break;
5568 case OPC_PADDUSB:
5569 gen_helper_paddusb(t0, t0, t1);
5570 break;
5571 case OPC_PADDB:
5572 gen_helper_paddb(t0, t0, t1);
5573 break;
5575 case OPC_PSUBSH:
5576 gen_helper_psubsh(t0, t0, t1);
5577 break;
5578 case OPC_PSUBUSH:
5579 gen_helper_psubush(t0, t0, t1);
5580 break;
5581 case OPC_PSUBH:
5582 gen_helper_psubh(t0, t0, t1);
5583 break;
5584 case OPC_PSUBW:
5585 gen_helper_psubw(t0, t0, t1);
5586 break;
5587 case OPC_PSUBSB:
5588 gen_helper_psubsb(t0, t0, t1);
5589 break;
5590 case OPC_PSUBUSB:
5591 gen_helper_psubusb(t0, t0, t1);
5592 break;
5593 case OPC_PSUBB:
5594 gen_helper_psubb(t0, t0, t1);
5595 break;
5597 case OPC_PSHUFH:
5598 gen_helper_pshufh(t0, t0, t1);
5599 break;
5600 case OPC_PACKSSWH:
5601 gen_helper_packsswh(t0, t0, t1);
5602 break;
5603 case OPC_PACKSSHB:
5604 gen_helper_packsshb(t0, t0, t1);
5605 break;
5606 case OPC_PACKUSHB:
5607 gen_helper_packushb(t0, t0, t1);
5608 break;
5610 case OPC_PUNPCKLHW:
5611 gen_helper_punpcklhw(t0, t0, t1);
5612 break;
5613 case OPC_PUNPCKHHW:
5614 gen_helper_punpckhhw(t0, t0, t1);
5615 break;
5616 case OPC_PUNPCKLBH:
5617 gen_helper_punpcklbh(t0, t0, t1);
5618 break;
5619 case OPC_PUNPCKHBH:
5620 gen_helper_punpckhbh(t0, t0, t1);
5621 break;
5622 case OPC_PUNPCKLWD:
5623 gen_helper_punpcklwd(t0, t0, t1);
5624 break;
5625 case OPC_PUNPCKHWD:
5626 gen_helper_punpckhwd(t0, t0, t1);
5627 break;
5629 case OPC_PAVGH:
5630 gen_helper_pavgh(t0, t0, t1);
5631 break;
5632 case OPC_PAVGB:
5633 gen_helper_pavgb(t0, t0, t1);
5634 break;
5635 case OPC_PMAXSH:
5636 gen_helper_pmaxsh(t0, t0, t1);
5637 break;
5638 case OPC_PMINSH:
5639 gen_helper_pminsh(t0, t0, t1);
5640 break;
5641 case OPC_PMAXUB:
5642 gen_helper_pmaxub(t0, t0, t1);
5643 break;
5644 case OPC_PMINUB:
5645 gen_helper_pminub(t0, t0, t1);
5646 break;
5648 case OPC_PCMPEQW:
5649 gen_helper_pcmpeqw(t0, t0, t1);
5650 break;
5651 case OPC_PCMPGTW:
5652 gen_helper_pcmpgtw(t0, t0, t1);
5653 break;
5654 case OPC_PCMPEQH:
5655 gen_helper_pcmpeqh(t0, t0, t1);
5656 break;
5657 case OPC_PCMPGTH:
5658 gen_helper_pcmpgth(t0, t0, t1);
5659 break;
5660 case OPC_PCMPEQB:
5661 gen_helper_pcmpeqb(t0, t0, t1);
5662 break;
5663 case OPC_PCMPGTB:
5664 gen_helper_pcmpgtb(t0, t0, t1);
5665 break;
5667 case OPC_PSLLW:
5668 gen_helper_psllw(t0, t0, t1);
5669 break;
5670 case OPC_PSLLH:
5671 gen_helper_psllh(t0, t0, t1);
5672 break;
5673 case OPC_PSRLW:
5674 gen_helper_psrlw(t0, t0, t1);
5675 break;
5676 case OPC_PSRLH:
5677 gen_helper_psrlh(t0, t0, t1);
5678 break;
5679 case OPC_PSRAW:
5680 gen_helper_psraw(t0, t0, t1);
5681 break;
5682 case OPC_PSRAH:
5683 gen_helper_psrah(t0, t0, t1);
5684 break;
5686 case OPC_PMULLH:
5687 gen_helper_pmullh(t0, t0, t1);
5688 break;
5689 case OPC_PMULHH:
5690 gen_helper_pmulhh(t0, t0, t1);
5691 break;
5692 case OPC_PMULHUH:
5693 gen_helper_pmulhuh(t0, t0, t1);
5694 break;
5695 case OPC_PMADDHW:
5696 gen_helper_pmaddhw(t0, t0, t1);
5697 break;
5699 case OPC_PASUBUB:
5700 gen_helper_pasubub(t0, t0, t1);
5701 break;
5702 case OPC_BIADD:
5703 gen_helper_biadd(t0, t0);
5704 break;
5705 case OPC_PMOVMSKB:
5706 gen_helper_pmovmskb(t0, t0);
5707 break;
5709 case OPC_PADDD:
5710 tcg_gen_add_i64(t0, t0, t1);
5711 break;
5712 case OPC_PSUBD:
5713 tcg_gen_sub_i64(t0, t0, t1);
5714 break;
5715 case OPC_XOR_CP2:
5716 tcg_gen_xor_i64(t0, t0, t1);
5717 break;
5718 case OPC_NOR_CP2:
5719 tcg_gen_nor_i64(t0, t0, t1);
5720 break;
5721 case OPC_AND_CP2:
5722 tcg_gen_and_i64(t0, t0, t1);
5723 break;
5724 case OPC_OR_CP2:
5725 tcg_gen_or_i64(t0, t0, t1);
5726 break;
5728 case OPC_PANDN:
5729 tcg_gen_andc_i64(t0, t1, t0);
5730 break;
5732 case OPC_PINSRH_0:
5733 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5734 break;
5735 case OPC_PINSRH_1:
5736 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5737 break;
5738 case OPC_PINSRH_2:
5739 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5740 break;
5741 case OPC_PINSRH_3:
5742 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5743 break;
5745 case OPC_PEXTRH:
5746 tcg_gen_andi_i64(t1, t1, 3);
5747 tcg_gen_shli_i64(t1, t1, 4);
5748 tcg_gen_shr_i64(t0, t0, t1);
5749 tcg_gen_ext16u_i64(t0, t0);
5750 break;
5752 case OPC_ADDU_CP2:
5753 tcg_gen_add_i64(t0, t0, t1);
5754 tcg_gen_ext32s_i64(t0, t0);
5755 break;
5756 case OPC_SUBU_CP2:
5757 tcg_gen_sub_i64(t0, t0, t1);
5758 tcg_gen_ext32s_i64(t0, t0);
5759 break;
5761 case OPC_SLL_CP2:
5762 shift_max = 32;
5763 goto do_shift;
5764 case OPC_SRL_CP2:
5765 shift_max = 32;
5766 goto do_shift;
5767 case OPC_SRA_CP2:
5768 shift_max = 32;
5769 goto do_shift;
5770 case OPC_DSLL_CP2:
5771 shift_max = 64;
5772 goto do_shift;
5773 case OPC_DSRL_CP2:
5774 shift_max = 64;
5775 goto do_shift;
5776 case OPC_DSRA_CP2:
5777 shift_max = 64;
5778 goto do_shift;
5779 do_shift:
5780 /* Make sure shift count isn't TCG undefined behaviour. */
5781 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5783 switch (opc) {
5784 case OPC_SLL_CP2:
5785 case OPC_DSLL_CP2:
5786 tcg_gen_shl_i64(t0, t0, t1);
5787 break;
5788 case OPC_SRA_CP2:
5789 case OPC_DSRA_CP2:
5791 * Since SRA is UndefinedResult without sign-extended inputs,
5792 * we can treat SRA and DSRA the same.
5794 tcg_gen_sar_i64(t0, t0, t1);
5795 break;
5796 case OPC_SRL_CP2:
5797 /* We want to shift in zeros for SRL; zero-extend first. */
5798 tcg_gen_ext32u_i64(t0, t0);
5799 /* FALLTHRU */
5800 case OPC_DSRL_CP2:
5801 tcg_gen_shr_i64(t0, t0, t1);
5802 break;
5805 if (shift_max == 32) {
5806 tcg_gen_ext32s_i64(t0, t0);
5809 /* Shifts larger than MAX produce zero. */
5810 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5811 tcg_gen_neg_i64(t1, t1);
5812 tcg_gen_and_i64(t0, t0, t1);
5813 break;
5815 case OPC_ADD_CP2:
5816 case OPC_DADD_CP2:
5818 TCGv_i64 t2 = tcg_temp_new_i64();
5819 TCGLabel *lab = gen_new_label();
5821 tcg_gen_mov_i64(t2, t0);
5822 tcg_gen_add_i64(t0, t1, t2);
5823 if (opc == OPC_ADD_CP2) {
5824 tcg_gen_ext32s_i64(t0, t0);
5826 tcg_gen_xor_i64(t1, t1, t2);
5827 tcg_gen_xor_i64(t2, t2, t0);
5828 tcg_gen_andc_i64(t1, t2, t1);
5829 tcg_temp_free_i64(t2);
5830 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5831 generate_exception(ctx, EXCP_OVERFLOW);
5832 gen_set_label(lab);
5833 break;
5836 case OPC_SUB_CP2:
5837 case OPC_DSUB_CP2:
5839 TCGv_i64 t2 = tcg_temp_new_i64();
5840 TCGLabel *lab = gen_new_label();
5842 tcg_gen_mov_i64(t2, t0);
5843 tcg_gen_sub_i64(t0, t1, t2);
5844 if (opc == OPC_SUB_CP2) {
5845 tcg_gen_ext32s_i64(t0, t0);
5847 tcg_gen_xor_i64(t1, t1, t2);
5848 tcg_gen_xor_i64(t2, t2, t0);
5849 tcg_gen_and_i64(t1, t1, t2);
5850 tcg_temp_free_i64(t2);
5851 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5852 generate_exception(ctx, EXCP_OVERFLOW);
5853 gen_set_label(lab);
5854 break;
5857 case OPC_PMULUW:
5858 tcg_gen_ext32u_i64(t0, t0);
5859 tcg_gen_ext32u_i64(t1, t1);
5860 tcg_gen_mul_i64(t0, t0, t1);
5861 break;
5863 case OPC_SEQU_CP2:
5864 case OPC_SEQ_CP2:
5865 case OPC_SLTU_CP2:
5866 case OPC_SLT_CP2:
5867 case OPC_SLEU_CP2:
5868 case OPC_SLE_CP2:
5870 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5871 * FD field is the CC field?
5873 default:
5874 MIPS_INVAL("loongson_cp2");
5875 generate_exception_end(ctx, EXCP_RI);
5876 return;
5879 gen_store_fpr64(ctx, t0, rd);
5881 tcg_temp_free_i64(t0);
5882 tcg_temp_free_i64(t1);
5885 /* Traps */
5886 static void gen_trap(DisasContext *ctx, uint32_t opc,
5887 int rs, int rt, int16_t imm)
5889 int cond;
5890 TCGv t0 = tcg_temp_new();
5891 TCGv t1 = tcg_temp_new();
5893 cond = 0;
5894 /* Load needed operands */
5895 switch (opc) {
5896 case OPC_TEQ:
5897 case OPC_TGE:
5898 case OPC_TGEU:
5899 case OPC_TLT:
5900 case OPC_TLTU:
5901 case OPC_TNE:
5902 /* Compare two registers */
5903 if (rs != rt) {
5904 gen_load_gpr(t0, rs);
5905 gen_load_gpr(t1, rt);
5906 cond = 1;
5908 break;
5909 case OPC_TEQI:
5910 case OPC_TGEI:
5911 case OPC_TGEIU:
5912 case OPC_TLTI:
5913 case OPC_TLTIU:
5914 case OPC_TNEI:
5915 /* Compare register to immediate */
5916 if (rs != 0 || imm != 0) {
5917 gen_load_gpr(t0, rs);
5918 tcg_gen_movi_tl(t1, (int32_t)imm);
5919 cond = 1;
5921 break;
5923 if (cond == 0) {
5924 switch (opc) {
5925 case OPC_TEQ: /* rs == rs */
5926 case OPC_TEQI: /* r0 == 0 */
5927 case OPC_TGE: /* rs >= rs */
5928 case OPC_TGEI: /* r0 >= 0 */
5929 case OPC_TGEU: /* rs >= rs unsigned */
5930 case OPC_TGEIU: /* r0 >= 0 unsigned */
5931 /* Always trap */
5932 generate_exception_end(ctx, EXCP_TRAP);
5933 break;
5934 case OPC_TLT: /* rs < rs */
5935 case OPC_TLTI: /* r0 < 0 */
5936 case OPC_TLTU: /* rs < rs unsigned */
5937 case OPC_TLTIU: /* r0 < 0 unsigned */
5938 case OPC_TNE: /* rs != rs */
5939 case OPC_TNEI: /* r0 != 0 */
5940 /* Never trap: treat as NOP. */
5941 break;
5943 } else {
5944 TCGLabel *l1 = gen_new_label();
5946 switch (opc) {
5947 case OPC_TEQ:
5948 case OPC_TEQI:
5949 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5950 break;
5951 case OPC_TGE:
5952 case OPC_TGEI:
5953 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5954 break;
5955 case OPC_TGEU:
5956 case OPC_TGEIU:
5957 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5958 break;
5959 case OPC_TLT:
5960 case OPC_TLTI:
5961 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5962 break;
5963 case OPC_TLTU:
5964 case OPC_TLTIU:
5965 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5966 break;
5967 case OPC_TNE:
5968 case OPC_TNEI:
5969 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5970 break;
5972 generate_exception(ctx, EXCP_TRAP);
5973 gen_set_label(l1);
5975 tcg_temp_free(t0);
5976 tcg_temp_free(t1);
5979 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5981 if (unlikely(ctx->base.singlestep_enabled)) {
5982 return false;
5985 #ifndef CONFIG_USER_ONLY
5986 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5987 #else
5988 return true;
5989 #endif
5992 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5994 if (use_goto_tb(ctx, dest)) {
5995 tcg_gen_goto_tb(n);
5996 gen_save_pc(dest);
5997 tcg_gen_exit_tb(ctx->base.tb, n);
5998 } else {
5999 gen_save_pc(dest);
6000 if (ctx->base.singlestep_enabled) {
6001 save_cpu_state(ctx, 0);
6002 gen_helper_raise_exception_debug(cpu_env);
6004 tcg_gen_lookup_and_goto_ptr();
6008 /* Branches (before delay slot) */
6009 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6010 int insn_bytes,
6011 int rs, int rt, int32_t offset,
6012 int delayslot_size)
6014 target_ulong btgt = -1;
6015 int blink = 0;
6016 int bcond_compute = 0;
6017 TCGv t0 = tcg_temp_new();
6018 TCGv t1 = tcg_temp_new();
6020 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6021 #ifdef MIPS_DEBUG_DISAS
6022 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6023 TARGET_FMT_lx "\n", ctx->base.pc_next);
6024 #endif
6025 generate_exception_end(ctx, EXCP_RI);
6026 goto out;
6029 /* Load needed operands */
6030 switch (opc) {
6031 case OPC_BEQ:
6032 case OPC_BEQL:
6033 case OPC_BNE:
6034 case OPC_BNEL:
6035 /* Compare two registers */
6036 if (rs != rt) {
6037 gen_load_gpr(t0, rs);
6038 gen_load_gpr(t1, rt);
6039 bcond_compute = 1;
6041 btgt = ctx->base.pc_next + insn_bytes + offset;
6042 break;
6043 case OPC_BGEZ:
6044 case OPC_BGEZAL:
6045 case OPC_BGEZALL:
6046 case OPC_BGEZL:
6047 case OPC_BGTZ:
6048 case OPC_BGTZL:
6049 case OPC_BLEZ:
6050 case OPC_BLEZL:
6051 case OPC_BLTZ:
6052 case OPC_BLTZAL:
6053 case OPC_BLTZALL:
6054 case OPC_BLTZL:
6055 /* Compare to zero */
6056 if (rs != 0) {
6057 gen_load_gpr(t0, rs);
6058 bcond_compute = 1;
6060 btgt = ctx->base.pc_next + insn_bytes + offset;
6061 break;
6062 case OPC_BPOSGE32:
6063 #if defined(TARGET_MIPS64)
6064 case OPC_BPOSGE64:
6065 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6066 #else
6067 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6068 #endif
6069 bcond_compute = 1;
6070 btgt = ctx->base.pc_next + insn_bytes + offset;
6071 break;
6072 case OPC_J:
6073 case OPC_JAL:
6074 case OPC_JALX:
6075 /* Jump to immediate */
6076 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6077 (uint32_t)offset;
6078 break;
6079 case OPC_JR:
6080 case OPC_JALR:
6081 /* Jump to register */
6082 if (offset != 0 && offset != 16) {
6084 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6085 * others are reserved.
6087 MIPS_INVAL("jump hint");
6088 generate_exception_end(ctx, EXCP_RI);
6089 goto out;
6091 gen_load_gpr(btarget, rs);
6092 break;
6093 default:
6094 MIPS_INVAL("branch/jump");
6095 generate_exception_end(ctx, EXCP_RI);
6096 goto out;
6098 if (bcond_compute == 0) {
6099 /* No condition to be computed */
6100 switch (opc) {
6101 case OPC_BEQ: /* rx == rx */
6102 case OPC_BEQL: /* rx == rx likely */
6103 case OPC_BGEZ: /* 0 >= 0 */
6104 case OPC_BGEZL: /* 0 >= 0 likely */
6105 case OPC_BLEZ: /* 0 <= 0 */
6106 case OPC_BLEZL: /* 0 <= 0 likely */
6107 /* Always take */
6108 ctx->hflags |= MIPS_HFLAG_B;
6109 break;
6110 case OPC_BGEZAL: /* 0 >= 0 */
6111 case OPC_BGEZALL: /* 0 >= 0 likely */
6112 /* Always take and link */
6113 blink = 31;
6114 ctx->hflags |= MIPS_HFLAG_B;
6115 break;
6116 case OPC_BNE: /* rx != rx */
6117 case OPC_BGTZ: /* 0 > 0 */
6118 case OPC_BLTZ: /* 0 < 0 */
6119 /* Treat as NOP. */
6120 goto out;
6121 case OPC_BLTZAL: /* 0 < 0 */
6123 * Handle as an unconditional branch to get correct delay
6124 * slot checking.
6126 blink = 31;
6127 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6128 ctx->hflags |= MIPS_HFLAG_B;
6129 break;
6130 case OPC_BLTZALL: /* 0 < 0 likely */
6131 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6132 /* Skip the instruction in the delay slot */
6133 ctx->base.pc_next += 4;
6134 goto out;
6135 case OPC_BNEL: /* rx != rx likely */
6136 case OPC_BGTZL: /* 0 > 0 likely */
6137 case OPC_BLTZL: /* 0 < 0 likely */
6138 /* Skip the instruction in the delay slot */
6139 ctx->base.pc_next += 4;
6140 goto out;
6141 case OPC_J:
6142 ctx->hflags |= MIPS_HFLAG_B;
6143 break;
6144 case OPC_JALX:
6145 ctx->hflags |= MIPS_HFLAG_BX;
6146 /* Fallthrough */
6147 case OPC_JAL:
6148 blink = 31;
6149 ctx->hflags |= MIPS_HFLAG_B;
6150 break;
6151 case OPC_JR:
6152 ctx->hflags |= MIPS_HFLAG_BR;
6153 break;
6154 case OPC_JALR:
6155 blink = rt;
6156 ctx->hflags |= MIPS_HFLAG_BR;
6157 break;
6158 default:
6159 MIPS_INVAL("branch/jump");
6160 generate_exception_end(ctx, EXCP_RI);
6161 goto out;
6163 } else {
6164 switch (opc) {
6165 case OPC_BEQ:
6166 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6167 goto not_likely;
6168 case OPC_BEQL:
6169 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6170 goto likely;
6171 case OPC_BNE:
6172 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6173 goto not_likely;
6174 case OPC_BNEL:
6175 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6176 goto likely;
6177 case OPC_BGEZ:
6178 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6179 goto not_likely;
6180 case OPC_BGEZL:
6181 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6182 goto likely;
6183 case OPC_BGEZAL:
6184 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6185 blink = 31;
6186 goto not_likely;
6187 case OPC_BGEZALL:
6188 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6189 blink = 31;
6190 goto likely;
6191 case OPC_BGTZ:
6192 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6193 goto not_likely;
6194 case OPC_BGTZL:
6195 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6196 goto likely;
6197 case OPC_BLEZ:
6198 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6199 goto not_likely;
6200 case OPC_BLEZL:
6201 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6202 goto likely;
6203 case OPC_BLTZ:
6204 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6205 goto not_likely;
6206 case OPC_BLTZL:
6207 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6208 goto likely;
6209 case OPC_BPOSGE32:
6210 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6211 goto not_likely;
6212 #if defined(TARGET_MIPS64)
6213 case OPC_BPOSGE64:
6214 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6215 goto not_likely;
6216 #endif
6217 case OPC_BLTZAL:
6218 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6219 blink = 31;
6220 not_likely:
6221 ctx->hflags |= MIPS_HFLAG_BC;
6222 break;
6223 case OPC_BLTZALL:
6224 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6225 blink = 31;
6226 likely:
6227 ctx->hflags |= MIPS_HFLAG_BL;
6228 break;
6229 default:
6230 MIPS_INVAL("conditional branch/jump");
6231 generate_exception_end(ctx, EXCP_RI);
6232 goto out;
6236 ctx->btarget = btgt;
6238 switch (delayslot_size) {
6239 case 2:
6240 ctx->hflags |= MIPS_HFLAG_BDS16;
6241 break;
6242 case 4:
6243 ctx->hflags |= MIPS_HFLAG_BDS32;
6244 break;
6247 if (blink > 0) {
6248 int post_delay = insn_bytes + delayslot_size;
6249 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6251 tcg_gen_movi_tl(cpu_gpr[blink],
6252 ctx->base.pc_next + post_delay + lowbit);
6255 out:
6256 if (insn_bytes == 2) {
6257 ctx->hflags |= MIPS_HFLAG_B16;
6259 tcg_temp_free(t0);
6260 tcg_temp_free(t1);
6264 /* nanoMIPS Branches */
6265 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6266 int insn_bytes,
6267 int rs, int rt, int32_t offset)
6269 target_ulong btgt = -1;
6270 int bcond_compute = 0;
6271 TCGv t0 = tcg_temp_new();
6272 TCGv t1 = tcg_temp_new();
6274 /* Load needed operands */
6275 switch (opc) {
6276 case OPC_BEQ:
6277 case OPC_BNE:
6278 /* Compare two registers */
6279 if (rs != rt) {
6280 gen_load_gpr(t0, rs);
6281 gen_load_gpr(t1, rt);
6282 bcond_compute = 1;
6284 btgt = ctx->base.pc_next + insn_bytes + offset;
6285 break;
6286 case OPC_BGEZAL:
6287 /* Compare to zero */
6288 if (rs != 0) {
6289 gen_load_gpr(t0, rs);
6290 bcond_compute = 1;
6292 btgt = ctx->base.pc_next + insn_bytes + offset;
6293 break;
6294 case OPC_BPOSGE32:
6295 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6296 bcond_compute = 1;
6297 btgt = ctx->base.pc_next + insn_bytes + offset;
6298 break;
6299 case OPC_JR:
6300 case OPC_JALR:
6301 /* Jump to register */
6302 if (offset != 0 && offset != 16) {
6304 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6305 * others are reserved.
6307 MIPS_INVAL("jump hint");
6308 generate_exception_end(ctx, EXCP_RI);
6309 goto out;
6311 gen_load_gpr(btarget, rs);
6312 break;
6313 default:
6314 MIPS_INVAL("branch/jump");
6315 generate_exception_end(ctx, EXCP_RI);
6316 goto out;
6318 if (bcond_compute == 0) {
6319 /* No condition to be computed */
6320 switch (opc) {
6321 case OPC_BEQ: /* rx == rx */
6322 /* Always take */
6323 ctx->hflags |= MIPS_HFLAG_B;
6324 break;
6325 case OPC_BGEZAL: /* 0 >= 0 */
6326 /* Always take and link */
6327 tcg_gen_movi_tl(cpu_gpr[31],
6328 ctx->base.pc_next + insn_bytes);
6329 ctx->hflags |= MIPS_HFLAG_B;
6330 break;
6331 case OPC_BNE: /* rx != rx */
6332 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6333 /* Skip the instruction in the delay slot */
6334 ctx->base.pc_next += 4;
6335 goto out;
6336 case OPC_JR:
6337 ctx->hflags |= MIPS_HFLAG_BR;
6338 break;
6339 case OPC_JALR:
6340 if (rt > 0) {
6341 tcg_gen_movi_tl(cpu_gpr[rt],
6342 ctx->base.pc_next + insn_bytes);
6344 ctx->hflags |= MIPS_HFLAG_BR;
6345 break;
6346 default:
6347 MIPS_INVAL("branch/jump");
6348 generate_exception_end(ctx, EXCP_RI);
6349 goto out;
6351 } else {
6352 switch (opc) {
6353 case OPC_BEQ:
6354 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6355 goto not_likely;
6356 case OPC_BNE:
6357 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6358 goto not_likely;
6359 case OPC_BGEZAL:
6360 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6361 tcg_gen_movi_tl(cpu_gpr[31],
6362 ctx->base.pc_next + insn_bytes);
6363 goto not_likely;
6364 case OPC_BPOSGE32:
6365 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6366 not_likely:
6367 ctx->hflags |= MIPS_HFLAG_BC;
6368 break;
6369 default:
6370 MIPS_INVAL("conditional branch/jump");
6371 generate_exception_end(ctx, EXCP_RI);
6372 goto out;
6376 ctx->btarget = btgt;
6378 out:
6379 if (insn_bytes == 2) {
6380 ctx->hflags |= MIPS_HFLAG_B16;
6382 tcg_temp_free(t0);
6383 tcg_temp_free(t1);
6387 /* special3 bitfield operations */
6388 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6389 int rs, int lsb, int msb)
6391 TCGv t0 = tcg_temp_new();
6392 TCGv t1 = tcg_temp_new();
6394 gen_load_gpr(t1, rs);
6395 switch (opc) {
6396 case OPC_EXT:
6397 if (lsb + msb > 31) {
6398 goto fail;
6400 if (msb != 31) {
6401 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6402 } else {
6404 * The two checks together imply that lsb == 0,
6405 * so this is a simple sign-extension.
6407 tcg_gen_ext32s_tl(t0, t1);
6409 break;
6410 #if defined(TARGET_MIPS64)
6411 case OPC_DEXTU:
6412 lsb += 32;
6413 goto do_dext;
6414 case OPC_DEXTM:
6415 msb += 32;
6416 goto do_dext;
6417 case OPC_DEXT:
6418 do_dext:
6419 if (lsb + msb > 63) {
6420 goto fail;
6422 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6423 break;
6424 #endif
6425 case OPC_INS:
6426 if (lsb > msb) {
6427 goto fail;
6429 gen_load_gpr(t0, rt);
6430 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6431 tcg_gen_ext32s_tl(t0, t0);
6432 break;
6433 #if defined(TARGET_MIPS64)
6434 case OPC_DINSU:
6435 lsb += 32;
6436 /* FALLTHRU */
6437 case OPC_DINSM:
6438 msb += 32;
6439 /* FALLTHRU */
6440 case OPC_DINS:
6441 if (lsb > msb) {
6442 goto fail;
6444 gen_load_gpr(t0, rt);
6445 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6446 break;
6447 #endif
6448 default:
6449 fail:
6450 MIPS_INVAL("bitops");
6451 generate_exception_end(ctx, EXCP_RI);
6452 tcg_temp_free(t0);
6453 tcg_temp_free(t1);
6454 return;
6456 gen_store_gpr(t0, rt);
6457 tcg_temp_free(t0);
6458 tcg_temp_free(t1);
6461 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6463 TCGv t0;
6465 if (rd == 0) {
6466 /* If no destination, treat it as a NOP. */
6467 return;
6470 t0 = tcg_temp_new();
6471 gen_load_gpr(t0, rt);
6472 switch (op2) {
6473 case OPC_WSBH:
6475 TCGv t1 = tcg_temp_new();
6476 TCGv t2 = tcg_const_tl(0x00FF00FF);
6478 tcg_gen_shri_tl(t1, t0, 8);
6479 tcg_gen_and_tl(t1, t1, t2);
6480 tcg_gen_and_tl(t0, t0, t2);
6481 tcg_gen_shli_tl(t0, t0, 8);
6482 tcg_gen_or_tl(t0, t0, t1);
6483 tcg_temp_free(t2);
6484 tcg_temp_free(t1);
6485 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6487 break;
6488 case OPC_SEB:
6489 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6490 break;
6491 case OPC_SEH:
6492 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6493 break;
6494 #if defined(TARGET_MIPS64)
6495 case OPC_DSBH:
6497 TCGv t1 = tcg_temp_new();
6498 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6500 tcg_gen_shri_tl(t1, t0, 8);
6501 tcg_gen_and_tl(t1, t1, t2);
6502 tcg_gen_and_tl(t0, t0, t2);
6503 tcg_gen_shli_tl(t0, t0, 8);
6504 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6505 tcg_temp_free(t2);
6506 tcg_temp_free(t1);
6508 break;
6509 case OPC_DSHD:
6511 TCGv t1 = tcg_temp_new();
6512 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6514 tcg_gen_shri_tl(t1, t0, 16);
6515 tcg_gen_and_tl(t1, t1, t2);
6516 tcg_gen_and_tl(t0, t0, t2);
6517 tcg_gen_shli_tl(t0, t0, 16);
6518 tcg_gen_or_tl(t0, t0, t1);
6519 tcg_gen_shri_tl(t1, t0, 32);
6520 tcg_gen_shli_tl(t0, t0, 32);
6521 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6522 tcg_temp_free(t2);
6523 tcg_temp_free(t1);
6525 break;
6526 #endif
6527 default:
6528 MIPS_INVAL("bsfhl");
6529 generate_exception_end(ctx, EXCP_RI);
6530 tcg_temp_free(t0);
6531 return;
6533 tcg_temp_free(t0);
6536 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6537 int imm2)
6539 TCGv t0;
6540 TCGv t1;
6541 if (rd == 0) {
6542 /* Treat as NOP. */
6543 return;
6545 t0 = tcg_temp_new();
6546 t1 = tcg_temp_new();
6547 gen_load_gpr(t0, rs);
6548 gen_load_gpr(t1, rt);
6549 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6550 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6551 if (opc == OPC_LSA) {
6552 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6555 tcg_temp_free(t1);
6556 tcg_temp_free(t0);
6558 return;
6561 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6562 int rt, int bits)
6564 TCGv t0;
6565 if (rd == 0) {
6566 /* Treat as NOP. */
6567 return;
6569 t0 = tcg_temp_new();
6570 if (bits == 0 || bits == wordsz) {
6571 if (bits == 0) {
6572 gen_load_gpr(t0, rt);
6573 } else {
6574 gen_load_gpr(t0, rs);
6576 switch (wordsz) {
6577 case 32:
6578 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6579 break;
6580 #if defined(TARGET_MIPS64)
6581 case 64:
6582 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6583 break;
6584 #endif
6586 } else {
6587 TCGv t1 = tcg_temp_new();
6588 gen_load_gpr(t0, rt);
6589 gen_load_gpr(t1, rs);
6590 switch (wordsz) {
6591 case 32:
6593 TCGv_i64 t2 = tcg_temp_new_i64();
6594 tcg_gen_concat_tl_i64(t2, t1, t0);
6595 tcg_gen_shri_i64(t2, t2, 32 - bits);
6596 gen_move_low32(cpu_gpr[rd], t2);
6597 tcg_temp_free_i64(t2);
6599 break;
6600 #if defined(TARGET_MIPS64)
6601 case 64:
6602 tcg_gen_shli_tl(t0, t0, bits);
6603 tcg_gen_shri_tl(t1, t1, 64 - bits);
6604 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6605 break;
6606 #endif
6608 tcg_temp_free(t1);
6611 tcg_temp_free(t0);
6614 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6615 int bp)
6617 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6620 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6621 int shift)
6623 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6626 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6628 TCGv t0;
6629 if (rd == 0) {
6630 /* Treat as NOP. */
6631 return;
6633 t0 = tcg_temp_new();
6634 gen_load_gpr(t0, rt);
6635 switch (opc) {
6636 case OPC_BITSWAP:
6637 gen_helper_bitswap(cpu_gpr[rd], t0);
6638 break;
6639 #if defined(TARGET_MIPS64)
6640 case OPC_DBITSWAP:
6641 gen_helper_dbitswap(cpu_gpr[rd], t0);
6642 break;
6643 #endif
6645 tcg_temp_free(t0);
6648 #ifndef CONFIG_USER_ONLY
6649 /* CP0 (MMU and control) */
6650 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6652 TCGv_i64 t0 = tcg_temp_new_i64();
6653 TCGv_i64 t1 = tcg_temp_new_i64();
6655 tcg_gen_ext_tl_i64(t0, arg);
6656 tcg_gen_ld_i64(t1, cpu_env, off);
6657 #if defined(TARGET_MIPS64)
6658 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6659 #else
6660 tcg_gen_concat32_i64(t1, t1, t0);
6661 #endif
6662 tcg_gen_st_i64(t1, cpu_env, off);
6663 tcg_temp_free_i64(t1);
6664 tcg_temp_free_i64(t0);
6667 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6669 TCGv_i64 t0 = tcg_temp_new_i64();
6670 TCGv_i64 t1 = tcg_temp_new_i64();
6672 tcg_gen_ext_tl_i64(t0, arg);
6673 tcg_gen_ld_i64(t1, cpu_env, off);
6674 tcg_gen_concat32_i64(t1, t1, t0);
6675 tcg_gen_st_i64(t1, cpu_env, off);
6676 tcg_temp_free_i64(t1);
6677 tcg_temp_free_i64(t0);
6680 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6682 TCGv_i64 t0 = tcg_temp_new_i64();
6684 tcg_gen_ld_i64(t0, cpu_env, off);
6685 #if defined(TARGET_MIPS64)
6686 tcg_gen_shri_i64(t0, t0, 30);
6687 #else
6688 tcg_gen_shri_i64(t0, t0, 32);
6689 #endif
6690 gen_move_low32(arg, t0);
6691 tcg_temp_free_i64(t0);
6694 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6696 TCGv_i64 t0 = tcg_temp_new_i64();
6698 tcg_gen_ld_i64(t0, cpu_env, off);
6699 tcg_gen_shri_i64(t0, t0, 32 + shift);
6700 gen_move_low32(arg, t0);
6701 tcg_temp_free_i64(t0);
6704 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6706 TCGv_i32 t0 = tcg_temp_new_i32();
6708 tcg_gen_ld_i32(t0, cpu_env, off);
6709 tcg_gen_ext_i32_tl(arg, t0);
6710 tcg_temp_free_i32(t0);
6713 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6715 tcg_gen_ld_tl(arg, cpu_env, off);
6716 tcg_gen_ext32s_tl(arg, arg);
6719 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6721 TCGv_i32 t0 = tcg_temp_new_i32();
6723 tcg_gen_trunc_tl_i32(t0, arg);
6724 tcg_gen_st_i32(t0, cpu_env, off);
6725 tcg_temp_free_i32(t0);
6728 #define CP0_CHECK(c) \
6729 do { \
6730 if (!(c)) { \
6731 goto cp0_unimplemented; \
6733 } while (0)
6735 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6737 const char *register_name = "invalid";
6739 switch (reg) {
6740 case CP0_REGISTER_02:
6741 switch (sel) {
6742 case 0:
6743 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6744 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6745 register_name = "EntryLo0";
6746 break;
6747 default:
6748 goto cp0_unimplemented;
6750 break;
6751 case CP0_REGISTER_03:
6752 switch (sel) {
6753 case CP0_REG03__ENTRYLO1:
6754 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6755 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6756 register_name = "EntryLo1";
6757 break;
6758 default:
6759 goto cp0_unimplemented;
6761 break;
6762 case CP0_REGISTER_09:
6763 switch (sel) {
6764 case CP0_REG09__SAAR:
6765 CP0_CHECK(ctx->saar);
6766 gen_helper_mfhc0_saar(arg, cpu_env);
6767 register_name = "SAAR";
6768 break;
6769 default:
6770 goto cp0_unimplemented;
6772 break;
6773 case CP0_REGISTER_17:
6774 switch (sel) {
6775 case CP0_REG17__LLADDR:
6776 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6777 ctx->CP0_LLAddr_shift);
6778 register_name = "LLAddr";
6779 break;
6780 case CP0_REG17__MAAR:
6781 CP0_CHECK(ctx->mrp);
6782 gen_helper_mfhc0_maar(arg, cpu_env);
6783 register_name = "MAAR";
6784 break;
6785 default:
6786 goto cp0_unimplemented;
6788 break;
6789 case CP0_REGISTER_19:
6790 switch (sel) {
6791 case CP0_REG19__WATCHHI0:
6792 case CP0_REG19__WATCHHI1:
6793 case CP0_REG19__WATCHHI2:
6794 case CP0_REG19__WATCHHI3:
6795 case CP0_REG19__WATCHHI4:
6796 case CP0_REG19__WATCHHI5:
6797 case CP0_REG19__WATCHHI6:
6798 case CP0_REG19__WATCHHI7:
6799 /* upper 32 bits are only available when Config5MI != 0 */
6800 CP0_CHECK(ctx->mi);
6801 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6802 register_name = "WatchHi";
6803 break;
6804 default:
6805 goto cp0_unimplemented;
6807 break;
6808 case CP0_REGISTER_28:
6809 switch (sel) {
6810 case 0:
6811 case 2:
6812 case 4:
6813 case 6:
6814 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6815 register_name = "TagLo";
6816 break;
6817 default:
6818 goto cp0_unimplemented;
6820 break;
6821 default:
6822 goto cp0_unimplemented;
6824 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6825 return;
6827 cp0_unimplemented:
6828 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6829 register_name, reg, sel);
6830 tcg_gen_movi_tl(arg, 0);
6833 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6835 const char *register_name = "invalid";
6836 uint64_t mask = ctx->PAMask >> 36;
6838 switch (reg) {
6839 case CP0_REGISTER_02:
6840 switch (sel) {
6841 case 0:
6842 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6843 tcg_gen_andi_tl(arg, arg, mask);
6844 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6845 register_name = "EntryLo0";
6846 break;
6847 default:
6848 goto cp0_unimplemented;
6850 break;
6851 case CP0_REGISTER_03:
6852 switch (sel) {
6853 case CP0_REG03__ENTRYLO1:
6854 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6855 tcg_gen_andi_tl(arg, arg, mask);
6856 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6857 register_name = "EntryLo1";
6858 break;
6859 default:
6860 goto cp0_unimplemented;
6862 break;
6863 case CP0_REGISTER_09:
6864 switch (sel) {
6865 case CP0_REG09__SAAR:
6866 CP0_CHECK(ctx->saar);
6867 gen_helper_mthc0_saar(cpu_env, arg);
6868 register_name = "SAAR";
6869 break;
6870 default:
6871 goto cp0_unimplemented;
6873 break;
6874 case CP0_REGISTER_17:
6875 switch (sel) {
6876 case CP0_REG17__LLADDR:
6878 * LLAddr is read-only (the only exception is bit 0 if LLB is
6879 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6880 * relevant for modern MIPS cores supporting MTHC0, therefore
6881 * treating MTHC0 to LLAddr as NOP.
6883 register_name = "LLAddr";
6884 break;
6885 case CP0_REG17__MAAR:
6886 CP0_CHECK(ctx->mrp);
6887 gen_helper_mthc0_maar(cpu_env, arg);
6888 register_name = "MAAR";
6889 break;
6890 default:
6891 goto cp0_unimplemented;
6893 break;
6894 case CP0_REGISTER_19:
6895 switch (sel) {
6896 case CP0_REG19__WATCHHI0:
6897 case CP0_REG19__WATCHHI1:
6898 case CP0_REG19__WATCHHI2:
6899 case CP0_REG19__WATCHHI3:
6900 case CP0_REG19__WATCHHI4:
6901 case CP0_REG19__WATCHHI5:
6902 case CP0_REG19__WATCHHI6:
6903 case CP0_REG19__WATCHHI7:
6904 /* upper 32 bits are only available when Config5MI != 0 */
6905 CP0_CHECK(ctx->mi);
6906 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6907 register_name = "WatchHi";
6908 break;
6909 default:
6910 goto cp0_unimplemented;
6912 break;
6913 case CP0_REGISTER_28:
6914 switch (sel) {
6915 case 0:
6916 case 2:
6917 case 4:
6918 case 6:
6919 tcg_gen_andi_tl(arg, arg, mask);
6920 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6921 register_name = "TagLo";
6922 break;
6923 default:
6924 goto cp0_unimplemented;
6926 break;
6927 default:
6928 goto cp0_unimplemented;
6930 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6932 cp0_unimplemented:
6933 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6934 register_name, reg, sel);
6937 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6939 if (ctx->insn_flags & ISA_MIPS32R6) {
6940 tcg_gen_movi_tl(arg, 0);
6941 } else {
6942 tcg_gen_movi_tl(arg, ~0);
6946 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6948 const char *register_name = "invalid";
6950 if (sel != 0) {
6951 check_insn(ctx, ISA_MIPS32);
6954 switch (reg) {
6955 case CP0_REGISTER_00:
6956 switch (sel) {
6957 case CP0_REG00__INDEX:
6958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6959 register_name = "Index";
6960 break;
6961 case CP0_REG00__MVPCONTROL:
6962 CP0_CHECK(ctx->insn_flags & ASE_MT);
6963 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6964 register_name = "MVPControl";
6965 break;
6966 case CP0_REG00__MVPCONF0:
6967 CP0_CHECK(ctx->insn_flags & ASE_MT);
6968 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6969 register_name = "MVPConf0";
6970 break;
6971 case CP0_REG00__MVPCONF1:
6972 CP0_CHECK(ctx->insn_flags & ASE_MT);
6973 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6974 register_name = "MVPConf1";
6975 break;
6976 case CP0_REG00__VPCONTROL:
6977 CP0_CHECK(ctx->vp);
6978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6979 register_name = "VPControl";
6980 break;
6981 default:
6982 goto cp0_unimplemented;
6984 break;
6985 case CP0_REGISTER_01:
6986 switch (sel) {
6987 case CP0_REG01__RANDOM:
6988 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6989 gen_helper_mfc0_random(arg, cpu_env);
6990 register_name = "Random";
6991 break;
6992 case CP0_REG01__VPECONTROL:
6993 CP0_CHECK(ctx->insn_flags & ASE_MT);
6994 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6995 register_name = "VPEControl";
6996 break;
6997 case CP0_REG01__VPECONF0:
6998 CP0_CHECK(ctx->insn_flags & ASE_MT);
6999 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7000 register_name = "VPEConf0";
7001 break;
7002 case CP0_REG01__VPECONF1:
7003 CP0_CHECK(ctx->insn_flags & ASE_MT);
7004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7005 register_name = "VPEConf1";
7006 break;
7007 case CP0_REG01__YQMASK:
7008 CP0_CHECK(ctx->insn_flags & ASE_MT);
7009 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7010 register_name = "YQMask";
7011 break;
7012 case CP0_REG01__VPESCHEDULE:
7013 CP0_CHECK(ctx->insn_flags & ASE_MT);
7014 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7015 register_name = "VPESchedule";
7016 break;
7017 case CP0_REG01__VPESCHEFBACK:
7018 CP0_CHECK(ctx->insn_flags & ASE_MT);
7019 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7020 register_name = "VPEScheFBack";
7021 break;
7022 case CP0_REG01__VPEOPT:
7023 CP0_CHECK(ctx->insn_flags & ASE_MT);
7024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7025 register_name = "VPEOpt";
7026 break;
7027 default:
7028 goto cp0_unimplemented;
7030 break;
7031 case CP0_REGISTER_02:
7032 switch (sel) {
7033 case CP0_REG02__ENTRYLO0:
7035 TCGv_i64 tmp = tcg_temp_new_i64();
7036 tcg_gen_ld_i64(tmp, cpu_env,
7037 offsetof(CPUMIPSState, CP0_EntryLo0));
7038 #if defined(TARGET_MIPS64)
7039 if (ctx->rxi) {
7040 /* Move RI/XI fields to bits 31:30 */
7041 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7042 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7044 #endif
7045 gen_move_low32(arg, tmp);
7046 tcg_temp_free_i64(tmp);
7048 register_name = "EntryLo0";
7049 break;
7050 case CP0_REG02__TCSTATUS:
7051 CP0_CHECK(ctx->insn_flags & ASE_MT);
7052 gen_helper_mfc0_tcstatus(arg, cpu_env);
7053 register_name = "TCStatus";
7054 break;
7055 case CP0_REG02__TCBIND:
7056 CP0_CHECK(ctx->insn_flags & ASE_MT);
7057 gen_helper_mfc0_tcbind(arg, cpu_env);
7058 register_name = "TCBind";
7059 break;
7060 case CP0_REG02__TCRESTART:
7061 CP0_CHECK(ctx->insn_flags & ASE_MT);
7062 gen_helper_mfc0_tcrestart(arg, cpu_env);
7063 register_name = "TCRestart";
7064 break;
7065 case CP0_REG02__TCHALT:
7066 CP0_CHECK(ctx->insn_flags & ASE_MT);
7067 gen_helper_mfc0_tchalt(arg, cpu_env);
7068 register_name = "TCHalt";
7069 break;
7070 case CP0_REG02__TCCONTEXT:
7071 CP0_CHECK(ctx->insn_flags & ASE_MT);
7072 gen_helper_mfc0_tccontext(arg, cpu_env);
7073 register_name = "TCContext";
7074 break;
7075 case CP0_REG02__TCSCHEDULE:
7076 CP0_CHECK(ctx->insn_flags & ASE_MT);
7077 gen_helper_mfc0_tcschedule(arg, cpu_env);
7078 register_name = "TCSchedule";
7079 break;
7080 case CP0_REG02__TCSCHEFBACK:
7081 CP0_CHECK(ctx->insn_flags & ASE_MT);
7082 gen_helper_mfc0_tcschefback(arg, cpu_env);
7083 register_name = "TCScheFBack";
7084 break;
7085 default:
7086 goto cp0_unimplemented;
7088 break;
7089 case CP0_REGISTER_03:
7090 switch (sel) {
7091 case CP0_REG03__ENTRYLO1:
7093 TCGv_i64 tmp = tcg_temp_new_i64();
7094 tcg_gen_ld_i64(tmp, cpu_env,
7095 offsetof(CPUMIPSState, CP0_EntryLo1));
7096 #if defined(TARGET_MIPS64)
7097 if (ctx->rxi) {
7098 /* Move RI/XI fields to bits 31:30 */
7099 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7100 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7102 #endif
7103 gen_move_low32(arg, tmp);
7104 tcg_temp_free_i64(tmp);
7106 register_name = "EntryLo1";
7107 break;
7108 case CP0_REG03__GLOBALNUM:
7109 CP0_CHECK(ctx->vp);
7110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7111 register_name = "GlobalNumber";
7112 break;
7113 default:
7114 goto cp0_unimplemented;
7116 break;
7117 case CP0_REGISTER_04:
7118 switch (sel) {
7119 case CP0_REG04__CONTEXT:
7120 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7121 tcg_gen_ext32s_tl(arg, arg);
7122 register_name = "Context";
7123 break;
7124 case CP0_REG04__CONTEXTCONFIG:
7125 /* SmartMIPS ASE */
7126 /* gen_helper_mfc0_contextconfig(arg); */
7127 register_name = "ContextConfig";
7128 goto cp0_unimplemented;
7129 case CP0_REG04__USERLOCAL:
7130 CP0_CHECK(ctx->ulri);
7131 tcg_gen_ld_tl(arg, cpu_env,
7132 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7133 tcg_gen_ext32s_tl(arg, arg);
7134 register_name = "UserLocal";
7135 break;
7136 case CP0_REG04__MMID:
7137 CP0_CHECK(ctx->mi);
7138 gen_helper_mtc0_memorymapid(cpu_env, arg);
7139 register_name = "MMID";
7140 break;
7141 default:
7142 goto cp0_unimplemented;
7144 break;
7145 case CP0_REGISTER_05:
7146 switch (sel) {
7147 case CP0_REG05__PAGEMASK:
7148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7149 register_name = "PageMask";
7150 break;
7151 case CP0_REG05__PAGEGRAIN:
7152 check_insn(ctx, ISA_MIPS32R2);
7153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7154 register_name = "PageGrain";
7155 break;
7156 case CP0_REG05__SEGCTL0:
7157 CP0_CHECK(ctx->sc);
7158 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7159 tcg_gen_ext32s_tl(arg, arg);
7160 register_name = "SegCtl0";
7161 break;
7162 case CP0_REG05__SEGCTL1:
7163 CP0_CHECK(ctx->sc);
7164 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7165 tcg_gen_ext32s_tl(arg, arg);
7166 register_name = "SegCtl1";
7167 break;
7168 case CP0_REG05__SEGCTL2:
7169 CP0_CHECK(ctx->sc);
7170 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7171 tcg_gen_ext32s_tl(arg, arg);
7172 register_name = "SegCtl2";
7173 break;
7174 case CP0_REG05__PWBASE:
7175 check_pw(ctx);
7176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7177 register_name = "PWBase";
7178 break;
7179 case CP0_REG05__PWFIELD:
7180 check_pw(ctx);
7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7182 register_name = "PWField";
7183 break;
7184 case CP0_REG05__PWSIZE:
7185 check_pw(ctx);
7186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7187 register_name = "PWSize";
7188 break;
7189 default:
7190 goto cp0_unimplemented;
7192 break;
7193 case CP0_REGISTER_06:
7194 switch (sel) {
7195 case CP0_REG06__WIRED:
7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7197 register_name = "Wired";
7198 break;
7199 case CP0_REG06__SRSCONF0:
7200 check_insn(ctx, ISA_MIPS32R2);
7201 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7202 register_name = "SRSConf0";
7203 break;
7204 case CP0_REG06__SRSCONF1:
7205 check_insn(ctx, ISA_MIPS32R2);
7206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7207 register_name = "SRSConf1";
7208 break;
7209 case CP0_REG06__SRSCONF2:
7210 check_insn(ctx, ISA_MIPS32R2);
7211 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7212 register_name = "SRSConf2";
7213 break;
7214 case CP0_REG06__SRSCONF3:
7215 check_insn(ctx, ISA_MIPS32R2);
7216 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7217 register_name = "SRSConf3";
7218 break;
7219 case CP0_REG06__SRSCONF4:
7220 check_insn(ctx, ISA_MIPS32R2);
7221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7222 register_name = "SRSConf4";
7223 break;
7224 case CP0_REG06__PWCTL:
7225 check_pw(ctx);
7226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7227 register_name = "PWCtl";
7228 break;
7229 default:
7230 goto cp0_unimplemented;
7232 break;
7233 case CP0_REGISTER_07:
7234 switch (sel) {
7235 case CP0_REG07__HWRENA:
7236 check_insn(ctx, ISA_MIPS32R2);
7237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7238 register_name = "HWREna";
7239 break;
7240 default:
7241 goto cp0_unimplemented;
7243 break;
7244 case CP0_REGISTER_08:
7245 switch (sel) {
7246 case CP0_REG08__BADVADDR:
7247 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7248 tcg_gen_ext32s_tl(arg, arg);
7249 register_name = "BadVAddr";
7250 break;
7251 case CP0_REG08__BADINSTR:
7252 CP0_CHECK(ctx->bi);
7253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7254 register_name = "BadInstr";
7255 break;
7256 case CP0_REG08__BADINSTRP:
7257 CP0_CHECK(ctx->bp);
7258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7259 register_name = "BadInstrP";
7260 break;
7261 case CP0_REG08__BADINSTRX:
7262 CP0_CHECK(ctx->bi);
7263 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7264 tcg_gen_andi_tl(arg, arg, ~0xffff);
7265 register_name = "BadInstrX";
7266 break;
7267 default:
7268 goto cp0_unimplemented;
7270 break;
7271 case CP0_REGISTER_09:
7272 switch (sel) {
7273 case CP0_REG09__COUNT:
7274 /* Mark as an IO operation because we read the time. */
7275 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7276 gen_io_start();
7278 gen_helper_mfc0_count(arg, cpu_env);
7280 * Break the TB to be able to take timer interrupts immediately
7281 * after reading count. DISAS_STOP isn't sufficient, we need to
7282 * ensure we break completely out of translated code.
7284 gen_save_pc(ctx->base.pc_next + 4);
7285 ctx->base.is_jmp = DISAS_EXIT;
7286 register_name = "Count";
7287 break;
7288 case CP0_REG09__SAARI:
7289 CP0_CHECK(ctx->saar);
7290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7291 register_name = "SAARI";
7292 break;
7293 case CP0_REG09__SAAR:
7294 CP0_CHECK(ctx->saar);
7295 gen_helper_mfc0_saar(arg, cpu_env);
7296 register_name = "SAAR";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case CP0_REGISTER_10:
7303 switch (sel) {
7304 case CP0_REG10__ENTRYHI:
7305 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7306 tcg_gen_ext32s_tl(arg, arg);
7307 register_name = "EntryHi";
7308 break;
7309 default:
7310 goto cp0_unimplemented;
7312 break;
7313 case CP0_REGISTER_11:
7314 switch (sel) {
7315 case CP0_REG11__COMPARE:
7316 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7317 register_name = "Compare";
7318 break;
7319 /* 6,7 are implementation dependent */
7320 default:
7321 goto cp0_unimplemented;
7323 break;
7324 case CP0_REGISTER_12:
7325 switch (sel) {
7326 case CP0_REG12__STATUS:
7327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7328 register_name = "Status";
7329 break;
7330 case CP0_REG12__INTCTL:
7331 check_insn(ctx, ISA_MIPS32R2);
7332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7333 register_name = "IntCtl";
7334 break;
7335 case CP0_REG12__SRSCTL:
7336 check_insn(ctx, ISA_MIPS32R2);
7337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7338 register_name = "SRSCtl";
7339 break;
7340 case CP0_REG12__SRSMAP:
7341 check_insn(ctx, ISA_MIPS32R2);
7342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7343 register_name = "SRSMap";
7344 break;
7345 default:
7346 goto cp0_unimplemented;
7348 break;
7349 case CP0_REGISTER_13:
7350 switch (sel) {
7351 case CP0_REG13__CAUSE:
7352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7353 register_name = "Cause";
7354 break;
7355 default:
7356 goto cp0_unimplemented;
7358 break;
7359 case CP0_REGISTER_14:
7360 switch (sel) {
7361 case CP0_REG14__EPC:
7362 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7363 tcg_gen_ext32s_tl(arg, arg);
7364 register_name = "EPC";
7365 break;
7366 default:
7367 goto cp0_unimplemented;
7369 break;
7370 case CP0_REGISTER_15:
7371 switch (sel) {
7372 case CP0_REG15__PRID:
7373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7374 register_name = "PRid";
7375 break;
7376 case CP0_REG15__EBASE:
7377 check_insn(ctx, ISA_MIPS32R2);
7378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7379 tcg_gen_ext32s_tl(arg, arg);
7380 register_name = "EBase";
7381 break;
7382 case CP0_REG15__CMGCRBASE:
7383 check_insn(ctx, ISA_MIPS32R2);
7384 CP0_CHECK(ctx->cmgcr);
7385 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7386 tcg_gen_ext32s_tl(arg, arg);
7387 register_name = "CMGCRBase";
7388 break;
7389 default:
7390 goto cp0_unimplemented;
7392 break;
7393 case CP0_REGISTER_16:
7394 switch (sel) {
7395 case CP0_REG16__CONFIG:
7396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7397 register_name = "Config";
7398 break;
7399 case CP0_REG16__CONFIG1:
7400 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7401 register_name = "Config1";
7402 break;
7403 case CP0_REG16__CONFIG2:
7404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7405 register_name = "Config2";
7406 break;
7407 case CP0_REG16__CONFIG3:
7408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7409 register_name = "Config3";
7410 break;
7411 case CP0_REG16__CONFIG4:
7412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7413 register_name = "Config4";
7414 break;
7415 case CP0_REG16__CONFIG5:
7416 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7417 register_name = "Config5";
7418 break;
7419 /* 6,7 are implementation dependent */
7420 case CP0_REG16__CONFIG6:
7421 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7422 register_name = "Config6";
7423 break;
7424 case CP0_REG16__CONFIG7:
7425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7426 register_name = "Config7";
7427 break;
7428 default:
7429 goto cp0_unimplemented;
7431 break;
7432 case CP0_REGISTER_17:
7433 switch (sel) {
7434 case CP0_REG17__LLADDR:
7435 gen_helper_mfc0_lladdr(arg, cpu_env);
7436 register_name = "LLAddr";
7437 break;
7438 case CP0_REG17__MAAR:
7439 CP0_CHECK(ctx->mrp);
7440 gen_helper_mfc0_maar(arg, cpu_env);
7441 register_name = "MAAR";
7442 break;
7443 case CP0_REG17__MAARI:
7444 CP0_CHECK(ctx->mrp);
7445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7446 register_name = "MAARI";
7447 break;
7448 default:
7449 goto cp0_unimplemented;
7451 break;
7452 case CP0_REGISTER_18:
7453 switch (sel) {
7454 case CP0_REG18__WATCHLO0:
7455 case CP0_REG18__WATCHLO1:
7456 case CP0_REG18__WATCHLO2:
7457 case CP0_REG18__WATCHLO3:
7458 case CP0_REG18__WATCHLO4:
7459 case CP0_REG18__WATCHLO5:
7460 case CP0_REG18__WATCHLO6:
7461 case CP0_REG18__WATCHLO7:
7462 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7463 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7464 register_name = "WatchLo";
7465 break;
7466 default:
7467 goto cp0_unimplemented;
7469 break;
7470 case CP0_REGISTER_19:
7471 switch (sel) {
7472 case CP0_REG19__WATCHHI0:
7473 case CP0_REG19__WATCHHI1:
7474 case CP0_REG19__WATCHHI2:
7475 case CP0_REG19__WATCHHI3:
7476 case CP0_REG19__WATCHHI4:
7477 case CP0_REG19__WATCHHI5:
7478 case CP0_REG19__WATCHHI6:
7479 case CP0_REG19__WATCHHI7:
7480 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7481 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7482 register_name = "WatchHi";
7483 break;
7484 default:
7485 goto cp0_unimplemented;
7487 break;
7488 case CP0_REGISTER_20:
7489 switch (sel) {
7490 case CP0_REG20__XCONTEXT:
7491 #if defined(TARGET_MIPS64)
7492 check_insn(ctx, ISA_MIPS3);
7493 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7494 tcg_gen_ext32s_tl(arg, arg);
7495 register_name = "XContext";
7496 break;
7497 #endif
7498 default:
7499 goto cp0_unimplemented;
7501 break;
7502 case CP0_REGISTER_21:
7503 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7504 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7505 switch (sel) {
7506 case 0:
7507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7508 register_name = "Framemask";
7509 break;
7510 default:
7511 goto cp0_unimplemented;
7513 break;
7514 case CP0_REGISTER_22:
7515 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7516 register_name = "'Diagnostic"; /* implementation dependent */
7517 break;
7518 case CP0_REGISTER_23:
7519 switch (sel) {
7520 case CP0_REG23__DEBUG:
7521 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7522 register_name = "Debug";
7523 break;
7524 case CP0_REG23__TRACECONTROL:
7525 /* PDtrace support */
7526 /* gen_helper_mfc0_tracecontrol(arg); */
7527 register_name = "TraceControl";
7528 goto cp0_unimplemented;
7529 case CP0_REG23__TRACECONTROL2:
7530 /* PDtrace support */
7531 /* gen_helper_mfc0_tracecontrol2(arg); */
7532 register_name = "TraceControl2";
7533 goto cp0_unimplemented;
7534 case CP0_REG23__USERTRACEDATA1:
7535 /* PDtrace support */
7536 /* gen_helper_mfc0_usertracedata1(arg);*/
7537 register_name = "UserTraceData1";
7538 goto cp0_unimplemented;
7539 case CP0_REG23__TRACEIBPC:
7540 /* PDtrace support */
7541 /* gen_helper_mfc0_traceibpc(arg); */
7542 register_name = "TraceIBPC";
7543 goto cp0_unimplemented;
7544 case CP0_REG23__TRACEDBPC:
7545 /* PDtrace support */
7546 /* gen_helper_mfc0_tracedbpc(arg); */
7547 register_name = "TraceDBPC";
7548 goto cp0_unimplemented;
7549 default:
7550 goto cp0_unimplemented;
7552 break;
7553 case CP0_REGISTER_24:
7554 switch (sel) {
7555 case CP0_REG24__DEPC:
7556 /* EJTAG support */
7557 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7558 tcg_gen_ext32s_tl(arg, arg);
7559 register_name = "DEPC";
7560 break;
7561 default:
7562 goto cp0_unimplemented;
7564 break;
7565 case CP0_REGISTER_25:
7566 switch (sel) {
7567 case CP0_REG25__PERFCTL0:
7568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7569 register_name = "Performance0";
7570 break;
7571 case CP0_REG25__PERFCNT0:
7572 /* gen_helper_mfc0_performance1(arg); */
7573 register_name = "Performance1";
7574 goto cp0_unimplemented;
7575 case CP0_REG25__PERFCTL1:
7576 /* gen_helper_mfc0_performance2(arg); */
7577 register_name = "Performance2";
7578 goto cp0_unimplemented;
7579 case CP0_REG25__PERFCNT1:
7580 /* gen_helper_mfc0_performance3(arg); */
7581 register_name = "Performance3";
7582 goto cp0_unimplemented;
7583 case CP0_REG25__PERFCTL2:
7584 /* gen_helper_mfc0_performance4(arg); */
7585 register_name = "Performance4";
7586 goto cp0_unimplemented;
7587 case CP0_REG25__PERFCNT2:
7588 /* gen_helper_mfc0_performance5(arg); */
7589 register_name = "Performance5";
7590 goto cp0_unimplemented;
7591 case CP0_REG25__PERFCTL3:
7592 /* gen_helper_mfc0_performance6(arg); */
7593 register_name = "Performance6";
7594 goto cp0_unimplemented;
7595 case CP0_REG25__PERFCNT3:
7596 /* gen_helper_mfc0_performance7(arg); */
7597 register_name = "Performance7";
7598 goto cp0_unimplemented;
7599 default:
7600 goto cp0_unimplemented;
7602 break;
7603 case CP0_REGISTER_26:
7604 switch (sel) {
7605 case CP0_REG26__ERRCTL:
7606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7607 register_name = "ErrCtl";
7608 break;
7609 default:
7610 goto cp0_unimplemented;
7612 break;
7613 case CP0_REGISTER_27:
7614 switch (sel) {
7615 case CP0_REG27__CACHERR:
7616 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7617 register_name = "CacheErr";
7618 break;
7619 default:
7620 goto cp0_unimplemented;
7622 break;
7623 case CP0_REGISTER_28:
7624 switch (sel) {
7625 case CP0_REG28__TAGLO:
7626 case CP0_REG28__TAGLO1:
7627 case CP0_REG28__TAGLO2:
7628 case CP0_REG28__TAGLO3:
7630 TCGv_i64 tmp = tcg_temp_new_i64();
7631 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7632 gen_move_low32(arg, tmp);
7633 tcg_temp_free_i64(tmp);
7635 register_name = "TagLo";
7636 break;
7637 case CP0_REG28__DATALO:
7638 case CP0_REG28__DATALO1:
7639 case CP0_REG28__DATALO2:
7640 case CP0_REG28__DATALO3:
7641 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7642 register_name = "DataLo";
7643 break;
7644 default:
7645 goto cp0_unimplemented;
7647 break;
7648 case CP0_REGISTER_29:
7649 switch (sel) {
7650 case CP0_REG29__TAGHI:
7651 case CP0_REG29__TAGHI1:
7652 case CP0_REG29__TAGHI2:
7653 case CP0_REG29__TAGHI3:
7654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7655 register_name = "TagHi";
7656 break;
7657 case CP0_REG29__DATAHI:
7658 case CP0_REG29__DATAHI1:
7659 case CP0_REG29__DATAHI2:
7660 case CP0_REG29__DATAHI3:
7661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7662 register_name = "DataHi";
7663 break;
7664 default:
7665 goto cp0_unimplemented;
7667 break;
7668 case CP0_REGISTER_30:
7669 switch (sel) {
7670 case CP0_REG30__ERROREPC:
7671 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7672 tcg_gen_ext32s_tl(arg, arg);
7673 register_name = "ErrorEPC";
7674 break;
7675 default:
7676 goto cp0_unimplemented;
7678 break;
7679 case CP0_REGISTER_31:
7680 switch (sel) {
7681 case CP0_REG31__DESAVE:
7682 /* EJTAG support */
7683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7684 register_name = "DESAVE";
7685 break;
7686 case CP0_REG31__KSCRATCH1:
7687 case CP0_REG31__KSCRATCH2:
7688 case CP0_REG31__KSCRATCH3:
7689 case CP0_REG31__KSCRATCH4:
7690 case CP0_REG31__KSCRATCH5:
7691 case CP0_REG31__KSCRATCH6:
7692 CP0_CHECK(ctx->kscrexist & (1 << sel));
7693 tcg_gen_ld_tl(arg, cpu_env,
7694 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7695 tcg_gen_ext32s_tl(arg, arg);
7696 register_name = "KScratch";
7697 break;
7698 default:
7699 goto cp0_unimplemented;
7701 break;
7702 default:
7703 goto cp0_unimplemented;
7705 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7706 return;
7708 cp0_unimplemented:
7709 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7710 register_name, reg, sel);
7711 gen_mfc0_unimplemented(ctx, arg);
7714 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7716 const char *register_name = "invalid";
7718 if (sel != 0) {
7719 check_insn(ctx, ISA_MIPS32);
7722 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7723 gen_io_start();
7726 switch (reg) {
7727 case CP0_REGISTER_00:
7728 switch (sel) {
7729 case CP0_REG00__INDEX:
7730 gen_helper_mtc0_index(cpu_env, arg);
7731 register_name = "Index";
7732 break;
7733 case CP0_REG00__MVPCONTROL:
7734 CP0_CHECK(ctx->insn_flags & ASE_MT);
7735 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7736 register_name = "MVPControl";
7737 break;
7738 case CP0_REG00__MVPCONF0:
7739 CP0_CHECK(ctx->insn_flags & ASE_MT);
7740 /* ignored */
7741 register_name = "MVPConf0";
7742 break;
7743 case CP0_REG00__MVPCONF1:
7744 CP0_CHECK(ctx->insn_flags & ASE_MT);
7745 /* ignored */
7746 register_name = "MVPConf1";
7747 break;
7748 case CP0_REG00__VPCONTROL:
7749 CP0_CHECK(ctx->vp);
7750 /* ignored */
7751 register_name = "VPControl";
7752 break;
7753 default:
7754 goto cp0_unimplemented;
7756 break;
7757 case CP0_REGISTER_01:
7758 switch (sel) {
7759 case CP0_REG01__RANDOM:
7760 /* ignored */
7761 register_name = "Random";
7762 break;
7763 case CP0_REG01__VPECONTROL:
7764 CP0_CHECK(ctx->insn_flags & ASE_MT);
7765 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7766 register_name = "VPEControl";
7767 break;
7768 case CP0_REG01__VPECONF0:
7769 CP0_CHECK(ctx->insn_flags & ASE_MT);
7770 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7771 register_name = "VPEConf0";
7772 break;
7773 case CP0_REG01__VPECONF1:
7774 CP0_CHECK(ctx->insn_flags & ASE_MT);
7775 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7776 register_name = "VPEConf1";
7777 break;
7778 case CP0_REG01__YQMASK:
7779 CP0_CHECK(ctx->insn_flags & ASE_MT);
7780 gen_helper_mtc0_yqmask(cpu_env, arg);
7781 register_name = "YQMask";
7782 break;
7783 case CP0_REG01__VPESCHEDULE:
7784 CP0_CHECK(ctx->insn_flags & ASE_MT);
7785 tcg_gen_st_tl(arg, cpu_env,
7786 offsetof(CPUMIPSState, CP0_VPESchedule));
7787 register_name = "VPESchedule";
7788 break;
7789 case CP0_REG01__VPESCHEFBACK:
7790 CP0_CHECK(ctx->insn_flags & ASE_MT);
7791 tcg_gen_st_tl(arg, cpu_env,
7792 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7793 register_name = "VPEScheFBack";
7794 break;
7795 case CP0_REG01__VPEOPT:
7796 CP0_CHECK(ctx->insn_flags & ASE_MT);
7797 gen_helper_mtc0_vpeopt(cpu_env, arg);
7798 register_name = "VPEOpt";
7799 break;
7800 default:
7801 goto cp0_unimplemented;
7803 break;
7804 case CP0_REGISTER_02:
7805 switch (sel) {
7806 case CP0_REG02__ENTRYLO0:
7807 gen_helper_mtc0_entrylo0(cpu_env, arg);
7808 register_name = "EntryLo0";
7809 break;
7810 case CP0_REG02__TCSTATUS:
7811 CP0_CHECK(ctx->insn_flags & ASE_MT);
7812 gen_helper_mtc0_tcstatus(cpu_env, arg);
7813 register_name = "TCStatus";
7814 break;
7815 case CP0_REG02__TCBIND:
7816 CP0_CHECK(ctx->insn_flags & ASE_MT);
7817 gen_helper_mtc0_tcbind(cpu_env, arg);
7818 register_name = "TCBind";
7819 break;
7820 case CP0_REG02__TCRESTART:
7821 CP0_CHECK(ctx->insn_flags & ASE_MT);
7822 gen_helper_mtc0_tcrestart(cpu_env, arg);
7823 register_name = "TCRestart";
7824 break;
7825 case CP0_REG02__TCHALT:
7826 CP0_CHECK(ctx->insn_flags & ASE_MT);
7827 gen_helper_mtc0_tchalt(cpu_env, arg);
7828 register_name = "TCHalt";
7829 break;
7830 case CP0_REG02__TCCONTEXT:
7831 CP0_CHECK(ctx->insn_flags & ASE_MT);
7832 gen_helper_mtc0_tccontext(cpu_env, arg);
7833 register_name = "TCContext";
7834 break;
7835 case CP0_REG02__TCSCHEDULE:
7836 CP0_CHECK(ctx->insn_flags & ASE_MT);
7837 gen_helper_mtc0_tcschedule(cpu_env, arg);
7838 register_name = "TCSchedule";
7839 break;
7840 case CP0_REG02__TCSCHEFBACK:
7841 CP0_CHECK(ctx->insn_flags & ASE_MT);
7842 gen_helper_mtc0_tcschefback(cpu_env, arg);
7843 register_name = "TCScheFBack";
7844 break;
7845 default:
7846 goto cp0_unimplemented;
7848 break;
7849 case CP0_REGISTER_03:
7850 switch (sel) {
7851 case CP0_REG03__ENTRYLO1:
7852 gen_helper_mtc0_entrylo1(cpu_env, arg);
7853 register_name = "EntryLo1";
7854 break;
7855 case CP0_REG03__GLOBALNUM:
7856 CP0_CHECK(ctx->vp);
7857 /* ignored */
7858 register_name = "GlobalNumber";
7859 break;
7860 default:
7861 goto cp0_unimplemented;
7863 break;
7864 case CP0_REGISTER_04:
7865 switch (sel) {
7866 case CP0_REG04__CONTEXT:
7867 gen_helper_mtc0_context(cpu_env, arg);
7868 register_name = "Context";
7869 break;
7870 case CP0_REG04__CONTEXTCONFIG:
7871 /* SmartMIPS ASE */
7872 /* gen_helper_mtc0_contextconfig(arg); */
7873 register_name = "ContextConfig";
7874 goto cp0_unimplemented;
7875 case CP0_REG04__USERLOCAL:
7876 CP0_CHECK(ctx->ulri);
7877 tcg_gen_st_tl(arg, cpu_env,
7878 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7879 register_name = "UserLocal";
7880 break;
7881 case CP0_REG04__MMID:
7882 CP0_CHECK(ctx->mi);
7883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7884 register_name = "MMID";
7885 break;
7886 default:
7887 goto cp0_unimplemented;
7889 break;
7890 case CP0_REGISTER_05:
7891 switch (sel) {
7892 case CP0_REG05__PAGEMASK:
7893 gen_helper_mtc0_pagemask(cpu_env, arg);
7894 register_name = "PageMask";
7895 break;
7896 case CP0_REG05__PAGEGRAIN:
7897 check_insn(ctx, ISA_MIPS32R2);
7898 gen_helper_mtc0_pagegrain(cpu_env, arg);
7899 register_name = "PageGrain";
7900 ctx->base.is_jmp = DISAS_STOP;
7901 break;
7902 case CP0_REG05__SEGCTL0:
7903 CP0_CHECK(ctx->sc);
7904 gen_helper_mtc0_segctl0(cpu_env, arg);
7905 register_name = "SegCtl0";
7906 break;
7907 case CP0_REG05__SEGCTL1:
7908 CP0_CHECK(ctx->sc);
7909 gen_helper_mtc0_segctl1(cpu_env, arg);
7910 register_name = "SegCtl1";
7911 break;
7912 case CP0_REG05__SEGCTL2:
7913 CP0_CHECK(ctx->sc);
7914 gen_helper_mtc0_segctl2(cpu_env, arg);
7915 register_name = "SegCtl2";
7916 break;
7917 case CP0_REG05__PWBASE:
7918 check_pw(ctx);
7919 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7920 register_name = "PWBase";
7921 break;
7922 case CP0_REG05__PWFIELD:
7923 check_pw(ctx);
7924 gen_helper_mtc0_pwfield(cpu_env, arg);
7925 register_name = "PWField";
7926 break;
7927 case CP0_REG05__PWSIZE:
7928 check_pw(ctx);
7929 gen_helper_mtc0_pwsize(cpu_env, arg);
7930 register_name = "PWSize";
7931 break;
7932 default:
7933 goto cp0_unimplemented;
7935 break;
7936 case CP0_REGISTER_06:
7937 switch (sel) {
7938 case CP0_REG06__WIRED:
7939 gen_helper_mtc0_wired(cpu_env, arg);
7940 register_name = "Wired";
7941 break;
7942 case CP0_REG06__SRSCONF0:
7943 check_insn(ctx, ISA_MIPS32R2);
7944 gen_helper_mtc0_srsconf0(cpu_env, arg);
7945 register_name = "SRSConf0";
7946 break;
7947 case CP0_REG06__SRSCONF1:
7948 check_insn(ctx, ISA_MIPS32R2);
7949 gen_helper_mtc0_srsconf1(cpu_env, arg);
7950 register_name = "SRSConf1";
7951 break;
7952 case CP0_REG06__SRSCONF2:
7953 check_insn(ctx, ISA_MIPS32R2);
7954 gen_helper_mtc0_srsconf2(cpu_env, arg);
7955 register_name = "SRSConf2";
7956 break;
7957 case CP0_REG06__SRSCONF3:
7958 check_insn(ctx, ISA_MIPS32R2);
7959 gen_helper_mtc0_srsconf3(cpu_env, arg);
7960 register_name = "SRSConf3";
7961 break;
7962 case CP0_REG06__SRSCONF4:
7963 check_insn(ctx, ISA_MIPS32R2);
7964 gen_helper_mtc0_srsconf4(cpu_env, arg);
7965 register_name = "SRSConf4";
7966 break;
7967 case CP0_REG06__PWCTL:
7968 check_pw(ctx);
7969 gen_helper_mtc0_pwctl(cpu_env, arg);
7970 register_name = "PWCtl";
7971 break;
7972 default:
7973 goto cp0_unimplemented;
7975 break;
7976 case CP0_REGISTER_07:
7977 switch (sel) {
7978 case CP0_REG07__HWRENA:
7979 check_insn(ctx, ISA_MIPS32R2);
7980 gen_helper_mtc0_hwrena(cpu_env, arg);
7981 ctx->base.is_jmp = DISAS_STOP;
7982 register_name = "HWREna";
7983 break;
7984 default:
7985 goto cp0_unimplemented;
7987 break;
7988 case CP0_REGISTER_08:
7989 switch (sel) {
7990 case CP0_REG08__BADVADDR:
7991 /* ignored */
7992 register_name = "BadVAddr";
7993 break;
7994 case CP0_REG08__BADINSTR:
7995 /* ignored */
7996 register_name = "BadInstr";
7997 break;
7998 case CP0_REG08__BADINSTRP:
7999 /* ignored */
8000 register_name = "BadInstrP";
8001 break;
8002 case CP0_REG08__BADINSTRX:
8003 /* ignored */
8004 register_name = "BadInstrX";
8005 break;
8006 default:
8007 goto cp0_unimplemented;
8009 break;
8010 case CP0_REGISTER_09:
8011 switch (sel) {
8012 case CP0_REG09__COUNT:
8013 gen_helper_mtc0_count(cpu_env, arg);
8014 register_name = "Count";
8015 break;
8016 case CP0_REG09__SAARI:
8017 CP0_CHECK(ctx->saar);
8018 gen_helper_mtc0_saari(cpu_env, arg);
8019 register_name = "SAARI";
8020 break;
8021 case CP0_REG09__SAAR:
8022 CP0_CHECK(ctx->saar);
8023 gen_helper_mtc0_saar(cpu_env, arg);
8024 register_name = "SAAR";
8025 break;
8026 default:
8027 goto cp0_unimplemented;
8029 break;
8030 case CP0_REGISTER_10:
8031 switch (sel) {
8032 case CP0_REG10__ENTRYHI:
8033 gen_helper_mtc0_entryhi(cpu_env, arg);
8034 register_name = "EntryHi";
8035 break;
8036 default:
8037 goto cp0_unimplemented;
8039 break;
8040 case CP0_REGISTER_11:
8041 switch (sel) {
8042 case CP0_REG11__COMPARE:
8043 gen_helper_mtc0_compare(cpu_env, arg);
8044 register_name = "Compare";
8045 break;
8046 /* 6,7 are implementation dependent */
8047 default:
8048 goto cp0_unimplemented;
8050 break;
8051 case CP0_REGISTER_12:
8052 switch (sel) {
8053 case CP0_REG12__STATUS:
8054 save_cpu_state(ctx, 1);
8055 gen_helper_mtc0_status(cpu_env, arg);
8056 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8057 gen_save_pc(ctx->base.pc_next + 4);
8058 ctx->base.is_jmp = DISAS_EXIT;
8059 register_name = "Status";
8060 break;
8061 case CP0_REG12__INTCTL:
8062 check_insn(ctx, ISA_MIPS32R2);
8063 gen_helper_mtc0_intctl(cpu_env, arg);
8064 /* Stop translation as we may have switched the execution mode */
8065 ctx->base.is_jmp = DISAS_STOP;
8066 register_name = "IntCtl";
8067 break;
8068 case CP0_REG12__SRSCTL:
8069 check_insn(ctx, ISA_MIPS32R2);
8070 gen_helper_mtc0_srsctl(cpu_env, arg);
8071 /* Stop translation as we may have switched the execution mode */
8072 ctx->base.is_jmp = DISAS_STOP;
8073 register_name = "SRSCtl";
8074 break;
8075 case CP0_REG12__SRSMAP:
8076 check_insn(ctx, ISA_MIPS32R2);
8077 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8078 /* Stop translation as we may have switched the execution mode */
8079 ctx->base.is_jmp = DISAS_STOP;
8080 register_name = "SRSMap";
8081 break;
8082 default:
8083 goto cp0_unimplemented;
8085 break;
8086 case CP0_REGISTER_13:
8087 switch (sel) {
8088 case CP0_REG13__CAUSE:
8089 save_cpu_state(ctx, 1);
8090 gen_helper_mtc0_cause(cpu_env, arg);
8092 * Stop translation as we may have triggered an interrupt.
8093 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8094 * translated code to check for pending interrupts.
8096 gen_save_pc(ctx->base.pc_next + 4);
8097 ctx->base.is_jmp = DISAS_EXIT;
8098 register_name = "Cause";
8099 break;
8100 default:
8101 goto cp0_unimplemented;
8103 break;
8104 case CP0_REGISTER_14:
8105 switch (sel) {
8106 case CP0_REG14__EPC:
8107 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8108 register_name = "EPC";
8109 break;
8110 default:
8111 goto cp0_unimplemented;
8113 break;
8114 case CP0_REGISTER_15:
8115 switch (sel) {
8116 case CP0_REG15__PRID:
8117 /* ignored */
8118 register_name = "PRid";
8119 break;
8120 case CP0_REG15__EBASE:
8121 check_insn(ctx, ISA_MIPS32R2);
8122 gen_helper_mtc0_ebase(cpu_env, arg);
8123 register_name = "EBase";
8124 break;
8125 default:
8126 goto cp0_unimplemented;
8128 break;
8129 case CP0_REGISTER_16:
8130 switch (sel) {
8131 case CP0_REG16__CONFIG:
8132 gen_helper_mtc0_config0(cpu_env, arg);
8133 register_name = "Config";
8134 /* Stop translation as we may have switched the execution mode */
8135 ctx->base.is_jmp = DISAS_STOP;
8136 break;
8137 case CP0_REG16__CONFIG1:
8138 /* ignored, read only */
8139 register_name = "Config1";
8140 break;
8141 case CP0_REG16__CONFIG2:
8142 gen_helper_mtc0_config2(cpu_env, arg);
8143 register_name = "Config2";
8144 /* Stop translation as we may have switched the execution mode */
8145 ctx->base.is_jmp = DISAS_STOP;
8146 break;
8147 case CP0_REG16__CONFIG3:
8148 gen_helper_mtc0_config3(cpu_env, arg);
8149 register_name = "Config3";
8150 /* Stop translation as we may have switched the execution mode */
8151 ctx->base.is_jmp = DISAS_STOP;
8152 break;
8153 case CP0_REG16__CONFIG4:
8154 gen_helper_mtc0_config4(cpu_env, arg);
8155 register_name = "Config4";
8156 ctx->base.is_jmp = DISAS_STOP;
8157 break;
8158 case CP0_REG16__CONFIG5:
8159 gen_helper_mtc0_config5(cpu_env, arg);
8160 register_name = "Config5";
8161 /* Stop translation as we may have switched the execution mode */
8162 ctx->base.is_jmp = DISAS_STOP;
8163 break;
8164 /* 6,7 are implementation dependent */
8165 case CP0_REG16__CONFIG6:
8166 /* ignored */
8167 register_name = "Config6";
8168 break;
8169 case CP0_REG16__CONFIG7:
8170 /* ignored */
8171 register_name = "Config7";
8172 break;
8173 default:
8174 register_name = "Invalid config selector";
8175 goto cp0_unimplemented;
8177 break;
8178 case CP0_REGISTER_17:
8179 switch (sel) {
8180 case CP0_REG17__LLADDR:
8181 gen_helper_mtc0_lladdr(cpu_env, arg);
8182 register_name = "LLAddr";
8183 break;
8184 case CP0_REG17__MAAR:
8185 CP0_CHECK(ctx->mrp);
8186 gen_helper_mtc0_maar(cpu_env, arg);
8187 register_name = "MAAR";
8188 break;
8189 case CP0_REG17__MAARI:
8190 CP0_CHECK(ctx->mrp);
8191 gen_helper_mtc0_maari(cpu_env, arg);
8192 register_name = "MAARI";
8193 break;
8194 default:
8195 goto cp0_unimplemented;
8197 break;
8198 case CP0_REGISTER_18:
8199 switch (sel) {
8200 case CP0_REG18__WATCHLO0:
8201 case CP0_REG18__WATCHLO1:
8202 case CP0_REG18__WATCHLO2:
8203 case CP0_REG18__WATCHLO3:
8204 case CP0_REG18__WATCHLO4:
8205 case CP0_REG18__WATCHLO5:
8206 case CP0_REG18__WATCHLO6:
8207 case CP0_REG18__WATCHLO7:
8208 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8209 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8210 register_name = "WatchLo";
8211 break;
8212 default:
8213 goto cp0_unimplemented;
8215 break;
8216 case CP0_REGISTER_19:
8217 switch (sel) {
8218 case CP0_REG19__WATCHHI0:
8219 case CP0_REG19__WATCHHI1:
8220 case CP0_REG19__WATCHHI2:
8221 case CP0_REG19__WATCHHI3:
8222 case CP0_REG19__WATCHHI4:
8223 case CP0_REG19__WATCHHI5:
8224 case CP0_REG19__WATCHHI6:
8225 case CP0_REG19__WATCHHI7:
8226 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8227 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8228 register_name = "WatchHi";
8229 break;
8230 default:
8231 goto cp0_unimplemented;
8233 break;
8234 case CP0_REGISTER_20:
8235 switch (sel) {
8236 case CP0_REG20__XCONTEXT:
8237 #if defined(TARGET_MIPS64)
8238 check_insn(ctx, ISA_MIPS3);
8239 gen_helper_mtc0_xcontext(cpu_env, arg);
8240 register_name = "XContext";
8241 break;
8242 #endif
8243 default:
8244 goto cp0_unimplemented;
8246 break;
8247 case CP0_REGISTER_21:
8248 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8249 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8250 switch (sel) {
8251 case 0:
8252 gen_helper_mtc0_framemask(cpu_env, arg);
8253 register_name = "Framemask";
8254 break;
8255 default:
8256 goto cp0_unimplemented;
8258 break;
8259 case CP0_REGISTER_22:
8260 /* ignored */
8261 register_name = "Diagnostic"; /* implementation dependent */
8262 break;
8263 case CP0_REGISTER_23:
8264 switch (sel) {
8265 case CP0_REG23__DEBUG:
8266 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8267 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8268 gen_save_pc(ctx->base.pc_next + 4);
8269 ctx->base.is_jmp = DISAS_EXIT;
8270 register_name = "Debug";
8271 break;
8272 case CP0_REG23__TRACECONTROL:
8273 /* PDtrace support */
8274 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8275 register_name = "TraceControl";
8276 /* Stop translation as we may have switched the execution mode */
8277 ctx->base.is_jmp = DISAS_STOP;
8278 goto cp0_unimplemented;
8279 case CP0_REG23__TRACECONTROL2:
8280 /* PDtrace support */
8281 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8282 register_name = "TraceControl2";
8283 /* Stop translation as we may have switched the execution mode */
8284 ctx->base.is_jmp = DISAS_STOP;
8285 goto cp0_unimplemented;
8286 case CP0_REG23__USERTRACEDATA1:
8287 /* Stop translation as we may have switched the execution mode */
8288 ctx->base.is_jmp = DISAS_STOP;
8289 /* PDtrace support */
8290 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8291 register_name = "UserTraceData";
8292 /* Stop translation as we may have switched the execution mode */
8293 ctx->base.is_jmp = DISAS_STOP;
8294 goto cp0_unimplemented;
8295 case CP0_REG23__TRACEIBPC:
8296 /* PDtrace support */
8297 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8298 /* Stop translation as we may have switched the execution mode */
8299 ctx->base.is_jmp = DISAS_STOP;
8300 register_name = "TraceIBPC";
8301 goto cp0_unimplemented;
8302 case CP0_REG23__TRACEDBPC:
8303 /* PDtrace support */
8304 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8305 /* Stop translation as we may have switched the execution mode */
8306 ctx->base.is_jmp = DISAS_STOP;
8307 register_name = "TraceDBPC";
8308 goto cp0_unimplemented;
8309 default:
8310 goto cp0_unimplemented;
8312 break;
8313 case CP0_REGISTER_24:
8314 switch (sel) {
8315 case CP0_REG24__DEPC:
8316 /* EJTAG support */
8317 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8318 register_name = "DEPC";
8319 break;
8320 default:
8321 goto cp0_unimplemented;
8323 break;
8324 case CP0_REGISTER_25:
8325 switch (sel) {
8326 case CP0_REG25__PERFCTL0:
8327 gen_helper_mtc0_performance0(cpu_env, arg);
8328 register_name = "Performance0";
8329 break;
8330 case CP0_REG25__PERFCNT0:
8331 /* gen_helper_mtc0_performance1(arg); */
8332 register_name = "Performance1";
8333 goto cp0_unimplemented;
8334 case CP0_REG25__PERFCTL1:
8335 /* gen_helper_mtc0_performance2(arg); */
8336 register_name = "Performance2";
8337 goto cp0_unimplemented;
8338 case CP0_REG25__PERFCNT1:
8339 /* gen_helper_mtc0_performance3(arg); */
8340 register_name = "Performance3";
8341 goto cp0_unimplemented;
8342 case CP0_REG25__PERFCTL2:
8343 /* gen_helper_mtc0_performance4(arg); */
8344 register_name = "Performance4";
8345 goto cp0_unimplemented;
8346 case CP0_REG25__PERFCNT2:
8347 /* gen_helper_mtc0_performance5(arg); */
8348 register_name = "Performance5";
8349 goto cp0_unimplemented;
8350 case CP0_REG25__PERFCTL3:
8351 /* gen_helper_mtc0_performance6(arg); */
8352 register_name = "Performance6";
8353 goto cp0_unimplemented;
8354 case CP0_REG25__PERFCNT3:
8355 /* gen_helper_mtc0_performance7(arg); */
8356 register_name = "Performance7";
8357 goto cp0_unimplemented;
8358 default:
8359 goto cp0_unimplemented;
8361 break;
8362 case CP0_REGISTER_26:
8363 switch (sel) {
8364 case CP0_REG26__ERRCTL:
8365 gen_helper_mtc0_errctl(cpu_env, arg);
8366 ctx->base.is_jmp = DISAS_STOP;
8367 register_name = "ErrCtl";
8368 break;
8369 default:
8370 goto cp0_unimplemented;
8372 break;
8373 case CP0_REGISTER_27:
8374 switch (sel) {
8375 case CP0_REG27__CACHERR:
8376 /* ignored */
8377 register_name = "CacheErr";
8378 break;
8379 default:
8380 goto cp0_unimplemented;
8382 break;
8383 case CP0_REGISTER_28:
8384 switch (sel) {
8385 case CP0_REG28__TAGLO:
8386 case CP0_REG28__TAGLO1:
8387 case CP0_REG28__TAGLO2:
8388 case CP0_REG28__TAGLO3:
8389 gen_helper_mtc0_taglo(cpu_env, arg);
8390 register_name = "TagLo";
8391 break;
8392 case CP0_REG28__DATALO:
8393 case CP0_REG28__DATALO1:
8394 case CP0_REG28__DATALO2:
8395 case CP0_REG28__DATALO3:
8396 gen_helper_mtc0_datalo(cpu_env, arg);
8397 register_name = "DataLo";
8398 break;
8399 default:
8400 goto cp0_unimplemented;
8402 break;
8403 case CP0_REGISTER_29:
8404 switch (sel) {
8405 case CP0_REG29__TAGHI:
8406 case CP0_REG29__TAGHI1:
8407 case CP0_REG29__TAGHI2:
8408 case CP0_REG29__TAGHI3:
8409 gen_helper_mtc0_taghi(cpu_env, arg);
8410 register_name = "TagHi";
8411 break;
8412 case CP0_REG29__DATAHI:
8413 case CP0_REG29__DATAHI1:
8414 case CP0_REG29__DATAHI2:
8415 case CP0_REG29__DATAHI3:
8416 gen_helper_mtc0_datahi(cpu_env, arg);
8417 register_name = "DataHi";
8418 break;
8419 default:
8420 register_name = "invalid sel";
8421 goto cp0_unimplemented;
8423 break;
8424 case CP0_REGISTER_30:
8425 switch (sel) {
8426 case CP0_REG30__ERROREPC:
8427 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8428 register_name = "ErrorEPC";
8429 break;
8430 default:
8431 goto cp0_unimplemented;
8433 break;
8434 case CP0_REGISTER_31:
8435 switch (sel) {
8436 case CP0_REG31__DESAVE:
8437 /* EJTAG support */
8438 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8439 register_name = "DESAVE";
8440 break;
8441 case CP0_REG31__KSCRATCH1:
8442 case CP0_REG31__KSCRATCH2:
8443 case CP0_REG31__KSCRATCH3:
8444 case CP0_REG31__KSCRATCH4:
8445 case CP0_REG31__KSCRATCH5:
8446 case CP0_REG31__KSCRATCH6:
8447 CP0_CHECK(ctx->kscrexist & (1 << sel));
8448 tcg_gen_st_tl(arg, cpu_env,
8449 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8450 register_name = "KScratch";
8451 break;
8452 default:
8453 goto cp0_unimplemented;
8455 break;
8456 default:
8457 goto cp0_unimplemented;
8459 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8461 /* For simplicity assume that all writes can cause interrupts. */
8462 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8464 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8465 * translated code to check for pending interrupts.
8467 gen_save_pc(ctx->base.pc_next + 4);
8468 ctx->base.is_jmp = DISAS_EXIT;
8470 return;
8472 cp0_unimplemented:
8473 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8474 register_name, reg, sel);
8477 #if defined(TARGET_MIPS64)
8478 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8480 const char *register_name = "invalid";
8482 if (sel != 0) {
8483 check_insn(ctx, ISA_MIPS64);
8486 switch (reg) {
8487 case CP0_REGISTER_00:
8488 switch (sel) {
8489 case CP0_REG00__INDEX:
8490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8491 register_name = "Index";
8492 break;
8493 case CP0_REG00__MVPCONTROL:
8494 CP0_CHECK(ctx->insn_flags & ASE_MT);
8495 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8496 register_name = "MVPControl";
8497 break;
8498 case CP0_REG00__MVPCONF0:
8499 CP0_CHECK(ctx->insn_flags & ASE_MT);
8500 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8501 register_name = "MVPConf0";
8502 break;
8503 case CP0_REG00__MVPCONF1:
8504 CP0_CHECK(ctx->insn_flags & ASE_MT);
8505 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8506 register_name = "MVPConf1";
8507 break;
8508 case CP0_REG00__VPCONTROL:
8509 CP0_CHECK(ctx->vp);
8510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8511 register_name = "VPControl";
8512 break;
8513 default:
8514 goto cp0_unimplemented;
8516 break;
8517 case CP0_REGISTER_01:
8518 switch (sel) {
8519 case CP0_REG01__RANDOM:
8520 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8521 gen_helper_mfc0_random(arg, cpu_env);
8522 register_name = "Random";
8523 break;
8524 case CP0_REG01__VPECONTROL:
8525 CP0_CHECK(ctx->insn_flags & ASE_MT);
8526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8527 register_name = "VPEControl";
8528 break;
8529 case CP0_REG01__VPECONF0:
8530 CP0_CHECK(ctx->insn_flags & ASE_MT);
8531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8532 register_name = "VPEConf0";
8533 break;
8534 case CP0_REG01__VPECONF1:
8535 CP0_CHECK(ctx->insn_flags & ASE_MT);
8536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8537 register_name = "VPEConf1";
8538 break;
8539 case CP0_REG01__YQMASK:
8540 CP0_CHECK(ctx->insn_flags & ASE_MT);
8541 tcg_gen_ld_tl(arg, cpu_env,
8542 offsetof(CPUMIPSState, CP0_YQMask));
8543 register_name = "YQMask";
8544 break;
8545 case CP0_REG01__VPESCHEDULE:
8546 CP0_CHECK(ctx->insn_flags & ASE_MT);
8547 tcg_gen_ld_tl(arg, cpu_env,
8548 offsetof(CPUMIPSState, CP0_VPESchedule));
8549 register_name = "VPESchedule";
8550 break;
8551 case CP0_REG01__VPESCHEFBACK:
8552 CP0_CHECK(ctx->insn_flags & ASE_MT);
8553 tcg_gen_ld_tl(arg, cpu_env,
8554 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8555 register_name = "VPEScheFBack";
8556 break;
8557 case CP0_REG01__VPEOPT:
8558 CP0_CHECK(ctx->insn_flags & ASE_MT);
8559 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8560 register_name = "VPEOpt";
8561 break;
8562 default:
8563 goto cp0_unimplemented;
8565 break;
8566 case CP0_REGISTER_02:
8567 switch (sel) {
8568 case CP0_REG02__ENTRYLO0:
8569 tcg_gen_ld_tl(arg, cpu_env,
8570 offsetof(CPUMIPSState, CP0_EntryLo0));
8571 register_name = "EntryLo0";
8572 break;
8573 case CP0_REG02__TCSTATUS:
8574 CP0_CHECK(ctx->insn_flags & ASE_MT);
8575 gen_helper_mfc0_tcstatus(arg, cpu_env);
8576 register_name = "TCStatus";
8577 break;
8578 case CP0_REG02__TCBIND:
8579 CP0_CHECK(ctx->insn_flags & ASE_MT);
8580 gen_helper_mfc0_tcbind(arg, cpu_env);
8581 register_name = "TCBind";
8582 break;
8583 case CP0_REG02__TCRESTART:
8584 CP0_CHECK(ctx->insn_flags & ASE_MT);
8585 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8586 register_name = "TCRestart";
8587 break;
8588 case CP0_REG02__TCHALT:
8589 CP0_CHECK(ctx->insn_flags & ASE_MT);
8590 gen_helper_dmfc0_tchalt(arg, cpu_env);
8591 register_name = "TCHalt";
8592 break;
8593 case CP0_REG02__TCCONTEXT:
8594 CP0_CHECK(ctx->insn_flags & ASE_MT);
8595 gen_helper_dmfc0_tccontext(arg, cpu_env);
8596 register_name = "TCContext";
8597 break;
8598 case CP0_REG02__TCSCHEDULE:
8599 CP0_CHECK(ctx->insn_flags & ASE_MT);
8600 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8601 register_name = "TCSchedule";
8602 break;
8603 case CP0_REG02__TCSCHEFBACK:
8604 CP0_CHECK(ctx->insn_flags & ASE_MT);
8605 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8606 register_name = "TCScheFBack";
8607 break;
8608 default:
8609 goto cp0_unimplemented;
8611 break;
8612 case CP0_REGISTER_03:
8613 switch (sel) {
8614 case CP0_REG03__ENTRYLO1:
8615 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8616 register_name = "EntryLo1";
8617 break;
8618 case CP0_REG03__GLOBALNUM:
8619 CP0_CHECK(ctx->vp);
8620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8621 register_name = "GlobalNumber";
8622 break;
8623 default:
8624 goto cp0_unimplemented;
8626 break;
8627 case CP0_REGISTER_04:
8628 switch (sel) {
8629 case CP0_REG04__CONTEXT:
8630 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8631 register_name = "Context";
8632 break;
8633 case CP0_REG04__CONTEXTCONFIG:
8634 /* SmartMIPS ASE */
8635 /* gen_helper_dmfc0_contextconfig(arg); */
8636 register_name = "ContextConfig";
8637 goto cp0_unimplemented;
8638 case CP0_REG04__USERLOCAL:
8639 CP0_CHECK(ctx->ulri);
8640 tcg_gen_ld_tl(arg, cpu_env,
8641 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8642 register_name = "UserLocal";
8643 break;
8644 case CP0_REG04__MMID:
8645 CP0_CHECK(ctx->mi);
8646 gen_helper_mtc0_memorymapid(cpu_env, arg);
8647 register_name = "MMID";
8648 break;
8649 default:
8650 goto cp0_unimplemented;
8652 break;
8653 case CP0_REGISTER_05:
8654 switch (sel) {
8655 case CP0_REG05__PAGEMASK:
8656 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8657 register_name = "PageMask";
8658 break;
8659 case CP0_REG05__PAGEGRAIN:
8660 check_insn(ctx, ISA_MIPS32R2);
8661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8662 register_name = "PageGrain";
8663 break;
8664 case CP0_REG05__SEGCTL0:
8665 CP0_CHECK(ctx->sc);
8666 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8667 register_name = "SegCtl0";
8668 break;
8669 case CP0_REG05__SEGCTL1:
8670 CP0_CHECK(ctx->sc);
8671 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8672 register_name = "SegCtl1";
8673 break;
8674 case CP0_REG05__SEGCTL2:
8675 CP0_CHECK(ctx->sc);
8676 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8677 register_name = "SegCtl2";
8678 break;
8679 case CP0_REG05__PWBASE:
8680 check_pw(ctx);
8681 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8682 register_name = "PWBase";
8683 break;
8684 case CP0_REG05__PWFIELD:
8685 check_pw(ctx);
8686 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8687 register_name = "PWField";
8688 break;
8689 case CP0_REG05__PWSIZE:
8690 check_pw(ctx);
8691 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8692 register_name = "PWSize";
8693 break;
8694 default:
8695 goto cp0_unimplemented;
8697 break;
8698 case CP0_REGISTER_06:
8699 switch (sel) {
8700 case CP0_REG06__WIRED:
8701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8702 register_name = "Wired";
8703 break;
8704 case CP0_REG06__SRSCONF0:
8705 check_insn(ctx, ISA_MIPS32R2);
8706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8707 register_name = "SRSConf0";
8708 break;
8709 case CP0_REG06__SRSCONF1:
8710 check_insn(ctx, ISA_MIPS32R2);
8711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8712 register_name = "SRSConf1";
8713 break;
8714 case CP0_REG06__SRSCONF2:
8715 check_insn(ctx, ISA_MIPS32R2);
8716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8717 register_name = "SRSConf2";
8718 break;
8719 case CP0_REG06__SRSCONF3:
8720 check_insn(ctx, ISA_MIPS32R2);
8721 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8722 register_name = "SRSConf3";
8723 break;
8724 case CP0_REG06__SRSCONF4:
8725 check_insn(ctx, ISA_MIPS32R2);
8726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8727 register_name = "SRSConf4";
8728 break;
8729 case CP0_REG06__PWCTL:
8730 check_pw(ctx);
8731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8732 register_name = "PWCtl";
8733 break;
8734 default:
8735 goto cp0_unimplemented;
8737 break;
8738 case CP0_REGISTER_07:
8739 switch (sel) {
8740 case CP0_REG07__HWRENA:
8741 check_insn(ctx, ISA_MIPS32R2);
8742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8743 register_name = "HWREna";
8744 break;
8745 default:
8746 goto cp0_unimplemented;
8748 break;
8749 case CP0_REGISTER_08:
8750 switch (sel) {
8751 case CP0_REG08__BADVADDR:
8752 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8753 register_name = "BadVAddr";
8754 break;
8755 case CP0_REG08__BADINSTR:
8756 CP0_CHECK(ctx->bi);
8757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8758 register_name = "BadInstr";
8759 break;
8760 case CP0_REG08__BADINSTRP:
8761 CP0_CHECK(ctx->bp);
8762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8763 register_name = "BadInstrP";
8764 break;
8765 case CP0_REG08__BADINSTRX:
8766 CP0_CHECK(ctx->bi);
8767 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8768 tcg_gen_andi_tl(arg, arg, ~0xffff);
8769 register_name = "BadInstrX";
8770 break;
8771 default:
8772 goto cp0_unimplemented;
8774 break;
8775 case CP0_REGISTER_09:
8776 switch (sel) {
8777 case CP0_REG09__COUNT:
8778 /* Mark as an IO operation because we read the time. */
8779 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8780 gen_io_start();
8782 gen_helper_mfc0_count(arg, cpu_env);
8784 * Break the TB to be able to take timer interrupts immediately
8785 * after reading count. DISAS_STOP isn't sufficient, we need to
8786 * ensure we break completely out of translated code.
8788 gen_save_pc(ctx->base.pc_next + 4);
8789 ctx->base.is_jmp = DISAS_EXIT;
8790 register_name = "Count";
8791 break;
8792 case CP0_REG09__SAARI:
8793 CP0_CHECK(ctx->saar);
8794 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8795 register_name = "SAARI";
8796 break;
8797 case CP0_REG09__SAAR:
8798 CP0_CHECK(ctx->saar);
8799 gen_helper_dmfc0_saar(arg, cpu_env);
8800 register_name = "SAAR";
8801 break;
8802 default:
8803 goto cp0_unimplemented;
8805 break;
8806 case CP0_REGISTER_10:
8807 switch (sel) {
8808 case CP0_REG10__ENTRYHI:
8809 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8810 register_name = "EntryHi";
8811 break;
8812 default:
8813 goto cp0_unimplemented;
8815 break;
8816 case CP0_REGISTER_11:
8817 switch (sel) {
8818 case CP0_REG11__COMPARE:
8819 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8820 register_name = "Compare";
8821 break;
8822 /* 6,7 are implementation dependent */
8823 default:
8824 goto cp0_unimplemented;
8826 break;
8827 case CP0_REGISTER_12:
8828 switch (sel) {
8829 case CP0_REG12__STATUS:
8830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8831 register_name = "Status";
8832 break;
8833 case CP0_REG12__INTCTL:
8834 check_insn(ctx, ISA_MIPS32R2);
8835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8836 register_name = "IntCtl";
8837 break;
8838 case CP0_REG12__SRSCTL:
8839 check_insn(ctx, ISA_MIPS32R2);
8840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8841 register_name = "SRSCtl";
8842 break;
8843 case CP0_REG12__SRSMAP:
8844 check_insn(ctx, ISA_MIPS32R2);
8845 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8846 register_name = "SRSMap";
8847 break;
8848 default:
8849 goto cp0_unimplemented;
8851 break;
8852 case CP0_REGISTER_13:
8853 switch (sel) {
8854 case CP0_REG13__CAUSE:
8855 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8856 register_name = "Cause";
8857 break;
8858 default:
8859 goto cp0_unimplemented;
8861 break;
8862 case CP0_REGISTER_14:
8863 switch (sel) {
8864 case CP0_REG14__EPC:
8865 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8866 register_name = "EPC";
8867 break;
8868 default:
8869 goto cp0_unimplemented;
8871 break;
8872 case CP0_REGISTER_15:
8873 switch (sel) {
8874 case CP0_REG15__PRID:
8875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8876 register_name = "PRid";
8877 break;
8878 case CP0_REG15__EBASE:
8879 check_insn(ctx, ISA_MIPS32R2);
8880 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8881 register_name = "EBase";
8882 break;
8883 case CP0_REG15__CMGCRBASE:
8884 check_insn(ctx, ISA_MIPS32R2);
8885 CP0_CHECK(ctx->cmgcr);
8886 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8887 register_name = "CMGCRBase";
8888 break;
8889 default:
8890 goto cp0_unimplemented;
8892 break;
8893 case CP0_REGISTER_16:
8894 switch (sel) {
8895 case CP0_REG16__CONFIG:
8896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8897 register_name = "Config";
8898 break;
8899 case CP0_REG16__CONFIG1:
8900 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8901 register_name = "Config1";
8902 break;
8903 case CP0_REG16__CONFIG2:
8904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8905 register_name = "Config2";
8906 break;
8907 case CP0_REG16__CONFIG3:
8908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8909 register_name = "Config3";
8910 break;
8911 case CP0_REG16__CONFIG4:
8912 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8913 register_name = "Config4";
8914 break;
8915 case CP0_REG16__CONFIG5:
8916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8917 register_name = "Config5";
8918 break;
8919 /* 6,7 are implementation dependent */
8920 case CP0_REG16__CONFIG6:
8921 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8922 register_name = "Config6";
8923 break;
8924 case CP0_REG16__CONFIG7:
8925 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8926 register_name = "Config7";
8927 break;
8928 default:
8929 goto cp0_unimplemented;
8931 break;
8932 case CP0_REGISTER_17:
8933 switch (sel) {
8934 case CP0_REG17__LLADDR:
8935 gen_helper_dmfc0_lladdr(arg, cpu_env);
8936 register_name = "LLAddr";
8937 break;
8938 case CP0_REG17__MAAR:
8939 CP0_CHECK(ctx->mrp);
8940 gen_helper_dmfc0_maar(arg, cpu_env);
8941 register_name = "MAAR";
8942 break;
8943 case CP0_REG17__MAARI:
8944 CP0_CHECK(ctx->mrp);
8945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8946 register_name = "MAARI";
8947 break;
8948 default:
8949 goto cp0_unimplemented;
8951 break;
8952 case CP0_REGISTER_18:
8953 switch (sel) {
8954 case CP0_REG18__WATCHLO0:
8955 case CP0_REG18__WATCHLO1:
8956 case CP0_REG18__WATCHLO2:
8957 case CP0_REG18__WATCHLO3:
8958 case CP0_REG18__WATCHLO4:
8959 case CP0_REG18__WATCHLO5:
8960 case CP0_REG18__WATCHLO6:
8961 case CP0_REG18__WATCHLO7:
8962 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8963 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8964 register_name = "WatchLo";
8965 break;
8966 default:
8967 goto cp0_unimplemented;
8969 break;
8970 case CP0_REGISTER_19:
8971 switch (sel) {
8972 case CP0_REG19__WATCHHI0:
8973 case CP0_REG19__WATCHHI1:
8974 case CP0_REG19__WATCHHI2:
8975 case CP0_REG19__WATCHHI3:
8976 case CP0_REG19__WATCHHI4:
8977 case CP0_REG19__WATCHHI5:
8978 case CP0_REG19__WATCHHI6:
8979 case CP0_REG19__WATCHHI7:
8980 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8981 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
8982 register_name = "WatchHi";
8983 break;
8984 default:
8985 goto cp0_unimplemented;
8987 break;
8988 case CP0_REGISTER_20:
8989 switch (sel) {
8990 case CP0_REG20__XCONTEXT:
8991 check_insn(ctx, ISA_MIPS3);
8992 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8993 register_name = "XContext";
8994 break;
8995 default:
8996 goto cp0_unimplemented;
8998 break;
8999 case CP0_REGISTER_21:
9000 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9001 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9002 switch (sel) {
9003 case 0:
9004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9005 register_name = "Framemask";
9006 break;
9007 default:
9008 goto cp0_unimplemented;
9010 break;
9011 case CP0_REGISTER_22:
9012 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9013 register_name = "'Diagnostic"; /* implementation dependent */
9014 break;
9015 case CP0_REGISTER_23:
9016 switch (sel) {
9017 case CP0_REG23__DEBUG:
9018 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9019 register_name = "Debug";
9020 break;
9021 case CP0_REG23__TRACECONTROL:
9022 /* PDtrace support */
9023 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9024 register_name = "TraceControl";
9025 goto cp0_unimplemented;
9026 case CP0_REG23__TRACECONTROL2:
9027 /* PDtrace support */
9028 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9029 register_name = "TraceControl2";
9030 goto cp0_unimplemented;
9031 case CP0_REG23__USERTRACEDATA1:
9032 /* PDtrace support */
9033 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9034 register_name = "UserTraceData1";
9035 goto cp0_unimplemented;
9036 case CP0_REG23__TRACEIBPC:
9037 /* PDtrace support */
9038 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9039 register_name = "TraceIBPC";
9040 goto cp0_unimplemented;
9041 case CP0_REG23__TRACEDBPC:
9042 /* PDtrace support */
9043 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9044 register_name = "TraceDBPC";
9045 goto cp0_unimplemented;
9046 default:
9047 goto cp0_unimplemented;
9049 break;
9050 case CP0_REGISTER_24:
9051 switch (sel) {
9052 case CP0_REG24__DEPC:
9053 /* EJTAG support */
9054 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9055 register_name = "DEPC";
9056 break;
9057 default:
9058 goto cp0_unimplemented;
9060 break;
9061 case CP0_REGISTER_25:
9062 switch (sel) {
9063 case CP0_REG25__PERFCTL0:
9064 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9065 register_name = "Performance0";
9066 break;
9067 case CP0_REG25__PERFCNT0:
9068 /* gen_helper_dmfc0_performance1(arg); */
9069 register_name = "Performance1";
9070 goto cp0_unimplemented;
9071 case CP0_REG25__PERFCTL1:
9072 /* gen_helper_dmfc0_performance2(arg); */
9073 register_name = "Performance2";
9074 goto cp0_unimplemented;
9075 case CP0_REG25__PERFCNT1:
9076 /* gen_helper_dmfc0_performance3(arg); */
9077 register_name = "Performance3";
9078 goto cp0_unimplemented;
9079 case CP0_REG25__PERFCTL2:
9080 /* gen_helper_dmfc0_performance4(arg); */
9081 register_name = "Performance4";
9082 goto cp0_unimplemented;
9083 case CP0_REG25__PERFCNT2:
9084 /* gen_helper_dmfc0_performance5(arg); */
9085 register_name = "Performance5";
9086 goto cp0_unimplemented;
9087 case CP0_REG25__PERFCTL3:
9088 /* gen_helper_dmfc0_performance6(arg); */
9089 register_name = "Performance6";
9090 goto cp0_unimplemented;
9091 case CP0_REG25__PERFCNT3:
9092 /* gen_helper_dmfc0_performance7(arg); */
9093 register_name = "Performance7";
9094 goto cp0_unimplemented;
9095 default:
9096 goto cp0_unimplemented;
9098 break;
9099 case CP0_REGISTER_26:
9100 switch (sel) {
9101 case CP0_REG26__ERRCTL:
9102 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9103 register_name = "ErrCtl";
9104 break;
9105 default:
9106 goto cp0_unimplemented;
9108 break;
9109 case CP0_REGISTER_27:
9110 switch (sel) {
9111 /* ignored */
9112 case CP0_REG27__CACHERR:
9113 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9114 register_name = "CacheErr";
9115 break;
9116 default:
9117 goto cp0_unimplemented;
9119 break;
9120 case CP0_REGISTER_28:
9121 switch (sel) {
9122 case CP0_REG28__TAGLO:
9123 case CP0_REG28__TAGLO1:
9124 case CP0_REG28__TAGLO2:
9125 case CP0_REG28__TAGLO3:
9126 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9127 register_name = "TagLo";
9128 break;
9129 case CP0_REG28__DATALO:
9130 case CP0_REG28__DATALO1:
9131 case CP0_REG28__DATALO2:
9132 case CP0_REG28__DATALO3:
9133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9134 register_name = "DataLo";
9135 break;
9136 default:
9137 goto cp0_unimplemented;
9139 break;
9140 case CP0_REGISTER_29:
9141 switch (sel) {
9142 case CP0_REG29__TAGHI:
9143 case CP0_REG29__TAGHI1:
9144 case CP0_REG29__TAGHI2:
9145 case CP0_REG29__TAGHI3:
9146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9147 register_name = "TagHi";
9148 break;
9149 case CP0_REG29__DATAHI:
9150 case CP0_REG29__DATAHI1:
9151 case CP0_REG29__DATAHI2:
9152 case CP0_REG29__DATAHI3:
9153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9154 register_name = "DataHi";
9155 break;
9156 default:
9157 goto cp0_unimplemented;
9159 break;
9160 case CP0_REGISTER_30:
9161 switch (sel) {
9162 case CP0_REG30__ERROREPC:
9163 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9164 register_name = "ErrorEPC";
9165 break;
9166 default:
9167 goto cp0_unimplemented;
9169 break;
9170 case CP0_REGISTER_31:
9171 switch (sel) {
9172 case CP0_REG31__DESAVE:
9173 /* EJTAG support */
9174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9175 register_name = "DESAVE";
9176 break;
9177 case CP0_REG31__KSCRATCH1:
9178 case CP0_REG31__KSCRATCH2:
9179 case CP0_REG31__KSCRATCH3:
9180 case CP0_REG31__KSCRATCH4:
9181 case CP0_REG31__KSCRATCH5:
9182 case CP0_REG31__KSCRATCH6:
9183 CP0_CHECK(ctx->kscrexist & (1 << sel));
9184 tcg_gen_ld_tl(arg, cpu_env,
9185 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9186 register_name = "KScratch";
9187 break;
9188 default:
9189 goto cp0_unimplemented;
9191 break;
9192 default:
9193 goto cp0_unimplemented;
9195 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9196 return;
9198 cp0_unimplemented:
9199 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9200 register_name, reg, sel);
9201 gen_mfc0_unimplemented(ctx, arg);
9204 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9206 const char *register_name = "invalid";
9208 if (sel != 0) {
9209 check_insn(ctx, ISA_MIPS64);
9212 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9213 gen_io_start();
9216 switch (reg) {
9217 case CP0_REGISTER_00:
9218 switch (sel) {
9219 case CP0_REG00__INDEX:
9220 gen_helper_mtc0_index(cpu_env, arg);
9221 register_name = "Index";
9222 break;
9223 case CP0_REG00__MVPCONTROL:
9224 CP0_CHECK(ctx->insn_flags & ASE_MT);
9225 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9226 register_name = "MVPControl";
9227 break;
9228 case CP0_REG00__MVPCONF0:
9229 CP0_CHECK(ctx->insn_flags & ASE_MT);
9230 /* ignored */
9231 register_name = "MVPConf0";
9232 break;
9233 case CP0_REG00__MVPCONF1:
9234 CP0_CHECK(ctx->insn_flags & ASE_MT);
9235 /* ignored */
9236 register_name = "MVPConf1";
9237 break;
9238 case CP0_REG00__VPCONTROL:
9239 CP0_CHECK(ctx->vp);
9240 /* ignored */
9241 register_name = "VPControl";
9242 break;
9243 default:
9244 goto cp0_unimplemented;
9246 break;
9247 case CP0_REGISTER_01:
9248 switch (sel) {
9249 case CP0_REG01__RANDOM:
9250 /* ignored */
9251 register_name = "Random";
9252 break;
9253 case CP0_REG01__VPECONTROL:
9254 CP0_CHECK(ctx->insn_flags & ASE_MT);
9255 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9256 register_name = "VPEControl";
9257 break;
9258 case CP0_REG01__VPECONF0:
9259 CP0_CHECK(ctx->insn_flags & ASE_MT);
9260 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9261 register_name = "VPEConf0";
9262 break;
9263 case CP0_REG01__VPECONF1:
9264 CP0_CHECK(ctx->insn_flags & ASE_MT);
9265 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9266 register_name = "VPEConf1";
9267 break;
9268 case CP0_REG01__YQMASK:
9269 CP0_CHECK(ctx->insn_flags & ASE_MT);
9270 gen_helper_mtc0_yqmask(cpu_env, arg);
9271 register_name = "YQMask";
9272 break;
9273 case CP0_REG01__VPESCHEDULE:
9274 CP0_CHECK(ctx->insn_flags & ASE_MT);
9275 tcg_gen_st_tl(arg, cpu_env,
9276 offsetof(CPUMIPSState, CP0_VPESchedule));
9277 register_name = "VPESchedule";
9278 break;
9279 case CP0_REG01__VPESCHEFBACK:
9280 CP0_CHECK(ctx->insn_flags & ASE_MT);
9281 tcg_gen_st_tl(arg, cpu_env,
9282 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9283 register_name = "VPEScheFBack";
9284 break;
9285 case CP0_REG01__VPEOPT:
9286 CP0_CHECK(ctx->insn_flags & ASE_MT);
9287 gen_helper_mtc0_vpeopt(cpu_env, arg);
9288 register_name = "VPEOpt";
9289 break;
9290 default:
9291 goto cp0_unimplemented;
9293 break;
9294 case CP0_REGISTER_02:
9295 switch (sel) {
9296 case CP0_REG02__ENTRYLO0:
9297 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9298 register_name = "EntryLo0";
9299 break;
9300 case CP0_REG02__TCSTATUS:
9301 CP0_CHECK(ctx->insn_flags & ASE_MT);
9302 gen_helper_mtc0_tcstatus(cpu_env, arg);
9303 register_name = "TCStatus";
9304 break;
9305 case CP0_REG02__TCBIND:
9306 CP0_CHECK(ctx->insn_flags & ASE_MT);
9307 gen_helper_mtc0_tcbind(cpu_env, arg);
9308 register_name = "TCBind";
9309 break;
9310 case CP0_REG02__TCRESTART:
9311 CP0_CHECK(ctx->insn_flags & ASE_MT);
9312 gen_helper_mtc0_tcrestart(cpu_env, arg);
9313 register_name = "TCRestart";
9314 break;
9315 case CP0_REG02__TCHALT:
9316 CP0_CHECK(ctx->insn_flags & ASE_MT);
9317 gen_helper_mtc0_tchalt(cpu_env, arg);
9318 register_name = "TCHalt";
9319 break;
9320 case CP0_REG02__TCCONTEXT:
9321 CP0_CHECK(ctx->insn_flags & ASE_MT);
9322 gen_helper_mtc0_tccontext(cpu_env, arg);
9323 register_name = "TCContext";
9324 break;
9325 case CP0_REG02__TCSCHEDULE:
9326 CP0_CHECK(ctx->insn_flags & ASE_MT);
9327 gen_helper_mtc0_tcschedule(cpu_env, arg);
9328 register_name = "TCSchedule";
9329 break;
9330 case CP0_REG02__TCSCHEFBACK:
9331 CP0_CHECK(ctx->insn_flags & ASE_MT);
9332 gen_helper_mtc0_tcschefback(cpu_env, arg);
9333 register_name = "TCScheFBack";
9334 break;
9335 default:
9336 goto cp0_unimplemented;
9338 break;
9339 case CP0_REGISTER_03:
9340 switch (sel) {
9341 case CP0_REG03__ENTRYLO1:
9342 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9343 register_name = "EntryLo1";
9344 break;
9345 case CP0_REG03__GLOBALNUM:
9346 CP0_CHECK(ctx->vp);
9347 /* ignored */
9348 register_name = "GlobalNumber";
9349 break;
9350 default:
9351 goto cp0_unimplemented;
9353 break;
9354 case CP0_REGISTER_04:
9355 switch (sel) {
9356 case CP0_REG04__CONTEXT:
9357 gen_helper_mtc0_context(cpu_env, arg);
9358 register_name = "Context";
9359 break;
9360 case CP0_REG04__CONTEXTCONFIG:
9361 /* SmartMIPS ASE */
9362 /* gen_helper_dmtc0_contextconfig(arg); */
9363 register_name = "ContextConfig";
9364 goto cp0_unimplemented;
9365 case CP0_REG04__USERLOCAL:
9366 CP0_CHECK(ctx->ulri);
9367 tcg_gen_st_tl(arg, cpu_env,
9368 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9369 register_name = "UserLocal";
9370 break;
9371 case CP0_REG04__MMID:
9372 CP0_CHECK(ctx->mi);
9373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9374 register_name = "MMID";
9375 break;
9376 default:
9377 goto cp0_unimplemented;
9379 break;
9380 case CP0_REGISTER_05:
9381 switch (sel) {
9382 case CP0_REG05__PAGEMASK:
9383 gen_helper_mtc0_pagemask(cpu_env, arg);
9384 register_name = "PageMask";
9385 break;
9386 case CP0_REG05__PAGEGRAIN:
9387 check_insn(ctx, ISA_MIPS32R2);
9388 gen_helper_mtc0_pagegrain(cpu_env, arg);
9389 register_name = "PageGrain";
9390 break;
9391 case CP0_REG05__SEGCTL0:
9392 CP0_CHECK(ctx->sc);
9393 gen_helper_mtc0_segctl0(cpu_env, arg);
9394 register_name = "SegCtl0";
9395 break;
9396 case CP0_REG05__SEGCTL1:
9397 CP0_CHECK(ctx->sc);
9398 gen_helper_mtc0_segctl1(cpu_env, arg);
9399 register_name = "SegCtl1";
9400 break;
9401 case CP0_REG05__SEGCTL2:
9402 CP0_CHECK(ctx->sc);
9403 gen_helper_mtc0_segctl2(cpu_env, arg);
9404 register_name = "SegCtl2";
9405 break;
9406 case CP0_REG05__PWBASE:
9407 check_pw(ctx);
9408 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9409 register_name = "PWBase";
9410 break;
9411 case CP0_REG05__PWFIELD:
9412 check_pw(ctx);
9413 gen_helper_mtc0_pwfield(cpu_env, arg);
9414 register_name = "PWField";
9415 break;
9416 case CP0_REG05__PWSIZE:
9417 check_pw(ctx);
9418 gen_helper_mtc0_pwsize(cpu_env, arg);
9419 register_name = "PWSize";
9420 break;
9421 default:
9422 goto cp0_unimplemented;
9424 break;
9425 case CP0_REGISTER_06:
9426 switch (sel) {
9427 case CP0_REG06__WIRED:
9428 gen_helper_mtc0_wired(cpu_env, arg);
9429 register_name = "Wired";
9430 break;
9431 case CP0_REG06__SRSCONF0:
9432 check_insn(ctx, ISA_MIPS32R2);
9433 gen_helper_mtc0_srsconf0(cpu_env, arg);
9434 register_name = "SRSConf0";
9435 break;
9436 case CP0_REG06__SRSCONF1:
9437 check_insn(ctx, ISA_MIPS32R2);
9438 gen_helper_mtc0_srsconf1(cpu_env, arg);
9439 register_name = "SRSConf1";
9440 break;
9441 case CP0_REG06__SRSCONF2:
9442 check_insn(ctx, ISA_MIPS32R2);
9443 gen_helper_mtc0_srsconf2(cpu_env, arg);
9444 register_name = "SRSConf2";
9445 break;
9446 case CP0_REG06__SRSCONF3:
9447 check_insn(ctx, ISA_MIPS32R2);
9448 gen_helper_mtc0_srsconf3(cpu_env, arg);
9449 register_name = "SRSConf3";
9450 break;
9451 case CP0_REG06__SRSCONF4:
9452 check_insn(ctx, ISA_MIPS32R2);
9453 gen_helper_mtc0_srsconf4(cpu_env, arg);
9454 register_name = "SRSConf4";
9455 break;
9456 case CP0_REG06__PWCTL:
9457 check_pw(ctx);
9458 gen_helper_mtc0_pwctl(cpu_env, arg);
9459 register_name = "PWCtl";
9460 break;
9461 default:
9462 goto cp0_unimplemented;
9464 break;
9465 case CP0_REGISTER_07:
9466 switch (sel) {
9467 case CP0_REG07__HWRENA:
9468 check_insn(ctx, ISA_MIPS32R2);
9469 gen_helper_mtc0_hwrena(cpu_env, arg);
9470 ctx->base.is_jmp = DISAS_STOP;
9471 register_name = "HWREna";
9472 break;
9473 default:
9474 goto cp0_unimplemented;
9476 break;
9477 case CP0_REGISTER_08:
9478 switch (sel) {
9479 case CP0_REG08__BADVADDR:
9480 /* ignored */
9481 register_name = "BadVAddr";
9482 break;
9483 case CP0_REG08__BADINSTR:
9484 /* ignored */
9485 register_name = "BadInstr";
9486 break;
9487 case CP0_REG08__BADINSTRP:
9488 /* ignored */
9489 register_name = "BadInstrP";
9490 break;
9491 case CP0_REG08__BADINSTRX:
9492 /* ignored */
9493 register_name = "BadInstrX";
9494 break;
9495 default:
9496 goto cp0_unimplemented;
9498 break;
9499 case CP0_REGISTER_09:
9500 switch (sel) {
9501 case CP0_REG09__COUNT:
9502 gen_helper_mtc0_count(cpu_env, arg);
9503 register_name = "Count";
9504 break;
9505 case CP0_REG09__SAARI:
9506 CP0_CHECK(ctx->saar);
9507 gen_helper_mtc0_saari(cpu_env, arg);
9508 register_name = "SAARI";
9509 break;
9510 case CP0_REG09__SAAR:
9511 CP0_CHECK(ctx->saar);
9512 gen_helper_mtc0_saar(cpu_env, arg);
9513 register_name = "SAAR";
9514 break;
9515 default:
9516 goto cp0_unimplemented;
9518 /* Stop translation as we may have switched the execution mode */
9519 ctx->base.is_jmp = DISAS_STOP;
9520 break;
9521 case CP0_REGISTER_10:
9522 switch (sel) {
9523 case CP0_REG10__ENTRYHI:
9524 gen_helper_mtc0_entryhi(cpu_env, arg);
9525 register_name = "EntryHi";
9526 break;
9527 default:
9528 goto cp0_unimplemented;
9530 break;
9531 case CP0_REGISTER_11:
9532 switch (sel) {
9533 case CP0_REG11__COMPARE:
9534 gen_helper_mtc0_compare(cpu_env, arg);
9535 register_name = "Compare";
9536 break;
9537 /* 6,7 are implementation dependent */
9538 default:
9539 goto cp0_unimplemented;
9541 /* Stop translation as we may have switched the execution mode */
9542 ctx->base.is_jmp = DISAS_STOP;
9543 break;
9544 case CP0_REGISTER_12:
9545 switch (sel) {
9546 case CP0_REG12__STATUS:
9547 save_cpu_state(ctx, 1);
9548 gen_helper_mtc0_status(cpu_env, arg);
9549 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9550 gen_save_pc(ctx->base.pc_next + 4);
9551 ctx->base.is_jmp = DISAS_EXIT;
9552 register_name = "Status";
9553 break;
9554 case CP0_REG12__INTCTL:
9555 check_insn(ctx, ISA_MIPS32R2);
9556 gen_helper_mtc0_intctl(cpu_env, arg);
9557 /* Stop translation as we may have switched the execution mode */
9558 ctx->base.is_jmp = DISAS_STOP;
9559 register_name = "IntCtl";
9560 break;
9561 case CP0_REG12__SRSCTL:
9562 check_insn(ctx, ISA_MIPS32R2);
9563 gen_helper_mtc0_srsctl(cpu_env, arg);
9564 /* Stop translation as we may have switched the execution mode */
9565 ctx->base.is_jmp = DISAS_STOP;
9566 register_name = "SRSCtl";
9567 break;
9568 case CP0_REG12__SRSMAP:
9569 check_insn(ctx, ISA_MIPS32R2);
9570 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9571 /* Stop translation as we may have switched the execution mode */
9572 ctx->base.is_jmp = DISAS_STOP;
9573 register_name = "SRSMap";
9574 break;
9575 default:
9576 goto cp0_unimplemented;
9578 break;
9579 case CP0_REGISTER_13:
9580 switch (sel) {
9581 case CP0_REG13__CAUSE:
9582 save_cpu_state(ctx, 1);
9583 gen_helper_mtc0_cause(cpu_env, arg);
9585 * Stop translation as we may have triggered an interrupt.
9586 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9587 * translated code to check for pending interrupts.
9589 gen_save_pc(ctx->base.pc_next + 4);
9590 ctx->base.is_jmp = DISAS_EXIT;
9591 register_name = "Cause";
9592 break;
9593 default:
9594 goto cp0_unimplemented;
9596 break;
9597 case CP0_REGISTER_14:
9598 switch (sel) {
9599 case CP0_REG14__EPC:
9600 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9601 register_name = "EPC";
9602 break;
9603 default:
9604 goto cp0_unimplemented;
9606 break;
9607 case CP0_REGISTER_15:
9608 switch (sel) {
9609 case CP0_REG15__PRID:
9610 /* ignored */
9611 register_name = "PRid";
9612 break;
9613 case CP0_REG15__EBASE:
9614 check_insn(ctx, ISA_MIPS32R2);
9615 gen_helper_mtc0_ebase(cpu_env, arg);
9616 register_name = "EBase";
9617 break;
9618 default:
9619 goto cp0_unimplemented;
9621 break;
9622 case CP0_REGISTER_16:
9623 switch (sel) {
9624 case CP0_REG16__CONFIG:
9625 gen_helper_mtc0_config0(cpu_env, arg);
9626 register_name = "Config";
9627 /* Stop translation as we may have switched the execution mode */
9628 ctx->base.is_jmp = DISAS_STOP;
9629 break;
9630 case CP0_REG16__CONFIG1:
9631 /* ignored, read only */
9632 register_name = "Config1";
9633 break;
9634 case CP0_REG16__CONFIG2:
9635 gen_helper_mtc0_config2(cpu_env, arg);
9636 register_name = "Config2";
9637 /* Stop translation as we may have switched the execution mode */
9638 ctx->base.is_jmp = DISAS_STOP;
9639 break;
9640 case CP0_REG16__CONFIG3:
9641 gen_helper_mtc0_config3(cpu_env, arg);
9642 register_name = "Config3";
9643 /* Stop translation as we may have switched the execution mode */
9644 ctx->base.is_jmp = DISAS_STOP;
9645 break;
9646 case CP0_REG16__CONFIG4:
9647 /* currently ignored */
9648 register_name = "Config4";
9649 break;
9650 case CP0_REG16__CONFIG5:
9651 gen_helper_mtc0_config5(cpu_env, arg);
9652 register_name = "Config5";
9653 /* Stop translation as we may have switched the execution mode */
9654 ctx->base.is_jmp = DISAS_STOP;
9655 break;
9656 /* 6,7 are implementation dependent */
9657 default:
9658 register_name = "Invalid config selector";
9659 goto cp0_unimplemented;
9661 break;
9662 case CP0_REGISTER_17:
9663 switch (sel) {
9664 case CP0_REG17__LLADDR:
9665 gen_helper_mtc0_lladdr(cpu_env, arg);
9666 register_name = "LLAddr";
9667 break;
9668 case CP0_REG17__MAAR:
9669 CP0_CHECK(ctx->mrp);
9670 gen_helper_mtc0_maar(cpu_env, arg);
9671 register_name = "MAAR";
9672 break;
9673 case CP0_REG17__MAARI:
9674 CP0_CHECK(ctx->mrp);
9675 gen_helper_mtc0_maari(cpu_env, arg);
9676 register_name = "MAARI";
9677 break;
9678 default:
9679 goto cp0_unimplemented;
9681 break;
9682 case CP0_REGISTER_18:
9683 switch (sel) {
9684 case CP0_REG18__WATCHLO0:
9685 case CP0_REG18__WATCHLO1:
9686 case CP0_REG18__WATCHLO2:
9687 case CP0_REG18__WATCHLO3:
9688 case CP0_REG18__WATCHLO4:
9689 case CP0_REG18__WATCHLO5:
9690 case CP0_REG18__WATCHLO6:
9691 case CP0_REG18__WATCHLO7:
9692 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9693 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9694 register_name = "WatchLo";
9695 break;
9696 default:
9697 goto cp0_unimplemented;
9699 break;
9700 case CP0_REGISTER_19:
9701 switch (sel) {
9702 case CP0_REG19__WATCHHI0:
9703 case CP0_REG19__WATCHHI1:
9704 case CP0_REG19__WATCHHI2:
9705 case CP0_REG19__WATCHHI3:
9706 case CP0_REG19__WATCHHI4:
9707 case CP0_REG19__WATCHHI5:
9708 case CP0_REG19__WATCHHI6:
9709 case CP0_REG19__WATCHHI7:
9710 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9711 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9712 register_name = "WatchHi";
9713 break;
9714 default:
9715 goto cp0_unimplemented;
9717 break;
9718 case CP0_REGISTER_20:
9719 switch (sel) {
9720 case CP0_REG20__XCONTEXT:
9721 check_insn(ctx, ISA_MIPS3);
9722 gen_helper_mtc0_xcontext(cpu_env, arg);
9723 register_name = "XContext";
9724 break;
9725 default:
9726 goto cp0_unimplemented;
9728 break;
9729 case CP0_REGISTER_21:
9730 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9731 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9732 switch (sel) {
9733 case 0:
9734 gen_helper_mtc0_framemask(cpu_env, arg);
9735 register_name = "Framemask";
9736 break;
9737 default:
9738 goto cp0_unimplemented;
9740 break;
9741 case CP0_REGISTER_22:
9742 /* ignored */
9743 register_name = "Diagnostic"; /* implementation dependent */
9744 break;
9745 case CP0_REGISTER_23:
9746 switch (sel) {
9747 case CP0_REG23__DEBUG:
9748 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9749 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9750 gen_save_pc(ctx->base.pc_next + 4);
9751 ctx->base.is_jmp = DISAS_EXIT;
9752 register_name = "Debug";
9753 break;
9754 case CP0_REG23__TRACECONTROL:
9755 /* PDtrace support */
9756 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9757 /* Stop translation as we may have switched the execution mode */
9758 ctx->base.is_jmp = DISAS_STOP;
9759 register_name = "TraceControl";
9760 goto cp0_unimplemented;
9761 case CP0_REG23__TRACECONTROL2:
9762 /* PDtrace support */
9763 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9764 /* Stop translation as we may have switched the execution mode */
9765 ctx->base.is_jmp = DISAS_STOP;
9766 register_name = "TraceControl2";
9767 goto cp0_unimplemented;
9768 case CP0_REG23__USERTRACEDATA1:
9769 /* PDtrace support */
9770 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9771 /* Stop translation as we may have switched the execution mode */
9772 ctx->base.is_jmp = DISAS_STOP;
9773 register_name = "UserTraceData1";
9774 goto cp0_unimplemented;
9775 case CP0_REG23__TRACEIBPC:
9776 /* PDtrace support */
9777 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9778 /* Stop translation as we may have switched the execution mode */
9779 ctx->base.is_jmp = DISAS_STOP;
9780 register_name = "TraceIBPC";
9781 goto cp0_unimplemented;
9782 case CP0_REG23__TRACEDBPC:
9783 /* PDtrace support */
9784 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9785 /* Stop translation as we may have switched the execution mode */
9786 ctx->base.is_jmp = DISAS_STOP;
9787 register_name = "TraceDBPC";
9788 goto cp0_unimplemented;
9789 default:
9790 goto cp0_unimplemented;
9792 break;
9793 case CP0_REGISTER_24:
9794 switch (sel) {
9795 case CP0_REG24__DEPC:
9796 /* EJTAG support */
9797 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9798 register_name = "DEPC";
9799 break;
9800 default:
9801 goto cp0_unimplemented;
9803 break;
9804 case CP0_REGISTER_25:
9805 switch (sel) {
9806 case CP0_REG25__PERFCTL0:
9807 gen_helper_mtc0_performance0(cpu_env, arg);
9808 register_name = "Performance0";
9809 break;
9810 case CP0_REG25__PERFCNT0:
9811 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9812 register_name = "Performance1";
9813 goto cp0_unimplemented;
9814 case CP0_REG25__PERFCTL1:
9815 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9816 register_name = "Performance2";
9817 goto cp0_unimplemented;
9818 case CP0_REG25__PERFCNT1:
9819 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9820 register_name = "Performance3";
9821 goto cp0_unimplemented;
9822 case CP0_REG25__PERFCTL2:
9823 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9824 register_name = "Performance4";
9825 goto cp0_unimplemented;
9826 case CP0_REG25__PERFCNT2:
9827 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9828 register_name = "Performance5";
9829 goto cp0_unimplemented;
9830 case CP0_REG25__PERFCTL3:
9831 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9832 register_name = "Performance6";
9833 goto cp0_unimplemented;
9834 case CP0_REG25__PERFCNT3:
9835 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9836 register_name = "Performance7";
9837 goto cp0_unimplemented;
9838 default:
9839 goto cp0_unimplemented;
9841 break;
9842 case CP0_REGISTER_26:
9843 switch (sel) {
9844 case CP0_REG26__ERRCTL:
9845 gen_helper_mtc0_errctl(cpu_env, arg);
9846 ctx->base.is_jmp = DISAS_STOP;
9847 register_name = "ErrCtl";
9848 break;
9849 default:
9850 goto cp0_unimplemented;
9852 break;
9853 case CP0_REGISTER_27:
9854 switch (sel) {
9855 case CP0_REG27__CACHERR:
9856 /* ignored */
9857 register_name = "CacheErr";
9858 break;
9859 default:
9860 goto cp0_unimplemented;
9862 break;
9863 case CP0_REGISTER_28:
9864 switch (sel) {
9865 case CP0_REG28__TAGLO:
9866 case CP0_REG28__TAGLO1:
9867 case CP0_REG28__TAGLO2:
9868 case CP0_REG28__TAGLO3:
9869 gen_helper_mtc0_taglo(cpu_env, arg);
9870 register_name = "TagLo";
9871 break;
9872 case CP0_REG28__DATALO:
9873 case CP0_REG28__DATALO1:
9874 case CP0_REG28__DATALO2:
9875 case CP0_REG28__DATALO3:
9876 gen_helper_mtc0_datalo(cpu_env, arg);
9877 register_name = "DataLo";
9878 break;
9879 default:
9880 goto cp0_unimplemented;
9882 break;
9883 case CP0_REGISTER_29:
9884 switch (sel) {
9885 case CP0_REG29__TAGHI:
9886 case CP0_REG29__TAGHI1:
9887 case CP0_REG29__TAGHI2:
9888 case CP0_REG29__TAGHI3:
9889 gen_helper_mtc0_taghi(cpu_env, arg);
9890 register_name = "TagHi";
9891 break;
9892 case CP0_REG29__DATAHI:
9893 case CP0_REG29__DATAHI1:
9894 case CP0_REG29__DATAHI2:
9895 case CP0_REG29__DATAHI3:
9896 gen_helper_mtc0_datahi(cpu_env, arg);
9897 register_name = "DataHi";
9898 break;
9899 default:
9900 register_name = "invalid sel";
9901 goto cp0_unimplemented;
9903 break;
9904 case CP0_REGISTER_30:
9905 switch (sel) {
9906 case CP0_REG30__ERROREPC:
9907 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9908 register_name = "ErrorEPC";
9909 break;
9910 default:
9911 goto cp0_unimplemented;
9913 break;
9914 case CP0_REGISTER_31:
9915 switch (sel) {
9916 case CP0_REG31__DESAVE:
9917 /* EJTAG support */
9918 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9919 register_name = "DESAVE";
9920 break;
9921 case CP0_REG31__KSCRATCH1:
9922 case CP0_REG31__KSCRATCH2:
9923 case CP0_REG31__KSCRATCH3:
9924 case CP0_REG31__KSCRATCH4:
9925 case CP0_REG31__KSCRATCH5:
9926 case CP0_REG31__KSCRATCH6:
9927 CP0_CHECK(ctx->kscrexist & (1 << sel));
9928 tcg_gen_st_tl(arg, cpu_env,
9929 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9930 register_name = "KScratch";
9931 break;
9932 default:
9933 goto cp0_unimplemented;
9935 break;
9936 default:
9937 goto cp0_unimplemented;
9939 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9941 /* For simplicity assume that all writes can cause interrupts. */
9942 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9944 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9945 * translated code to check for pending interrupts.
9947 gen_save_pc(ctx->base.pc_next + 4);
9948 ctx->base.is_jmp = DISAS_EXIT;
9950 return;
9952 cp0_unimplemented:
9953 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9954 register_name, reg, sel);
9956 #endif /* TARGET_MIPS64 */
9958 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9959 int u, int sel, int h)
9961 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9962 TCGv t0 = tcg_temp_local_new();
9964 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9965 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9966 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9967 tcg_gen_movi_tl(t0, -1);
9968 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9969 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9970 tcg_gen_movi_tl(t0, -1);
9971 } else if (u == 0) {
9972 switch (rt) {
9973 case 1:
9974 switch (sel) {
9975 case 1:
9976 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9977 break;
9978 case 2:
9979 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9980 break;
9981 default:
9982 goto die;
9983 break;
9985 break;
9986 case 2:
9987 switch (sel) {
9988 case 1:
9989 gen_helper_mftc0_tcstatus(t0, cpu_env);
9990 break;
9991 case 2:
9992 gen_helper_mftc0_tcbind(t0, cpu_env);
9993 break;
9994 case 3:
9995 gen_helper_mftc0_tcrestart(t0, cpu_env);
9996 break;
9997 case 4:
9998 gen_helper_mftc0_tchalt(t0, cpu_env);
9999 break;
10000 case 5:
10001 gen_helper_mftc0_tccontext(t0, cpu_env);
10002 break;
10003 case 6:
10004 gen_helper_mftc0_tcschedule(t0, cpu_env);
10005 break;
10006 case 7:
10007 gen_helper_mftc0_tcschefback(t0, cpu_env);
10008 break;
10009 default:
10010 gen_mfc0(ctx, t0, rt, sel);
10011 break;
10013 break;
10014 case 10:
10015 switch (sel) {
10016 case 0:
10017 gen_helper_mftc0_entryhi(t0, cpu_env);
10018 break;
10019 default:
10020 gen_mfc0(ctx, t0, rt, sel);
10021 break;
10023 break;
10024 case 12:
10025 switch (sel) {
10026 case 0:
10027 gen_helper_mftc0_status(t0, cpu_env);
10028 break;
10029 default:
10030 gen_mfc0(ctx, t0, rt, sel);
10031 break;
10033 break;
10034 case 13:
10035 switch (sel) {
10036 case 0:
10037 gen_helper_mftc0_cause(t0, cpu_env);
10038 break;
10039 default:
10040 goto die;
10041 break;
10043 break;
10044 case 14:
10045 switch (sel) {
10046 case 0:
10047 gen_helper_mftc0_epc(t0, cpu_env);
10048 break;
10049 default:
10050 goto die;
10051 break;
10053 break;
10054 case 15:
10055 switch (sel) {
10056 case 1:
10057 gen_helper_mftc0_ebase(t0, cpu_env);
10058 break;
10059 default:
10060 goto die;
10061 break;
10063 break;
10064 case 16:
10065 switch (sel) {
10066 case 0:
10067 case 1:
10068 case 2:
10069 case 3:
10070 case 4:
10071 case 5:
10072 case 6:
10073 case 7:
10074 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10075 break;
10076 default:
10077 goto die;
10078 break;
10080 break;
10081 case 23:
10082 switch (sel) {
10083 case 0:
10084 gen_helper_mftc0_debug(t0, cpu_env);
10085 break;
10086 default:
10087 gen_mfc0(ctx, t0, rt, sel);
10088 break;
10090 break;
10091 default:
10092 gen_mfc0(ctx, t0, rt, sel);
10094 } else {
10095 switch (sel) {
10096 /* GPR registers. */
10097 case 0:
10098 gen_helper_1e0i(mftgpr, t0, rt);
10099 break;
10100 /* Auxiliary CPU registers */
10101 case 1:
10102 switch (rt) {
10103 case 0:
10104 gen_helper_1e0i(mftlo, t0, 0);
10105 break;
10106 case 1:
10107 gen_helper_1e0i(mfthi, t0, 0);
10108 break;
10109 case 2:
10110 gen_helper_1e0i(mftacx, t0, 0);
10111 break;
10112 case 4:
10113 gen_helper_1e0i(mftlo, t0, 1);
10114 break;
10115 case 5:
10116 gen_helper_1e0i(mfthi, t0, 1);
10117 break;
10118 case 6:
10119 gen_helper_1e0i(mftacx, t0, 1);
10120 break;
10121 case 8:
10122 gen_helper_1e0i(mftlo, t0, 2);
10123 break;
10124 case 9:
10125 gen_helper_1e0i(mfthi, t0, 2);
10126 break;
10127 case 10:
10128 gen_helper_1e0i(mftacx, t0, 2);
10129 break;
10130 case 12:
10131 gen_helper_1e0i(mftlo, t0, 3);
10132 break;
10133 case 13:
10134 gen_helper_1e0i(mfthi, t0, 3);
10135 break;
10136 case 14:
10137 gen_helper_1e0i(mftacx, t0, 3);
10138 break;
10139 case 16:
10140 gen_helper_mftdsp(t0, cpu_env);
10141 break;
10142 default:
10143 goto die;
10145 break;
10146 /* Floating point (COP1). */
10147 case 2:
10148 /* XXX: For now we support only a single FPU context. */
10149 if (h == 0) {
10150 TCGv_i32 fp0 = tcg_temp_new_i32();
10152 gen_load_fpr32(ctx, fp0, rt);
10153 tcg_gen_ext_i32_tl(t0, fp0);
10154 tcg_temp_free_i32(fp0);
10155 } else {
10156 TCGv_i32 fp0 = tcg_temp_new_i32();
10158 gen_load_fpr32h(ctx, fp0, rt);
10159 tcg_gen_ext_i32_tl(t0, fp0);
10160 tcg_temp_free_i32(fp0);
10162 break;
10163 case 3:
10164 /* XXX: For now we support only a single FPU context. */
10165 gen_helper_1e0i(cfc1, t0, rt);
10166 break;
10167 /* COP2: Not implemented. */
10168 case 4:
10169 case 5:
10170 /* fall through */
10171 default:
10172 goto die;
10175 trace_mips_translate_tr("mftr", rt, u, sel, h);
10176 gen_store_gpr(t0, rd);
10177 tcg_temp_free(t0);
10178 return;
10180 die:
10181 tcg_temp_free(t0);
10182 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10183 generate_exception_end(ctx, EXCP_RI);
10186 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10187 int u, int sel, int h)
10189 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10190 TCGv t0 = tcg_temp_local_new();
10192 gen_load_gpr(t0, rt);
10193 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10194 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10195 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10196 /* NOP */
10198 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10199 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10200 /* NOP */
10202 } else if (u == 0) {
10203 switch (rd) {
10204 case 1:
10205 switch (sel) {
10206 case 1:
10207 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10208 break;
10209 case 2:
10210 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10211 break;
10212 default:
10213 goto die;
10214 break;
10216 break;
10217 case 2:
10218 switch (sel) {
10219 case 1:
10220 gen_helper_mttc0_tcstatus(cpu_env, t0);
10221 break;
10222 case 2:
10223 gen_helper_mttc0_tcbind(cpu_env, t0);
10224 break;
10225 case 3:
10226 gen_helper_mttc0_tcrestart(cpu_env, t0);
10227 break;
10228 case 4:
10229 gen_helper_mttc0_tchalt(cpu_env, t0);
10230 break;
10231 case 5:
10232 gen_helper_mttc0_tccontext(cpu_env, t0);
10233 break;
10234 case 6:
10235 gen_helper_mttc0_tcschedule(cpu_env, t0);
10236 break;
10237 case 7:
10238 gen_helper_mttc0_tcschefback(cpu_env, t0);
10239 break;
10240 default:
10241 gen_mtc0(ctx, t0, rd, sel);
10242 break;
10244 break;
10245 case 10:
10246 switch (sel) {
10247 case 0:
10248 gen_helper_mttc0_entryhi(cpu_env, t0);
10249 break;
10250 default:
10251 gen_mtc0(ctx, t0, rd, sel);
10252 break;
10254 break;
10255 case 12:
10256 switch (sel) {
10257 case 0:
10258 gen_helper_mttc0_status(cpu_env, t0);
10259 break;
10260 default:
10261 gen_mtc0(ctx, t0, rd, sel);
10262 break;
10264 break;
10265 case 13:
10266 switch (sel) {
10267 case 0:
10268 gen_helper_mttc0_cause(cpu_env, t0);
10269 break;
10270 default:
10271 goto die;
10272 break;
10274 break;
10275 case 15:
10276 switch (sel) {
10277 case 1:
10278 gen_helper_mttc0_ebase(cpu_env, t0);
10279 break;
10280 default:
10281 goto die;
10282 break;
10284 break;
10285 case 23:
10286 switch (sel) {
10287 case 0:
10288 gen_helper_mttc0_debug(cpu_env, t0);
10289 break;
10290 default:
10291 gen_mtc0(ctx, t0, rd, sel);
10292 break;
10294 break;
10295 default:
10296 gen_mtc0(ctx, t0, rd, sel);
10298 } else {
10299 switch (sel) {
10300 /* GPR registers. */
10301 case 0:
10302 gen_helper_0e1i(mttgpr, t0, rd);
10303 break;
10304 /* Auxiliary CPU registers */
10305 case 1:
10306 switch (rd) {
10307 case 0:
10308 gen_helper_0e1i(mttlo, t0, 0);
10309 break;
10310 case 1:
10311 gen_helper_0e1i(mtthi, t0, 0);
10312 break;
10313 case 2:
10314 gen_helper_0e1i(mttacx, t0, 0);
10315 break;
10316 case 4:
10317 gen_helper_0e1i(mttlo, t0, 1);
10318 break;
10319 case 5:
10320 gen_helper_0e1i(mtthi, t0, 1);
10321 break;
10322 case 6:
10323 gen_helper_0e1i(mttacx, t0, 1);
10324 break;
10325 case 8:
10326 gen_helper_0e1i(mttlo, t0, 2);
10327 break;
10328 case 9:
10329 gen_helper_0e1i(mtthi, t0, 2);
10330 break;
10331 case 10:
10332 gen_helper_0e1i(mttacx, t0, 2);
10333 break;
10334 case 12:
10335 gen_helper_0e1i(mttlo, t0, 3);
10336 break;
10337 case 13:
10338 gen_helper_0e1i(mtthi, t0, 3);
10339 break;
10340 case 14:
10341 gen_helper_0e1i(mttacx, t0, 3);
10342 break;
10343 case 16:
10344 gen_helper_mttdsp(cpu_env, t0);
10345 break;
10346 default:
10347 goto die;
10349 break;
10350 /* Floating point (COP1). */
10351 case 2:
10352 /* XXX: For now we support only a single FPU context. */
10353 if (h == 0) {
10354 TCGv_i32 fp0 = tcg_temp_new_i32();
10356 tcg_gen_trunc_tl_i32(fp0, t0);
10357 gen_store_fpr32(ctx, fp0, rd);
10358 tcg_temp_free_i32(fp0);
10359 } else {
10360 TCGv_i32 fp0 = tcg_temp_new_i32();
10362 tcg_gen_trunc_tl_i32(fp0, t0);
10363 gen_store_fpr32h(ctx, fp0, rd);
10364 tcg_temp_free_i32(fp0);
10366 break;
10367 case 3:
10368 /* XXX: For now we support only a single FPU context. */
10370 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10372 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10373 tcg_temp_free_i32(fs_tmp);
10375 /* Stop translation as we may have changed hflags */
10376 ctx->base.is_jmp = DISAS_STOP;
10377 break;
10378 /* COP2: Not implemented. */
10379 case 4:
10380 case 5:
10381 /* fall through */
10382 default:
10383 goto die;
10386 trace_mips_translate_tr("mttr", rd, u, sel, h);
10387 tcg_temp_free(t0);
10388 return;
10390 die:
10391 tcg_temp_free(t0);
10392 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10393 generate_exception_end(ctx, EXCP_RI);
10396 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10397 int rt, int rd)
10399 const char *opn = "ldst";
10401 check_cp0_enabled(ctx);
10402 switch (opc) {
10403 case OPC_MFC0:
10404 if (rt == 0) {
10405 /* Treat as NOP. */
10406 return;
10408 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10409 opn = "mfc0";
10410 break;
10411 case OPC_MTC0:
10413 TCGv t0 = tcg_temp_new();
10415 gen_load_gpr(t0, rt);
10416 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10417 tcg_temp_free(t0);
10419 opn = "mtc0";
10420 break;
10421 #if defined(TARGET_MIPS64)
10422 case OPC_DMFC0:
10423 check_insn(ctx, ISA_MIPS3);
10424 if (rt == 0) {
10425 /* Treat as NOP. */
10426 return;
10428 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10429 opn = "dmfc0";
10430 break;
10431 case OPC_DMTC0:
10432 check_insn(ctx, ISA_MIPS3);
10434 TCGv t0 = tcg_temp_new();
10436 gen_load_gpr(t0, rt);
10437 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10438 tcg_temp_free(t0);
10440 opn = "dmtc0";
10441 break;
10442 #endif
10443 case OPC_MFHC0:
10444 check_mvh(ctx);
10445 if (rt == 0) {
10446 /* Treat as NOP. */
10447 return;
10449 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10450 opn = "mfhc0";
10451 break;
10452 case OPC_MTHC0:
10453 check_mvh(ctx);
10455 TCGv t0 = tcg_temp_new();
10456 gen_load_gpr(t0, rt);
10457 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10458 tcg_temp_free(t0);
10460 opn = "mthc0";
10461 break;
10462 case OPC_MFTR:
10463 check_cp0_enabled(ctx);
10464 if (rd == 0) {
10465 /* Treat as NOP. */
10466 return;
10468 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10469 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10470 opn = "mftr";
10471 break;
10472 case OPC_MTTR:
10473 check_cp0_enabled(ctx);
10474 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10475 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10476 opn = "mttr";
10477 break;
10478 case OPC_TLBWI:
10479 opn = "tlbwi";
10480 if (!env->tlb->helper_tlbwi) {
10481 goto die;
10483 gen_helper_tlbwi(cpu_env);
10484 break;
10485 case OPC_TLBINV:
10486 opn = "tlbinv";
10487 if (ctx->ie >= 2) {
10488 if (!env->tlb->helper_tlbinv) {
10489 goto die;
10491 gen_helper_tlbinv(cpu_env);
10492 } /* treat as nop if TLBINV not supported */
10493 break;
10494 case OPC_TLBINVF:
10495 opn = "tlbinvf";
10496 if (ctx->ie >= 2) {
10497 if (!env->tlb->helper_tlbinvf) {
10498 goto die;
10500 gen_helper_tlbinvf(cpu_env);
10501 } /* treat as nop if TLBINV not supported */
10502 break;
10503 case OPC_TLBWR:
10504 opn = "tlbwr";
10505 if (!env->tlb->helper_tlbwr) {
10506 goto die;
10508 gen_helper_tlbwr(cpu_env);
10509 break;
10510 case OPC_TLBP:
10511 opn = "tlbp";
10512 if (!env->tlb->helper_tlbp) {
10513 goto die;
10515 gen_helper_tlbp(cpu_env);
10516 break;
10517 case OPC_TLBR:
10518 opn = "tlbr";
10519 if (!env->tlb->helper_tlbr) {
10520 goto die;
10522 gen_helper_tlbr(cpu_env);
10523 break;
10524 case OPC_ERET: /* OPC_ERETNC */
10525 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10526 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10527 goto die;
10528 } else {
10529 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10530 if (ctx->opcode & (1 << bit_shift)) {
10531 /* OPC_ERETNC */
10532 opn = "eretnc";
10533 check_insn(ctx, ISA_MIPS32R5);
10534 gen_helper_eretnc(cpu_env);
10535 } else {
10536 /* OPC_ERET */
10537 opn = "eret";
10538 check_insn(ctx, ISA_MIPS2);
10539 gen_helper_eret(cpu_env);
10541 ctx->base.is_jmp = DISAS_EXIT;
10543 break;
10544 case OPC_DERET:
10545 opn = "deret";
10546 check_insn(ctx, ISA_MIPS32);
10547 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10548 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10549 goto die;
10551 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10552 MIPS_INVAL(opn);
10553 generate_exception_end(ctx, EXCP_RI);
10554 } else {
10555 gen_helper_deret(cpu_env);
10556 ctx->base.is_jmp = DISAS_EXIT;
10558 break;
10559 case OPC_WAIT:
10560 opn = "wait";
10561 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10562 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10563 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10564 goto die;
10566 /* If we get an exception, we want to restart at next instruction */
10567 ctx->base.pc_next += 4;
10568 save_cpu_state(ctx, 1);
10569 ctx->base.pc_next -= 4;
10570 gen_helper_wait(cpu_env);
10571 ctx->base.is_jmp = DISAS_NORETURN;
10572 break;
10573 default:
10574 die:
10575 MIPS_INVAL(opn);
10576 generate_exception_end(ctx, EXCP_RI);
10577 return;
10579 (void)opn; /* avoid a compiler warning */
10581 #endif /* !CONFIG_USER_ONLY */
10583 /* CP1 Branches (before delay slot) */
10584 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10585 int32_t cc, int32_t offset)
10587 target_ulong btarget;
10588 TCGv_i32 t0 = tcg_temp_new_i32();
10590 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10591 generate_exception_end(ctx, EXCP_RI);
10592 goto out;
10595 if (cc != 0) {
10596 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10599 btarget = ctx->base.pc_next + 4 + offset;
10601 switch (op) {
10602 case OPC_BC1F:
10603 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10604 tcg_gen_not_i32(t0, t0);
10605 tcg_gen_andi_i32(t0, t0, 1);
10606 tcg_gen_extu_i32_tl(bcond, t0);
10607 goto not_likely;
10608 case OPC_BC1FL:
10609 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10610 tcg_gen_not_i32(t0, t0);
10611 tcg_gen_andi_i32(t0, t0, 1);
10612 tcg_gen_extu_i32_tl(bcond, t0);
10613 goto likely;
10614 case OPC_BC1T:
10615 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10616 tcg_gen_andi_i32(t0, t0, 1);
10617 tcg_gen_extu_i32_tl(bcond, t0);
10618 goto not_likely;
10619 case OPC_BC1TL:
10620 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10621 tcg_gen_andi_i32(t0, t0, 1);
10622 tcg_gen_extu_i32_tl(bcond, t0);
10623 likely:
10624 ctx->hflags |= MIPS_HFLAG_BL;
10625 break;
10626 case OPC_BC1FANY2:
10628 TCGv_i32 t1 = tcg_temp_new_i32();
10629 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10630 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10631 tcg_gen_nand_i32(t0, t0, t1);
10632 tcg_temp_free_i32(t1);
10633 tcg_gen_andi_i32(t0, t0, 1);
10634 tcg_gen_extu_i32_tl(bcond, t0);
10636 goto not_likely;
10637 case OPC_BC1TANY2:
10639 TCGv_i32 t1 = tcg_temp_new_i32();
10640 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10641 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10642 tcg_gen_or_i32(t0, t0, t1);
10643 tcg_temp_free_i32(t1);
10644 tcg_gen_andi_i32(t0, t0, 1);
10645 tcg_gen_extu_i32_tl(bcond, t0);
10647 goto not_likely;
10648 case OPC_BC1FANY4:
10650 TCGv_i32 t1 = tcg_temp_new_i32();
10651 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10652 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10653 tcg_gen_and_i32(t0, t0, t1);
10654 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10655 tcg_gen_and_i32(t0, t0, t1);
10656 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10657 tcg_gen_nand_i32(t0, t0, t1);
10658 tcg_temp_free_i32(t1);
10659 tcg_gen_andi_i32(t0, t0, 1);
10660 tcg_gen_extu_i32_tl(bcond, t0);
10662 goto not_likely;
10663 case OPC_BC1TANY4:
10665 TCGv_i32 t1 = tcg_temp_new_i32();
10666 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10667 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10668 tcg_gen_or_i32(t0, t0, t1);
10669 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10670 tcg_gen_or_i32(t0, t0, t1);
10671 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10672 tcg_gen_or_i32(t0, t0, t1);
10673 tcg_temp_free_i32(t1);
10674 tcg_gen_andi_i32(t0, t0, 1);
10675 tcg_gen_extu_i32_tl(bcond, t0);
10677 not_likely:
10678 ctx->hflags |= MIPS_HFLAG_BC;
10679 break;
10680 default:
10681 MIPS_INVAL("cp1 cond branch");
10682 generate_exception_end(ctx, EXCP_RI);
10683 goto out;
10685 ctx->btarget = btarget;
10686 ctx->hflags |= MIPS_HFLAG_BDS32;
10687 out:
10688 tcg_temp_free_i32(t0);
10691 /* R6 CP1 Branches */
10692 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10693 int32_t ft, int32_t offset,
10694 int delayslot_size)
10696 target_ulong btarget;
10697 TCGv_i64 t0 = tcg_temp_new_i64();
10699 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10700 #ifdef MIPS_DEBUG_DISAS
10701 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10702 "\n", ctx->base.pc_next);
10703 #endif
10704 generate_exception_end(ctx, EXCP_RI);
10705 goto out;
10708 gen_load_fpr64(ctx, t0, ft);
10709 tcg_gen_andi_i64(t0, t0, 1);
10711 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10713 switch (op) {
10714 case OPC_BC1EQZ:
10715 tcg_gen_xori_i64(t0, t0, 1);
10716 ctx->hflags |= MIPS_HFLAG_BC;
10717 break;
10718 case OPC_BC1NEZ:
10719 /* t0 already set */
10720 ctx->hflags |= MIPS_HFLAG_BC;
10721 break;
10722 default:
10723 MIPS_INVAL("cp1 cond branch");
10724 generate_exception_end(ctx, EXCP_RI);
10725 goto out;
10728 tcg_gen_trunc_i64_tl(bcond, t0);
10730 ctx->btarget = btarget;
10732 switch (delayslot_size) {
10733 case 2:
10734 ctx->hflags |= MIPS_HFLAG_BDS16;
10735 break;
10736 case 4:
10737 ctx->hflags |= MIPS_HFLAG_BDS32;
10738 break;
10741 out:
10742 tcg_temp_free_i64(t0);
10745 /* Coprocessor 1 (FPU) */
10747 #define FOP(func, fmt) (((fmt) << 21) | (func))
10749 enum fopcode {
10750 OPC_ADD_S = FOP(0, FMT_S),
10751 OPC_SUB_S = FOP(1, FMT_S),
10752 OPC_MUL_S = FOP(2, FMT_S),
10753 OPC_DIV_S = FOP(3, FMT_S),
10754 OPC_SQRT_S = FOP(4, FMT_S),
10755 OPC_ABS_S = FOP(5, FMT_S),
10756 OPC_MOV_S = FOP(6, FMT_S),
10757 OPC_NEG_S = FOP(7, FMT_S),
10758 OPC_ROUND_L_S = FOP(8, FMT_S),
10759 OPC_TRUNC_L_S = FOP(9, FMT_S),
10760 OPC_CEIL_L_S = FOP(10, FMT_S),
10761 OPC_FLOOR_L_S = FOP(11, FMT_S),
10762 OPC_ROUND_W_S = FOP(12, FMT_S),
10763 OPC_TRUNC_W_S = FOP(13, FMT_S),
10764 OPC_CEIL_W_S = FOP(14, FMT_S),
10765 OPC_FLOOR_W_S = FOP(15, FMT_S),
10766 OPC_SEL_S = FOP(16, FMT_S),
10767 OPC_MOVCF_S = FOP(17, FMT_S),
10768 OPC_MOVZ_S = FOP(18, FMT_S),
10769 OPC_MOVN_S = FOP(19, FMT_S),
10770 OPC_SELEQZ_S = FOP(20, FMT_S),
10771 OPC_RECIP_S = FOP(21, FMT_S),
10772 OPC_RSQRT_S = FOP(22, FMT_S),
10773 OPC_SELNEZ_S = FOP(23, FMT_S),
10774 OPC_MADDF_S = FOP(24, FMT_S),
10775 OPC_MSUBF_S = FOP(25, FMT_S),
10776 OPC_RINT_S = FOP(26, FMT_S),
10777 OPC_CLASS_S = FOP(27, FMT_S),
10778 OPC_MIN_S = FOP(28, FMT_S),
10779 OPC_RECIP2_S = FOP(28, FMT_S),
10780 OPC_MINA_S = FOP(29, FMT_S),
10781 OPC_RECIP1_S = FOP(29, FMT_S),
10782 OPC_MAX_S = FOP(30, FMT_S),
10783 OPC_RSQRT1_S = FOP(30, FMT_S),
10784 OPC_MAXA_S = FOP(31, FMT_S),
10785 OPC_RSQRT2_S = FOP(31, FMT_S),
10786 OPC_CVT_D_S = FOP(33, FMT_S),
10787 OPC_CVT_W_S = FOP(36, FMT_S),
10788 OPC_CVT_L_S = FOP(37, FMT_S),
10789 OPC_CVT_PS_S = FOP(38, FMT_S),
10790 OPC_CMP_F_S = FOP(48, FMT_S),
10791 OPC_CMP_UN_S = FOP(49, FMT_S),
10792 OPC_CMP_EQ_S = FOP(50, FMT_S),
10793 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10794 OPC_CMP_OLT_S = FOP(52, FMT_S),
10795 OPC_CMP_ULT_S = FOP(53, FMT_S),
10796 OPC_CMP_OLE_S = FOP(54, FMT_S),
10797 OPC_CMP_ULE_S = FOP(55, FMT_S),
10798 OPC_CMP_SF_S = FOP(56, FMT_S),
10799 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10800 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10801 OPC_CMP_NGL_S = FOP(59, FMT_S),
10802 OPC_CMP_LT_S = FOP(60, FMT_S),
10803 OPC_CMP_NGE_S = FOP(61, FMT_S),
10804 OPC_CMP_LE_S = FOP(62, FMT_S),
10805 OPC_CMP_NGT_S = FOP(63, FMT_S),
10807 OPC_ADD_D = FOP(0, FMT_D),
10808 OPC_SUB_D = FOP(1, FMT_D),
10809 OPC_MUL_D = FOP(2, FMT_D),
10810 OPC_DIV_D = FOP(3, FMT_D),
10811 OPC_SQRT_D = FOP(4, FMT_D),
10812 OPC_ABS_D = FOP(5, FMT_D),
10813 OPC_MOV_D = FOP(6, FMT_D),
10814 OPC_NEG_D = FOP(7, FMT_D),
10815 OPC_ROUND_L_D = FOP(8, FMT_D),
10816 OPC_TRUNC_L_D = FOP(9, FMT_D),
10817 OPC_CEIL_L_D = FOP(10, FMT_D),
10818 OPC_FLOOR_L_D = FOP(11, FMT_D),
10819 OPC_ROUND_W_D = FOP(12, FMT_D),
10820 OPC_TRUNC_W_D = FOP(13, FMT_D),
10821 OPC_CEIL_W_D = FOP(14, FMT_D),
10822 OPC_FLOOR_W_D = FOP(15, FMT_D),
10823 OPC_SEL_D = FOP(16, FMT_D),
10824 OPC_MOVCF_D = FOP(17, FMT_D),
10825 OPC_MOVZ_D = FOP(18, FMT_D),
10826 OPC_MOVN_D = FOP(19, FMT_D),
10827 OPC_SELEQZ_D = FOP(20, FMT_D),
10828 OPC_RECIP_D = FOP(21, FMT_D),
10829 OPC_RSQRT_D = FOP(22, FMT_D),
10830 OPC_SELNEZ_D = FOP(23, FMT_D),
10831 OPC_MADDF_D = FOP(24, FMT_D),
10832 OPC_MSUBF_D = FOP(25, FMT_D),
10833 OPC_RINT_D = FOP(26, FMT_D),
10834 OPC_CLASS_D = FOP(27, FMT_D),
10835 OPC_MIN_D = FOP(28, FMT_D),
10836 OPC_RECIP2_D = FOP(28, FMT_D),
10837 OPC_MINA_D = FOP(29, FMT_D),
10838 OPC_RECIP1_D = FOP(29, FMT_D),
10839 OPC_MAX_D = FOP(30, FMT_D),
10840 OPC_RSQRT1_D = FOP(30, FMT_D),
10841 OPC_MAXA_D = FOP(31, FMT_D),
10842 OPC_RSQRT2_D = FOP(31, FMT_D),
10843 OPC_CVT_S_D = FOP(32, FMT_D),
10844 OPC_CVT_W_D = FOP(36, FMT_D),
10845 OPC_CVT_L_D = FOP(37, FMT_D),
10846 OPC_CMP_F_D = FOP(48, FMT_D),
10847 OPC_CMP_UN_D = FOP(49, FMT_D),
10848 OPC_CMP_EQ_D = FOP(50, FMT_D),
10849 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10850 OPC_CMP_OLT_D = FOP(52, FMT_D),
10851 OPC_CMP_ULT_D = FOP(53, FMT_D),
10852 OPC_CMP_OLE_D = FOP(54, FMT_D),
10853 OPC_CMP_ULE_D = FOP(55, FMT_D),
10854 OPC_CMP_SF_D = FOP(56, FMT_D),
10855 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10856 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10857 OPC_CMP_NGL_D = FOP(59, FMT_D),
10858 OPC_CMP_LT_D = FOP(60, FMT_D),
10859 OPC_CMP_NGE_D = FOP(61, FMT_D),
10860 OPC_CMP_LE_D = FOP(62, FMT_D),
10861 OPC_CMP_NGT_D = FOP(63, FMT_D),
10863 OPC_CVT_S_W = FOP(32, FMT_W),
10864 OPC_CVT_D_W = FOP(33, FMT_W),
10865 OPC_CVT_S_L = FOP(32, FMT_L),
10866 OPC_CVT_D_L = FOP(33, FMT_L),
10867 OPC_CVT_PS_PW = FOP(38, FMT_W),
10869 OPC_ADD_PS = FOP(0, FMT_PS),
10870 OPC_SUB_PS = FOP(1, FMT_PS),
10871 OPC_MUL_PS = FOP(2, FMT_PS),
10872 OPC_DIV_PS = FOP(3, FMT_PS),
10873 OPC_ABS_PS = FOP(5, FMT_PS),
10874 OPC_MOV_PS = FOP(6, FMT_PS),
10875 OPC_NEG_PS = FOP(7, FMT_PS),
10876 OPC_MOVCF_PS = FOP(17, FMT_PS),
10877 OPC_MOVZ_PS = FOP(18, FMT_PS),
10878 OPC_MOVN_PS = FOP(19, FMT_PS),
10879 OPC_ADDR_PS = FOP(24, FMT_PS),
10880 OPC_MULR_PS = FOP(26, FMT_PS),
10881 OPC_RECIP2_PS = FOP(28, FMT_PS),
10882 OPC_RECIP1_PS = FOP(29, FMT_PS),
10883 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10884 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10886 OPC_CVT_S_PU = FOP(32, FMT_PS),
10887 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10888 OPC_CVT_S_PL = FOP(40, FMT_PS),
10889 OPC_PLL_PS = FOP(44, FMT_PS),
10890 OPC_PLU_PS = FOP(45, FMT_PS),
10891 OPC_PUL_PS = FOP(46, FMT_PS),
10892 OPC_PUU_PS = FOP(47, FMT_PS),
10893 OPC_CMP_F_PS = FOP(48, FMT_PS),
10894 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10895 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10896 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10897 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10898 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10899 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10900 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10901 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10902 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10903 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10904 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10905 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10906 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10907 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10908 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10911 enum r6_f_cmp_op {
10912 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10913 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10914 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10915 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10916 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10917 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10918 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10919 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10920 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10921 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10922 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10923 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10924 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10925 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10926 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10927 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10928 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10929 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10930 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10931 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10932 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10933 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10935 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10936 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10937 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10938 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10939 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10940 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10941 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10942 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10943 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10944 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10945 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10946 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10947 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10948 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10949 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10950 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10951 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10952 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10953 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10954 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10955 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10956 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10959 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10961 TCGv t0 = tcg_temp_new();
10963 switch (opc) {
10964 case OPC_MFC1:
10966 TCGv_i32 fp0 = tcg_temp_new_i32();
10968 gen_load_fpr32(ctx, fp0, fs);
10969 tcg_gen_ext_i32_tl(t0, fp0);
10970 tcg_temp_free_i32(fp0);
10972 gen_store_gpr(t0, rt);
10973 break;
10974 case OPC_MTC1:
10975 gen_load_gpr(t0, rt);
10977 TCGv_i32 fp0 = tcg_temp_new_i32();
10979 tcg_gen_trunc_tl_i32(fp0, t0);
10980 gen_store_fpr32(ctx, fp0, fs);
10981 tcg_temp_free_i32(fp0);
10983 break;
10984 case OPC_CFC1:
10985 gen_helper_1e0i(cfc1, t0, fs);
10986 gen_store_gpr(t0, rt);
10987 break;
10988 case OPC_CTC1:
10989 gen_load_gpr(t0, rt);
10990 save_cpu_state(ctx, 0);
10992 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10994 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10995 tcg_temp_free_i32(fs_tmp);
10997 /* Stop translation as we may have changed hflags */
10998 ctx->base.is_jmp = DISAS_STOP;
10999 break;
11000 #if defined(TARGET_MIPS64)
11001 case OPC_DMFC1:
11002 gen_load_fpr64(ctx, t0, fs);
11003 gen_store_gpr(t0, rt);
11004 break;
11005 case OPC_DMTC1:
11006 gen_load_gpr(t0, rt);
11007 gen_store_fpr64(ctx, t0, fs);
11008 break;
11009 #endif
11010 case OPC_MFHC1:
11012 TCGv_i32 fp0 = tcg_temp_new_i32();
11014 gen_load_fpr32h(ctx, fp0, fs);
11015 tcg_gen_ext_i32_tl(t0, fp0);
11016 tcg_temp_free_i32(fp0);
11018 gen_store_gpr(t0, rt);
11019 break;
11020 case OPC_MTHC1:
11021 gen_load_gpr(t0, rt);
11023 TCGv_i32 fp0 = tcg_temp_new_i32();
11025 tcg_gen_trunc_tl_i32(fp0, t0);
11026 gen_store_fpr32h(ctx, fp0, fs);
11027 tcg_temp_free_i32(fp0);
11029 break;
11030 default:
11031 MIPS_INVAL("cp1 move");
11032 generate_exception_end(ctx, EXCP_RI);
11033 goto out;
11036 out:
11037 tcg_temp_free(t0);
11040 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11042 TCGLabel *l1;
11043 TCGCond cond;
11044 TCGv_i32 t0;
11046 if (rd == 0) {
11047 /* Treat as NOP. */
11048 return;
11051 if (tf) {
11052 cond = TCG_COND_EQ;
11053 } else {
11054 cond = TCG_COND_NE;
11057 l1 = gen_new_label();
11058 t0 = tcg_temp_new_i32();
11059 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11060 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11061 tcg_temp_free_i32(t0);
11062 if (rs == 0) {
11063 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11064 } else {
11065 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11067 gen_set_label(l1);
11070 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11071 int tf)
11073 int cond;
11074 TCGv_i32 t0 = tcg_temp_new_i32();
11075 TCGLabel *l1 = gen_new_label();
11077 if (tf) {
11078 cond = TCG_COND_EQ;
11079 } else {
11080 cond = TCG_COND_NE;
11083 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11084 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11085 gen_load_fpr32(ctx, t0, fs);
11086 gen_store_fpr32(ctx, t0, fd);
11087 gen_set_label(l1);
11088 tcg_temp_free_i32(t0);
11091 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11092 int tf)
11094 int cond;
11095 TCGv_i32 t0 = tcg_temp_new_i32();
11096 TCGv_i64 fp0;
11097 TCGLabel *l1 = gen_new_label();
11099 if (tf) {
11100 cond = TCG_COND_EQ;
11101 } else {
11102 cond = TCG_COND_NE;
11105 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11106 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11107 tcg_temp_free_i32(t0);
11108 fp0 = tcg_temp_new_i64();
11109 gen_load_fpr64(ctx, fp0, fs);
11110 gen_store_fpr64(ctx, fp0, fd);
11111 tcg_temp_free_i64(fp0);
11112 gen_set_label(l1);
11115 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11116 int cc, int tf)
11118 int cond;
11119 TCGv_i32 t0 = tcg_temp_new_i32();
11120 TCGLabel *l1 = gen_new_label();
11121 TCGLabel *l2 = gen_new_label();
11123 if (tf) {
11124 cond = TCG_COND_EQ;
11125 } else {
11126 cond = TCG_COND_NE;
11129 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11130 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11131 gen_load_fpr32(ctx, t0, fs);
11132 gen_store_fpr32(ctx, t0, fd);
11133 gen_set_label(l1);
11135 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11136 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11137 gen_load_fpr32h(ctx, t0, fs);
11138 gen_store_fpr32h(ctx, t0, fd);
11139 tcg_temp_free_i32(t0);
11140 gen_set_label(l2);
11143 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11144 int fs)
11146 TCGv_i32 t1 = tcg_const_i32(0);
11147 TCGv_i32 fp0 = tcg_temp_new_i32();
11148 TCGv_i32 fp1 = tcg_temp_new_i32();
11149 TCGv_i32 fp2 = tcg_temp_new_i32();
11150 gen_load_fpr32(ctx, fp0, fd);
11151 gen_load_fpr32(ctx, fp1, ft);
11152 gen_load_fpr32(ctx, fp2, fs);
11154 switch (op1) {
11155 case OPC_SEL_S:
11156 tcg_gen_andi_i32(fp0, fp0, 1);
11157 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11158 break;
11159 case OPC_SELEQZ_S:
11160 tcg_gen_andi_i32(fp1, fp1, 1);
11161 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11162 break;
11163 case OPC_SELNEZ_S:
11164 tcg_gen_andi_i32(fp1, fp1, 1);
11165 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11166 break;
11167 default:
11168 MIPS_INVAL("gen_sel_s");
11169 generate_exception_end(ctx, EXCP_RI);
11170 break;
11173 gen_store_fpr32(ctx, fp0, fd);
11174 tcg_temp_free_i32(fp2);
11175 tcg_temp_free_i32(fp1);
11176 tcg_temp_free_i32(fp0);
11177 tcg_temp_free_i32(t1);
11180 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11181 int fs)
11183 TCGv_i64 t1 = tcg_const_i64(0);
11184 TCGv_i64 fp0 = tcg_temp_new_i64();
11185 TCGv_i64 fp1 = tcg_temp_new_i64();
11186 TCGv_i64 fp2 = tcg_temp_new_i64();
11187 gen_load_fpr64(ctx, fp0, fd);
11188 gen_load_fpr64(ctx, fp1, ft);
11189 gen_load_fpr64(ctx, fp2, fs);
11191 switch (op1) {
11192 case OPC_SEL_D:
11193 tcg_gen_andi_i64(fp0, fp0, 1);
11194 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11195 break;
11196 case OPC_SELEQZ_D:
11197 tcg_gen_andi_i64(fp1, fp1, 1);
11198 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11199 break;
11200 case OPC_SELNEZ_D:
11201 tcg_gen_andi_i64(fp1, fp1, 1);
11202 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11203 break;
11204 default:
11205 MIPS_INVAL("gen_sel_d");
11206 generate_exception_end(ctx, EXCP_RI);
11207 break;
11210 gen_store_fpr64(ctx, fp0, fd);
11211 tcg_temp_free_i64(fp2);
11212 tcg_temp_free_i64(fp1);
11213 tcg_temp_free_i64(fp0);
11214 tcg_temp_free_i64(t1);
11217 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11218 int ft, int fs, int fd, int cc)
11220 uint32_t func = ctx->opcode & 0x3f;
11221 switch (op1) {
11222 case OPC_ADD_S:
11224 TCGv_i32 fp0 = tcg_temp_new_i32();
11225 TCGv_i32 fp1 = tcg_temp_new_i32();
11227 gen_load_fpr32(ctx, fp0, fs);
11228 gen_load_fpr32(ctx, fp1, ft);
11229 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11230 tcg_temp_free_i32(fp1);
11231 gen_store_fpr32(ctx, fp0, fd);
11232 tcg_temp_free_i32(fp0);
11234 break;
11235 case OPC_SUB_S:
11237 TCGv_i32 fp0 = tcg_temp_new_i32();
11238 TCGv_i32 fp1 = tcg_temp_new_i32();
11240 gen_load_fpr32(ctx, fp0, fs);
11241 gen_load_fpr32(ctx, fp1, ft);
11242 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11243 tcg_temp_free_i32(fp1);
11244 gen_store_fpr32(ctx, fp0, fd);
11245 tcg_temp_free_i32(fp0);
11247 break;
11248 case OPC_MUL_S:
11250 TCGv_i32 fp0 = tcg_temp_new_i32();
11251 TCGv_i32 fp1 = tcg_temp_new_i32();
11253 gen_load_fpr32(ctx, fp0, fs);
11254 gen_load_fpr32(ctx, fp1, ft);
11255 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11256 tcg_temp_free_i32(fp1);
11257 gen_store_fpr32(ctx, fp0, fd);
11258 tcg_temp_free_i32(fp0);
11260 break;
11261 case OPC_DIV_S:
11263 TCGv_i32 fp0 = tcg_temp_new_i32();
11264 TCGv_i32 fp1 = tcg_temp_new_i32();
11266 gen_load_fpr32(ctx, fp0, fs);
11267 gen_load_fpr32(ctx, fp1, ft);
11268 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11269 tcg_temp_free_i32(fp1);
11270 gen_store_fpr32(ctx, fp0, fd);
11271 tcg_temp_free_i32(fp0);
11273 break;
11274 case OPC_SQRT_S:
11276 TCGv_i32 fp0 = tcg_temp_new_i32();
11278 gen_load_fpr32(ctx, fp0, fs);
11279 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11280 gen_store_fpr32(ctx, fp0, fd);
11281 tcg_temp_free_i32(fp0);
11283 break;
11284 case OPC_ABS_S:
11286 TCGv_i32 fp0 = tcg_temp_new_i32();
11288 gen_load_fpr32(ctx, fp0, fs);
11289 if (ctx->abs2008) {
11290 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11291 } else {
11292 gen_helper_float_abs_s(fp0, fp0);
11294 gen_store_fpr32(ctx, fp0, fd);
11295 tcg_temp_free_i32(fp0);
11297 break;
11298 case OPC_MOV_S:
11300 TCGv_i32 fp0 = tcg_temp_new_i32();
11302 gen_load_fpr32(ctx, fp0, fs);
11303 gen_store_fpr32(ctx, fp0, fd);
11304 tcg_temp_free_i32(fp0);
11306 break;
11307 case OPC_NEG_S:
11309 TCGv_i32 fp0 = tcg_temp_new_i32();
11311 gen_load_fpr32(ctx, fp0, fs);
11312 if (ctx->abs2008) {
11313 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11314 } else {
11315 gen_helper_float_chs_s(fp0, fp0);
11317 gen_store_fpr32(ctx, fp0, fd);
11318 tcg_temp_free_i32(fp0);
11320 break;
11321 case OPC_ROUND_L_S:
11322 check_cp1_64bitmode(ctx);
11324 TCGv_i32 fp32 = tcg_temp_new_i32();
11325 TCGv_i64 fp64 = tcg_temp_new_i64();
11327 gen_load_fpr32(ctx, fp32, fs);
11328 if (ctx->nan2008) {
11329 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11330 } else {
11331 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11333 tcg_temp_free_i32(fp32);
11334 gen_store_fpr64(ctx, fp64, fd);
11335 tcg_temp_free_i64(fp64);
11337 break;
11338 case OPC_TRUNC_L_S:
11339 check_cp1_64bitmode(ctx);
11341 TCGv_i32 fp32 = tcg_temp_new_i32();
11342 TCGv_i64 fp64 = tcg_temp_new_i64();
11344 gen_load_fpr32(ctx, fp32, fs);
11345 if (ctx->nan2008) {
11346 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11347 } else {
11348 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11350 tcg_temp_free_i32(fp32);
11351 gen_store_fpr64(ctx, fp64, fd);
11352 tcg_temp_free_i64(fp64);
11354 break;
11355 case OPC_CEIL_L_S:
11356 check_cp1_64bitmode(ctx);
11358 TCGv_i32 fp32 = tcg_temp_new_i32();
11359 TCGv_i64 fp64 = tcg_temp_new_i64();
11361 gen_load_fpr32(ctx, fp32, fs);
11362 if (ctx->nan2008) {
11363 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11364 } else {
11365 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11367 tcg_temp_free_i32(fp32);
11368 gen_store_fpr64(ctx, fp64, fd);
11369 tcg_temp_free_i64(fp64);
11371 break;
11372 case OPC_FLOOR_L_S:
11373 check_cp1_64bitmode(ctx);
11375 TCGv_i32 fp32 = tcg_temp_new_i32();
11376 TCGv_i64 fp64 = tcg_temp_new_i64();
11378 gen_load_fpr32(ctx, fp32, fs);
11379 if (ctx->nan2008) {
11380 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11381 } else {
11382 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11384 tcg_temp_free_i32(fp32);
11385 gen_store_fpr64(ctx, fp64, fd);
11386 tcg_temp_free_i64(fp64);
11388 break;
11389 case OPC_ROUND_W_S:
11391 TCGv_i32 fp0 = tcg_temp_new_i32();
11393 gen_load_fpr32(ctx, fp0, fs);
11394 if (ctx->nan2008) {
11395 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11396 } else {
11397 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11399 gen_store_fpr32(ctx, fp0, fd);
11400 tcg_temp_free_i32(fp0);
11402 break;
11403 case OPC_TRUNC_W_S:
11405 TCGv_i32 fp0 = tcg_temp_new_i32();
11407 gen_load_fpr32(ctx, fp0, fs);
11408 if (ctx->nan2008) {
11409 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11410 } else {
11411 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11413 gen_store_fpr32(ctx, fp0, fd);
11414 tcg_temp_free_i32(fp0);
11416 break;
11417 case OPC_CEIL_W_S:
11419 TCGv_i32 fp0 = tcg_temp_new_i32();
11421 gen_load_fpr32(ctx, fp0, fs);
11422 if (ctx->nan2008) {
11423 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11424 } else {
11425 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11427 gen_store_fpr32(ctx, fp0, fd);
11428 tcg_temp_free_i32(fp0);
11430 break;
11431 case OPC_FLOOR_W_S:
11433 TCGv_i32 fp0 = tcg_temp_new_i32();
11435 gen_load_fpr32(ctx, fp0, fs);
11436 if (ctx->nan2008) {
11437 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11438 } else {
11439 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11441 gen_store_fpr32(ctx, fp0, fd);
11442 tcg_temp_free_i32(fp0);
11444 break;
11445 case OPC_SEL_S:
11446 check_insn(ctx, ISA_MIPS32R6);
11447 gen_sel_s(ctx, op1, fd, ft, fs);
11448 break;
11449 case OPC_SELEQZ_S:
11450 check_insn(ctx, ISA_MIPS32R6);
11451 gen_sel_s(ctx, op1, fd, ft, fs);
11452 break;
11453 case OPC_SELNEZ_S:
11454 check_insn(ctx, ISA_MIPS32R6);
11455 gen_sel_s(ctx, op1, fd, ft, fs);
11456 break;
11457 case OPC_MOVCF_S:
11458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11459 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11460 break;
11461 case OPC_MOVZ_S:
11462 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11464 TCGLabel *l1 = gen_new_label();
11465 TCGv_i32 fp0;
11467 if (ft != 0) {
11468 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11470 fp0 = tcg_temp_new_i32();
11471 gen_load_fpr32(ctx, fp0, fs);
11472 gen_store_fpr32(ctx, fp0, fd);
11473 tcg_temp_free_i32(fp0);
11474 gen_set_label(l1);
11476 break;
11477 case OPC_MOVN_S:
11478 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11480 TCGLabel *l1 = gen_new_label();
11481 TCGv_i32 fp0;
11483 if (ft != 0) {
11484 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11485 fp0 = tcg_temp_new_i32();
11486 gen_load_fpr32(ctx, fp0, fs);
11487 gen_store_fpr32(ctx, fp0, fd);
11488 tcg_temp_free_i32(fp0);
11489 gen_set_label(l1);
11492 break;
11493 case OPC_RECIP_S:
11495 TCGv_i32 fp0 = tcg_temp_new_i32();
11497 gen_load_fpr32(ctx, fp0, fs);
11498 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11499 gen_store_fpr32(ctx, fp0, fd);
11500 tcg_temp_free_i32(fp0);
11502 break;
11503 case OPC_RSQRT_S:
11505 TCGv_i32 fp0 = tcg_temp_new_i32();
11507 gen_load_fpr32(ctx, fp0, fs);
11508 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11509 gen_store_fpr32(ctx, fp0, fd);
11510 tcg_temp_free_i32(fp0);
11512 break;
11513 case OPC_MADDF_S:
11514 check_insn(ctx, ISA_MIPS32R6);
11516 TCGv_i32 fp0 = tcg_temp_new_i32();
11517 TCGv_i32 fp1 = tcg_temp_new_i32();
11518 TCGv_i32 fp2 = tcg_temp_new_i32();
11519 gen_load_fpr32(ctx, fp0, fs);
11520 gen_load_fpr32(ctx, fp1, ft);
11521 gen_load_fpr32(ctx, fp2, fd);
11522 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11523 gen_store_fpr32(ctx, fp2, fd);
11524 tcg_temp_free_i32(fp2);
11525 tcg_temp_free_i32(fp1);
11526 tcg_temp_free_i32(fp0);
11528 break;
11529 case OPC_MSUBF_S:
11530 check_insn(ctx, ISA_MIPS32R6);
11532 TCGv_i32 fp0 = tcg_temp_new_i32();
11533 TCGv_i32 fp1 = tcg_temp_new_i32();
11534 TCGv_i32 fp2 = tcg_temp_new_i32();
11535 gen_load_fpr32(ctx, fp0, fs);
11536 gen_load_fpr32(ctx, fp1, ft);
11537 gen_load_fpr32(ctx, fp2, fd);
11538 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11539 gen_store_fpr32(ctx, fp2, fd);
11540 tcg_temp_free_i32(fp2);
11541 tcg_temp_free_i32(fp1);
11542 tcg_temp_free_i32(fp0);
11544 break;
11545 case OPC_RINT_S:
11546 check_insn(ctx, ISA_MIPS32R6);
11548 TCGv_i32 fp0 = tcg_temp_new_i32();
11549 gen_load_fpr32(ctx, fp0, fs);
11550 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11551 gen_store_fpr32(ctx, fp0, fd);
11552 tcg_temp_free_i32(fp0);
11554 break;
11555 case OPC_CLASS_S:
11556 check_insn(ctx, ISA_MIPS32R6);
11558 TCGv_i32 fp0 = tcg_temp_new_i32();
11559 gen_load_fpr32(ctx, fp0, fs);
11560 gen_helper_float_class_s(fp0, cpu_env, fp0);
11561 gen_store_fpr32(ctx, fp0, fd);
11562 tcg_temp_free_i32(fp0);
11564 break;
11565 case OPC_MIN_S: /* OPC_RECIP2_S */
11566 if (ctx->insn_flags & ISA_MIPS32R6) {
11567 /* OPC_MIN_S */
11568 TCGv_i32 fp0 = tcg_temp_new_i32();
11569 TCGv_i32 fp1 = tcg_temp_new_i32();
11570 TCGv_i32 fp2 = tcg_temp_new_i32();
11571 gen_load_fpr32(ctx, fp0, fs);
11572 gen_load_fpr32(ctx, fp1, ft);
11573 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11574 gen_store_fpr32(ctx, fp2, fd);
11575 tcg_temp_free_i32(fp2);
11576 tcg_temp_free_i32(fp1);
11577 tcg_temp_free_i32(fp0);
11578 } else {
11579 /* OPC_RECIP2_S */
11580 check_cp1_64bitmode(ctx);
11582 TCGv_i32 fp0 = tcg_temp_new_i32();
11583 TCGv_i32 fp1 = tcg_temp_new_i32();
11585 gen_load_fpr32(ctx, fp0, fs);
11586 gen_load_fpr32(ctx, fp1, ft);
11587 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11588 tcg_temp_free_i32(fp1);
11589 gen_store_fpr32(ctx, fp0, fd);
11590 tcg_temp_free_i32(fp0);
11593 break;
11594 case OPC_MINA_S: /* OPC_RECIP1_S */
11595 if (ctx->insn_flags & ISA_MIPS32R6) {
11596 /* OPC_MINA_S */
11597 TCGv_i32 fp0 = tcg_temp_new_i32();
11598 TCGv_i32 fp1 = tcg_temp_new_i32();
11599 TCGv_i32 fp2 = tcg_temp_new_i32();
11600 gen_load_fpr32(ctx, fp0, fs);
11601 gen_load_fpr32(ctx, fp1, ft);
11602 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11603 gen_store_fpr32(ctx, fp2, fd);
11604 tcg_temp_free_i32(fp2);
11605 tcg_temp_free_i32(fp1);
11606 tcg_temp_free_i32(fp0);
11607 } else {
11608 /* OPC_RECIP1_S */
11609 check_cp1_64bitmode(ctx);
11611 TCGv_i32 fp0 = tcg_temp_new_i32();
11613 gen_load_fpr32(ctx, fp0, fs);
11614 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11615 gen_store_fpr32(ctx, fp0, fd);
11616 tcg_temp_free_i32(fp0);
11619 break;
11620 case OPC_MAX_S: /* OPC_RSQRT1_S */
11621 if (ctx->insn_flags & ISA_MIPS32R6) {
11622 /* OPC_MAX_S */
11623 TCGv_i32 fp0 = tcg_temp_new_i32();
11624 TCGv_i32 fp1 = tcg_temp_new_i32();
11625 gen_load_fpr32(ctx, fp0, fs);
11626 gen_load_fpr32(ctx, fp1, ft);
11627 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11628 gen_store_fpr32(ctx, fp1, fd);
11629 tcg_temp_free_i32(fp1);
11630 tcg_temp_free_i32(fp0);
11631 } else {
11632 /* OPC_RSQRT1_S */
11633 check_cp1_64bitmode(ctx);
11635 TCGv_i32 fp0 = tcg_temp_new_i32();
11637 gen_load_fpr32(ctx, fp0, fs);
11638 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11639 gen_store_fpr32(ctx, fp0, fd);
11640 tcg_temp_free_i32(fp0);
11643 break;
11644 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11645 if (ctx->insn_flags & ISA_MIPS32R6) {
11646 /* OPC_MAXA_S */
11647 TCGv_i32 fp0 = tcg_temp_new_i32();
11648 TCGv_i32 fp1 = tcg_temp_new_i32();
11649 gen_load_fpr32(ctx, fp0, fs);
11650 gen_load_fpr32(ctx, fp1, ft);
11651 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11652 gen_store_fpr32(ctx, fp1, fd);
11653 tcg_temp_free_i32(fp1);
11654 tcg_temp_free_i32(fp0);
11655 } else {
11656 /* OPC_RSQRT2_S */
11657 check_cp1_64bitmode(ctx);
11659 TCGv_i32 fp0 = tcg_temp_new_i32();
11660 TCGv_i32 fp1 = tcg_temp_new_i32();
11662 gen_load_fpr32(ctx, fp0, fs);
11663 gen_load_fpr32(ctx, fp1, ft);
11664 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11665 tcg_temp_free_i32(fp1);
11666 gen_store_fpr32(ctx, fp0, fd);
11667 tcg_temp_free_i32(fp0);
11670 break;
11671 case OPC_CVT_D_S:
11672 check_cp1_registers(ctx, fd);
11674 TCGv_i32 fp32 = tcg_temp_new_i32();
11675 TCGv_i64 fp64 = tcg_temp_new_i64();
11677 gen_load_fpr32(ctx, fp32, fs);
11678 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11679 tcg_temp_free_i32(fp32);
11680 gen_store_fpr64(ctx, fp64, fd);
11681 tcg_temp_free_i64(fp64);
11683 break;
11684 case OPC_CVT_W_S:
11686 TCGv_i32 fp0 = tcg_temp_new_i32();
11688 gen_load_fpr32(ctx, fp0, fs);
11689 if (ctx->nan2008) {
11690 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11691 } else {
11692 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11694 gen_store_fpr32(ctx, fp0, fd);
11695 tcg_temp_free_i32(fp0);
11697 break;
11698 case OPC_CVT_L_S:
11699 check_cp1_64bitmode(ctx);
11701 TCGv_i32 fp32 = tcg_temp_new_i32();
11702 TCGv_i64 fp64 = tcg_temp_new_i64();
11704 gen_load_fpr32(ctx, fp32, fs);
11705 if (ctx->nan2008) {
11706 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11707 } else {
11708 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11710 tcg_temp_free_i32(fp32);
11711 gen_store_fpr64(ctx, fp64, fd);
11712 tcg_temp_free_i64(fp64);
11714 break;
11715 case OPC_CVT_PS_S:
11716 check_ps(ctx);
11718 TCGv_i64 fp64 = tcg_temp_new_i64();
11719 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11720 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11722 gen_load_fpr32(ctx, fp32_0, fs);
11723 gen_load_fpr32(ctx, fp32_1, ft);
11724 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11725 tcg_temp_free_i32(fp32_1);
11726 tcg_temp_free_i32(fp32_0);
11727 gen_store_fpr64(ctx, fp64, fd);
11728 tcg_temp_free_i64(fp64);
11730 break;
11731 case OPC_CMP_F_S:
11732 case OPC_CMP_UN_S:
11733 case OPC_CMP_EQ_S:
11734 case OPC_CMP_UEQ_S:
11735 case OPC_CMP_OLT_S:
11736 case OPC_CMP_ULT_S:
11737 case OPC_CMP_OLE_S:
11738 case OPC_CMP_ULE_S:
11739 case OPC_CMP_SF_S:
11740 case OPC_CMP_NGLE_S:
11741 case OPC_CMP_SEQ_S:
11742 case OPC_CMP_NGL_S:
11743 case OPC_CMP_LT_S:
11744 case OPC_CMP_NGE_S:
11745 case OPC_CMP_LE_S:
11746 case OPC_CMP_NGT_S:
11747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11748 if (ctx->opcode & (1 << 6)) {
11749 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11750 } else {
11751 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11753 break;
11754 case OPC_ADD_D:
11755 check_cp1_registers(ctx, fs | ft | fd);
11757 TCGv_i64 fp0 = tcg_temp_new_i64();
11758 TCGv_i64 fp1 = tcg_temp_new_i64();
11760 gen_load_fpr64(ctx, fp0, fs);
11761 gen_load_fpr64(ctx, fp1, ft);
11762 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11763 tcg_temp_free_i64(fp1);
11764 gen_store_fpr64(ctx, fp0, fd);
11765 tcg_temp_free_i64(fp0);
11767 break;
11768 case OPC_SUB_D:
11769 check_cp1_registers(ctx, fs | ft | fd);
11771 TCGv_i64 fp0 = tcg_temp_new_i64();
11772 TCGv_i64 fp1 = tcg_temp_new_i64();
11774 gen_load_fpr64(ctx, fp0, fs);
11775 gen_load_fpr64(ctx, fp1, ft);
11776 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11777 tcg_temp_free_i64(fp1);
11778 gen_store_fpr64(ctx, fp0, fd);
11779 tcg_temp_free_i64(fp0);
11781 break;
11782 case OPC_MUL_D:
11783 check_cp1_registers(ctx, fs | ft | fd);
11785 TCGv_i64 fp0 = tcg_temp_new_i64();
11786 TCGv_i64 fp1 = tcg_temp_new_i64();
11788 gen_load_fpr64(ctx, fp0, fs);
11789 gen_load_fpr64(ctx, fp1, ft);
11790 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11791 tcg_temp_free_i64(fp1);
11792 gen_store_fpr64(ctx, fp0, fd);
11793 tcg_temp_free_i64(fp0);
11795 break;
11796 case OPC_DIV_D:
11797 check_cp1_registers(ctx, fs | ft | fd);
11799 TCGv_i64 fp0 = tcg_temp_new_i64();
11800 TCGv_i64 fp1 = tcg_temp_new_i64();
11802 gen_load_fpr64(ctx, fp0, fs);
11803 gen_load_fpr64(ctx, fp1, ft);
11804 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11805 tcg_temp_free_i64(fp1);
11806 gen_store_fpr64(ctx, fp0, fd);
11807 tcg_temp_free_i64(fp0);
11809 break;
11810 case OPC_SQRT_D:
11811 check_cp1_registers(ctx, fs | fd);
11813 TCGv_i64 fp0 = tcg_temp_new_i64();
11815 gen_load_fpr64(ctx, fp0, fs);
11816 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11817 gen_store_fpr64(ctx, fp0, fd);
11818 tcg_temp_free_i64(fp0);
11820 break;
11821 case OPC_ABS_D:
11822 check_cp1_registers(ctx, fs | fd);
11824 TCGv_i64 fp0 = tcg_temp_new_i64();
11826 gen_load_fpr64(ctx, fp0, fs);
11827 if (ctx->abs2008) {
11828 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11829 } else {
11830 gen_helper_float_abs_d(fp0, fp0);
11832 gen_store_fpr64(ctx, fp0, fd);
11833 tcg_temp_free_i64(fp0);
11835 break;
11836 case OPC_MOV_D:
11837 check_cp1_registers(ctx, fs | fd);
11839 TCGv_i64 fp0 = tcg_temp_new_i64();
11841 gen_load_fpr64(ctx, fp0, fs);
11842 gen_store_fpr64(ctx, fp0, fd);
11843 tcg_temp_free_i64(fp0);
11845 break;
11846 case OPC_NEG_D:
11847 check_cp1_registers(ctx, fs | fd);
11849 TCGv_i64 fp0 = tcg_temp_new_i64();
11851 gen_load_fpr64(ctx, fp0, fs);
11852 if (ctx->abs2008) {
11853 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11854 } else {
11855 gen_helper_float_chs_d(fp0, fp0);
11857 gen_store_fpr64(ctx, fp0, fd);
11858 tcg_temp_free_i64(fp0);
11860 break;
11861 case OPC_ROUND_L_D:
11862 check_cp1_64bitmode(ctx);
11864 TCGv_i64 fp0 = tcg_temp_new_i64();
11866 gen_load_fpr64(ctx, fp0, fs);
11867 if (ctx->nan2008) {
11868 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11869 } else {
11870 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11872 gen_store_fpr64(ctx, fp0, fd);
11873 tcg_temp_free_i64(fp0);
11875 break;
11876 case OPC_TRUNC_L_D:
11877 check_cp1_64bitmode(ctx);
11879 TCGv_i64 fp0 = tcg_temp_new_i64();
11881 gen_load_fpr64(ctx, fp0, fs);
11882 if (ctx->nan2008) {
11883 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11884 } else {
11885 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11887 gen_store_fpr64(ctx, fp0, fd);
11888 tcg_temp_free_i64(fp0);
11890 break;
11891 case OPC_CEIL_L_D:
11892 check_cp1_64bitmode(ctx);
11894 TCGv_i64 fp0 = tcg_temp_new_i64();
11896 gen_load_fpr64(ctx, fp0, fs);
11897 if (ctx->nan2008) {
11898 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11899 } else {
11900 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11902 gen_store_fpr64(ctx, fp0, fd);
11903 tcg_temp_free_i64(fp0);
11905 break;
11906 case OPC_FLOOR_L_D:
11907 check_cp1_64bitmode(ctx);
11909 TCGv_i64 fp0 = tcg_temp_new_i64();
11911 gen_load_fpr64(ctx, fp0, fs);
11912 if (ctx->nan2008) {
11913 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11914 } else {
11915 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11917 gen_store_fpr64(ctx, fp0, fd);
11918 tcg_temp_free_i64(fp0);
11920 break;
11921 case OPC_ROUND_W_D:
11922 check_cp1_registers(ctx, fs);
11924 TCGv_i32 fp32 = tcg_temp_new_i32();
11925 TCGv_i64 fp64 = tcg_temp_new_i64();
11927 gen_load_fpr64(ctx, fp64, fs);
11928 if (ctx->nan2008) {
11929 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11930 } else {
11931 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11933 tcg_temp_free_i64(fp64);
11934 gen_store_fpr32(ctx, fp32, fd);
11935 tcg_temp_free_i32(fp32);
11937 break;
11938 case OPC_TRUNC_W_D:
11939 check_cp1_registers(ctx, fs);
11941 TCGv_i32 fp32 = tcg_temp_new_i32();
11942 TCGv_i64 fp64 = tcg_temp_new_i64();
11944 gen_load_fpr64(ctx, fp64, fs);
11945 if (ctx->nan2008) {
11946 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11947 } else {
11948 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11950 tcg_temp_free_i64(fp64);
11951 gen_store_fpr32(ctx, fp32, fd);
11952 tcg_temp_free_i32(fp32);
11954 break;
11955 case OPC_CEIL_W_D:
11956 check_cp1_registers(ctx, fs);
11958 TCGv_i32 fp32 = tcg_temp_new_i32();
11959 TCGv_i64 fp64 = tcg_temp_new_i64();
11961 gen_load_fpr64(ctx, fp64, fs);
11962 if (ctx->nan2008) {
11963 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11964 } else {
11965 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11967 tcg_temp_free_i64(fp64);
11968 gen_store_fpr32(ctx, fp32, fd);
11969 tcg_temp_free_i32(fp32);
11971 break;
11972 case OPC_FLOOR_W_D:
11973 check_cp1_registers(ctx, fs);
11975 TCGv_i32 fp32 = tcg_temp_new_i32();
11976 TCGv_i64 fp64 = tcg_temp_new_i64();
11978 gen_load_fpr64(ctx, fp64, fs);
11979 if (ctx->nan2008) {
11980 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11981 } else {
11982 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11984 tcg_temp_free_i64(fp64);
11985 gen_store_fpr32(ctx, fp32, fd);
11986 tcg_temp_free_i32(fp32);
11988 break;
11989 case OPC_SEL_D:
11990 check_insn(ctx, ISA_MIPS32R6);
11991 gen_sel_d(ctx, op1, fd, ft, fs);
11992 break;
11993 case OPC_SELEQZ_D:
11994 check_insn(ctx, ISA_MIPS32R6);
11995 gen_sel_d(ctx, op1, fd, ft, fs);
11996 break;
11997 case OPC_SELNEZ_D:
11998 check_insn(ctx, ISA_MIPS32R6);
11999 gen_sel_d(ctx, op1, fd, ft, fs);
12000 break;
12001 case OPC_MOVCF_D:
12002 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12003 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12004 break;
12005 case OPC_MOVZ_D:
12006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12008 TCGLabel *l1 = gen_new_label();
12009 TCGv_i64 fp0;
12011 if (ft != 0) {
12012 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12014 fp0 = tcg_temp_new_i64();
12015 gen_load_fpr64(ctx, fp0, fs);
12016 gen_store_fpr64(ctx, fp0, fd);
12017 tcg_temp_free_i64(fp0);
12018 gen_set_label(l1);
12020 break;
12021 case OPC_MOVN_D:
12022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12024 TCGLabel *l1 = gen_new_label();
12025 TCGv_i64 fp0;
12027 if (ft != 0) {
12028 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12029 fp0 = tcg_temp_new_i64();
12030 gen_load_fpr64(ctx, fp0, fs);
12031 gen_store_fpr64(ctx, fp0, fd);
12032 tcg_temp_free_i64(fp0);
12033 gen_set_label(l1);
12036 break;
12037 case OPC_RECIP_D:
12038 check_cp1_registers(ctx, fs | fd);
12040 TCGv_i64 fp0 = tcg_temp_new_i64();
12042 gen_load_fpr64(ctx, fp0, fs);
12043 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12044 gen_store_fpr64(ctx, fp0, fd);
12045 tcg_temp_free_i64(fp0);
12047 break;
12048 case OPC_RSQRT_D:
12049 check_cp1_registers(ctx, fs | fd);
12051 TCGv_i64 fp0 = tcg_temp_new_i64();
12053 gen_load_fpr64(ctx, fp0, fs);
12054 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12055 gen_store_fpr64(ctx, fp0, fd);
12056 tcg_temp_free_i64(fp0);
12058 break;
12059 case OPC_MADDF_D:
12060 check_insn(ctx, ISA_MIPS32R6);
12062 TCGv_i64 fp0 = tcg_temp_new_i64();
12063 TCGv_i64 fp1 = tcg_temp_new_i64();
12064 TCGv_i64 fp2 = tcg_temp_new_i64();
12065 gen_load_fpr64(ctx, fp0, fs);
12066 gen_load_fpr64(ctx, fp1, ft);
12067 gen_load_fpr64(ctx, fp2, fd);
12068 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12069 gen_store_fpr64(ctx, fp2, fd);
12070 tcg_temp_free_i64(fp2);
12071 tcg_temp_free_i64(fp1);
12072 tcg_temp_free_i64(fp0);
12074 break;
12075 case OPC_MSUBF_D:
12076 check_insn(ctx, ISA_MIPS32R6);
12078 TCGv_i64 fp0 = tcg_temp_new_i64();
12079 TCGv_i64 fp1 = tcg_temp_new_i64();
12080 TCGv_i64 fp2 = tcg_temp_new_i64();
12081 gen_load_fpr64(ctx, fp0, fs);
12082 gen_load_fpr64(ctx, fp1, ft);
12083 gen_load_fpr64(ctx, fp2, fd);
12084 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12085 gen_store_fpr64(ctx, fp2, fd);
12086 tcg_temp_free_i64(fp2);
12087 tcg_temp_free_i64(fp1);
12088 tcg_temp_free_i64(fp0);
12090 break;
12091 case OPC_RINT_D:
12092 check_insn(ctx, ISA_MIPS32R6);
12094 TCGv_i64 fp0 = tcg_temp_new_i64();
12095 gen_load_fpr64(ctx, fp0, fs);
12096 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12097 gen_store_fpr64(ctx, fp0, fd);
12098 tcg_temp_free_i64(fp0);
12100 break;
12101 case OPC_CLASS_D:
12102 check_insn(ctx, ISA_MIPS32R6);
12104 TCGv_i64 fp0 = tcg_temp_new_i64();
12105 gen_load_fpr64(ctx, fp0, fs);
12106 gen_helper_float_class_d(fp0, cpu_env, fp0);
12107 gen_store_fpr64(ctx, fp0, fd);
12108 tcg_temp_free_i64(fp0);
12110 break;
12111 case OPC_MIN_D: /* OPC_RECIP2_D */
12112 if (ctx->insn_flags & ISA_MIPS32R6) {
12113 /* OPC_MIN_D */
12114 TCGv_i64 fp0 = tcg_temp_new_i64();
12115 TCGv_i64 fp1 = tcg_temp_new_i64();
12116 gen_load_fpr64(ctx, fp0, fs);
12117 gen_load_fpr64(ctx, fp1, ft);
12118 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12119 gen_store_fpr64(ctx, fp1, fd);
12120 tcg_temp_free_i64(fp1);
12121 tcg_temp_free_i64(fp0);
12122 } else {
12123 /* OPC_RECIP2_D */
12124 check_cp1_64bitmode(ctx);
12126 TCGv_i64 fp0 = tcg_temp_new_i64();
12127 TCGv_i64 fp1 = tcg_temp_new_i64();
12129 gen_load_fpr64(ctx, fp0, fs);
12130 gen_load_fpr64(ctx, fp1, ft);
12131 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12132 tcg_temp_free_i64(fp1);
12133 gen_store_fpr64(ctx, fp0, fd);
12134 tcg_temp_free_i64(fp0);
12137 break;
12138 case OPC_MINA_D: /* OPC_RECIP1_D */
12139 if (ctx->insn_flags & ISA_MIPS32R6) {
12140 /* OPC_MINA_D */
12141 TCGv_i64 fp0 = tcg_temp_new_i64();
12142 TCGv_i64 fp1 = tcg_temp_new_i64();
12143 gen_load_fpr64(ctx, fp0, fs);
12144 gen_load_fpr64(ctx, fp1, ft);
12145 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12146 gen_store_fpr64(ctx, fp1, fd);
12147 tcg_temp_free_i64(fp1);
12148 tcg_temp_free_i64(fp0);
12149 } else {
12150 /* OPC_RECIP1_D */
12151 check_cp1_64bitmode(ctx);
12153 TCGv_i64 fp0 = tcg_temp_new_i64();
12155 gen_load_fpr64(ctx, fp0, fs);
12156 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12157 gen_store_fpr64(ctx, fp0, fd);
12158 tcg_temp_free_i64(fp0);
12161 break;
12162 case OPC_MAX_D: /* OPC_RSQRT1_D */
12163 if (ctx->insn_flags & ISA_MIPS32R6) {
12164 /* OPC_MAX_D */
12165 TCGv_i64 fp0 = tcg_temp_new_i64();
12166 TCGv_i64 fp1 = tcg_temp_new_i64();
12167 gen_load_fpr64(ctx, fp0, fs);
12168 gen_load_fpr64(ctx, fp1, ft);
12169 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12170 gen_store_fpr64(ctx, fp1, fd);
12171 tcg_temp_free_i64(fp1);
12172 tcg_temp_free_i64(fp0);
12173 } else {
12174 /* OPC_RSQRT1_D */
12175 check_cp1_64bitmode(ctx);
12177 TCGv_i64 fp0 = tcg_temp_new_i64();
12179 gen_load_fpr64(ctx, fp0, fs);
12180 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12181 gen_store_fpr64(ctx, fp0, fd);
12182 tcg_temp_free_i64(fp0);
12185 break;
12186 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12187 if (ctx->insn_flags & ISA_MIPS32R6) {
12188 /* OPC_MAXA_D */
12189 TCGv_i64 fp0 = tcg_temp_new_i64();
12190 TCGv_i64 fp1 = tcg_temp_new_i64();
12191 gen_load_fpr64(ctx, fp0, fs);
12192 gen_load_fpr64(ctx, fp1, ft);
12193 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12194 gen_store_fpr64(ctx, fp1, fd);
12195 tcg_temp_free_i64(fp1);
12196 tcg_temp_free_i64(fp0);
12197 } else {
12198 /* OPC_RSQRT2_D */
12199 check_cp1_64bitmode(ctx);
12201 TCGv_i64 fp0 = tcg_temp_new_i64();
12202 TCGv_i64 fp1 = tcg_temp_new_i64();
12204 gen_load_fpr64(ctx, fp0, fs);
12205 gen_load_fpr64(ctx, fp1, ft);
12206 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12207 tcg_temp_free_i64(fp1);
12208 gen_store_fpr64(ctx, fp0, fd);
12209 tcg_temp_free_i64(fp0);
12212 break;
12213 case OPC_CMP_F_D:
12214 case OPC_CMP_UN_D:
12215 case OPC_CMP_EQ_D:
12216 case OPC_CMP_UEQ_D:
12217 case OPC_CMP_OLT_D:
12218 case OPC_CMP_ULT_D:
12219 case OPC_CMP_OLE_D:
12220 case OPC_CMP_ULE_D:
12221 case OPC_CMP_SF_D:
12222 case OPC_CMP_NGLE_D:
12223 case OPC_CMP_SEQ_D:
12224 case OPC_CMP_NGL_D:
12225 case OPC_CMP_LT_D:
12226 case OPC_CMP_NGE_D:
12227 case OPC_CMP_LE_D:
12228 case OPC_CMP_NGT_D:
12229 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12230 if (ctx->opcode & (1 << 6)) {
12231 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12232 } else {
12233 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12235 break;
12236 case OPC_CVT_S_D:
12237 check_cp1_registers(ctx, fs);
12239 TCGv_i32 fp32 = tcg_temp_new_i32();
12240 TCGv_i64 fp64 = tcg_temp_new_i64();
12242 gen_load_fpr64(ctx, fp64, fs);
12243 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12244 tcg_temp_free_i64(fp64);
12245 gen_store_fpr32(ctx, fp32, fd);
12246 tcg_temp_free_i32(fp32);
12248 break;
12249 case OPC_CVT_W_D:
12250 check_cp1_registers(ctx, fs);
12252 TCGv_i32 fp32 = tcg_temp_new_i32();
12253 TCGv_i64 fp64 = tcg_temp_new_i64();
12255 gen_load_fpr64(ctx, fp64, fs);
12256 if (ctx->nan2008) {
12257 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12258 } else {
12259 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12261 tcg_temp_free_i64(fp64);
12262 gen_store_fpr32(ctx, fp32, fd);
12263 tcg_temp_free_i32(fp32);
12265 break;
12266 case OPC_CVT_L_D:
12267 check_cp1_64bitmode(ctx);
12269 TCGv_i64 fp0 = tcg_temp_new_i64();
12271 gen_load_fpr64(ctx, fp0, fs);
12272 if (ctx->nan2008) {
12273 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12274 } else {
12275 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12277 gen_store_fpr64(ctx, fp0, fd);
12278 tcg_temp_free_i64(fp0);
12280 break;
12281 case OPC_CVT_S_W:
12283 TCGv_i32 fp0 = tcg_temp_new_i32();
12285 gen_load_fpr32(ctx, fp0, fs);
12286 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12287 gen_store_fpr32(ctx, fp0, fd);
12288 tcg_temp_free_i32(fp0);
12290 break;
12291 case OPC_CVT_D_W:
12292 check_cp1_registers(ctx, fd);
12294 TCGv_i32 fp32 = tcg_temp_new_i32();
12295 TCGv_i64 fp64 = tcg_temp_new_i64();
12297 gen_load_fpr32(ctx, fp32, fs);
12298 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12299 tcg_temp_free_i32(fp32);
12300 gen_store_fpr64(ctx, fp64, fd);
12301 tcg_temp_free_i64(fp64);
12303 break;
12304 case OPC_CVT_S_L:
12305 check_cp1_64bitmode(ctx);
12307 TCGv_i32 fp32 = tcg_temp_new_i32();
12308 TCGv_i64 fp64 = tcg_temp_new_i64();
12310 gen_load_fpr64(ctx, fp64, fs);
12311 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12312 tcg_temp_free_i64(fp64);
12313 gen_store_fpr32(ctx, fp32, fd);
12314 tcg_temp_free_i32(fp32);
12316 break;
12317 case OPC_CVT_D_L:
12318 check_cp1_64bitmode(ctx);
12320 TCGv_i64 fp0 = tcg_temp_new_i64();
12322 gen_load_fpr64(ctx, fp0, fs);
12323 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12324 gen_store_fpr64(ctx, fp0, fd);
12325 tcg_temp_free_i64(fp0);
12327 break;
12328 case OPC_CVT_PS_PW:
12329 check_ps(ctx);
12331 TCGv_i64 fp0 = tcg_temp_new_i64();
12333 gen_load_fpr64(ctx, fp0, fs);
12334 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12335 gen_store_fpr64(ctx, fp0, fd);
12336 tcg_temp_free_i64(fp0);
12338 break;
12339 case OPC_ADD_PS:
12340 check_ps(ctx);
12342 TCGv_i64 fp0 = tcg_temp_new_i64();
12343 TCGv_i64 fp1 = tcg_temp_new_i64();
12345 gen_load_fpr64(ctx, fp0, fs);
12346 gen_load_fpr64(ctx, fp1, ft);
12347 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12348 tcg_temp_free_i64(fp1);
12349 gen_store_fpr64(ctx, fp0, fd);
12350 tcg_temp_free_i64(fp0);
12352 break;
12353 case OPC_SUB_PS:
12354 check_ps(ctx);
12356 TCGv_i64 fp0 = tcg_temp_new_i64();
12357 TCGv_i64 fp1 = tcg_temp_new_i64();
12359 gen_load_fpr64(ctx, fp0, fs);
12360 gen_load_fpr64(ctx, fp1, ft);
12361 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12362 tcg_temp_free_i64(fp1);
12363 gen_store_fpr64(ctx, fp0, fd);
12364 tcg_temp_free_i64(fp0);
12366 break;
12367 case OPC_MUL_PS:
12368 check_ps(ctx);
12370 TCGv_i64 fp0 = tcg_temp_new_i64();
12371 TCGv_i64 fp1 = tcg_temp_new_i64();
12373 gen_load_fpr64(ctx, fp0, fs);
12374 gen_load_fpr64(ctx, fp1, ft);
12375 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12376 tcg_temp_free_i64(fp1);
12377 gen_store_fpr64(ctx, fp0, fd);
12378 tcg_temp_free_i64(fp0);
12380 break;
12381 case OPC_ABS_PS:
12382 check_ps(ctx);
12384 TCGv_i64 fp0 = tcg_temp_new_i64();
12386 gen_load_fpr64(ctx, fp0, fs);
12387 gen_helper_float_abs_ps(fp0, fp0);
12388 gen_store_fpr64(ctx, fp0, fd);
12389 tcg_temp_free_i64(fp0);
12391 break;
12392 case OPC_MOV_PS:
12393 check_ps(ctx);
12395 TCGv_i64 fp0 = tcg_temp_new_i64();
12397 gen_load_fpr64(ctx, fp0, fs);
12398 gen_store_fpr64(ctx, fp0, fd);
12399 tcg_temp_free_i64(fp0);
12401 break;
12402 case OPC_NEG_PS:
12403 check_ps(ctx);
12405 TCGv_i64 fp0 = tcg_temp_new_i64();
12407 gen_load_fpr64(ctx, fp0, fs);
12408 gen_helper_float_chs_ps(fp0, fp0);
12409 gen_store_fpr64(ctx, fp0, fd);
12410 tcg_temp_free_i64(fp0);
12412 break;
12413 case OPC_MOVCF_PS:
12414 check_ps(ctx);
12415 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12416 break;
12417 case OPC_MOVZ_PS:
12418 check_ps(ctx);
12420 TCGLabel *l1 = gen_new_label();
12421 TCGv_i64 fp0;
12423 if (ft != 0) {
12424 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12426 fp0 = tcg_temp_new_i64();
12427 gen_load_fpr64(ctx, fp0, fs);
12428 gen_store_fpr64(ctx, fp0, fd);
12429 tcg_temp_free_i64(fp0);
12430 gen_set_label(l1);
12432 break;
12433 case OPC_MOVN_PS:
12434 check_ps(ctx);
12436 TCGLabel *l1 = gen_new_label();
12437 TCGv_i64 fp0;
12439 if (ft != 0) {
12440 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12441 fp0 = tcg_temp_new_i64();
12442 gen_load_fpr64(ctx, fp0, fs);
12443 gen_store_fpr64(ctx, fp0, fd);
12444 tcg_temp_free_i64(fp0);
12445 gen_set_label(l1);
12448 break;
12449 case OPC_ADDR_PS:
12450 check_ps(ctx);
12452 TCGv_i64 fp0 = tcg_temp_new_i64();
12453 TCGv_i64 fp1 = tcg_temp_new_i64();
12455 gen_load_fpr64(ctx, fp0, ft);
12456 gen_load_fpr64(ctx, fp1, fs);
12457 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12458 tcg_temp_free_i64(fp1);
12459 gen_store_fpr64(ctx, fp0, fd);
12460 tcg_temp_free_i64(fp0);
12462 break;
12463 case OPC_MULR_PS:
12464 check_ps(ctx);
12466 TCGv_i64 fp0 = tcg_temp_new_i64();
12467 TCGv_i64 fp1 = tcg_temp_new_i64();
12469 gen_load_fpr64(ctx, fp0, ft);
12470 gen_load_fpr64(ctx, fp1, fs);
12471 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12472 tcg_temp_free_i64(fp1);
12473 gen_store_fpr64(ctx, fp0, fd);
12474 tcg_temp_free_i64(fp0);
12476 break;
12477 case OPC_RECIP2_PS:
12478 check_ps(ctx);
12480 TCGv_i64 fp0 = tcg_temp_new_i64();
12481 TCGv_i64 fp1 = tcg_temp_new_i64();
12483 gen_load_fpr64(ctx, fp0, fs);
12484 gen_load_fpr64(ctx, fp1, ft);
12485 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12486 tcg_temp_free_i64(fp1);
12487 gen_store_fpr64(ctx, fp0, fd);
12488 tcg_temp_free_i64(fp0);
12490 break;
12491 case OPC_RECIP1_PS:
12492 check_ps(ctx);
12494 TCGv_i64 fp0 = tcg_temp_new_i64();
12496 gen_load_fpr64(ctx, fp0, fs);
12497 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12498 gen_store_fpr64(ctx, fp0, fd);
12499 tcg_temp_free_i64(fp0);
12501 break;
12502 case OPC_RSQRT1_PS:
12503 check_ps(ctx);
12505 TCGv_i64 fp0 = tcg_temp_new_i64();
12507 gen_load_fpr64(ctx, fp0, fs);
12508 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12509 gen_store_fpr64(ctx, fp0, fd);
12510 tcg_temp_free_i64(fp0);
12512 break;
12513 case OPC_RSQRT2_PS:
12514 check_ps(ctx);
12516 TCGv_i64 fp0 = tcg_temp_new_i64();
12517 TCGv_i64 fp1 = tcg_temp_new_i64();
12519 gen_load_fpr64(ctx, fp0, fs);
12520 gen_load_fpr64(ctx, fp1, ft);
12521 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12522 tcg_temp_free_i64(fp1);
12523 gen_store_fpr64(ctx, fp0, fd);
12524 tcg_temp_free_i64(fp0);
12526 break;
12527 case OPC_CVT_S_PU:
12528 check_cp1_64bitmode(ctx);
12530 TCGv_i32 fp0 = tcg_temp_new_i32();
12532 gen_load_fpr32h(ctx, fp0, fs);
12533 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12534 gen_store_fpr32(ctx, fp0, fd);
12535 tcg_temp_free_i32(fp0);
12537 break;
12538 case OPC_CVT_PW_PS:
12539 check_ps(ctx);
12541 TCGv_i64 fp0 = tcg_temp_new_i64();
12543 gen_load_fpr64(ctx, fp0, fs);
12544 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12545 gen_store_fpr64(ctx, fp0, fd);
12546 tcg_temp_free_i64(fp0);
12548 break;
12549 case OPC_CVT_S_PL:
12550 check_cp1_64bitmode(ctx);
12552 TCGv_i32 fp0 = tcg_temp_new_i32();
12554 gen_load_fpr32(ctx, fp0, fs);
12555 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12556 gen_store_fpr32(ctx, fp0, fd);
12557 tcg_temp_free_i32(fp0);
12559 break;
12560 case OPC_PLL_PS:
12561 check_ps(ctx);
12563 TCGv_i32 fp0 = tcg_temp_new_i32();
12564 TCGv_i32 fp1 = tcg_temp_new_i32();
12566 gen_load_fpr32(ctx, fp0, fs);
12567 gen_load_fpr32(ctx, fp1, ft);
12568 gen_store_fpr32h(ctx, fp0, fd);
12569 gen_store_fpr32(ctx, fp1, fd);
12570 tcg_temp_free_i32(fp0);
12571 tcg_temp_free_i32(fp1);
12573 break;
12574 case OPC_PLU_PS:
12575 check_ps(ctx);
12577 TCGv_i32 fp0 = tcg_temp_new_i32();
12578 TCGv_i32 fp1 = tcg_temp_new_i32();
12580 gen_load_fpr32(ctx, fp0, fs);
12581 gen_load_fpr32h(ctx, fp1, ft);
12582 gen_store_fpr32(ctx, fp1, fd);
12583 gen_store_fpr32h(ctx, fp0, fd);
12584 tcg_temp_free_i32(fp0);
12585 tcg_temp_free_i32(fp1);
12587 break;
12588 case OPC_PUL_PS:
12589 check_ps(ctx);
12591 TCGv_i32 fp0 = tcg_temp_new_i32();
12592 TCGv_i32 fp1 = tcg_temp_new_i32();
12594 gen_load_fpr32h(ctx, fp0, fs);
12595 gen_load_fpr32(ctx, fp1, ft);
12596 gen_store_fpr32(ctx, fp1, fd);
12597 gen_store_fpr32h(ctx, fp0, fd);
12598 tcg_temp_free_i32(fp0);
12599 tcg_temp_free_i32(fp1);
12601 break;
12602 case OPC_PUU_PS:
12603 check_ps(ctx);
12605 TCGv_i32 fp0 = tcg_temp_new_i32();
12606 TCGv_i32 fp1 = tcg_temp_new_i32();
12608 gen_load_fpr32h(ctx, fp0, fs);
12609 gen_load_fpr32h(ctx, fp1, ft);
12610 gen_store_fpr32(ctx, fp1, fd);
12611 gen_store_fpr32h(ctx, fp0, fd);
12612 tcg_temp_free_i32(fp0);
12613 tcg_temp_free_i32(fp1);
12615 break;
12616 case OPC_CMP_F_PS:
12617 case OPC_CMP_UN_PS:
12618 case OPC_CMP_EQ_PS:
12619 case OPC_CMP_UEQ_PS:
12620 case OPC_CMP_OLT_PS:
12621 case OPC_CMP_ULT_PS:
12622 case OPC_CMP_OLE_PS:
12623 case OPC_CMP_ULE_PS:
12624 case OPC_CMP_SF_PS:
12625 case OPC_CMP_NGLE_PS:
12626 case OPC_CMP_SEQ_PS:
12627 case OPC_CMP_NGL_PS:
12628 case OPC_CMP_LT_PS:
12629 case OPC_CMP_NGE_PS:
12630 case OPC_CMP_LE_PS:
12631 case OPC_CMP_NGT_PS:
12632 if (ctx->opcode & (1 << 6)) {
12633 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12634 } else {
12635 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12637 break;
12638 default:
12639 MIPS_INVAL("farith");
12640 generate_exception_end(ctx, EXCP_RI);
12641 return;
12645 /* Coprocessor 3 (FPU) */
12646 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12647 int fd, int fs, int base, int index)
12649 TCGv t0 = tcg_temp_new();
12651 if (base == 0) {
12652 gen_load_gpr(t0, index);
12653 } else if (index == 0) {
12654 gen_load_gpr(t0, base);
12655 } else {
12656 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12659 * Don't do NOP if destination is zero: we must perform the actual
12660 * memory access.
12662 switch (opc) {
12663 case OPC_LWXC1:
12664 check_cop1x(ctx);
12666 TCGv_i32 fp0 = tcg_temp_new_i32();
12668 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12669 tcg_gen_trunc_tl_i32(fp0, t0);
12670 gen_store_fpr32(ctx, fp0, fd);
12671 tcg_temp_free_i32(fp0);
12673 break;
12674 case OPC_LDXC1:
12675 check_cop1x(ctx);
12676 check_cp1_registers(ctx, fd);
12678 TCGv_i64 fp0 = tcg_temp_new_i64();
12679 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12680 gen_store_fpr64(ctx, fp0, fd);
12681 tcg_temp_free_i64(fp0);
12683 break;
12684 case OPC_LUXC1:
12685 check_cp1_64bitmode(ctx);
12686 tcg_gen_andi_tl(t0, t0, ~0x7);
12688 TCGv_i64 fp0 = tcg_temp_new_i64();
12690 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12691 gen_store_fpr64(ctx, fp0, fd);
12692 tcg_temp_free_i64(fp0);
12694 break;
12695 case OPC_SWXC1:
12696 check_cop1x(ctx);
12698 TCGv_i32 fp0 = tcg_temp_new_i32();
12699 gen_load_fpr32(ctx, fp0, fs);
12700 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12701 tcg_temp_free_i32(fp0);
12703 break;
12704 case OPC_SDXC1:
12705 check_cop1x(ctx);
12706 check_cp1_registers(ctx, fs);
12708 TCGv_i64 fp0 = tcg_temp_new_i64();
12709 gen_load_fpr64(ctx, fp0, fs);
12710 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12711 tcg_temp_free_i64(fp0);
12713 break;
12714 case OPC_SUXC1:
12715 check_cp1_64bitmode(ctx);
12716 tcg_gen_andi_tl(t0, t0, ~0x7);
12718 TCGv_i64 fp0 = tcg_temp_new_i64();
12719 gen_load_fpr64(ctx, fp0, fs);
12720 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12721 tcg_temp_free_i64(fp0);
12723 break;
12725 tcg_temp_free(t0);
12728 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12729 int fd, int fr, int fs, int ft)
12731 switch (opc) {
12732 case OPC_ALNV_PS:
12733 check_ps(ctx);
12735 TCGv t0 = tcg_temp_local_new();
12736 TCGv_i32 fp = tcg_temp_new_i32();
12737 TCGv_i32 fph = tcg_temp_new_i32();
12738 TCGLabel *l1 = gen_new_label();
12739 TCGLabel *l2 = gen_new_label();
12741 gen_load_gpr(t0, fr);
12742 tcg_gen_andi_tl(t0, t0, 0x7);
12744 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12745 gen_load_fpr32(ctx, fp, fs);
12746 gen_load_fpr32h(ctx, fph, fs);
12747 gen_store_fpr32(ctx, fp, fd);
12748 gen_store_fpr32h(ctx, fph, fd);
12749 tcg_gen_br(l2);
12750 gen_set_label(l1);
12751 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12752 tcg_temp_free(t0);
12753 #ifdef TARGET_WORDS_BIGENDIAN
12754 gen_load_fpr32(ctx, fp, fs);
12755 gen_load_fpr32h(ctx, fph, ft);
12756 gen_store_fpr32h(ctx, fp, fd);
12757 gen_store_fpr32(ctx, fph, fd);
12758 #else
12759 gen_load_fpr32h(ctx, fph, fs);
12760 gen_load_fpr32(ctx, fp, ft);
12761 gen_store_fpr32(ctx, fph, fd);
12762 gen_store_fpr32h(ctx, fp, fd);
12763 #endif
12764 gen_set_label(l2);
12765 tcg_temp_free_i32(fp);
12766 tcg_temp_free_i32(fph);
12768 break;
12769 case OPC_MADD_S:
12770 check_cop1x(ctx);
12772 TCGv_i32 fp0 = tcg_temp_new_i32();
12773 TCGv_i32 fp1 = tcg_temp_new_i32();
12774 TCGv_i32 fp2 = tcg_temp_new_i32();
12776 gen_load_fpr32(ctx, fp0, fs);
12777 gen_load_fpr32(ctx, fp1, ft);
12778 gen_load_fpr32(ctx, fp2, fr);
12779 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12780 tcg_temp_free_i32(fp0);
12781 tcg_temp_free_i32(fp1);
12782 gen_store_fpr32(ctx, fp2, fd);
12783 tcg_temp_free_i32(fp2);
12785 break;
12786 case OPC_MADD_D:
12787 check_cop1x(ctx);
12788 check_cp1_registers(ctx, fd | fs | ft | fr);
12790 TCGv_i64 fp0 = tcg_temp_new_i64();
12791 TCGv_i64 fp1 = tcg_temp_new_i64();
12792 TCGv_i64 fp2 = tcg_temp_new_i64();
12794 gen_load_fpr64(ctx, fp0, fs);
12795 gen_load_fpr64(ctx, fp1, ft);
12796 gen_load_fpr64(ctx, fp2, fr);
12797 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12798 tcg_temp_free_i64(fp0);
12799 tcg_temp_free_i64(fp1);
12800 gen_store_fpr64(ctx, fp2, fd);
12801 tcg_temp_free_i64(fp2);
12803 break;
12804 case OPC_MADD_PS:
12805 check_ps(ctx);
12807 TCGv_i64 fp0 = tcg_temp_new_i64();
12808 TCGv_i64 fp1 = tcg_temp_new_i64();
12809 TCGv_i64 fp2 = tcg_temp_new_i64();
12811 gen_load_fpr64(ctx, fp0, fs);
12812 gen_load_fpr64(ctx, fp1, ft);
12813 gen_load_fpr64(ctx, fp2, fr);
12814 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12815 tcg_temp_free_i64(fp0);
12816 tcg_temp_free_i64(fp1);
12817 gen_store_fpr64(ctx, fp2, fd);
12818 tcg_temp_free_i64(fp2);
12820 break;
12821 case OPC_MSUB_S:
12822 check_cop1x(ctx);
12824 TCGv_i32 fp0 = tcg_temp_new_i32();
12825 TCGv_i32 fp1 = tcg_temp_new_i32();
12826 TCGv_i32 fp2 = tcg_temp_new_i32();
12828 gen_load_fpr32(ctx, fp0, fs);
12829 gen_load_fpr32(ctx, fp1, ft);
12830 gen_load_fpr32(ctx, fp2, fr);
12831 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12832 tcg_temp_free_i32(fp0);
12833 tcg_temp_free_i32(fp1);
12834 gen_store_fpr32(ctx, fp2, fd);
12835 tcg_temp_free_i32(fp2);
12837 break;
12838 case OPC_MSUB_D:
12839 check_cop1x(ctx);
12840 check_cp1_registers(ctx, fd | fs | ft | fr);
12842 TCGv_i64 fp0 = tcg_temp_new_i64();
12843 TCGv_i64 fp1 = tcg_temp_new_i64();
12844 TCGv_i64 fp2 = tcg_temp_new_i64();
12846 gen_load_fpr64(ctx, fp0, fs);
12847 gen_load_fpr64(ctx, fp1, ft);
12848 gen_load_fpr64(ctx, fp2, fr);
12849 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12850 tcg_temp_free_i64(fp0);
12851 tcg_temp_free_i64(fp1);
12852 gen_store_fpr64(ctx, fp2, fd);
12853 tcg_temp_free_i64(fp2);
12855 break;
12856 case OPC_MSUB_PS:
12857 check_ps(ctx);
12859 TCGv_i64 fp0 = tcg_temp_new_i64();
12860 TCGv_i64 fp1 = tcg_temp_new_i64();
12861 TCGv_i64 fp2 = tcg_temp_new_i64();
12863 gen_load_fpr64(ctx, fp0, fs);
12864 gen_load_fpr64(ctx, fp1, ft);
12865 gen_load_fpr64(ctx, fp2, fr);
12866 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12867 tcg_temp_free_i64(fp0);
12868 tcg_temp_free_i64(fp1);
12869 gen_store_fpr64(ctx, fp2, fd);
12870 tcg_temp_free_i64(fp2);
12872 break;
12873 case OPC_NMADD_S:
12874 check_cop1x(ctx);
12876 TCGv_i32 fp0 = tcg_temp_new_i32();
12877 TCGv_i32 fp1 = tcg_temp_new_i32();
12878 TCGv_i32 fp2 = tcg_temp_new_i32();
12880 gen_load_fpr32(ctx, fp0, fs);
12881 gen_load_fpr32(ctx, fp1, ft);
12882 gen_load_fpr32(ctx, fp2, fr);
12883 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12884 tcg_temp_free_i32(fp0);
12885 tcg_temp_free_i32(fp1);
12886 gen_store_fpr32(ctx, fp2, fd);
12887 tcg_temp_free_i32(fp2);
12889 break;
12890 case OPC_NMADD_D:
12891 check_cop1x(ctx);
12892 check_cp1_registers(ctx, fd | fs | ft | fr);
12894 TCGv_i64 fp0 = tcg_temp_new_i64();
12895 TCGv_i64 fp1 = tcg_temp_new_i64();
12896 TCGv_i64 fp2 = tcg_temp_new_i64();
12898 gen_load_fpr64(ctx, fp0, fs);
12899 gen_load_fpr64(ctx, fp1, ft);
12900 gen_load_fpr64(ctx, fp2, fr);
12901 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12902 tcg_temp_free_i64(fp0);
12903 tcg_temp_free_i64(fp1);
12904 gen_store_fpr64(ctx, fp2, fd);
12905 tcg_temp_free_i64(fp2);
12907 break;
12908 case OPC_NMADD_PS:
12909 check_ps(ctx);
12911 TCGv_i64 fp0 = tcg_temp_new_i64();
12912 TCGv_i64 fp1 = tcg_temp_new_i64();
12913 TCGv_i64 fp2 = tcg_temp_new_i64();
12915 gen_load_fpr64(ctx, fp0, fs);
12916 gen_load_fpr64(ctx, fp1, ft);
12917 gen_load_fpr64(ctx, fp2, fr);
12918 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12919 tcg_temp_free_i64(fp0);
12920 tcg_temp_free_i64(fp1);
12921 gen_store_fpr64(ctx, fp2, fd);
12922 tcg_temp_free_i64(fp2);
12924 break;
12925 case OPC_NMSUB_S:
12926 check_cop1x(ctx);
12928 TCGv_i32 fp0 = tcg_temp_new_i32();
12929 TCGv_i32 fp1 = tcg_temp_new_i32();
12930 TCGv_i32 fp2 = tcg_temp_new_i32();
12932 gen_load_fpr32(ctx, fp0, fs);
12933 gen_load_fpr32(ctx, fp1, ft);
12934 gen_load_fpr32(ctx, fp2, fr);
12935 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12936 tcg_temp_free_i32(fp0);
12937 tcg_temp_free_i32(fp1);
12938 gen_store_fpr32(ctx, fp2, fd);
12939 tcg_temp_free_i32(fp2);
12941 break;
12942 case OPC_NMSUB_D:
12943 check_cop1x(ctx);
12944 check_cp1_registers(ctx, fd | fs | ft | fr);
12946 TCGv_i64 fp0 = tcg_temp_new_i64();
12947 TCGv_i64 fp1 = tcg_temp_new_i64();
12948 TCGv_i64 fp2 = tcg_temp_new_i64();
12950 gen_load_fpr64(ctx, fp0, fs);
12951 gen_load_fpr64(ctx, fp1, ft);
12952 gen_load_fpr64(ctx, fp2, fr);
12953 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12954 tcg_temp_free_i64(fp0);
12955 tcg_temp_free_i64(fp1);
12956 gen_store_fpr64(ctx, fp2, fd);
12957 tcg_temp_free_i64(fp2);
12959 break;
12960 case OPC_NMSUB_PS:
12961 check_ps(ctx);
12963 TCGv_i64 fp0 = tcg_temp_new_i64();
12964 TCGv_i64 fp1 = tcg_temp_new_i64();
12965 TCGv_i64 fp2 = tcg_temp_new_i64();
12967 gen_load_fpr64(ctx, fp0, fs);
12968 gen_load_fpr64(ctx, fp1, ft);
12969 gen_load_fpr64(ctx, fp2, fr);
12970 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12971 tcg_temp_free_i64(fp0);
12972 tcg_temp_free_i64(fp1);
12973 gen_store_fpr64(ctx, fp2, fd);
12974 tcg_temp_free_i64(fp2);
12976 break;
12977 default:
12978 MIPS_INVAL("flt3_arith");
12979 generate_exception_end(ctx, EXCP_RI);
12980 return;
12984 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12986 TCGv t0;
12988 #if !defined(CONFIG_USER_ONLY)
12990 * The Linux kernel will emulate rdhwr if it's not supported natively.
12991 * Therefore only check the ISA in system mode.
12993 check_insn(ctx, ISA_MIPS32R2);
12994 #endif
12995 t0 = tcg_temp_new();
12997 switch (rd) {
12998 case 0:
12999 gen_helper_rdhwr_cpunum(t0, cpu_env);
13000 gen_store_gpr(t0, rt);
13001 break;
13002 case 1:
13003 gen_helper_rdhwr_synci_step(t0, cpu_env);
13004 gen_store_gpr(t0, rt);
13005 break;
13006 case 2:
13007 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13008 gen_io_start();
13010 gen_helper_rdhwr_cc(t0, cpu_env);
13011 gen_store_gpr(t0, rt);
13013 * Break the TB to be able to take timer interrupts immediately
13014 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13015 * we break completely out of translated code.
13017 gen_save_pc(ctx->base.pc_next + 4);
13018 ctx->base.is_jmp = DISAS_EXIT;
13019 break;
13020 case 3:
13021 gen_helper_rdhwr_ccres(t0, cpu_env);
13022 gen_store_gpr(t0, rt);
13023 break;
13024 case 4:
13025 check_insn(ctx, ISA_MIPS32R6);
13026 if (sel != 0) {
13028 * Performance counter registers are not implemented other than
13029 * control register 0.
13031 generate_exception(ctx, EXCP_RI);
13033 gen_helper_rdhwr_performance(t0, cpu_env);
13034 gen_store_gpr(t0, rt);
13035 break;
13036 case 5:
13037 check_insn(ctx, ISA_MIPS32R6);
13038 gen_helper_rdhwr_xnp(t0, cpu_env);
13039 gen_store_gpr(t0, rt);
13040 break;
13041 case 29:
13042 #if defined(CONFIG_USER_ONLY)
13043 tcg_gen_ld_tl(t0, cpu_env,
13044 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13045 gen_store_gpr(t0, rt);
13046 break;
13047 #else
13048 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13049 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13050 tcg_gen_ld_tl(t0, cpu_env,
13051 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13052 gen_store_gpr(t0, rt);
13053 } else {
13054 generate_exception_end(ctx, EXCP_RI);
13056 break;
13057 #endif
13058 default: /* Invalid */
13059 MIPS_INVAL("rdhwr");
13060 generate_exception_end(ctx, EXCP_RI);
13061 break;
13063 tcg_temp_free(t0);
13066 static inline void clear_branch_hflags(DisasContext *ctx)
13068 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13069 if (ctx->base.is_jmp == DISAS_NEXT) {
13070 save_cpu_state(ctx, 0);
13071 } else {
13073 * It is not safe to save ctx->hflags as hflags may be changed
13074 * in execution time by the instruction in delay / forbidden slot.
13076 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13080 static void gen_branch(DisasContext *ctx, int insn_bytes)
13082 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13083 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13084 /* Branches completion */
13085 clear_branch_hflags(ctx);
13086 ctx->base.is_jmp = DISAS_NORETURN;
13087 /* FIXME: Need to clear can_do_io. */
13088 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13089 case MIPS_HFLAG_FBNSLOT:
13090 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13091 break;
13092 case MIPS_HFLAG_B:
13093 /* unconditional branch */
13094 if (proc_hflags & MIPS_HFLAG_BX) {
13095 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13097 gen_goto_tb(ctx, 0, ctx->btarget);
13098 break;
13099 case MIPS_HFLAG_BL:
13100 /* blikely taken case */
13101 gen_goto_tb(ctx, 0, ctx->btarget);
13102 break;
13103 case MIPS_HFLAG_BC:
13104 /* Conditional branch */
13106 TCGLabel *l1 = gen_new_label();
13108 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13109 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13110 gen_set_label(l1);
13111 gen_goto_tb(ctx, 0, ctx->btarget);
13113 break;
13114 case MIPS_HFLAG_BR:
13115 /* unconditional branch to register */
13116 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13117 TCGv t0 = tcg_temp_new();
13118 TCGv_i32 t1 = tcg_temp_new_i32();
13120 tcg_gen_andi_tl(t0, btarget, 0x1);
13121 tcg_gen_trunc_tl_i32(t1, t0);
13122 tcg_temp_free(t0);
13123 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13124 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13125 tcg_gen_or_i32(hflags, hflags, t1);
13126 tcg_temp_free_i32(t1);
13128 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13129 } else {
13130 tcg_gen_mov_tl(cpu_PC, btarget);
13132 if (ctx->base.singlestep_enabled) {
13133 save_cpu_state(ctx, 0);
13134 gen_helper_raise_exception_debug(cpu_env);
13136 tcg_gen_lookup_and_goto_ptr();
13137 break;
13138 default:
13139 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13140 abort();
13145 /* Compact Branches */
13146 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13147 int rs, int rt, int32_t offset)
13149 int bcond_compute = 0;
13150 TCGv t0 = tcg_temp_new();
13151 TCGv t1 = tcg_temp_new();
13152 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13154 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13155 #ifdef MIPS_DEBUG_DISAS
13156 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13157 "\n", ctx->base.pc_next);
13158 #endif
13159 generate_exception_end(ctx, EXCP_RI);
13160 goto out;
13163 /* Load needed operands and calculate btarget */
13164 switch (opc) {
13165 /* compact branch */
13166 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13167 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13168 gen_load_gpr(t0, rs);
13169 gen_load_gpr(t1, rt);
13170 bcond_compute = 1;
13171 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13172 if (rs <= rt && rs == 0) {
13173 /* OPC_BEQZALC, OPC_BNEZALC */
13174 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13176 break;
13177 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13178 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13179 gen_load_gpr(t0, rs);
13180 gen_load_gpr(t1, rt);
13181 bcond_compute = 1;
13182 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13183 break;
13184 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13185 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13186 if (rs == 0 || rs == rt) {
13187 /* OPC_BLEZALC, OPC_BGEZALC */
13188 /* OPC_BGTZALC, OPC_BLTZALC */
13189 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13191 gen_load_gpr(t0, rs);
13192 gen_load_gpr(t1, rt);
13193 bcond_compute = 1;
13194 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13195 break;
13196 case OPC_BC:
13197 case OPC_BALC:
13198 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13199 break;
13200 case OPC_BEQZC:
13201 case OPC_BNEZC:
13202 if (rs != 0) {
13203 /* OPC_BEQZC, OPC_BNEZC */
13204 gen_load_gpr(t0, rs);
13205 bcond_compute = 1;
13206 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13207 } else {
13208 /* OPC_JIC, OPC_JIALC */
13209 TCGv tbase = tcg_temp_new();
13210 TCGv toffset = tcg_temp_new();
13212 gen_load_gpr(tbase, rt);
13213 tcg_gen_movi_tl(toffset, offset);
13214 gen_op_addr_add(ctx, btarget, tbase, toffset);
13215 tcg_temp_free(tbase);
13216 tcg_temp_free(toffset);
13218 break;
13219 default:
13220 MIPS_INVAL("Compact branch/jump");
13221 generate_exception_end(ctx, EXCP_RI);
13222 goto out;
13225 if (bcond_compute == 0) {
13226 /* Uncoditional compact branch */
13227 switch (opc) {
13228 case OPC_JIALC:
13229 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13230 /* Fallthrough */
13231 case OPC_JIC:
13232 ctx->hflags |= MIPS_HFLAG_BR;
13233 break;
13234 case OPC_BALC:
13235 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13236 /* Fallthrough */
13237 case OPC_BC:
13238 ctx->hflags |= MIPS_HFLAG_B;
13239 break;
13240 default:
13241 MIPS_INVAL("Compact branch/jump");
13242 generate_exception_end(ctx, EXCP_RI);
13243 goto out;
13246 /* Generating branch here as compact branches don't have delay slot */
13247 gen_branch(ctx, 4);
13248 } else {
13249 /* Conditional compact branch */
13250 TCGLabel *fs = gen_new_label();
13251 save_cpu_state(ctx, 0);
13253 switch (opc) {
13254 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13255 if (rs == 0 && rt != 0) {
13256 /* OPC_BLEZALC */
13257 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13258 } else if (rs != 0 && rt != 0 && rs == rt) {
13259 /* OPC_BGEZALC */
13260 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13261 } else {
13262 /* OPC_BGEUC */
13263 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13265 break;
13266 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13267 if (rs == 0 && rt != 0) {
13268 /* OPC_BGTZALC */
13269 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13270 } else if (rs != 0 && rt != 0 && rs == rt) {
13271 /* OPC_BLTZALC */
13272 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13273 } else {
13274 /* OPC_BLTUC */
13275 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13277 break;
13278 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13279 if (rs == 0 && rt != 0) {
13280 /* OPC_BLEZC */
13281 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13282 } else if (rs != 0 && rt != 0 && rs == rt) {
13283 /* OPC_BGEZC */
13284 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13285 } else {
13286 /* OPC_BGEC */
13287 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13289 break;
13290 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13291 if (rs == 0 && rt != 0) {
13292 /* OPC_BGTZC */
13293 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13294 } else if (rs != 0 && rt != 0 && rs == rt) {
13295 /* OPC_BLTZC */
13296 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13297 } else {
13298 /* OPC_BLTC */
13299 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13301 break;
13302 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13303 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13304 if (rs >= rt) {
13305 /* OPC_BOVC, OPC_BNVC */
13306 TCGv t2 = tcg_temp_new();
13307 TCGv t3 = tcg_temp_new();
13308 TCGv t4 = tcg_temp_new();
13309 TCGv input_overflow = tcg_temp_new();
13311 gen_load_gpr(t0, rs);
13312 gen_load_gpr(t1, rt);
13313 tcg_gen_ext32s_tl(t2, t0);
13314 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13315 tcg_gen_ext32s_tl(t3, t1);
13316 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13317 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13319 tcg_gen_add_tl(t4, t2, t3);
13320 tcg_gen_ext32s_tl(t4, t4);
13321 tcg_gen_xor_tl(t2, t2, t3);
13322 tcg_gen_xor_tl(t3, t4, t3);
13323 tcg_gen_andc_tl(t2, t3, t2);
13324 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13325 tcg_gen_or_tl(t4, t4, input_overflow);
13326 if (opc == OPC_BOVC) {
13327 /* OPC_BOVC */
13328 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13329 } else {
13330 /* OPC_BNVC */
13331 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13333 tcg_temp_free(input_overflow);
13334 tcg_temp_free(t4);
13335 tcg_temp_free(t3);
13336 tcg_temp_free(t2);
13337 } else if (rs < rt && rs == 0) {
13338 /* OPC_BEQZALC, OPC_BNEZALC */
13339 if (opc == OPC_BEQZALC) {
13340 /* OPC_BEQZALC */
13341 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13342 } else {
13343 /* OPC_BNEZALC */
13344 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13346 } else {
13347 /* OPC_BEQC, OPC_BNEC */
13348 if (opc == OPC_BEQC) {
13349 /* OPC_BEQC */
13350 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13351 } else {
13352 /* OPC_BNEC */
13353 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13356 break;
13357 case OPC_BEQZC:
13358 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13359 break;
13360 case OPC_BNEZC:
13361 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13362 break;
13363 default:
13364 MIPS_INVAL("Compact conditional branch/jump");
13365 generate_exception_end(ctx, EXCP_RI);
13366 goto out;
13369 /* Generating branch here as compact branches don't have delay slot */
13370 gen_goto_tb(ctx, 1, ctx->btarget);
13371 gen_set_label(fs);
13373 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13376 out:
13377 tcg_temp_free(t0);
13378 tcg_temp_free(t1);
13381 /* ISA extensions (ASEs) */
13382 /* MIPS16 extension to MIPS32 */
13384 /* MIPS16 major opcodes */
13385 enum {
13386 M16_OPC_ADDIUSP = 0x00,
13387 M16_OPC_ADDIUPC = 0x01,
13388 M16_OPC_B = 0x02,
13389 M16_OPC_JAL = 0x03,
13390 M16_OPC_BEQZ = 0x04,
13391 M16_OPC_BNEQZ = 0x05,
13392 M16_OPC_SHIFT = 0x06,
13393 M16_OPC_LD = 0x07,
13394 M16_OPC_RRIA = 0x08,
13395 M16_OPC_ADDIU8 = 0x09,
13396 M16_OPC_SLTI = 0x0a,
13397 M16_OPC_SLTIU = 0x0b,
13398 M16_OPC_I8 = 0x0c,
13399 M16_OPC_LI = 0x0d,
13400 M16_OPC_CMPI = 0x0e,
13401 M16_OPC_SD = 0x0f,
13402 M16_OPC_LB = 0x10,
13403 M16_OPC_LH = 0x11,
13404 M16_OPC_LWSP = 0x12,
13405 M16_OPC_LW = 0x13,
13406 M16_OPC_LBU = 0x14,
13407 M16_OPC_LHU = 0x15,
13408 M16_OPC_LWPC = 0x16,
13409 M16_OPC_LWU = 0x17,
13410 M16_OPC_SB = 0x18,
13411 M16_OPC_SH = 0x19,
13412 M16_OPC_SWSP = 0x1a,
13413 M16_OPC_SW = 0x1b,
13414 M16_OPC_RRR = 0x1c,
13415 M16_OPC_RR = 0x1d,
13416 M16_OPC_EXTEND = 0x1e,
13417 M16_OPC_I64 = 0x1f
13420 /* I8 funct field */
13421 enum {
13422 I8_BTEQZ = 0x0,
13423 I8_BTNEZ = 0x1,
13424 I8_SWRASP = 0x2,
13425 I8_ADJSP = 0x3,
13426 I8_SVRS = 0x4,
13427 I8_MOV32R = 0x5,
13428 I8_MOVR32 = 0x7
13431 /* RRR f field */
13432 enum {
13433 RRR_DADDU = 0x0,
13434 RRR_ADDU = 0x1,
13435 RRR_DSUBU = 0x2,
13436 RRR_SUBU = 0x3
13439 /* RR funct field */
13440 enum {
13441 RR_JR = 0x00,
13442 RR_SDBBP = 0x01,
13443 RR_SLT = 0x02,
13444 RR_SLTU = 0x03,
13445 RR_SLLV = 0x04,
13446 RR_BREAK = 0x05,
13447 RR_SRLV = 0x06,
13448 RR_SRAV = 0x07,
13449 RR_DSRL = 0x08,
13450 RR_CMP = 0x0a,
13451 RR_NEG = 0x0b,
13452 RR_AND = 0x0c,
13453 RR_OR = 0x0d,
13454 RR_XOR = 0x0e,
13455 RR_NOT = 0x0f,
13456 RR_MFHI = 0x10,
13457 RR_CNVT = 0x11,
13458 RR_MFLO = 0x12,
13459 RR_DSRA = 0x13,
13460 RR_DSLLV = 0x14,
13461 RR_DSRLV = 0x16,
13462 RR_DSRAV = 0x17,
13463 RR_MULT = 0x18,
13464 RR_MULTU = 0x19,
13465 RR_DIV = 0x1a,
13466 RR_DIVU = 0x1b,
13467 RR_DMULT = 0x1c,
13468 RR_DMULTU = 0x1d,
13469 RR_DDIV = 0x1e,
13470 RR_DDIVU = 0x1f
13473 /* I64 funct field */
13474 enum {
13475 I64_LDSP = 0x0,
13476 I64_SDSP = 0x1,
13477 I64_SDRASP = 0x2,
13478 I64_DADJSP = 0x3,
13479 I64_LDPC = 0x4,
13480 I64_DADDIU5 = 0x5,
13481 I64_DADDIUPC = 0x6,
13482 I64_DADDIUSP = 0x7
13485 /* RR ry field for CNVT */
13486 enum {
13487 RR_RY_CNVT_ZEB = 0x0,
13488 RR_RY_CNVT_ZEH = 0x1,
13489 RR_RY_CNVT_ZEW = 0x2,
13490 RR_RY_CNVT_SEB = 0x4,
13491 RR_RY_CNVT_SEH = 0x5,
13492 RR_RY_CNVT_SEW = 0x6,
13495 static int xlat(int r)
13497 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13499 return map[r];
13502 static void gen_mips16_save(DisasContext *ctx,
13503 int xsregs, int aregs,
13504 int do_ra, int do_s0, int do_s1,
13505 int framesize)
13507 TCGv t0 = tcg_temp_new();
13508 TCGv t1 = tcg_temp_new();
13509 TCGv t2 = tcg_temp_new();
13510 int args, astatic;
13512 switch (aregs) {
13513 case 0:
13514 case 1:
13515 case 2:
13516 case 3:
13517 case 11:
13518 args = 0;
13519 break;
13520 case 4:
13521 case 5:
13522 case 6:
13523 case 7:
13524 args = 1;
13525 break;
13526 case 8:
13527 case 9:
13528 case 10:
13529 args = 2;
13530 break;
13531 case 12:
13532 case 13:
13533 args = 3;
13534 break;
13535 case 14:
13536 args = 4;
13537 break;
13538 default:
13539 generate_exception_end(ctx, EXCP_RI);
13540 return;
13543 switch (args) {
13544 case 4:
13545 gen_base_offset_addr(ctx, t0, 29, 12);
13546 gen_load_gpr(t1, 7);
13547 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13548 /* Fall through */
13549 case 3:
13550 gen_base_offset_addr(ctx, t0, 29, 8);
13551 gen_load_gpr(t1, 6);
13552 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13553 /* Fall through */
13554 case 2:
13555 gen_base_offset_addr(ctx, t0, 29, 4);
13556 gen_load_gpr(t1, 5);
13557 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13558 /* Fall through */
13559 case 1:
13560 gen_base_offset_addr(ctx, t0, 29, 0);
13561 gen_load_gpr(t1, 4);
13562 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13565 gen_load_gpr(t0, 29);
13567 #define DECR_AND_STORE(reg) do { \
13568 tcg_gen_movi_tl(t2, -4); \
13569 gen_op_addr_add(ctx, t0, t0, t2); \
13570 gen_load_gpr(t1, reg); \
13571 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13572 } while (0)
13574 if (do_ra) {
13575 DECR_AND_STORE(31);
13578 switch (xsregs) {
13579 case 7:
13580 DECR_AND_STORE(30);
13581 /* Fall through */
13582 case 6:
13583 DECR_AND_STORE(23);
13584 /* Fall through */
13585 case 5:
13586 DECR_AND_STORE(22);
13587 /* Fall through */
13588 case 4:
13589 DECR_AND_STORE(21);
13590 /* Fall through */
13591 case 3:
13592 DECR_AND_STORE(20);
13593 /* Fall through */
13594 case 2:
13595 DECR_AND_STORE(19);
13596 /* Fall through */
13597 case 1:
13598 DECR_AND_STORE(18);
13601 if (do_s1) {
13602 DECR_AND_STORE(17);
13604 if (do_s0) {
13605 DECR_AND_STORE(16);
13608 switch (aregs) {
13609 case 0:
13610 case 4:
13611 case 8:
13612 case 12:
13613 case 14:
13614 astatic = 0;
13615 break;
13616 case 1:
13617 case 5:
13618 case 9:
13619 case 13:
13620 astatic = 1;
13621 break;
13622 case 2:
13623 case 6:
13624 case 10:
13625 astatic = 2;
13626 break;
13627 case 3:
13628 case 7:
13629 astatic = 3;
13630 break;
13631 case 11:
13632 astatic = 4;
13633 break;
13634 default:
13635 generate_exception_end(ctx, EXCP_RI);
13636 return;
13639 if (astatic > 0) {
13640 DECR_AND_STORE(7);
13641 if (astatic > 1) {
13642 DECR_AND_STORE(6);
13643 if (astatic > 2) {
13644 DECR_AND_STORE(5);
13645 if (astatic > 3) {
13646 DECR_AND_STORE(4);
13651 #undef DECR_AND_STORE
13653 tcg_gen_movi_tl(t2, -framesize);
13654 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13655 tcg_temp_free(t0);
13656 tcg_temp_free(t1);
13657 tcg_temp_free(t2);
13660 static void gen_mips16_restore(DisasContext *ctx,
13661 int xsregs, int aregs,
13662 int do_ra, int do_s0, int do_s1,
13663 int framesize)
13665 int astatic;
13666 TCGv t0 = tcg_temp_new();
13667 TCGv t1 = tcg_temp_new();
13668 TCGv t2 = tcg_temp_new();
13670 tcg_gen_movi_tl(t2, framesize);
13671 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13673 #define DECR_AND_LOAD(reg) do { \
13674 tcg_gen_movi_tl(t2, -4); \
13675 gen_op_addr_add(ctx, t0, t0, t2); \
13676 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13677 gen_store_gpr(t1, reg); \
13678 } while (0)
13680 if (do_ra) {
13681 DECR_AND_LOAD(31);
13684 switch (xsregs) {
13685 case 7:
13686 DECR_AND_LOAD(30);
13687 /* Fall through */
13688 case 6:
13689 DECR_AND_LOAD(23);
13690 /* Fall through */
13691 case 5:
13692 DECR_AND_LOAD(22);
13693 /* Fall through */
13694 case 4:
13695 DECR_AND_LOAD(21);
13696 /* Fall through */
13697 case 3:
13698 DECR_AND_LOAD(20);
13699 /* Fall through */
13700 case 2:
13701 DECR_AND_LOAD(19);
13702 /* Fall through */
13703 case 1:
13704 DECR_AND_LOAD(18);
13707 if (do_s1) {
13708 DECR_AND_LOAD(17);
13710 if (do_s0) {
13711 DECR_AND_LOAD(16);
13714 switch (aregs) {
13715 case 0:
13716 case 4:
13717 case 8:
13718 case 12:
13719 case 14:
13720 astatic = 0;
13721 break;
13722 case 1:
13723 case 5:
13724 case 9:
13725 case 13:
13726 astatic = 1;
13727 break;
13728 case 2:
13729 case 6:
13730 case 10:
13731 astatic = 2;
13732 break;
13733 case 3:
13734 case 7:
13735 astatic = 3;
13736 break;
13737 case 11:
13738 astatic = 4;
13739 break;
13740 default:
13741 generate_exception_end(ctx, EXCP_RI);
13742 return;
13745 if (astatic > 0) {
13746 DECR_AND_LOAD(7);
13747 if (astatic > 1) {
13748 DECR_AND_LOAD(6);
13749 if (astatic > 2) {
13750 DECR_AND_LOAD(5);
13751 if (astatic > 3) {
13752 DECR_AND_LOAD(4);
13757 #undef DECR_AND_LOAD
13759 tcg_gen_movi_tl(t2, framesize);
13760 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13761 tcg_temp_free(t0);
13762 tcg_temp_free(t1);
13763 tcg_temp_free(t2);
13766 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13767 int is_64_bit, int extended)
13769 TCGv t0;
13771 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13772 generate_exception_end(ctx, EXCP_RI);
13773 return;
13776 t0 = tcg_temp_new();
13778 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13779 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13780 if (!is_64_bit) {
13781 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13784 tcg_temp_free(t0);
13787 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13788 int16_t offset)
13790 TCGv_i32 t0 = tcg_const_i32(op);
13791 TCGv t1 = tcg_temp_new();
13792 gen_base_offset_addr(ctx, t1, base, offset);
13793 gen_helper_cache(cpu_env, t1, t0);
13796 #if defined(TARGET_MIPS64)
13797 static void decode_i64_mips16(DisasContext *ctx,
13798 int ry, int funct, int16_t offset,
13799 int extended)
13801 switch (funct) {
13802 case I64_LDSP:
13803 check_insn(ctx, ISA_MIPS3);
13804 check_mips_64(ctx);
13805 offset = extended ? offset : offset << 3;
13806 gen_ld(ctx, OPC_LD, ry, 29, offset);
13807 break;
13808 case I64_SDSP:
13809 check_insn(ctx, ISA_MIPS3);
13810 check_mips_64(ctx);
13811 offset = extended ? offset : offset << 3;
13812 gen_st(ctx, OPC_SD, ry, 29, offset);
13813 break;
13814 case I64_SDRASP:
13815 check_insn(ctx, ISA_MIPS3);
13816 check_mips_64(ctx);
13817 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13818 gen_st(ctx, OPC_SD, 31, 29, offset);
13819 break;
13820 case I64_DADJSP:
13821 check_insn(ctx, ISA_MIPS3);
13822 check_mips_64(ctx);
13823 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13824 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13825 break;
13826 case I64_LDPC:
13827 check_insn(ctx, ISA_MIPS3);
13828 check_mips_64(ctx);
13829 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13830 generate_exception_end(ctx, EXCP_RI);
13831 } else {
13832 offset = extended ? offset : offset << 3;
13833 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13835 break;
13836 case I64_DADDIU5:
13837 check_insn(ctx, ISA_MIPS3);
13838 check_mips_64(ctx);
13839 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13840 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13841 break;
13842 case I64_DADDIUPC:
13843 check_insn(ctx, ISA_MIPS3);
13844 check_mips_64(ctx);
13845 offset = extended ? offset : offset << 2;
13846 gen_addiupc(ctx, ry, offset, 1, extended);
13847 break;
13848 case I64_DADDIUSP:
13849 check_insn(ctx, ISA_MIPS3);
13850 check_mips_64(ctx);
13851 offset = extended ? offset : offset << 2;
13852 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13853 break;
13856 #endif
13858 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13860 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13861 int op, rx, ry, funct, sa;
13862 int16_t imm, offset;
13864 ctx->opcode = (ctx->opcode << 16) | extend;
13865 op = (ctx->opcode >> 11) & 0x1f;
13866 sa = (ctx->opcode >> 22) & 0x1f;
13867 funct = (ctx->opcode >> 8) & 0x7;
13868 rx = xlat((ctx->opcode >> 8) & 0x7);
13869 ry = xlat((ctx->opcode >> 5) & 0x7);
13870 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13871 | ((ctx->opcode >> 21) & 0x3f) << 5
13872 | (ctx->opcode & 0x1f));
13875 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13876 * counterparts.
13878 switch (op) {
13879 case M16_OPC_ADDIUSP:
13880 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13881 break;
13882 case M16_OPC_ADDIUPC:
13883 gen_addiupc(ctx, rx, imm, 0, 1);
13884 break;
13885 case M16_OPC_B:
13886 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13887 /* No delay slot, so just process as a normal instruction */
13888 break;
13889 case M16_OPC_BEQZ:
13890 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13891 /* No delay slot, so just process as a normal instruction */
13892 break;
13893 case M16_OPC_BNEQZ:
13894 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13895 /* No delay slot, so just process as a normal instruction */
13896 break;
13897 case M16_OPC_SHIFT:
13898 switch (ctx->opcode & 0x3) {
13899 case 0x0:
13900 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13901 break;
13902 case 0x1:
13903 #if defined(TARGET_MIPS64)
13904 check_mips_64(ctx);
13905 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13906 #else
13907 generate_exception_end(ctx, EXCP_RI);
13908 #endif
13909 break;
13910 case 0x2:
13911 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13912 break;
13913 case 0x3:
13914 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13915 break;
13917 break;
13918 #if defined(TARGET_MIPS64)
13919 case M16_OPC_LD:
13920 check_insn(ctx, ISA_MIPS3);
13921 check_mips_64(ctx);
13922 gen_ld(ctx, OPC_LD, ry, rx, offset);
13923 break;
13924 #endif
13925 case M16_OPC_RRIA:
13926 imm = ctx->opcode & 0xf;
13927 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13928 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13929 imm = (int16_t) (imm << 1) >> 1;
13930 if ((ctx->opcode >> 4) & 0x1) {
13931 #if defined(TARGET_MIPS64)
13932 check_mips_64(ctx);
13933 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13934 #else
13935 generate_exception_end(ctx, EXCP_RI);
13936 #endif
13937 } else {
13938 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13940 break;
13941 case M16_OPC_ADDIU8:
13942 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13943 break;
13944 case M16_OPC_SLTI:
13945 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13946 break;
13947 case M16_OPC_SLTIU:
13948 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13949 break;
13950 case M16_OPC_I8:
13951 switch (funct) {
13952 case I8_BTEQZ:
13953 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13954 break;
13955 case I8_BTNEZ:
13956 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13957 break;
13958 case I8_SWRASP:
13959 gen_st(ctx, OPC_SW, 31, 29, imm);
13960 break;
13961 case I8_ADJSP:
13962 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13963 break;
13964 case I8_SVRS:
13965 check_insn(ctx, ISA_MIPS32);
13967 int xsregs = (ctx->opcode >> 24) & 0x7;
13968 int aregs = (ctx->opcode >> 16) & 0xf;
13969 int do_ra = (ctx->opcode >> 6) & 0x1;
13970 int do_s0 = (ctx->opcode >> 5) & 0x1;
13971 int do_s1 = (ctx->opcode >> 4) & 0x1;
13972 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13973 | (ctx->opcode & 0xf)) << 3;
13975 if (ctx->opcode & (1 << 7)) {
13976 gen_mips16_save(ctx, xsregs, aregs,
13977 do_ra, do_s0, do_s1,
13978 framesize);
13979 } else {
13980 gen_mips16_restore(ctx, xsregs, aregs,
13981 do_ra, do_s0, do_s1,
13982 framesize);
13985 break;
13986 default:
13987 generate_exception_end(ctx, EXCP_RI);
13988 break;
13990 break;
13991 case M16_OPC_LI:
13992 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13993 break;
13994 case M16_OPC_CMPI:
13995 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13996 break;
13997 #if defined(TARGET_MIPS64)
13998 case M16_OPC_SD:
13999 check_insn(ctx, ISA_MIPS3);
14000 check_mips_64(ctx);
14001 gen_st(ctx, OPC_SD, ry, rx, offset);
14002 break;
14003 #endif
14004 case M16_OPC_LB:
14005 gen_ld(ctx, OPC_LB, ry, rx, offset);
14006 break;
14007 case M16_OPC_LH:
14008 gen_ld(ctx, OPC_LH, ry, rx, offset);
14009 break;
14010 case M16_OPC_LWSP:
14011 gen_ld(ctx, OPC_LW, rx, 29, offset);
14012 break;
14013 case M16_OPC_LW:
14014 gen_ld(ctx, OPC_LW, ry, rx, offset);
14015 break;
14016 case M16_OPC_LBU:
14017 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14018 break;
14019 case M16_OPC_LHU:
14020 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14021 break;
14022 case M16_OPC_LWPC:
14023 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14024 break;
14025 #if defined(TARGET_MIPS64)
14026 case M16_OPC_LWU:
14027 check_insn(ctx, ISA_MIPS3);
14028 check_mips_64(ctx);
14029 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14030 break;
14031 #endif
14032 case M16_OPC_SB:
14033 gen_st(ctx, OPC_SB, ry, rx, offset);
14034 break;
14035 case M16_OPC_SH:
14036 gen_st(ctx, OPC_SH, ry, rx, offset);
14037 break;
14038 case M16_OPC_SWSP:
14039 gen_st(ctx, OPC_SW, rx, 29, offset);
14040 break;
14041 case M16_OPC_SW:
14042 gen_st(ctx, OPC_SW, ry, rx, offset);
14043 break;
14044 #if defined(TARGET_MIPS64)
14045 case M16_OPC_I64:
14046 decode_i64_mips16(ctx, ry, funct, offset, 1);
14047 break;
14048 #endif
14049 default:
14050 generate_exception_end(ctx, EXCP_RI);
14051 break;
14054 return 4;
14057 static inline bool is_uhi(int sdbbp_code)
14059 #ifdef CONFIG_USER_ONLY
14060 return false;
14061 #else
14062 return semihosting_enabled() && sdbbp_code == 1;
14063 #endif
14066 #ifdef CONFIG_USER_ONLY
14067 /* The above should dead-code away any calls to this..*/
14068 static inline void gen_helper_do_semihosting(void *env)
14070 g_assert_not_reached();
14072 #endif
14074 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14076 int rx, ry;
14077 int sa;
14078 int op, cnvt_op, op1, offset;
14079 int funct;
14080 int n_bytes;
14082 op = (ctx->opcode >> 11) & 0x1f;
14083 sa = (ctx->opcode >> 2) & 0x7;
14084 sa = sa == 0 ? 8 : sa;
14085 rx = xlat((ctx->opcode >> 8) & 0x7);
14086 cnvt_op = (ctx->opcode >> 5) & 0x7;
14087 ry = xlat((ctx->opcode >> 5) & 0x7);
14088 op1 = offset = ctx->opcode & 0x1f;
14090 n_bytes = 2;
14092 switch (op) {
14093 case M16_OPC_ADDIUSP:
14095 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14097 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14099 break;
14100 case M16_OPC_ADDIUPC:
14101 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14102 break;
14103 case M16_OPC_B:
14104 offset = (ctx->opcode & 0x7ff) << 1;
14105 offset = (int16_t)(offset << 4) >> 4;
14106 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14107 /* No delay slot, so just process as a normal instruction */
14108 break;
14109 case M16_OPC_JAL:
14110 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14111 offset = (((ctx->opcode & 0x1f) << 21)
14112 | ((ctx->opcode >> 5) & 0x1f) << 16
14113 | offset) << 2;
14114 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14115 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14116 n_bytes = 4;
14117 break;
14118 case M16_OPC_BEQZ:
14119 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14120 ((int8_t)ctx->opcode) << 1, 0);
14121 /* No delay slot, so just process as a normal instruction */
14122 break;
14123 case M16_OPC_BNEQZ:
14124 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14125 ((int8_t)ctx->opcode) << 1, 0);
14126 /* No delay slot, so just process as a normal instruction */
14127 break;
14128 case M16_OPC_SHIFT:
14129 switch (ctx->opcode & 0x3) {
14130 case 0x0:
14131 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14132 break;
14133 case 0x1:
14134 #if defined(TARGET_MIPS64)
14135 check_insn(ctx, ISA_MIPS3);
14136 check_mips_64(ctx);
14137 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14138 #else
14139 generate_exception_end(ctx, EXCP_RI);
14140 #endif
14141 break;
14142 case 0x2:
14143 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14144 break;
14145 case 0x3:
14146 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14147 break;
14149 break;
14150 #if defined(TARGET_MIPS64)
14151 case M16_OPC_LD:
14152 check_insn(ctx, ISA_MIPS3);
14153 check_mips_64(ctx);
14154 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14155 break;
14156 #endif
14157 case M16_OPC_RRIA:
14159 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14161 if ((ctx->opcode >> 4) & 1) {
14162 #if defined(TARGET_MIPS64)
14163 check_insn(ctx, ISA_MIPS3);
14164 check_mips_64(ctx);
14165 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14166 #else
14167 generate_exception_end(ctx, EXCP_RI);
14168 #endif
14169 } else {
14170 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14173 break;
14174 case M16_OPC_ADDIU8:
14176 int16_t imm = (int8_t) ctx->opcode;
14178 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14180 break;
14181 case M16_OPC_SLTI:
14183 int16_t imm = (uint8_t) ctx->opcode;
14184 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14186 break;
14187 case M16_OPC_SLTIU:
14189 int16_t imm = (uint8_t) ctx->opcode;
14190 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14192 break;
14193 case M16_OPC_I8:
14195 int reg32;
14197 funct = (ctx->opcode >> 8) & 0x7;
14198 switch (funct) {
14199 case I8_BTEQZ:
14200 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14201 ((int8_t)ctx->opcode) << 1, 0);
14202 break;
14203 case I8_BTNEZ:
14204 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14205 ((int8_t)ctx->opcode) << 1, 0);
14206 break;
14207 case I8_SWRASP:
14208 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14209 break;
14210 case I8_ADJSP:
14211 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14212 ((int8_t)ctx->opcode) << 3);
14213 break;
14214 case I8_SVRS:
14215 check_insn(ctx, ISA_MIPS32);
14217 int do_ra = ctx->opcode & (1 << 6);
14218 int do_s0 = ctx->opcode & (1 << 5);
14219 int do_s1 = ctx->opcode & (1 << 4);
14220 int framesize = ctx->opcode & 0xf;
14222 if (framesize == 0) {
14223 framesize = 128;
14224 } else {
14225 framesize = framesize << 3;
14228 if (ctx->opcode & (1 << 7)) {
14229 gen_mips16_save(ctx, 0, 0,
14230 do_ra, do_s0, do_s1, framesize);
14231 } else {
14232 gen_mips16_restore(ctx, 0, 0,
14233 do_ra, do_s0, do_s1, framesize);
14236 break;
14237 case I8_MOV32R:
14239 int rz = xlat(ctx->opcode & 0x7);
14241 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14242 ((ctx->opcode >> 5) & 0x7);
14243 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14245 break;
14246 case I8_MOVR32:
14247 reg32 = ctx->opcode & 0x1f;
14248 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14249 break;
14250 default:
14251 generate_exception_end(ctx, EXCP_RI);
14252 break;
14255 break;
14256 case M16_OPC_LI:
14258 int16_t imm = (uint8_t) ctx->opcode;
14260 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14262 break;
14263 case M16_OPC_CMPI:
14265 int16_t imm = (uint8_t) ctx->opcode;
14266 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14268 break;
14269 #if defined(TARGET_MIPS64)
14270 case M16_OPC_SD:
14271 check_insn(ctx, ISA_MIPS3);
14272 check_mips_64(ctx);
14273 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14274 break;
14275 #endif
14276 case M16_OPC_LB:
14277 gen_ld(ctx, OPC_LB, ry, rx, offset);
14278 break;
14279 case M16_OPC_LH:
14280 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14281 break;
14282 case M16_OPC_LWSP:
14283 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14284 break;
14285 case M16_OPC_LW:
14286 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14287 break;
14288 case M16_OPC_LBU:
14289 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14290 break;
14291 case M16_OPC_LHU:
14292 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14293 break;
14294 case M16_OPC_LWPC:
14295 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14296 break;
14297 #if defined(TARGET_MIPS64)
14298 case M16_OPC_LWU:
14299 check_insn(ctx, ISA_MIPS3);
14300 check_mips_64(ctx);
14301 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14302 break;
14303 #endif
14304 case M16_OPC_SB:
14305 gen_st(ctx, OPC_SB, ry, rx, offset);
14306 break;
14307 case M16_OPC_SH:
14308 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14309 break;
14310 case M16_OPC_SWSP:
14311 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14312 break;
14313 case M16_OPC_SW:
14314 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14315 break;
14316 case M16_OPC_RRR:
14318 int rz = xlat((ctx->opcode >> 2) & 0x7);
14319 int mips32_op;
14321 switch (ctx->opcode & 0x3) {
14322 case RRR_ADDU:
14323 mips32_op = OPC_ADDU;
14324 break;
14325 case RRR_SUBU:
14326 mips32_op = OPC_SUBU;
14327 break;
14328 #if defined(TARGET_MIPS64)
14329 case RRR_DADDU:
14330 mips32_op = OPC_DADDU;
14331 check_insn(ctx, ISA_MIPS3);
14332 check_mips_64(ctx);
14333 break;
14334 case RRR_DSUBU:
14335 mips32_op = OPC_DSUBU;
14336 check_insn(ctx, ISA_MIPS3);
14337 check_mips_64(ctx);
14338 break;
14339 #endif
14340 default:
14341 generate_exception_end(ctx, EXCP_RI);
14342 goto done;
14345 gen_arith(ctx, mips32_op, rz, rx, ry);
14346 done:
14349 break;
14350 case M16_OPC_RR:
14351 switch (op1) {
14352 case RR_JR:
14354 int nd = (ctx->opcode >> 7) & 0x1;
14355 int link = (ctx->opcode >> 6) & 0x1;
14356 int ra = (ctx->opcode >> 5) & 0x1;
14358 if (nd) {
14359 check_insn(ctx, ISA_MIPS32);
14362 if (link) {
14363 op = OPC_JALR;
14364 } else {
14365 op = OPC_JR;
14368 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14369 (nd ? 0 : 2));
14371 break;
14372 case RR_SDBBP:
14373 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14374 gen_helper_do_semihosting(cpu_env);
14375 } else {
14377 * XXX: not clear which exception should be raised
14378 * when in debug mode...
14380 check_insn(ctx, ISA_MIPS32);
14381 generate_exception_end(ctx, EXCP_DBp);
14383 break;
14384 case RR_SLT:
14385 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14386 break;
14387 case RR_SLTU:
14388 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14389 break;
14390 case RR_BREAK:
14391 generate_exception_end(ctx, EXCP_BREAK);
14392 break;
14393 case RR_SLLV:
14394 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14395 break;
14396 case RR_SRLV:
14397 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14398 break;
14399 case RR_SRAV:
14400 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14401 break;
14402 #if defined(TARGET_MIPS64)
14403 case RR_DSRL:
14404 check_insn(ctx, ISA_MIPS3);
14405 check_mips_64(ctx);
14406 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14407 break;
14408 #endif
14409 case RR_CMP:
14410 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14411 break;
14412 case RR_NEG:
14413 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14414 break;
14415 case RR_AND:
14416 gen_logic(ctx, OPC_AND, rx, rx, ry);
14417 break;
14418 case RR_OR:
14419 gen_logic(ctx, OPC_OR, rx, rx, ry);
14420 break;
14421 case RR_XOR:
14422 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14423 break;
14424 case RR_NOT:
14425 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14426 break;
14427 case RR_MFHI:
14428 gen_HILO(ctx, OPC_MFHI, 0, rx);
14429 break;
14430 case RR_CNVT:
14431 check_insn(ctx, ISA_MIPS32);
14432 switch (cnvt_op) {
14433 case RR_RY_CNVT_ZEB:
14434 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14435 break;
14436 case RR_RY_CNVT_ZEH:
14437 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14438 break;
14439 case RR_RY_CNVT_SEB:
14440 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14441 break;
14442 case RR_RY_CNVT_SEH:
14443 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14444 break;
14445 #if defined(TARGET_MIPS64)
14446 case RR_RY_CNVT_ZEW:
14447 check_insn(ctx, ISA_MIPS64);
14448 check_mips_64(ctx);
14449 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14450 break;
14451 case RR_RY_CNVT_SEW:
14452 check_insn(ctx, ISA_MIPS64);
14453 check_mips_64(ctx);
14454 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14455 break;
14456 #endif
14457 default:
14458 generate_exception_end(ctx, EXCP_RI);
14459 break;
14461 break;
14462 case RR_MFLO:
14463 gen_HILO(ctx, OPC_MFLO, 0, rx);
14464 break;
14465 #if defined(TARGET_MIPS64)
14466 case RR_DSRA:
14467 check_insn(ctx, ISA_MIPS3);
14468 check_mips_64(ctx);
14469 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14470 break;
14471 case RR_DSLLV:
14472 check_insn(ctx, ISA_MIPS3);
14473 check_mips_64(ctx);
14474 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14475 break;
14476 case RR_DSRLV:
14477 check_insn(ctx, ISA_MIPS3);
14478 check_mips_64(ctx);
14479 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14480 break;
14481 case RR_DSRAV:
14482 check_insn(ctx, ISA_MIPS3);
14483 check_mips_64(ctx);
14484 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14485 break;
14486 #endif
14487 case RR_MULT:
14488 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14489 break;
14490 case RR_MULTU:
14491 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14492 break;
14493 case RR_DIV:
14494 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14495 break;
14496 case RR_DIVU:
14497 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14498 break;
14499 #if defined(TARGET_MIPS64)
14500 case RR_DMULT:
14501 check_insn(ctx, ISA_MIPS3);
14502 check_mips_64(ctx);
14503 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14504 break;
14505 case RR_DMULTU:
14506 check_insn(ctx, ISA_MIPS3);
14507 check_mips_64(ctx);
14508 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14509 break;
14510 case RR_DDIV:
14511 check_insn(ctx, ISA_MIPS3);
14512 check_mips_64(ctx);
14513 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14514 break;
14515 case RR_DDIVU:
14516 check_insn(ctx, ISA_MIPS3);
14517 check_mips_64(ctx);
14518 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14519 break;
14520 #endif
14521 default:
14522 generate_exception_end(ctx, EXCP_RI);
14523 break;
14525 break;
14526 case M16_OPC_EXTEND:
14527 decode_extended_mips16_opc(env, ctx);
14528 n_bytes = 4;
14529 break;
14530 #if defined(TARGET_MIPS64)
14531 case M16_OPC_I64:
14532 funct = (ctx->opcode >> 8) & 0x7;
14533 decode_i64_mips16(ctx, ry, funct, offset, 0);
14534 break;
14535 #endif
14536 default:
14537 generate_exception_end(ctx, EXCP_RI);
14538 break;
14541 return n_bytes;
14544 /* microMIPS extension to MIPS32/MIPS64 */
14547 * microMIPS32/microMIPS64 major opcodes
14549 * 1. MIPS Architecture for Programmers Volume II-B:
14550 * The microMIPS32 Instruction Set (Revision 3.05)
14552 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14554 * 2. MIPS Architecture For Programmers Volume II-A:
14555 * The MIPS64 Instruction Set (Revision 3.51)
14558 enum {
14559 POOL32A = 0x00,
14560 POOL16A = 0x01,
14561 LBU16 = 0x02,
14562 MOVE16 = 0x03,
14563 ADDI32 = 0x04,
14564 R6_LUI = 0x04,
14565 AUI = 0x04,
14566 LBU32 = 0x05,
14567 SB32 = 0x06,
14568 LB32 = 0x07,
14570 POOL32B = 0x08,
14571 POOL16B = 0x09,
14572 LHU16 = 0x0a,
14573 ANDI16 = 0x0b,
14574 ADDIU32 = 0x0c,
14575 LHU32 = 0x0d,
14576 SH32 = 0x0e,
14577 LH32 = 0x0f,
14579 POOL32I = 0x10,
14580 POOL16C = 0x11,
14581 LWSP16 = 0x12,
14582 POOL16D = 0x13,
14583 ORI32 = 0x14,
14584 POOL32F = 0x15,
14585 POOL32S = 0x16, /* MIPS64 */
14586 DADDIU32 = 0x17, /* MIPS64 */
14588 POOL32C = 0x18,
14589 LWGP16 = 0x19,
14590 LW16 = 0x1a,
14591 POOL16E = 0x1b,
14592 XORI32 = 0x1c,
14593 JALS32 = 0x1d,
14594 BOVC = 0x1d,
14595 BEQC = 0x1d,
14596 BEQZALC = 0x1d,
14597 ADDIUPC = 0x1e,
14598 PCREL = 0x1e,
14599 BNVC = 0x1f,
14600 BNEC = 0x1f,
14601 BNEZALC = 0x1f,
14603 R6_BEQZC = 0x20,
14604 JIC = 0x20,
14605 POOL16F = 0x21,
14606 SB16 = 0x22,
14607 BEQZ16 = 0x23,
14608 BEQZC16 = 0x23,
14609 SLTI32 = 0x24,
14610 BEQ32 = 0x25,
14611 BC = 0x25,
14612 SWC132 = 0x26,
14613 LWC132 = 0x27,
14615 /* 0x29 is reserved */
14616 RES_29 = 0x29,
14617 R6_BNEZC = 0x28,
14618 JIALC = 0x28,
14619 SH16 = 0x2a,
14620 BNEZ16 = 0x2b,
14621 BNEZC16 = 0x2b,
14622 SLTIU32 = 0x2c,
14623 BNE32 = 0x2d,
14624 BALC = 0x2d,
14625 SDC132 = 0x2e,
14626 LDC132 = 0x2f,
14628 /* 0x31 is reserved */
14629 RES_31 = 0x31,
14630 BLEZALC = 0x30,
14631 BGEZALC = 0x30,
14632 BGEUC = 0x30,
14633 SWSP16 = 0x32,
14634 B16 = 0x33,
14635 BC16 = 0x33,
14636 ANDI32 = 0x34,
14637 J32 = 0x35,
14638 BGTZC = 0x35,
14639 BLTZC = 0x35,
14640 BLTC = 0x35,
14641 SD32 = 0x36, /* MIPS64 */
14642 LD32 = 0x37, /* MIPS64 */
14644 /* 0x39 is reserved */
14645 RES_39 = 0x39,
14646 BGTZALC = 0x38,
14647 BLTZALC = 0x38,
14648 BLTUC = 0x38,
14649 SW16 = 0x3a,
14650 LI16 = 0x3b,
14651 JALX32 = 0x3c,
14652 JAL32 = 0x3d,
14653 BLEZC = 0x3d,
14654 BGEZC = 0x3d,
14655 BGEC = 0x3d,
14656 SW32 = 0x3e,
14657 LW32 = 0x3f
14660 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14661 enum {
14662 ADDIUPC_00 = 0x00,
14663 ADDIUPC_01 = 0x01,
14664 ADDIUPC_02 = 0x02,
14665 ADDIUPC_03 = 0x03,
14666 ADDIUPC_04 = 0x04,
14667 ADDIUPC_05 = 0x05,
14668 ADDIUPC_06 = 0x06,
14669 ADDIUPC_07 = 0x07,
14670 AUIPC = 0x1e,
14671 ALUIPC = 0x1f,
14672 LWPC_08 = 0x08,
14673 LWPC_09 = 0x09,
14674 LWPC_0A = 0x0A,
14675 LWPC_0B = 0x0B,
14676 LWPC_0C = 0x0C,
14677 LWPC_0D = 0x0D,
14678 LWPC_0E = 0x0E,
14679 LWPC_0F = 0x0F,
14682 /* POOL32A encoding of minor opcode field */
14684 enum {
14686 * These opcodes are distinguished only by bits 9..6; those bits are
14687 * what are recorded below.
14689 SLL32 = 0x0,
14690 SRL32 = 0x1,
14691 SRA = 0x2,
14692 ROTR = 0x3,
14693 SELEQZ = 0x5,
14694 SELNEZ = 0x6,
14695 R6_RDHWR = 0x7,
14697 SLLV = 0x0,
14698 SRLV = 0x1,
14699 SRAV = 0x2,
14700 ROTRV = 0x3,
14701 ADD = 0x4,
14702 ADDU32 = 0x5,
14703 SUB = 0x6,
14704 SUBU32 = 0x7,
14705 MUL = 0x8,
14706 AND = 0x9,
14707 OR32 = 0xa,
14708 NOR = 0xb,
14709 XOR32 = 0xc,
14710 SLT = 0xd,
14711 SLTU = 0xe,
14713 MOVN = 0x0,
14714 R6_MUL = 0x0,
14715 MOVZ = 0x1,
14716 MUH = 0x1,
14717 MULU = 0x2,
14718 MUHU = 0x3,
14719 LWXS = 0x4,
14720 R6_DIV = 0x4,
14721 MOD = 0x5,
14722 R6_DIVU = 0x6,
14723 MODU = 0x7,
14725 /* The following can be distinguished by their lower 6 bits. */
14726 BREAK32 = 0x07,
14727 INS = 0x0c,
14728 LSA = 0x0f,
14729 ALIGN = 0x1f,
14730 EXT = 0x2c,
14731 POOL32AXF = 0x3c,
14732 SIGRIE = 0x3f
14735 /* POOL32AXF encoding of minor opcode field extension */
14738 * 1. MIPS Architecture for Programmers Volume II-B:
14739 * The microMIPS32 Instruction Set (Revision 3.05)
14741 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14743 * 2. MIPS Architecture for Programmers VolumeIV-e:
14744 * The MIPS DSP Application-Specific Extension
14745 * to the microMIPS32 Architecture (Revision 2.34)
14747 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14750 enum {
14751 /* bits 11..6 */
14752 TEQ = 0x00,
14753 TGE = 0x08,
14754 TGEU = 0x10,
14755 TLT = 0x20,
14756 TLTU = 0x28,
14757 TNE = 0x30,
14759 MFC0 = 0x03,
14760 MTC0 = 0x0b,
14762 /* begin of microMIPS32 DSP */
14764 /* bits 13..12 for 0x01 */
14765 MFHI_ACC = 0x0,
14766 MFLO_ACC = 0x1,
14767 MTHI_ACC = 0x2,
14768 MTLO_ACC = 0x3,
14770 /* bits 13..12 for 0x2a */
14771 MADD_ACC = 0x0,
14772 MADDU_ACC = 0x1,
14773 MSUB_ACC = 0x2,
14774 MSUBU_ACC = 0x3,
14776 /* bits 13..12 for 0x32 */
14777 MULT_ACC = 0x0,
14778 MULTU_ACC = 0x1,
14780 /* end of microMIPS32 DSP */
14782 /* bits 15..12 for 0x2c */
14783 BITSWAP = 0x0,
14784 SEB = 0x2,
14785 SEH = 0x3,
14786 CLO = 0x4,
14787 CLZ = 0x5,
14788 RDHWR = 0x6,
14789 WSBH = 0x7,
14790 MULT = 0x8,
14791 MULTU = 0x9,
14792 DIV = 0xa,
14793 DIVU = 0xb,
14794 MADD = 0xc,
14795 MADDU = 0xd,
14796 MSUB = 0xe,
14797 MSUBU = 0xf,
14799 /* bits 15..12 for 0x34 */
14800 MFC2 = 0x4,
14801 MTC2 = 0x5,
14802 MFHC2 = 0x8,
14803 MTHC2 = 0x9,
14804 CFC2 = 0xc,
14805 CTC2 = 0xd,
14807 /* bits 15..12 for 0x3c */
14808 JALR = 0x0,
14809 JR = 0x0, /* alias */
14810 JALRC = 0x0,
14811 JRC = 0x0,
14812 JALR_HB = 0x1,
14813 JALRC_HB = 0x1,
14814 JALRS = 0x4,
14815 JALRS_HB = 0x5,
14817 /* bits 15..12 for 0x05 */
14818 RDPGPR = 0xe,
14819 WRPGPR = 0xf,
14821 /* bits 15..12 for 0x0d */
14822 TLBP = 0x0,
14823 TLBR = 0x1,
14824 TLBWI = 0x2,
14825 TLBWR = 0x3,
14826 TLBINV = 0x4,
14827 TLBINVF = 0x5,
14828 WAIT = 0x9,
14829 IRET = 0xd,
14830 DERET = 0xe,
14831 ERET = 0xf,
14833 /* bits 15..12 for 0x15 */
14834 DMT = 0x0,
14835 DVPE = 0x1,
14836 EMT = 0x2,
14837 EVPE = 0x3,
14839 /* bits 15..12 for 0x1d */
14840 DI = 0x4,
14841 EI = 0x5,
14843 /* bits 15..12 for 0x2d */
14844 SYNC = 0x6,
14845 SYSCALL = 0x8,
14846 SDBBP = 0xd,
14848 /* bits 15..12 for 0x35 */
14849 MFHI32 = 0x0,
14850 MFLO32 = 0x1,
14851 MTHI32 = 0x2,
14852 MTLO32 = 0x3,
14855 /* POOL32B encoding of minor opcode field (bits 15..12) */
14857 enum {
14858 LWC2 = 0x0,
14859 LWP = 0x1,
14860 LDP = 0x4,
14861 LWM32 = 0x5,
14862 CACHE = 0x6,
14863 LDM = 0x7,
14864 SWC2 = 0x8,
14865 SWP = 0x9,
14866 SDP = 0xc,
14867 SWM32 = 0xd,
14868 SDM = 0xf
14871 /* POOL32C encoding of minor opcode field (bits 15..12) */
14873 enum {
14874 LWL = 0x0,
14875 SWL = 0x8,
14876 LWR = 0x1,
14877 SWR = 0x9,
14878 PREF = 0x2,
14879 ST_EVA = 0xa,
14880 LL = 0x3,
14881 SC = 0xb,
14882 LDL = 0x4,
14883 SDL = 0xc,
14884 LDR = 0x5,
14885 SDR = 0xd,
14886 LD_EVA = 0x6,
14887 LWU = 0xe,
14888 LLD = 0x7,
14889 SCD = 0xf
14892 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14894 enum {
14895 LBUE = 0x0,
14896 LHUE = 0x1,
14897 LWLE = 0x2,
14898 LWRE = 0x3,
14899 LBE = 0x4,
14900 LHE = 0x5,
14901 LLE = 0x6,
14902 LWE = 0x7,
14905 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14907 enum {
14908 SWLE = 0x0,
14909 SWRE = 0x1,
14910 PREFE = 0x2,
14911 CACHEE = 0x3,
14912 SBE = 0x4,
14913 SHE = 0x5,
14914 SCE = 0x6,
14915 SWE = 0x7,
14918 /* POOL32F encoding of minor opcode field (bits 5..0) */
14920 enum {
14921 /* These are the bit 7..6 values */
14922 ADD_FMT = 0x0,
14924 SUB_FMT = 0x1,
14926 MUL_FMT = 0x2,
14928 DIV_FMT = 0x3,
14930 /* These are the bit 8..6 values */
14931 MOVN_FMT = 0x0,
14932 RSQRT2_FMT = 0x0,
14933 MOVF_FMT = 0x0,
14934 RINT_FMT = 0x0,
14935 SELNEZ_FMT = 0x0,
14937 MOVZ_FMT = 0x1,
14938 LWXC1 = 0x1,
14939 MOVT_FMT = 0x1,
14940 CLASS_FMT = 0x1,
14941 SELEQZ_FMT = 0x1,
14943 PLL_PS = 0x2,
14944 SWXC1 = 0x2,
14945 SEL_FMT = 0x2,
14947 PLU_PS = 0x3,
14948 LDXC1 = 0x3,
14950 MOVN_FMT_04 = 0x4,
14951 PUL_PS = 0x4,
14952 SDXC1 = 0x4,
14953 RECIP2_FMT = 0x4,
14955 MOVZ_FMT_05 = 0x05,
14956 PUU_PS = 0x5,
14957 LUXC1 = 0x5,
14959 CVT_PS_S = 0x6,
14960 SUXC1 = 0x6,
14961 ADDR_PS = 0x6,
14962 PREFX = 0x6,
14963 MADDF_FMT = 0x6,
14965 MULR_PS = 0x7,
14966 MSUBF_FMT = 0x7,
14968 MADD_S = 0x01,
14969 MADD_D = 0x09,
14970 MADD_PS = 0x11,
14971 ALNV_PS = 0x19,
14972 MSUB_S = 0x21,
14973 MSUB_D = 0x29,
14974 MSUB_PS = 0x31,
14976 NMADD_S = 0x02,
14977 NMADD_D = 0x0a,
14978 NMADD_PS = 0x12,
14979 NMSUB_S = 0x22,
14980 NMSUB_D = 0x2a,
14981 NMSUB_PS = 0x32,
14983 MIN_FMT = 0x3,
14984 MAX_FMT = 0xb,
14985 MINA_FMT = 0x23,
14986 MAXA_FMT = 0x2b,
14987 POOL32FXF = 0x3b,
14989 CABS_COND_FMT = 0x1c, /* MIPS3D */
14990 C_COND_FMT = 0x3c,
14992 CMP_CONDN_S = 0x5,
14993 CMP_CONDN_D = 0x15
14996 /* POOL32Fxf encoding of minor opcode extension field */
14998 enum {
14999 CVT_L = 0x04,
15000 RSQRT_FMT = 0x08,
15001 FLOOR_L = 0x0c,
15002 CVT_PW_PS = 0x1c,
15003 CVT_W = 0x24,
15004 SQRT_FMT = 0x28,
15005 FLOOR_W = 0x2c,
15006 CVT_PS_PW = 0x3c,
15007 CFC1 = 0x40,
15008 RECIP_FMT = 0x48,
15009 CEIL_L = 0x4c,
15010 CTC1 = 0x60,
15011 CEIL_W = 0x6c,
15012 MFC1 = 0x80,
15013 CVT_S_PL = 0x84,
15014 TRUNC_L = 0x8c,
15015 MTC1 = 0xa0,
15016 CVT_S_PU = 0xa4,
15017 TRUNC_W = 0xac,
15018 MFHC1 = 0xc0,
15019 ROUND_L = 0xcc,
15020 MTHC1 = 0xe0,
15021 ROUND_W = 0xec,
15023 MOV_FMT = 0x01,
15024 MOVF = 0x05,
15025 ABS_FMT = 0x0d,
15026 RSQRT1_FMT = 0x1d,
15027 MOVT = 0x25,
15028 NEG_FMT = 0x2d,
15029 CVT_D = 0x4d,
15030 RECIP1_FMT = 0x5d,
15031 CVT_S = 0x6d
15034 /* POOL32I encoding of minor opcode field (bits 25..21) */
15036 enum {
15037 BLTZ = 0x00,
15038 BLTZAL = 0x01,
15039 BGEZ = 0x02,
15040 BGEZAL = 0x03,
15041 BLEZ = 0x04,
15042 BNEZC = 0x05,
15043 BGTZ = 0x06,
15044 BEQZC = 0x07,
15045 TLTI = 0x08,
15046 BC1EQZC = 0x08,
15047 TGEI = 0x09,
15048 BC1NEZC = 0x09,
15049 TLTIU = 0x0a,
15050 BC2EQZC = 0x0a,
15051 TGEIU = 0x0b,
15052 BC2NEZC = 0x0a,
15053 TNEI = 0x0c,
15054 R6_SYNCI = 0x0c,
15055 LUI = 0x0d,
15056 TEQI = 0x0e,
15057 SYNCI = 0x10,
15058 BLTZALS = 0x11,
15059 BGEZALS = 0x13,
15060 BC2F = 0x14,
15061 BC2T = 0x15,
15062 BPOSGE64 = 0x1a,
15063 BPOSGE32 = 0x1b,
15064 /* These overlap and are distinguished by bit16 of the instruction */
15065 BC1F = 0x1c,
15066 BC1T = 0x1d,
15067 BC1ANY2F = 0x1c,
15068 BC1ANY2T = 0x1d,
15069 BC1ANY4F = 0x1e,
15070 BC1ANY4T = 0x1f
15073 /* POOL16A encoding of minor opcode field */
15075 enum {
15076 ADDU16 = 0x0,
15077 SUBU16 = 0x1
15080 /* POOL16B encoding of minor opcode field */
15082 enum {
15083 SLL16 = 0x0,
15084 SRL16 = 0x1
15087 /* POOL16C encoding of minor opcode field */
15089 enum {
15090 NOT16 = 0x00,
15091 XOR16 = 0x04,
15092 AND16 = 0x08,
15093 OR16 = 0x0c,
15094 LWM16 = 0x10,
15095 SWM16 = 0x14,
15096 JR16 = 0x18,
15097 JRC16 = 0x1a,
15098 JALR16 = 0x1c,
15099 JALR16S = 0x1e,
15100 MFHI16 = 0x20,
15101 MFLO16 = 0x24,
15102 BREAK16 = 0x28,
15103 SDBBP16 = 0x2c,
15104 JRADDIUSP = 0x30
15107 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15109 enum {
15110 R6_NOT16 = 0x00,
15111 R6_AND16 = 0x01,
15112 R6_LWM16 = 0x02,
15113 R6_JRC16 = 0x03,
15114 MOVEP = 0x04,
15115 MOVEP_05 = 0x05,
15116 MOVEP_06 = 0x06,
15117 MOVEP_07 = 0x07,
15118 R6_XOR16 = 0x08,
15119 R6_OR16 = 0x09,
15120 R6_SWM16 = 0x0a,
15121 JALRC16 = 0x0b,
15122 MOVEP_0C = 0x0c,
15123 MOVEP_0D = 0x0d,
15124 MOVEP_0E = 0x0e,
15125 MOVEP_0F = 0x0f,
15126 JRCADDIUSP = 0x13,
15127 R6_BREAK16 = 0x1b,
15128 R6_SDBBP16 = 0x3b
15131 /* POOL16D encoding of minor opcode field */
15133 enum {
15134 ADDIUS5 = 0x0,
15135 ADDIUSP = 0x1
15138 /* POOL16E encoding of minor opcode field */
15140 enum {
15141 ADDIUR2 = 0x0,
15142 ADDIUR1SP = 0x1
15145 static int mmreg(int r)
15147 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15149 return map[r];
15152 /* Used for 16-bit store instructions. */
15153 static int mmreg2(int r)
15155 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15157 return map[r];
15160 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15161 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15162 #define uMIPS_RS2(op) uMIPS_RS(op)
15163 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15164 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15165 #define uMIPS_RS5(op) (op & 0x1f)
15167 /* Signed immediate */
15168 #define SIMM(op, start, width) \
15169 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15170 << (32 - width)) \
15171 >> (32 - width))
15172 /* Zero-extended immediate */
15173 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15175 static void gen_addiur1sp(DisasContext *ctx)
15177 int rd = mmreg(uMIPS_RD(ctx->opcode));
15179 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15182 static void gen_addiur2(DisasContext *ctx)
15184 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15185 int rd = mmreg(uMIPS_RD(ctx->opcode));
15186 int rs = mmreg(uMIPS_RS(ctx->opcode));
15188 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15191 static void gen_addiusp(DisasContext *ctx)
15193 int encoded = ZIMM(ctx->opcode, 1, 9);
15194 int decoded;
15196 if (encoded <= 1) {
15197 decoded = 256 + encoded;
15198 } else if (encoded <= 255) {
15199 decoded = encoded;
15200 } else if (encoded <= 509) {
15201 decoded = encoded - 512;
15202 } else {
15203 decoded = encoded - 768;
15206 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15209 static void gen_addius5(DisasContext *ctx)
15211 int imm = SIMM(ctx->opcode, 1, 4);
15212 int rd = (ctx->opcode >> 5) & 0x1f;
15214 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15217 static void gen_andi16(DisasContext *ctx)
15219 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15220 31, 32, 63, 64, 255, 32768, 65535 };
15221 int rd = mmreg(uMIPS_RD(ctx->opcode));
15222 int rs = mmreg(uMIPS_RS(ctx->opcode));
15223 int encoded = ZIMM(ctx->opcode, 0, 4);
15225 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15228 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15229 int base, int16_t offset)
15231 TCGv t0, t1;
15232 TCGv_i32 t2;
15234 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15235 generate_exception_end(ctx, EXCP_RI);
15236 return;
15239 t0 = tcg_temp_new();
15241 gen_base_offset_addr(ctx, t0, base, offset);
15243 t1 = tcg_const_tl(reglist);
15244 t2 = tcg_const_i32(ctx->mem_idx);
15246 save_cpu_state(ctx, 1);
15247 switch (opc) {
15248 case LWM32:
15249 gen_helper_lwm(cpu_env, t0, t1, t2);
15250 break;
15251 case SWM32:
15252 gen_helper_swm(cpu_env, t0, t1, t2);
15253 break;
15254 #ifdef TARGET_MIPS64
15255 case LDM:
15256 gen_helper_ldm(cpu_env, t0, t1, t2);
15257 break;
15258 case SDM:
15259 gen_helper_sdm(cpu_env, t0, t1, t2);
15260 break;
15261 #endif
15263 tcg_temp_free(t0);
15264 tcg_temp_free(t1);
15265 tcg_temp_free_i32(t2);
15269 static void gen_pool16c_insn(DisasContext *ctx)
15271 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15272 int rs = mmreg(ctx->opcode & 0x7);
15274 switch (((ctx->opcode) >> 4) & 0x3f) {
15275 case NOT16 + 0:
15276 case NOT16 + 1:
15277 case NOT16 + 2:
15278 case NOT16 + 3:
15279 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15280 break;
15281 case XOR16 + 0:
15282 case XOR16 + 1:
15283 case XOR16 + 2:
15284 case XOR16 + 3:
15285 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15286 break;
15287 case AND16 + 0:
15288 case AND16 + 1:
15289 case AND16 + 2:
15290 case AND16 + 3:
15291 gen_logic(ctx, OPC_AND, rd, rd, rs);
15292 break;
15293 case OR16 + 0:
15294 case OR16 + 1:
15295 case OR16 + 2:
15296 case OR16 + 3:
15297 gen_logic(ctx, OPC_OR, rd, rd, rs);
15298 break;
15299 case LWM16 + 0:
15300 case LWM16 + 1:
15301 case LWM16 + 2:
15302 case LWM16 + 3:
15304 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15305 int offset = ZIMM(ctx->opcode, 0, 4);
15307 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15308 29, offset << 2);
15310 break;
15311 case SWM16 + 0:
15312 case SWM16 + 1:
15313 case SWM16 + 2:
15314 case SWM16 + 3:
15316 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15317 int offset = ZIMM(ctx->opcode, 0, 4);
15319 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15320 29, offset << 2);
15322 break;
15323 case JR16 + 0:
15324 case JR16 + 1:
15326 int reg = ctx->opcode & 0x1f;
15328 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15330 break;
15331 case JRC16 + 0:
15332 case JRC16 + 1:
15334 int reg = ctx->opcode & 0x1f;
15335 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15337 * Let normal delay slot handling in our caller take us
15338 * to the branch target.
15341 break;
15342 case JALR16 + 0:
15343 case JALR16 + 1:
15344 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15345 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15346 break;
15347 case JALR16S + 0:
15348 case JALR16S + 1:
15349 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15350 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15351 break;
15352 case MFHI16 + 0:
15353 case MFHI16 + 1:
15354 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15355 break;
15356 case MFLO16 + 0:
15357 case MFLO16 + 1:
15358 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15359 break;
15360 case BREAK16:
15361 generate_exception_end(ctx, EXCP_BREAK);
15362 break;
15363 case SDBBP16:
15364 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15365 gen_helper_do_semihosting(cpu_env);
15366 } else {
15368 * XXX: not clear which exception should be raised
15369 * when in debug mode...
15371 check_insn(ctx, ISA_MIPS32);
15372 generate_exception_end(ctx, EXCP_DBp);
15374 break;
15375 case JRADDIUSP + 0:
15376 case JRADDIUSP + 1:
15378 int imm = ZIMM(ctx->opcode, 0, 5);
15379 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15380 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15382 * Let normal delay slot handling in our caller take us
15383 * to the branch target.
15386 break;
15387 default:
15388 generate_exception_end(ctx, EXCP_RI);
15389 break;
15393 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15394 int enc_rs)
15396 int rd, rs, re, rt;
15397 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15398 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15399 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15400 rd = rd_enc[enc_dest];
15401 re = re_enc[enc_dest];
15402 rs = rs_rt_enc[enc_rs];
15403 rt = rs_rt_enc[enc_rt];
15404 if (rs) {
15405 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15406 } else {
15407 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15409 if (rt) {
15410 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15411 } else {
15412 tcg_gen_movi_tl(cpu_gpr[re], 0);
15416 static void gen_pool16c_r6_insn(DisasContext *ctx)
15418 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15419 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15421 switch (ctx->opcode & 0xf) {
15422 case R6_NOT16:
15423 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15424 break;
15425 case R6_AND16:
15426 gen_logic(ctx, OPC_AND, rt, rt, rs);
15427 break;
15428 case R6_LWM16:
15430 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15431 int offset = extract32(ctx->opcode, 4, 4);
15432 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15434 break;
15435 case R6_JRC16: /* JRCADDIUSP */
15436 if ((ctx->opcode >> 4) & 1) {
15437 /* JRCADDIUSP */
15438 int imm = extract32(ctx->opcode, 5, 5);
15439 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15440 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15441 } else {
15442 /* JRC16 */
15443 rs = extract32(ctx->opcode, 5, 5);
15444 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15446 break;
15447 case MOVEP:
15448 case MOVEP_05:
15449 case MOVEP_06:
15450 case MOVEP_07:
15451 case MOVEP_0C:
15452 case MOVEP_0D:
15453 case MOVEP_0E:
15454 case MOVEP_0F:
15456 int enc_dest = uMIPS_RD(ctx->opcode);
15457 int enc_rt = uMIPS_RS2(ctx->opcode);
15458 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15459 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15461 break;
15462 case R6_XOR16:
15463 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15464 break;
15465 case R6_OR16:
15466 gen_logic(ctx, OPC_OR, rt, rt, rs);
15467 break;
15468 case R6_SWM16:
15470 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15471 int offset = extract32(ctx->opcode, 4, 4);
15472 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15474 break;
15475 case JALRC16: /* BREAK16, SDBBP16 */
15476 switch (ctx->opcode & 0x3f) {
15477 case JALRC16:
15478 case JALRC16 + 0x20:
15479 /* JALRC16 */
15480 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15481 31, 0, 0);
15482 break;
15483 case R6_BREAK16:
15484 /* BREAK16 */
15485 generate_exception(ctx, EXCP_BREAK);
15486 break;
15487 case R6_SDBBP16:
15488 /* SDBBP16 */
15489 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15490 gen_helper_do_semihosting(cpu_env);
15491 } else {
15492 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15493 generate_exception(ctx, EXCP_RI);
15494 } else {
15495 generate_exception(ctx, EXCP_DBp);
15498 break;
15500 break;
15501 default:
15502 generate_exception(ctx, EXCP_RI);
15503 break;
15507 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15509 TCGv t0 = tcg_temp_new();
15510 TCGv t1 = tcg_temp_new();
15512 gen_load_gpr(t0, base);
15514 if (index != 0) {
15515 gen_load_gpr(t1, index);
15516 tcg_gen_shli_tl(t1, t1, 2);
15517 gen_op_addr_add(ctx, t0, t1, t0);
15520 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15521 gen_store_gpr(t1, rd);
15523 tcg_temp_free(t0);
15524 tcg_temp_free(t1);
15527 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15528 int base, int16_t offset)
15530 TCGv t0, t1;
15532 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15533 generate_exception_end(ctx, EXCP_RI);
15534 return;
15537 t0 = tcg_temp_new();
15538 t1 = tcg_temp_new();
15540 gen_base_offset_addr(ctx, t0, base, offset);
15542 switch (opc) {
15543 case LWP:
15544 if (rd == base) {
15545 generate_exception_end(ctx, EXCP_RI);
15546 return;
15548 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15549 gen_store_gpr(t1, rd);
15550 tcg_gen_movi_tl(t1, 4);
15551 gen_op_addr_add(ctx, t0, t0, t1);
15552 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15553 gen_store_gpr(t1, rd + 1);
15554 break;
15555 case SWP:
15556 gen_load_gpr(t1, rd);
15557 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15558 tcg_gen_movi_tl(t1, 4);
15559 gen_op_addr_add(ctx, t0, t0, t1);
15560 gen_load_gpr(t1, rd + 1);
15561 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15562 break;
15563 #ifdef TARGET_MIPS64
15564 case LDP:
15565 if (rd == base) {
15566 generate_exception_end(ctx, EXCP_RI);
15567 return;
15569 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15570 gen_store_gpr(t1, rd);
15571 tcg_gen_movi_tl(t1, 8);
15572 gen_op_addr_add(ctx, t0, t0, t1);
15573 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15574 gen_store_gpr(t1, rd + 1);
15575 break;
15576 case SDP:
15577 gen_load_gpr(t1, rd);
15578 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15579 tcg_gen_movi_tl(t1, 8);
15580 gen_op_addr_add(ctx, t0, t0, t1);
15581 gen_load_gpr(t1, rd + 1);
15582 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15583 break;
15584 #endif
15586 tcg_temp_free(t0);
15587 tcg_temp_free(t1);
15590 static void gen_sync(int stype)
15592 TCGBar tcg_mo = TCG_BAR_SC;
15594 switch (stype) {
15595 case 0x4: /* SYNC_WMB */
15596 tcg_mo |= TCG_MO_ST_ST;
15597 break;
15598 case 0x10: /* SYNC_MB */
15599 tcg_mo |= TCG_MO_ALL;
15600 break;
15601 case 0x11: /* SYNC_ACQUIRE */
15602 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15603 break;
15604 case 0x12: /* SYNC_RELEASE */
15605 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15606 break;
15607 case 0x13: /* SYNC_RMB */
15608 tcg_mo |= TCG_MO_LD_LD;
15609 break;
15610 default:
15611 tcg_mo |= TCG_MO_ALL;
15612 break;
15615 tcg_gen_mb(tcg_mo);
15618 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15620 int extension = (ctx->opcode >> 6) & 0x3f;
15621 int minor = (ctx->opcode >> 12) & 0xf;
15622 uint32_t mips32_op;
15624 switch (extension) {
15625 case TEQ:
15626 mips32_op = OPC_TEQ;
15627 goto do_trap;
15628 case TGE:
15629 mips32_op = OPC_TGE;
15630 goto do_trap;
15631 case TGEU:
15632 mips32_op = OPC_TGEU;
15633 goto do_trap;
15634 case TLT:
15635 mips32_op = OPC_TLT;
15636 goto do_trap;
15637 case TLTU:
15638 mips32_op = OPC_TLTU;
15639 goto do_trap;
15640 case TNE:
15641 mips32_op = OPC_TNE;
15642 do_trap:
15643 gen_trap(ctx, mips32_op, rs, rt, -1);
15644 break;
15645 #ifndef CONFIG_USER_ONLY
15646 case MFC0:
15647 case MFC0 + 32:
15648 check_cp0_enabled(ctx);
15649 if (rt == 0) {
15650 /* Treat as NOP. */
15651 break;
15653 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15654 break;
15655 case MTC0:
15656 case MTC0 + 32:
15657 check_cp0_enabled(ctx);
15659 TCGv t0 = tcg_temp_new();
15661 gen_load_gpr(t0, rt);
15662 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15663 tcg_temp_free(t0);
15665 break;
15666 #endif
15667 case 0x2a:
15668 switch (minor & 3) {
15669 case MADD_ACC:
15670 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15671 break;
15672 case MADDU_ACC:
15673 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15674 break;
15675 case MSUB_ACC:
15676 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15677 break;
15678 case MSUBU_ACC:
15679 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15680 break;
15681 default:
15682 goto pool32axf_invalid;
15684 break;
15685 case 0x32:
15686 switch (minor & 3) {
15687 case MULT_ACC:
15688 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15689 break;
15690 case MULTU_ACC:
15691 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15692 break;
15693 default:
15694 goto pool32axf_invalid;
15696 break;
15697 case 0x2c:
15698 switch (minor) {
15699 case BITSWAP:
15700 check_insn(ctx, ISA_MIPS32R6);
15701 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15702 break;
15703 case SEB:
15704 gen_bshfl(ctx, OPC_SEB, rs, rt);
15705 break;
15706 case SEH:
15707 gen_bshfl(ctx, OPC_SEH, rs, rt);
15708 break;
15709 case CLO:
15710 mips32_op = OPC_CLO;
15711 goto do_cl;
15712 case CLZ:
15713 mips32_op = OPC_CLZ;
15714 do_cl:
15715 check_insn(ctx, ISA_MIPS32);
15716 gen_cl(ctx, mips32_op, rt, rs);
15717 break;
15718 case RDHWR:
15719 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15720 gen_rdhwr(ctx, rt, rs, 0);
15721 break;
15722 case WSBH:
15723 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15724 break;
15725 case MULT:
15726 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15727 mips32_op = OPC_MULT;
15728 goto do_mul;
15729 case MULTU:
15730 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15731 mips32_op = OPC_MULTU;
15732 goto do_mul;
15733 case DIV:
15734 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15735 mips32_op = OPC_DIV;
15736 goto do_div;
15737 case DIVU:
15738 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15739 mips32_op = OPC_DIVU;
15740 goto do_div;
15741 do_div:
15742 check_insn(ctx, ISA_MIPS32);
15743 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15744 break;
15745 case MADD:
15746 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15747 mips32_op = OPC_MADD;
15748 goto do_mul;
15749 case MADDU:
15750 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15751 mips32_op = OPC_MADDU;
15752 goto do_mul;
15753 case MSUB:
15754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15755 mips32_op = OPC_MSUB;
15756 goto do_mul;
15757 case MSUBU:
15758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15759 mips32_op = OPC_MSUBU;
15760 do_mul:
15761 check_insn(ctx, ISA_MIPS32);
15762 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15763 break;
15764 default:
15765 goto pool32axf_invalid;
15767 break;
15768 case 0x34:
15769 switch (minor) {
15770 case MFC2:
15771 case MTC2:
15772 case MFHC2:
15773 case MTHC2:
15774 case CFC2:
15775 case CTC2:
15776 generate_exception_err(ctx, EXCP_CpU, 2);
15777 break;
15778 default:
15779 goto pool32axf_invalid;
15781 break;
15782 case 0x3c:
15783 switch (minor) {
15784 case JALR: /* JALRC */
15785 case JALR_HB: /* JALRC_HB */
15786 if (ctx->insn_flags & ISA_MIPS32R6) {
15787 /* JALRC, JALRC_HB */
15788 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15789 } else {
15790 /* JALR, JALR_HB */
15791 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15792 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15794 break;
15795 case JALRS:
15796 case JALRS_HB:
15797 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15798 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15799 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15800 break;
15801 default:
15802 goto pool32axf_invalid;
15804 break;
15805 case 0x05:
15806 switch (minor) {
15807 case RDPGPR:
15808 check_cp0_enabled(ctx);
15809 check_insn(ctx, ISA_MIPS32R2);
15810 gen_load_srsgpr(rs, rt);
15811 break;
15812 case WRPGPR:
15813 check_cp0_enabled(ctx);
15814 check_insn(ctx, ISA_MIPS32R2);
15815 gen_store_srsgpr(rs, rt);
15816 break;
15817 default:
15818 goto pool32axf_invalid;
15820 break;
15821 #ifndef CONFIG_USER_ONLY
15822 case 0x0d:
15823 switch (minor) {
15824 case TLBP:
15825 mips32_op = OPC_TLBP;
15826 goto do_cp0;
15827 case TLBR:
15828 mips32_op = OPC_TLBR;
15829 goto do_cp0;
15830 case TLBWI:
15831 mips32_op = OPC_TLBWI;
15832 goto do_cp0;
15833 case TLBWR:
15834 mips32_op = OPC_TLBWR;
15835 goto do_cp0;
15836 case TLBINV:
15837 mips32_op = OPC_TLBINV;
15838 goto do_cp0;
15839 case TLBINVF:
15840 mips32_op = OPC_TLBINVF;
15841 goto do_cp0;
15842 case WAIT:
15843 mips32_op = OPC_WAIT;
15844 goto do_cp0;
15845 case DERET:
15846 mips32_op = OPC_DERET;
15847 goto do_cp0;
15848 case ERET:
15849 mips32_op = OPC_ERET;
15850 do_cp0:
15851 gen_cp0(env, ctx, mips32_op, rt, rs);
15852 break;
15853 default:
15854 goto pool32axf_invalid;
15856 break;
15857 case 0x1d:
15858 switch (minor) {
15859 case DI:
15860 check_cp0_enabled(ctx);
15862 TCGv t0 = tcg_temp_new();
15864 save_cpu_state(ctx, 1);
15865 gen_helper_di(t0, cpu_env);
15866 gen_store_gpr(t0, rs);
15868 * Stop translation as we may have switched the execution
15869 * mode.
15871 ctx->base.is_jmp = DISAS_STOP;
15872 tcg_temp_free(t0);
15874 break;
15875 case EI:
15876 check_cp0_enabled(ctx);
15878 TCGv t0 = tcg_temp_new();
15880 save_cpu_state(ctx, 1);
15881 gen_helper_ei(t0, cpu_env);
15882 gen_store_gpr(t0, rs);
15884 * DISAS_STOP isn't sufficient, we need to ensure we break out
15885 * of translated code to check for pending interrupts.
15887 gen_save_pc(ctx->base.pc_next + 4);
15888 ctx->base.is_jmp = DISAS_EXIT;
15889 tcg_temp_free(t0);
15891 break;
15892 default:
15893 goto pool32axf_invalid;
15895 break;
15896 #endif
15897 case 0x2d:
15898 switch (minor) {
15899 case SYNC:
15900 gen_sync(extract32(ctx->opcode, 16, 5));
15901 break;
15902 case SYSCALL:
15903 generate_exception_end(ctx, EXCP_SYSCALL);
15904 break;
15905 case SDBBP:
15906 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15907 gen_helper_do_semihosting(cpu_env);
15908 } else {
15909 check_insn(ctx, ISA_MIPS32);
15910 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15911 generate_exception_end(ctx, EXCP_RI);
15912 } else {
15913 generate_exception_end(ctx, EXCP_DBp);
15916 break;
15917 default:
15918 goto pool32axf_invalid;
15920 break;
15921 case 0x01:
15922 switch (minor & 3) {
15923 case MFHI_ACC:
15924 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15925 break;
15926 case MFLO_ACC:
15927 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15928 break;
15929 case MTHI_ACC:
15930 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15931 break;
15932 case MTLO_ACC:
15933 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15934 break;
15935 default:
15936 goto pool32axf_invalid;
15938 break;
15939 case 0x35:
15940 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15941 switch (minor) {
15942 case MFHI32:
15943 gen_HILO(ctx, OPC_MFHI, 0, rs);
15944 break;
15945 case MFLO32:
15946 gen_HILO(ctx, OPC_MFLO, 0, rs);
15947 break;
15948 case MTHI32:
15949 gen_HILO(ctx, OPC_MTHI, 0, rs);
15950 break;
15951 case MTLO32:
15952 gen_HILO(ctx, OPC_MTLO, 0, rs);
15953 break;
15954 default:
15955 goto pool32axf_invalid;
15957 break;
15958 default:
15959 pool32axf_invalid:
15960 MIPS_INVAL("pool32axf");
15961 generate_exception_end(ctx, EXCP_RI);
15962 break;
15967 * Values for microMIPS fmt field. Variable-width, depending on which
15968 * formats the instruction supports.
15970 enum {
15971 FMT_SD_S = 0,
15972 FMT_SD_D = 1,
15974 FMT_SDPS_S = 0,
15975 FMT_SDPS_D = 1,
15976 FMT_SDPS_PS = 2,
15978 FMT_SWL_S = 0,
15979 FMT_SWL_W = 1,
15980 FMT_SWL_L = 2,
15982 FMT_DWL_D = 0,
15983 FMT_DWL_W = 1,
15984 FMT_DWL_L = 2
15987 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15989 int extension = (ctx->opcode >> 6) & 0x3ff;
15990 uint32_t mips32_op;
15992 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15993 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15994 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15996 switch (extension) {
15997 case FLOAT_1BIT_FMT(CFC1, 0):
15998 mips32_op = OPC_CFC1;
15999 goto do_cp1;
16000 case FLOAT_1BIT_FMT(CTC1, 0):
16001 mips32_op = OPC_CTC1;
16002 goto do_cp1;
16003 case FLOAT_1BIT_FMT(MFC1, 0):
16004 mips32_op = OPC_MFC1;
16005 goto do_cp1;
16006 case FLOAT_1BIT_FMT(MTC1, 0):
16007 mips32_op = OPC_MTC1;
16008 goto do_cp1;
16009 case FLOAT_1BIT_FMT(MFHC1, 0):
16010 mips32_op = OPC_MFHC1;
16011 goto do_cp1;
16012 case FLOAT_1BIT_FMT(MTHC1, 0):
16013 mips32_op = OPC_MTHC1;
16014 do_cp1:
16015 gen_cp1(ctx, mips32_op, rt, rs);
16016 break;
16018 /* Reciprocal square root */
16019 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16020 mips32_op = OPC_RSQRT_S;
16021 goto do_unaryfp;
16022 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16023 mips32_op = OPC_RSQRT_D;
16024 goto do_unaryfp;
16026 /* Square root */
16027 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16028 mips32_op = OPC_SQRT_S;
16029 goto do_unaryfp;
16030 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16031 mips32_op = OPC_SQRT_D;
16032 goto do_unaryfp;
16034 /* Reciprocal */
16035 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16036 mips32_op = OPC_RECIP_S;
16037 goto do_unaryfp;
16038 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16039 mips32_op = OPC_RECIP_D;
16040 goto do_unaryfp;
16042 /* Floor */
16043 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16044 mips32_op = OPC_FLOOR_L_S;
16045 goto do_unaryfp;
16046 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16047 mips32_op = OPC_FLOOR_L_D;
16048 goto do_unaryfp;
16049 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16050 mips32_op = OPC_FLOOR_W_S;
16051 goto do_unaryfp;
16052 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16053 mips32_op = OPC_FLOOR_W_D;
16054 goto do_unaryfp;
16056 /* Ceiling */
16057 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16058 mips32_op = OPC_CEIL_L_S;
16059 goto do_unaryfp;
16060 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16061 mips32_op = OPC_CEIL_L_D;
16062 goto do_unaryfp;
16063 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16064 mips32_op = OPC_CEIL_W_S;
16065 goto do_unaryfp;
16066 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16067 mips32_op = OPC_CEIL_W_D;
16068 goto do_unaryfp;
16070 /* Truncation */
16071 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16072 mips32_op = OPC_TRUNC_L_S;
16073 goto do_unaryfp;
16074 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16075 mips32_op = OPC_TRUNC_L_D;
16076 goto do_unaryfp;
16077 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16078 mips32_op = OPC_TRUNC_W_S;
16079 goto do_unaryfp;
16080 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16081 mips32_op = OPC_TRUNC_W_D;
16082 goto do_unaryfp;
16084 /* Round */
16085 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16086 mips32_op = OPC_ROUND_L_S;
16087 goto do_unaryfp;
16088 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16089 mips32_op = OPC_ROUND_L_D;
16090 goto do_unaryfp;
16091 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16092 mips32_op = OPC_ROUND_W_S;
16093 goto do_unaryfp;
16094 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16095 mips32_op = OPC_ROUND_W_D;
16096 goto do_unaryfp;
16098 /* Integer to floating-point conversion */
16099 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16100 mips32_op = OPC_CVT_L_S;
16101 goto do_unaryfp;
16102 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16103 mips32_op = OPC_CVT_L_D;
16104 goto do_unaryfp;
16105 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16106 mips32_op = OPC_CVT_W_S;
16107 goto do_unaryfp;
16108 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16109 mips32_op = OPC_CVT_W_D;
16110 goto do_unaryfp;
16112 /* Paired-foo conversions */
16113 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16114 mips32_op = OPC_CVT_S_PL;
16115 goto do_unaryfp;
16116 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16117 mips32_op = OPC_CVT_S_PU;
16118 goto do_unaryfp;
16119 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16120 mips32_op = OPC_CVT_PW_PS;
16121 goto do_unaryfp;
16122 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16123 mips32_op = OPC_CVT_PS_PW;
16124 goto do_unaryfp;
16126 /* Floating-point moves */
16127 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16128 mips32_op = OPC_MOV_S;
16129 goto do_unaryfp;
16130 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16131 mips32_op = OPC_MOV_D;
16132 goto do_unaryfp;
16133 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16134 mips32_op = OPC_MOV_PS;
16135 goto do_unaryfp;
16137 /* Absolute value */
16138 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16139 mips32_op = OPC_ABS_S;
16140 goto do_unaryfp;
16141 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16142 mips32_op = OPC_ABS_D;
16143 goto do_unaryfp;
16144 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16145 mips32_op = OPC_ABS_PS;
16146 goto do_unaryfp;
16148 /* Negation */
16149 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16150 mips32_op = OPC_NEG_S;
16151 goto do_unaryfp;
16152 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16153 mips32_op = OPC_NEG_D;
16154 goto do_unaryfp;
16155 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16156 mips32_op = OPC_NEG_PS;
16157 goto do_unaryfp;
16159 /* Reciprocal square root step */
16160 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16161 mips32_op = OPC_RSQRT1_S;
16162 goto do_unaryfp;
16163 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16164 mips32_op = OPC_RSQRT1_D;
16165 goto do_unaryfp;
16166 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16167 mips32_op = OPC_RSQRT1_PS;
16168 goto do_unaryfp;
16170 /* Reciprocal step */
16171 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16172 mips32_op = OPC_RECIP1_S;
16173 goto do_unaryfp;
16174 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16175 mips32_op = OPC_RECIP1_S;
16176 goto do_unaryfp;
16177 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16178 mips32_op = OPC_RECIP1_PS;
16179 goto do_unaryfp;
16181 /* Conversions from double */
16182 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16183 mips32_op = OPC_CVT_D_S;
16184 goto do_unaryfp;
16185 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16186 mips32_op = OPC_CVT_D_W;
16187 goto do_unaryfp;
16188 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16189 mips32_op = OPC_CVT_D_L;
16190 goto do_unaryfp;
16192 /* Conversions from single */
16193 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16194 mips32_op = OPC_CVT_S_D;
16195 goto do_unaryfp;
16196 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16197 mips32_op = OPC_CVT_S_W;
16198 goto do_unaryfp;
16199 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16200 mips32_op = OPC_CVT_S_L;
16201 do_unaryfp:
16202 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16203 break;
16205 /* Conditional moves on floating-point codes */
16206 case COND_FLOAT_MOV(MOVT, 0):
16207 case COND_FLOAT_MOV(MOVT, 1):
16208 case COND_FLOAT_MOV(MOVT, 2):
16209 case COND_FLOAT_MOV(MOVT, 3):
16210 case COND_FLOAT_MOV(MOVT, 4):
16211 case COND_FLOAT_MOV(MOVT, 5):
16212 case COND_FLOAT_MOV(MOVT, 6):
16213 case COND_FLOAT_MOV(MOVT, 7):
16214 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16215 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16216 break;
16217 case COND_FLOAT_MOV(MOVF, 0):
16218 case COND_FLOAT_MOV(MOVF, 1):
16219 case COND_FLOAT_MOV(MOVF, 2):
16220 case COND_FLOAT_MOV(MOVF, 3):
16221 case COND_FLOAT_MOV(MOVF, 4):
16222 case COND_FLOAT_MOV(MOVF, 5):
16223 case COND_FLOAT_MOV(MOVF, 6):
16224 case COND_FLOAT_MOV(MOVF, 7):
16225 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16226 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16227 break;
16228 default:
16229 MIPS_INVAL("pool32fxf");
16230 generate_exception_end(ctx, EXCP_RI);
16231 break;
16235 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16237 int32_t offset;
16238 uint16_t insn;
16239 int rt, rs, rd, rr;
16240 int16_t imm;
16241 uint32_t op, minor, minor2, mips32_op;
16242 uint32_t cond, fmt, cc;
16244 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16245 ctx->opcode = (ctx->opcode << 16) | insn;
16247 rt = (ctx->opcode >> 21) & 0x1f;
16248 rs = (ctx->opcode >> 16) & 0x1f;
16249 rd = (ctx->opcode >> 11) & 0x1f;
16250 rr = (ctx->opcode >> 6) & 0x1f;
16251 imm = (int16_t) ctx->opcode;
16253 op = (ctx->opcode >> 26) & 0x3f;
16254 switch (op) {
16255 case POOL32A:
16256 minor = ctx->opcode & 0x3f;
16257 switch (minor) {
16258 case 0x00:
16259 minor = (ctx->opcode >> 6) & 0xf;
16260 switch (minor) {
16261 case SLL32:
16262 mips32_op = OPC_SLL;
16263 goto do_shifti;
16264 case SRA:
16265 mips32_op = OPC_SRA;
16266 goto do_shifti;
16267 case SRL32:
16268 mips32_op = OPC_SRL;
16269 goto do_shifti;
16270 case ROTR:
16271 mips32_op = OPC_ROTR;
16272 do_shifti:
16273 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16274 break;
16275 case SELEQZ:
16276 check_insn(ctx, ISA_MIPS32R6);
16277 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16278 break;
16279 case SELNEZ:
16280 check_insn(ctx, ISA_MIPS32R6);
16281 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16282 break;
16283 case R6_RDHWR:
16284 check_insn(ctx, ISA_MIPS32R6);
16285 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16286 break;
16287 default:
16288 goto pool32a_invalid;
16290 break;
16291 case 0x10:
16292 minor = (ctx->opcode >> 6) & 0xf;
16293 switch (minor) {
16294 /* Arithmetic */
16295 case ADD:
16296 mips32_op = OPC_ADD;
16297 goto do_arith;
16298 case ADDU32:
16299 mips32_op = OPC_ADDU;
16300 goto do_arith;
16301 case SUB:
16302 mips32_op = OPC_SUB;
16303 goto do_arith;
16304 case SUBU32:
16305 mips32_op = OPC_SUBU;
16306 goto do_arith;
16307 case MUL:
16308 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16309 mips32_op = OPC_MUL;
16310 do_arith:
16311 gen_arith(ctx, mips32_op, rd, rs, rt);
16312 break;
16313 /* Shifts */
16314 case SLLV:
16315 mips32_op = OPC_SLLV;
16316 goto do_shift;
16317 case SRLV:
16318 mips32_op = OPC_SRLV;
16319 goto do_shift;
16320 case SRAV:
16321 mips32_op = OPC_SRAV;
16322 goto do_shift;
16323 case ROTRV:
16324 mips32_op = OPC_ROTRV;
16325 do_shift:
16326 gen_shift(ctx, mips32_op, rd, rs, rt);
16327 break;
16328 /* Logical operations */
16329 case AND:
16330 mips32_op = OPC_AND;
16331 goto do_logic;
16332 case OR32:
16333 mips32_op = OPC_OR;
16334 goto do_logic;
16335 case NOR:
16336 mips32_op = OPC_NOR;
16337 goto do_logic;
16338 case XOR32:
16339 mips32_op = OPC_XOR;
16340 do_logic:
16341 gen_logic(ctx, mips32_op, rd, rs, rt);
16342 break;
16343 /* Set less than */
16344 case SLT:
16345 mips32_op = OPC_SLT;
16346 goto do_slt;
16347 case SLTU:
16348 mips32_op = OPC_SLTU;
16349 do_slt:
16350 gen_slt(ctx, mips32_op, rd, rs, rt);
16351 break;
16352 default:
16353 goto pool32a_invalid;
16355 break;
16356 case 0x18:
16357 minor = (ctx->opcode >> 6) & 0xf;
16358 switch (minor) {
16359 /* Conditional moves */
16360 case MOVN: /* MUL */
16361 if (ctx->insn_flags & ISA_MIPS32R6) {
16362 /* MUL */
16363 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16364 } else {
16365 /* MOVN */
16366 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16368 break;
16369 case MOVZ: /* MUH */
16370 if (ctx->insn_flags & ISA_MIPS32R6) {
16371 /* MUH */
16372 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16373 } else {
16374 /* MOVZ */
16375 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16377 break;
16378 case MULU:
16379 check_insn(ctx, ISA_MIPS32R6);
16380 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16381 break;
16382 case MUHU:
16383 check_insn(ctx, ISA_MIPS32R6);
16384 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16385 break;
16386 case LWXS: /* DIV */
16387 if (ctx->insn_flags & ISA_MIPS32R6) {
16388 /* DIV */
16389 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16390 } else {
16391 /* LWXS */
16392 gen_ldxs(ctx, rs, rt, rd);
16394 break;
16395 case MOD:
16396 check_insn(ctx, ISA_MIPS32R6);
16397 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16398 break;
16399 case R6_DIVU:
16400 check_insn(ctx, ISA_MIPS32R6);
16401 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16402 break;
16403 case MODU:
16404 check_insn(ctx, ISA_MIPS32R6);
16405 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16406 break;
16407 default:
16408 goto pool32a_invalid;
16410 break;
16411 case INS:
16412 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16413 return;
16414 case LSA:
16415 check_insn(ctx, ISA_MIPS32R6);
16416 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16417 extract32(ctx->opcode, 9, 2));
16418 break;
16419 case ALIGN:
16420 check_insn(ctx, ISA_MIPS32R6);
16421 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16422 break;
16423 case EXT:
16424 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16425 return;
16426 case POOL32AXF:
16427 gen_pool32axf(env, ctx, rt, rs);
16428 break;
16429 case BREAK32:
16430 generate_exception_end(ctx, EXCP_BREAK);
16431 break;
16432 case SIGRIE:
16433 check_insn(ctx, ISA_MIPS32R6);
16434 generate_exception_end(ctx, EXCP_RI);
16435 break;
16436 default:
16437 pool32a_invalid:
16438 MIPS_INVAL("pool32a");
16439 generate_exception_end(ctx, EXCP_RI);
16440 break;
16442 break;
16443 case POOL32B:
16444 minor = (ctx->opcode >> 12) & 0xf;
16445 switch (minor) {
16446 case CACHE:
16447 check_cp0_enabled(ctx);
16448 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16449 gen_cache_operation(ctx, rt, rs, imm);
16451 break;
16452 case LWC2:
16453 case SWC2:
16454 /* COP2: Not implemented. */
16455 generate_exception_err(ctx, EXCP_CpU, 2);
16456 break;
16457 #ifdef TARGET_MIPS64
16458 case LDP:
16459 case SDP:
16460 check_insn(ctx, ISA_MIPS3);
16461 check_mips_64(ctx);
16462 #endif
16463 /* fall through */
16464 case LWP:
16465 case SWP:
16466 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16467 break;
16468 #ifdef TARGET_MIPS64
16469 case LDM:
16470 case SDM:
16471 check_insn(ctx, ISA_MIPS3);
16472 check_mips_64(ctx);
16473 #endif
16474 /* fall through */
16475 case LWM32:
16476 case SWM32:
16477 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16478 break;
16479 default:
16480 MIPS_INVAL("pool32b");
16481 generate_exception_end(ctx, EXCP_RI);
16482 break;
16484 break;
16485 case POOL32F:
16486 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16487 minor = ctx->opcode & 0x3f;
16488 check_cp1_enabled(ctx);
16489 switch (minor) {
16490 case ALNV_PS:
16491 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16492 mips32_op = OPC_ALNV_PS;
16493 goto do_madd;
16494 case MADD_S:
16495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16496 mips32_op = OPC_MADD_S;
16497 goto do_madd;
16498 case MADD_D:
16499 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16500 mips32_op = OPC_MADD_D;
16501 goto do_madd;
16502 case MADD_PS:
16503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16504 mips32_op = OPC_MADD_PS;
16505 goto do_madd;
16506 case MSUB_S:
16507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16508 mips32_op = OPC_MSUB_S;
16509 goto do_madd;
16510 case MSUB_D:
16511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16512 mips32_op = OPC_MSUB_D;
16513 goto do_madd;
16514 case MSUB_PS:
16515 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16516 mips32_op = OPC_MSUB_PS;
16517 goto do_madd;
16518 case NMADD_S:
16519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16520 mips32_op = OPC_NMADD_S;
16521 goto do_madd;
16522 case NMADD_D:
16523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16524 mips32_op = OPC_NMADD_D;
16525 goto do_madd;
16526 case NMADD_PS:
16527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16528 mips32_op = OPC_NMADD_PS;
16529 goto do_madd;
16530 case NMSUB_S:
16531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16532 mips32_op = OPC_NMSUB_S;
16533 goto do_madd;
16534 case NMSUB_D:
16535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16536 mips32_op = OPC_NMSUB_D;
16537 goto do_madd;
16538 case NMSUB_PS:
16539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16540 mips32_op = OPC_NMSUB_PS;
16541 do_madd:
16542 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16543 break;
16544 case CABS_COND_FMT:
16545 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16546 cond = (ctx->opcode >> 6) & 0xf;
16547 cc = (ctx->opcode >> 13) & 0x7;
16548 fmt = (ctx->opcode >> 10) & 0x3;
16549 switch (fmt) {
16550 case 0x0:
16551 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16552 break;
16553 case 0x1:
16554 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16555 break;
16556 case 0x2:
16557 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16558 break;
16559 default:
16560 goto pool32f_invalid;
16562 break;
16563 case C_COND_FMT:
16564 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16565 cond = (ctx->opcode >> 6) & 0xf;
16566 cc = (ctx->opcode >> 13) & 0x7;
16567 fmt = (ctx->opcode >> 10) & 0x3;
16568 switch (fmt) {
16569 case 0x0:
16570 gen_cmp_s(ctx, cond, rt, rs, cc);
16571 break;
16572 case 0x1:
16573 gen_cmp_d(ctx, cond, rt, rs, cc);
16574 break;
16575 case 0x2:
16576 gen_cmp_ps(ctx, cond, rt, rs, cc);
16577 break;
16578 default:
16579 goto pool32f_invalid;
16581 break;
16582 case CMP_CONDN_S:
16583 check_insn(ctx, ISA_MIPS32R6);
16584 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16585 break;
16586 case CMP_CONDN_D:
16587 check_insn(ctx, ISA_MIPS32R6);
16588 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16589 break;
16590 case POOL32FXF:
16591 gen_pool32fxf(ctx, rt, rs);
16592 break;
16593 case 0x00:
16594 /* PLL foo */
16595 switch ((ctx->opcode >> 6) & 0x7) {
16596 case PLL_PS:
16597 mips32_op = OPC_PLL_PS;
16598 goto do_ps;
16599 case PLU_PS:
16600 mips32_op = OPC_PLU_PS;
16601 goto do_ps;
16602 case PUL_PS:
16603 mips32_op = OPC_PUL_PS;
16604 goto do_ps;
16605 case PUU_PS:
16606 mips32_op = OPC_PUU_PS;
16607 goto do_ps;
16608 case CVT_PS_S:
16609 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16610 mips32_op = OPC_CVT_PS_S;
16611 do_ps:
16612 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16613 break;
16614 default:
16615 goto pool32f_invalid;
16617 break;
16618 case MIN_FMT:
16619 check_insn(ctx, ISA_MIPS32R6);
16620 switch ((ctx->opcode >> 9) & 0x3) {
16621 case FMT_SDPS_S:
16622 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16623 break;
16624 case FMT_SDPS_D:
16625 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16626 break;
16627 default:
16628 goto pool32f_invalid;
16630 break;
16631 case 0x08:
16632 /* [LS][WDU]XC1 */
16633 switch ((ctx->opcode >> 6) & 0x7) {
16634 case LWXC1:
16635 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16636 mips32_op = OPC_LWXC1;
16637 goto do_ldst_cp1;
16638 case SWXC1:
16639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16640 mips32_op = OPC_SWXC1;
16641 goto do_ldst_cp1;
16642 case LDXC1:
16643 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16644 mips32_op = OPC_LDXC1;
16645 goto do_ldst_cp1;
16646 case SDXC1:
16647 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16648 mips32_op = OPC_SDXC1;
16649 goto do_ldst_cp1;
16650 case LUXC1:
16651 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16652 mips32_op = OPC_LUXC1;
16653 goto do_ldst_cp1;
16654 case SUXC1:
16655 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16656 mips32_op = OPC_SUXC1;
16657 do_ldst_cp1:
16658 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16659 break;
16660 default:
16661 goto pool32f_invalid;
16663 break;
16664 case MAX_FMT:
16665 check_insn(ctx, ISA_MIPS32R6);
16666 switch ((ctx->opcode >> 9) & 0x3) {
16667 case FMT_SDPS_S:
16668 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16669 break;
16670 case FMT_SDPS_D:
16671 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16672 break;
16673 default:
16674 goto pool32f_invalid;
16676 break;
16677 case 0x18:
16678 /* 3D insns */
16679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16680 fmt = (ctx->opcode >> 9) & 0x3;
16681 switch ((ctx->opcode >> 6) & 0x7) {
16682 case RSQRT2_FMT:
16683 switch (fmt) {
16684 case FMT_SDPS_S:
16685 mips32_op = OPC_RSQRT2_S;
16686 goto do_3d;
16687 case FMT_SDPS_D:
16688 mips32_op = OPC_RSQRT2_D;
16689 goto do_3d;
16690 case FMT_SDPS_PS:
16691 mips32_op = OPC_RSQRT2_PS;
16692 goto do_3d;
16693 default:
16694 goto pool32f_invalid;
16696 break;
16697 case RECIP2_FMT:
16698 switch (fmt) {
16699 case FMT_SDPS_S:
16700 mips32_op = OPC_RECIP2_S;
16701 goto do_3d;
16702 case FMT_SDPS_D:
16703 mips32_op = OPC_RECIP2_D;
16704 goto do_3d;
16705 case FMT_SDPS_PS:
16706 mips32_op = OPC_RECIP2_PS;
16707 goto do_3d;
16708 default:
16709 goto pool32f_invalid;
16711 break;
16712 case ADDR_PS:
16713 mips32_op = OPC_ADDR_PS;
16714 goto do_3d;
16715 case MULR_PS:
16716 mips32_op = OPC_MULR_PS;
16717 do_3d:
16718 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16719 break;
16720 default:
16721 goto pool32f_invalid;
16723 break;
16724 case 0x20:
16725 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16726 cc = (ctx->opcode >> 13) & 0x7;
16727 fmt = (ctx->opcode >> 9) & 0x3;
16728 switch ((ctx->opcode >> 6) & 0x7) {
16729 case MOVF_FMT: /* RINT_FMT */
16730 if (ctx->insn_flags & ISA_MIPS32R6) {
16731 /* RINT_FMT */
16732 switch (fmt) {
16733 case FMT_SDPS_S:
16734 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16735 break;
16736 case FMT_SDPS_D:
16737 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16738 break;
16739 default:
16740 goto pool32f_invalid;
16742 } else {
16743 /* MOVF_FMT */
16744 switch (fmt) {
16745 case FMT_SDPS_S:
16746 gen_movcf_s(ctx, rs, rt, cc, 0);
16747 break;
16748 case FMT_SDPS_D:
16749 gen_movcf_d(ctx, rs, rt, cc, 0);
16750 break;
16751 case FMT_SDPS_PS:
16752 check_ps(ctx);
16753 gen_movcf_ps(ctx, rs, rt, cc, 0);
16754 break;
16755 default:
16756 goto pool32f_invalid;
16759 break;
16760 case MOVT_FMT: /* CLASS_FMT */
16761 if (ctx->insn_flags & ISA_MIPS32R6) {
16762 /* CLASS_FMT */
16763 switch (fmt) {
16764 case FMT_SDPS_S:
16765 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16766 break;
16767 case FMT_SDPS_D:
16768 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16769 break;
16770 default:
16771 goto pool32f_invalid;
16773 } else {
16774 /* MOVT_FMT */
16775 switch (fmt) {
16776 case FMT_SDPS_S:
16777 gen_movcf_s(ctx, rs, rt, cc, 1);
16778 break;
16779 case FMT_SDPS_D:
16780 gen_movcf_d(ctx, rs, rt, cc, 1);
16781 break;
16782 case FMT_SDPS_PS:
16783 check_ps(ctx);
16784 gen_movcf_ps(ctx, rs, rt, cc, 1);
16785 break;
16786 default:
16787 goto pool32f_invalid;
16790 break;
16791 case PREFX:
16792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16793 break;
16794 default:
16795 goto pool32f_invalid;
16797 break;
16798 #define FINSN_3ARG_SDPS(prfx) \
16799 switch ((ctx->opcode >> 8) & 0x3) { \
16800 case FMT_SDPS_S: \
16801 mips32_op = OPC_##prfx##_S; \
16802 goto do_fpop; \
16803 case FMT_SDPS_D: \
16804 mips32_op = OPC_##prfx##_D; \
16805 goto do_fpop; \
16806 case FMT_SDPS_PS: \
16807 check_ps(ctx); \
16808 mips32_op = OPC_##prfx##_PS; \
16809 goto do_fpop; \
16810 default: \
16811 goto pool32f_invalid; \
16813 case MINA_FMT:
16814 check_insn(ctx, ISA_MIPS32R6);
16815 switch ((ctx->opcode >> 9) & 0x3) {
16816 case FMT_SDPS_S:
16817 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16818 break;
16819 case FMT_SDPS_D:
16820 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16821 break;
16822 default:
16823 goto pool32f_invalid;
16825 break;
16826 case MAXA_FMT:
16827 check_insn(ctx, ISA_MIPS32R6);
16828 switch ((ctx->opcode >> 9) & 0x3) {
16829 case FMT_SDPS_S:
16830 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16831 break;
16832 case FMT_SDPS_D:
16833 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16834 break;
16835 default:
16836 goto pool32f_invalid;
16838 break;
16839 case 0x30:
16840 /* regular FP ops */
16841 switch ((ctx->opcode >> 6) & 0x3) {
16842 case ADD_FMT:
16843 FINSN_3ARG_SDPS(ADD);
16844 break;
16845 case SUB_FMT:
16846 FINSN_3ARG_SDPS(SUB);
16847 break;
16848 case MUL_FMT:
16849 FINSN_3ARG_SDPS(MUL);
16850 break;
16851 case DIV_FMT:
16852 fmt = (ctx->opcode >> 8) & 0x3;
16853 if (fmt == 1) {
16854 mips32_op = OPC_DIV_D;
16855 } else if (fmt == 0) {
16856 mips32_op = OPC_DIV_S;
16857 } else {
16858 goto pool32f_invalid;
16860 goto do_fpop;
16861 default:
16862 goto pool32f_invalid;
16864 break;
16865 case 0x38:
16866 /* cmovs */
16867 switch ((ctx->opcode >> 6) & 0x7) {
16868 case MOVN_FMT: /* SELEQZ_FMT */
16869 if (ctx->insn_flags & ISA_MIPS32R6) {
16870 /* SELEQZ_FMT */
16871 switch ((ctx->opcode >> 9) & 0x3) {
16872 case FMT_SDPS_S:
16873 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16874 break;
16875 case FMT_SDPS_D:
16876 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16877 break;
16878 default:
16879 goto pool32f_invalid;
16881 } else {
16882 /* MOVN_FMT */
16883 FINSN_3ARG_SDPS(MOVN);
16885 break;
16886 case MOVN_FMT_04:
16887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16888 FINSN_3ARG_SDPS(MOVN);
16889 break;
16890 case MOVZ_FMT: /* SELNEZ_FMT */
16891 if (ctx->insn_flags & ISA_MIPS32R6) {
16892 /* SELNEZ_FMT */
16893 switch ((ctx->opcode >> 9) & 0x3) {
16894 case FMT_SDPS_S:
16895 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16896 break;
16897 case FMT_SDPS_D:
16898 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16899 break;
16900 default:
16901 goto pool32f_invalid;
16903 } else {
16904 /* MOVZ_FMT */
16905 FINSN_3ARG_SDPS(MOVZ);
16907 break;
16908 case MOVZ_FMT_05:
16909 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16910 FINSN_3ARG_SDPS(MOVZ);
16911 break;
16912 case SEL_FMT:
16913 check_insn(ctx, ISA_MIPS32R6);
16914 switch ((ctx->opcode >> 9) & 0x3) {
16915 case FMT_SDPS_S:
16916 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16917 break;
16918 case FMT_SDPS_D:
16919 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16920 break;
16921 default:
16922 goto pool32f_invalid;
16924 break;
16925 case MADDF_FMT:
16926 check_insn(ctx, ISA_MIPS32R6);
16927 switch ((ctx->opcode >> 9) & 0x3) {
16928 case FMT_SDPS_S:
16929 mips32_op = OPC_MADDF_S;
16930 goto do_fpop;
16931 case FMT_SDPS_D:
16932 mips32_op = OPC_MADDF_D;
16933 goto do_fpop;
16934 default:
16935 goto pool32f_invalid;
16937 break;
16938 case MSUBF_FMT:
16939 check_insn(ctx, ISA_MIPS32R6);
16940 switch ((ctx->opcode >> 9) & 0x3) {
16941 case FMT_SDPS_S:
16942 mips32_op = OPC_MSUBF_S;
16943 goto do_fpop;
16944 case FMT_SDPS_D:
16945 mips32_op = OPC_MSUBF_D;
16946 goto do_fpop;
16947 default:
16948 goto pool32f_invalid;
16950 break;
16951 default:
16952 goto pool32f_invalid;
16954 break;
16955 do_fpop:
16956 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16957 break;
16958 default:
16959 pool32f_invalid:
16960 MIPS_INVAL("pool32f");
16961 generate_exception_end(ctx, EXCP_RI);
16962 break;
16964 } else {
16965 generate_exception_err(ctx, EXCP_CpU, 1);
16967 break;
16968 case POOL32I:
16969 minor = (ctx->opcode >> 21) & 0x1f;
16970 switch (minor) {
16971 case BLTZ:
16972 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16973 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16974 break;
16975 case BLTZAL:
16976 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16977 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16978 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16979 break;
16980 case BLTZALS:
16981 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16982 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16983 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16984 break;
16985 case BGEZ:
16986 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16987 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16988 break;
16989 case BGEZAL:
16990 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16991 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16992 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16993 break;
16994 case BGEZALS:
16995 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16996 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16997 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16998 break;
16999 case BLEZ:
17000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17001 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17002 break;
17003 case BGTZ:
17004 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17005 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17006 break;
17008 /* Traps */
17009 case TLTI: /* BC1EQZC */
17010 if (ctx->insn_flags & ISA_MIPS32R6) {
17011 /* BC1EQZC */
17012 check_cp1_enabled(ctx);
17013 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17014 } else {
17015 /* TLTI */
17016 mips32_op = OPC_TLTI;
17017 goto do_trapi;
17019 break;
17020 case TGEI: /* BC1NEZC */
17021 if (ctx->insn_flags & ISA_MIPS32R6) {
17022 /* BC1NEZC */
17023 check_cp1_enabled(ctx);
17024 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17025 } else {
17026 /* TGEI */
17027 mips32_op = OPC_TGEI;
17028 goto do_trapi;
17030 break;
17031 case TLTIU:
17032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17033 mips32_op = OPC_TLTIU;
17034 goto do_trapi;
17035 case TGEIU:
17036 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17037 mips32_op = OPC_TGEIU;
17038 goto do_trapi;
17039 case TNEI: /* SYNCI */
17040 if (ctx->insn_flags & ISA_MIPS32R6) {
17041 /* SYNCI */
17043 * Break the TB to be able to sync copied instructions
17044 * immediately.
17046 ctx->base.is_jmp = DISAS_STOP;
17047 } else {
17048 /* TNEI */
17049 mips32_op = OPC_TNEI;
17050 goto do_trapi;
17052 break;
17053 case TEQI:
17054 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17055 mips32_op = OPC_TEQI;
17056 do_trapi:
17057 gen_trap(ctx, mips32_op, rs, -1, imm);
17058 break;
17060 case BNEZC:
17061 case BEQZC:
17062 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17063 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17064 4, rs, 0, imm << 1, 0);
17066 * Compact branches don't have a delay slot, so just let
17067 * the normal delay slot handling take us to the branch
17068 * target.
17070 break;
17071 case LUI:
17072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17073 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17074 break;
17075 case SYNCI:
17076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17078 * Break the TB to be able to sync copied instructions
17079 * immediately.
17081 ctx->base.is_jmp = DISAS_STOP;
17082 break;
17083 case BC2F:
17084 case BC2T:
17085 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17086 /* COP2: Not implemented. */
17087 generate_exception_err(ctx, EXCP_CpU, 2);
17088 break;
17089 case BC1F:
17090 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17091 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17092 goto do_cp1branch;
17093 case BC1T:
17094 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17095 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17096 goto do_cp1branch;
17097 case BC1ANY4F:
17098 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17099 mips32_op = OPC_BC1FANY4;
17100 goto do_cp1mips3d;
17101 case BC1ANY4T:
17102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17103 mips32_op = OPC_BC1TANY4;
17104 do_cp1mips3d:
17105 check_cop1x(ctx);
17106 check_insn(ctx, ASE_MIPS3D);
17107 /* Fall through */
17108 do_cp1branch:
17109 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17110 check_cp1_enabled(ctx);
17111 gen_compute_branch1(ctx, mips32_op,
17112 (ctx->opcode >> 18) & 0x7, imm << 1);
17113 } else {
17114 generate_exception_err(ctx, EXCP_CpU, 1);
17116 break;
17117 case BPOSGE64:
17118 case BPOSGE32:
17119 /* MIPS DSP: not implemented */
17120 /* Fall through */
17121 default:
17122 MIPS_INVAL("pool32i");
17123 generate_exception_end(ctx, EXCP_RI);
17124 break;
17126 break;
17127 case POOL32C:
17128 minor = (ctx->opcode >> 12) & 0xf;
17129 offset = sextract32(ctx->opcode, 0,
17130 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
17131 switch (minor) {
17132 case LWL:
17133 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17134 mips32_op = OPC_LWL;
17135 goto do_ld_lr;
17136 case SWL:
17137 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17138 mips32_op = OPC_SWL;
17139 goto do_st_lr;
17140 case LWR:
17141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17142 mips32_op = OPC_LWR;
17143 goto do_ld_lr;
17144 case SWR:
17145 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17146 mips32_op = OPC_SWR;
17147 goto do_st_lr;
17148 #if defined(TARGET_MIPS64)
17149 case LDL:
17150 check_insn(ctx, ISA_MIPS3);
17151 check_mips_64(ctx);
17152 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17153 mips32_op = OPC_LDL;
17154 goto do_ld_lr;
17155 case SDL:
17156 check_insn(ctx, ISA_MIPS3);
17157 check_mips_64(ctx);
17158 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17159 mips32_op = OPC_SDL;
17160 goto do_st_lr;
17161 case LDR:
17162 check_insn(ctx, ISA_MIPS3);
17163 check_mips_64(ctx);
17164 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17165 mips32_op = OPC_LDR;
17166 goto do_ld_lr;
17167 case SDR:
17168 check_insn(ctx, ISA_MIPS3);
17169 check_mips_64(ctx);
17170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17171 mips32_op = OPC_SDR;
17172 goto do_st_lr;
17173 case LWU:
17174 check_insn(ctx, ISA_MIPS3);
17175 check_mips_64(ctx);
17176 mips32_op = OPC_LWU;
17177 goto do_ld_lr;
17178 case LLD:
17179 check_insn(ctx, ISA_MIPS3);
17180 check_mips_64(ctx);
17181 mips32_op = OPC_LLD;
17182 goto do_ld_lr;
17183 #endif
17184 case LL:
17185 mips32_op = OPC_LL;
17186 goto do_ld_lr;
17187 do_ld_lr:
17188 gen_ld(ctx, mips32_op, rt, rs, offset);
17189 break;
17190 do_st_lr:
17191 gen_st(ctx, mips32_op, rt, rs, offset);
17192 break;
17193 case SC:
17194 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17195 break;
17196 #if defined(TARGET_MIPS64)
17197 case SCD:
17198 check_insn(ctx, ISA_MIPS3);
17199 check_mips_64(ctx);
17200 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17201 break;
17202 #endif
17203 case LD_EVA:
17204 if (!ctx->eva) {
17205 MIPS_INVAL("pool32c ld-eva");
17206 generate_exception_end(ctx, EXCP_RI);
17207 break;
17209 check_cp0_enabled(ctx);
17211 minor2 = (ctx->opcode >> 9) & 0x7;
17212 offset = sextract32(ctx->opcode, 0, 9);
17213 switch (minor2) {
17214 case LBUE:
17215 mips32_op = OPC_LBUE;
17216 goto do_ld_lr;
17217 case LHUE:
17218 mips32_op = OPC_LHUE;
17219 goto do_ld_lr;
17220 case LWLE:
17221 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17222 mips32_op = OPC_LWLE;
17223 goto do_ld_lr;
17224 case LWRE:
17225 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17226 mips32_op = OPC_LWRE;
17227 goto do_ld_lr;
17228 case LBE:
17229 mips32_op = OPC_LBE;
17230 goto do_ld_lr;
17231 case LHE:
17232 mips32_op = OPC_LHE;
17233 goto do_ld_lr;
17234 case LLE:
17235 mips32_op = OPC_LLE;
17236 goto do_ld_lr;
17237 case LWE:
17238 mips32_op = OPC_LWE;
17239 goto do_ld_lr;
17241 break;
17242 case ST_EVA:
17243 if (!ctx->eva) {
17244 MIPS_INVAL("pool32c st-eva");
17245 generate_exception_end(ctx, EXCP_RI);
17246 break;
17248 check_cp0_enabled(ctx);
17250 minor2 = (ctx->opcode >> 9) & 0x7;
17251 offset = sextract32(ctx->opcode, 0, 9);
17252 switch (minor2) {
17253 case SWLE:
17254 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17255 mips32_op = OPC_SWLE;
17256 goto do_st_lr;
17257 case SWRE:
17258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17259 mips32_op = OPC_SWRE;
17260 goto do_st_lr;
17261 case PREFE:
17262 /* Treat as no-op */
17263 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17264 /* hint codes 24-31 are reserved and signal RI */
17265 generate_exception(ctx, EXCP_RI);
17267 break;
17268 case CACHEE:
17269 /* Treat as no-op */
17270 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17271 gen_cache_operation(ctx, rt, rs, offset);
17273 break;
17274 case SBE:
17275 mips32_op = OPC_SBE;
17276 goto do_st_lr;
17277 case SHE:
17278 mips32_op = OPC_SHE;
17279 goto do_st_lr;
17280 case SCE:
17281 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17282 break;
17283 case SWE:
17284 mips32_op = OPC_SWE;
17285 goto do_st_lr;
17287 break;
17288 case PREF:
17289 /* Treat as no-op */
17290 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17291 /* hint codes 24-31 are reserved and signal RI */
17292 generate_exception(ctx, EXCP_RI);
17294 break;
17295 default:
17296 MIPS_INVAL("pool32c");
17297 generate_exception_end(ctx, EXCP_RI);
17298 break;
17300 break;
17301 case ADDI32: /* AUI, LUI */
17302 if (ctx->insn_flags & ISA_MIPS32R6) {
17303 /* AUI, LUI */
17304 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17305 } else {
17306 /* ADDI32 */
17307 mips32_op = OPC_ADDI;
17308 goto do_addi;
17310 break;
17311 case ADDIU32:
17312 mips32_op = OPC_ADDIU;
17313 do_addi:
17314 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17315 break;
17317 /* Logical operations */
17318 case ORI32:
17319 mips32_op = OPC_ORI;
17320 goto do_logici;
17321 case XORI32:
17322 mips32_op = OPC_XORI;
17323 goto do_logici;
17324 case ANDI32:
17325 mips32_op = OPC_ANDI;
17326 do_logici:
17327 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17328 break;
17330 /* Set less than immediate */
17331 case SLTI32:
17332 mips32_op = OPC_SLTI;
17333 goto do_slti;
17334 case SLTIU32:
17335 mips32_op = OPC_SLTIU;
17336 do_slti:
17337 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17338 break;
17339 case JALX32:
17340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17341 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17342 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17343 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17344 break;
17345 case JALS32: /* BOVC, BEQC, BEQZALC */
17346 if (ctx->insn_flags & ISA_MIPS32R6) {
17347 if (rs >= rt) {
17348 /* BOVC */
17349 mips32_op = OPC_BOVC;
17350 } else if (rs < rt && rs == 0) {
17351 /* BEQZALC */
17352 mips32_op = OPC_BEQZALC;
17353 } else {
17354 /* BEQC */
17355 mips32_op = OPC_BEQC;
17357 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17358 } else {
17359 /* JALS32 */
17360 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17361 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17362 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17364 break;
17365 case BEQ32: /* BC */
17366 if (ctx->insn_flags & ISA_MIPS32R6) {
17367 /* BC */
17368 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17369 sextract32(ctx->opcode << 1, 0, 27));
17370 } else {
17371 /* BEQ32 */
17372 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17374 break;
17375 case BNE32: /* BALC */
17376 if (ctx->insn_flags & ISA_MIPS32R6) {
17377 /* BALC */
17378 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17379 sextract32(ctx->opcode << 1, 0, 27));
17380 } else {
17381 /* BNE32 */
17382 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17384 break;
17385 case J32: /* BGTZC, BLTZC, BLTC */
17386 if (ctx->insn_flags & ISA_MIPS32R6) {
17387 if (rs == 0 && rt != 0) {
17388 /* BGTZC */
17389 mips32_op = OPC_BGTZC;
17390 } else if (rs != 0 && rt != 0 && rs == rt) {
17391 /* BLTZC */
17392 mips32_op = OPC_BLTZC;
17393 } else {
17394 /* BLTC */
17395 mips32_op = OPC_BLTC;
17397 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17398 } else {
17399 /* J32 */
17400 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17401 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17403 break;
17404 case JAL32: /* BLEZC, BGEZC, BGEC */
17405 if (ctx->insn_flags & ISA_MIPS32R6) {
17406 if (rs == 0 && rt != 0) {
17407 /* BLEZC */
17408 mips32_op = OPC_BLEZC;
17409 } else if (rs != 0 && rt != 0 && rs == rt) {
17410 /* BGEZC */
17411 mips32_op = OPC_BGEZC;
17412 } else {
17413 /* BGEC */
17414 mips32_op = OPC_BGEC;
17416 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17417 } else {
17418 /* JAL32 */
17419 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17420 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17421 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17423 break;
17424 /* Floating point (COP1) */
17425 case LWC132:
17426 mips32_op = OPC_LWC1;
17427 goto do_cop1;
17428 case LDC132:
17429 mips32_op = OPC_LDC1;
17430 goto do_cop1;
17431 case SWC132:
17432 mips32_op = OPC_SWC1;
17433 goto do_cop1;
17434 case SDC132:
17435 mips32_op = OPC_SDC1;
17436 do_cop1:
17437 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17438 break;
17439 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17440 if (ctx->insn_flags & ISA_MIPS32R6) {
17441 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17442 switch ((ctx->opcode >> 16) & 0x1f) {
17443 case ADDIUPC_00:
17444 case ADDIUPC_01:
17445 case ADDIUPC_02:
17446 case ADDIUPC_03:
17447 case ADDIUPC_04:
17448 case ADDIUPC_05:
17449 case ADDIUPC_06:
17450 case ADDIUPC_07:
17451 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17452 break;
17453 case AUIPC:
17454 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17455 break;
17456 case ALUIPC:
17457 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17458 break;
17459 case LWPC_08:
17460 case LWPC_09:
17461 case LWPC_0A:
17462 case LWPC_0B:
17463 case LWPC_0C:
17464 case LWPC_0D:
17465 case LWPC_0E:
17466 case LWPC_0F:
17467 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17468 break;
17469 default:
17470 generate_exception(ctx, EXCP_RI);
17471 break;
17473 } else {
17474 /* ADDIUPC */
17475 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17476 offset = SIMM(ctx->opcode, 0, 23) << 2;
17478 gen_addiupc(ctx, reg, offset, 0, 0);
17480 break;
17481 case BNVC: /* BNEC, BNEZALC */
17482 check_insn(ctx, ISA_MIPS32R6);
17483 if (rs >= rt) {
17484 /* BNVC */
17485 mips32_op = OPC_BNVC;
17486 } else if (rs < rt && rs == 0) {
17487 /* BNEZALC */
17488 mips32_op = OPC_BNEZALC;
17489 } else {
17490 /* BNEC */
17491 mips32_op = OPC_BNEC;
17493 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17494 break;
17495 case R6_BNEZC: /* JIALC */
17496 check_insn(ctx, ISA_MIPS32R6);
17497 if (rt != 0) {
17498 /* BNEZC */
17499 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17500 sextract32(ctx->opcode << 1, 0, 22));
17501 } else {
17502 /* JIALC */
17503 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17505 break;
17506 case R6_BEQZC: /* JIC */
17507 check_insn(ctx, ISA_MIPS32R6);
17508 if (rt != 0) {
17509 /* BEQZC */
17510 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17511 sextract32(ctx->opcode << 1, 0, 22));
17512 } else {
17513 /* JIC */
17514 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17516 break;
17517 case BLEZALC: /* BGEZALC, BGEUC */
17518 check_insn(ctx, ISA_MIPS32R6);
17519 if (rs == 0 && rt != 0) {
17520 /* BLEZALC */
17521 mips32_op = OPC_BLEZALC;
17522 } else if (rs != 0 && rt != 0 && rs == rt) {
17523 /* BGEZALC */
17524 mips32_op = OPC_BGEZALC;
17525 } else {
17526 /* BGEUC */
17527 mips32_op = OPC_BGEUC;
17529 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17530 break;
17531 case BGTZALC: /* BLTZALC, BLTUC */
17532 check_insn(ctx, ISA_MIPS32R6);
17533 if (rs == 0 && rt != 0) {
17534 /* BGTZALC */
17535 mips32_op = OPC_BGTZALC;
17536 } else if (rs != 0 && rt != 0 && rs == rt) {
17537 /* BLTZALC */
17538 mips32_op = OPC_BLTZALC;
17539 } else {
17540 /* BLTUC */
17541 mips32_op = OPC_BLTUC;
17543 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17544 break;
17545 /* Loads and stores */
17546 case LB32:
17547 mips32_op = OPC_LB;
17548 goto do_ld;
17549 case LBU32:
17550 mips32_op = OPC_LBU;
17551 goto do_ld;
17552 case LH32:
17553 mips32_op = OPC_LH;
17554 goto do_ld;
17555 case LHU32:
17556 mips32_op = OPC_LHU;
17557 goto do_ld;
17558 case LW32:
17559 mips32_op = OPC_LW;
17560 goto do_ld;
17561 #ifdef TARGET_MIPS64
17562 case LD32:
17563 check_insn(ctx, ISA_MIPS3);
17564 check_mips_64(ctx);
17565 mips32_op = OPC_LD;
17566 goto do_ld;
17567 case SD32:
17568 check_insn(ctx, ISA_MIPS3);
17569 check_mips_64(ctx);
17570 mips32_op = OPC_SD;
17571 goto do_st;
17572 #endif
17573 case SB32:
17574 mips32_op = OPC_SB;
17575 goto do_st;
17576 case SH32:
17577 mips32_op = OPC_SH;
17578 goto do_st;
17579 case SW32:
17580 mips32_op = OPC_SW;
17581 goto do_st;
17582 do_ld:
17583 gen_ld(ctx, mips32_op, rt, rs, imm);
17584 break;
17585 do_st:
17586 gen_st(ctx, mips32_op, rt, rs, imm);
17587 break;
17588 default:
17589 generate_exception_end(ctx, EXCP_RI);
17590 break;
17594 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17596 uint32_t op;
17598 /* make sure instructions are on a halfword boundary */
17599 if (ctx->base.pc_next & 0x1) {
17600 env->CP0_BadVAddr = ctx->base.pc_next;
17601 generate_exception_end(ctx, EXCP_AdEL);
17602 return 2;
17605 op = (ctx->opcode >> 10) & 0x3f;
17606 /* Enforce properly-sized instructions in a delay slot */
17607 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17608 switch (op & 0x7) { /* MSB-3..MSB-5 */
17609 case 0:
17610 /* POOL32A, POOL32B, POOL32I, POOL32C */
17611 case 4:
17612 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17613 case 5:
17614 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17615 case 6:
17616 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17617 case 7:
17618 /* LB32, LH32, LWC132, LDC132, LW32 */
17619 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17620 generate_exception_end(ctx, EXCP_RI);
17621 return 2;
17623 break;
17624 case 1:
17625 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17626 case 2:
17627 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17628 case 3:
17629 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17630 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17631 generate_exception_end(ctx, EXCP_RI);
17632 return 2;
17634 break;
17638 switch (op) {
17639 case POOL16A:
17641 int rd = mmreg(uMIPS_RD(ctx->opcode));
17642 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17643 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17644 uint32_t opc = 0;
17646 switch (ctx->opcode & 0x1) {
17647 case ADDU16:
17648 opc = OPC_ADDU;
17649 break;
17650 case SUBU16:
17651 opc = OPC_SUBU;
17652 break;
17654 if (ctx->insn_flags & ISA_MIPS32R6) {
17656 * In the Release 6, the register number location in
17657 * the instruction encoding has changed.
17659 gen_arith(ctx, opc, rs1, rd, rs2);
17660 } else {
17661 gen_arith(ctx, opc, rd, rs1, rs2);
17664 break;
17665 case POOL16B:
17667 int rd = mmreg(uMIPS_RD(ctx->opcode));
17668 int rs = mmreg(uMIPS_RS(ctx->opcode));
17669 int amount = (ctx->opcode >> 1) & 0x7;
17670 uint32_t opc = 0;
17671 amount = amount == 0 ? 8 : amount;
17673 switch (ctx->opcode & 0x1) {
17674 case SLL16:
17675 opc = OPC_SLL;
17676 break;
17677 case SRL16:
17678 opc = OPC_SRL;
17679 break;
17682 gen_shift_imm(ctx, opc, rd, rs, amount);
17684 break;
17685 case POOL16C:
17686 if (ctx->insn_flags & ISA_MIPS32R6) {
17687 gen_pool16c_r6_insn(ctx);
17688 } else {
17689 gen_pool16c_insn(ctx);
17691 break;
17692 case LWGP16:
17694 int rd = mmreg(uMIPS_RD(ctx->opcode));
17695 int rb = 28; /* GP */
17696 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17698 gen_ld(ctx, OPC_LW, rd, rb, offset);
17700 break;
17701 case POOL16F:
17702 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17703 if (ctx->opcode & 1) {
17704 generate_exception_end(ctx, EXCP_RI);
17705 } else {
17706 /* MOVEP */
17707 int enc_dest = uMIPS_RD(ctx->opcode);
17708 int enc_rt = uMIPS_RS2(ctx->opcode);
17709 int enc_rs = uMIPS_RS1(ctx->opcode);
17710 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17712 break;
17713 case LBU16:
17715 int rd = mmreg(uMIPS_RD(ctx->opcode));
17716 int rb = mmreg(uMIPS_RS(ctx->opcode));
17717 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17718 offset = (offset == 0xf ? -1 : offset);
17720 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17722 break;
17723 case LHU16:
17725 int rd = mmreg(uMIPS_RD(ctx->opcode));
17726 int rb = mmreg(uMIPS_RS(ctx->opcode));
17727 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17729 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17731 break;
17732 case LWSP16:
17734 int rd = (ctx->opcode >> 5) & 0x1f;
17735 int rb = 29; /* SP */
17736 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17738 gen_ld(ctx, OPC_LW, rd, rb, offset);
17740 break;
17741 case LW16:
17743 int rd = mmreg(uMIPS_RD(ctx->opcode));
17744 int rb = mmreg(uMIPS_RS(ctx->opcode));
17745 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17747 gen_ld(ctx, OPC_LW, rd, rb, offset);
17749 break;
17750 case SB16:
17752 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17753 int rb = mmreg(uMIPS_RS(ctx->opcode));
17754 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17756 gen_st(ctx, OPC_SB, rd, rb, offset);
17758 break;
17759 case SH16:
17761 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17762 int rb = mmreg(uMIPS_RS(ctx->opcode));
17763 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17765 gen_st(ctx, OPC_SH, rd, rb, offset);
17767 break;
17768 case SWSP16:
17770 int rd = (ctx->opcode >> 5) & 0x1f;
17771 int rb = 29; /* SP */
17772 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17774 gen_st(ctx, OPC_SW, rd, rb, offset);
17776 break;
17777 case SW16:
17779 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17780 int rb = mmreg(uMIPS_RS(ctx->opcode));
17781 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17783 gen_st(ctx, OPC_SW, rd, rb, offset);
17785 break;
17786 case MOVE16:
17788 int rd = uMIPS_RD5(ctx->opcode);
17789 int rs = uMIPS_RS5(ctx->opcode);
17791 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17793 break;
17794 case ANDI16:
17795 gen_andi16(ctx);
17796 break;
17797 case POOL16D:
17798 switch (ctx->opcode & 0x1) {
17799 case ADDIUS5:
17800 gen_addius5(ctx);
17801 break;
17802 case ADDIUSP:
17803 gen_addiusp(ctx);
17804 break;
17806 break;
17807 case POOL16E:
17808 switch (ctx->opcode & 0x1) {
17809 case ADDIUR2:
17810 gen_addiur2(ctx);
17811 break;
17812 case ADDIUR1SP:
17813 gen_addiur1sp(ctx);
17814 break;
17816 break;
17817 case B16: /* BC16 */
17818 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17819 sextract32(ctx->opcode, 0, 10) << 1,
17820 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17821 break;
17822 case BNEZ16: /* BNEZC16 */
17823 case BEQZ16: /* BEQZC16 */
17824 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17825 mmreg(uMIPS_RD(ctx->opcode)),
17826 0, sextract32(ctx->opcode, 0, 7) << 1,
17827 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17829 break;
17830 case LI16:
17832 int reg = mmreg(uMIPS_RD(ctx->opcode));
17833 int imm = ZIMM(ctx->opcode, 0, 7);
17835 imm = (imm == 0x7f ? -1 : imm);
17836 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17838 break;
17839 case RES_29:
17840 case RES_31:
17841 case RES_39:
17842 generate_exception_end(ctx, EXCP_RI);
17843 break;
17844 default:
17845 decode_micromips32_opc(env, ctx);
17846 return 4;
17849 return 2;
17854 * nanoMIPS opcodes
17858 /* MAJOR, P16, and P32 pools opcodes */
17859 enum {
17860 NM_P_ADDIU = 0x00,
17861 NM_ADDIUPC = 0x01,
17862 NM_MOVE_BALC = 0x02,
17863 NM_P16_MV = 0x04,
17864 NM_LW16 = 0x05,
17865 NM_BC16 = 0x06,
17866 NM_P16_SR = 0x07,
17868 NM_POOL32A = 0x08,
17869 NM_P_BAL = 0x0a,
17870 NM_P16_SHIFT = 0x0c,
17871 NM_LWSP16 = 0x0d,
17872 NM_BALC16 = 0x0e,
17873 NM_P16_4X4 = 0x0f,
17875 NM_P_GP_W = 0x10,
17876 NM_P_GP_BH = 0x11,
17877 NM_P_J = 0x12,
17878 NM_P16C = 0x14,
17879 NM_LWGP16 = 0x15,
17880 NM_P16_LB = 0x17,
17882 NM_P48I = 0x18,
17883 NM_P16_A1 = 0x1c,
17884 NM_LW4X4 = 0x1d,
17885 NM_P16_LH = 0x1f,
17887 NM_P_U12 = 0x20,
17888 NM_P_LS_U12 = 0x21,
17889 NM_P_BR1 = 0x22,
17890 NM_P16_A2 = 0x24,
17891 NM_SW16 = 0x25,
17892 NM_BEQZC16 = 0x26,
17894 NM_POOL32F = 0x28,
17895 NM_P_LS_S9 = 0x29,
17896 NM_P_BR2 = 0x2a,
17898 NM_P16_ADDU = 0x2c,
17899 NM_SWSP16 = 0x2d,
17900 NM_BNEZC16 = 0x2e,
17901 NM_MOVEP = 0x2f,
17903 NM_POOL32S = 0x30,
17904 NM_P_BRI = 0x32,
17905 NM_LI16 = 0x34,
17906 NM_SWGP16 = 0x35,
17907 NM_P16_BR = 0x36,
17909 NM_P_LUI = 0x38,
17910 NM_ANDI16 = 0x3c,
17911 NM_SW4X4 = 0x3d,
17912 NM_MOVEPREV = 0x3f,
17915 /* POOL32A instruction pool */
17916 enum {
17917 NM_POOL32A0 = 0x00,
17918 NM_SPECIAL2 = 0x01,
17919 NM_COP2_1 = 0x02,
17920 NM_UDI = 0x03,
17921 NM_POOL32A5 = 0x05,
17922 NM_POOL32A7 = 0x07,
17925 /* P.GP.W instruction pool */
17926 enum {
17927 NM_ADDIUGP_W = 0x00,
17928 NM_LWGP = 0x02,
17929 NM_SWGP = 0x03,
17932 /* P48I instruction pool */
17933 enum {
17934 NM_LI48 = 0x00,
17935 NM_ADDIU48 = 0x01,
17936 NM_ADDIUGP48 = 0x02,
17937 NM_ADDIUPC48 = 0x03,
17938 NM_LWPC48 = 0x0b,
17939 NM_SWPC48 = 0x0f,
17942 /* P.U12 instruction pool */
17943 enum {
17944 NM_ORI = 0x00,
17945 NM_XORI = 0x01,
17946 NM_ANDI = 0x02,
17947 NM_P_SR = 0x03,
17948 NM_SLTI = 0x04,
17949 NM_SLTIU = 0x05,
17950 NM_SEQI = 0x06,
17951 NM_ADDIUNEG = 0x08,
17952 NM_P_SHIFT = 0x0c,
17953 NM_P_ROTX = 0x0d,
17954 NM_P_INS = 0x0e,
17955 NM_P_EXT = 0x0f,
17958 /* POOL32F instruction pool */
17959 enum {
17960 NM_POOL32F_0 = 0x00,
17961 NM_POOL32F_3 = 0x03,
17962 NM_POOL32F_5 = 0x05,
17965 /* POOL32S instruction pool */
17966 enum {
17967 NM_POOL32S_0 = 0x00,
17968 NM_POOL32S_4 = 0x04,
17971 /* P.LUI instruction pool */
17972 enum {
17973 NM_LUI = 0x00,
17974 NM_ALUIPC = 0x01,
17977 /* P.GP.BH instruction pool */
17978 enum {
17979 NM_LBGP = 0x00,
17980 NM_SBGP = 0x01,
17981 NM_LBUGP = 0x02,
17982 NM_ADDIUGP_B = 0x03,
17983 NM_P_GP_LH = 0x04,
17984 NM_P_GP_SH = 0x05,
17985 NM_P_GP_CP1 = 0x06,
17988 /* P.LS.U12 instruction pool */
17989 enum {
17990 NM_LB = 0x00,
17991 NM_SB = 0x01,
17992 NM_LBU = 0x02,
17993 NM_P_PREFU12 = 0x03,
17994 NM_LH = 0x04,
17995 NM_SH = 0x05,
17996 NM_LHU = 0x06,
17997 NM_LWU = 0x07,
17998 NM_LW = 0x08,
17999 NM_SW = 0x09,
18000 NM_LWC1 = 0x0a,
18001 NM_SWC1 = 0x0b,
18002 NM_LDC1 = 0x0e,
18003 NM_SDC1 = 0x0f,
18006 /* P.LS.S9 instruction pool */
18007 enum {
18008 NM_P_LS_S0 = 0x00,
18009 NM_P_LS_S1 = 0x01,
18010 NM_P_LS_E0 = 0x02,
18011 NM_P_LS_WM = 0x04,
18012 NM_P_LS_UAWM = 0x05,
18015 /* P.BAL instruction pool */
18016 enum {
18017 NM_BC = 0x00,
18018 NM_BALC = 0x01,
18021 /* P.J instruction pool */
18022 enum {
18023 NM_JALRC = 0x00,
18024 NM_JALRC_HB = 0x01,
18025 NM_P_BALRSC = 0x08,
18028 /* P.BR1 instruction pool */
18029 enum {
18030 NM_BEQC = 0x00,
18031 NM_P_BR3A = 0x01,
18032 NM_BGEC = 0x02,
18033 NM_BGEUC = 0x03,
18036 /* P.BR2 instruction pool */
18037 enum {
18038 NM_BNEC = 0x00,
18039 NM_BLTC = 0x02,
18040 NM_BLTUC = 0x03,
18043 /* P.BRI instruction pool */
18044 enum {
18045 NM_BEQIC = 0x00,
18046 NM_BBEQZC = 0x01,
18047 NM_BGEIC = 0x02,
18048 NM_BGEIUC = 0x03,
18049 NM_BNEIC = 0x04,
18050 NM_BBNEZC = 0x05,
18051 NM_BLTIC = 0x06,
18052 NM_BLTIUC = 0x07,
18055 /* P16.SHIFT instruction pool */
18056 enum {
18057 NM_SLL16 = 0x00,
18058 NM_SRL16 = 0x01,
18061 /* POOL16C instruction pool */
18062 enum {
18063 NM_POOL16C_0 = 0x00,
18064 NM_LWXS16 = 0x01,
18067 /* P16.A1 instruction pool */
18068 enum {
18069 NM_ADDIUR1SP = 0x01,
18072 /* P16.A2 instruction pool */
18073 enum {
18074 NM_ADDIUR2 = 0x00,
18075 NM_P_ADDIURS5 = 0x01,
18078 /* P16.ADDU instruction pool */
18079 enum {
18080 NM_ADDU16 = 0x00,
18081 NM_SUBU16 = 0x01,
18084 /* P16.SR instruction pool */
18085 enum {
18086 NM_SAVE16 = 0x00,
18087 NM_RESTORE_JRC16 = 0x01,
18090 /* P16.4X4 instruction pool */
18091 enum {
18092 NM_ADDU4X4 = 0x00,
18093 NM_MUL4X4 = 0x01,
18096 /* P16.LB instruction pool */
18097 enum {
18098 NM_LB16 = 0x00,
18099 NM_SB16 = 0x01,
18100 NM_LBU16 = 0x02,
18103 /* P16.LH instruction pool */
18104 enum {
18105 NM_LH16 = 0x00,
18106 NM_SH16 = 0x01,
18107 NM_LHU16 = 0x02,
18110 /* P.RI instruction pool */
18111 enum {
18112 NM_SIGRIE = 0x00,
18113 NM_P_SYSCALL = 0x01,
18114 NM_BREAK = 0x02,
18115 NM_SDBBP = 0x03,
18118 /* POOL32A0 instruction pool */
18119 enum {
18120 NM_P_TRAP = 0x00,
18121 NM_SEB = 0x01,
18122 NM_SLLV = 0x02,
18123 NM_MUL = 0x03,
18124 NM_MFC0 = 0x06,
18125 NM_MFHC0 = 0x07,
18126 NM_SEH = 0x09,
18127 NM_SRLV = 0x0a,
18128 NM_MUH = 0x0b,
18129 NM_MTC0 = 0x0e,
18130 NM_MTHC0 = 0x0f,
18131 NM_SRAV = 0x12,
18132 NM_MULU = 0x13,
18133 NM_ROTRV = 0x1a,
18134 NM_MUHU = 0x1b,
18135 NM_ADD = 0x22,
18136 NM_DIV = 0x23,
18137 NM_ADDU = 0x2a,
18138 NM_MOD = 0x2b,
18139 NM_SUB = 0x32,
18140 NM_DIVU = 0x33,
18141 NM_RDHWR = 0x38,
18142 NM_SUBU = 0x3a,
18143 NM_MODU = 0x3b,
18144 NM_P_CMOVE = 0x42,
18145 NM_FORK = 0x45,
18146 NM_MFTR = 0x46,
18147 NM_MFHTR = 0x47,
18148 NM_AND = 0x4a,
18149 NM_YIELD = 0x4d,
18150 NM_MTTR = 0x4e,
18151 NM_MTHTR = 0x4f,
18152 NM_OR = 0x52,
18153 NM_D_E_MT_VPE = 0x56,
18154 NM_NOR = 0x5a,
18155 NM_XOR = 0x62,
18156 NM_SLT = 0x6a,
18157 NM_P_SLTU = 0x72,
18158 NM_SOV = 0x7a,
18161 /* CRC32 instruction pool */
18162 enum {
18163 NM_CRC32B = 0x00,
18164 NM_CRC32H = 0x01,
18165 NM_CRC32W = 0x02,
18166 NM_CRC32CB = 0x04,
18167 NM_CRC32CH = 0x05,
18168 NM_CRC32CW = 0x06,
18171 /* POOL32A5 instruction pool */
18172 enum {
18173 NM_CMP_EQ_PH = 0x00,
18174 NM_CMP_LT_PH = 0x08,
18175 NM_CMP_LE_PH = 0x10,
18176 NM_CMPGU_EQ_QB = 0x18,
18177 NM_CMPGU_LT_QB = 0x20,
18178 NM_CMPGU_LE_QB = 0x28,
18179 NM_CMPGDU_EQ_QB = 0x30,
18180 NM_CMPGDU_LT_QB = 0x38,
18181 NM_CMPGDU_LE_QB = 0x40,
18182 NM_CMPU_EQ_QB = 0x48,
18183 NM_CMPU_LT_QB = 0x50,
18184 NM_CMPU_LE_QB = 0x58,
18185 NM_ADDQ_S_W = 0x60,
18186 NM_SUBQ_S_W = 0x68,
18187 NM_ADDSC = 0x70,
18188 NM_ADDWC = 0x78,
18190 NM_ADDQ_S_PH = 0x01,
18191 NM_ADDQH_R_PH = 0x09,
18192 NM_ADDQH_R_W = 0x11,
18193 NM_ADDU_S_QB = 0x19,
18194 NM_ADDU_S_PH = 0x21,
18195 NM_ADDUH_R_QB = 0x29,
18196 NM_SHRAV_R_PH = 0x31,
18197 NM_SHRAV_R_QB = 0x39,
18198 NM_SUBQ_S_PH = 0x41,
18199 NM_SUBQH_R_PH = 0x49,
18200 NM_SUBQH_R_W = 0x51,
18201 NM_SUBU_S_QB = 0x59,
18202 NM_SUBU_S_PH = 0x61,
18203 NM_SUBUH_R_QB = 0x69,
18204 NM_SHLLV_S_PH = 0x71,
18205 NM_PRECR_SRA_R_PH_W = 0x79,
18207 NM_MULEU_S_PH_QBL = 0x12,
18208 NM_MULEU_S_PH_QBR = 0x1a,
18209 NM_MULQ_RS_PH = 0x22,
18210 NM_MULQ_S_PH = 0x2a,
18211 NM_MULQ_RS_W = 0x32,
18212 NM_MULQ_S_W = 0x3a,
18213 NM_APPEND = 0x42,
18214 NM_MODSUB = 0x52,
18215 NM_SHRAV_R_W = 0x5a,
18216 NM_SHRLV_PH = 0x62,
18217 NM_SHRLV_QB = 0x6a,
18218 NM_SHLLV_QB = 0x72,
18219 NM_SHLLV_S_W = 0x7a,
18221 NM_SHILO = 0x03,
18223 NM_MULEQ_S_W_PHL = 0x04,
18224 NM_MULEQ_S_W_PHR = 0x0c,
18226 NM_MUL_S_PH = 0x05,
18227 NM_PRECR_QB_PH = 0x0d,
18228 NM_PRECRQ_QB_PH = 0x15,
18229 NM_PRECRQ_PH_W = 0x1d,
18230 NM_PRECRQ_RS_PH_W = 0x25,
18231 NM_PRECRQU_S_QB_PH = 0x2d,
18232 NM_PACKRL_PH = 0x35,
18233 NM_PICK_QB = 0x3d,
18234 NM_PICK_PH = 0x45,
18236 NM_SHRA_R_W = 0x5e,
18237 NM_SHRA_R_PH = 0x66,
18238 NM_SHLL_S_PH = 0x76,
18239 NM_SHLL_S_W = 0x7e,
18241 NM_REPL_PH = 0x07
18244 /* POOL32A7 instruction pool */
18245 enum {
18246 NM_P_LSX = 0x00,
18247 NM_LSA = 0x01,
18248 NM_EXTW = 0x03,
18249 NM_POOL32AXF = 0x07,
18252 /* P.SR instruction pool */
18253 enum {
18254 NM_PP_SR = 0x00,
18255 NM_P_SR_F = 0x01,
18258 /* P.SHIFT instruction pool */
18259 enum {
18260 NM_P_SLL = 0x00,
18261 NM_SRL = 0x02,
18262 NM_SRA = 0x04,
18263 NM_ROTR = 0x06,
18266 /* P.ROTX instruction pool */
18267 enum {
18268 NM_ROTX = 0x00,
18271 /* P.INS instruction pool */
18272 enum {
18273 NM_INS = 0x00,
18276 /* P.EXT instruction pool */
18277 enum {
18278 NM_EXT = 0x00,
18281 /* POOL32F_0 (fmt) instruction pool */
18282 enum {
18283 NM_RINT_S = 0x04,
18284 NM_RINT_D = 0x44,
18285 NM_ADD_S = 0x06,
18286 NM_SELEQZ_S = 0x07,
18287 NM_SELEQZ_D = 0x47,
18288 NM_CLASS_S = 0x0c,
18289 NM_CLASS_D = 0x4c,
18290 NM_SUB_S = 0x0e,
18291 NM_SELNEZ_S = 0x0f,
18292 NM_SELNEZ_D = 0x4f,
18293 NM_MUL_S = 0x16,
18294 NM_SEL_S = 0x17,
18295 NM_SEL_D = 0x57,
18296 NM_DIV_S = 0x1e,
18297 NM_ADD_D = 0x26,
18298 NM_SUB_D = 0x2e,
18299 NM_MUL_D = 0x36,
18300 NM_MADDF_S = 0x37,
18301 NM_MADDF_D = 0x77,
18302 NM_DIV_D = 0x3e,
18303 NM_MSUBF_S = 0x3f,
18304 NM_MSUBF_D = 0x7f,
18307 /* POOL32F_3 instruction pool */
18308 enum {
18309 NM_MIN_FMT = 0x00,
18310 NM_MAX_FMT = 0x01,
18311 NM_MINA_FMT = 0x04,
18312 NM_MAXA_FMT = 0x05,
18313 NM_POOL32FXF = 0x07,
18316 /* POOL32F_5 instruction pool */
18317 enum {
18318 NM_CMP_CONDN_S = 0x00,
18319 NM_CMP_CONDN_D = 0x02,
18322 /* P.GP.LH instruction pool */
18323 enum {
18324 NM_LHGP = 0x00,
18325 NM_LHUGP = 0x01,
18328 /* P.GP.SH instruction pool */
18329 enum {
18330 NM_SHGP = 0x00,
18333 /* P.GP.CP1 instruction pool */
18334 enum {
18335 NM_LWC1GP = 0x00,
18336 NM_SWC1GP = 0x01,
18337 NM_LDC1GP = 0x02,
18338 NM_SDC1GP = 0x03,
18341 /* P.LS.S0 instruction pool */
18342 enum {
18343 NM_LBS9 = 0x00,
18344 NM_LHS9 = 0x04,
18345 NM_LWS9 = 0x08,
18346 NM_LDS9 = 0x0c,
18348 NM_SBS9 = 0x01,
18349 NM_SHS9 = 0x05,
18350 NM_SWS9 = 0x09,
18351 NM_SDS9 = 0x0d,
18353 NM_LBUS9 = 0x02,
18354 NM_LHUS9 = 0x06,
18355 NM_LWC1S9 = 0x0a,
18356 NM_LDC1S9 = 0x0e,
18358 NM_P_PREFS9 = 0x03,
18359 NM_LWUS9 = 0x07,
18360 NM_SWC1S9 = 0x0b,
18361 NM_SDC1S9 = 0x0f,
18364 /* P.LS.S1 instruction pool */
18365 enum {
18366 NM_ASET_ACLR = 0x02,
18367 NM_UALH = 0x04,
18368 NM_UASH = 0x05,
18369 NM_CACHE = 0x07,
18370 NM_P_LL = 0x0a,
18371 NM_P_SC = 0x0b,
18374 /* P.LS.E0 instruction pool */
18375 enum {
18376 NM_LBE = 0x00,
18377 NM_SBE = 0x01,
18378 NM_LBUE = 0x02,
18379 NM_P_PREFE = 0x03,
18380 NM_LHE = 0x04,
18381 NM_SHE = 0x05,
18382 NM_LHUE = 0x06,
18383 NM_CACHEE = 0x07,
18384 NM_LWE = 0x08,
18385 NM_SWE = 0x09,
18386 NM_P_LLE = 0x0a,
18387 NM_P_SCE = 0x0b,
18390 /* P.PREFE instruction pool */
18391 enum {
18392 NM_SYNCIE = 0x00,
18393 NM_PREFE = 0x01,
18396 /* P.LLE instruction pool */
18397 enum {
18398 NM_LLE = 0x00,
18399 NM_LLWPE = 0x01,
18402 /* P.SCE instruction pool */
18403 enum {
18404 NM_SCE = 0x00,
18405 NM_SCWPE = 0x01,
18408 /* P.LS.WM instruction pool */
18409 enum {
18410 NM_LWM = 0x00,
18411 NM_SWM = 0x01,
18414 /* P.LS.UAWM instruction pool */
18415 enum {
18416 NM_UALWM = 0x00,
18417 NM_UASWM = 0x01,
18420 /* P.BR3A instruction pool */
18421 enum {
18422 NM_BC1EQZC = 0x00,
18423 NM_BC1NEZC = 0x01,
18424 NM_BC2EQZC = 0x02,
18425 NM_BC2NEZC = 0x03,
18426 NM_BPOSGE32C = 0x04,
18429 /* P16.RI instruction pool */
18430 enum {
18431 NM_P16_SYSCALL = 0x01,
18432 NM_BREAK16 = 0x02,
18433 NM_SDBBP16 = 0x03,
18436 /* POOL16C_0 instruction pool */
18437 enum {
18438 NM_POOL16C_00 = 0x00,
18441 /* P16.JRC instruction pool */
18442 enum {
18443 NM_JRC = 0x00,
18444 NM_JALRC16 = 0x01,
18447 /* P.SYSCALL instruction pool */
18448 enum {
18449 NM_SYSCALL = 0x00,
18450 NM_HYPCALL = 0x01,
18453 /* P.TRAP instruction pool */
18454 enum {
18455 NM_TEQ = 0x00,
18456 NM_TNE = 0x01,
18459 /* P.CMOVE instruction pool */
18460 enum {
18461 NM_MOVZ = 0x00,
18462 NM_MOVN = 0x01,
18465 /* POOL32Axf instruction pool */
18466 enum {
18467 NM_POOL32AXF_1 = 0x01,
18468 NM_POOL32AXF_2 = 0x02,
18469 NM_POOL32AXF_4 = 0x04,
18470 NM_POOL32AXF_5 = 0x05,
18471 NM_POOL32AXF_7 = 0x07,
18474 /* POOL32Axf_1 instruction pool */
18475 enum {
18476 NM_POOL32AXF_1_0 = 0x00,
18477 NM_POOL32AXF_1_1 = 0x01,
18478 NM_POOL32AXF_1_3 = 0x03,
18479 NM_POOL32AXF_1_4 = 0x04,
18480 NM_POOL32AXF_1_5 = 0x05,
18481 NM_POOL32AXF_1_7 = 0x07,
18484 /* POOL32Axf_2 instruction pool */
18485 enum {
18486 NM_POOL32AXF_2_0_7 = 0x00,
18487 NM_POOL32AXF_2_8_15 = 0x01,
18488 NM_POOL32AXF_2_16_23 = 0x02,
18489 NM_POOL32AXF_2_24_31 = 0x03,
18492 /* POOL32Axf_7 instruction pool */
18493 enum {
18494 NM_SHRA_R_QB = 0x0,
18495 NM_SHRL_PH = 0x1,
18496 NM_REPL_QB = 0x2,
18499 /* POOL32Axf_1_0 instruction pool */
18500 enum {
18501 NM_MFHI = 0x0,
18502 NM_MFLO = 0x1,
18503 NM_MTHI = 0x2,
18504 NM_MTLO = 0x3,
18507 /* POOL32Axf_1_1 instruction pool */
18508 enum {
18509 NM_MTHLIP = 0x0,
18510 NM_SHILOV = 0x1,
18513 /* POOL32Axf_1_3 instruction pool */
18514 enum {
18515 NM_RDDSP = 0x0,
18516 NM_WRDSP = 0x1,
18517 NM_EXTP = 0x2,
18518 NM_EXTPDP = 0x3,
18521 /* POOL32Axf_1_4 instruction pool */
18522 enum {
18523 NM_SHLL_QB = 0x0,
18524 NM_SHRL_QB = 0x1,
18527 /* POOL32Axf_1_5 instruction pool */
18528 enum {
18529 NM_MAQ_S_W_PHR = 0x0,
18530 NM_MAQ_S_W_PHL = 0x1,
18531 NM_MAQ_SA_W_PHR = 0x2,
18532 NM_MAQ_SA_W_PHL = 0x3,
18535 /* POOL32Axf_1_7 instruction pool */
18536 enum {
18537 NM_EXTR_W = 0x0,
18538 NM_EXTR_R_W = 0x1,
18539 NM_EXTR_RS_W = 0x2,
18540 NM_EXTR_S_H = 0x3,
18543 /* POOL32Axf_2_0_7 instruction pool */
18544 enum {
18545 NM_DPA_W_PH = 0x0,
18546 NM_DPAQ_S_W_PH = 0x1,
18547 NM_DPS_W_PH = 0x2,
18548 NM_DPSQ_S_W_PH = 0x3,
18549 NM_BALIGN = 0x4,
18550 NM_MADD = 0x5,
18551 NM_MULT = 0x6,
18552 NM_EXTRV_W = 0x7,
18555 /* POOL32Axf_2_8_15 instruction pool */
18556 enum {
18557 NM_DPAX_W_PH = 0x0,
18558 NM_DPAQ_SA_L_W = 0x1,
18559 NM_DPSX_W_PH = 0x2,
18560 NM_DPSQ_SA_L_W = 0x3,
18561 NM_MADDU = 0x5,
18562 NM_MULTU = 0x6,
18563 NM_EXTRV_R_W = 0x7,
18566 /* POOL32Axf_2_16_23 instruction pool */
18567 enum {
18568 NM_DPAU_H_QBL = 0x0,
18569 NM_DPAQX_S_W_PH = 0x1,
18570 NM_DPSU_H_QBL = 0x2,
18571 NM_DPSQX_S_W_PH = 0x3,
18572 NM_EXTPV = 0x4,
18573 NM_MSUB = 0x5,
18574 NM_MULSA_W_PH = 0x6,
18575 NM_EXTRV_RS_W = 0x7,
18578 /* POOL32Axf_2_24_31 instruction pool */
18579 enum {
18580 NM_DPAU_H_QBR = 0x0,
18581 NM_DPAQX_SA_W_PH = 0x1,
18582 NM_DPSU_H_QBR = 0x2,
18583 NM_DPSQX_SA_W_PH = 0x3,
18584 NM_EXTPDPV = 0x4,
18585 NM_MSUBU = 0x5,
18586 NM_MULSAQ_S_W_PH = 0x6,
18587 NM_EXTRV_S_H = 0x7,
18590 /* POOL32Axf_{4, 5} instruction pool */
18591 enum {
18592 NM_CLO = 0x25,
18593 NM_CLZ = 0x2d,
18595 NM_TLBP = 0x01,
18596 NM_TLBR = 0x09,
18597 NM_TLBWI = 0x11,
18598 NM_TLBWR = 0x19,
18599 NM_TLBINV = 0x03,
18600 NM_TLBINVF = 0x0b,
18601 NM_DI = 0x23,
18602 NM_EI = 0x2b,
18603 NM_RDPGPR = 0x70,
18604 NM_WRPGPR = 0x78,
18605 NM_WAIT = 0x61,
18606 NM_DERET = 0x71,
18607 NM_ERETX = 0x79,
18609 /* nanoMIPS DSP instructions */
18610 NM_ABSQ_S_QB = 0x00,
18611 NM_ABSQ_S_PH = 0x08,
18612 NM_ABSQ_S_W = 0x10,
18613 NM_PRECEQ_W_PHL = 0x28,
18614 NM_PRECEQ_W_PHR = 0x30,
18615 NM_PRECEQU_PH_QBL = 0x38,
18616 NM_PRECEQU_PH_QBR = 0x48,
18617 NM_PRECEU_PH_QBL = 0x58,
18618 NM_PRECEU_PH_QBR = 0x68,
18619 NM_PRECEQU_PH_QBLA = 0x39,
18620 NM_PRECEQU_PH_QBRA = 0x49,
18621 NM_PRECEU_PH_QBLA = 0x59,
18622 NM_PRECEU_PH_QBRA = 0x69,
18623 NM_REPLV_PH = 0x01,
18624 NM_REPLV_QB = 0x09,
18625 NM_BITREV = 0x18,
18626 NM_INSV = 0x20,
18627 NM_RADDU_W_QB = 0x78,
18629 NM_BITSWAP = 0x05,
18630 NM_WSBH = 0x3d,
18633 /* PP.SR instruction pool */
18634 enum {
18635 NM_SAVE = 0x00,
18636 NM_RESTORE = 0x02,
18637 NM_RESTORE_JRC = 0x03,
18640 /* P.SR.F instruction pool */
18641 enum {
18642 NM_SAVEF = 0x00,
18643 NM_RESTOREF = 0x01,
18646 /* P16.SYSCALL instruction pool */
18647 enum {
18648 NM_SYSCALL16 = 0x00,
18649 NM_HYPCALL16 = 0x01,
18652 /* POOL16C_00 instruction pool */
18653 enum {
18654 NM_NOT16 = 0x00,
18655 NM_XOR16 = 0x01,
18656 NM_AND16 = 0x02,
18657 NM_OR16 = 0x03,
18660 /* PP.LSX and PP.LSXS instruction pool */
18661 enum {
18662 NM_LBX = 0x00,
18663 NM_LHX = 0x04,
18664 NM_LWX = 0x08,
18665 NM_LDX = 0x0c,
18667 NM_SBX = 0x01,
18668 NM_SHX = 0x05,
18669 NM_SWX = 0x09,
18670 NM_SDX = 0x0d,
18672 NM_LBUX = 0x02,
18673 NM_LHUX = 0x06,
18674 NM_LWC1X = 0x0a,
18675 NM_LDC1X = 0x0e,
18677 NM_LWUX = 0x07,
18678 NM_SWC1X = 0x0b,
18679 NM_SDC1X = 0x0f,
18681 NM_LHXS = 0x04,
18682 NM_LWXS = 0x08,
18683 NM_LDXS = 0x0c,
18685 NM_SHXS = 0x05,
18686 NM_SWXS = 0x09,
18687 NM_SDXS = 0x0d,
18689 NM_LHUXS = 0x06,
18690 NM_LWC1XS = 0x0a,
18691 NM_LDC1XS = 0x0e,
18693 NM_LWUXS = 0x07,
18694 NM_SWC1XS = 0x0b,
18695 NM_SDC1XS = 0x0f,
18698 /* ERETx instruction pool */
18699 enum {
18700 NM_ERET = 0x00,
18701 NM_ERETNC = 0x01,
18704 /* POOL32FxF_{0, 1} insturction pool */
18705 enum {
18706 NM_CFC1 = 0x40,
18707 NM_CTC1 = 0x60,
18708 NM_MFC1 = 0x80,
18709 NM_MTC1 = 0xa0,
18710 NM_MFHC1 = 0xc0,
18711 NM_MTHC1 = 0xe0,
18713 NM_CVT_S_PL = 0x84,
18714 NM_CVT_S_PU = 0xa4,
18716 NM_CVT_L_S = 0x004,
18717 NM_CVT_L_D = 0x104,
18718 NM_CVT_W_S = 0x024,
18719 NM_CVT_W_D = 0x124,
18721 NM_RSQRT_S = 0x008,
18722 NM_RSQRT_D = 0x108,
18724 NM_SQRT_S = 0x028,
18725 NM_SQRT_D = 0x128,
18727 NM_RECIP_S = 0x048,
18728 NM_RECIP_D = 0x148,
18730 NM_FLOOR_L_S = 0x00c,
18731 NM_FLOOR_L_D = 0x10c,
18733 NM_FLOOR_W_S = 0x02c,
18734 NM_FLOOR_W_D = 0x12c,
18736 NM_CEIL_L_S = 0x04c,
18737 NM_CEIL_L_D = 0x14c,
18738 NM_CEIL_W_S = 0x06c,
18739 NM_CEIL_W_D = 0x16c,
18740 NM_TRUNC_L_S = 0x08c,
18741 NM_TRUNC_L_D = 0x18c,
18742 NM_TRUNC_W_S = 0x0ac,
18743 NM_TRUNC_W_D = 0x1ac,
18744 NM_ROUND_L_S = 0x0cc,
18745 NM_ROUND_L_D = 0x1cc,
18746 NM_ROUND_W_S = 0x0ec,
18747 NM_ROUND_W_D = 0x1ec,
18749 NM_MOV_S = 0x01,
18750 NM_MOV_D = 0x81,
18751 NM_ABS_S = 0x0d,
18752 NM_ABS_D = 0x8d,
18753 NM_NEG_S = 0x2d,
18754 NM_NEG_D = 0xad,
18755 NM_CVT_D_S = 0x04d,
18756 NM_CVT_D_W = 0x0cd,
18757 NM_CVT_D_L = 0x14d,
18758 NM_CVT_S_D = 0x06d,
18759 NM_CVT_S_W = 0x0ed,
18760 NM_CVT_S_L = 0x16d,
18763 /* P.LL instruction pool */
18764 enum {
18765 NM_LL = 0x00,
18766 NM_LLWP = 0x01,
18769 /* P.SC instruction pool */
18770 enum {
18771 NM_SC = 0x00,
18772 NM_SCWP = 0x01,
18775 /* P.DVP instruction pool */
18776 enum {
18777 NM_DVP = 0x00,
18778 NM_EVP = 0x01,
18784 * nanoMIPS decoding engine
18789 /* extraction utilities */
18791 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18792 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18793 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18794 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18795 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18797 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18798 static inline int decode_gpr_gpr3(int r)
18800 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18802 return map[r & 0x7];
18805 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18806 static inline int decode_gpr_gpr3_src_store(int r)
18808 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18810 return map[r & 0x7];
18813 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18814 static inline int decode_gpr_gpr4(int r)
18816 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18817 16, 17, 18, 19, 20, 21, 22, 23 };
18819 return map[r & 0xf];
18822 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18823 static inline int decode_gpr_gpr4_zero(int r)
18825 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18826 16, 17, 18, 19, 20, 21, 22, 23 };
18828 return map[r & 0xf];
18832 static void gen_adjust_sp(DisasContext *ctx, int u)
18834 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18837 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18838 uint8_t gp, uint16_t u)
18840 int counter = 0;
18841 TCGv va = tcg_temp_new();
18842 TCGv t0 = tcg_temp_new();
18844 while (counter != count) {
18845 bool use_gp = gp && (counter == count - 1);
18846 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18847 int this_offset = -((counter + 1) << 2);
18848 gen_base_offset_addr(ctx, va, 29, this_offset);
18849 gen_load_gpr(t0, this_rt);
18850 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18851 (MO_TEUL | ctx->default_tcg_memop_mask));
18852 counter++;
18855 /* adjust stack pointer */
18856 gen_adjust_sp(ctx, -u);
18858 tcg_temp_free(t0);
18859 tcg_temp_free(va);
18862 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18863 uint8_t gp, uint16_t u)
18865 int counter = 0;
18866 TCGv va = tcg_temp_new();
18867 TCGv t0 = tcg_temp_new();
18869 while (counter != count) {
18870 bool use_gp = gp && (counter == count - 1);
18871 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18872 int this_offset = u - ((counter + 1) << 2);
18873 gen_base_offset_addr(ctx, va, 29, this_offset);
18874 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18875 ctx->default_tcg_memop_mask);
18876 tcg_gen_ext32s_tl(t0, t0);
18877 gen_store_gpr(t0, this_rt);
18878 counter++;
18881 /* adjust stack pointer */
18882 gen_adjust_sp(ctx, u);
18884 tcg_temp_free(t0);
18885 tcg_temp_free(va);
18888 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18890 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18891 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18893 switch (extract32(ctx->opcode, 2, 2)) {
18894 case NM_NOT16:
18895 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18896 break;
18897 case NM_AND16:
18898 gen_logic(ctx, OPC_AND, rt, rt, rs);
18899 break;
18900 case NM_XOR16:
18901 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18902 break;
18903 case NM_OR16:
18904 gen_logic(ctx, OPC_OR, rt, rt, rs);
18905 break;
18909 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18911 int rt = extract32(ctx->opcode, 21, 5);
18912 int rs = extract32(ctx->opcode, 16, 5);
18913 int rd = extract32(ctx->opcode, 11, 5);
18915 switch (extract32(ctx->opcode, 3, 7)) {
18916 case NM_P_TRAP:
18917 switch (extract32(ctx->opcode, 10, 1)) {
18918 case NM_TEQ:
18919 check_nms(ctx);
18920 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18921 break;
18922 case NM_TNE:
18923 check_nms(ctx);
18924 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18925 break;
18927 break;
18928 case NM_RDHWR:
18929 check_nms(ctx);
18930 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18931 break;
18932 case NM_SEB:
18933 check_nms(ctx);
18934 gen_bshfl(ctx, OPC_SEB, rs, rt);
18935 break;
18936 case NM_SEH:
18937 gen_bshfl(ctx, OPC_SEH, rs, rt);
18938 break;
18939 case NM_SLLV:
18940 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18941 break;
18942 case NM_SRLV:
18943 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18944 break;
18945 case NM_SRAV:
18946 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18947 break;
18948 case NM_ROTRV:
18949 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18950 break;
18951 case NM_ADD:
18952 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18953 break;
18954 case NM_ADDU:
18955 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18956 break;
18957 case NM_SUB:
18958 check_nms(ctx);
18959 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18960 break;
18961 case NM_SUBU:
18962 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18963 break;
18964 case NM_P_CMOVE:
18965 switch (extract32(ctx->opcode, 10, 1)) {
18966 case NM_MOVZ:
18967 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18968 break;
18969 case NM_MOVN:
18970 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18971 break;
18973 break;
18974 case NM_AND:
18975 gen_logic(ctx, OPC_AND, rd, rs, rt);
18976 break;
18977 case NM_OR:
18978 gen_logic(ctx, OPC_OR, rd, rs, rt);
18979 break;
18980 case NM_NOR:
18981 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18982 break;
18983 case NM_XOR:
18984 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18985 break;
18986 case NM_SLT:
18987 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18988 break;
18989 case NM_P_SLTU:
18990 if (rd == 0) {
18991 /* P_DVP */
18992 #ifndef CONFIG_USER_ONLY
18993 TCGv t0 = tcg_temp_new();
18994 switch (extract32(ctx->opcode, 10, 1)) {
18995 case NM_DVP:
18996 if (ctx->vp) {
18997 check_cp0_enabled(ctx);
18998 gen_helper_dvp(t0, cpu_env);
18999 gen_store_gpr(t0, rt);
19001 break;
19002 case NM_EVP:
19003 if (ctx->vp) {
19004 check_cp0_enabled(ctx);
19005 gen_helper_evp(t0, cpu_env);
19006 gen_store_gpr(t0, rt);
19008 break;
19010 tcg_temp_free(t0);
19011 #endif
19012 } else {
19013 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19015 break;
19016 case NM_SOV:
19018 TCGv t0 = tcg_temp_new();
19019 TCGv t1 = tcg_temp_new();
19020 TCGv t2 = tcg_temp_new();
19022 gen_load_gpr(t1, rs);
19023 gen_load_gpr(t2, rt);
19024 tcg_gen_add_tl(t0, t1, t2);
19025 tcg_gen_ext32s_tl(t0, t0);
19026 tcg_gen_xor_tl(t1, t1, t2);
19027 tcg_gen_xor_tl(t2, t0, t2);
19028 tcg_gen_andc_tl(t1, t2, t1);
19030 /* operands of same sign, result different sign */
19031 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19032 gen_store_gpr(t0, rd);
19034 tcg_temp_free(t0);
19035 tcg_temp_free(t1);
19036 tcg_temp_free(t2);
19038 break;
19039 case NM_MUL:
19040 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19041 break;
19042 case NM_MUH:
19043 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19044 break;
19045 case NM_MULU:
19046 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19047 break;
19048 case NM_MUHU:
19049 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19050 break;
19051 case NM_DIV:
19052 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19053 break;
19054 case NM_MOD:
19055 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19056 break;
19057 case NM_DIVU:
19058 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19059 break;
19060 case NM_MODU:
19061 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19062 break;
19063 #ifndef CONFIG_USER_ONLY
19064 case NM_MFC0:
19065 check_cp0_enabled(ctx);
19066 if (rt == 0) {
19067 /* Treat as NOP. */
19068 break;
19070 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19071 break;
19072 case NM_MTC0:
19073 check_cp0_enabled(ctx);
19075 TCGv t0 = tcg_temp_new();
19077 gen_load_gpr(t0, rt);
19078 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19079 tcg_temp_free(t0);
19081 break;
19082 case NM_D_E_MT_VPE:
19084 uint8_t sc = extract32(ctx->opcode, 10, 1);
19085 TCGv t0 = tcg_temp_new();
19087 switch (sc) {
19088 case 0:
19089 if (rs == 1) {
19090 /* DMT */
19091 check_cp0_mt(ctx);
19092 gen_helper_dmt(t0);
19093 gen_store_gpr(t0, rt);
19094 } else if (rs == 0) {
19095 /* DVPE */
19096 check_cp0_mt(ctx);
19097 gen_helper_dvpe(t0, cpu_env);
19098 gen_store_gpr(t0, rt);
19099 } else {
19100 generate_exception_end(ctx, EXCP_RI);
19102 break;
19103 case 1:
19104 if (rs == 1) {
19105 /* EMT */
19106 check_cp0_mt(ctx);
19107 gen_helper_emt(t0);
19108 gen_store_gpr(t0, rt);
19109 } else if (rs == 0) {
19110 /* EVPE */
19111 check_cp0_mt(ctx);
19112 gen_helper_evpe(t0, cpu_env);
19113 gen_store_gpr(t0, rt);
19114 } else {
19115 generate_exception_end(ctx, EXCP_RI);
19117 break;
19120 tcg_temp_free(t0);
19122 break;
19123 case NM_FORK:
19124 check_mt(ctx);
19126 TCGv t0 = tcg_temp_new();
19127 TCGv t1 = tcg_temp_new();
19129 gen_load_gpr(t0, rt);
19130 gen_load_gpr(t1, rs);
19131 gen_helper_fork(t0, t1);
19132 tcg_temp_free(t0);
19133 tcg_temp_free(t1);
19135 break;
19136 case NM_MFTR:
19137 case NM_MFHTR:
19138 check_cp0_enabled(ctx);
19139 if (rd == 0) {
19140 /* Treat as NOP. */
19141 return;
19143 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19144 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19145 break;
19146 case NM_MTTR:
19147 case NM_MTHTR:
19148 check_cp0_enabled(ctx);
19149 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19150 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19151 break;
19152 case NM_YIELD:
19153 check_mt(ctx);
19155 TCGv t0 = tcg_temp_new();
19157 gen_load_gpr(t0, rs);
19158 gen_helper_yield(t0, cpu_env, t0);
19159 gen_store_gpr(t0, rt);
19160 tcg_temp_free(t0);
19162 break;
19163 #endif
19164 default:
19165 generate_exception_end(ctx, EXCP_RI);
19166 break;
19170 /* dsp */
19171 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19172 int ret, int v1, int v2)
19174 TCGv_i32 t0;
19175 TCGv v0_t;
19176 TCGv v1_t;
19178 t0 = tcg_temp_new_i32();
19180 v0_t = tcg_temp_new();
19181 v1_t = tcg_temp_new();
19183 tcg_gen_movi_i32(t0, v2 >> 3);
19185 gen_load_gpr(v0_t, ret);
19186 gen_load_gpr(v1_t, v1);
19188 switch (opc) {
19189 case NM_MAQ_S_W_PHR:
19190 check_dsp(ctx);
19191 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19192 break;
19193 case NM_MAQ_S_W_PHL:
19194 check_dsp(ctx);
19195 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19196 break;
19197 case NM_MAQ_SA_W_PHR:
19198 check_dsp(ctx);
19199 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19200 break;
19201 case NM_MAQ_SA_W_PHL:
19202 check_dsp(ctx);
19203 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19204 break;
19205 default:
19206 generate_exception_end(ctx, EXCP_RI);
19207 break;
19210 tcg_temp_free_i32(t0);
19212 tcg_temp_free(v0_t);
19213 tcg_temp_free(v1_t);
19217 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19218 int ret, int v1, int v2)
19220 int16_t imm;
19221 TCGv t0 = tcg_temp_new();
19222 TCGv t1 = tcg_temp_new();
19223 TCGv v0_t = tcg_temp_new();
19225 gen_load_gpr(v0_t, v1);
19227 switch (opc) {
19228 case NM_POOL32AXF_1_0:
19229 check_dsp(ctx);
19230 switch (extract32(ctx->opcode, 12, 2)) {
19231 case NM_MFHI:
19232 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19233 break;
19234 case NM_MFLO:
19235 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19236 break;
19237 case NM_MTHI:
19238 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19239 break;
19240 case NM_MTLO:
19241 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19242 break;
19244 break;
19245 case NM_POOL32AXF_1_1:
19246 check_dsp(ctx);
19247 switch (extract32(ctx->opcode, 12, 2)) {
19248 case NM_MTHLIP:
19249 tcg_gen_movi_tl(t0, v2);
19250 gen_helper_mthlip(t0, v0_t, cpu_env);
19251 break;
19252 case NM_SHILOV:
19253 tcg_gen_movi_tl(t0, v2 >> 3);
19254 gen_helper_shilo(t0, v0_t, cpu_env);
19255 break;
19256 default:
19257 generate_exception_end(ctx, EXCP_RI);
19258 break;
19260 break;
19261 case NM_POOL32AXF_1_3:
19262 check_dsp(ctx);
19263 imm = extract32(ctx->opcode, 14, 7);
19264 switch (extract32(ctx->opcode, 12, 2)) {
19265 case NM_RDDSP:
19266 tcg_gen_movi_tl(t0, imm);
19267 gen_helper_rddsp(t0, t0, cpu_env);
19268 gen_store_gpr(t0, ret);
19269 break;
19270 case NM_WRDSP:
19271 gen_load_gpr(t0, ret);
19272 tcg_gen_movi_tl(t1, imm);
19273 gen_helper_wrdsp(t0, t1, cpu_env);
19274 break;
19275 case NM_EXTP:
19276 tcg_gen_movi_tl(t0, v2 >> 3);
19277 tcg_gen_movi_tl(t1, v1);
19278 gen_helper_extp(t0, t0, t1, cpu_env);
19279 gen_store_gpr(t0, ret);
19280 break;
19281 case NM_EXTPDP:
19282 tcg_gen_movi_tl(t0, v2 >> 3);
19283 tcg_gen_movi_tl(t1, v1);
19284 gen_helper_extpdp(t0, t0, t1, cpu_env);
19285 gen_store_gpr(t0, ret);
19286 break;
19288 break;
19289 case NM_POOL32AXF_1_4:
19290 check_dsp(ctx);
19291 tcg_gen_movi_tl(t0, v2 >> 2);
19292 switch (extract32(ctx->opcode, 12, 1)) {
19293 case NM_SHLL_QB:
19294 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19295 gen_store_gpr(t0, ret);
19296 break;
19297 case NM_SHRL_QB:
19298 gen_helper_shrl_qb(t0, t0, v0_t);
19299 gen_store_gpr(t0, ret);
19300 break;
19302 break;
19303 case NM_POOL32AXF_1_5:
19304 opc = extract32(ctx->opcode, 12, 2);
19305 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19306 break;
19307 case NM_POOL32AXF_1_7:
19308 check_dsp(ctx);
19309 tcg_gen_movi_tl(t0, v2 >> 3);
19310 tcg_gen_movi_tl(t1, v1);
19311 switch (extract32(ctx->opcode, 12, 2)) {
19312 case NM_EXTR_W:
19313 gen_helper_extr_w(t0, t0, t1, cpu_env);
19314 gen_store_gpr(t0, ret);
19315 break;
19316 case NM_EXTR_R_W:
19317 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19318 gen_store_gpr(t0, ret);
19319 break;
19320 case NM_EXTR_RS_W:
19321 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19322 gen_store_gpr(t0, ret);
19323 break;
19324 case NM_EXTR_S_H:
19325 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19326 gen_store_gpr(t0, ret);
19327 break;
19329 break;
19330 default:
19331 generate_exception_end(ctx, EXCP_RI);
19332 break;
19335 tcg_temp_free(t0);
19336 tcg_temp_free(t1);
19337 tcg_temp_free(v0_t);
19340 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19341 TCGv v0, TCGv v1, int rd)
19343 TCGv_i32 t0;
19345 t0 = tcg_temp_new_i32();
19347 tcg_gen_movi_i32(t0, rd >> 3);
19349 switch (opc) {
19350 case NM_POOL32AXF_2_0_7:
19351 switch (extract32(ctx->opcode, 9, 3)) {
19352 case NM_DPA_W_PH:
19353 check_dsp_r2(ctx);
19354 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19355 break;
19356 case NM_DPAQ_S_W_PH:
19357 check_dsp(ctx);
19358 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19359 break;
19360 case NM_DPS_W_PH:
19361 check_dsp_r2(ctx);
19362 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19363 break;
19364 case NM_DPSQ_S_W_PH:
19365 check_dsp(ctx);
19366 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19367 break;
19368 default:
19369 generate_exception_end(ctx, EXCP_RI);
19370 break;
19372 break;
19373 case NM_POOL32AXF_2_8_15:
19374 switch (extract32(ctx->opcode, 9, 3)) {
19375 case NM_DPAX_W_PH:
19376 check_dsp_r2(ctx);
19377 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19378 break;
19379 case NM_DPAQ_SA_L_W:
19380 check_dsp(ctx);
19381 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19382 break;
19383 case NM_DPSX_W_PH:
19384 check_dsp_r2(ctx);
19385 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19386 break;
19387 case NM_DPSQ_SA_L_W:
19388 check_dsp(ctx);
19389 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19390 break;
19391 default:
19392 generate_exception_end(ctx, EXCP_RI);
19393 break;
19395 break;
19396 case NM_POOL32AXF_2_16_23:
19397 switch (extract32(ctx->opcode, 9, 3)) {
19398 case NM_DPAU_H_QBL:
19399 check_dsp(ctx);
19400 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19401 break;
19402 case NM_DPAQX_S_W_PH:
19403 check_dsp_r2(ctx);
19404 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19405 break;
19406 case NM_DPSU_H_QBL:
19407 check_dsp(ctx);
19408 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19409 break;
19410 case NM_DPSQX_S_W_PH:
19411 check_dsp_r2(ctx);
19412 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19413 break;
19414 case NM_MULSA_W_PH:
19415 check_dsp_r2(ctx);
19416 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19417 break;
19418 default:
19419 generate_exception_end(ctx, EXCP_RI);
19420 break;
19422 break;
19423 case NM_POOL32AXF_2_24_31:
19424 switch (extract32(ctx->opcode, 9, 3)) {
19425 case NM_DPAU_H_QBR:
19426 check_dsp(ctx);
19427 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19428 break;
19429 case NM_DPAQX_SA_W_PH:
19430 check_dsp_r2(ctx);
19431 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19432 break;
19433 case NM_DPSU_H_QBR:
19434 check_dsp(ctx);
19435 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19436 break;
19437 case NM_DPSQX_SA_W_PH:
19438 check_dsp_r2(ctx);
19439 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19440 break;
19441 case NM_MULSAQ_S_W_PH:
19442 check_dsp(ctx);
19443 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19444 break;
19445 default:
19446 generate_exception_end(ctx, EXCP_RI);
19447 break;
19449 break;
19450 default:
19451 generate_exception_end(ctx, EXCP_RI);
19452 break;
19455 tcg_temp_free_i32(t0);
19458 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19459 int rt, int rs, int rd)
19461 int ret = rt;
19462 TCGv t0 = tcg_temp_new();
19463 TCGv t1 = tcg_temp_new();
19464 TCGv v0_t = tcg_temp_new();
19465 TCGv v1_t = tcg_temp_new();
19467 gen_load_gpr(v0_t, rt);
19468 gen_load_gpr(v1_t, rs);
19470 switch (opc) {
19471 case NM_POOL32AXF_2_0_7:
19472 switch (extract32(ctx->opcode, 9, 3)) {
19473 case NM_DPA_W_PH:
19474 case NM_DPAQ_S_W_PH:
19475 case NM_DPS_W_PH:
19476 case NM_DPSQ_S_W_PH:
19477 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19478 break;
19479 case NM_BALIGN:
19480 check_dsp_r2(ctx);
19481 if (rt != 0) {
19482 gen_load_gpr(t0, rs);
19483 rd &= 3;
19484 if (rd != 0 && rd != 2) {
19485 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19486 tcg_gen_ext32u_tl(t0, t0);
19487 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19488 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19490 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19492 break;
19493 case NM_MADD:
19494 check_dsp(ctx);
19496 int acc = extract32(ctx->opcode, 14, 2);
19497 TCGv_i64 t2 = tcg_temp_new_i64();
19498 TCGv_i64 t3 = tcg_temp_new_i64();
19500 gen_load_gpr(t0, rt);
19501 gen_load_gpr(t1, rs);
19502 tcg_gen_ext_tl_i64(t2, t0);
19503 tcg_gen_ext_tl_i64(t3, t1);
19504 tcg_gen_mul_i64(t2, t2, t3);
19505 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19506 tcg_gen_add_i64(t2, t2, t3);
19507 tcg_temp_free_i64(t3);
19508 gen_move_low32(cpu_LO[acc], t2);
19509 gen_move_high32(cpu_HI[acc], t2);
19510 tcg_temp_free_i64(t2);
19512 break;
19513 case NM_MULT:
19514 check_dsp(ctx);
19516 int acc = extract32(ctx->opcode, 14, 2);
19517 TCGv_i32 t2 = tcg_temp_new_i32();
19518 TCGv_i32 t3 = tcg_temp_new_i32();
19520 gen_load_gpr(t0, rs);
19521 gen_load_gpr(t1, rt);
19522 tcg_gen_trunc_tl_i32(t2, t0);
19523 tcg_gen_trunc_tl_i32(t3, t1);
19524 tcg_gen_muls2_i32(t2, t3, t2, t3);
19525 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19526 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19527 tcg_temp_free_i32(t2);
19528 tcg_temp_free_i32(t3);
19530 break;
19531 case NM_EXTRV_W:
19532 check_dsp(ctx);
19533 gen_load_gpr(v1_t, rs);
19534 tcg_gen_movi_tl(t0, rd >> 3);
19535 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19536 gen_store_gpr(t0, ret);
19537 break;
19539 break;
19540 case NM_POOL32AXF_2_8_15:
19541 switch (extract32(ctx->opcode, 9, 3)) {
19542 case NM_DPAX_W_PH:
19543 case NM_DPAQ_SA_L_W:
19544 case NM_DPSX_W_PH:
19545 case NM_DPSQ_SA_L_W:
19546 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19547 break;
19548 case NM_MADDU:
19549 check_dsp(ctx);
19551 int acc = extract32(ctx->opcode, 14, 2);
19552 TCGv_i64 t2 = tcg_temp_new_i64();
19553 TCGv_i64 t3 = tcg_temp_new_i64();
19555 gen_load_gpr(t0, rs);
19556 gen_load_gpr(t1, rt);
19557 tcg_gen_ext32u_tl(t0, t0);
19558 tcg_gen_ext32u_tl(t1, t1);
19559 tcg_gen_extu_tl_i64(t2, t0);
19560 tcg_gen_extu_tl_i64(t3, t1);
19561 tcg_gen_mul_i64(t2, t2, t3);
19562 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19563 tcg_gen_add_i64(t2, t2, t3);
19564 tcg_temp_free_i64(t3);
19565 gen_move_low32(cpu_LO[acc], t2);
19566 gen_move_high32(cpu_HI[acc], t2);
19567 tcg_temp_free_i64(t2);
19569 break;
19570 case NM_MULTU:
19571 check_dsp(ctx);
19573 int acc = extract32(ctx->opcode, 14, 2);
19574 TCGv_i32 t2 = tcg_temp_new_i32();
19575 TCGv_i32 t3 = tcg_temp_new_i32();
19577 gen_load_gpr(t0, rs);
19578 gen_load_gpr(t1, rt);
19579 tcg_gen_trunc_tl_i32(t2, t0);
19580 tcg_gen_trunc_tl_i32(t3, t1);
19581 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19582 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19583 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19584 tcg_temp_free_i32(t2);
19585 tcg_temp_free_i32(t3);
19587 break;
19588 case NM_EXTRV_R_W:
19589 check_dsp(ctx);
19590 tcg_gen_movi_tl(t0, rd >> 3);
19591 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19592 gen_store_gpr(t0, ret);
19593 break;
19594 default:
19595 generate_exception_end(ctx, EXCP_RI);
19596 break;
19598 break;
19599 case NM_POOL32AXF_2_16_23:
19600 switch (extract32(ctx->opcode, 9, 3)) {
19601 case NM_DPAU_H_QBL:
19602 case NM_DPAQX_S_W_PH:
19603 case NM_DPSU_H_QBL:
19604 case NM_DPSQX_S_W_PH:
19605 case NM_MULSA_W_PH:
19606 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19607 break;
19608 case NM_EXTPV:
19609 check_dsp(ctx);
19610 tcg_gen_movi_tl(t0, rd >> 3);
19611 gen_helper_extp(t0, t0, v1_t, cpu_env);
19612 gen_store_gpr(t0, ret);
19613 break;
19614 case NM_MSUB:
19615 check_dsp(ctx);
19617 int acc = extract32(ctx->opcode, 14, 2);
19618 TCGv_i64 t2 = tcg_temp_new_i64();
19619 TCGv_i64 t3 = tcg_temp_new_i64();
19621 gen_load_gpr(t0, rs);
19622 gen_load_gpr(t1, rt);
19623 tcg_gen_ext_tl_i64(t2, t0);
19624 tcg_gen_ext_tl_i64(t3, t1);
19625 tcg_gen_mul_i64(t2, t2, t3);
19626 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19627 tcg_gen_sub_i64(t2, t3, t2);
19628 tcg_temp_free_i64(t3);
19629 gen_move_low32(cpu_LO[acc], t2);
19630 gen_move_high32(cpu_HI[acc], t2);
19631 tcg_temp_free_i64(t2);
19633 break;
19634 case NM_EXTRV_RS_W:
19635 check_dsp(ctx);
19636 tcg_gen_movi_tl(t0, rd >> 3);
19637 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19638 gen_store_gpr(t0, ret);
19639 break;
19641 break;
19642 case NM_POOL32AXF_2_24_31:
19643 switch (extract32(ctx->opcode, 9, 3)) {
19644 case NM_DPAU_H_QBR:
19645 case NM_DPAQX_SA_W_PH:
19646 case NM_DPSU_H_QBR:
19647 case NM_DPSQX_SA_W_PH:
19648 case NM_MULSAQ_S_W_PH:
19649 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19650 break;
19651 case NM_EXTPDPV:
19652 check_dsp(ctx);
19653 tcg_gen_movi_tl(t0, rd >> 3);
19654 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19655 gen_store_gpr(t0, ret);
19656 break;
19657 case NM_MSUBU:
19658 check_dsp(ctx);
19660 int acc = extract32(ctx->opcode, 14, 2);
19661 TCGv_i64 t2 = tcg_temp_new_i64();
19662 TCGv_i64 t3 = tcg_temp_new_i64();
19664 gen_load_gpr(t0, rs);
19665 gen_load_gpr(t1, rt);
19666 tcg_gen_ext32u_tl(t0, t0);
19667 tcg_gen_ext32u_tl(t1, t1);
19668 tcg_gen_extu_tl_i64(t2, t0);
19669 tcg_gen_extu_tl_i64(t3, t1);
19670 tcg_gen_mul_i64(t2, t2, t3);
19671 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19672 tcg_gen_sub_i64(t2, t3, t2);
19673 tcg_temp_free_i64(t3);
19674 gen_move_low32(cpu_LO[acc], t2);
19675 gen_move_high32(cpu_HI[acc], t2);
19676 tcg_temp_free_i64(t2);
19678 break;
19679 case NM_EXTRV_S_H:
19680 check_dsp(ctx);
19681 tcg_gen_movi_tl(t0, rd >> 3);
19682 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19683 gen_store_gpr(t0, ret);
19684 break;
19686 break;
19687 default:
19688 generate_exception_end(ctx, EXCP_RI);
19689 break;
19692 tcg_temp_free(t0);
19693 tcg_temp_free(t1);
19695 tcg_temp_free(v0_t);
19696 tcg_temp_free(v1_t);
19699 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19700 int rt, int rs)
19702 int ret = rt;
19703 TCGv t0 = tcg_temp_new();
19704 TCGv v0_t = tcg_temp_new();
19706 gen_load_gpr(v0_t, rs);
19708 switch (opc) {
19709 case NM_ABSQ_S_QB:
19710 check_dsp_r2(ctx);
19711 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19712 gen_store_gpr(v0_t, ret);
19713 break;
19714 case NM_ABSQ_S_PH:
19715 check_dsp(ctx);
19716 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19717 gen_store_gpr(v0_t, ret);
19718 break;
19719 case NM_ABSQ_S_W:
19720 check_dsp(ctx);
19721 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19722 gen_store_gpr(v0_t, ret);
19723 break;
19724 case NM_PRECEQ_W_PHL:
19725 check_dsp(ctx);
19726 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19727 tcg_gen_ext32s_tl(v0_t, v0_t);
19728 gen_store_gpr(v0_t, ret);
19729 break;
19730 case NM_PRECEQ_W_PHR:
19731 check_dsp(ctx);
19732 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19733 tcg_gen_shli_tl(v0_t, v0_t, 16);
19734 tcg_gen_ext32s_tl(v0_t, v0_t);
19735 gen_store_gpr(v0_t, ret);
19736 break;
19737 case NM_PRECEQU_PH_QBL:
19738 check_dsp(ctx);
19739 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19740 gen_store_gpr(v0_t, ret);
19741 break;
19742 case NM_PRECEQU_PH_QBR:
19743 check_dsp(ctx);
19744 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19745 gen_store_gpr(v0_t, ret);
19746 break;
19747 case NM_PRECEQU_PH_QBLA:
19748 check_dsp(ctx);
19749 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19750 gen_store_gpr(v0_t, ret);
19751 break;
19752 case NM_PRECEQU_PH_QBRA:
19753 check_dsp(ctx);
19754 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19755 gen_store_gpr(v0_t, ret);
19756 break;
19757 case NM_PRECEU_PH_QBL:
19758 check_dsp(ctx);
19759 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19760 gen_store_gpr(v0_t, ret);
19761 break;
19762 case NM_PRECEU_PH_QBR:
19763 check_dsp(ctx);
19764 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19765 gen_store_gpr(v0_t, ret);
19766 break;
19767 case NM_PRECEU_PH_QBLA:
19768 check_dsp(ctx);
19769 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19770 gen_store_gpr(v0_t, ret);
19771 break;
19772 case NM_PRECEU_PH_QBRA:
19773 check_dsp(ctx);
19774 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19775 gen_store_gpr(v0_t, ret);
19776 break;
19777 case NM_REPLV_PH:
19778 check_dsp(ctx);
19779 tcg_gen_ext16u_tl(v0_t, v0_t);
19780 tcg_gen_shli_tl(t0, v0_t, 16);
19781 tcg_gen_or_tl(v0_t, v0_t, t0);
19782 tcg_gen_ext32s_tl(v0_t, v0_t);
19783 gen_store_gpr(v0_t, ret);
19784 break;
19785 case NM_REPLV_QB:
19786 check_dsp(ctx);
19787 tcg_gen_ext8u_tl(v0_t, v0_t);
19788 tcg_gen_shli_tl(t0, v0_t, 8);
19789 tcg_gen_or_tl(v0_t, v0_t, t0);
19790 tcg_gen_shli_tl(t0, v0_t, 16);
19791 tcg_gen_or_tl(v0_t, v0_t, t0);
19792 tcg_gen_ext32s_tl(v0_t, v0_t);
19793 gen_store_gpr(v0_t, ret);
19794 break;
19795 case NM_BITREV:
19796 check_dsp(ctx);
19797 gen_helper_bitrev(v0_t, v0_t);
19798 gen_store_gpr(v0_t, ret);
19799 break;
19800 case NM_INSV:
19801 check_dsp(ctx);
19803 TCGv tv0 = tcg_temp_new();
19805 gen_load_gpr(tv0, rt);
19806 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19807 gen_store_gpr(v0_t, ret);
19808 tcg_temp_free(tv0);
19810 break;
19811 case NM_RADDU_W_QB:
19812 check_dsp(ctx);
19813 gen_helper_raddu_w_qb(v0_t, v0_t);
19814 gen_store_gpr(v0_t, ret);
19815 break;
19816 case NM_BITSWAP:
19817 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19818 break;
19819 case NM_CLO:
19820 check_nms(ctx);
19821 gen_cl(ctx, OPC_CLO, ret, rs);
19822 break;
19823 case NM_CLZ:
19824 check_nms(ctx);
19825 gen_cl(ctx, OPC_CLZ, ret, rs);
19826 break;
19827 case NM_WSBH:
19828 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19829 break;
19830 default:
19831 generate_exception_end(ctx, EXCP_RI);
19832 break;
19835 tcg_temp_free(v0_t);
19836 tcg_temp_free(t0);
19839 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19840 int rt, int rs, int rd)
19842 TCGv t0 = tcg_temp_new();
19843 TCGv rs_t = tcg_temp_new();
19845 gen_load_gpr(rs_t, rs);
19847 switch (opc) {
19848 case NM_SHRA_R_QB:
19849 check_dsp_r2(ctx);
19850 tcg_gen_movi_tl(t0, rd >> 2);
19851 switch (extract32(ctx->opcode, 12, 1)) {
19852 case 0:
19853 /* NM_SHRA_QB */
19854 gen_helper_shra_qb(t0, t0, rs_t);
19855 gen_store_gpr(t0, rt);
19856 break;
19857 case 1:
19858 /* NM_SHRA_R_QB */
19859 gen_helper_shra_r_qb(t0, t0, rs_t);
19860 gen_store_gpr(t0, rt);
19861 break;
19863 break;
19864 case NM_SHRL_PH:
19865 check_dsp_r2(ctx);
19866 tcg_gen_movi_tl(t0, rd >> 1);
19867 gen_helper_shrl_ph(t0, t0, rs_t);
19868 gen_store_gpr(t0, rt);
19869 break;
19870 case NM_REPL_QB:
19871 check_dsp(ctx);
19873 int16_t imm;
19874 target_long result;
19875 imm = extract32(ctx->opcode, 13, 8);
19876 result = (uint32_t)imm << 24 |
19877 (uint32_t)imm << 16 |
19878 (uint32_t)imm << 8 |
19879 (uint32_t)imm;
19880 result = (int32_t)result;
19881 tcg_gen_movi_tl(t0, result);
19882 gen_store_gpr(t0, rt);
19884 break;
19885 default:
19886 generate_exception_end(ctx, EXCP_RI);
19887 break;
19889 tcg_temp_free(t0);
19890 tcg_temp_free(rs_t);
19894 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19896 int rt = extract32(ctx->opcode, 21, 5);
19897 int rs = extract32(ctx->opcode, 16, 5);
19898 int rd = extract32(ctx->opcode, 11, 5);
19900 switch (extract32(ctx->opcode, 6, 3)) {
19901 case NM_POOL32AXF_1:
19903 int32_t op1 = extract32(ctx->opcode, 9, 3);
19904 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19906 break;
19907 case NM_POOL32AXF_2:
19909 int32_t op1 = extract32(ctx->opcode, 12, 2);
19910 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19912 break;
19913 case NM_POOL32AXF_4:
19915 int32_t op1 = extract32(ctx->opcode, 9, 7);
19916 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19918 break;
19919 case NM_POOL32AXF_5:
19920 switch (extract32(ctx->opcode, 9, 7)) {
19921 #ifndef CONFIG_USER_ONLY
19922 case NM_TLBP:
19923 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19924 break;
19925 case NM_TLBR:
19926 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19927 break;
19928 case NM_TLBWI:
19929 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19930 break;
19931 case NM_TLBWR:
19932 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19933 break;
19934 case NM_TLBINV:
19935 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19936 break;
19937 case NM_TLBINVF:
19938 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19939 break;
19940 case NM_DI:
19941 check_cp0_enabled(ctx);
19943 TCGv t0 = tcg_temp_new();
19945 save_cpu_state(ctx, 1);
19946 gen_helper_di(t0, cpu_env);
19947 gen_store_gpr(t0, rt);
19948 /* Stop translation as we may have switched the execution mode */
19949 ctx->base.is_jmp = DISAS_STOP;
19950 tcg_temp_free(t0);
19952 break;
19953 case NM_EI:
19954 check_cp0_enabled(ctx);
19956 TCGv t0 = tcg_temp_new();
19958 save_cpu_state(ctx, 1);
19959 gen_helper_ei(t0, cpu_env);
19960 gen_store_gpr(t0, rt);
19961 /* Stop translation as we may have switched the execution mode */
19962 ctx->base.is_jmp = DISAS_STOP;
19963 tcg_temp_free(t0);
19965 break;
19966 case NM_RDPGPR:
19967 gen_load_srsgpr(rs, rt);
19968 break;
19969 case NM_WRPGPR:
19970 gen_store_srsgpr(rs, rt);
19971 break;
19972 case NM_WAIT:
19973 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19974 break;
19975 case NM_DERET:
19976 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19977 break;
19978 case NM_ERETX:
19979 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19980 break;
19981 #endif
19982 default:
19983 generate_exception_end(ctx, EXCP_RI);
19984 break;
19986 break;
19987 case NM_POOL32AXF_7:
19989 int32_t op1 = extract32(ctx->opcode, 9, 3);
19990 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19992 break;
19993 default:
19994 generate_exception_end(ctx, EXCP_RI);
19995 break;
19999 /* Immediate Value Compact Branches */
20000 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20001 int rt, int32_t imm, int32_t offset)
20003 TCGCond cond;
20004 int bcond_compute = 0;
20005 TCGv t0 = tcg_temp_new();
20006 TCGv t1 = tcg_temp_new();
20008 gen_load_gpr(t0, rt);
20009 tcg_gen_movi_tl(t1, imm);
20010 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20012 /* Load needed operands and calculate btarget */
20013 switch (opc) {
20014 case NM_BEQIC:
20015 if (rt == 0 && imm == 0) {
20016 /* Unconditional branch */
20017 } else if (rt == 0 && imm != 0) {
20018 /* Treat as NOP */
20019 goto out;
20020 } else {
20021 bcond_compute = 1;
20022 cond = TCG_COND_EQ;
20024 break;
20025 case NM_BBEQZC:
20026 case NM_BBNEZC:
20027 check_nms(ctx);
20028 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20029 generate_exception_end(ctx, EXCP_RI);
20030 goto out;
20031 } else if (rt == 0 && opc == NM_BBEQZC) {
20032 /* Unconditional branch */
20033 } else if (rt == 0 && opc == NM_BBNEZC) {
20034 /* Treat as NOP */
20035 goto out;
20036 } else {
20037 tcg_gen_shri_tl(t0, t0, imm);
20038 tcg_gen_andi_tl(t0, t0, 1);
20039 tcg_gen_movi_tl(t1, 0);
20040 bcond_compute = 1;
20041 if (opc == NM_BBEQZC) {
20042 cond = TCG_COND_EQ;
20043 } else {
20044 cond = TCG_COND_NE;
20047 break;
20048 case NM_BNEIC:
20049 if (rt == 0 && imm == 0) {
20050 /* Treat as NOP */
20051 goto out;
20052 } else if (rt == 0 && imm != 0) {
20053 /* Unconditional branch */
20054 } else {
20055 bcond_compute = 1;
20056 cond = TCG_COND_NE;
20058 break;
20059 case NM_BGEIC:
20060 if (rt == 0 && imm == 0) {
20061 /* Unconditional branch */
20062 } else {
20063 bcond_compute = 1;
20064 cond = TCG_COND_GE;
20066 break;
20067 case NM_BLTIC:
20068 bcond_compute = 1;
20069 cond = TCG_COND_LT;
20070 break;
20071 case NM_BGEIUC:
20072 if (rt == 0 && imm == 0) {
20073 /* Unconditional branch */
20074 } else {
20075 bcond_compute = 1;
20076 cond = TCG_COND_GEU;
20078 break;
20079 case NM_BLTIUC:
20080 bcond_compute = 1;
20081 cond = TCG_COND_LTU;
20082 break;
20083 default:
20084 MIPS_INVAL("Immediate Value Compact branch");
20085 generate_exception_end(ctx, EXCP_RI);
20086 goto out;
20089 /* branch completion */
20090 clear_branch_hflags(ctx);
20091 ctx->base.is_jmp = DISAS_NORETURN;
20093 if (bcond_compute == 0) {
20094 /* Uncoditional compact branch */
20095 gen_goto_tb(ctx, 0, ctx->btarget);
20096 } else {
20097 /* Conditional compact branch */
20098 TCGLabel *fs = gen_new_label();
20100 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20102 gen_goto_tb(ctx, 1, ctx->btarget);
20103 gen_set_label(fs);
20105 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20108 out:
20109 tcg_temp_free(t0);
20110 tcg_temp_free(t1);
20113 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20114 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20115 int rt)
20117 TCGv t0 = tcg_temp_new();
20118 TCGv t1 = tcg_temp_new();
20120 /* load rs */
20121 gen_load_gpr(t0, rs);
20123 /* link */
20124 if (rt != 0) {
20125 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20128 /* calculate btarget */
20129 tcg_gen_shli_tl(t0, t0, 1);
20130 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20131 gen_op_addr_add(ctx, btarget, t1, t0);
20133 /* branch completion */
20134 clear_branch_hflags(ctx);
20135 ctx->base.is_jmp = DISAS_NORETURN;
20137 /* unconditional branch to register */
20138 tcg_gen_mov_tl(cpu_PC, btarget);
20139 tcg_gen_lookup_and_goto_ptr();
20141 tcg_temp_free(t0);
20142 tcg_temp_free(t1);
20145 /* nanoMIPS Branches */
20146 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20147 int rs, int rt, int32_t offset)
20149 int bcond_compute = 0;
20150 TCGv t0 = tcg_temp_new();
20151 TCGv t1 = tcg_temp_new();
20153 /* Load needed operands and calculate btarget */
20154 switch (opc) {
20155 /* compact branch */
20156 case OPC_BGEC:
20157 case OPC_BLTC:
20158 gen_load_gpr(t0, rs);
20159 gen_load_gpr(t1, rt);
20160 bcond_compute = 1;
20161 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20162 break;
20163 case OPC_BGEUC:
20164 case OPC_BLTUC:
20165 if (rs == 0 || rs == rt) {
20166 /* OPC_BLEZALC, OPC_BGEZALC */
20167 /* OPC_BGTZALC, OPC_BLTZALC */
20168 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20170 gen_load_gpr(t0, rs);
20171 gen_load_gpr(t1, rt);
20172 bcond_compute = 1;
20173 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20174 break;
20175 case OPC_BC:
20176 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20177 break;
20178 case OPC_BEQZC:
20179 if (rs != 0) {
20180 /* OPC_BEQZC, OPC_BNEZC */
20181 gen_load_gpr(t0, rs);
20182 bcond_compute = 1;
20183 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20184 } else {
20185 /* OPC_JIC, OPC_JIALC */
20186 TCGv tbase = tcg_temp_new();
20187 TCGv toffset = tcg_temp_new();
20189 gen_load_gpr(tbase, rt);
20190 tcg_gen_movi_tl(toffset, offset);
20191 gen_op_addr_add(ctx, btarget, tbase, toffset);
20192 tcg_temp_free(tbase);
20193 tcg_temp_free(toffset);
20195 break;
20196 default:
20197 MIPS_INVAL("Compact branch/jump");
20198 generate_exception_end(ctx, EXCP_RI);
20199 goto out;
20202 if (bcond_compute == 0) {
20203 /* Uncoditional compact branch */
20204 switch (opc) {
20205 case OPC_BC:
20206 gen_goto_tb(ctx, 0, ctx->btarget);
20207 break;
20208 default:
20209 MIPS_INVAL("Compact branch/jump");
20210 generate_exception_end(ctx, EXCP_RI);
20211 goto out;
20213 } else {
20214 /* Conditional compact branch */
20215 TCGLabel *fs = gen_new_label();
20217 switch (opc) {
20218 case OPC_BGEUC:
20219 if (rs == 0 && rt != 0) {
20220 /* OPC_BLEZALC */
20221 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20222 } else if (rs != 0 && rt != 0 && rs == rt) {
20223 /* OPC_BGEZALC */
20224 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20225 } else {
20226 /* OPC_BGEUC */
20227 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20229 break;
20230 case OPC_BLTUC:
20231 if (rs == 0 && rt != 0) {
20232 /* OPC_BGTZALC */
20233 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20234 } else if (rs != 0 && rt != 0 && rs == rt) {
20235 /* OPC_BLTZALC */
20236 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20237 } else {
20238 /* OPC_BLTUC */
20239 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20241 break;
20242 case OPC_BGEC:
20243 if (rs == 0 && rt != 0) {
20244 /* OPC_BLEZC */
20245 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20246 } else if (rs != 0 && rt != 0 && rs == rt) {
20247 /* OPC_BGEZC */
20248 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20249 } else {
20250 /* OPC_BGEC */
20251 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20253 break;
20254 case OPC_BLTC:
20255 if (rs == 0 && rt != 0) {
20256 /* OPC_BGTZC */
20257 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20258 } else if (rs != 0 && rt != 0 && rs == rt) {
20259 /* OPC_BLTZC */
20260 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20261 } else {
20262 /* OPC_BLTC */
20263 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20265 break;
20266 case OPC_BEQZC:
20267 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20268 break;
20269 default:
20270 MIPS_INVAL("Compact conditional branch/jump");
20271 generate_exception_end(ctx, EXCP_RI);
20272 goto out;
20275 /* branch completion */
20276 clear_branch_hflags(ctx);
20277 ctx->base.is_jmp = DISAS_NORETURN;
20279 /* Generating branch here as compact branches don't have delay slot */
20280 gen_goto_tb(ctx, 1, ctx->btarget);
20281 gen_set_label(fs);
20283 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20286 out:
20287 tcg_temp_free(t0);
20288 tcg_temp_free(t1);
20292 /* nanoMIPS CP1 Branches */
20293 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20294 int32_t ft, int32_t offset)
20296 target_ulong btarget;
20297 TCGv_i64 t0 = tcg_temp_new_i64();
20299 gen_load_fpr64(ctx, t0, ft);
20300 tcg_gen_andi_i64(t0, t0, 1);
20302 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20304 switch (op) {
20305 case NM_BC1EQZC:
20306 tcg_gen_xori_i64(t0, t0, 1);
20307 ctx->hflags |= MIPS_HFLAG_BC;
20308 break;
20309 case NM_BC1NEZC:
20310 /* t0 already set */
20311 ctx->hflags |= MIPS_HFLAG_BC;
20312 break;
20313 default:
20314 MIPS_INVAL("cp1 cond branch");
20315 generate_exception_end(ctx, EXCP_RI);
20316 goto out;
20319 tcg_gen_trunc_i64_tl(bcond, t0);
20321 ctx->btarget = btarget;
20323 out:
20324 tcg_temp_free_i64(t0);
20328 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20330 TCGv t0, t1;
20331 t0 = tcg_temp_new();
20332 t1 = tcg_temp_new();
20334 gen_load_gpr(t0, rs);
20335 gen_load_gpr(t1, rt);
20337 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20338 /* PP.LSXS instructions require shifting */
20339 switch (extract32(ctx->opcode, 7, 4)) {
20340 case NM_SHXS:
20341 check_nms(ctx);
20342 /* fall through */
20343 case NM_LHXS:
20344 case NM_LHUXS:
20345 tcg_gen_shli_tl(t0, t0, 1);
20346 break;
20347 case NM_SWXS:
20348 check_nms(ctx);
20349 /* fall through */
20350 case NM_LWXS:
20351 case NM_LWC1XS:
20352 case NM_SWC1XS:
20353 tcg_gen_shli_tl(t0, t0, 2);
20354 break;
20355 case NM_LDC1XS:
20356 case NM_SDC1XS:
20357 tcg_gen_shli_tl(t0, t0, 3);
20358 break;
20361 gen_op_addr_add(ctx, t0, t0, t1);
20363 switch (extract32(ctx->opcode, 7, 4)) {
20364 case NM_LBX:
20365 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20366 MO_SB);
20367 gen_store_gpr(t0, rd);
20368 break;
20369 case NM_LHX:
20370 /*case NM_LHXS:*/
20371 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20372 MO_TESW);
20373 gen_store_gpr(t0, rd);
20374 break;
20375 case NM_LWX:
20376 /*case NM_LWXS:*/
20377 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20378 MO_TESL);
20379 gen_store_gpr(t0, rd);
20380 break;
20381 case NM_LBUX:
20382 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20383 MO_UB);
20384 gen_store_gpr(t0, rd);
20385 break;
20386 case NM_LHUX:
20387 /*case NM_LHUXS:*/
20388 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20389 MO_TEUW);
20390 gen_store_gpr(t0, rd);
20391 break;
20392 case NM_SBX:
20393 check_nms(ctx);
20394 gen_load_gpr(t1, rd);
20395 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20396 MO_8);
20397 break;
20398 case NM_SHX:
20399 /*case NM_SHXS:*/
20400 check_nms(ctx);
20401 gen_load_gpr(t1, rd);
20402 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20403 MO_TEUW);
20404 break;
20405 case NM_SWX:
20406 /*case NM_SWXS:*/
20407 check_nms(ctx);
20408 gen_load_gpr(t1, rd);
20409 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20410 MO_TEUL);
20411 break;
20412 case NM_LWC1X:
20413 /*case NM_LWC1XS:*/
20414 case NM_LDC1X:
20415 /*case NM_LDC1XS:*/
20416 case NM_SWC1X:
20417 /*case NM_SWC1XS:*/
20418 case NM_SDC1X:
20419 /*case NM_SDC1XS:*/
20420 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20421 check_cp1_enabled(ctx);
20422 switch (extract32(ctx->opcode, 7, 4)) {
20423 case NM_LWC1X:
20424 /*case NM_LWC1XS:*/
20425 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20426 break;
20427 case NM_LDC1X:
20428 /*case NM_LDC1XS:*/
20429 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20430 break;
20431 case NM_SWC1X:
20432 /*case NM_SWC1XS:*/
20433 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20434 break;
20435 case NM_SDC1X:
20436 /*case NM_SDC1XS:*/
20437 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20438 break;
20440 } else {
20441 generate_exception_err(ctx, EXCP_CpU, 1);
20443 break;
20444 default:
20445 generate_exception_end(ctx, EXCP_RI);
20446 break;
20449 tcg_temp_free(t0);
20450 tcg_temp_free(t1);
20453 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20455 int rt, rs, rd;
20457 rt = extract32(ctx->opcode, 21, 5);
20458 rs = extract32(ctx->opcode, 16, 5);
20459 rd = extract32(ctx->opcode, 11, 5);
20461 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20462 generate_exception_end(ctx, EXCP_RI);
20463 return;
20465 check_cp1_enabled(ctx);
20466 switch (extract32(ctx->opcode, 0, 3)) {
20467 case NM_POOL32F_0:
20468 switch (extract32(ctx->opcode, 3, 7)) {
20469 case NM_RINT_S:
20470 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20471 break;
20472 case NM_RINT_D:
20473 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20474 break;
20475 case NM_CLASS_S:
20476 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20477 break;
20478 case NM_CLASS_D:
20479 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20480 break;
20481 case NM_ADD_S:
20482 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20483 break;
20484 case NM_ADD_D:
20485 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20486 break;
20487 case NM_SUB_S:
20488 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20489 break;
20490 case NM_SUB_D:
20491 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20492 break;
20493 case NM_MUL_S:
20494 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20495 break;
20496 case NM_MUL_D:
20497 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20498 break;
20499 case NM_DIV_S:
20500 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20501 break;
20502 case NM_DIV_D:
20503 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20504 break;
20505 case NM_SELEQZ_S:
20506 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20507 break;
20508 case NM_SELEQZ_D:
20509 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20510 break;
20511 case NM_SELNEZ_S:
20512 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20513 break;
20514 case NM_SELNEZ_D:
20515 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20516 break;
20517 case NM_SEL_S:
20518 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20519 break;
20520 case NM_SEL_D:
20521 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20522 break;
20523 case NM_MADDF_S:
20524 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20525 break;
20526 case NM_MADDF_D:
20527 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20528 break;
20529 case NM_MSUBF_S:
20530 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20531 break;
20532 case NM_MSUBF_D:
20533 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20534 break;
20535 default:
20536 generate_exception_end(ctx, EXCP_RI);
20537 break;
20539 break;
20540 case NM_POOL32F_3:
20541 switch (extract32(ctx->opcode, 3, 3)) {
20542 case NM_MIN_FMT:
20543 switch (extract32(ctx->opcode, 9, 1)) {
20544 case FMT_SDPS_S:
20545 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20546 break;
20547 case FMT_SDPS_D:
20548 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20549 break;
20551 break;
20552 case NM_MAX_FMT:
20553 switch (extract32(ctx->opcode, 9, 1)) {
20554 case FMT_SDPS_S:
20555 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20556 break;
20557 case FMT_SDPS_D:
20558 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20559 break;
20561 break;
20562 case NM_MINA_FMT:
20563 switch (extract32(ctx->opcode, 9, 1)) {
20564 case FMT_SDPS_S:
20565 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20566 break;
20567 case FMT_SDPS_D:
20568 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20569 break;
20571 break;
20572 case NM_MAXA_FMT:
20573 switch (extract32(ctx->opcode, 9, 1)) {
20574 case FMT_SDPS_S:
20575 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20576 break;
20577 case FMT_SDPS_D:
20578 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20579 break;
20581 break;
20582 case NM_POOL32FXF:
20583 switch (extract32(ctx->opcode, 6, 8)) {
20584 case NM_CFC1:
20585 gen_cp1(ctx, OPC_CFC1, rt, rs);
20586 break;
20587 case NM_CTC1:
20588 gen_cp1(ctx, OPC_CTC1, rt, rs);
20589 break;
20590 case NM_MFC1:
20591 gen_cp1(ctx, OPC_MFC1, rt, rs);
20592 break;
20593 case NM_MTC1:
20594 gen_cp1(ctx, OPC_MTC1, rt, rs);
20595 break;
20596 case NM_MFHC1:
20597 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20598 break;
20599 case NM_MTHC1:
20600 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20601 break;
20602 case NM_CVT_S_PL:
20603 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20604 break;
20605 case NM_CVT_S_PU:
20606 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20607 break;
20608 default:
20609 switch (extract32(ctx->opcode, 6, 9)) {
20610 case NM_CVT_L_S:
20611 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20612 break;
20613 case NM_CVT_L_D:
20614 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20615 break;
20616 case NM_CVT_W_S:
20617 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20618 break;
20619 case NM_CVT_W_D:
20620 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20621 break;
20622 case NM_RSQRT_S:
20623 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20624 break;
20625 case NM_RSQRT_D:
20626 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20627 break;
20628 case NM_SQRT_S:
20629 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20630 break;
20631 case NM_SQRT_D:
20632 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20633 break;
20634 case NM_RECIP_S:
20635 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20636 break;
20637 case NM_RECIP_D:
20638 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20639 break;
20640 case NM_FLOOR_L_S:
20641 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20642 break;
20643 case NM_FLOOR_L_D:
20644 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20645 break;
20646 case NM_FLOOR_W_S:
20647 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20648 break;
20649 case NM_FLOOR_W_D:
20650 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20651 break;
20652 case NM_CEIL_L_S:
20653 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20654 break;
20655 case NM_CEIL_L_D:
20656 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20657 break;
20658 case NM_CEIL_W_S:
20659 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20660 break;
20661 case NM_CEIL_W_D:
20662 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20663 break;
20664 case NM_TRUNC_L_S:
20665 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20666 break;
20667 case NM_TRUNC_L_D:
20668 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20669 break;
20670 case NM_TRUNC_W_S:
20671 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20672 break;
20673 case NM_TRUNC_W_D:
20674 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20675 break;
20676 case NM_ROUND_L_S:
20677 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20678 break;
20679 case NM_ROUND_L_D:
20680 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20681 break;
20682 case NM_ROUND_W_S:
20683 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20684 break;
20685 case NM_ROUND_W_D:
20686 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20687 break;
20688 case NM_MOV_S:
20689 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20690 break;
20691 case NM_MOV_D:
20692 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20693 break;
20694 case NM_ABS_S:
20695 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20696 break;
20697 case NM_ABS_D:
20698 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20699 break;
20700 case NM_NEG_S:
20701 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20702 break;
20703 case NM_NEG_D:
20704 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20705 break;
20706 case NM_CVT_D_S:
20707 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20708 break;
20709 case NM_CVT_D_W:
20710 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20711 break;
20712 case NM_CVT_D_L:
20713 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20714 break;
20715 case NM_CVT_S_D:
20716 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20717 break;
20718 case NM_CVT_S_W:
20719 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20720 break;
20721 case NM_CVT_S_L:
20722 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20723 break;
20724 default:
20725 generate_exception_end(ctx, EXCP_RI);
20726 break;
20728 break;
20730 break;
20732 break;
20733 case NM_POOL32F_5:
20734 switch (extract32(ctx->opcode, 3, 3)) {
20735 case NM_CMP_CONDN_S:
20736 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20737 break;
20738 case NM_CMP_CONDN_D:
20739 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20740 break;
20741 default:
20742 generate_exception_end(ctx, EXCP_RI);
20743 break;
20745 break;
20746 default:
20747 generate_exception_end(ctx, EXCP_RI);
20748 break;
20752 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20753 int rd, int rs, int rt)
20755 int ret = rd;
20756 TCGv t0 = tcg_temp_new();
20757 TCGv v1_t = tcg_temp_new();
20758 TCGv v2_t = tcg_temp_new();
20760 gen_load_gpr(v1_t, rs);
20761 gen_load_gpr(v2_t, rt);
20763 switch (opc) {
20764 case NM_CMP_EQ_PH:
20765 check_dsp(ctx);
20766 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20767 break;
20768 case NM_CMP_LT_PH:
20769 check_dsp(ctx);
20770 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20771 break;
20772 case NM_CMP_LE_PH:
20773 check_dsp(ctx);
20774 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20775 break;
20776 case NM_CMPU_EQ_QB:
20777 check_dsp(ctx);
20778 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20779 break;
20780 case NM_CMPU_LT_QB:
20781 check_dsp(ctx);
20782 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20783 break;
20784 case NM_CMPU_LE_QB:
20785 check_dsp(ctx);
20786 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20787 break;
20788 case NM_CMPGU_EQ_QB:
20789 check_dsp(ctx);
20790 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20791 gen_store_gpr(v1_t, ret);
20792 break;
20793 case NM_CMPGU_LT_QB:
20794 check_dsp(ctx);
20795 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20796 gen_store_gpr(v1_t, ret);
20797 break;
20798 case NM_CMPGU_LE_QB:
20799 check_dsp(ctx);
20800 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20801 gen_store_gpr(v1_t, ret);
20802 break;
20803 case NM_CMPGDU_EQ_QB:
20804 check_dsp_r2(ctx);
20805 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20806 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20807 gen_store_gpr(v1_t, ret);
20808 break;
20809 case NM_CMPGDU_LT_QB:
20810 check_dsp_r2(ctx);
20811 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20812 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20813 gen_store_gpr(v1_t, ret);
20814 break;
20815 case NM_CMPGDU_LE_QB:
20816 check_dsp_r2(ctx);
20817 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20818 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20819 gen_store_gpr(v1_t, ret);
20820 break;
20821 case NM_PACKRL_PH:
20822 check_dsp(ctx);
20823 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20824 gen_store_gpr(v1_t, ret);
20825 break;
20826 case NM_PICK_QB:
20827 check_dsp(ctx);
20828 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20829 gen_store_gpr(v1_t, ret);
20830 break;
20831 case NM_PICK_PH:
20832 check_dsp(ctx);
20833 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20834 gen_store_gpr(v1_t, ret);
20835 break;
20836 case NM_ADDQ_S_W:
20837 check_dsp(ctx);
20838 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20839 gen_store_gpr(v1_t, ret);
20840 break;
20841 case NM_SUBQ_S_W:
20842 check_dsp(ctx);
20843 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20844 gen_store_gpr(v1_t, ret);
20845 break;
20846 case NM_ADDSC:
20847 check_dsp(ctx);
20848 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20849 gen_store_gpr(v1_t, ret);
20850 break;
20851 case NM_ADDWC:
20852 check_dsp(ctx);
20853 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20854 gen_store_gpr(v1_t, ret);
20855 break;
20856 case NM_ADDQ_S_PH:
20857 check_dsp(ctx);
20858 switch (extract32(ctx->opcode, 10, 1)) {
20859 case 0:
20860 /* ADDQ_PH */
20861 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20862 gen_store_gpr(v1_t, ret);
20863 break;
20864 case 1:
20865 /* ADDQ_S_PH */
20866 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20867 gen_store_gpr(v1_t, ret);
20868 break;
20870 break;
20871 case NM_ADDQH_R_PH:
20872 check_dsp_r2(ctx);
20873 switch (extract32(ctx->opcode, 10, 1)) {
20874 case 0:
20875 /* ADDQH_PH */
20876 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20877 gen_store_gpr(v1_t, ret);
20878 break;
20879 case 1:
20880 /* ADDQH_R_PH */
20881 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20882 gen_store_gpr(v1_t, ret);
20883 break;
20885 break;
20886 case NM_ADDQH_R_W:
20887 check_dsp_r2(ctx);
20888 switch (extract32(ctx->opcode, 10, 1)) {
20889 case 0:
20890 /* ADDQH_W */
20891 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20892 gen_store_gpr(v1_t, ret);
20893 break;
20894 case 1:
20895 /* ADDQH_R_W */
20896 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20897 gen_store_gpr(v1_t, ret);
20898 break;
20900 break;
20901 case NM_ADDU_S_QB:
20902 check_dsp(ctx);
20903 switch (extract32(ctx->opcode, 10, 1)) {
20904 case 0:
20905 /* ADDU_QB */
20906 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20907 gen_store_gpr(v1_t, ret);
20908 break;
20909 case 1:
20910 /* ADDU_S_QB */
20911 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20912 gen_store_gpr(v1_t, ret);
20913 break;
20915 break;
20916 case NM_ADDU_S_PH:
20917 check_dsp_r2(ctx);
20918 switch (extract32(ctx->opcode, 10, 1)) {
20919 case 0:
20920 /* ADDU_PH */
20921 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20922 gen_store_gpr(v1_t, ret);
20923 break;
20924 case 1:
20925 /* ADDU_S_PH */
20926 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20927 gen_store_gpr(v1_t, ret);
20928 break;
20930 break;
20931 case NM_ADDUH_R_QB:
20932 check_dsp_r2(ctx);
20933 switch (extract32(ctx->opcode, 10, 1)) {
20934 case 0:
20935 /* ADDUH_QB */
20936 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20937 gen_store_gpr(v1_t, ret);
20938 break;
20939 case 1:
20940 /* ADDUH_R_QB */
20941 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20942 gen_store_gpr(v1_t, ret);
20943 break;
20945 break;
20946 case NM_SHRAV_R_PH:
20947 check_dsp(ctx);
20948 switch (extract32(ctx->opcode, 10, 1)) {
20949 case 0:
20950 /* SHRAV_PH */
20951 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20952 gen_store_gpr(v1_t, ret);
20953 break;
20954 case 1:
20955 /* SHRAV_R_PH */
20956 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20960 break;
20961 case NM_SHRAV_R_QB:
20962 check_dsp_r2(ctx);
20963 switch (extract32(ctx->opcode, 10, 1)) {
20964 case 0:
20965 /* SHRAV_QB */
20966 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20967 gen_store_gpr(v1_t, ret);
20968 break;
20969 case 1:
20970 /* SHRAV_R_QB */
20971 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20972 gen_store_gpr(v1_t, ret);
20973 break;
20975 break;
20976 case NM_SUBQ_S_PH:
20977 check_dsp(ctx);
20978 switch (extract32(ctx->opcode, 10, 1)) {
20979 case 0:
20980 /* SUBQ_PH */
20981 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20982 gen_store_gpr(v1_t, ret);
20983 break;
20984 case 1:
20985 /* SUBQ_S_PH */
20986 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20987 gen_store_gpr(v1_t, ret);
20988 break;
20990 break;
20991 case NM_SUBQH_R_PH:
20992 check_dsp_r2(ctx);
20993 switch (extract32(ctx->opcode, 10, 1)) {
20994 case 0:
20995 /* SUBQH_PH */
20996 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20997 gen_store_gpr(v1_t, ret);
20998 break;
20999 case 1:
21000 /* SUBQH_R_PH */
21001 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21002 gen_store_gpr(v1_t, ret);
21003 break;
21005 break;
21006 case NM_SUBQH_R_W:
21007 check_dsp_r2(ctx);
21008 switch (extract32(ctx->opcode, 10, 1)) {
21009 case 0:
21010 /* SUBQH_W */
21011 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21012 gen_store_gpr(v1_t, ret);
21013 break;
21014 case 1:
21015 /* SUBQH_R_W */
21016 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21017 gen_store_gpr(v1_t, ret);
21018 break;
21020 break;
21021 case NM_SUBU_S_QB:
21022 check_dsp(ctx);
21023 switch (extract32(ctx->opcode, 10, 1)) {
21024 case 0:
21025 /* SUBU_QB */
21026 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21027 gen_store_gpr(v1_t, ret);
21028 break;
21029 case 1:
21030 /* SUBU_S_QB */
21031 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21032 gen_store_gpr(v1_t, ret);
21033 break;
21035 break;
21036 case NM_SUBU_S_PH:
21037 check_dsp_r2(ctx);
21038 switch (extract32(ctx->opcode, 10, 1)) {
21039 case 0:
21040 /* SUBU_PH */
21041 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21042 gen_store_gpr(v1_t, ret);
21043 break;
21044 case 1:
21045 /* SUBU_S_PH */
21046 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21047 gen_store_gpr(v1_t, ret);
21048 break;
21050 break;
21051 case NM_SUBUH_R_QB:
21052 check_dsp_r2(ctx);
21053 switch (extract32(ctx->opcode, 10, 1)) {
21054 case 0:
21055 /* SUBUH_QB */
21056 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21057 gen_store_gpr(v1_t, ret);
21058 break;
21059 case 1:
21060 /* SUBUH_R_QB */
21061 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21062 gen_store_gpr(v1_t, ret);
21063 break;
21065 break;
21066 case NM_SHLLV_S_PH:
21067 check_dsp(ctx);
21068 switch (extract32(ctx->opcode, 10, 1)) {
21069 case 0:
21070 /* SHLLV_PH */
21071 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21072 gen_store_gpr(v1_t, ret);
21073 break;
21074 case 1:
21075 /* SHLLV_S_PH */
21076 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21077 gen_store_gpr(v1_t, ret);
21078 break;
21080 break;
21081 case NM_PRECR_SRA_R_PH_W:
21082 check_dsp_r2(ctx);
21083 switch (extract32(ctx->opcode, 10, 1)) {
21084 case 0:
21085 /* PRECR_SRA_PH_W */
21087 TCGv_i32 sa_t = tcg_const_i32(rd);
21088 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21089 cpu_gpr[rt]);
21090 gen_store_gpr(v1_t, rt);
21091 tcg_temp_free_i32(sa_t);
21093 break;
21094 case 1:
21095 /* PRECR_SRA_R_PH_W */
21097 TCGv_i32 sa_t = tcg_const_i32(rd);
21098 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21099 cpu_gpr[rt]);
21100 gen_store_gpr(v1_t, rt);
21101 tcg_temp_free_i32(sa_t);
21103 break;
21105 break;
21106 case NM_MULEU_S_PH_QBL:
21107 check_dsp(ctx);
21108 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21109 gen_store_gpr(v1_t, ret);
21110 break;
21111 case NM_MULEU_S_PH_QBR:
21112 check_dsp(ctx);
21113 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21114 gen_store_gpr(v1_t, ret);
21115 break;
21116 case NM_MULQ_RS_PH:
21117 check_dsp(ctx);
21118 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21119 gen_store_gpr(v1_t, ret);
21120 break;
21121 case NM_MULQ_S_PH:
21122 check_dsp_r2(ctx);
21123 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21124 gen_store_gpr(v1_t, ret);
21125 break;
21126 case NM_MULQ_RS_W:
21127 check_dsp_r2(ctx);
21128 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21129 gen_store_gpr(v1_t, ret);
21130 break;
21131 case NM_MULQ_S_W:
21132 check_dsp_r2(ctx);
21133 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21134 gen_store_gpr(v1_t, ret);
21135 break;
21136 case NM_APPEND:
21137 check_dsp_r2(ctx);
21138 gen_load_gpr(t0, rs);
21139 if (rd != 0) {
21140 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21142 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21143 break;
21144 case NM_MODSUB:
21145 check_dsp(ctx);
21146 gen_helper_modsub(v1_t, v1_t, v2_t);
21147 gen_store_gpr(v1_t, ret);
21148 break;
21149 case NM_SHRAV_R_W:
21150 check_dsp(ctx);
21151 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21152 gen_store_gpr(v1_t, ret);
21153 break;
21154 case NM_SHRLV_PH:
21155 check_dsp_r2(ctx);
21156 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21157 gen_store_gpr(v1_t, ret);
21158 break;
21159 case NM_SHRLV_QB:
21160 check_dsp(ctx);
21161 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21162 gen_store_gpr(v1_t, ret);
21163 break;
21164 case NM_SHLLV_QB:
21165 check_dsp(ctx);
21166 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21167 gen_store_gpr(v1_t, ret);
21168 break;
21169 case NM_SHLLV_S_W:
21170 check_dsp(ctx);
21171 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21172 gen_store_gpr(v1_t, ret);
21173 break;
21174 case NM_SHILO:
21175 check_dsp(ctx);
21177 TCGv tv0 = tcg_temp_new();
21178 TCGv tv1 = tcg_temp_new();
21179 int16_t imm = extract32(ctx->opcode, 16, 7);
21181 tcg_gen_movi_tl(tv0, rd >> 3);
21182 tcg_gen_movi_tl(tv1, imm);
21183 gen_helper_shilo(tv0, tv1, cpu_env);
21185 break;
21186 case NM_MULEQ_S_W_PHL:
21187 check_dsp(ctx);
21188 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21189 gen_store_gpr(v1_t, ret);
21190 break;
21191 case NM_MULEQ_S_W_PHR:
21192 check_dsp(ctx);
21193 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21194 gen_store_gpr(v1_t, ret);
21195 break;
21196 case NM_MUL_S_PH:
21197 check_dsp_r2(ctx);
21198 switch (extract32(ctx->opcode, 10, 1)) {
21199 case 0:
21200 /* MUL_PH */
21201 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21202 gen_store_gpr(v1_t, ret);
21203 break;
21204 case 1:
21205 /* MUL_S_PH */
21206 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21207 gen_store_gpr(v1_t, ret);
21208 break;
21210 break;
21211 case NM_PRECR_QB_PH:
21212 check_dsp_r2(ctx);
21213 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21214 gen_store_gpr(v1_t, ret);
21215 break;
21216 case NM_PRECRQ_QB_PH:
21217 check_dsp(ctx);
21218 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21219 gen_store_gpr(v1_t, ret);
21220 break;
21221 case NM_PRECRQ_PH_W:
21222 check_dsp(ctx);
21223 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21224 gen_store_gpr(v1_t, ret);
21225 break;
21226 case NM_PRECRQ_RS_PH_W:
21227 check_dsp(ctx);
21228 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21229 gen_store_gpr(v1_t, ret);
21230 break;
21231 case NM_PRECRQU_S_QB_PH:
21232 check_dsp(ctx);
21233 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21234 gen_store_gpr(v1_t, ret);
21235 break;
21236 case NM_SHRA_R_W:
21237 check_dsp(ctx);
21238 tcg_gen_movi_tl(t0, rd);
21239 gen_helper_shra_r_w(v1_t, t0, v1_t);
21240 gen_store_gpr(v1_t, rt);
21241 break;
21242 case NM_SHRA_R_PH:
21243 check_dsp(ctx);
21244 tcg_gen_movi_tl(t0, rd >> 1);
21245 switch (extract32(ctx->opcode, 10, 1)) {
21246 case 0:
21247 /* SHRA_PH */
21248 gen_helper_shra_ph(v1_t, t0, v1_t);
21249 gen_store_gpr(v1_t, rt);
21250 break;
21251 case 1:
21252 /* SHRA_R_PH */
21253 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21254 gen_store_gpr(v1_t, rt);
21255 break;
21257 break;
21258 case NM_SHLL_S_PH:
21259 check_dsp(ctx);
21260 tcg_gen_movi_tl(t0, rd >> 1);
21261 switch (extract32(ctx->opcode, 10, 2)) {
21262 case 0:
21263 /* SHLL_PH */
21264 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21265 gen_store_gpr(v1_t, rt);
21266 break;
21267 case 2:
21268 /* SHLL_S_PH */
21269 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21270 gen_store_gpr(v1_t, rt);
21271 break;
21272 default:
21273 generate_exception_end(ctx, EXCP_RI);
21274 break;
21276 break;
21277 case NM_SHLL_S_W:
21278 check_dsp(ctx);
21279 tcg_gen_movi_tl(t0, rd);
21280 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21281 gen_store_gpr(v1_t, rt);
21282 break;
21283 case NM_REPL_PH:
21284 check_dsp(ctx);
21286 int16_t imm;
21287 imm = sextract32(ctx->opcode, 11, 11);
21288 imm = (int16_t)(imm << 6) >> 6;
21289 if (rt != 0) {
21290 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21293 break;
21294 default:
21295 generate_exception_end(ctx, EXCP_RI);
21296 break;
21300 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21302 uint16_t insn;
21303 uint32_t op;
21304 int rt, rs, rd;
21305 int offset;
21306 int imm;
21308 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21309 ctx->opcode = (ctx->opcode << 16) | insn;
21311 rt = extract32(ctx->opcode, 21, 5);
21312 rs = extract32(ctx->opcode, 16, 5);
21313 rd = extract32(ctx->opcode, 11, 5);
21315 op = extract32(ctx->opcode, 26, 6);
21316 switch (op) {
21317 case NM_P_ADDIU:
21318 if (rt == 0) {
21319 /* P.RI */
21320 switch (extract32(ctx->opcode, 19, 2)) {
21321 case NM_SIGRIE:
21322 default:
21323 generate_exception_end(ctx, EXCP_RI);
21324 break;
21325 case NM_P_SYSCALL:
21326 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21327 generate_exception_end(ctx, EXCP_SYSCALL);
21328 } else {
21329 generate_exception_end(ctx, EXCP_RI);
21331 break;
21332 case NM_BREAK:
21333 generate_exception_end(ctx, EXCP_BREAK);
21334 break;
21335 case NM_SDBBP:
21336 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21337 gen_helper_do_semihosting(cpu_env);
21338 } else {
21339 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21340 generate_exception_end(ctx, EXCP_RI);
21341 } else {
21342 generate_exception_end(ctx, EXCP_DBp);
21345 break;
21347 } else {
21348 /* NM_ADDIU */
21349 imm = extract32(ctx->opcode, 0, 16);
21350 if (rs != 0) {
21351 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21352 } else {
21353 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21355 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21357 break;
21358 case NM_ADDIUPC:
21359 if (rt != 0) {
21360 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21361 extract32(ctx->opcode, 1, 20) << 1;
21362 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21363 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21365 break;
21366 case NM_POOL32A:
21367 switch (ctx->opcode & 0x07) {
21368 case NM_POOL32A0:
21369 gen_pool32a0_nanomips_insn(env, ctx);
21370 break;
21371 case NM_POOL32A5:
21373 int32_t op1 = extract32(ctx->opcode, 3, 7);
21374 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21376 break;
21377 case NM_POOL32A7:
21378 switch (extract32(ctx->opcode, 3, 3)) {
21379 case NM_P_LSX:
21380 gen_p_lsx(ctx, rd, rs, rt);
21381 break;
21382 case NM_LSA:
21384 * In nanoMIPS, the shift field directly encodes the shift
21385 * amount, meaning that the supported shift values are in
21386 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21388 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21389 extract32(ctx->opcode, 9, 2) - 1);
21390 break;
21391 case NM_EXTW:
21392 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21393 break;
21394 case NM_POOL32AXF:
21395 gen_pool32axf_nanomips_insn(env, ctx);
21396 break;
21397 default:
21398 generate_exception_end(ctx, EXCP_RI);
21399 break;
21401 break;
21402 default:
21403 generate_exception_end(ctx, EXCP_RI);
21404 break;
21406 break;
21407 case NM_P_GP_W:
21408 switch (ctx->opcode & 0x03) {
21409 case NM_ADDIUGP_W:
21410 if (rt != 0) {
21411 offset = extract32(ctx->opcode, 0, 21);
21412 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21414 break;
21415 case NM_LWGP:
21416 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21417 break;
21418 case NM_SWGP:
21419 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21420 break;
21421 default:
21422 generate_exception_end(ctx, EXCP_RI);
21423 break;
21425 break;
21426 case NM_P48I:
21428 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21429 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21430 switch (extract32(ctx->opcode, 16, 5)) {
21431 case NM_LI48:
21432 check_nms(ctx);
21433 if (rt != 0) {
21434 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21436 break;
21437 case NM_ADDIU48:
21438 check_nms(ctx);
21439 if (rt != 0) {
21440 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21441 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21443 break;
21444 case NM_ADDIUGP48:
21445 check_nms(ctx);
21446 if (rt != 0) {
21447 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21449 break;
21450 case NM_ADDIUPC48:
21451 check_nms(ctx);
21452 if (rt != 0) {
21453 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21454 addr_off);
21456 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21458 break;
21459 case NM_LWPC48:
21460 check_nms(ctx);
21461 if (rt != 0) {
21462 TCGv t0;
21463 t0 = tcg_temp_new();
21465 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21466 addr_off);
21468 tcg_gen_movi_tl(t0, addr);
21469 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21470 tcg_temp_free(t0);
21472 break;
21473 case NM_SWPC48:
21474 check_nms(ctx);
21476 TCGv t0, t1;
21477 t0 = tcg_temp_new();
21478 t1 = tcg_temp_new();
21480 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21481 addr_off);
21483 tcg_gen_movi_tl(t0, addr);
21484 gen_load_gpr(t1, rt);
21486 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21488 tcg_temp_free(t0);
21489 tcg_temp_free(t1);
21491 break;
21492 default:
21493 generate_exception_end(ctx, EXCP_RI);
21494 break;
21496 return 6;
21498 case NM_P_U12:
21499 switch (extract32(ctx->opcode, 12, 4)) {
21500 case NM_ORI:
21501 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21502 break;
21503 case NM_XORI:
21504 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21505 break;
21506 case NM_ANDI:
21507 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21508 break;
21509 case NM_P_SR:
21510 switch (extract32(ctx->opcode, 20, 1)) {
21511 case NM_PP_SR:
21512 switch (ctx->opcode & 3) {
21513 case NM_SAVE:
21514 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21515 extract32(ctx->opcode, 2, 1),
21516 extract32(ctx->opcode, 3, 9) << 3);
21517 break;
21518 case NM_RESTORE:
21519 case NM_RESTORE_JRC:
21520 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21521 extract32(ctx->opcode, 2, 1),
21522 extract32(ctx->opcode, 3, 9) << 3);
21523 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21524 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21526 break;
21527 default:
21528 generate_exception_end(ctx, EXCP_RI);
21529 break;
21531 break;
21532 case NM_P_SR_F:
21533 generate_exception_end(ctx, EXCP_RI);
21534 break;
21536 break;
21537 case NM_SLTI:
21538 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21539 break;
21540 case NM_SLTIU:
21541 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21542 break;
21543 case NM_SEQI:
21545 TCGv t0 = tcg_temp_new();
21547 imm = extract32(ctx->opcode, 0, 12);
21548 gen_load_gpr(t0, rs);
21549 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21550 gen_store_gpr(t0, rt);
21552 tcg_temp_free(t0);
21554 break;
21555 case NM_ADDIUNEG:
21556 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21557 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21558 break;
21559 case NM_P_SHIFT:
21561 int shift = extract32(ctx->opcode, 0, 5);
21562 switch (extract32(ctx->opcode, 5, 4)) {
21563 case NM_P_SLL:
21564 if (rt == 0 && shift == 0) {
21565 /* NOP */
21566 } else if (rt == 0 && shift == 3) {
21567 /* EHB - treat as NOP */
21568 } else if (rt == 0 && shift == 5) {
21569 /* PAUSE - treat as NOP */
21570 } else if (rt == 0 && shift == 6) {
21571 /* SYNC */
21572 gen_sync(extract32(ctx->opcode, 16, 5));
21573 } else {
21574 /* SLL */
21575 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21576 extract32(ctx->opcode, 0, 5));
21578 break;
21579 case NM_SRL:
21580 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21581 extract32(ctx->opcode, 0, 5));
21582 break;
21583 case NM_SRA:
21584 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21585 extract32(ctx->opcode, 0, 5));
21586 break;
21587 case NM_ROTR:
21588 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21589 extract32(ctx->opcode, 0, 5));
21590 break;
21593 break;
21594 case NM_P_ROTX:
21595 check_nms(ctx);
21596 if (rt != 0) {
21597 TCGv t0 = tcg_temp_new();
21598 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21599 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21600 << 1);
21601 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21603 gen_load_gpr(t0, rs);
21604 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21605 tcg_temp_free(t0);
21607 tcg_temp_free_i32(shift);
21608 tcg_temp_free_i32(shiftx);
21609 tcg_temp_free_i32(stripe);
21611 break;
21612 case NM_P_INS:
21613 switch (((ctx->opcode >> 10) & 2) |
21614 (extract32(ctx->opcode, 5, 1))) {
21615 case NM_INS:
21616 check_nms(ctx);
21617 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21618 extract32(ctx->opcode, 6, 5));
21619 break;
21620 default:
21621 generate_exception_end(ctx, EXCP_RI);
21622 break;
21624 break;
21625 case NM_P_EXT:
21626 switch (((ctx->opcode >> 10) & 2) |
21627 (extract32(ctx->opcode, 5, 1))) {
21628 case NM_EXT:
21629 check_nms(ctx);
21630 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21631 extract32(ctx->opcode, 6, 5));
21632 break;
21633 default:
21634 generate_exception_end(ctx, EXCP_RI);
21635 break;
21637 break;
21638 default:
21639 generate_exception_end(ctx, EXCP_RI);
21640 break;
21642 break;
21643 case NM_POOL32F:
21644 gen_pool32f_nanomips_insn(ctx);
21645 break;
21646 case NM_POOL32S:
21647 break;
21648 case NM_P_LUI:
21649 switch (extract32(ctx->opcode, 1, 1)) {
21650 case NM_LUI:
21651 if (rt != 0) {
21652 tcg_gen_movi_tl(cpu_gpr[rt],
21653 sextract32(ctx->opcode, 0, 1) << 31 |
21654 extract32(ctx->opcode, 2, 10) << 21 |
21655 extract32(ctx->opcode, 12, 9) << 12);
21657 break;
21658 case NM_ALUIPC:
21659 if (rt != 0) {
21660 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21661 extract32(ctx->opcode, 2, 10) << 21 |
21662 extract32(ctx->opcode, 12, 9) << 12;
21663 target_long addr;
21664 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21665 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21667 break;
21669 break;
21670 case NM_P_GP_BH:
21672 uint32_t u = extract32(ctx->opcode, 0, 18);
21674 switch (extract32(ctx->opcode, 18, 3)) {
21675 case NM_LBGP:
21676 gen_ld(ctx, OPC_LB, rt, 28, u);
21677 break;
21678 case NM_SBGP:
21679 gen_st(ctx, OPC_SB, rt, 28, u);
21680 break;
21681 case NM_LBUGP:
21682 gen_ld(ctx, OPC_LBU, rt, 28, u);
21683 break;
21684 case NM_ADDIUGP_B:
21685 if (rt != 0) {
21686 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21688 break;
21689 case NM_P_GP_LH:
21690 u &= ~1;
21691 switch (ctx->opcode & 1) {
21692 case NM_LHGP:
21693 gen_ld(ctx, OPC_LH, rt, 28, u);
21694 break;
21695 case NM_LHUGP:
21696 gen_ld(ctx, OPC_LHU, rt, 28, u);
21697 break;
21699 break;
21700 case NM_P_GP_SH:
21701 u &= ~1;
21702 switch (ctx->opcode & 1) {
21703 case NM_SHGP:
21704 gen_st(ctx, OPC_SH, rt, 28, u);
21705 break;
21706 default:
21707 generate_exception_end(ctx, EXCP_RI);
21708 break;
21710 break;
21711 case NM_P_GP_CP1:
21712 u &= ~0x3;
21713 switch (ctx->opcode & 0x3) {
21714 case NM_LWC1GP:
21715 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21716 break;
21717 case NM_LDC1GP:
21718 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21719 break;
21720 case NM_SWC1GP:
21721 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21722 break;
21723 case NM_SDC1GP:
21724 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21725 break;
21727 break;
21728 default:
21729 generate_exception_end(ctx, EXCP_RI);
21730 break;
21733 break;
21734 case NM_P_LS_U12:
21736 uint32_t u = extract32(ctx->opcode, 0, 12);
21738 switch (extract32(ctx->opcode, 12, 4)) {
21739 case NM_P_PREFU12:
21740 if (rt == 31) {
21741 /* SYNCI */
21743 * Break the TB to be able to sync copied instructions
21744 * immediately.
21746 ctx->base.is_jmp = DISAS_STOP;
21747 } else {
21748 /* PREF */
21749 /* Treat as NOP. */
21751 break;
21752 case NM_LB:
21753 gen_ld(ctx, OPC_LB, rt, rs, u);
21754 break;
21755 case NM_LH:
21756 gen_ld(ctx, OPC_LH, rt, rs, u);
21757 break;
21758 case NM_LW:
21759 gen_ld(ctx, OPC_LW, rt, rs, u);
21760 break;
21761 case NM_LBU:
21762 gen_ld(ctx, OPC_LBU, rt, rs, u);
21763 break;
21764 case NM_LHU:
21765 gen_ld(ctx, OPC_LHU, rt, rs, u);
21766 break;
21767 case NM_SB:
21768 gen_st(ctx, OPC_SB, rt, rs, u);
21769 break;
21770 case NM_SH:
21771 gen_st(ctx, OPC_SH, rt, rs, u);
21772 break;
21773 case NM_SW:
21774 gen_st(ctx, OPC_SW, rt, rs, u);
21775 break;
21776 case NM_LWC1:
21777 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21778 break;
21779 case NM_LDC1:
21780 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21781 break;
21782 case NM_SWC1:
21783 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21784 break;
21785 case NM_SDC1:
21786 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21787 break;
21788 default:
21789 generate_exception_end(ctx, EXCP_RI);
21790 break;
21793 break;
21794 case NM_P_LS_S9:
21796 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21797 extract32(ctx->opcode, 0, 8);
21799 switch (extract32(ctx->opcode, 8, 3)) {
21800 case NM_P_LS_S0:
21801 switch (extract32(ctx->opcode, 11, 4)) {
21802 case NM_LBS9:
21803 gen_ld(ctx, OPC_LB, rt, rs, s);
21804 break;
21805 case NM_LHS9:
21806 gen_ld(ctx, OPC_LH, rt, rs, s);
21807 break;
21808 case NM_LWS9:
21809 gen_ld(ctx, OPC_LW, rt, rs, s);
21810 break;
21811 case NM_LBUS9:
21812 gen_ld(ctx, OPC_LBU, rt, rs, s);
21813 break;
21814 case NM_LHUS9:
21815 gen_ld(ctx, OPC_LHU, rt, rs, s);
21816 break;
21817 case NM_SBS9:
21818 gen_st(ctx, OPC_SB, rt, rs, s);
21819 break;
21820 case NM_SHS9:
21821 gen_st(ctx, OPC_SH, rt, rs, s);
21822 break;
21823 case NM_SWS9:
21824 gen_st(ctx, OPC_SW, rt, rs, s);
21825 break;
21826 case NM_LWC1S9:
21827 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21828 break;
21829 case NM_LDC1S9:
21830 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21831 break;
21832 case NM_SWC1S9:
21833 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21834 break;
21835 case NM_SDC1S9:
21836 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21837 break;
21838 case NM_P_PREFS9:
21839 if (rt == 31) {
21840 /* SYNCI */
21842 * Break the TB to be able to sync copied instructions
21843 * immediately.
21845 ctx->base.is_jmp = DISAS_STOP;
21846 } else {
21847 /* PREF */
21848 /* Treat as NOP. */
21850 break;
21851 default:
21852 generate_exception_end(ctx, EXCP_RI);
21853 break;
21855 break;
21856 case NM_P_LS_S1:
21857 switch (extract32(ctx->opcode, 11, 4)) {
21858 case NM_UALH:
21859 case NM_UASH:
21860 check_nms(ctx);
21862 TCGv t0 = tcg_temp_new();
21863 TCGv t1 = tcg_temp_new();
21865 gen_base_offset_addr(ctx, t0, rs, s);
21867 switch (extract32(ctx->opcode, 11, 4)) {
21868 case NM_UALH:
21869 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21870 MO_UNALN);
21871 gen_store_gpr(t0, rt);
21872 break;
21873 case NM_UASH:
21874 gen_load_gpr(t1, rt);
21875 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21876 MO_UNALN);
21877 break;
21879 tcg_temp_free(t0);
21880 tcg_temp_free(t1);
21882 break;
21883 case NM_P_LL:
21884 switch (ctx->opcode & 0x03) {
21885 case NM_LL:
21886 gen_ld(ctx, OPC_LL, rt, rs, s);
21887 break;
21888 case NM_LLWP:
21889 check_xnp(ctx);
21890 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21891 break;
21893 break;
21894 case NM_P_SC:
21895 switch (ctx->opcode & 0x03) {
21896 case NM_SC:
21897 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21898 break;
21899 case NM_SCWP:
21900 check_xnp(ctx);
21901 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21902 false);
21903 break;
21905 break;
21906 case NM_CACHE:
21907 check_cp0_enabled(ctx);
21908 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21909 gen_cache_operation(ctx, rt, rs, s);
21911 break;
21913 break;
21914 case NM_P_LS_E0:
21915 switch (extract32(ctx->opcode, 11, 4)) {
21916 case NM_LBE:
21917 check_eva(ctx);
21918 check_cp0_enabled(ctx);
21919 gen_ld(ctx, OPC_LBE, rt, rs, s);
21920 break;
21921 case NM_SBE:
21922 check_eva(ctx);
21923 check_cp0_enabled(ctx);
21924 gen_st(ctx, OPC_SBE, rt, rs, s);
21925 break;
21926 case NM_LBUE:
21927 check_eva(ctx);
21928 check_cp0_enabled(ctx);
21929 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21930 break;
21931 case NM_P_PREFE:
21932 if (rt == 31) {
21933 /* case NM_SYNCIE */
21934 check_eva(ctx);
21935 check_cp0_enabled(ctx);
21937 * Break the TB to be able to sync copied instructions
21938 * immediately.
21940 ctx->base.is_jmp = DISAS_STOP;
21941 } else {
21942 /* case NM_PREFE */
21943 check_eva(ctx);
21944 check_cp0_enabled(ctx);
21945 /* Treat as NOP. */
21947 break;
21948 case NM_LHE:
21949 check_eva(ctx);
21950 check_cp0_enabled(ctx);
21951 gen_ld(ctx, OPC_LHE, rt, rs, s);
21952 break;
21953 case NM_SHE:
21954 check_eva(ctx);
21955 check_cp0_enabled(ctx);
21956 gen_st(ctx, OPC_SHE, rt, rs, s);
21957 break;
21958 case NM_LHUE:
21959 check_eva(ctx);
21960 check_cp0_enabled(ctx);
21961 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21962 break;
21963 case NM_CACHEE:
21964 check_nms_dl_il_sl_tl_l2c(ctx);
21965 gen_cache_operation(ctx, rt, rs, s);
21966 break;
21967 case NM_LWE:
21968 check_eva(ctx);
21969 check_cp0_enabled(ctx);
21970 gen_ld(ctx, OPC_LWE, rt, rs, s);
21971 break;
21972 case NM_SWE:
21973 check_eva(ctx);
21974 check_cp0_enabled(ctx);
21975 gen_st(ctx, OPC_SWE, rt, rs, s);
21976 break;
21977 case NM_P_LLE:
21978 switch (extract32(ctx->opcode, 2, 2)) {
21979 case NM_LLE:
21980 check_xnp(ctx);
21981 check_eva(ctx);
21982 check_cp0_enabled(ctx);
21983 gen_ld(ctx, OPC_LLE, rt, rs, s);
21984 break;
21985 case NM_LLWPE:
21986 check_xnp(ctx);
21987 check_eva(ctx);
21988 check_cp0_enabled(ctx);
21989 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21990 break;
21991 default:
21992 generate_exception_end(ctx, EXCP_RI);
21993 break;
21995 break;
21996 case NM_P_SCE:
21997 switch (extract32(ctx->opcode, 2, 2)) {
21998 case NM_SCE:
21999 check_xnp(ctx);
22000 check_eva(ctx);
22001 check_cp0_enabled(ctx);
22002 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22003 break;
22004 case NM_SCWPE:
22005 check_xnp(ctx);
22006 check_eva(ctx);
22007 check_cp0_enabled(ctx);
22008 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22009 true);
22010 break;
22011 default:
22012 generate_exception_end(ctx, EXCP_RI);
22013 break;
22015 break;
22017 break;
22018 case NM_P_LS_WM:
22019 case NM_P_LS_UAWM:
22020 check_nms(ctx);
22022 int count = extract32(ctx->opcode, 12, 3);
22023 int counter = 0;
22025 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22026 extract32(ctx->opcode, 0, 8);
22027 TCGv va = tcg_temp_new();
22028 TCGv t1 = tcg_temp_new();
22029 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22030 NM_P_LS_UAWM ? MO_UNALN : 0;
22032 count = (count == 0) ? 8 : count;
22033 while (counter != count) {
22034 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22035 int this_offset = offset + (counter << 2);
22037 gen_base_offset_addr(ctx, va, rs, this_offset);
22039 switch (extract32(ctx->opcode, 11, 1)) {
22040 case NM_LWM:
22041 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22042 memop | MO_TESL);
22043 gen_store_gpr(t1, this_rt);
22044 if ((this_rt == rs) &&
22045 (counter != (count - 1))) {
22046 /* UNPREDICTABLE */
22048 break;
22049 case NM_SWM:
22050 this_rt = (rt == 0) ? 0 : this_rt;
22051 gen_load_gpr(t1, this_rt);
22052 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22053 memop | MO_TEUL);
22054 break;
22056 counter++;
22058 tcg_temp_free(va);
22059 tcg_temp_free(t1);
22061 break;
22062 default:
22063 generate_exception_end(ctx, EXCP_RI);
22064 break;
22067 break;
22068 case NM_MOVE_BALC:
22069 check_nms(ctx);
22071 TCGv t0 = tcg_temp_new();
22072 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22073 extract32(ctx->opcode, 1, 20) << 1;
22074 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22075 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22076 extract32(ctx->opcode, 21, 3));
22077 gen_load_gpr(t0, rt);
22078 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22079 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22080 tcg_temp_free(t0);
22082 break;
22083 case NM_P_BAL:
22085 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22086 extract32(ctx->opcode, 1, 24) << 1;
22088 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22089 /* BC */
22090 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22091 } else {
22092 /* BALC */
22093 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22096 break;
22097 case NM_P_J:
22098 switch (extract32(ctx->opcode, 12, 4)) {
22099 case NM_JALRC:
22100 case NM_JALRC_HB:
22101 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22102 break;
22103 case NM_P_BALRSC:
22104 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22105 break;
22106 default:
22107 generate_exception_end(ctx, EXCP_RI);
22108 break;
22110 break;
22111 case NM_P_BR1:
22113 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22114 extract32(ctx->opcode, 1, 13) << 1;
22115 switch (extract32(ctx->opcode, 14, 2)) {
22116 case NM_BEQC:
22117 check_nms(ctx);
22118 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22119 break;
22120 case NM_P_BR3A:
22121 s = sextract32(ctx->opcode, 0, 1) << 14 |
22122 extract32(ctx->opcode, 1, 13) << 1;
22123 check_cp1_enabled(ctx);
22124 switch (extract32(ctx->opcode, 16, 5)) {
22125 case NM_BC1EQZC:
22126 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22127 break;
22128 case NM_BC1NEZC:
22129 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22130 break;
22131 case NM_BPOSGE32C:
22132 check_dsp_r3(ctx);
22134 int32_t imm = extract32(ctx->opcode, 1, 13) |
22135 extract32(ctx->opcode, 0, 1) << 13;
22137 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22138 imm);
22140 break;
22141 default:
22142 generate_exception_end(ctx, EXCP_RI);
22143 break;
22145 break;
22146 case NM_BGEC:
22147 if (rs == rt) {
22148 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22149 } else {
22150 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22152 break;
22153 case NM_BGEUC:
22154 if (rs == rt || rt == 0) {
22155 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22156 } else if (rs == 0) {
22157 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22158 } else {
22159 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22161 break;
22164 break;
22165 case NM_P_BR2:
22167 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22168 extract32(ctx->opcode, 1, 13) << 1;
22169 switch (extract32(ctx->opcode, 14, 2)) {
22170 case NM_BNEC:
22171 check_nms(ctx);
22172 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22173 break;
22174 case NM_BLTC:
22175 if (rs != 0 && rt != 0 && rs == rt) {
22176 /* NOP */
22177 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22178 } else {
22179 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22181 break;
22182 case NM_BLTUC:
22183 if (rs == 0 || rs == rt) {
22184 /* NOP */
22185 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22186 } else {
22187 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22189 break;
22190 default:
22191 generate_exception_end(ctx, EXCP_RI);
22192 break;
22195 break;
22196 case NM_P_BRI:
22198 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22199 extract32(ctx->opcode, 1, 10) << 1;
22200 uint32_t u = extract32(ctx->opcode, 11, 7);
22202 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22203 rt, u, s);
22205 break;
22206 default:
22207 generate_exception_end(ctx, EXCP_RI);
22208 break;
22210 return 4;
22213 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22215 uint32_t op;
22216 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22217 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22218 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22219 int offset;
22220 int imm;
22222 /* make sure instructions are on a halfword boundary */
22223 if (ctx->base.pc_next & 0x1) {
22224 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22225 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22226 tcg_temp_free(tmp);
22227 generate_exception_end(ctx, EXCP_AdEL);
22228 return 2;
22231 op = extract32(ctx->opcode, 10, 6);
22232 switch (op) {
22233 case NM_P16_MV:
22234 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22235 if (rt != 0) {
22236 /* MOVE */
22237 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22238 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22239 } else {
22240 /* P16.RI */
22241 switch (extract32(ctx->opcode, 3, 2)) {
22242 case NM_P16_SYSCALL:
22243 if (extract32(ctx->opcode, 2, 1) == 0) {
22244 generate_exception_end(ctx, EXCP_SYSCALL);
22245 } else {
22246 generate_exception_end(ctx, EXCP_RI);
22248 break;
22249 case NM_BREAK16:
22250 generate_exception_end(ctx, EXCP_BREAK);
22251 break;
22252 case NM_SDBBP16:
22253 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22254 gen_helper_do_semihosting(cpu_env);
22255 } else {
22256 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22257 generate_exception_end(ctx, EXCP_RI);
22258 } else {
22259 generate_exception_end(ctx, EXCP_DBp);
22262 break;
22263 default:
22264 generate_exception_end(ctx, EXCP_RI);
22265 break;
22268 break;
22269 case NM_P16_SHIFT:
22271 int shift = extract32(ctx->opcode, 0, 3);
22272 uint32_t opc = 0;
22273 shift = (shift == 0) ? 8 : shift;
22275 switch (extract32(ctx->opcode, 3, 1)) {
22276 case NM_SLL16:
22277 opc = OPC_SLL;
22278 break;
22279 case NM_SRL16:
22280 opc = OPC_SRL;
22281 break;
22283 gen_shift_imm(ctx, opc, rt, rs, shift);
22285 break;
22286 case NM_P16C:
22287 switch (ctx->opcode & 1) {
22288 case NM_POOL16C_0:
22289 gen_pool16c_nanomips_insn(ctx);
22290 break;
22291 case NM_LWXS16:
22292 gen_ldxs(ctx, rt, rs, rd);
22293 break;
22295 break;
22296 case NM_P16_A1:
22297 switch (extract32(ctx->opcode, 6, 1)) {
22298 case NM_ADDIUR1SP:
22299 imm = extract32(ctx->opcode, 0, 6) << 2;
22300 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22301 break;
22302 default:
22303 generate_exception_end(ctx, EXCP_RI);
22304 break;
22306 break;
22307 case NM_P16_A2:
22308 switch (extract32(ctx->opcode, 3, 1)) {
22309 case NM_ADDIUR2:
22310 imm = extract32(ctx->opcode, 0, 3) << 2;
22311 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22312 break;
22313 case NM_P_ADDIURS5:
22314 rt = extract32(ctx->opcode, 5, 5);
22315 if (rt != 0) {
22316 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22317 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22318 (extract32(ctx->opcode, 0, 3));
22319 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22321 break;
22323 break;
22324 case NM_P16_ADDU:
22325 switch (ctx->opcode & 0x1) {
22326 case NM_ADDU16:
22327 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22328 break;
22329 case NM_SUBU16:
22330 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22331 break;
22333 break;
22334 case NM_P16_4X4:
22335 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22336 extract32(ctx->opcode, 5, 3);
22337 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22338 extract32(ctx->opcode, 0, 3);
22339 rt = decode_gpr_gpr4(rt);
22340 rs = decode_gpr_gpr4(rs);
22341 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22342 (extract32(ctx->opcode, 3, 1))) {
22343 case NM_ADDU4X4:
22344 check_nms(ctx);
22345 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22346 break;
22347 case NM_MUL4X4:
22348 check_nms(ctx);
22349 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22350 break;
22351 default:
22352 generate_exception_end(ctx, EXCP_RI);
22353 break;
22355 break;
22356 case NM_LI16:
22358 int imm = extract32(ctx->opcode, 0, 7);
22359 imm = (imm == 0x7f ? -1 : imm);
22360 if (rt != 0) {
22361 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22364 break;
22365 case NM_ANDI16:
22367 uint32_t u = extract32(ctx->opcode, 0, 4);
22368 u = (u == 12) ? 0xff :
22369 (u == 13) ? 0xffff : u;
22370 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22372 break;
22373 case NM_P16_LB:
22374 offset = extract32(ctx->opcode, 0, 2);
22375 switch (extract32(ctx->opcode, 2, 2)) {
22376 case NM_LB16:
22377 gen_ld(ctx, OPC_LB, rt, rs, offset);
22378 break;
22379 case NM_SB16:
22380 rt = decode_gpr_gpr3_src_store(
22381 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22382 gen_st(ctx, OPC_SB, rt, rs, offset);
22383 break;
22384 case NM_LBU16:
22385 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22386 break;
22387 default:
22388 generate_exception_end(ctx, EXCP_RI);
22389 break;
22391 break;
22392 case NM_P16_LH:
22393 offset = extract32(ctx->opcode, 1, 2) << 1;
22394 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22395 case NM_LH16:
22396 gen_ld(ctx, OPC_LH, rt, rs, offset);
22397 break;
22398 case NM_SH16:
22399 rt = decode_gpr_gpr3_src_store(
22400 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22401 gen_st(ctx, OPC_SH, rt, rs, offset);
22402 break;
22403 case NM_LHU16:
22404 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22405 break;
22406 default:
22407 generate_exception_end(ctx, EXCP_RI);
22408 break;
22410 break;
22411 case NM_LW16:
22412 offset = extract32(ctx->opcode, 0, 4) << 2;
22413 gen_ld(ctx, OPC_LW, rt, rs, offset);
22414 break;
22415 case NM_LWSP16:
22416 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22417 offset = extract32(ctx->opcode, 0, 5) << 2;
22418 gen_ld(ctx, OPC_LW, rt, 29, offset);
22419 break;
22420 case NM_LW4X4:
22421 check_nms(ctx);
22422 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22423 extract32(ctx->opcode, 5, 3);
22424 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22425 extract32(ctx->opcode, 0, 3);
22426 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22427 (extract32(ctx->opcode, 8, 1) << 2);
22428 rt = decode_gpr_gpr4(rt);
22429 rs = decode_gpr_gpr4(rs);
22430 gen_ld(ctx, OPC_LW, rt, rs, offset);
22431 break;
22432 case NM_SW4X4:
22433 check_nms(ctx);
22434 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22435 extract32(ctx->opcode, 5, 3);
22436 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22437 extract32(ctx->opcode, 0, 3);
22438 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22439 (extract32(ctx->opcode, 8, 1) << 2);
22440 rt = decode_gpr_gpr4_zero(rt);
22441 rs = decode_gpr_gpr4(rs);
22442 gen_st(ctx, OPC_SW, rt, rs, offset);
22443 break;
22444 case NM_LWGP16:
22445 offset = extract32(ctx->opcode, 0, 7) << 2;
22446 gen_ld(ctx, OPC_LW, rt, 28, offset);
22447 break;
22448 case NM_SWSP16:
22449 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22450 offset = extract32(ctx->opcode, 0, 5) << 2;
22451 gen_st(ctx, OPC_SW, rt, 29, offset);
22452 break;
22453 case NM_SW16:
22454 rt = decode_gpr_gpr3_src_store(
22455 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22456 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22457 offset = extract32(ctx->opcode, 0, 4) << 2;
22458 gen_st(ctx, OPC_SW, rt, rs, offset);
22459 break;
22460 case NM_SWGP16:
22461 rt = decode_gpr_gpr3_src_store(
22462 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22463 offset = extract32(ctx->opcode, 0, 7) << 2;
22464 gen_st(ctx, OPC_SW, rt, 28, offset);
22465 break;
22466 case NM_BC16:
22467 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22468 (sextract32(ctx->opcode, 0, 1) << 10) |
22469 (extract32(ctx->opcode, 1, 9) << 1));
22470 break;
22471 case NM_BALC16:
22472 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22473 (sextract32(ctx->opcode, 0, 1) << 10) |
22474 (extract32(ctx->opcode, 1, 9) << 1));
22475 break;
22476 case NM_BEQZC16:
22477 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22478 (sextract32(ctx->opcode, 0, 1) << 7) |
22479 (extract32(ctx->opcode, 1, 6) << 1));
22480 break;
22481 case NM_BNEZC16:
22482 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22483 (sextract32(ctx->opcode, 0, 1) << 7) |
22484 (extract32(ctx->opcode, 1, 6) << 1));
22485 break;
22486 case NM_P16_BR:
22487 switch (ctx->opcode & 0xf) {
22488 case 0:
22489 /* P16.JRC */
22490 switch (extract32(ctx->opcode, 4, 1)) {
22491 case NM_JRC:
22492 gen_compute_branch_nm(ctx, OPC_JR, 2,
22493 extract32(ctx->opcode, 5, 5), 0, 0);
22494 break;
22495 case NM_JALRC16:
22496 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22497 extract32(ctx->opcode, 5, 5), 31, 0);
22498 break;
22500 break;
22501 default:
22503 /* P16.BRI */
22504 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22505 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22506 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22507 extract32(ctx->opcode, 0, 4) << 1);
22509 break;
22511 break;
22512 case NM_P16_SR:
22514 int count = extract32(ctx->opcode, 0, 4);
22515 int u = extract32(ctx->opcode, 4, 4) << 4;
22517 rt = 30 + extract32(ctx->opcode, 9, 1);
22518 switch (extract32(ctx->opcode, 8, 1)) {
22519 case NM_SAVE16:
22520 gen_save(ctx, rt, count, 0, u);
22521 break;
22522 case NM_RESTORE_JRC16:
22523 gen_restore(ctx, rt, count, 0, u);
22524 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22525 break;
22528 break;
22529 case NM_MOVEP:
22530 case NM_MOVEPREV:
22531 check_nms(ctx);
22533 static const int gpr2reg1[] = {4, 5, 6, 7};
22534 static const int gpr2reg2[] = {5, 6, 7, 8};
22535 int re;
22536 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22537 extract32(ctx->opcode, 8, 1);
22538 int r1 = gpr2reg1[rd2];
22539 int r2 = gpr2reg2[rd2];
22540 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22541 extract32(ctx->opcode, 0, 3);
22542 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22543 extract32(ctx->opcode, 5, 3);
22544 TCGv t0 = tcg_temp_new();
22545 TCGv t1 = tcg_temp_new();
22546 if (op == NM_MOVEP) {
22547 rd = r1;
22548 re = r2;
22549 rs = decode_gpr_gpr4_zero(r3);
22550 rt = decode_gpr_gpr4_zero(r4);
22551 } else {
22552 rd = decode_gpr_gpr4(r3);
22553 re = decode_gpr_gpr4(r4);
22554 rs = r1;
22555 rt = r2;
22557 gen_load_gpr(t0, rs);
22558 gen_load_gpr(t1, rt);
22559 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22560 tcg_gen_mov_tl(cpu_gpr[re], t1);
22561 tcg_temp_free(t0);
22562 tcg_temp_free(t1);
22564 break;
22565 default:
22566 return decode_nanomips_32_48_opc(env, ctx);
22569 return 2;
22573 /* SmartMIPS extension to MIPS32 */
22575 #if defined(TARGET_MIPS64)
22577 /* MDMX extension to MIPS64 */
22579 #endif
22581 /* MIPSDSP functions. */
22582 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22583 int rd, int base, int offset)
22585 TCGv t0;
22587 check_dsp(ctx);
22588 t0 = tcg_temp_new();
22590 if (base == 0) {
22591 gen_load_gpr(t0, offset);
22592 } else if (offset == 0) {
22593 gen_load_gpr(t0, base);
22594 } else {
22595 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22598 switch (opc) {
22599 case OPC_LBUX:
22600 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22601 gen_store_gpr(t0, rd);
22602 break;
22603 case OPC_LHX:
22604 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22605 gen_store_gpr(t0, rd);
22606 break;
22607 case OPC_LWX:
22608 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22609 gen_store_gpr(t0, rd);
22610 break;
22611 #if defined(TARGET_MIPS64)
22612 case OPC_LDX:
22613 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22614 gen_store_gpr(t0, rd);
22615 break;
22616 #endif
22618 tcg_temp_free(t0);
22621 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22622 int ret, int v1, int v2)
22624 TCGv v1_t;
22625 TCGv v2_t;
22627 if (ret == 0) {
22628 /* Treat as NOP. */
22629 return;
22632 v1_t = tcg_temp_new();
22633 v2_t = tcg_temp_new();
22635 gen_load_gpr(v1_t, v1);
22636 gen_load_gpr(v2_t, v2);
22638 switch (op1) {
22639 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22640 case OPC_MULT_G_2E:
22641 check_dsp_r2(ctx);
22642 switch (op2) {
22643 case OPC_ADDUH_QB:
22644 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22645 break;
22646 case OPC_ADDUH_R_QB:
22647 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22648 break;
22649 case OPC_ADDQH_PH:
22650 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22651 break;
22652 case OPC_ADDQH_R_PH:
22653 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22654 break;
22655 case OPC_ADDQH_W:
22656 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22657 break;
22658 case OPC_ADDQH_R_W:
22659 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22660 break;
22661 case OPC_SUBUH_QB:
22662 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22663 break;
22664 case OPC_SUBUH_R_QB:
22665 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22666 break;
22667 case OPC_SUBQH_PH:
22668 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22669 break;
22670 case OPC_SUBQH_R_PH:
22671 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22672 break;
22673 case OPC_SUBQH_W:
22674 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22675 break;
22676 case OPC_SUBQH_R_W:
22677 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22678 break;
22680 break;
22681 case OPC_ABSQ_S_PH_DSP:
22682 switch (op2) {
22683 case OPC_ABSQ_S_QB:
22684 check_dsp_r2(ctx);
22685 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22686 break;
22687 case OPC_ABSQ_S_PH:
22688 check_dsp(ctx);
22689 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22690 break;
22691 case OPC_ABSQ_S_W:
22692 check_dsp(ctx);
22693 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22694 break;
22695 case OPC_PRECEQ_W_PHL:
22696 check_dsp(ctx);
22697 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22698 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22699 break;
22700 case OPC_PRECEQ_W_PHR:
22701 check_dsp(ctx);
22702 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22703 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22704 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22705 break;
22706 case OPC_PRECEQU_PH_QBL:
22707 check_dsp(ctx);
22708 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22709 break;
22710 case OPC_PRECEQU_PH_QBR:
22711 check_dsp(ctx);
22712 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22713 break;
22714 case OPC_PRECEQU_PH_QBLA:
22715 check_dsp(ctx);
22716 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22717 break;
22718 case OPC_PRECEQU_PH_QBRA:
22719 check_dsp(ctx);
22720 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22721 break;
22722 case OPC_PRECEU_PH_QBL:
22723 check_dsp(ctx);
22724 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22725 break;
22726 case OPC_PRECEU_PH_QBR:
22727 check_dsp(ctx);
22728 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22729 break;
22730 case OPC_PRECEU_PH_QBLA:
22731 check_dsp(ctx);
22732 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22733 break;
22734 case OPC_PRECEU_PH_QBRA:
22735 check_dsp(ctx);
22736 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22737 break;
22739 break;
22740 case OPC_ADDU_QB_DSP:
22741 switch (op2) {
22742 case OPC_ADDQ_PH:
22743 check_dsp(ctx);
22744 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22745 break;
22746 case OPC_ADDQ_S_PH:
22747 check_dsp(ctx);
22748 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22749 break;
22750 case OPC_ADDQ_S_W:
22751 check_dsp(ctx);
22752 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22753 break;
22754 case OPC_ADDU_QB:
22755 check_dsp(ctx);
22756 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22757 break;
22758 case OPC_ADDU_S_QB:
22759 check_dsp(ctx);
22760 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22761 break;
22762 case OPC_ADDU_PH:
22763 check_dsp_r2(ctx);
22764 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_ADDU_S_PH:
22767 check_dsp_r2(ctx);
22768 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22769 break;
22770 case OPC_SUBQ_PH:
22771 check_dsp(ctx);
22772 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_SUBQ_S_PH:
22775 check_dsp(ctx);
22776 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22777 break;
22778 case OPC_SUBQ_S_W:
22779 check_dsp(ctx);
22780 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_SUBU_QB:
22783 check_dsp(ctx);
22784 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_SUBU_S_QB:
22787 check_dsp(ctx);
22788 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_SUBU_PH:
22791 check_dsp_r2(ctx);
22792 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_SUBU_S_PH:
22795 check_dsp_r2(ctx);
22796 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_ADDSC:
22799 check_dsp(ctx);
22800 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_ADDWC:
22803 check_dsp(ctx);
22804 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_MODSUB:
22807 check_dsp(ctx);
22808 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22809 break;
22810 case OPC_RADDU_W_QB:
22811 check_dsp(ctx);
22812 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22813 break;
22815 break;
22816 case OPC_CMPU_EQ_QB_DSP:
22817 switch (op2) {
22818 case OPC_PRECR_QB_PH:
22819 check_dsp_r2(ctx);
22820 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22821 break;
22822 case OPC_PRECRQ_QB_PH:
22823 check_dsp(ctx);
22824 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22825 break;
22826 case OPC_PRECR_SRA_PH_W:
22827 check_dsp_r2(ctx);
22829 TCGv_i32 sa_t = tcg_const_i32(v2);
22830 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22831 cpu_gpr[ret]);
22832 tcg_temp_free_i32(sa_t);
22833 break;
22835 case OPC_PRECR_SRA_R_PH_W:
22836 check_dsp_r2(ctx);
22838 TCGv_i32 sa_t = tcg_const_i32(v2);
22839 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22840 cpu_gpr[ret]);
22841 tcg_temp_free_i32(sa_t);
22842 break;
22844 case OPC_PRECRQ_PH_W:
22845 check_dsp(ctx);
22846 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22847 break;
22848 case OPC_PRECRQ_RS_PH_W:
22849 check_dsp(ctx);
22850 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22851 break;
22852 case OPC_PRECRQU_S_QB_PH:
22853 check_dsp(ctx);
22854 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22855 break;
22857 break;
22858 #ifdef TARGET_MIPS64
22859 case OPC_ABSQ_S_QH_DSP:
22860 switch (op2) {
22861 case OPC_PRECEQ_L_PWL:
22862 check_dsp(ctx);
22863 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22864 break;
22865 case OPC_PRECEQ_L_PWR:
22866 check_dsp(ctx);
22867 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22868 break;
22869 case OPC_PRECEQ_PW_QHL:
22870 check_dsp(ctx);
22871 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22872 break;
22873 case OPC_PRECEQ_PW_QHR:
22874 check_dsp(ctx);
22875 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22876 break;
22877 case OPC_PRECEQ_PW_QHLA:
22878 check_dsp(ctx);
22879 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22880 break;
22881 case OPC_PRECEQ_PW_QHRA:
22882 check_dsp(ctx);
22883 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22884 break;
22885 case OPC_PRECEQU_QH_OBL:
22886 check_dsp(ctx);
22887 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22888 break;
22889 case OPC_PRECEQU_QH_OBR:
22890 check_dsp(ctx);
22891 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22892 break;
22893 case OPC_PRECEQU_QH_OBLA:
22894 check_dsp(ctx);
22895 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22896 break;
22897 case OPC_PRECEQU_QH_OBRA:
22898 check_dsp(ctx);
22899 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22900 break;
22901 case OPC_PRECEU_QH_OBL:
22902 check_dsp(ctx);
22903 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22904 break;
22905 case OPC_PRECEU_QH_OBR:
22906 check_dsp(ctx);
22907 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22908 break;
22909 case OPC_PRECEU_QH_OBLA:
22910 check_dsp(ctx);
22911 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22912 break;
22913 case OPC_PRECEU_QH_OBRA:
22914 check_dsp(ctx);
22915 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22916 break;
22917 case OPC_ABSQ_S_OB:
22918 check_dsp_r2(ctx);
22919 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22920 break;
22921 case OPC_ABSQ_S_PW:
22922 check_dsp(ctx);
22923 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22924 break;
22925 case OPC_ABSQ_S_QH:
22926 check_dsp(ctx);
22927 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22928 break;
22930 break;
22931 case OPC_ADDU_OB_DSP:
22932 switch (op2) {
22933 case OPC_RADDU_L_OB:
22934 check_dsp(ctx);
22935 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22936 break;
22937 case OPC_SUBQ_PW:
22938 check_dsp(ctx);
22939 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22940 break;
22941 case OPC_SUBQ_S_PW:
22942 check_dsp(ctx);
22943 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22944 break;
22945 case OPC_SUBQ_QH:
22946 check_dsp(ctx);
22947 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22948 break;
22949 case OPC_SUBQ_S_QH:
22950 check_dsp(ctx);
22951 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22952 break;
22953 case OPC_SUBU_OB:
22954 check_dsp(ctx);
22955 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22956 break;
22957 case OPC_SUBU_S_OB:
22958 check_dsp(ctx);
22959 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22960 break;
22961 case OPC_SUBU_QH:
22962 check_dsp_r2(ctx);
22963 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22964 break;
22965 case OPC_SUBU_S_QH:
22966 check_dsp_r2(ctx);
22967 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22968 break;
22969 case OPC_SUBUH_OB:
22970 check_dsp_r2(ctx);
22971 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22972 break;
22973 case OPC_SUBUH_R_OB:
22974 check_dsp_r2(ctx);
22975 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22976 break;
22977 case OPC_ADDQ_PW:
22978 check_dsp(ctx);
22979 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22980 break;
22981 case OPC_ADDQ_S_PW:
22982 check_dsp(ctx);
22983 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22984 break;
22985 case OPC_ADDQ_QH:
22986 check_dsp(ctx);
22987 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22988 break;
22989 case OPC_ADDQ_S_QH:
22990 check_dsp(ctx);
22991 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22992 break;
22993 case OPC_ADDU_OB:
22994 check_dsp(ctx);
22995 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22996 break;
22997 case OPC_ADDU_S_OB:
22998 check_dsp(ctx);
22999 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23000 break;
23001 case OPC_ADDU_QH:
23002 check_dsp_r2(ctx);
23003 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23004 break;
23005 case OPC_ADDU_S_QH:
23006 check_dsp_r2(ctx);
23007 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23008 break;
23009 case OPC_ADDUH_OB:
23010 check_dsp_r2(ctx);
23011 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23012 break;
23013 case OPC_ADDUH_R_OB:
23014 check_dsp_r2(ctx);
23015 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23016 break;
23018 break;
23019 case OPC_CMPU_EQ_OB_DSP:
23020 switch (op2) {
23021 case OPC_PRECR_OB_QH:
23022 check_dsp_r2(ctx);
23023 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23024 break;
23025 case OPC_PRECR_SRA_QH_PW:
23026 check_dsp_r2(ctx);
23028 TCGv_i32 ret_t = tcg_const_i32(ret);
23029 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23030 tcg_temp_free_i32(ret_t);
23031 break;
23033 case OPC_PRECR_SRA_R_QH_PW:
23034 check_dsp_r2(ctx);
23036 TCGv_i32 sa_v = tcg_const_i32(ret);
23037 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23038 tcg_temp_free_i32(sa_v);
23039 break;
23041 case OPC_PRECRQ_OB_QH:
23042 check_dsp(ctx);
23043 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23044 break;
23045 case OPC_PRECRQ_PW_L:
23046 check_dsp(ctx);
23047 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23048 break;
23049 case OPC_PRECRQ_QH_PW:
23050 check_dsp(ctx);
23051 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23052 break;
23053 case OPC_PRECRQ_RS_QH_PW:
23054 check_dsp(ctx);
23055 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23056 break;
23057 case OPC_PRECRQU_S_OB_QH:
23058 check_dsp(ctx);
23059 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23060 break;
23062 break;
23063 #endif
23066 tcg_temp_free(v1_t);
23067 tcg_temp_free(v2_t);
23070 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23071 int ret, int v1, int v2)
23073 uint32_t op2;
23074 TCGv t0;
23075 TCGv v1_t;
23076 TCGv v2_t;
23078 if (ret == 0) {
23079 /* Treat as NOP. */
23080 return;
23083 t0 = tcg_temp_new();
23084 v1_t = tcg_temp_new();
23085 v2_t = tcg_temp_new();
23087 tcg_gen_movi_tl(t0, v1);
23088 gen_load_gpr(v1_t, v1);
23089 gen_load_gpr(v2_t, v2);
23091 switch (opc) {
23092 case OPC_SHLL_QB_DSP:
23094 op2 = MASK_SHLL_QB(ctx->opcode);
23095 switch (op2) {
23096 case OPC_SHLL_QB:
23097 check_dsp(ctx);
23098 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23099 break;
23100 case OPC_SHLLV_QB:
23101 check_dsp(ctx);
23102 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23103 break;
23104 case OPC_SHLL_PH:
23105 check_dsp(ctx);
23106 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23107 break;
23108 case OPC_SHLLV_PH:
23109 check_dsp(ctx);
23110 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23111 break;
23112 case OPC_SHLL_S_PH:
23113 check_dsp(ctx);
23114 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23115 break;
23116 case OPC_SHLLV_S_PH:
23117 check_dsp(ctx);
23118 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23119 break;
23120 case OPC_SHLL_S_W:
23121 check_dsp(ctx);
23122 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23123 break;
23124 case OPC_SHLLV_S_W:
23125 check_dsp(ctx);
23126 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23127 break;
23128 case OPC_SHRL_QB:
23129 check_dsp(ctx);
23130 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23131 break;
23132 case OPC_SHRLV_QB:
23133 check_dsp(ctx);
23134 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23135 break;
23136 case OPC_SHRL_PH:
23137 check_dsp_r2(ctx);
23138 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23139 break;
23140 case OPC_SHRLV_PH:
23141 check_dsp_r2(ctx);
23142 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23143 break;
23144 case OPC_SHRA_QB:
23145 check_dsp_r2(ctx);
23146 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23147 break;
23148 case OPC_SHRA_R_QB:
23149 check_dsp_r2(ctx);
23150 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23151 break;
23152 case OPC_SHRAV_QB:
23153 check_dsp_r2(ctx);
23154 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23155 break;
23156 case OPC_SHRAV_R_QB:
23157 check_dsp_r2(ctx);
23158 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23159 break;
23160 case OPC_SHRA_PH:
23161 check_dsp(ctx);
23162 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23163 break;
23164 case OPC_SHRA_R_PH:
23165 check_dsp(ctx);
23166 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23167 break;
23168 case OPC_SHRAV_PH:
23169 check_dsp(ctx);
23170 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23171 break;
23172 case OPC_SHRAV_R_PH:
23173 check_dsp(ctx);
23174 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23175 break;
23176 case OPC_SHRA_R_W:
23177 check_dsp(ctx);
23178 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23179 break;
23180 case OPC_SHRAV_R_W:
23181 check_dsp(ctx);
23182 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23183 break;
23184 default: /* Invalid */
23185 MIPS_INVAL("MASK SHLL.QB");
23186 generate_exception_end(ctx, EXCP_RI);
23187 break;
23189 break;
23191 #ifdef TARGET_MIPS64
23192 case OPC_SHLL_OB_DSP:
23193 op2 = MASK_SHLL_OB(ctx->opcode);
23194 switch (op2) {
23195 case OPC_SHLL_PW:
23196 check_dsp(ctx);
23197 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23198 break;
23199 case OPC_SHLLV_PW:
23200 check_dsp(ctx);
23201 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23202 break;
23203 case OPC_SHLL_S_PW:
23204 check_dsp(ctx);
23205 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23206 break;
23207 case OPC_SHLLV_S_PW:
23208 check_dsp(ctx);
23209 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23210 break;
23211 case OPC_SHLL_OB:
23212 check_dsp(ctx);
23213 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23214 break;
23215 case OPC_SHLLV_OB:
23216 check_dsp(ctx);
23217 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23218 break;
23219 case OPC_SHLL_QH:
23220 check_dsp(ctx);
23221 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23222 break;
23223 case OPC_SHLLV_QH:
23224 check_dsp(ctx);
23225 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23226 break;
23227 case OPC_SHLL_S_QH:
23228 check_dsp(ctx);
23229 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23230 break;
23231 case OPC_SHLLV_S_QH:
23232 check_dsp(ctx);
23233 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23234 break;
23235 case OPC_SHRA_OB:
23236 check_dsp_r2(ctx);
23237 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23238 break;
23239 case OPC_SHRAV_OB:
23240 check_dsp_r2(ctx);
23241 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23242 break;
23243 case OPC_SHRA_R_OB:
23244 check_dsp_r2(ctx);
23245 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23246 break;
23247 case OPC_SHRAV_R_OB:
23248 check_dsp_r2(ctx);
23249 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23250 break;
23251 case OPC_SHRA_PW:
23252 check_dsp(ctx);
23253 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23254 break;
23255 case OPC_SHRAV_PW:
23256 check_dsp(ctx);
23257 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23258 break;
23259 case OPC_SHRA_R_PW:
23260 check_dsp(ctx);
23261 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23262 break;
23263 case OPC_SHRAV_R_PW:
23264 check_dsp(ctx);
23265 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23266 break;
23267 case OPC_SHRA_QH:
23268 check_dsp(ctx);
23269 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23270 break;
23271 case OPC_SHRAV_QH:
23272 check_dsp(ctx);
23273 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23274 break;
23275 case OPC_SHRA_R_QH:
23276 check_dsp(ctx);
23277 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23278 break;
23279 case OPC_SHRAV_R_QH:
23280 check_dsp(ctx);
23281 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23282 break;
23283 case OPC_SHRL_OB:
23284 check_dsp(ctx);
23285 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23286 break;
23287 case OPC_SHRLV_OB:
23288 check_dsp(ctx);
23289 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23290 break;
23291 case OPC_SHRL_QH:
23292 check_dsp_r2(ctx);
23293 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23294 break;
23295 case OPC_SHRLV_QH:
23296 check_dsp_r2(ctx);
23297 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23298 break;
23299 default: /* Invalid */
23300 MIPS_INVAL("MASK SHLL.OB");
23301 generate_exception_end(ctx, EXCP_RI);
23302 break;
23304 break;
23305 #endif
23308 tcg_temp_free(t0);
23309 tcg_temp_free(v1_t);
23310 tcg_temp_free(v2_t);
23313 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23314 int ret, int v1, int v2, int check_ret)
23316 TCGv_i32 t0;
23317 TCGv v1_t;
23318 TCGv v2_t;
23320 if ((ret == 0) && (check_ret == 1)) {
23321 /* Treat as NOP. */
23322 return;
23325 t0 = tcg_temp_new_i32();
23326 v1_t = tcg_temp_new();
23327 v2_t = tcg_temp_new();
23329 tcg_gen_movi_i32(t0, ret);
23330 gen_load_gpr(v1_t, v1);
23331 gen_load_gpr(v2_t, v2);
23333 switch (op1) {
23335 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23336 * the same mask and op1.
23338 case OPC_MULT_G_2E:
23339 check_dsp_r2(ctx);
23340 switch (op2) {
23341 case OPC_MUL_PH:
23342 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23343 break;
23344 case OPC_MUL_S_PH:
23345 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23346 break;
23347 case OPC_MULQ_S_W:
23348 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23349 break;
23350 case OPC_MULQ_RS_W:
23351 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23352 break;
23354 break;
23355 case OPC_DPA_W_PH_DSP:
23356 switch (op2) {
23357 case OPC_DPAU_H_QBL:
23358 check_dsp(ctx);
23359 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23360 break;
23361 case OPC_DPAU_H_QBR:
23362 check_dsp(ctx);
23363 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23364 break;
23365 case OPC_DPSU_H_QBL:
23366 check_dsp(ctx);
23367 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23368 break;
23369 case OPC_DPSU_H_QBR:
23370 check_dsp(ctx);
23371 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23372 break;
23373 case OPC_DPA_W_PH:
23374 check_dsp_r2(ctx);
23375 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23376 break;
23377 case OPC_DPAX_W_PH:
23378 check_dsp_r2(ctx);
23379 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23380 break;
23381 case OPC_DPAQ_S_W_PH:
23382 check_dsp(ctx);
23383 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23384 break;
23385 case OPC_DPAQX_S_W_PH:
23386 check_dsp_r2(ctx);
23387 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23388 break;
23389 case OPC_DPAQX_SA_W_PH:
23390 check_dsp_r2(ctx);
23391 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23392 break;
23393 case OPC_DPS_W_PH:
23394 check_dsp_r2(ctx);
23395 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23396 break;
23397 case OPC_DPSX_W_PH:
23398 check_dsp_r2(ctx);
23399 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23400 break;
23401 case OPC_DPSQ_S_W_PH:
23402 check_dsp(ctx);
23403 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23404 break;
23405 case OPC_DPSQX_S_W_PH:
23406 check_dsp_r2(ctx);
23407 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23408 break;
23409 case OPC_DPSQX_SA_W_PH:
23410 check_dsp_r2(ctx);
23411 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23412 break;
23413 case OPC_MULSAQ_S_W_PH:
23414 check_dsp(ctx);
23415 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23416 break;
23417 case OPC_DPAQ_SA_L_W:
23418 check_dsp(ctx);
23419 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23420 break;
23421 case OPC_DPSQ_SA_L_W:
23422 check_dsp(ctx);
23423 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23424 break;
23425 case OPC_MAQ_S_W_PHL:
23426 check_dsp(ctx);
23427 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23428 break;
23429 case OPC_MAQ_S_W_PHR:
23430 check_dsp(ctx);
23431 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23432 break;
23433 case OPC_MAQ_SA_W_PHL:
23434 check_dsp(ctx);
23435 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23436 break;
23437 case OPC_MAQ_SA_W_PHR:
23438 check_dsp(ctx);
23439 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23440 break;
23441 case OPC_MULSA_W_PH:
23442 check_dsp_r2(ctx);
23443 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23444 break;
23446 break;
23447 #ifdef TARGET_MIPS64
23448 case OPC_DPAQ_W_QH_DSP:
23450 int ac = ret & 0x03;
23451 tcg_gen_movi_i32(t0, ac);
23453 switch (op2) {
23454 case OPC_DMADD:
23455 check_dsp(ctx);
23456 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23457 break;
23458 case OPC_DMADDU:
23459 check_dsp(ctx);
23460 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23461 break;
23462 case OPC_DMSUB:
23463 check_dsp(ctx);
23464 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23465 break;
23466 case OPC_DMSUBU:
23467 check_dsp(ctx);
23468 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23469 break;
23470 case OPC_DPA_W_QH:
23471 check_dsp_r2(ctx);
23472 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23473 break;
23474 case OPC_DPAQ_S_W_QH:
23475 check_dsp(ctx);
23476 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23477 break;
23478 case OPC_DPAQ_SA_L_PW:
23479 check_dsp(ctx);
23480 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23481 break;
23482 case OPC_DPAU_H_OBL:
23483 check_dsp(ctx);
23484 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23485 break;
23486 case OPC_DPAU_H_OBR:
23487 check_dsp(ctx);
23488 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23489 break;
23490 case OPC_DPS_W_QH:
23491 check_dsp_r2(ctx);
23492 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23493 break;
23494 case OPC_DPSQ_S_W_QH:
23495 check_dsp(ctx);
23496 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23497 break;
23498 case OPC_DPSQ_SA_L_PW:
23499 check_dsp(ctx);
23500 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23501 break;
23502 case OPC_DPSU_H_OBL:
23503 check_dsp(ctx);
23504 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23505 break;
23506 case OPC_DPSU_H_OBR:
23507 check_dsp(ctx);
23508 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23509 break;
23510 case OPC_MAQ_S_L_PWL:
23511 check_dsp(ctx);
23512 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23513 break;
23514 case OPC_MAQ_S_L_PWR:
23515 check_dsp(ctx);
23516 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23517 break;
23518 case OPC_MAQ_S_W_QHLL:
23519 check_dsp(ctx);
23520 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23521 break;
23522 case OPC_MAQ_SA_W_QHLL:
23523 check_dsp(ctx);
23524 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23525 break;
23526 case OPC_MAQ_S_W_QHLR:
23527 check_dsp(ctx);
23528 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23529 break;
23530 case OPC_MAQ_SA_W_QHLR:
23531 check_dsp(ctx);
23532 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23533 break;
23534 case OPC_MAQ_S_W_QHRL:
23535 check_dsp(ctx);
23536 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23537 break;
23538 case OPC_MAQ_SA_W_QHRL:
23539 check_dsp(ctx);
23540 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23541 break;
23542 case OPC_MAQ_S_W_QHRR:
23543 check_dsp(ctx);
23544 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23545 break;
23546 case OPC_MAQ_SA_W_QHRR:
23547 check_dsp(ctx);
23548 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23549 break;
23550 case OPC_MULSAQ_S_L_PW:
23551 check_dsp(ctx);
23552 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23553 break;
23554 case OPC_MULSAQ_S_W_QH:
23555 check_dsp(ctx);
23556 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23557 break;
23560 break;
23561 #endif
23562 case OPC_ADDU_QB_DSP:
23563 switch (op2) {
23564 case OPC_MULEU_S_PH_QBL:
23565 check_dsp(ctx);
23566 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23567 break;
23568 case OPC_MULEU_S_PH_QBR:
23569 check_dsp(ctx);
23570 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23571 break;
23572 case OPC_MULQ_RS_PH:
23573 check_dsp(ctx);
23574 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23575 break;
23576 case OPC_MULEQ_S_W_PHL:
23577 check_dsp(ctx);
23578 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23579 break;
23580 case OPC_MULEQ_S_W_PHR:
23581 check_dsp(ctx);
23582 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23583 break;
23584 case OPC_MULQ_S_PH:
23585 check_dsp_r2(ctx);
23586 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23587 break;
23589 break;
23590 #ifdef TARGET_MIPS64
23591 case OPC_ADDU_OB_DSP:
23592 switch (op2) {
23593 case OPC_MULEQ_S_PW_QHL:
23594 check_dsp(ctx);
23595 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23596 break;
23597 case OPC_MULEQ_S_PW_QHR:
23598 check_dsp(ctx);
23599 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23600 break;
23601 case OPC_MULEU_S_QH_OBL:
23602 check_dsp(ctx);
23603 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23604 break;
23605 case OPC_MULEU_S_QH_OBR:
23606 check_dsp(ctx);
23607 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23608 break;
23609 case OPC_MULQ_RS_QH:
23610 check_dsp(ctx);
23611 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23612 break;
23614 break;
23615 #endif
23618 tcg_temp_free_i32(t0);
23619 tcg_temp_free(v1_t);
23620 tcg_temp_free(v2_t);
23623 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23624 int ret, int val)
23626 int16_t imm;
23627 TCGv t0;
23628 TCGv val_t;
23630 if (ret == 0) {
23631 /* Treat as NOP. */
23632 return;
23635 t0 = tcg_temp_new();
23636 val_t = tcg_temp_new();
23637 gen_load_gpr(val_t, val);
23639 switch (op1) {
23640 case OPC_ABSQ_S_PH_DSP:
23641 switch (op2) {
23642 case OPC_BITREV:
23643 check_dsp(ctx);
23644 gen_helper_bitrev(cpu_gpr[ret], val_t);
23645 break;
23646 case OPC_REPL_QB:
23647 check_dsp(ctx);
23649 target_long result;
23650 imm = (ctx->opcode >> 16) & 0xFF;
23651 result = (uint32_t)imm << 24 |
23652 (uint32_t)imm << 16 |
23653 (uint32_t)imm << 8 |
23654 (uint32_t)imm;
23655 result = (int32_t)result;
23656 tcg_gen_movi_tl(cpu_gpr[ret], result);
23658 break;
23659 case OPC_REPLV_QB:
23660 check_dsp(ctx);
23661 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23662 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23663 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23664 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23665 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23666 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23667 break;
23668 case OPC_REPL_PH:
23669 check_dsp(ctx);
23671 imm = (ctx->opcode >> 16) & 0x03FF;
23672 imm = (int16_t)(imm << 6) >> 6;
23673 tcg_gen_movi_tl(cpu_gpr[ret], \
23674 (target_long)((int32_t)imm << 16 | \
23675 (uint16_t)imm));
23677 break;
23678 case OPC_REPLV_PH:
23679 check_dsp(ctx);
23680 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23681 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23682 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23683 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23684 break;
23686 break;
23687 #ifdef TARGET_MIPS64
23688 case OPC_ABSQ_S_QH_DSP:
23689 switch (op2) {
23690 case OPC_REPL_OB:
23691 check_dsp(ctx);
23693 target_long temp;
23695 imm = (ctx->opcode >> 16) & 0xFF;
23696 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23697 temp = (temp << 16) | temp;
23698 temp = (temp << 32) | temp;
23699 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23700 break;
23702 case OPC_REPL_PW:
23703 check_dsp(ctx);
23705 target_long temp;
23707 imm = (ctx->opcode >> 16) & 0x03FF;
23708 imm = (int16_t)(imm << 6) >> 6;
23709 temp = ((target_long)imm << 32) \
23710 | ((target_long)imm & 0xFFFFFFFF);
23711 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23712 break;
23714 case OPC_REPL_QH:
23715 check_dsp(ctx);
23717 target_long temp;
23719 imm = (ctx->opcode >> 16) & 0x03FF;
23720 imm = (int16_t)(imm << 6) >> 6;
23722 temp = ((uint64_t)(uint16_t)imm << 48) |
23723 ((uint64_t)(uint16_t)imm << 32) |
23724 ((uint64_t)(uint16_t)imm << 16) |
23725 (uint64_t)(uint16_t)imm;
23726 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23727 break;
23729 case OPC_REPLV_OB:
23730 check_dsp(ctx);
23731 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23732 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23733 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23734 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23735 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23736 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23737 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23738 break;
23739 case OPC_REPLV_PW:
23740 check_dsp(ctx);
23741 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23742 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23743 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23744 break;
23745 case OPC_REPLV_QH:
23746 check_dsp(ctx);
23747 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23748 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23749 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23750 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23751 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23752 break;
23754 break;
23755 #endif
23757 tcg_temp_free(t0);
23758 tcg_temp_free(val_t);
23761 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23762 uint32_t op1, uint32_t op2,
23763 int ret, int v1, int v2, int check_ret)
23765 TCGv t1;
23766 TCGv v1_t;
23767 TCGv v2_t;
23769 if ((ret == 0) && (check_ret == 1)) {
23770 /* Treat as NOP. */
23771 return;
23774 t1 = tcg_temp_new();
23775 v1_t = tcg_temp_new();
23776 v2_t = tcg_temp_new();
23778 gen_load_gpr(v1_t, v1);
23779 gen_load_gpr(v2_t, v2);
23781 switch (op1) {
23782 case OPC_CMPU_EQ_QB_DSP:
23783 switch (op2) {
23784 case OPC_CMPU_EQ_QB:
23785 check_dsp(ctx);
23786 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23787 break;
23788 case OPC_CMPU_LT_QB:
23789 check_dsp(ctx);
23790 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23791 break;
23792 case OPC_CMPU_LE_QB:
23793 check_dsp(ctx);
23794 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23795 break;
23796 case OPC_CMPGU_EQ_QB:
23797 check_dsp(ctx);
23798 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23799 break;
23800 case OPC_CMPGU_LT_QB:
23801 check_dsp(ctx);
23802 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23803 break;
23804 case OPC_CMPGU_LE_QB:
23805 check_dsp(ctx);
23806 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23807 break;
23808 case OPC_CMPGDU_EQ_QB:
23809 check_dsp_r2(ctx);
23810 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23811 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23812 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23813 tcg_gen_shli_tl(t1, t1, 24);
23814 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23815 break;
23816 case OPC_CMPGDU_LT_QB:
23817 check_dsp_r2(ctx);
23818 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23819 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23820 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23821 tcg_gen_shli_tl(t1, t1, 24);
23822 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23823 break;
23824 case OPC_CMPGDU_LE_QB:
23825 check_dsp_r2(ctx);
23826 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23827 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23828 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23829 tcg_gen_shli_tl(t1, t1, 24);
23830 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23831 break;
23832 case OPC_CMP_EQ_PH:
23833 check_dsp(ctx);
23834 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23835 break;
23836 case OPC_CMP_LT_PH:
23837 check_dsp(ctx);
23838 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23839 break;
23840 case OPC_CMP_LE_PH:
23841 check_dsp(ctx);
23842 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23843 break;
23844 case OPC_PICK_QB:
23845 check_dsp(ctx);
23846 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23847 break;
23848 case OPC_PICK_PH:
23849 check_dsp(ctx);
23850 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23851 break;
23852 case OPC_PACKRL_PH:
23853 check_dsp(ctx);
23854 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23855 break;
23857 break;
23858 #ifdef TARGET_MIPS64
23859 case OPC_CMPU_EQ_OB_DSP:
23860 switch (op2) {
23861 case OPC_CMP_EQ_PW:
23862 check_dsp(ctx);
23863 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23864 break;
23865 case OPC_CMP_LT_PW:
23866 check_dsp(ctx);
23867 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23868 break;
23869 case OPC_CMP_LE_PW:
23870 check_dsp(ctx);
23871 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23872 break;
23873 case OPC_CMP_EQ_QH:
23874 check_dsp(ctx);
23875 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23876 break;
23877 case OPC_CMP_LT_QH:
23878 check_dsp(ctx);
23879 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23880 break;
23881 case OPC_CMP_LE_QH:
23882 check_dsp(ctx);
23883 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23884 break;
23885 case OPC_CMPGDU_EQ_OB:
23886 check_dsp_r2(ctx);
23887 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23888 break;
23889 case OPC_CMPGDU_LT_OB:
23890 check_dsp_r2(ctx);
23891 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23892 break;
23893 case OPC_CMPGDU_LE_OB:
23894 check_dsp_r2(ctx);
23895 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23896 break;
23897 case OPC_CMPGU_EQ_OB:
23898 check_dsp(ctx);
23899 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23900 break;
23901 case OPC_CMPGU_LT_OB:
23902 check_dsp(ctx);
23903 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23904 break;
23905 case OPC_CMPGU_LE_OB:
23906 check_dsp(ctx);
23907 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23908 break;
23909 case OPC_CMPU_EQ_OB:
23910 check_dsp(ctx);
23911 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23912 break;
23913 case OPC_CMPU_LT_OB:
23914 check_dsp(ctx);
23915 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23916 break;
23917 case OPC_CMPU_LE_OB:
23918 check_dsp(ctx);
23919 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23920 break;
23921 case OPC_PACKRL_PW:
23922 check_dsp(ctx);
23923 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23924 break;
23925 case OPC_PICK_OB:
23926 check_dsp(ctx);
23927 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23928 break;
23929 case OPC_PICK_PW:
23930 check_dsp(ctx);
23931 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23932 break;
23933 case OPC_PICK_QH:
23934 check_dsp(ctx);
23935 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23936 break;
23938 break;
23939 #endif
23942 tcg_temp_free(t1);
23943 tcg_temp_free(v1_t);
23944 tcg_temp_free(v2_t);
23947 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23948 uint32_t op1, int rt, int rs, int sa)
23950 TCGv t0;
23952 check_dsp_r2(ctx);
23954 if (rt == 0) {
23955 /* Treat as NOP. */
23956 return;
23959 t0 = tcg_temp_new();
23960 gen_load_gpr(t0, rs);
23962 switch (op1) {
23963 case OPC_APPEND_DSP:
23964 switch (MASK_APPEND(ctx->opcode)) {
23965 case OPC_APPEND:
23966 if (sa != 0) {
23967 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23969 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23970 break;
23971 case OPC_PREPEND:
23972 if (sa != 0) {
23973 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23974 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23975 tcg_gen_shli_tl(t0, t0, 32 - sa);
23976 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23978 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23979 break;
23980 case OPC_BALIGN:
23981 sa &= 3;
23982 if (sa != 0 && sa != 2) {
23983 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23984 tcg_gen_ext32u_tl(t0, t0);
23985 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23986 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23988 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23989 break;
23990 default: /* Invalid */
23991 MIPS_INVAL("MASK APPEND");
23992 generate_exception_end(ctx, EXCP_RI);
23993 break;
23995 break;
23996 #ifdef TARGET_MIPS64
23997 case OPC_DAPPEND_DSP:
23998 switch (MASK_DAPPEND(ctx->opcode)) {
23999 case OPC_DAPPEND:
24000 if (sa != 0) {
24001 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24003 break;
24004 case OPC_PREPENDD:
24005 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24006 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24007 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24008 break;
24009 case OPC_PREPENDW:
24010 if (sa != 0) {
24011 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24012 tcg_gen_shli_tl(t0, t0, 64 - sa);
24013 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24015 break;
24016 case OPC_DBALIGN:
24017 sa &= 7;
24018 if (sa != 0 && sa != 2 && sa != 4) {
24019 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24020 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24021 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24023 break;
24024 default: /* Invalid */
24025 MIPS_INVAL("MASK DAPPEND");
24026 generate_exception_end(ctx, EXCP_RI);
24027 break;
24029 break;
24030 #endif
24032 tcg_temp_free(t0);
24035 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24036 int ret, int v1, int v2, int check_ret)
24039 TCGv t0;
24040 TCGv t1;
24041 TCGv v1_t;
24042 TCGv v2_t;
24043 int16_t imm;
24045 if ((ret == 0) && (check_ret == 1)) {
24046 /* Treat as NOP. */
24047 return;
24050 t0 = tcg_temp_new();
24051 t1 = tcg_temp_new();
24052 v1_t = tcg_temp_new();
24053 v2_t = tcg_temp_new();
24055 gen_load_gpr(v1_t, v1);
24056 gen_load_gpr(v2_t, v2);
24058 switch (op1) {
24059 case OPC_EXTR_W_DSP:
24060 check_dsp(ctx);
24061 switch (op2) {
24062 case OPC_EXTR_W:
24063 tcg_gen_movi_tl(t0, v2);
24064 tcg_gen_movi_tl(t1, v1);
24065 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24066 break;
24067 case OPC_EXTR_R_W:
24068 tcg_gen_movi_tl(t0, v2);
24069 tcg_gen_movi_tl(t1, v1);
24070 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24071 break;
24072 case OPC_EXTR_RS_W:
24073 tcg_gen_movi_tl(t0, v2);
24074 tcg_gen_movi_tl(t1, v1);
24075 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24076 break;
24077 case OPC_EXTR_S_H:
24078 tcg_gen_movi_tl(t0, v2);
24079 tcg_gen_movi_tl(t1, v1);
24080 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24081 break;
24082 case OPC_EXTRV_S_H:
24083 tcg_gen_movi_tl(t0, v2);
24084 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24085 break;
24086 case OPC_EXTRV_W:
24087 tcg_gen_movi_tl(t0, v2);
24088 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24089 break;
24090 case OPC_EXTRV_R_W:
24091 tcg_gen_movi_tl(t0, v2);
24092 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24093 break;
24094 case OPC_EXTRV_RS_W:
24095 tcg_gen_movi_tl(t0, v2);
24096 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24097 break;
24098 case OPC_EXTP:
24099 tcg_gen_movi_tl(t0, v2);
24100 tcg_gen_movi_tl(t1, v1);
24101 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24102 break;
24103 case OPC_EXTPV:
24104 tcg_gen_movi_tl(t0, v2);
24105 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24106 break;
24107 case OPC_EXTPDP:
24108 tcg_gen_movi_tl(t0, v2);
24109 tcg_gen_movi_tl(t1, v1);
24110 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24111 break;
24112 case OPC_EXTPDPV:
24113 tcg_gen_movi_tl(t0, v2);
24114 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24115 break;
24116 case OPC_SHILO:
24117 imm = (ctx->opcode >> 20) & 0x3F;
24118 tcg_gen_movi_tl(t0, ret);
24119 tcg_gen_movi_tl(t1, imm);
24120 gen_helper_shilo(t0, t1, cpu_env);
24121 break;
24122 case OPC_SHILOV:
24123 tcg_gen_movi_tl(t0, ret);
24124 gen_helper_shilo(t0, v1_t, cpu_env);
24125 break;
24126 case OPC_MTHLIP:
24127 tcg_gen_movi_tl(t0, ret);
24128 gen_helper_mthlip(t0, v1_t, cpu_env);
24129 break;
24130 case OPC_WRDSP:
24131 imm = (ctx->opcode >> 11) & 0x3FF;
24132 tcg_gen_movi_tl(t0, imm);
24133 gen_helper_wrdsp(v1_t, t0, cpu_env);
24134 break;
24135 case OPC_RDDSP:
24136 imm = (ctx->opcode >> 16) & 0x03FF;
24137 tcg_gen_movi_tl(t0, imm);
24138 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24139 break;
24141 break;
24142 #ifdef TARGET_MIPS64
24143 case OPC_DEXTR_W_DSP:
24144 check_dsp(ctx);
24145 switch (op2) {
24146 case OPC_DMTHLIP:
24147 tcg_gen_movi_tl(t0, ret);
24148 gen_helper_dmthlip(v1_t, t0, cpu_env);
24149 break;
24150 case OPC_DSHILO:
24152 int shift = (ctx->opcode >> 19) & 0x7F;
24153 int ac = (ctx->opcode >> 11) & 0x03;
24154 tcg_gen_movi_tl(t0, shift);
24155 tcg_gen_movi_tl(t1, ac);
24156 gen_helper_dshilo(t0, t1, cpu_env);
24157 break;
24159 case OPC_DSHILOV:
24161 int ac = (ctx->opcode >> 11) & 0x03;
24162 tcg_gen_movi_tl(t0, ac);
24163 gen_helper_dshilo(v1_t, t0, cpu_env);
24164 break;
24166 case OPC_DEXTP:
24167 tcg_gen_movi_tl(t0, v2);
24168 tcg_gen_movi_tl(t1, v1);
24170 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24171 break;
24172 case OPC_DEXTPV:
24173 tcg_gen_movi_tl(t0, v2);
24174 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24175 break;
24176 case OPC_DEXTPDP:
24177 tcg_gen_movi_tl(t0, v2);
24178 tcg_gen_movi_tl(t1, v1);
24179 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24180 break;
24181 case OPC_DEXTPDPV:
24182 tcg_gen_movi_tl(t0, v2);
24183 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24184 break;
24185 case OPC_DEXTR_L:
24186 tcg_gen_movi_tl(t0, v2);
24187 tcg_gen_movi_tl(t1, v1);
24188 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24189 break;
24190 case OPC_DEXTR_R_L:
24191 tcg_gen_movi_tl(t0, v2);
24192 tcg_gen_movi_tl(t1, v1);
24193 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24194 break;
24195 case OPC_DEXTR_RS_L:
24196 tcg_gen_movi_tl(t0, v2);
24197 tcg_gen_movi_tl(t1, v1);
24198 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24199 break;
24200 case OPC_DEXTR_W:
24201 tcg_gen_movi_tl(t0, v2);
24202 tcg_gen_movi_tl(t1, v1);
24203 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24204 break;
24205 case OPC_DEXTR_R_W:
24206 tcg_gen_movi_tl(t0, v2);
24207 tcg_gen_movi_tl(t1, v1);
24208 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24209 break;
24210 case OPC_DEXTR_RS_W:
24211 tcg_gen_movi_tl(t0, v2);
24212 tcg_gen_movi_tl(t1, v1);
24213 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24214 break;
24215 case OPC_DEXTR_S_H:
24216 tcg_gen_movi_tl(t0, v2);
24217 tcg_gen_movi_tl(t1, v1);
24218 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24219 break;
24220 case OPC_DEXTRV_S_H:
24221 tcg_gen_movi_tl(t0, v2);
24222 tcg_gen_movi_tl(t1, v1);
24223 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24224 break;
24225 case OPC_DEXTRV_L:
24226 tcg_gen_movi_tl(t0, v2);
24227 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24228 break;
24229 case OPC_DEXTRV_R_L:
24230 tcg_gen_movi_tl(t0, v2);
24231 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24232 break;
24233 case OPC_DEXTRV_RS_L:
24234 tcg_gen_movi_tl(t0, v2);
24235 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24236 break;
24237 case OPC_DEXTRV_W:
24238 tcg_gen_movi_tl(t0, v2);
24239 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24240 break;
24241 case OPC_DEXTRV_R_W:
24242 tcg_gen_movi_tl(t0, v2);
24243 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24244 break;
24245 case OPC_DEXTRV_RS_W:
24246 tcg_gen_movi_tl(t0, v2);
24247 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24248 break;
24250 break;
24251 #endif
24254 tcg_temp_free(t0);
24255 tcg_temp_free(t1);
24256 tcg_temp_free(v1_t);
24257 tcg_temp_free(v2_t);
24260 /* End MIPSDSP functions. */
24262 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24264 int rs, rt, rd, sa;
24265 uint32_t op1, op2;
24267 rs = (ctx->opcode >> 21) & 0x1f;
24268 rt = (ctx->opcode >> 16) & 0x1f;
24269 rd = (ctx->opcode >> 11) & 0x1f;
24270 sa = (ctx->opcode >> 6) & 0x1f;
24272 op1 = MASK_SPECIAL(ctx->opcode);
24273 switch (op1) {
24274 case OPC_LSA:
24275 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24276 break;
24277 case OPC_MULT:
24278 case OPC_MULTU:
24279 case OPC_DIV:
24280 case OPC_DIVU:
24281 op2 = MASK_R6_MULDIV(ctx->opcode);
24282 switch (op2) {
24283 case R6_OPC_MUL:
24284 case R6_OPC_MUH:
24285 case R6_OPC_MULU:
24286 case R6_OPC_MUHU:
24287 case R6_OPC_DIV:
24288 case R6_OPC_MOD:
24289 case R6_OPC_DIVU:
24290 case R6_OPC_MODU:
24291 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24292 break;
24293 default:
24294 MIPS_INVAL("special_r6 muldiv");
24295 generate_exception_end(ctx, EXCP_RI);
24296 break;
24298 break;
24299 case OPC_SELEQZ:
24300 case OPC_SELNEZ:
24301 gen_cond_move(ctx, op1, rd, rs, rt);
24302 break;
24303 case R6_OPC_CLO:
24304 case R6_OPC_CLZ:
24305 if (rt == 0 && sa == 1) {
24307 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24308 * We need additionally to check other fields.
24310 gen_cl(ctx, op1, rd, rs);
24311 } else {
24312 generate_exception_end(ctx, EXCP_RI);
24314 break;
24315 case R6_OPC_SDBBP:
24316 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24317 gen_helper_do_semihosting(cpu_env);
24318 } else {
24319 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24320 generate_exception_end(ctx, EXCP_RI);
24321 } else {
24322 generate_exception_end(ctx, EXCP_DBp);
24325 break;
24326 #if defined(TARGET_MIPS64)
24327 case OPC_DLSA:
24328 check_mips_64(ctx);
24329 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24330 break;
24331 case R6_OPC_DCLO:
24332 case R6_OPC_DCLZ:
24333 if (rt == 0 && sa == 1) {
24335 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24336 * We need additionally to check other fields.
24338 check_mips_64(ctx);
24339 gen_cl(ctx, op1, rd, rs);
24340 } else {
24341 generate_exception_end(ctx, EXCP_RI);
24343 break;
24344 case OPC_DMULT:
24345 case OPC_DMULTU:
24346 case OPC_DDIV:
24347 case OPC_DDIVU:
24349 op2 = MASK_R6_MULDIV(ctx->opcode);
24350 switch (op2) {
24351 case R6_OPC_DMUL:
24352 case R6_OPC_DMUH:
24353 case R6_OPC_DMULU:
24354 case R6_OPC_DMUHU:
24355 case R6_OPC_DDIV:
24356 case R6_OPC_DMOD:
24357 case R6_OPC_DDIVU:
24358 case R6_OPC_DMODU:
24359 check_mips_64(ctx);
24360 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24361 break;
24362 default:
24363 MIPS_INVAL("special_r6 muldiv");
24364 generate_exception_end(ctx, EXCP_RI);
24365 break;
24367 break;
24368 #endif
24369 default: /* Invalid */
24370 MIPS_INVAL("special_r6");
24371 generate_exception_end(ctx, EXCP_RI);
24372 break;
24376 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24378 int rs = extract32(ctx->opcode, 21, 5);
24379 int rt = extract32(ctx->opcode, 16, 5);
24380 int rd = extract32(ctx->opcode, 11, 5);
24381 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24383 switch (op1) {
24384 case OPC_MOVN: /* Conditional move */
24385 case OPC_MOVZ:
24386 gen_cond_move(ctx, op1, rd, rs, rt);
24387 break;
24388 case OPC_MFHI: /* Move from HI/LO */
24389 case OPC_MFLO:
24390 gen_HILO(ctx, op1, 0, rd);
24391 break;
24392 case OPC_MTHI:
24393 case OPC_MTLO: /* Move to HI/LO */
24394 gen_HILO(ctx, op1, 0, rs);
24395 break;
24396 case OPC_MULT:
24397 case OPC_MULTU:
24398 gen_mul_txx9(ctx, op1, rd, rs, rt);
24399 break;
24400 case OPC_DIV:
24401 case OPC_DIVU:
24402 gen_muldiv(ctx, op1, 0, rs, rt);
24403 break;
24404 #if defined(TARGET_MIPS64)
24405 case OPC_DMULT:
24406 case OPC_DMULTU:
24407 case OPC_DDIV:
24408 case OPC_DDIVU:
24409 check_insn_opc_user_only(ctx, INSN_R5900);
24410 gen_muldiv(ctx, op1, 0, rs, rt);
24411 break;
24412 #endif
24413 case OPC_JR:
24414 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24415 break;
24416 default: /* Invalid */
24417 MIPS_INVAL("special_tx79");
24418 generate_exception_end(ctx, EXCP_RI);
24419 break;
24423 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24425 int rs, rt, rd, sa;
24426 uint32_t op1;
24428 rs = (ctx->opcode >> 21) & 0x1f;
24429 rt = (ctx->opcode >> 16) & 0x1f;
24430 rd = (ctx->opcode >> 11) & 0x1f;
24431 sa = (ctx->opcode >> 6) & 0x1f;
24433 op1 = MASK_SPECIAL(ctx->opcode);
24434 switch (op1) {
24435 case OPC_MOVN: /* Conditional move */
24436 case OPC_MOVZ:
24437 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24438 INSN_LOONGSON2E | INSN_LOONGSON2F);
24439 gen_cond_move(ctx, op1, rd, rs, rt);
24440 break;
24441 case OPC_MFHI: /* Move from HI/LO */
24442 case OPC_MFLO:
24443 gen_HILO(ctx, op1, rs & 3, rd);
24444 break;
24445 case OPC_MTHI:
24446 case OPC_MTLO: /* Move to HI/LO */
24447 gen_HILO(ctx, op1, rd & 3, rs);
24448 break;
24449 case OPC_MOVCI:
24450 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24451 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24452 check_cp1_enabled(ctx);
24453 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24454 (ctx->opcode >> 16) & 1);
24455 } else {
24456 generate_exception_err(ctx, EXCP_CpU, 1);
24458 break;
24459 case OPC_MULT:
24460 case OPC_MULTU:
24461 if (sa) {
24462 check_insn(ctx, INSN_VR54XX);
24463 op1 = MASK_MUL_VR54XX(ctx->opcode);
24464 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24465 } else {
24466 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24468 break;
24469 case OPC_DIV:
24470 case OPC_DIVU:
24471 gen_muldiv(ctx, op1, 0, rs, rt);
24472 break;
24473 #if defined(TARGET_MIPS64)
24474 case OPC_DMULT:
24475 case OPC_DMULTU:
24476 case OPC_DDIV:
24477 case OPC_DDIVU:
24478 check_insn(ctx, ISA_MIPS3);
24479 check_mips_64(ctx);
24480 gen_muldiv(ctx, op1, 0, rs, rt);
24481 break;
24482 #endif
24483 case OPC_JR:
24484 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24485 break;
24486 case OPC_SPIM:
24487 #ifdef MIPS_STRICT_STANDARD
24488 MIPS_INVAL("SPIM");
24489 generate_exception_end(ctx, EXCP_RI);
24490 #else
24491 /* Implemented as RI exception for now. */
24492 MIPS_INVAL("spim (unofficial)");
24493 generate_exception_end(ctx, EXCP_RI);
24494 #endif
24495 break;
24496 default: /* Invalid */
24497 MIPS_INVAL("special_legacy");
24498 generate_exception_end(ctx, EXCP_RI);
24499 break;
24503 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24505 int rs, rt, rd, sa;
24506 uint32_t op1;
24508 rs = (ctx->opcode >> 21) & 0x1f;
24509 rt = (ctx->opcode >> 16) & 0x1f;
24510 rd = (ctx->opcode >> 11) & 0x1f;
24511 sa = (ctx->opcode >> 6) & 0x1f;
24513 op1 = MASK_SPECIAL(ctx->opcode);
24514 switch (op1) {
24515 case OPC_SLL: /* Shift with immediate */
24516 if (sa == 5 && rd == 0 &&
24517 rs == 0 && rt == 0) { /* PAUSE */
24518 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24519 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24520 generate_exception_end(ctx, EXCP_RI);
24521 break;
24524 /* Fallthrough */
24525 case OPC_SRA:
24526 gen_shift_imm(ctx, op1, rd, rt, sa);
24527 break;
24528 case OPC_SRL:
24529 switch ((ctx->opcode >> 21) & 0x1f) {
24530 case 1:
24531 /* rotr is decoded as srl on non-R2 CPUs */
24532 if (ctx->insn_flags & ISA_MIPS32R2) {
24533 op1 = OPC_ROTR;
24535 /* Fallthrough */
24536 case 0:
24537 gen_shift_imm(ctx, op1, rd, rt, sa);
24538 break;
24539 default:
24540 generate_exception_end(ctx, EXCP_RI);
24541 break;
24543 break;
24544 case OPC_ADD:
24545 case OPC_ADDU:
24546 case OPC_SUB:
24547 case OPC_SUBU:
24548 gen_arith(ctx, op1, rd, rs, rt);
24549 break;
24550 case OPC_SLLV: /* Shifts */
24551 case OPC_SRAV:
24552 gen_shift(ctx, op1, rd, rs, rt);
24553 break;
24554 case OPC_SRLV:
24555 switch ((ctx->opcode >> 6) & 0x1f) {
24556 case 1:
24557 /* rotrv is decoded as srlv on non-R2 CPUs */
24558 if (ctx->insn_flags & ISA_MIPS32R2) {
24559 op1 = OPC_ROTRV;
24561 /* Fallthrough */
24562 case 0:
24563 gen_shift(ctx, op1, rd, rs, rt);
24564 break;
24565 default:
24566 generate_exception_end(ctx, EXCP_RI);
24567 break;
24569 break;
24570 case OPC_SLT: /* Set on less than */
24571 case OPC_SLTU:
24572 gen_slt(ctx, op1, rd, rs, rt);
24573 break;
24574 case OPC_AND: /* Logic*/
24575 case OPC_OR:
24576 case OPC_NOR:
24577 case OPC_XOR:
24578 gen_logic(ctx, op1, rd, rs, rt);
24579 break;
24580 case OPC_JALR:
24581 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24582 break;
24583 case OPC_TGE: /* Traps */
24584 case OPC_TGEU:
24585 case OPC_TLT:
24586 case OPC_TLTU:
24587 case OPC_TEQ:
24588 case OPC_TNE:
24589 check_insn(ctx, ISA_MIPS2);
24590 gen_trap(ctx, op1, rs, rt, -1);
24591 break;
24592 case OPC_LSA: /* OPC_PMON */
24593 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24594 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24595 decode_opc_special_r6(env, ctx);
24596 } else {
24597 /* Pmon entry point, also R4010 selsl */
24598 #ifdef MIPS_STRICT_STANDARD
24599 MIPS_INVAL("PMON / selsl");
24600 generate_exception_end(ctx, EXCP_RI);
24601 #else
24602 gen_helper_0e0i(pmon, sa);
24603 #endif
24605 break;
24606 case OPC_SYSCALL:
24607 generate_exception_end(ctx, EXCP_SYSCALL);
24608 break;
24609 case OPC_BREAK:
24610 generate_exception_end(ctx, EXCP_BREAK);
24611 break;
24612 case OPC_SYNC:
24613 check_insn(ctx, ISA_MIPS2);
24614 gen_sync(extract32(ctx->opcode, 6, 5));
24615 break;
24617 #if defined(TARGET_MIPS64)
24618 /* MIPS64 specific opcodes */
24619 case OPC_DSLL:
24620 case OPC_DSRA:
24621 case OPC_DSLL32:
24622 case OPC_DSRA32:
24623 check_insn(ctx, ISA_MIPS3);
24624 check_mips_64(ctx);
24625 gen_shift_imm(ctx, op1, rd, rt, sa);
24626 break;
24627 case OPC_DSRL:
24628 switch ((ctx->opcode >> 21) & 0x1f) {
24629 case 1:
24630 /* drotr is decoded as dsrl on non-R2 CPUs */
24631 if (ctx->insn_flags & ISA_MIPS32R2) {
24632 op1 = OPC_DROTR;
24634 /* Fallthrough */
24635 case 0:
24636 check_insn(ctx, ISA_MIPS3);
24637 check_mips_64(ctx);
24638 gen_shift_imm(ctx, op1, rd, rt, sa);
24639 break;
24640 default:
24641 generate_exception_end(ctx, EXCP_RI);
24642 break;
24644 break;
24645 case OPC_DSRL32:
24646 switch ((ctx->opcode >> 21) & 0x1f) {
24647 case 1:
24648 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24649 if (ctx->insn_flags & ISA_MIPS32R2) {
24650 op1 = OPC_DROTR32;
24652 /* Fallthrough */
24653 case 0:
24654 check_insn(ctx, ISA_MIPS3);
24655 check_mips_64(ctx);
24656 gen_shift_imm(ctx, op1, rd, rt, sa);
24657 break;
24658 default:
24659 generate_exception_end(ctx, EXCP_RI);
24660 break;
24662 break;
24663 case OPC_DADD:
24664 case OPC_DADDU:
24665 case OPC_DSUB:
24666 case OPC_DSUBU:
24667 check_insn(ctx, ISA_MIPS3);
24668 check_mips_64(ctx);
24669 gen_arith(ctx, op1, rd, rs, rt);
24670 break;
24671 case OPC_DSLLV:
24672 case OPC_DSRAV:
24673 check_insn(ctx, ISA_MIPS3);
24674 check_mips_64(ctx);
24675 gen_shift(ctx, op1, rd, rs, rt);
24676 break;
24677 case OPC_DSRLV:
24678 switch ((ctx->opcode >> 6) & 0x1f) {
24679 case 1:
24680 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24681 if (ctx->insn_flags & ISA_MIPS32R2) {
24682 op1 = OPC_DROTRV;
24684 /* Fallthrough */
24685 case 0:
24686 check_insn(ctx, ISA_MIPS3);
24687 check_mips_64(ctx);
24688 gen_shift(ctx, op1, rd, rs, rt);
24689 break;
24690 default:
24691 generate_exception_end(ctx, EXCP_RI);
24692 break;
24694 break;
24695 case OPC_DLSA:
24696 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24697 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24698 decode_opc_special_r6(env, ctx);
24700 break;
24701 #endif
24702 default:
24703 if (ctx->insn_flags & ISA_MIPS32R6) {
24704 decode_opc_special_r6(env, ctx);
24705 } else if (ctx->insn_flags & INSN_R5900) {
24706 decode_opc_special_tx79(env, ctx);
24707 } else {
24708 decode_opc_special_legacy(env, ctx);
24714 #if defined(TARGET_MIPS64)
24718 * MMI (MultiMedia Interface) ASE instructions
24719 * ===========================================
24723 * MMI instructions category: data communication
24724 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24726 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24727 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24728 * PCPYUD PEXEH PEXTLW PPACW
24729 * PEXEW PEXTUB
24730 * PEXTUH
24731 * PEXTUW
24735 * PCPYH rd, rt
24737 * Parallel Copy Halfword
24739 * 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
24740 * +-----------+---------+---------+---------+---------+-----------+
24741 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24742 * +-----------+---------+---------+---------+---------+-----------+
24744 static void gen_mmi_pcpyh(DisasContext *ctx)
24746 uint32_t pd, rt, rd;
24747 uint32_t opcode;
24749 opcode = ctx->opcode;
24751 pd = extract32(opcode, 21, 5);
24752 rt = extract32(opcode, 16, 5);
24753 rd = extract32(opcode, 11, 5);
24755 if (unlikely(pd != 0)) {
24756 generate_exception_end(ctx, EXCP_RI);
24757 } else if (rd == 0) {
24758 /* nop */
24759 } else if (rt == 0) {
24760 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24761 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24762 } else {
24763 TCGv_i64 t0 = tcg_temp_new();
24764 TCGv_i64 t1 = tcg_temp_new();
24765 uint64_t mask = (1ULL << 16) - 1;
24767 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24768 tcg_gen_movi_i64(t1, 0);
24769 tcg_gen_or_i64(t1, t0, t1);
24770 tcg_gen_shli_i64(t0, t0, 16);
24771 tcg_gen_or_i64(t1, t0, t1);
24772 tcg_gen_shli_i64(t0, t0, 16);
24773 tcg_gen_or_i64(t1, t0, t1);
24774 tcg_gen_shli_i64(t0, t0, 16);
24775 tcg_gen_or_i64(t1, t0, t1);
24777 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24779 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24780 tcg_gen_movi_i64(t1, 0);
24781 tcg_gen_or_i64(t1, t0, t1);
24782 tcg_gen_shli_i64(t0, t0, 16);
24783 tcg_gen_or_i64(t1, t0, t1);
24784 tcg_gen_shli_i64(t0, t0, 16);
24785 tcg_gen_or_i64(t1, t0, t1);
24786 tcg_gen_shli_i64(t0, t0, 16);
24787 tcg_gen_or_i64(t1, t0, t1);
24789 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24791 tcg_temp_free(t0);
24792 tcg_temp_free(t1);
24797 * PCPYLD rd, rs, rt
24799 * Parallel Copy Lower Doubleword
24801 * 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
24802 * +-----------+---------+---------+---------+---------+-----------+
24803 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24804 * +-----------+---------+---------+---------+---------+-----------+
24806 static void gen_mmi_pcpyld(DisasContext *ctx)
24808 uint32_t rs, rt, rd;
24809 uint32_t opcode;
24811 opcode = ctx->opcode;
24813 rs = extract32(opcode, 21, 5);
24814 rt = extract32(opcode, 16, 5);
24815 rd = extract32(opcode, 11, 5);
24817 if (rd == 0) {
24818 /* nop */
24819 } else {
24820 if (rs == 0) {
24821 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24822 } else {
24823 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24825 if (rt == 0) {
24826 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24827 } else {
24828 if (rd != rt) {
24829 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24836 * PCPYUD rd, rs, rt
24838 * Parallel Copy Upper Doubleword
24840 * 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
24841 * +-----------+---------+---------+---------+---------+-----------+
24842 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24843 * +-----------+---------+---------+---------+---------+-----------+
24845 static void gen_mmi_pcpyud(DisasContext *ctx)
24847 uint32_t rs, rt, rd;
24848 uint32_t opcode;
24850 opcode = ctx->opcode;
24852 rs = extract32(opcode, 21, 5);
24853 rt = extract32(opcode, 16, 5);
24854 rd = extract32(opcode, 11, 5);
24856 if (rd == 0) {
24857 /* nop */
24858 } else {
24859 if (rs == 0) {
24860 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24861 } else {
24862 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24864 if (rt == 0) {
24865 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24866 } else {
24867 if (rd != rt) {
24868 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24874 #endif
24877 #if !defined(TARGET_MIPS64)
24879 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24880 #define MXU_APTN1_A 0
24881 #define MXU_APTN1_S 1
24883 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24884 #define MXU_APTN2_AA 0
24885 #define MXU_APTN2_AS 1
24886 #define MXU_APTN2_SA 2
24887 #define MXU_APTN2_SS 3
24889 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24890 #define MXU_EPTN2_AA 0
24891 #define MXU_EPTN2_AS 1
24892 #define MXU_EPTN2_SA 2
24893 #define MXU_EPTN2_SS 3
24895 /* MXU operand getting pattern 'optn2' */
24896 #define MXU_OPTN2_PTN0 0
24897 #define MXU_OPTN2_PTN1 1
24898 #define MXU_OPTN2_PTN2 2
24899 #define MXU_OPTN2_PTN3 3
24900 /* alternative naming scheme for 'optn2' */
24901 #define MXU_OPTN2_WW 0
24902 #define MXU_OPTN2_LW 1
24903 #define MXU_OPTN2_HW 2
24904 #define MXU_OPTN2_XW 3
24906 /* MXU operand getting pattern 'optn3' */
24907 #define MXU_OPTN3_PTN0 0
24908 #define MXU_OPTN3_PTN1 1
24909 #define MXU_OPTN3_PTN2 2
24910 #define MXU_OPTN3_PTN3 3
24911 #define MXU_OPTN3_PTN4 4
24912 #define MXU_OPTN3_PTN5 5
24913 #define MXU_OPTN3_PTN6 6
24914 #define MXU_OPTN3_PTN7 7
24918 * S32I2M XRa, rb - Register move from GRF to XRF
24920 static void gen_mxu_s32i2m(DisasContext *ctx)
24922 TCGv t0;
24923 uint32_t XRa, Rb;
24925 t0 = tcg_temp_new();
24927 XRa = extract32(ctx->opcode, 6, 5);
24928 Rb = extract32(ctx->opcode, 16, 5);
24930 gen_load_gpr(t0, Rb);
24931 if (XRa <= 15) {
24932 gen_store_mxu_gpr(t0, XRa);
24933 } else if (XRa == 16) {
24934 gen_store_mxu_cr(t0);
24937 tcg_temp_free(t0);
24941 * S32M2I XRa, rb - Register move from XRF to GRF
24943 static void gen_mxu_s32m2i(DisasContext *ctx)
24945 TCGv t0;
24946 uint32_t XRa, Rb;
24948 t0 = tcg_temp_new();
24950 XRa = extract32(ctx->opcode, 6, 5);
24951 Rb = extract32(ctx->opcode, 16, 5);
24953 if (XRa <= 15) {
24954 gen_load_mxu_gpr(t0, XRa);
24955 } else if (XRa == 16) {
24956 gen_load_mxu_cr(t0);
24959 gen_store_gpr(t0, Rb);
24961 tcg_temp_free(t0);
24965 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24967 static void gen_mxu_s8ldd(DisasContext *ctx)
24969 TCGv t0, t1;
24970 uint32_t XRa, Rb, s8, optn3;
24972 t0 = tcg_temp_new();
24973 t1 = tcg_temp_new();
24975 XRa = extract32(ctx->opcode, 6, 4);
24976 s8 = extract32(ctx->opcode, 10, 8);
24977 optn3 = extract32(ctx->opcode, 18, 3);
24978 Rb = extract32(ctx->opcode, 21, 5);
24980 gen_load_gpr(t0, Rb);
24981 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24983 switch (optn3) {
24984 /* XRa[7:0] = tmp8 */
24985 case MXU_OPTN3_PTN0:
24986 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24987 gen_load_mxu_gpr(t0, XRa);
24988 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24989 break;
24990 /* XRa[15:8] = tmp8 */
24991 case MXU_OPTN3_PTN1:
24992 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24993 gen_load_mxu_gpr(t0, XRa);
24994 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24995 break;
24996 /* XRa[23:16] = tmp8 */
24997 case MXU_OPTN3_PTN2:
24998 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24999 gen_load_mxu_gpr(t0, XRa);
25000 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25001 break;
25002 /* XRa[31:24] = tmp8 */
25003 case MXU_OPTN3_PTN3:
25004 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25005 gen_load_mxu_gpr(t0, XRa);
25006 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25007 break;
25008 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25009 case MXU_OPTN3_PTN4:
25010 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25011 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25012 break;
25013 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25014 case MXU_OPTN3_PTN5:
25015 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25016 tcg_gen_shli_tl(t1, t1, 8);
25017 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25018 break;
25019 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25020 case MXU_OPTN3_PTN6:
25021 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25022 tcg_gen_mov_tl(t0, t1);
25023 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25024 tcg_gen_shli_tl(t1, t1, 16);
25025 tcg_gen_or_tl(t0, t0, t1);
25026 break;
25027 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25028 case MXU_OPTN3_PTN7:
25029 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25030 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25031 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25032 break;
25035 gen_store_mxu_gpr(t0, XRa);
25037 tcg_temp_free(t0);
25038 tcg_temp_free(t1);
25042 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25044 static void gen_mxu_d16mul(DisasContext *ctx)
25046 TCGv t0, t1, t2, t3;
25047 uint32_t XRa, XRb, XRc, XRd, optn2;
25049 t0 = tcg_temp_new();
25050 t1 = tcg_temp_new();
25051 t2 = tcg_temp_new();
25052 t3 = tcg_temp_new();
25054 XRa = extract32(ctx->opcode, 6, 4);
25055 XRb = extract32(ctx->opcode, 10, 4);
25056 XRc = extract32(ctx->opcode, 14, 4);
25057 XRd = extract32(ctx->opcode, 18, 4);
25058 optn2 = extract32(ctx->opcode, 22, 2);
25060 gen_load_mxu_gpr(t1, XRb);
25061 tcg_gen_sextract_tl(t0, t1, 0, 16);
25062 tcg_gen_sextract_tl(t1, t1, 16, 16);
25063 gen_load_mxu_gpr(t3, XRc);
25064 tcg_gen_sextract_tl(t2, t3, 0, 16);
25065 tcg_gen_sextract_tl(t3, t3, 16, 16);
25067 switch (optn2) {
25068 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25069 tcg_gen_mul_tl(t3, t1, t3);
25070 tcg_gen_mul_tl(t2, t0, t2);
25071 break;
25072 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25073 tcg_gen_mul_tl(t3, t0, t3);
25074 tcg_gen_mul_tl(t2, t0, t2);
25075 break;
25076 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25077 tcg_gen_mul_tl(t3, t1, t3);
25078 tcg_gen_mul_tl(t2, t1, t2);
25079 break;
25080 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25081 tcg_gen_mul_tl(t3, t0, t3);
25082 tcg_gen_mul_tl(t2, t1, t2);
25083 break;
25085 gen_store_mxu_gpr(t3, XRa);
25086 gen_store_mxu_gpr(t2, XRd);
25088 tcg_temp_free(t0);
25089 tcg_temp_free(t1);
25090 tcg_temp_free(t2);
25091 tcg_temp_free(t3);
25095 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25096 * and accumulate
25098 static void gen_mxu_d16mac(DisasContext *ctx)
25100 TCGv t0, t1, t2, t3;
25101 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25103 t0 = tcg_temp_new();
25104 t1 = tcg_temp_new();
25105 t2 = tcg_temp_new();
25106 t3 = tcg_temp_new();
25108 XRa = extract32(ctx->opcode, 6, 4);
25109 XRb = extract32(ctx->opcode, 10, 4);
25110 XRc = extract32(ctx->opcode, 14, 4);
25111 XRd = extract32(ctx->opcode, 18, 4);
25112 optn2 = extract32(ctx->opcode, 22, 2);
25113 aptn2 = extract32(ctx->opcode, 24, 2);
25115 gen_load_mxu_gpr(t1, XRb);
25116 tcg_gen_sextract_tl(t0, t1, 0, 16);
25117 tcg_gen_sextract_tl(t1, t1, 16, 16);
25119 gen_load_mxu_gpr(t3, XRc);
25120 tcg_gen_sextract_tl(t2, t3, 0, 16);
25121 tcg_gen_sextract_tl(t3, t3, 16, 16);
25123 switch (optn2) {
25124 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25125 tcg_gen_mul_tl(t3, t1, t3);
25126 tcg_gen_mul_tl(t2, t0, t2);
25127 break;
25128 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25129 tcg_gen_mul_tl(t3, t0, t3);
25130 tcg_gen_mul_tl(t2, t0, t2);
25131 break;
25132 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25133 tcg_gen_mul_tl(t3, t1, t3);
25134 tcg_gen_mul_tl(t2, t1, t2);
25135 break;
25136 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25137 tcg_gen_mul_tl(t3, t0, t3);
25138 tcg_gen_mul_tl(t2, t1, t2);
25139 break;
25141 gen_load_mxu_gpr(t0, XRa);
25142 gen_load_mxu_gpr(t1, XRd);
25144 switch (aptn2) {
25145 case MXU_APTN2_AA:
25146 tcg_gen_add_tl(t3, t0, t3);
25147 tcg_gen_add_tl(t2, t1, t2);
25148 break;
25149 case MXU_APTN2_AS:
25150 tcg_gen_add_tl(t3, t0, t3);
25151 tcg_gen_sub_tl(t2, t1, t2);
25152 break;
25153 case MXU_APTN2_SA:
25154 tcg_gen_sub_tl(t3, t0, t3);
25155 tcg_gen_add_tl(t2, t1, t2);
25156 break;
25157 case MXU_APTN2_SS:
25158 tcg_gen_sub_tl(t3, t0, t3);
25159 tcg_gen_sub_tl(t2, t1, t2);
25160 break;
25162 gen_store_mxu_gpr(t3, XRa);
25163 gen_store_mxu_gpr(t2, XRd);
25165 tcg_temp_free(t0);
25166 tcg_temp_free(t1);
25167 tcg_temp_free(t2);
25168 tcg_temp_free(t3);
25172 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25173 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25175 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25177 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25178 uint32_t XRa, XRb, XRc, XRd, sel;
25180 t0 = tcg_temp_new();
25181 t1 = tcg_temp_new();
25182 t2 = tcg_temp_new();
25183 t3 = tcg_temp_new();
25184 t4 = tcg_temp_new();
25185 t5 = tcg_temp_new();
25186 t6 = tcg_temp_new();
25187 t7 = tcg_temp_new();
25189 XRa = extract32(ctx->opcode, 6, 4);
25190 XRb = extract32(ctx->opcode, 10, 4);
25191 XRc = extract32(ctx->opcode, 14, 4);
25192 XRd = extract32(ctx->opcode, 18, 4);
25193 sel = extract32(ctx->opcode, 22, 2);
25195 gen_load_mxu_gpr(t3, XRb);
25196 gen_load_mxu_gpr(t7, XRc);
25198 if (sel == 0x2) {
25199 /* Q8MULSU */
25200 tcg_gen_ext8s_tl(t0, t3);
25201 tcg_gen_shri_tl(t3, t3, 8);
25202 tcg_gen_ext8s_tl(t1, t3);
25203 tcg_gen_shri_tl(t3, t3, 8);
25204 tcg_gen_ext8s_tl(t2, t3);
25205 tcg_gen_shri_tl(t3, t3, 8);
25206 tcg_gen_ext8s_tl(t3, t3);
25207 } else {
25208 /* Q8MUL */
25209 tcg_gen_ext8u_tl(t0, t3);
25210 tcg_gen_shri_tl(t3, t3, 8);
25211 tcg_gen_ext8u_tl(t1, t3);
25212 tcg_gen_shri_tl(t3, t3, 8);
25213 tcg_gen_ext8u_tl(t2, t3);
25214 tcg_gen_shri_tl(t3, t3, 8);
25215 tcg_gen_ext8u_tl(t3, t3);
25218 tcg_gen_ext8u_tl(t4, t7);
25219 tcg_gen_shri_tl(t7, t7, 8);
25220 tcg_gen_ext8u_tl(t5, t7);
25221 tcg_gen_shri_tl(t7, t7, 8);
25222 tcg_gen_ext8u_tl(t6, t7);
25223 tcg_gen_shri_tl(t7, t7, 8);
25224 tcg_gen_ext8u_tl(t7, t7);
25226 tcg_gen_mul_tl(t0, t0, t4);
25227 tcg_gen_mul_tl(t1, t1, t5);
25228 tcg_gen_mul_tl(t2, t2, t6);
25229 tcg_gen_mul_tl(t3, t3, t7);
25231 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25232 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25233 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25234 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25236 tcg_gen_shli_tl(t1, t1, 16);
25237 tcg_gen_shli_tl(t3, t3, 16);
25239 tcg_gen_or_tl(t0, t0, t1);
25240 tcg_gen_or_tl(t1, t2, t3);
25242 gen_store_mxu_gpr(t0, XRd);
25243 gen_store_mxu_gpr(t1, XRa);
25245 tcg_temp_free(t0);
25246 tcg_temp_free(t1);
25247 tcg_temp_free(t2);
25248 tcg_temp_free(t3);
25249 tcg_temp_free(t4);
25250 tcg_temp_free(t5);
25251 tcg_temp_free(t6);
25252 tcg_temp_free(t7);
25256 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25257 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25259 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25261 TCGv t0, t1;
25262 uint32_t XRa, Rb, s12, sel;
25264 t0 = tcg_temp_new();
25265 t1 = tcg_temp_new();
25267 XRa = extract32(ctx->opcode, 6, 4);
25268 s12 = extract32(ctx->opcode, 10, 10);
25269 sel = extract32(ctx->opcode, 20, 1);
25270 Rb = extract32(ctx->opcode, 21, 5);
25272 gen_load_gpr(t0, Rb);
25274 tcg_gen_movi_tl(t1, s12);
25275 tcg_gen_shli_tl(t1, t1, 2);
25276 if (s12 & 0x200) {
25277 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25279 tcg_gen_add_tl(t1, t0, t1);
25280 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25282 if (sel == 1) {
25283 /* S32LDDR */
25284 tcg_gen_bswap32_tl(t1, t1);
25286 gen_store_mxu_gpr(t1, XRa);
25288 tcg_temp_free(t0);
25289 tcg_temp_free(t1);
25294 * MXU instruction category: logic
25295 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25297 * S32NOR S32AND S32OR S32XOR
25301 * S32NOR XRa, XRb, XRc
25302 * Update XRa with the result of logical bitwise 'nor' operation
25303 * applied to the content of XRb and XRc.
25305 * 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
25306 * +-----------+---------+-----+-------+-------+-------+-----------+
25307 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25308 * +-----------+---------+-----+-------+-------+-------+-----------+
25310 static void gen_mxu_S32NOR(DisasContext *ctx)
25312 uint32_t pad, XRc, XRb, XRa;
25314 pad = extract32(ctx->opcode, 21, 5);
25315 XRc = extract32(ctx->opcode, 14, 4);
25316 XRb = extract32(ctx->opcode, 10, 4);
25317 XRa = extract32(ctx->opcode, 6, 4);
25319 if (unlikely(pad != 0)) {
25320 /* opcode padding incorrect -> do nothing */
25321 } else if (unlikely(XRa == 0)) {
25322 /* destination is zero register -> do nothing */
25323 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25324 /* both operands zero registers -> just set destination to all 1s */
25325 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25326 } else if (unlikely(XRb == 0)) {
25327 /* XRb zero register -> just set destination to the negation of XRc */
25328 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25329 } else if (unlikely(XRc == 0)) {
25330 /* XRa zero register -> just set destination to the negation of XRb */
25331 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25332 } else if (unlikely(XRb == XRc)) {
25333 /* both operands same -> just set destination to the negation of XRb */
25334 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25335 } else {
25336 /* the most general case */
25337 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25342 * S32AND XRa, XRb, XRc
25343 * Update XRa with the result of logical bitwise 'and' operation
25344 * applied to the content of XRb and XRc.
25346 * 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
25347 * +-----------+---------+-----+-------+-------+-------+-----------+
25348 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25349 * +-----------+---------+-----+-------+-------+-------+-----------+
25351 static void gen_mxu_S32AND(DisasContext *ctx)
25353 uint32_t pad, XRc, XRb, XRa;
25355 pad = extract32(ctx->opcode, 21, 5);
25356 XRc = extract32(ctx->opcode, 14, 4);
25357 XRb = extract32(ctx->opcode, 10, 4);
25358 XRa = extract32(ctx->opcode, 6, 4);
25360 if (unlikely(pad != 0)) {
25361 /* opcode padding incorrect -> do nothing */
25362 } else if (unlikely(XRa == 0)) {
25363 /* destination is zero register -> do nothing */
25364 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25365 /* one of operands zero register -> just set destination to all 0s */
25366 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25367 } else if (unlikely(XRb == XRc)) {
25368 /* both operands same -> just set destination to one of them */
25369 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25370 } else {
25371 /* the most general case */
25372 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25377 * S32OR XRa, XRb, XRc
25378 * Update XRa with the result of logical bitwise 'or' operation
25379 * applied to the content of XRb and XRc.
25381 * 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
25382 * +-----------+---------+-----+-------+-------+-------+-----------+
25383 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25384 * +-----------+---------+-----+-------+-------+-------+-----------+
25386 static void gen_mxu_S32OR(DisasContext *ctx)
25388 uint32_t pad, XRc, XRb, XRa;
25390 pad = extract32(ctx->opcode, 21, 5);
25391 XRc = extract32(ctx->opcode, 14, 4);
25392 XRb = extract32(ctx->opcode, 10, 4);
25393 XRa = extract32(ctx->opcode, 6, 4);
25395 if (unlikely(pad != 0)) {
25396 /* opcode padding incorrect -> do nothing */
25397 } else if (unlikely(XRa == 0)) {
25398 /* destination is zero register -> do nothing */
25399 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25400 /* both operands zero registers -> just set destination to all 0s */
25401 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25402 } else if (unlikely(XRb == 0)) {
25403 /* XRb zero register -> just set destination to the content of XRc */
25404 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25405 } else if (unlikely(XRc == 0)) {
25406 /* XRc zero register -> just set destination to the content of XRb */
25407 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25408 } else if (unlikely(XRb == XRc)) {
25409 /* both operands same -> just set destination to one of them */
25410 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25411 } else {
25412 /* the most general case */
25413 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25418 * S32XOR XRa, XRb, XRc
25419 * Update XRa with the result of logical bitwise 'xor' operation
25420 * applied to the content of XRb and XRc.
25422 * 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
25423 * +-----------+---------+-----+-------+-------+-------+-----------+
25424 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25425 * +-----------+---------+-----+-------+-------+-------+-----------+
25427 static void gen_mxu_S32XOR(DisasContext *ctx)
25429 uint32_t pad, XRc, XRb, XRa;
25431 pad = extract32(ctx->opcode, 21, 5);
25432 XRc = extract32(ctx->opcode, 14, 4);
25433 XRb = extract32(ctx->opcode, 10, 4);
25434 XRa = extract32(ctx->opcode, 6, 4);
25436 if (unlikely(pad != 0)) {
25437 /* opcode padding incorrect -> do nothing */
25438 } else if (unlikely(XRa == 0)) {
25439 /* destination is zero register -> do nothing */
25440 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25441 /* both operands zero registers -> just set destination to all 0s */
25442 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25443 } else if (unlikely(XRb == 0)) {
25444 /* XRb zero register -> just set destination to the content of XRc */
25445 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25446 } else if (unlikely(XRc == 0)) {
25447 /* XRc zero register -> just set destination to the content of XRb */
25448 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25449 } else if (unlikely(XRb == XRc)) {
25450 /* both operands same -> just set destination to all 0s */
25451 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25452 } else {
25453 /* the most general case */
25454 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25460 * MXU instruction category max/min
25461 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25463 * S32MAX D16MAX Q8MAX
25464 * S32MIN D16MIN Q8MIN
25468 * S32MAX XRa, XRb, XRc
25469 * Update XRa with the maximum of signed 32-bit integers contained
25470 * in XRb and XRc.
25472 * S32MIN XRa, XRb, XRc
25473 * Update XRa with the minimum of signed 32-bit integers contained
25474 * in XRb and XRc.
25476 * 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
25477 * +-----------+---------+-----+-------+-------+-------+-----------+
25478 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25479 * +-----------+---------+-----+-------+-------+-------+-----------+
25481 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25483 uint32_t pad, opc, XRc, XRb, XRa;
25485 pad = extract32(ctx->opcode, 21, 5);
25486 opc = extract32(ctx->opcode, 18, 3);
25487 XRc = extract32(ctx->opcode, 14, 4);
25488 XRb = extract32(ctx->opcode, 10, 4);
25489 XRa = extract32(ctx->opcode, 6, 4);
25491 if (unlikely(pad != 0)) {
25492 /* opcode padding incorrect -> do nothing */
25493 } else if (unlikely(XRa == 0)) {
25494 /* destination is zero register -> do nothing */
25495 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25496 /* both operands zero registers -> just set destination to zero */
25497 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25498 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25499 /* exactly one operand is zero register - find which one is not...*/
25500 uint32_t XRx = XRb ? XRb : XRc;
25501 /* ...and do max/min operation with one operand 0 */
25502 if (opc == OPC_MXU_S32MAX) {
25503 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25504 } else {
25505 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25507 } else if (unlikely(XRb == XRc)) {
25508 /* both operands same -> just set destination to one of them */
25509 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25510 } else {
25511 /* the most general case */
25512 if (opc == OPC_MXU_S32MAX) {
25513 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25514 mxu_gpr[XRc - 1]);
25515 } else {
25516 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25517 mxu_gpr[XRc - 1]);
25523 * D16MAX
25524 * Update XRa with the 16-bit-wise maximums of signed integers
25525 * contained in XRb and XRc.
25527 * D16MIN
25528 * Update XRa with the 16-bit-wise minimums of signed integers
25529 * contained in XRb and XRc.
25531 * 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
25532 * +-----------+---------+-----+-------+-------+-------+-----------+
25533 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25534 * +-----------+---------+-----+-------+-------+-------+-----------+
25536 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25538 uint32_t pad, opc, XRc, XRb, XRa;
25540 pad = extract32(ctx->opcode, 21, 5);
25541 opc = extract32(ctx->opcode, 18, 3);
25542 XRc = extract32(ctx->opcode, 14, 4);
25543 XRb = extract32(ctx->opcode, 10, 4);
25544 XRa = extract32(ctx->opcode, 6, 4);
25546 if (unlikely(pad != 0)) {
25547 /* opcode padding incorrect -> do nothing */
25548 } else if (unlikely(XRc == 0)) {
25549 /* destination is zero register -> do nothing */
25550 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25551 /* both operands zero registers -> just set destination to zero */
25552 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25553 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25554 /* exactly one operand is zero register - find which one is not...*/
25555 uint32_t XRx = XRb ? XRb : XRc;
25556 /* ...and do half-word-wise max/min with one operand 0 */
25557 TCGv_i32 t0 = tcg_temp_new();
25558 TCGv_i32 t1 = tcg_const_i32(0);
25560 /* the left half-word first */
25561 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25562 if (opc == OPC_MXU_D16MAX) {
25563 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25564 } else {
25565 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25568 /* the right half-word */
25569 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25570 /* move half-words to the leftmost position */
25571 tcg_gen_shli_i32(t0, t0, 16);
25572 /* t0 will be max/min of t0 and t1 */
25573 if (opc == OPC_MXU_D16MAX) {
25574 tcg_gen_smax_i32(t0, t0, t1);
25575 } else {
25576 tcg_gen_smin_i32(t0, t0, t1);
25578 /* return resulting half-words to its original position */
25579 tcg_gen_shri_i32(t0, t0, 16);
25580 /* finaly update the destination */
25581 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25583 tcg_temp_free(t1);
25584 tcg_temp_free(t0);
25585 } else if (unlikely(XRb == XRc)) {
25586 /* both operands same -> just set destination to one of them */
25587 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25588 } else {
25589 /* the most general case */
25590 TCGv_i32 t0 = tcg_temp_new();
25591 TCGv_i32 t1 = tcg_temp_new();
25593 /* the left half-word first */
25594 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25595 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25596 if (opc == OPC_MXU_D16MAX) {
25597 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25598 } else {
25599 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25602 /* the right half-word */
25603 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25604 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25605 /* move half-words to the leftmost position */
25606 tcg_gen_shli_i32(t0, t0, 16);
25607 tcg_gen_shli_i32(t1, t1, 16);
25608 /* t0 will be max/min of t0 and t1 */
25609 if (opc == OPC_MXU_D16MAX) {
25610 tcg_gen_smax_i32(t0, t0, t1);
25611 } else {
25612 tcg_gen_smin_i32(t0, t0, t1);
25614 /* return resulting half-words to its original position */
25615 tcg_gen_shri_i32(t0, t0, 16);
25616 /* finaly update the destination */
25617 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25619 tcg_temp_free(t1);
25620 tcg_temp_free(t0);
25625 * Q8MAX
25626 * Update XRa with the 8-bit-wise maximums of signed integers
25627 * contained in XRb and XRc.
25629 * Q8MIN
25630 * Update XRa with the 8-bit-wise minimums of signed integers
25631 * contained in XRb and XRc.
25633 * 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
25634 * +-----------+---------+-----+-------+-------+-------+-----------+
25635 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25636 * +-----------+---------+-----+-------+-------+-------+-----------+
25638 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25640 uint32_t pad, opc, XRc, XRb, XRa;
25642 pad = extract32(ctx->opcode, 21, 5);
25643 opc = extract32(ctx->opcode, 18, 3);
25644 XRc = extract32(ctx->opcode, 14, 4);
25645 XRb = extract32(ctx->opcode, 10, 4);
25646 XRa = extract32(ctx->opcode, 6, 4);
25648 if (unlikely(pad != 0)) {
25649 /* opcode padding incorrect -> do nothing */
25650 } else if (unlikely(XRa == 0)) {
25651 /* destination is zero register -> do nothing */
25652 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25653 /* both operands zero registers -> just set destination to zero */
25654 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25655 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25656 /* exactly one operand is zero register - make it be the first...*/
25657 uint32_t XRx = XRb ? XRb : XRc;
25658 /* ...and do byte-wise max/min with one operand 0 */
25659 TCGv_i32 t0 = tcg_temp_new();
25660 TCGv_i32 t1 = tcg_const_i32(0);
25661 int32_t i;
25663 /* the leftmost byte (byte 3) first */
25664 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25665 if (opc == OPC_MXU_Q8MAX) {
25666 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25667 } else {
25668 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25671 /* bytes 2, 1, 0 */
25672 for (i = 2; i >= 0; i--) {
25673 /* extract the byte */
25674 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25675 /* move the byte to the leftmost position */
25676 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25677 /* t0 will be max/min of t0 and t1 */
25678 if (opc == OPC_MXU_Q8MAX) {
25679 tcg_gen_smax_i32(t0, t0, t1);
25680 } else {
25681 tcg_gen_smin_i32(t0, t0, t1);
25683 /* return resulting byte to its original position */
25684 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25685 /* finaly update the destination */
25686 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25689 tcg_temp_free(t1);
25690 tcg_temp_free(t0);
25691 } else if (unlikely(XRb == XRc)) {
25692 /* both operands same -> just set destination to one of them */
25693 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25694 } else {
25695 /* the most general case */
25696 TCGv_i32 t0 = tcg_temp_new();
25697 TCGv_i32 t1 = tcg_temp_new();
25698 int32_t i;
25700 /* the leftmost bytes (bytes 3) first */
25701 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25702 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25703 if (opc == OPC_MXU_Q8MAX) {
25704 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25705 } else {
25706 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25709 /* bytes 2, 1, 0 */
25710 for (i = 2; i >= 0; i--) {
25711 /* extract corresponding bytes */
25712 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25713 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25714 /* move the bytes to the leftmost position */
25715 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25716 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25717 /* t0 will be max/min of t0 and t1 */
25718 if (opc == OPC_MXU_Q8MAX) {
25719 tcg_gen_smax_i32(t0, t0, t1);
25720 } else {
25721 tcg_gen_smin_i32(t0, t0, t1);
25723 /* return resulting byte to its original position */
25724 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25725 /* finaly update the destination */
25726 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25729 tcg_temp_free(t1);
25730 tcg_temp_free(t0);
25736 * MXU instruction category: align
25737 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25739 * S32ALN S32ALNI
25743 * S32ALNI XRc, XRb, XRa, optn3
25744 * Arrange bytes from XRb and XRc according to one of five sets of
25745 * rules determined by optn3, and place the result in XRa.
25747 * 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
25748 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25749 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25750 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25753 static void gen_mxu_S32ALNI(DisasContext *ctx)
25755 uint32_t optn3, pad, XRc, XRb, XRa;
25757 optn3 = extract32(ctx->opcode, 23, 3);
25758 pad = extract32(ctx->opcode, 21, 2);
25759 XRc = extract32(ctx->opcode, 14, 4);
25760 XRb = extract32(ctx->opcode, 10, 4);
25761 XRa = extract32(ctx->opcode, 6, 4);
25763 if (unlikely(pad != 0)) {
25764 /* opcode padding incorrect -> do nothing */
25765 } else if (unlikely(XRa == 0)) {
25766 /* destination is zero register -> do nothing */
25767 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25768 /* both operands zero registers -> just set destination to all 0s */
25769 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25770 } else if (unlikely(XRb == 0)) {
25771 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25772 switch (optn3) {
25773 case MXU_OPTN3_PTN0:
25774 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25775 break;
25776 case MXU_OPTN3_PTN1:
25777 case MXU_OPTN3_PTN2:
25778 case MXU_OPTN3_PTN3:
25779 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25780 8 * (4 - optn3));
25781 break;
25782 case MXU_OPTN3_PTN4:
25783 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25784 break;
25786 } else if (unlikely(XRc == 0)) {
25787 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25788 switch (optn3) {
25789 case MXU_OPTN3_PTN0:
25790 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25791 break;
25792 case MXU_OPTN3_PTN1:
25793 case MXU_OPTN3_PTN2:
25794 case MXU_OPTN3_PTN3:
25795 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25796 break;
25797 case MXU_OPTN3_PTN4:
25798 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25799 break;
25801 } else if (unlikely(XRb == XRc)) {
25802 /* both operands same -> just rotation or moving from any of them */
25803 switch (optn3) {
25804 case MXU_OPTN3_PTN0:
25805 case MXU_OPTN3_PTN4:
25806 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25807 break;
25808 case MXU_OPTN3_PTN1:
25809 case MXU_OPTN3_PTN2:
25810 case MXU_OPTN3_PTN3:
25811 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25812 break;
25814 } else {
25815 /* the most general case */
25816 switch (optn3) {
25817 case MXU_OPTN3_PTN0:
25819 /* */
25820 /* XRb XRc */
25821 /* +---------------+ */
25822 /* | A B C D | E F G H */
25823 /* +-------+-------+ */
25824 /* | */
25825 /* XRa */
25826 /* */
25828 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25830 break;
25831 case MXU_OPTN3_PTN1:
25833 /* */
25834 /* XRb XRc */
25835 /* +-------------------+ */
25836 /* A | B C D E | F G H */
25837 /* +---------+---------+ */
25838 /* | */
25839 /* XRa */
25840 /* */
25842 TCGv_i32 t0 = tcg_temp_new();
25843 TCGv_i32 t1 = tcg_temp_new();
25845 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25846 tcg_gen_shli_i32(t0, t0, 8);
25848 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25849 tcg_gen_shri_i32(t1, t1, 24);
25851 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25853 tcg_temp_free(t1);
25854 tcg_temp_free(t0);
25856 break;
25857 case MXU_OPTN3_PTN2:
25859 /* */
25860 /* XRb XRc */
25861 /* +-------------------+ */
25862 /* A B | C D E F | G H */
25863 /* +---------+---------+ */
25864 /* | */
25865 /* XRa */
25866 /* */
25868 TCGv_i32 t0 = tcg_temp_new();
25869 TCGv_i32 t1 = tcg_temp_new();
25871 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25872 tcg_gen_shli_i32(t0, t0, 16);
25874 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25875 tcg_gen_shri_i32(t1, t1, 16);
25877 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25879 tcg_temp_free(t1);
25880 tcg_temp_free(t0);
25882 break;
25883 case MXU_OPTN3_PTN3:
25885 /* */
25886 /* XRb XRc */
25887 /* +-------------------+ */
25888 /* A B C | D E F G | H */
25889 /* +---------+---------+ */
25890 /* | */
25891 /* XRa */
25892 /* */
25894 TCGv_i32 t0 = tcg_temp_new();
25895 TCGv_i32 t1 = tcg_temp_new();
25897 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25898 tcg_gen_shli_i32(t0, t0, 24);
25900 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25901 tcg_gen_shri_i32(t1, t1, 8);
25903 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25905 tcg_temp_free(t1);
25906 tcg_temp_free(t0);
25908 break;
25909 case MXU_OPTN3_PTN4:
25911 /* */
25912 /* XRb XRc */
25913 /* +---------------+ */
25914 /* A B C D | E F G H | */
25915 /* +-------+-------+ */
25916 /* | */
25917 /* XRa */
25918 /* */
25920 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25922 break;
25929 * Decoding engine for MXU
25930 * =======================
25935 * Decode MXU pool00
25937 * 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
25938 * +-----------+---------+-----+-------+-------+-------+-----------+
25939 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25940 * +-----------+---------+-----+-------+-------+-------+-----------+
25943 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25945 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25947 switch (opcode) {
25948 case OPC_MXU_S32MAX:
25949 case OPC_MXU_S32MIN:
25950 gen_mxu_S32MAX_S32MIN(ctx);
25951 break;
25952 case OPC_MXU_D16MAX:
25953 case OPC_MXU_D16MIN:
25954 gen_mxu_D16MAX_D16MIN(ctx);
25955 break;
25956 case OPC_MXU_Q8MAX:
25957 case OPC_MXU_Q8MIN:
25958 gen_mxu_Q8MAX_Q8MIN(ctx);
25959 break;
25960 case OPC_MXU_Q8SLT:
25961 /* TODO: Implement emulation of Q8SLT instruction. */
25962 MIPS_INVAL("OPC_MXU_Q8SLT");
25963 generate_exception_end(ctx, EXCP_RI);
25964 break;
25965 case OPC_MXU_Q8SLTU:
25966 /* TODO: Implement emulation of Q8SLTU instruction. */
25967 MIPS_INVAL("OPC_MXU_Q8SLTU");
25968 generate_exception_end(ctx, EXCP_RI);
25969 break;
25970 default:
25971 MIPS_INVAL("decode_opc_mxu");
25972 generate_exception_end(ctx, EXCP_RI);
25973 break;
25979 * Decode MXU pool01
25981 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25982 * 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
25983 * +-----------+---------+-----+-------+-------+-------+-----------+
25984 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25985 * +-----------+---------+-----+-------+-------+-------+-----------+
25987 * Q8ADD:
25988 * 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
25989 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25990 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25991 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25994 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25996 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25998 switch (opcode) {
25999 case OPC_MXU_S32SLT:
26000 /* TODO: Implement emulation of S32SLT instruction. */
26001 MIPS_INVAL("OPC_MXU_S32SLT");
26002 generate_exception_end(ctx, EXCP_RI);
26003 break;
26004 case OPC_MXU_D16SLT:
26005 /* TODO: Implement emulation of D16SLT instruction. */
26006 MIPS_INVAL("OPC_MXU_D16SLT");
26007 generate_exception_end(ctx, EXCP_RI);
26008 break;
26009 case OPC_MXU_D16AVG:
26010 /* TODO: Implement emulation of D16AVG instruction. */
26011 MIPS_INVAL("OPC_MXU_D16AVG");
26012 generate_exception_end(ctx, EXCP_RI);
26013 break;
26014 case OPC_MXU_D16AVGR:
26015 /* TODO: Implement emulation of D16AVGR instruction. */
26016 MIPS_INVAL("OPC_MXU_D16AVGR");
26017 generate_exception_end(ctx, EXCP_RI);
26018 break;
26019 case OPC_MXU_Q8AVG:
26020 /* TODO: Implement emulation of Q8AVG instruction. */
26021 MIPS_INVAL("OPC_MXU_Q8AVG");
26022 generate_exception_end(ctx, EXCP_RI);
26023 break;
26024 case OPC_MXU_Q8AVGR:
26025 /* TODO: Implement emulation of Q8AVGR instruction. */
26026 MIPS_INVAL("OPC_MXU_Q8AVGR");
26027 generate_exception_end(ctx, EXCP_RI);
26028 break;
26029 case OPC_MXU_Q8ADD:
26030 /* TODO: Implement emulation of Q8ADD instruction. */
26031 MIPS_INVAL("OPC_MXU_Q8ADD");
26032 generate_exception_end(ctx, EXCP_RI);
26033 break;
26034 default:
26035 MIPS_INVAL("decode_opc_mxu");
26036 generate_exception_end(ctx, EXCP_RI);
26037 break;
26043 * Decode MXU pool02
26045 * 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
26046 * +-----------+---------+-----+-------+-------+-------+-----------+
26047 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26048 * +-----------+---------+-----+-------+-------+-------+-----------+
26051 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26053 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26055 switch (opcode) {
26056 case OPC_MXU_S32CPS:
26057 /* TODO: Implement emulation of S32CPS instruction. */
26058 MIPS_INVAL("OPC_MXU_S32CPS");
26059 generate_exception_end(ctx, EXCP_RI);
26060 break;
26061 case OPC_MXU_D16CPS:
26062 /* TODO: Implement emulation of D16CPS instruction. */
26063 MIPS_INVAL("OPC_MXU_D16CPS");
26064 generate_exception_end(ctx, EXCP_RI);
26065 break;
26066 case OPC_MXU_Q8ABD:
26067 /* TODO: Implement emulation of Q8ABD instruction. */
26068 MIPS_INVAL("OPC_MXU_Q8ABD");
26069 generate_exception_end(ctx, EXCP_RI);
26070 break;
26071 case OPC_MXU_Q16SAT:
26072 /* TODO: Implement emulation of Q16SAT instruction. */
26073 MIPS_INVAL("OPC_MXU_Q16SAT");
26074 generate_exception_end(ctx, EXCP_RI);
26075 break;
26076 default:
26077 MIPS_INVAL("decode_opc_mxu");
26078 generate_exception_end(ctx, EXCP_RI);
26079 break;
26085 * Decode MXU pool03
26087 * D16MULF:
26088 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26089 * +-----------+---+---+-------+-------+-------+-------+-----------+
26090 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26091 * +-----------+---+---+-------+-------+-------+-------+-----------+
26093 * D16MULE:
26094 * 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
26095 * +-----------+---+---+-------+-------+-------+-------+-----------+
26096 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26097 * +-----------+---+---+-------+-------+-------+-------+-----------+
26100 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26102 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26104 switch (opcode) {
26105 case OPC_MXU_D16MULF:
26106 /* TODO: Implement emulation of D16MULF instruction. */
26107 MIPS_INVAL("OPC_MXU_D16MULF");
26108 generate_exception_end(ctx, EXCP_RI);
26109 break;
26110 case OPC_MXU_D16MULE:
26111 /* TODO: Implement emulation of D16MULE instruction. */
26112 MIPS_INVAL("OPC_MXU_D16MULE");
26113 generate_exception_end(ctx, EXCP_RI);
26114 break;
26115 default:
26116 MIPS_INVAL("decode_opc_mxu");
26117 generate_exception_end(ctx, EXCP_RI);
26118 break;
26124 * Decode MXU pool04
26126 * 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
26127 * +-----------+---------+-+-------------------+-------+-----------+
26128 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26129 * +-----------+---------+-+-------------------+-------+-----------+
26132 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26134 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26136 switch (opcode) {
26137 case OPC_MXU_S32LDD:
26138 case OPC_MXU_S32LDDR:
26139 gen_mxu_s32ldd_s32lddr(ctx);
26140 break;
26141 default:
26142 MIPS_INVAL("decode_opc_mxu");
26143 generate_exception_end(ctx, EXCP_RI);
26144 break;
26150 * Decode MXU pool05
26152 * 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
26153 * +-----------+---------+-+-------------------+-------+-----------+
26154 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26155 * +-----------+---------+-+-------------------+-------+-----------+
26158 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26160 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26162 switch (opcode) {
26163 case OPC_MXU_S32STD:
26164 /* TODO: Implement emulation of S32STD instruction. */
26165 MIPS_INVAL("OPC_MXU_S32STD");
26166 generate_exception_end(ctx, EXCP_RI);
26167 break;
26168 case OPC_MXU_S32STDR:
26169 /* TODO: Implement emulation of S32STDR instruction. */
26170 MIPS_INVAL("OPC_MXU_S32STDR");
26171 generate_exception_end(ctx, EXCP_RI);
26172 break;
26173 default:
26174 MIPS_INVAL("decode_opc_mxu");
26175 generate_exception_end(ctx, EXCP_RI);
26176 break;
26182 * Decode MXU pool06
26184 * 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
26185 * +-----------+---------+---------+---+-------+-------+-----------+
26186 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26187 * +-----------+---------+---------+---+-------+-------+-----------+
26190 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26192 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26194 switch (opcode) {
26195 case OPC_MXU_S32LDDV:
26196 /* TODO: Implement emulation of S32LDDV instruction. */
26197 MIPS_INVAL("OPC_MXU_S32LDDV");
26198 generate_exception_end(ctx, EXCP_RI);
26199 break;
26200 case OPC_MXU_S32LDDVR:
26201 /* TODO: Implement emulation of S32LDDVR instruction. */
26202 MIPS_INVAL("OPC_MXU_S32LDDVR");
26203 generate_exception_end(ctx, EXCP_RI);
26204 break;
26205 default:
26206 MIPS_INVAL("decode_opc_mxu");
26207 generate_exception_end(ctx, EXCP_RI);
26208 break;
26214 * Decode MXU pool07
26216 * 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
26217 * +-----------+---------+---------+---+-------+-------+-----------+
26218 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26219 * +-----------+---------+---------+---+-------+-------+-----------+
26222 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26224 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26226 switch (opcode) {
26227 case OPC_MXU_S32STDV:
26228 /* TODO: Implement emulation of S32TDV instruction. */
26229 MIPS_INVAL("OPC_MXU_S32TDV");
26230 generate_exception_end(ctx, EXCP_RI);
26231 break;
26232 case OPC_MXU_S32STDVR:
26233 /* TODO: Implement emulation of S32TDVR instruction. */
26234 MIPS_INVAL("OPC_MXU_S32TDVR");
26235 generate_exception_end(ctx, EXCP_RI);
26236 break;
26237 default:
26238 MIPS_INVAL("decode_opc_mxu");
26239 generate_exception_end(ctx, EXCP_RI);
26240 break;
26246 * Decode MXU pool08
26248 * 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
26249 * +-----------+---------+-+-------------------+-------+-----------+
26250 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26251 * +-----------+---------+-+-------------------+-------+-----------+
26254 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26256 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26258 switch (opcode) {
26259 case OPC_MXU_S32LDI:
26260 /* TODO: Implement emulation of S32LDI instruction. */
26261 MIPS_INVAL("OPC_MXU_S32LDI");
26262 generate_exception_end(ctx, EXCP_RI);
26263 break;
26264 case OPC_MXU_S32LDIR:
26265 /* TODO: Implement emulation of S32LDIR instruction. */
26266 MIPS_INVAL("OPC_MXU_S32LDIR");
26267 generate_exception_end(ctx, EXCP_RI);
26268 break;
26269 default:
26270 MIPS_INVAL("decode_opc_mxu");
26271 generate_exception_end(ctx, EXCP_RI);
26272 break;
26278 * Decode MXU pool09
26280 * 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
26281 * +-----------+---------+-+-------------------+-------+-----------+
26282 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26283 * +-----------+---------+-+-------------------+-------+-----------+
26286 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26288 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26290 switch (opcode) {
26291 case OPC_MXU_S32SDI:
26292 /* TODO: Implement emulation of S32SDI instruction. */
26293 MIPS_INVAL("OPC_MXU_S32SDI");
26294 generate_exception_end(ctx, EXCP_RI);
26295 break;
26296 case OPC_MXU_S32SDIR:
26297 /* TODO: Implement emulation of S32SDIR instruction. */
26298 MIPS_INVAL("OPC_MXU_S32SDIR");
26299 generate_exception_end(ctx, EXCP_RI);
26300 break;
26301 default:
26302 MIPS_INVAL("decode_opc_mxu");
26303 generate_exception_end(ctx, EXCP_RI);
26304 break;
26310 * Decode MXU pool10
26312 * 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
26313 * +-----------+---------+---------+---+-------+-------+-----------+
26314 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26315 * +-----------+---------+---------+---+-------+-------+-----------+
26318 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26320 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26322 switch (opcode) {
26323 case OPC_MXU_S32LDIV:
26324 /* TODO: Implement emulation of S32LDIV instruction. */
26325 MIPS_INVAL("OPC_MXU_S32LDIV");
26326 generate_exception_end(ctx, EXCP_RI);
26327 break;
26328 case OPC_MXU_S32LDIVR:
26329 /* TODO: Implement emulation of S32LDIVR instruction. */
26330 MIPS_INVAL("OPC_MXU_S32LDIVR");
26331 generate_exception_end(ctx, EXCP_RI);
26332 break;
26333 default:
26334 MIPS_INVAL("decode_opc_mxu");
26335 generate_exception_end(ctx, EXCP_RI);
26336 break;
26342 * Decode MXU pool11
26344 * 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
26345 * +-----------+---------+---------+---+-------+-------+-----------+
26346 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26347 * +-----------+---------+---------+---+-------+-------+-----------+
26350 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26352 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26354 switch (opcode) {
26355 case OPC_MXU_S32SDIV:
26356 /* TODO: Implement emulation of S32SDIV instruction. */
26357 MIPS_INVAL("OPC_MXU_S32SDIV");
26358 generate_exception_end(ctx, EXCP_RI);
26359 break;
26360 case OPC_MXU_S32SDIVR:
26361 /* TODO: Implement emulation of S32SDIVR instruction. */
26362 MIPS_INVAL("OPC_MXU_S32SDIVR");
26363 generate_exception_end(ctx, EXCP_RI);
26364 break;
26365 default:
26366 MIPS_INVAL("decode_opc_mxu");
26367 generate_exception_end(ctx, EXCP_RI);
26368 break;
26374 * Decode MXU pool12
26376 * 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
26377 * +-----------+---+---+-------+-------+-------+-------+-----------+
26378 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26379 * +-----------+---+---+-------+-------+-------+-------+-----------+
26382 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26384 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26386 switch (opcode) {
26387 case OPC_MXU_D32ACC:
26388 /* TODO: Implement emulation of D32ACC instruction. */
26389 MIPS_INVAL("OPC_MXU_D32ACC");
26390 generate_exception_end(ctx, EXCP_RI);
26391 break;
26392 case OPC_MXU_D32ACCM:
26393 /* TODO: Implement emulation of D32ACCM instruction. */
26394 MIPS_INVAL("OPC_MXU_D32ACCM");
26395 generate_exception_end(ctx, EXCP_RI);
26396 break;
26397 case OPC_MXU_D32ASUM:
26398 /* TODO: Implement emulation of D32ASUM instruction. */
26399 MIPS_INVAL("OPC_MXU_D32ASUM");
26400 generate_exception_end(ctx, EXCP_RI);
26401 break;
26402 default:
26403 MIPS_INVAL("decode_opc_mxu");
26404 generate_exception_end(ctx, EXCP_RI);
26405 break;
26411 * Decode MXU pool13
26413 * 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
26414 * +-----------+---+---+-------+-------+-------+-------+-----------+
26415 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26416 * +-----------+---+---+-------+-------+-------+-------+-----------+
26419 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26421 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26423 switch (opcode) {
26424 case OPC_MXU_Q16ACC:
26425 /* TODO: Implement emulation of Q16ACC instruction. */
26426 MIPS_INVAL("OPC_MXU_Q16ACC");
26427 generate_exception_end(ctx, EXCP_RI);
26428 break;
26429 case OPC_MXU_Q16ACCM:
26430 /* TODO: Implement emulation of Q16ACCM instruction. */
26431 MIPS_INVAL("OPC_MXU_Q16ACCM");
26432 generate_exception_end(ctx, EXCP_RI);
26433 break;
26434 case OPC_MXU_Q16ASUM:
26435 /* TODO: Implement emulation of Q16ASUM instruction. */
26436 MIPS_INVAL("OPC_MXU_Q16ASUM");
26437 generate_exception_end(ctx, EXCP_RI);
26438 break;
26439 default:
26440 MIPS_INVAL("decode_opc_mxu");
26441 generate_exception_end(ctx, EXCP_RI);
26442 break;
26448 * Decode MXU pool14
26450 * Q8ADDE, Q8ACCE:
26451 * 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
26452 * +-----------+---+---+-------+-------+-------+-------+-----------+
26453 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26454 * +-----------+---+---+-------+-------+-------+-------+-----------+
26456 * D8SUM, D8SUMC:
26457 * 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
26458 * +-----------+---+---+-------+-------+-------+-------+-----------+
26459 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26460 * +-----------+---+---+-------+-------+-------+-------+-----------+
26463 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26465 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26467 switch (opcode) {
26468 case OPC_MXU_Q8ADDE:
26469 /* TODO: Implement emulation of Q8ADDE instruction. */
26470 MIPS_INVAL("OPC_MXU_Q8ADDE");
26471 generate_exception_end(ctx, EXCP_RI);
26472 break;
26473 case OPC_MXU_D8SUM:
26474 /* TODO: Implement emulation of D8SUM instruction. */
26475 MIPS_INVAL("OPC_MXU_D8SUM");
26476 generate_exception_end(ctx, EXCP_RI);
26477 break;
26478 case OPC_MXU_D8SUMC:
26479 /* TODO: Implement emulation of D8SUMC instruction. */
26480 MIPS_INVAL("OPC_MXU_D8SUMC");
26481 generate_exception_end(ctx, EXCP_RI);
26482 break;
26483 default:
26484 MIPS_INVAL("decode_opc_mxu");
26485 generate_exception_end(ctx, EXCP_RI);
26486 break;
26492 * Decode MXU pool15
26494 * S32MUL, S32MULU, S32EXTRV:
26495 * 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
26496 * +-----------+---------+---------+---+-------+-------+-----------+
26497 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26498 * +-----------+---------+---------+---+-------+-------+-----------+
26500 * S32EXTR:
26501 * 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
26502 * +-----------+---------+---------+---+-------+-------+-----------+
26503 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26504 * +-----------+---------+---------+---+-------+-------+-----------+
26507 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26509 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26511 switch (opcode) {
26512 case OPC_MXU_S32MUL:
26513 /* TODO: Implement emulation of S32MUL instruction. */
26514 MIPS_INVAL("OPC_MXU_S32MUL");
26515 generate_exception_end(ctx, EXCP_RI);
26516 break;
26517 case OPC_MXU_S32MULU:
26518 /* TODO: Implement emulation of S32MULU instruction. */
26519 MIPS_INVAL("OPC_MXU_S32MULU");
26520 generate_exception_end(ctx, EXCP_RI);
26521 break;
26522 case OPC_MXU_S32EXTR:
26523 /* TODO: Implement emulation of S32EXTR instruction. */
26524 MIPS_INVAL("OPC_MXU_S32EXTR");
26525 generate_exception_end(ctx, EXCP_RI);
26526 break;
26527 case OPC_MXU_S32EXTRV:
26528 /* TODO: Implement emulation of S32EXTRV instruction. */
26529 MIPS_INVAL("OPC_MXU_S32EXTRV");
26530 generate_exception_end(ctx, EXCP_RI);
26531 break;
26532 default:
26533 MIPS_INVAL("decode_opc_mxu");
26534 generate_exception_end(ctx, EXCP_RI);
26535 break;
26541 * Decode MXU pool16
26543 * D32SARW:
26544 * 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
26545 * +-----------+---------+-----+-------+-------+-------+-----------+
26546 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26547 * +-----------+---------+-----+-------+-------+-------+-----------+
26549 * S32ALN:
26550 * 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
26551 * +-----------+---------+-----+-------+-------+-------+-----------+
26552 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26553 * +-----------+---------+-----+-------+-------+-------+-----------+
26555 * S32ALNI:
26556 * 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
26557 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26558 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26559 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26561 * S32LUI:
26562 * 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
26563 * +-----------+-----+---+-----+-------+---------------+-----------+
26564 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26565 * +-----------+-----+---+-----+-------+---------------+-----------+
26567 * S32NOR, S32AND, S32OR, S32XOR:
26568 * 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
26569 * +-----------+---------+-----+-------+-------+-------+-----------+
26570 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26571 * +-----------+---------+-----+-------+-------+-------+-----------+
26574 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26576 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26578 switch (opcode) {
26579 case OPC_MXU_D32SARW:
26580 /* TODO: Implement emulation of D32SARW instruction. */
26581 MIPS_INVAL("OPC_MXU_D32SARW");
26582 generate_exception_end(ctx, EXCP_RI);
26583 break;
26584 case OPC_MXU_S32ALN:
26585 /* TODO: Implement emulation of S32ALN instruction. */
26586 MIPS_INVAL("OPC_MXU_S32ALN");
26587 generate_exception_end(ctx, EXCP_RI);
26588 break;
26589 case OPC_MXU_S32ALNI:
26590 gen_mxu_S32ALNI(ctx);
26591 break;
26592 case OPC_MXU_S32LUI:
26593 /* TODO: Implement emulation of S32LUI instruction. */
26594 MIPS_INVAL("OPC_MXU_S32LUI");
26595 generate_exception_end(ctx, EXCP_RI);
26596 break;
26597 case OPC_MXU_S32NOR:
26598 gen_mxu_S32NOR(ctx);
26599 break;
26600 case OPC_MXU_S32AND:
26601 gen_mxu_S32AND(ctx);
26602 break;
26603 case OPC_MXU_S32OR:
26604 gen_mxu_S32OR(ctx);
26605 break;
26606 case OPC_MXU_S32XOR:
26607 gen_mxu_S32XOR(ctx);
26608 break;
26609 default:
26610 MIPS_INVAL("decode_opc_mxu");
26611 generate_exception_end(ctx, EXCP_RI);
26612 break;
26618 * Decode MXU pool17
26620 * 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
26621 * +-----------+---------+---------+---+---------+-----+-----------+
26622 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26623 * +-----------+---------+---------+---+---------+-----+-----------+
26626 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26628 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26630 switch (opcode) {
26631 case OPC_MXU_LXW:
26632 /* TODO: Implement emulation of LXW instruction. */
26633 MIPS_INVAL("OPC_MXU_LXW");
26634 generate_exception_end(ctx, EXCP_RI);
26635 break;
26636 case OPC_MXU_LXH:
26637 /* TODO: Implement emulation of LXH instruction. */
26638 MIPS_INVAL("OPC_MXU_LXH");
26639 generate_exception_end(ctx, EXCP_RI);
26640 break;
26641 case OPC_MXU_LXHU:
26642 /* TODO: Implement emulation of LXHU instruction. */
26643 MIPS_INVAL("OPC_MXU_LXHU");
26644 generate_exception_end(ctx, EXCP_RI);
26645 break;
26646 case OPC_MXU_LXB:
26647 /* TODO: Implement emulation of LXB instruction. */
26648 MIPS_INVAL("OPC_MXU_LXB");
26649 generate_exception_end(ctx, EXCP_RI);
26650 break;
26651 case OPC_MXU_LXBU:
26652 /* TODO: Implement emulation of LXBU instruction. */
26653 MIPS_INVAL("OPC_MXU_LXBU");
26654 generate_exception_end(ctx, EXCP_RI);
26655 break;
26656 default:
26657 MIPS_INVAL("decode_opc_mxu");
26658 generate_exception_end(ctx, EXCP_RI);
26659 break;
26664 * Decode MXU pool18
26666 * 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
26667 * +-----------+---------+-----+-------+-------+-------+-----------+
26668 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26669 * +-----------+---------+-----+-------+-------+-------+-----------+
26672 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26674 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26676 switch (opcode) {
26677 case OPC_MXU_D32SLLV:
26678 /* TODO: Implement emulation of D32SLLV instruction. */
26679 MIPS_INVAL("OPC_MXU_D32SLLV");
26680 generate_exception_end(ctx, EXCP_RI);
26681 break;
26682 case OPC_MXU_D32SLRV:
26683 /* TODO: Implement emulation of D32SLRV instruction. */
26684 MIPS_INVAL("OPC_MXU_D32SLRV");
26685 generate_exception_end(ctx, EXCP_RI);
26686 break;
26687 case OPC_MXU_D32SARV:
26688 /* TODO: Implement emulation of D32SARV instruction. */
26689 MIPS_INVAL("OPC_MXU_D32SARV");
26690 generate_exception_end(ctx, EXCP_RI);
26691 break;
26692 case OPC_MXU_Q16SLLV:
26693 /* TODO: Implement emulation of Q16SLLV instruction. */
26694 MIPS_INVAL("OPC_MXU_Q16SLLV");
26695 generate_exception_end(ctx, EXCP_RI);
26696 break;
26697 case OPC_MXU_Q16SLRV:
26698 /* TODO: Implement emulation of Q16SLRV instruction. */
26699 MIPS_INVAL("OPC_MXU_Q16SLRV");
26700 generate_exception_end(ctx, EXCP_RI);
26701 break;
26702 case OPC_MXU_Q16SARV:
26703 /* TODO: Implement emulation of Q16SARV instruction. */
26704 MIPS_INVAL("OPC_MXU_Q16SARV");
26705 generate_exception_end(ctx, EXCP_RI);
26706 break;
26707 default:
26708 MIPS_INVAL("decode_opc_mxu");
26709 generate_exception_end(ctx, EXCP_RI);
26710 break;
26716 * Decode MXU pool19
26718 * 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
26719 * +-----------+---+---+-------+-------+-------+-------+-----------+
26720 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26721 * +-----------+---+---+-------+-------+-------+-------+-----------+
26724 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26726 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26728 switch (opcode) {
26729 case OPC_MXU_Q8MUL:
26730 case OPC_MXU_Q8MULSU:
26731 gen_mxu_q8mul_q8mulsu(ctx);
26732 break;
26733 default:
26734 MIPS_INVAL("decode_opc_mxu");
26735 generate_exception_end(ctx, EXCP_RI);
26736 break;
26742 * Decode MXU pool20
26744 * 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
26745 * +-----------+---------+-----+-------+-------+-------+-----------+
26746 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26747 * +-----------+---------+-----+-------+-------+-------+-----------+
26750 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26752 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26754 switch (opcode) {
26755 case OPC_MXU_Q8MOVZ:
26756 /* TODO: Implement emulation of Q8MOVZ instruction. */
26757 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26758 generate_exception_end(ctx, EXCP_RI);
26759 break;
26760 case OPC_MXU_Q8MOVN:
26761 /* TODO: Implement emulation of Q8MOVN instruction. */
26762 MIPS_INVAL("OPC_MXU_Q8MOVN");
26763 generate_exception_end(ctx, EXCP_RI);
26764 break;
26765 case OPC_MXU_D16MOVZ:
26766 /* TODO: Implement emulation of D16MOVZ instruction. */
26767 MIPS_INVAL("OPC_MXU_D16MOVZ");
26768 generate_exception_end(ctx, EXCP_RI);
26769 break;
26770 case OPC_MXU_D16MOVN:
26771 /* TODO: Implement emulation of D16MOVN instruction. */
26772 MIPS_INVAL("OPC_MXU_D16MOVN");
26773 generate_exception_end(ctx, EXCP_RI);
26774 break;
26775 case OPC_MXU_S32MOVZ:
26776 /* TODO: Implement emulation of S32MOVZ instruction. */
26777 MIPS_INVAL("OPC_MXU_S32MOVZ");
26778 generate_exception_end(ctx, EXCP_RI);
26779 break;
26780 case OPC_MXU_S32MOVN:
26781 /* TODO: Implement emulation of S32MOVN instruction. */
26782 MIPS_INVAL("OPC_MXU_S32MOVN");
26783 generate_exception_end(ctx, EXCP_RI);
26784 break;
26785 default:
26786 MIPS_INVAL("decode_opc_mxu");
26787 generate_exception_end(ctx, EXCP_RI);
26788 break;
26794 * Decode MXU pool21
26796 * 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
26797 * +-----------+---+---+-------+-------+-------+-------+-----------+
26798 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26799 * +-----------+---+---+-------+-------+-------+-------+-----------+
26802 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26804 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26806 switch (opcode) {
26807 case OPC_MXU_Q8MAC:
26808 /* TODO: Implement emulation of Q8MAC instruction. */
26809 MIPS_INVAL("OPC_MXU_Q8MAC");
26810 generate_exception_end(ctx, EXCP_RI);
26811 break;
26812 case OPC_MXU_Q8MACSU:
26813 /* TODO: Implement emulation of Q8MACSU instruction. */
26814 MIPS_INVAL("OPC_MXU_Q8MACSU");
26815 generate_exception_end(ctx, EXCP_RI);
26816 break;
26817 default:
26818 MIPS_INVAL("decode_opc_mxu");
26819 generate_exception_end(ctx, EXCP_RI);
26820 break;
26826 * Main MXU decoding function
26828 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26829 * +-----------+---------------------------------------+-----------+
26830 * | SPECIAL2 | |x x x x x x|
26831 * +-----------+---------------------------------------+-----------+
26834 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26837 * TODO: Investigate necessity of including handling of
26838 * CLZ, CLO, SDBB in this function, as they belong to
26839 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26841 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26843 if (opcode == OPC__MXU_MUL) {
26844 uint32_t rs, rt, rd, op1;
26846 rs = extract32(ctx->opcode, 21, 5);
26847 rt = extract32(ctx->opcode, 16, 5);
26848 rd = extract32(ctx->opcode, 11, 5);
26849 op1 = MASK_SPECIAL2(ctx->opcode);
26851 gen_arith(ctx, op1, rd, rs, rt);
26853 return;
26856 if (opcode == OPC_MXU_S32M2I) {
26857 gen_mxu_s32m2i(ctx);
26858 return;
26861 if (opcode == OPC_MXU_S32I2M) {
26862 gen_mxu_s32i2m(ctx);
26863 return;
26867 TCGv t_mxu_cr = tcg_temp_new();
26868 TCGLabel *l_exit = gen_new_label();
26870 gen_load_mxu_cr(t_mxu_cr);
26871 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26872 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26874 switch (opcode) {
26875 case OPC_MXU_S32MADD:
26876 /* TODO: Implement emulation of S32MADD instruction. */
26877 MIPS_INVAL("OPC_MXU_S32MADD");
26878 generate_exception_end(ctx, EXCP_RI);
26879 break;
26880 case OPC_MXU_S32MADDU:
26881 /* TODO: Implement emulation of S32MADDU instruction. */
26882 MIPS_INVAL("OPC_MXU_S32MADDU");
26883 generate_exception_end(ctx, EXCP_RI);
26884 break;
26885 case OPC_MXU__POOL00:
26886 decode_opc_mxu__pool00(env, ctx);
26887 break;
26888 case OPC_MXU_S32MSUB:
26889 /* TODO: Implement emulation of S32MSUB instruction. */
26890 MIPS_INVAL("OPC_MXU_S32MSUB");
26891 generate_exception_end(ctx, EXCP_RI);
26892 break;
26893 case OPC_MXU_S32MSUBU:
26894 /* TODO: Implement emulation of S32MSUBU instruction. */
26895 MIPS_INVAL("OPC_MXU_S32MSUBU");
26896 generate_exception_end(ctx, EXCP_RI);
26897 break;
26898 case OPC_MXU__POOL01:
26899 decode_opc_mxu__pool01(env, ctx);
26900 break;
26901 case OPC_MXU__POOL02:
26902 decode_opc_mxu__pool02(env, ctx);
26903 break;
26904 case OPC_MXU_D16MUL:
26905 gen_mxu_d16mul(ctx);
26906 break;
26907 case OPC_MXU__POOL03:
26908 decode_opc_mxu__pool03(env, ctx);
26909 break;
26910 case OPC_MXU_D16MAC:
26911 gen_mxu_d16mac(ctx);
26912 break;
26913 case OPC_MXU_D16MACF:
26914 /* TODO: Implement emulation of D16MACF instruction. */
26915 MIPS_INVAL("OPC_MXU_D16MACF");
26916 generate_exception_end(ctx, EXCP_RI);
26917 break;
26918 case OPC_MXU_D16MADL:
26919 /* TODO: Implement emulation of D16MADL instruction. */
26920 MIPS_INVAL("OPC_MXU_D16MADL");
26921 generate_exception_end(ctx, EXCP_RI);
26922 break;
26923 case OPC_MXU_S16MAD:
26924 /* TODO: Implement emulation of S16MAD instruction. */
26925 MIPS_INVAL("OPC_MXU_S16MAD");
26926 generate_exception_end(ctx, EXCP_RI);
26927 break;
26928 case OPC_MXU_Q16ADD:
26929 /* TODO: Implement emulation of Q16ADD instruction. */
26930 MIPS_INVAL("OPC_MXU_Q16ADD");
26931 generate_exception_end(ctx, EXCP_RI);
26932 break;
26933 case OPC_MXU_D16MACE:
26934 /* TODO: Implement emulation of D16MACE instruction. */
26935 MIPS_INVAL("OPC_MXU_D16MACE");
26936 generate_exception_end(ctx, EXCP_RI);
26937 break;
26938 case OPC_MXU__POOL04:
26939 decode_opc_mxu__pool04(env, ctx);
26940 break;
26941 case OPC_MXU__POOL05:
26942 decode_opc_mxu__pool05(env, ctx);
26943 break;
26944 case OPC_MXU__POOL06:
26945 decode_opc_mxu__pool06(env, ctx);
26946 break;
26947 case OPC_MXU__POOL07:
26948 decode_opc_mxu__pool07(env, ctx);
26949 break;
26950 case OPC_MXU__POOL08:
26951 decode_opc_mxu__pool08(env, ctx);
26952 break;
26953 case OPC_MXU__POOL09:
26954 decode_opc_mxu__pool09(env, ctx);
26955 break;
26956 case OPC_MXU__POOL10:
26957 decode_opc_mxu__pool10(env, ctx);
26958 break;
26959 case OPC_MXU__POOL11:
26960 decode_opc_mxu__pool11(env, ctx);
26961 break;
26962 case OPC_MXU_D32ADD:
26963 /* TODO: Implement emulation of D32ADD instruction. */
26964 MIPS_INVAL("OPC_MXU_D32ADD");
26965 generate_exception_end(ctx, EXCP_RI);
26966 break;
26967 case OPC_MXU__POOL12:
26968 decode_opc_mxu__pool12(env, ctx);
26969 break;
26970 case OPC_MXU__POOL13:
26971 decode_opc_mxu__pool13(env, ctx);
26972 break;
26973 case OPC_MXU__POOL14:
26974 decode_opc_mxu__pool14(env, ctx);
26975 break;
26976 case OPC_MXU_Q8ACCE:
26977 /* TODO: Implement emulation of Q8ACCE instruction. */
26978 MIPS_INVAL("OPC_MXU_Q8ACCE");
26979 generate_exception_end(ctx, EXCP_RI);
26980 break;
26981 case OPC_MXU_S8LDD:
26982 gen_mxu_s8ldd(ctx);
26983 break;
26984 case OPC_MXU_S8STD:
26985 /* TODO: Implement emulation of S8STD instruction. */
26986 MIPS_INVAL("OPC_MXU_S8STD");
26987 generate_exception_end(ctx, EXCP_RI);
26988 break;
26989 case OPC_MXU_S8LDI:
26990 /* TODO: Implement emulation of S8LDI instruction. */
26991 MIPS_INVAL("OPC_MXU_S8LDI");
26992 generate_exception_end(ctx, EXCP_RI);
26993 break;
26994 case OPC_MXU_S8SDI:
26995 /* TODO: Implement emulation of S8SDI instruction. */
26996 MIPS_INVAL("OPC_MXU_S8SDI");
26997 generate_exception_end(ctx, EXCP_RI);
26998 break;
26999 case OPC_MXU__POOL15:
27000 decode_opc_mxu__pool15(env, ctx);
27001 break;
27002 case OPC_MXU__POOL16:
27003 decode_opc_mxu__pool16(env, ctx);
27004 break;
27005 case OPC_MXU__POOL17:
27006 decode_opc_mxu__pool17(env, ctx);
27007 break;
27008 case OPC_MXU_S16LDD:
27009 /* TODO: Implement emulation of S16LDD instruction. */
27010 MIPS_INVAL("OPC_MXU_S16LDD");
27011 generate_exception_end(ctx, EXCP_RI);
27012 break;
27013 case OPC_MXU_S16STD:
27014 /* TODO: Implement emulation of S16STD instruction. */
27015 MIPS_INVAL("OPC_MXU_S16STD");
27016 generate_exception_end(ctx, EXCP_RI);
27017 break;
27018 case OPC_MXU_S16LDI:
27019 /* TODO: Implement emulation of S16LDI instruction. */
27020 MIPS_INVAL("OPC_MXU_S16LDI");
27021 generate_exception_end(ctx, EXCP_RI);
27022 break;
27023 case OPC_MXU_S16SDI:
27024 /* TODO: Implement emulation of S16SDI instruction. */
27025 MIPS_INVAL("OPC_MXU_S16SDI");
27026 generate_exception_end(ctx, EXCP_RI);
27027 break;
27028 case OPC_MXU_D32SLL:
27029 /* TODO: Implement emulation of D32SLL instruction. */
27030 MIPS_INVAL("OPC_MXU_D32SLL");
27031 generate_exception_end(ctx, EXCP_RI);
27032 break;
27033 case OPC_MXU_D32SLR:
27034 /* TODO: Implement emulation of D32SLR instruction. */
27035 MIPS_INVAL("OPC_MXU_D32SLR");
27036 generate_exception_end(ctx, EXCP_RI);
27037 break;
27038 case OPC_MXU_D32SARL:
27039 /* TODO: Implement emulation of D32SARL instruction. */
27040 MIPS_INVAL("OPC_MXU_D32SARL");
27041 generate_exception_end(ctx, EXCP_RI);
27042 break;
27043 case OPC_MXU_D32SAR:
27044 /* TODO: Implement emulation of D32SAR instruction. */
27045 MIPS_INVAL("OPC_MXU_D32SAR");
27046 generate_exception_end(ctx, EXCP_RI);
27047 break;
27048 case OPC_MXU_Q16SLL:
27049 /* TODO: Implement emulation of Q16SLL instruction. */
27050 MIPS_INVAL("OPC_MXU_Q16SLL");
27051 generate_exception_end(ctx, EXCP_RI);
27052 break;
27053 case OPC_MXU_Q16SLR:
27054 /* TODO: Implement emulation of Q16SLR instruction. */
27055 MIPS_INVAL("OPC_MXU_Q16SLR");
27056 generate_exception_end(ctx, EXCP_RI);
27057 break;
27058 case OPC_MXU__POOL18:
27059 decode_opc_mxu__pool18(env, ctx);
27060 break;
27061 case OPC_MXU_Q16SAR:
27062 /* TODO: Implement emulation of Q16SAR instruction. */
27063 MIPS_INVAL("OPC_MXU_Q16SAR");
27064 generate_exception_end(ctx, EXCP_RI);
27065 break;
27066 case OPC_MXU__POOL19:
27067 decode_opc_mxu__pool19(env, ctx);
27068 break;
27069 case OPC_MXU__POOL20:
27070 decode_opc_mxu__pool20(env, ctx);
27071 break;
27072 case OPC_MXU__POOL21:
27073 decode_opc_mxu__pool21(env, ctx);
27074 break;
27075 case OPC_MXU_Q16SCOP:
27076 /* TODO: Implement emulation of Q16SCOP instruction. */
27077 MIPS_INVAL("OPC_MXU_Q16SCOP");
27078 generate_exception_end(ctx, EXCP_RI);
27079 break;
27080 case OPC_MXU_Q8MADL:
27081 /* TODO: Implement emulation of Q8MADL instruction. */
27082 MIPS_INVAL("OPC_MXU_Q8MADL");
27083 generate_exception_end(ctx, EXCP_RI);
27084 break;
27085 case OPC_MXU_S32SFL:
27086 /* TODO: Implement emulation of S32SFL instruction. */
27087 MIPS_INVAL("OPC_MXU_S32SFL");
27088 generate_exception_end(ctx, EXCP_RI);
27089 break;
27090 case OPC_MXU_Q8SAD:
27091 /* TODO: Implement emulation of Q8SAD instruction. */
27092 MIPS_INVAL("OPC_MXU_Q8SAD");
27093 generate_exception_end(ctx, EXCP_RI);
27094 break;
27095 default:
27096 MIPS_INVAL("decode_opc_mxu");
27097 generate_exception_end(ctx, EXCP_RI);
27100 gen_set_label(l_exit);
27101 tcg_temp_free(t_mxu_cr);
27105 #endif /* !defined(TARGET_MIPS64) */
27108 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27110 int rs, rt, rd;
27111 uint32_t op1;
27113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27115 rs = (ctx->opcode >> 21) & 0x1f;
27116 rt = (ctx->opcode >> 16) & 0x1f;
27117 rd = (ctx->opcode >> 11) & 0x1f;
27119 op1 = MASK_SPECIAL2(ctx->opcode);
27120 switch (op1) {
27121 case OPC_MADD: /* Multiply and add/sub */
27122 case OPC_MADDU:
27123 case OPC_MSUB:
27124 case OPC_MSUBU:
27125 check_insn(ctx, ISA_MIPS32);
27126 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27127 break;
27128 case OPC_MUL:
27129 gen_arith(ctx, op1, rd, rs, rt);
27130 break;
27131 case OPC_DIV_G_2F:
27132 case OPC_DIVU_G_2F:
27133 case OPC_MULT_G_2F:
27134 case OPC_MULTU_G_2F:
27135 case OPC_MOD_G_2F:
27136 case OPC_MODU_G_2F:
27137 check_insn(ctx, INSN_LOONGSON2F);
27138 gen_loongson_integer(ctx, op1, rd, rs, rt);
27139 break;
27140 case OPC_CLO:
27141 case OPC_CLZ:
27142 check_insn(ctx, ISA_MIPS32);
27143 gen_cl(ctx, op1, rd, rs);
27144 break;
27145 case OPC_SDBBP:
27146 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27147 gen_helper_do_semihosting(cpu_env);
27148 } else {
27150 * XXX: not clear which exception should be raised
27151 * when in debug mode...
27153 check_insn(ctx, ISA_MIPS32);
27154 generate_exception_end(ctx, EXCP_DBp);
27156 break;
27157 #if defined(TARGET_MIPS64)
27158 case OPC_DCLO:
27159 case OPC_DCLZ:
27160 check_insn(ctx, ISA_MIPS64);
27161 check_mips_64(ctx);
27162 gen_cl(ctx, op1, rd, rs);
27163 break;
27164 case OPC_DMULT_G_2F:
27165 case OPC_DMULTU_G_2F:
27166 case OPC_DDIV_G_2F:
27167 case OPC_DDIVU_G_2F:
27168 case OPC_DMOD_G_2F:
27169 case OPC_DMODU_G_2F:
27170 check_insn(ctx, INSN_LOONGSON2F);
27171 gen_loongson_integer(ctx, op1, rd, rs, rt);
27172 break;
27173 #endif
27174 default: /* Invalid */
27175 MIPS_INVAL("special2_legacy");
27176 generate_exception_end(ctx, EXCP_RI);
27177 break;
27181 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27183 int rs, rt, rd, sa;
27184 uint32_t op1, op2;
27185 int16_t imm;
27187 rs = (ctx->opcode >> 21) & 0x1f;
27188 rt = (ctx->opcode >> 16) & 0x1f;
27189 rd = (ctx->opcode >> 11) & 0x1f;
27190 sa = (ctx->opcode >> 6) & 0x1f;
27191 imm = (int16_t)ctx->opcode >> 7;
27193 op1 = MASK_SPECIAL3(ctx->opcode);
27194 switch (op1) {
27195 case R6_OPC_PREF:
27196 if (rt >= 24) {
27197 /* hint codes 24-31 are reserved and signal RI */
27198 generate_exception_end(ctx, EXCP_RI);
27200 /* Treat as NOP. */
27201 break;
27202 case R6_OPC_CACHE:
27203 check_cp0_enabled(ctx);
27204 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27205 gen_cache_operation(ctx, rt, rs, imm);
27207 break;
27208 case R6_OPC_SC:
27209 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27210 break;
27211 case R6_OPC_LL:
27212 gen_ld(ctx, op1, rt, rs, imm);
27213 break;
27214 case OPC_BSHFL:
27216 if (rd == 0) {
27217 /* Treat as NOP. */
27218 break;
27220 op2 = MASK_BSHFL(ctx->opcode);
27221 switch (op2) {
27222 case OPC_ALIGN:
27223 case OPC_ALIGN_1:
27224 case OPC_ALIGN_2:
27225 case OPC_ALIGN_3:
27226 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27227 break;
27228 case OPC_BITSWAP:
27229 gen_bitswap(ctx, op2, rd, rt);
27230 break;
27233 break;
27234 #ifndef CONFIG_USER_ONLY
27235 case OPC_GINV:
27236 if (unlikely(ctx->gi <= 1)) {
27237 generate_exception_end(ctx, EXCP_RI);
27239 check_cp0_enabled(ctx);
27240 switch ((ctx->opcode >> 6) & 3) {
27241 case 0: /* GINVI */
27242 /* Treat as NOP. */
27243 break;
27244 case 2: /* GINVT */
27245 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27246 break;
27247 default:
27248 generate_exception_end(ctx, EXCP_RI);
27249 break;
27251 break;
27252 #endif
27253 #if defined(TARGET_MIPS64)
27254 case R6_OPC_SCD:
27255 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27256 break;
27257 case R6_OPC_LLD:
27258 gen_ld(ctx, op1, rt, rs, imm);
27259 break;
27260 case OPC_DBSHFL:
27261 check_mips_64(ctx);
27263 if (rd == 0) {
27264 /* Treat as NOP. */
27265 break;
27267 op2 = MASK_DBSHFL(ctx->opcode);
27268 switch (op2) {
27269 case OPC_DALIGN:
27270 case OPC_DALIGN_1:
27271 case OPC_DALIGN_2:
27272 case OPC_DALIGN_3:
27273 case OPC_DALIGN_4:
27274 case OPC_DALIGN_5:
27275 case OPC_DALIGN_6:
27276 case OPC_DALIGN_7:
27277 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27278 break;
27279 case OPC_DBITSWAP:
27280 gen_bitswap(ctx, op2, rd, rt);
27281 break;
27285 break;
27286 #endif
27287 default: /* Invalid */
27288 MIPS_INVAL("special3_r6");
27289 generate_exception_end(ctx, EXCP_RI);
27290 break;
27294 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27296 int rs, rt, rd;
27297 uint32_t op1, op2;
27299 rs = (ctx->opcode >> 21) & 0x1f;
27300 rt = (ctx->opcode >> 16) & 0x1f;
27301 rd = (ctx->opcode >> 11) & 0x1f;
27303 op1 = MASK_SPECIAL3(ctx->opcode);
27304 switch (op1) {
27305 case OPC_DIV_G_2E:
27306 case OPC_DIVU_G_2E:
27307 case OPC_MOD_G_2E:
27308 case OPC_MODU_G_2E:
27309 case OPC_MULT_G_2E:
27310 case OPC_MULTU_G_2E:
27312 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27313 * the same mask and op1.
27315 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27316 op2 = MASK_ADDUH_QB(ctx->opcode);
27317 switch (op2) {
27318 case OPC_ADDUH_QB:
27319 case OPC_ADDUH_R_QB:
27320 case OPC_ADDQH_PH:
27321 case OPC_ADDQH_R_PH:
27322 case OPC_ADDQH_W:
27323 case OPC_ADDQH_R_W:
27324 case OPC_SUBUH_QB:
27325 case OPC_SUBUH_R_QB:
27326 case OPC_SUBQH_PH:
27327 case OPC_SUBQH_R_PH:
27328 case OPC_SUBQH_W:
27329 case OPC_SUBQH_R_W:
27330 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27331 break;
27332 case OPC_MUL_PH:
27333 case OPC_MUL_S_PH:
27334 case OPC_MULQ_S_W:
27335 case OPC_MULQ_RS_W:
27336 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27337 break;
27338 default:
27339 MIPS_INVAL("MASK ADDUH.QB");
27340 generate_exception_end(ctx, EXCP_RI);
27341 break;
27343 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27344 gen_loongson_integer(ctx, op1, rd, rs, rt);
27345 } else {
27346 generate_exception_end(ctx, EXCP_RI);
27348 break;
27349 case OPC_LX_DSP:
27350 op2 = MASK_LX(ctx->opcode);
27351 switch (op2) {
27352 #if defined(TARGET_MIPS64)
27353 case OPC_LDX:
27354 #endif
27355 case OPC_LBUX:
27356 case OPC_LHX:
27357 case OPC_LWX:
27358 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27359 break;
27360 default: /* Invalid */
27361 MIPS_INVAL("MASK LX");
27362 generate_exception_end(ctx, EXCP_RI);
27363 break;
27365 break;
27366 case OPC_ABSQ_S_PH_DSP:
27367 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27368 switch (op2) {
27369 case OPC_ABSQ_S_QB:
27370 case OPC_ABSQ_S_PH:
27371 case OPC_ABSQ_S_W:
27372 case OPC_PRECEQ_W_PHL:
27373 case OPC_PRECEQ_W_PHR:
27374 case OPC_PRECEQU_PH_QBL:
27375 case OPC_PRECEQU_PH_QBR:
27376 case OPC_PRECEQU_PH_QBLA:
27377 case OPC_PRECEQU_PH_QBRA:
27378 case OPC_PRECEU_PH_QBL:
27379 case OPC_PRECEU_PH_QBR:
27380 case OPC_PRECEU_PH_QBLA:
27381 case OPC_PRECEU_PH_QBRA:
27382 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27383 break;
27384 case OPC_BITREV:
27385 case OPC_REPL_QB:
27386 case OPC_REPLV_QB:
27387 case OPC_REPL_PH:
27388 case OPC_REPLV_PH:
27389 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27390 break;
27391 default:
27392 MIPS_INVAL("MASK ABSQ_S.PH");
27393 generate_exception_end(ctx, EXCP_RI);
27394 break;
27396 break;
27397 case OPC_ADDU_QB_DSP:
27398 op2 = MASK_ADDU_QB(ctx->opcode);
27399 switch (op2) {
27400 case OPC_ADDQ_PH:
27401 case OPC_ADDQ_S_PH:
27402 case OPC_ADDQ_S_W:
27403 case OPC_ADDU_QB:
27404 case OPC_ADDU_S_QB:
27405 case OPC_ADDU_PH:
27406 case OPC_ADDU_S_PH:
27407 case OPC_SUBQ_PH:
27408 case OPC_SUBQ_S_PH:
27409 case OPC_SUBQ_S_W:
27410 case OPC_SUBU_QB:
27411 case OPC_SUBU_S_QB:
27412 case OPC_SUBU_PH:
27413 case OPC_SUBU_S_PH:
27414 case OPC_ADDSC:
27415 case OPC_ADDWC:
27416 case OPC_MODSUB:
27417 case OPC_RADDU_W_QB:
27418 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27419 break;
27420 case OPC_MULEU_S_PH_QBL:
27421 case OPC_MULEU_S_PH_QBR:
27422 case OPC_MULQ_RS_PH:
27423 case OPC_MULEQ_S_W_PHL:
27424 case OPC_MULEQ_S_W_PHR:
27425 case OPC_MULQ_S_PH:
27426 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27427 break;
27428 default: /* Invalid */
27429 MIPS_INVAL("MASK ADDU.QB");
27430 generate_exception_end(ctx, EXCP_RI);
27431 break;
27434 break;
27435 case OPC_CMPU_EQ_QB_DSP:
27436 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27437 switch (op2) {
27438 case OPC_PRECR_SRA_PH_W:
27439 case OPC_PRECR_SRA_R_PH_W:
27440 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27441 break;
27442 case OPC_PRECR_QB_PH:
27443 case OPC_PRECRQ_QB_PH:
27444 case OPC_PRECRQ_PH_W:
27445 case OPC_PRECRQ_RS_PH_W:
27446 case OPC_PRECRQU_S_QB_PH:
27447 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27448 break;
27449 case OPC_CMPU_EQ_QB:
27450 case OPC_CMPU_LT_QB:
27451 case OPC_CMPU_LE_QB:
27452 case OPC_CMP_EQ_PH:
27453 case OPC_CMP_LT_PH:
27454 case OPC_CMP_LE_PH:
27455 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27456 break;
27457 case OPC_CMPGU_EQ_QB:
27458 case OPC_CMPGU_LT_QB:
27459 case OPC_CMPGU_LE_QB:
27460 case OPC_CMPGDU_EQ_QB:
27461 case OPC_CMPGDU_LT_QB:
27462 case OPC_CMPGDU_LE_QB:
27463 case OPC_PICK_QB:
27464 case OPC_PICK_PH:
27465 case OPC_PACKRL_PH:
27466 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27467 break;
27468 default: /* Invalid */
27469 MIPS_INVAL("MASK CMPU.EQ.QB");
27470 generate_exception_end(ctx, EXCP_RI);
27471 break;
27473 break;
27474 case OPC_SHLL_QB_DSP:
27475 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27476 break;
27477 case OPC_DPA_W_PH_DSP:
27478 op2 = MASK_DPA_W_PH(ctx->opcode);
27479 switch (op2) {
27480 case OPC_DPAU_H_QBL:
27481 case OPC_DPAU_H_QBR:
27482 case OPC_DPSU_H_QBL:
27483 case OPC_DPSU_H_QBR:
27484 case OPC_DPA_W_PH:
27485 case OPC_DPAX_W_PH:
27486 case OPC_DPAQ_S_W_PH:
27487 case OPC_DPAQX_S_W_PH:
27488 case OPC_DPAQX_SA_W_PH:
27489 case OPC_DPS_W_PH:
27490 case OPC_DPSX_W_PH:
27491 case OPC_DPSQ_S_W_PH:
27492 case OPC_DPSQX_S_W_PH:
27493 case OPC_DPSQX_SA_W_PH:
27494 case OPC_MULSAQ_S_W_PH:
27495 case OPC_DPAQ_SA_L_W:
27496 case OPC_DPSQ_SA_L_W:
27497 case OPC_MAQ_S_W_PHL:
27498 case OPC_MAQ_S_W_PHR:
27499 case OPC_MAQ_SA_W_PHL:
27500 case OPC_MAQ_SA_W_PHR:
27501 case OPC_MULSA_W_PH:
27502 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27503 break;
27504 default: /* Invalid */
27505 MIPS_INVAL("MASK DPAW.PH");
27506 generate_exception_end(ctx, EXCP_RI);
27507 break;
27509 break;
27510 case OPC_INSV_DSP:
27511 op2 = MASK_INSV(ctx->opcode);
27512 switch (op2) {
27513 case OPC_INSV:
27514 check_dsp(ctx);
27516 TCGv t0, t1;
27518 if (rt == 0) {
27519 break;
27522 t0 = tcg_temp_new();
27523 t1 = tcg_temp_new();
27525 gen_load_gpr(t0, rt);
27526 gen_load_gpr(t1, rs);
27528 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27530 tcg_temp_free(t0);
27531 tcg_temp_free(t1);
27532 break;
27534 default: /* Invalid */
27535 MIPS_INVAL("MASK INSV");
27536 generate_exception_end(ctx, EXCP_RI);
27537 break;
27539 break;
27540 case OPC_APPEND_DSP:
27541 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27542 break;
27543 case OPC_EXTR_W_DSP:
27544 op2 = MASK_EXTR_W(ctx->opcode);
27545 switch (op2) {
27546 case OPC_EXTR_W:
27547 case OPC_EXTR_R_W:
27548 case OPC_EXTR_RS_W:
27549 case OPC_EXTR_S_H:
27550 case OPC_EXTRV_S_H:
27551 case OPC_EXTRV_W:
27552 case OPC_EXTRV_R_W:
27553 case OPC_EXTRV_RS_W:
27554 case OPC_EXTP:
27555 case OPC_EXTPV:
27556 case OPC_EXTPDP:
27557 case OPC_EXTPDPV:
27558 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27559 break;
27560 case OPC_RDDSP:
27561 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27562 break;
27563 case OPC_SHILO:
27564 case OPC_SHILOV:
27565 case OPC_MTHLIP:
27566 case OPC_WRDSP:
27567 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27568 break;
27569 default: /* Invalid */
27570 MIPS_INVAL("MASK EXTR.W");
27571 generate_exception_end(ctx, EXCP_RI);
27572 break;
27574 break;
27575 #if defined(TARGET_MIPS64)
27576 case OPC_DDIV_G_2E:
27577 case OPC_DDIVU_G_2E:
27578 case OPC_DMULT_G_2E:
27579 case OPC_DMULTU_G_2E:
27580 case OPC_DMOD_G_2E:
27581 case OPC_DMODU_G_2E:
27582 check_insn(ctx, INSN_LOONGSON2E);
27583 gen_loongson_integer(ctx, op1, rd, rs, rt);
27584 break;
27585 case OPC_ABSQ_S_QH_DSP:
27586 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27587 switch (op2) {
27588 case OPC_PRECEQ_L_PWL:
27589 case OPC_PRECEQ_L_PWR:
27590 case OPC_PRECEQ_PW_QHL:
27591 case OPC_PRECEQ_PW_QHR:
27592 case OPC_PRECEQ_PW_QHLA:
27593 case OPC_PRECEQ_PW_QHRA:
27594 case OPC_PRECEQU_QH_OBL:
27595 case OPC_PRECEQU_QH_OBR:
27596 case OPC_PRECEQU_QH_OBLA:
27597 case OPC_PRECEQU_QH_OBRA:
27598 case OPC_PRECEU_QH_OBL:
27599 case OPC_PRECEU_QH_OBR:
27600 case OPC_PRECEU_QH_OBLA:
27601 case OPC_PRECEU_QH_OBRA:
27602 case OPC_ABSQ_S_OB:
27603 case OPC_ABSQ_S_PW:
27604 case OPC_ABSQ_S_QH:
27605 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27606 break;
27607 case OPC_REPL_OB:
27608 case OPC_REPL_PW:
27609 case OPC_REPL_QH:
27610 case OPC_REPLV_OB:
27611 case OPC_REPLV_PW:
27612 case OPC_REPLV_QH:
27613 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27614 break;
27615 default: /* Invalid */
27616 MIPS_INVAL("MASK ABSQ_S.QH");
27617 generate_exception_end(ctx, EXCP_RI);
27618 break;
27620 break;
27621 case OPC_ADDU_OB_DSP:
27622 op2 = MASK_ADDU_OB(ctx->opcode);
27623 switch (op2) {
27624 case OPC_RADDU_L_OB:
27625 case OPC_SUBQ_PW:
27626 case OPC_SUBQ_S_PW:
27627 case OPC_SUBQ_QH:
27628 case OPC_SUBQ_S_QH:
27629 case OPC_SUBU_OB:
27630 case OPC_SUBU_S_OB:
27631 case OPC_SUBU_QH:
27632 case OPC_SUBU_S_QH:
27633 case OPC_SUBUH_OB:
27634 case OPC_SUBUH_R_OB:
27635 case OPC_ADDQ_PW:
27636 case OPC_ADDQ_S_PW:
27637 case OPC_ADDQ_QH:
27638 case OPC_ADDQ_S_QH:
27639 case OPC_ADDU_OB:
27640 case OPC_ADDU_S_OB:
27641 case OPC_ADDU_QH:
27642 case OPC_ADDU_S_QH:
27643 case OPC_ADDUH_OB:
27644 case OPC_ADDUH_R_OB:
27645 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27646 break;
27647 case OPC_MULEQ_S_PW_QHL:
27648 case OPC_MULEQ_S_PW_QHR:
27649 case OPC_MULEU_S_QH_OBL:
27650 case OPC_MULEU_S_QH_OBR:
27651 case OPC_MULQ_RS_QH:
27652 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27653 break;
27654 default: /* Invalid */
27655 MIPS_INVAL("MASK ADDU.OB");
27656 generate_exception_end(ctx, EXCP_RI);
27657 break;
27659 break;
27660 case OPC_CMPU_EQ_OB_DSP:
27661 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27662 switch (op2) {
27663 case OPC_PRECR_SRA_QH_PW:
27664 case OPC_PRECR_SRA_R_QH_PW:
27665 /* Return value is rt. */
27666 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27667 break;
27668 case OPC_PRECR_OB_QH:
27669 case OPC_PRECRQ_OB_QH:
27670 case OPC_PRECRQ_PW_L:
27671 case OPC_PRECRQ_QH_PW:
27672 case OPC_PRECRQ_RS_QH_PW:
27673 case OPC_PRECRQU_S_OB_QH:
27674 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27675 break;
27676 case OPC_CMPU_EQ_OB:
27677 case OPC_CMPU_LT_OB:
27678 case OPC_CMPU_LE_OB:
27679 case OPC_CMP_EQ_QH:
27680 case OPC_CMP_LT_QH:
27681 case OPC_CMP_LE_QH:
27682 case OPC_CMP_EQ_PW:
27683 case OPC_CMP_LT_PW:
27684 case OPC_CMP_LE_PW:
27685 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27686 break;
27687 case OPC_CMPGDU_EQ_OB:
27688 case OPC_CMPGDU_LT_OB:
27689 case OPC_CMPGDU_LE_OB:
27690 case OPC_CMPGU_EQ_OB:
27691 case OPC_CMPGU_LT_OB:
27692 case OPC_CMPGU_LE_OB:
27693 case OPC_PACKRL_PW:
27694 case OPC_PICK_OB:
27695 case OPC_PICK_PW:
27696 case OPC_PICK_QH:
27697 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27698 break;
27699 default: /* Invalid */
27700 MIPS_INVAL("MASK CMPU_EQ.OB");
27701 generate_exception_end(ctx, EXCP_RI);
27702 break;
27704 break;
27705 case OPC_DAPPEND_DSP:
27706 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27707 break;
27708 case OPC_DEXTR_W_DSP:
27709 op2 = MASK_DEXTR_W(ctx->opcode);
27710 switch (op2) {
27711 case OPC_DEXTP:
27712 case OPC_DEXTPDP:
27713 case OPC_DEXTPDPV:
27714 case OPC_DEXTPV:
27715 case OPC_DEXTR_L:
27716 case OPC_DEXTR_R_L:
27717 case OPC_DEXTR_RS_L:
27718 case OPC_DEXTR_W:
27719 case OPC_DEXTR_R_W:
27720 case OPC_DEXTR_RS_W:
27721 case OPC_DEXTR_S_H:
27722 case OPC_DEXTRV_L:
27723 case OPC_DEXTRV_R_L:
27724 case OPC_DEXTRV_RS_L:
27725 case OPC_DEXTRV_S_H:
27726 case OPC_DEXTRV_W:
27727 case OPC_DEXTRV_R_W:
27728 case OPC_DEXTRV_RS_W:
27729 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27730 break;
27731 case OPC_DMTHLIP:
27732 case OPC_DSHILO:
27733 case OPC_DSHILOV:
27734 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27735 break;
27736 default: /* Invalid */
27737 MIPS_INVAL("MASK EXTR.W");
27738 generate_exception_end(ctx, EXCP_RI);
27739 break;
27741 break;
27742 case OPC_DPAQ_W_QH_DSP:
27743 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27744 switch (op2) {
27745 case OPC_DPAU_H_OBL:
27746 case OPC_DPAU_H_OBR:
27747 case OPC_DPSU_H_OBL:
27748 case OPC_DPSU_H_OBR:
27749 case OPC_DPA_W_QH:
27750 case OPC_DPAQ_S_W_QH:
27751 case OPC_DPS_W_QH:
27752 case OPC_DPSQ_S_W_QH:
27753 case OPC_MULSAQ_S_W_QH:
27754 case OPC_DPAQ_SA_L_PW:
27755 case OPC_DPSQ_SA_L_PW:
27756 case OPC_MULSAQ_S_L_PW:
27757 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27758 break;
27759 case OPC_MAQ_S_W_QHLL:
27760 case OPC_MAQ_S_W_QHLR:
27761 case OPC_MAQ_S_W_QHRL:
27762 case OPC_MAQ_S_W_QHRR:
27763 case OPC_MAQ_SA_W_QHLL:
27764 case OPC_MAQ_SA_W_QHLR:
27765 case OPC_MAQ_SA_W_QHRL:
27766 case OPC_MAQ_SA_W_QHRR:
27767 case OPC_MAQ_S_L_PWL:
27768 case OPC_MAQ_S_L_PWR:
27769 case OPC_DMADD:
27770 case OPC_DMADDU:
27771 case OPC_DMSUB:
27772 case OPC_DMSUBU:
27773 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27774 break;
27775 default: /* Invalid */
27776 MIPS_INVAL("MASK DPAQ.W.QH");
27777 generate_exception_end(ctx, EXCP_RI);
27778 break;
27780 break;
27781 case OPC_DINSV_DSP:
27782 op2 = MASK_INSV(ctx->opcode);
27783 switch (op2) {
27784 case OPC_DINSV:
27786 TCGv t0, t1;
27788 if (rt == 0) {
27789 break;
27791 check_dsp(ctx);
27793 t0 = tcg_temp_new();
27794 t1 = tcg_temp_new();
27796 gen_load_gpr(t0, rt);
27797 gen_load_gpr(t1, rs);
27799 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27801 tcg_temp_free(t0);
27802 tcg_temp_free(t1);
27803 break;
27805 default: /* Invalid */
27806 MIPS_INVAL("MASK DINSV");
27807 generate_exception_end(ctx, EXCP_RI);
27808 break;
27810 break;
27811 case OPC_SHLL_OB_DSP:
27812 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27813 break;
27814 #endif
27815 default: /* Invalid */
27816 MIPS_INVAL("special3_legacy");
27817 generate_exception_end(ctx, EXCP_RI);
27818 break;
27823 #if defined(TARGET_MIPS64)
27825 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27827 uint32_t opc = MASK_MMI0(ctx->opcode);
27829 switch (opc) {
27830 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27831 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27832 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27833 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27834 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27835 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27836 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27837 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27838 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27839 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27840 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27841 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27842 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27843 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27844 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27845 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27846 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27847 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27848 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27849 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27850 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27851 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27852 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27853 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27854 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27855 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27856 break;
27857 default:
27858 MIPS_INVAL("TX79 MMI class MMI0");
27859 generate_exception_end(ctx, EXCP_RI);
27860 break;
27864 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27866 uint32_t opc = MASK_MMI1(ctx->opcode);
27868 switch (opc) {
27869 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27870 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27871 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27872 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27873 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27874 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27875 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27876 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27877 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27878 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27879 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27880 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27881 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27882 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27883 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27884 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27885 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27886 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27887 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27888 break;
27889 default:
27890 MIPS_INVAL("TX79 MMI class MMI1");
27891 generate_exception_end(ctx, EXCP_RI);
27892 break;
27896 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27898 uint32_t opc = MASK_MMI2(ctx->opcode);
27900 switch (opc) {
27901 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27902 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27903 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27904 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27905 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27906 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27907 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27908 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27909 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27910 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27911 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27912 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27913 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27914 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27915 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27916 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27917 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27918 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27919 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27920 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27921 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27922 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27923 break;
27924 case MMI_OPC_2_PCPYLD:
27925 gen_mmi_pcpyld(ctx);
27926 break;
27927 default:
27928 MIPS_INVAL("TX79 MMI class MMI2");
27929 generate_exception_end(ctx, EXCP_RI);
27930 break;
27934 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27936 uint32_t opc = MASK_MMI3(ctx->opcode);
27938 switch (opc) {
27939 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27940 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27941 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27942 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27943 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27944 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27945 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27946 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27947 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27948 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27949 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27950 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27951 break;
27952 case MMI_OPC_3_PCPYH:
27953 gen_mmi_pcpyh(ctx);
27954 break;
27955 case MMI_OPC_3_PCPYUD:
27956 gen_mmi_pcpyud(ctx);
27957 break;
27958 default:
27959 MIPS_INVAL("TX79 MMI class MMI3");
27960 generate_exception_end(ctx, EXCP_RI);
27961 break;
27965 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27967 uint32_t opc = MASK_MMI(ctx->opcode);
27968 int rs = extract32(ctx->opcode, 21, 5);
27969 int rt = extract32(ctx->opcode, 16, 5);
27970 int rd = extract32(ctx->opcode, 11, 5);
27972 switch (opc) {
27973 case MMI_OPC_CLASS_MMI0:
27974 decode_mmi0(env, ctx);
27975 break;
27976 case MMI_OPC_CLASS_MMI1:
27977 decode_mmi1(env, ctx);
27978 break;
27979 case MMI_OPC_CLASS_MMI2:
27980 decode_mmi2(env, ctx);
27981 break;
27982 case MMI_OPC_CLASS_MMI3:
27983 decode_mmi3(env, ctx);
27984 break;
27985 case MMI_OPC_MULT1:
27986 case MMI_OPC_MULTU1:
27987 case MMI_OPC_MADD:
27988 case MMI_OPC_MADDU:
27989 case MMI_OPC_MADD1:
27990 case MMI_OPC_MADDU1:
27991 gen_mul_txx9(ctx, opc, rd, rs, rt);
27992 break;
27993 case MMI_OPC_DIV1:
27994 case MMI_OPC_DIVU1:
27995 gen_div1_tx79(ctx, opc, rs, rt);
27996 break;
27997 case MMI_OPC_MTLO1:
27998 case MMI_OPC_MTHI1:
27999 gen_HILO1_tx79(ctx, opc, rs);
28000 break;
28001 case MMI_OPC_MFLO1:
28002 case MMI_OPC_MFHI1:
28003 gen_HILO1_tx79(ctx, opc, rd);
28004 break;
28005 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28006 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28007 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28008 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28009 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28010 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28011 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28012 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28013 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28014 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
28015 break;
28016 default:
28017 MIPS_INVAL("TX79 MMI class");
28018 generate_exception_end(ctx, EXCP_RI);
28019 break;
28023 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28025 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
28028 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28030 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
28034 * The TX79-specific instruction Store Quadword
28036 * +--------+-------+-------+------------------------+
28037 * | 011111 | base | rt | offset | SQ
28038 * +--------+-------+-------+------------------------+
28039 * 6 5 5 16
28041 * has the same opcode as the Read Hardware Register instruction
28043 * +--------+-------+-------+-------+-------+--------+
28044 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28045 * +--------+-------+-------+-------+-------+--------+
28046 * 6 5 5 5 5 6
28048 * that is required, trapped and emulated by the Linux kernel. However, all
28049 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28050 * offset is odd. Therefore all valid SQ instructions can execute normally.
28051 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28052 * between SQ and RDHWR, as the Linux kernel does.
28054 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28056 int base = extract32(ctx->opcode, 21, 5);
28057 int rt = extract32(ctx->opcode, 16, 5);
28058 int offset = extract32(ctx->opcode, 0, 16);
28060 #ifdef CONFIG_USER_ONLY
28061 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28062 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28064 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28065 int rd = extract32(ctx->opcode, 11, 5);
28067 gen_rdhwr(ctx, rt, rd, 0);
28068 return;
28070 #endif
28072 gen_mmi_sq(ctx, base, rt, offset);
28075 #endif
28077 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28079 int rs, rt, rd, sa;
28080 uint32_t op1, op2;
28081 int16_t imm;
28083 rs = (ctx->opcode >> 21) & 0x1f;
28084 rt = (ctx->opcode >> 16) & 0x1f;
28085 rd = (ctx->opcode >> 11) & 0x1f;
28086 sa = (ctx->opcode >> 6) & 0x1f;
28087 imm = sextract32(ctx->opcode, 7, 9);
28089 op1 = MASK_SPECIAL3(ctx->opcode);
28092 * EVA loads and stores overlap Loongson 2E instructions decoded by
28093 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28094 * EVA is absent.
28096 if (ctx->eva) {
28097 switch (op1) {
28098 case OPC_LWLE:
28099 case OPC_LWRE:
28100 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28101 /* fall through */
28102 case OPC_LBUE:
28103 case OPC_LHUE:
28104 case OPC_LBE:
28105 case OPC_LHE:
28106 case OPC_LLE:
28107 case OPC_LWE:
28108 check_cp0_enabled(ctx);
28109 gen_ld(ctx, op1, rt, rs, imm);
28110 return;
28111 case OPC_SWLE:
28112 case OPC_SWRE:
28113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28114 /* fall through */
28115 case OPC_SBE:
28116 case OPC_SHE:
28117 case OPC_SWE:
28118 check_cp0_enabled(ctx);
28119 gen_st(ctx, op1, rt, rs, imm);
28120 return;
28121 case OPC_SCE:
28122 check_cp0_enabled(ctx);
28123 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28124 return;
28125 case OPC_CACHEE:
28126 check_cp0_enabled(ctx);
28127 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28128 gen_cache_operation(ctx, rt, rs, imm);
28130 /* Treat as NOP. */
28131 return;
28132 case OPC_PREFE:
28133 check_cp0_enabled(ctx);
28134 /* Treat as NOP. */
28135 return;
28139 switch (op1) {
28140 case OPC_EXT:
28141 case OPC_INS:
28142 check_insn(ctx, ISA_MIPS32R2);
28143 gen_bitops(ctx, op1, rt, rs, sa, rd);
28144 break;
28145 case OPC_BSHFL:
28146 op2 = MASK_BSHFL(ctx->opcode);
28147 switch (op2) {
28148 case OPC_ALIGN:
28149 case OPC_ALIGN_1:
28150 case OPC_ALIGN_2:
28151 case OPC_ALIGN_3:
28152 case OPC_BITSWAP:
28153 check_insn(ctx, ISA_MIPS32R6);
28154 decode_opc_special3_r6(env, ctx);
28155 break;
28156 default:
28157 check_insn(ctx, ISA_MIPS32R2);
28158 gen_bshfl(ctx, op2, rt, rd);
28159 break;
28161 break;
28162 #if defined(TARGET_MIPS64)
28163 case OPC_DEXTM:
28164 case OPC_DEXTU:
28165 case OPC_DEXT:
28166 case OPC_DINSM:
28167 case OPC_DINSU:
28168 case OPC_DINS:
28169 check_insn(ctx, ISA_MIPS64R2);
28170 check_mips_64(ctx);
28171 gen_bitops(ctx, op1, rt, rs, sa, rd);
28172 break;
28173 case OPC_DBSHFL:
28174 op2 = MASK_DBSHFL(ctx->opcode);
28175 switch (op2) {
28176 case OPC_DALIGN:
28177 case OPC_DALIGN_1:
28178 case OPC_DALIGN_2:
28179 case OPC_DALIGN_3:
28180 case OPC_DALIGN_4:
28181 case OPC_DALIGN_5:
28182 case OPC_DALIGN_6:
28183 case OPC_DALIGN_7:
28184 case OPC_DBITSWAP:
28185 check_insn(ctx, ISA_MIPS32R6);
28186 decode_opc_special3_r6(env, ctx);
28187 break;
28188 default:
28189 check_insn(ctx, ISA_MIPS64R2);
28190 check_mips_64(ctx);
28191 op2 = MASK_DBSHFL(ctx->opcode);
28192 gen_bshfl(ctx, op2, rt, rd);
28193 break;
28195 break;
28196 #endif
28197 case OPC_RDHWR:
28198 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28199 break;
28200 case OPC_FORK:
28201 check_mt(ctx);
28203 TCGv t0 = tcg_temp_new();
28204 TCGv t1 = tcg_temp_new();
28206 gen_load_gpr(t0, rt);
28207 gen_load_gpr(t1, rs);
28208 gen_helper_fork(t0, t1);
28209 tcg_temp_free(t0);
28210 tcg_temp_free(t1);
28212 break;
28213 case OPC_YIELD:
28214 check_mt(ctx);
28216 TCGv t0 = tcg_temp_new();
28218 gen_load_gpr(t0, rs);
28219 gen_helper_yield(t0, cpu_env, t0);
28220 gen_store_gpr(t0, rd);
28221 tcg_temp_free(t0);
28223 break;
28224 default:
28225 if (ctx->insn_flags & ISA_MIPS32R6) {
28226 decode_opc_special3_r6(env, ctx);
28227 } else {
28228 decode_opc_special3_legacy(env, ctx);
28233 /* MIPS SIMD Architecture (MSA) */
28234 static inline int check_msa_access(DisasContext *ctx)
28236 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28237 !(ctx->hflags & MIPS_HFLAG_F64))) {
28238 generate_exception_end(ctx, EXCP_RI);
28239 return 0;
28242 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28243 if (ctx->insn_flags & ASE_MSA) {
28244 generate_exception_end(ctx, EXCP_MSADIS);
28245 return 0;
28246 } else {
28247 generate_exception_end(ctx, EXCP_RI);
28248 return 0;
28251 return 1;
28254 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28256 /* generates tcg ops to check if any element is 0 */
28257 /* Note this function only works with MSA_WRLEN = 128 */
28258 uint64_t eval_zero_or_big = 0;
28259 uint64_t eval_big = 0;
28260 TCGv_i64 t0 = tcg_temp_new_i64();
28261 TCGv_i64 t1 = tcg_temp_new_i64();
28262 switch (df) {
28263 case DF_BYTE:
28264 eval_zero_or_big = 0x0101010101010101ULL;
28265 eval_big = 0x8080808080808080ULL;
28266 break;
28267 case DF_HALF:
28268 eval_zero_or_big = 0x0001000100010001ULL;
28269 eval_big = 0x8000800080008000ULL;
28270 break;
28271 case DF_WORD:
28272 eval_zero_or_big = 0x0000000100000001ULL;
28273 eval_big = 0x8000000080000000ULL;
28274 break;
28275 case DF_DOUBLE:
28276 eval_zero_or_big = 0x0000000000000001ULL;
28277 eval_big = 0x8000000000000000ULL;
28278 break;
28280 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28281 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28282 tcg_gen_andi_i64(t0, t0, eval_big);
28283 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28284 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28285 tcg_gen_andi_i64(t1, t1, eval_big);
28286 tcg_gen_or_i64(t0, t0, t1);
28287 /* if all bits are zero then all elements are not zero */
28288 /* if some bit is non-zero then some element is zero */
28289 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28290 tcg_gen_trunc_i64_tl(tresult, t0);
28291 tcg_temp_free_i64(t0);
28292 tcg_temp_free_i64(t1);
28295 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28297 uint8_t df = (ctx->opcode >> 21) & 0x3;
28298 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28299 int64_t s16 = (int16_t)ctx->opcode;
28301 check_msa_access(ctx);
28303 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28304 generate_exception_end(ctx, EXCP_RI);
28305 return;
28307 switch (op1) {
28308 case OPC_BZ_V:
28309 case OPC_BNZ_V:
28311 TCGv_i64 t0 = tcg_temp_new_i64();
28312 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28313 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28314 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28315 tcg_gen_trunc_i64_tl(bcond, t0);
28316 tcg_temp_free_i64(t0);
28318 break;
28319 case OPC_BZ_B:
28320 case OPC_BZ_H:
28321 case OPC_BZ_W:
28322 case OPC_BZ_D:
28323 gen_check_zero_element(bcond, df, wt);
28324 break;
28325 case OPC_BNZ_B:
28326 case OPC_BNZ_H:
28327 case OPC_BNZ_W:
28328 case OPC_BNZ_D:
28329 gen_check_zero_element(bcond, df, wt);
28330 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28331 break;
28334 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28336 ctx->hflags |= MIPS_HFLAG_BC;
28337 ctx->hflags |= MIPS_HFLAG_BDS32;
28340 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28342 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28343 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28344 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28345 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28347 TCGv_i32 twd = tcg_const_i32(wd);
28348 TCGv_i32 tws = tcg_const_i32(ws);
28349 TCGv_i32 ti8 = tcg_const_i32(i8);
28351 switch (MASK_MSA_I8(ctx->opcode)) {
28352 case OPC_ANDI_B:
28353 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28354 break;
28355 case OPC_ORI_B:
28356 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28357 break;
28358 case OPC_NORI_B:
28359 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28360 break;
28361 case OPC_XORI_B:
28362 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28363 break;
28364 case OPC_BMNZI_B:
28365 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28366 break;
28367 case OPC_BMZI_B:
28368 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28369 break;
28370 case OPC_BSELI_B:
28371 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28372 break;
28373 case OPC_SHF_B:
28374 case OPC_SHF_H:
28375 case OPC_SHF_W:
28377 uint8_t df = (ctx->opcode >> 24) & 0x3;
28378 if (df == DF_DOUBLE) {
28379 generate_exception_end(ctx, EXCP_RI);
28380 } else {
28381 TCGv_i32 tdf = tcg_const_i32(df);
28382 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28383 tcg_temp_free_i32(tdf);
28386 break;
28387 default:
28388 MIPS_INVAL("MSA instruction");
28389 generate_exception_end(ctx, EXCP_RI);
28390 break;
28393 tcg_temp_free_i32(twd);
28394 tcg_temp_free_i32(tws);
28395 tcg_temp_free_i32(ti8);
28398 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28400 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28401 uint8_t df = (ctx->opcode >> 21) & 0x3;
28402 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28403 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28404 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28405 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28407 TCGv_i32 tdf = tcg_const_i32(df);
28408 TCGv_i32 twd = tcg_const_i32(wd);
28409 TCGv_i32 tws = tcg_const_i32(ws);
28410 TCGv_i32 timm = tcg_temp_new_i32();
28411 tcg_gen_movi_i32(timm, u5);
28413 switch (MASK_MSA_I5(ctx->opcode)) {
28414 case OPC_ADDVI_df:
28415 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28416 break;
28417 case OPC_SUBVI_df:
28418 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28419 break;
28420 case OPC_MAXI_S_df:
28421 tcg_gen_movi_i32(timm, s5);
28422 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28423 break;
28424 case OPC_MAXI_U_df:
28425 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28426 break;
28427 case OPC_MINI_S_df:
28428 tcg_gen_movi_i32(timm, s5);
28429 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28430 break;
28431 case OPC_MINI_U_df:
28432 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28433 break;
28434 case OPC_CEQI_df:
28435 tcg_gen_movi_i32(timm, s5);
28436 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28437 break;
28438 case OPC_CLTI_S_df:
28439 tcg_gen_movi_i32(timm, s5);
28440 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28441 break;
28442 case OPC_CLTI_U_df:
28443 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28444 break;
28445 case OPC_CLEI_S_df:
28446 tcg_gen_movi_i32(timm, s5);
28447 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28448 break;
28449 case OPC_CLEI_U_df:
28450 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28451 break;
28452 case OPC_LDI_df:
28454 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28455 tcg_gen_movi_i32(timm, s10);
28456 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28458 break;
28459 default:
28460 MIPS_INVAL("MSA instruction");
28461 generate_exception_end(ctx, EXCP_RI);
28462 break;
28465 tcg_temp_free_i32(tdf);
28466 tcg_temp_free_i32(twd);
28467 tcg_temp_free_i32(tws);
28468 tcg_temp_free_i32(timm);
28471 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28473 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28474 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28475 uint32_t df = 0, m = 0;
28476 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28477 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28479 TCGv_i32 tdf;
28480 TCGv_i32 tm;
28481 TCGv_i32 twd;
28482 TCGv_i32 tws;
28484 if ((dfm & 0x40) == 0x00) {
28485 m = dfm & 0x3f;
28486 df = DF_DOUBLE;
28487 } else if ((dfm & 0x60) == 0x40) {
28488 m = dfm & 0x1f;
28489 df = DF_WORD;
28490 } else if ((dfm & 0x70) == 0x60) {
28491 m = dfm & 0x0f;
28492 df = DF_HALF;
28493 } else if ((dfm & 0x78) == 0x70) {
28494 m = dfm & 0x7;
28495 df = DF_BYTE;
28496 } else {
28497 generate_exception_end(ctx, EXCP_RI);
28498 return;
28501 tdf = tcg_const_i32(df);
28502 tm = tcg_const_i32(m);
28503 twd = tcg_const_i32(wd);
28504 tws = tcg_const_i32(ws);
28506 switch (MASK_MSA_BIT(ctx->opcode)) {
28507 case OPC_SLLI_df:
28508 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28509 break;
28510 case OPC_SRAI_df:
28511 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28512 break;
28513 case OPC_SRLI_df:
28514 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28515 break;
28516 case OPC_BCLRI_df:
28517 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28518 break;
28519 case OPC_BSETI_df:
28520 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28521 break;
28522 case OPC_BNEGI_df:
28523 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28524 break;
28525 case OPC_BINSLI_df:
28526 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28527 break;
28528 case OPC_BINSRI_df:
28529 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28530 break;
28531 case OPC_SAT_S_df:
28532 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28533 break;
28534 case OPC_SAT_U_df:
28535 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28536 break;
28537 case OPC_SRARI_df:
28538 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28539 break;
28540 case OPC_SRLRI_df:
28541 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28542 break;
28543 default:
28544 MIPS_INVAL("MSA instruction");
28545 generate_exception_end(ctx, EXCP_RI);
28546 break;
28549 tcg_temp_free_i32(tdf);
28550 tcg_temp_free_i32(tm);
28551 tcg_temp_free_i32(twd);
28552 tcg_temp_free_i32(tws);
28555 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28557 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28558 uint8_t df = (ctx->opcode >> 21) & 0x3;
28559 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28560 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28561 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28563 TCGv_i32 tdf = tcg_const_i32(df);
28564 TCGv_i32 twd = tcg_const_i32(wd);
28565 TCGv_i32 tws = tcg_const_i32(ws);
28566 TCGv_i32 twt = tcg_const_i32(wt);
28568 switch (MASK_MSA_3R(ctx->opcode)) {
28569 case OPC_BINSL_df:
28570 switch (df) {
28571 case DF_BYTE:
28572 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28573 break;
28574 case DF_HALF:
28575 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28576 break;
28577 case DF_WORD:
28578 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28579 break;
28580 case DF_DOUBLE:
28581 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28582 break;
28584 break;
28585 case OPC_BINSR_df:
28586 switch (df) {
28587 case DF_BYTE:
28588 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28589 break;
28590 case DF_HALF:
28591 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28592 break;
28593 case DF_WORD:
28594 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28595 break;
28596 case DF_DOUBLE:
28597 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28598 break;
28600 break;
28601 case OPC_BCLR_df:
28602 switch (df) {
28603 case DF_BYTE:
28604 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28605 break;
28606 case DF_HALF:
28607 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28608 break;
28609 case DF_WORD:
28610 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28611 break;
28612 case DF_DOUBLE:
28613 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28614 break;
28616 break;
28617 case OPC_BNEG_df:
28618 switch (df) {
28619 case DF_BYTE:
28620 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28621 break;
28622 case DF_HALF:
28623 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28624 break;
28625 case DF_WORD:
28626 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28627 break;
28628 case DF_DOUBLE:
28629 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28630 break;
28632 break;
28633 case OPC_BSET_df:
28634 switch (df) {
28635 case DF_BYTE:
28636 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28637 break;
28638 case DF_HALF:
28639 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28640 break;
28641 case DF_WORD:
28642 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28643 break;
28644 case DF_DOUBLE:
28645 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28646 break;
28648 break;
28649 case OPC_ADD_A_df:
28650 switch (df) {
28651 case DF_BYTE:
28652 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28653 break;
28654 case DF_HALF:
28655 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28656 break;
28657 case DF_WORD:
28658 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28659 break;
28660 case DF_DOUBLE:
28661 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28662 break;
28664 break;
28665 case OPC_ADDS_A_df:
28666 switch (df) {
28667 case DF_BYTE:
28668 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28669 break;
28670 case DF_HALF:
28671 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28672 break;
28673 case DF_WORD:
28674 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
28675 break;
28676 case DF_DOUBLE:
28677 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
28678 break;
28680 break;
28681 case OPC_ADDS_S_df:
28682 switch (df) {
28683 case DF_BYTE:
28684 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
28685 break;
28686 case DF_HALF:
28687 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
28688 break;
28689 case DF_WORD:
28690 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
28691 break;
28692 case DF_DOUBLE:
28693 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
28694 break;
28696 break;
28697 case OPC_ADDS_U_df:
28698 switch (df) {
28699 case DF_BYTE:
28700 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
28701 break;
28702 case DF_HALF:
28703 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
28704 break;
28705 case DF_WORD:
28706 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
28707 break;
28708 case DF_DOUBLE:
28709 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
28710 break;
28712 break;
28713 case OPC_ADDV_df:
28714 switch (df) {
28715 case DF_BYTE:
28716 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
28717 break;
28718 case DF_HALF:
28719 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
28720 break;
28721 case DF_WORD:
28722 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
28723 break;
28724 case DF_DOUBLE:
28725 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
28726 break;
28728 break;
28729 case OPC_AVE_S_df:
28730 switch (df) {
28731 case DF_BYTE:
28732 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
28733 break;
28734 case DF_HALF:
28735 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
28736 break;
28737 case DF_WORD:
28738 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
28739 break;
28740 case DF_DOUBLE:
28741 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
28742 break;
28744 break;
28745 case OPC_AVE_U_df:
28746 switch (df) {
28747 case DF_BYTE:
28748 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
28749 break;
28750 case DF_HALF:
28751 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
28752 break;
28753 case DF_WORD:
28754 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
28755 break;
28756 case DF_DOUBLE:
28757 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
28758 break;
28760 break;
28761 case OPC_AVER_S_df:
28762 switch (df) {
28763 case DF_BYTE:
28764 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
28765 break;
28766 case DF_HALF:
28767 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
28768 break;
28769 case DF_WORD:
28770 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
28771 break;
28772 case DF_DOUBLE:
28773 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
28774 break;
28776 break;
28777 case OPC_AVER_U_df:
28778 switch (df) {
28779 case DF_BYTE:
28780 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
28781 break;
28782 case DF_HALF:
28783 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
28784 break;
28785 case DF_WORD:
28786 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
28787 break;
28788 case DF_DOUBLE:
28789 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
28790 break;
28792 break;
28793 case OPC_CEQ_df:
28794 switch (df) {
28795 case DF_BYTE:
28796 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
28797 break;
28798 case DF_HALF:
28799 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
28800 break;
28801 case DF_WORD:
28802 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
28803 break;
28804 case DF_DOUBLE:
28805 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
28806 break;
28808 break;
28809 case OPC_CLE_S_df:
28810 switch (df) {
28811 case DF_BYTE:
28812 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
28813 break;
28814 case DF_HALF:
28815 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
28816 break;
28817 case DF_WORD:
28818 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
28819 break;
28820 case DF_DOUBLE:
28821 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
28822 break;
28824 break;
28825 case OPC_CLE_U_df:
28826 switch (df) {
28827 case DF_BYTE:
28828 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
28829 break;
28830 case DF_HALF:
28831 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
28832 break;
28833 case DF_WORD:
28834 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
28835 break;
28836 case DF_DOUBLE:
28837 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
28838 break;
28840 break;
28841 case OPC_CLT_S_df:
28842 switch (df) {
28843 case DF_BYTE:
28844 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
28845 break;
28846 case DF_HALF:
28847 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
28848 break;
28849 case DF_WORD:
28850 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
28851 break;
28852 case DF_DOUBLE:
28853 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
28854 break;
28856 break;
28857 case OPC_CLT_U_df:
28858 switch (df) {
28859 case DF_BYTE:
28860 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
28861 break;
28862 case DF_HALF:
28863 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
28864 break;
28865 case DF_WORD:
28866 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
28867 break;
28868 case DF_DOUBLE:
28869 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
28870 break;
28872 break;
28873 case OPC_DIV_S_df:
28874 switch (df) {
28875 case DF_BYTE:
28876 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
28877 break;
28878 case DF_HALF:
28879 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
28880 break;
28881 case DF_WORD:
28882 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
28883 break;
28884 case DF_DOUBLE:
28885 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
28886 break;
28888 break;
28889 case OPC_DIV_U_df:
28890 switch (df) {
28891 case DF_BYTE:
28892 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
28893 break;
28894 case DF_HALF:
28895 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
28896 break;
28897 case DF_WORD:
28898 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
28899 break;
28900 case DF_DOUBLE:
28901 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
28902 break;
28904 break;
28905 case OPC_MAX_A_df:
28906 switch (df) {
28907 case DF_BYTE:
28908 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
28909 break;
28910 case DF_HALF:
28911 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
28912 break;
28913 case DF_WORD:
28914 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
28915 break;
28916 case DF_DOUBLE:
28917 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
28918 break;
28920 break;
28921 case OPC_MAX_S_df:
28922 switch (df) {
28923 case DF_BYTE:
28924 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
28925 break;
28926 case DF_HALF:
28927 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
28928 break;
28929 case DF_WORD:
28930 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
28931 break;
28932 case DF_DOUBLE:
28933 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
28934 break;
28936 break;
28937 case OPC_MAX_U_df:
28938 switch (df) {
28939 case DF_BYTE:
28940 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
28941 break;
28942 case DF_HALF:
28943 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
28944 break;
28945 case DF_WORD:
28946 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
28947 break;
28948 case DF_DOUBLE:
28949 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
28950 break;
28952 break;
28953 case OPC_MIN_A_df:
28954 switch (df) {
28955 case DF_BYTE:
28956 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
28957 break;
28958 case DF_HALF:
28959 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
28960 break;
28961 case DF_WORD:
28962 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
28963 break;
28964 case DF_DOUBLE:
28965 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
28966 break;
28968 break;
28969 case OPC_MIN_S_df:
28970 switch (df) {
28971 case DF_BYTE:
28972 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
28973 break;
28974 case DF_HALF:
28975 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
28976 break;
28977 case DF_WORD:
28978 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
28979 break;
28980 case DF_DOUBLE:
28981 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
28982 break;
28984 break;
28985 case OPC_MIN_U_df:
28986 switch (df) {
28987 case DF_BYTE:
28988 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
28989 break;
28990 case DF_HALF:
28991 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
28992 break;
28993 case DF_WORD:
28994 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
28995 break;
28996 case DF_DOUBLE:
28997 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
28998 break;
29000 break;
29001 case OPC_MOD_S_df:
29002 switch (df) {
29003 case DF_BYTE:
29004 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29005 break;
29006 case DF_HALF:
29007 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29008 break;
29009 case DF_WORD:
29010 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29011 break;
29012 case DF_DOUBLE:
29013 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29014 break;
29016 break;
29017 case OPC_MOD_U_df:
29018 switch (df) {
29019 case DF_BYTE:
29020 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29021 break;
29022 case DF_HALF:
29023 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29024 break;
29025 case DF_WORD:
29026 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29027 break;
29028 case DF_DOUBLE:
29029 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29030 break;
29032 break;
29033 case OPC_ASUB_S_df:
29034 switch (df) {
29035 case DF_BYTE:
29036 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29037 break;
29038 case DF_HALF:
29039 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29040 break;
29041 case DF_WORD:
29042 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29043 break;
29044 case DF_DOUBLE:
29045 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29046 break;
29048 break;
29049 case OPC_ASUB_U_df:
29050 switch (df) {
29051 case DF_BYTE:
29052 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29053 break;
29054 case DF_HALF:
29055 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29056 break;
29057 case DF_WORD:
29058 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29059 break;
29060 case DF_DOUBLE:
29061 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29062 break;
29064 break;
29065 case OPC_ILVEV_df:
29066 switch (df) {
29067 case DF_BYTE:
29068 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29069 break;
29070 case DF_HALF:
29071 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29072 break;
29073 case DF_WORD:
29074 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29075 break;
29076 case DF_DOUBLE:
29077 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29078 break;
29080 break;
29081 case OPC_ILVOD_df:
29082 switch (df) {
29083 case DF_BYTE:
29084 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29085 break;
29086 case DF_HALF:
29087 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29088 break;
29089 case DF_WORD:
29090 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29091 break;
29092 case DF_DOUBLE:
29093 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29094 break;
29096 break;
29097 case OPC_ILVL_df:
29098 switch (df) {
29099 case DF_BYTE:
29100 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29101 break;
29102 case DF_HALF:
29103 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29104 break;
29105 case DF_WORD:
29106 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29107 break;
29108 case DF_DOUBLE:
29109 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29110 break;
29112 break;
29113 case OPC_ILVR_df:
29114 switch (df) {
29115 case DF_BYTE:
29116 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29117 break;
29118 case DF_HALF:
29119 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29120 break;
29121 case DF_WORD:
29122 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29123 break;
29124 case DF_DOUBLE:
29125 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29126 break;
29128 break;
29129 case OPC_PCKEV_df:
29130 switch (df) {
29131 case DF_BYTE:
29132 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29133 break;
29134 case DF_HALF:
29135 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29136 break;
29137 case DF_WORD:
29138 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29139 break;
29140 case DF_DOUBLE:
29141 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29142 break;
29144 break;
29145 case OPC_PCKOD_df:
29146 switch (df) {
29147 case DF_BYTE:
29148 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29149 break;
29150 case DF_HALF:
29151 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29152 break;
29153 case DF_WORD:
29154 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29155 break;
29156 case DF_DOUBLE:
29157 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29158 break;
29160 break;
29161 case OPC_SLL_df:
29162 switch (df) {
29163 case DF_BYTE:
29164 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29165 break;
29166 case DF_HALF:
29167 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29168 break;
29169 case DF_WORD:
29170 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29171 break;
29172 case DF_DOUBLE:
29173 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29174 break;
29176 break;
29177 case OPC_SRA_df:
29178 switch (df) {
29179 case DF_BYTE:
29180 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29181 break;
29182 case DF_HALF:
29183 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29184 break;
29185 case DF_WORD:
29186 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29187 break;
29188 case DF_DOUBLE:
29189 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29190 break;
29192 break;
29193 case OPC_SRAR_df:
29194 switch (df) {
29195 case DF_BYTE:
29196 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29197 break;
29198 case DF_HALF:
29199 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29200 break;
29201 case DF_WORD:
29202 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29203 break;
29204 case DF_DOUBLE:
29205 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29206 break;
29208 break;
29209 case OPC_SRL_df:
29210 switch (df) {
29211 case DF_BYTE:
29212 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29213 break;
29214 case DF_HALF:
29215 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29216 break;
29217 case DF_WORD:
29218 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29219 break;
29220 case DF_DOUBLE:
29221 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29222 break;
29224 break;
29225 case OPC_SRLR_df:
29226 switch (df) {
29227 case DF_BYTE:
29228 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29229 break;
29230 case DF_HALF:
29231 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29232 break;
29233 case DF_WORD:
29234 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29235 break;
29236 case DF_DOUBLE:
29237 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29238 break;
29240 break;
29241 case OPC_SUBS_S_df:
29242 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
29243 break;
29244 case OPC_MULV_df:
29245 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
29246 break;
29247 case OPC_SLD_df:
29248 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29249 break;
29250 case OPC_VSHF_df:
29251 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29252 break;
29253 case OPC_SUBV_df:
29254 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
29255 break;
29256 case OPC_SUBS_U_df:
29257 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
29258 break;
29259 case OPC_MADDV_df:
29260 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
29261 break;
29262 case OPC_SPLAT_df:
29263 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29264 break;
29265 case OPC_SUBSUS_U_df:
29266 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
29267 break;
29268 case OPC_MSUBV_df:
29269 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
29270 break;
29271 case OPC_SUBSUU_S_df:
29272 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
29273 break;
29275 case OPC_DOTP_S_df:
29276 case OPC_DOTP_U_df:
29277 case OPC_DPADD_S_df:
29278 case OPC_DPADD_U_df:
29279 case OPC_DPSUB_S_df:
29280 case OPC_HADD_S_df:
29281 case OPC_DPSUB_U_df:
29282 case OPC_HADD_U_df:
29283 case OPC_HSUB_S_df:
29284 case OPC_HSUB_U_df:
29285 if (df == DF_BYTE) {
29286 generate_exception_end(ctx, EXCP_RI);
29287 break;
29289 switch (MASK_MSA_3R(ctx->opcode)) {
29290 case OPC_HADD_S_df:
29291 switch (df) {
29292 case DF_HALF:
29293 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29294 break;
29295 case DF_WORD:
29296 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29297 break;
29298 case DF_DOUBLE:
29299 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29300 break;
29302 break;
29303 case OPC_HADD_U_df:
29304 switch (df) {
29305 case DF_HALF:
29306 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29307 break;
29308 case DF_WORD:
29309 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29310 break;
29311 case DF_DOUBLE:
29312 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29313 break;
29315 break;
29316 case OPC_HSUB_S_df:
29317 switch (df) {
29318 case DF_HALF:
29319 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29320 break;
29321 case DF_WORD:
29322 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29323 break;
29324 case DF_DOUBLE:
29325 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29326 break;
29328 break;
29329 case OPC_HSUB_U_df:
29330 switch (df) {
29331 case DF_HALF:
29332 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29333 break;
29334 case DF_WORD:
29335 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29336 break;
29337 case DF_DOUBLE:
29338 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29339 break;
29341 break;
29342 case OPC_DOTP_S_df:
29343 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
29344 break;
29345 case OPC_DOTP_U_df:
29346 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
29347 break;
29348 case OPC_DPADD_S_df:
29349 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
29350 break;
29351 case OPC_DPADD_U_df:
29352 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
29353 break;
29354 case OPC_DPSUB_S_df:
29355 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
29356 break;
29357 case OPC_DPSUB_U_df:
29358 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
29359 break;
29361 break;
29362 default:
29363 MIPS_INVAL("MSA instruction");
29364 generate_exception_end(ctx, EXCP_RI);
29365 break;
29367 tcg_temp_free_i32(twd);
29368 tcg_temp_free_i32(tws);
29369 tcg_temp_free_i32(twt);
29370 tcg_temp_free_i32(tdf);
29373 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29375 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29376 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29377 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29378 TCGv telm = tcg_temp_new();
29379 TCGv_i32 tsr = tcg_const_i32(source);
29380 TCGv_i32 tdt = tcg_const_i32(dest);
29382 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29383 case OPC_CTCMSA:
29384 gen_load_gpr(telm, source);
29385 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29386 break;
29387 case OPC_CFCMSA:
29388 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29389 gen_store_gpr(telm, dest);
29390 break;
29391 case OPC_MOVE_V:
29392 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29393 break;
29394 default:
29395 MIPS_INVAL("MSA instruction");
29396 generate_exception_end(ctx, EXCP_RI);
29397 break;
29400 tcg_temp_free(telm);
29401 tcg_temp_free_i32(tdt);
29402 tcg_temp_free_i32(tsr);
29405 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29406 uint32_t n)
29408 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29409 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29410 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29412 TCGv_i32 tws = tcg_const_i32(ws);
29413 TCGv_i32 twd = tcg_const_i32(wd);
29414 TCGv_i32 tn = tcg_const_i32(n);
29415 TCGv_i32 tdf = tcg_const_i32(df);
29417 switch (MASK_MSA_ELM(ctx->opcode)) {
29418 case OPC_SLDI_df:
29419 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29420 break;
29421 case OPC_SPLATI_df:
29422 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29423 break;
29424 case OPC_INSVE_df:
29425 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29426 break;
29427 case OPC_COPY_S_df:
29428 case OPC_COPY_U_df:
29429 case OPC_INSERT_df:
29430 #if !defined(TARGET_MIPS64)
29431 /* Double format valid only for MIPS64 */
29432 if (df == DF_DOUBLE) {
29433 generate_exception_end(ctx, EXCP_RI);
29434 break;
29436 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29437 (df == DF_WORD)) {
29438 generate_exception_end(ctx, EXCP_RI);
29439 break;
29441 #endif
29442 switch (MASK_MSA_ELM(ctx->opcode)) {
29443 case OPC_COPY_S_df:
29444 if (likely(wd != 0)) {
29445 switch (df) {
29446 case DF_BYTE:
29447 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29448 break;
29449 case DF_HALF:
29450 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29451 break;
29452 case DF_WORD:
29453 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29454 break;
29455 #if defined(TARGET_MIPS64)
29456 case DF_DOUBLE:
29457 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29458 break;
29459 #endif
29460 default:
29461 assert(0);
29464 break;
29465 case OPC_COPY_U_df:
29466 if (likely(wd != 0)) {
29467 switch (df) {
29468 case DF_BYTE:
29469 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29470 break;
29471 case DF_HALF:
29472 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29473 break;
29474 #if defined(TARGET_MIPS64)
29475 case DF_WORD:
29476 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29477 break;
29478 #endif
29479 default:
29480 assert(0);
29483 break;
29484 case OPC_INSERT_df:
29485 switch (df) {
29486 case DF_BYTE:
29487 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29488 break;
29489 case DF_HALF:
29490 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29491 break;
29492 case DF_WORD:
29493 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29494 break;
29495 #if defined(TARGET_MIPS64)
29496 case DF_DOUBLE:
29497 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29498 break;
29499 #endif
29500 default:
29501 assert(0);
29503 break;
29505 break;
29506 default:
29507 MIPS_INVAL("MSA instruction");
29508 generate_exception_end(ctx, EXCP_RI);
29510 tcg_temp_free_i32(twd);
29511 tcg_temp_free_i32(tws);
29512 tcg_temp_free_i32(tn);
29513 tcg_temp_free_i32(tdf);
29516 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
29518 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
29519 uint32_t df = 0, n = 0;
29521 if ((dfn & 0x30) == 0x00) {
29522 n = dfn & 0x0f;
29523 df = DF_BYTE;
29524 } else if ((dfn & 0x38) == 0x20) {
29525 n = dfn & 0x07;
29526 df = DF_HALF;
29527 } else if ((dfn & 0x3c) == 0x30) {
29528 n = dfn & 0x03;
29529 df = DF_WORD;
29530 } else if ((dfn & 0x3e) == 0x38) {
29531 n = dfn & 0x01;
29532 df = DF_DOUBLE;
29533 } else if (dfn == 0x3E) {
29534 /* CTCMSA, CFCMSA, MOVE.V */
29535 gen_msa_elm_3e(env, ctx);
29536 return;
29537 } else {
29538 generate_exception_end(ctx, EXCP_RI);
29539 return;
29542 gen_msa_elm_df(env, ctx, df, n);
29545 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
29547 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29548 uint8_t df = (ctx->opcode >> 21) & 0x1;
29549 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29550 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29551 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29553 TCGv_i32 twd = tcg_const_i32(wd);
29554 TCGv_i32 tws = tcg_const_i32(ws);
29555 TCGv_i32 twt = tcg_const_i32(wt);
29556 TCGv_i32 tdf = tcg_temp_new_i32();
29558 /* adjust df value for floating-point instruction */
29559 tcg_gen_movi_i32(tdf, df + 2);
29561 switch (MASK_MSA_3RF(ctx->opcode)) {
29562 case OPC_FCAF_df:
29563 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
29564 break;
29565 case OPC_FADD_df:
29566 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
29567 break;
29568 case OPC_FCUN_df:
29569 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
29570 break;
29571 case OPC_FSUB_df:
29572 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
29573 break;
29574 case OPC_FCOR_df:
29575 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
29576 break;
29577 case OPC_FCEQ_df:
29578 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
29579 break;
29580 case OPC_FMUL_df:
29581 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
29582 break;
29583 case OPC_FCUNE_df:
29584 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
29585 break;
29586 case OPC_FCUEQ_df:
29587 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
29588 break;
29589 case OPC_FDIV_df:
29590 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
29591 break;
29592 case OPC_FCNE_df:
29593 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
29594 break;
29595 case OPC_FCLT_df:
29596 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
29597 break;
29598 case OPC_FMADD_df:
29599 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
29600 break;
29601 case OPC_MUL_Q_df:
29602 tcg_gen_movi_i32(tdf, df + 1);
29603 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
29604 break;
29605 case OPC_FCULT_df:
29606 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
29607 break;
29608 case OPC_FMSUB_df:
29609 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
29610 break;
29611 case OPC_MADD_Q_df:
29612 tcg_gen_movi_i32(tdf, df + 1);
29613 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
29614 break;
29615 case OPC_FCLE_df:
29616 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
29617 break;
29618 case OPC_MSUB_Q_df:
29619 tcg_gen_movi_i32(tdf, df + 1);
29620 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
29621 break;
29622 case OPC_FCULE_df:
29623 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
29624 break;
29625 case OPC_FEXP2_df:
29626 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
29627 break;
29628 case OPC_FSAF_df:
29629 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
29630 break;
29631 case OPC_FEXDO_df:
29632 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
29633 break;
29634 case OPC_FSUN_df:
29635 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
29636 break;
29637 case OPC_FSOR_df:
29638 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
29639 break;
29640 case OPC_FSEQ_df:
29641 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
29642 break;
29643 case OPC_FTQ_df:
29644 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
29645 break;
29646 case OPC_FSUNE_df:
29647 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
29648 break;
29649 case OPC_FSUEQ_df:
29650 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
29651 break;
29652 case OPC_FSNE_df:
29653 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
29654 break;
29655 case OPC_FSLT_df:
29656 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
29657 break;
29658 case OPC_FMIN_df:
29659 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
29660 break;
29661 case OPC_MULR_Q_df:
29662 tcg_gen_movi_i32(tdf, df + 1);
29663 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
29664 break;
29665 case OPC_FSULT_df:
29666 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
29667 break;
29668 case OPC_FMIN_A_df:
29669 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
29670 break;
29671 case OPC_MADDR_Q_df:
29672 tcg_gen_movi_i32(tdf, df + 1);
29673 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
29674 break;
29675 case OPC_FSLE_df:
29676 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
29677 break;
29678 case OPC_FMAX_df:
29679 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
29680 break;
29681 case OPC_MSUBR_Q_df:
29682 tcg_gen_movi_i32(tdf, df + 1);
29683 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
29684 break;
29685 case OPC_FSULE_df:
29686 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
29687 break;
29688 case OPC_FMAX_A_df:
29689 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
29690 break;
29691 default:
29692 MIPS_INVAL("MSA instruction");
29693 generate_exception_end(ctx, EXCP_RI);
29694 break;
29697 tcg_temp_free_i32(twd);
29698 tcg_temp_free_i32(tws);
29699 tcg_temp_free_i32(twt);
29700 tcg_temp_free_i32(tdf);
29703 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
29705 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29706 (op & (0x7 << 18)))
29707 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29708 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29709 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29710 uint8_t df = (ctx->opcode >> 16) & 0x3;
29711 TCGv_i32 twd = tcg_const_i32(wd);
29712 TCGv_i32 tws = tcg_const_i32(ws);
29713 TCGv_i32 twt = tcg_const_i32(wt);
29714 TCGv_i32 tdf = tcg_const_i32(df);
29716 switch (MASK_MSA_2R(ctx->opcode)) {
29717 case OPC_FILL_df:
29718 #if !defined(TARGET_MIPS64)
29719 /* Double format valid only for MIPS64 */
29720 if (df == DF_DOUBLE) {
29721 generate_exception_end(ctx, EXCP_RI);
29722 break;
29724 #endif
29725 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
29726 break;
29727 case OPC_NLOC_df:
29728 switch (df) {
29729 case DF_BYTE:
29730 gen_helper_msa_nloc_b(cpu_env, twd, tws);
29731 break;
29732 case DF_HALF:
29733 gen_helper_msa_nloc_h(cpu_env, twd, tws);
29734 break;
29735 case DF_WORD:
29736 gen_helper_msa_nloc_w(cpu_env, twd, tws);
29737 break;
29738 case DF_DOUBLE:
29739 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29740 break;
29742 break;
29743 case OPC_NLZC_df:
29744 switch (df) {
29745 case DF_BYTE:
29746 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29747 break;
29748 case DF_HALF:
29749 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29750 break;
29751 case DF_WORD:
29752 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29753 break;
29754 case DF_DOUBLE:
29755 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29756 break;
29758 break;
29759 case OPC_PCNT_df:
29760 switch (df) {
29761 case DF_BYTE:
29762 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29763 break;
29764 case DF_HALF:
29765 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29766 break;
29767 case DF_WORD:
29768 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29769 break;
29770 case DF_DOUBLE:
29771 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29772 break;
29774 break;
29775 default:
29776 MIPS_INVAL("MSA instruction");
29777 generate_exception_end(ctx, EXCP_RI);
29778 break;
29781 tcg_temp_free_i32(twd);
29782 tcg_temp_free_i32(tws);
29783 tcg_temp_free_i32(twt);
29784 tcg_temp_free_i32(tdf);
29787 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29789 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29790 (op & (0xf << 17)))
29791 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29792 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29793 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29794 uint8_t df = (ctx->opcode >> 16) & 0x1;
29795 TCGv_i32 twd = tcg_const_i32(wd);
29796 TCGv_i32 tws = tcg_const_i32(ws);
29797 TCGv_i32 twt = tcg_const_i32(wt);
29798 /* adjust df value for floating-point instruction */
29799 TCGv_i32 tdf = tcg_const_i32(df + 2);
29801 switch (MASK_MSA_2RF(ctx->opcode)) {
29802 case OPC_FCLASS_df:
29803 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29804 break;
29805 case OPC_FTRUNC_S_df:
29806 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29807 break;
29808 case OPC_FTRUNC_U_df:
29809 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
29810 break;
29811 case OPC_FSQRT_df:
29812 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29813 break;
29814 case OPC_FRSQRT_df:
29815 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
29816 break;
29817 case OPC_FRCP_df:
29818 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
29819 break;
29820 case OPC_FRINT_df:
29821 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
29822 break;
29823 case OPC_FLOG2_df:
29824 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
29825 break;
29826 case OPC_FEXUPL_df:
29827 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
29828 break;
29829 case OPC_FEXUPR_df:
29830 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
29831 break;
29832 case OPC_FFQL_df:
29833 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
29834 break;
29835 case OPC_FFQR_df:
29836 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
29837 break;
29838 case OPC_FTINT_S_df:
29839 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29840 break;
29841 case OPC_FTINT_U_df:
29842 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29843 break;
29844 case OPC_FFINT_S_df:
29845 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29846 break;
29847 case OPC_FFINT_U_df:
29848 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29849 break;
29852 tcg_temp_free_i32(twd);
29853 tcg_temp_free_i32(tws);
29854 tcg_temp_free_i32(twt);
29855 tcg_temp_free_i32(tdf);
29858 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29860 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29861 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29862 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29863 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29864 TCGv_i32 twd = tcg_const_i32(wd);
29865 TCGv_i32 tws = tcg_const_i32(ws);
29866 TCGv_i32 twt = tcg_const_i32(wt);
29868 switch (MASK_MSA_VEC(ctx->opcode)) {
29869 case OPC_AND_V:
29870 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29871 break;
29872 case OPC_OR_V:
29873 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29874 break;
29875 case OPC_NOR_V:
29876 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29877 break;
29878 case OPC_XOR_V:
29879 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29880 break;
29881 case OPC_BMNZ_V:
29882 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29883 break;
29884 case OPC_BMZ_V:
29885 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29886 break;
29887 case OPC_BSEL_V:
29888 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29889 break;
29890 default:
29891 MIPS_INVAL("MSA instruction");
29892 generate_exception_end(ctx, EXCP_RI);
29893 break;
29896 tcg_temp_free_i32(twd);
29897 tcg_temp_free_i32(tws);
29898 tcg_temp_free_i32(twt);
29901 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29903 switch (MASK_MSA_VEC(ctx->opcode)) {
29904 case OPC_AND_V:
29905 case OPC_OR_V:
29906 case OPC_NOR_V:
29907 case OPC_XOR_V:
29908 case OPC_BMNZ_V:
29909 case OPC_BMZ_V:
29910 case OPC_BSEL_V:
29911 gen_msa_vec_v(env, ctx);
29912 break;
29913 case OPC_MSA_2R:
29914 gen_msa_2r(env, ctx);
29915 break;
29916 case OPC_MSA_2RF:
29917 gen_msa_2rf(env, ctx);
29918 break;
29919 default:
29920 MIPS_INVAL("MSA instruction");
29921 generate_exception_end(ctx, EXCP_RI);
29922 break;
29926 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29928 uint32_t opcode = ctx->opcode;
29929 check_insn(ctx, ASE_MSA);
29930 check_msa_access(ctx);
29932 switch (MASK_MSA_MINOR(opcode)) {
29933 case OPC_MSA_I8_00:
29934 case OPC_MSA_I8_01:
29935 case OPC_MSA_I8_02:
29936 gen_msa_i8(env, ctx);
29937 break;
29938 case OPC_MSA_I5_06:
29939 case OPC_MSA_I5_07:
29940 gen_msa_i5(env, ctx);
29941 break;
29942 case OPC_MSA_BIT_09:
29943 case OPC_MSA_BIT_0A:
29944 gen_msa_bit(env, ctx);
29945 break;
29946 case OPC_MSA_3R_0D:
29947 case OPC_MSA_3R_0E:
29948 case OPC_MSA_3R_0F:
29949 case OPC_MSA_3R_10:
29950 case OPC_MSA_3R_11:
29951 case OPC_MSA_3R_12:
29952 case OPC_MSA_3R_13:
29953 case OPC_MSA_3R_14:
29954 case OPC_MSA_3R_15:
29955 gen_msa_3r(env, ctx);
29956 break;
29957 case OPC_MSA_ELM:
29958 gen_msa_elm(env, ctx);
29959 break;
29960 case OPC_MSA_3RF_1A:
29961 case OPC_MSA_3RF_1B:
29962 case OPC_MSA_3RF_1C:
29963 gen_msa_3rf(env, ctx);
29964 break;
29965 case OPC_MSA_VEC:
29966 gen_msa_vec(env, ctx);
29967 break;
29968 case OPC_LD_B:
29969 case OPC_LD_H:
29970 case OPC_LD_W:
29971 case OPC_LD_D:
29972 case OPC_ST_B:
29973 case OPC_ST_H:
29974 case OPC_ST_W:
29975 case OPC_ST_D:
29977 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29978 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29979 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29980 uint8_t df = (ctx->opcode >> 0) & 0x3;
29982 TCGv_i32 twd = tcg_const_i32(wd);
29983 TCGv taddr = tcg_temp_new();
29984 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
29986 switch (MASK_MSA_MINOR(opcode)) {
29987 case OPC_LD_B:
29988 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29989 break;
29990 case OPC_LD_H:
29991 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29992 break;
29993 case OPC_LD_W:
29994 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29995 break;
29996 case OPC_LD_D:
29997 gen_helper_msa_ld_d(cpu_env, twd, taddr);
29998 break;
29999 case OPC_ST_B:
30000 gen_helper_msa_st_b(cpu_env, twd, taddr);
30001 break;
30002 case OPC_ST_H:
30003 gen_helper_msa_st_h(cpu_env, twd, taddr);
30004 break;
30005 case OPC_ST_W:
30006 gen_helper_msa_st_w(cpu_env, twd, taddr);
30007 break;
30008 case OPC_ST_D:
30009 gen_helper_msa_st_d(cpu_env, twd, taddr);
30010 break;
30013 tcg_temp_free_i32(twd);
30014 tcg_temp_free(taddr);
30016 break;
30017 default:
30018 MIPS_INVAL("MSA instruction");
30019 generate_exception_end(ctx, EXCP_RI);
30020 break;
30025 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30027 int32_t offset;
30028 int rs, rt, rd, sa;
30029 uint32_t op, op1;
30030 int16_t imm;
30032 /* make sure instructions are on a word boundary */
30033 if (ctx->base.pc_next & 0x3) {
30034 env->CP0_BadVAddr = ctx->base.pc_next;
30035 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30036 return;
30039 /* Handle blikely not taken case */
30040 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30041 TCGLabel *l1 = gen_new_label();
30043 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30044 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30045 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30046 gen_set_label(l1);
30049 op = MASK_OP_MAJOR(ctx->opcode);
30050 rs = (ctx->opcode >> 21) & 0x1f;
30051 rt = (ctx->opcode >> 16) & 0x1f;
30052 rd = (ctx->opcode >> 11) & 0x1f;
30053 sa = (ctx->opcode >> 6) & 0x1f;
30054 imm = (int16_t)ctx->opcode;
30055 switch (op) {
30056 case OPC_SPECIAL:
30057 decode_opc_special(env, ctx);
30058 break;
30059 case OPC_SPECIAL2:
30060 #if defined(TARGET_MIPS64)
30061 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30062 decode_mmi(env, ctx);
30063 #else
30064 if (ctx->insn_flags & ASE_MXU) {
30065 decode_opc_mxu(env, ctx);
30066 #endif
30067 } else {
30068 decode_opc_special2_legacy(env, ctx);
30070 break;
30071 case OPC_SPECIAL3:
30072 #if defined(TARGET_MIPS64)
30073 if (ctx->insn_flags & INSN_R5900) {
30074 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30075 } else {
30076 decode_opc_special3(env, ctx);
30078 #else
30079 decode_opc_special3(env, ctx);
30080 #endif
30081 break;
30082 case OPC_REGIMM:
30083 op1 = MASK_REGIMM(ctx->opcode);
30084 switch (op1) {
30085 case OPC_BLTZL: /* REGIMM branches */
30086 case OPC_BGEZL:
30087 case OPC_BLTZALL:
30088 case OPC_BGEZALL:
30089 check_insn(ctx, ISA_MIPS2);
30090 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30091 /* Fallthrough */
30092 case OPC_BLTZ:
30093 case OPC_BGEZ:
30094 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30095 break;
30096 case OPC_BLTZAL:
30097 case OPC_BGEZAL:
30098 if (ctx->insn_flags & ISA_MIPS32R6) {
30099 if (rs == 0) {
30100 /* OPC_NAL, OPC_BAL */
30101 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30102 } else {
30103 generate_exception_end(ctx, EXCP_RI);
30105 } else {
30106 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30108 break;
30109 case OPC_TGEI: /* REGIMM traps */
30110 case OPC_TGEIU:
30111 case OPC_TLTI:
30112 case OPC_TLTIU:
30113 case OPC_TEQI:
30115 case OPC_TNEI:
30116 check_insn(ctx, ISA_MIPS2);
30117 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30118 gen_trap(ctx, op1, rs, -1, imm);
30119 break;
30120 case OPC_SIGRIE:
30121 check_insn(ctx, ISA_MIPS32R6);
30122 generate_exception_end(ctx, EXCP_RI);
30123 break;
30124 case OPC_SYNCI:
30125 check_insn(ctx, ISA_MIPS32R2);
30127 * Break the TB to be able to sync copied instructions
30128 * immediately.
30130 ctx->base.is_jmp = DISAS_STOP;
30131 break;
30132 case OPC_BPOSGE32: /* MIPS DSP branch */
30133 #if defined(TARGET_MIPS64)
30134 case OPC_BPOSGE64:
30135 #endif
30136 check_dsp(ctx);
30137 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30138 break;
30139 #if defined(TARGET_MIPS64)
30140 case OPC_DAHI:
30141 check_insn(ctx, ISA_MIPS32R6);
30142 check_mips_64(ctx);
30143 if (rs != 0) {
30144 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30146 break;
30147 case OPC_DATI:
30148 check_insn(ctx, ISA_MIPS32R6);
30149 check_mips_64(ctx);
30150 if (rs != 0) {
30151 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30153 break;
30154 #endif
30155 default: /* Invalid */
30156 MIPS_INVAL("regimm");
30157 generate_exception_end(ctx, EXCP_RI);
30158 break;
30160 break;
30161 case OPC_CP0:
30162 check_cp0_enabled(ctx);
30163 op1 = MASK_CP0(ctx->opcode);
30164 switch (op1) {
30165 case OPC_MFC0:
30166 case OPC_MTC0:
30167 case OPC_MFTR:
30168 case OPC_MTTR:
30169 case OPC_MFHC0:
30170 case OPC_MTHC0:
30171 #if defined(TARGET_MIPS64)
30172 case OPC_DMFC0:
30173 case OPC_DMTC0:
30174 #endif
30175 #ifndef CONFIG_USER_ONLY
30176 gen_cp0(env, ctx, op1, rt, rd);
30177 #endif /* !CONFIG_USER_ONLY */
30178 break;
30179 case OPC_C0:
30180 case OPC_C0_1:
30181 case OPC_C0_2:
30182 case OPC_C0_3:
30183 case OPC_C0_4:
30184 case OPC_C0_5:
30185 case OPC_C0_6:
30186 case OPC_C0_7:
30187 case OPC_C0_8:
30188 case OPC_C0_9:
30189 case OPC_C0_A:
30190 case OPC_C0_B:
30191 case OPC_C0_C:
30192 case OPC_C0_D:
30193 case OPC_C0_E:
30194 case OPC_C0_F:
30195 #ifndef CONFIG_USER_ONLY
30196 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30197 #endif /* !CONFIG_USER_ONLY */
30198 break;
30199 case OPC_MFMC0:
30200 #ifndef CONFIG_USER_ONLY
30202 uint32_t op2;
30203 TCGv t0 = tcg_temp_new();
30205 op2 = MASK_MFMC0(ctx->opcode);
30206 switch (op2) {
30207 case OPC_DMT:
30208 check_cp0_mt(ctx);
30209 gen_helper_dmt(t0);
30210 gen_store_gpr(t0, rt);
30211 break;
30212 case OPC_EMT:
30213 check_cp0_mt(ctx);
30214 gen_helper_emt(t0);
30215 gen_store_gpr(t0, rt);
30216 break;
30217 case OPC_DVPE:
30218 check_cp0_mt(ctx);
30219 gen_helper_dvpe(t0, cpu_env);
30220 gen_store_gpr(t0, rt);
30221 break;
30222 case OPC_EVPE:
30223 check_cp0_mt(ctx);
30224 gen_helper_evpe(t0, cpu_env);
30225 gen_store_gpr(t0, rt);
30226 break;
30227 case OPC_DVP:
30228 check_insn(ctx, ISA_MIPS32R6);
30229 if (ctx->vp) {
30230 gen_helper_dvp(t0, cpu_env);
30231 gen_store_gpr(t0, rt);
30233 break;
30234 case OPC_EVP:
30235 check_insn(ctx, ISA_MIPS32R6);
30236 if (ctx->vp) {
30237 gen_helper_evp(t0, cpu_env);
30238 gen_store_gpr(t0, rt);
30240 break;
30241 case OPC_DI:
30242 check_insn(ctx, ISA_MIPS32R2);
30243 save_cpu_state(ctx, 1);
30244 gen_helper_di(t0, cpu_env);
30245 gen_store_gpr(t0, rt);
30247 * Stop translation as we may have switched
30248 * the execution mode.
30250 ctx->base.is_jmp = DISAS_STOP;
30251 break;
30252 case OPC_EI:
30253 check_insn(ctx, ISA_MIPS32R2);
30254 save_cpu_state(ctx, 1);
30255 gen_helper_ei(t0, cpu_env);
30256 gen_store_gpr(t0, rt);
30258 * DISAS_STOP isn't sufficient, we need to ensure we break
30259 * out of translated code to check for pending interrupts.
30261 gen_save_pc(ctx->base.pc_next + 4);
30262 ctx->base.is_jmp = DISAS_EXIT;
30263 break;
30264 default: /* Invalid */
30265 MIPS_INVAL("mfmc0");
30266 generate_exception_end(ctx, EXCP_RI);
30267 break;
30269 tcg_temp_free(t0);
30271 #endif /* !CONFIG_USER_ONLY */
30272 break;
30273 case OPC_RDPGPR:
30274 check_insn(ctx, ISA_MIPS32R2);
30275 gen_load_srsgpr(rt, rd);
30276 break;
30277 case OPC_WRPGPR:
30278 check_insn(ctx, ISA_MIPS32R2);
30279 gen_store_srsgpr(rt, rd);
30280 break;
30281 default:
30282 MIPS_INVAL("cp0");
30283 generate_exception_end(ctx, EXCP_RI);
30284 break;
30286 break;
30287 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30288 if (ctx->insn_flags & ISA_MIPS32R6) {
30289 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30290 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30291 } else {
30292 /* OPC_ADDI */
30293 /* Arithmetic with immediate opcode */
30294 gen_arith_imm(ctx, op, rt, rs, imm);
30296 break;
30297 case OPC_ADDIU:
30298 gen_arith_imm(ctx, op, rt, rs, imm);
30299 break;
30300 case OPC_SLTI: /* Set on less than with immediate opcode */
30301 case OPC_SLTIU:
30302 gen_slt_imm(ctx, op, rt, rs, imm);
30303 break;
30304 case OPC_ANDI: /* Arithmetic with immediate opcode */
30305 case OPC_LUI: /* OPC_AUI */
30306 case OPC_ORI:
30307 case OPC_XORI:
30308 gen_logic_imm(ctx, op, rt, rs, imm);
30309 break;
30310 case OPC_J: /* Jump */
30311 case OPC_JAL:
30312 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30313 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30314 break;
30315 /* Branch */
30316 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30317 if (ctx->insn_flags & ISA_MIPS32R6) {
30318 if (rt == 0) {
30319 generate_exception_end(ctx, EXCP_RI);
30320 break;
30322 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30323 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30324 } else {
30325 /* OPC_BLEZL */
30326 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30328 break;
30329 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30330 if (ctx->insn_flags & ISA_MIPS32R6) {
30331 if (rt == 0) {
30332 generate_exception_end(ctx, EXCP_RI);
30333 break;
30335 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30336 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30337 } else {
30338 /* OPC_BGTZL */
30339 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30341 break;
30342 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30343 if (rt == 0) {
30344 /* OPC_BLEZ */
30345 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30346 } else {
30347 check_insn(ctx, ISA_MIPS32R6);
30348 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30349 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30351 break;
30352 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30353 if (rt == 0) {
30354 /* OPC_BGTZ */
30355 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30356 } else {
30357 check_insn(ctx, ISA_MIPS32R6);
30358 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30359 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30361 break;
30362 case OPC_BEQL:
30363 case OPC_BNEL:
30364 check_insn(ctx, ISA_MIPS2);
30365 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30366 /* Fallthrough */
30367 case OPC_BEQ:
30368 case OPC_BNE:
30369 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30370 break;
30371 case OPC_LL: /* Load and stores */
30372 check_insn(ctx, ISA_MIPS2);
30373 if (ctx->insn_flags & INSN_R5900) {
30374 check_insn_opc_user_only(ctx, INSN_R5900);
30376 /* Fallthrough */
30377 case OPC_LWL:
30378 case OPC_LWR:
30379 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30380 /* Fallthrough */
30381 case OPC_LB:
30382 case OPC_LH:
30383 case OPC_LW:
30384 case OPC_LWPC:
30385 case OPC_LBU:
30386 case OPC_LHU:
30387 gen_ld(ctx, op, rt, rs, imm);
30388 break;
30389 case OPC_SWL:
30390 case OPC_SWR:
30391 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30392 /* fall through */
30393 case OPC_SB:
30394 case OPC_SH:
30395 case OPC_SW:
30396 gen_st(ctx, op, rt, rs, imm);
30397 break;
30398 case OPC_SC:
30399 check_insn(ctx, ISA_MIPS2);
30400 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30401 if (ctx->insn_flags & INSN_R5900) {
30402 check_insn_opc_user_only(ctx, INSN_R5900);
30404 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30405 break;
30406 case OPC_CACHE:
30407 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30408 check_cp0_enabled(ctx);
30409 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
30410 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30411 gen_cache_operation(ctx, rt, rs, imm);
30413 /* Treat as NOP. */
30414 break;
30415 case OPC_PREF:
30416 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30417 if (ctx->insn_flags & INSN_R5900) {
30418 /* Treat as NOP. */
30419 } else {
30420 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
30421 /* Treat as NOP. */
30423 break;
30425 /* Floating point (COP1). */
30426 case OPC_LWC1:
30427 case OPC_LDC1:
30428 case OPC_SWC1:
30429 case OPC_SDC1:
30430 gen_cop1_ldst(ctx, op, rt, rs, imm);
30431 break;
30433 case OPC_CP1:
30434 op1 = MASK_CP1(ctx->opcode);
30436 switch (op1) {
30437 case OPC_MFHC1:
30438 case OPC_MTHC1:
30439 check_cp1_enabled(ctx);
30440 check_insn(ctx, ISA_MIPS32R2);
30441 /* fall through */
30442 case OPC_MFC1:
30443 case OPC_CFC1:
30444 case OPC_MTC1:
30445 case OPC_CTC1:
30446 check_cp1_enabled(ctx);
30447 gen_cp1(ctx, op1, rt, rd);
30448 break;
30449 #if defined(TARGET_MIPS64)
30450 case OPC_DMFC1:
30451 case OPC_DMTC1:
30452 check_cp1_enabled(ctx);
30453 check_insn(ctx, ISA_MIPS3);
30454 check_mips_64(ctx);
30455 gen_cp1(ctx, op1, rt, rd);
30456 break;
30457 #endif
30458 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30459 check_cp1_enabled(ctx);
30460 if (ctx->insn_flags & ISA_MIPS32R6) {
30461 /* OPC_BC1EQZ */
30462 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30463 rt, imm << 2, 4);
30464 } else {
30465 /* OPC_BC1ANY2 */
30466 check_cop1x(ctx);
30467 check_insn(ctx, ASE_MIPS3D);
30468 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30469 (rt >> 2) & 0x7, imm << 2);
30471 break;
30472 case OPC_BC1NEZ:
30473 check_cp1_enabled(ctx);
30474 check_insn(ctx, ISA_MIPS32R6);
30475 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30476 rt, imm << 2, 4);
30477 break;
30478 case OPC_BC1ANY4:
30479 check_cp1_enabled(ctx);
30480 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30481 check_cop1x(ctx);
30482 check_insn(ctx, ASE_MIPS3D);
30483 /* fall through */
30484 case OPC_BC1:
30485 check_cp1_enabled(ctx);
30486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30487 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30488 (rt >> 2) & 0x7, imm << 2);
30489 break;
30490 case OPC_PS_FMT:
30491 check_ps(ctx);
30492 /* fall through */
30493 case OPC_S_FMT:
30494 case OPC_D_FMT:
30495 check_cp1_enabled(ctx);
30496 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30497 (imm >> 8) & 0x7);
30498 break;
30499 case OPC_W_FMT:
30500 case OPC_L_FMT:
30502 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30503 check_cp1_enabled(ctx);
30504 if (ctx->insn_flags & ISA_MIPS32R6) {
30505 switch (r6_op) {
30506 case R6_OPC_CMP_AF_S:
30507 case R6_OPC_CMP_UN_S:
30508 case R6_OPC_CMP_EQ_S:
30509 case R6_OPC_CMP_UEQ_S:
30510 case R6_OPC_CMP_LT_S:
30511 case R6_OPC_CMP_ULT_S:
30512 case R6_OPC_CMP_LE_S:
30513 case R6_OPC_CMP_ULE_S:
30514 case R6_OPC_CMP_SAF_S:
30515 case R6_OPC_CMP_SUN_S:
30516 case R6_OPC_CMP_SEQ_S:
30517 case R6_OPC_CMP_SEUQ_S:
30518 case R6_OPC_CMP_SLT_S:
30519 case R6_OPC_CMP_SULT_S:
30520 case R6_OPC_CMP_SLE_S:
30521 case R6_OPC_CMP_SULE_S:
30522 case R6_OPC_CMP_OR_S:
30523 case R6_OPC_CMP_UNE_S:
30524 case R6_OPC_CMP_NE_S:
30525 case R6_OPC_CMP_SOR_S:
30526 case R6_OPC_CMP_SUNE_S:
30527 case R6_OPC_CMP_SNE_S:
30528 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30529 break;
30530 case R6_OPC_CMP_AF_D:
30531 case R6_OPC_CMP_UN_D:
30532 case R6_OPC_CMP_EQ_D:
30533 case R6_OPC_CMP_UEQ_D:
30534 case R6_OPC_CMP_LT_D:
30535 case R6_OPC_CMP_ULT_D:
30536 case R6_OPC_CMP_LE_D:
30537 case R6_OPC_CMP_ULE_D:
30538 case R6_OPC_CMP_SAF_D:
30539 case R6_OPC_CMP_SUN_D:
30540 case R6_OPC_CMP_SEQ_D:
30541 case R6_OPC_CMP_SEUQ_D:
30542 case R6_OPC_CMP_SLT_D:
30543 case R6_OPC_CMP_SULT_D:
30544 case R6_OPC_CMP_SLE_D:
30545 case R6_OPC_CMP_SULE_D:
30546 case R6_OPC_CMP_OR_D:
30547 case R6_OPC_CMP_UNE_D:
30548 case R6_OPC_CMP_NE_D:
30549 case R6_OPC_CMP_SOR_D:
30550 case R6_OPC_CMP_SUNE_D:
30551 case R6_OPC_CMP_SNE_D:
30552 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30553 break;
30554 default:
30555 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
30556 rt, rd, sa, (imm >> 8) & 0x7);
30558 break;
30560 } else {
30561 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30562 (imm >> 8) & 0x7);
30564 break;
30566 case OPC_BZ_V:
30567 case OPC_BNZ_V:
30568 case OPC_BZ_B:
30569 case OPC_BZ_H:
30570 case OPC_BZ_W:
30571 case OPC_BZ_D:
30572 case OPC_BNZ_B:
30573 case OPC_BNZ_H:
30574 case OPC_BNZ_W:
30575 case OPC_BNZ_D:
30576 check_insn(ctx, ASE_MSA);
30577 gen_msa_branch(env, ctx, op1);
30578 break;
30579 default:
30580 MIPS_INVAL("cp1");
30581 generate_exception_end(ctx, EXCP_RI);
30582 break;
30584 break;
30586 /* Compact branches [R6] and COP2 [non-R6] */
30587 case OPC_BC: /* OPC_LWC2 */
30588 case OPC_BALC: /* OPC_SWC2 */
30589 if (ctx->insn_flags & ISA_MIPS32R6) {
30590 /* OPC_BC, OPC_BALC */
30591 gen_compute_compact_branch(ctx, op, 0, 0,
30592 sextract32(ctx->opcode << 2, 0, 28));
30593 } else {
30594 /* OPC_LWC2, OPC_SWC2 */
30595 /* COP2: Not implemented. */
30596 generate_exception_err(ctx, EXCP_CpU, 2);
30598 break;
30599 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
30600 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
30601 if (ctx->insn_flags & ISA_MIPS32R6) {
30602 if (rs != 0) {
30603 /* OPC_BEQZC, OPC_BNEZC */
30604 gen_compute_compact_branch(ctx, op, rs, 0,
30605 sextract32(ctx->opcode << 2, 0, 23));
30606 } else {
30607 /* OPC_JIC, OPC_JIALC */
30608 gen_compute_compact_branch(ctx, op, 0, rt, imm);
30610 } else {
30611 /* OPC_LWC2, OPC_SWC2 */
30612 /* COP2: Not implemented. */
30613 generate_exception_err(ctx, EXCP_CpU, 2);
30615 break;
30616 case OPC_CP2:
30617 check_insn(ctx, INSN_LOONGSON2F);
30618 /* Note that these instructions use different fields. */
30619 gen_loongson_multimedia(ctx, sa, rd, rt);
30620 break;
30622 case OPC_CP3:
30623 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30624 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
30625 check_cp1_enabled(ctx);
30626 op1 = MASK_CP3(ctx->opcode);
30627 switch (op1) {
30628 case OPC_LUXC1:
30629 case OPC_SUXC1:
30630 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30631 /* Fallthrough */
30632 case OPC_LWXC1:
30633 case OPC_LDXC1:
30634 case OPC_SWXC1:
30635 case OPC_SDXC1:
30636 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30637 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
30638 break;
30639 case OPC_PREFX:
30640 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30641 /* Treat as NOP. */
30642 break;
30643 case OPC_ALNV_PS:
30644 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30645 /* Fallthrough */
30646 case OPC_MADD_S:
30647 case OPC_MADD_D:
30648 case OPC_MADD_PS:
30649 case OPC_MSUB_S:
30650 case OPC_MSUB_D:
30651 case OPC_MSUB_PS:
30652 case OPC_NMADD_S:
30653 case OPC_NMADD_D:
30654 case OPC_NMADD_PS:
30655 case OPC_NMSUB_S:
30656 case OPC_NMSUB_D:
30657 case OPC_NMSUB_PS:
30658 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30659 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
30660 break;
30661 default:
30662 MIPS_INVAL("cp3");
30663 generate_exception_end(ctx, EXCP_RI);
30664 break;
30666 } else {
30667 generate_exception_err(ctx, EXCP_CpU, 1);
30669 break;
30671 #if defined(TARGET_MIPS64)
30672 /* MIPS64 opcodes */
30673 case OPC_LLD:
30674 if (ctx->insn_flags & INSN_R5900) {
30675 check_insn_opc_user_only(ctx, INSN_R5900);
30677 /* fall through */
30678 case OPC_LDL:
30679 case OPC_LDR:
30680 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30681 /* fall through */
30682 case OPC_LWU:
30683 case OPC_LD:
30684 check_insn(ctx, ISA_MIPS3);
30685 check_mips_64(ctx);
30686 gen_ld(ctx, op, rt, rs, imm);
30687 break;
30688 case OPC_SDL:
30689 case OPC_SDR:
30690 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30691 /* fall through */
30692 case OPC_SD:
30693 check_insn(ctx, ISA_MIPS3);
30694 check_mips_64(ctx);
30695 gen_st(ctx, op, rt, rs, imm);
30696 break;
30697 case OPC_SCD:
30698 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30699 check_insn(ctx, ISA_MIPS3);
30700 if (ctx->insn_flags & INSN_R5900) {
30701 check_insn_opc_user_only(ctx, INSN_R5900);
30703 check_mips_64(ctx);
30704 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
30705 break;
30706 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
30707 if (ctx->insn_flags & ISA_MIPS32R6) {
30708 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
30709 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30710 } else {
30711 /* OPC_DADDI */
30712 check_insn(ctx, ISA_MIPS3);
30713 check_mips_64(ctx);
30714 gen_arith_imm(ctx, op, rt, rs, imm);
30716 break;
30717 case OPC_DADDIU:
30718 check_insn(ctx, ISA_MIPS3);
30719 check_mips_64(ctx);
30720 gen_arith_imm(ctx, op, rt, rs, imm);
30721 break;
30722 #else
30723 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
30724 if (ctx->insn_flags & ISA_MIPS32R6) {
30725 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30726 } else {
30727 MIPS_INVAL("major opcode");
30728 generate_exception_end(ctx, EXCP_RI);
30730 break;
30731 #endif
30732 case OPC_DAUI: /* OPC_JALX */
30733 if (ctx->insn_flags & ISA_MIPS32R6) {
30734 #if defined(TARGET_MIPS64)
30735 /* OPC_DAUI */
30736 check_mips_64(ctx);
30737 if (rs == 0) {
30738 generate_exception(ctx, EXCP_RI);
30739 } else if (rt != 0) {
30740 TCGv t0 = tcg_temp_new();
30741 gen_load_gpr(t0, rs);
30742 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30743 tcg_temp_free(t0);
30745 #else
30746 generate_exception_end(ctx, EXCP_RI);
30747 MIPS_INVAL("major opcode");
30748 #endif
30749 } else {
30750 /* OPC_JALX */
30751 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30752 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30753 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30755 break;
30756 case OPC_MSA: /* OPC_MDMX */
30757 if (ctx->insn_flags & INSN_R5900) {
30758 #if defined(TARGET_MIPS64)
30759 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
30760 #endif
30761 } else {
30762 /* MDMX: Not implemented. */
30763 gen_msa(env, ctx);
30765 break;
30766 case OPC_PCREL:
30767 check_insn(ctx, ISA_MIPS32R6);
30768 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
30769 break;
30770 default: /* Invalid */
30771 MIPS_INVAL("major opcode");
30772 generate_exception_end(ctx, EXCP_RI);
30773 break;
30777 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
30779 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30780 CPUMIPSState *env = cs->env_ptr;
30782 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
30783 ctx->saved_pc = -1;
30784 ctx->insn_flags = env->insn_flags;
30785 ctx->CP0_Config1 = env->CP0_Config1;
30786 ctx->CP0_Config2 = env->CP0_Config2;
30787 ctx->CP0_Config3 = env->CP0_Config3;
30788 ctx->CP0_Config5 = env->CP0_Config5;
30789 ctx->btarget = 0;
30790 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30791 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30792 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30793 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30794 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30795 ctx->PAMask = env->PAMask;
30796 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30797 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30798 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30799 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30800 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
30801 /* Restore delay slot state from the tb context. */
30802 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30803 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30804 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
30805 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
30806 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30807 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
30808 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
30809 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
30810 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
30811 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
30812 restore_cpu_state(env, ctx);
30813 #ifdef CONFIG_USER_ONLY
30814 ctx->mem_idx = MIPS_HFLAG_UM;
30815 #else
30816 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
30817 #endif
30818 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
30819 MO_UNALN : MO_ALIGN;
30821 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
30822 ctx->hflags);
30825 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
30829 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
30831 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30833 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
30834 ctx->btarget);
30837 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
30838 const CPUBreakpoint *bp)
30840 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30842 save_cpu_state(ctx, 1);
30843 ctx->base.is_jmp = DISAS_NORETURN;
30844 gen_helper_raise_exception_debug(cpu_env);
30846 * The address covered by the breakpoint must be included in
30847 * [tb->pc, tb->pc + tb->size) in order to for it to be
30848 * properly cleared -- thus we increment the PC here so that
30849 * the logic setting tb->size below does the right thing.
30851 ctx->base.pc_next += 4;
30852 return true;
30855 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30857 CPUMIPSState *env = cs->env_ptr;
30858 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30859 int insn_bytes;
30860 int is_slot;
30862 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
30863 if (ctx->insn_flags & ISA_NANOMIPS32) {
30864 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30865 insn_bytes = decode_nanomips_opc(env, ctx);
30866 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
30867 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30868 insn_bytes = 4;
30869 decode_opc(env, ctx);
30870 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30871 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30872 insn_bytes = decode_micromips_opc(env, ctx);
30873 } else if (ctx->insn_flags & ASE_MIPS16) {
30874 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30875 insn_bytes = decode_mips16_opc(env, ctx);
30876 } else {
30877 generate_exception_end(ctx, EXCP_RI);
30878 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30879 return;
30882 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30883 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30884 MIPS_HFLAG_FBNSLOT))) {
30886 * Force to generate branch as there is neither delay nor
30887 * forbidden slot.
30889 is_slot = 1;
30891 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30892 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
30894 * Force to generate branch as microMIPS R6 doesn't restrict
30895 * branches in the forbidden slot.
30897 is_slot = 1;
30900 if (is_slot) {
30901 gen_branch(ctx, insn_bytes);
30903 ctx->base.pc_next += insn_bytes;
30905 if (ctx->base.is_jmp != DISAS_NEXT) {
30906 return;
30909 * Execute a branch and its delay slot as a single instruction.
30910 * This is what GDB expects and is consistent with what the
30911 * hardware does (e.g. if a delay slot instruction faults, the
30912 * reported PC is the PC of the branch).
30914 if (ctx->base.singlestep_enabled &&
30915 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30916 ctx->base.is_jmp = DISAS_TOO_MANY;
30918 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30919 ctx->base.is_jmp = DISAS_TOO_MANY;
30923 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30925 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30927 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30928 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
30929 gen_helper_raise_exception_debug(cpu_env);
30930 } else {
30931 switch (ctx->base.is_jmp) {
30932 case DISAS_STOP:
30933 gen_save_pc(ctx->base.pc_next);
30934 tcg_gen_lookup_and_goto_ptr();
30935 break;
30936 case DISAS_NEXT:
30937 case DISAS_TOO_MANY:
30938 save_cpu_state(ctx, 0);
30939 gen_goto_tb(ctx, 0, ctx->base.pc_next);
30940 break;
30941 case DISAS_EXIT:
30942 tcg_gen_exit_tb(NULL, 0);
30943 break;
30944 case DISAS_NORETURN:
30945 break;
30946 default:
30947 g_assert_not_reached();
30952 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30954 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30955 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30958 static const TranslatorOps mips_tr_ops = {
30959 .init_disas_context = mips_tr_init_disas_context,
30960 .tb_start = mips_tr_tb_start,
30961 .insn_start = mips_tr_insn_start,
30962 .breakpoint_check = mips_tr_breakpoint_check,
30963 .translate_insn = mips_tr_translate_insn,
30964 .tb_stop = mips_tr_tb_stop,
30965 .disas_log = mips_tr_disas_log,
30968 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30970 DisasContext ctx;
30972 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
30975 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
30977 int i;
30978 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
30980 #define printfpr(fp) \
30981 do { \
30982 if (is_fpu64) \
30983 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30984 " fd:%13g fs:%13g psu: %13g\n", \
30985 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30986 (double)(fp)->fd, \
30987 (double)(fp)->fs[FP_ENDIAN_IDX], \
30988 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
30989 else { \
30990 fpr_t tmp; \
30991 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30992 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
30993 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30994 " fd:%13g fs:%13g psu:%13g\n", \
30995 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30996 (double)tmp.fd, \
30997 (double)tmp.fs[FP_ENDIAN_IDX], \
30998 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31000 } while (0)
31003 qemu_fprintf(f,
31004 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31005 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31006 get_float_exception_flags(&env->active_fpu.fp_status));
31007 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31008 qemu_fprintf(f, "%3s: ", fregnames[i]);
31009 printfpr(&env->active_fpu.fpr[i]);
31012 #undef printfpr
31015 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31017 MIPSCPU *cpu = MIPS_CPU(cs);
31018 CPUMIPSState *env = &cpu->env;
31019 int i;
31021 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31022 " LO=0x" TARGET_FMT_lx " ds %04x "
31023 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31024 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31025 env->hflags, env->btarget, env->bcond);
31026 for (i = 0; i < 32; i++) {
31027 if ((i & 3) == 0) {
31028 qemu_fprintf(f, "GPR%02d:", i);
31030 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31031 regnames[i], env->active_tc.gpr[i]);
31032 if ((i & 3) == 3) {
31033 qemu_fprintf(f, "\n");
31037 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31038 TARGET_FMT_lx "\n",
31039 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31040 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31041 PRIx64 "\n",
31042 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31043 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31044 env->CP0_Config2, env->CP0_Config3);
31045 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31046 env->CP0_Config4, env->CP0_Config5);
31047 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31048 fpu_dump_state(env, f, flags);
31052 void mips_tcg_init(void)
31054 int i;
31056 cpu_gpr[0] = NULL;
31057 for (i = 1; i < 32; i++)
31058 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31059 offsetof(CPUMIPSState,
31060 active_tc.gpr[i]),
31061 regnames[i]);
31063 for (i = 0; i < 32; i++) {
31064 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31065 msa_wr_d[i * 2] =
31066 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31068 * The scalar floating-point unit (FPU) registers are mapped on
31069 * the MSA vector registers.
31071 fpu_f64[i] = msa_wr_d[i * 2];
31072 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31073 msa_wr_d[i * 2 + 1] =
31074 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31077 cpu_PC = tcg_global_mem_new(cpu_env,
31078 offsetof(CPUMIPSState, active_tc.PC), "PC");
31079 for (i = 0; i < MIPS_DSP_ACC; i++) {
31080 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31081 offsetof(CPUMIPSState, active_tc.HI[i]),
31082 regnames_HI[i]);
31083 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31084 offsetof(CPUMIPSState, active_tc.LO[i]),
31085 regnames_LO[i]);
31087 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31088 offsetof(CPUMIPSState,
31089 active_tc.DSPControl),
31090 "DSPControl");
31091 bcond = tcg_global_mem_new(cpu_env,
31092 offsetof(CPUMIPSState, bcond), "bcond");
31093 btarget = tcg_global_mem_new(cpu_env,
31094 offsetof(CPUMIPSState, btarget), "btarget");
31095 hflags = tcg_global_mem_new_i32(cpu_env,
31096 offsetof(CPUMIPSState, hflags), "hflags");
31098 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31099 offsetof(CPUMIPSState, active_fpu.fcr0),
31100 "fcr0");
31101 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31102 offsetof(CPUMIPSState, active_fpu.fcr31),
31103 "fcr31");
31104 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31105 "lladdr");
31106 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31107 "llval");
31109 #if defined(TARGET_MIPS64)
31110 cpu_mmr[0] = NULL;
31111 for (i = 1; i < 32; i++) {
31112 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31113 offsetof(CPUMIPSState,
31114 active_tc.mmr[i]),
31115 regnames[i]);
31117 #endif
31119 #if !defined(TARGET_MIPS64)
31120 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31121 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31122 offsetof(CPUMIPSState,
31123 active_tc.mxu_gpr[i]),
31124 mxuregnames[i]);
31127 mxu_CR = tcg_global_mem_new(cpu_env,
31128 offsetof(CPUMIPSState, active_tc.mxu_cr),
31129 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31130 #endif
31133 #include "translate_init.inc.c"
31135 void cpu_mips_realize_env(CPUMIPSState *env)
31137 env->exception_base = (int32_t)0xBFC00000;
31139 #ifndef CONFIG_USER_ONLY
31140 mmu_init(env, env->cpu_model);
31141 #endif
31142 fpu_init(env, env->cpu_model);
31143 mvp_init(env, env->cpu_model);
31146 bool cpu_supports_cps_smp(const char *cpu_type)
31148 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31149 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
31152 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
31154 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31155 return (mcc->cpu_def->insn_flags & isa) != 0;
31158 void cpu_set_exception_base(int vp_index, target_ulong address)
31160 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31161 vp->env.exception_base = address;
31164 void cpu_state_reset(CPUMIPSState *env)
31166 CPUState *cs = env_cpu(env);
31168 /* Reset registers to their default values */
31169 env->CP0_PRid = env->cpu_model->CP0_PRid;
31170 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31171 #ifdef TARGET_WORDS_BIGENDIAN
31172 env->CP0_Config0 |= (1 << CP0C0_BE);
31173 #endif
31174 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31175 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31176 env->CP0_Config3 = env->cpu_model->CP0_Config3;
31177 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31178 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
31179 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31180 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
31181 env->CP0_Config6 = env->cpu_model->CP0_Config6;
31182 env->CP0_Config7 = env->cpu_model->CP0_Config7;
31183 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31184 << env->cpu_model->CP0_LLAddr_shift;
31185 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
31186 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31187 env->CCRes = env->cpu_model->CCRes;
31188 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31189 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31190 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31191 env->current_tc = 0;
31192 env->SEGBITS = env->cpu_model->SEGBITS;
31193 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31194 #if defined(TARGET_MIPS64)
31195 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31196 env->SEGMask |= 3ULL << 62;
31198 #endif
31199 env->PABITS = env->cpu_model->PABITS;
31200 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31201 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31202 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31203 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31204 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31205 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31206 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31207 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31208 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31209 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
31210 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31211 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
31212 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
31213 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
31214 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
31215 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
31216 env->msair = env->cpu_model->MSAIR;
31217 env->insn_flags = env->cpu_model->insn_flags;
31219 #if defined(CONFIG_USER_ONLY)
31220 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
31221 # ifdef TARGET_MIPS64
31222 /* Enable 64-bit register mode. */
31223 env->CP0_Status |= (1 << CP0St_PX);
31224 # endif
31225 # ifdef TARGET_ABI_MIPSN64
31226 /* Enable 64-bit address mode. */
31227 env->CP0_Status |= (1 << CP0St_UX);
31228 # endif
31230 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31231 * hardware registers.
31233 env->CP0_HWREna |= 0x0000000F;
31234 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
31235 env->CP0_Status |= (1 << CP0St_CU1);
31237 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31238 env->CP0_Status |= (1 << CP0St_MX);
31240 # if defined(TARGET_MIPS64)
31241 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31242 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31243 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
31244 env->CP0_Status |= (1 << CP0St_FR);
31246 # endif
31247 #else
31248 if (env->hflags & MIPS_HFLAG_BMASK) {
31250 * If the exception was raised from a delay slot,
31251 * come back to the jump.
31253 env->CP0_ErrorEPC = (env->active_tc.PC
31254 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
31255 } else {
31256 env->CP0_ErrorEPC = env->active_tc.PC;
31258 env->active_tc.PC = env->exception_base;
31259 env->CP0_Random = env->tlb->nb_tlb - 1;
31260 env->tlb->tlb_in_use = env->tlb->nb_tlb;
31261 env->CP0_Wired = 0;
31262 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
31263 env->CP0_EBase = (cs->cpu_index & 0x3FF);
31264 if (mips_um_ksegs_enabled()) {
31265 env->CP0_EBase |= 0x40000000;
31266 } else {
31267 env->CP0_EBase |= (int32_t)0x80000000;
31269 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31270 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31272 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
31273 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
31274 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
31276 * Vectored interrupts not implemented, timer on int 7,
31277 * no performance counters.
31279 env->CP0_IntCtl = 0xe0000000;
31281 int i;
31283 for (i = 0; i < 7; i++) {
31284 env->CP0_WatchLo[i] = 0;
31285 env->CP0_WatchHi[i] = 0x80000000;
31287 env->CP0_WatchLo[7] = 0;
31288 env->CP0_WatchHi[7] = 0;
31290 /* Count register increments in debug mode, EJTAG version 1 */
31291 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
31293 cpu_mips_store_count(env, 1);
31295 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31296 int i;
31298 /* Only TC0 on VPE 0 starts as active. */
31299 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
31300 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
31301 env->tcs[i].CP0_TCHalt = 1;
31303 env->active_tc.CP0_TCHalt = 1;
31304 cs->halted = 1;
31306 if (cs->cpu_index == 0) {
31307 /* VPE0 starts up enabled. */
31308 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31309 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31311 /* TC0 starts up unhalted. */
31312 cs->halted = 0;
31313 env->active_tc.CP0_TCHalt = 0;
31314 env->tcs[0].CP0_TCHalt = 0;
31315 /* With thread 0 active. */
31316 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31317 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31322 * Configure default legacy segmentation control. We use this regardless of
31323 * whether segmentation control is presented to the guest.
31325 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31326 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31327 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31328 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31329 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31330 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31331 (2 << CP0SC_C);
31332 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31333 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31334 (3 << CP0SC_C)) << 16;
31335 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31336 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31337 (1 << CP0SC_EU) | (2 << CP0SC_C);
31338 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31339 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31340 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31341 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31342 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
31343 #endif
31344 if ((env->insn_flags & ISA_MIPS32R6) &&
31345 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31346 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31347 env->CP0_Status |= (1 << CP0St_FR);
31350 if (env->insn_flags & ISA_MIPS32R6) {
31351 /* PTW = 1 */
31352 env->CP0_PWSize = 0x40;
31353 /* GDI = 12 */
31354 /* UDI = 12 */
31355 /* MDI = 12 */
31356 /* PRI = 12 */
31357 /* PTEI = 2 */
31358 env->CP0_PWField = 0x0C30C302;
31359 } else {
31360 /* GDI = 0 */
31361 /* UDI = 0 */
31362 /* MDI = 0 */
31363 /* PRI = 0 */
31364 /* PTEI = 2 */
31365 env->CP0_PWField = 0x02;
31368 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31369 /* microMIPS on reset when Config3.ISA is 3 */
31370 env->hflags |= MIPS_HFLAG_M16;
31373 /* MSA */
31374 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
31375 msa_reset(env);
31378 compute_hflags(env);
31379 restore_fp_status(env);
31380 restore_pamask(env);
31381 cs->exception_index = EXCP_NONE;
31383 if (semihosting_get_argc()) {
31384 /* UHI interface can be used to obtain argc and argv */
31385 env->active_tc.gpr[4] = -1;
31389 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31390 target_ulong *data)
31392 env->active_tc.PC = data[0];
31393 env->hflags &= ~MIPS_HFLAG_BMASK;
31394 env->hflags |= data[1];
31395 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31396 case MIPS_HFLAG_BR:
31397 break;
31398 case MIPS_HFLAG_BC:
31399 case MIPS_HFLAG_BL:
31400 case MIPS_HFLAG_B:
31401 env->btarget = data[2];
31402 break;