Convert "translator internals" docs to RST, move to devel manual
[qemu/ar7.git] / target / mips / translate.c
bloba3cf976ab6508335beff9b1f18e134ee2dcbf2ed
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-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,
262 /* R6 Multiply and Divide instructions have the same Opcode
263 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
264 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
266 enum {
267 R6_OPC_MUL = OPC_MULT | (2 << 6),
268 R6_OPC_MUH = OPC_MULT | (3 << 6),
269 R6_OPC_MULU = OPC_MULTU | (2 << 6),
270 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
271 R6_OPC_DIV = OPC_DIV | (2 << 6),
272 R6_OPC_MOD = OPC_DIV | (3 << 6),
273 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
274 R6_OPC_MODU = OPC_DIVU | (3 << 6),
276 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
277 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
278 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
279 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
280 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
281 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
282 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
283 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
285 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
286 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
287 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
288 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
289 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
291 OPC_LSA = 0x05 | OPC_SPECIAL,
292 OPC_DLSA = 0x15 | OPC_SPECIAL,
295 /* Multiplication variants of the vr54xx. */
296 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
298 enum {
299 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
300 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
301 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
302 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
303 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
304 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
305 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
306 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
308 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
309 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
310 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
311 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
312 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
315 /* REGIMM (rt field) opcodes */
316 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
318 enum {
319 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
320 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
321 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
322 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
323 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
324 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
325 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
326 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
327 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
328 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
329 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
330 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
331 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
332 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
333 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
334 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
336 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
337 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
340 /* Special2 opcodes */
341 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
343 enum {
344 /* Multiply & xxx operations */
345 OPC_MADD = 0x00 | OPC_SPECIAL2,
346 OPC_MADDU = 0x01 | OPC_SPECIAL2,
347 OPC_MUL = 0x02 | OPC_SPECIAL2,
348 OPC_MSUB = 0x04 | OPC_SPECIAL2,
349 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
350 /* Loongson 2F */
351 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
352 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
353 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
354 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
355 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
356 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
357 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
358 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
359 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
360 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
361 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
362 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
363 /* Misc */
364 OPC_CLZ = 0x20 | OPC_SPECIAL2,
365 OPC_CLO = 0x21 | OPC_SPECIAL2,
366 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
367 OPC_DCLO = 0x25 | OPC_SPECIAL2,
368 /* Special */
369 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
372 /* Special3 opcodes */
373 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
375 enum {
376 OPC_EXT = 0x00 | OPC_SPECIAL3,
377 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
378 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
379 OPC_DEXT = 0x03 | OPC_SPECIAL3,
380 OPC_INS = 0x04 | OPC_SPECIAL3,
381 OPC_DINSM = 0x05 | OPC_SPECIAL3,
382 OPC_DINSU = 0x06 | OPC_SPECIAL3,
383 OPC_DINS = 0x07 | OPC_SPECIAL3,
384 OPC_FORK = 0x08 | OPC_SPECIAL3,
385 OPC_YIELD = 0x09 | OPC_SPECIAL3,
386 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
387 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
388 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
390 /* Loongson 2E */
391 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
392 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
393 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
394 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
395 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
396 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
397 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
398 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
399 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
400 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
401 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
402 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
404 /* MIPS DSP Load */
405 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
406 /* MIPS DSP Arithmetic */
407 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
408 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
409 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
410 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
411 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
412 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
413 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
414 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
415 /* MIPS DSP GPR-Based Shift Sub-class */
416 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
417 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
418 /* MIPS DSP Multiply Sub-class insns */
419 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
420 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
421 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
422 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
423 /* DSP Bit/Manipulation Sub-class */
424 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
425 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
426 /* MIPS DSP Append Sub-class */
427 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
428 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
429 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
430 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
431 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
433 /* EVA */
434 OPC_LWLE = 0x19 | OPC_SPECIAL3,
435 OPC_LWRE = 0x1A | OPC_SPECIAL3,
436 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
437 OPC_SBE = 0x1C | OPC_SPECIAL3,
438 OPC_SHE = 0x1D | OPC_SPECIAL3,
439 OPC_SCE = 0x1E | OPC_SPECIAL3,
440 OPC_SWE = 0x1F | OPC_SPECIAL3,
441 OPC_SWLE = 0x21 | OPC_SPECIAL3,
442 OPC_SWRE = 0x22 | OPC_SPECIAL3,
443 OPC_PREFE = 0x23 | OPC_SPECIAL3,
444 OPC_LBUE = 0x28 | OPC_SPECIAL3,
445 OPC_LHUE = 0x29 | OPC_SPECIAL3,
446 OPC_LBE = 0x2C | OPC_SPECIAL3,
447 OPC_LHE = 0x2D | OPC_SPECIAL3,
448 OPC_LLE = 0x2E | OPC_SPECIAL3,
449 OPC_LWE = 0x2F | OPC_SPECIAL3,
451 /* R6 */
452 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
453 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
454 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
455 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
456 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
457 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
460 /* BSHFL opcodes */
461 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
463 enum {
464 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
465 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
466 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
467 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
468 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
469 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
470 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
471 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
474 /* DBSHFL opcodes */
475 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
477 enum {
478 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
479 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
480 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
481 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
482 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
483 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
484 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
485 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
486 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
487 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
488 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
491 /* MIPS DSP REGIMM opcodes */
492 enum {
493 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
494 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
497 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 /* MIPS DSP Load */
499 enum {
500 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
501 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
502 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
503 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
506 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
507 enum {
508 /* MIPS DSP Arithmetic Sub-class */
509 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
524 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
525 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
526 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
527 /* MIPS DSP Multiply Sub-class insns */
528 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
536 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
537 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
538 enum {
539 /* MIPS DSP Arithmetic Sub-class */
540 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
552 /* MIPS DSP Multiply Sub-class insns */
553 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
556 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
559 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
560 enum {
561 /* MIPS DSP Arithmetic Sub-class */
562 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
575 /* DSP Bit/Manipulation Sub-class */
576 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
583 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
584 enum {
585 /* MIPS DSP Arithmetic Sub-class */
586 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
593 /* DSP Compare-Pick Sub-class */
594 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
611 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
612 enum {
613 /* MIPS DSP GPR-Based Shift Sub-class */
614 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
638 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
639 enum {
640 /* MIPS DSP Multiply Sub-class insns */
641 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
655 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
657 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
665 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
666 enum {
667 /* DSP Bit/Manipulation Sub-class */
668 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
671 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Append Sub-class */
674 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
675 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
676 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
679 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
680 enum {
681 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
682 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
695 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
696 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
697 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
698 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
701 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
702 enum {
703 /* MIPS DSP Arithmetic Sub-class */
704 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
721 /* DSP Bit/Manipulation Sub-class */
722 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
730 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
731 enum {
732 /* MIPS DSP Multiply Sub-class insns */
733 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
738 /* MIPS DSP Arithmetic Sub-class */
739 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
762 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
763 enum {
764 /* DSP Compare-Pick Sub-class */
765 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
784 /* MIPS DSP Arithmetic Sub-class */
785 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
795 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Append Sub-class */
798 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
800 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
801 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
804 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
805 enum {
806 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
807 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
808 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
827 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
830 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
831 enum {
832 /* DSP Bit/Manipulation Sub-class */
833 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
836 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
837 enum {
838 /* MIPS DSP Multiply Sub-class insns */
839 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
867 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
868 enum {
869 /* MIPS DSP GPR-Based Shift Sub-class */
870 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
898 /* Coprocessor 0 (rs field) */
899 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
901 enum {
902 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
903 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
904 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
905 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
906 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
907 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
908 OPC_MFTR = (0x08 << 21) | OPC_CP0,
909 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
910 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
911 OPC_MTTR = (0x0C << 21) | OPC_CP0,
912 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
913 OPC_C0 = (0x10 << 21) | OPC_CP0,
914 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
915 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
916 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
917 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
918 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
919 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
920 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
921 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
922 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
923 OPC_C0_A = (0x1A << 21) | OPC_CP0,
924 OPC_C0_B = (0x1B << 21) | OPC_CP0,
925 OPC_C0_C = (0x1C << 21) | OPC_CP0,
926 OPC_C0_D = (0x1D << 21) | OPC_CP0,
927 OPC_C0_E = (0x1E << 21) | OPC_CP0,
928 OPC_C0_F = (0x1F << 21) | OPC_CP0,
931 /* MFMC0 opcodes */
932 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
934 enum {
935 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
937 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
938 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
939 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
941 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
942 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
945 /* Coprocessor 0 (with rs == C0) */
946 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
948 enum {
949 OPC_TLBR = 0x01 | OPC_C0,
950 OPC_TLBWI = 0x02 | OPC_C0,
951 OPC_TLBINV = 0x03 | OPC_C0,
952 OPC_TLBINVF = 0x04 | OPC_C0,
953 OPC_TLBWR = 0x06 | OPC_C0,
954 OPC_TLBP = 0x08 | OPC_C0,
955 OPC_RFE = 0x10 | OPC_C0,
956 OPC_ERET = 0x18 | OPC_C0,
957 OPC_DERET = 0x1F | OPC_C0,
958 OPC_WAIT = 0x20 | OPC_C0,
961 /* Coprocessor 1 (rs field) */
962 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
964 /* Values for the fmt field in FP instructions */
965 enum {
966 /* 0 - 15 are reserved */
967 FMT_S = 16, /* single fp */
968 FMT_D = 17, /* double fp */
969 FMT_E = 18, /* extended fp */
970 FMT_Q = 19, /* quad fp */
971 FMT_W = 20, /* 32-bit fixed */
972 FMT_L = 21, /* 64-bit fixed */
973 FMT_PS = 22, /* paired single fp */
974 /* 23 - 31 are reserved */
977 enum {
978 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
979 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
980 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
981 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
982 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
983 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
984 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
985 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
986 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
987 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
988 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
989 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
990 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
991 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
992 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
993 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
994 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
995 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
996 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
997 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
998 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
999 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1000 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1001 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1002 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1003 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1004 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1005 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1006 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1007 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1010 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1011 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1013 enum {
1014 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1015 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1016 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1017 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1020 enum {
1021 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1022 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1025 enum {
1026 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1027 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1030 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1032 enum {
1033 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1034 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1035 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1036 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1037 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1038 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1039 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1040 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1041 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1042 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1043 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1046 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1048 enum {
1049 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1058 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1070 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1071 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1072 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1073 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1074 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1076 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1079 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1085 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1086 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1092 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1099 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1113 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1114 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1115 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1116 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1118 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1121 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1122 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1123 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1125 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1128 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1130 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1132 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1135 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1136 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1137 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1138 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1139 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1143 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1145 enum {
1146 OPC_LWXC1 = 0x00 | OPC_CP3,
1147 OPC_LDXC1 = 0x01 | OPC_CP3,
1148 OPC_LUXC1 = 0x05 | OPC_CP3,
1149 OPC_SWXC1 = 0x08 | OPC_CP3,
1150 OPC_SDXC1 = 0x09 | OPC_CP3,
1151 OPC_SUXC1 = 0x0D | OPC_CP3,
1152 OPC_PREFX = 0x0F | OPC_CP3,
1153 OPC_ALNV_PS = 0x1E | OPC_CP3,
1154 OPC_MADD_S = 0x20 | OPC_CP3,
1155 OPC_MADD_D = 0x21 | OPC_CP3,
1156 OPC_MADD_PS = 0x26 | OPC_CP3,
1157 OPC_MSUB_S = 0x28 | OPC_CP3,
1158 OPC_MSUB_D = 0x29 | OPC_CP3,
1159 OPC_MSUB_PS = 0x2E | OPC_CP3,
1160 OPC_NMADD_S = 0x30 | OPC_CP3,
1161 OPC_NMADD_D = 0x31 | OPC_CP3,
1162 OPC_NMADD_PS= 0x36 | OPC_CP3,
1163 OPC_NMSUB_S = 0x38 | OPC_CP3,
1164 OPC_NMSUB_D = 0x39 | OPC_CP3,
1165 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1168 /* MSA Opcodes */
1169 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1170 enum {
1171 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1172 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1173 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1174 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1175 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1176 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1177 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1178 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1179 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1180 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1181 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1182 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1183 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1184 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1185 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1186 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1187 OPC_MSA_ELM = 0x19 | OPC_MSA,
1188 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1189 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1190 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1191 OPC_MSA_VEC = 0x1E | OPC_MSA,
1193 /* MI10 instruction */
1194 OPC_LD_B = (0x20) | OPC_MSA,
1195 OPC_LD_H = (0x21) | OPC_MSA,
1196 OPC_LD_W = (0x22) | OPC_MSA,
1197 OPC_LD_D = (0x23) | OPC_MSA,
1198 OPC_ST_B = (0x24) | OPC_MSA,
1199 OPC_ST_H = (0x25) | OPC_MSA,
1200 OPC_ST_W = (0x26) | OPC_MSA,
1201 OPC_ST_D = (0x27) | OPC_MSA,
1204 enum {
1205 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1206 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1207 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1208 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1209 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1210 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1211 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1212 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1213 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1214 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1215 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1216 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1217 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1219 /* I8 instruction */
1220 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1221 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1222 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1223 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1224 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1225 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1226 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1227 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1228 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1229 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1231 /* VEC/2R/2RF instruction */
1232 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1233 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1234 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1235 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1236 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1237 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1238 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1241 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1243 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1244 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1245 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1246 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1247 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1249 /* 2RF instruction df(bit 16) = _w, _d */
1250 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1252 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1253 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1254 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1255 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1256 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1257 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1259 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1260 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1261 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1263 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1265 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1267 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1268 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1269 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1270 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1271 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1272 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1273 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1274 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1275 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1276 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1277 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1278 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1279 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1281 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1282 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1283 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1284 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1285 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1290 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1291 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1292 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1293 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1294 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1295 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1296 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1297 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1298 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1299 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1300 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1301 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1310 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1311 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1312 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1313 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1314 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1315 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1316 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1317 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1318 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1319 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1320 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1321 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1322 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1323 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1324 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1325 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1326 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1327 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1328 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1329 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1330 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1332 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1333 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1335 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1336 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1337 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1338 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1339 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 /* 3RF instruction _df(bit 21) = _w, _d */
1344 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1345 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1346 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1348 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1351 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1353 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1354 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1355 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1356 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1357 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1358 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1360 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1361 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1362 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1363 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1364 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1365 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1366 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1367 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1368 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1369 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1370 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1371 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1372 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1373 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1376 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1377 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1378 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1379 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1380 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1381 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1382 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1383 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1384 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1386 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1387 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1388 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1389 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1390 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1391 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1392 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1393 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1394 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1395 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1396 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1398 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1404 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1405 * ============================================
1408 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1409 * instructions set. It is designed to fit the needs of signal, graphical and
1410 * video processing applications. MXU instruction set is used in Xburst family
1411 * of microprocessors by Ingenic.
1413 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1414 * the control register.
1417 * The notation used in MXU assembler mnemonics
1418 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1420 * Register operands:
1422 * XRa, XRb, XRc, XRd - MXU registers
1423 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1425 * Non-register operands:
1427 * aptn1 - 1-bit accumulate add/subtract pattern
1428 * aptn2 - 2-bit accumulate add/subtract pattern
1429 * eptn2 - 2-bit execute add/subtract pattern
1430 * optn2 - 2-bit operand pattern
1431 * optn3 - 3-bit operand pattern
1432 * sft4 - 4-bit shift amount
1433 * strd2 - 2-bit stride amount
1435 * Prefixes:
1437 * Level of parallelism: Operand size:
1438 * S - single operation at a time 32 - word
1439 * D - two operations in parallel 16 - half word
1440 * Q - four operations in parallel 8 - byte
1442 * Operations:
1444 * ADD - Add or subtract
1445 * ADDC - Add with carry-in
1446 * ACC - Accumulate
1447 * ASUM - Sum together then accumulate (add or subtract)
1448 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1449 * AVG - Average between 2 operands
1450 * ABD - Absolute difference
1451 * ALN - Align data
1452 * AND - Logical bitwise 'and' operation
1453 * CPS - Copy sign
1454 * EXTR - Extract bits
1455 * I2M - Move from GPR register to MXU register
1456 * LDD - Load data from memory to XRF
1457 * LDI - Load data from memory to XRF (and increase the address base)
1458 * LUI - Load unsigned immediate
1459 * MUL - Multiply
1460 * MULU - Unsigned multiply
1461 * MADD - 64-bit operand add 32x32 product
1462 * MSUB - 64-bit operand subtract 32x32 product
1463 * MAC - Multiply and accumulate (add or subtract)
1464 * MAD - Multiply and add or subtract
1465 * MAX - Maximum between 2 operands
1466 * MIN - Minimum between 2 operands
1467 * M2I - Move from MXU register to GPR register
1468 * MOVZ - Move if zero
1469 * MOVN - Move if non-zero
1470 * NOR - Logical bitwise 'nor' operation
1471 * OR - Logical bitwise 'or' operation
1472 * STD - Store data from XRF to memory
1473 * SDI - Store data from XRF to memory (and increase the address base)
1474 * SLT - Set of less than comparison
1475 * SAD - Sum of absolute differences
1476 * SLL - Logical shift left
1477 * SLR - Logical shift right
1478 * SAR - Arithmetic shift right
1479 * SAT - Saturation
1480 * SFL - Shuffle
1481 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1482 * XOR - Logical bitwise 'exclusive or' operation
1484 * Suffixes:
1486 * E - Expand results
1487 * F - Fixed point multiplication
1488 * L - Low part result
1489 * R - Doing rounding
1490 * V - Variable instead of immediate
1491 * W - Combine above L and V
1494 * The list of MXU instructions grouped by functionality
1495 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1497 * Load/Store instructions Multiplication instructions
1498 * ----------------------- ---------------------------
1500 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1501 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1502 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1503 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1504 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1505 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1506 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1507 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1508 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1509 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1510 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1511 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1514 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1515 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1516 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1517 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1518 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1519 * S16SDI XRa, Rb, s10, eptn2
1520 * S8LDD XRa, Rb, s8, eptn3
1521 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1522 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1523 * S8SDI XRa, Rb, s8, eptn3
1524 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1525 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1526 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1527 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1528 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1529 * S32CPS XRa, XRb, XRc
1530 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1531 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1532 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1533 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1534 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1535 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1536 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1537 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1538 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1539 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1540 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1541 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1542 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1543 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1544 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1545 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1546 * Q8SLT XRa, XRb, XRc
1547 * Q8SLTU XRa, XRb, XRc
1548 * Q8MOVZ XRa, XRb, XRc Shift instructions
1549 * Q8MOVN XRa, XRb, XRc ------------------
1551 * D32SLL XRa, XRb, XRc, XRd, sft4
1552 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1553 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1554 * D32SARL XRa, XRb, XRc, sft4
1555 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1556 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1557 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1558 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1559 * Q16SLL XRa, XRb, XRc, XRd, sft4
1560 * Q16SLR XRa, XRb, XRc, XRd, sft4
1561 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1562 * ------------------------- Q16SLLV XRa, XRb, Rb
1563 * Q16SLRV XRa, XRb, Rb
1564 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1565 * S32ALN XRa, XRb, XRc, Rb
1566 * S32ALNI XRa, XRb, XRc, s3
1567 * S32LUI XRa, s8, optn3 Move instructions
1568 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1569 * S32EXTRV XRa, XRb, Rs, Rt
1570 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1571 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1574 * The opcode organization of MXU instructions
1575 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1577 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1578 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1579 * other bits up to the instruction level is as follows:
1581 * bits
1582 * 05..00
1584 * ┌─ 000000 ─ OPC_MXU_S32MADD
1585 * ├─ 000001 ─ OPC_MXU_S32MADDU
1586 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1587 * │
1588 * │ 20..18
1589 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1590 * │ ├─ 001 ─ OPC_MXU_S32MIN
1591 * │ ├─ 010 ─ OPC_MXU_D16MAX
1592 * │ ├─ 011 ─ OPC_MXU_D16MIN
1593 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1594 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1595 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1596 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1597 * ├─ 000100 ─ OPC_MXU_S32MSUB
1598 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1599 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1600 * │ ├─ 001 ─ OPC_MXU_D16SLT
1601 * │ ├─ 010 ─ OPC_MXU_D16AVG
1602 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1603 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1604 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1605 * │ └─ 111 ─ OPC_MXU_Q8ADD
1606 * │
1607 * │ 20..18
1608 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1609 * │ ├─ 010 ─ OPC_MXU_D16CPS
1610 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1611 * │ └─ 110 ─ OPC_MXU_Q16SAT
1612 * ├─ 001000 ─ OPC_MXU_D16MUL
1613 * │ 25..24
1614 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1615 * │ └─ 01 ─ OPC_MXU_D16MULE
1616 * ├─ 001010 ─ OPC_MXU_D16MAC
1617 * ├─ 001011 ─ OPC_MXU_D16MACF
1618 * ├─ 001100 ─ OPC_MXU_D16MADL
1619 * ├─ 001101 ─ OPC_MXU_S16MAD
1620 * ├─ 001110 ─ OPC_MXU_Q16ADD
1621 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1622 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1623 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1624 * │
1625 * │ 23
1626 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1627 * │ └─ 1 ─ OPC_MXU_S32STDR
1628 * │
1629 * │ 13..10
1630 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1631 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1632 * │
1633 * │ 13..10
1634 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1635 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1636 * │
1637 * │ 23
1638 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1639 * │ └─ 1 ─ OPC_MXU_S32LDIR
1640 * │
1641 * │ 23
1642 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1643 * │ └─ 1 ─ OPC_MXU_S32SDIR
1644 * │
1645 * │ 13..10
1646 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1647 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1648 * │
1649 * │ 13..10
1650 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1651 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1652 * ├─ 011000 ─ OPC_MXU_D32ADD
1653 * │ 23..22
1654 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1655 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1656 * │ └─ 10 ─ OPC_MXU_D32ASUM
1657 * ├─ 011010 ─ <not assigned>
1658 * │ 23..22
1659 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1660 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1661 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1662 * │
1663 * │ 23..22
1664 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1665 * │ ├─ 01 ─ OPC_MXU_D8SUM
1666 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1667 * ├─ 011110 ─ <not assigned>
1668 * ├─ 011111 ─ <not assigned>
1669 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1670 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1671 * ├─ 100010 ─ OPC_MXU_S8LDD
1672 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1673 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1674 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1675 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1676 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1677 * │
1678 * │ 20..18
1679 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1680 * │ ├─ 001 ─ OPC_MXU_S32ALN
1681 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1682 * │ ├─ 011 ─ OPC_MXU_S32LUI
1683 * │ ├─ 100 ─ OPC_MXU_S32NOR
1684 * │ ├─ 101 ─ OPC_MXU_S32AND
1685 * │ ├─ 110 ─ OPC_MXU_S32OR
1686 * │ └─ 111 ─ OPC_MXU_S32XOR
1687 * │
1688 * │ 7..5
1689 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1690 * │ ├─ 001 ─ OPC_MXU_LXH
1691 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1692 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1693 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1694 * ├─ 101100 ─ OPC_MXU_S16LDI
1695 * ├─ 101101 ─ OPC_MXU_S16SDI
1696 * ├─ 101110 ─ OPC_MXU_S32M2I
1697 * ├─ 101111 ─ OPC_MXU_S32I2M
1698 * ├─ 110000 ─ OPC_MXU_D32SLL
1699 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1700 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1701 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1702 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1703 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1704 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1705 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1706 * │
1707 * ├─ 110111 ─ OPC_MXU_Q16SAR
1708 * │ 23..22
1709 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1710 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1711 * │
1712 * │ 20..18
1713 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1714 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1715 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1716 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1717 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1718 * │ └─ 101 ─ OPC_MXU_S32MOVN
1719 * │
1720 * │ 23..22
1721 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1722 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1723 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1724 * ├─ 111100 ─ OPC_MXU_Q8MADL
1725 * ├─ 111101 ─ OPC_MXU_S32SFL
1726 * ├─ 111110 ─ OPC_MXU_Q8SAD
1727 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1730 * Compiled after:
1732 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1733 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1736 enum {
1737 OPC_MXU_S32MADD = 0x00,
1738 OPC_MXU_S32MADDU = 0x01,
1739 OPC__MXU_MUL = 0x02,
1740 OPC_MXU__POOL00 = 0x03,
1741 OPC_MXU_S32MSUB = 0x04,
1742 OPC_MXU_S32MSUBU = 0x05,
1743 OPC_MXU__POOL01 = 0x06,
1744 OPC_MXU__POOL02 = 0x07,
1745 OPC_MXU_D16MUL = 0x08,
1746 OPC_MXU__POOL03 = 0x09,
1747 OPC_MXU_D16MAC = 0x0A,
1748 OPC_MXU_D16MACF = 0x0B,
1749 OPC_MXU_D16MADL = 0x0C,
1750 OPC_MXU_S16MAD = 0x0D,
1751 OPC_MXU_Q16ADD = 0x0E,
1752 OPC_MXU_D16MACE = 0x0F,
1753 OPC_MXU__POOL04 = 0x10,
1754 OPC_MXU__POOL05 = 0x11,
1755 OPC_MXU__POOL06 = 0x12,
1756 OPC_MXU__POOL07 = 0x13,
1757 OPC_MXU__POOL08 = 0x14,
1758 OPC_MXU__POOL09 = 0x15,
1759 OPC_MXU__POOL10 = 0x16,
1760 OPC_MXU__POOL11 = 0x17,
1761 OPC_MXU_D32ADD = 0x18,
1762 OPC_MXU__POOL12 = 0x19,
1763 /* not assigned 0x1A */
1764 OPC_MXU__POOL13 = 0x1B,
1765 OPC_MXU__POOL14 = 0x1C,
1766 OPC_MXU_Q8ACCE = 0x1D,
1767 /* not assigned 0x1E */
1768 /* not assigned 0x1F */
1769 /* not assigned 0x20 */
1770 /* not assigned 0x21 */
1771 OPC_MXU_S8LDD = 0x22,
1772 OPC_MXU_S8STD = 0x23,
1773 OPC_MXU_S8LDI = 0x24,
1774 OPC_MXU_S8SDI = 0x25,
1775 OPC_MXU__POOL15 = 0x26,
1776 OPC_MXU__POOL16 = 0x27,
1777 OPC_MXU__POOL17 = 0x28,
1778 /* not assigned 0x29 */
1779 OPC_MXU_S16LDD = 0x2A,
1780 OPC_MXU_S16STD = 0x2B,
1781 OPC_MXU_S16LDI = 0x2C,
1782 OPC_MXU_S16SDI = 0x2D,
1783 OPC_MXU_S32M2I = 0x2E,
1784 OPC_MXU_S32I2M = 0x2F,
1785 OPC_MXU_D32SLL = 0x30,
1786 OPC_MXU_D32SLR = 0x31,
1787 OPC_MXU_D32SARL = 0x32,
1788 OPC_MXU_D32SAR = 0x33,
1789 OPC_MXU_Q16SLL = 0x34,
1790 OPC_MXU_Q16SLR = 0x35,
1791 OPC_MXU__POOL18 = 0x36,
1792 OPC_MXU_Q16SAR = 0x37,
1793 OPC_MXU__POOL19 = 0x38,
1794 OPC_MXU__POOL20 = 0x39,
1795 OPC_MXU__POOL21 = 0x3A,
1796 OPC_MXU_Q16SCOP = 0x3B,
1797 OPC_MXU_Q8MADL = 0x3C,
1798 OPC_MXU_S32SFL = 0x3D,
1799 OPC_MXU_Q8SAD = 0x3E,
1800 /* not assigned 0x3F */
1805 * MXU pool 00
1807 enum {
1808 OPC_MXU_S32MAX = 0x00,
1809 OPC_MXU_S32MIN = 0x01,
1810 OPC_MXU_D16MAX = 0x02,
1811 OPC_MXU_D16MIN = 0x03,
1812 OPC_MXU_Q8MAX = 0x04,
1813 OPC_MXU_Q8MIN = 0x05,
1814 OPC_MXU_Q8SLT = 0x06,
1815 OPC_MXU_Q8SLTU = 0x07,
1819 * MXU pool 01
1821 enum {
1822 OPC_MXU_S32SLT = 0x00,
1823 OPC_MXU_D16SLT = 0x01,
1824 OPC_MXU_D16AVG = 0x02,
1825 OPC_MXU_D16AVGR = 0x03,
1826 OPC_MXU_Q8AVG = 0x04,
1827 OPC_MXU_Q8AVGR = 0x05,
1828 OPC_MXU_Q8ADD = 0x07,
1832 * MXU pool 02
1834 enum {
1835 OPC_MXU_S32CPS = 0x00,
1836 OPC_MXU_D16CPS = 0x02,
1837 OPC_MXU_Q8ABD = 0x04,
1838 OPC_MXU_Q16SAT = 0x06,
1842 * MXU pool 03
1844 enum {
1845 OPC_MXU_D16MULF = 0x00,
1846 OPC_MXU_D16MULE = 0x01,
1850 * MXU pool 04
1852 enum {
1853 OPC_MXU_S32LDD = 0x00,
1854 OPC_MXU_S32LDDR = 0x01,
1858 * MXU pool 05
1860 enum {
1861 OPC_MXU_S32STD = 0x00,
1862 OPC_MXU_S32STDR = 0x01,
1866 * MXU pool 06
1868 enum {
1869 OPC_MXU_S32LDDV = 0x00,
1870 OPC_MXU_S32LDDVR = 0x01,
1874 * MXU pool 07
1876 enum {
1877 OPC_MXU_S32STDV = 0x00,
1878 OPC_MXU_S32STDVR = 0x01,
1882 * MXU pool 08
1884 enum {
1885 OPC_MXU_S32LDI = 0x00,
1886 OPC_MXU_S32LDIR = 0x01,
1890 * MXU pool 09
1892 enum {
1893 OPC_MXU_S32SDI = 0x00,
1894 OPC_MXU_S32SDIR = 0x01,
1898 * MXU pool 10
1900 enum {
1901 OPC_MXU_S32LDIV = 0x00,
1902 OPC_MXU_S32LDIVR = 0x01,
1906 * MXU pool 11
1908 enum {
1909 OPC_MXU_S32SDIV = 0x00,
1910 OPC_MXU_S32SDIVR = 0x01,
1914 * MXU pool 12
1916 enum {
1917 OPC_MXU_D32ACC = 0x00,
1918 OPC_MXU_D32ACCM = 0x01,
1919 OPC_MXU_D32ASUM = 0x02,
1923 * MXU pool 13
1925 enum {
1926 OPC_MXU_Q16ACC = 0x00,
1927 OPC_MXU_Q16ACCM = 0x01,
1928 OPC_MXU_Q16ASUM = 0x02,
1932 * MXU pool 14
1934 enum {
1935 OPC_MXU_Q8ADDE = 0x00,
1936 OPC_MXU_D8SUM = 0x01,
1937 OPC_MXU_D8SUMC = 0x02,
1941 * MXU pool 15
1943 enum {
1944 OPC_MXU_S32MUL = 0x00,
1945 OPC_MXU_S32MULU = 0x01,
1946 OPC_MXU_S32EXTR = 0x02,
1947 OPC_MXU_S32EXTRV = 0x03,
1951 * MXU pool 16
1953 enum {
1954 OPC_MXU_D32SARW = 0x00,
1955 OPC_MXU_S32ALN = 0x01,
1956 OPC_MXU_S32ALNI = 0x02,
1957 OPC_MXU_S32LUI = 0x03,
1958 OPC_MXU_S32NOR = 0x04,
1959 OPC_MXU_S32AND = 0x05,
1960 OPC_MXU_S32OR = 0x06,
1961 OPC_MXU_S32XOR = 0x07,
1965 * MXU pool 17
1967 enum {
1968 OPC_MXU_LXB = 0x00,
1969 OPC_MXU_LXH = 0x01,
1970 OPC_MXU_LXW = 0x03,
1971 OPC_MXU_LXBU = 0x04,
1972 OPC_MXU_LXHU = 0x05,
1976 * MXU pool 18
1978 enum {
1979 OPC_MXU_D32SLLV = 0x00,
1980 OPC_MXU_D32SLRV = 0x01,
1981 OPC_MXU_D32SARV = 0x03,
1982 OPC_MXU_Q16SLLV = 0x04,
1983 OPC_MXU_Q16SLRV = 0x05,
1984 OPC_MXU_Q16SARV = 0x07,
1988 * MXU pool 19
1990 enum {
1991 OPC_MXU_Q8MUL = 0x00,
1992 OPC_MXU_Q8MULSU = 0x01,
1996 * MXU pool 20
1998 enum {
1999 OPC_MXU_Q8MOVZ = 0x00,
2000 OPC_MXU_Q8MOVN = 0x01,
2001 OPC_MXU_D16MOVZ = 0x02,
2002 OPC_MXU_D16MOVN = 0x03,
2003 OPC_MXU_S32MOVZ = 0x04,
2004 OPC_MXU_S32MOVN = 0x05,
2008 * MXU pool 21
2010 enum {
2011 OPC_MXU_Q8MAC = 0x00,
2012 OPC_MXU_Q8MACSU = 0x01,
2016 * Overview of the TX79-specific instruction set
2017 * =============================================
2019 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2020 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2021 * instructions and certain multimedia instructions (MMIs). These MMIs
2022 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2023 * or sixteen 8-bit paths.
2025 * Reference:
2027 * The Toshiba TX System RISC TX79 Core Architecture manual,
2028 * https://wiki.qemu.org/File:C790.pdf
2030 * Three-Operand Multiply and Multiply-Add (4 instructions)
2031 * --------------------------------------------------------
2032 * MADD [rd,] rs, rt Multiply/Add
2033 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2034 * MULT [rd,] rs, rt Multiply (3-operand)
2035 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2037 * Multiply Instructions for Pipeline 1 (10 instructions)
2038 * ------------------------------------------------------
2039 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2040 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2041 * DIV1 rs, rt Divide Pipeline 1
2042 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2043 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2044 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2045 * MFHI1 rd Move From HI1 Register
2046 * MFLO1 rd Move From LO1 Register
2047 * MTHI1 rs Move To HI1 Register
2048 * MTLO1 rs Move To LO1 Register
2050 * Arithmetic (19 instructions)
2051 * ----------------------------
2052 * PADDB rd, rs, rt Parallel Add Byte
2053 * PSUBB rd, rs, rt Parallel Subtract Byte
2054 * PADDH rd, rs, rt Parallel Add Halfword
2055 * PSUBH rd, rs, rt Parallel Subtract Halfword
2056 * PADDW rd, rs, rt Parallel Add Word
2057 * PSUBW rd, rs, rt Parallel Subtract Word
2058 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2059 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2060 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2061 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2062 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2063 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2064 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2065 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2066 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2067 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2068 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2069 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2070 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2072 * Min/Max (4 instructions)
2073 * ------------------------
2074 * PMAXH rd, rs, rt Parallel Maximum Halfword
2075 * PMINH rd, rs, rt Parallel Minimum Halfword
2076 * PMAXW rd, rs, rt Parallel Maximum Word
2077 * PMINW rd, rs, rt Parallel Minimum Word
2079 * Absolute (2 instructions)
2080 * -------------------------
2081 * PABSH rd, rt Parallel Absolute Halfword
2082 * PABSW rd, rt Parallel Absolute Word
2084 * Logical (4 instructions)
2085 * ------------------------
2086 * PAND rd, rs, rt Parallel AND
2087 * POR rd, rs, rt Parallel OR
2088 * PXOR rd, rs, rt Parallel XOR
2089 * PNOR rd, rs, rt Parallel NOR
2091 * Shift (9 instructions)
2092 * ----------------------
2093 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2094 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2095 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2096 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2097 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2098 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2099 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2100 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2101 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2103 * Compare (6 instructions)
2104 * ------------------------
2105 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2106 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2107 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2108 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2109 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2110 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2112 * LZC (1 instruction)
2113 * -------------------
2114 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2116 * Quadword Load and Store (2 instructions)
2117 * ----------------------------------------
2118 * LQ rt, offset(base) Load Quadword
2119 * SQ rt, offset(base) Store Quadword
2121 * Multiply and Divide (19 instructions)
2122 * -------------------------------------
2123 * PMULTW rd, rs, rt Parallel Multiply Word
2124 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2125 * PDIVW rs, rt Parallel Divide Word
2126 * PDIVUW rs, rt Parallel Divide Unsigned Word
2127 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2128 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2129 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2130 * PMULTH rd, rs, rt Parallel Multiply Halfword
2131 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2132 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2133 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2134 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2135 * PDIVBW rs, rt Parallel Divide Broadcast Word
2136 * PMFHI rd Parallel Move From HI Register
2137 * PMFLO rd Parallel Move From LO Register
2138 * PMTHI rs Parallel Move To HI Register
2139 * PMTLO rs Parallel Move To LO Register
2140 * PMFHL rd Parallel Move From HI/LO Register
2141 * PMTHL rs Parallel Move To HI/LO Register
2143 * Pack/Extend (11 instructions)
2144 * -----------------------------
2145 * PPAC5 rd, rt Parallel Pack to 5 bits
2146 * PPACB rd, rs, rt Parallel Pack to Byte
2147 * PPACH rd, rs, rt Parallel Pack to Halfword
2148 * PPACW rd, rs, rt Parallel Pack to Word
2149 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2150 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2151 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2152 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2153 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2154 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2155 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2157 * Others (16 instructions)
2158 * ------------------------
2159 * PCPYH rd, rt Parallel Copy Halfword
2160 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2161 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2162 * PREVH rd, rt Parallel Reverse Halfword
2163 * PINTH rd, rs, rt Parallel Interleave Halfword
2164 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2165 * PEXEH rd, rt Parallel Exchange Even Halfword
2166 * PEXCH rd, rt Parallel Exchange Center Halfword
2167 * PEXEW rd, rt Parallel Exchange Even Word
2168 * PEXCW rd, rt Parallel Exchange Center Word
2169 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2170 * MFSA rd Move from Shift Amount Register
2171 * MTSA rs Move to Shift Amount Register
2172 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2173 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2174 * PROT3W rd, rt Parallel Rotate 3 Words
2176 * MMI (MultiMedia Instruction) encodings
2177 * ======================================
2179 * MMI instructions encoding table keys:
2181 * * This code is reserved for future use. An attempt to execute it
2182 * causes a Reserved Instruction exception.
2183 * % This code indicates an instruction class. The instruction word
2184 * must be further decoded by examining additional tables that show
2185 * the values for other instruction fields.
2186 * # This code is reserved for the unsupported instructions DMULT,
2187 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2188 * to execute it causes a Reserved Instruction exception.
2190 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2192 * 31 26 0
2193 * +--------+----------------------------------------+
2194 * | opcode | |
2195 * +--------+----------------------------------------+
2197 * opcode bits 28..26
2198 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2199 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2200 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2201 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2202 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2203 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2204 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2205 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2206 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2207 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2208 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2211 enum {
2212 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2213 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2214 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2218 * MMI instructions with opcode field = MMI:
2220 * 31 26 5 0
2221 * +--------+-------------------------------+--------+
2222 * | MMI | |function|
2223 * +--------+-------------------------------+--------+
2225 * function bits 2..0
2226 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2227 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2228 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2229 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2230 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2231 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2232 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2233 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2234 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2235 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2236 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2239 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2240 enum {
2241 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2242 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2243 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2244 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2245 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2246 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2247 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2248 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2249 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2250 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2251 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2252 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2253 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2254 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2255 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2256 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2269 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2271 * 31 26 10 6 5 0
2272 * +--------+----------------------+--------+--------+
2273 * | MMI | |function| MMI0 |
2274 * +--------+----------------------+--------+--------+
2276 * function bits 7..6
2277 * bits | 0 | 1 | 2 | 3
2278 * 10..8 | 00 | 01 | 10 | 11
2279 * -------+-------+-------+-------+-------
2280 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2281 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2282 * 2 010 | PADDB | PSUBB | PCGTB | *
2283 * 3 011 | * | * | * | *
2284 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2285 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2286 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2287 * 7 111 | * | * | PEXT5 | PPAC5
2290 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2291 enum {
2292 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2293 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2294 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2320 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2322 * 31 26 10 6 5 0
2323 * +--------+----------------------+--------+--------+
2324 * | MMI | |function| MMI1 |
2325 * +--------+----------------------+--------+--------+
2327 * function bits 7..6
2328 * bits | 0 | 1 | 2 | 3
2329 * 10..8 | 00 | 01 | 10 | 11
2330 * -------+-------+-------+-------+-------
2331 * 0 000 | * | PABSW | PCEQW | PMINW
2332 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2333 * 2 010 | * | * | PCEQB | *
2334 * 3 011 | * | * | * | *
2335 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2336 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2337 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2338 * 7 111 | * | * | * | *
2341 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2342 enum {
2343 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2344 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2345 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2364 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2366 * 31 26 10 6 5 0
2367 * +--------+----------------------+--------+--------+
2368 * | MMI | |function| MMI2 |
2369 * +--------+----------------------+--------+--------+
2371 * function bits 7..6
2372 * bits | 0 | 1 | 2 | 3
2373 * 10..8 | 00 | 01 | 10 | 11
2374 * -------+-------+-------+-------+-------
2375 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2376 * 1 001 | PMSUBW| * | * | *
2377 * 2 010 | PMFHI | PMFLO | PINTH | *
2378 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2379 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2380 * 5 101 | PMSUBH| PHMSBH| * | *
2381 * 6 110 | * | * | PEXEH | PREVH
2382 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2385 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2386 enum {
2387 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2388 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2389 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2412 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2414 * 31 26 10 6 5 0
2415 * +--------+----------------------+--------+--------+
2416 * | MMI | |function| MMI3 |
2417 * +--------+----------------------+--------+--------+
2419 * function bits 7..6
2420 * bits | 0 | 1 | 2 | 3
2421 * 10..8 | 00 | 01 | 10 | 11
2422 * -------+-------+-------+-------+-------
2423 * 0 000 |PMADDUW| * | * | PSRAVW
2424 * 1 001 | * | * | * | *
2425 * 2 010 | PMTHI | PMTLO | PINTEH| *
2426 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2427 * 4 100 | * | * | POR | PNOR
2428 * 5 101 | * | * | * | *
2429 * 6 110 | * | * | PEXCH | PCPYH
2430 * 7 111 | * | * | PEXCW | *
2433 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2434 enum {
2435 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2436 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2437 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2450 /* global register indices */
2451 static TCGv cpu_gpr[32], cpu_PC;
2452 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2453 static TCGv cpu_dspctrl, btarget, bcond;
2454 static TCGv cpu_lladdr, cpu_llval;
2455 static TCGv_i32 hflags;
2456 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2457 static TCGv_i64 fpu_f64[32];
2458 static TCGv_i64 msa_wr_d[64];
2460 #if defined(TARGET_MIPS64)
2461 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2462 static TCGv_i64 cpu_mmr[32];
2463 #endif
2465 #if !defined(TARGET_MIPS64)
2466 /* MXU registers */
2467 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2468 static TCGv mxu_CR;
2469 #endif
2471 #include "exec/gen-icount.h"
2473 #define gen_helper_0e0i(name, arg) do { \
2474 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2475 gen_helper_##name(cpu_env, helper_tmp); \
2476 tcg_temp_free_i32(helper_tmp); \
2477 } while(0)
2479 #define gen_helper_0e1i(name, arg1, arg2) do { \
2480 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2481 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2482 tcg_temp_free_i32(helper_tmp); \
2483 } while(0)
2485 #define gen_helper_1e0i(name, ret, arg1) do { \
2486 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2487 gen_helper_##name(ret, cpu_env, helper_tmp); \
2488 tcg_temp_free_i32(helper_tmp); \
2489 } while(0)
2491 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2492 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2493 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2494 tcg_temp_free_i32(helper_tmp); \
2495 } while(0)
2497 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2498 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2499 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2500 tcg_temp_free_i32(helper_tmp); \
2501 } while(0)
2503 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2504 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2505 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2506 tcg_temp_free_i32(helper_tmp); \
2507 } while(0)
2509 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2510 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2511 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2512 tcg_temp_free_i32(helper_tmp); \
2513 } while(0)
2515 typedef struct DisasContext {
2516 DisasContextBase base;
2517 target_ulong saved_pc;
2518 target_ulong page_start;
2519 uint32_t opcode;
2520 uint64_t insn_flags;
2521 int32_t CP0_Config1;
2522 int32_t CP0_Config2;
2523 int32_t CP0_Config3;
2524 int32_t CP0_Config5;
2525 /* Routine used to access memory */
2526 int mem_idx;
2527 TCGMemOp default_tcg_memop_mask;
2528 uint32_t hflags, saved_hflags;
2529 target_ulong btarget;
2530 bool ulri;
2531 int kscrexist;
2532 bool rxi;
2533 int ie;
2534 bool bi;
2535 bool bp;
2536 uint64_t PAMask;
2537 bool mvh;
2538 bool eva;
2539 bool sc;
2540 int CP0_LLAddr_shift;
2541 bool ps;
2542 bool vp;
2543 bool cmgcr;
2544 bool mrp;
2545 bool nan2008;
2546 bool abs2008;
2547 bool saar;
2548 } DisasContext;
2550 #define DISAS_STOP DISAS_TARGET_0
2551 #define DISAS_EXIT DISAS_TARGET_1
2553 static const char * const regnames[] = {
2554 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2555 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2556 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2557 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2560 static const char * const regnames_HI[] = {
2561 "HI0", "HI1", "HI2", "HI3",
2564 static const char * const regnames_LO[] = {
2565 "LO0", "LO1", "LO2", "LO3",
2568 static const char * const fregnames[] = {
2569 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2570 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2571 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2572 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2575 static const char * const msaregnames[] = {
2576 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2577 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2578 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2579 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2580 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2581 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2582 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2583 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2584 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2585 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2586 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2587 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2588 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2589 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2590 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2591 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2594 #if !defined(TARGET_MIPS64)
2595 static const char * const mxuregnames[] = {
2596 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2597 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2599 #endif
2601 #define LOG_DISAS(...) \
2602 do { \
2603 if (MIPS_DEBUG_DISAS) { \
2604 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2606 } while (0)
2608 #define MIPS_INVAL(op) \
2609 do { \
2610 if (MIPS_DEBUG_DISAS) { \
2611 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2612 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2613 ctx->base.pc_next, ctx->opcode, op, \
2614 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2615 ((ctx->opcode >> 16) & 0x1F)); \
2617 } while (0)
2619 /* General purpose registers moves. */
2620 static inline void gen_load_gpr (TCGv t, int reg)
2622 if (reg == 0)
2623 tcg_gen_movi_tl(t, 0);
2624 else
2625 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2628 static inline void gen_store_gpr (TCGv t, int reg)
2630 if (reg != 0)
2631 tcg_gen_mov_tl(cpu_gpr[reg], t);
2634 /* Moves to/from shadow registers. */
2635 static inline void gen_load_srsgpr (int from, int to)
2637 TCGv t0 = tcg_temp_new();
2639 if (from == 0)
2640 tcg_gen_movi_tl(t0, 0);
2641 else {
2642 TCGv_i32 t2 = tcg_temp_new_i32();
2643 TCGv_ptr addr = tcg_temp_new_ptr();
2645 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2646 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2647 tcg_gen_andi_i32(t2, t2, 0xf);
2648 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2649 tcg_gen_ext_i32_ptr(addr, t2);
2650 tcg_gen_add_ptr(addr, cpu_env, addr);
2652 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2653 tcg_temp_free_ptr(addr);
2654 tcg_temp_free_i32(t2);
2656 gen_store_gpr(t0, to);
2657 tcg_temp_free(t0);
2660 static inline void gen_store_srsgpr (int from, int to)
2662 if (to != 0) {
2663 TCGv t0 = tcg_temp_new();
2664 TCGv_i32 t2 = tcg_temp_new_i32();
2665 TCGv_ptr addr = tcg_temp_new_ptr();
2667 gen_load_gpr(t0, from);
2668 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2669 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2670 tcg_gen_andi_i32(t2, t2, 0xf);
2671 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2672 tcg_gen_ext_i32_ptr(addr, t2);
2673 tcg_gen_add_ptr(addr, cpu_env, addr);
2675 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2676 tcg_temp_free_ptr(addr);
2677 tcg_temp_free_i32(t2);
2678 tcg_temp_free(t0);
2682 #if !defined(TARGET_MIPS64)
2683 /* MXU General purpose registers moves. */
2684 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2686 if (reg == 0) {
2687 tcg_gen_movi_tl(t, 0);
2688 } else if (reg <= 15) {
2689 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2693 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2695 if (reg > 0 && reg <= 15) {
2696 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2700 /* MXU control register moves. */
2701 static inline void gen_load_mxu_cr(TCGv t)
2703 tcg_gen_mov_tl(t, mxu_CR);
2706 static inline void gen_store_mxu_cr(TCGv t)
2708 /* TODO: Add handling of RW rules for MXU_CR. */
2709 tcg_gen_mov_tl(mxu_CR, t);
2711 #endif
2714 /* Tests */
2715 static inline void gen_save_pc(target_ulong pc)
2717 tcg_gen_movi_tl(cpu_PC, pc);
2720 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2722 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2723 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2724 gen_save_pc(ctx->base.pc_next);
2725 ctx->saved_pc = ctx->base.pc_next;
2727 if (ctx->hflags != ctx->saved_hflags) {
2728 tcg_gen_movi_i32(hflags, ctx->hflags);
2729 ctx->saved_hflags = ctx->hflags;
2730 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2731 case MIPS_HFLAG_BR:
2732 break;
2733 case MIPS_HFLAG_BC:
2734 case MIPS_HFLAG_BL:
2735 case MIPS_HFLAG_B:
2736 tcg_gen_movi_tl(btarget, ctx->btarget);
2737 break;
2742 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2744 ctx->saved_hflags = ctx->hflags;
2745 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2746 case MIPS_HFLAG_BR:
2747 break;
2748 case MIPS_HFLAG_BC:
2749 case MIPS_HFLAG_BL:
2750 case MIPS_HFLAG_B:
2751 ctx->btarget = env->btarget;
2752 break;
2756 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2758 TCGv_i32 texcp = tcg_const_i32(excp);
2759 TCGv_i32 terr = tcg_const_i32(err);
2760 save_cpu_state(ctx, 1);
2761 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2762 tcg_temp_free_i32(terr);
2763 tcg_temp_free_i32(texcp);
2764 ctx->base.is_jmp = DISAS_NORETURN;
2767 static inline void generate_exception(DisasContext *ctx, int excp)
2769 gen_helper_0e0i(raise_exception, excp);
2772 static inline void generate_exception_end(DisasContext *ctx, int excp)
2774 generate_exception_err(ctx, excp, 0);
2777 /* Floating point register moves. */
2778 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2780 if (ctx->hflags & MIPS_HFLAG_FRE) {
2781 generate_exception(ctx, EXCP_RI);
2783 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2786 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2788 TCGv_i64 t64;
2789 if (ctx->hflags & MIPS_HFLAG_FRE) {
2790 generate_exception(ctx, EXCP_RI);
2792 t64 = tcg_temp_new_i64();
2793 tcg_gen_extu_i32_i64(t64, t);
2794 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2795 tcg_temp_free_i64(t64);
2798 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2800 if (ctx->hflags & MIPS_HFLAG_F64) {
2801 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2802 } else {
2803 gen_load_fpr32(ctx, t, reg | 1);
2807 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2809 if (ctx->hflags & MIPS_HFLAG_F64) {
2810 TCGv_i64 t64 = tcg_temp_new_i64();
2811 tcg_gen_extu_i32_i64(t64, t);
2812 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2813 tcg_temp_free_i64(t64);
2814 } else {
2815 gen_store_fpr32(ctx, t, reg | 1);
2819 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2821 if (ctx->hflags & MIPS_HFLAG_F64) {
2822 tcg_gen_mov_i64(t, fpu_f64[reg]);
2823 } else {
2824 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2828 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2830 if (ctx->hflags & MIPS_HFLAG_F64) {
2831 tcg_gen_mov_i64(fpu_f64[reg], t);
2832 } else {
2833 TCGv_i64 t0;
2834 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2835 t0 = tcg_temp_new_i64();
2836 tcg_gen_shri_i64(t0, t, 32);
2837 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2838 tcg_temp_free_i64(t0);
2842 static inline int get_fp_bit (int cc)
2844 if (cc)
2845 return 24 + cc;
2846 else
2847 return 23;
2850 /* Addresses computation */
2851 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2853 tcg_gen_add_tl(ret, arg0, arg1);
2855 #if defined(TARGET_MIPS64)
2856 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2857 tcg_gen_ext32s_i64(ret, ret);
2859 #endif
2862 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2863 target_long ofs)
2865 tcg_gen_addi_tl(ret, base, ofs);
2867 #if defined(TARGET_MIPS64)
2868 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2869 tcg_gen_ext32s_i64(ret, ret);
2871 #endif
2874 /* Addresses computation (translation time) */
2875 static target_long addr_add(DisasContext *ctx, target_long base,
2876 target_long offset)
2878 target_long sum = base + offset;
2880 #if defined(TARGET_MIPS64)
2881 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2882 sum = (int32_t)sum;
2884 #endif
2885 return sum;
2888 /* Sign-extract the low 32-bits to a target_long. */
2889 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2891 #if defined(TARGET_MIPS64)
2892 tcg_gen_ext32s_i64(ret, arg);
2893 #else
2894 tcg_gen_extrl_i64_i32(ret, arg);
2895 #endif
2898 /* Sign-extract the high 32-bits to a target_long. */
2899 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2901 #if defined(TARGET_MIPS64)
2902 tcg_gen_sari_i64(ret, arg, 32);
2903 #else
2904 tcg_gen_extrh_i64_i32(ret, arg);
2905 #endif
2908 static inline void check_cp0_enabled(DisasContext *ctx)
2910 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2911 generate_exception_err(ctx, EXCP_CpU, 0);
2914 static inline void check_cp1_enabled(DisasContext *ctx)
2916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2917 generate_exception_err(ctx, EXCP_CpU, 1);
2920 /* Verify that the processor is running with COP1X instructions enabled.
2921 This is associated with the nabla symbol in the MIPS32 and MIPS64
2922 opcode tables. */
2924 static inline void check_cop1x(DisasContext *ctx)
2926 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2927 generate_exception_end(ctx, EXCP_RI);
2930 /* Verify that the processor is running with 64-bit floating-point
2931 operations enabled. */
2933 static inline void check_cp1_64bitmode(DisasContext *ctx)
2935 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2936 generate_exception_end(ctx, EXCP_RI);
2940 * Verify if floating point register is valid; an operation is not defined
2941 * if bit 0 of any register specification is set and the FR bit in the
2942 * Status register equals zero, since the register numbers specify an
2943 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2944 * in the Status register equals one, both even and odd register numbers
2945 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2947 * Multiple 64 bit wide registers can be checked by calling
2948 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2950 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2952 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2953 generate_exception_end(ctx, EXCP_RI);
2956 /* Verify that the processor is running with DSP instructions enabled.
2957 This is enabled by CP0 Status register MX(24) bit.
2960 static inline void check_dsp(DisasContext *ctx)
2962 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2963 if (ctx->insn_flags & ASE_DSP) {
2964 generate_exception_end(ctx, EXCP_DSPDIS);
2965 } else {
2966 generate_exception_end(ctx, EXCP_RI);
2971 static inline void check_dsp_r2(DisasContext *ctx)
2973 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2974 if (ctx->insn_flags & ASE_DSP) {
2975 generate_exception_end(ctx, EXCP_DSPDIS);
2976 } else {
2977 generate_exception_end(ctx, EXCP_RI);
2982 static inline void check_dsp_r3(DisasContext *ctx)
2984 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2985 if (ctx->insn_flags & ASE_DSP) {
2986 generate_exception_end(ctx, EXCP_DSPDIS);
2987 } else {
2988 generate_exception_end(ctx, EXCP_RI);
2993 /* This code generates a "reserved instruction" exception if the
2994 CPU does not support the instruction set corresponding to flags. */
2995 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2997 if (unlikely(!(ctx->insn_flags & flags))) {
2998 generate_exception_end(ctx, EXCP_RI);
3002 /* This code generates a "reserved instruction" exception if the
3003 CPU has corresponding flag set which indicates that the instruction
3004 has been removed. */
3005 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3007 if (unlikely(ctx->insn_flags & flags)) {
3008 generate_exception_end(ctx, EXCP_RI);
3013 * The Linux kernel traps certain reserved instruction exceptions to
3014 * emulate the corresponding instructions. QEMU is the kernel in user
3015 * mode, so those traps are emulated by accepting the instructions.
3017 * A reserved instruction exception is generated for flagged CPUs if
3018 * QEMU runs in system mode.
3020 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3022 #ifndef CONFIG_USER_ONLY
3023 check_insn_opc_removed(ctx, flags);
3024 #endif
3027 /* This code generates a "reserved instruction" exception if the
3028 CPU does not support 64-bit paired-single (PS) floating point data type */
3029 static inline void check_ps(DisasContext *ctx)
3031 if (unlikely(!ctx->ps)) {
3032 generate_exception(ctx, EXCP_RI);
3034 check_cp1_64bitmode(ctx);
3037 #ifdef TARGET_MIPS64
3038 /* This code generates a "reserved instruction" exception if 64-bit
3039 instructions are not enabled. */
3040 static inline void check_mips_64(DisasContext *ctx)
3042 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
3043 generate_exception_end(ctx, EXCP_RI);
3045 #endif
3047 #ifndef CONFIG_USER_ONLY
3048 static inline void check_mvh(DisasContext *ctx)
3050 if (unlikely(!ctx->mvh)) {
3051 generate_exception(ctx, EXCP_RI);
3054 #endif
3057 * This code generates a "reserved instruction" exception if the
3058 * Config5 XNP bit is set.
3060 static inline void check_xnp(DisasContext *ctx)
3062 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3063 generate_exception_end(ctx, EXCP_RI);
3067 #ifndef CONFIG_USER_ONLY
3069 * This code generates a "reserved instruction" exception if the
3070 * Config3 PW bit is NOT set.
3072 static inline void check_pw(DisasContext *ctx)
3074 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3075 generate_exception_end(ctx, EXCP_RI);
3078 #endif
3081 * This code generates a "reserved instruction" exception if the
3082 * Config3 MT bit is NOT set.
3084 static inline void check_mt(DisasContext *ctx)
3086 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3087 generate_exception_end(ctx, EXCP_RI);
3091 #ifndef CONFIG_USER_ONLY
3093 * This code generates a "coprocessor unusable" exception if CP0 is not
3094 * available, and, if that is not the case, generates a "reserved instruction"
3095 * exception if the Config5 MT bit is NOT set. This is needed for availability
3096 * control of some of MT ASE instructions.
3098 static inline void check_cp0_mt(DisasContext *ctx)
3100 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3101 generate_exception_err(ctx, EXCP_CpU, 0);
3102 } else {
3103 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3104 generate_exception_err(ctx, EXCP_RI, 0);
3108 #endif
3111 * This code generates a "reserved instruction" exception if the
3112 * Config5 NMS bit is set.
3114 static inline void check_nms(DisasContext *ctx)
3116 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3117 generate_exception_end(ctx, EXCP_RI);
3122 * This code generates a "reserved instruction" exception if the
3123 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3124 * Config2 TL, and Config5 L2C are unset.
3126 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3128 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3129 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3130 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3131 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3132 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3133 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3135 generate_exception_end(ctx, EXCP_RI);
3140 * This code generates a "reserved instruction" exception if the
3141 * Config5 EVA bit is NOT set.
3143 static inline void check_eva(DisasContext *ctx)
3145 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3146 generate_exception_end(ctx, EXCP_RI);
3151 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3152 calling interface for 32 and 64-bit FPRs. No sense in changing
3153 all callers for gen_load_fpr32 when we need the CTX parameter for
3154 this one use. */
3155 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3156 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3157 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3158 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3159 int ft, int fs, int cc) \
3161 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3162 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3163 switch (ifmt) { \
3164 case FMT_PS: \
3165 check_ps(ctx); \
3166 break; \
3167 case FMT_D: \
3168 if (abs) { \
3169 check_cop1x(ctx); \
3171 check_cp1_registers(ctx, fs | ft); \
3172 break; \
3173 case FMT_S: \
3174 if (abs) { \
3175 check_cop1x(ctx); \
3177 break; \
3179 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3180 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3181 switch (n) { \
3182 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3183 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3184 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3185 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3186 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3187 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3188 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3189 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3190 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3191 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3192 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3193 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3194 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3195 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3196 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3197 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3198 default: abort(); \
3200 tcg_temp_free_i##bits (fp0); \
3201 tcg_temp_free_i##bits (fp1); \
3204 FOP_CONDS(, 0, d, FMT_D, 64)
3205 FOP_CONDS(abs, 1, d, FMT_D, 64)
3206 FOP_CONDS(, 0, s, FMT_S, 32)
3207 FOP_CONDS(abs, 1, s, FMT_S, 32)
3208 FOP_CONDS(, 0, ps, FMT_PS, 64)
3209 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3210 #undef FOP_CONDS
3212 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3213 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3214 int ft, int fs, int fd) \
3216 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3217 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3218 if (ifmt == FMT_D) { \
3219 check_cp1_registers(ctx, fs | ft | fd); \
3221 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3222 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3223 switch (n) { \
3224 case 0: \
3225 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3226 break; \
3227 case 1: \
3228 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3229 break; \
3230 case 2: \
3231 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3232 break; \
3233 case 3: \
3234 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3235 break; \
3236 case 4: \
3237 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3238 break; \
3239 case 5: \
3240 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3241 break; \
3242 case 6: \
3243 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3244 break; \
3245 case 7: \
3246 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3247 break; \
3248 case 8: \
3249 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3250 break; \
3251 case 9: \
3252 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3253 break; \
3254 case 10: \
3255 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3256 break; \
3257 case 11: \
3258 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3259 break; \
3260 case 12: \
3261 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3262 break; \
3263 case 13: \
3264 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3265 break; \
3266 case 14: \
3267 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3268 break; \
3269 case 15: \
3270 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3271 break; \
3272 case 17: \
3273 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3274 break; \
3275 case 18: \
3276 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3277 break; \
3278 case 19: \
3279 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3280 break; \
3281 case 25: \
3282 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3283 break; \
3284 case 26: \
3285 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3286 break; \
3287 case 27: \
3288 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3289 break; \
3290 default: \
3291 abort(); \
3293 STORE; \
3294 tcg_temp_free_i ## bits (fp0); \
3295 tcg_temp_free_i ## bits (fp1); \
3298 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3299 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3300 #undef FOP_CONDNS
3301 #undef gen_ldcmp_fpr32
3302 #undef gen_ldcmp_fpr64
3304 /* load/store instructions. */
3305 #ifdef CONFIG_USER_ONLY
3306 #define OP_LD_ATOMIC(insn,fname) \
3307 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3308 DisasContext *ctx) \
3310 TCGv t0 = tcg_temp_new(); \
3311 tcg_gen_mov_tl(t0, arg1); \
3312 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3313 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3314 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3315 tcg_temp_free(t0); \
3317 #else
3318 #define OP_LD_ATOMIC(insn,fname) \
3319 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3320 DisasContext *ctx) \
3322 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3324 #endif
3325 OP_LD_ATOMIC(ll,ld32s);
3326 #if defined(TARGET_MIPS64)
3327 OP_LD_ATOMIC(lld,ld64);
3328 #endif
3329 #undef OP_LD_ATOMIC
3331 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3332 int base, int offset)
3334 if (base == 0) {
3335 tcg_gen_movi_tl(addr, offset);
3336 } else if (offset == 0) {
3337 gen_load_gpr(addr, base);
3338 } else {
3339 tcg_gen_movi_tl(addr, offset);
3340 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3344 static target_ulong pc_relative_pc (DisasContext *ctx)
3346 target_ulong pc = ctx->base.pc_next;
3348 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3349 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3351 pc -= branch_bytes;
3354 pc &= ~(target_ulong)3;
3355 return pc;
3358 /* Load */
3359 static void gen_ld(DisasContext *ctx, uint32_t opc,
3360 int rt, int base, int offset)
3362 TCGv t0, t1, t2;
3363 int mem_idx = ctx->mem_idx;
3365 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3366 /* Loongson CPU uses a load to zero register for prefetch.
3367 We emulate it as a NOP. On other CPU we must perform the
3368 actual memory access. */
3369 return;
3372 t0 = tcg_temp_new();
3373 gen_base_offset_addr(ctx, t0, base, offset);
3375 switch (opc) {
3376 #if defined(TARGET_MIPS64)
3377 case OPC_LWU:
3378 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3379 ctx->default_tcg_memop_mask);
3380 gen_store_gpr(t0, rt);
3381 break;
3382 case OPC_LD:
3383 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3384 ctx->default_tcg_memop_mask);
3385 gen_store_gpr(t0, rt);
3386 break;
3387 case OPC_LLD:
3388 case R6_OPC_LLD:
3389 op_ld_lld(t0, t0, mem_idx, ctx);
3390 gen_store_gpr(t0, rt);
3391 break;
3392 case OPC_LDL:
3393 t1 = tcg_temp_new();
3394 /* Do a byte access to possibly trigger a page
3395 fault with the unaligned address. */
3396 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3397 tcg_gen_andi_tl(t1, t0, 7);
3398 #ifndef TARGET_WORDS_BIGENDIAN
3399 tcg_gen_xori_tl(t1, t1, 7);
3400 #endif
3401 tcg_gen_shli_tl(t1, t1, 3);
3402 tcg_gen_andi_tl(t0, t0, ~7);
3403 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3404 tcg_gen_shl_tl(t0, t0, t1);
3405 t2 = tcg_const_tl(-1);
3406 tcg_gen_shl_tl(t2, t2, t1);
3407 gen_load_gpr(t1, rt);
3408 tcg_gen_andc_tl(t1, t1, t2);
3409 tcg_temp_free(t2);
3410 tcg_gen_or_tl(t0, t0, t1);
3411 tcg_temp_free(t1);
3412 gen_store_gpr(t0, rt);
3413 break;
3414 case OPC_LDR:
3415 t1 = tcg_temp_new();
3416 /* Do a byte access to possibly trigger a page
3417 fault with the unaligned address. */
3418 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3419 tcg_gen_andi_tl(t1, t0, 7);
3420 #ifdef TARGET_WORDS_BIGENDIAN
3421 tcg_gen_xori_tl(t1, t1, 7);
3422 #endif
3423 tcg_gen_shli_tl(t1, t1, 3);
3424 tcg_gen_andi_tl(t0, t0, ~7);
3425 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3426 tcg_gen_shr_tl(t0, t0, t1);
3427 tcg_gen_xori_tl(t1, t1, 63);
3428 t2 = tcg_const_tl(0xfffffffffffffffeull);
3429 tcg_gen_shl_tl(t2, t2, t1);
3430 gen_load_gpr(t1, rt);
3431 tcg_gen_and_tl(t1, t1, t2);
3432 tcg_temp_free(t2);
3433 tcg_gen_or_tl(t0, t0, t1);
3434 tcg_temp_free(t1);
3435 gen_store_gpr(t0, rt);
3436 break;
3437 case OPC_LDPC:
3438 t1 = tcg_const_tl(pc_relative_pc(ctx));
3439 gen_op_addr_add(ctx, t0, t0, t1);
3440 tcg_temp_free(t1);
3441 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3442 gen_store_gpr(t0, rt);
3443 break;
3444 #endif
3445 case OPC_LWPC:
3446 t1 = tcg_const_tl(pc_relative_pc(ctx));
3447 gen_op_addr_add(ctx, t0, t0, t1);
3448 tcg_temp_free(t1);
3449 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3450 gen_store_gpr(t0, rt);
3451 break;
3452 case OPC_LWE:
3453 mem_idx = MIPS_HFLAG_UM;
3454 /* fall through */
3455 case OPC_LW:
3456 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3457 ctx->default_tcg_memop_mask);
3458 gen_store_gpr(t0, rt);
3459 break;
3460 case OPC_LHE:
3461 mem_idx = MIPS_HFLAG_UM;
3462 /* fall through */
3463 case OPC_LH:
3464 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3465 ctx->default_tcg_memop_mask);
3466 gen_store_gpr(t0, rt);
3467 break;
3468 case OPC_LHUE:
3469 mem_idx = MIPS_HFLAG_UM;
3470 /* fall through */
3471 case OPC_LHU:
3472 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3473 ctx->default_tcg_memop_mask);
3474 gen_store_gpr(t0, rt);
3475 break;
3476 case OPC_LBE:
3477 mem_idx = MIPS_HFLAG_UM;
3478 /* fall through */
3479 case OPC_LB:
3480 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3481 gen_store_gpr(t0, rt);
3482 break;
3483 case OPC_LBUE:
3484 mem_idx = MIPS_HFLAG_UM;
3485 /* fall through */
3486 case OPC_LBU:
3487 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3488 gen_store_gpr(t0, rt);
3489 break;
3490 case OPC_LWLE:
3491 mem_idx = MIPS_HFLAG_UM;
3492 /* fall through */
3493 case OPC_LWL:
3494 t1 = tcg_temp_new();
3495 /* Do a byte access to possibly trigger a page
3496 fault with the unaligned address. */
3497 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3498 tcg_gen_andi_tl(t1, t0, 3);
3499 #ifndef TARGET_WORDS_BIGENDIAN
3500 tcg_gen_xori_tl(t1, t1, 3);
3501 #endif
3502 tcg_gen_shli_tl(t1, t1, 3);
3503 tcg_gen_andi_tl(t0, t0, ~3);
3504 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3505 tcg_gen_shl_tl(t0, t0, t1);
3506 t2 = tcg_const_tl(-1);
3507 tcg_gen_shl_tl(t2, t2, t1);
3508 gen_load_gpr(t1, rt);
3509 tcg_gen_andc_tl(t1, t1, t2);
3510 tcg_temp_free(t2);
3511 tcg_gen_or_tl(t0, t0, t1);
3512 tcg_temp_free(t1);
3513 tcg_gen_ext32s_tl(t0, t0);
3514 gen_store_gpr(t0, rt);
3515 break;
3516 case OPC_LWRE:
3517 mem_idx = MIPS_HFLAG_UM;
3518 /* fall through */
3519 case OPC_LWR:
3520 t1 = tcg_temp_new();
3521 /* Do a byte access to possibly trigger a page
3522 fault with the unaligned address. */
3523 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3524 tcg_gen_andi_tl(t1, t0, 3);
3525 #ifdef TARGET_WORDS_BIGENDIAN
3526 tcg_gen_xori_tl(t1, t1, 3);
3527 #endif
3528 tcg_gen_shli_tl(t1, t1, 3);
3529 tcg_gen_andi_tl(t0, t0, ~3);
3530 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3531 tcg_gen_shr_tl(t0, t0, t1);
3532 tcg_gen_xori_tl(t1, t1, 31);
3533 t2 = tcg_const_tl(0xfffffffeull);
3534 tcg_gen_shl_tl(t2, t2, t1);
3535 gen_load_gpr(t1, rt);
3536 tcg_gen_and_tl(t1, t1, t2);
3537 tcg_temp_free(t2);
3538 tcg_gen_or_tl(t0, t0, t1);
3539 tcg_temp_free(t1);
3540 tcg_gen_ext32s_tl(t0, t0);
3541 gen_store_gpr(t0, rt);
3542 break;
3543 case OPC_LLE:
3544 mem_idx = MIPS_HFLAG_UM;
3545 /* fall through */
3546 case OPC_LL:
3547 case R6_OPC_LL:
3548 op_ld_ll(t0, t0, mem_idx, ctx);
3549 gen_store_gpr(t0, rt);
3550 break;
3552 tcg_temp_free(t0);
3555 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3556 uint32_t reg1, uint32_t reg2)
3558 TCGv taddr = tcg_temp_new();
3559 TCGv_i64 tval = tcg_temp_new_i64();
3560 TCGv tmp1 = tcg_temp_new();
3561 TCGv tmp2 = tcg_temp_new();
3563 gen_base_offset_addr(ctx, taddr, base, offset);
3564 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3565 #ifdef TARGET_WORDS_BIGENDIAN
3566 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3567 #else
3568 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3569 #endif
3570 gen_store_gpr(tmp1, reg1);
3571 tcg_temp_free(tmp1);
3572 gen_store_gpr(tmp2, reg2);
3573 tcg_temp_free(tmp2);
3574 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3575 tcg_temp_free_i64(tval);
3576 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3577 tcg_temp_free(taddr);
3580 /* Store */
3581 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3582 int base, int offset)
3584 TCGv t0 = tcg_temp_new();
3585 TCGv t1 = tcg_temp_new();
3586 int mem_idx = ctx->mem_idx;
3588 gen_base_offset_addr(ctx, t0, base, offset);
3589 gen_load_gpr(t1, rt);
3590 switch (opc) {
3591 #if defined(TARGET_MIPS64)
3592 case OPC_SD:
3593 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3594 ctx->default_tcg_memop_mask);
3595 break;
3596 case OPC_SDL:
3597 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3598 break;
3599 case OPC_SDR:
3600 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3601 break;
3602 #endif
3603 case OPC_SWE:
3604 mem_idx = MIPS_HFLAG_UM;
3605 /* fall through */
3606 case OPC_SW:
3607 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3608 ctx->default_tcg_memop_mask);
3609 break;
3610 case OPC_SHE:
3611 mem_idx = MIPS_HFLAG_UM;
3612 /* fall through */
3613 case OPC_SH:
3614 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3615 ctx->default_tcg_memop_mask);
3616 break;
3617 case OPC_SBE:
3618 mem_idx = MIPS_HFLAG_UM;
3619 /* fall through */
3620 case OPC_SB:
3621 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3622 break;
3623 case OPC_SWLE:
3624 mem_idx = MIPS_HFLAG_UM;
3625 /* fall through */
3626 case OPC_SWL:
3627 gen_helper_0e2i(swl, t1, t0, mem_idx);
3628 break;
3629 case OPC_SWRE:
3630 mem_idx = MIPS_HFLAG_UM;
3631 /* fall through */
3632 case OPC_SWR:
3633 gen_helper_0e2i(swr, t1, t0, mem_idx);
3634 break;
3636 tcg_temp_free(t0);
3637 tcg_temp_free(t1);
3641 /* Store conditional */
3642 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3643 TCGMemOp tcg_mo, bool eva)
3645 TCGv addr, t0, val;
3646 TCGLabel *l1 = gen_new_label();
3647 TCGLabel *done = gen_new_label();
3649 t0 = tcg_temp_new();
3650 addr = tcg_temp_new();
3651 /* compare the address against that of the preceeding LL */
3652 gen_base_offset_addr(ctx, addr, base, offset);
3653 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3654 tcg_temp_free(addr);
3655 tcg_gen_movi_tl(t0, 0);
3656 gen_store_gpr(t0, rt);
3657 tcg_gen_br(done);
3659 gen_set_label(l1);
3660 /* generate cmpxchg */
3661 val = tcg_temp_new();
3662 gen_load_gpr(val, rt);
3663 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3664 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3665 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3666 gen_store_gpr(t0, rt);
3667 tcg_temp_free(val);
3669 gen_set_label(done);
3670 tcg_temp_free(t0);
3674 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3675 uint32_t reg1, uint32_t reg2, bool eva)
3677 TCGv taddr = tcg_temp_local_new();
3678 TCGv lladdr = tcg_temp_local_new();
3679 TCGv_i64 tval = tcg_temp_new_i64();
3680 TCGv_i64 llval = tcg_temp_new_i64();
3681 TCGv_i64 val = tcg_temp_new_i64();
3682 TCGv tmp1 = tcg_temp_new();
3683 TCGv tmp2 = tcg_temp_new();
3684 TCGLabel *lab_fail = gen_new_label();
3685 TCGLabel *lab_done = gen_new_label();
3687 gen_base_offset_addr(ctx, taddr, base, offset);
3689 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3690 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3692 gen_load_gpr(tmp1, reg1);
3693 gen_load_gpr(tmp2, reg2);
3695 #ifdef TARGET_WORDS_BIGENDIAN
3696 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3697 #else
3698 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3699 #endif
3701 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3702 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3703 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3704 if (reg1 != 0) {
3705 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3707 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3709 gen_set_label(lab_fail);
3711 if (reg1 != 0) {
3712 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3714 gen_set_label(lab_done);
3715 tcg_gen_movi_tl(lladdr, -1);
3716 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3719 /* Load and store */
3720 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3721 TCGv t0)
3723 /* Don't do NOP if destination is zero: we must perform the actual
3724 memory access. */
3725 switch (opc) {
3726 case OPC_LWC1:
3728 TCGv_i32 fp0 = tcg_temp_new_i32();
3729 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3730 ctx->default_tcg_memop_mask);
3731 gen_store_fpr32(ctx, fp0, ft);
3732 tcg_temp_free_i32(fp0);
3734 break;
3735 case OPC_SWC1:
3737 TCGv_i32 fp0 = tcg_temp_new_i32();
3738 gen_load_fpr32(ctx, fp0, ft);
3739 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3740 ctx->default_tcg_memop_mask);
3741 tcg_temp_free_i32(fp0);
3743 break;
3744 case OPC_LDC1:
3746 TCGv_i64 fp0 = tcg_temp_new_i64();
3747 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3748 ctx->default_tcg_memop_mask);
3749 gen_store_fpr64(ctx, fp0, ft);
3750 tcg_temp_free_i64(fp0);
3752 break;
3753 case OPC_SDC1:
3755 TCGv_i64 fp0 = tcg_temp_new_i64();
3756 gen_load_fpr64(ctx, fp0, ft);
3757 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3758 ctx->default_tcg_memop_mask);
3759 tcg_temp_free_i64(fp0);
3761 break;
3762 default:
3763 MIPS_INVAL("flt_ldst");
3764 generate_exception_end(ctx, EXCP_RI);
3765 break;
3769 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3770 int rs, int16_t imm)
3772 TCGv t0 = tcg_temp_new();
3774 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3775 check_cp1_enabled(ctx);
3776 switch (op) {
3777 case OPC_LDC1:
3778 case OPC_SDC1:
3779 check_insn(ctx, ISA_MIPS2);
3780 /* Fallthrough */
3781 default:
3782 gen_base_offset_addr(ctx, t0, rs, imm);
3783 gen_flt_ldst(ctx, op, rt, t0);
3785 } else {
3786 generate_exception_err(ctx, EXCP_CpU, 1);
3788 tcg_temp_free(t0);
3791 /* Arithmetic with immediate operand */
3792 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3793 int rt, int rs, int imm)
3795 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3797 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3798 /* If no destination, treat it as a NOP.
3799 For addi, we must generate the overflow exception when needed. */
3800 return;
3802 switch (opc) {
3803 case OPC_ADDI:
3805 TCGv t0 = tcg_temp_local_new();
3806 TCGv t1 = tcg_temp_new();
3807 TCGv t2 = tcg_temp_new();
3808 TCGLabel *l1 = gen_new_label();
3810 gen_load_gpr(t1, rs);
3811 tcg_gen_addi_tl(t0, t1, uimm);
3812 tcg_gen_ext32s_tl(t0, t0);
3814 tcg_gen_xori_tl(t1, t1, ~uimm);
3815 tcg_gen_xori_tl(t2, t0, uimm);
3816 tcg_gen_and_tl(t1, t1, t2);
3817 tcg_temp_free(t2);
3818 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3819 tcg_temp_free(t1);
3820 /* operands of same sign, result different sign */
3821 generate_exception(ctx, EXCP_OVERFLOW);
3822 gen_set_label(l1);
3823 tcg_gen_ext32s_tl(t0, t0);
3824 gen_store_gpr(t0, rt);
3825 tcg_temp_free(t0);
3827 break;
3828 case OPC_ADDIU:
3829 if (rs != 0) {
3830 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3831 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3832 } else {
3833 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3835 break;
3836 #if defined(TARGET_MIPS64)
3837 case OPC_DADDI:
3839 TCGv t0 = tcg_temp_local_new();
3840 TCGv t1 = tcg_temp_new();
3841 TCGv t2 = tcg_temp_new();
3842 TCGLabel *l1 = gen_new_label();
3844 gen_load_gpr(t1, rs);
3845 tcg_gen_addi_tl(t0, t1, uimm);
3847 tcg_gen_xori_tl(t1, t1, ~uimm);
3848 tcg_gen_xori_tl(t2, t0, uimm);
3849 tcg_gen_and_tl(t1, t1, t2);
3850 tcg_temp_free(t2);
3851 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3852 tcg_temp_free(t1);
3853 /* operands of same sign, result different sign */
3854 generate_exception(ctx, EXCP_OVERFLOW);
3855 gen_set_label(l1);
3856 gen_store_gpr(t0, rt);
3857 tcg_temp_free(t0);
3859 break;
3860 case OPC_DADDIU:
3861 if (rs != 0) {
3862 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3863 } else {
3864 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3866 break;
3867 #endif
3871 /* Logic with immediate operand */
3872 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3873 int rt, int rs, int16_t imm)
3875 target_ulong uimm;
3877 if (rt == 0) {
3878 /* If no destination, treat it as a NOP. */
3879 return;
3881 uimm = (uint16_t)imm;
3882 switch (opc) {
3883 case OPC_ANDI:
3884 if (likely(rs != 0))
3885 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3886 else
3887 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3888 break;
3889 case OPC_ORI:
3890 if (rs != 0)
3891 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3892 else
3893 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3894 break;
3895 case OPC_XORI:
3896 if (likely(rs != 0))
3897 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3898 else
3899 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3900 break;
3901 case OPC_LUI:
3902 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3903 /* OPC_AUI */
3904 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3905 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3906 } else {
3907 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3909 break;
3911 default:
3912 break;
3916 /* Set on less than with immediate operand */
3917 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3918 int rt, int rs, int16_t imm)
3920 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3921 TCGv t0;
3923 if (rt == 0) {
3924 /* If no destination, treat it as a NOP. */
3925 return;
3927 t0 = tcg_temp_new();
3928 gen_load_gpr(t0, rs);
3929 switch (opc) {
3930 case OPC_SLTI:
3931 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3932 break;
3933 case OPC_SLTIU:
3934 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3935 break;
3937 tcg_temp_free(t0);
3940 /* Shifts with immediate operand */
3941 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3942 int rt, int rs, int16_t imm)
3944 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3945 TCGv t0;
3947 if (rt == 0) {
3948 /* If no destination, treat it as a NOP. */
3949 return;
3952 t0 = tcg_temp_new();
3953 gen_load_gpr(t0, rs);
3954 switch (opc) {
3955 case OPC_SLL:
3956 tcg_gen_shli_tl(t0, t0, uimm);
3957 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3958 break;
3959 case OPC_SRA:
3960 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3961 break;
3962 case OPC_SRL:
3963 if (uimm != 0) {
3964 tcg_gen_ext32u_tl(t0, t0);
3965 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3966 } else {
3967 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3969 break;
3970 case OPC_ROTR:
3971 if (uimm != 0) {
3972 TCGv_i32 t1 = tcg_temp_new_i32();
3974 tcg_gen_trunc_tl_i32(t1, t0);
3975 tcg_gen_rotri_i32(t1, t1, uimm);
3976 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3977 tcg_temp_free_i32(t1);
3978 } else {
3979 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3981 break;
3982 #if defined(TARGET_MIPS64)
3983 case OPC_DSLL:
3984 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3985 break;
3986 case OPC_DSRA:
3987 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3988 break;
3989 case OPC_DSRL:
3990 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3991 break;
3992 case OPC_DROTR:
3993 if (uimm != 0) {
3994 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3995 } else {
3996 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3998 break;
3999 case OPC_DSLL32:
4000 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4001 break;
4002 case OPC_DSRA32:
4003 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4004 break;
4005 case OPC_DSRL32:
4006 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4007 break;
4008 case OPC_DROTR32:
4009 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4010 break;
4011 #endif
4013 tcg_temp_free(t0);
4016 /* Arithmetic */
4017 static void gen_arith(DisasContext *ctx, uint32_t opc,
4018 int rd, int rs, int rt)
4020 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4021 && opc != OPC_DADD && opc != OPC_DSUB) {
4022 /* If no destination, treat it as a NOP.
4023 For add & sub, we must generate the overflow exception when needed. */
4024 return;
4027 switch (opc) {
4028 case OPC_ADD:
4030 TCGv t0 = tcg_temp_local_new();
4031 TCGv t1 = tcg_temp_new();
4032 TCGv t2 = tcg_temp_new();
4033 TCGLabel *l1 = gen_new_label();
4035 gen_load_gpr(t1, rs);
4036 gen_load_gpr(t2, rt);
4037 tcg_gen_add_tl(t0, t1, t2);
4038 tcg_gen_ext32s_tl(t0, t0);
4039 tcg_gen_xor_tl(t1, t1, t2);
4040 tcg_gen_xor_tl(t2, t0, t2);
4041 tcg_gen_andc_tl(t1, t2, t1);
4042 tcg_temp_free(t2);
4043 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4044 tcg_temp_free(t1);
4045 /* operands of same sign, result different sign */
4046 generate_exception(ctx, EXCP_OVERFLOW);
4047 gen_set_label(l1);
4048 gen_store_gpr(t0, rd);
4049 tcg_temp_free(t0);
4051 break;
4052 case OPC_ADDU:
4053 if (rs != 0 && rt != 0) {
4054 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4055 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4056 } else if (rs == 0 && rt != 0) {
4057 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4058 } else if (rs != 0 && rt == 0) {
4059 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4060 } else {
4061 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4063 break;
4064 case OPC_SUB:
4066 TCGv t0 = tcg_temp_local_new();
4067 TCGv t1 = tcg_temp_new();
4068 TCGv t2 = tcg_temp_new();
4069 TCGLabel *l1 = gen_new_label();
4071 gen_load_gpr(t1, rs);
4072 gen_load_gpr(t2, rt);
4073 tcg_gen_sub_tl(t0, t1, t2);
4074 tcg_gen_ext32s_tl(t0, t0);
4075 tcg_gen_xor_tl(t2, t1, t2);
4076 tcg_gen_xor_tl(t1, t0, t1);
4077 tcg_gen_and_tl(t1, t1, t2);
4078 tcg_temp_free(t2);
4079 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4080 tcg_temp_free(t1);
4081 /* operands of different sign, first operand and result different sign */
4082 generate_exception(ctx, EXCP_OVERFLOW);
4083 gen_set_label(l1);
4084 gen_store_gpr(t0, rd);
4085 tcg_temp_free(t0);
4087 break;
4088 case OPC_SUBU:
4089 if (rs != 0 && rt != 0) {
4090 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4091 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4092 } else if (rs == 0 && rt != 0) {
4093 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4094 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4095 } else if (rs != 0 && rt == 0) {
4096 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4097 } else {
4098 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4100 break;
4101 #if defined(TARGET_MIPS64)
4102 case OPC_DADD:
4104 TCGv t0 = tcg_temp_local_new();
4105 TCGv t1 = tcg_temp_new();
4106 TCGv t2 = tcg_temp_new();
4107 TCGLabel *l1 = gen_new_label();
4109 gen_load_gpr(t1, rs);
4110 gen_load_gpr(t2, rt);
4111 tcg_gen_add_tl(t0, t1, t2);
4112 tcg_gen_xor_tl(t1, t1, t2);
4113 tcg_gen_xor_tl(t2, t0, t2);
4114 tcg_gen_andc_tl(t1, t2, t1);
4115 tcg_temp_free(t2);
4116 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4117 tcg_temp_free(t1);
4118 /* operands of same sign, result different sign */
4119 generate_exception(ctx, EXCP_OVERFLOW);
4120 gen_set_label(l1);
4121 gen_store_gpr(t0, rd);
4122 tcg_temp_free(t0);
4124 break;
4125 case OPC_DADDU:
4126 if (rs != 0 && rt != 0) {
4127 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4128 } else if (rs == 0 && rt != 0) {
4129 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4130 } else if (rs != 0 && rt == 0) {
4131 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4132 } else {
4133 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4135 break;
4136 case OPC_DSUB:
4138 TCGv t0 = tcg_temp_local_new();
4139 TCGv t1 = tcg_temp_new();
4140 TCGv t2 = tcg_temp_new();
4141 TCGLabel *l1 = gen_new_label();
4143 gen_load_gpr(t1, rs);
4144 gen_load_gpr(t2, rt);
4145 tcg_gen_sub_tl(t0, t1, t2);
4146 tcg_gen_xor_tl(t2, t1, t2);
4147 tcg_gen_xor_tl(t1, t0, t1);
4148 tcg_gen_and_tl(t1, t1, t2);
4149 tcg_temp_free(t2);
4150 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4151 tcg_temp_free(t1);
4152 /* operands of different sign, first operand and result different sign */
4153 generate_exception(ctx, EXCP_OVERFLOW);
4154 gen_set_label(l1);
4155 gen_store_gpr(t0, rd);
4156 tcg_temp_free(t0);
4158 break;
4159 case OPC_DSUBU:
4160 if (rs != 0 && rt != 0) {
4161 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4162 } else if (rs == 0 && rt != 0) {
4163 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4164 } else if (rs != 0 && rt == 0) {
4165 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4166 } else {
4167 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4169 break;
4170 #endif
4171 case OPC_MUL:
4172 if (likely(rs != 0 && rt != 0)) {
4173 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4174 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4175 } else {
4176 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4178 break;
4182 /* Conditional move */
4183 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4184 int rd, int rs, int rt)
4186 TCGv t0, t1, t2;
4188 if (rd == 0) {
4189 /* If no destination, treat it as a NOP. */
4190 return;
4193 t0 = tcg_temp_new();
4194 gen_load_gpr(t0, rt);
4195 t1 = tcg_const_tl(0);
4196 t2 = tcg_temp_new();
4197 gen_load_gpr(t2, rs);
4198 switch (opc) {
4199 case OPC_MOVN:
4200 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4201 break;
4202 case OPC_MOVZ:
4203 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4204 break;
4205 case OPC_SELNEZ:
4206 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4207 break;
4208 case OPC_SELEQZ:
4209 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4210 break;
4212 tcg_temp_free(t2);
4213 tcg_temp_free(t1);
4214 tcg_temp_free(t0);
4217 /* Logic */
4218 static void gen_logic(DisasContext *ctx, uint32_t opc,
4219 int rd, int rs, int rt)
4221 if (rd == 0) {
4222 /* If no destination, treat it as a NOP. */
4223 return;
4226 switch (opc) {
4227 case OPC_AND:
4228 if (likely(rs != 0 && rt != 0)) {
4229 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4230 } else {
4231 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4233 break;
4234 case OPC_NOR:
4235 if (rs != 0 && rt != 0) {
4236 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4237 } else if (rs == 0 && rt != 0) {
4238 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4239 } else if (rs != 0 && rt == 0) {
4240 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4241 } else {
4242 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4244 break;
4245 case OPC_OR:
4246 if (likely(rs != 0 && rt != 0)) {
4247 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4248 } else if (rs == 0 && rt != 0) {
4249 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4250 } else if (rs != 0 && rt == 0) {
4251 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4252 } else {
4253 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4255 break;
4256 case OPC_XOR:
4257 if (likely(rs != 0 && rt != 0)) {
4258 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4259 } else if (rs == 0 && rt != 0) {
4260 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4261 } else if (rs != 0 && rt == 0) {
4262 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4263 } else {
4264 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4266 break;
4270 /* Set on lower than */
4271 static void gen_slt(DisasContext *ctx, uint32_t opc,
4272 int rd, int rs, int rt)
4274 TCGv t0, t1;
4276 if (rd == 0) {
4277 /* If no destination, treat it as a NOP. */
4278 return;
4281 t0 = tcg_temp_new();
4282 t1 = tcg_temp_new();
4283 gen_load_gpr(t0, rs);
4284 gen_load_gpr(t1, rt);
4285 switch (opc) {
4286 case OPC_SLT:
4287 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4288 break;
4289 case OPC_SLTU:
4290 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4291 break;
4293 tcg_temp_free(t0);
4294 tcg_temp_free(t1);
4297 /* Shifts */
4298 static void gen_shift(DisasContext *ctx, uint32_t opc,
4299 int rd, int rs, int rt)
4301 TCGv t0, t1;
4303 if (rd == 0) {
4304 /* If no destination, treat it as a NOP.
4305 For add & sub, we must generate the overflow exception when needed. */
4306 return;
4309 t0 = tcg_temp_new();
4310 t1 = tcg_temp_new();
4311 gen_load_gpr(t0, rs);
4312 gen_load_gpr(t1, rt);
4313 switch (opc) {
4314 case OPC_SLLV:
4315 tcg_gen_andi_tl(t0, t0, 0x1f);
4316 tcg_gen_shl_tl(t0, t1, t0);
4317 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4318 break;
4319 case OPC_SRAV:
4320 tcg_gen_andi_tl(t0, t0, 0x1f);
4321 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4322 break;
4323 case OPC_SRLV:
4324 tcg_gen_ext32u_tl(t1, t1);
4325 tcg_gen_andi_tl(t0, t0, 0x1f);
4326 tcg_gen_shr_tl(t0, t1, t0);
4327 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4328 break;
4329 case OPC_ROTRV:
4331 TCGv_i32 t2 = tcg_temp_new_i32();
4332 TCGv_i32 t3 = tcg_temp_new_i32();
4334 tcg_gen_trunc_tl_i32(t2, t0);
4335 tcg_gen_trunc_tl_i32(t3, t1);
4336 tcg_gen_andi_i32(t2, t2, 0x1f);
4337 tcg_gen_rotr_i32(t2, t3, t2);
4338 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4339 tcg_temp_free_i32(t2);
4340 tcg_temp_free_i32(t3);
4342 break;
4343 #if defined(TARGET_MIPS64)
4344 case OPC_DSLLV:
4345 tcg_gen_andi_tl(t0, t0, 0x3f);
4346 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4347 break;
4348 case OPC_DSRAV:
4349 tcg_gen_andi_tl(t0, t0, 0x3f);
4350 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4351 break;
4352 case OPC_DSRLV:
4353 tcg_gen_andi_tl(t0, t0, 0x3f);
4354 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4355 break;
4356 case OPC_DROTRV:
4357 tcg_gen_andi_tl(t0, t0, 0x3f);
4358 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4359 break;
4360 #endif
4362 tcg_temp_free(t0);
4363 tcg_temp_free(t1);
4366 #if defined(TARGET_MIPS64)
4367 /* Copy GPR to and from TX79 HI1/LO1 register. */
4368 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4370 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4371 /* Treat as NOP. */
4372 return;
4375 switch (opc) {
4376 case MMI_OPC_MFHI1:
4377 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4378 break;
4379 case MMI_OPC_MFLO1:
4380 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4381 break;
4382 case MMI_OPC_MTHI1:
4383 if (reg != 0) {
4384 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4385 } else {
4386 tcg_gen_movi_tl(cpu_HI[1], 0);
4388 break;
4389 case MMI_OPC_MTLO1:
4390 if (reg != 0) {
4391 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4392 } else {
4393 tcg_gen_movi_tl(cpu_LO[1], 0);
4395 break;
4396 default:
4397 MIPS_INVAL("mfthilo1 TX79");
4398 generate_exception_end(ctx, EXCP_RI);
4399 break;
4402 #endif
4404 /* Arithmetic on HI/LO registers */
4405 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4407 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4408 /* Treat as NOP. */
4409 return;
4412 if (acc != 0) {
4413 check_dsp(ctx);
4416 switch (opc) {
4417 case OPC_MFHI:
4418 #if defined(TARGET_MIPS64)
4419 if (acc != 0) {
4420 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4421 } else
4422 #endif
4424 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4426 break;
4427 case OPC_MFLO:
4428 #if defined(TARGET_MIPS64)
4429 if (acc != 0) {
4430 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4431 } else
4432 #endif
4434 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4436 break;
4437 case OPC_MTHI:
4438 if (reg != 0) {
4439 #if defined(TARGET_MIPS64)
4440 if (acc != 0) {
4441 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4442 } else
4443 #endif
4445 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4447 } else {
4448 tcg_gen_movi_tl(cpu_HI[acc], 0);
4450 break;
4451 case OPC_MTLO:
4452 if (reg != 0) {
4453 #if defined(TARGET_MIPS64)
4454 if (acc != 0) {
4455 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4456 } else
4457 #endif
4459 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4461 } else {
4462 tcg_gen_movi_tl(cpu_LO[acc], 0);
4464 break;
4468 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4469 TCGMemOp memop)
4471 TCGv t0 = tcg_const_tl(addr);
4472 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4473 gen_store_gpr(t0, reg);
4474 tcg_temp_free(t0);
4477 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4478 int rs)
4480 target_long offset;
4481 target_long addr;
4483 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4484 case OPC_ADDIUPC:
4485 if (rs != 0) {
4486 offset = sextract32(ctx->opcode << 2, 0, 21);
4487 addr = addr_add(ctx, pc, offset);
4488 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4490 break;
4491 case R6_OPC_LWPC:
4492 offset = sextract32(ctx->opcode << 2, 0, 21);
4493 addr = addr_add(ctx, pc, offset);
4494 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4495 break;
4496 #if defined(TARGET_MIPS64)
4497 case OPC_LWUPC:
4498 check_mips_64(ctx);
4499 offset = sextract32(ctx->opcode << 2, 0, 21);
4500 addr = addr_add(ctx, pc, offset);
4501 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4502 break;
4503 #endif
4504 default:
4505 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4506 case OPC_AUIPC:
4507 if (rs != 0) {
4508 offset = sextract32(ctx->opcode, 0, 16) << 16;
4509 addr = addr_add(ctx, pc, offset);
4510 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4512 break;
4513 case OPC_ALUIPC:
4514 if (rs != 0) {
4515 offset = sextract32(ctx->opcode, 0, 16) << 16;
4516 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4517 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4519 break;
4520 #if defined(TARGET_MIPS64)
4521 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4522 case R6_OPC_LDPC + (1 << 16):
4523 case R6_OPC_LDPC + (2 << 16):
4524 case R6_OPC_LDPC + (3 << 16):
4525 check_mips_64(ctx);
4526 offset = sextract32(ctx->opcode << 3, 0, 21);
4527 addr = addr_add(ctx, (pc & ~0x7), offset);
4528 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4529 break;
4530 #endif
4531 default:
4532 MIPS_INVAL("OPC_PCREL");
4533 generate_exception_end(ctx, EXCP_RI);
4534 break;
4536 break;
4540 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4542 TCGv t0, t1;
4544 if (rd == 0) {
4545 /* Treat as NOP. */
4546 return;
4549 t0 = tcg_temp_new();
4550 t1 = tcg_temp_new();
4552 gen_load_gpr(t0, rs);
4553 gen_load_gpr(t1, rt);
4555 switch (opc) {
4556 case R6_OPC_DIV:
4558 TCGv t2 = tcg_temp_new();
4559 TCGv t3 = tcg_temp_new();
4560 tcg_gen_ext32s_tl(t0, t0);
4561 tcg_gen_ext32s_tl(t1, t1);
4562 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4563 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4564 tcg_gen_and_tl(t2, t2, t3);
4565 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4566 tcg_gen_or_tl(t2, t2, t3);
4567 tcg_gen_movi_tl(t3, 0);
4568 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4569 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4570 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4571 tcg_temp_free(t3);
4572 tcg_temp_free(t2);
4574 break;
4575 case R6_OPC_MOD:
4577 TCGv t2 = tcg_temp_new();
4578 TCGv t3 = tcg_temp_new();
4579 tcg_gen_ext32s_tl(t0, t0);
4580 tcg_gen_ext32s_tl(t1, t1);
4581 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4582 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4583 tcg_gen_and_tl(t2, t2, t3);
4584 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4585 tcg_gen_or_tl(t2, t2, t3);
4586 tcg_gen_movi_tl(t3, 0);
4587 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4588 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4589 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4590 tcg_temp_free(t3);
4591 tcg_temp_free(t2);
4593 break;
4594 case R6_OPC_DIVU:
4596 TCGv t2 = tcg_const_tl(0);
4597 TCGv t3 = tcg_const_tl(1);
4598 tcg_gen_ext32u_tl(t0, t0);
4599 tcg_gen_ext32u_tl(t1, t1);
4600 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4601 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4602 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4603 tcg_temp_free(t3);
4604 tcg_temp_free(t2);
4606 break;
4607 case R6_OPC_MODU:
4609 TCGv t2 = tcg_const_tl(0);
4610 TCGv t3 = tcg_const_tl(1);
4611 tcg_gen_ext32u_tl(t0, t0);
4612 tcg_gen_ext32u_tl(t1, t1);
4613 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4614 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4615 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4616 tcg_temp_free(t3);
4617 tcg_temp_free(t2);
4619 break;
4620 case R6_OPC_MUL:
4622 TCGv_i32 t2 = tcg_temp_new_i32();
4623 TCGv_i32 t3 = tcg_temp_new_i32();
4624 tcg_gen_trunc_tl_i32(t2, t0);
4625 tcg_gen_trunc_tl_i32(t3, t1);
4626 tcg_gen_mul_i32(t2, t2, t3);
4627 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4628 tcg_temp_free_i32(t2);
4629 tcg_temp_free_i32(t3);
4631 break;
4632 case R6_OPC_MUH:
4634 TCGv_i32 t2 = tcg_temp_new_i32();
4635 TCGv_i32 t3 = tcg_temp_new_i32();
4636 tcg_gen_trunc_tl_i32(t2, t0);
4637 tcg_gen_trunc_tl_i32(t3, t1);
4638 tcg_gen_muls2_i32(t2, t3, t2, t3);
4639 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4640 tcg_temp_free_i32(t2);
4641 tcg_temp_free_i32(t3);
4643 break;
4644 case R6_OPC_MULU:
4646 TCGv_i32 t2 = tcg_temp_new_i32();
4647 TCGv_i32 t3 = tcg_temp_new_i32();
4648 tcg_gen_trunc_tl_i32(t2, t0);
4649 tcg_gen_trunc_tl_i32(t3, t1);
4650 tcg_gen_mul_i32(t2, t2, t3);
4651 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4652 tcg_temp_free_i32(t2);
4653 tcg_temp_free_i32(t3);
4655 break;
4656 case R6_OPC_MUHU:
4658 TCGv_i32 t2 = tcg_temp_new_i32();
4659 TCGv_i32 t3 = tcg_temp_new_i32();
4660 tcg_gen_trunc_tl_i32(t2, t0);
4661 tcg_gen_trunc_tl_i32(t3, t1);
4662 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4663 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4664 tcg_temp_free_i32(t2);
4665 tcg_temp_free_i32(t3);
4667 break;
4668 #if defined(TARGET_MIPS64)
4669 case R6_OPC_DDIV:
4671 TCGv t2 = tcg_temp_new();
4672 TCGv t3 = tcg_temp_new();
4673 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4674 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4675 tcg_gen_and_tl(t2, t2, t3);
4676 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4677 tcg_gen_or_tl(t2, t2, t3);
4678 tcg_gen_movi_tl(t3, 0);
4679 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4680 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4681 tcg_temp_free(t3);
4682 tcg_temp_free(t2);
4684 break;
4685 case R6_OPC_DMOD:
4687 TCGv t2 = tcg_temp_new();
4688 TCGv t3 = tcg_temp_new();
4689 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4690 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4691 tcg_gen_and_tl(t2, t2, t3);
4692 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4693 tcg_gen_or_tl(t2, t2, t3);
4694 tcg_gen_movi_tl(t3, 0);
4695 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4696 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4697 tcg_temp_free(t3);
4698 tcg_temp_free(t2);
4700 break;
4701 case R6_OPC_DDIVU:
4703 TCGv t2 = tcg_const_tl(0);
4704 TCGv t3 = tcg_const_tl(1);
4705 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4706 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4707 tcg_temp_free(t3);
4708 tcg_temp_free(t2);
4710 break;
4711 case R6_OPC_DMODU:
4713 TCGv t2 = tcg_const_tl(0);
4714 TCGv t3 = tcg_const_tl(1);
4715 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4716 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4717 tcg_temp_free(t3);
4718 tcg_temp_free(t2);
4720 break;
4721 case R6_OPC_DMUL:
4722 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4723 break;
4724 case R6_OPC_DMUH:
4726 TCGv t2 = tcg_temp_new();
4727 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4728 tcg_temp_free(t2);
4730 break;
4731 case R6_OPC_DMULU:
4732 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4733 break;
4734 case R6_OPC_DMUHU:
4736 TCGv t2 = tcg_temp_new();
4737 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4738 tcg_temp_free(t2);
4740 break;
4741 #endif
4742 default:
4743 MIPS_INVAL("r6 mul/div");
4744 generate_exception_end(ctx, EXCP_RI);
4745 goto out;
4747 out:
4748 tcg_temp_free(t0);
4749 tcg_temp_free(t1);
4752 #if defined(TARGET_MIPS64)
4753 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4755 TCGv t0, t1;
4757 t0 = tcg_temp_new();
4758 t1 = tcg_temp_new();
4760 gen_load_gpr(t0, rs);
4761 gen_load_gpr(t1, rt);
4763 switch (opc) {
4764 case MMI_OPC_DIV1:
4766 TCGv t2 = tcg_temp_new();
4767 TCGv t3 = tcg_temp_new();
4768 tcg_gen_ext32s_tl(t0, t0);
4769 tcg_gen_ext32s_tl(t1, t1);
4770 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4771 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4772 tcg_gen_and_tl(t2, t2, t3);
4773 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4774 tcg_gen_or_tl(t2, t2, t3);
4775 tcg_gen_movi_tl(t3, 0);
4776 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4777 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4778 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4779 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4780 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4781 tcg_temp_free(t3);
4782 tcg_temp_free(t2);
4784 break;
4785 case MMI_OPC_DIVU1:
4787 TCGv t2 = tcg_const_tl(0);
4788 TCGv t3 = tcg_const_tl(1);
4789 tcg_gen_ext32u_tl(t0, t0);
4790 tcg_gen_ext32u_tl(t1, t1);
4791 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4792 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4793 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4794 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4795 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4796 tcg_temp_free(t3);
4797 tcg_temp_free(t2);
4799 break;
4800 default:
4801 MIPS_INVAL("div1 TX79");
4802 generate_exception_end(ctx, EXCP_RI);
4803 goto out;
4805 out:
4806 tcg_temp_free(t0);
4807 tcg_temp_free(t1);
4809 #endif
4811 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4812 int acc, int rs, int rt)
4814 TCGv t0, t1;
4816 t0 = tcg_temp_new();
4817 t1 = tcg_temp_new();
4819 gen_load_gpr(t0, rs);
4820 gen_load_gpr(t1, rt);
4822 if (acc != 0) {
4823 check_dsp(ctx);
4826 switch (opc) {
4827 case OPC_DIV:
4829 TCGv t2 = tcg_temp_new();
4830 TCGv t3 = tcg_temp_new();
4831 tcg_gen_ext32s_tl(t0, t0);
4832 tcg_gen_ext32s_tl(t1, t1);
4833 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4834 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4835 tcg_gen_and_tl(t2, t2, t3);
4836 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4837 tcg_gen_or_tl(t2, t2, t3);
4838 tcg_gen_movi_tl(t3, 0);
4839 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4840 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4841 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4842 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4843 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4844 tcg_temp_free(t3);
4845 tcg_temp_free(t2);
4847 break;
4848 case OPC_DIVU:
4850 TCGv t2 = tcg_const_tl(0);
4851 TCGv t3 = tcg_const_tl(1);
4852 tcg_gen_ext32u_tl(t0, t0);
4853 tcg_gen_ext32u_tl(t1, t1);
4854 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4855 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4856 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4857 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4858 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4859 tcg_temp_free(t3);
4860 tcg_temp_free(t2);
4862 break;
4863 case OPC_MULT:
4865 TCGv_i32 t2 = tcg_temp_new_i32();
4866 TCGv_i32 t3 = tcg_temp_new_i32();
4867 tcg_gen_trunc_tl_i32(t2, t0);
4868 tcg_gen_trunc_tl_i32(t3, t1);
4869 tcg_gen_muls2_i32(t2, t3, t2, t3);
4870 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4871 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4872 tcg_temp_free_i32(t2);
4873 tcg_temp_free_i32(t3);
4875 break;
4876 case OPC_MULTU:
4878 TCGv_i32 t2 = tcg_temp_new_i32();
4879 TCGv_i32 t3 = tcg_temp_new_i32();
4880 tcg_gen_trunc_tl_i32(t2, t0);
4881 tcg_gen_trunc_tl_i32(t3, t1);
4882 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4883 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4884 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4885 tcg_temp_free_i32(t2);
4886 tcg_temp_free_i32(t3);
4888 break;
4889 #if defined(TARGET_MIPS64)
4890 case OPC_DDIV:
4892 TCGv t2 = tcg_temp_new();
4893 TCGv t3 = tcg_temp_new();
4894 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4895 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4896 tcg_gen_and_tl(t2, t2, t3);
4897 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4898 tcg_gen_or_tl(t2, t2, t3);
4899 tcg_gen_movi_tl(t3, 0);
4900 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4901 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4902 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4903 tcg_temp_free(t3);
4904 tcg_temp_free(t2);
4906 break;
4907 case OPC_DDIVU:
4909 TCGv t2 = tcg_const_tl(0);
4910 TCGv t3 = tcg_const_tl(1);
4911 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4912 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4913 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4914 tcg_temp_free(t3);
4915 tcg_temp_free(t2);
4917 break;
4918 case OPC_DMULT:
4919 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4920 break;
4921 case OPC_DMULTU:
4922 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4923 break;
4924 #endif
4925 case OPC_MADD:
4927 TCGv_i64 t2 = tcg_temp_new_i64();
4928 TCGv_i64 t3 = tcg_temp_new_i64();
4930 tcg_gen_ext_tl_i64(t2, t0);
4931 tcg_gen_ext_tl_i64(t3, t1);
4932 tcg_gen_mul_i64(t2, t2, t3);
4933 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4934 tcg_gen_add_i64(t2, t2, t3);
4935 tcg_temp_free_i64(t3);
4936 gen_move_low32(cpu_LO[acc], t2);
4937 gen_move_high32(cpu_HI[acc], t2);
4938 tcg_temp_free_i64(t2);
4940 break;
4941 case OPC_MADDU:
4943 TCGv_i64 t2 = tcg_temp_new_i64();
4944 TCGv_i64 t3 = tcg_temp_new_i64();
4946 tcg_gen_ext32u_tl(t0, t0);
4947 tcg_gen_ext32u_tl(t1, t1);
4948 tcg_gen_extu_tl_i64(t2, t0);
4949 tcg_gen_extu_tl_i64(t3, t1);
4950 tcg_gen_mul_i64(t2, t2, t3);
4951 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4952 tcg_gen_add_i64(t2, t2, t3);
4953 tcg_temp_free_i64(t3);
4954 gen_move_low32(cpu_LO[acc], t2);
4955 gen_move_high32(cpu_HI[acc], t2);
4956 tcg_temp_free_i64(t2);
4958 break;
4959 case OPC_MSUB:
4961 TCGv_i64 t2 = tcg_temp_new_i64();
4962 TCGv_i64 t3 = tcg_temp_new_i64();
4964 tcg_gen_ext_tl_i64(t2, t0);
4965 tcg_gen_ext_tl_i64(t3, t1);
4966 tcg_gen_mul_i64(t2, t2, t3);
4967 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4968 tcg_gen_sub_i64(t2, t3, t2);
4969 tcg_temp_free_i64(t3);
4970 gen_move_low32(cpu_LO[acc], t2);
4971 gen_move_high32(cpu_HI[acc], t2);
4972 tcg_temp_free_i64(t2);
4974 break;
4975 case OPC_MSUBU:
4977 TCGv_i64 t2 = tcg_temp_new_i64();
4978 TCGv_i64 t3 = tcg_temp_new_i64();
4980 tcg_gen_ext32u_tl(t0, t0);
4981 tcg_gen_ext32u_tl(t1, t1);
4982 tcg_gen_extu_tl_i64(t2, t0);
4983 tcg_gen_extu_tl_i64(t3, t1);
4984 tcg_gen_mul_i64(t2, t2, t3);
4985 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4986 tcg_gen_sub_i64(t2, t3, t2);
4987 tcg_temp_free_i64(t3);
4988 gen_move_low32(cpu_LO[acc], t2);
4989 gen_move_high32(cpu_HI[acc], t2);
4990 tcg_temp_free_i64(t2);
4992 break;
4993 default:
4994 MIPS_INVAL("mul/div");
4995 generate_exception_end(ctx, EXCP_RI);
4996 goto out;
4998 out:
4999 tcg_temp_free(t0);
5000 tcg_temp_free(t1);
5004 * These MULT[U] and MADD[U] instructions implemented in for example
5005 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5006 * architectures are special three-operand variants with the syntax
5008 * MULT[U][1] rd, rs, rt
5010 * such that
5012 * (rd, LO, HI) <- rs * rt
5014 * and
5016 * MADD[U][1] rd, rs, rt
5018 * such that
5020 * (rd, LO, HI) <- (LO, HI) + rs * rt
5022 * where the low-order 32-bits of the result is placed into both the
5023 * GPR rd and the special register LO. The high-order 32-bits of the
5024 * result is placed into the special register HI.
5026 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5027 * which is the zero register that always reads as 0.
5029 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5030 int rd, int rs, int rt)
5032 TCGv t0 = tcg_temp_new();
5033 TCGv t1 = tcg_temp_new();
5034 int acc = 0;
5036 gen_load_gpr(t0, rs);
5037 gen_load_gpr(t1, rt);
5039 switch (opc) {
5040 case MMI_OPC_MULT1:
5041 acc = 1;
5042 /* Fall through */
5043 case OPC_MULT:
5045 TCGv_i32 t2 = tcg_temp_new_i32();
5046 TCGv_i32 t3 = tcg_temp_new_i32();
5047 tcg_gen_trunc_tl_i32(t2, t0);
5048 tcg_gen_trunc_tl_i32(t3, t1);
5049 tcg_gen_muls2_i32(t2, t3, t2, t3);
5050 if (rd) {
5051 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5053 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5054 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5055 tcg_temp_free_i32(t2);
5056 tcg_temp_free_i32(t3);
5058 break;
5059 case MMI_OPC_MULTU1:
5060 acc = 1;
5061 /* Fall through */
5062 case OPC_MULTU:
5064 TCGv_i32 t2 = tcg_temp_new_i32();
5065 TCGv_i32 t3 = tcg_temp_new_i32();
5066 tcg_gen_trunc_tl_i32(t2, t0);
5067 tcg_gen_trunc_tl_i32(t3, t1);
5068 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5069 if (rd) {
5070 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5072 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5073 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5074 tcg_temp_free_i32(t2);
5075 tcg_temp_free_i32(t3);
5077 break;
5078 case MMI_OPC_MADD1:
5079 acc = 1;
5080 /* Fall through */
5081 case MMI_OPC_MADD:
5083 TCGv_i64 t2 = tcg_temp_new_i64();
5084 TCGv_i64 t3 = tcg_temp_new_i64();
5086 tcg_gen_ext_tl_i64(t2, t0);
5087 tcg_gen_ext_tl_i64(t3, t1);
5088 tcg_gen_mul_i64(t2, t2, t3);
5089 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5090 tcg_gen_add_i64(t2, t2, t3);
5091 tcg_temp_free_i64(t3);
5092 gen_move_low32(cpu_LO[acc], t2);
5093 gen_move_high32(cpu_HI[acc], t2);
5094 if (rd) {
5095 gen_move_low32(cpu_gpr[rd], t2);
5097 tcg_temp_free_i64(t2);
5099 break;
5100 case MMI_OPC_MADDU1:
5101 acc = 1;
5102 /* Fall through */
5103 case MMI_OPC_MADDU:
5105 TCGv_i64 t2 = tcg_temp_new_i64();
5106 TCGv_i64 t3 = tcg_temp_new_i64();
5108 tcg_gen_ext32u_tl(t0, t0);
5109 tcg_gen_ext32u_tl(t1, t1);
5110 tcg_gen_extu_tl_i64(t2, t0);
5111 tcg_gen_extu_tl_i64(t3, t1);
5112 tcg_gen_mul_i64(t2, t2, t3);
5113 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5114 tcg_gen_add_i64(t2, t2, t3);
5115 tcg_temp_free_i64(t3);
5116 gen_move_low32(cpu_LO[acc], t2);
5117 gen_move_high32(cpu_HI[acc], t2);
5118 if (rd) {
5119 gen_move_low32(cpu_gpr[rd], t2);
5121 tcg_temp_free_i64(t2);
5123 break;
5124 default:
5125 MIPS_INVAL("mul/madd TXx9");
5126 generate_exception_end(ctx, EXCP_RI);
5127 goto out;
5130 out:
5131 tcg_temp_free(t0);
5132 tcg_temp_free(t1);
5135 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
5136 int rd, int rs, int rt)
5138 TCGv t0 = tcg_temp_new();
5139 TCGv t1 = tcg_temp_new();
5141 gen_load_gpr(t0, rs);
5142 gen_load_gpr(t1, rt);
5144 switch (opc) {
5145 case OPC_VR54XX_MULS:
5146 gen_helper_muls(t0, cpu_env, t0, t1);
5147 break;
5148 case OPC_VR54XX_MULSU:
5149 gen_helper_mulsu(t0, cpu_env, t0, t1);
5150 break;
5151 case OPC_VR54XX_MACC:
5152 gen_helper_macc(t0, cpu_env, t0, t1);
5153 break;
5154 case OPC_VR54XX_MACCU:
5155 gen_helper_maccu(t0, cpu_env, t0, t1);
5156 break;
5157 case OPC_VR54XX_MSAC:
5158 gen_helper_msac(t0, cpu_env, t0, t1);
5159 break;
5160 case OPC_VR54XX_MSACU:
5161 gen_helper_msacu(t0, cpu_env, t0, t1);
5162 break;
5163 case OPC_VR54XX_MULHI:
5164 gen_helper_mulhi(t0, cpu_env, t0, t1);
5165 break;
5166 case OPC_VR54XX_MULHIU:
5167 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5168 break;
5169 case OPC_VR54XX_MULSHI:
5170 gen_helper_mulshi(t0, cpu_env, t0, t1);
5171 break;
5172 case OPC_VR54XX_MULSHIU:
5173 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5174 break;
5175 case OPC_VR54XX_MACCHI:
5176 gen_helper_macchi(t0, cpu_env, t0, t1);
5177 break;
5178 case OPC_VR54XX_MACCHIU:
5179 gen_helper_macchiu(t0, cpu_env, t0, t1);
5180 break;
5181 case OPC_VR54XX_MSACHI:
5182 gen_helper_msachi(t0, cpu_env, t0, t1);
5183 break;
5184 case OPC_VR54XX_MSACHIU:
5185 gen_helper_msachiu(t0, cpu_env, t0, t1);
5186 break;
5187 default:
5188 MIPS_INVAL("mul vr54xx");
5189 generate_exception_end(ctx, EXCP_RI);
5190 goto out;
5192 gen_store_gpr(t0, rd);
5194 out:
5195 tcg_temp_free(t0);
5196 tcg_temp_free(t1);
5199 static void gen_cl (DisasContext *ctx, uint32_t opc,
5200 int rd, int rs)
5202 TCGv t0;
5204 if (rd == 0) {
5205 /* Treat as NOP. */
5206 return;
5208 t0 = cpu_gpr[rd];
5209 gen_load_gpr(t0, rs);
5211 switch (opc) {
5212 case OPC_CLO:
5213 case R6_OPC_CLO:
5214 #if defined(TARGET_MIPS64)
5215 case OPC_DCLO:
5216 case R6_OPC_DCLO:
5217 #endif
5218 tcg_gen_not_tl(t0, t0);
5219 break;
5222 switch (opc) {
5223 case OPC_CLO:
5224 case R6_OPC_CLO:
5225 case OPC_CLZ:
5226 case R6_OPC_CLZ:
5227 tcg_gen_ext32u_tl(t0, t0);
5228 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5229 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5230 break;
5231 #if defined(TARGET_MIPS64)
5232 case OPC_DCLO:
5233 case R6_OPC_DCLO:
5234 case OPC_DCLZ:
5235 case R6_OPC_DCLZ:
5236 tcg_gen_clzi_i64(t0, t0, 64);
5237 break;
5238 #endif
5242 /* Godson integer instructions */
5243 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5244 int rd, int rs, int rt)
5246 TCGv t0, t1;
5248 if (rd == 0) {
5249 /* Treat as NOP. */
5250 return;
5253 switch (opc) {
5254 case OPC_MULT_G_2E:
5255 case OPC_MULT_G_2F:
5256 case OPC_MULTU_G_2E:
5257 case OPC_MULTU_G_2F:
5258 #if defined(TARGET_MIPS64)
5259 case OPC_DMULT_G_2E:
5260 case OPC_DMULT_G_2F:
5261 case OPC_DMULTU_G_2E:
5262 case OPC_DMULTU_G_2F:
5263 #endif
5264 t0 = tcg_temp_new();
5265 t1 = tcg_temp_new();
5266 break;
5267 default:
5268 t0 = tcg_temp_local_new();
5269 t1 = tcg_temp_local_new();
5270 break;
5273 gen_load_gpr(t0, rs);
5274 gen_load_gpr(t1, rt);
5276 switch (opc) {
5277 case OPC_MULT_G_2E:
5278 case OPC_MULT_G_2F:
5279 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5280 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5281 break;
5282 case OPC_MULTU_G_2E:
5283 case OPC_MULTU_G_2F:
5284 tcg_gen_ext32u_tl(t0, t0);
5285 tcg_gen_ext32u_tl(t1, t1);
5286 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5287 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5288 break;
5289 case OPC_DIV_G_2E:
5290 case OPC_DIV_G_2F:
5292 TCGLabel *l1 = gen_new_label();
5293 TCGLabel *l2 = gen_new_label();
5294 TCGLabel *l3 = gen_new_label();
5295 tcg_gen_ext32s_tl(t0, t0);
5296 tcg_gen_ext32s_tl(t1, t1);
5297 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5298 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5299 tcg_gen_br(l3);
5300 gen_set_label(l1);
5301 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5302 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5303 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5304 tcg_gen_br(l3);
5305 gen_set_label(l2);
5306 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5307 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5308 gen_set_label(l3);
5310 break;
5311 case OPC_DIVU_G_2E:
5312 case OPC_DIVU_G_2F:
5314 TCGLabel *l1 = gen_new_label();
5315 TCGLabel *l2 = gen_new_label();
5316 tcg_gen_ext32u_tl(t0, t0);
5317 tcg_gen_ext32u_tl(t1, t1);
5318 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5319 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5320 tcg_gen_br(l2);
5321 gen_set_label(l1);
5322 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5323 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5324 gen_set_label(l2);
5326 break;
5327 case OPC_MOD_G_2E:
5328 case OPC_MOD_G_2F:
5330 TCGLabel *l1 = gen_new_label();
5331 TCGLabel *l2 = gen_new_label();
5332 TCGLabel *l3 = gen_new_label();
5333 tcg_gen_ext32u_tl(t0, t0);
5334 tcg_gen_ext32u_tl(t1, t1);
5335 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5336 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5337 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5338 gen_set_label(l1);
5339 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5340 tcg_gen_br(l3);
5341 gen_set_label(l2);
5342 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5343 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5344 gen_set_label(l3);
5346 break;
5347 case OPC_MODU_G_2E:
5348 case OPC_MODU_G_2F:
5350 TCGLabel *l1 = gen_new_label();
5351 TCGLabel *l2 = gen_new_label();
5352 tcg_gen_ext32u_tl(t0, t0);
5353 tcg_gen_ext32u_tl(t1, t1);
5354 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5355 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5356 tcg_gen_br(l2);
5357 gen_set_label(l1);
5358 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5359 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5360 gen_set_label(l2);
5362 break;
5363 #if defined(TARGET_MIPS64)
5364 case OPC_DMULT_G_2E:
5365 case OPC_DMULT_G_2F:
5366 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5367 break;
5368 case OPC_DMULTU_G_2E:
5369 case OPC_DMULTU_G_2F:
5370 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5371 break;
5372 case OPC_DDIV_G_2E:
5373 case OPC_DDIV_G_2F:
5375 TCGLabel *l1 = gen_new_label();
5376 TCGLabel *l2 = gen_new_label();
5377 TCGLabel *l3 = gen_new_label();
5378 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5379 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5380 tcg_gen_br(l3);
5381 gen_set_label(l1);
5382 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5383 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5384 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5385 tcg_gen_br(l3);
5386 gen_set_label(l2);
5387 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5388 gen_set_label(l3);
5390 break;
5391 case OPC_DDIVU_G_2E:
5392 case OPC_DDIVU_G_2F:
5394 TCGLabel *l1 = gen_new_label();
5395 TCGLabel *l2 = gen_new_label();
5396 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5397 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5398 tcg_gen_br(l2);
5399 gen_set_label(l1);
5400 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5401 gen_set_label(l2);
5403 break;
5404 case OPC_DMOD_G_2E:
5405 case OPC_DMOD_G_2F:
5407 TCGLabel *l1 = gen_new_label();
5408 TCGLabel *l2 = gen_new_label();
5409 TCGLabel *l3 = gen_new_label();
5410 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5411 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5412 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5413 gen_set_label(l1);
5414 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5415 tcg_gen_br(l3);
5416 gen_set_label(l2);
5417 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5418 gen_set_label(l3);
5420 break;
5421 case OPC_DMODU_G_2E:
5422 case OPC_DMODU_G_2F:
5424 TCGLabel *l1 = gen_new_label();
5425 TCGLabel *l2 = gen_new_label();
5426 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5427 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5428 tcg_gen_br(l2);
5429 gen_set_label(l1);
5430 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5431 gen_set_label(l2);
5433 break;
5434 #endif
5437 tcg_temp_free(t0);
5438 tcg_temp_free(t1);
5441 /* Loongson multimedia instructions */
5442 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5444 uint32_t opc, shift_max;
5445 TCGv_i64 t0, t1;
5447 opc = MASK_LMI(ctx->opcode);
5448 switch (opc) {
5449 case OPC_ADD_CP2:
5450 case OPC_SUB_CP2:
5451 case OPC_DADD_CP2:
5452 case OPC_DSUB_CP2:
5453 t0 = tcg_temp_local_new_i64();
5454 t1 = tcg_temp_local_new_i64();
5455 break;
5456 default:
5457 t0 = tcg_temp_new_i64();
5458 t1 = tcg_temp_new_i64();
5459 break;
5462 check_cp1_enabled(ctx);
5463 gen_load_fpr64(ctx, t0, rs);
5464 gen_load_fpr64(ctx, t1, rt);
5466 #define LMI_HELPER(UP, LO) \
5467 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5468 #define LMI_HELPER_1(UP, LO) \
5469 case OPC_##UP: gen_helper_##LO(t0, t0); break
5470 #define LMI_DIRECT(UP, LO, OP) \
5471 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5473 switch (opc) {
5474 LMI_HELPER(PADDSH, paddsh);
5475 LMI_HELPER(PADDUSH, paddush);
5476 LMI_HELPER(PADDH, paddh);
5477 LMI_HELPER(PADDW, paddw);
5478 LMI_HELPER(PADDSB, paddsb);
5479 LMI_HELPER(PADDUSB, paddusb);
5480 LMI_HELPER(PADDB, paddb);
5482 LMI_HELPER(PSUBSH, psubsh);
5483 LMI_HELPER(PSUBUSH, psubush);
5484 LMI_HELPER(PSUBH, psubh);
5485 LMI_HELPER(PSUBW, psubw);
5486 LMI_HELPER(PSUBSB, psubsb);
5487 LMI_HELPER(PSUBUSB, psubusb);
5488 LMI_HELPER(PSUBB, psubb);
5490 LMI_HELPER(PSHUFH, pshufh);
5491 LMI_HELPER(PACKSSWH, packsswh);
5492 LMI_HELPER(PACKSSHB, packsshb);
5493 LMI_HELPER(PACKUSHB, packushb);
5495 LMI_HELPER(PUNPCKLHW, punpcklhw);
5496 LMI_HELPER(PUNPCKHHW, punpckhhw);
5497 LMI_HELPER(PUNPCKLBH, punpcklbh);
5498 LMI_HELPER(PUNPCKHBH, punpckhbh);
5499 LMI_HELPER(PUNPCKLWD, punpcklwd);
5500 LMI_HELPER(PUNPCKHWD, punpckhwd);
5502 LMI_HELPER(PAVGH, pavgh);
5503 LMI_HELPER(PAVGB, pavgb);
5504 LMI_HELPER(PMAXSH, pmaxsh);
5505 LMI_HELPER(PMINSH, pminsh);
5506 LMI_HELPER(PMAXUB, pmaxub);
5507 LMI_HELPER(PMINUB, pminub);
5509 LMI_HELPER(PCMPEQW, pcmpeqw);
5510 LMI_HELPER(PCMPGTW, pcmpgtw);
5511 LMI_HELPER(PCMPEQH, pcmpeqh);
5512 LMI_HELPER(PCMPGTH, pcmpgth);
5513 LMI_HELPER(PCMPEQB, pcmpeqb);
5514 LMI_HELPER(PCMPGTB, pcmpgtb);
5516 LMI_HELPER(PSLLW, psllw);
5517 LMI_HELPER(PSLLH, psllh);
5518 LMI_HELPER(PSRLW, psrlw);
5519 LMI_HELPER(PSRLH, psrlh);
5520 LMI_HELPER(PSRAW, psraw);
5521 LMI_HELPER(PSRAH, psrah);
5523 LMI_HELPER(PMULLH, pmullh);
5524 LMI_HELPER(PMULHH, pmulhh);
5525 LMI_HELPER(PMULHUH, pmulhuh);
5526 LMI_HELPER(PMADDHW, pmaddhw);
5528 LMI_HELPER(PASUBUB, pasubub);
5529 LMI_HELPER_1(BIADD, biadd);
5530 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5532 LMI_DIRECT(PADDD, paddd, add);
5533 LMI_DIRECT(PSUBD, psubd, sub);
5534 LMI_DIRECT(XOR_CP2, xor, xor);
5535 LMI_DIRECT(NOR_CP2, nor, nor);
5536 LMI_DIRECT(AND_CP2, and, and);
5537 LMI_DIRECT(OR_CP2, or, or);
5539 case OPC_PANDN:
5540 tcg_gen_andc_i64(t0, t1, t0);
5541 break;
5543 case OPC_PINSRH_0:
5544 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5545 break;
5546 case OPC_PINSRH_1:
5547 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5548 break;
5549 case OPC_PINSRH_2:
5550 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5551 break;
5552 case OPC_PINSRH_3:
5553 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5554 break;
5556 case OPC_PEXTRH:
5557 tcg_gen_andi_i64(t1, t1, 3);
5558 tcg_gen_shli_i64(t1, t1, 4);
5559 tcg_gen_shr_i64(t0, t0, t1);
5560 tcg_gen_ext16u_i64(t0, t0);
5561 break;
5563 case OPC_ADDU_CP2:
5564 tcg_gen_add_i64(t0, t0, t1);
5565 tcg_gen_ext32s_i64(t0, t0);
5566 break;
5567 case OPC_SUBU_CP2:
5568 tcg_gen_sub_i64(t0, t0, t1);
5569 tcg_gen_ext32s_i64(t0, t0);
5570 break;
5572 case OPC_SLL_CP2:
5573 shift_max = 32;
5574 goto do_shift;
5575 case OPC_SRL_CP2:
5576 shift_max = 32;
5577 goto do_shift;
5578 case OPC_SRA_CP2:
5579 shift_max = 32;
5580 goto do_shift;
5581 case OPC_DSLL_CP2:
5582 shift_max = 64;
5583 goto do_shift;
5584 case OPC_DSRL_CP2:
5585 shift_max = 64;
5586 goto do_shift;
5587 case OPC_DSRA_CP2:
5588 shift_max = 64;
5589 goto do_shift;
5590 do_shift:
5591 /* Make sure shift count isn't TCG undefined behaviour. */
5592 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5594 switch (opc) {
5595 case OPC_SLL_CP2:
5596 case OPC_DSLL_CP2:
5597 tcg_gen_shl_i64(t0, t0, t1);
5598 break;
5599 case OPC_SRA_CP2:
5600 case OPC_DSRA_CP2:
5601 /* Since SRA is UndefinedResult without sign-extended inputs,
5602 we can treat SRA and DSRA the same. */
5603 tcg_gen_sar_i64(t0, t0, t1);
5604 break;
5605 case OPC_SRL_CP2:
5606 /* We want to shift in zeros for SRL; zero-extend first. */
5607 tcg_gen_ext32u_i64(t0, t0);
5608 /* FALLTHRU */
5609 case OPC_DSRL_CP2:
5610 tcg_gen_shr_i64(t0, t0, t1);
5611 break;
5614 if (shift_max == 32) {
5615 tcg_gen_ext32s_i64(t0, t0);
5618 /* Shifts larger than MAX produce zero. */
5619 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5620 tcg_gen_neg_i64(t1, t1);
5621 tcg_gen_and_i64(t0, t0, t1);
5622 break;
5624 case OPC_ADD_CP2:
5625 case OPC_DADD_CP2:
5627 TCGv_i64 t2 = tcg_temp_new_i64();
5628 TCGLabel *lab = gen_new_label();
5630 tcg_gen_mov_i64(t2, t0);
5631 tcg_gen_add_i64(t0, t1, t2);
5632 if (opc == OPC_ADD_CP2) {
5633 tcg_gen_ext32s_i64(t0, t0);
5635 tcg_gen_xor_i64(t1, t1, t2);
5636 tcg_gen_xor_i64(t2, t2, t0);
5637 tcg_gen_andc_i64(t1, t2, t1);
5638 tcg_temp_free_i64(t2);
5639 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5640 generate_exception(ctx, EXCP_OVERFLOW);
5641 gen_set_label(lab);
5642 break;
5645 case OPC_SUB_CP2:
5646 case OPC_DSUB_CP2:
5648 TCGv_i64 t2 = tcg_temp_new_i64();
5649 TCGLabel *lab = gen_new_label();
5651 tcg_gen_mov_i64(t2, t0);
5652 tcg_gen_sub_i64(t0, t1, t2);
5653 if (opc == OPC_SUB_CP2) {
5654 tcg_gen_ext32s_i64(t0, t0);
5656 tcg_gen_xor_i64(t1, t1, t2);
5657 tcg_gen_xor_i64(t2, t2, t0);
5658 tcg_gen_and_i64(t1, t1, t2);
5659 tcg_temp_free_i64(t2);
5660 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5661 generate_exception(ctx, EXCP_OVERFLOW);
5662 gen_set_label(lab);
5663 break;
5666 case OPC_PMULUW:
5667 tcg_gen_ext32u_i64(t0, t0);
5668 tcg_gen_ext32u_i64(t1, t1);
5669 tcg_gen_mul_i64(t0, t0, t1);
5670 break;
5672 case OPC_SEQU_CP2:
5673 case OPC_SEQ_CP2:
5674 case OPC_SLTU_CP2:
5675 case OPC_SLT_CP2:
5676 case OPC_SLEU_CP2:
5677 case OPC_SLE_CP2:
5678 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5679 FD field is the CC field? */
5680 default:
5681 MIPS_INVAL("loongson_cp2");
5682 generate_exception_end(ctx, EXCP_RI);
5683 return;
5686 #undef LMI_HELPER
5687 #undef LMI_DIRECT
5689 gen_store_fpr64(ctx, t0, rd);
5691 tcg_temp_free_i64(t0);
5692 tcg_temp_free_i64(t1);
5695 /* Traps */
5696 static void gen_trap (DisasContext *ctx, uint32_t opc,
5697 int rs, int rt, int16_t imm)
5699 int cond;
5700 TCGv t0 = tcg_temp_new();
5701 TCGv t1 = tcg_temp_new();
5703 cond = 0;
5704 /* Load needed operands */
5705 switch (opc) {
5706 case OPC_TEQ:
5707 case OPC_TGE:
5708 case OPC_TGEU:
5709 case OPC_TLT:
5710 case OPC_TLTU:
5711 case OPC_TNE:
5712 /* Compare two registers */
5713 if (rs != rt) {
5714 gen_load_gpr(t0, rs);
5715 gen_load_gpr(t1, rt);
5716 cond = 1;
5718 break;
5719 case OPC_TEQI:
5720 case OPC_TGEI:
5721 case OPC_TGEIU:
5722 case OPC_TLTI:
5723 case OPC_TLTIU:
5724 case OPC_TNEI:
5725 /* Compare register to immediate */
5726 if (rs != 0 || imm != 0) {
5727 gen_load_gpr(t0, rs);
5728 tcg_gen_movi_tl(t1, (int32_t)imm);
5729 cond = 1;
5731 break;
5733 if (cond == 0) {
5734 switch (opc) {
5735 case OPC_TEQ: /* rs == rs */
5736 case OPC_TEQI: /* r0 == 0 */
5737 case OPC_TGE: /* rs >= rs */
5738 case OPC_TGEI: /* r0 >= 0 */
5739 case OPC_TGEU: /* rs >= rs unsigned */
5740 case OPC_TGEIU: /* r0 >= 0 unsigned */
5741 /* Always trap */
5742 generate_exception_end(ctx, EXCP_TRAP);
5743 break;
5744 case OPC_TLT: /* rs < rs */
5745 case OPC_TLTI: /* r0 < 0 */
5746 case OPC_TLTU: /* rs < rs unsigned */
5747 case OPC_TLTIU: /* r0 < 0 unsigned */
5748 case OPC_TNE: /* rs != rs */
5749 case OPC_TNEI: /* r0 != 0 */
5750 /* Never trap: treat as NOP. */
5751 break;
5753 } else {
5754 TCGLabel *l1 = gen_new_label();
5756 switch (opc) {
5757 case OPC_TEQ:
5758 case OPC_TEQI:
5759 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5760 break;
5761 case OPC_TGE:
5762 case OPC_TGEI:
5763 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5764 break;
5765 case OPC_TGEU:
5766 case OPC_TGEIU:
5767 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5768 break;
5769 case OPC_TLT:
5770 case OPC_TLTI:
5771 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5772 break;
5773 case OPC_TLTU:
5774 case OPC_TLTIU:
5775 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5776 break;
5777 case OPC_TNE:
5778 case OPC_TNEI:
5779 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5780 break;
5782 generate_exception(ctx, EXCP_TRAP);
5783 gen_set_label(l1);
5785 tcg_temp_free(t0);
5786 tcg_temp_free(t1);
5789 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5791 if (unlikely(ctx->base.singlestep_enabled)) {
5792 return false;
5795 #ifndef CONFIG_USER_ONLY
5796 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5797 #else
5798 return true;
5799 #endif
5802 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5804 if (use_goto_tb(ctx, dest)) {
5805 tcg_gen_goto_tb(n);
5806 gen_save_pc(dest);
5807 tcg_gen_exit_tb(ctx->base.tb, n);
5808 } else {
5809 gen_save_pc(dest);
5810 if (ctx->base.singlestep_enabled) {
5811 save_cpu_state(ctx, 0);
5812 gen_helper_raise_exception_debug(cpu_env);
5814 tcg_gen_lookup_and_goto_ptr();
5818 /* Branches (before delay slot) */
5819 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5820 int insn_bytes,
5821 int rs, int rt, int32_t offset,
5822 int delayslot_size)
5824 target_ulong btgt = -1;
5825 int blink = 0;
5826 int bcond_compute = 0;
5827 TCGv t0 = tcg_temp_new();
5828 TCGv t1 = tcg_temp_new();
5830 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5831 #ifdef MIPS_DEBUG_DISAS
5832 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5833 TARGET_FMT_lx "\n", ctx->base.pc_next);
5834 #endif
5835 generate_exception_end(ctx, EXCP_RI);
5836 goto out;
5839 /* Load needed operands */
5840 switch (opc) {
5841 case OPC_BEQ:
5842 case OPC_BEQL:
5843 case OPC_BNE:
5844 case OPC_BNEL:
5845 /* Compare two registers */
5846 if (rs != rt) {
5847 gen_load_gpr(t0, rs);
5848 gen_load_gpr(t1, rt);
5849 bcond_compute = 1;
5851 btgt = ctx->base.pc_next + insn_bytes + offset;
5852 break;
5853 case OPC_BGEZ:
5854 case OPC_BGEZAL:
5855 case OPC_BGEZALL:
5856 case OPC_BGEZL:
5857 case OPC_BGTZ:
5858 case OPC_BGTZL:
5859 case OPC_BLEZ:
5860 case OPC_BLEZL:
5861 case OPC_BLTZ:
5862 case OPC_BLTZAL:
5863 case OPC_BLTZALL:
5864 case OPC_BLTZL:
5865 /* Compare to zero */
5866 if (rs != 0) {
5867 gen_load_gpr(t0, rs);
5868 bcond_compute = 1;
5870 btgt = ctx->base.pc_next + insn_bytes + offset;
5871 break;
5872 case OPC_BPOSGE32:
5873 #if defined(TARGET_MIPS64)
5874 case OPC_BPOSGE64:
5875 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5876 #else
5877 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5878 #endif
5879 bcond_compute = 1;
5880 btgt = ctx->base.pc_next + insn_bytes + offset;
5881 break;
5882 case OPC_J:
5883 case OPC_JAL:
5884 case OPC_JALX:
5885 /* Jump to immediate */
5886 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5887 (uint32_t)offset;
5888 break;
5889 case OPC_JR:
5890 case OPC_JALR:
5891 /* Jump to register */
5892 if (offset != 0 && offset != 16) {
5893 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5894 others are reserved. */
5895 MIPS_INVAL("jump hint");
5896 generate_exception_end(ctx, EXCP_RI);
5897 goto out;
5899 gen_load_gpr(btarget, rs);
5900 break;
5901 default:
5902 MIPS_INVAL("branch/jump");
5903 generate_exception_end(ctx, EXCP_RI);
5904 goto out;
5906 if (bcond_compute == 0) {
5907 /* No condition to be computed */
5908 switch (opc) {
5909 case OPC_BEQ: /* rx == rx */
5910 case OPC_BEQL: /* rx == rx likely */
5911 case OPC_BGEZ: /* 0 >= 0 */
5912 case OPC_BGEZL: /* 0 >= 0 likely */
5913 case OPC_BLEZ: /* 0 <= 0 */
5914 case OPC_BLEZL: /* 0 <= 0 likely */
5915 /* Always take */
5916 ctx->hflags |= MIPS_HFLAG_B;
5917 break;
5918 case OPC_BGEZAL: /* 0 >= 0 */
5919 case OPC_BGEZALL: /* 0 >= 0 likely */
5920 /* Always take and link */
5921 blink = 31;
5922 ctx->hflags |= MIPS_HFLAG_B;
5923 break;
5924 case OPC_BNE: /* rx != rx */
5925 case OPC_BGTZ: /* 0 > 0 */
5926 case OPC_BLTZ: /* 0 < 0 */
5927 /* Treat as NOP. */
5928 goto out;
5929 case OPC_BLTZAL: /* 0 < 0 */
5930 /* Handle as an unconditional branch to get correct delay
5931 slot checking. */
5932 blink = 31;
5933 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5934 ctx->hflags |= MIPS_HFLAG_B;
5935 break;
5936 case OPC_BLTZALL: /* 0 < 0 likely */
5937 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5938 /* Skip the instruction in the delay slot */
5939 ctx->base.pc_next += 4;
5940 goto out;
5941 case OPC_BNEL: /* rx != rx likely */
5942 case OPC_BGTZL: /* 0 > 0 likely */
5943 case OPC_BLTZL: /* 0 < 0 likely */
5944 /* Skip the instruction in the delay slot */
5945 ctx->base.pc_next += 4;
5946 goto out;
5947 case OPC_J:
5948 ctx->hflags |= MIPS_HFLAG_B;
5949 break;
5950 case OPC_JALX:
5951 ctx->hflags |= MIPS_HFLAG_BX;
5952 /* Fallthrough */
5953 case OPC_JAL:
5954 blink = 31;
5955 ctx->hflags |= MIPS_HFLAG_B;
5956 break;
5957 case OPC_JR:
5958 ctx->hflags |= MIPS_HFLAG_BR;
5959 break;
5960 case OPC_JALR:
5961 blink = rt;
5962 ctx->hflags |= MIPS_HFLAG_BR;
5963 break;
5964 default:
5965 MIPS_INVAL("branch/jump");
5966 generate_exception_end(ctx, EXCP_RI);
5967 goto out;
5969 } else {
5970 switch (opc) {
5971 case OPC_BEQ:
5972 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5973 goto not_likely;
5974 case OPC_BEQL:
5975 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5976 goto likely;
5977 case OPC_BNE:
5978 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5979 goto not_likely;
5980 case OPC_BNEL:
5981 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5982 goto likely;
5983 case OPC_BGEZ:
5984 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5985 goto not_likely;
5986 case OPC_BGEZL:
5987 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5988 goto likely;
5989 case OPC_BGEZAL:
5990 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5991 blink = 31;
5992 goto not_likely;
5993 case OPC_BGEZALL:
5994 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5995 blink = 31;
5996 goto likely;
5997 case OPC_BGTZ:
5998 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5999 goto not_likely;
6000 case OPC_BGTZL:
6001 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6002 goto likely;
6003 case OPC_BLEZ:
6004 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6005 goto not_likely;
6006 case OPC_BLEZL:
6007 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6008 goto likely;
6009 case OPC_BLTZ:
6010 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6011 goto not_likely;
6012 case OPC_BLTZL:
6013 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6014 goto likely;
6015 case OPC_BPOSGE32:
6016 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6017 goto not_likely;
6018 #if defined(TARGET_MIPS64)
6019 case OPC_BPOSGE64:
6020 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6021 goto not_likely;
6022 #endif
6023 case OPC_BLTZAL:
6024 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6025 blink = 31;
6026 not_likely:
6027 ctx->hflags |= MIPS_HFLAG_BC;
6028 break;
6029 case OPC_BLTZALL:
6030 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6031 blink = 31;
6032 likely:
6033 ctx->hflags |= MIPS_HFLAG_BL;
6034 break;
6035 default:
6036 MIPS_INVAL("conditional branch/jump");
6037 generate_exception_end(ctx, EXCP_RI);
6038 goto out;
6042 ctx->btarget = btgt;
6044 switch (delayslot_size) {
6045 case 2:
6046 ctx->hflags |= MIPS_HFLAG_BDS16;
6047 break;
6048 case 4:
6049 ctx->hflags |= MIPS_HFLAG_BDS32;
6050 break;
6053 if (blink > 0) {
6054 int post_delay = insn_bytes + delayslot_size;
6055 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6057 tcg_gen_movi_tl(cpu_gpr[blink],
6058 ctx->base.pc_next + post_delay + lowbit);
6061 out:
6062 if (insn_bytes == 2)
6063 ctx->hflags |= MIPS_HFLAG_B16;
6064 tcg_temp_free(t0);
6065 tcg_temp_free(t1);
6069 /* nanoMIPS Branches */
6070 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6071 int insn_bytes,
6072 int rs, int rt, int32_t offset)
6074 target_ulong btgt = -1;
6075 int bcond_compute = 0;
6076 TCGv t0 = tcg_temp_new();
6077 TCGv t1 = tcg_temp_new();
6079 /* Load needed operands */
6080 switch (opc) {
6081 case OPC_BEQ:
6082 case OPC_BNE:
6083 /* Compare two registers */
6084 if (rs != rt) {
6085 gen_load_gpr(t0, rs);
6086 gen_load_gpr(t1, rt);
6087 bcond_compute = 1;
6089 btgt = ctx->base.pc_next + insn_bytes + offset;
6090 break;
6091 case OPC_BGEZAL:
6092 /* Compare to zero */
6093 if (rs != 0) {
6094 gen_load_gpr(t0, rs);
6095 bcond_compute = 1;
6097 btgt = ctx->base.pc_next + insn_bytes + offset;
6098 break;
6099 case OPC_BPOSGE32:
6100 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6101 bcond_compute = 1;
6102 btgt = ctx->base.pc_next + insn_bytes + offset;
6103 break;
6104 case OPC_JR:
6105 case OPC_JALR:
6106 /* Jump to register */
6107 if (offset != 0 && offset != 16) {
6108 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6109 others are reserved. */
6110 MIPS_INVAL("jump hint");
6111 generate_exception_end(ctx, EXCP_RI);
6112 goto out;
6114 gen_load_gpr(btarget, rs);
6115 break;
6116 default:
6117 MIPS_INVAL("branch/jump");
6118 generate_exception_end(ctx, EXCP_RI);
6119 goto out;
6121 if (bcond_compute == 0) {
6122 /* No condition to be computed */
6123 switch (opc) {
6124 case OPC_BEQ: /* rx == rx */
6125 /* Always take */
6126 ctx->hflags |= MIPS_HFLAG_B;
6127 break;
6128 case OPC_BGEZAL: /* 0 >= 0 */
6129 /* Always take and link */
6130 tcg_gen_movi_tl(cpu_gpr[31],
6131 ctx->base.pc_next + insn_bytes);
6132 ctx->hflags |= MIPS_HFLAG_B;
6133 break;
6134 case OPC_BNE: /* rx != rx */
6135 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6136 /* Skip the instruction in the delay slot */
6137 ctx->base.pc_next += 4;
6138 goto out;
6139 case OPC_JR:
6140 ctx->hflags |= MIPS_HFLAG_BR;
6141 break;
6142 case OPC_JALR:
6143 if (rt > 0) {
6144 tcg_gen_movi_tl(cpu_gpr[rt],
6145 ctx->base.pc_next + insn_bytes);
6147 ctx->hflags |= MIPS_HFLAG_BR;
6148 break;
6149 default:
6150 MIPS_INVAL("branch/jump");
6151 generate_exception_end(ctx, EXCP_RI);
6152 goto out;
6154 } else {
6155 switch (opc) {
6156 case OPC_BEQ:
6157 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6158 goto not_likely;
6159 case OPC_BNE:
6160 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6161 goto not_likely;
6162 case OPC_BGEZAL:
6163 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6164 tcg_gen_movi_tl(cpu_gpr[31],
6165 ctx->base.pc_next + insn_bytes);
6166 goto not_likely;
6167 case OPC_BPOSGE32:
6168 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6169 not_likely:
6170 ctx->hflags |= MIPS_HFLAG_BC;
6171 break;
6172 default:
6173 MIPS_INVAL("conditional branch/jump");
6174 generate_exception_end(ctx, EXCP_RI);
6175 goto out;
6179 ctx->btarget = btgt;
6181 out:
6182 if (insn_bytes == 2) {
6183 ctx->hflags |= MIPS_HFLAG_B16;
6185 tcg_temp_free(t0);
6186 tcg_temp_free(t1);
6190 /* special3 bitfield operations */
6191 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
6192 int rs, int lsb, int msb)
6194 TCGv t0 = tcg_temp_new();
6195 TCGv t1 = tcg_temp_new();
6197 gen_load_gpr(t1, rs);
6198 switch (opc) {
6199 case OPC_EXT:
6200 if (lsb + msb > 31) {
6201 goto fail;
6203 if (msb != 31) {
6204 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6205 } else {
6206 /* The two checks together imply that lsb == 0,
6207 so this is a simple sign-extension. */
6208 tcg_gen_ext32s_tl(t0, t1);
6210 break;
6211 #if defined(TARGET_MIPS64)
6212 case OPC_DEXTU:
6213 lsb += 32;
6214 goto do_dext;
6215 case OPC_DEXTM:
6216 msb += 32;
6217 goto do_dext;
6218 case OPC_DEXT:
6219 do_dext:
6220 if (lsb + msb > 63) {
6221 goto fail;
6223 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6224 break;
6225 #endif
6226 case OPC_INS:
6227 if (lsb > msb) {
6228 goto fail;
6230 gen_load_gpr(t0, rt);
6231 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6232 tcg_gen_ext32s_tl(t0, t0);
6233 break;
6234 #if defined(TARGET_MIPS64)
6235 case OPC_DINSU:
6236 lsb += 32;
6237 /* FALLTHRU */
6238 case OPC_DINSM:
6239 msb += 32;
6240 /* FALLTHRU */
6241 case OPC_DINS:
6242 if (lsb > msb) {
6243 goto fail;
6245 gen_load_gpr(t0, rt);
6246 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6247 break;
6248 #endif
6249 default:
6250 fail:
6251 MIPS_INVAL("bitops");
6252 generate_exception_end(ctx, EXCP_RI);
6253 tcg_temp_free(t0);
6254 tcg_temp_free(t1);
6255 return;
6257 gen_store_gpr(t0, rt);
6258 tcg_temp_free(t0);
6259 tcg_temp_free(t1);
6262 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6264 TCGv t0;
6266 if (rd == 0) {
6267 /* If no destination, treat it as a NOP. */
6268 return;
6271 t0 = tcg_temp_new();
6272 gen_load_gpr(t0, rt);
6273 switch (op2) {
6274 case OPC_WSBH:
6276 TCGv t1 = tcg_temp_new();
6277 TCGv t2 = tcg_const_tl(0x00FF00FF);
6279 tcg_gen_shri_tl(t1, t0, 8);
6280 tcg_gen_and_tl(t1, t1, t2);
6281 tcg_gen_and_tl(t0, t0, t2);
6282 tcg_gen_shli_tl(t0, t0, 8);
6283 tcg_gen_or_tl(t0, t0, t1);
6284 tcg_temp_free(t2);
6285 tcg_temp_free(t1);
6286 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6288 break;
6289 case OPC_SEB:
6290 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6291 break;
6292 case OPC_SEH:
6293 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6294 break;
6295 #if defined(TARGET_MIPS64)
6296 case OPC_DSBH:
6298 TCGv t1 = tcg_temp_new();
6299 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6301 tcg_gen_shri_tl(t1, t0, 8);
6302 tcg_gen_and_tl(t1, t1, t2);
6303 tcg_gen_and_tl(t0, t0, t2);
6304 tcg_gen_shli_tl(t0, t0, 8);
6305 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6306 tcg_temp_free(t2);
6307 tcg_temp_free(t1);
6309 break;
6310 case OPC_DSHD:
6312 TCGv t1 = tcg_temp_new();
6313 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6315 tcg_gen_shri_tl(t1, t0, 16);
6316 tcg_gen_and_tl(t1, t1, t2);
6317 tcg_gen_and_tl(t0, t0, t2);
6318 tcg_gen_shli_tl(t0, t0, 16);
6319 tcg_gen_or_tl(t0, t0, t1);
6320 tcg_gen_shri_tl(t1, t0, 32);
6321 tcg_gen_shli_tl(t0, t0, 32);
6322 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6323 tcg_temp_free(t2);
6324 tcg_temp_free(t1);
6326 break;
6327 #endif
6328 default:
6329 MIPS_INVAL("bsfhl");
6330 generate_exception_end(ctx, EXCP_RI);
6331 tcg_temp_free(t0);
6332 return;
6334 tcg_temp_free(t0);
6337 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6338 int imm2)
6340 TCGv t0;
6341 TCGv t1;
6342 if (rd == 0) {
6343 /* Treat as NOP. */
6344 return;
6346 t0 = tcg_temp_new();
6347 t1 = tcg_temp_new();
6348 gen_load_gpr(t0, rs);
6349 gen_load_gpr(t1, rt);
6350 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6351 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6352 if (opc == OPC_LSA) {
6353 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6356 tcg_temp_free(t1);
6357 tcg_temp_free(t0);
6359 return;
6362 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6363 int rt, int bits)
6365 TCGv t0;
6366 if (rd == 0) {
6367 /* Treat as NOP. */
6368 return;
6370 t0 = tcg_temp_new();
6371 if (bits == 0 || bits == wordsz) {
6372 if (bits == 0) {
6373 gen_load_gpr(t0, rt);
6374 } else {
6375 gen_load_gpr(t0, rs);
6377 switch (wordsz) {
6378 case 32:
6379 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6380 break;
6381 #if defined(TARGET_MIPS64)
6382 case 64:
6383 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6384 break;
6385 #endif
6387 } else {
6388 TCGv t1 = tcg_temp_new();
6389 gen_load_gpr(t0, rt);
6390 gen_load_gpr(t1, rs);
6391 switch (wordsz) {
6392 case 32:
6394 TCGv_i64 t2 = tcg_temp_new_i64();
6395 tcg_gen_concat_tl_i64(t2, t1, t0);
6396 tcg_gen_shri_i64(t2, t2, 32 - bits);
6397 gen_move_low32(cpu_gpr[rd], t2);
6398 tcg_temp_free_i64(t2);
6400 break;
6401 #if defined(TARGET_MIPS64)
6402 case 64:
6403 tcg_gen_shli_tl(t0, t0, bits);
6404 tcg_gen_shri_tl(t1, t1, 64 - bits);
6405 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6406 break;
6407 #endif
6409 tcg_temp_free(t1);
6412 tcg_temp_free(t0);
6415 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6416 int bp)
6418 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6421 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6422 int shift)
6424 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6427 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6429 TCGv t0;
6430 if (rd == 0) {
6431 /* Treat as NOP. */
6432 return;
6434 t0 = tcg_temp_new();
6435 gen_load_gpr(t0, rt);
6436 switch (opc) {
6437 case OPC_BITSWAP:
6438 gen_helper_bitswap(cpu_gpr[rd], t0);
6439 break;
6440 #if defined(TARGET_MIPS64)
6441 case OPC_DBITSWAP:
6442 gen_helper_dbitswap(cpu_gpr[rd], t0);
6443 break;
6444 #endif
6446 tcg_temp_free(t0);
6449 #ifndef CONFIG_USER_ONLY
6450 /* CP0 (MMU and control) */
6451 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6453 TCGv_i64 t0 = tcg_temp_new_i64();
6454 TCGv_i64 t1 = tcg_temp_new_i64();
6456 tcg_gen_ext_tl_i64(t0, arg);
6457 tcg_gen_ld_i64(t1, cpu_env, off);
6458 #if defined(TARGET_MIPS64)
6459 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6460 #else
6461 tcg_gen_concat32_i64(t1, t1, t0);
6462 #endif
6463 tcg_gen_st_i64(t1, cpu_env, off);
6464 tcg_temp_free_i64(t1);
6465 tcg_temp_free_i64(t0);
6468 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6470 TCGv_i64 t0 = tcg_temp_new_i64();
6471 TCGv_i64 t1 = tcg_temp_new_i64();
6473 tcg_gen_ext_tl_i64(t0, arg);
6474 tcg_gen_ld_i64(t1, cpu_env, off);
6475 tcg_gen_concat32_i64(t1, t1, t0);
6476 tcg_gen_st_i64(t1, cpu_env, off);
6477 tcg_temp_free_i64(t1);
6478 tcg_temp_free_i64(t0);
6481 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6483 TCGv_i64 t0 = tcg_temp_new_i64();
6485 tcg_gen_ld_i64(t0, cpu_env, off);
6486 #if defined(TARGET_MIPS64)
6487 tcg_gen_shri_i64(t0, t0, 30);
6488 #else
6489 tcg_gen_shri_i64(t0, t0, 32);
6490 #endif
6491 gen_move_low32(arg, t0);
6492 tcg_temp_free_i64(t0);
6495 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6497 TCGv_i64 t0 = tcg_temp_new_i64();
6499 tcg_gen_ld_i64(t0, cpu_env, off);
6500 tcg_gen_shri_i64(t0, t0, 32 + shift);
6501 gen_move_low32(arg, t0);
6502 tcg_temp_free_i64(t0);
6505 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6507 TCGv_i32 t0 = tcg_temp_new_i32();
6509 tcg_gen_ld_i32(t0, cpu_env, off);
6510 tcg_gen_ext_i32_tl(arg, t0);
6511 tcg_temp_free_i32(t0);
6514 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6516 tcg_gen_ld_tl(arg, cpu_env, off);
6517 tcg_gen_ext32s_tl(arg, arg);
6520 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6522 TCGv_i32 t0 = tcg_temp_new_i32();
6524 tcg_gen_trunc_tl_i32(t0, arg);
6525 tcg_gen_st_i32(t0, cpu_env, off);
6526 tcg_temp_free_i32(t0);
6529 #define CP0_CHECK(c) \
6530 do { \
6531 if (!(c)) { \
6532 goto cp0_unimplemented; \
6534 } while (0)
6536 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6538 const char *register_name = "invalid";
6540 switch (reg) {
6541 case CP0_REGISTER_02:
6542 switch (sel) {
6543 case 0:
6544 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6545 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6546 register_name = "EntryLo0";
6547 break;
6548 default:
6549 goto cp0_unimplemented;
6551 break;
6552 case CP0_REGISTER_03:
6553 switch (sel) {
6554 case 0:
6555 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6556 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6557 register_name = "EntryLo1";
6558 break;
6559 default:
6560 goto cp0_unimplemented;
6562 break;
6563 case CP0_REGISTER_09:
6564 switch (sel) {
6565 case 7:
6566 CP0_CHECK(ctx->saar);
6567 gen_helper_mfhc0_saar(arg, cpu_env);
6568 register_name = "SAAR";
6569 break;
6570 default:
6571 goto cp0_unimplemented;
6573 break;
6574 case CP0_REGISTER_17:
6575 switch (sel) {
6576 case 0:
6577 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6578 ctx->CP0_LLAddr_shift);
6579 register_name = "LLAddr";
6580 break;
6581 case 1:
6582 CP0_CHECK(ctx->mrp);
6583 gen_helper_mfhc0_maar(arg, cpu_env);
6584 register_name = "MAAR";
6585 break;
6586 default:
6587 goto cp0_unimplemented;
6589 break;
6590 case CP0_REGISTER_28:
6591 switch (sel) {
6592 case 0:
6593 case 2:
6594 case 4:
6595 case 6:
6596 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6597 register_name = "TagLo";
6598 break;
6599 default:
6600 goto cp0_unimplemented;
6602 break;
6603 default:
6604 goto cp0_unimplemented;
6606 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6607 return;
6609 cp0_unimplemented:
6610 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6611 register_name, reg, sel);
6612 tcg_gen_movi_tl(arg, 0);
6615 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6617 const char *register_name = "invalid";
6618 uint64_t mask = ctx->PAMask >> 36;
6620 switch (reg) {
6621 case CP0_REGISTER_02:
6622 switch (sel) {
6623 case 0:
6624 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6625 tcg_gen_andi_tl(arg, arg, mask);
6626 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6627 register_name = "EntryLo0";
6628 break;
6629 default:
6630 goto cp0_unimplemented;
6632 break;
6633 case CP0_REGISTER_03:
6634 switch (sel) {
6635 case 0:
6636 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6637 tcg_gen_andi_tl(arg, arg, mask);
6638 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6639 register_name = "EntryLo1";
6640 break;
6641 default:
6642 goto cp0_unimplemented;
6644 break;
6645 case CP0_REGISTER_09:
6646 switch (sel) {
6647 case 7:
6648 CP0_CHECK(ctx->saar);
6649 gen_helper_mthc0_saar(cpu_env, arg);
6650 register_name = "SAAR";
6651 break;
6652 default:
6653 goto cp0_unimplemented;
6655 case CP0_REGISTER_17:
6656 switch (sel) {
6657 case 0:
6658 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6659 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6660 relevant for modern MIPS cores supporting MTHC0, therefore
6661 treating MTHC0 to LLAddr as NOP. */
6662 register_name = "LLAddr";
6663 break;
6664 case 1:
6665 CP0_CHECK(ctx->mrp);
6666 gen_helper_mthc0_maar(cpu_env, arg);
6667 register_name = "MAAR";
6668 break;
6669 default:
6670 goto cp0_unimplemented;
6672 break;
6673 case CP0_REGISTER_28:
6674 switch (sel) {
6675 case 0:
6676 case 2:
6677 case 4:
6678 case 6:
6679 tcg_gen_andi_tl(arg, arg, mask);
6680 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6681 register_name = "TagLo";
6682 break;
6683 default:
6684 goto cp0_unimplemented;
6686 break;
6687 default:
6688 goto cp0_unimplemented;
6690 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6692 cp0_unimplemented:
6693 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6694 register_name, reg, sel);
6697 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6699 if (ctx->insn_flags & ISA_MIPS32R6) {
6700 tcg_gen_movi_tl(arg, 0);
6701 } else {
6702 tcg_gen_movi_tl(arg, ~0);
6706 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6708 const char *register_name = "invalid";
6710 if (sel != 0)
6711 check_insn(ctx, ISA_MIPS32);
6713 switch (reg) {
6714 case CP0_REGISTER_00:
6715 switch (sel) {
6716 case 0:
6717 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6718 register_name = "Index";
6719 break;
6720 case 1:
6721 CP0_CHECK(ctx->insn_flags & ASE_MT);
6722 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6723 register_name = "MVPControl";
6724 break;
6725 case 2:
6726 CP0_CHECK(ctx->insn_flags & ASE_MT);
6727 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6728 register_name = "MVPConf0";
6729 break;
6730 case 3:
6731 CP0_CHECK(ctx->insn_flags & ASE_MT);
6732 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6733 register_name = "MVPConf1";
6734 break;
6735 case 4:
6736 CP0_CHECK(ctx->vp);
6737 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6738 register_name = "VPControl";
6739 break;
6740 default:
6741 goto cp0_unimplemented;
6743 break;
6744 case CP0_REGISTER_01:
6745 switch (sel) {
6746 case 0:
6747 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6748 gen_helper_mfc0_random(arg, cpu_env);
6749 register_name = "Random";
6750 break;
6751 case 1:
6752 CP0_CHECK(ctx->insn_flags & ASE_MT);
6753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6754 register_name = "VPEControl";
6755 break;
6756 case 2:
6757 CP0_CHECK(ctx->insn_flags & ASE_MT);
6758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6759 register_name = "VPEConf0";
6760 break;
6761 case 3:
6762 CP0_CHECK(ctx->insn_flags & ASE_MT);
6763 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6764 register_name = "VPEConf1";
6765 break;
6766 case 4:
6767 CP0_CHECK(ctx->insn_flags & ASE_MT);
6768 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6769 register_name = "YQMask";
6770 break;
6771 case 5:
6772 CP0_CHECK(ctx->insn_flags & ASE_MT);
6773 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6774 register_name = "VPESchedule";
6775 break;
6776 case 6:
6777 CP0_CHECK(ctx->insn_flags & ASE_MT);
6778 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6779 register_name = "VPEScheFBack";
6780 break;
6781 case 7:
6782 CP0_CHECK(ctx->insn_flags & ASE_MT);
6783 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6784 register_name = "VPEOpt";
6785 break;
6786 default:
6787 goto cp0_unimplemented;
6789 break;
6790 case CP0_REGISTER_02:
6791 switch (sel) {
6792 case 0:
6794 TCGv_i64 tmp = tcg_temp_new_i64();
6795 tcg_gen_ld_i64(tmp, cpu_env,
6796 offsetof(CPUMIPSState, CP0_EntryLo0));
6797 #if defined(TARGET_MIPS64)
6798 if (ctx->rxi) {
6799 /* Move RI/XI fields to bits 31:30 */
6800 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6801 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6803 #endif
6804 gen_move_low32(arg, tmp);
6805 tcg_temp_free_i64(tmp);
6807 register_name = "EntryLo0";
6808 break;
6809 case 1:
6810 CP0_CHECK(ctx->insn_flags & ASE_MT);
6811 gen_helper_mfc0_tcstatus(arg, cpu_env);
6812 register_name = "TCStatus";
6813 break;
6814 case 2:
6815 CP0_CHECK(ctx->insn_flags & ASE_MT);
6816 gen_helper_mfc0_tcbind(arg, cpu_env);
6817 register_name = "TCBind";
6818 break;
6819 case 3:
6820 CP0_CHECK(ctx->insn_flags & ASE_MT);
6821 gen_helper_mfc0_tcrestart(arg, cpu_env);
6822 register_name = "TCRestart";
6823 break;
6824 case 4:
6825 CP0_CHECK(ctx->insn_flags & ASE_MT);
6826 gen_helper_mfc0_tchalt(arg, cpu_env);
6827 register_name = "TCHalt";
6828 break;
6829 case 5:
6830 CP0_CHECK(ctx->insn_flags & ASE_MT);
6831 gen_helper_mfc0_tccontext(arg, cpu_env);
6832 register_name = "TCContext";
6833 break;
6834 case 6:
6835 CP0_CHECK(ctx->insn_flags & ASE_MT);
6836 gen_helper_mfc0_tcschedule(arg, cpu_env);
6837 register_name = "TCSchedule";
6838 break;
6839 case 7:
6840 CP0_CHECK(ctx->insn_flags & ASE_MT);
6841 gen_helper_mfc0_tcschefback(arg, cpu_env);
6842 register_name = "TCScheFBack";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 case CP0_REGISTER_03:
6849 switch (sel) {
6850 case 0:
6852 TCGv_i64 tmp = tcg_temp_new_i64();
6853 tcg_gen_ld_i64(tmp, cpu_env,
6854 offsetof(CPUMIPSState, CP0_EntryLo1));
6855 #if defined(TARGET_MIPS64)
6856 if (ctx->rxi) {
6857 /* Move RI/XI fields to bits 31:30 */
6858 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6859 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6861 #endif
6862 gen_move_low32(arg, tmp);
6863 tcg_temp_free_i64(tmp);
6865 register_name = "EntryLo1";
6866 break;
6867 case 1:
6868 CP0_CHECK(ctx->vp);
6869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6870 register_name = "GlobalNumber";
6871 break;
6872 default:
6873 goto cp0_unimplemented;
6875 break;
6876 case CP0_REGISTER_04:
6877 switch (sel) {
6878 case 0:
6879 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6880 tcg_gen_ext32s_tl(arg, arg);
6881 register_name = "Context";
6882 break;
6883 case 1:
6884 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6885 register_name = "ContextConfig";
6886 goto cp0_unimplemented;
6887 case 2:
6888 CP0_CHECK(ctx->ulri);
6889 tcg_gen_ld_tl(arg, cpu_env,
6890 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6891 tcg_gen_ext32s_tl(arg, arg);
6892 register_name = "UserLocal";
6893 break;
6894 default:
6895 goto cp0_unimplemented;
6897 break;
6898 case CP0_REGISTER_05:
6899 switch (sel) {
6900 case 0:
6901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6902 register_name = "PageMask";
6903 break;
6904 case 1:
6905 check_insn(ctx, ISA_MIPS32R2);
6906 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6907 register_name = "PageGrain";
6908 break;
6909 case 2:
6910 CP0_CHECK(ctx->sc);
6911 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6912 tcg_gen_ext32s_tl(arg, arg);
6913 register_name = "SegCtl0";
6914 break;
6915 case 3:
6916 CP0_CHECK(ctx->sc);
6917 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6918 tcg_gen_ext32s_tl(arg, arg);
6919 register_name = "SegCtl1";
6920 break;
6921 case 4:
6922 CP0_CHECK(ctx->sc);
6923 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6924 tcg_gen_ext32s_tl(arg, arg);
6925 register_name = "SegCtl2";
6926 break;
6927 case 5:
6928 check_pw(ctx);
6929 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6930 register_name = "PWBase";
6931 break;
6932 case 6:
6933 check_pw(ctx);
6934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6935 register_name = "PWField";
6936 break;
6937 case 7:
6938 check_pw(ctx);
6939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6940 register_name = "PWSize";
6941 break;
6942 default:
6943 goto cp0_unimplemented;
6945 break;
6946 case CP0_REGISTER_06:
6947 switch (sel) {
6948 case 0:
6949 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6950 register_name = "Wired";
6951 break;
6952 case 1:
6953 check_insn(ctx, ISA_MIPS32R2);
6954 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6955 register_name = "SRSConf0";
6956 break;
6957 case 2:
6958 check_insn(ctx, ISA_MIPS32R2);
6959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6960 register_name = "SRSConf1";
6961 break;
6962 case 3:
6963 check_insn(ctx, ISA_MIPS32R2);
6964 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6965 register_name = "SRSConf2";
6966 break;
6967 case 4:
6968 check_insn(ctx, ISA_MIPS32R2);
6969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6970 register_name = "SRSConf3";
6971 break;
6972 case 5:
6973 check_insn(ctx, ISA_MIPS32R2);
6974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6975 register_name = "SRSConf4";
6976 break;
6977 case 6:
6978 check_pw(ctx);
6979 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6980 register_name = "PWCtl";
6981 break;
6982 default:
6983 goto cp0_unimplemented;
6985 break;
6986 case CP0_REGISTER_07:
6987 switch (sel) {
6988 case 0:
6989 check_insn(ctx, ISA_MIPS32R2);
6990 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6991 register_name = "HWREna";
6992 break;
6993 default:
6994 goto cp0_unimplemented;
6996 break;
6997 case CP0_REGISTER_08:
6998 switch (sel) {
6999 case 0:
7000 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7001 tcg_gen_ext32s_tl(arg, arg);
7002 register_name = "BadVAddr";
7003 break;
7004 case 1:
7005 CP0_CHECK(ctx->bi);
7006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7007 register_name = "BadInstr";
7008 break;
7009 case 2:
7010 CP0_CHECK(ctx->bp);
7011 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7012 register_name = "BadInstrP";
7013 break;
7014 case 3:
7015 CP0_CHECK(ctx->bi);
7016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7017 tcg_gen_andi_tl(arg, arg, ~0xffff);
7018 register_name = "BadInstrX";
7019 break;
7020 default:
7021 goto cp0_unimplemented;
7023 break;
7024 case CP0_REGISTER_09:
7025 switch (sel) {
7026 case 0:
7027 /* Mark as an IO operation because we read the time. */
7028 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7029 gen_io_start();
7031 gen_helper_mfc0_count(arg, cpu_env);
7032 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7033 gen_io_end();
7035 /* Break the TB to be able to take timer interrupts immediately
7036 after reading count. DISAS_STOP isn't sufficient, we need to
7037 ensure we break completely out of translated code. */
7038 gen_save_pc(ctx->base.pc_next + 4);
7039 ctx->base.is_jmp = DISAS_EXIT;
7040 register_name = "Count";
7041 break;
7042 case 6:
7043 CP0_CHECK(ctx->saar);
7044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7045 register_name = "SAARI";
7046 break;
7047 case 7:
7048 CP0_CHECK(ctx->saar);
7049 gen_helper_mfc0_saar(arg, cpu_env);
7050 register_name = "SAAR";
7051 break;
7052 default:
7053 goto cp0_unimplemented;
7055 break;
7056 case CP0_REGISTER_10:
7057 switch (sel) {
7058 case 0:
7059 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7060 tcg_gen_ext32s_tl(arg, arg);
7061 register_name = "EntryHi";
7062 break;
7063 default:
7064 goto cp0_unimplemented;
7066 break;
7067 case CP0_REGISTER_11:
7068 switch (sel) {
7069 case 0:
7070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7071 register_name = "Compare";
7072 break;
7073 /* 6,7 are implementation dependent */
7074 default:
7075 goto cp0_unimplemented;
7077 break;
7078 case CP0_REGISTER_12:
7079 switch (sel) {
7080 case 0:
7081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7082 register_name = "Status";
7083 break;
7084 case 1:
7085 check_insn(ctx, ISA_MIPS32R2);
7086 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7087 register_name = "IntCtl";
7088 break;
7089 case 2:
7090 check_insn(ctx, ISA_MIPS32R2);
7091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7092 register_name = "SRSCtl";
7093 break;
7094 case 3:
7095 check_insn(ctx, ISA_MIPS32R2);
7096 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7097 register_name = "SRSMap";
7098 break;
7099 default:
7100 goto cp0_unimplemented;
7102 break;
7103 case CP0_REGISTER_13:
7104 switch (sel) {
7105 case 0:
7106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7107 register_name = "Cause";
7108 break;
7109 default:
7110 goto cp0_unimplemented;
7112 break;
7113 case CP0_REGISTER_14:
7114 switch (sel) {
7115 case 0:
7116 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7117 tcg_gen_ext32s_tl(arg, arg);
7118 register_name = "EPC";
7119 break;
7120 default:
7121 goto cp0_unimplemented;
7123 break;
7124 case CP0_REGISTER_15:
7125 switch (sel) {
7126 case 0:
7127 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7128 register_name = "PRid";
7129 break;
7130 case 1:
7131 check_insn(ctx, ISA_MIPS32R2);
7132 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7133 tcg_gen_ext32s_tl(arg, arg);
7134 register_name = "EBase";
7135 break;
7136 case 3:
7137 check_insn(ctx, ISA_MIPS32R2);
7138 CP0_CHECK(ctx->cmgcr);
7139 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7140 tcg_gen_ext32s_tl(arg, arg);
7141 register_name = "CMGCRBase";
7142 break;
7143 default:
7144 goto cp0_unimplemented;
7146 break;
7147 case CP0_REGISTER_16:
7148 switch (sel) {
7149 case 0:
7150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7151 register_name = "Config";
7152 break;
7153 case 1:
7154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7155 register_name = "Config1";
7156 break;
7157 case 2:
7158 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7159 register_name = "Config2";
7160 break;
7161 case 3:
7162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7163 register_name = "Config3";
7164 break;
7165 case 4:
7166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7167 register_name = "Config4";
7168 break;
7169 case 5:
7170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7171 register_name = "Config5";
7172 break;
7173 /* 6,7 are implementation dependent */
7174 case 6:
7175 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7176 register_name = "Config6";
7177 break;
7178 case 7:
7179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7180 register_name = "Config7";
7181 break;
7182 default:
7183 goto cp0_unimplemented;
7185 break;
7186 case CP0_REGISTER_17:
7187 switch (sel) {
7188 case 0:
7189 gen_helper_mfc0_lladdr(arg, cpu_env);
7190 register_name = "LLAddr";
7191 break;
7192 case 1:
7193 CP0_CHECK(ctx->mrp);
7194 gen_helper_mfc0_maar(arg, cpu_env);
7195 register_name = "MAAR";
7196 break;
7197 case 2:
7198 CP0_CHECK(ctx->mrp);
7199 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7200 register_name = "MAARI";
7201 break;
7202 default:
7203 goto cp0_unimplemented;
7205 break;
7206 case CP0_REGISTER_18:
7207 switch (sel) {
7208 case 0:
7209 case 1:
7210 case 2:
7211 case 3:
7212 case 4:
7213 case 5:
7214 case 6:
7215 case 7:
7216 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7217 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7218 register_name = "WatchLo";
7219 break;
7220 default:
7221 goto cp0_unimplemented;
7223 break;
7224 case CP0_REGISTER_19:
7225 switch (sel) {
7226 case 0:
7227 case 1:
7228 case 2:
7229 case 3:
7230 case 4:
7231 case 5:
7232 case 6:
7233 case 7:
7234 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7235 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7236 register_name = "WatchHi";
7237 break;
7238 default:
7239 goto cp0_unimplemented;
7241 break;
7242 case CP0_REGISTER_20:
7243 switch (sel) {
7244 case 0:
7245 #if defined(TARGET_MIPS64)
7246 check_insn(ctx, ISA_MIPS3);
7247 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7248 tcg_gen_ext32s_tl(arg, arg);
7249 register_name = "XContext";
7250 break;
7251 #endif
7252 default:
7253 goto cp0_unimplemented;
7255 break;
7256 case CP0_REGISTER_21:
7257 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7258 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7259 switch (sel) {
7260 case 0:
7261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7262 register_name = "Framemask";
7263 break;
7264 default:
7265 goto cp0_unimplemented;
7267 break;
7268 case CP0_REGISTER_22:
7269 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7270 register_name = "'Diagnostic"; /* implementation dependent */
7271 break;
7272 case CP0_REGISTER_23:
7273 switch (sel) {
7274 case 0:
7275 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7276 register_name = "Debug";
7277 break;
7278 case 1:
7279 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7280 register_name = "TraceControl";
7281 goto cp0_unimplemented;
7282 case 2:
7283 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7284 register_name = "TraceControl2";
7285 goto cp0_unimplemented;
7286 case 3:
7287 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7288 register_name = "UserTraceData";
7289 goto cp0_unimplemented;
7290 case 4:
7291 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7292 register_name = "TraceBPC";
7293 goto cp0_unimplemented;
7294 default:
7295 goto cp0_unimplemented;
7297 break;
7298 case CP0_REGISTER_24:
7299 switch (sel) {
7300 case 0:
7301 /* EJTAG support */
7302 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7303 tcg_gen_ext32s_tl(arg, arg);
7304 register_name = "DEPC";
7305 break;
7306 default:
7307 goto cp0_unimplemented;
7309 break;
7310 case CP0_REGISTER_25:
7311 switch (sel) {
7312 case 0:
7313 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7314 register_name = "Performance0";
7315 break;
7316 case 1:
7317 // gen_helper_mfc0_performance1(arg);
7318 register_name = "Performance1";
7319 goto cp0_unimplemented;
7320 case 2:
7321 // gen_helper_mfc0_performance2(arg);
7322 register_name = "Performance2";
7323 goto cp0_unimplemented;
7324 case 3:
7325 // gen_helper_mfc0_performance3(arg);
7326 register_name = "Performance3";
7327 goto cp0_unimplemented;
7328 case 4:
7329 // gen_helper_mfc0_performance4(arg);
7330 register_name = "Performance4";
7331 goto cp0_unimplemented;
7332 case 5:
7333 // gen_helper_mfc0_performance5(arg);
7334 register_name = "Performance5";
7335 goto cp0_unimplemented;
7336 case 6:
7337 // gen_helper_mfc0_performance6(arg);
7338 register_name = "Performance6";
7339 goto cp0_unimplemented;
7340 case 7:
7341 // gen_helper_mfc0_performance7(arg);
7342 register_name = "Performance7";
7343 goto cp0_unimplemented;
7344 default:
7345 goto cp0_unimplemented;
7347 break;
7348 case CP0_REGISTER_26:
7349 switch (sel) {
7350 case 0:
7351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7352 register_name = "ErrCtl";
7353 break;
7354 default:
7355 goto cp0_unimplemented;
7357 break;
7358 case CP0_REGISTER_27:
7359 switch (sel) {
7360 case 0:
7361 case 1:
7362 case 2:
7363 case 3:
7364 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7365 register_name = "CacheErr";
7366 break;
7367 default:
7368 goto cp0_unimplemented;
7370 break;
7371 case CP0_REGISTER_28:
7372 switch (sel) {
7373 case 0:
7374 case 2:
7375 case 4:
7376 case 6:
7378 TCGv_i64 tmp = tcg_temp_new_i64();
7379 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7380 gen_move_low32(arg, tmp);
7381 tcg_temp_free_i64(tmp);
7383 register_name = "TagLo";
7384 break;
7385 case 1:
7386 case 3:
7387 case 5:
7388 case 7:
7389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7390 register_name = "DataLo";
7391 break;
7392 default:
7393 goto cp0_unimplemented;
7395 break;
7396 case CP0_REGISTER_29:
7397 switch (sel) {
7398 case 0:
7399 case 2:
7400 case 4:
7401 case 6:
7402 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7403 register_name = "TagHi";
7404 break;
7405 case 1:
7406 case 3:
7407 case 5:
7408 case 7:
7409 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7410 register_name = "DataHi";
7411 break;
7412 default:
7413 goto cp0_unimplemented;
7415 break;
7416 case CP0_REGISTER_30:
7417 switch (sel) {
7418 case 0:
7419 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7420 tcg_gen_ext32s_tl(arg, arg);
7421 register_name = "ErrorEPC";
7422 break;
7423 default:
7424 goto cp0_unimplemented;
7426 break;
7427 case CP0_REGISTER_31:
7428 switch (sel) {
7429 case 0:
7430 /* EJTAG support */
7431 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7432 register_name = "DESAVE";
7433 break;
7434 case 2:
7435 case 3:
7436 case 4:
7437 case 5:
7438 case 6:
7439 case 7:
7440 CP0_CHECK(ctx->kscrexist & (1 << sel));
7441 tcg_gen_ld_tl(arg, cpu_env,
7442 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7443 tcg_gen_ext32s_tl(arg, arg);
7444 register_name = "KScratch";
7445 break;
7446 default:
7447 goto cp0_unimplemented;
7449 break;
7450 default:
7451 goto cp0_unimplemented;
7453 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7454 return;
7456 cp0_unimplemented:
7457 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7458 register_name, reg, sel);
7459 gen_mfc0_unimplemented(ctx, arg);
7462 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7464 const char *register_name = "invalid";
7466 if (sel != 0)
7467 check_insn(ctx, ISA_MIPS32);
7469 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7470 gen_io_start();
7473 switch (reg) {
7474 case CP0_REGISTER_00:
7475 switch (sel) {
7476 case 0:
7477 gen_helper_mtc0_index(cpu_env, arg);
7478 register_name = "Index";
7479 break;
7480 case 1:
7481 CP0_CHECK(ctx->insn_flags & ASE_MT);
7482 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7483 register_name = "MVPControl";
7484 break;
7485 case 2:
7486 CP0_CHECK(ctx->insn_flags & ASE_MT);
7487 /* ignored */
7488 register_name = "MVPConf0";
7489 break;
7490 case 3:
7491 CP0_CHECK(ctx->insn_flags & ASE_MT);
7492 /* ignored */
7493 register_name = "MVPConf1";
7494 break;
7495 case 4:
7496 CP0_CHECK(ctx->vp);
7497 /* ignored */
7498 register_name = "VPControl";
7499 break;
7500 default:
7501 goto cp0_unimplemented;
7503 break;
7504 case CP0_REGISTER_01:
7505 switch (sel) {
7506 case 0:
7507 /* ignored */
7508 register_name = "Random";
7509 break;
7510 case 1:
7511 CP0_CHECK(ctx->insn_flags & ASE_MT);
7512 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7513 register_name = "VPEControl";
7514 break;
7515 case 2:
7516 CP0_CHECK(ctx->insn_flags & ASE_MT);
7517 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7518 register_name = "VPEConf0";
7519 break;
7520 case 3:
7521 CP0_CHECK(ctx->insn_flags & ASE_MT);
7522 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7523 register_name = "VPEConf1";
7524 break;
7525 case 4:
7526 CP0_CHECK(ctx->insn_flags & ASE_MT);
7527 gen_helper_mtc0_yqmask(cpu_env, arg);
7528 register_name = "YQMask";
7529 break;
7530 case 5:
7531 CP0_CHECK(ctx->insn_flags & ASE_MT);
7532 tcg_gen_st_tl(arg, cpu_env,
7533 offsetof(CPUMIPSState, CP0_VPESchedule));
7534 register_name = "VPESchedule";
7535 break;
7536 case 6:
7537 CP0_CHECK(ctx->insn_flags & ASE_MT);
7538 tcg_gen_st_tl(arg, cpu_env,
7539 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7540 register_name = "VPEScheFBack";
7541 break;
7542 case 7:
7543 CP0_CHECK(ctx->insn_flags & ASE_MT);
7544 gen_helper_mtc0_vpeopt(cpu_env, arg);
7545 register_name = "VPEOpt";
7546 break;
7547 default:
7548 goto cp0_unimplemented;
7550 break;
7551 case CP0_REGISTER_02:
7552 switch (sel) {
7553 case 0:
7554 gen_helper_mtc0_entrylo0(cpu_env, arg);
7555 register_name = "EntryLo0";
7556 break;
7557 case 1:
7558 CP0_CHECK(ctx->insn_flags & ASE_MT);
7559 gen_helper_mtc0_tcstatus(cpu_env, arg);
7560 register_name = "TCStatus";
7561 break;
7562 case 2:
7563 CP0_CHECK(ctx->insn_flags & ASE_MT);
7564 gen_helper_mtc0_tcbind(cpu_env, arg);
7565 register_name = "TCBind";
7566 break;
7567 case 3:
7568 CP0_CHECK(ctx->insn_flags & ASE_MT);
7569 gen_helper_mtc0_tcrestart(cpu_env, arg);
7570 register_name = "TCRestart";
7571 break;
7572 case 4:
7573 CP0_CHECK(ctx->insn_flags & ASE_MT);
7574 gen_helper_mtc0_tchalt(cpu_env, arg);
7575 register_name = "TCHalt";
7576 break;
7577 case 5:
7578 CP0_CHECK(ctx->insn_flags & ASE_MT);
7579 gen_helper_mtc0_tccontext(cpu_env, arg);
7580 register_name = "TCContext";
7581 break;
7582 case 6:
7583 CP0_CHECK(ctx->insn_flags & ASE_MT);
7584 gen_helper_mtc0_tcschedule(cpu_env, arg);
7585 register_name = "TCSchedule";
7586 break;
7587 case 7:
7588 CP0_CHECK(ctx->insn_flags & ASE_MT);
7589 gen_helper_mtc0_tcschefback(cpu_env, arg);
7590 register_name = "TCScheFBack";
7591 break;
7592 default:
7593 goto cp0_unimplemented;
7595 break;
7596 case CP0_REGISTER_03:
7597 switch (sel) {
7598 case 0:
7599 gen_helper_mtc0_entrylo1(cpu_env, arg);
7600 register_name = "EntryLo1";
7601 break;
7602 case 1:
7603 CP0_CHECK(ctx->vp);
7604 /* ignored */
7605 register_name = "GlobalNumber";
7606 break;
7607 default:
7608 goto cp0_unimplemented;
7610 break;
7611 case CP0_REGISTER_04:
7612 switch (sel) {
7613 case 0:
7614 gen_helper_mtc0_context(cpu_env, arg);
7615 register_name = "Context";
7616 break;
7617 case 1:
7618 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7619 register_name = "ContextConfig";
7620 goto cp0_unimplemented;
7621 case 2:
7622 CP0_CHECK(ctx->ulri);
7623 tcg_gen_st_tl(arg, cpu_env,
7624 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7625 register_name = "UserLocal";
7626 break;
7627 default:
7628 goto cp0_unimplemented;
7630 break;
7631 case CP0_REGISTER_05:
7632 switch (sel) {
7633 case 0:
7634 gen_helper_mtc0_pagemask(cpu_env, arg);
7635 register_name = "PageMask";
7636 break;
7637 case 1:
7638 check_insn(ctx, ISA_MIPS32R2);
7639 gen_helper_mtc0_pagegrain(cpu_env, arg);
7640 register_name = "PageGrain";
7641 ctx->base.is_jmp = DISAS_STOP;
7642 break;
7643 case 2:
7644 CP0_CHECK(ctx->sc);
7645 gen_helper_mtc0_segctl0(cpu_env, arg);
7646 register_name = "SegCtl0";
7647 break;
7648 case 3:
7649 CP0_CHECK(ctx->sc);
7650 gen_helper_mtc0_segctl1(cpu_env, arg);
7651 register_name = "SegCtl1";
7652 break;
7653 case 4:
7654 CP0_CHECK(ctx->sc);
7655 gen_helper_mtc0_segctl2(cpu_env, arg);
7656 register_name = "SegCtl2";
7657 break;
7658 case 5:
7659 check_pw(ctx);
7660 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7661 register_name = "PWBase";
7662 break;
7663 case 6:
7664 check_pw(ctx);
7665 gen_helper_mtc0_pwfield(cpu_env, arg);
7666 register_name = "PWField";
7667 break;
7668 case 7:
7669 check_pw(ctx);
7670 gen_helper_mtc0_pwsize(cpu_env, arg);
7671 register_name = "PWSize";
7672 break;
7673 default:
7674 goto cp0_unimplemented;
7676 break;
7677 case CP0_REGISTER_06:
7678 switch (sel) {
7679 case 0:
7680 gen_helper_mtc0_wired(cpu_env, arg);
7681 register_name = "Wired";
7682 break;
7683 case 1:
7684 check_insn(ctx, ISA_MIPS32R2);
7685 gen_helper_mtc0_srsconf0(cpu_env, arg);
7686 register_name = "SRSConf0";
7687 break;
7688 case 2:
7689 check_insn(ctx, ISA_MIPS32R2);
7690 gen_helper_mtc0_srsconf1(cpu_env, arg);
7691 register_name = "SRSConf1";
7692 break;
7693 case 3:
7694 check_insn(ctx, ISA_MIPS32R2);
7695 gen_helper_mtc0_srsconf2(cpu_env, arg);
7696 register_name = "SRSConf2";
7697 break;
7698 case 4:
7699 check_insn(ctx, ISA_MIPS32R2);
7700 gen_helper_mtc0_srsconf3(cpu_env, arg);
7701 register_name = "SRSConf3";
7702 break;
7703 case 5:
7704 check_insn(ctx, ISA_MIPS32R2);
7705 gen_helper_mtc0_srsconf4(cpu_env, arg);
7706 register_name = "SRSConf4";
7707 break;
7708 case 6:
7709 check_pw(ctx);
7710 gen_helper_mtc0_pwctl(cpu_env, arg);
7711 register_name = "PWCtl";
7712 break;
7713 default:
7714 goto cp0_unimplemented;
7716 break;
7717 case CP0_REGISTER_07:
7718 switch (sel) {
7719 case 0:
7720 check_insn(ctx, ISA_MIPS32R2);
7721 gen_helper_mtc0_hwrena(cpu_env, arg);
7722 ctx->base.is_jmp = DISAS_STOP;
7723 register_name = "HWREna";
7724 break;
7725 default:
7726 goto cp0_unimplemented;
7728 break;
7729 case CP0_REGISTER_08:
7730 switch (sel) {
7731 case 0:
7732 /* ignored */
7733 register_name = "BadVAddr";
7734 break;
7735 case 1:
7736 /* ignored */
7737 register_name = "BadInstr";
7738 break;
7739 case 2:
7740 /* ignored */
7741 register_name = "BadInstrP";
7742 break;
7743 case 3:
7744 /* ignored */
7745 register_name = "BadInstrX";
7746 break;
7747 default:
7748 goto cp0_unimplemented;
7750 break;
7751 case CP0_REGISTER_09:
7752 switch (sel) {
7753 case 0:
7754 gen_helper_mtc0_count(cpu_env, arg);
7755 register_name = "Count";
7756 break;
7757 case 6:
7758 CP0_CHECK(ctx->saar);
7759 gen_helper_mtc0_saari(cpu_env, arg);
7760 register_name = "SAARI";
7761 break;
7762 case 7:
7763 CP0_CHECK(ctx->saar);
7764 gen_helper_mtc0_saar(cpu_env, arg);
7765 register_name = "SAAR";
7766 break;
7767 default:
7768 goto cp0_unimplemented;
7770 break;
7771 case CP0_REGISTER_10:
7772 switch (sel) {
7773 case 0:
7774 gen_helper_mtc0_entryhi(cpu_env, arg);
7775 register_name = "EntryHi";
7776 break;
7777 default:
7778 goto cp0_unimplemented;
7780 break;
7781 case CP0_REGISTER_11:
7782 switch (sel) {
7783 case 0:
7784 gen_helper_mtc0_compare(cpu_env, arg);
7785 register_name = "Compare";
7786 break;
7787 /* 6,7 are implementation dependent */
7788 default:
7789 goto cp0_unimplemented;
7791 break;
7792 case CP0_REGISTER_12:
7793 switch (sel) {
7794 case 0:
7795 save_cpu_state(ctx, 1);
7796 gen_helper_mtc0_status(cpu_env, arg);
7797 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7798 gen_save_pc(ctx->base.pc_next + 4);
7799 ctx->base.is_jmp = DISAS_EXIT;
7800 register_name = "Status";
7801 break;
7802 case 1:
7803 check_insn(ctx, ISA_MIPS32R2);
7804 gen_helper_mtc0_intctl(cpu_env, arg);
7805 /* Stop translation as we may have switched the execution mode */
7806 ctx->base.is_jmp = DISAS_STOP;
7807 register_name = "IntCtl";
7808 break;
7809 case 2:
7810 check_insn(ctx, ISA_MIPS32R2);
7811 gen_helper_mtc0_srsctl(cpu_env, arg);
7812 /* Stop translation as we may have switched the execution mode */
7813 ctx->base.is_jmp = DISAS_STOP;
7814 register_name = "SRSCtl";
7815 break;
7816 case 3:
7817 check_insn(ctx, ISA_MIPS32R2);
7818 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7819 /* Stop translation as we may have switched the execution mode */
7820 ctx->base.is_jmp = DISAS_STOP;
7821 register_name = "SRSMap";
7822 break;
7823 default:
7824 goto cp0_unimplemented;
7826 break;
7827 case CP0_REGISTER_13:
7828 switch (sel) {
7829 case 0:
7830 save_cpu_state(ctx, 1);
7831 gen_helper_mtc0_cause(cpu_env, arg);
7832 /* Stop translation as we may have triggered an interrupt.
7833 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7834 * translated code to check for pending interrupts. */
7835 gen_save_pc(ctx->base.pc_next + 4);
7836 ctx->base.is_jmp = DISAS_EXIT;
7837 register_name = "Cause";
7838 break;
7839 default:
7840 goto cp0_unimplemented;
7842 break;
7843 case CP0_REGISTER_14:
7844 switch (sel) {
7845 case 0:
7846 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7847 register_name = "EPC";
7848 break;
7849 default:
7850 goto cp0_unimplemented;
7852 break;
7853 case CP0_REGISTER_15:
7854 switch (sel) {
7855 case 0:
7856 /* ignored */
7857 register_name = "PRid";
7858 break;
7859 case 1:
7860 check_insn(ctx, ISA_MIPS32R2);
7861 gen_helper_mtc0_ebase(cpu_env, arg);
7862 register_name = "EBase";
7863 break;
7864 default:
7865 goto cp0_unimplemented;
7867 break;
7868 case CP0_REGISTER_16:
7869 switch (sel) {
7870 case 0:
7871 gen_helper_mtc0_config0(cpu_env, arg);
7872 register_name = "Config";
7873 /* Stop translation as we may have switched the execution mode */
7874 ctx->base.is_jmp = DISAS_STOP;
7875 break;
7876 case 1:
7877 /* ignored, read only */
7878 register_name = "Config1";
7879 break;
7880 case 2:
7881 gen_helper_mtc0_config2(cpu_env, arg);
7882 register_name = "Config2";
7883 /* Stop translation as we may have switched the execution mode */
7884 ctx->base.is_jmp = DISAS_STOP;
7885 break;
7886 case 3:
7887 gen_helper_mtc0_config3(cpu_env, arg);
7888 register_name = "Config3";
7889 /* Stop translation as we may have switched the execution mode */
7890 ctx->base.is_jmp = DISAS_STOP;
7891 break;
7892 case 4:
7893 gen_helper_mtc0_config4(cpu_env, arg);
7894 register_name = "Config4";
7895 ctx->base.is_jmp = DISAS_STOP;
7896 break;
7897 case 5:
7898 gen_helper_mtc0_config5(cpu_env, arg);
7899 register_name = "Config5";
7900 /* Stop translation as we may have switched the execution mode */
7901 ctx->base.is_jmp = DISAS_STOP;
7902 break;
7903 /* 6,7 are implementation dependent */
7904 case 6:
7905 /* ignored */
7906 register_name = "Config6";
7907 break;
7908 case 7:
7909 /* ignored */
7910 register_name = "Config7";
7911 break;
7912 default:
7913 register_name = "Invalid config selector";
7914 goto cp0_unimplemented;
7916 break;
7917 case CP0_REGISTER_17:
7918 switch (sel) {
7919 case 0:
7920 gen_helper_mtc0_lladdr(cpu_env, arg);
7921 register_name = "LLAddr";
7922 break;
7923 case 1:
7924 CP0_CHECK(ctx->mrp);
7925 gen_helper_mtc0_maar(cpu_env, arg);
7926 register_name = "MAAR";
7927 break;
7928 case 2:
7929 CP0_CHECK(ctx->mrp);
7930 gen_helper_mtc0_maari(cpu_env, arg);
7931 register_name = "MAARI";
7932 break;
7933 default:
7934 goto cp0_unimplemented;
7936 break;
7937 case CP0_REGISTER_18:
7938 switch (sel) {
7939 case 0:
7940 case 1:
7941 case 2:
7942 case 3:
7943 case 4:
7944 case 5:
7945 case 6:
7946 case 7:
7947 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7948 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7949 register_name = "WatchLo";
7950 break;
7951 default:
7952 goto cp0_unimplemented;
7954 break;
7955 case CP0_REGISTER_19:
7956 switch (sel) {
7957 case 0:
7958 case 1:
7959 case 2:
7960 case 3:
7961 case 4:
7962 case 5:
7963 case 6:
7964 case 7:
7965 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7966 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7967 register_name = "WatchHi";
7968 break;
7969 default:
7970 goto cp0_unimplemented;
7972 break;
7973 case CP0_REGISTER_20:
7974 switch (sel) {
7975 case 0:
7976 #if defined(TARGET_MIPS64)
7977 check_insn(ctx, ISA_MIPS3);
7978 gen_helper_mtc0_xcontext(cpu_env, arg);
7979 register_name = "XContext";
7980 break;
7981 #endif
7982 default:
7983 goto cp0_unimplemented;
7985 break;
7986 case CP0_REGISTER_21:
7987 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7988 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7989 switch (sel) {
7990 case 0:
7991 gen_helper_mtc0_framemask(cpu_env, arg);
7992 register_name = "Framemask";
7993 break;
7994 default:
7995 goto cp0_unimplemented;
7997 break;
7998 case CP0_REGISTER_22:
7999 /* ignored */
8000 register_name = "Diagnostic"; /* implementation dependent */
8001 break;
8002 case CP0_REGISTER_23:
8003 switch (sel) {
8004 case 0:
8005 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8006 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8007 gen_save_pc(ctx->base.pc_next + 4);
8008 ctx->base.is_jmp = DISAS_EXIT;
8009 register_name = "Debug";
8010 break;
8011 case 1:
8012 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8013 register_name = "TraceControl";
8014 /* Stop translation as we may have switched the execution mode */
8015 ctx->base.is_jmp = DISAS_STOP;
8016 goto cp0_unimplemented;
8017 case 2:
8018 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8019 register_name = "TraceControl2";
8020 /* Stop translation as we may have switched the execution mode */
8021 ctx->base.is_jmp = DISAS_STOP;
8022 goto cp0_unimplemented;
8023 case 3:
8024 /* Stop translation as we may have switched the execution mode */
8025 ctx->base.is_jmp = DISAS_STOP;
8026 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8027 register_name = "UserTraceData";
8028 /* Stop translation as we may have switched the execution mode */
8029 ctx->base.is_jmp = DISAS_STOP;
8030 goto cp0_unimplemented;
8031 case 4:
8032 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8033 /* Stop translation as we may have switched the execution mode */
8034 ctx->base.is_jmp = DISAS_STOP;
8035 register_name = "TraceBPC";
8036 goto cp0_unimplemented;
8037 default:
8038 goto cp0_unimplemented;
8040 break;
8041 case CP0_REGISTER_24:
8042 switch (sel) {
8043 case 0:
8044 /* EJTAG support */
8045 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8046 register_name = "DEPC";
8047 break;
8048 default:
8049 goto cp0_unimplemented;
8051 break;
8052 case CP0_REGISTER_25:
8053 switch (sel) {
8054 case 0:
8055 gen_helper_mtc0_performance0(cpu_env, arg);
8056 register_name = "Performance0";
8057 break;
8058 case 1:
8059 // gen_helper_mtc0_performance1(arg);
8060 register_name = "Performance1";
8061 goto cp0_unimplemented;
8062 case 2:
8063 // gen_helper_mtc0_performance2(arg);
8064 register_name = "Performance2";
8065 goto cp0_unimplemented;
8066 case 3:
8067 // gen_helper_mtc0_performance3(arg);
8068 register_name = "Performance3";
8069 goto cp0_unimplemented;
8070 case 4:
8071 // gen_helper_mtc0_performance4(arg);
8072 register_name = "Performance4";
8073 goto cp0_unimplemented;
8074 case 5:
8075 // gen_helper_mtc0_performance5(arg);
8076 register_name = "Performance5";
8077 goto cp0_unimplemented;
8078 case 6:
8079 // gen_helper_mtc0_performance6(arg);
8080 register_name = "Performance6";
8081 goto cp0_unimplemented;
8082 case 7:
8083 // gen_helper_mtc0_performance7(arg);
8084 register_name = "Performance7";
8085 goto cp0_unimplemented;
8086 default:
8087 goto cp0_unimplemented;
8089 break;
8090 case CP0_REGISTER_26:
8091 switch (sel) {
8092 case 0:
8093 gen_helper_mtc0_errctl(cpu_env, arg);
8094 ctx->base.is_jmp = DISAS_STOP;
8095 register_name = "ErrCtl";
8096 break;
8097 default:
8098 goto cp0_unimplemented;
8100 break;
8101 case CP0_REGISTER_27:
8102 switch (sel) {
8103 case 0:
8104 case 1:
8105 case 2:
8106 case 3:
8107 /* ignored */
8108 register_name = "CacheErr";
8109 break;
8110 default:
8111 goto cp0_unimplemented;
8113 break;
8114 case CP0_REGISTER_28:
8115 switch (sel) {
8116 case 0:
8117 case 2:
8118 case 4:
8119 case 6:
8120 gen_helper_mtc0_taglo(cpu_env, arg);
8121 register_name = "TagLo";
8122 break;
8123 case 1:
8124 case 3:
8125 case 5:
8126 case 7:
8127 gen_helper_mtc0_datalo(cpu_env, arg);
8128 register_name = "DataLo";
8129 break;
8130 default:
8131 goto cp0_unimplemented;
8133 break;
8134 case CP0_REGISTER_29:
8135 switch (sel) {
8136 case 0:
8137 case 2:
8138 case 4:
8139 case 6:
8140 gen_helper_mtc0_taghi(cpu_env, arg);
8141 register_name = "TagHi";
8142 break;
8143 case 1:
8144 case 3:
8145 case 5:
8146 case 7:
8147 gen_helper_mtc0_datahi(cpu_env, arg);
8148 register_name = "DataHi";
8149 break;
8150 default:
8151 register_name = "invalid sel";
8152 goto cp0_unimplemented;
8154 break;
8155 case CP0_REGISTER_30:
8156 switch (sel) {
8157 case 0:
8158 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8159 register_name = "ErrorEPC";
8160 break;
8161 default:
8162 goto cp0_unimplemented;
8164 break;
8165 case CP0_REGISTER_31:
8166 switch (sel) {
8167 case 0:
8168 /* EJTAG support */
8169 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8170 register_name = "DESAVE";
8171 break;
8172 case 2:
8173 case 3:
8174 case 4:
8175 case 5:
8176 case 6:
8177 case 7:
8178 CP0_CHECK(ctx->kscrexist & (1 << sel));
8179 tcg_gen_st_tl(arg, cpu_env,
8180 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8181 register_name = "KScratch";
8182 break;
8183 default:
8184 goto cp0_unimplemented;
8186 break;
8187 default:
8188 goto cp0_unimplemented;
8190 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8192 /* For simplicity assume that all writes can cause interrupts. */
8193 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8194 gen_io_end();
8195 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8196 * translated code to check for pending interrupts. */
8197 gen_save_pc(ctx->base.pc_next + 4);
8198 ctx->base.is_jmp = DISAS_EXIT;
8200 return;
8202 cp0_unimplemented:
8203 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8204 register_name, reg, sel);
8207 #if defined(TARGET_MIPS64)
8208 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8210 const char *register_name = "invalid";
8212 if (sel != 0)
8213 check_insn(ctx, ISA_MIPS64);
8215 switch (reg) {
8216 case CP0_REGISTER_00:
8217 switch (sel) {
8218 case 0:
8219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8220 register_name = "Index";
8221 break;
8222 case 1:
8223 CP0_CHECK(ctx->insn_flags & ASE_MT);
8224 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8225 register_name = "MVPControl";
8226 break;
8227 case 2:
8228 CP0_CHECK(ctx->insn_flags & ASE_MT);
8229 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8230 register_name = "MVPConf0";
8231 break;
8232 case 3:
8233 CP0_CHECK(ctx->insn_flags & ASE_MT);
8234 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8235 register_name = "MVPConf1";
8236 break;
8237 case 4:
8238 CP0_CHECK(ctx->vp);
8239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8240 register_name = "VPControl";
8241 break;
8242 default:
8243 goto cp0_unimplemented;
8245 break;
8246 case CP0_REGISTER_01:
8247 switch (sel) {
8248 case 0:
8249 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8250 gen_helper_mfc0_random(arg, cpu_env);
8251 register_name = "Random";
8252 break;
8253 case 1:
8254 CP0_CHECK(ctx->insn_flags & ASE_MT);
8255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8256 register_name = "VPEControl";
8257 break;
8258 case 2:
8259 CP0_CHECK(ctx->insn_flags & ASE_MT);
8260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8261 register_name = "VPEConf0";
8262 break;
8263 case 3:
8264 CP0_CHECK(ctx->insn_flags & ASE_MT);
8265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8266 register_name = "VPEConf1";
8267 break;
8268 case 4:
8269 CP0_CHECK(ctx->insn_flags & ASE_MT);
8270 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8271 register_name = "YQMask";
8272 break;
8273 case 5:
8274 CP0_CHECK(ctx->insn_flags & ASE_MT);
8275 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8276 register_name = "VPESchedule";
8277 break;
8278 case 6:
8279 CP0_CHECK(ctx->insn_flags & ASE_MT);
8280 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8281 register_name = "VPEScheFBack";
8282 break;
8283 case 7:
8284 CP0_CHECK(ctx->insn_flags & ASE_MT);
8285 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8286 register_name = "VPEOpt";
8287 break;
8288 default:
8289 goto cp0_unimplemented;
8291 break;
8292 case CP0_REGISTER_02:
8293 switch (sel) {
8294 case 0:
8295 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8296 register_name = "EntryLo0";
8297 break;
8298 case 1:
8299 CP0_CHECK(ctx->insn_flags & ASE_MT);
8300 gen_helper_mfc0_tcstatus(arg, cpu_env);
8301 register_name = "TCStatus";
8302 break;
8303 case 2:
8304 CP0_CHECK(ctx->insn_flags & ASE_MT);
8305 gen_helper_mfc0_tcbind(arg, cpu_env);
8306 register_name = "TCBind";
8307 break;
8308 case 3:
8309 CP0_CHECK(ctx->insn_flags & ASE_MT);
8310 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8311 register_name = "TCRestart";
8312 break;
8313 case 4:
8314 CP0_CHECK(ctx->insn_flags & ASE_MT);
8315 gen_helper_dmfc0_tchalt(arg, cpu_env);
8316 register_name = "TCHalt";
8317 break;
8318 case 5:
8319 CP0_CHECK(ctx->insn_flags & ASE_MT);
8320 gen_helper_dmfc0_tccontext(arg, cpu_env);
8321 register_name = "TCContext";
8322 break;
8323 case 6:
8324 CP0_CHECK(ctx->insn_flags & ASE_MT);
8325 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8326 register_name = "TCSchedule";
8327 break;
8328 case 7:
8329 CP0_CHECK(ctx->insn_flags & ASE_MT);
8330 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8331 register_name = "TCScheFBack";
8332 break;
8333 default:
8334 goto cp0_unimplemented;
8336 break;
8337 case CP0_REGISTER_03:
8338 switch (sel) {
8339 case 0:
8340 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8341 register_name = "EntryLo1";
8342 break;
8343 case 1:
8344 CP0_CHECK(ctx->vp);
8345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8346 register_name = "GlobalNumber";
8347 break;
8348 default:
8349 goto cp0_unimplemented;
8351 break;
8352 case CP0_REGISTER_04:
8353 switch (sel) {
8354 case 0:
8355 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8356 register_name = "Context";
8357 break;
8358 case 1:
8359 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8360 register_name = "ContextConfig";
8361 goto cp0_unimplemented;
8362 case 2:
8363 CP0_CHECK(ctx->ulri);
8364 tcg_gen_ld_tl(arg, cpu_env,
8365 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8366 register_name = "UserLocal";
8367 break;
8368 default:
8369 goto cp0_unimplemented;
8371 break;
8372 case CP0_REGISTER_05:
8373 switch (sel) {
8374 case 0:
8375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8376 register_name = "PageMask";
8377 break;
8378 case 1:
8379 check_insn(ctx, ISA_MIPS32R2);
8380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8381 register_name = "PageGrain";
8382 break;
8383 case 2:
8384 CP0_CHECK(ctx->sc);
8385 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8386 register_name = "SegCtl0";
8387 break;
8388 case 3:
8389 CP0_CHECK(ctx->sc);
8390 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8391 register_name = "SegCtl1";
8392 break;
8393 case 4:
8394 CP0_CHECK(ctx->sc);
8395 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8396 register_name = "SegCtl2";
8397 break;
8398 case 5:
8399 check_pw(ctx);
8400 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8401 register_name = "PWBase";
8402 break;
8403 case 6:
8404 check_pw(ctx);
8405 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8406 register_name = "PWField";
8407 break;
8408 case 7:
8409 check_pw(ctx);
8410 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8411 register_name = "PWSize";
8412 break;
8413 default:
8414 goto cp0_unimplemented;
8416 break;
8417 case CP0_REGISTER_06:
8418 switch (sel) {
8419 case 0:
8420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8421 register_name = "Wired";
8422 break;
8423 case 1:
8424 check_insn(ctx, ISA_MIPS32R2);
8425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8426 register_name = "SRSConf0";
8427 break;
8428 case 2:
8429 check_insn(ctx, ISA_MIPS32R2);
8430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8431 register_name = "SRSConf1";
8432 break;
8433 case 3:
8434 check_insn(ctx, ISA_MIPS32R2);
8435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8436 register_name = "SRSConf2";
8437 break;
8438 case 4:
8439 check_insn(ctx, ISA_MIPS32R2);
8440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8441 register_name = "SRSConf3";
8442 break;
8443 case 5:
8444 check_insn(ctx, ISA_MIPS32R2);
8445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8446 register_name = "SRSConf4";
8447 break;
8448 case 6:
8449 check_pw(ctx);
8450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8451 register_name = "PWCtl";
8452 break;
8453 default:
8454 goto cp0_unimplemented;
8456 break;
8457 case CP0_REGISTER_07:
8458 switch (sel) {
8459 case 0:
8460 check_insn(ctx, ISA_MIPS32R2);
8461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8462 register_name = "HWREna";
8463 break;
8464 default:
8465 goto cp0_unimplemented;
8467 break;
8468 case CP0_REGISTER_08:
8469 switch (sel) {
8470 case 0:
8471 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8472 register_name = "BadVAddr";
8473 break;
8474 case 1:
8475 CP0_CHECK(ctx->bi);
8476 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8477 register_name = "BadInstr";
8478 break;
8479 case 2:
8480 CP0_CHECK(ctx->bp);
8481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8482 register_name = "BadInstrP";
8483 break;
8484 case 3:
8485 CP0_CHECK(ctx->bi);
8486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8487 tcg_gen_andi_tl(arg, arg, ~0xffff);
8488 register_name = "BadInstrX";
8489 break;
8490 default:
8491 goto cp0_unimplemented;
8493 break;
8494 case CP0_REGISTER_09:
8495 switch (sel) {
8496 case 0:
8497 /* Mark as an IO operation because we read the time. */
8498 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8499 gen_io_start();
8501 gen_helper_mfc0_count(arg, cpu_env);
8502 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8503 gen_io_end();
8505 /* Break the TB to be able to take timer interrupts immediately
8506 after reading count. DISAS_STOP isn't sufficient, we need to
8507 ensure we break completely out of translated code. */
8508 gen_save_pc(ctx->base.pc_next + 4);
8509 ctx->base.is_jmp = DISAS_EXIT;
8510 register_name = "Count";
8511 break;
8512 case 6:
8513 CP0_CHECK(ctx->saar);
8514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8515 register_name = "SAARI";
8516 break;
8517 case 7:
8518 CP0_CHECK(ctx->saar);
8519 gen_helper_dmfc0_saar(arg, cpu_env);
8520 register_name = "SAAR";
8521 break;
8522 default:
8523 goto cp0_unimplemented;
8525 break;
8526 case CP0_REGISTER_10:
8527 switch (sel) {
8528 case 0:
8529 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8530 register_name = "EntryHi";
8531 break;
8532 default:
8533 goto cp0_unimplemented;
8535 break;
8536 case CP0_REGISTER_11:
8537 switch (sel) {
8538 case 0:
8539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8540 register_name = "Compare";
8541 break;
8542 /* 6,7 are implementation dependent */
8543 default:
8544 goto cp0_unimplemented;
8546 break;
8547 case CP0_REGISTER_12:
8548 switch (sel) {
8549 case 0:
8550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8551 register_name = "Status";
8552 break;
8553 case 1:
8554 check_insn(ctx, ISA_MIPS32R2);
8555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8556 register_name = "IntCtl";
8557 break;
8558 case 2:
8559 check_insn(ctx, ISA_MIPS32R2);
8560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8561 register_name = "SRSCtl";
8562 break;
8563 case 3:
8564 check_insn(ctx, ISA_MIPS32R2);
8565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8566 register_name = "SRSMap";
8567 break;
8568 default:
8569 goto cp0_unimplemented;
8571 break;
8572 case CP0_REGISTER_13:
8573 switch (sel) {
8574 case 0:
8575 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8576 register_name = "Cause";
8577 break;
8578 default:
8579 goto cp0_unimplemented;
8581 break;
8582 case CP0_REGISTER_14:
8583 switch (sel) {
8584 case 0:
8585 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8586 register_name = "EPC";
8587 break;
8588 default:
8589 goto cp0_unimplemented;
8591 break;
8592 case CP0_REGISTER_15:
8593 switch (sel) {
8594 case 0:
8595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8596 register_name = "PRid";
8597 break;
8598 case 1:
8599 check_insn(ctx, ISA_MIPS32R2);
8600 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8601 register_name = "EBase";
8602 break;
8603 case 3:
8604 check_insn(ctx, ISA_MIPS32R2);
8605 CP0_CHECK(ctx->cmgcr);
8606 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8607 register_name = "CMGCRBase";
8608 break;
8609 default:
8610 goto cp0_unimplemented;
8612 break;
8613 case CP0_REGISTER_16:
8614 switch (sel) {
8615 case 0:
8616 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8617 register_name = "Config";
8618 break;
8619 case 1:
8620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8621 register_name = "Config1";
8622 break;
8623 case 2:
8624 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8625 register_name = "Config2";
8626 break;
8627 case 3:
8628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8629 register_name = "Config3";
8630 break;
8631 case 4:
8632 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8633 register_name = "Config4";
8634 break;
8635 case 5:
8636 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8637 register_name = "Config5";
8638 break;
8639 /* 6,7 are implementation dependent */
8640 case 6:
8641 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8642 register_name = "Config6";
8643 break;
8644 case 7:
8645 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8646 register_name = "Config7";
8647 break;
8648 default:
8649 goto cp0_unimplemented;
8651 break;
8652 case CP0_REGISTER_17:
8653 switch (sel) {
8654 case 0:
8655 gen_helper_dmfc0_lladdr(arg, cpu_env);
8656 register_name = "LLAddr";
8657 break;
8658 case 1:
8659 CP0_CHECK(ctx->mrp);
8660 gen_helper_dmfc0_maar(arg, cpu_env);
8661 register_name = "MAAR";
8662 break;
8663 case 2:
8664 CP0_CHECK(ctx->mrp);
8665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8666 register_name = "MAARI";
8667 break;
8668 default:
8669 goto cp0_unimplemented;
8671 break;
8672 case CP0_REGISTER_18:
8673 switch (sel) {
8674 case 0:
8675 case 1:
8676 case 2:
8677 case 3:
8678 case 4:
8679 case 5:
8680 case 6:
8681 case 7:
8682 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8683 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8684 register_name = "WatchLo";
8685 break;
8686 default:
8687 goto cp0_unimplemented;
8689 break;
8690 case CP0_REGISTER_19:
8691 switch (sel) {
8692 case 0:
8693 case 1:
8694 case 2:
8695 case 3:
8696 case 4:
8697 case 5:
8698 case 6:
8699 case 7:
8700 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8701 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8702 register_name = "WatchHi";
8703 break;
8704 default:
8705 goto cp0_unimplemented;
8707 break;
8708 case CP0_REGISTER_20:
8709 switch (sel) {
8710 case 0:
8711 check_insn(ctx, ISA_MIPS3);
8712 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8713 register_name = "XContext";
8714 break;
8715 default:
8716 goto cp0_unimplemented;
8718 break;
8719 case CP0_REGISTER_21:
8720 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8721 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8722 switch (sel) {
8723 case 0:
8724 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8725 register_name = "Framemask";
8726 break;
8727 default:
8728 goto cp0_unimplemented;
8730 break;
8731 case CP0_REGISTER_22:
8732 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8733 register_name = "'Diagnostic"; /* implementation dependent */
8734 break;
8735 case CP0_REGISTER_23:
8736 switch (sel) {
8737 case 0:
8738 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8739 register_name = "Debug";
8740 break;
8741 case 1:
8742 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8743 register_name = "TraceControl";
8744 goto cp0_unimplemented;
8745 case 2:
8746 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8747 register_name = "TraceControl2";
8748 goto cp0_unimplemented;
8749 case 3:
8750 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8751 register_name = "UserTraceData";
8752 goto cp0_unimplemented;
8753 case 4:
8754 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8755 register_name = "TraceBPC";
8756 goto cp0_unimplemented;
8757 default:
8758 goto cp0_unimplemented;
8760 break;
8761 case CP0_REGISTER_24:
8762 switch (sel) {
8763 case 0:
8764 /* EJTAG support */
8765 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8766 register_name = "DEPC";
8767 break;
8768 default:
8769 goto cp0_unimplemented;
8771 break;
8772 case CP0_REGISTER_25:
8773 switch (sel) {
8774 case 0:
8775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8776 register_name = "Performance0";
8777 break;
8778 case 1:
8779 // gen_helper_dmfc0_performance1(arg);
8780 register_name = "Performance1";
8781 goto cp0_unimplemented;
8782 case 2:
8783 // gen_helper_dmfc0_performance2(arg);
8784 register_name = "Performance2";
8785 goto cp0_unimplemented;
8786 case 3:
8787 // gen_helper_dmfc0_performance3(arg);
8788 register_name = "Performance3";
8789 goto cp0_unimplemented;
8790 case 4:
8791 // gen_helper_dmfc0_performance4(arg);
8792 register_name = "Performance4";
8793 goto cp0_unimplemented;
8794 case 5:
8795 // gen_helper_dmfc0_performance5(arg);
8796 register_name = "Performance5";
8797 goto cp0_unimplemented;
8798 case 6:
8799 // gen_helper_dmfc0_performance6(arg);
8800 register_name = "Performance6";
8801 goto cp0_unimplemented;
8802 case 7:
8803 // gen_helper_dmfc0_performance7(arg);
8804 register_name = "Performance7";
8805 goto cp0_unimplemented;
8806 default:
8807 goto cp0_unimplemented;
8809 break;
8810 case CP0_REGISTER_26:
8811 switch (sel) {
8812 case 0:
8813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8814 register_name = "ErrCtl";
8815 break;
8816 default:
8817 goto cp0_unimplemented;
8819 break;
8820 case CP0_REGISTER_27:
8821 switch (sel) {
8822 /* ignored */
8823 case 0:
8824 case 1:
8825 case 2:
8826 case 3:
8827 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8828 register_name = "CacheErr";
8829 break;
8830 default:
8831 goto cp0_unimplemented;
8833 break;
8834 case CP0_REGISTER_28:
8835 switch (sel) {
8836 case 0:
8837 case 2:
8838 case 4:
8839 case 6:
8840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8841 register_name = "TagLo";
8842 break;
8843 case 1:
8844 case 3:
8845 case 5:
8846 case 7:
8847 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8848 register_name = "DataLo";
8849 break;
8850 default:
8851 goto cp0_unimplemented;
8853 break;
8854 case CP0_REGISTER_29:
8855 switch (sel) {
8856 case 0:
8857 case 2:
8858 case 4:
8859 case 6:
8860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8861 register_name = "TagHi";
8862 break;
8863 case 1:
8864 case 3:
8865 case 5:
8866 case 7:
8867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8868 register_name = "DataHi";
8869 break;
8870 default:
8871 goto cp0_unimplemented;
8873 break;
8874 case CP0_REGISTER_30:
8875 switch (sel) {
8876 case 0:
8877 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8878 register_name = "ErrorEPC";
8879 break;
8880 default:
8881 goto cp0_unimplemented;
8883 break;
8884 case CP0_REGISTER_31:
8885 switch (sel) {
8886 case 0:
8887 /* EJTAG support */
8888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8889 register_name = "DESAVE";
8890 break;
8891 case 2:
8892 case 3:
8893 case 4:
8894 case 5:
8895 case 6:
8896 case 7:
8897 CP0_CHECK(ctx->kscrexist & (1 << sel));
8898 tcg_gen_ld_tl(arg, cpu_env,
8899 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8900 register_name = "KScratch";
8901 break;
8902 default:
8903 goto cp0_unimplemented;
8905 break;
8906 default:
8907 goto cp0_unimplemented;
8909 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8910 return;
8912 cp0_unimplemented:
8913 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8914 register_name, reg, sel);
8915 gen_mfc0_unimplemented(ctx, arg);
8918 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8920 const char *register_name = "invalid";
8922 if (sel != 0)
8923 check_insn(ctx, ISA_MIPS64);
8925 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8926 gen_io_start();
8929 switch (reg) {
8930 case CP0_REGISTER_00:
8931 switch (sel) {
8932 case 0:
8933 gen_helper_mtc0_index(cpu_env, arg);
8934 register_name = "Index";
8935 break;
8936 case 1:
8937 CP0_CHECK(ctx->insn_flags & ASE_MT);
8938 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8939 register_name = "MVPControl";
8940 break;
8941 case 2:
8942 CP0_CHECK(ctx->insn_flags & ASE_MT);
8943 /* ignored */
8944 register_name = "MVPConf0";
8945 break;
8946 case 3:
8947 CP0_CHECK(ctx->insn_flags & ASE_MT);
8948 /* ignored */
8949 register_name = "MVPConf1";
8950 break;
8951 case 4:
8952 CP0_CHECK(ctx->vp);
8953 /* ignored */
8954 register_name = "VPControl";
8955 break;
8956 default:
8957 goto cp0_unimplemented;
8959 break;
8960 case CP0_REGISTER_01:
8961 switch (sel) {
8962 case 0:
8963 /* ignored */
8964 register_name = "Random";
8965 break;
8966 case 1:
8967 CP0_CHECK(ctx->insn_flags & ASE_MT);
8968 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8969 register_name = "VPEControl";
8970 break;
8971 case 2:
8972 CP0_CHECK(ctx->insn_flags & ASE_MT);
8973 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8974 register_name = "VPEConf0";
8975 break;
8976 case 3:
8977 CP0_CHECK(ctx->insn_flags & ASE_MT);
8978 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8979 register_name = "VPEConf1";
8980 break;
8981 case 4:
8982 CP0_CHECK(ctx->insn_flags & ASE_MT);
8983 gen_helper_mtc0_yqmask(cpu_env, arg);
8984 register_name = "YQMask";
8985 break;
8986 case 5:
8987 CP0_CHECK(ctx->insn_flags & ASE_MT);
8988 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8989 register_name = "VPESchedule";
8990 break;
8991 case 6:
8992 CP0_CHECK(ctx->insn_flags & ASE_MT);
8993 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8994 register_name = "VPEScheFBack";
8995 break;
8996 case 7:
8997 CP0_CHECK(ctx->insn_flags & ASE_MT);
8998 gen_helper_mtc0_vpeopt(cpu_env, arg);
8999 register_name = "VPEOpt";
9000 break;
9001 default:
9002 goto cp0_unimplemented;
9004 break;
9005 case CP0_REGISTER_02:
9006 switch (sel) {
9007 case 0:
9008 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9009 register_name = "EntryLo0";
9010 break;
9011 case 1:
9012 CP0_CHECK(ctx->insn_flags & ASE_MT);
9013 gen_helper_mtc0_tcstatus(cpu_env, arg);
9014 register_name = "TCStatus";
9015 break;
9016 case 2:
9017 CP0_CHECK(ctx->insn_flags & ASE_MT);
9018 gen_helper_mtc0_tcbind(cpu_env, arg);
9019 register_name = "TCBind";
9020 break;
9021 case 3:
9022 CP0_CHECK(ctx->insn_flags & ASE_MT);
9023 gen_helper_mtc0_tcrestart(cpu_env, arg);
9024 register_name = "TCRestart";
9025 break;
9026 case 4:
9027 CP0_CHECK(ctx->insn_flags & ASE_MT);
9028 gen_helper_mtc0_tchalt(cpu_env, arg);
9029 register_name = "TCHalt";
9030 break;
9031 case 5:
9032 CP0_CHECK(ctx->insn_flags & ASE_MT);
9033 gen_helper_mtc0_tccontext(cpu_env, arg);
9034 register_name = "TCContext";
9035 break;
9036 case 6:
9037 CP0_CHECK(ctx->insn_flags & ASE_MT);
9038 gen_helper_mtc0_tcschedule(cpu_env, arg);
9039 register_name = "TCSchedule";
9040 break;
9041 case 7:
9042 CP0_CHECK(ctx->insn_flags & ASE_MT);
9043 gen_helper_mtc0_tcschefback(cpu_env, arg);
9044 register_name = "TCScheFBack";
9045 break;
9046 default:
9047 goto cp0_unimplemented;
9049 break;
9050 case CP0_REGISTER_03:
9051 switch (sel) {
9052 case 0:
9053 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9054 register_name = "EntryLo1";
9055 break;
9056 case 1:
9057 CP0_CHECK(ctx->vp);
9058 /* ignored */
9059 register_name = "GlobalNumber";
9060 break;
9061 default:
9062 goto cp0_unimplemented;
9064 break;
9065 case CP0_REGISTER_04:
9066 switch (sel) {
9067 case 0:
9068 gen_helper_mtc0_context(cpu_env, arg);
9069 register_name = "Context";
9070 break;
9071 case 1:
9072 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
9073 register_name = "ContextConfig";
9074 goto cp0_unimplemented;
9075 case 2:
9076 CP0_CHECK(ctx->ulri);
9077 tcg_gen_st_tl(arg, cpu_env,
9078 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9079 register_name = "UserLocal";
9080 break;
9081 default:
9082 goto cp0_unimplemented;
9084 break;
9085 case CP0_REGISTER_05:
9086 switch (sel) {
9087 case 0:
9088 gen_helper_mtc0_pagemask(cpu_env, arg);
9089 register_name = "PageMask";
9090 break;
9091 case 1:
9092 check_insn(ctx, ISA_MIPS32R2);
9093 gen_helper_mtc0_pagegrain(cpu_env, arg);
9094 register_name = "PageGrain";
9095 break;
9096 case 2:
9097 CP0_CHECK(ctx->sc);
9098 gen_helper_mtc0_segctl0(cpu_env, arg);
9099 register_name = "SegCtl0";
9100 break;
9101 case 3:
9102 CP0_CHECK(ctx->sc);
9103 gen_helper_mtc0_segctl1(cpu_env, arg);
9104 register_name = "SegCtl1";
9105 break;
9106 case 4:
9107 CP0_CHECK(ctx->sc);
9108 gen_helper_mtc0_segctl2(cpu_env, arg);
9109 register_name = "SegCtl2";
9110 break;
9111 case 5:
9112 check_pw(ctx);
9113 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9114 register_name = "PWBase";
9115 break;
9116 case 6:
9117 check_pw(ctx);
9118 gen_helper_mtc0_pwfield(cpu_env, arg);
9119 register_name = "PWField";
9120 break;
9121 case 7:
9122 check_pw(ctx);
9123 gen_helper_mtc0_pwsize(cpu_env, arg);
9124 register_name = "PWSize";
9125 break;
9126 default:
9127 goto cp0_unimplemented;
9129 break;
9130 case CP0_REGISTER_06:
9131 switch (sel) {
9132 case 0:
9133 gen_helper_mtc0_wired(cpu_env, arg);
9134 register_name = "Wired";
9135 break;
9136 case 1:
9137 check_insn(ctx, ISA_MIPS32R2);
9138 gen_helper_mtc0_srsconf0(cpu_env, arg);
9139 register_name = "SRSConf0";
9140 break;
9141 case 2:
9142 check_insn(ctx, ISA_MIPS32R2);
9143 gen_helper_mtc0_srsconf1(cpu_env, arg);
9144 register_name = "SRSConf1";
9145 break;
9146 case 3:
9147 check_insn(ctx, ISA_MIPS32R2);
9148 gen_helper_mtc0_srsconf2(cpu_env, arg);
9149 register_name = "SRSConf2";
9150 break;
9151 case 4:
9152 check_insn(ctx, ISA_MIPS32R2);
9153 gen_helper_mtc0_srsconf3(cpu_env, arg);
9154 register_name = "SRSConf3";
9155 break;
9156 case 5:
9157 check_insn(ctx, ISA_MIPS32R2);
9158 gen_helper_mtc0_srsconf4(cpu_env, arg);
9159 register_name = "SRSConf4";
9160 break;
9161 case 6:
9162 check_pw(ctx);
9163 gen_helper_mtc0_pwctl(cpu_env, arg);
9164 register_name = "PWCtl";
9165 break;
9166 default:
9167 goto cp0_unimplemented;
9169 break;
9170 case CP0_REGISTER_07:
9171 switch (sel) {
9172 case 0:
9173 check_insn(ctx, ISA_MIPS32R2);
9174 gen_helper_mtc0_hwrena(cpu_env, arg);
9175 ctx->base.is_jmp = DISAS_STOP;
9176 register_name = "HWREna";
9177 break;
9178 default:
9179 goto cp0_unimplemented;
9181 break;
9182 case CP0_REGISTER_08:
9183 switch (sel) {
9184 case 0:
9185 /* ignored */
9186 register_name = "BadVAddr";
9187 break;
9188 case 1:
9189 /* ignored */
9190 register_name = "BadInstr";
9191 break;
9192 case 2:
9193 /* ignored */
9194 register_name = "BadInstrP";
9195 break;
9196 case 3:
9197 /* ignored */
9198 register_name = "BadInstrX";
9199 break;
9200 default:
9201 goto cp0_unimplemented;
9203 break;
9204 case CP0_REGISTER_09:
9205 switch (sel) {
9206 case 0:
9207 gen_helper_mtc0_count(cpu_env, arg);
9208 register_name = "Count";
9209 break;
9210 case 6:
9211 CP0_CHECK(ctx->saar);
9212 gen_helper_mtc0_saari(cpu_env, arg);
9213 register_name = "SAARI";
9214 break;
9215 case 7:
9216 CP0_CHECK(ctx->saar);
9217 gen_helper_mtc0_saar(cpu_env, arg);
9218 register_name = "SAAR";
9219 break;
9220 default:
9221 goto cp0_unimplemented;
9223 /* Stop translation as we may have switched the execution mode */
9224 ctx->base.is_jmp = DISAS_STOP;
9225 break;
9226 case CP0_REGISTER_10:
9227 switch (sel) {
9228 case 0:
9229 gen_helper_mtc0_entryhi(cpu_env, arg);
9230 register_name = "EntryHi";
9231 break;
9232 default:
9233 goto cp0_unimplemented;
9235 break;
9236 case CP0_REGISTER_11:
9237 switch (sel) {
9238 case 0:
9239 gen_helper_mtc0_compare(cpu_env, arg);
9240 register_name = "Compare";
9241 break;
9242 /* 6,7 are implementation dependent */
9243 default:
9244 goto cp0_unimplemented;
9246 /* Stop translation as we may have switched the execution mode */
9247 ctx->base.is_jmp = DISAS_STOP;
9248 break;
9249 case CP0_REGISTER_12:
9250 switch (sel) {
9251 case 0:
9252 save_cpu_state(ctx, 1);
9253 gen_helper_mtc0_status(cpu_env, arg);
9254 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9255 gen_save_pc(ctx->base.pc_next + 4);
9256 ctx->base.is_jmp = DISAS_EXIT;
9257 register_name = "Status";
9258 break;
9259 case 1:
9260 check_insn(ctx, ISA_MIPS32R2);
9261 gen_helper_mtc0_intctl(cpu_env, arg);
9262 /* Stop translation as we may have switched the execution mode */
9263 ctx->base.is_jmp = DISAS_STOP;
9264 register_name = "IntCtl";
9265 break;
9266 case 2:
9267 check_insn(ctx, ISA_MIPS32R2);
9268 gen_helper_mtc0_srsctl(cpu_env, arg);
9269 /* Stop translation as we may have switched the execution mode */
9270 ctx->base.is_jmp = DISAS_STOP;
9271 register_name = "SRSCtl";
9272 break;
9273 case 3:
9274 check_insn(ctx, ISA_MIPS32R2);
9275 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9276 /* Stop translation as we may have switched the execution mode */
9277 ctx->base.is_jmp = DISAS_STOP;
9278 register_name = "SRSMap";
9279 break;
9280 default:
9281 goto cp0_unimplemented;
9283 break;
9284 case CP0_REGISTER_13:
9285 switch (sel) {
9286 case 0:
9287 save_cpu_state(ctx, 1);
9288 gen_helper_mtc0_cause(cpu_env, arg);
9289 /* Stop translation as we may have triggered an interrupt.
9290 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9291 * translated code to check for pending interrupts. */
9292 gen_save_pc(ctx->base.pc_next + 4);
9293 ctx->base.is_jmp = DISAS_EXIT;
9294 register_name = "Cause";
9295 break;
9296 default:
9297 goto cp0_unimplemented;
9299 break;
9300 case CP0_REGISTER_14:
9301 switch (sel) {
9302 case 0:
9303 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9304 register_name = "EPC";
9305 break;
9306 default:
9307 goto cp0_unimplemented;
9309 break;
9310 case CP0_REGISTER_15:
9311 switch (sel) {
9312 case 0:
9313 /* ignored */
9314 register_name = "PRid";
9315 break;
9316 case 1:
9317 check_insn(ctx, ISA_MIPS32R2);
9318 gen_helper_mtc0_ebase(cpu_env, arg);
9319 register_name = "EBase";
9320 break;
9321 default:
9322 goto cp0_unimplemented;
9324 break;
9325 case CP0_REGISTER_16:
9326 switch (sel) {
9327 case 0:
9328 gen_helper_mtc0_config0(cpu_env, arg);
9329 register_name = "Config";
9330 /* Stop translation as we may have switched the execution mode */
9331 ctx->base.is_jmp = DISAS_STOP;
9332 break;
9333 case 1:
9334 /* ignored, read only */
9335 register_name = "Config1";
9336 break;
9337 case 2:
9338 gen_helper_mtc0_config2(cpu_env, arg);
9339 register_name = "Config2";
9340 /* Stop translation as we may have switched the execution mode */
9341 ctx->base.is_jmp = DISAS_STOP;
9342 break;
9343 case 3:
9344 gen_helper_mtc0_config3(cpu_env, arg);
9345 register_name = "Config3";
9346 /* Stop translation as we may have switched the execution mode */
9347 ctx->base.is_jmp = DISAS_STOP;
9348 break;
9349 case 4:
9350 /* currently ignored */
9351 register_name = "Config4";
9352 break;
9353 case 5:
9354 gen_helper_mtc0_config5(cpu_env, arg);
9355 register_name = "Config5";
9356 /* Stop translation as we may have switched the execution mode */
9357 ctx->base.is_jmp = DISAS_STOP;
9358 break;
9359 /* 6,7 are implementation dependent */
9360 default:
9361 register_name = "Invalid config selector";
9362 goto cp0_unimplemented;
9364 break;
9365 case CP0_REGISTER_17:
9366 switch (sel) {
9367 case 0:
9368 gen_helper_mtc0_lladdr(cpu_env, arg);
9369 register_name = "LLAddr";
9370 break;
9371 case 1:
9372 CP0_CHECK(ctx->mrp);
9373 gen_helper_mtc0_maar(cpu_env, arg);
9374 register_name = "MAAR";
9375 break;
9376 case 2:
9377 CP0_CHECK(ctx->mrp);
9378 gen_helper_mtc0_maari(cpu_env, arg);
9379 register_name = "MAARI";
9380 break;
9381 default:
9382 goto cp0_unimplemented;
9384 break;
9385 case CP0_REGISTER_18:
9386 switch (sel) {
9387 case 0:
9388 case 1:
9389 case 2:
9390 case 3:
9391 case 4:
9392 case 5:
9393 case 6:
9394 case 7:
9395 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9396 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9397 register_name = "WatchLo";
9398 break;
9399 default:
9400 goto cp0_unimplemented;
9402 break;
9403 case CP0_REGISTER_19:
9404 switch (sel) {
9405 case 0:
9406 case 1:
9407 case 2:
9408 case 3:
9409 case 4:
9410 case 5:
9411 case 6:
9412 case 7:
9413 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9414 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9415 register_name = "WatchHi";
9416 break;
9417 default:
9418 goto cp0_unimplemented;
9420 break;
9421 case CP0_REGISTER_20:
9422 switch (sel) {
9423 case 0:
9424 check_insn(ctx, ISA_MIPS3);
9425 gen_helper_mtc0_xcontext(cpu_env, arg);
9426 register_name = "XContext";
9427 break;
9428 default:
9429 goto cp0_unimplemented;
9431 break;
9432 case CP0_REGISTER_21:
9433 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9434 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9435 switch (sel) {
9436 case 0:
9437 gen_helper_mtc0_framemask(cpu_env, arg);
9438 register_name = "Framemask";
9439 break;
9440 default:
9441 goto cp0_unimplemented;
9443 break;
9444 case CP0_REGISTER_22:
9445 /* ignored */
9446 register_name = "Diagnostic"; /* implementation dependent */
9447 break;
9448 case CP0_REGISTER_23:
9449 switch (sel) {
9450 case 0:
9451 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9452 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9453 gen_save_pc(ctx->base.pc_next + 4);
9454 ctx->base.is_jmp = DISAS_EXIT;
9455 register_name = "Debug";
9456 break;
9457 case 1:
9458 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9459 /* Stop translation as we may have switched the execution mode */
9460 ctx->base.is_jmp = DISAS_STOP;
9461 register_name = "TraceControl";
9462 goto cp0_unimplemented;
9463 case 2:
9464 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9465 /* Stop translation as we may have switched the execution mode */
9466 ctx->base.is_jmp = DISAS_STOP;
9467 register_name = "TraceControl2";
9468 goto cp0_unimplemented;
9469 case 3:
9470 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9471 /* Stop translation as we may have switched the execution mode */
9472 ctx->base.is_jmp = DISAS_STOP;
9473 register_name = "UserTraceData";
9474 goto cp0_unimplemented;
9475 case 4:
9476 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9477 /* Stop translation as we may have switched the execution mode */
9478 ctx->base.is_jmp = DISAS_STOP;
9479 register_name = "TraceBPC";
9480 goto cp0_unimplemented;
9481 default:
9482 goto cp0_unimplemented;
9484 break;
9485 case CP0_REGISTER_24:
9486 switch (sel) {
9487 case 0:
9488 /* EJTAG support */
9489 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9490 register_name = "DEPC";
9491 break;
9492 default:
9493 goto cp0_unimplemented;
9495 break;
9496 case CP0_REGISTER_25:
9497 switch (sel) {
9498 case 0:
9499 gen_helper_mtc0_performance0(cpu_env, arg);
9500 register_name = "Performance0";
9501 break;
9502 case 1:
9503 // gen_helper_mtc0_performance1(cpu_env, arg);
9504 register_name = "Performance1";
9505 goto cp0_unimplemented;
9506 case 2:
9507 // gen_helper_mtc0_performance2(cpu_env, arg);
9508 register_name = "Performance2";
9509 goto cp0_unimplemented;
9510 case 3:
9511 // gen_helper_mtc0_performance3(cpu_env, arg);
9512 register_name = "Performance3";
9513 goto cp0_unimplemented;
9514 case 4:
9515 // gen_helper_mtc0_performance4(cpu_env, arg);
9516 register_name = "Performance4";
9517 goto cp0_unimplemented;
9518 case 5:
9519 // gen_helper_mtc0_performance5(cpu_env, arg);
9520 register_name = "Performance5";
9521 goto cp0_unimplemented;
9522 case 6:
9523 // gen_helper_mtc0_performance6(cpu_env, arg);
9524 register_name = "Performance6";
9525 goto cp0_unimplemented;
9526 case 7:
9527 // gen_helper_mtc0_performance7(cpu_env, arg);
9528 register_name = "Performance7";
9529 goto cp0_unimplemented;
9530 default:
9531 goto cp0_unimplemented;
9533 break;
9534 case CP0_REGISTER_26:
9535 switch (sel) {
9536 case 0:
9537 gen_helper_mtc0_errctl(cpu_env, arg);
9538 ctx->base.is_jmp = DISAS_STOP;
9539 register_name = "ErrCtl";
9540 break;
9541 default:
9542 goto cp0_unimplemented;
9544 break;
9545 case CP0_REGISTER_27:
9546 switch (sel) {
9547 case 0:
9548 case 1:
9549 case 2:
9550 case 3:
9551 /* ignored */
9552 register_name = "CacheErr";
9553 break;
9554 default:
9555 goto cp0_unimplemented;
9557 break;
9558 case CP0_REGISTER_28:
9559 switch (sel) {
9560 case 0:
9561 case 2:
9562 case 4:
9563 case 6:
9564 gen_helper_mtc0_taglo(cpu_env, arg);
9565 register_name = "TagLo";
9566 break;
9567 case 1:
9568 case 3:
9569 case 5:
9570 case 7:
9571 gen_helper_mtc0_datalo(cpu_env, arg);
9572 register_name = "DataLo";
9573 break;
9574 default:
9575 goto cp0_unimplemented;
9577 break;
9578 case CP0_REGISTER_29:
9579 switch (sel) {
9580 case 0:
9581 case 2:
9582 case 4:
9583 case 6:
9584 gen_helper_mtc0_taghi(cpu_env, arg);
9585 register_name = "TagHi";
9586 break;
9587 case 1:
9588 case 3:
9589 case 5:
9590 case 7:
9591 gen_helper_mtc0_datahi(cpu_env, arg);
9592 register_name = "DataHi";
9593 break;
9594 default:
9595 register_name = "invalid sel";
9596 goto cp0_unimplemented;
9598 break;
9599 case CP0_REGISTER_30:
9600 switch (sel) {
9601 case 0:
9602 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9603 register_name = "ErrorEPC";
9604 break;
9605 default:
9606 goto cp0_unimplemented;
9608 break;
9609 case CP0_REGISTER_31:
9610 switch (sel) {
9611 case 0:
9612 /* EJTAG support */
9613 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9614 register_name = "DESAVE";
9615 break;
9616 case 2:
9617 case 3:
9618 case 4:
9619 case 5:
9620 case 6:
9621 case 7:
9622 CP0_CHECK(ctx->kscrexist & (1 << sel));
9623 tcg_gen_st_tl(arg, cpu_env,
9624 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9625 register_name = "KScratch";
9626 break;
9627 default:
9628 goto cp0_unimplemented;
9630 break;
9631 default:
9632 goto cp0_unimplemented;
9634 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9636 /* For simplicity assume that all writes can cause interrupts. */
9637 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9638 gen_io_end();
9639 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9640 * translated code to check for pending interrupts. */
9641 gen_save_pc(ctx->base.pc_next + 4);
9642 ctx->base.is_jmp = DISAS_EXIT;
9644 return;
9646 cp0_unimplemented:
9647 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9648 register_name, reg, sel);
9650 #endif /* TARGET_MIPS64 */
9652 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9653 int u, int sel, int h)
9655 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9656 TCGv t0 = tcg_temp_local_new();
9658 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9659 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9660 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9661 tcg_gen_movi_tl(t0, -1);
9662 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9663 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9664 tcg_gen_movi_tl(t0, -1);
9665 else if (u == 0) {
9666 switch (rt) {
9667 case 1:
9668 switch (sel) {
9669 case 1:
9670 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9671 break;
9672 case 2:
9673 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9674 break;
9675 default:
9676 goto die;
9677 break;
9679 break;
9680 case 2:
9681 switch (sel) {
9682 case 1:
9683 gen_helper_mftc0_tcstatus(t0, cpu_env);
9684 break;
9685 case 2:
9686 gen_helper_mftc0_tcbind(t0, cpu_env);
9687 break;
9688 case 3:
9689 gen_helper_mftc0_tcrestart(t0, cpu_env);
9690 break;
9691 case 4:
9692 gen_helper_mftc0_tchalt(t0, cpu_env);
9693 break;
9694 case 5:
9695 gen_helper_mftc0_tccontext(t0, cpu_env);
9696 break;
9697 case 6:
9698 gen_helper_mftc0_tcschedule(t0, cpu_env);
9699 break;
9700 case 7:
9701 gen_helper_mftc0_tcschefback(t0, cpu_env);
9702 break;
9703 default:
9704 gen_mfc0(ctx, t0, rt, sel);
9705 break;
9707 break;
9708 case 10:
9709 switch (sel) {
9710 case 0:
9711 gen_helper_mftc0_entryhi(t0, cpu_env);
9712 break;
9713 default:
9714 gen_mfc0(ctx, t0, rt, sel);
9715 break;
9717 case 12:
9718 switch (sel) {
9719 case 0:
9720 gen_helper_mftc0_status(t0, cpu_env);
9721 break;
9722 default:
9723 gen_mfc0(ctx, t0, rt, sel);
9724 break;
9726 case 13:
9727 switch (sel) {
9728 case 0:
9729 gen_helper_mftc0_cause(t0, cpu_env);
9730 break;
9731 default:
9732 goto die;
9733 break;
9735 break;
9736 case 14:
9737 switch (sel) {
9738 case 0:
9739 gen_helper_mftc0_epc(t0, cpu_env);
9740 break;
9741 default:
9742 goto die;
9743 break;
9745 break;
9746 case 15:
9747 switch (sel) {
9748 case 1:
9749 gen_helper_mftc0_ebase(t0, cpu_env);
9750 break;
9751 default:
9752 goto die;
9753 break;
9755 break;
9756 case 16:
9757 switch (sel) {
9758 case 0:
9759 case 1:
9760 case 2:
9761 case 3:
9762 case 4:
9763 case 5:
9764 case 6:
9765 case 7:
9766 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9767 break;
9768 default:
9769 goto die;
9770 break;
9772 break;
9773 case 23:
9774 switch (sel) {
9775 case 0:
9776 gen_helper_mftc0_debug(t0, cpu_env);
9777 break;
9778 default:
9779 gen_mfc0(ctx, t0, rt, sel);
9780 break;
9782 break;
9783 default:
9784 gen_mfc0(ctx, t0, rt, sel);
9786 } else switch (sel) {
9787 /* GPR registers. */
9788 case 0:
9789 gen_helper_1e0i(mftgpr, t0, rt);
9790 break;
9791 /* Auxiliary CPU registers */
9792 case 1:
9793 switch (rt) {
9794 case 0:
9795 gen_helper_1e0i(mftlo, t0, 0);
9796 break;
9797 case 1:
9798 gen_helper_1e0i(mfthi, t0, 0);
9799 break;
9800 case 2:
9801 gen_helper_1e0i(mftacx, t0, 0);
9802 break;
9803 case 4:
9804 gen_helper_1e0i(mftlo, t0, 1);
9805 break;
9806 case 5:
9807 gen_helper_1e0i(mfthi, t0, 1);
9808 break;
9809 case 6:
9810 gen_helper_1e0i(mftacx, t0, 1);
9811 break;
9812 case 8:
9813 gen_helper_1e0i(mftlo, t0, 2);
9814 break;
9815 case 9:
9816 gen_helper_1e0i(mfthi, t0, 2);
9817 break;
9818 case 10:
9819 gen_helper_1e0i(mftacx, t0, 2);
9820 break;
9821 case 12:
9822 gen_helper_1e0i(mftlo, t0, 3);
9823 break;
9824 case 13:
9825 gen_helper_1e0i(mfthi, t0, 3);
9826 break;
9827 case 14:
9828 gen_helper_1e0i(mftacx, t0, 3);
9829 break;
9830 case 16:
9831 gen_helper_mftdsp(t0, cpu_env);
9832 break;
9833 default:
9834 goto die;
9836 break;
9837 /* Floating point (COP1). */
9838 case 2:
9839 /* XXX: For now we support only a single FPU context. */
9840 if (h == 0) {
9841 TCGv_i32 fp0 = tcg_temp_new_i32();
9843 gen_load_fpr32(ctx, fp0, rt);
9844 tcg_gen_ext_i32_tl(t0, fp0);
9845 tcg_temp_free_i32(fp0);
9846 } else {
9847 TCGv_i32 fp0 = tcg_temp_new_i32();
9849 gen_load_fpr32h(ctx, fp0, rt);
9850 tcg_gen_ext_i32_tl(t0, fp0);
9851 tcg_temp_free_i32(fp0);
9853 break;
9854 case 3:
9855 /* XXX: For now we support only a single FPU context. */
9856 gen_helper_1e0i(cfc1, t0, rt);
9857 break;
9858 /* COP2: Not implemented. */
9859 case 4:
9860 case 5:
9861 /* fall through */
9862 default:
9863 goto die;
9865 trace_mips_translate_tr("mftr", rt, u, sel, h);
9866 gen_store_gpr(t0, rd);
9867 tcg_temp_free(t0);
9868 return;
9870 die:
9871 tcg_temp_free(t0);
9872 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9873 generate_exception_end(ctx, EXCP_RI);
9876 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9877 int u, int sel, int h)
9879 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9880 TCGv t0 = tcg_temp_local_new();
9882 gen_load_gpr(t0, rt);
9883 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9884 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9885 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9886 /* NOP */ ;
9887 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9888 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9889 /* NOP */ ;
9890 else if (u == 0) {
9891 switch (rd) {
9892 case 1:
9893 switch (sel) {
9894 case 1:
9895 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9896 break;
9897 case 2:
9898 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9899 break;
9900 default:
9901 goto die;
9902 break;
9904 break;
9905 case 2:
9906 switch (sel) {
9907 case 1:
9908 gen_helper_mttc0_tcstatus(cpu_env, t0);
9909 break;
9910 case 2:
9911 gen_helper_mttc0_tcbind(cpu_env, t0);
9912 break;
9913 case 3:
9914 gen_helper_mttc0_tcrestart(cpu_env, t0);
9915 break;
9916 case 4:
9917 gen_helper_mttc0_tchalt(cpu_env, t0);
9918 break;
9919 case 5:
9920 gen_helper_mttc0_tccontext(cpu_env, t0);
9921 break;
9922 case 6:
9923 gen_helper_mttc0_tcschedule(cpu_env, t0);
9924 break;
9925 case 7:
9926 gen_helper_mttc0_tcschefback(cpu_env, t0);
9927 break;
9928 default:
9929 gen_mtc0(ctx, t0, rd, sel);
9930 break;
9932 break;
9933 case 10:
9934 switch (sel) {
9935 case 0:
9936 gen_helper_mttc0_entryhi(cpu_env, t0);
9937 break;
9938 default:
9939 gen_mtc0(ctx, t0, rd, sel);
9940 break;
9942 case 12:
9943 switch (sel) {
9944 case 0:
9945 gen_helper_mttc0_status(cpu_env, t0);
9946 break;
9947 default:
9948 gen_mtc0(ctx, t0, rd, sel);
9949 break;
9951 case 13:
9952 switch (sel) {
9953 case 0:
9954 gen_helper_mttc0_cause(cpu_env, t0);
9955 break;
9956 default:
9957 goto die;
9958 break;
9960 break;
9961 case 15:
9962 switch (sel) {
9963 case 1:
9964 gen_helper_mttc0_ebase(cpu_env, t0);
9965 break;
9966 default:
9967 goto die;
9968 break;
9970 break;
9971 case 23:
9972 switch (sel) {
9973 case 0:
9974 gen_helper_mttc0_debug(cpu_env, t0);
9975 break;
9976 default:
9977 gen_mtc0(ctx, t0, rd, sel);
9978 break;
9980 break;
9981 default:
9982 gen_mtc0(ctx, t0, rd, sel);
9984 } else switch (sel) {
9985 /* GPR registers. */
9986 case 0:
9987 gen_helper_0e1i(mttgpr, t0, rd);
9988 break;
9989 /* Auxiliary CPU registers */
9990 case 1:
9991 switch (rd) {
9992 case 0:
9993 gen_helper_0e1i(mttlo, t0, 0);
9994 break;
9995 case 1:
9996 gen_helper_0e1i(mtthi, t0, 0);
9997 break;
9998 case 2:
9999 gen_helper_0e1i(mttacx, t0, 0);
10000 break;
10001 case 4:
10002 gen_helper_0e1i(mttlo, t0, 1);
10003 break;
10004 case 5:
10005 gen_helper_0e1i(mtthi, t0, 1);
10006 break;
10007 case 6:
10008 gen_helper_0e1i(mttacx, t0, 1);
10009 break;
10010 case 8:
10011 gen_helper_0e1i(mttlo, t0, 2);
10012 break;
10013 case 9:
10014 gen_helper_0e1i(mtthi, t0, 2);
10015 break;
10016 case 10:
10017 gen_helper_0e1i(mttacx, t0, 2);
10018 break;
10019 case 12:
10020 gen_helper_0e1i(mttlo, t0, 3);
10021 break;
10022 case 13:
10023 gen_helper_0e1i(mtthi, t0, 3);
10024 break;
10025 case 14:
10026 gen_helper_0e1i(mttacx, t0, 3);
10027 break;
10028 case 16:
10029 gen_helper_mttdsp(cpu_env, t0);
10030 break;
10031 default:
10032 goto die;
10034 break;
10035 /* Floating point (COP1). */
10036 case 2:
10037 /* XXX: For now we support only a single FPU context. */
10038 if (h == 0) {
10039 TCGv_i32 fp0 = tcg_temp_new_i32();
10041 tcg_gen_trunc_tl_i32(fp0, t0);
10042 gen_store_fpr32(ctx, fp0, rd);
10043 tcg_temp_free_i32(fp0);
10044 } else {
10045 TCGv_i32 fp0 = tcg_temp_new_i32();
10047 tcg_gen_trunc_tl_i32(fp0, t0);
10048 gen_store_fpr32h(ctx, fp0, rd);
10049 tcg_temp_free_i32(fp0);
10051 break;
10052 case 3:
10053 /* XXX: For now we support only a single FPU context. */
10055 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10057 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10058 tcg_temp_free_i32(fs_tmp);
10060 /* Stop translation as we may have changed hflags */
10061 ctx->base.is_jmp = DISAS_STOP;
10062 break;
10063 /* COP2: Not implemented. */
10064 case 4:
10065 case 5:
10066 /* fall through */
10067 default:
10068 goto die;
10070 trace_mips_translate_tr("mttr", rd, u, sel, h);
10071 tcg_temp_free(t0);
10072 return;
10074 die:
10075 tcg_temp_free(t0);
10076 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10077 generate_exception_end(ctx, EXCP_RI);
10080 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
10082 const char *opn = "ldst";
10084 check_cp0_enabled(ctx);
10085 switch (opc) {
10086 case OPC_MFC0:
10087 if (rt == 0) {
10088 /* Treat as NOP. */
10089 return;
10091 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10092 opn = "mfc0";
10093 break;
10094 case OPC_MTC0:
10096 TCGv t0 = tcg_temp_new();
10098 gen_load_gpr(t0, rt);
10099 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10100 tcg_temp_free(t0);
10102 opn = "mtc0";
10103 break;
10104 #if defined(TARGET_MIPS64)
10105 case OPC_DMFC0:
10106 check_insn(ctx, ISA_MIPS3);
10107 if (rt == 0) {
10108 /* Treat as NOP. */
10109 return;
10111 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10112 opn = "dmfc0";
10113 break;
10114 case OPC_DMTC0:
10115 check_insn(ctx, ISA_MIPS3);
10117 TCGv t0 = tcg_temp_new();
10119 gen_load_gpr(t0, rt);
10120 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10121 tcg_temp_free(t0);
10123 opn = "dmtc0";
10124 break;
10125 #endif
10126 case OPC_MFHC0:
10127 check_mvh(ctx);
10128 if (rt == 0) {
10129 /* Treat as NOP. */
10130 return;
10132 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10133 opn = "mfhc0";
10134 break;
10135 case OPC_MTHC0:
10136 check_mvh(ctx);
10138 TCGv t0 = tcg_temp_new();
10139 gen_load_gpr(t0, rt);
10140 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10141 tcg_temp_free(t0);
10143 opn = "mthc0";
10144 break;
10145 case OPC_MFTR:
10146 check_cp0_enabled(ctx);
10147 if (rd == 0) {
10148 /* Treat as NOP. */
10149 return;
10151 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10152 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10153 opn = "mftr";
10154 break;
10155 case OPC_MTTR:
10156 check_cp0_enabled(ctx);
10157 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10158 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10159 opn = "mttr";
10160 break;
10161 case OPC_TLBWI:
10162 opn = "tlbwi";
10163 if (!env->tlb->helper_tlbwi)
10164 goto die;
10165 gen_helper_tlbwi(cpu_env);
10166 break;
10167 case OPC_TLBINV:
10168 opn = "tlbinv";
10169 if (ctx->ie >= 2) {
10170 if (!env->tlb->helper_tlbinv) {
10171 goto die;
10173 gen_helper_tlbinv(cpu_env);
10174 } /* treat as nop if TLBINV not supported */
10175 break;
10176 case OPC_TLBINVF:
10177 opn = "tlbinvf";
10178 if (ctx->ie >= 2) {
10179 if (!env->tlb->helper_tlbinvf) {
10180 goto die;
10182 gen_helper_tlbinvf(cpu_env);
10183 } /* treat as nop if TLBINV not supported */
10184 break;
10185 case OPC_TLBWR:
10186 opn = "tlbwr";
10187 if (!env->tlb->helper_tlbwr)
10188 goto die;
10189 gen_helper_tlbwr(cpu_env);
10190 break;
10191 case OPC_TLBP:
10192 opn = "tlbp";
10193 if (!env->tlb->helper_tlbp)
10194 goto die;
10195 gen_helper_tlbp(cpu_env);
10196 break;
10197 case OPC_TLBR:
10198 opn = "tlbr";
10199 if (!env->tlb->helper_tlbr)
10200 goto die;
10201 gen_helper_tlbr(cpu_env);
10202 break;
10203 case OPC_ERET: /* OPC_ERETNC */
10204 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10205 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10206 goto die;
10207 } else {
10208 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10209 if (ctx->opcode & (1 << bit_shift)) {
10210 /* OPC_ERETNC */
10211 opn = "eretnc";
10212 check_insn(ctx, ISA_MIPS32R5);
10213 gen_helper_eretnc(cpu_env);
10214 } else {
10215 /* OPC_ERET */
10216 opn = "eret";
10217 check_insn(ctx, ISA_MIPS2);
10218 gen_helper_eret(cpu_env);
10220 ctx->base.is_jmp = DISAS_EXIT;
10222 break;
10223 case OPC_DERET:
10224 opn = "deret";
10225 check_insn(ctx, ISA_MIPS32);
10226 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10227 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10228 goto die;
10230 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10231 MIPS_INVAL(opn);
10232 generate_exception_end(ctx, EXCP_RI);
10233 } else {
10234 gen_helper_deret(cpu_env);
10235 ctx->base.is_jmp = DISAS_EXIT;
10237 break;
10238 case OPC_WAIT:
10239 opn = "wait";
10240 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10241 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10242 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10243 goto die;
10245 /* If we get an exception, we want to restart at next instruction */
10246 ctx->base.pc_next += 4;
10247 save_cpu_state(ctx, 1);
10248 ctx->base.pc_next -= 4;
10249 gen_helper_wait(cpu_env);
10250 ctx->base.is_jmp = DISAS_NORETURN;
10251 break;
10252 default:
10253 die:
10254 MIPS_INVAL(opn);
10255 generate_exception_end(ctx, EXCP_RI);
10256 return;
10258 (void)opn; /* avoid a compiler warning */
10260 #endif /* !CONFIG_USER_ONLY */
10262 /* CP1 Branches (before delay slot) */
10263 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10264 int32_t cc, int32_t offset)
10266 target_ulong btarget;
10267 TCGv_i32 t0 = tcg_temp_new_i32();
10269 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10270 generate_exception_end(ctx, EXCP_RI);
10271 goto out;
10274 if (cc != 0)
10275 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10277 btarget = ctx->base.pc_next + 4 + offset;
10279 switch (op) {
10280 case OPC_BC1F:
10281 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10282 tcg_gen_not_i32(t0, t0);
10283 tcg_gen_andi_i32(t0, t0, 1);
10284 tcg_gen_extu_i32_tl(bcond, t0);
10285 goto not_likely;
10286 case OPC_BC1FL:
10287 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10288 tcg_gen_not_i32(t0, t0);
10289 tcg_gen_andi_i32(t0, t0, 1);
10290 tcg_gen_extu_i32_tl(bcond, t0);
10291 goto likely;
10292 case OPC_BC1T:
10293 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10294 tcg_gen_andi_i32(t0, t0, 1);
10295 tcg_gen_extu_i32_tl(bcond, t0);
10296 goto not_likely;
10297 case OPC_BC1TL:
10298 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10299 tcg_gen_andi_i32(t0, t0, 1);
10300 tcg_gen_extu_i32_tl(bcond, t0);
10301 likely:
10302 ctx->hflags |= MIPS_HFLAG_BL;
10303 break;
10304 case OPC_BC1FANY2:
10306 TCGv_i32 t1 = tcg_temp_new_i32();
10307 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10308 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10309 tcg_gen_nand_i32(t0, t0, t1);
10310 tcg_temp_free_i32(t1);
10311 tcg_gen_andi_i32(t0, t0, 1);
10312 tcg_gen_extu_i32_tl(bcond, t0);
10314 goto not_likely;
10315 case OPC_BC1TANY2:
10317 TCGv_i32 t1 = tcg_temp_new_i32();
10318 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10319 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10320 tcg_gen_or_i32(t0, t0, t1);
10321 tcg_temp_free_i32(t1);
10322 tcg_gen_andi_i32(t0, t0, 1);
10323 tcg_gen_extu_i32_tl(bcond, t0);
10325 goto not_likely;
10326 case OPC_BC1FANY4:
10328 TCGv_i32 t1 = tcg_temp_new_i32();
10329 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10330 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10331 tcg_gen_and_i32(t0, t0, t1);
10332 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10333 tcg_gen_and_i32(t0, t0, t1);
10334 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10335 tcg_gen_nand_i32(t0, t0, t1);
10336 tcg_temp_free_i32(t1);
10337 tcg_gen_andi_i32(t0, t0, 1);
10338 tcg_gen_extu_i32_tl(bcond, t0);
10340 goto not_likely;
10341 case OPC_BC1TANY4:
10343 TCGv_i32 t1 = tcg_temp_new_i32();
10344 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10345 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10346 tcg_gen_or_i32(t0, t0, t1);
10347 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10348 tcg_gen_or_i32(t0, t0, t1);
10349 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10350 tcg_gen_or_i32(t0, t0, t1);
10351 tcg_temp_free_i32(t1);
10352 tcg_gen_andi_i32(t0, t0, 1);
10353 tcg_gen_extu_i32_tl(bcond, t0);
10355 not_likely:
10356 ctx->hflags |= MIPS_HFLAG_BC;
10357 break;
10358 default:
10359 MIPS_INVAL("cp1 cond branch");
10360 generate_exception_end(ctx, EXCP_RI);
10361 goto out;
10363 ctx->btarget = btarget;
10364 ctx->hflags |= MIPS_HFLAG_BDS32;
10365 out:
10366 tcg_temp_free_i32(t0);
10369 /* R6 CP1 Branches */
10370 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10371 int32_t ft, int32_t offset,
10372 int delayslot_size)
10374 target_ulong btarget;
10375 TCGv_i64 t0 = tcg_temp_new_i64();
10377 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10378 #ifdef MIPS_DEBUG_DISAS
10379 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10380 "\n", ctx->base.pc_next);
10381 #endif
10382 generate_exception_end(ctx, EXCP_RI);
10383 goto out;
10386 gen_load_fpr64(ctx, t0, ft);
10387 tcg_gen_andi_i64(t0, t0, 1);
10389 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10391 switch (op) {
10392 case OPC_BC1EQZ:
10393 tcg_gen_xori_i64(t0, t0, 1);
10394 ctx->hflags |= MIPS_HFLAG_BC;
10395 break;
10396 case OPC_BC1NEZ:
10397 /* t0 already set */
10398 ctx->hflags |= MIPS_HFLAG_BC;
10399 break;
10400 default:
10401 MIPS_INVAL("cp1 cond branch");
10402 generate_exception_end(ctx, EXCP_RI);
10403 goto out;
10406 tcg_gen_trunc_i64_tl(bcond, t0);
10408 ctx->btarget = btarget;
10410 switch (delayslot_size) {
10411 case 2:
10412 ctx->hflags |= MIPS_HFLAG_BDS16;
10413 break;
10414 case 4:
10415 ctx->hflags |= MIPS_HFLAG_BDS32;
10416 break;
10419 out:
10420 tcg_temp_free_i64(t0);
10423 /* Coprocessor 1 (FPU) */
10425 #define FOP(func, fmt) (((fmt) << 21) | (func))
10427 enum fopcode {
10428 OPC_ADD_S = FOP(0, FMT_S),
10429 OPC_SUB_S = FOP(1, FMT_S),
10430 OPC_MUL_S = FOP(2, FMT_S),
10431 OPC_DIV_S = FOP(3, FMT_S),
10432 OPC_SQRT_S = FOP(4, FMT_S),
10433 OPC_ABS_S = FOP(5, FMT_S),
10434 OPC_MOV_S = FOP(6, FMT_S),
10435 OPC_NEG_S = FOP(7, FMT_S),
10436 OPC_ROUND_L_S = FOP(8, FMT_S),
10437 OPC_TRUNC_L_S = FOP(9, FMT_S),
10438 OPC_CEIL_L_S = FOP(10, FMT_S),
10439 OPC_FLOOR_L_S = FOP(11, FMT_S),
10440 OPC_ROUND_W_S = FOP(12, FMT_S),
10441 OPC_TRUNC_W_S = FOP(13, FMT_S),
10442 OPC_CEIL_W_S = FOP(14, FMT_S),
10443 OPC_FLOOR_W_S = FOP(15, FMT_S),
10444 OPC_SEL_S = FOP(16, FMT_S),
10445 OPC_MOVCF_S = FOP(17, FMT_S),
10446 OPC_MOVZ_S = FOP(18, FMT_S),
10447 OPC_MOVN_S = FOP(19, FMT_S),
10448 OPC_SELEQZ_S = FOP(20, FMT_S),
10449 OPC_RECIP_S = FOP(21, FMT_S),
10450 OPC_RSQRT_S = FOP(22, FMT_S),
10451 OPC_SELNEZ_S = FOP(23, FMT_S),
10452 OPC_MADDF_S = FOP(24, FMT_S),
10453 OPC_MSUBF_S = FOP(25, FMT_S),
10454 OPC_RINT_S = FOP(26, FMT_S),
10455 OPC_CLASS_S = FOP(27, FMT_S),
10456 OPC_MIN_S = FOP(28, FMT_S),
10457 OPC_RECIP2_S = FOP(28, FMT_S),
10458 OPC_MINA_S = FOP(29, FMT_S),
10459 OPC_RECIP1_S = FOP(29, FMT_S),
10460 OPC_MAX_S = FOP(30, FMT_S),
10461 OPC_RSQRT1_S = FOP(30, FMT_S),
10462 OPC_MAXA_S = FOP(31, FMT_S),
10463 OPC_RSQRT2_S = FOP(31, FMT_S),
10464 OPC_CVT_D_S = FOP(33, FMT_S),
10465 OPC_CVT_W_S = FOP(36, FMT_S),
10466 OPC_CVT_L_S = FOP(37, FMT_S),
10467 OPC_CVT_PS_S = FOP(38, FMT_S),
10468 OPC_CMP_F_S = FOP (48, FMT_S),
10469 OPC_CMP_UN_S = FOP (49, FMT_S),
10470 OPC_CMP_EQ_S = FOP (50, FMT_S),
10471 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10472 OPC_CMP_OLT_S = FOP (52, FMT_S),
10473 OPC_CMP_ULT_S = FOP (53, FMT_S),
10474 OPC_CMP_OLE_S = FOP (54, FMT_S),
10475 OPC_CMP_ULE_S = FOP (55, FMT_S),
10476 OPC_CMP_SF_S = FOP (56, FMT_S),
10477 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10478 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10479 OPC_CMP_NGL_S = FOP (59, FMT_S),
10480 OPC_CMP_LT_S = FOP (60, FMT_S),
10481 OPC_CMP_NGE_S = FOP (61, FMT_S),
10482 OPC_CMP_LE_S = FOP (62, FMT_S),
10483 OPC_CMP_NGT_S = FOP (63, FMT_S),
10485 OPC_ADD_D = FOP(0, FMT_D),
10486 OPC_SUB_D = FOP(1, FMT_D),
10487 OPC_MUL_D = FOP(2, FMT_D),
10488 OPC_DIV_D = FOP(3, FMT_D),
10489 OPC_SQRT_D = FOP(4, FMT_D),
10490 OPC_ABS_D = FOP(5, FMT_D),
10491 OPC_MOV_D = FOP(6, FMT_D),
10492 OPC_NEG_D = FOP(7, FMT_D),
10493 OPC_ROUND_L_D = FOP(8, FMT_D),
10494 OPC_TRUNC_L_D = FOP(9, FMT_D),
10495 OPC_CEIL_L_D = FOP(10, FMT_D),
10496 OPC_FLOOR_L_D = FOP(11, FMT_D),
10497 OPC_ROUND_W_D = FOP(12, FMT_D),
10498 OPC_TRUNC_W_D = FOP(13, FMT_D),
10499 OPC_CEIL_W_D = FOP(14, FMT_D),
10500 OPC_FLOOR_W_D = FOP(15, FMT_D),
10501 OPC_SEL_D = FOP(16, FMT_D),
10502 OPC_MOVCF_D = FOP(17, FMT_D),
10503 OPC_MOVZ_D = FOP(18, FMT_D),
10504 OPC_MOVN_D = FOP(19, FMT_D),
10505 OPC_SELEQZ_D = FOP(20, FMT_D),
10506 OPC_RECIP_D = FOP(21, FMT_D),
10507 OPC_RSQRT_D = FOP(22, FMT_D),
10508 OPC_SELNEZ_D = FOP(23, FMT_D),
10509 OPC_MADDF_D = FOP(24, FMT_D),
10510 OPC_MSUBF_D = FOP(25, FMT_D),
10511 OPC_RINT_D = FOP(26, FMT_D),
10512 OPC_CLASS_D = FOP(27, FMT_D),
10513 OPC_MIN_D = FOP(28, FMT_D),
10514 OPC_RECIP2_D = FOP(28, FMT_D),
10515 OPC_MINA_D = FOP(29, FMT_D),
10516 OPC_RECIP1_D = FOP(29, FMT_D),
10517 OPC_MAX_D = FOP(30, FMT_D),
10518 OPC_RSQRT1_D = FOP(30, FMT_D),
10519 OPC_MAXA_D = FOP(31, FMT_D),
10520 OPC_RSQRT2_D = FOP(31, FMT_D),
10521 OPC_CVT_S_D = FOP(32, FMT_D),
10522 OPC_CVT_W_D = FOP(36, FMT_D),
10523 OPC_CVT_L_D = FOP(37, FMT_D),
10524 OPC_CMP_F_D = FOP (48, FMT_D),
10525 OPC_CMP_UN_D = FOP (49, FMT_D),
10526 OPC_CMP_EQ_D = FOP (50, FMT_D),
10527 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10528 OPC_CMP_OLT_D = FOP (52, FMT_D),
10529 OPC_CMP_ULT_D = FOP (53, FMT_D),
10530 OPC_CMP_OLE_D = FOP (54, FMT_D),
10531 OPC_CMP_ULE_D = FOP (55, FMT_D),
10532 OPC_CMP_SF_D = FOP (56, FMT_D),
10533 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10534 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10535 OPC_CMP_NGL_D = FOP (59, FMT_D),
10536 OPC_CMP_LT_D = FOP (60, FMT_D),
10537 OPC_CMP_NGE_D = FOP (61, FMT_D),
10538 OPC_CMP_LE_D = FOP (62, FMT_D),
10539 OPC_CMP_NGT_D = FOP (63, FMT_D),
10541 OPC_CVT_S_W = FOP(32, FMT_W),
10542 OPC_CVT_D_W = FOP(33, FMT_W),
10543 OPC_CVT_S_L = FOP(32, FMT_L),
10544 OPC_CVT_D_L = FOP(33, FMT_L),
10545 OPC_CVT_PS_PW = FOP(38, FMT_W),
10547 OPC_ADD_PS = FOP(0, FMT_PS),
10548 OPC_SUB_PS = FOP(1, FMT_PS),
10549 OPC_MUL_PS = FOP(2, FMT_PS),
10550 OPC_DIV_PS = FOP(3, FMT_PS),
10551 OPC_ABS_PS = FOP(5, FMT_PS),
10552 OPC_MOV_PS = FOP(6, FMT_PS),
10553 OPC_NEG_PS = FOP(7, FMT_PS),
10554 OPC_MOVCF_PS = FOP(17, FMT_PS),
10555 OPC_MOVZ_PS = FOP(18, FMT_PS),
10556 OPC_MOVN_PS = FOP(19, FMT_PS),
10557 OPC_ADDR_PS = FOP(24, FMT_PS),
10558 OPC_MULR_PS = FOP(26, FMT_PS),
10559 OPC_RECIP2_PS = FOP(28, FMT_PS),
10560 OPC_RECIP1_PS = FOP(29, FMT_PS),
10561 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10562 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10564 OPC_CVT_S_PU = FOP(32, FMT_PS),
10565 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10566 OPC_CVT_S_PL = FOP(40, FMT_PS),
10567 OPC_PLL_PS = FOP(44, FMT_PS),
10568 OPC_PLU_PS = FOP(45, FMT_PS),
10569 OPC_PUL_PS = FOP(46, FMT_PS),
10570 OPC_PUU_PS = FOP(47, FMT_PS),
10571 OPC_CMP_F_PS = FOP (48, FMT_PS),
10572 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10573 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10574 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10575 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10576 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10577 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10578 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10579 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10580 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10581 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10582 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10583 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10584 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10585 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10586 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10589 enum r6_f_cmp_op {
10590 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10591 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10592 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10593 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10594 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10595 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10596 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10597 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10598 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10599 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10600 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10601 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10602 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10603 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10604 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10605 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10606 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10607 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10608 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10609 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10610 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10611 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10613 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10614 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10615 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10616 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10617 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10618 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10619 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10620 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10621 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10622 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10623 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10624 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10625 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10626 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10627 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10628 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10629 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10630 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10631 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10632 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10633 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10634 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10636 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10638 TCGv t0 = tcg_temp_new();
10640 switch (opc) {
10641 case OPC_MFC1:
10643 TCGv_i32 fp0 = tcg_temp_new_i32();
10645 gen_load_fpr32(ctx, fp0, fs);
10646 tcg_gen_ext_i32_tl(t0, fp0);
10647 tcg_temp_free_i32(fp0);
10649 gen_store_gpr(t0, rt);
10650 break;
10651 case OPC_MTC1:
10652 gen_load_gpr(t0, rt);
10654 TCGv_i32 fp0 = tcg_temp_new_i32();
10656 tcg_gen_trunc_tl_i32(fp0, t0);
10657 gen_store_fpr32(ctx, fp0, fs);
10658 tcg_temp_free_i32(fp0);
10660 break;
10661 case OPC_CFC1:
10662 gen_helper_1e0i(cfc1, t0, fs);
10663 gen_store_gpr(t0, rt);
10664 break;
10665 case OPC_CTC1:
10666 gen_load_gpr(t0, rt);
10667 save_cpu_state(ctx, 0);
10669 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10671 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10672 tcg_temp_free_i32(fs_tmp);
10674 /* Stop translation as we may have changed hflags */
10675 ctx->base.is_jmp = DISAS_STOP;
10676 break;
10677 #if defined(TARGET_MIPS64)
10678 case OPC_DMFC1:
10679 gen_load_fpr64(ctx, t0, fs);
10680 gen_store_gpr(t0, rt);
10681 break;
10682 case OPC_DMTC1:
10683 gen_load_gpr(t0, rt);
10684 gen_store_fpr64(ctx, t0, fs);
10685 break;
10686 #endif
10687 case OPC_MFHC1:
10689 TCGv_i32 fp0 = tcg_temp_new_i32();
10691 gen_load_fpr32h(ctx, fp0, fs);
10692 tcg_gen_ext_i32_tl(t0, fp0);
10693 tcg_temp_free_i32(fp0);
10695 gen_store_gpr(t0, rt);
10696 break;
10697 case OPC_MTHC1:
10698 gen_load_gpr(t0, rt);
10700 TCGv_i32 fp0 = tcg_temp_new_i32();
10702 tcg_gen_trunc_tl_i32(fp0, t0);
10703 gen_store_fpr32h(ctx, fp0, fs);
10704 tcg_temp_free_i32(fp0);
10706 break;
10707 default:
10708 MIPS_INVAL("cp1 move");
10709 generate_exception_end(ctx, EXCP_RI);
10710 goto out;
10713 out:
10714 tcg_temp_free(t0);
10717 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10719 TCGLabel *l1;
10720 TCGCond cond;
10721 TCGv_i32 t0;
10723 if (rd == 0) {
10724 /* Treat as NOP. */
10725 return;
10728 if (tf)
10729 cond = TCG_COND_EQ;
10730 else
10731 cond = TCG_COND_NE;
10733 l1 = gen_new_label();
10734 t0 = tcg_temp_new_i32();
10735 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10736 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10737 tcg_temp_free_i32(t0);
10738 if (rs == 0) {
10739 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10740 } else {
10741 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10743 gen_set_label(l1);
10746 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10747 int tf)
10749 int cond;
10750 TCGv_i32 t0 = tcg_temp_new_i32();
10751 TCGLabel *l1 = gen_new_label();
10753 if (tf)
10754 cond = TCG_COND_EQ;
10755 else
10756 cond = TCG_COND_NE;
10758 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10759 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10760 gen_load_fpr32(ctx, t0, fs);
10761 gen_store_fpr32(ctx, t0, fd);
10762 gen_set_label(l1);
10763 tcg_temp_free_i32(t0);
10766 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10768 int cond;
10769 TCGv_i32 t0 = tcg_temp_new_i32();
10770 TCGv_i64 fp0;
10771 TCGLabel *l1 = gen_new_label();
10773 if (tf)
10774 cond = TCG_COND_EQ;
10775 else
10776 cond = TCG_COND_NE;
10778 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10779 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10780 tcg_temp_free_i32(t0);
10781 fp0 = tcg_temp_new_i64();
10782 gen_load_fpr64(ctx, fp0, fs);
10783 gen_store_fpr64(ctx, fp0, fd);
10784 tcg_temp_free_i64(fp0);
10785 gen_set_label(l1);
10788 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10789 int cc, int tf)
10791 int cond;
10792 TCGv_i32 t0 = tcg_temp_new_i32();
10793 TCGLabel *l1 = gen_new_label();
10794 TCGLabel *l2 = gen_new_label();
10796 if (tf)
10797 cond = TCG_COND_EQ;
10798 else
10799 cond = TCG_COND_NE;
10801 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10802 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10803 gen_load_fpr32(ctx, t0, fs);
10804 gen_store_fpr32(ctx, t0, fd);
10805 gen_set_label(l1);
10807 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10808 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10809 gen_load_fpr32h(ctx, t0, fs);
10810 gen_store_fpr32h(ctx, t0, fd);
10811 tcg_temp_free_i32(t0);
10812 gen_set_label(l2);
10815 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10816 int fs)
10818 TCGv_i32 t1 = tcg_const_i32(0);
10819 TCGv_i32 fp0 = tcg_temp_new_i32();
10820 TCGv_i32 fp1 = tcg_temp_new_i32();
10821 TCGv_i32 fp2 = tcg_temp_new_i32();
10822 gen_load_fpr32(ctx, fp0, fd);
10823 gen_load_fpr32(ctx, fp1, ft);
10824 gen_load_fpr32(ctx, fp2, fs);
10826 switch (op1) {
10827 case OPC_SEL_S:
10828 tcg_gen_andi_i32(fp0, fp0, 1);
10829 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10830 break;
10831 case OPC_SELEQZ_S:
10832 tcg_gen_andi_i32(fp1, fp1, 1);
10833 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10834 break;
10835 case OPC_SELNEZ_S:
10836 tcg_gen_andi_i32(fp1, fp1, 1);
10837 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10838 break;
10839 default:
10840 MIPS_INVAL("gen_sel_s");
10841 generate_exception_end(ctx, EXCP_RI);
10842 break;
10845 gen_store_fpr32(ctx, fp0, fd);
10846 tcg_temp_free_i32(fp2);
10847 tcg_temp_free_i32(fp1);
10848 tcg_temp_free_i32(fp0);
10849 tcg_temp_free_i32(t1);
10852 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10853 int fs)
10855 TCGv_i64 t1 = tcg_const_i64(0);
10856 TCGv_i64 fp0 = tcg_temp_new_i64();
10857 TCGv_i64 fp1 = tcg_temp_new_i64();
10858 TCGv_i64 fp2 = tcg_temp_new_i64();
10859 gen_load_fpr64(ctx, fp0, fd);
10860 gen_load_fpr64(ctx, fp1, ft);
10861 gen_load_fpr64(ctx, fp2, fs);
10863 switch (op1) {
10864 case OPC_SEL_D:
10865 tcg_gen_andi_i64(fp0, fp0, 1);
10866 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10867 break;
10868 case OPC_SELEQZ_D:
10869 tcg_gen_andi_i64(fp1, fp1, 1);
10870 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10871 break;
10872 case OPC_SELNEZ_D:
10873 tcg_gen_andi_i64(fp1, fp1, 1);
10874 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10875 break;
10876 default:
10877 MIPS_INVAL("gen_sel_d");
10878 generate_exception_end(ctx, EXCP_RI);
10879 break;
10882 gen_store_fpr64(ctx, fp0, fd);
10883 tcg_temp_free_i64(fp2);
10884 tcg_temp_free_i64(fp1);
10885 tcg_temp_free_i64(fp0);
10886 tcg_temp_free_i64(t1);
10889 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10890 int ft, int fs, int fd, int cc)
10892 uint32_t func = ctx->opcode & 0x3f;
10893 switch (op1) {
10894 case OPC_ADD_S:
10896 TCGv_i32 fp0 = tcg_temp_new_i32();
10897 TCGv_i32 fp1 = tcg_temp_new_i32();
10899 gen_load_fpr32(ctx, fp0, fs);
10900 gen_load_fpr32(ctx, fp1, ft);
10901 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10902 tcg_temp_free_i32(fp1);
10903 gen_store_fpr32(ctx, fp0, fd);
10904 tcg_temp_free_i32(fp0);
10906 break;
10907 case OPC_SUB_S:
10909 TCGv_i32 fp0 = tcg_temp_new_i32();
10910 TCGv_i32 fp1 = tcg_temp_new_i32();
10912 gen_load_fpr32(ctx, fp0, fs);
10913 gen_load_fpr32(ctx, fp1, ft);
10914 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10915 tcg_temp_free_i32(fp1);
10916 gen_store_fpr32(ctx, fp0, fd);
10917 tcg_temp_free_i32(fp0);
10919 break;
10920 case OPC_MUL_S:
10922 TCGv_i32 fp0 = tcg_temp_new_i32();
10923 TCGv_i32 fp1 = tcg_temp_new_i32();
10925 gen_load_fpr32(ctx, fp0, fs);
10926 gen_load_fpr32(ctx, fp1, ft);
10927 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10928 tcg_temp_free_i32(fp1);
10929 gen_store_fpr32(ctx, fp0, fd);
10930 tcg_temp_free_i32(fp0);
10932 break;
10933 case OPC_DIV_S:
10935 TCGv_i32 fp0 = tcg_temp_new_i32();
10936 TCGv_i32 fp1 = tcg_temp_new_i32();
10938 gen_load_fpr32(ctx, fp0, fs);
10939 gen_load_fpr32(ctx, fp1, ft);
10940 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10941 tcg_temp_free_i32(fp1);
10942 gen_store_fpr32(ctx, fp0, fd);
10943 tcg_temp_free_i32(fp0);
10945 break;
10946 case OPC_SQRT_S:
10948 TCGv_i32 fp0 = tcg_temp_new_i32();
10950 gen_load_fpr32(ctx, fp0, fs);
10951 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10952 gen_store_fpr32(ctx, fp0, fd);
10953 tcg_temp_free_i32(fp0);
10955 break;
10956 case OPC_ABS_S:
10958 TCGv_i32 fp0 = tcg_temp_new_i32();
10960 gen_load_fpr32(ctx, fp0, fs);
10961 if (ctx->abs2008) {
10962 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10963 } else {
10964 gen_helper_float_abs_s(fp0, fp0);
10966 gen_store_fpr32(ctx, fp0, fd);
10967 tcg_temp_free_i32(fp0);
10969 break;
10970 case OPC_MOV_S:
10972 TCGv_i32 fp0 = tcg_temp_new_i32();
10974 gen_load_fpr32(ctx, fp0, fs);
10975 gen_store_fpr32(ctx, fp0, fd);
10976 tcg_temp_free_i32(fp0);
10978 break;
10979 case OPC_NEG_S:
10981 TCGv_i32 fp0 = tcg_temp_new_i32();
10983 gen_load_fpr32(ctx, fp0, fs);
10984 if (ctx->abs2008) {
10985 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10986 } else {
10987 gen_helper_float_chs_s(fp0, fp0);
10989 gen_store_fpr32(ctx, fp0, fd);
10990 tcg_temp_free_i32(fp0);
10992 break;
10993 case OPC_ROUND_L_S:
10994 check_cp1_64bitmode(ctx);
10996 TCGv_i32 fp32 = tcg_temp_new_i32();
10997 TCGv_i64 fp64 = tcg_temp_new_i64();
10999 gen_load_fpr32(ctx, fp32, fs);
11000 if (ctx->nan2008) {
11001 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11002 } else {
11003 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11005 tcg_temp_free_i32(fp32);
11006 gen_store_fpr64(ctx, fp64, fd);
11007 tcg_temp_free_i64(fp64);
11009 break;
11010 case OPC_TRUNC_L_S:
11011 check_cp1_64bitmode(ctx);
11013 TCGv_i32 fp32 = tcg_temp_new_i32();
11014 TCGv_i64 fp64 = tcg_temp_new_i64();
11016 gen_load_fpr32(ctx, fp32, fs);
11017 if (ctx->nan2008) {
11018 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11019 } else {
11020 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11022 tcg_temp_free_i32(fp32);
11023 gen_store_fpr64(ctx, fp64, fd);
11024 tcg_temp_free_i64(fp64);
11026 break;
11027 case OPC_CEIL_L_S:
11028 check_cp1_64bitmode(ctx);
11030 TCGv_i32 fp32 = tcg_temp_new_i32();
11031 TCGv_i64 fp64 = tcg_temp_new_i64();
11033 gen_load_fpr32(ctx, fp32, fs);
11034 if (ctx->nan2008) {
11035 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11036 } else {
11037 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11039 tcg_temp_free_i32(fp32);
11040 gen_store_fpr64(ctx, fp64, fd);
11041 tcg_temp_free_i64(fp64);
11043 break;
11044 case OPC_FLOOR_L_S:
11045 check_cp1_64bitmode(ctx);
11047 TCGv_i32 fp32 = tcg_temp_new_i32();
11048 TCGv_i64 fp64 = tcg_temp_new_i64();
11050 gen_load_fpr32(ctx, fp32, fs);
11051 if (ctx->nan2008) {
11052 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11053 } else {
11054 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11056 tcg_temp_free_i32(fp32);
11057 gen_store_fpr64(ctx, fp64, fd);
11058 tcg_temp_free_i64(fp64);
11060 break;
11061 case OPC_ROUND_W_S:
11063 TCGv_i32 fp0 = tcg_temp_new_i32();
11065 gen_load_fpr32(ctx, fp0, fs);
11066 if (ctx->nan2008) {
11067 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11068 } else {
11069 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11071 gen_store_fpr32(ctx, fp0, fd);
11072 tcg_temp_free_i32(fp0);
11074 break;
11075 case OPC_TRUNC_W_S:
11077 TCGv_i32 fp0 = tcg_temp_new_i32();
11079 gen_load_fpr32(ctx, fp0, fs);
11080 if (ctx->nan2008) {
11081 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11082 } else {
11083 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11085 gen_store_fpr32(ctx, fp0, fd);
11086 tcg_temp_free_i32(fp0);
11088 break;
11089 case OPC_CEIL_W_S:
11091 TCGv_i32 fp0 = tcg_temp_new_i32();
11093 gen_load_fpr32(ctx, fp0, fs);
11094 if (ctx->nan2008) {
11095 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11096 } else {
11097 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11099 gen_store_fpr32(ctx, fp0, fd);
11100 tcg_temp_free_i32(fp0);
11102 break;
11103 case OPC_FLOOR_W_S:
11105 TCGv_i32 fp0 = tcg_temp_new_i32();
11107 gen_load_fpr32(ctx, fp0, fs);
11108 if (ctx->nan2008) {
11109 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11110 } else {
11111 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11113 gen_store_fpr32(ctx, fp0, fd);
11114 tcg_temp_free_i32(fp0);
11116 break;
11117 case OPC_SEL_S:
11118 check_insn(ctx, ISA_MIPS32R6);
11119 gen_sel_s(ctx, op1, fd, ft, fs);
11120 break;
11121 case OPC_SELEQZ_S:
11122 check_insn(ctx, ISA_MIPS32R6);
11123 gen_sel_s(ctx, op1, fd, ft, fs);
11124 break;
11125 case OPC_SELNEZ_S:
11126 check_insn(ctx, ISA_MIPS32R6);
11127 gen_sel_s(ctx, op1, fd, ft, fs);
11128 break;
11129 case OPC_MOVCF_S:
11130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11131 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11132 break;
11133 case OPC_MOVZ_S:
11134 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11136 TCGLabel *l1 = gen_new_label();
11137 TCGv_i32 fp0;
11139 if (ft != 0) {
11140 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11142 fp0 = tcg_temp_new_i32();
11143 gen_load_fpr32(ctx, fp0, fs);
11144 gen_store_fpr32(ctx, fp0, fd);
11145 tcg_temp_free_i32(fp0);
11146 gen_set_label(l1);
11148 break;
11149 case OPC_MOVN_S:
11150 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11152 TCGLabel *l1 = gen_new_label();
11153 TCGv_i32 fp0;
11155 if (ft != 0) {
11156 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11157 fp0 = tcg_temp_new_i32();
11158 gen_load_fpr32(ctx, fp0, fs);
11159 gen_store_fpr32(ctx, fp0, fd);
11160 tcg_temp_free_i32(fp0);
11161 gen_set_label(l1);
11164 break;
11165 case OPC_RECIP_S:
11167 TCGv_i32 fp0 = tcg_temp_new_i32();
11169 gen_load_fpr32(ctx, fp0, fs);
11170 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11171 gen_store_fpr32(ctx, fp0, fd);
11172 tcg_temp_free_i32(fp0);
11174 break;
11175 case OPC_RSQRT_S:
11177 TCGv_i32 fp0 = tcg_temp_new_i32();
11179 gen_load_fpr32(ctx, fp0, fs);
11180 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11181 gen_store_fpr32(ctx, fp0, fd);
11182 tcg_temp_free_i32(fp0);
11184 break;
11185 case OPC_MADDF_S:
11186 check_insn(ctx, ISA_MIPS32R6);
11188 TCGv_i32 fp0 = tcg_temp_new_i32();
11189 TCGv_i32 fp1 = tcg_temp_new_i32();
11190 TCGv_i32 fp2 = tcg_temp_new_i32();
11191 gen_load_fpr32(ctx, fp0, fs);
11192 gen_load_fpr32(ctx, fp1, ft);
11193 gen_load_fpr32(ctx, fp2, fd);
11194 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11195 gen_store_fpr32(ctx, fp2, fd);
11196 tcg_temp_free_i32(fp2);
11197 tcg_temp_free_i32(fp1);
11198 tcg_temp_free_i32(fp0);
11200 break;
11201 case OPC_MSUBF_S:
11202 check_insn(ctx, ISA_MIPS32R6);
11204 TCGv_i32 fp0 = tcg_temp_new_i32();
11205 TCGv_i32 fp1 = tcg_temp_new_i32();
11206 TCGv_i32 fp2 = tcg_temp_new_i32();
11207 gen_load_fpr32(ctx, fp0, fs);
11208 gen_load_fpr32(ctx, fp1, ft);
11209 gen_load_fpr32(ctx, fp2, fd);
11210 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11211 gen_store_fpr32(ctx, fp2, fd);
11212 tcg_temp_free_i32(fp2);
11213 tcg_temp_free_i32(fp1);
11214 tcg_temp_free_i32(fp0);
11216 break;
11217 case OPC_RINT_S:
11218 check_insn(ctx, ISA_MIPS32R6);
11220 TCGv_i32 fp0 = tcg_temp_new_i32();
11221 gen_load_fpr32(ctx, fp0, fs);
11222 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11223 gen_store_fpr32(ctx, fp0, fd);
11224 tcg_temp_free_i32(fp0);
11226 break;
11227 case OPC_CLASS_S:
11228 check_insn(ctx, ISA_MIPS32R6);
11230 TCGv_i32 fp0 = tcg_temp_new_i32();
11231 gen_load_fpr32(ctx, fp0, fs);
11232 gen_helper_float_class_s(fp0, cpu_env, fp0);
11233 gen_store_fpr32(ctx, fp0, fd);
11234 tcg_temp_free_i32(fp0);
11236 break;
11237 case OPC_MIN_S: /* OPC_RECIP2_S */
11238 if (ctx->insn_flags & ISA_MIPS32R6) {
11239 /* OPC_MIN_S */
11240 TCGv_i32 fp0 = tcg_temp_new_i32();
11241 TCGv_i32 fp1 = tcg_temp_new_i32();
11242 TCGv_i32 fp2 = tcg_temp_new_i32();
11243 gen_load_fpr32(ctx, fp0, fs);
11244 gen_load_fpr32(ctx, fp1, ft);
11245 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11246 gen_store_fpr32(ctx, fp2, fd);
11247 tcg_temp_free_i32(fp2);
11248 tcg_temp_free_i32(fp1);
11249 tcg_temp_free_i32(fp0);
11250 } else {
11251 /* OPC_RECIP2_S */
11252 check_cp1_64bitmode(ctx);
11254 TCGv_i32 fp0 = tcg_temp_new_i32();
11255 TCGv_i32 fp1 = tcg_temp_new_i32();
11257 gen_load_fpr32(ctx, fp0, fs);
11258 gen_load_fpr32(ctx, fp1, ft);
11259 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11260 tcg_temp_free_i32(fp1);
11261 gen_store_fpr32(ctx, fp0, fd);
11262 tcg_temp_free_i32(fp0);
11265 break;
11266 case OPC_MINA_S: /* OPC_RECIP1_S */
11267 if (ctx->insn_flags & ISA_MIPS32R6) {
11268 /* OPC_MINA_S */
11269 TCGv_i32 fp0 = tcg_temp_new_i32();
11270 TCGv_i32 fp1 = tcg_temp_new_i32();
11271 TCGv_i32 fp2 = tcg_temp_new_i32();
11272 gen_load_fpr32(ctx, fp0, fs);
11273 gen_load_fpr32(ctx, fp1, ft);
11274 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11275 gen_store_fpr32(ctx, fp2, fd);
11276 tcg_temp_free_i32(fp2);
11277 tcg_temp_free_i32(fp1);
11278 tcg_temp_free_i32(fp0);
11279 } else {
11280 /* OPC_RECIP1_S */
11281 check_cp1_64bitmode(ctx);
11283 TCGv_i32 fp0 = tcg_temp_new_i32();
11285 gen_load_fpr32(ctx, fp0, fs);
11286 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11287 gen_store_fpr32(ctx, fp0, fd);
11288 tcg_temp_free_i32(fp0);
11291 break;
11292 case OPC_MAX_S: /* OPC_RSQRT1_S */
11293 if (ctx->insn_flags & ISA_MIPS32R6) {
11294 /* OPC_MAX_S */
11295 TCGv_i32 fp0 = tcg_temp_new_i32();
11296 TCGv_i32 fp1 = tcg_temp_new_i32();
11297 gen_load_fpr32(ctx, fp0, fs);
11298 gen_load_fpr32(ctx, fp1, ft);
11299 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11300 gen_store_fpr32(ctx, fp1, fd);
11301 tcg_temp_free_i32(fp1);
11302 tcg_temp_free_i32(fp0);
11303 } else {
11304 /* OPC_RSQRT1_S */
11305 check_cp1_64bitmode(ctx);
11307 TCGv_i32 fp0 = tcg_temp_new_i32();
11309 gen_load_fpr32(ctx, fp0, fs);
11310 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11311 gen_store_fpr32(ctx, fp0, fd);
11312 tcg_temp_free_i32(fp0);
11315 break;
11316 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11317 if (ctx->insn_flags & ISA_MIPS32R6) {
11318 /* OPC_MAXA_S */
11319 TCGv_i32 fp0 = tcg_temp_new_i32();
11320 TCGv_i32 fp1 = tcg_temp_new_i32();
11321 gen_load_fpr32(ctx, fp0, fs);
11322 gen_load_fpr32(ctx, fp1, ft);
11323 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11324 gen_store_fpr32(ctx, fp1, fd);
11325 tcg_temp_free_i32(fp1);
11326 tcg_temp_free_i32(fp0);
11327 } else {
11328 /* OPC_RSQRT2_S */
11329 check_cp1_64bitmode(ctx);
11331 TCGv_i32 fp0 = tcg_temp_new_i32();
11332 TCGv_i32 fp1 = tcg_temp_new_i32();
11334 gen_load_fpr32(ctx, fp0, fs);
11335 gen_load_fpr32(ctx, fp1, ft);
11336 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11337 tcg_temp_free_i32(fp1);
11338 gen_store_fpr32(ctx, fp0, fd);
11339 tcg_temp_free_i32(fp0);
11342 break;
11343 case OPC_CVT_D_S:
11344 check_cp1_registers(ctx, fd);
11346 TCGv_i32 fp32 = tcg_temp_new_i32();
11347 TCGv_i64 fp64 = tcg_temp_new_i64();
11349 gen_load_fpr32(ctx, fp32, fs);
11350 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11351 tcg_temp_free_i32(fp32);
11352 gen_store_fpr64(ctx, fp64, fd);
11353 tcg_temp_free_i64(fp64);
11355 break;
11356 case OPC_CVT_W_S:
11358 TCGv_i32 fp0 = tcg_temp_new_i32();
11360 gen_load_fpr32(ctx, fp0, fs);
11361 if (ctx->nan2008) {
11362 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11363 } else {
11364 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11366 gen_store_fpr32(ctx, fp0, fd);
11367 tcg_temp_free_i32(fp0);
11369 break;
11370 case OPC_CVT_L_S:
11371 check_cp1_64bitmode(ctx);
11373 TCGv_i32 fp32 = tcg_temp_new_i32();
11374 TCGv_i64 fp64 = tcg_temp_new_i64();
11376 gen_load_fpr32(ctx, fp32, fs);
11377 if (ctx->nan2008) {
11378 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11379 } else {
11380 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11382 tcg_temp_free_i32(fp32);
11383 gen_store_fpr64(ctx, fp64, fd);
11384 tcg_temp_free_i64(fp64);
11386 break;
11387 case OPC_CVT_PS_S:
11388 check_ps(ctx);
11390 TCGv_i64 fp64 = tcg_temp_new_i64();
11391 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11392 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11394 gen_load_fpr32(ctx, fp32_0, fs);
11395 gen_load_fpr32(ctx, fp32_1, ft);
11396 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11397 tcg_temp_free_i32(fp32_1);
11398 tcg_temp_free_i32(fp32_0);
11399 gen_store_fpr64(ctx, fp64, fd);
11400 tcg_temp_free_i64(fp64);
11402 break;
11403 case OPC_CMP_F_S:
11404 case OPC_CMP_UN_S:
11405 case OPC_CMP_EQ_S:
11406 case OPC_CMP_UEQ_S:
11407 case OPC_CMP_OLT_S:
11408 case OPC_CMP_ULT_S:
11409 case OPC_CMP_OLE_S:
11410 case OPC_CMP_ULE_S:
11411 case OPC_CMP_SF_S:
11412 case OPC_CMP_NGLE_S:
11413 case OPC_CMP_SEQ_S:
11414 case OPC_CMP_NGL_S:
11415 case OPC_CMP_LT_S:
11416 case OPC_CMP_NGE_S:
11417 case OPC_CMP_LE_S:
11418 case OPC_CMP_NGT_S:
11419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11420 if (ctx->opcode & (1 << 6)) {
11421 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11422 } else {
11423 gen_cmp_s(ctx, func-48, ft, fs, cc);
11425 break;
11426 case OPC_ADD_D:
11427 check_cp1_registers(ctx, fs | ft | fd);
11429 TCGv_i64 fp0 = tcg_temp_new_i64();
11430 TCGv_i64 fp1 = tcg_temp_new_i64();
11432 gen_load_fpr64(ctx, fp0, fs);
11433 gen_load_fpr64(ctx, fp1, ft);
11434 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11435 tcg_temp_free_i64(fp1);
11436 gen_store_fpr64(ctx, fp0, fd);
11437 tcg_temp_free_i64(fp0);
11439 break;
11440 case OPC_SUB_D:
11441 check_cp1_registers(ctx, fs | ft | fd);
11443 TCGv_i64 fp0 = tcg_temp_new_i64();
11444 TCGv_i64 fp1 = tcg_temp_new_i64();
11446 gen_load_fpr64(ctx, fp0, fs);
11447 gen_load_fpr64(ctx, fp1, ft);
11448 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11449 tcg_temp_free_i64(fp1);
11450 gen_store_fpr64(ctx, fp0, fd);
11451 tcg_temp_free_i64(fp0);
11453 break;
11454 case OPC_MUL_D:
11455 check_cp1_registers(ctx, fs | ft | fd);
11457 TCGv_i64 fp0 = tcg_temp_new_i64();
11458 TCGv_i64 fp1 = tcg_temp_new_i64();
11460 gen_load_fpr64(ctx, fp0, fs);
11461 gen_load_fpr64(ctx, fp1, ft);
11462 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11463 tcg_temp_free_i64(fp1);
11464 gen_store_fpr64(ctx, fp0, fd);
11465 tcg_temp_free_i64(fp0);
11467 break;
11468 case OPC_DIV_D:
11469 check_cp1_registers(ctx, fs | ft | fd);
11471 TCGv_i64 fp0 = tcg_temp_new_i64();
11472 TCGv_i64 fp1 = tcg_temp_new_i64();
11474 gen_load_fpr64(ctx, fp0, fs);
11475 gen_load_fpr64(ctx, fp1, ft);
11476 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11477 tcg_temp_free_i64(fp1);
11478 gen_store_fpr64(ctx, fp0, fd);
11479 tcg_temp_free_i64(fp0);
11481 break;
11482 case OPC_SQRT_D:
11483 check_cp1_registers(ctx, fs | fd);
11485 TCGv_i64 fp0 = tcg_temp_new_i64();
11487 gen_load_fpr64(ctx, fp0, fs);
11488 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11489 gen_store_fpr64(ctx, fp0, fd);
11490 tcg_temp_free_i64(fp0);
11492 break;
11493 case OPC_ABS_D:
11494 check_cp1_registers(ctx, fs | fd);
11496 TCGv_i64 fp0 = tcg_temp_new_i64();
11498 gen_load_fpr64(ctx, fp0, fs);
11499 if (ctx->abs2008) {
11500 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11501 } else {
11502 gen_helper_float_abs_d(fp0, fp0);
11504 gen_store_fpr64(ctx, fp0, fd);
11505 tcg_temp_free_i64(fp0);
11507 break;
11508 case OPC_MOV_D:
11509 check_cp1_registers(ctx, fs | fd);
11511 TCGv_i64 fp0 = tcg_temp_new_i64();
11513 gen_load_fpr64(ctx, fp0, fs);
11514 gen_store_fpr64(ctx, fp0, fd);
11515 tcg_temp_free_i64(fp0);
11517 break;
11518 case OPC_NEG_D:
11519 check_cp1_registers(ctx, fs | fd);
11521 TCGv_i64 fp0 = tcg_temp_new_i64();
11523 gen_load_fpr64(ctx, fp0, fs);
11524 if (ctx->abs2008) {
11525 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11526 } else {
11527 gen_helper_float_chs_d(fp0, fp0);
11529 gen_store_fpr64(ctx, fp0, fd);
11530 tcg_temp_free_i64(fp0);
11532 break;
11533 case OPC_ROUND_L_D:
11534 check_cp1_64bitmode(ctx);
11536 TCGv_i64 fp0 = tcg_temp_new_i64();
11538 gen_load_fpr64(ctx, fp0, fs);
11539 if (ctx->nan2008) {
11540 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11541 } else {
11542 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11544 gen_store_fpr64(ctx, fp0, fd);
11545 tcg_temp_free_i64(fp0);
11547 break;
11548 case OPC_TRUNC_L_D:
11549 check_cp1_64bitmode(ctx);
11551 TCGv_i64 fp0 = tcg_temp_new_i64();
11553 gen_load_fpr64(ctx, fp0, fs);
11554 if (ctx->nan2008) {
11555 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11556 } else {
11557 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11559 gen_store_fpr64(ctx, fp0, fd);
11560 tcg_temp_free_i64(fp0);
11562 break;
11563 case OPC_CEIL_L_D:
11564 check_cp1_64bitmode(ctx);
11566 TCGv_i64 fp0 = tcg_temp_new_i64();
11568 gen_load_fpr64(ctx, fp0, fs);
11569 if (ctx->nan2008) {
11570 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11571 } else {
11572 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11574 gen_store_fpr64(ctx, fp0, fd);
11575 tcg_temp_free_i64(fp0);
11577 break;
11578 case OPC_FLOOR_L_D:
11579 check_cp1_64bitmode(ctx);
11581 TCGv_i64 fp0 = tcg_temp_new_i64();
11583 gen_load_fpr64(ctx, fp0, fs);
11584 if (ctx->nan2008) {
11585 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11586 } else {
11587 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11589 gen_store_fpr64(ctx, fp0, fd);
11590 tcg_temp_free_i64(fp0);
11592 break;
11593 case OPC_ROUND_W_D:
11594 check_cp1_registers(ctx, fs);
11596 TCGv_i32 fp32 = tcg_temp_new_i32();
11597 TCGv_i64 fp64 = tcg_temp_new_i64();
11599 gen_load_fpr64(ctx, fp64, fs);
11600 if (ctx->nan2008) {
11601 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11602 } else {
11603 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11605 tcg_temp_free_i64(fp64);
11606 gen_store_fpr32(ctx, fp32, fd);
11607 tcg_temp_free_i32(fp32);
11609 break;
11610 case OPC_TRUNC_W_D:
11611 check_cp1_registers(ctx, fs);
11613 TCGv_i32 fp32 = tcg_temp_new_i32();
11614 TCGv_i64 fp64 = tcg_temp_new_i64();
11616 gen_load_fpr64(ctx, fp64, fs);
11617 if (ctx->nan2008) {
11618 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11619 } else {
11620 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11622 tcg_temp_free_i64(fp64);
11623 gen_store_fpr32(ctx, fp32, fd);
11624 tcg_temp_free_i32(fp32);
11626 break;
11627 case OPC_CEIL_W_D:
11628 check_cp1_registers(ctx, fs);
11630 TCGv_i32 fp32 = tcg_temp_new_i32();
11631 TCGv_i64 fp64 = tcg_temp_new_i64();
11633 gen_load_fpr64(ctx, fp64, fs);
11634 if (ctx->nan2008) {
11635 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11636 } else {
11637 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11639 tcg_temp_free_i64(fp64);
11640 gen_store_fpr32(ctx, fp32, fd);
11641 tcg_temp_free_i32(fp32);
11643 break;
11644 case OPC_FLOOR_W_D:
11645 check_cp1_registers(ctx, fs);
11647 TCGv_i32 fp32 = tcg_temp_new_i32();
11648 TCGv_i64 fp64 = tcg_temp_new_i64();
11650 gen_load_fpr64(ctx, fp64, fs);
11651 if (ctx->nan2008) {
11652 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11653 } else {
11654 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11656 tcg_temp_free_i64(fp64);
11657 gen_store_fpr32(ctx, fp32, fd);
11658 tcg_temp_free_i32(fp32);
11660 break;
11661 case OPC_SEL_D:
11662 check_insn(ctx, ISA_MIPS32R6);
11663 gen_sel_d(ctx, op1, fd, ft, fs);
11664 break;
11665 case OPC_SELEQZ_D:
11666 check_insn(ctx, ISA_MIPS32R6);
11667 gen_sel_d(ctx, op1, fd, ft, fs);
11668 break;
11669 case OPC_SELNEZ_D:
11670 check_insn(ctx, ISA_MIPS32R6);
11671 gen_sel_d(ctx, op1, fd, ft, fs);
11672 break;
11673 case OPC_MOVCF_D:
11674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11675 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11676 break;
11677 case OPC_MOVZ_D:
11678 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11680 TCGLabel *l1 = gen_new_label();
11681 TCGv_i64 fp0;
11683 if (ft != 0) {
11684 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11686 fp0 = tcg_temp_new_i64();
11687 gen_load_fpr64(ctx, fp0, fs);
11688 gen_store_fpr64(ctx, fp0, fd);
11689 tcg_temp_free_i64(fp0);
11690 gen_set_label(l1);
11692 break;
11693 case OPC_MOVN_D:
11694 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11696 TCGLabel *l1 = gen_new_label();
11697 TCGv_i64 fp0;
11699 if (ft != 0) {
11700 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11701 fp0 = tcg_temp_new_i64();
11702 gen_load_fpr64(ctx, fp0, fs);
11703 gen_store_fpr64(ctx, fp0, fd);
11704 tcg_temp_free_i64(fp0);
11705 gen_set_label(l1);
11708 break;
11709 case OPC_RECIP_D:
11710 check_cp1_registers(ctx, fs | fd);
11712 TCGv_i64 fp0 = tcg_temp_new_i64();
11714 gen_load_fpr64(ctx, fp0, fs);
11715 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11716 gen_store_fpr64(ctx, fp0, fd);
11717 tcg_temp_free_i64(fp0);
11719 break;
11720 case OPC_RSQRT_D:
11721 check_cp1_registers(ctx, fs | fd);
11723 TCGv_i64 fp0 = tcg_temp_new_i64();
11725 gen_load_fpr64(ctx, fp0, fs);
11726 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11727 gen_store_fpr64(ctx, fp0, fd);
11728 tcg_temp_free_i64(fp0);
11730 break;
11731 case OPC_MADDF_D:
11732 check_insn(ctx, ISA_MIPS32R6);
11734 TCGv_i64 fp0 = tcg_temp_new_i64();
11735 TCGv_i64 fp1 = tcg_temp_new_i64();
11736 TCGv_i64 fp2 = tcg_temp_new_i64();
11737 gen_load_fpr64(ctx, fp0, fs);
11738 gen_load_fpr64(ctx, fp1, ft);
11739 gen_load_fpr64(ctx, fp2, fd);
11740 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11741 gen_store_fpr64(ctx, fp2, fd);
11742 tcg_temp_free_i64(fp2);
11743 tcg_temp_free_i64(fp1);
11744 tcg_temp_free_i64(fp0);
11746 break;
11747 case OPC_MSUBF_D:
11748 check_insn(ctx, ISA_MIPS32R6);
11750 TCGv_i64 fp0 = tcg_temp_new_i64();
11751 TCGv_i64 fp1 = tcg_temp_new_i64();
11752 TCGv_i64 fp2 = tcg_temp_new_i64();
11753 gen_load_fpr64(ctx, fp0, fs);
11754 gen_load_fpr64(ctx, fp1, ft);
11755 gen_load_fpr64(ctx, fp2, fd);
11756 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11757 gen_store_fpr64(ctx, fp2, fd);
11758 tcg_temp_free_i64(fp2);
11759 tcg_temp_free_i64(fp1);
11760 tcg_temp_free_i64(fp0);
11762 break;
11763 case OPC_RINT_D:
11764 check_insn(ctx, ISA_MIPS32R6);
11766 TCGv_i64 fp0 = tcg_temp_new_i64();
11767 gen_load_fpr64(ctx, fp0, fs);
11768 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11769 gen_store_fpr64(ctx, fp0, fd);
11770 tcg_temp_free_i64(fp0);
11772 break;
11773 case OPC_CLASS_D:
11774 check_insn(ctx, ISA_MIPS32R6);
11776 TCGv_i64 fp0 = tcg_temp_new_i64();
11777 gen_load_fpr64(ctx, fp0, fs);
11778 gen_helper_float_class_d(fp0, cpu_env, fp0);
11779 gen_store_fpr64(ctx, fp0, fd);
11780 tcg_temp_free_i64(fp0);
11782 break;
11783 case OPC_MIN_D: /* OPC_RECIP2_D */
11784 if (ctx->insn_flags & ISA_MIPS32R6) {
11785 /* OPC_MIN_D */
11786 TCGv_i64 fp0 = tcg_temp_new_i64();
11787 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_min_d(fp1, cpu_env, fp0, fp1);
11791 gen_store_fpr64(ctx, fp1, fd);
11792 tcg_temp_free_i64(fp1);
11793 tcg_temp_free_i64(fp0);
11794 } else {
11795 /* OPC_RECIP2_D */
11796 check_cp1_64bitmode(ctx);
11798 TCGv_i64 fp0 = tcg_temp_new_i64();
11799 TCGv_i64 fp1 = tcg_temp_new_i64();
11801 gen_load_fpr64(ctx, fp0, fs);
11802 gen_load_fpr64(ctx, fp1, ft);
11803 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11804 tcg_temp_free_i64(fp1);
11805 gen_store_fpr64(ctx, fp0, fd);
11806 tcg_temp_free_i64(fp0);
11809 break;
11810 case OPC_MINA_D: /* OPC_RECIP1_D */
11811 if (ctx->insn_flags & ISA_MIPS32R6) {
11812 /* OPC_MINA_D */
11813 TCGv_i64 fp0 = tcg_temp_new_i64();
11814 TCGv_i64 fp1 = tcg_temp_new_i64();
11815 gen_load_fpr64(ctx, fp0, fs);
11816 gen_load_fpr64(ctx, fp1, ft);
11817 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11818 gen_store_fpr64(ctx, fp1, fd);
11819 tcg_temp_free_i64(fp1);
11820 tcg_temp_free_i64(fp0);
11821 } else {
11822 /* OPC_RECIP1_D */
11823 check_cp1_64bitmode(ctx);
11825 TCGv_i64 fp0 = tcg_temp_new_i64();
11827 gen_load_fpr64(ctx, fp0, fs);
11828 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11829 gen_store_fpr64(ctx, fp0, fd);
11830 tcg_temp_free_i64(fp0);
11833 break;
11834 case OPC_MAX_D: /* OPC_RSQRT1_D */
11835 if (ctx->insn_flags & ISA_MIPS32R6) {
11836 /* OPC_MAX_D */
11837 TCGv_i64 fp0 = tcg_temp_new_i64();
11838 TCGv_i64 fp1 = tcg_temp_new_i64();
11839 gen_load_fpr64(ctx, fp0, fs);
11840 gen_load_fpr64(ctx, fp1, ft);
11841 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11842 gen_store_fpr64(ctx, fp1, fd);
11843 tcg_temp_free_i64(fp1);
11844 tcg_temp_free_i64(fp0);
11845 } else {
11846 /* OPC_RSQRT1_D */
11847 check_cp1_64bitmode(ctx);
11849 TCGv_i64 fp0 = tcg_temp_new_i64();
11851 gen_load_fpr64(ctx, fp0, fs);
11852 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11853 gen_store_fpr64(ctx, fp0, fd);
11854 tcg_temp_free_i64(fp0);
11857 break;
11858 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11859 if (ctx->insn_flags & ISA_MIPS32R6) {
11860 /* OPC_MAXA_D */
11861 TCGv_i64 fp0 = tcg_temp_new_i64();
11862 TCGv_i64 fp1 = tcg_temp_new_i64();
11863 gen_load_fpr64(ctx, fp0, fs);
11864 gen_load_fpr64(ctx, fp1, ft);
11865 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11866 gen_store_fpr64(ctx, fp1, fd);
11867 tcg_temp_free_i64(fp1);
11868 tcg_temp_free_i64(fp0);
11869 } else {
11870 /* OPC_RSQRT2_D */
11871 check_cp1_64bitmode(ctx);
11873 TCGv_i64 fp0 = tcg_temp_new_i64();
11874 TCGv_i64 fp1 = tcg_temp_new_i64();
11876 gen_load_fpr64(ctx, fp0, fs);
11877 gen_load_fpr64(ctx, fp1, ft);
11878 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11879 tcg_temp_free_i64(fp1);
11880 gen_store_fpr64(ctx, fp0, fd);
11881 tcg_temp_free_i64(fp0);
11884 break;
11885 case OPC_CMP_F_D:
11886 case OPC_CMP_UN_D:
11887 case OPC_CMP_EQ_D:
11888 case OPC_CMP_UEQ_D:
11889 case OPC_CMP_OLT_D:
11890 case OPC_CMP_ULT_D:
11891 case OPC_CMP_OLE_D:
11892 case OPC_CMP_ULE_D:
11893 case OPC_CMP_SF_D:
11894 case OPC_CMP_NGLE_D:
11895 case OPC_CMP_SEQ_D:
11896 case OPC_CMP_NGL_D:
11897 case OPC_CMP_LT_D:
11898 case OPC_CMP_NGE_D:
11899 case OPC_CMP_LE_D:
11900 case OPC_CMP_NGT_D:
11901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11902 if (ctx->opcode & (1 << 6)) {
11903 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11904 } else {
11905 gen_cmp_d(ctx, func-48, ft, fs, cc);
11907 break;
11908 case OPC_CVT_S_D:
11909 check_cp1_registers(ctx, fs);
11911 TCGv_i32 fp32 = tcg_temp_new_i32();
11912 TCGv_i64 fp64 = tcg_temp_new_i64();
11914 gen_load_fpr64(ctx, fp64, fs);
11915 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11916 tcg_temp_free_i64(fp64);
11917 gen_store_fpr32(ctx, fp32, fd);
11918 tcg_temp_free_i32(fp32);
11920 break;
11921 case OPC_CVT_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_cvt_2008_w_d(fp32, cpu_env, fp64);
11930 } else {
11931 gen_helper_float_cvt_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_CVT_L_D:
11939 check_cp1_64bitmode(ctx);
11941 TCGv_i64 fp0 = tcg_temp_new_i64();
11943 gen_load_fpr64(ctx, fp0, fs);
11944 if (ctx->nan2008) {
11945 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11946 } else {
11947 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11949 gen_store_fpr64(ctx, fp0, fd);
11950 tcg_temp_free_i64(fp0);
11952 break;
11953 case OPC_CVT_S_W:
11955 TCGv_i32 fp0 = tcg_temp_new_i32();
11957 gen_load_fpr32(ctx, fp0, fs);
11958 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11959 gen_store_fpr32(ctx, fp0, fd);
11960 tcg_temp_free_i32(fp0);
11962 break;
11963 case OPC_CVT_D_W:
11964 check_cp1_registers(ctx, fd);
11966 TCGv_i32 fp32 = tcg_temp_new_i32();
11967 TCGv_i64 fp64 = tcg_temp_new_i64();
11969 gen_load_fpr32(ctx, fp32, fs);
11970 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11971 tcg_temp_free_i32(fp32);
11972 gen_store_fpr64(ctx, fp64, fd);
11973 tcg_temp_free_i64(fp64);
11975 break;
11976 case OPC_CVT_S_L:
11977 check_cp1_64bitmode(ctx);
11979 TCGv_i32 fp32 = tcg_temp_new_i32();
11980 TCGv_i64 fp64 = tcg_temp_new_i64();
11982 gen_load_fpr64(ctx, fp64, fs);
11983 gen_helper_float_cvts_l(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_CVT_D_L:
11990 check_cp1_64bitmode(ctx);
11992 TCGv_i64 fp0 = tcg_temp_new_i64();
11994 gen_load_fpr64(ctx, fp0, fs);
11995 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11996 gen_store_fpr64(ctx, fp0, fd);
11997 tcg_temp_free_i64(fp0);
11999 break;
12000 case OPC_CVT_PS_PW:
12001 check_ps(ctx);
12003 TCGv_i64 fp0 = tcg_temp_new_i64();
12005 gen_load_fpr64(ctx, fp0, fs);
12006 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12007 gen_store_fpr64(ctx, fp0, fd);
12008 tcg_temp_free_i64(fp0);
12010 break;
12011 case OPC_ADD_PS:
12012 check_ps(ctx);
12014 TCGv_i64 fp0 = tcg_temp_new_i64();
12015 TCGv_i64 fp1 = tcg_temp_new_i64();
12017 gen_load_fpr64(ctx, fp0, fs);
12018 gen_load_fpr64(ctx, fp1, ft);
12019 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12020 tcg_temp_free_i64(fp1);
12021 gen_store_fpr64(ctx, fp0, fd);
12022 tcg_temp_free_i64(fp0);
12024 break;
12025 case OPC_SUB_PS:
12026 check_ps(ctx);
12028 TCGv_i64 fp0 = tcg_temp_new_i64();
12029 TCGv_i64 fp1 = tcg_temp_new_i64();
12031 gen_load_fpr64(ctx, fp0, fs);
12032 gen_load_fpr64(ctx, fp1, ft);
12033 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12034 tcg_temp_free_i64(fp1);
12035 gen_store_fpr64(ctx, fp0, fd);
12036 tcg_temp_free_i64(fp0);
12038 break;
12039 case OPC_MUL_PS:
12040 check_ps(ctx);
12042 TCGv_i64 fp0 = tcg_temp_new_i64();
12043 TCGv_i64 fp1 = tcg_temp_new_i64();
12045 gen_load_fpr64(ctx, fp0, fs);
12046 gen_load_fpr64(ctx, fp1, ft);
12047 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12048 tcg_temp_free_i64(fp1);
12049 gen_store_fpr64(ctx, fp0, fd);
12050 tcg_temp_free_i64(fp0);
12052 break;
12053 case OPC_ABS_PS:
12054 check_ps(ctx);
12056 TCGv_i64 fp0 = tcg_temp_new_i64();
12058 gen_load_fpr64(ctx, fp0, fs);
12059 gen_helper_float_abs_ps(fp0, fp0);
12060 gen_store_fpr64(ctx, fp0, fd);
12061 tcg_temp_free_i64(fp0);
12063 break;
12064 case OPC_MOV_PS:
12065 check_ps(ctx);
12067 TCGv_i64 fp0 = tcg_temp_new_i64();
12069 gen_load_fpr64(ctx, fp0, fs);
12070 gen_store_fpr64(ctx, fp0, fd);
12071 tcg_temp_free_i64(fp0);
12073 break;
12074 case OPC_NEG_PS:
12075 check_ps(ctx);
12077 TCGv_i64 fp0 = tcg_temp_new_i64();
12079 gen_load_fpr64(ctx, fp0, fs);
12080 gen_helper_float_chs_ps(fp0, fp0);
12081 gen_store_fpr64(ctx, fp0, fd);
12082 tcg_temp_free_i64(fp0);
12084 break;
12085 case OPC_MOVCF_PS:
12086 check_ps(ctx);
12087 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12088 break;
12089 case OPC_MOVZ_PS:
12090 check_ps(ctx);
12092 TCGLabel *l1 = gen_new_label();
12093 TCGv_i64 fp0;
12095 if (ft != 0)
12096 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12097 fp0 = tcg_temp_new_i64();
12098 gen_load_fpr64(ctx, fp0, fs);
12099 gen_store_fpr64(ctx, fp0, fd);
12100 tcg_temp_free_i64(fp0);
12101 gen_set_label(l1);
12103 break;
12104 case OPC_MOVN_PS:
12105 check_ps(ctx);
12107 TCGLabel *l1 = gen_new_label();
12108 TCGv_i64 fp0;
12110 if (ft != 0) {
12111 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12112 fp0 = tcg_temp_new_i64();
12113 gen_load_fpr64(ctx, fp0, fs);
12114 gen_store_fpr64(ctx, fp0, fd);
12115 tcg_temp_free_i64(fp0);
12116 gen_set_label(l1);
12119 break;
12120 case OPC_ADDR_PS:
12121 check_ps(ctx);
12123 TCGv_i64 fp0 = tcg_temp_new_i64();
12124 TCGv_i64 fp1 = tcg_temp_new_i64();
12126 gen_load_fpr64(ctx, fp0, ft);
12127 gen_load_fpr64(ctx, fp1, fs);
12128 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12129 tcg_temp_free_i64(fp1);
12130 gen_store_fpr64(ctx, fp0, fd);
12131 tcg_temp_free_i64(fp0);
12133 break;
12134 case OPC_MULR_PS:
12135 check_ps(ctx);
12137 TCGv_i64 fp0 = tcg_temp_new_i64();
12138 TCGv_i64 fp1 = tcg_temp_new_i64();
12140 gen_load_fpr64(ctx, fp0, ft);
12141 gen_load_fpr64(ctx, fp1, fs);
12142 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12143 tcg_temp_free_i64(fp1);
12144 gen_store_fpr64(ctx, fp0, fd);
12145 tcg_temp_free_i64(fp0);
12147 break;
12148 case OPC_RECIP2_PS:
12149 check_ps(ctx);
12151 TCGv_i64 fp0 = tcg_temp_new_i64();
12152 TCGv_i64 fp1 = tcg_temp_new_i64();
12154 gen_load_fpr64(ctx, fp0, fs);
12155 gen_load_fpr64(ctx, fp1, ft);
12156 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12157 tcg_temp_free_i64(fp1);
12158 gen_store_fpr64(ctx, fp0, fd);
12159 tcg_temp_free_i64(fp0);
12161 break;
12162 case OPC_RECIP1_PS:
12163 check_ps(ctx);
12165 TCGv_i64 fp0 = tcg_temp_new_i64();
12167 gen_load_fpr64(ctx, fp0, fs);
12168 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12169 gen_store_fpr64(ctx, fp0, fd);
12170 tcg_temp_free_i64(fp0);
12172 break;
12173 case OPC_RSQRT1_PS:
12174 check_ps(ctx);
12176 TCGv_i64 fp0 = tcg_temp_new_i64();
12178 gen_load_fpr64(ctx, fp0, fs);
12179 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12180 gen_store_fpr64(ctx, fp0, fd);
12181 tcg_temp_free_i64(fp0);
12183 break;
12184 case OPC_RSQRT2_PS:
12185 check_ps(ctx);
12187 TCGv_i64 fp0 = tcg_temp_new_i64();
12188 TCGv_i64 fp1 = tcg_temp_new_i64();
12190 gen_load_fpr64(ctx, fp0, fs);
12191 gen_load_fpr64(ctx, fp1, ft);
12192 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12193 tcg_temp_free_i64(fp1);
12194 gen_store_fpr64(ctx, fp0, fd);
12195 tcg_temp_free_i64(fp0);
12197 break;
12198 case OPC_CVT_S_PU:
12199 check_cp1_64bitmode(ctx);
12201 TCGv_i32 fp0 = tcg_temp_new_i32();
12203 gen_load_fpr32h(ctx, fp0, fs);
12204 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12205 gen_store_fpr32(ctx, fp0, fd);
12206 tcg_temp_free_i32(fp0);
12208 break;
12209 case OPC_CVT_PW_PS:
12210 check_ps(ctx);
12212 TCGv_i64 fp0 = tcg_temp_new_i64();
12214 gen_load_fpr64(ctx, fp0, fs);
12215 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12216 gen_store_fpr64(ctx, fp0, fd);
12217 tcg_temp_free_i64(fp0);
12219 break;
12220 case OPC_CVT_S_PL:
12221 check_cp1_64bitmode(ctx);
12223 TCGv_i32 fp0 = tcg_temp_new_i32();
12225 gen_load_fpr32(ctx, fp0, fs);
12226 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12227 gen_store_fpr32(ctx, fp0, fd);
12228 tcg_temp_free_i32(fp0);
12230 break;
12231 case OPC_PLL_PS:
12232 check_ps(ctx);
12234 TCGv_i32 fp0 = tcg_temp_new_i32();
12235 TCGv_i32 fp1 = tcg_temp_new_i32();
12237 gen_load_fpr32(ctx, fp0, fs);
12238 gen_load_fpr32(ctx, fp1, ft);
12239 gen_store_fpr32h(ctx, fp0, fd);
12240 gen_store_fpr32(ctx, fp1, fd);
12241 tcg_temp_free_i32(fp0);
12242 tcg_temp_free_i32(fp1);
12244 break;
12245 case OPC_PLU_PS:
12246 check_ps(ctx);
12248 TCGv_i32 fp0 = tcg_temp_new_i32();
12249 TCGv_i32 fp1 = tcg_temp_new_i32();
12251 gen_load_fpr32(ctx, fp0, fs);
12252 gen_load_fpr32h(ctx, fp1, ft);
12253 gen_store_fpr32(ctx, fp1, fd);
12254 gen_store_fpr32h(ctx, fp0, fd);
12255 tcg_temp_free_i32(fp0);
12256 tcg_temp_free_i32(fp1);
12258 break;
12259 case OPC_PUL_PS:
12260 check_ps(ctx);
12262 TCGv_i32 fp0 = tcg_temp_new_i32();
12263 TCGv_i32 fp1 = tcg_temp_new_i32();
12265 gen_load_fpr32h(ctx, fp0, fs);
12266 gen_load_fpr32(ctx, fp1, ft);
12267 gen_store_fpr32(ctx, fp1, fd);
12268 gen_store_fpr32h(ctx, fp0, fd);
12269 tcg_temp_free_i32(fp0);
12270 tcg_temp_free_i32(fp1);
12272 break;
12273 case OPC_PUU_PS:
12274 check_ps(ctx);
12276 TCGv_i32 fp0 = tcg_temp_new_i32();
12277 TCGv_i32 fp1 = tcg_temp_new_i32();
12279 gen_load_fpr32h(ctx, fp0, fs);
12280 gen_load_fpr32h(ctx, fp1, ft);
12281 gen_store_fpr32(ctx, fp1, fd);
12282 gen_store_fpr32h(ctx, fp0, fd);
12283 tcg_temp_free_i32(fp0);
12284 tcg_temp_free_i32(fp1);
12286 break;
12287 case OPC_CMP_F_PS:
12288 case OPC_CMP_UN_PS:
12289 case OPC_CMP_EQ_PS:
12290 case OPC_CMP_UEQ_PS:
12291 case OPC_CMP_OLT_PS:
12292 case OPC_CMP_ULT_PS:
12293 case OPC_CMP_OLE_PS:
12294 case OPC_CMP_ULE_PS:
12295 case OPC_CMP_SF_PS:
12296 case OPC_CMP_NGLE_PS:
12297 case OPC_CMP_SEQ_PS:
12298 case OPC_CMP_NGL_PS:
12299 case OPC_CMP_LT_PS:
12300 case OPC_CMP_NGE_PS:
12301 case OPC_CMP_LE_PS:
12302 case OPC_CMP_NGT_PS:
12303 if (ctx->opcode & (1 << 6)) {
12304 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12305 } else {
12306 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12308 break;
12309 default:
12310 MIPS_INVAL("farith");
12311 generate_exception_end(ctx, EXCP_RI);
12312 return;
12316 /* Coprocessor 3 (FPU) */
12317 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12318 int fd, int fs, int base, int index)
12320 TCGv t0 = tcg_temp_new();
12322 if (base == 0) {
12323 gen_load_gpr(t0, index);
12324 } else if (index == 0) {
12325 gen_load_gpr(t0, base);
12326 } else {
12327 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12329 /* Don't do NOP if destination is zero: we must perform the actual
12330 memory access. */
12331 switch (opc) {
12332 case OPC_LWXC1:
12333 check_cop1x(ctx);
12335 TCGv_i32 fp0 = tcg_temp_new_i32();
12337 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12338 tcg_gen_trunc_tl_i32(fp0, t0);
12339 gen_store_fpr32(ctx, fp0, fd);
12340 tcg_temp_free_i32(fp0);
12342 break;
12343 case OPC_LDXC1:
12344 check_cop1x(ctx);
12345 check_cp1_registers(ctx, fd);
12347 TCGv_i64 fp0 = tcg_temp_new_i64();
12348 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12349 gen_store_fpr64(ctx, fp0, fd);
12350 tcg_temp_free_i64(fp0);
12352 break;
12353 case OPC_LUXC1:
12354 check_cp1_64bitmode(ctx);
12355 tcg_gen_andi_tl(t0, t0, ~0x7);
12357 TCGv_i64 fp0 = tcg_temp_new_i64();
12359 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12360 gen_store_fpr64(ctx, fp0, fd);
12361 tcg_temp_free_i64(fp0);
12363 break;
12364 case OPC_SWXC1:
12365 check_cop1x(ctx);
12367 TCGv_i32 fp0 = tcg_temp_new_i32();
12368 gen_load_fpr32(ctx, fp0, fs);
12369 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12370 tcg_temp_free_i32(fp0);
12372 break;
12373 case OPC_SDXC1:
12374 check_cop1x(ctx);
12375 check_cp1_registers(ctx, fs);
12377 TCGv_i64 fp0 = tcg_temp_new_i64();
12378 gen_load_fpr64(ctx, fp0, fs);
12379 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12380 tcg_temp_free_i64(fp0);
12382 break;
12383 case OPC_SUXC1:
12384 check_cp1_64bitmode(ctx);
12385 tcg_gen_andi_tl(t0, t0, ~0x7);
12387 TCGv_i64 fp0 = tcg_temp_new_i64();
12388 gen_load_fpr64(ctx, fp0, fs);
12389 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12390 tcg_temp_free_i64(fp0);
12392 break;
12394 tcg_temp_free(t0);
12397 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12398 int fd, int fr, int fs, int ft)
12400 switch (opc) {
12401 case OPC_ALNV_PS:
12402 check_ps(ctx);
12404 TCGv t0 = tcg_temp_local_new();
12405 TCGv_i32 fp = tcg_temp_new_i32();
12406 TCGv_i32 fph = tcg_temp_new_i32();
12407 TCGLabel *l1 = gen_new_label();
12408 TCGLabel *l2 = gen_new_label();
12410 gen_load_gpr(t0, fr);
12411 tcg_gen_andi_tl(t0, t0, 0x7);
12413 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12414 gen_load_fpr32(ctx, fp, fs);
12415 gen_load_fpr32h(ctx, fph, fs);
12416 gen_store_fpr32(ctx, fp, fd);
12417 gen_store_fpr32h(ctx, fph, fd);
12418 tcg_gen_br(l2);
12419 gen_set_label(l1);
12420 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12421 tcg_temp_free(t0);
12422 #ifdef TARGET_WORDS_BIGENDIAN
12423 gen_load_fpr32(ctx, fp, fs);
12424 gen_load_fpr32h(ctx, fph, ft);
12425 gen_store_fpr32h(ctx, fp, fd);
12426 gen_store_fpr32(ctx, fph, fd);
12427 #else
12428 gen_load_fpr32h(ctx, fph, fs);
12429 gen_load_fpr32(ctx, fp, ft);
12430 gen_store_fpr32(ctx, fph, fd);
12431 gen_store_fpr32h(ctx, fp, fd);
12432 #endif
12433 gen_set_label(l2);
12434 tcg_temp_free_i32(fp);
12435 tcg_temp_free_i32(fph);
12437 break;
12438 case OPC_MADD_S:
12439 check_cop1x(ctx);
12441 TCGv_i32 fp0 = tcg_temp_new_i32();
12442 TCGv_i32 fp1 = tcg_temp_new_i32();
12443 TCGv_i32 fp2 = tcg_temp_new_i32();
12445 gen_load_fpr32(ctx, fp0, fs);
12446 gen_load_fpr32(ctx, fp1, ft);
12447 gen_load_fpr32(ctx, fp2, fr);
12448 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12449 tcg_temp_free_i32(fp0);
12450 tcg_temp_free_i32(fp1);
12451 gen_store_fpr32(ctx, fp2, fd);
12452 tcg_temp_free_i32(fp2);
12454 break;
12455 case OPC_MADD_D:
12456 check_cop1x(ctx);
12457 check_cp1_registers(ctx, fd | fs | ft | fr);
12459 TCGv_i64 fp0 = tcg_temp_new_i64();
12460 TCGv_i64 fp1 = tcg_temp_new_i64();
12461 TCGv_i64 fp2 = tcg_temp_new_i64();
12463 gen_load_fpr64(ctx, fp0, fs);
12464 gen_load_fpr64(ctx, fp1, ft);
12465 gen_load_fpr64(ctx, fp2, fr);
12466 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12467 tcg_temp_free_i64(fp0);
12468 tcg_temp_free_i64(fp1);
12469 gen_store_fpr64(ctx, fp2, fd);
12470 tcg_temp_free_i64(fp2);
12472 break;
12473 case OPC_MADD_PS:
12474 check_ps(ctx);
12476 TCGv_i64 fp0 = tcg_temp_new_i64();
12477 TCGv_i64 fp1 = tcg_temp_new_i64();
12478 TCGv_i64 fp2 = tcg_temp_new_i64();
12480 gen_load_fpr64(ctx, fp0, fs);
12481 gen_load_fpr64(ctx, fp1, ft);
12482 gen_load_fpr64(ctx, fp2, fr);
12483 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12484 tcg_temp_free_i64(fp0);
12485 tcg_temp_free_i64(fp1);
12486 gen_store_fpr64(ctx, fp2, fd);
12487 tcg_temp_free_i64(fp2);
12489 break;
12490 case OPC_MSUB_S:
12491 check_cop1x(ctx);
12493 TCGv_i32 fp0 = tcg_temp_new_i32();
12494 TCGv_i32 fp1 = tcg_temp_new_i32();
12495 TCGv_i32 fp2 = tcg_temp_new_i32();
12497 gen_load_fpr32(ctx, fp0, fs);
12498 gen_load_fpr32(ctx, fp1, ft);
12499 gen_load_fpr32(ctx, fp2, fr);
12500 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12501 tcg_temp_free_i32(fp0);
12502 tcg_temp_free_i32(fp1);
12503 gen_store_fpr32(ctx, fp2, fd);
12504 tcg_temp_free_i32(fp2);
12506 break;
12507 case OPC_MSUB_D:
12508 check_cop1x(ctx);
12509 check_cp1_registers(ctx, fd | fs | ft | fr);
12511 TCGv_i64 fp0 = tcg_temp_new_i64();
12512 TCGv_i64 fp1 = tcg_temp_new_i64();
12513 TCGv_i64 fp2 = tcg_temp_new_i64();
12515 gen_load_fpr64(ctx, fp0, fs);
12516 gen_load_fpr64(ctx, fp1, ft);
12517 gen_load_fpr64(ctx, fp2, fr);
12518 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12519 tcg_temp_free_i64(fp0);
12520 tcg_temp_free_i64(fp1);
12521 gen_store_fpr64(ctx, fp2, fd);
12522 tcg_temp_free_i64(fp2);
12524 break;
12525 case OPC_MSUB_PS:
12526 check_ps(ctx);
12528 TCGv_i64 fp0 = tcg_temp_new_i64();
12529 TCGv_i64 fp1 = tcg_temp_new_i64();
12530 TCGv_i64 fp2 = tcg_temp_new_i64();
12532 gen_load_fpr64(ctx, fp0, fs);
12533 gen_load_fpr64(ctx, fp1, ft);
12534 gen_load_fpr64(ctx, fp2, fr);
12535 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12536 tcg_temp_free_i64(fp0);
12537 tcg_temp_free_i64(fp1);
12538 gen_store_fpr64(ctx, fp2, fd);
12539 tcg_temp_free_i64(fp2);
12541 break;
12542 case OPC_NMADD_S:
12543 check_cop1x(ctx);
12545 TCGv_i32 fp0 = tcg_temp_new_i32();
12546 TCGv_i32 fp1 = tcg_temp_new_i32();
12547 TCGv_i32 fp2 = tcg_temp_new_i32();
12549 gen_load_fpr32(ctx, fp0, fs);
12550 gen_load_fpr32(ctx, fp1, ft);
12551 gen_load_fpr32(ctx, fp2, fr);
12552 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12553 tcg_temp_free_i32(fp0);
12554 tcg_temp_free_i32(fp1);
12555 gen_store_fpr32(ctx, fp2, fd);
12556 tcg_temp_free_i32(fp2);
12558 break;
12559 case OPC_NMADD_D:
12560 check_cop1x(ctx);
12561 check_cp1_registers(ctx, fd | fs | ft | fr);
12563 TCGv_i64 fp0 = tcg_temp_new_i64();
12564 TCGv_i64 fp1 = tcg_temp_new_i64();
12565 TCGv_i64 fp2 = tcg_temp_new_i64();
12567 gen_load_fpr64(ctx, fp0, fs);
12568 gen_load_fpr64(ctx, fp1, ft);
12569 gen_load_fpr64(ctx, fp2, fr);
12570 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12571 tcg_temp_free_i64(fp0);
12572 tcg_temp_free_i64(fp1);
12573 gen_store_fpr64(ctx, fp2, fd);
12574 tcg_temp_free_i64(fp2);
12576 break;
12577 case OPC_NMADD_PS:
12578 check_ps(ctx);
12580 TCGv_i64 fp0 = tcg_temp_new_i64();
12581 TCGv_i64 fp1 = tcg_temp_new_i64();
12582 TCGv_i64 fp2 = tcg_temp_new_i64();
12584 gen_load_fpr64(ctx, fp0, fs);
12585 gen_load_fpr64(ctx, fp1, ft);
12586 gen_load_fpr64(ctx, fp2, fr);
12587 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12588 tcg_temp_free_i64(fp0);
12589 tcg_temp_free_i64(fp1);
12590 gen_store_fpr64(ctx, fp2, fd);
12591 tcg_temp_free_i64(fp2);
12593 break;
12594 case OPC_NMSUB_S:
12595 check_cop1x(ctx);
12597 TCGv_i32 fp0 = tcg_temp_new_i32();
12598 TCGv_i32 fp1 = tcg_temp_new_i32();
12599 TCGv_i32 fp2 = tcg_temp_new_i32();
12601 gen_load_fpr32(ctx, fp0, fs);
12602 gen_load_fpr32(ctx, fp1, ft);
12603 gen_load_fpr32(ctx, fp2, fr);
12604 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12605 tcg_temp_free_i32(fp0);
12606 tcg_temp_free_i32(fp1);
12607 gen_store_fpr32(ctx, fp2, fd);
12608 tcg_temp_free_i32(fp2);
12610 break;
12611 case OPC_NMSUB_D:
12612 check_cop1x(ctx);
12613 check_cp1_registers(ctx, fd | fs | ft | fr);
12615 TCGv_i64 fp0 = tcg_temp_new_i64();
12616 TCGv_i64 fp1 = tcg_temp_new_i64();
12617 TCGv_i64 fp2 = tcg_temp_new_i64();
12619 gen_load_fpr64(ctx, fp0, fs);
12620 gen_load_fpr64(ctx, fp1, ft);
12621 gen_load_fpr64(ctx, fp2, fr);
12622 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12623 tcg_temp_free_i64(fp0);
12624 tcg_temp_free_i64(fp1);
12625 gen_store_fpr64(ctx, fp2, fd);
12626 tcg_temp_free_i64(fp2);
12628 break;
12629 case OPC_NMSUB_PS:
12630 check_ps(ctx);
12632 TCGv_i64 fp0 = tcg_temp_new_i64();
12633 TCGv_i64 fp1 = tcg_temp_new_i64();
12634 TCGv_i64 fp2 = tcg_temp_new_i64();
12636 gen_load_fpr64(ctx, fp0, fs);
12637 gen_load_fpr64(ctx, fp1, ft);
12638 gen_load_fpr64(ctx, fp2, fr);
12639 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12640 tcg_temp_free_i64(fp0);
12641 tcg_temp_free_i64(fp1);
12642 gen_store_fpr64(ctx, fp2, fd);
12643 tcg_temp_free_i64(fp2);
12645 break;
12646 default:
12647 MIPS_INVAL("flt3_arith");
12648 generate_exception_end(ctx, EXCP_RI);
12649 return;
12653 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12655 TCGv t0;
12657 #if !defined(CONFIG_USER_ONLY)
12658 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12659 Therefore only check the ISA in system mode. */
12660 check_insn(ctx, ISA_MIPS32R2);
12661 #endif
12662 t0 = tcg_temp_new();
12664 switch (rd) {
12665 case 0:
12666 gen_helper_rdhwr_cpunum(t0, cpu_env);
12667 gen_store_gpr(t0, rt);
12668 break;
12669 case 1:
12670 gen_helper_rdhwr_synci_step(t0, cpu_env);
12671 gen_store_gpr(t0, rt);
12672 break;
12673 case 2:
12674 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12675 gen_io_start();
12677 gen_helper_rdhwr_cc(t0, cpu_env);
12678 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12679 gen_io_end();
12681 gen_store_gpr(t0, rt);
12682 /* Break the TB to be able to take timer interrupts immediately
12683 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12684 we break completely out of translated code. */
12685 gen_save_pc(ctx->base.pc_next + 4);
12686 ctx->base.is_jmp = DISAS_EXIT;
12687 break;
12688 case 3:
12689 gen_helper_rdhwr_ccres(t0, cpu_env);
12690 gen_store_gpr(t0, rt);
12691 break;
12692 case 4:
12693 check_insn(ctx, ISA_MIPS32R6);
12694 if (sel != 0) {
12695 /* Performance counter registers are not implemented other than
12696 * control register 0.
12698 generate_exception(ctx, EXCP_RI);
12700 gen_helper_rdhwr_performance(t0, cpu_env);
12701 gen_store_gpr(t0, rt);
12702 break;
12703 case 5:
12704 check_insn(ctx, ISA_MIPS32R6);
12705 gen_helper_rdhwr_xnp(t0, cpu_env);
12706 gen_store_gpr(t0, rt);
12707 break;
12708 case 29:
12709 #if defined(CONFIG_USER_ONLY)
12710 tcg_gen_ld_tl(t0, cpu_env,
12711 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12712 gen_store_gpr(t0, rt);
12713 break;
12714 #else
12715 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12716 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12717 tcg_gen_ld_tl(t0, cpu_env,
12718 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12719 gen_store_gpr(t0, rt);
12720 } else {
12721 generate_exception_end(ctx, EXCP_RI);
12723 break;
12724 #endif
12725 default: /* Invalid */
12726 MIPS_INVAL("rdhwr");
12727 generate_exception_end(ctx, EXCP_RI);
12728 break;
12730 tcg_temp_free(t0);
12733 static inline void clear_branch_hflags(DisasContext *ctx)
12735 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12736 if (ctx->base.is_jmp == DISAS_NEXT) {
12737 save_cpu_state(ctx, 0);
12738 } else {
12739 /* it is not safe to save ctx->hflags as hflags may be changed
12740 in execution time by the instruction in delay / forbidden slot. */
12741 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12745 static void gen_branch(DisasContext *ctx, int insn_bytes)
12747 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12748 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12749 /* Branches completion */
12750 clear_branch_hflags(ctx);
12751 ctx->base.is_jmp = DISAS_NORETURN;
12752 /* FIXME: Need to clear can_do_io. */
12753 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12754 case MIPS_HFLAG_FBNSLOT:
12755 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12756 break;
12757 case MIPS_HFLAG_B:
12758 /* unconditional branch */
12759 if (proc_hflags & MIPS_HFLAG_BX) {
12760 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12762 gen_goto_tb(ctx, 0, ctx->btarget);
12763 break;
12764 case MIPS_HFLAG_BL:
12765 /* blikely taken case */
12766 gen_goto_tb(ctx, 0, ctx->btarget);
12767 break;
12768 case MIPS_HFLAG_BC:
12769 /* Conditional branch */
12771 TCGLabel *l1 = gen_new_label();
12773 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12774 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12775 gen_set_label(l1);
12776 gen_goto_tb(ctx, 0, ctx->btarget);
12778 break;
12779 case MIPS_HFLAG_BR:
12780 /* unconditional branch to register */
12781 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12782 TCGv t0 = tcg_temp_new();
12783 TCGv_i32 t1 = tcg_temp_new_i32();
12785 tcg_gen_andi_tl(t0, btarget, 0x1);
12786 tcg_gen_trunc_tl_i32(t1, t0);
12787 tcg_temp_free(t0);
12788 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12789 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12790 tcg_gen_or_i32(hflags, hflags, t1);
12791 tcg_temp_free_i32(t1);
12793 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12794 } else {
12795 tcg_gen_mov_tl(cpu_PC, btarget);
12797 if (ctx->base.singlestep_enabled) {
12798 save_cpu_state(ctx, 0);
12799 gen_helper_raise_exception_debug(cpu_env);
12801 tcg_gen_lookup_and_goto_ptr();
12802 break;
12803 default:
12804 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12805 abort();
12810 /* Compact Branches */
12811 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12812 int rs, int rt, int32_t offset)
12814 int bcond_compute = 0;
12815 TCGv t0 = tcg_temp_new();
12816 TCGv t1 = tcg_temp_new();
12817 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12819 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12820 #ifdef MIPS_DEBUG_DISAS
12821 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12822 "\n", ctx->base.pc_next);
12823 #endif
12824 generate_exception_end(ctx, EXCP_RI);
12825 goto out;
12828 /* Load needed operands and calculate btarget */
12829 switch (opc) {
12830 /* compact branch */
12831 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12832 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12833 gen_load_gpr(t0, rs);
12834 gen_load_gpr(t1, rt);
12835 bcond_compute = 1;
12836 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12837 if (rs <= rt && rs == 0) {
12838 /* OPC_BEQZALC, OPC_BNEZALC */
12839 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12841 break;
12842 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12843 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12844 gen_load_gpr(t0, rs);
12845 gen_load_gpr(t1, rt);
12846 bcond_compute = 1;
12847 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12848 break;
12849 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12850 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12851 if (rs == 0 || rs == rt) {
12852 /* OPC_BLEZALC, OPC_BGEZALC */
12853 /* OPC_BGTZALC, OPC_BLTZALC */
12854 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12856 gen_load_gpr(t0, rs);
12857 gen_load_gpr(t1, rt);
12858 bcond_compute = 1;
12859 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12860 break;
12861 case OPC_BC:
12862 case OPC_BALC:
12863 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12864 break;
12865 case OPC_BEQZC:
12866 case OPC_BNEZC:
12867 if (rs != 0) {
12868 /* OPC_BEQZC, OPC_BNEZC */
12869 gen_load_gpr(t0, rs);
12870 bcond_compute = 1;
12871 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12872 } else {
12873 /* OPC_JIC, OPC_JIALC */
12874 TCGv tbase = tcg_temp_new();
12875 TCGv toffset = tcg_temp_new();
12877 gen_load_gpr(tbase, rt);
12878 tcg_gen_movi_tl(toffset, offset);
12879 gen_op_addr_add(ctx, btarget, tbase, toffset);
12880 tcg_temp_free(tbase);
12881 tcg_temp_free(toffset);
12883 break;
12884 default:
12885 MIPS_INVAL("Compact branch/jump");
12886 generate_exception_end(ctx, EXCP_RI);
12887 goto out;
12890 if (bcond_compute == 0) {
12891 /* Uncoditional compact branch */
12892 switch (opc) {
12893 case OPC_JIALC:
12894 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12895 /* Fallthrough */
12896 case OPC_JIC:
12897 ctx->hflags |= MIPS_HFLAG_BR;
12898 break;
12899 case OPC_BALC:
12900 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12901 /* Fallthrough */
12902 case OPC_BC:
12903 ctx->hflags |= MIPS_HFLAG_B;
12904 break;
12905 default:
12906 MIPS_INVAL("Compact branch/jump");
12907 generate_exception_end(ctx, EXCP_RI);
12908 goto out;
12911 /* Generating branch here as compact branches don't have delay slot */
12912 gen_branch(ctx, 4);
12913 } else {
12914 /* Conditional compact branch */
12915 TCGLabel *fs = gen_new_label();
12916 save_cpu_state(ctx, 0);
12918 switch (opc) {
12919 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12920 if (rs == 0 && rt != 0) {
12921 /* OPC_BLEZALC */
12922 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12923 } else if (rs != 0 && rt != 0 && rs == rt) {
12924 /* OPC_BGEZALC */
12925 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12926 } else {
12927 /* OPC_BGEUC */
12928 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12930 break;
12931 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12932 if (rs == 0 && rt != 0) {
12933 /* OPC_BGTZALC */
12934 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12935 } else if (rs != 0 && rt != 0 && rs == rt) {
12936 /* OPC_BLTZALC */
12937 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12938 } else {
12939 /* OPC_BLTUC */
12940 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12942 break;
12943 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12944 if (rs == 0 && rt != 0) {
12945 /* OPC_BLEZC */
12946 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12947 } else if (rs != 0 && rt != 0 && rs == rt) {
12948 /* OPC_BGEZC */
12949 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12950 } else {
12951 /* OPC_BGEC */
12952 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12954 break;
12955 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12956 if (rs == 0 && rt != 0) {
12957 /* OPC_BGTZC */
12958 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12959 } else if (rs != 0 && rt != 0 && rs == rt) {
12960 /* OPC_BLTZC */
12961 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12962 } else {
12963 /* OPC_BLTC */
12964 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12966 break;
12967 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12968 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12969 if (rs >= rt) {
12970 /* OPC_BOVC, OPC_BNVC */
12971 TCGv t2 = tcg_temp_new();
12972 TCGv t3 = tcg_temp_new();
12973 TCGv t4 = tcg_temp_new();
12974 TCGv input_overflow = tcg_temp_new();
12976 gen_load_gpr(t0, rs);
12977 gen_load_gpr(t1, rt);
12978 tcg_gen_ext32s_tl(t2, t0);
12979 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12980 tcg_gen_ext32s_tl(t3, t1);
12981 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12982 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12984 tcg_gen_add_tl(t4, t2, t3);
12985 tcg_gen_ext32s_tl(t4, t4);
12986 tcg_gen_xor_tl(t2, t2, t3);
12987 tcg_gen_xor_tl(t3, t4, t3);
12988 tcg_gen_andc_tl(t2, t3, t2);
12989 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12990 tcg_gen_or_tl(t4, t4, input_overflow);
12991 if (opc == OPC_BOVC) {
12992 /* OPC_BOVC */
12993 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12994 } else {
12995 /* OPC_BNVC */
12996 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12998 tcg_temp_free(input_overflow);
12999 tcg_temp_free(t4);
13000 tcg_temp_free(t3);
13001 tcg_temp_free(t2);
13002 } else if (rs < rt && rs == 0) {
13003 /* OPC_BEQZALC, OPC_BNEZALC */
13004 if (opc == OPC_BEQZALC) {
13005 /* OPC_BEQZALC */
13006 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13007 } else {
13008 /* OPC_BNEZALC */
13009 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13011 } else {
13012 /* OPC_BEQC, OPC_BNEC */
13013 if (opc == OPC_BEQC) {
13014 /* OPC_BEQC */
13015 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13016 } else {
13017 /* OPC_BNEC */
13018 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13021 break;
13022 case OPC_BEQZC:
13023 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13024 break;
13025 case OPC_BNEZC:
13026 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13027 break;
13028 default:
13029 MIPS_INVAL("Compact conditional branch/jump");
13030 generate_exception_end(ctx, EXCP_RI);
13031 goto out;
13034 /* Generating branch here as compact branches don't have delay slot */
13035 gen_goto_tb(ctx, 1, ctx->btarget);
13036 gen_set_label(fs);
13038 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13041 out:
13042 tcg_temp_free(t0);
13043 tcg_temp_free(t1);
13046 /* ISA extensions (ASEs) */
13047 /* MIPS16 extension to MIPS32 */
13049 /* MIPS16 major opcodes */
13050 enum {
13051 M16_OPC_ADDIUSP = 0x00,
13052 M16_OPC_ADDIUPC = 0x01,
13053 M16_OPC_B = 0x02,
13054 M16_OPC_JAL = 0x03,
13055 M16_OPC_BEQZ = 0x04,
13056 M16_OPC_BNEQZ = 0x05,
13057 M16_OPC_SHIFT = 0x06,
13058 M16_OPC_LD = 0x07,
13059 M16_OPC_RRIA = 0x08,
13060 M16_OPC_ADDIU8 = 0x09,
13061 M16_OPC_SLTI = 0x0a,
13062 M16_OPC_SLTIU = 0x0b,
13063 M16_OPC_I8 = 0x0c,
13064 M16_OPC_LI = 0x0d,
13065 M16_OPC_CMPI = 0x0e,
13066 M16_OPC_SD = 0x0f,
13067 M16_OPC_LB = 0x10,
13068 M16_OPC_LH = 0x11,
13069 M16_OPC_LWSP = 0x12,
13070 M16_OPC_LW = 0x13,
13071 M16_OPC_LBU = 0x14,
13072 M16_OPC_LHU = 0x15,
13073 M16_OPC_LWPC = 0x16,
13074 M16_OPC_LWU = 0x17,
13075 M16_OPC_SB = 0x18,
13076 M16_OPC_SH = 0x19,
13077 M16_OPC_SWSP = 0x1a,
13078 M16_OPC_SW = 0x1b,
13079 M16_OPC_RRR = 0x1c,
13080 M16_OPC_RR = 0x1d,
13081 M16_OPC_EXTEND = 0x1e,
13082 M16_OPC_I64 = 0x1f
13085 /* I8 funct field */
13086 enum {
13087 I8_BTEQZ = 0x0,
13088 I8_BTNEZ = 0x1,
13089 I8_SWRASP = 0x2,
13090 I8_ADJSP = 0x3,
13091 I8_SVRS = 0x4,
13092 I8_MOV32R = 0x5,
13093 I8_MOVR32 = 0x7
13096 /* RRR f field */
13097 enum {
13098 RRR_DADDU = 0x0,
13099 RRR_ADDU = 0x1,
13100 RRR_DSUBU = 0x2,
13101 RRR_SUBU = 0x3
13104 /* RR funct field */
13105 enum {
13106 RR_JR = 0x00,
13107 RR_SDBBP = 0x01,
13108 RR_SLT = 0x02,
13109 RR_SLTU = 0x03,
13110 RR_SLLV = 0x04,
13111 RR_BREAK = 0x05,
13112 RR_SRLV = 0x06,
13113 RR_SRAV = 0x07,
13114 RR_DSRL = 0x08,
13115 RR_CMP = 0x0a,
13116 RR_NEG = 0x0b,
13117 RR_AND = 0x0c,
13118 RR_OR = 0x0d,
13119 RR_XOR = 0x0e,
13120 RR_NOT = 0x0f,
13121 RR_MFHI = 0x10,
13122 RR_CNVT = 0x11,
13123 RR_MFLO = 0x12,
13124 RR_DSRA = 0x13,
13125 RR_DSLLV = 0x14,
13126 RR_DSRLV = 0x16,
13127 RR_DSRAV = 0x17,
13128 RR_MULT = 0x18,
13129 RR_MULTU = 0x19,
13130 RR_DIV = 0x1a,
13131 RR_DIVU = 0x1b,
13132 RR_DMULT = 0x1c,
13133 RR_DMULTU = 0x1d,
13134 RR_DDIV = 0x1e,
13135 RR_DDIVU = 0x1f
13138 /* I64 funct field */
13139 enum {
13140 I64_LDSP = 0x0,
13141 I64_SDSP = 0x1,
13142 I64_SDRASP = 0x2,
13143 I64_DADJSP = 0x3,
13144 I64_LDPC = 0x4,
13145 I64_DADDIU5 = 0x5,
13146 I64_DADDIUPC = 0x6,
13147 I64_DADDIUSP = 0x7
13150 /* RR ry field for CNVT */
13151 enum {
13152 RR_RY_CNVT_ZEB = 0x0,
13153 RR_RY_CNVT_ZEH = 0x1,
13154 RR_RY_CNVT_ZEW = 0x2,
13155 RR_RY_CNVT_SEB = 0x4,
13156 RR_RY_CNVT_SEH = 0x5,
13157 RR_RY_CNVT_SEW = 0x6,
13160 static int xlat (int r)
13162 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13164 return map[r];
13167 static void gen_mips16_save (DisasContext *ctx,
13168 int xsregs, int aregs,
13169 int do_ra, int do_s0, int do_s1,
13170 int framesize)
13172 TCGv t0 = tcg_temp_new();
13173 TCGv t1 = tcg_temp_new();
13174 TCGv t2 = tcg_temp_new();
13175 int args, astatic;
13177 switch (aregs) {
13178 case 0:
13179 case 1:
13180 case 2:
13181 case 3:
13182 case 11:
13183 args = 0;
13184 break;
13185 case 4:
13186 case 5:
13187 case 6:
13188 case 7:
13189 args = 1;
13190 break;
13191 case 8:
13192 case 9:
13193 case 10:
13194 args = 2;
13195 break;
13196 case 12:
13197 case 13:
13198 args = 3;
13199 break;
13200 case 14:
13201 args = 4;
13202 break;
13203 default:
13204 generate_exception_end(ctx, EXCP_RI);
13205 return;
13208 switch (args) {
13209 case 4:
13210 gen_base_offset_addr(ctx, t0, 29, 12);
13211 gen_load_gpr(t1, 7);
13212 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13213 /* Fall through */
13214 case 3:
13215 gen_base_offset_addr(ctx, t0, 29, 8);
13216 gen_load_gpr(t1, 6);
13217 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13218 /* Fall through */
13219 case 2:
13220 gen_base_offset_addr(ctx, t0, 29, 4);
13221 gen_load_gpr(t1, 5);
13222 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13223 /* Fall through */
13224 case 1:
13225 gen_base_offset_addr(ctx, t0, 29, 0);
13226 gen_load_gpr(t1, 4);
13227 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13230 gen_load_gpr(t0, 29);
13232 #define DECR_AND_STORE(reg) do { \
13233 tcg_gen_movi_tl(t2, -4); \
13234 gen_op_addr_add(ctx, t0, t0, t2); \
13235 gen_load_gpr(t1, reg); \
13236 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13237 } while (0)
13239 if (do_ra) {
13240 DECR_AND_STORE(31);
13243 switch (xsregs) {
13244 case 7:
13245 DECR_AND_STORE(30);
13246 /* Fall through */
13247 case 6:
13248 DECR_AND_STORE(23);
13249 /* Fall through */
13250 case 5:
13251 DECR_AND_STORE(22);
13252 /* Fall through */
13253 case 4:
13254 DECR_AND_STORE(21);
13255 /* Fall through */
13256 case 3:
13257 DECR_AND_STORE(20);
13258 /* Fall through */
13259 case 2:
13260 DECR_AND_STORE(19);
13261 /* Fall through */
13262 case 1:
13263 DECR_AND_STORE(18);
13266 if (do_s1) {
13267 DECR_AND_STORE(17);
13269 if (do_s0) {
13270 DECR_AND_STORE(16);
13273 switch (aregs) {
13274 case 0:
13275 case 4:
13276 case 8:
13277 case 12:
13278 case 14:
13279 astatic = 0;
13280 break;
13281 case 1:
13282 case 5:
13283 case 9:
13284 case 13:
13285 astatic = 1;
13286 break;
13287 case 2:
13288 case 6:
13289 case 10:
13290 astatic = 2;
13291 break;
13292 case 3:
13293 case 7:
13294 astatic = 3;
13295 break;
13296 case 11:
13297 astatic = 4;
13298 break;
13299 default:
13300 generate_exception_end(ctx, EXCP_RI);
13301 return;
13304 if (astatic > 0) {
13305 DECR_AND_STORE(7);
13306 if (astatic > 1) {
13307 DECR_AND_STORE(6);
13308 if (astatic > 2) {
13309 DECR_AND_STORE(5);
13310 if (astatic > 3) {
13311 DECR_AND_STORE(4);
13316 #undef DECR_AND_STORE
13318 tcg_gen_movi_tl(t2, -framesize);
13319 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13320 tcg_temp_free(t0);
13321 tcg_temp_free(t1);
13322 tcg_temp_free(t2);
13325 static void gen_mips16_restore (DisasContext *ctx,
13326 int xsregs, int aregs,
13327 int do_ra, int do_s0, int do_s1,
13328 int framesize)
13330 int astatic;
13331 TCGv t0 = tcg_temp_new();
13332 TCGv t1 = tcg_temp_new();
13333 TCGv t2 = tcg_temp_new();
13335 tcg_gen_movi_tl(t2, framesize);
13336 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13338 #define DECR_AND_LOAD(reg) do { \
13339 tcg_gen_movi_tl(t2, -4); \
13340 gen_op_addr_add(ctx, t0, t0, t2); \
13341 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13342 gen_store_gpr(t1, reg); \
13343 } while (0)
13345 if (do_ra) {
13346 DECR_AND_LOAD(31);
13349 switch (xsregs) {
13350 case 7:
13351 DECR_AND_LOAD(30);
13352 /* Fall through */
13353 case 6:
13354 DECR_AND_LOAD(23);
13355 /* Fall through */
13356 case 5:
13357 DECR_AND_LOAD(22);
13358 /* Fall through */
13359 case 4:
13360 DECR_AND_LOAD(21);
13361 /* Fall through */
13362 case 3:
13363 DECR_AND_LOAD(20);
13364 /* Fall through */
13365 case 2:
13366 DECR_AND_LOAD(19);
13367 /* Fall through */
13368 case 1:
13369 DECR_AND_LOAD(18);
13372 if (do_s1) {
13373 DECR_AND_LOAD(17);
13375 if (do_s0) {
13376 DECR_AND_LOAD(16);
13379 switch (aregs) {
13380 case 0:
13381 case 4:
13382 case 8:
13383 case 12:
13384 case 14:
13385 astatic = 0;
13386 break;
13387 case 1:
13388 case 5:
13389 case 9:
13390 case 13:
13391 astatic = 1;
13392 break;
13393 case 2:
13394 case 6:
13395 case 10:
13396 astatic = 2;
13397 break;
13398 case 3:
13399 case 7:
13400 astatic = 3;
13401 break;
13402 case 11:
13403 astatic = 4;
13404 break;
13405 default:
13406 generate_exception_end(ctx, EXCP_RI);
13407 return;
13410 if (astatic > 0) {
13411 DECR_AND_LOAD(7);
13412 if (astatic > 1) {
13413 DECR_AND_LOAD(6);
13414 if (astatic > 2) {
13415 DECR_AND_LOAD(5);
13416 if (astatic > 3) {
13417 DECR_AND_LOAD(4);
13422 #undef DECR_AND_LOAD
13424 tcg_gen_movi_tl(t2, framesize);
13425 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13426 tcg_temp_free(t0);
13427 tcg_temp_free(t1);
13428 tcg_temp_free(t2);
13431 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13432 int is_64_bit, int extended)
13434 TCGv t0;
13436 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13437 generate_exception_end(ctx, EXCP_RI);
13438 return;
13441 t0 = tcg_temp_new();
13443 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13444 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13445 if (!is_64_bit) {
13446 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13449 tcg_temp_free(t0);
13452 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13453 int16_t offset)
13455 TCGv_i32 t0 = tcg_const_i32(op);
13456 TCGv t1 = tcg_temp_new();
13457 gen_base_offset_addr(ctx, t1, base, offset);
13458 gen_helper_cache(cpu_env, t1, t0);
13461 #if defined(TARGET_MIPS64)
13462 static void decode_i64_mips16 (DisasContext *ctx,
13463 int ry, int funct, int16_t offset,
13464 int extended)
13466 switch (funct) {
13467 case I64_LDSP:
13468 check_insn(ctx, ISA_MIPS3);
13469 check_mips_64(ctx);
13470 offset = extended ? offset : offset << 3;
13471 gen_ld(ctx, OPC_LD, ry, 29, offset);
13472 break;
13473 case I64_SDSP:
13474 check_insn(ctx, ISA_MIPS3);
13475 check_mips_64(ctx);
13476 offset = extended ? offset : offset << 3;
13477 gen_st(ctx, OPC_SD, ry, 29, offset);
13478 break;
13479 case I64_SDRASP:
13480 check_insn(ctx, ISA_MIPS3);
13481 check_mips_64(ctx);
13482 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13483 gen_st(ctx, OPC_SD, 31, 29, offset);
13484 break;
13485 case I64_DADJSP:
13486 check_insn(ctx, ISA_MIPS3);
13487 check_mips_64(ctx);
13488 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13489 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13490 break;
13491 case I64_LDPC:
13492 check_insn(ctx, ISA_MIPS3);
13493 check_mips_64(ctx);
13494 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13495 generate_exception_end(ctx, EXCP_RI);
13496 } else {
13497 offset = extended ? offset : offset << 3;
13498 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13500 break;
13501 case I64_DADDIU5:
13502 check_insn(ctx, ISA_MIPS3);
13503 check_mips_64(ctx);
13504 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13505 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13506 break;
13507 case I64_DADDIUPC:
13508 check_insn(ctx, ISA_MIPS3);
13509 check_mips_64(ctx);
13510 offset = extended ? offset : offset << 2;
13511 gen_addiupc(ctx, ry, offset, 1, extended);
13512 break;
13513 case I64_DADDIUSP:
13514 check_insn(ctx, ISA_MIPS3);
13515 check_mips_64(ctx);
13516 offset = extended ? offset : offset << 2;
13517 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13518 break;
13521 #endif
13523 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13525 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13526 int op, rx, ry, funct, sa;
13527 int16_t imm, offset;
13529 ctx->opcode = (ctx->opcode << 16) | extend;
13530 op = (ctx->opcode >> 11) & 0x1f;
13531 sa = (ctx->opcode >> 22) & 0x1f;
13532 funct = (ctx->opcode >> 8) & 0x7;
13533 rx = xlat((ctx->opcode >> 8) & 0x7);
13534 ry = xlat((ctx->opcode >> 5) & 0x7);
13535 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13536 | ((ctx->opcode >> 21) & 0x3f) << 5
13537 | (ctx->opcode & 0x1f));
13539 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13540 counterparts. */
13541 switch (op) {
13542 case M16_OPC_ADDIUSP:
13543 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13544 break;
13545 case M16_OPC_ADDIUPC:
13546 gen_addiupc(ctx, rx, imm, 0, 1);
13547 break;
13548 case M16_OPC_B:
13549 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13550 /* No delay slot, so just process as a normal instruction */
13551 break;
13552 case M16_OPC_BEQZ:
13553 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13554 /* No delay slot, so just process as a normal instruction */
13555 break;
13556 case M16_OPC_BNEQZ:
13557 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13558 /* No delay slot, so just process as a normal instruction */
13559 break;
13560 case M16_OPC_SHIFT:
13561 switch (ctx->opcode & 0x3) {
13562 case 0x0:
13563 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13564 break;
13565 case 0x1:
13566 #if defined(TARGET_MIPS64)
13567 check_mips_64(ctx);
13568 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13569 #else
13570 generate_exception_end(ctx, EXCP_RI);
13571 #endif
13572 break;
13573 case 0x2:
13574 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13575 break;
13576 case 0x3:
13577 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13578 break;
13580 break;
13581 #if defined(TARGET_MIPS64)
13582 case M16_OPC_LD:
13583 check_insn(ctx, ISA_MIPS3);
13584 check_mips_64(ctx);
13585 gen_ld(ctx, OPC_LD, ry, rx, offset);
13586 break;
13587 #endif
13588 case M16_OPC_RRIA:
13589 imm = ctx->opcode & 0xf;
13590 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13591 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13592 imm = (int16_t) (imm << 1) >> 1;
13593 if ((ctx->opcode >> 4) & 0x1) {
13594 #if defined(TARGET_MIPS64)
13595 check_mips_64(ctx);
13596 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13597 #else
13598 generate_exception_end(ctx, EXCP_RI);
13599 #endif
13600 } else {
13601 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13603 break;
13604 case M16_OPC_ADDIU8:
13605 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13606 break;
13607 case M16_OPC_SLTI:
13608 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13609 break;
13610 case M16_OPC_SLTIU:
13611 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13612 break;
13613 case M16_OPC_I8:
13614 switch (funct) {
13615 case I8_BTEQZ:
13616 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13617 break;
13618 case I8_BTNEZ:
13619 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13620 break;
13621 case I8_SWRASP:
13622 gen_st(ctx, OPC_SW, 31, 29, imm);
13623 break;
13624 case I8_ADJSP:
13625 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13626 break;
13627 case I8_SVRS:
13628 check_insn(ctx, ISA_MIPS32);
13630 int xsregs = (ctx->opcode >> 24) & 0x7;
13631 int aregs = (ctx->opcode >> 16) & 0xf;
13632 int do_ra = (ctx->opcode >> 6) & 0x1;
13633 int do_s0 = (ctx->opcode >> 5) & 0x1;
13634 int do_s1 = (ctx->opcode >> 4) & 0x1;
13635 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13636 | (ctx->opcode & 0xf)) << 3;
13638 if (ctx->opcode & (1 << 7)) {
13639 gen_mips16_save(ctx, xsregs, aregs,
13640 do_ra, do_s0, do_s1,
13641 framesize);
13642 } else {
13643 gen_mips16_restore(ctx, xsregs, aregs,
13644 do_ra, do_s0, do_s1,
13645 framesize);
13648 break;
13649 default:
13650 generate_exception_end(ctx, EXCP_RI);
13651 break;
13653 break;
13654 case M16_OPC_LI:
13655 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13656 break;
13657 case M16_OPC_CMPI:
13658 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13659 break;
13660 #if defined(TARGET_MIPS64)
13661 case M16_OPC_SD:
13662 check_insn(ctx, ISA_MIPS3);
13663 check_mips_64(ctx);
13664 gen_st(ctx, OPC_SD, ry, rx, offset);
13665 break;
13666 #endif
13667 case M16_OPC_LB:
13668 gen_ld(ctx, OPC_LB, ry, rx, offset);
13669 break;
13670 case M16_OPC_LH:
13671 gen_ld(ctx, OPC_LH, ry, rx, offset);
13672 break;
13673 case M16_OPC_LWSP:
13674 gen_ld(ctx, OPC_LW, rx, 29, offset);
13675 break;
13676 case M16_OPC_LW:
13677 gen_ld(ctx, OPC_LW, ry, rx, offset);
13678 break;
13679 case M16_OPC_LBU:
13680 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13681 break;
13682 case M16_OPC_LHU:
13683 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13684 break;
13685 case M16_OPC_LWPC:
13686 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13687 break;
13688 #if defined(TARGET_MIPS64)
13689 case M16_OPC_LWU:
13690 check_insn(ctx, ISA_MIPS3);
13691 check_mips_64(ctx);
13692 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13693 break;
13694 #endif
13695 case M16_OPC_SB:
13696 gen_st(ctx, OPC_SB, ry, rx, offset);
13697 break;
13698 case M16_OPC_SH:
13699 gen_st(ctx, OPC_SH, ry, rx, offset);
13700 break;
13701 case M16_OPC_SWSP:
13702 gen_st(ctx, OPC_SW, rx, 29, offset);
13703 break;
13704 case M16_OPC_SW:
13705 gen_st(ctx, OPC_SW, ry, rx, offset);
13706 break;
13707 #if defined(TARGET_MIPS64)
13708 case M16_OPC_I64:
13709 decode_i64_mips16(ctx, ry, funct, offset, 1);
13710 break;
13711 #endif
13712 default:
13713 generate_exception_end(ctx, EXCP_RI);
13714 break;
13717 return 4;
13720 static inline bool is_uhi(int sdbbp_code)
13722 #ifdef CONFIG_USER_ONLY
13723 return false;
13724 #else
13725 return semihosting_enabled() && sdbbp_code == 1;
13726 #endif
13729 #ifdef CONFIG_USER_ONLY
13730 /* The above should dead-code away any calls to this..*/
13731 static inline void gen_helper_do_semihosting(void *env)
13733 g_assert_not_reached();
13735 #endif
13737 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13739 int rx, ry;
13740 int sa;
13741 int op, cnvt_op, op1, offset;
13742 int funct;
13743 int n_bytes;
13745 op = (ctx->opcode >> 11) & 0x1f;
13746 sa = (ctx->opcode >> 2) & 0x7;
13747 sa = sa == 0 ? 8 : sa;
13748 rx = xlat((ctx->opcode >> 8) & 0x7);
13749 cnvt_op = (ctx->opcode >> 5) & 0x7;
13750 ry = xlat((ctx->opcode >> 5) & 0x7);
13751 op1 = offset = ctx->opcode & 0x1f;
13753 n_bytes = 2;
13755 switch (op) {
13756 case M16_OPC_ADDIUSP:
13758 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13760 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13762 break;
13763 case M16_OPC_ADDIUPC:
13764 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13765 break;
13766 case M16_OPC_B:
13767 offset = (ctx->opcode & 0x7ff) << 1;
13768 offset = (int16_t)(offset << 4) >> 4;
13769 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13770 /* No delay slot, so just process as a normal instruction */
13771 break;
13772 case M16_OPC_JAL:
13773 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13774 offset = (((ctx->opcode & 0x1f) << 21)
13775 | ((ctx->opcode >> 5) & 0x1f) << 16
13776 | offset) << 2;
13777 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13778 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13779 n_bytes = 4;
13780 break;
13781 case M16_OPC_BEQZ:
13782 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13783 ((int8_t)ctx->opcode) << 1, 0);
13784 /* No delay slot, so just process as a normal instruction */
13785 break;
13786 case M16_OPC_BNEQZ:
13787 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13788 ((int8_t)ctx->opcode) << 1, 0);
13789 /* No delay slot, so just process as a normal instruction */
13790 break;
13791 case M16_OPC_SHIFT:
13792 switch (ctx->opcode & 0x3) {
13793 case 0x0:
13794 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13795 break;
13796 case 0x1:
13797 #if defined(TARGET_MIPS64)
13798 check_insn(ctx, ISA_MIPS3);
13799 check_mips_64(ctx);
13800 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13801 #else
13802 generate_exception_end(ctx, EXCP_RI);
13803 #endif
13804 break;
13805 case 0x2:
13806 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13807 break;
13808 case 0x3:
13809 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13810 break;
13812 break;
13813 #if defined(TARGET_MIPS64)
13814 case M16_OPC_LD:
13815 check_insn(ctx, ISA_MIPS3);
13816 check_mips_64(ctx);
13817 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13818 break;
13819 #endif
13820 case M16_OPC_RRIA:
13822 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13824 if ((ctx->opcode >> 4) & 1) {
13825 #if defined(TARGET_MIPS64)
13826 check_insn(ctx, ISA_MIPS3);
13827 check_mips_64(ctx);
13828 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13829 #else
13830 generate_exception_end(ctx, EXCP_RI);
13831 #endif
13832 } else {
13833 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13836 break;
13837 case M16_OPC_ADDIU8:
13839 int16_t imm = (int8_t) ctx->opcode;
13841 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13843 break;
13844 case M16_OPC_SLTI:
13846 int16_t imm = (uint8_t) ctx->opcode;
13847 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13849 break;
13850 case M16_OPC_SLTIU:
13852 int16_t imm = (uint8_t) ctx->opcode;
13853 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13855 break;
13856 case M16_OPC_I8:
13858 int reg32;
13860 funct = (ctx->opcode >> 8) & 0x7;
13861 switch (funct) {
13862 case I8_BTEQZ:
13863 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13864 ((int8_t)ctx->opcode) << 1, 0);
13865 break;
13866 case I8_BTNEZ:
13867 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13868 ((int8_t)ctx->opcode) << 1, 0);
13869 break;
13870 case I8_SWRASP:
13871 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13872 break;
13873 case I8_ADJSP:
13874 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13875 ((int8_t)ctx->opcode) << 3);
13876 break;
13877 case I8_SVRS:
13878 check_insn(ctx, ISA_MIPS32);
13880 int do_ra = ctx->opcode & (1 << 6);
13881 int do_s0 = ctx->opcode & (1 << 5);
13882 int do_s1 = ctx->opcode & (1 << 4);
13883 int framesize = ctx->opcode & 0xf;
13885 if (framesize == 0) {
13886 framesize = 128;
13887 } else {
13888 framesize = framesize << 3;
13891 if (ctx->opcode & (1 << 7)) {
13892 gen_mips16_save(ctx, 0, 0,
13893 do_ra, do_s0, do_s1, framesize);
13894 } else {
13895 gen_mips16_restore(ctx, 0, 0,
13896 do_ra, do_s0, do_s1, framesize);
13899 break;
13900 case I8_MOV32R:
13902 int rz = xlat(ctx->opcode & 0x7);
13904 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13905 ((ctx->opcode >> 5) & 0x7);
13906 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13908 break;
13909 case I8_MOVR32:
13910 reg32 = ctx->opcode & 0x1f;
13911 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13912 break;
13913 default:
13914 generate_exception_end(ctx, EXCP_RI);
13915 break;
13918 break;
13919 case M16_OPC_LI:
13921 int16_t imm = (uint8_t) ctx->opcode;
13923 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13925 break;
13926 case M16_OPC_CMPI:
13928 int16_t imm = (uint8_t) ctx->opcode;
13929 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13931 break;
13932 #if defined(TARGET_MIPS64)
13933 case M16_OPC_SD:
13934 check_insn(ctx, ISA_MIPS3);
13935 check_mips_64(ctx);
13936 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13937 break;
13938 #endif
13939 case M16_OPC_LB:
13940 gen_ld(ctx, OPC_LB, ry, rx, offset);
13941 break;
13942 case M16_OPC_LH:
13943 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13944 break;
13945 case M16_OPC_LWSP:
13946 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13947 break;
13948 case M16_OPC_LW:
13949 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13950 break;
13951 case M16_OPC_LBU:
13952 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13953 break;
13954 case M16_OPC_LHU:
13955 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13956 break;
13957 case M16_OPC_LWPC:
13958 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13959 break;
13960 #if defined (TARGET_MIPS64)
13961 case M16_OPC_LWU:
13962 check_insn(ctx, ISA_MIPS3);
13963 check_mips_64(ctx);
13964 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13965 break;
13966 #endif
13967 case M16_OPC_SB:
13968 gen_st(ctx, OPC_SB, ry, rx, offset);
13969 break;
13970 case M16_OPC_SH:
13971 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13972 break;
13973 case M16_OPC_SWSP:
13974 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13975 break;
13976 case M16_OPC_SW:
13977 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13978 break;
13979 case M16_OPC_RRR:
13981 int rz = xlat((ctx->opcode >> 2) & 0x7);
13982 int mips32_op;
13984 switch (ctx->opcode & 0x3) {
13985 case RRR_ADDU:
13986 mips32_op = OPC_ADDU;
13987 break;
13988 case RRR_SUBU:
13989 mips32_op = OPC_SUBU;
13990 break;
13991 #if defined(TARGET_MIPS64)
13992 case RRR_DADDU:
13993 mips32_op = OPC_DADDU;
13994 check_insn(ctx, ISA_MIPS3);
13995 check_mips_64(ctx);
13996 break;
13997 case RRR_DSUBU:
13998 mips32_op = OPC_DSUBU;
13999 check_insn(ctx, ISA_MIPS3);
14000 check_mips_64(ctx);
14001 break;
14002 #endif
14003 default:
14004 generate_exception_end(ctx, EXCP_RI);
14005 goto done;
14008 gen_arith(ctx, mips32_op, rz, rx, ry);
14009 done:
14012 break;
14013 case M16_OPC_RR:
14014 switch (op1) {
14015 case RR_JR:
14017 int nd = (ctx->opcode >> 7) & 0x1;
14018 int link = (ctx->opcode >> 6) & 0x1;
14019 int ra = (ctx->opcode >> 5) & 0x1;
14021 if (nd) {
14022 check_insn(ctx, ISA_MIPS32);
14025 if (link) {
14026 op = OPC_JALR;
14027 } else {
14028 op = OPC_JR;
14031 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14032 (nd ? 0 : 2));
14034 break;
14035 case RR_SDBBP:
14036 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14037 gen_helper_do_semihosting(cpu_env);
14038 } else {
14039 /* XXX: not clear which exception should be raised
14040 * when in debug mode...
14042 check_insn(ctx, ISA_MIPS32);
14043 generate_exception_end(ctx, EXCP_DBp);
14045 break;
14046 case RR_SLT:
14047 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14048 break;
14049 case RR_SLTU:
14050 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14051 break;
14052 case RR_BREAK:
14053 generate_exception_end(ctx, EXCP_BREAK);
14054 break;
14055 case RR_SLLV:
14056 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14057 break;
14058 case RR_SRLV:
14059 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14060 break;
14061 case RR_SRAV:
14062 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14063 break;
14064 #if defined (TARGET_MIPS64)
14065 case RR_DSRL:
14066 check_insn(ctx, ISA_MIPS3);
14067 check_mips_64(ctx);
14068 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14069 break;
14070 #endif
14071 case RR_CMP:
14072 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14073 break;
14074 case RR_NEG:
14075 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14076 break;
14077 case RR_AND:
14078 gen_logic(ctx, OPC_AND, rx, rx, ry);
14079 break;
14080 case RR_OR:
14081 gen_logic(ctx, OPC_OR, rx, rx, ry);
14082 break;
14083 case RR_XOR:
14084 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14085 break;
14086 case RR_NOT:
14087 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14088 break;
14089 case RR_MFHI:
14090 gen_HILO(ctx, OPC_MFHI, 0, rx);
14091 break;
14092 case RR_CNVT:
14093 check_insn(ctx, ISA_MIPS32);
14094 switch (cnvt_op) {
14095 case RR_RY_CNVT_ZEB:
14096 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14097 break;
14098 case RR_RY_CNVT_ZEH:
14099 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14100 break;
14101 case RR_RY_CNVT_SEB:
14102 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14103 break;
14104 case RR_RY_CNVT_SEH:
14105 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14106 break;
14107 #if defined (TARGET_MIPS64)
14108 case RR_RY_CNVT_ZEW:
14109 check_insn(ctx, ISA_MIPS64);
14110 check_mips_64(ctx);
14111 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14112 break;
14113 case RR_RY_CNVT_SEW:
14114 check_insn(ctx, ISA_MIPS64);
14115 check_mips_64(ctx);
14116 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14117 break;
14118 #endif
14119 default:
14120 generate_exception_end(ctx, EXCP_RI);
14121 break;
14123 break;
14124 case RR_MFLO:
14125 gen_HILO(ctx, OPC_MFLO, 0, rx);
14126 break;
14127 #if defined (TARGET_MIPS64)
14128 case RR_DSRA:
14129 check_insn(ctx, ISA_MIPS3);
14130 check_mips_64(ctx);
14131 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14132 break;
14133 case RR_DSLLV:
14134 check_insn(ctx, ISA_MIPS3);
14135 check_mips_64(ctx);
14136 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14137 break;
14138 case RR_DSRLV:
14139 check_insn(ctx, ISA_MIPS3);
14140 check_mips_64(ctx);
14141 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14142 break;
14143 case RR_DSRAV:
14144 check_insn(ctx, ISA_MIPS3);
14145 check_mips_64(ctx);
14146 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14147 break;
14148 #endif
14149 case RR_MULT:
14150 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14151 break;
14152 case RR_MULTU:
14153 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14154 break;
14155 case RR_DIV:
14156 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14157 break;
14158 case RR_DIVU:
14159 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14160 break;
14161 #if defined (TARGET_MIPS64)
14162 case RR_DMULT:
14163 check_insn(ctx, ISA_MIPS3);
14164 check_mips_64(ctx);
14165 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14166 break;
14167 case RR_DMULTU:
14168 check_insn(ctx, ISA_MIPS3);
14169 check_mips_64(ctx);
14170 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14171 break;
14172 case RR_DDIV:
14173 check_insn(ctx, ISA_MIPS3);
14174 check_mips_64(ctx);
14175 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14176 break;
14177 case RR_DDIVU:
14178 check_insn(ctx, ISA_MIPS3);
14179 check_mips_64(ctx);
14180 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14181 break;
14182 #endif
14183 default:
14184 generate_exception_end(ctx, EXCP_RI);
14185 break;
14187 break;
14188 case M16_OPC_EXTEND:
14189 decode_extended_mips16_opc(env, ctx);
14190 n_bytes = 4;
14191 break;
14192 #if defined(TARGET_MIPS64)
14193 case M16_OPC_I64:
14194 funct = (ctx->opcode >> 8) & 0x7;
14195 decode_i64_mips16(ctx, ry, funct, offset, 0);
14196 break;
14197 #endif
14198 default:
14199 generate_exception_end(ctx, EXCP_RI);
14200 break;
14203 return n_bytes;
14206 /* microMIPS extension to MIPS32/MIPS64 */
14209 * microMIPS32/microMIPS64 major opcodes
14211 * 1. MIPS Architecture for Programmers Volume II-B:
14212 * The microMIPS32 Instruction Set (Revision 3.05)
14214 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14216 * 2. MIPS Architecture For Programmers Volume II-A:
14217 * The MIPS64 Instruction Set (Revision 3.51)
14220 enum {
14221 POOL32A = 0x00,
14222 POOL16A = 0x01,
14223 LBU16 = 0x02,
14224 MOVE16 = 0x03,
14225 ADDI32 = 0x04,
14226 R6_LUI = 0x04,
14227 AUI = 0x04,
14228 LBU32 = 0x05,
14229 SB32 = 0x06,
14230 LB32 = 0x07,
14232 POOL32B = 0x08,
14233 POOL16B = 0x09,
14234 LHU16 = 0x0a,
14235 ANDI16 = 0x0b,
14236 ADDIU32 = 0x0c,
14237 LHU32 = 0x0d,
14238 SH32 = 0x0e,
14239 LH32 = 0x0f,
14241 POOL32I = 0x10,
14242 POOL16C = 0x11,
14243 LWSP16 = 0x12,
14244 POOL16D = 0x13,
14245 ORI32 = 0x14,
14246 POOL32F = 0x15,
14247 POOL32S = 0x16, /* MIPS64 */
14248 DADDIU32 = 0x17, /* MIPS64 */
14250 POOL32C = 0x18,
14251 LWGP16 = 0x19,
14252 LW16 = 0x1a,
14253 POOL16E = 0x1b,
14254 XORI32 = 0x1c,
14255 JALS32 = 0x1d,
14256 BOVC = 0x1d,
14257 BEQC = 0x1d,
14258 BEQZALC = 0x1d,
14259 ADDIUPC = 0x1e,
14260 PCREL = 0x1e,
14261 BNVC = 0x1f,
14262 BNEC = 0x1f,
14263 BNEZALC = 0x1f,
14265 R6_BEQZC = 0x20,
14266 JIC = 0x20,
14267 POOL16F = 0x21,
14268 SB16 = 0x22,
14269 BEQZ16 = 0x23,
14270 BEQZC16 = 0x23,
14271 SLTI32 = 0x24,
14272 BEQ32 = 0x25,
14273 BC = 0x25,
14274 SWC132 = 0x26,
14275 LWC132 = 0x27,
14277 /* 0x29 is reserved */
14278 RES_29 = 0x29,
14279 R6_BNEZC = 0x28,
14280 JIALC = 0x28,
14281 SH16 = 0x2a,
14282 BNEZ16 = 0x2b,
14283 BNEZC16 = 0x2b,
14284 SLTIU32 = 0x2c,
14285 BNE32 = 0x2d,
14286 BALC = 0x2d,
14287 SDC132 = 0x2e,
14288 LDC132 = 0x2f,
14290 /* 0x31 is reserved */
14291 RES_31 = 0x31,
14292 BLEZALC = 0x30,
14293 BGEZALC = 0x30,
14294 BGEUC = 0x30,
14295 SWSP16 = 0x32,
14296 B16 = 0x33,
14297 BC16 = 0x33,
14298 ANDI32 = 0x34,
14299 J32 = 0x35,
14300 BGTZC = 0x35,
14301 BLTZC = 0x35,
14302 BLTC = 0x35,
14303 SD32 = 0x36, /* MIPS64 */
14304 LD32 = 0x37, /* MIPS64 */
14306 /* 0x39 is reserved */
14307 RES_39 = 0x39,
14308 BGTZALC = 0x38,
14309 BLTZALC = 0x38,
14310 BLTUC = 0x38,
14311 SW16 = 0x3a,
14312 LI16 = 0x3b,
14313 JALX32 = 0x3c,
14314 JAL32 = 0x3d,
14315 BLEZC = 0x3d,
14316 BGEZC = 0x3d,
14317 BGEC = 0x3d,
14318 SW32 = 0x3e,
14319 LW32 = 0x3f
14322 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14323 enum {
14324 ADDIUPC_00 = 0x00,
14325 ADDIUPC_01 = 0x01,
14326 ADDIUPC_02 = 0x02,
14327 ADDIUPC_03 = 0x03,
14328 ADDIUPC_04 = 0x04,
14329 ADDIUPC_05 = 0x05,
14330 ADDIUPC_06 = 0x06,
14331 ADDIUPC_07 = 0x07,
14332 AUIPC = 0x1e,
14333 ALUIPC = 0x1f,
14334 LWPC_08 = 0x08,
14335 LWPC_09 = 0x09,
14336 LWPC_0A = 0x0A,
14337 LWPC_0B = 0x0B,
14338 LWPC_0C = 0x0C,
14339 LWPC_0D = 0x0D,
14340 LWPC_0E = 0x0E,
14341 LWPC_0F = 0x0F,
14344 /* POOL32A encoding of minor opcode field */
14346 enum {
14347 /* These opcodes are distinguished only by bits 9..6; those bits are
14348 * what are recorded below. */
14349 SLL32 = 0x0,
14350 SRL32 = 0x1,
14351 SRA = 0x2,
14352 ROTR = 0x3,
14353 SELEQZ = 0x5,
14354 SELNEZ = 0x6,
14355 R6_RDHWR = 0x7,
14357 SLLV = 0x0,
14358 SRLV = 0x1,
14359 SRAV = 0x2,
14360 ROTRV = 0x3,
14361 ADD = 0x4,
14362 ADDU32 = 0x5,
14363 SUB = 0x6,
14364 SUBU32 = 0x7,
14365 MUL = 0x8,
14366 AND = 0x9,
14367 OR32 = 0xa,
14368 NOR = 0xb,
14369 XOR32 = 0xc,
14370 SLT = 0xd,
14371 SLTU = 0xe,
14373 MOVN = 0x0,
14374 R6_MUL = 0x0,
14375 MOVZ = 0x1,
14376 MUH = 0x1,
14377 MULU = 0x2,
14378 MUHU = 0x3,
14379 LWXS = 0x4,
14380 R6_DIV = 0x4,
14381 MOD = 0x5,
14382 R6_DIVU = 0x6,
14383 MODU = 0x7,
14385 /* The following can be distinguished by their lower 6 bits. */
14386 BREAK32 = 0x07,
14387 INS = 0x0c,
14388 LSA = 0x0f,
14389 ALIGN = 0x1f,
14390 EXT = 0x2c,
14391 POOL32AXF = 0x3c,
14392 SIGRIE = 0x3f
14395 /* POOL32AXF encoding of minor opcode field extension */
14398 * 1. MIPS Architecture for Programmers Volume II-B:
14399 * The microMIPS32 Instruction Set (Revision 3.05)
14401 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14403 * 2. MIPS Architecture for Programmers VolumeIV-e:
14404 * The MIPS DSP Application-Specific Extension
14405 * to the microMIPS32 Architecture (Revision 2.34)
14407 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14410 enum {
14411 /* bits 11..6 */
14412 TEQ = 0x00,
14413 TGE = 0x08,
14414 TGEU = 0x10,
14415 TLT = 0x20,
14416 TLTU = 0x28,
14417 TNE = 0x30,
14419 MFC0 = 0x03,
14420 MTC0 = 0x0b,
14422 /* begin of microMIPS32 DSP */
14424 /* bits 13..12 for 0x01 */
14425 MFHI_ACC = 0x0,
14426 MFLO_ACC = 0x1,
14427 MTHI_ACC = 0x2,
14428 MTLO_ACC = 0x3,
14430 /* bits 13..12 for 0x2a */
14431 MADD_ACC = 0x0,
14432 MADDU_ACC = 0x1,
14433 MSUB_ACC = 0x2,
14434 MSUBU_ACC = 0x3,
14436 /* bits 13..12 for 0x32 */
14437 MULT_ACC = 0x0,
14438 MULTU_ACC = 0x1,
14440 /* end of microMIPS32 DSP */
14442 /* bits 15..12 for 0x2c */
14443 BITSWAP = 0x0,
14444 SEB = 0x2,
14445 SEH = 0x3,
14446 CLO = 0x4,
14447 CLZ = 0x5,
14448 RDHWR = 0x6,
14449 WSBH = 0x7,
14450 MULT = 0x8,
14451 MULTU = 0x9,
14452 DIV = 0xa,
14453 DIVU = 0xb,
14454 MADD = 0xc,
14455 MADDU = 0xd,
14456 MSUB = 0xe,
14457 MSUBU = 0xf,
14459 /* bits 15..12 for 0x34 */
14460 MFC2 = 0x4,
14461 MTC2 = 0x5,
14462 MFHC2 = 0x8,
14463 MTHC2 = 0x9,
14464 CFC2 = 0xc,
14465 CTC2 = 0xd,
14467 /* bits 15..12 for 0x3c */
14468 JALR = 0x0,
14469 JR = 0x0, /* alias */
14470 JALRC = 0x0,
14471 JRC = 0x0,
14472 JALR_HB = 0x1,
14473 JALRC_HB = 0x1,
14474 JALRS = 0x4,
14475 JALRS_HB = 0x5,
14477 /* bits 15..12 for 0x05 */
14478 RDPGPR = 0xe,
14479 WRPGPR = 0xf,
14481 /* bits 15..12 for 0x0d */
14482 TLBP = 0x0,
14483 TLBR = 0x1,
14484 TLBWI = 0x2,
14485 TLBWR = 0x3,
14486 TLBINV = 0x4,
14487 TLBINVF = 0x5,
14488 WAIT = 0x9,
14489 IRET = 0xd,
14490 DERET = 0xe,
14491 ERET = 0xf,
14493 /* bits 15..12 for 0x15 */
14494 DMT = 0x0,
14495 DVPE = 0x1,
14496 EMT = 0x2,
14497 EVPE = 0x3,
14499 /* bits 15..12 for 0x1d */
14500 DI = 0x4,
14501 EI = 0x5,
14503 /* bits 15..12 for 0x2d */
14504 SYNC = 0x6,
14505 SYSCALL = 0x8,
14506 SDBBP = 0xd,
14508 /* bits 15..12 for 0x35 */
14509 MFHI32 = 0x0,
14510 MFLO32 = 0x1,
14511 MTHI32 = 0x2,
14512 MTLO32 = 0x3,
14515 /* POOL32B encoding of minor opcode field (bits 15..12) */
14517 enum {
14518 LWC2 = 0x0,
14519 LWP = 0x1,
14520 LDP = 0x4,
14521 LWM32 = 0x5,
14522 CACHE = 0x6,
14523 LDM = 0x7,
14524 SWC2 = 0x8,
14525 SWP = 0x9,
14526 SDP = 0xc,
14527 SWM32 = 0xd,
14528 SDM = 0xf
14531 /* POOL32C encoding of minor opcode field (bits 15..12) */
14533 enum {
14534 LWL = 0x0,
14535 SWL = 0x8,
14536 LWR = 0x1,
14537 SWR = 0x9,
14538 PREF = 0x2,
14539 ST_EVA = 0xa,
14540 LL = 0x3,
14541 SC = 0xb,
14542 LDL = 0x4,
14543 SDL = 0xc,
14544 LDR = 0x5,
14545 SDR = 0xd,
14546 LD_EVA = 0x6,
14547 LWU = 0xe,
14548 LLD = 0x7,
14549 SCD = 0xf
14552 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14554 enum {
14555 LBUE = 0x0,
14556 LHUE = 0x1,
14557 LWLE = 0x2,
14558 LWRE = 0x3,
14559 LBE = 0x4,
14560 LHE = 0x5,
14561 LLE = 0x6,
14562 LWE = 0x7,
14565 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14567 enum {
14568 SWLE = 0x0,
14569 SWRE = 0x1,
14570 PREFE = 0x2,
14571 CACHEE = 0x3,
14572 SBE = 0x4,
14573 SHE = 0x5,
14574 SCE = 0x6,
14575 SWE = 0x7,
14578 /* POOL32F encoding of minor opcode field (bits 5..0) */
14580 enum {
14581 /* These are the bit 7..6 values */
14582 ADD_FMT = 0x0,
14584 SUB_FMT = 0x1,
14586 MUL_FMT = 0x2,
14588 DIV_FMT = 0x3,
14590 /* These are the bit 8..6 values */
14591 MOVN_FMT = 0x0,
14592 RSQRT2_FMT = 0x0,
14593 MOVF_FMT = 0x0,
14594 RINT_FMT = 0x0,
14595 SELNEZ_FMT = 0x0,
14597 MOVZ_FMT = 0x1,
14598 LWXC1 = 0x1,
14599 MOVT_FMT = 0x1,
14600 CLASS_FMT = 0x1,
14601 SELEQZ_FMT = 0x1,
14603 PLL_PS = 0x2,
14604 SWXC1 = 0x2,
14605 SEL_FMT = 0x2,
14607 PLU_PS = 0x3,
14608 LDXC1 = 0x3,
14610 MOVN_FMT_04 = 0x4,
14611 PUL_PS = 0x4,
14612 SDXC1 = 0x4,
14613 RECIP2_FMT = 0x4,
14615 MOVZ_FMT_05 = 0x05,
14616 PUU_PS = 0x5,
14617 LUXC1 = 0x5,
14619 CVT_PS_S = 0x6,
14620 SUXC1 = 0x6,
14621 ADDR_PS = 0x6,
14622 PREFX = 0x6,
14623 MADDF_FMT = 0x6,
14625 MULR_PS = 0x7,
14626 MSUBF_FMT = 0x7,
14628 MADD_S = 0x01,
14629 MADD_D = 0x09,
14630 MADD_PS = 0x11,
14631 ALNV_PS = 0x19,
14632 MSUB_S = 0x21,
14633 MSUB_D = 0x29,
14634 MSUB_PS = 0x31,
14636 NMADD_S = 0x02,
14637 NMADD_D = 0x0a,
14638 NMADD_PS = 0x12,
14639 NMSUB_S = 0x22,
14640 NMSUB_D = 0x2a,
14641 NMSUB_PS = 0x32,
14643 MIN_FMT = 0x3,
14644 MAX_FMT = 0xb,
14645 MINA_FMT = 0x23,
14646 MAXA_FMT = 0x2b,
14647 POOL32FXF = 0x3b,
14649 CABS_COND_FMT = 0x1c, /* MIPS3D */
14650 C_COND_FMT = 0x3c,
14652 CMP_CONDN_S = 0x5,
14653 CMP_CONDN_D = 0x15
14656 /* POOL32Fxf encoding of minor opcode extension field */
14658 enum {
14659 CVT_L = 0x04,
14660 RSQRT_FMT = 0x08,
14661 FLOOR_L = 0x0c,
14662 CVT_PW_PS = 0x1c,
14663 CVT_W = 0x24,
14664 SQRT_FMT = 0x28,
14665 FLOOR_W = 0x2c,
14666 CVT_PS_PW = 0x3c,
14667 CFC1 = 0x40,
14668 RECIP_FMT = 0x48,
14669 CEIL_L = 0x4c,
14670 CTC1 = 0x60,
14671 CEIL_W = 0x6c,
14672 MFC1 = 0x80,
14673 CVT_S_PL = 0x84,
14674 TRUNC_L = 0x8c,
14675 MTC1 = 0xa0,
14676 CVT_S_PU = 0xa4,
14677 TRUNC_W = 0xac,
14678 MFHC1 = 0xc0,
14679 ROUND_L = 0xcc,
14680 MTHC1 = 0xe0,
14681 ROUND_W = 0xec,
14683 MOV_FMT = 0x01,
14684 MOVF = 0x05,
14685 ABS_FMT = 0x0d,
14686 RSQRT1_FMT = 0x1d,
14687 MOVT = 0x25,
14688 NEG_FMT = 0x2d,
14689 CVT_D = 0x4d,
14690 RECIP1_FMT = 0x5d,
14691 CVT_S = 0x6d
14694 /* POOL32I encoding of minor opcode field (bits 25..21) */
14696 enum {
14697 BLTZ = 0x00,
14698 BLTZAL = 0x01,
14699 BGEZ = 0x02,
14700 BGEZAL = 0x03,
14701 BLEZ = 0x04,
14702 BNEZC = 0x05,
14703 BGTZ = 0x06,
14704 BEQZC = 0x07,
14705 TLTI = 0x08,
14706 BC1EQZC = 0x08,
14707 TGEI = 0x09,
14708 BC1NEZC = 0x09,
14709 TLTIU = 0x0a,
14710 BC2EQZC = 0x0a,
14711 TGEIU = 0x0b,
14712 BC2NEZC = 0x0a,
14713 TNEI = 0x0c,
14714 R6_SYNCI = 0x0c,
14715 LUI = 0x0d,
14716 TEQI = 0x0e,
14717 SYNCI = 0x10,
14718 BLTZALS = 0x11,
14719 BGEZALS = 0x13,
14720 BC2F = 0x14,
14721 BC2T = 0x15,
14722 BPOSGE64 = 0x1a,
14723 BPOSGE32 = 0x1b,
14724 /* These overlap and are distinguished by bit16 of the instruction */
14725 BC1F = 0x1c,
14726 BC1T = 0x1d,
14727 BC1ANY2F = 0x1c,
14728 BC1ANY2T = 0x1d,
14729 BC1ANY4F = 0x1e,
14730 BC1ANY4T = 0x1f
14733 /* POOL16A encoding of minor opcode field */
14735 enum {
14736 ADDU16 = 0x0,
14737 SUBU16 = 0x1
14740 /* POOL16B encoding of minor opcode field */
14742 enum {
14743 SLL16 = 0x0,
14744 SRL16 = 0x1
14747 /* POOL16C encoding of minor opcode field */
14749 enum {
14750 NOT16 = 0x00,
14751 XOR16 = 0x04,
14752 AND16 = 0x08,
14753 OR16 = 0x0c,
14754 LWM16 = 0x10,
14755 SWM16 = 0x14,
14756 JR16 = 0x18,
14757 JRC16 = 0x1a,
14758 JALR16 = 0x1c,
14759 JALR16S = 0x1e,
14760 MFHI16 = 0x20,
14761 MFLO16 = 0x24,
14762 BREAK16 = 0x28,
14763 SDBBP16 = 0x2c,
14764 JRADDIUSP = 0x30
14767 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14769 enum {
14770 R6_NOT16 = 0x00,
14771 R6_AND16 = 0x01,
14772 R6_LWM16 = 0x02,
14773 R6_JRC16 = 0x03,
14774 MOVEP = 0x04,
14775 MOVEP_05 = 0x05,
14776 MOVEP_06 = 0x06,
14777 MOVEP_07 = 0x07,
14778 R6_XOR16 = 0x08,
14779 R6_OR16 = 0x09,
14780 R6_SWM16 = 0x0a,
14781 JALRC16 = 0x0b,
14782 MOVEP_0C = 0x0c,
14783 MOVEP_0D = 0x0d,
14784 MOVEP_0E = 0x0e,
14785 MOVEP_0F = 0x0f,
14786 JRCADDIUSP = 0x13,
14787 R6_BREAK16 = 0x1b,
14788 R6_SDBBP16 = 0x3b
14791 /* POOL16D encoding of minor opcode field */
14793 enum {
14794 ADDIUS5 = 0x0,
14795 ADDIUSP = 0x1
14798 /* POOL16E encoding of minor opcode field */
14800 enum {
14801 ADDIUR2 = 0x0,
14802 ADDIUR1SP = 0x1
14805 static int mmreg (int r)
14807 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14809 return map[r];
14812 /* Used for 16-bit store instructions. */
14813 static int mmreg2 (int r)
14815 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14817 return map[r];
14820 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14821 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14822 #define uMIPS_RS2(op) uMIPS_RS(op)
14823 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14824 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14825 #define uMIPS_RS5(op) (op & 0x1f)
14827 /* Signed immediate */
14828 #define SIMM(op, start, width) \
14829 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14830 << (32-width)) \
14831 >> (32-width))
14832 /* Zero-extended immediate */
14833 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14835 static void gen_addiur1sp(DisasContext *ctx)
14837 int rd = mmreg(uMIPS_RD(ctx->opcode));
14839 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14842 static void gen_addiur2(DisasContext *ctx)
14844 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14845 int rd = mmreg(uMIPS_RD(ctx->opcode));
14846 int rs = mmreg(uMIPS_RS(ctx->opcode));
14848 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14851 static void gen_addiusp(DisasContext *ctx)
14853 int encoded = ZIMM(ctx->opcode, 1, 9);
14854 int decoded;
14856 if (encoded <= 1) {
14857 decoded = 256 + encoded;
14858 } else if (encoded <= 255) {
14859 decoded = encoded;
14860 } else if (encoded <= 509) {
14861 decoded = encoded - 512;
14862 } else {
14863 decoded = encoded - 768;
14866 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14869 static void gen_addius5(DisasContext *ctx)
14871 int imm = SIMM(ctx->opcode, 1, 4);
14872 int rd = (ctx->opcode >> 5) & 0x1f;
14874 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14877 static void gen_andi16(DisasContext *ctx)
14879 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14880 31, 32, 63, 64, 255, 32768, 65535 };
14881 int rd = mmreg(uMIPS_RD(ctx->opcode));
14882 int rs = mmreg(uMIPS_RS(ctx->opcode));
14883 int encoded = ZIMM(ctx->opcode, 0, 4);
14885 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14888 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14889 int base, int16_t offset)
14891 TCGv t0, t1;
14892 TCGv_i32 t2;
14894 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14895 generate_exception_end(ctx, EXCP_RI);
14896 return;
14899 t0 = tcg_temp_new();
14901 gen_base_offset_addr(ctx, t0, base, offset);
14903 t1 = tcg_const_tl(reglist);
14904 t2 = tcg_const_i32(ctx->mem_idx);
14906 save_cpu_state(ctx, 1);
14907 switch (opc) {
14908 case LWM32:
14909 gen_helper_lwm(cpu_env, t0, t1, t2);
14910 break;
14911 case SWM32:
14912 gen_helper_swm(cpu_env, t0, t1, t2);
14913 break;
14914 #ifdef TARGET_MIPS64
14915 case LDM:
14916 gen_helper_ldm(cpu_env, t0, t1, t2);
14917 break;
14918 case SDM:
14919 gen_helper_sdm(cpu_env, t0, t1, t2);
14920 break;
14921 #endif
14923 tcg_temp_free(t0);
14924 tcg_temp_free(t1);
14925 tcg_temp_free_i32(t2);
14929 static void gen_pool16c_insn(DisasContext *ctx)
14931 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14932 int rs = mmreg(ctx->opcode & 0x7);
14934 switch (((ctx->opcode) >> 4) & 0x3f) {
14935 case NOT16 + 0:
14936 case NOT16 + 1:
14937 case NOT16 + 2:
14938 case NOT16 + 3:
14939 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14940 break;
14941 case XOR16 + 0:
14942 case XOR16 + 1:
14943 case XOR16 + 2:
14944 case XOR16 + 3:
14945 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14946 break;
14947 case AND16 + 0:
14948 case AND16 + 1:
14949 case AND16 + 2:
14950 case AND16 + 3:
14951 gen_logic(ctx, OPC_AND, rd, rd, rs);
14952 break;
14953 case OR16 + 0:
14954 case OR16 + 1:
14955 case OR16 + 2:
14956 case OR16 + 3:
14957 gen_logic(ctx, OPC_OR, rd, rd, rs);
14958 break;
14959 case LWM16 + 0:
14960 case LWM16 + 1:
14961 case LWM16 + 2:
14962 case LWM16 + 3:
14964 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14965 int offset = ZIMM(ctx->opcode, 0, 4);
14967 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14968 29, offset << 2);
14970 break;
14971 case SWM16 + 0:
14972 case SWM16 + 1:
14973 case SWM16 + 2:
14974 case SWM16 + 3:
14976 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14977 int offset = ZIMM(ctx->opcode, 0, 4);
14979 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14980 29, offset << 2);
14982 break;
14983 case JR16 + 0:
14984 case JR16 + 1:
14986 int reg = ctx->opcode & 0x1f;
14988 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14990 break;
14991 case JRC16 + 0:
14992 case JRC16 + 1:
14994 int reg = ctx->opcode & 0x1f;
14995 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14996 /* Let normal delay slot handling in our caller take us
14997 to the branch target. */
14999 break;
15000 case JALR16 + 0:
15001 case JALR16 + 1:
15002 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15003 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15004 break;
15005 case JALR16S + 0:
15006 case JALR16S + 1:
15007 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15008 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15009 break;
15010 case MFHI16 + 0:
15011 case MFHI16 + 1:
15012 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15013 break;
15014 case MFLO16 + 0:
15015 case MFLO16 + 1:
15016 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15017 break;
15018 case BREAK16:
15019 generate_exception_end(ctx, EXCP_BREAK);
15020 break;
15021 case SDBBP16:
15022 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15023 gen_helper_do_semihosting(cpu_env);
15024 } else {
15025 /* XXX: not clear which exception should be raised
15026 * when in debug mode...
15028 check_insn(ctx, ISA_MIPS32);
15029 generate_exception_end(ctx, EXCP_DBp);
15031 break;
15032 case JRADDIUSP + 0:
15033 case JRADDIUSP + 1:
15035 int imm = ZIMM(ctx->opcode, 0, 5);
15036 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15037 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15038 /* Let normal delay slot handling in our caller take us
15039 to the branch target. */
15041 break;
15042 default:
15043 generate_exception_end(ctx, EXCP_RI);
15044 break;
15048 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15049 int enc_rs)
15051 int rd, rs, re, rt;
15052 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15053 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15054 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15055 rd = rd_enc[enc_dest];
15056 re = re_enc[enc_dest];
15057 rs = rs_rt_enc[enc_rs];
15058 rt = rs_rt_enc[enc_rt];
15059 if (rs) {
15060 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15061 } else {
15062 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15064 if (rt) {
15065 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15066 } else {
15067 tcg_gen_movi_tl(cpu_gpr[re], 0);
15071 static void gen_pool16c_r6_insn(DisasContext *ctx)
15073 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15074 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15076 switch (ctx->opcode & 0xf) {
15077 case R6_NOT16:
15078 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15079 break;
15080 case R6_AND16:
15081 gen_logic(ctx, OPC_AND, rt, rt, rs);
15082 break;
15083 case R6_LWM16:
15085 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15086 int offset = extract32(ctx->opcode, 4, 4);
15087 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15089 break;
15090 case R6_JRC16: /* JRCADDIUSP */
15091 if ((ctx->opcode >> 4) & 1) {
15092 /* JRCADDIUSP */
15093 int imm = extract32(ctx->opcode, 5, 5);
15094 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15095 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15096 } else {
15097 /* JRC16 */
15098 rs = extract32(ctx->opcode, 5, 5);
15099 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15101 break;
15102 case MOVEP:
15103 case MOVEP_05:
15104 case MOVEP_06:
15105 case MOVEP_07:
15106 case MOVEP_0C:
15107 case MOVEP_0D:
15108 case MOVEP_0E:
15109 case MOVEP_0F:
15111 int enc_dest = uMIPS_RD(ctx->opcode);
15112 int enc_rt = uMIPS_RS2(ctx->opcode);
15113 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15114 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15116 break;
15117 case R6_XOR16:
15118 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15119 break;
15120 case R6_OR16:
15121 gen_logic(ctx, OPC_OR, rt, rt, rs);
15122 break;
15123 case R6_SWM16:
15125 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15126 int offset = extract32(ctx->opcode, 4, 4);
15127 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15129 break;
15130 case JALRC16: /* BREAK16, SDBBP16 */
15131 switch (ctx->opcode & 0x3f) {
15132 case JALRC16:
15133 case JALRC16 + 0x20:
15134 /* JALRC16 */
15135 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15136 31, 0, 0);
15137 break;
15138 case R6_BREAK16:
15139 /* BREAK16 */
15140 generate_exception(ctx, EXCP_BREAK);
15141 break;
15142 case R6_SDBBP16:
15143 /* SDBBP16 */
15144 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15145 gen_helper_do_semihosting(cpu_env);
15146 } else {
15147 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15148 generate_exception(ctx, EXCP_RI);
15149 } else {
15150 generate_exception(ctx, EXCP_DBp);
15153 break;
15155 break;
15156 default:
15157 generate_exception(ctx, EXCP_RI);
15158 break;
15162 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
15164 TCGv t0 = tcg_temp_new();
15165 TCGv t1 = tcg_temp_new();
15167 gen_load_gpr(t0, base);
15169 if (index != 0) {
15170 gen_load_gpr(t1, index);
15171 tcg_gen_shli_tl(t1, t1, 2);
15172 gen_op_addr_add(ctx, t0, t1, t0);
15175 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15176 gen_store_gpr(t1, rd);
15178 tcg_temp_free(t0);
15179 tcg_temp_free(t1);
15182 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
15183 int base, int16_t offset)
15185 TCGv t0, t1;
15187 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15188 generate_exception_end(ctx, EXCP_RI);
15189 return;
15192 t0 = tcg_temp_new();
15193 t1 = tcg_temp_new();
15195 gen_base_offset_addr(ctx, t0, base, offset);
15197 switch (opc) {
15198 case LWP:
15199 if (rd == base) {
15200 generate_exception_end(ctx, EXCP_RI);
15201 return;
15203 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15204 gen_store_gpr(t1, rd);
15205 tcg_gen_movi_tl(t1, 4);
15206 gen_op_addr_add(ctx, t0, t0, t1);
15207 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15208 gen_store_gpr(t1, rd+1);
15209 break;
15210 case SWP:
15211 gen_load_gpr(t1, rd);
15212 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15213 tcg_gen_movi_tl(t1, 4);
15214 gen_op_addr_add(ctx, t0, t0, t1);
15215 gen_load_gpr(t1, rd+1);
15216 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15217 break;
15218 #ifdef TARGET_MIPS64
15219 case LDP:
15220 if (rd == base) {
15221 generate_exception_end(ctx, EXCP_RI);
15222 return;
15224 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15225 gen_store_gpr(t1, rd);
15226 tcg_gen_movi_tl(t1, 8);
15227 gen_op_addr_add(ctx, t0, t0, t1);
15228 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15229 gen_store_gpr(t1, rd+1);
15230 break;
15231 case SDP:
15232 gen_load_gpr(t1, rd);
15233 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15234 tcg_gen_movi_tl(t1, 8);
15235 gen_op_addr_add(ctx, t0, t0, t1);
15236 gen_load_gpr(t1, rd+1);
15237 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15238 break;
15239 #endif
15241 tcg_temp_free(t0);
15242 tcg_temp_free(t1);
15245 static void gen_sync(int stype)
15247 TCGBar tcg_mo = TCG_BAR_SC;
15249 switch (stype) {
15250 case 0x4: /* SYNC_WMB */
15251 tcg_mo |= TCG_MO_ST_ST;
15252 break;
15253 case 0x10: /* SYNC_MB */
15254 tcg_mo |= TCG_MO_ALL;
15255 break;
15256 case 0x11: /* SYNC_ACQUIRE */
15257 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15258 break;
15259 case 0x12: /* SYNC_RELEASE */
15260 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15261 break;
15262 case 0x13: /* SYNC_RMB */
15263 tcg_mo |= TCG_MO_LD_LD;
15264 break;
15265 default:
15266 tcg_mo |= TCG_MO_ALL;
15267 break;
15270 tcg_gen_mb(tcg_mo);
15273 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15275 int extension = (ctx->opcode >> 6) & 0x3f;
15276 int minor = (ctx->opcode >> 12) & 0xf;
15277 uint32_t mips32_op;
15279 switch (extension) {
15280 case TEQ:
15281 mips32_op = OPC_TEQ;
15282 goto do_trap;
15283 case TGE:
15284 mips32_op = OPC_TGE;
15285 goto do_trap;
15286 case TGEU:
15287 mips32_op = OPC_TGEU;
15288 goto do_trap;
15289 case TLT:
15290 mips32_op = OPC_TLT;
15291 goto do_trap;
15292 case TLTU:
15293 mips32_op = OPC_TLTU;
15294 goto do_trap;
15295 case TNE:
15296 mips32_op = OPC_TNE;
15297 do_trap:
15298 gen_trap(ctx, mips32_op, rs, rt, -1);
15299 break;
15300 #ifndef CONFIG_USER_ONLY
15301 case MFC0:
15302 case MFC0 + 32:
15303 check_cp0_enabled(ctx);
15304 if (rt == 0) {
15305 /* Treat as NOP. */
15306 break;
15308 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15309 break;
15310 case MTC0:
15311 case MTC0 + 32:
15312 check_cp0_enabled(ctx);
15314 TCGv t0 = tcg_temp_new();
15316 gen_load_gpr(t0, rt);
15317 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15318 tcg_temp_free(t0);
15320 break;
15321 #endif
15322 case 0x2a:
15323 switch (minor & 3) {
15324 case MADD_ACC:
15325 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15326 break;
15327 case MADDU_ACC:
15328 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15329 break;
15330 case MSUB_ACC:
15331 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15332 break;
15333 case MSUBU_ACC:
15334 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15335 break;
15336 default:
15337 goto pool32axf_invalid;
15339 break;
15340 case 0x32:
15341 switch (minor & 3) {
15342 case MULT_ACC:
15343 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15344 break;
15345 case MULTU_ACC:
15346 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15347 break;
15348 default:
15349 goto pool32axf_invalid;
15351 break;
15352 case 0x2c:
15353 switch (minor) {
15354 case BITSWAP:
15355 check_insn(ctx, ISA_MIPS32R6);
15356 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15357 break;
15358 case SEB:
15359 gen_bshfl(ctx, OPC_SEB, rs, rt);
15360 break;
15361 case SEH:
15362 gen_bshfl(ctx, OPC_SEH, rs, rt);
15363 break;
15364 case CLO:
15365 mips32_op = OPC_CLO;
15366 goto do_cl;
15367 case CLZ:
15368 mips32_op = OPC_CLZ;
15369 do_cl:
15370 check_insn(ctx, ISA_MIPS32);
15371 gen_cl(ctx, mips32_op, rt, rs);
15372 break;
15373 case RDHWR:
15374 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15375 gen_rdhwr(ctx, rt, rs, 0);
15376 break;
15377 case WSBH:
15378 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15379 break;
15380 case MULT:
15381 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15382 mips32_op = OPC_MULT;
15383 goto do_mul;
15384 case MULTU:
15385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15386 mips32_op = OPC_MULTU;
15387 goto do_mul;
15388 case DIV:
15389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15390 mips32_op = OPC_DIV;
15391 goto do_div;
15392 case DIVU:
15393 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15394 mips32_op = OPC_DIVU;
15395 goto do_div;
15396 do_div:
15397 check_insn(ctx, ISA_MIPS32);
15398 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15399 break;
15400 case MADD:
15401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15402 mips32_op = OPC_MADD;
15403 goto do_mul;
15404 case MADDU:
15405 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15406 mips32_op = OPC_MADDU;
15407 goto do_mul;
15408 case MSUB:
15409 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15410 mips32_op = OPC_MSUB;
15411 goto do_mul;
15412 case MSUBU:
15413 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15414 mips32_op = OPC_MSUBU;
15415 do_mul:
15416 check_insn(ctx, ISA_MIPS32);
15417 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15418 break;
15419 default:
15420 goto pool32axf_invalid;
15422 break;
15423 case 0x34:
15424 switch (minor) {
15425 case MFC2:
15426 case MTC2:
15427 case MFHC2:
15428 case MTHC2:
15429 case CFC2:
15430 case CTC2:
15431 generate_exception_err(ctx, EXCP_CpU, 2);
15432 break;
15433 default:
15434 goto pool32axf_invalid;
15436 break;
15437 case 0x3c:
15438 switch (minor) {
15439 case JALR: /* JALRC */
15440 case JALR_HB: /* JALRC_HB */
15441 if (ctx->insn_flags & ISA_MIPS32R6) {
15442 /* JALRC, JALRC_HB */
15443 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15444 } else {
15445 /* JALR, JALR_HB */
15446 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15447 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15449 break;
15450 case JALRS:
15451 case JALRS_HB:
15452 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15453 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15454 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15455 break;
15456 default:
15457 goto pool32axf_invalid;
15459 break;
15460 case 0x05:
15461 switch (minor) {
15462 case RDPGPR:
15463 check_cp0_enabled(ctx);
15464 check_insn(ctx, ISA_MIPS32R2);
15465 gen_load_srsgpr(rs, rt);
15466 break;
15467 case WRPGPR:
15468 check_cp0_enabled(ctx);
15469 check_insn(ctx, ISA_MIPS32R2);
15470 gen_store_srsgpr(rs, rt);
15471 break;
15472 default:
15473 goto pool32axf_invalid;
15475 break;
15476 #ifndef CONFIG_USER_ONLY
15477 case 0x0d:
15478 switch (minor) {
15479 case TLBP:
15480 mips32_op = OPC_TLBP;
15481 goto do_cp0;
15482 case TLBR:
15483 mips32_op = OPC_TLBR;
15484 goto do_cp0;
15485 case TLBWI:
15486 mips32_op = OPC_TLBWI;
15487 goto do_cp0;
15488 case TLBWR:
15489 mips32_op = OPC_TLBWR;
15490 goto do_cp0;
15491 case TLBINV:
15492 mips32_op = OPC_TLBINV;
15493 goto do_cp0;
15494 case TLBINVF:
15495 mips32_op = OPC_TLBINVF;
15496 goto do_cp0;
15497 case WAIT:
15498 mips32_op = OPC_WAIT;
15499 goto do_cp0;
15500 case DERET:
15501 mips32_op = OPC_DERET;
15502 goto do_cp0;
15503 case ERET:
15504 mips32_op = OPC_ERET;
15505 do_cp0:
15506 gen_cp0(env, ctx, mips32_op, rt, rs);
15507 break;
15508 default:
15509 goto pool32axf_invalid;
15511 break;
15512 case 0x1d:
15513 switch (minor) {
15514 case DI:
15515 check_cp0_enabled(ctx);
15517 TCGv t0 = tcg_temp_new();
15519 save_cpu_state(ctx, 1);
15520 gen_helper_di(t0, cpu_env);
15521 gen_store_gpr(t0, rs);
15522 /* Stop translation as we may have switched the execution mode */
15523 ctx->base.is_jmp = DISAS_STOP;
15524 tcg_temp_free(t0);
15526 break;
15527 case EI:
15528 check_cp0_enabled(ctx);
15530 TCGv t0 = tcg_temp_new();
15532 save_cpu_state(ctx, 1);
15533 gen_helper_ei(t0, cpu_env);
15534 gen_store_gpr(t0, rs);
15535 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15536 of translated code to check for pending interrupts. */
15537 gen_save_pc(ctx->base.pc_next + 4);
15538 ctx->base.is_jmp = DISAS_EXIT;
15539 tcg_temp_free(t0);
15541 break;
15542 default:
15543 goto pool32axf_invalid;
15545 break;
15546 #endif
15547 case 0x2d:
15548 switch (minor) {
15549 case SYNC:
15550 gen_sync(extract32(ctx->opcode, 16, 5));
15551 break;
15552 case SYSCALL:
15553 generate_exception_end(ctx, EXCP_SYSCALL);
15554 break;
15555 case SDBBP:
15556 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15557 gen_helper_do_semihosting(cpu_env);
15558 } else {
15559 check_insn(ctx, ISA_MIPS32);
15560 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15561 generate_exception_end(ctx, EXCP_RI);
15562 } else {
15563 generate_exception_end(ctx, EXCP_DBp);
15566 break;
15567 default:
15568 goto pool32axf_invalid;
15570 break;
15571 case 0x01:
15572 switch (minor & 3) {
15573 case MFHI_ACC:
15574 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15575 break;
15576 case MFLO_ACC:
15577 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15578 break;
15579 case MTHI_ACC:
15580 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15581 break;
15582 case MTLO_ACC:
15583 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15584 break;
15585 default:
15586 goto pool32axf_invalid;
15588 break;
15589 case 0x35:
15590 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15591 switch (minor) {
15592 case MFHI32:
15593 gen_HILO(ctx, OPC_MFHI, 0, rs);
15594 break;
15595 case MFLO32:
15596 gen_HILO(ctx, OPC_MFLO, 0, rs);
15597 break;
15598 case MTHI32:
15599 gen_HILO(ctx, OPC_MTHI, 0, rs);
15600 break;
15601 case MTLO32:
15602 gen_HILO(ctx, OPC_MTLO, 0, rs);
15603 break;
15604 default:
15605 goto pool32axf_invalid;
15607 break;
15608 default:
15609 pool32axf_invalid:
15610 MIPS_INVAL("pool32axf");
15611 generate_exception_end(ctx, EXCP_RI);
15612 break;
15616 /* Values for microMIPS fmt field. Variable-width, depending on which
15617 formats the instruction supports. */
15619 enum {
15620 FMT_SD_S = 0,
15621 FMT_SD_D = 1,
15623 FMT_SDPS_S = 0,
15624 FMT_SDPS_D = 1,
15625 FMT_SDPS_PS = 2,
15627 FMT_SWL_S = 0,
15628 FMT_SWL_W = 1,
15629 FMT_SWL_L = 2,
15631 FMT_DWL_D = 0,
15632 FMT_DWL_W = 1,
15633 FMT_DWL_L = 2
15636 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15638 int extension = (ctx->opcode >> 6) & 0x3ff;
15639 uint32_t mips32_op;
15641 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15642 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15643 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15645 switch (extension) {
15646 case FLOAT_1BIT_FMT(CFC1, 0):
15647 mips32_op = OPC_CFC1;
15648 goto do_cp1;
15649 case FLOAT_1BIT_FMT(CTC1, 0):
15650 mips32_op = OPC_CTC1;
15651 goto do_cp1;
15652 case FLOAT_1BIT_FMT(MFC1, 0):
15653 mips32_op = OPC_MFC1;
15654 goto do_cp1;
15655 case FLOAT_1BIT_FMT(MTC1, 0):
15656 mips32_op = OPC_MTC1;
15657 goto do_cp1;
15658 case FLOAT_1BIT_FMT(MFHC1, 0):
15659 mips32_op = OPC_MFHC1;
15660 goto do_cp1;
15661 case FLOAT_1BIT_FMT(MTHC1, 0):
15662 mips32_op = OPC_MTHC1;
15663 do_cp1:
15664 gen_cp1(ctx, mips32_op, rt, rs);
15665 break;
15667 /* Reciprocal square root */
15668 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15669 mips32_op = OPC_RSQRT_S;
15670 goto do_unaryfp;
15671 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15672 mips32_op = OPC_RSQRT_D;
15673 goto do_unaryfp;
15675 /* Square root */
15676 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15677 mips32_op = OPC_SQRT_S;
15678 goto do_unaryfp;
15679 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15680 mips32_op = OPC_SQRT_D;
15681 goto do_unaryfp;
15683 /* Reciprocal */
15684 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15685 mips32_op = OPC_RECIP_S;
15686 goto do_unaryfp;
15687 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15688 mips32_op = OPC_RECIP_D;
15689 goto do_unaryfp;
15691 /* Floor */
15692 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15693 mips32_op = OPC_FLOOR_L_S;
15694 goto do_unaryfp;
15695 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15696 mips32_op = OPC_FLOOR_L_D;
15697 goto do_unaryfp;
15698 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15699 mips32_op = OPC_FLOOR_W_S;
15700 goto do_unaryfp;
15701 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15702 mips32_op = OPC_FLOOR_W_D;
15703 goto do_unaryfp;
15705 /* Ceiling */
15706 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15707 mips32_op = OPC_CEIL_L_S;
15708 goto do_unaryfp;
15709 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15710 mips32_op = OPC_CEIL_L_D;
15711 goto do_unaryfp;
15712 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15713 mips32_op = OPC_CEIL_W_S;
15714 goto do_unaryfp;
15715 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15716 mips32_op = OPC_CEIL_W_D;
15717 goto do_unaryfp;
15719 /* Truncation */
15720 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15721 mips32_op = OPC_TRUNC_L_S;
15722 goto do_unaryfp;
15723 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15724 mips32_op = OPC_TRUNC_L_D;
15725 goto do_unaryfp;
15726 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15727 mips32_op = OPC_TRUNC_W_S;
15728 goto do_unaryfp;
15729 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15730 mips32_op = OPC_TRUNC_W_D;
15731 goto do_unaryfp;
15733 /* Round */
15734 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15735 mips32_op = OPC_ROUND_L_S;
15736 goto do_unaryfp;
15737 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15738 mips32_op = OPC_ROUND_L_D;
15739 goto do_unaryfp;
15740 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15741 mips32_op = OPC_ROUND_W_S;
15742 goto do_unaryfp;
15743 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15744 mips32_op = OPC_ROUND_W_D;
15745 goto do_unaryfp;
15747 /* Integer to floating-point conversion */
15748 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15749 mips32_op = OPC_CVT_L_S;
15750 goto do_unaryfp;
15751 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15752 mips32_op = OPC_CVT_L_D;
15753 goto do_unaryfp;
15754 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15755 mips32_op = OPC_CVT_W_S;
15756 goto do_unaryfp;
15757 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15758 mips32_op = OPC_CVT_W_D;
15759 goto do_unaryfp;
15761 /* Paired-foo conversions */
15762 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15763 mips32_op = OPC_CVT_S_PL;
15764 goto do_unaryfp;
15765 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15766 mips32_op = OPC_CVT_S_PU;
15767 goto do_unaryfp;
15768 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15769 mips32_op = OPC_CVT_PW_PS;
15770 goto do_unaryfp;
15771 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15772 mips32_op = OPC_CVT_PS_PW;
15773 goto do_unaryfp;
15775 /* Floating-point moves */
15776 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15777 mips32_op = OPC_MOV_S;
15778 goto do_unaryfp;
15779 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15780 mips32_op = OPC_MOV_D;
15781 goto do_unaryfp;
15782 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15783 mips32_op = OPC_MOV_PS;
15784 goto do_unaryfp;
15786 /* Absolute value */
15787 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15788 mips32_op = OPC_ABS_S;
15789 goto do_unaryfp;
15790 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15791 mips32_op = OPC_ABS_D;
15792 goto do_unaryfp;
15793 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15794 mips32_op = OPC_ABS_PS;
15795 goto do_unaryfp;
15797 /* Negation */
15798 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15799 mips32_op = OPC_NEG_S;
15800 goto do_unaryfp;
15801 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15802 mips32_op = OPC_NEG_D;
15803 goto do_unaryfp;
15804 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15805 mips32_op = OPC_NEG_PS;
15806 goto do_unaryfp;
15808 /* Reciprocal square root step */
15809 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15810 mips32_op = OPC_RSQRT1_S;
15811 goto do_unaryfp;
15812 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15813 mips32_op = OPC_RSQRT1_D;
15814 goto do_unaryfp;
15815 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15816 mips32_op = OPC_RSQRT1_PS;
15817 goto do_unaryfp;
15819 /* Reciprocal step */
15820 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15821 mips32_op = OPC_RECIP1_S;
15822 goto do_unaryfp;
15823 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15824 mips32_op = OPC_RECIP1_S;
15825 goto do_unaryfp;
15826 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15827 mips32_op = OPC_RECIP1_PS;
15828 goto do_unaryfp;
15830 /* Conversions from double */
15831 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15832 mips32_op = OPC_CVT_D_S;
15833 goto do_unaryfp;
15834 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15835 mips32_op = OPC_CVT_D_W;
15836 goto do_unaryfp;
15837 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15838 mips32_op = OPC_CVT_D_L;
15839 goto do_unaryfp;
15841 /* Conversions from single */
15842 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15843 mips32_op = OPC_CVT_S_D;
15844 goto do_unaryfp;
15845 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15846 mips32_op = OPC_CVT_S_W;
15847 goto do_unaryfp;
15848 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15849 mips32_op = OPC_CVT_S_L;
15850 do_unaryfp:
15851 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15852 break;
15854 /* Conditional moves on floating-point codes */
15855 case COND_FLOAT_MOV(MOVT, 0):
15856 case COND_FLOAT_MOV(MOVT, 1):
15857 case COND_FLOAT_MOV(MOVT, 2):
15858 case COND_FLOAT_MOV(MOVT, 3):
15859 case COND_FLOAT_MOV(MOVT, 4):
15860 case COND_FLOAT_MOV(MOVT, 5):
15861 case COND_FLOAT_MOV(MOVT, 6):
15862 case COND_FLOAT_MOV(MOVT, 7):
15863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15864 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15865 break;
15866 case COND_FLOAT_MOV(MOVF, 0):
15867 case COND_FLOAT_MOV(MOVF, 1):
15868 case COND_FLOAT_MOV(MOVF, 2):
15869 case COND_FLOAT_MOV(MOVF, 3):
15870 case COND_FLOAT_MOV(MOVF, 4):
15871 case COND_FLOAT_MOV(MOVF, 5):
15872 case COND_FLOAT_MOV(MOVF, 6):
15873 case COND_FLOAT_MOV(MOVF, 7):
15874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15875 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15876 break;
15877 default:
15878 MIPS_INVAL("pool32fxf");
15879 generate_exception_end(ctx, EXCP_RI);
15880 break;
15884 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15886 int32_t offset;
15887 uint16_t insn;
15888 int rt, rs, rd, rr;
15889 int16_t imm;
15890 uint32_t op, minor, minor2, mips32_op;
15891 uint32_t cond, fmt, cc;
15893 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15894 ctx->opcode = (ctx->opcode << 16) | insn;
15896 rt = (ctx->opcode >> 21) & 0x1f;
15897 rs = (ctx->opcode >> 16) & 0x1f;
15898 rd = (ctx->opcode >> 11) & 0x1f;
15899 rr = (ctx->opcode >> 6) & 0x1f;
15900 imm = (int16_t) ctx->opcode;
15902 op = (ctx->opcode >> 26) & 0x3f;
15903 switch (op) {
15904 case POOL32A:
15905 minor = ctx->opcode & 0x3f;
15906 switch (minor) {
15907 case 0x00:
15908 minor = (ctx->opcode >> 6) & 0xf;
15909 switch (minor) {
15910 case SLL32:
15911 mips32_op = OPC_SLL;
15912 goto do_shifti;
15913 case SRA:
15914 mips32_op = OPC_SRA;
15915 goto do_shifti;
15916 case SRL32:
15917 mips32_op = OPC_SRL;
15918 goto do_shifti;
15919 case ROTR:
15920 mips32_op = OPC_ROTR;
15921 do_shifti:
15922 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15923 break;
15924 case SELEQZ:
15925 check_insn(ctx, ISA_MIPS32R6);
15926 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15927 break;
15928 case SELNEZ:
15929 check_insn(ctx, ISA_MIPS32R6);
15930 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15931 break;
15932 case R6_RDHWR:
15933 check_insn(ctx, ISA_MIPS32R6);
15934 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15935 break;
15936 default:
15937 goto pool32a_invalid;
15939 break;
15940 case 0x10:
15941 minor = (ctx->opcode >> 6) & 0xf;
15942 switch (minor) {
15943 /* Arithmetic */
15944 case ADD:
15945 mips32_op = OPC_ADD;
15946 goto do_arith;
15947 case ADDU32:
15948 mips32_op = OPC_ADDU;
15949 goto do_arith;
15950 case SUB:
15951 mips32_op = OPC_SUB;
15952 goto do_arith;
15953 case SUBU32:
15954 mips32_op = OPC_SUBU;
15955 goto do_arith;
15956 case MUL:
15957 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15958 mips32_op = OPC_MUL;
15959 do_arith:
15960 gen_arith(ctx, mips32_op, rd, rs, rt);
15961 break;
15962 /* Shifts */
15963 case SLLV:
15964 mips32_op = OPC_SLLV;
15965 goto do_shift;
15966 case SRLV:
15967 mips32_op = OPC_SRLV;
15968 goto do_shift;
15969 case SRAV:
15970 mips32_op = OPC_SRAV;
15971 goto do_shift;
15972 case ROTRV:
15973 mips32_op = OPC_ROTRV;
15974 do_shift:
15975 gen_shift(ctx, mips32_op, rd, rs, rt);
15976 break;
15977 /* Logical operations */
15978 case AND:
15979 mips32_op = OPC_AND;
15980 goto do_logic;
15981 case OR32:
15982 mips32_op = OPC_OR;
15983 goto do_logic;
15984 case NOR:
15985 mips32_op = OPC_NOR;
15986 goto do_logic;
15987 case XOR32:
15988 mips32_op = OPC_XOR;
15989 do_logic:
15990 gen_logic(ctx, mips32_op, rd, rs, rt);
15991 break;
15992 /* Set less than */
15993 case SLT:
15994 mips32_op = OPC_SLT;
15995 goto do_slt;
15996 case SLTU:
15997 mips32_op = OPC_SLTU;
15998 do_slt:
15999 gen_slt(ctx, mips32_op, rd, rs, rt);
16000 break;
16001 default:
16002 goto pool32a_invalid;
16004 break;
16005 case 0x18:
16006 minor = (ctx->opcode >> 6) & 0xf;
16007 switch (minor) {
16008 /* Conditional moves */
16009 case MOVN: /* MUL */
16010 if (ctx->insn_flags & ISA_MIPS32R6) {
16011 /* MUL */
16012 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16013 } else {
16014 /* MOVN */
16015 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16017 break;
16018 case MOVZ: /* MUH */
16019 if (ctx->insn_flags & ISA_MIPS32R6) {
16020 /* MUH */
16021 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16022 } else {
16023 /* MOVZ */
16024 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16026 break;
16027 case MULU:
16028 check_insn(ctx, ISA_MIPS32R6);
16029 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16030 break;
16031 case MUHU:
16032 check_insn(ctx, ISA_MIPS32R6);
16033 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16034 break;
16035 case LWXS: /* DIV */
16036 if (ctx->insn_flags & ISA_MIPS32R6) {
16037 /* DIV */
16038 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16039 } else {
16040 /* LWXS */
16041 gen_ldxs(ctx, rs, rt, rd);
16043 break;
16044 case MOD:
16045 check_insn(ctx, ISA_MIPS32R6);
16046 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16047 break;
16048 case R6_DIVU:
16049 check_insn(ctx, ISA_MIPS32R6);
16050 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16051 break;
16052 case MODU:
16053 check_insn(ctx, ISA_MIPS32R6);
16054 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16055 break;
16056 default:
16057 goto pool32a_invalid;
16059 break;
16060 case INS:
16061 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16062 return;
16063 case LSA:
16064 check_insn(ctx, ISA_MIPS32R6);
16065 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16066 extract32(ctx->opcode, 9, 2));
16067 break;
16068 case ALIGN:
16069 check_insn(ctx, ISA_MIPS32R6);
16070 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16071 break;
16072 case EXT:
16073 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16074 return;
16075 case POOL32AXF:
16076 gen_pool32axf(env, ctx, rt, rs);
16077 break;
16078 case BREAK32:
16079 generate_exception_end(ctx, EXCP_BREAK);
16080 break;
16081 case SIGRIE:
16082 check_insn(ctx, ISA_MIPS32R6);
16083 generate_exception_end(ctx, EXCP_RI);
16084 break;
16085 default:
16086 pool32a_invalid:
16087 MIPS_INVAL("pool32a");
16088 generate_exception_end(ctx, EXCP_RI);
16089 break;
16091 break;
16092 case POOL32B:
16093 minor = (ctx->opcode >> 12) & 0xf;
16094 switch (minor) {
16095 case CACHE:
16096 check_cp0_enabled(ctx);
16097 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16098 gen_cache_operation(ctx, rt, rs, imm);
16100 break;
16101 case LWC2:
16102 case SWC2:
16103 /* COP2: Not implemented. */
16104 generate_exception_err(ctx, EXCP_CpU, 2);
16105 break;
16106 #ifdef TARGET_MIPS64
16107 case LDP:
16108 case SDP:
16109 check_insn(ctx, ISA_MIPS3);
16110 check_mips_64(ctx);
16111 #endif
16112 /* fall through */
16113 case LWP:
16114 case SWP:
16115 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16116 break;
16117 #ifdef TARGET_MIPS64
16118 case LDM:
16119 case SDM:
16120 check_insn(ctx, ISA_MIPS3);
16121 check_mips_64(ctx);
16122 #endif
16123 /* fall through */
16124 case LWM32:
16125 case SWM32:
16126 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16127 break;
16128 default:
16129 MIPS_INVAL("pool32b");
16130 generate_exception_end(ctx, EXCP_RI);
16131 break;
16133 break;
16134 case POOL32F:
16135 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16136 minor = ctx->opcode & 0x3f;
16137 check_cp1_enabled(ctx);
16138 switch (minor) {
16139 case ALNV_PS:
16140 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16141 mips32_op = OPC_ALNV_PS;
16142 goto do_madd;
16143 case MADD_S:
16144 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16145 mips32_op = OPC_MADD_S;
16146 goto do_madd;
16147 case MADD_D:
16148 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16149 mips32_op = OPC_MADD_D;
16150 goto do_madd;
16151 case MADD_PS:
16152 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16153 mips32_op = OPC_MADD_PS;
16154 goto do_madd;
16155 case MSUB_S:
16156 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16157 mips32_op = OPC_MSUB_S;
16158 goto do_madd;
16159 case MSUB_D:
16160 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16161 mips32_op = OPC_MSUB_D;
16162 goto do_madd;
16163 case MSUB_PS:
16164 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16165 mips32_op = OPC_MSUB_PS;
16166 goto do_madd;
16167 case NMADD_S:
16168 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16169 mips32_op = OPC_NMADD_S;
16170 goto do_madd;
16171 case NMADD_D:
16172 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16173 mips32_op = OPC_NMADD_D;
16174 goto do_madd;
16175 case NMADD_PS:
16176 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16177 mips32_op = OPC_NMADD_PS;
16178 goto do_madd;
16179 case NMSUB_S:
16180 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16181 mips32_op = OPC_NMSUB_S;
16182 goto do_madd;
16183 case NMSUB_D:
16184 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16185 mips32_op = OPC_NMSUB_D;
16186 goto do_madd;
16187 case NMSUB_PS:
16188 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16189 mips32_op = OPC_NMSUB_PS;
16190 do_madd:
16191 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16192 break;
16193 case CABS_COND_FMT:
16194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16195 cond = (ctx->opcode >> 6) & 0xf;
16196 cc = (ctx->opcode >> 13) & 0x7;
16197 fmt = (ctx->opcode >> 10) & 0x3;
16198 switch (fmt) {
16199 case 0x0:
16200 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16201 break;
16202 case 0x1:
16203 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16204 break;
16205 case 0x2:
16206 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16207 break;
16208 default:
16209 goto pool32f_invalid;
16211 break;
16212 case C_COND_FMT:
16213 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16214 cond = (ctx->opcode >> 6) & 0xf;
16215 cc = (ctx->opcode >> 13) & 0x7;
16216 fmt = (ctx->opcode >> 10) & 0x3;
16217 switch (fmt) {
16218 case 0x0:
16219 gen_cmp_s(ctx, cond, rt, rs, cc);
16220 break;
16221 case 0x1:
16222 gen_cmp_d(ctx, cond, rt, rs, cc);
16223 break;
16224 case 0x2:
16225 gen_cmp_ps(ctx, cond, rt, rs, cc);
16226 break;
16227 default:
16228 goto pool32f_invalid;
16230 break;
16231 case CMP_CONDN_S:
16232 check_insn(ctx, ISA_MIPS32R6);
16233 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16234 break;
16235 case CMP_CONDN_D:
16236 check_insn(ctx, ISA_MIPS32R6);
16237 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16238 break;
16239 case POOL32FXF:
16240 gen_pool32fxf(ctx, rt, rs);
16241 break;
16242 case 0x00:
16243 /* PLL foo */
16244 switch ((ctx->opcode >> 6) & 0x7) {
16245 case PLL_PS:
16246 mips32_op = OPC_PLL_PS;
16247 goto do_ps;
16248 case PLU_PS:
16249 mips32_op = OPC_PLU_PS;
16250 goto do_ps;
16251 case PUL_PS:
16252 mips32_op = OPC_PUL_PS;
16253 goto do_ps;
16254 case PUU_PS:
16255 mips32_op = OPC_PUU_PS;
16256 goto do_ps;
16257 case CVT_PS_S:
16258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16259 mips32_op = OPC_CVT_PS_S;
16260 do_ps:
16261 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16262 break;
16263 default:
16264 goto pool32f_invalid;
16266 break;
16267 case MIN_FMT:
16268 check_insn(ctx, ISA_MIPS32R6);
16269 switch ((ctx->opcode >> 9) & 0x3) {
16270 case FMT_SDPS_S:
16271 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16272 break;
16273 case FMT_SDPS_D:
16274 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16275 break;
16276 default:
16277 goto pool32f_invalid;
16279 break;
16280 case 0x08:
16281 /* [LS][WDU]XC1 */
16282 switch ((ctx->opcode >> 6) & 0x7) {
16283 case LWXC1:
16284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16285 mips32_op = OPC_LWXC1;
16286 goto do_ldst_cp1;
16287 case SWXC1:
16288 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16289 mips32_op = OPC_SWXC1;
16290 goto do_ldst_cp1;
16291 case LDXC1:
16292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16293 mips32_op = OPC_LDXC1;
16294 goto do_ldst_cp1;
16295 case SDXC1:
16296 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16297 mips32_op = OPC_SDXC1;
16298 goto do_ldst_cp1;
16299 case LUXC1:
16300 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16301 mips32_op = OPC_LUXC1;
16302 goto do_ldst_cp1;
16303 case SUXC1:
16304 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16305 mips32_op = OPC_SUXC1;
16306 do_ldst_cp1:
16307 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16308 break;
16309 default:
16310 goto pool32f_invalid;
16312 break;
16313 case MAX_FMT:
16314 check_insn(ctx, ISA_MIPS32R6);
16315 switch ((ctx->opcode >> 9) & 0x3) {
16316 case FMT_SDPS_S:
16317 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16318 break;
16319 case FMT_SDPS_D:
16320 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16321 break;
16322 default:
16323 goto pool32f_invalid;
16325 break;
16326 case 0x18:
16327 /* 3D insns */
16328 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16329 fmt = (ctx->opcode >> 9) & 0x3;
16330 switch ((ctx->opcode >> 6) & 0x7) {
16331 case RSQRT2_FMT:
16332 switch (fmt) {
16333 case FMT_SDPS_S:
16334 mips32_op = OPC_RSQRT2_S;
16335 goto do_3d;
16336 case FMT_SDPS_D:
16337 mips32_op = OPC_RSQRT2_D;
16338 goto do_3d;
16339 case FMT_SDPS_PS:
16340 mips32_op = OPC_RSQRT2_PS;
16341 goto do_3d;
16342 default:
16343 goto pool32f_invalid;
16345 break;
16346 case RECIP2_FMT:
16347 switch (fmt) {
16348 case FMT_SDPS_S:
16349 mips32_op = OPC_RECIP2_S;
16350 goto do_3d;
16351 case FMT_SDPS_D:
16352 mips32_op = OPC_RECIP2_D;
16353 goto do_3d;
16354 case FMT_SDPS_PS:
16355 mips32_op = OPC_RECIP2_PS;
16356 goto do_3d;
16357 default:
16358 goto pool32f_invalid;
16360 break;
16361 case ADDR_PS:
16362 mips32_op = OPC_ADDR_PS;
16363 goto do_3d;
16364 case MULR_PS:
16365 mips32_op = OPC_MULR_PS;
16366 do_3d:
16367 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16368 break;
16369 default:
16370 goto pool32f_invalid;
16372 break;
16373 case 0x20:
16374 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16375 cc = (ctx->opcode >> 13) & 0x7;
16376 fmt = (ctx->opcode >> 9) & 0x3;
16377 switch ((ctx->opcode >> 6) & 0x7) {
16378 case MOVF_FMT: /* RINT_FMT */
16379 if (ctx->insn_flags & ISA_MIPS32R6) {
16380 /* RINT_FMT */
16381 switch (fmt) {
16382 case FMT_SDPS_S:
16383 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16384 break;
16385 case FMT_SDPS_D:
16386 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16387 break;
16388 default:
16389 goto pool32f_invalid;
16391 } else {
16392 /* MOVF_FMT */
16393 switch (fmt) {
16394 case FMT_SDPS_S:
16395 gen_movcf_s(ctx, rs, rt, cc, 0);
16396 break;
16397 case FMT_SDPS_D:
16398 gen_movcf_d(ctx, rs, rt, cc, 0);
16399 break;
16400 case FMT_SDPS_PS:
16401 check_ps(ctx);
16402 gen_movcf_ps(ctx, rs, rt, cc, 0);
16403 break;
16404 default:
16405 goto pool32f_invalid;
16408 break;
16409 case MOVT_FMT: /* CLASS_FMT */
16410 if (ctx->insn_flags & ISA_MIPS32R6) {
16411 /* CLASS_FMT */
16412 switch (fmt) {
16413 case FMT_SDPS_S:
16414 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16415 break;
16416 case FMT_SDPS_D:
16417 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16418 break;
16419 default:
16420 goto pool32f_invalid;
16422 } else {
16423 /* MOVT_FMT */
16424 switch (fmt) {
16425 case FMT_SDPS_S:
16426 gen_movcf_s(ctx, rs, rt, cc, 1);
16427 break;
16428 case FMT_SDPS_D:
16429 gen_movcf_d(ctx, rs, rt, cc, 1);
16430 break;
16431 case FMT_SDPS_PS:
16432 check_ps(ctx);
16433 gen_movcf_ps(ctx, rs, rt, cc, 1);
16434 break;
16435 default:
16436 goto pool32f_invalid;
16439 break;
16440 case PREFX:
16441 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16442 break;
16443 default:
16444 goto pool32f_invalid;
16446 break;
16447 #define FINSN_3ARG_SDPS(prfx) \
16448 switch ((ctx->opcode >> 8) & 0x3) { \
16449 case FMT_SDPS_S: \
16450 mips32_op = OPC_##prfx##_S; \
16451 goto do_fpop; \
16452 case FMT_SDPS_D: \
16453 mips32_op = OPC_##prfx##_D; \
16454 goto do_fpop; \
16455 case FMT_SDPS_PS: \
16456 check_ps(ctx); \
16457 mips32_op = OPC_##prfx##_PS; \
16458 goto do_fpop; \
16459 default: \
16460 goto pool32f_invalid; \
16462 case MINA_FMT:
16463 check_insn(ctx, ISA_MIPS32R6);
16464 switch ((ctx->opcode >> 9) & 0x3) {
16465 case FMT_SDPS_S:
16466 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16467 break;
16468 case FMT_SDPS_D:
16469 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16470 break;
16471 default:
16472 goto pool32f_invalid;
16474 break;
16475 case MAXA_FMT:
16476 check_insn(ctx, ISA_MIPS32R6);
16477 switch ((ctx->opcode >> 9) & 0x3) {
16478 case FMT_SDPS_S:
16479 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16480 break;
16481 case FMT_SDPS_D:
16482 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16483 break;
16484 default:
16485 goto pool32f_invalid;
16487 break;
16488 case 0x30:
16489 /* regular FP ops */
16490 switch ((ctx->opcode >> 6) & 0x3) {
16491 case ADD_FMT:
16492 FINSN_3ARG_SDPS(ADD);
16493 break;
16494 case SUB_FMT:
16495 FINSN_3ARG_SDPS(SUB);
16496 break;
16497 case MUL_FMT:
16498 FINSN_3ARG_SDPS(MUL);
16499 break;
16500 case DIV_FMT:
16501 fmt = (ctx->opcode >> 8) & 0x3;
16502 if (fmt == 1) {
16503 mips32_op = OPC_DIV_D;
16504 } else if (fmt == 0) {
16505 mips32_op = OPC_DIV_S;
16506 } else {
16507 goto pool32f_invalid;
16509 goto do_fpop;
16510 default:
16511 goto pool32f_invalid;
16513 break;
16514 case 0x38:
16515 /* cmovs */
16516 switch ((ctx->opcode >> 6) & 0x7) {
16517 case MOVN_FMT: /* SELEQZ_FMT */
16518 if (ctx->insn_flags & ISA_MIPS32R6) {
16519 /* SELEQZ_FMT */
16520 switch ((ctx->opcode >> 9) & 0x3) {
16521 case FMT_SDPS_S:
16522 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16523 break;
16524 case FMT_SDPS_D:
16525 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16526 break;
16527 default:
16528 goto pool32f_invalid;
16530 } else {
16531 /* MOVN_FMT */
16532 FINSN_3ARG_SDPS(MOVN);
16534 break;
16535 case MOVN_FMT_04:
16536 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16537 FINSN_3ARG_SDPS(MOVN);
16538 break;
16539 case MOVZ_FMT: /* SELNEZ_FMT */
16540 if (ctx->insn_flags & ISA_MIPS32R6) {
16541 /* SELNEZ_FMT */
16542 switch ((ctx->opcode >> 9) & 0x3) {
16543 case FMT_SDPS_S:
16544 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16545 break;
16546 case FMT_SDPS_D:
16547 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16548 break;
16549 default:
16550 goto pool32f_invalid;
16552 } else {
16553 /* MOVZ_FMT */
16554 FINSN_3ARG_SDPS(MOVZ);
16556 break;
16557 case MOVZ_FMT_05:
16558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16559 FINSN_3ARG_SDPS(MOVZ);
16560 break;
16561 case SEL_FMT:
16562 check_insn(ctx, ISA_MIPS32R6);
16563 switch ((ctx->opcode >> 9) & 0x3) {
16564 case FMT_SDPS_S:
16565 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16566 break;
16567 case FMT_SDPS_D:
16568 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16569 break;
16570 default:
16571 goto pool32f_invalid;
16573 break;
16574 case MADDF_FMT:
16575 check_insn(ctx, ISA_MIPS32R6);
16576 switch ((ctx->opcode >> 9) & 0x3) {
16577 case FMT_SDPS_S:
16578 mips32_op = OPC_MADDF_S;
16579 goto do_fpop;
16580 case FMT_SDPS_D:
16581 mips32_op = OPC_MADDF_D;
16582 goto do_fpop;
16583 default:
16584 goto pool32f_invalid;
16586 break;
16587 case MSUBF_FMT:
16588 check_insn(ctx, ISA_MIPS32R6);
16589 switch ((ctx->opcode >> 9) & 0x3) {
16590 case FMT_SDPS_S:
16591 mips32_op = OPC_MSUBF_S;
16592 goto do_fpop;
16593 case FMT_SDPS_D:
16594 mips32_op = OPC_MSUBF_D;
16595 goto do_fpop;
16596 default:
16597 goto pool32f_invalid;
16599 break;
16600 default:
16601 goto pool32f_invalid;
16603 break;
16604 do_fpop:
16605 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16606 break;
16607 default:
16608 pool32f_invalid:
16609 MIPS_INVAL("pool32f");
16610 generate_exception_end(ctx, EXCP_RI);
16611 break;
16613 } else {
16614 generate_exception_err(ctx, EXCP_CpU, 1);
16616 break;
16617 case POOL32I:
16618 minor = (ctx->opcode >> 21) & 0x1f;
16619 switch (minor) {
16620 case BLTZ:
16621 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16622 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16623 break;
16624 case BLTZAL:
16625 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16626 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16627 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16628 break;
16629 case BLTZALS:
16630 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16631 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16632 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16633 break;
16634 case BGEZ:
16635 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16636 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16637 break;
16638 case BGEZAL:
16639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16640 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16641 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16642 break;
16643 case BGEZALS:
16644 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16645 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16646 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16647 break;
16648 case BLEZ:
16649 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16650 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16651 break;
16652 case BGTZ:
16653 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16654 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16655 break;
16657 /* Traps */
16658 case TLTI: /* BC1EQZC */
16659 if (ctx->insn_flags & ISA_MIPS32R6) {
16660 /* BC1EQZC */
16661 check_cp1_enabled(ctx);
16662 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16663 } else {
16664 /* TLTI */
16665 mips32_op = OPC_TLTI;
16666 goto do_trapi;
16668 break;
16669 case TGEI: /* BC1NEZC */
16670 if (ctx->insn_flags & ISA_MIPS32R6) {
16671 /* BC1NEZC */
16672 check_cp1_enabled(ctx);
16673 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16674 } else {
16675 /* TGEI */
16676 mips32_op = OPC_TGEI;
16677 goto do_trapi;
16679 break;
16680 case TLTIU:
16681 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16682 mips32_op = OPC_TLTIU;
16683 goto do_trapi;
16684 case TGEIU:
16685 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16686 mips32_op = OPC_TGEIU;
16687 goto do_trapi;
16688 case TNEI: /* SYNCI */
16689 if (ctx->insn_flags & ISA_MIPS32R6) {
16690 /* SYNCI */
16691 /* Break the TB to be able to sync copied instructions
16692 immediately */
16693 ctx->base.is_jmp = DISAS_STOP;
16694 } else {
16695 /* TNEI */
16696 mips32_op = OPC_TNEI;
16697 goto do_trapi;
16699 break;
16700 case TEQI:
16701 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16702 mips32_op = OPC_TEQI;
16703 do_trapi:
16704 gen_trap(ctx, mips32_op, rs, -1, imm);
16705 break;
16707 case BNEZC:
16708 case BEQZC:
16709 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16710 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16711 4, rs, 0, imm << 1, 0);
16712 /* Compact branches don't have a delay slot, so just let
16713 the normal delay slot handling take us to the branch
16714 target. */
16715 break;
16716 case LUI:
16717 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16718 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16719 break;
16720 case SYNCI:
16721 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16722 /* Break the TB to be able to sync copied instructions
16723 immediately */
16724 ctx->base.is_jmp = DISAS_STOP;
16725 break;
16726 case BC2F:
16727 case BC2T:
16728 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16729 /* COP2: Not implemented. */
16730 generate_exception_err(ctx, EXCP_CpU, 2);
16731 break;
16732 case BC1F:
16733 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16734 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16735 goto do_cp1branch;
16736 case BC1T:
16737 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16738 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16739 goto do_cp1branch;
16740 case BC1ANY4F:
16741 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16742 mips32_op = OPC_BC1FANY4;
16743 goto do_cp1mips3d;
16744 case BC1ANY4T:
16745 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16746 mips32_op = OPC_BC1TANY4;
16747 do_cp1mips3d:
16748 check_cop1x(ctx);
16749 check_insn(ctx, ASE_MIPS3D);
16750 /* Fall through */
16751 do_cp1branch:
16752 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16753 check_cp1_enabled(ctx);
16754 gen_compute_branch1(ctx, mips32_op,
16755 (ctx->opcode >> 18) & 0x7, imm << 1);
16756 } else {
16757 generate_exception_err(ctx, EXCP_CpU, 1);
16759 break;
16760 case BPOSGE64:
16761 case BPOSGE32:
16762 /* MIPS DSP: not implemented */
16763 /* Fall through */
16764 default:
16765 MIPS_INVAL("pool32i");
16766 generate_exception_end(ctx, EXCP_RI);
16767 break;
16769 break;
16770 case POOL32C:
16771 minor = (ctx->opcode >> 12) & 0xf;
16772 offset = sextract32(ctx->opcode, 0,
16773 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16774 switch (minor) {
16775 case LWL:
16776 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16777 mips32_op = OPC_LWL;
16778 goto do_ld_lr;
16779 case SWL:
16780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16781 mips32_op = OPC_SWL;
16782 goto do_st_lr;
16783 case LWR:
16784 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16785 mips32_op = OPC_LWR;
16786 goto do_ld_lr;
16787 case SWR:
16788 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16789 mips32_op = OPC_SWR;
16790 goto do_st_lr;
16791 #if defined(TARGET_MIPS64)
16792 case LDL:
16793 check_insn(ctx, ISA_MIPS3);
16794 check_mips_64(ctx);
16795 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16796 mips32_op = OPC_LDL;
16797 goto do_ld_lr;
16798 case SDL:
16799 check_insn(ctx, ISA_MIPS3);
16800 check_mips_64(ctx);
16801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16802 mips32_op = OPC_SDL;
16803 goto do_st_lr;
16804 case LDR:
16805 check_insn(ctx, ISA_MIPS3);
16806 check_mips_64(ctx);
16807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16808 mips32_op = OPC_LDR;
16809 goto do_ld_lr;
16810 case SDR:
16811 check_insn(ctx, ISA_MIPS3);
16812 check_mips_64(ctx);
16813 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16814 mips32_op = OPC_SDR;
16815 goto do_st_lr;
16816 case LWU:
16817 check_insn(ctx, ISA_MIPS3);
16818 check_mips_64(ctx);
16819 mips32_op = OPC_LWU;
16820 goto do_ld_lr;
16821 case LLD:
16822 check_insn(ctx, ISA_MIPS3);
16823 check_mips_64(ctx);
16824 mips32_op = OPC_LLD;
16825 goto do_ld_lr;
16826 #endif
16827 case LL:
16828 mips32_op = OPC_LL;
16829 goto do_ld_lr;
16830 do_ld_lr:
16831 gen_ld(ctx, mips32_op, rt, rs, offset);
16832 break;
16833 do_st_lr:
16834 gen_st(ctx, mips32_op, rt, rs, offset);
16835 break;
16836 case SC:
16837 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16838 break;
16839 #if defined(TARGET_MIPS64)
16840 case SCD:
16841 check_insn(ctx, ISA_MIPS3);
16842 check_mips_64(ctx);
16843 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16844 break;
16845 #endif
16846 case LD_EVA:
16847 if (!ctx->eva) {
16848 MIPS_INVAL("pool32c ld-eva");
16849 generate_exception_end(ctx, EXCP_RI);
16850 break;
16852 check_cp0_enabled(ctx);
16854 minor2 = (ctx->opcode >> 9) & 0x7;
16855 offset = sextract32(ctx->opcode, 0, 9);
16856 switch (minor2) {
16857 case LBUE:
16858 mips32_op = OPC_LBUE;
16859 goto do_ld_lr;
16860 case LHUE:
16861 mips32_op = OPC_LHUE;
16862 goto do_ld_lr;
16863 case LWLE:
16864 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16865 mips32_op = OPC_LWLE;
16866 goto do_ld_lr;
16867 case LWRE:
16868 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16869 mips32_op = OPC_LWRE;
16870 goto do_ld_lr;
16871 case LBE:
16872 mips32_op = OPC_LBE;
16873 goto do_ld_lr;
16874 case LHE:
16875 mips32_op = OPC_LHE;
16876 goto do_ld_lr;
16877 case LLE:
16878 mips32_op = OPC_LLE;
16879 goto do_ld_lr;
16880 case LWE:
16881 mips32_op = OPC_LWE;
16882 goto do_ld_lr;
16884 break;
16885 case ST_EVA:
16886 if (!ctx->eva) {
16887 MIPS_INVAL("pool32c st-eva");
16888 generate_exception_end(ctx, EXCP_RI);
16889 break;
16891 check_cp0_enabled(ctx);
16893 minor2 = (ctx->opcode >> 9) & 0x7;
16894 offset = sextract32(ctx->opcode, 0, 9);
16895 switch (minor2) {
16896 case SWLE:
16897 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16898 mips32_op = OPC_SWLE;
16899 goto do_st_lr;
16900 case SWRE:
16901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16902 mips32_op = OPC_SWRE;
16903 goto do_st_lr;
16904 case PREFE:
16905 /* Treat as no-op */
16906 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16907 /* hint codes 24-31 are reserved and signal RI */
16908 generate_exception(ctx, EXCP_RI);
16910 break;
16911 case CACHEE:
16912 /* Treat as no-op */
16913 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16914 gen_cache_operation(ctx, rt, rs, offset);
16916 break;
16917 case SBE:
16918 mips32_op = OPC_SBE;
16919 goto do_st_lr;
16920 case SHE:
16921 mips32_op = OPC_SHE;
16922 goto do_st_lr;
16923 case SCE:
16924 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16925 break;
16926 case SWE:
16927 mips32_op = OPC_SWE;
16928 goto do_st_lr;
16930 break;
16931 case PREF:
16932 /* Treat as no-op */
16933 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16934 /* hint codes 24-31 are reserved and signal RI */
16935 generate_exception(ctx, EXCP_RI);
16937 break;
16938 default:
16939 MIPS_INVAL("pool32c");
16940 generate_exception_end(ctx, EXCP_RI);
16941 break;
16943 break;
16944 case ADDI32: /* AUI, LUI */
16945 if (ctx->insn_flags & ISA_MIPS32R6) {
16946 /* AUI, LUI */
16947 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16948 } else {
16949 /* ADDI32 */
16950 mips32_op = OPC_ADDI;
16951 goto do_addi;
16953 break;
16954 case ADDIU32:
16955 mips32_op = OPC_ADDIU;
16956 do_addi:
16957 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16958 break;
16960 /* Logical operations */
16961 case ORI32:
16962 mips32_op = OPC_ORI;
16963 goto do_logici;
16964 case XORI32:
16965 mips32_op = OPC_XORI;
16966 goto do_logici;
16967 case ANDI32:
16968 mips32_op = OPC_ANDI;
16969 do_logici:
16970 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16971 break;
16973 /* Set less than immediate */
16974 case SLTI32:
16975 mips32_op = OPC_SLTI;
16976 goto do_slti;
16977 case SLTIU32:
16978 mips32_op = OPC_SLTIU;
16979 do_slti:
16980 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16981 break;
16982 case JALX32:
16983 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16984 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16985 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16986 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16987 break;
16988 case JALS32: /* BOVC, BEQC, BEQZALC */
16989 if (ctx->insn_flags & ISA_MIPS32R6) {
16990 if (rs >= rt) {
16991 /* BOVC */
16992 mips32_op = OPC_BOVC;
16993 } else if (rs < rt && rs == 0) {
16994 /* BEQZALC */
16995 mips32_op = OPC_BEQZALC;
16996 } else {
16997 /* BEQC */
16998 mips32_op = OPC_BEQC;
17000 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17001 } else {
17002 /* JALS32 */
17003 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17004 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17005 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17007 break;
17008 case BEQ32: /* BC */
17009 if (ctx->insn_flags & ISA_MIPS32R6) {
17010 /* BC */
17011 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17012 sextract32(ctx->opcode << 1, 0, 27));
17013 } else {
17014 /* BEQ32 */
17015 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17017 break;
17018 case BNE32: /* BALC */
17019 if (ctx->insn_flags & ISA_MIPS32R6) {
17020 /* BALC */
17021 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17022 sextract32(ctx->opcode << 1, 0, 27));
17023 } else {
17024 /* BNE32 */
17025 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17027 break;
17028 case J32: /* BGTZC, BLTZC, BLTC */
17029 if (ctx->insn_flags & ISA_MIPS32R6) {
17030 if (rs == 0 && rt != 0) {
17031 /* BGTZC */
17032 mips32_op = OPC_BGTZC;
17033 } else if (rs != 0 && rt != 0 && rs == rt) {
17034 /* BLTZC */
17035 mips32_op = OPC_BLTZC;
17036 } else {
17037 /* BLTC */
17038 mips32_op = OPC_BLTC;
17040 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17041 } else {
17042 /* J32 */
17043 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17044 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17046 break;
17047 case JAL32: /* BLEZC, BGEZC, BGEC */
17048 if (ctx->insn_flags & ISA_MIPS32R6) {
17049 if (rs == 0 && rt != 0) {
17050 /* BLEZC */
17051 mips32_op = OPC_BLEZC;
17052 } else if (rs != 0 && rt != 0 && rs == rt) {
17053 /* BGEZC */
17054 mips32_op = OPC_BGEZC;
17055 } else {
17056 /* BGEC */
17057 mips32_op = OPC_BGEC;
17059 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17060 } else {
17061 /* JAL32 */
17062 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17063 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17064 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17066 break;
17067 /* Floating point (COP1) */
17068 case LWC132:
17069 mips32_op = OPC_LWC1;
17070 goto do_cop1;
17071 case LDC132:
17072 mips32_op = OPC_LDC1;
17073 goto do_cop1;
17074 case SWC132:
17075 mips32_op = OPC_SWC1;
17076 goto do_cop1;
17077 case SDC132:
17078 mips32_op = OPC_SDC1;
17079 do_cop1:
17080 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17081 break;
17082 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17083 if (ctx->insn_flags & ISA_MIPS32R6) {
17084 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17085 switch ((ctx->opcode >> 16) & 0x1f) {
17086 case ADDIUPC_00:
17087 case ADDIUPC_01:
17088 case ADDIUPC_02:
17089 case ADDIUPC_03:
17090 case ADDIUPC_04:
17091 case ADDIUPC_05:
17092 case ADDIUPC_06:
17093 case ADDIUPC_07:
17094 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17095 break;
17096 case AUIPC:
17097 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17098 break;
17099 case ALUIPC:
17100 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17101 break;
17102 case LWPC_08:
17103 case LWPC_09:
17104 case LWPC_0A:
17105 case LWPC_0B:
17106 case LWPC_0C:
17107 case LWPC_0D:
17108 case LWPC_0E:
17109 case LWPC_0F:
17110 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17111 break;
17112 default:
17113 generate_exception(ctx, EXCP_RI);
17114 break;
17116 } else {
17117 /* ADDIUPC */
17118 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17119 offset = SIMM(ctx->opcode, 0, 23) << 2;
17121 gen_addiupc(ctx, reg, offset, 0, 0);
17123 break;
17124 case BNVC: /* BNEC, BNEZALC */
17125 check_insn(ctx, ISA_MIPS32R6);
17126 if (rs >= rt) {
17127 /* BNVC */
17128 mips32_op = OPC_BNVC;
17129 } else if (rs < rt && rs == 0) {
17130 /* BNEZALC */
17131 mips32_op = OPC_BNEZALC;
17132 } else {
17133 /* BNEC */
17134 mips32_op = OPC_BNEC;
17136 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17137 break;
17138 case R6_BNEZC: /* JIALC */
17139 check_insn(ctx, ISA_MIPS32R6);
17140 if (rt != 0) {
17141 /* BNEZC */
17142 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17143 sextract32(ctx->opcode << 1, 0, 22));
17144 } else {
17145 /* JIALC */
17146 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17148 break;
17149 case R6_BEQZC: /* JIC */
17150 check_insn(ctx, ISA_MIPS32R6);
17151 if (rt != 0) {
17152 /* BEQZC */
17153 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17154 sextract32(ctx->opcode << 1, 0, 22));
17155 } else {
17156 /* JIC */
17157 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17159 break;
17160 case BLEZALC: /* BGEZALC, BGEUC */
17161 check_insn(ctx, ISA_MIPS32R6);
17162 if (rs == 0 && rt != 0) {
17163 /* BLEZALC */
17164 mips32_op = OPC_BLEZALC;
17165 } else if (rs != 0 && rt != 0 && rs == rt) {
17166 /* BGEZALC */
17167 mips32_op = OPC_BGEZALC;
17168 } else {
17169 /* BGEUC */
17170 mips32_op = OPC_BGEUC;
17172 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17173 break;
17174 case BGTZALC: /* BLTZALC, BLTUC */
17175 check_insn(ctx, ISA_MIPS32R6);
17176 if (rs == 0 && rt != 0) {
17177 /* BGTZALC */
17178 mips32_op = OPC_BGTZALC;
17179 } else if (rs != 0 && rt != 0 && rs == rt) {
17180 /* BLTZALC */
17181 mips32_op = OPC_BLTZALC;
17182 } else {
17183 /* BLTUC */
17184 mips32_op = OPC_BLTUC;
17186 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17187 break;
17188 /* Loads and stores */
17189 case LB32:
17190 mips32_op = OPC_LB;
17191 goto do_ld;
17192 case LBU32:
17193 mips32_op = OPC_LBU;
17194 goto do_ld;
17195 case LH32:
17196 mips32_op = OPC_LH;
17197 goto do_ld;
17198 case LHU32:
17199 mips32_op = OPC_LHU;
17200 goto do_ld;
17201 case LW32:
17202 mips32_op = OPC_LW;
17203 goto do_ld;
17204 #ifdef TARGET_MIPS64
17205 case LD32:
17206 check_insn(ctx, ISA_MIPS3);
17207 check_mips_64(ctx);
17208 mips32_op = OPC_LD;
17209 goto do_ld;
17210 case SD32:
17211 check_insn(ctx, ISA_MIPS3);
17212 check_mips_64(ctx);
17213 mips32_op = OPC_SD;
17214 goto do_st;
17215 #endif
17216 case SB32:
17217 mips32_op = OPC_SB;
17218 goto do_st;
17219 case SH32:
17220 mips32_op = OPC_SH;
17221 goto do_st;
17222 case SW32:
17223 mips32_op = OPC_SW;
17224 goto do_st;
17225 do_ld:
17226 gen_ld(ctx, mips32_op, rt, rs, imm);
17227 break;
17228 do_st:
17229 gen_st(ctx, mips32_op, rt, rs, imm);
17230 break;
17231 default:
17232 generate_exception_end(ctx, EXCP_RI);
17233 break;
17237 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
17239 uint32_t op;
17241 /* make sure instructions are on a halfword boundary */
17242 if (ctx->base.pc_next & 0x1) {
17243 env->CP0_BadVAddr = ctx->base.pc_next;
17244 generate_exception_end(ctx, EXCP_AdEL);
17245 return 2;
17248 op = (ctx->opcode >> 10) & 0x3f;
17249 /* Enforce properly-sized instructions in a delay slot */
17250 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17251 switch (op & 0x7) { /* MSB-3..MSB-5 */
17252 case 0:
17253 /* POOL32A, POOL32B, POOL32I, POOL32C */
17254 case 4:
17255 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17256 case 5:
17257 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17258 case 6:
17259 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17260 case 7:
17261 /* LB32, LH32, LWC132, LDC132, LW32 */
17262 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17263 generate_exception_end(ctx, EXCP_RI);
17264 return 2;
17266 break;
17267 case 1:
17268 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17269 case 2:
17270 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17271 case 3:
17272 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17273 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17274 generate_exception_end(ctx, EXCP_RI);
17275 return 2;
17277 break;
17281 switch (op) {
17282 case POOL16A:
17284 int rd = mmreg(uMIPS_RD(ctx->opcode));
17285 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17286 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17287 uint32_t opc = 0;
17289 switch (ctx->opcode & 0x1) {
17290 case ADDU16:
17291 opc = OPC_ADDU;
17292 break;
17293 case SUBU16:
17294 opc = OPC_SUBU;
17295 break;
17297 if (ctx->insn_flags & ISA_MIPS32R6) {
17298 /* In the Release 6 the register number location in
17299 * the instruction encoding has changed.
17301 gen_arith(ctx, opc, rs1, rd, rs2);
17302 } else {
17303 gen_arith(ctx, opc, rd, rs1, rs2);
17306 break;
17307 case POOL16B:
17309 int rd = mmreg(uMIPS_RD(ctx->opcode));
17310 int rs = mmreg(uMIPS_RS(ctx->opcode));
17311 int amount = (ctx->opcode >> 1) & 0x7;
17312 uint32_t opc = 0;
17313 amount = amount == 0 ? 8 : amount;
17315 switch (ctx->opcode & 0x1) {
17316 case SLL16:
17317 opc = OPC_SLL;
17318 break;
17319 case SRL16:
17320 opc = OPC_SRL;
17321 break;
17324 gen_shift_imm(ctx, opc, rd, rs, amount);
17326 break;
17327 case POOL16C:
17328 if (ctx->insn_flags & ISA_MIPS32R6) {
17329 gen_pool16c_r6_insn(ctx);
17330 } else {
17331 gen_pool16c_insn(ctx);
17333 break;
17334 case LWGP16:
17336 int rd = mmreg(uMIPS_RD(ctx->opcode));
17337 int rb = 28; /* GP */
17338 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17340 gen_ld(ctx, OPC_LW, rd, rb, offset);
17342 break;
17343 case POOL16F:
17344 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17345 if (ctx->opcode & 1) {
17346 generate_exception_end(ctx, EXCP_RI);
17347 } else {
17348 /* MOVEP */
17349 int enc_dest = uMIPS_RD(ctx->opcode);
17350 int enc_rt = uMIPS_RS2(ctx->opcode);
17351 int enc_rs = uMIPS_RS1(ctx->opcode);
17352 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17354 break;
17355 case LBU16:
17357 int rd = mmreg(uMIPS_RD(ctx->opcode));
17358 int rb = mmreg(uMIPS_RS(ctx->opcode));
17359 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17360 offset = (offset == 0xf ? -1 : offset);
17362 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17364 break;
17365 case LHU16:
17367 int rd = mmreg(uMIPS_RD(ctx->opcode));
17368 int rb = mmreg(uMIPS_RS(ctx->opcode));
17369 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17371 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17373 break;
17374 case LWSP16:
17376 int rd = (ctx->opcode >> 5) & 0x1f;
17377 int rb = 29; /* SP */
17378 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17380 gen_ld(ctx, OPC_LW, rd, rb, offset);
17382 break;
17383 case LW16:
17385 int rd = mmreg(uMIPS_RD(ctx->opcode));
17386 int rb = mmreg(uMIPS_RS(ctx->opcode));
17387 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17389 gen_ld(ctx, OPC_LW, rd, rb, offset);
17391 break;
17392 case SB16:
17394 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17395 int rb = mmreg(uMIPS_RS(ctx->opcode));
17396 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17398 gen_st(ctx, OPC_SB, rd, rb, offset);
17400 break;
17401 case SH16:
17403 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17404 int rb = mmreg(uMIPS_RS(ctx->opcode));
17405 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17407 gen_st(ctx, OPC_SH, rd, rb, offset);
17409 break;
17410 case SWSP16:
17412 int rd = (ctx->opcode >> 5) & 0x1f;
17413 int rb = 29; /* SP */
17414 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17416 gen_st(ctx, OPC_SW, rd, rb, offset);
17418 break;
17419 case SW16:
17421 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17422 int rb = mmreg(uMIPS_RS(ctx->opcode));
17423 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17425 gen_st(ctx, OPC_SW, rd, rb, offset);
17427 break;
17428 case MOVE16:
17430 int rd = uMIPS_RD5(ctx->opcode);
17431 int rs = uMIPS_RS5(ctx->opcode);
17433 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17435 break;
17436 case ANDI16:
17437 gen_andi16(ctx);
17438 break;
17439 case POOL16D:
17440 switch (ctx->opcode & 0x1) {
17441 case ADDIUS5:
17442 gen_addius5(ctx);
17443 break;
17444 case ADDIUSP:
17445 gen_addiusp(ctx);
17446 break;
17448 break;
17449 case POOL16E:
17450 switch (ctx->opcode & 0x1) {
17451 case ADDIUR2:
17452 gen_addiur2(ctx);
17453 break;
17454 case ADDIUR1SP:
17455 gen_addiur1sp(ctx);
17456 break;
17458 break;
17459 case B16: /* BC16 */
17460 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17461 sextract32(ctx->opcode, 0, 10) << 1,
17462 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17463 break;
17464 case BNEZ16: /* BNEZC16 */
17465 case BEQZ16: /* BEQZC16 */
17466 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17467 mmreg(uMIPS_RD(ctx->opcode)),
17468 0, sextract32(ctx->opcode, 0, 7) << 1,
17469 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17471 break;
17472 case LI16:
17474 int reg = mmreg(uMIPS_RD(ctx->opcode));
17475 int imm = ZIMM(ctx->opcode, 0, 7);
17477 imm = (imm == 0x7f ? -1 : imm);
17478 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17480 break;
17481 case RES_29:
17482 case RES_31:
17483 case RES_39:
17484 generate_exception_end(ctx, EXCP_RI);
17485 break;
17486 default:
17487 decode_micromips32_opc(env, ctx);
17488 return 4;
17491 return 2;
17496 * nanoMIPS opcodes
17500 /* MAJOR, P16, and P32 pools opcodes */
17501 enum {
17502 NM_P_ADDIU = 0x00,
17503 NM_ADDIUPC = 0x01,
17504 NM_MOVE_BALC = 0x02,
17505 NM_P16_MV = 0x04,
17506 NM_LW16 = 0x05,
17507 NM_BC16 = 0x06,
17508 NM_P16_SR = 0x07,
17510 NM_POOL32A = 0x08,
17511 NM_P_BAL = 0x0a,
17512 NM_P16_SHIFT = 0x0c,
17513 NM_LWSP16 = 0x0d,
17514 NM_BALC16 = 0x0e,
17515 NM_P16_4X4 = 0x0f,
17517 NM_P_GP_W = 0x10,
17518 NM_P_GP_BH = 0x11,
17519 NM_P_J = 0x12,
17520 NM_P16C = 0x14,
17521 NM_LWGP16 = 0x15,
17522 NM_P16_LB = 0x17,
17524 NM_P48I = 0x18,
17525 NM_P16_A1 = 0x1c,
17526 NM_LW4X4 = 0x1d,
17527 NM_P16_LH = 0x1f,
17529 NM_P_U12 = 0x20,
17530 NM_P_LS_U12 = 0x21,
17531 NM_P_BR1 = 0x22,
17532 NM_P16_A2 = 0x24,
17533 NM_SW16 = 0x25,
17534 NM_BEQZC16 = 0x26,
17536 NM_POOL32F = 0x28,
17537 NM_P_LS_S9 = 0x29,
17538 NM_P_BR2 = 0x2a,
17540 NM_P16_ADDU = 0x2c,
17541 NM_SWSP16 = 0x2d,
17542 NM_BNEZC16 = 0x2e,
17543 NM_MOVEP = 0x2f,
17545 NM_POOL32S = 0x30,
17546 NM_P_BRI = 0x32,
17547 NM_LI16 = 0x34,
17548 NM_SWGP16 = 0x35,
17549 NM_P16_BR = 0x36,
17551 NM_P_LUI = 0x38,
17552 NM_ANDI16 = 0x3c,
17553 NM_SW4X4 = 0x3d,
17554 NM_MOVEPREV = 0x3f,
17557 /* POOL32A instruction pool */
17558 enum {
17559 NM_POOL32A0 = 0x00,
17560 NM_SPECIAL2 = 0x01,
17561 NM_COP2_1 = 0x02,
17562 NM_UDI = 0x03,
17563 NM_POOL32A5 = 0x05,
17564 NM_POOL32A7 = 0x07,
17567 /* P.GP.W instruction pool */
17568 enum {
17569 NM_ADDIUGP_W = 0x00,
17570 NM_LWGP = 0x02,
17571 NM_SWGP = 0x03,
17574 /* P48I instruction pool */
17575 enum {
17576 NM_LI48 = 0x00,
17577 NM_ADDIU48 = 0x01,
17578 NM_ADDIUGP48 = 0x02,
17579 NM_ADDIUPC48 = 0x03,
17580 NM_LWPC48 = 0x0b,
17581 NM_SWPC48 = 0x0f,
17584 /* P.U12 instruction pool */
17585 enum {
17586 NM_ORI = 0x00,
17587 NM_XORI = 0x01,
17588 NM_ANDI = 0x02,
17589 NM_P_SR = 0x03,
17590 NM_SLTI = 0x04,
17591 NM_SLTIU = 0x05,
17592 NM_SEQI = 0x06,
17593 NM_ADDIUNEG = 0x08,
17594 NM_P_SHIFT = 0x0c,
17595 NM_P_ROTX = 0x0d,
17596 NM_P_INS = 0x0e,
17597 NM_P_EXT = 0x0f,
17600 /* POOL32F instruction pool */
17601 enum {
17602 NM_POOL32F_0 = 0x00,
17603 NM_POOL32F_3 = 0x03,
17604 NM_POOL32F_5 = 0x05,
17607 /* POOL32S instruction pool */
17608 enum {
17609 NM_POOL32S_0 = 0x00,
17610 NM_POOL32S_4 = 0x04,
17613 /* P.LUI instruction pool */
17614 enum {
17615 NM_LUI = 0x00,
17616 NM_ALUIPC = 0x01,
17619 /* P.GP.BH instruction pool */
17620 enum {
17621 NM_LBGP = 0x00,
17622 NM_SBGP = 0x01,
17623 NM_LBUGP = 0x02,
17624 NM_ADDIUGP_B = 0x03,
17625 NM_P_GP_LH = 0x04,
17626 NM_P_GP_SH = 0x05,
17627 NM_P_GP_CP1 = 0x06,
17630 /* P.LS.U12 instruction pool */
17631 enum {
17632 NM_LB = 0x00,
17633 NM_SB = 0x01,
17634 NM_LBU = 0x02,
17635 NM_P_PREFU12 = 0x03,
17636 NM_LH = 0x04,
17637 NM_SH = 0x05,
17638 NM_LHU = 0x06,
17639 NM_LWU = 0x07,
17640 NM_LW = 0x08,
17641 NM_SW = 0x09,
17642 NM_LWC1 = 0x0a,
17643 NM_SWC1 = 0x0b,
17644 NM_LDC1 = 0x0e,
17645 NM_SDC1 = 0x0f,
17648 /* P.LS.S9 instruction pool */
17649 enum {
17650 NM_P_LS_S0 = 0x00,
17651 NM_P_LS_S1 = 0x01,
17652 NM_P_LS_E0 = 0x02,
17653 NM_P_LS_WM = 0x04,
17654 NM_P_LS_UAWM = 0x05,
17657 /* P.BAL instruction pool */
17658 enum {
17659 NM_BC = 0x00,
17660 NM_BALC = 0x01,
17663 /* P.J instruction pool */
17664 enum {
17665 NM_JALRC = 0x00,
17666 NM_JALRC_HB = 0x01,
17667 NM_P_BALRSC = 0x08,
17670 /* P.BR1 instruction pool */
17671 enum {
17672 NM_BEQC = 0x00,
17673 NM_P_BR3A = 0x01,
17674 NM_BGEC = 0x02,
17675 NM_BGEUC = 0x03,
17678 /* P.BR2 instruction pool */
17679 enum {
17680 NM_BNEC = 0x00,
17681 NM_BLTC = 0x02,
17682 NM_BLTUC = 0x03,
17685 /* P.BRI instruction pool */
17686 enum {
17687 NM_BEQIC = 0x00,
17688 NM_BBEQZC = 0x01,
17689 NM_BGEIC = 0x02,
17690 NM_BGEIUC = 0x03,
17691 NM_BNEIC = 0x04,
17692 NM_BBNEZC = 0x05,
17693 NM_BLTIC = 0x06,
17694 NM_BLTIUC = 0x07,
17697 /* P16.SHIFT instruction pool */
17698 enum {
17699 NM_SLL16 = 0x00,
17700 NM_SRL16 = 0x01,
17703 /* POOL16C instruction pool */
17704 enum {
17705 NM_POOL16C_0 = 0x00,
17706 NM_LWXS16 = 0x01,
17709 /* P16.A1 instruction pool */
17710 enum {
17711 NM_ADDIUR1SP = 0x01,
17714 /* P16.A2 instruction pool */
17715 enum {
17716 NM_ADDIUR2 = 0x00,
17717 NM_P_ADDIURS5 = 0x01,
17720 /* P16.ADDU instruction pool */
17721 enum {
17722 NM_ADDU16 = 0x00,
17723 NM_SUBU16 = 0x01,
17726 /* P16.SR instruction pool */
17727 enum {
17728 NM_SAVE16 = 0x00,
17729 NM_RESTORE_JRC16 = 0x01,
17732 /* P16.4X4 instruction pool */
17733 enum {
17734 NM_ADDU4X4 = 0x00,
17735 NM_MUL4X4 = 0x01,
17738 /* P16.LB instruction pool */
17739 enum {
17740 NM_LB16 = 0x00,
17741 NM_SB16 = 0x01,
17742 NM_LBU16 = 0x02,
17745 /* P16.LH instruction pool */
17746 enum {
17747 NM_LH16 = 0x00,
17748 NM_SH16 = 0x01,
17749 NM_LHU16 = 0x02,
17752 /* P.RI instruction pool */
17753 enum {
17754 NM_SIGRIE = 0x00,
17755 NM_P_SYSCALL = 0x01,
17756 NM_BREAK = 0x02,
17757 NM_SDBBP = 0x03,
17760 /* POOL32A0 instruction pool */
17761 enum {
17762 NM_P_TRAP = 0x00,
17763 NM_SEB = 0x01,
17764 NM_SLLV = 0x02,
17765 NM_MUL = 0x03,
17766 NM_MFC0 = 0x06,
17767 NM_MFHC0 = 0x07,
17768 NM_SEH = 0x09,
17769 NM_SRLV = 0x0a,
17770 NM_MUH = 0x0b,
17771 NM_MTC0 = 0x0e,
17772 NM_MTHC0 = 0x0f,
17773 NM_SRAV = 0x12,
17774 NM_MULU = 0x13,
17775 NM_ROTRV = 0x1a,
17776 NM_MUHU = 0x1b,
17777 NM_ADD = 0x22,
17778 NM_DIV = 0x23,
17779 NM_ADDU = 0x2a,
17780 NM_MOD = 0x2b,
17781 NM_SUB = 0x32,
17782 NM_DIVU = 0x33,
17783 NM_RDHWR = 0x38,
17784 NM_SUBU = 0x3a,
17785 NM_MODU = 0x3b,
17786 NM_P_CMOVE = 0x42,
17787 NM_FORK = 0x45,
17788 NM_MFTR = 0x46,
17789 NM_MFHTR = 0x47,
17790 NM_AND = 0x4a,
17791 NM_YIELD = 0x4d,
17792 NM_MTTR = 0x4e,
17793 NM_MTHTR = 0x4f,
17794 NM_OR = 0x52,
17795 NM_D_E_MT_VPE = 0x56,
17796 NM_NOR = 0x5a,
17797 NM_XOR = 0x62,
17798 NM_SLT = 0x6a,
17799 NM_P_SLTU = 0x72,
17800 NM_SOV = 0x7a,
17803 /* CRC32 instruction pool */
17804 enum {
17805 NM_CRC32B = 0x00,
17806 NM_CRC32H = 0x01,
17807 NM_CRC32W = 0x02,
17808 NM_CRC32CB = 0x04,
17809 NM_CRC32CH = 0x05,
17810 NM_CRC32CW = 0x06,
17813 /* POOL32A5 instruction pool */
17814 enum {
17815 NM_CMP_EQ_PH = 0x00,
17816 NM_CMP_LT_PH = 0x08,
17817 NM_CMP_LE_PH = 0x10,
17818 NM_CMPGU_EQ_QB = 0x18,
17819 NM_CMPGU_LT_QB = 0x20,
17820 NM_CMPGU_LE_QB = 0x28,
17821 NM_CMPGDU_EQ_QB = 0x30,
17822 NM_CMPGDU_LT_QB = 0x38,
17823 NM_CMPGDU_LE_QB = 0x40,
17824 NM_CMPU_EQ_QB = 0x48,
17825 NM_CMPU_LT_QB = 0x50,
17826 NM_CMPU_LE_QB = 0x58,
17827 NM_ADDQ_S_W = 0x60,
17828 NM_SUBQ_S_W = 0x68,
17829 NM_ADDSC = 0x70,
17830 NM_ADDWC = 0x78,
17832 NM_ADDQ_S_PH = 0x01,
17833 NM_ADDQH_R_PH = 0x09,
17834 NM_ADDQH_R_W = 0x11,
17835 NM_ADDU_S_QB = 0x19,
17836 NM_ADDU_S_PH = 0x21,
17837 NM_ADDUH_R_QB = 0x29,
17838 NM_SHRAV_R_PH = 0x31,
17839 NM_SHRAV_R_QB = 0x39,
17840 NM_SUBQ_S_PH = 0x41,
17841 NM_SUBQH_R_PH = 0x49,
17842 NM_SUBQH_R_W = 0x51,
17843 NM_SUBU_S_QB = 0x59,
17844 NM_SUBU_S_PH = 0x61,
17845 NM_SUBUH_R_QB = 0x69,
17846 NM_SHLLV_S_PH = 0x71,
17847 NM_PRECR_SRA_R_PH_W = 0x79,
17849 NM_MULEU_S_PH_QBL = 0x12,
17850 NM_MULEU_S_PH_QBR = 0x1a,
17851 NM_MULQ_RS_PH = 0x22,
17852 NM_MULQ_S_PH = 0x2a,
17853 NM_MULQ_RS_W = 0x32,
17854 NM_MULQ_S_W = 0x3a,
17855 NM_APPEND = 0x42,
17856 NM_MODSUB = 0x52,
17857 NM_SHRAV_R_W = 0x5a,
17858 NM_SHRLV_PH = 0x62,
17859 NM_SHRLV_QB = 0x6a,
17860 NM_SHLLV_QB = 0x72,
17861 NM_SHLLV_S_W = 0x7a,
17863 NM_SHILO = 0x03,
17865 NM_MULEQ_S_W_PHL = 0x04,
17866 NM_MULEQ_S_W_PHR = 0x0c,
17868 NM_MUL_S_PH = 0x05,
17869 NM_PRECR_QB_PH = 0x0d,
17870 NM_PRECRQ_QB_PH = 0x15,
17871 NM_PRECRQ_PH_W = 0x1d,
17872 NM_PRECRQ_RS_PH_W = 0x25,
17873 NM_PRECRQU_S_QB_PH = 0x2d,
17874 NM_PACKRL_PH = 0x35,
17875 NM_PICK_QB = 0x3d,
17876 NM_PICK_PH = 0x45,
17878 NM_SHRA_R_W = 0x5e,
17879 NM_SHRA_R_PH = 0x66,
17880 NM_SHLL_S_PH = 0x76,
17881 NM_SHLL_S_W = 0x7e,
17883 NM_REPL_PH = 0x07
17886 /* POOL32A7 instruction pool */
17887 enum {
17888 NM_P_LSX = 0x00,
17889 NM_LSA = 0x01,
17890 NM_EXTW = 0x03,
17891 NM_POOL32AXF = 0x07,
17894 /* P.SR instruction pool */
17895 enum {
17896 NM_PP_SR = 0x00,
17897 NM_P_SR_F = 0x01,
17900 /* P.SHIFT instruction pool */
17901 enum {
17902 NM_P_SLL = 0x00,
17903 NM_SRL = 0x02,
17904 NM_SRA = 0x04,
17905 NM_ROTR = 0x06,
17908 /* P.ROTX instruction pool */
17909 enum {
17910 NM_ROTX = 0x00,
17913 /* P.INS instruction pool */
17914 enum {
17915 NM_INS = 0x00,
17918 /* P.EXT instruction pool */
17919 enum {
17920 NM_EXT = 0x00,
17923 /* POOL32F_0 (fmt) instruction pool */
17924 enum {
17925 NM_RINT_S = 0x04,
17926 NM_RINT_D = 0x44,
17927 NM_ADD_S = 0x06,
17928 NM_SELEQZ_S = 0x07,
17929 NM_SELEQZ_D = 0x47,
17930 NM_CLASS_S = 0x0c,
17931 NM_CLASS_D = 0x4c,
17932 NM_SUB_S = 0x0e,
17933 NM_SELNEZ_S = 0x0f,
17934 NM_SELNEZ_D = 0x4f,
17935 NM_MUL_S = 0x16,
17936 NM_SEL_S = 0x17,
17937 NM_SEL_D = 0x57,
17938 NM_DIV_S = 0x1e,
17939 NM_ADD_D = 0x26,
17940 NM_SUB_D = 0x2e,
17941 NM_MUL_D = 0x36,
17942 NM_MADDF_S = 0x37,
17943 NM_MADDF_D = 0x77,
17944 NM_DIV_D = 0x3e,
17945 NM_MSUBF_S = 0x3f,
17946 NM_MSUBF_D = 0x7f,
17949 /* POOL32F_3 instruction pool */
17950 enum {
17951 NM_MIN_FMT = 0x00,
17952 NM_MAX_FMT = 0x01,
17953 NM_MINA_FMT = 0x04,
17954 NM_MAXA_FMT = 0x05,
17955 NM_POOL32FXF = 0x07,
17958 /* POOL32F_5 instruction pool */
17959 enum {
17960 NM_CMP_CONDN_S = 0x00,
17961 NM_CMP_CONDN_D = 0x02,
17964 /* P.GP.LH instruction pool */
17965 enum {
17966 NM_LHGP = 0x00,
17967 NM_LHUGP = 0x01,
17970 /* P.GP.SH instruction pool */
17971 enum {
17972 NM_SHGP = 0x00,
17975 /* P.GP.CP1 instruction pool */
17976 enum {
17977 NM_LWC1GP = 0x00,
17978 NM_SWC1GP = 0x01,
17979 NM_LDC1GP = 0x02,
17980 NM_SDC1GP = 0x03,
17983 /* P.LS.S0 instruction pool */
17984 enum {
17985 NM_LBS9 = 0x00,
17986 NM_LHS9 = 0x04,
17987 NM_LWS9 = 0x08,
17988 NM_LDS9 = 0x0c,
17990 NM_SBS9 = 0x01,
17991 NM_SHS9 = 0x05,
17992 NM_SWS9 = 0x09,
17993 NM_SDS9 = 0x0d,
17995 NM_LBUS9 = 0x02,
17996 NM_LHUS9 = 0x06,
17997 NM_LWC1S9 = 0x0a,
17998 NM_LDC1S9 = 0x0e,
18000 NM_P_PREFS9 = 0x03,
18001 NM_LWUS9 = 0x07,
18002 NM_SWC1S9 = 0x0b,
18003 NM_SDC1S9 = 0x0f,
18006 /* P.LS.S1 instruction pool */
18007 enum {
18008 NM_ASET_ACLR = 0x02,
18009 NM_UALH = 0x04,
18010 NM_UASH = 0x05,
18011 NM_CACHE = 0x07,
18012 NM_P_LL = 0x0a,
18013 NM_P_SC = 0x0b,
18016 /* P.LS.E0 instruction pool */
18017 enum {
18018 NM_LBE = 0x00,
18019 NM_SBE = 0x01,
18020 NM_LBUE = 0x02,
18021 NM_P_PREFE = 0x03,
18022 NM_LHE = 0x04,
18023 NM_SHE = 0x05,
18024 NM_LHUE = 0x06,
18025 NM_CACHEE = 0x07,
18026 NM_LWE = 0x08,
18027 NM_SWE = 0x09,
18028 NM_P_LLE = 0x0a,
18029 NM_P_SCE = 0x0b,
18032 /* P.PREFE instruction pool */
18033 enum {
18034 NM_SYNCIE = 0x00,
18035 NM_PREFE = 0x01,
18038 /* P.LLE instruction pool */
18039 enum {
18040 NM_LLE = 0x00,
18041 NM_LLWPE = 0x01,
18044 /* P.SCE instruction pool */
18045 enum {
18046 NM_SCE = 0x00,
18047 NM_SCWPE = 0x01,
18050 /* P.LS.WM instruction pool */
18051 enum {
18052 NM_LWM = 0x00,
18053 NM_SWM = 0x01,
18056 /* P.LS.UAWM instruction pool */
18057 enum {
18058 NM_UALWM = 0x00,
18059 NM_UASWM = 0x01,
18062 /* P.BR3A instruction pool */
18063 enum {
18064 NM_BC1EQZC = 0x00,
18065 NM_BC1NEZC = 0x01,
18066 NM_BC2EQZC = 0x02,
18067 NM_BC2NEZC = 0x03,
18068 NM_BPOSGE32C = 0x04,
18071 /* P16.RI instruction pool */
18072 enum {
18073 NM_P16_SYSCALL = 0x01,
18074 NM_BREAK16 = 0x02,
18075 NM_SDBBP16 = 0x03,
18078 /* POOL16C_0 instruction pool */
18079 enum {
18080 NM_POOL16C_00 = 0x00,
18083 /* P16.JRC instruction pool */
18084 enum {
18085 NM_JRC = 0x00,
18086 NM_JALRC16 = 0x01,
18089 /* P.SYSCALL instruction pool */
18090 enum {
18091 NM_SYSCALL = 0x00,
18092 NM_HYPCALL = 0x01,
18095 /* P.TRAP instruction pool */
18096 enum {
18097 NM_TEQ = 0x00,
18098 NM_TNE = 0x01,
18101 /* P.CMOVE instruction pool */
18102 enum {
18103 NM_MOVZ = 0x00,
18104 NM_MOVN = 0x01,
18107 /* POOL32Axf instruction pool */
18108 enum {
18109 NM_POOL32AXF_1 = 0x01,
18110 NM_POOL32AXF_2 = 0x02,
18111 NM_POOL32AXF_4 = 0x04,
18112 NM_POOL32AXF_5 = 0x05,
18113 NM_POOL32AXF_7 = 0x07,
18116 /* POOL32Axf_1 instruction pool */
18117 enum {
18118 NM_POOL32AXF_1_0 = 0x00,
18119 NM_POOL32AXF_1_1 = 0x01,
18120 NM_POOL32AXF_1_3 = 0x03,
18121 NM_POOL32AXF_1_4 = 0x04,
18122 NM_POOL32AXF_1_5 = 0x05,
18123 NM_POOL32AXF_1_7 = 0x07,
18126 /* POOL32Axf_2 instruction pool */
18127 enum {
18128 NM_POOL32AXF_2_0_7 = 0x00,
18129 NM_POOL32AXF_2_8_15 = 0x01,
18130 NM_POOL32AXF_2_16_23 = 0x02,
18131 NM_POOL32AXF_2_24_31 = 0x03,
18134 /* POOL32Axf_7 instruction pool */
18135 enum {
18136 NM_SHRA_R_QB = 0x0,
18137 NM_SHRL_PH = 0x1,
18138 NM_REPL_QB = 0x2,
18141 /* POOL32Axf_1_0 instruction pool */
18142 enum {
18143 NM_MFHI = 0x0,
18144 NM_MFLO = 0x1,
18145 NM_MTHI = 0x2,
18146 NM_MTLO = 0x3,
18149 /* POOL32Axf_1_1 instruction pool */
18150 enum {
18151 NM_MTHLIP = 0x0,
18152 NM_SHILOV = 0x1,
18155 /* POOL32Axf_1_3 instruction pool */
18156 enum {
18157 NM_RDDSP = 0x0,
18158 NM_WRDSP = 0x1,
18159 NM_EXTP = 0x2,
18160 NM_EXTPDP = 0x3,
18163 /* POOL32Axf_1_4 instruction pool */
18164 enum {
18165 NM_SHLL_QB = 0x0,
18166 NM_SHRL_QB = 0x1,
18169 /* POOL32Axf_1_5 instruction pool */
18170 enum {
18171 NM_MAQ_S_W_PHR = 0x0,
18172 NM_MAQ_S_W_PHL = 0x1,
18173 NM_MAQ_SA_W_PHR = 0x2,
18174 NM_MAQ_SA_W_PHL = 0x3,
18177 /* POOL32Axf_1_7 instruction pool */
18178 enum {
18179 NM_EXTR_W = 0x0,
18180 NM_EXTR_R_W = 0x1,
18181 NM_EXTR_RS_W = 0x2,
18182 NM_EXTR_S_H = 0x3,
18185 /* POOL32Axf_2_0_7 instruction pool */
18186 enum {
18187 NM_DPA_W_PH = 0x0,
18188 NM_DPAQ_S_W_PH = 0x1,
18189 NM_DPS_W_PH = 0x2,
18190 NM_DPSQ_S_W_PH = 0x3,
18191 NM_BALIGN = 0x4,
18192 NM_MADD = 0x5,
18193 NM_MULT = 0x6,
18194 NM_EXTRV_W = 0x7,
18197 /* POOL32Axf_2_8_15 instruction pool */
18198 enum {
18199 NM_DPAX_W_PH = 0x0,
18200 NM_DPAQ_SA_L_W = 0x1,
18201 NM_DPSX_W_PH = 0x2,
18202 NM_DPSQ_SA_L_W = 0x3,
18203 NM_MADDU = 0x5,
18204 NM_MULTU = 0x6,
18205 NM_EXTRV_R_W = 0x7,
18208 /* POOL32Axf_2_16_23 instruction pool */
18209 enum {
18210 NM_DPAU_H_QBL = 0x0,
18211 NM_DPAQX_S_W_PH = 0x1,
18212 NM_DPSU_H_QBL = 0x2,
18213 NM_DPSQX_S_W_PH = 0x3,
18214 NM_EXTPV = 0x4,
18215 NM_MSUB = 0x5,
18216 NM_MULSA_W_PH = 0x6,
18217 NM_EXTRV_RS_W = 0x7,
18220 /* POOL32Axf_2_24_31 instruction pool */
18221 enum {
18222 NM_DPAU_H_QBR = 0x0,
18223 NM_DPAQX_SA_W_PH = 0x1,
18224 NM_DPSU_H_QBR = 0x2,
18225 NM_DPSQX_SA_W_PH = 0x3,
18226 NM_EXTPDPV = 0x4,
18227 NM_MSUBU = 0x5,
18228 NM_MULSAQ_S_W_PH = 0x6,
18229 NM_EXTRV_S_H = 0x7,
18232 /* POOL32Axf_{4, 5} instruction pool */
18233 enum {
18234 NM_CLO = 0x25,
18235 NM_CLZ = 0x2d,
18237 NM_TLBP = 0x01,
18238 NM_TLBR = 0x09,
18239 NM_TLBWI = 0x11,
18240 NM_TLBWR = 0x19,
18241 NM_TLBINV = 0x03,
18242 NM_TLBINVF = 0x0b,
18243 NM_DI = 0x23,
18244 NM_EI = 0x2b,
18245 NM_RDPGPR = 0x70,
18246 NM_WRPGPR = 0x78,
18247 NM_WAIT = 0x61,
18248 NM_DERET = 0x71,
18249 NM_ERETX = 0x79,
18251 /* nanoMIPS DSP instructions */
18252 NM_ABSQ_S_QB = 0x00,
18253 NM_ABSQ_S_PH = 0x08,
18254 NM_ABSQ_S_W = 0x10,
18255 NM_PRECEQ_W_PHL = 0x28,
18256 NM_PRECEQ_W_PHR = 0x30,
18257 NM_PRECEQU_PH_QBL = 0x38,
18258 NM_PRECEQU_PH_QBR = 0x48,
18259 NM_PRECEU_PH_QBL = 0x58,
18260 NM_PRECEU_PH_QBR = 0x68,
18261 NM_PRECEQU_PH_QBLA = 0x39,
18262 NM_PRECEQU_PH_QBRA = 0x49,
18263 NM_PRECEU_PH_QBLA = 0x59,
18264 NM_PRECEU_PH_QBRA = 0x69,
18265 NM_REPLV_PH = 0x01,
18266 NM_REPLV_QB = 0x09,
18267 NM_BITREV = 0x18,
18268 NM_INSV = 0x20,
18269 NM_RADDU_W_QB = 0x78,
18271 NM_BITSWAP = 0x05,
18272 NM_WSBH = 0x3d,
18275 /* PP.SR instruction pool */
18276 enum {
18277 NM_SAVE = 0x00,
18278 NM_RESTORE = 0x02,
18279 NM_RESTORE_JRC = 0x03,
18282 /* P.SR.F instruction pool */
18283 enum {
18284 NM_SAVEF = 0x00,
18285 NM_RESTOREF = 0x01,
18288 /* P16.SYSCALL instruction pool */
18289 enum {
18290 NM_SYSCALL16 = 0x00,
18291 NM_HYPCALL16 = 0x01,
18294 /* POOL16C_00 instruction pool */
18295 enum {
18296 NM_NOT16 = 0x00,
18297 NM_XOR16 = 0x01,
18298 NM_AND16 = 0x02,
18299 NM_OR16 = 0x03,
18302 /* PP.LSX and PP.LSXS instruction pool */
18303 enum {
18304 NM_LBX = 0x00,
18305 NM_LHX = 0x04,
18306 NM_LWX = 0x08,
18307 NM_LDX = 0x0c,
18309 NM_SBX = 0x01,
18310 NM_SHX = 0x05,
18311 NM_SWX = 0x09,
18312 NM_SDX = 0x0d,
18314 NM_LBUX = 0x02,
18315 NM_LHUX = 0x06,
18316 NM_LWC1X = 0x0a,
18317 NM_LDC1X = 0x0e,
18319 NM_LWUX = 0x07,
18320 NM_SWC1X = 0x0b,
18321 NM_SDC1X = 0x0f,
18323 NM_LHXS = 0x04,
18324 NM_LWXS = 0x08,
18325 NM_LDXS = 0x0c,
18327 NM_SHXS = 0x05,
18328 NM_SWXS = 0x09,
18329 NM_SDXS = 0x0d,
18331 NM_LHUXS = 0x06,
18332 NM_LWC1XS = 0x0a,
18333 NM_LDC1XS = 0x0e,
18335 NM_LWUXS = 0x07,
18336 NM_SWC1XS = 0x0b,
18337 NM_SDC1XS = 0x0f,
18340 /* ERETx instruction pool */
18341 enum {
18342 NM_ERET = 0x00,
18343 NM_ERETNC = 0x01,
18346 /* POOL32FxF_{0, 1} insturction pool */
18347 enum {
18348 NM_CFC1 = 0x40,
18349 NM_CTC1 = 0x60,
18350 NM_MFC1 = 0x80,
18351 NM_MTC1 = 0xa0,
18352 NM_MFHC1 = 0xc0,
18353 NM_MTHC1 = 0xe0,
18355 NM_CVT_S_PL = 0x84,
18356 NM_CVT_S_PU = 0xa4,
18358 NM_CVT_L_S = 0x004,
18359 NM_CVT_L_D = 0x104,
18360 NM_CVT_W_S = 0x024,
18361 NM_CVT_W_D = 0x124,
18363 NM_RSQRT_S = 0x008,
18364 NM_RSQRT_D = 0x108,
18366 NM_SQRT_S = 0x028,
18367 NM_SQRT_D = 0x128,
18369 NM_RECIP_S = 0x048,
18370 NM_RECIP_D = 0x148,
18372 NM_FLOOR_L_S = 0x00c,
18373 NM_FLOOR_L_D = 0x10c,
18375 NM_FLOOR_W_S = 0x02c,
18376 NM_FLOOR_W_D = 0x12c,
18378 NM_CEIL_L_S = 0x04c,
18379 NM_CEIL_L_D = 0x14c,
18380 NM_CEIL_W_S = 0x06c,
18381 NM_CEIL_W_D = 0x16c,
18382 NM_TRUNC_L_S = 0x08c,
18383 NM_TRUNC_L_D = 0x18c,
18384 NM_TRUNC_W_S = 0x0ac,
18385 NM_TRUNC_W_D = 0x1ac,
18386 NM_ROUND_L_S = 0x0cc,
18387 NM_ROUND_L_D = 0x1cc,
18388 NM_ROUND_W_S = 0x0ec,
18389 NM_ROUND_W_D = 0x1ec,
18391 NM_MOV_S = 0x01,
18392 NM_MOV_D = 0x81,
18393 NM_ABS_S = 0x0d,
18394 NM_ABS_D = 0x8d,
18395 NM_NEG_S = 0x2d,
18396 NM_NEG_D = 0xad,
18397 NM_CVT_D_S = 0x04d,
18398 NM_CVT_D_W = 0x0cd,
18399 NM_CVT_D_L = 0x14d,
18400 NM_CVT_S_D = 0x06d,
18401 NM_CVT_S_W = 0x0ed,
18402 NM_CVT_S_L = 0x16d,
18405 /* P.LL instruction pool */
18406 enum {
18407 NM_LL = 0x00,
18408 NM_LLWP = 0x01,
18411 /* P.SC instruction pool */
18412 enum {
18413 NM_SC = 0x00,
18414 NM_SCWP = 0x01,
18417 /* P.DVP instruction pool */
18418 enum {
18419 NM_DVP = 0x00,
18420 NM_EVP = 0x01,
18426 * nanoMIPS decoding engine
18431 /* extraction utilities */
18433 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18434 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18435 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18436 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18437 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18439 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18440 static inline int decode_gpr_gpr3(int r)
18442 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18444 return map[r & 0x7];
18447 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18448 static inline int decode_gpr_gpr3_src_store(int r)
18450 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18452 return map[r & 0x7];
18455 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18456 static inline int decode_gpr_gpr4(int r)
18458 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18459 16, 17, 18, 19, 20, 21, 22, 23 };
18461 return map[r & 0xf];
18464 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18465 static inline int decode_gpr_gpr4_zero(int r)
18467 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18468 16, 17, 18, 19, 20, 21, 22, 23 };
18470 return map[r & 0xf];
18474 static void gen_adjust_sp(DisasContext *ctx, int u)
18476 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18479 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18480 uint8_t gp, uint16_t u)
18482 int counter = 0;
18483 TCGv va = tcg_temp_new();
18484 TCGv t0 = tcg_temp_new();
18486 while (counter != count) {
18487 bool use_gp = gp && (counter == count - 1);
18488 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18489 int this_offset = -((counter + 1) << 2);
18490 gen_base_offset_addr(ctx, va, 29, this_offset);
18491 gen_load_gpr(t0, this_rt);
18492 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18493 (MO_TEUL | ctx->default_tcg_memop_mask));
18494 counter++;
18497 /* adjust stack pointer */
18498 gen_adjust_sp(ctx, -u);
18500 tcg_temp_free(t0);
18501 tcg_temp_free(va);
18504 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18505 uint8_t gp, uint16_t u)
18507 int counter = 0;
18508 TCGv va = tcg_temp_new();
18509 TCGv t0 = tcg_temp_new();
18511 while (counter != count) {
18512 bool use_gp = gp && (counter == count - 1);
18513 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18514 int this_offset = u - ((counter + 1) << 2);
18515 gen_base_offset_addr(ctx, va, 29, this_offset);
18516 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18517 ctx->default_tcg_memop_mask);
18518 tcg_gen_ext32s_tl(t0, t0);
18519 gen_store_gpr(t0, this_rt);
18520 counter++;
18523 /* adjust stack pointer */
18524 gen_adjust_sp(ctx, u);
18526 tcg_temp_free(t0);
18527 tcg_temp_free(va);
18530 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18532 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18533 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18535 switch (extract32(ctx->opcode, 2, 2)) {
18536 case NM_NOT16:
18537 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18538 break;
18539 case NM_AND16:
18540 gen_logic(ctx, OPC_AND, rt, rt, rs);
18541 break;
18542 case NM_XOR16:
18543 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18544 break;
18545 case NM_OR16:
18546 gen_logic(ctx, OPC_OR, rt, rt, rs);
18547 break;
18551 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18553 int rt = extract32(ctx->opcode, 21, 5);
18554 int rs = extract32(ctx->opcode, 16, 5);
18555 int rd = extract32(ctx->opcode, 11, 5);
18557 switch (extract32(ctx->opcode, 3, 7)) {
18558 case NM_P_TRAP:
18559 switch (extract32(ctx->opcode, 10, 1)) {
18560 case NM_TEQ:
18561 check_nms(ctx);
18562 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18563 break;
18564 case NM_TNE:
18565 check_nms(ctx);
18566 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18567 break;
18569 break;
18570 case NM_RDHWR:
18571 check_nms(ctx);
18572 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18573 break;
18574 case NM_SEB:
18575 check_nms(ctx);
18576 gen_bshfl(ctx, OPC_SEB, rs, rt);
18577 break;
18578 case NM_SEH:
18579 gen_bshfl(ctx, OPC_SEH, rs, rt);
18580 break;
18581 case NM_SLLV:
18582 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18583 break;
18584 case NM_SRLV:
18585 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18586 break;
18587 case NM_SRAV:
18588 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18589 break;
18590 case NM_ROTRV:
18591 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18592 break;
18593 case NM_ADD:
18594 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18595 break;
18596 case NM_ADDU:
18597 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18598 break;
18599 case NM_SUB:
18600 check_nms(ctx);
18601 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18602 break;
18603 case NM_SUBU:
18604 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18605 break;
18606 case NM_P_CMOVE:
18607 switch (extract32(ctx->opcode, 10, 1)) {
18608 case NM_MOVZ:
18609 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18610 break;
18611 case NM_MOVN:
18612 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18613 break;
18615 break;
18616 case NM_AND:
18617 gen_logic(ctx, OPC_AND, rd, rs, rt);
18618 break;
18619 case NM_OR:
18620 gen_logic(ctx, OPC_OR, rd, rs, rt);
18621 break;
18622 case NM_NOR:
18623 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18624 break;
18625 case NM_XOR:
18626 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18627 break;
18628 case NM_SLT:
18629 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18630 break;
18631 case NM_P_SLTU:
18632 if (rd == 0) {
18633 /* P_DVP */
18634 #ifndef CONFIG_USER_ONLY
18635 TCGv t0 = tcg_temp_new();
18636 switch (extract32(ctx->opcode, 10, 1)) {
18637 case NM_DVP:
18638 if (ctx->vp) {
18639 check_cp0_enabled(ctx);
18640 gen_helper_dvp(t0, cpu_env);
18641 gen_store_gpr(t0, rt);
18643 break;
18644 case NM_EVP:
18645 if (ctx->vp) {
18646 check_cp0_enabled(ctx);
18647 gen_helper_evp(t0, cpu_env);
18648 gen_store_gpr(t0, rt);
18650 break;
18652 tcg_temp_free(t0);
18653 #endif
18654 } else {
18655 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18657 break;
18658 case NM_SOV:
18660 TCGv t0 = tcg_temp_new();
18661 TCGv t1 = tcg_temp_new();
18662 TCGv t2 = tcg_temp_new();
18664 gen_load_gpr(t1, rs);
18665 gen_load_gpr(t2, rt);
18666 tcg_gen_add_tl(t0, t1, t2);
18667 tcg_gen_ext32s_tl(t0, t0);
18668 tcg_gen_xor_tl(t1, t1, t2);
18669 tcg_gen_xor_tl(t2, t0, t2);
18670 tcg_gen_andc_tl(t1, t2, t1);
18672 /* operands of same sign, result different sign */
18673 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18674 gen_store_gpr(t0, rd);
18676 tcg_temp_free(t0);
18677 tcg_temp_free(t1);
18678 tcg_temp_free(t2);
18680 break;
18681 case NM_MUL:
18682 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18683 break;
18684 case NM_MUH:
18685 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18686 break;
18687 case NM_MULU:
18688 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18689 break;
18690 case NM_MUHU:
18691 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18692 break;
18693 case NM_DIV:
18694 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18695 break;
18696 case NM_MOD:
18697 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18698 break;
18699 case NM_DIVU:
18700 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18701 break;
18702 case NM_MODU:
18703 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18704 break;
18705 #ifndef CONFIG_USER_ONLY
18706 case NM_MFC0:
18707 check_cp0_enabled(ctx);
18708 if (rt == 0) {
18709 /* Treat as NOP. */
18710 break;
18712 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18713 break;
18714 case NM_MTC0:
18715 check_cp0_enabled(ctx);
18717 TCGv t0 = tcg_temp_new();
18719 gen_load_gpr(t0, rt);
18720 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18721 tcg_temp_free(t0);
18723 break;
18724 case NM_D_E_MT_VPE:
18726 uint8_t sc = extract32(ctx->opcode, 10, 1);
18727 TCGv t0 = tcg_temp_new();
18729 switch (sc) {
18730 case 0:
18731 if (rs == 1) {
18732 /* DMT */
18733 check_cp0_mt(ctx);
18734 gen_helper_dmt(t0);
18735 gen_store_gpr(t0, rt);
18736 } else if (rs == 0) {
18737 /* DVPE */
18738 check_cp0_mt(ctx);
18739 gen_helper_dvpe(t0, cpu_env);
18740 gen_store_gpr(t0, rt);
18741 } else {
18742 generate_exception_end(ctx, EXCP_RI);
18744 break;
18745 case 1:
18746 if (rs == 1) {
18747 /* EMT */
18748 check_cp0_mt(ctx);
18749 gen_helper_emt(t0);
18750 gen_store_gpr(t0, rt);
18751 } else if (rs == 0) {
18752 /* EVPE */
18753 check_cp0_mt(ctx);
18754 gen_helper_evpe(t0, cpu_env);
18755 gen_store_gpr(t0, rt);
18756 } else {
18757 generate_exception_end(ctx, EXCP_RI);
18759 break;
18762 tcg_temp_free(t0);
18764 break;
18765 case NM_FORK:
18766 check_mt(ctx);
18768 TCGv t0 = tcg_temp_new();
18769 TCGv t1 = tcg_temp_new();
18771 gen_load_gpr(t0, rt);
18772 gen_load_gpr(t1, rs);
18773 gen_helper_fork(t0, t1);
18774 tcg_temp_free(t0);
18775 tcg_temp_free(t1);
18777 break;
18778 case NM_MFTR:
18779 case NM_MFHTR:
18780 check_cp0_enabled(ctx);
18781 if (rd == 0) {
18782 /* Treat as NOP. */
18783 return;
18785 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18786 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18787 break;
18788 case NM_MTTR:
18789 case NM_MTHTR:
18790 check_cp0_enabled(ctx);
18791 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18792 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18793 break;
18794 case NM_YIELD:
18795 check_mt(ctx);
18797 TCGv t0 = tcg_temp_new();
18799 gen_load_gpr(t0, rs);
18800 gen_helper_yield(t0, cpu_env, t0);
18801 gen_store_gpr(t0, rt);
18802 tcg_temp_free(t0);
18804 break;
18805 #endif
18806 default:
18807 generate_exception_end(ctx, EXCP_RI);
18808 break;
18812 /* dsp */
18813 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18814 int ret, int v1, int v2)
18816 TCGv_i32 t0;
18817 TCGv v0_t;
18818 TCGv v1_t;
18820 t0 = tcg_temp_new_i32();
18822 v0_t = tcg_temp_new();
18823 v1_t = tcg_temp_new();
18825 tcg_gen_movi_i32(t0, v2 >> 3);
18827 gen_load_gpr(v0_t, ret);
18828 gen_load_gpr(v1_t, v1);
18830 switch (opc) {
18831 case NM_MAQ_S_W_PHR:
18832 check_dsp(ctx);
18833 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18834 break;
18835 case NM_MAQ_S_W_PHL:
18836 check_dsp(ctx);
18837 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18838 break;
18839 case NM_MAQ_SA_W_PHR:
18840 check_dsp(ctx);
18841 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18842 break;
18843 case NM_MAQ_SA_W_PHL:
18844 check_dsp(ctx);
18845 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18846 break;
18847 default:
18848 generate_exception_end(ctx, EXCP_RI);
18849 break;
18852 tcg_temp_free_i32(t0);
18854 tcg_temp_free(v0_t);
18855 tcg_temp_free(v1_t);
18859 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18860 int ret, int v1, int v2)
18862 int16_t imm;
18863 TCGv t0 = tcg_temp_new();
18864 TCGv t1 = tcg_temp_new();
18865 TCGv v0_t = tcg_temp_new();
18867 gen_load_gpr(v0_t, v1);
18869 switch (opc) {
18870 case NM_POOL32AXF_1_0:
18871 check_dsp(ctx);
18872 switch (extract32(ctx->opcode, 12, 2)) {
18873 case NM_MFHI:
18874 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18875 break;
18876 case NM_MFLO:
18877 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18878 break;
18879 case NM_MTHI:
18880 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18881 break;
18882 case NM_MTLO:
18883 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18884 break;
18886 break;
18887 case NM_POOL32AXF_1_1:
18888 check_dsp(ctx);
18889 switch (extract32(ctx->opcode, 12, 2)) {
18890 case NM_MTHLIP:
18891 tcg_gen_movi_tl(t0, v2);
18892 gen_helper_mthlip(t0, v0_t, cpu_env);
18893 break;
18894 case NM_SHILOV:
18895 tcg_gen_movi_tl(t0, v2 >> 3);
18896 gen_helper_shilo(t0, v0_t, cpu_env);
18897 break;
18898 default:
18899 generate_exception_end(ctx, EXCP_RI);
18900 break;
18902 break;
18903 case NM_POOL32AXF_1_3:
18904 check_dsp(ctx);
18905 imm = extract32(ctx->opcode, 14, 7);
18906 switch (extract32(ctx->opcode, 12, 2)) {
18907 case NM_RDDSP:
18908 tcg_gen_movi_tl(t0, imm);
18909 gen_helper_rddsp(t0, t0, cpu_env);
18910 gen_store_gpr(t0, ret);
18911 break;
18912 case NM_WRDSP:
18913 gen_load_gpr(t0, ret);
18914 tcg_gen_movi_tl(t1, imm);
18915 gen_helper_wrdsp(t0, t1, cpu_env);
18916 break;
18917 case NM_EXTP:
18918 tcg_gen_movi_tl(t0, v2 >> 3);
18919 tcg_gen_movi_tl(t1, v1);
18920 gen_helper_extp(t0, t0, t1, cpu_env);
18921 gen_store_gpr(t0, ret);
18922 break;
18923 case NM_EXTPDP:
18924 tcg_gen_movi_tl(t0, v2 >> 3);
18925 tcg_gen_movi_tl(t1, v1);
18926 gen_helper_extpdp(t0, t0, t1, cpu_env);
18927 gen_store_gpr(t0, ret);
18928 break;
18930 break;
18931 case NM_POOL32AXF_1_4:
18932 check_dsp(ctx);
18933 tcg_gen_movi_tl(t0, v2 >> 2);
18934 switch (extract32(ctx->opcode, 12, 1)) {
18935 case NM_SHLL_QB:
18936 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18937 gen_store_gpr(t0, ret);
18938 break;
18939 case NM_SHRL_QB:
18940 gen_helper_shrl_qb(t0, t0, v0_t);
18941 gen_store_gpr(t0, ret);
18942 break;
18944 break;
18945 case NM_POOL32AXF_1_5:
18946 opc = extract32(ctx->opcode, 12, 2);
18947 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18948 break;
18949 case NM_POOL32AXF_1_7:
18950 check_dsp(ctx);
18951 tcg_gen_movi_tl(t0, v2 >> 3);
18952 tcg_gen_movi_tl(t1, v1);
18953 switch (extract32(ctx->opcode, 12, 2)) {
18954 case NM_EXTR_W:
18955 gen_helper_extr_w(t0, t0, t1, cpu_env);
18956 gen_store_gpr(t0, ret);
18957 break;
18958 case NM_EXTR_R_W:
18959 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18960 gen_store_gpr(t0, ret);
18961 break;
18962 case NM_EXTR_RS_W:
18963 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18964 gen_store_gpr(t0, ret);
18965 break;
18966 case NM_EXTR_S_H:
18967 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18968 gen_store_gpr(t0, ret);
18969 break;
18971 break;
18972 default:
18973 generate_exception_end(ctx, EXCP_RI);
18974 break;
18977 tcg_temp_free(t0);
18978 tcg_temp_free(t1);
18979 tcg_temp_free(v0_t);
18982 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18983 TCGv v0, TCGv v1, int rd)
18985 TCGv_i32 t0;
18987 t0 = tcg_temp_new_i32();
18989 tcg_gen_movi_i32(t0, rd >> 3);
18991 switch (opc) {
18992 case NM_POOL32AXF_2_0_7:
18993 switch (extract32(ctx->opcode, 9, 3)) {
18994 case NM_DPA_W_PH:
18995 check_dsp_r2(ctx);
18996 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18997 break;
18998 case NM_DPAQ_S_W_PH:
18999 check_dsp(ctx);
19000 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19001 break;
19002 case NM_DPS_W_PH:
19003 check_dsp_r2(ctx);
19004 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19005 break;
19006 case NM_DPSQ_S_W_PH:
19007 check_dsp(ctx);
19008 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19009 break;
19010 default:
19011 generate_exception_end(ctx, EXCP_RI);
19012 break;
19014 break;
19015 case NM_POOL32AXF_2_8_15:
19016 switch (extract32(ctx->opcode, 9, 3)) {
19017 case NM_DPAX_W_PH:
19018 check_dsp_r2(ctx);
19019 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19020 break;
19021 case NM_DPAQ_SA_L_W:
19022 check_dsp(ctx);
19023 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19024 break;
19025 case NM_DPSX_W_PH:
19026 check_dsp_r2(ctx);
19027 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19028 break;
19029 case NM_DPSQ_SA_L_W:
19030 check_dsp(ctx);
19031 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19032 break;
19033 default:
19034 generate_exception_end(ctx, EXCP_RI);
19035 break;
19037 break;
19038 case NM_POOL32AXF_2_16_23:
19039 switch (extract32(ctx->opcode, 9, 3)) {
19040 case NM_DPAU_H_QBL:
19041 check_dsp(ctx);
19042 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19043 break;
19044 case NM_DPAQX_S_W_PH:
19045 check_dsp_r2(ctx);
19046 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19047 break;
19048 case NM_DPSU_H_QBL:
19049 check_dsp(ctx);
19050 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19051 break;
19052 case NM_DPSQX_S_W_PH:
19053 check_dsp_r2(ctx);
19054 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19055 break;
19056 case NM_MULSA_W_PH:
19057 check_dsp_r2(ctx);
19058 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19059 break;
19060 default:
19061 generate_exception_end(ctx, EXCP_RI);
19062 break;
19064 break;
19065 case NM_POOL32AXF_2_24_31:
19066 switch (extract32(ctx->opcode, 9, 3)) {
19067 case NM_DPAU_H_QBR:
19068 check_dsp(ctx);
19069 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19070 break;
19071 case NM_DPAQX_SA_W_PH:
19072 check_dsp_r2(ctx);
19073 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19074 break;
19075 case NM_DPSU_H_QBR:
19076 check_dsp(ctx);
19077 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19078 break;
19079 case NM_DPSQX_SA_W_PH:
19080 check_dsp_r2(ctx);
19081 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19082 break;
19083 case NM_MULSAQ_S_W_PH:
19084 check_dsp(ctx);
19085 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19086 break;
19087 default:
19088 generate_exception_end(ctx, EXCP_RI);
19089 break;
19091 break;
19092 default:
19093 generate_exception_end(ctx, EXCP_RI);
19094 break;
19097 tcg_temp_free_i32(t0);
19100 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19101 int rt, int rs, int rd)
19103 int ret = rt;
19104 TCGv t0 = tcg_temp_new();
19105 TCGv t1 = tcg_temp_new();
19106 TCGv v0_t = tcg_temp_new();
19107 TCGv v1_t = tcg_temp_new();
19109 gen_load_gpr(v0_t, rt);
19110 gen_load_gpr(v1_t, rs);
19112 switch (opc) {
19113 case NM_POOL32AXF_2_0_7:
19114 switch (extract32(ctx->opcode, 9, 3)) {
19115 case NM_DPA_W_PH:
19116 case NM_DPAQ_S_W_PH:
19117 case NM_DPS_W_PH:
19118 case NM_DPSQ_S_W_PH:
19119 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19120 break;
19121 case NM_BALIGN:
19122 check_dsp_r2(ctx);
19123 if (rt != 0) {
19124 gen_load_gpr(t0, rs);
19125 rd &= 3;
19126 if (rd != 0 && rd != 2) {
19127 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19128 tcg_gen_ext32u_tl(t0, t0);
19129 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19130 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19132 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19134 break;
19135 case NM_MADD:
19136 check_dsp(ctx);
19138 int acc = extract32(ctx->opcode, 14, 2);
19139 TCGv_i64 t2 = tcg_temp_new_i64();
19140 TCGv_i64 t3 = tcg_temp_new_i64();
19142 gen_load_gpr(t0, rt);
19143 gen_load_gpr(t1, rs);
19144 tcg_gen_ext_tl_i64(t2, t0);
19145 tcg_gen_ext_tl_i64(t3, t1);
19146 tcg_gen_mul_i64(t2, t2, t3);
19147 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19148 tcg_gen_add_i64(t2, t2, t3);
19149 tcg_temp_free_i64(t3);
19150 gen_move_low32(cpu_LO[acc], t2);
19151 gen_move_high32(cpu_HI[acc], t2);
19152 tcg_temp_free_i64(t2);
19154 break;
19155 case NM_MULT:
19156 check_dsp(ctx);
19158 int acc = extract32(ctx->opcode, 14, 2);
19159 TCGv_i32 t2 = tcg_temp_new_i32();
19160 TCGv_i32 t3 = tcg_temp_new_i32();
19162 gen_load_gpr(t0, rs);
19163 gen_load_gpr(t1, rt);
19164 tcg_gen_trunc_tl_i32(t2, t0);
19165 tcg_gen_trunc_tl_i32(t3, t1);
19166 tcg_gen_muls2_i32(t2, t3, t2, t3);
19167 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19168 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19169 tcg_temp_free_i32(t2);
19170 tcg_temp_free_i32(t3);
19172 break;
19173 case NM_EXTRV_W:
19174 check_dsp(ctx);
19175 gen_load_gpr(v1_t, rs);
19176 tcg_gen_movi_tl(t0, rd >> 3);
19177 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19178 gen_store_gpr(t0, ret);
19179 break;
19181 break;
19182 case NM_POOL32AXF_2_8_15:
19183 switch (extract32(ctx->opcode, 9, 3)) {
19184 case NM_DPAX_W_PH:
19185 case NM_DPAQ_SA_L_W:
19186 case NM_DPSX_W_PH:
19187 case NM_DPSQ_SA_L_W:
19188 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19189 break;
19190 case NM_MADDU:
19191 check_dsp(ctx);
19193 int acc = extract32(ctx->opcode, 14, 2);
19194 TCGv_i64 t2 = tcg_temp_new_i64();
19195 TCGv_i64 t3 = tcg_temp_new_i64();
19197 gen_load_gpr(t0, rs);
19198 gen_load_gpr(t1, rt);
19199 tcg_gen_ext32u_tl(t0, t0);
19200 tcg_gen_ext32u_tl(t1, t1);
19201 tcg_gen_extu_tl_i64(t2, t0);
19202 tcg_gen_extu_tl_i64(t3, t1);
19203 tcg_gen_mul_i64(t2, t2, t3);
19204 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19205 tcg_gen_add_i64(t2, t2, t3);
19206 tcg_temp_free_i64(t3);
19207 gen_move_low32(cpu_LO[acc], t2);
19208 gen_move_high32(cpu_HI[acc], t2);
19209 tcg_temp_free_i64(t2);
19211 break;
19212 case NM_MULTU:
19213 check_dsp(ctx);
19215 int acc = extract32(ctx->opcode, 14, 2);
19216 TCGv_i32 t2 = tcg_temp_new_i32();
19217 TCGv_i32 t3 = tcg_temp_new_i32();
19219 gen_load_gpr(t0, rs);
19220 gen_load_gpr(t1, rt);
19221 tcg_gen_trunc_tl_i32(t2, t0);
19222 tcg_gen_trunc_tl_i32(t3, t1);
19223 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19224 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19225 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19226 tcg_temp_free_i32(t2);
19227 tcg_temp_free_i32(t3);
19229 break;
19230 case NM_EXTRV_R_W:
19231 check_dsp(ctx);
19232 tcg_gen_movi_tl(t0, rd >> 3);
19233 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19234 gen_store_gpr(t0, ret);
19235 break;
19236 default:
19237 generate_exception_end(ctx, EXCP_RI);
19238 break;
19240 break;
19241 case NM_POOL32AXF_2_16_23:
19242 switch (extract32(ctx->opcode, 9, 3)) {
19243 case NM_DPAU_H_QBL:
19244 case NM_DPAQX_S_W_PH:
19245 case NM_DPSU_H_QBL:
19246 case NM_DPSQX_S_W_PH:
19247 case NM_MULSA_W_PH:
19248 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19249 break;
19250 case NM_EXTPV:
19251 check_dsp(ctx);
19252 tcg_gen_movi_tl(t0, rd >> 3);
19253 gen_helper_extp(t0, t0, v1_t, cpu_env);
19254 gen_store_gpr(t0, ret);
19255 break;
19256 case NM_MSUB:
19257 check_dsp(ctx);
19259 int acc = extract32(ctx->opcode, 14, 2);
19260 TCGv_i64 t2 = tcg_temp_new_i64();
19261 TCGv_i64 t3 = tcg_temp_new_i64();
19263 gen_load_gpr(t0, rs);
19264 gen_load_gpr(t1, rt);
19265 tcg_gen_ext_tl_i64(t2, t0);
19266 tcg_gen_ext_tl_i64(t3, t1);
19267 tcg_gen_mul_i64(t2, t2, t3);
19268 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19269 tcg_gen_sub_i64(t2, t3, t2);
19270 tcg_temp_free_i64(t3);
19271 gen_move_low32(cpu_LO[acc], t2);
19272 gen_move_high32(cpu_HI[acc], t2);
19273 tcg_temp_free_i64(t2);
19275 break;
19276 case NM_EXTRV_RS_W:
19277 check_dsp(ctx);
19278 tcg_gen_movi_tl(t0, rd >> 3);
19279 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19280 gen_store_gpr(t0, ret);
19281 break;
19283 break;
19284 case NM_POOL32AXF_2_24_31:
19285 switch (extract32(ctx->opcode, 9, 3)) {
19286 case NM_DPAU_H_QBR:
19287 case NM_DPAQX_SA_W_PH:
19288 case NM_DPSU_H_QBR:
19289 case NM_DPSQX_SA_W_PH:
19290 case NM_MULSAQ_S_W_PH:
19291 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19292 break;
19293 case NM_EXTPDPV:
19294 check_dsp(ctx);
19295 tcg_gen_movi_tl(t0, rd >> 3);
19296 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19297 gen_store_gpr(t0, ret);
19298 break;
19299 case NM_MSUBU:
19300 check_dsp(ctx);
19302 int acc = extract32(ctx->opcode, 14, 2);
19303 TCGv_i64 t2 = tcg_temp_new_i64();
19304 TCGv_i64 t3 = tcg_temp_new_i64();
19306 gen_load_gpr(t0, rs);
19307 gen_load_gpr(t1, rt);
19308 tcg_gen_ext32u_tl(t0, t0);
19309 tcg_gen_ext32u_tl(t1, t1);
19310 tcg_gen_extu_tl_i64(t2, t0);
19311 tcg_gen_extu_tl_i64(t3, t1);
19312 tcg_gen_mul_i64(t2, t2, t3);
19313 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19314 tcg_gen_sub_i64(t2, t3, t2);
19315 tcg_temp_free_i64(t3);
19316 gen_move_low32(cpu_LO[acc], t2);
19317 gen_move_high32(cpu_HI[acc], t2);
19318 tcg_temp_free_i64(t2);
19320 break;
19321 case NM_EXTRV_S_H:
19322 check_dsp(ctx);
19323 tcg_gen_movi_tl(t0, rd >> 3);
19324 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19325 gen_store_gpr(t0, ret);
19326 break;
19328 break;
19329 default:
19330 generate_exception_end(ctx, EXCP_RI);
19331 break;
19334 tcg_temp_free(t0);
19335 tcg_temp_free(t1);
19337 tcg_temp_free(v0_t);
19338 tcg_temp_free(v1_t);
19341 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19342 int rt, int rs)
19344 int ret = rt;
19345 TCGv t0 = tcg_temp_new();
19346 TCGv v0_t = tcg_temp_new();
19348 gen_load_gpr(v0_t, rs);
19350 switch (opc) {
19351 case NM_ABSQ_S_QB:
19352 check_dsp_r2(ctx);
19353 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19354 gen_store_gpr(v0_t, ret);
19355 break;
19356 case NM_ABSQ_S_PH:
19357 check_dsp(ctx);
19358 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19359 gen_store_gpr(v0_t, ret);
19360 break;
19361 case NM_ABSQ_S_W:
19362 check_dsp(ctx);
19363 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19364 gen_store_gpr(v0_t, ret);
19365 break;
19366 case NM_PRECEQ_W_PHL:
19367 check_dsp(ctx);
19368 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19369 tcg_gen_ext32s_tl(v0_t, v0_t);
19370 gen_store_gpr(v0_t, ret);
19371 break;
19372 case NM_PRECEQ_W_PHR:
19373 check_dsp(ctx);
19374 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19375 tcg_gen_shli_tl(v0_t, v0_t, 16);
19376 tcg_gen_ext32s_tl(v0_t, v0_t);
19377 gen_store_gpr(v0_t, ret);
19378 break;
19379 case NM_PRECEQU_PH_QBL:
19380 check_dsp(ctx);
19381 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19382 gen_store_gpr(v0_t, ret);
19383 break;
19384 case NM_PRECEQU_PH_QBR:
19385 check_dsp(ctx);
19386 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19387 gen_store_gpr(v0_t, ret);
19388 break;
19389 case NM_PRECEQU_PH_QBLA:
19390 check_dsp(ctx);
19391 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19392 gen_store_gpr(v0_t, ret);
19393 break;
19394 case NM_PRECEQU_PH_QBRA:
19395 check_dsp(ctx);
19396 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19397 gen_store_gpr(v0_t, ret);
19398 break;
19399 case NM_PRECEU_PH_QBL:
19400 check_dsp(ctx);
19401 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19402 gen_store_gpr(v0_t, ret);
19403 break;
19404 case NM_PRECEU_PH_QBR:
19405 check_dsp(ctx);
19406 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19407 gen_store_gpr(v0_t, ret);
19408 break;
19409 case NM_PRECEU_PH_QBLA:
19410 check_dsp(ctx);
19411 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19412 gen_store_gpr(v0_t, ret);
19413 break;
19414 case NM_PRECEU_PH_QBRA:
19415 check_dsp(ctx);
19416 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19417 gen_store_gpr(v0_t, ret);
19418 break;
19419 case NM_REPLV_PH:
19420 check_dsp(ctx);
19421 tcg_gen_ext16u_tl(v0_t, v0_t);
19422 tcg_gen_shli_tl(t0, v0_t, 16);
19423 tcg_gen_or_tl(v0_t, v0_t, t0);
19424 tcg_gen_ext32s_tl(v0_t, v0_t);
19425 gen_store_gpr(v0_t, ret);
19426 break;
19427 case NM_REPLV_QB:
19428 check_dsp(ctx);
19429 tcg_gen_ext8u_tl(v0_t, v0_t);
19430 tcg_gen_shli_tl(t0, v0_t, 8);
19431 tcg_gen_or_tl(v0_t, v0_t, t0);
19432 tcg_gen_shli_tl(t0, v0_t, 16);
19433 tcg_gen_or_tl(v0_t, v0_t, t0);
19434 tcg_gen_ext32s_tl(v0_t, v0_t);
19435 gen_store_gpr(v0_t, ret);
19436 break;
19437 case NM_BITREV:
19438 check_dsp(ctx);
19439 gen_helper_bitrev(v0_t, v0_t);
19440 gen_store_gpr(v0_t, ret);
19441 break;
19442 case NM_INSV:
19443 check_dsp(ctx);
19445 TCGv tv0 = tcg_temp_new();
19447 gen_load_gpr(tv0, rt);
19448 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19449 gen_store_gpr(v0_t, ret);
19450 tcg_temp_free(tv0);
19452 break;
19453 case NM_RADDU_W_QB:
19454 check_dsp(ctx);
19455 gen_helper_raddu_w_qb(v0_t, v0_t);
19456 gen_store_gpr(v0_t, ret);
19457 break;
19458 case NM_BITSWAP:
19459 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19460 break;
19461 case NM_CLO:
19462 check_nms(ctx);
19463 gen_cl(ctx, OPC_CLO, ret, rs);
19464 break;
19465 case NM_CLZ:
19466 check_nms(ctx);
19467 gen_cl(ctx, OPC_CLZ, ret, rs);
19468 break;
19469 case NM_WSBH:
19470 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19471 break;
19472 default:
19473 generate_exception_end(ctx, EXCP_RI);
19474 break;
19477 tcg_temp_free(v0_t);
19478 tcg_temp_free(t0);
19481 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19482 int rt, int rs, int rd)
19484 TCGv t0 = tcg_temp_new();
19485 TCGv rs_t = tcg_temp_new();
19487 gen_load_gpr(rs_t, rs);
19489 switch (opc) {
19490 case NM_SHRA_R_QB:
19491 check_dsp_r2(ctx);
19492 tcg_gen_movi_tl(t0, rd >> 2);
19493 switch (extract32(ctx->opcode, 12, 1)) {
19494 case 0:
19495 /* NM_SHRA_QB */
19496 gen_helper_shra_qb(t0, t0, rs_t);
19497 gen_store_gpr(t0, rt);
19498 break;
19499 case 1:
19500 /* NM_SHRA_R_QB */
19501 gen_helper_shra_r_qb(t0, t0, rs_t);
19502 gen_store_gpr(t0, rt);
19503 break;
19505 break;
19506 case NM_SHRL_PH:
19507 check_dsp_r2(ctx);
19508 tcg_gen_movi_tl(t0, rd >> 1);
19509 gen_helper_shrl_ph(t0, t0, rs_t);
19510 gen_store_gpr(t0, rt);
19511 break;
19512 case NM_REPL_QB:
19513 check_dsp(ctx);
19515 int16_t imm;
19516 target_long result;
19517 imm = extract32(ctx->opcode, 13, 8);
19518 result = (uint32_t)imm << 24 |
19519 (uint32_t)imm << 16 |
19520 (uint32_t)imm << 8 |
19521 (uint32_t)imm;
19522 result = (int32_t)result;
19523 tcg_gen_movi_tl(t0, result);
19524 gen_store_gpr(t0, rt);
19526 break;
19527 default:
19528 generate_exception_end(ctx, EXCP_RI);
19529 break;
19531 tcg_temp_free(t0);
19532 tcg_temp_free(rs_t);
19536 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19538 int rt = extract32(ctx->opcode, 21, 5);
19539 int rs = extract32(ctx->opcode, 16, 5);
19540 int rd = extract32(ctx->opcode, 11, 5);
19542 switch (extract32(ctx->opcode, 6, 3)) {
19543 case NM_POOL32AXF_1:
19545 int32_t op1 = extract32(ctx->opcode, 9, 3);
19546 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19548 break;
19549 case NM_POOL32AXF_2:
19551 int32_t op1 = extract32(ctx->opcode, 12, 2);
19552 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19554 break;
19555 case NM_POOL32AXF_4:
19557 int32_t op1 = extract32(ctx->opcode, 9, 7);
19558 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19560 break;
19561 case NM_POOL32AXF_5:
19562 switch (extract32(ctx->opcode, 9, 7)) {
19563 #ifndef CONFIG_USER_ONLY
19564 case NM_TLBP:
19565 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19566 break;
19567 case NM_TLBR:
19568 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19569 break;
19570 case NM_TLBWI:
19571 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19572 break;
19573 case NM_TLBWR:
19574 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19575 break;
19576 case NM_TLBINV:
19577 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19578 break;
19579 case NM_TLBINVF:
19580 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19581 break;
19582 case NM_DI:
19583 check_cp0_enabled(ctx);
19585 TCGv t0 = tcg_temp_new();
19587 save_cpu_state(ctx, 1);
19588 gen_helper_di(t0, cpu_env);
19589 gen_store_gpr(t0, rt);
19590 /* Stop translation as we may have switched the execution mode */
19591 ctx->base.is_jmp = DISAS_STOP;
19592 tcg_temp_free(t0);
19594 break;
19595 case NM_EI:
19596 check_cp0_enabled(ctx);
19598 TCGv t0 = tcg_temp_new();
19600 save_cpu_state(ctx, 1);
19601 gen_helper_ei(t0, cpu_env);
19602 gen_store_gpr(t0, rt);
19603 /* Stop translation as we may have switched the execution mode */
19604 ctx->base.is_jmp = DISAS_STOP;
19605 tcg_temp_free(t0);
19607 break;
19608 case NM_RDPGPR:
19609 gen_load_srsgpr(rs, rt);
19610 break;
19611 case NM_WRPGPR:
19612 gen_store_srsgpr(rs, rt);
19613 break;
19614 case NM_WAIT:
19615 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19616 break;
19617 case NM_DERET:
19618 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19619 break;
19620 case NM_ERETX:
19621 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19622 break;
19623 #endif
19624 default:
19625 generate_exception_end(ctx, EXCP_RI);
19626 break;
19628 break;
19629 case NM_POOL32AXF_7:
19631 int32_t op1 = extract32(ctx->opcode, 9, 3);
19632 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19634 break;
19635 default:
19636 generate_exception_end(ctx, EXCP_RI);
19637 break;
19641 /* Immediate Value Compact Branches */
19642 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19643 int rt, int32_t imm, int32_t offset)
19645 TCGCond cond;
19646 int bcond_compute = 0;
19647 TCGv t0 = tcg_temp_new();
19648 TCGv t1 = tcg_temp_new();
19650 gen_load_gpr(t0, rt);
19651 tcg_gen_movi_tl(t1, imm);
19652 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19654 /* Load needed operands and calculate btarget */
19655 switch (opc) {
19656 case NM_BEQIC:
19657 if (rt == 0 && imm == 0) {
19658 /* Unconditional branch */
19659 } else if (rt == 0 && imm != 0) {
19660 /* Treat as NOP */
19661 goto out;
19662 } else {
19663 bcond_compute = 1;
19664 cond = TCG_COND_EQ;
19666 break;
19667 case NM_BBEQZC:
19668 case NM_BBNEZC:
19669 check_nms(ctx);
19670 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19671 generate_exception_end(ctx, EXCP_RI);
19672 goto out;
19673 } else if (rt == 0 && opc == NM_BBEQZC) {
19674 /* Unconditional branch */
19675 } else if (rt == 0 && opc == NM_BBNEZC) {
19676 /* Treat as NOP */
19677 goto out;
19678 } else {
19679 tcg_gen_shri_tl(t0, t0, imm);
19680 tcg_gen_andi_tl(t0, t0, 1);
19681 tcg_gen_movi_tl(t1, 0);
19682 bcond_compute = 1;
19683 if (opc == NM_BBEQZC) {
19684 cond = TCG_COND_EQ;
19685 } else {
19686 cond = TCG_COND_NE;
19689 break;
19690 case NM_BNEIC:
19691 if (rt == 0 && imm == 0) {
19692 /* Treat as NOP */
19693 goto out;
19694 } else if (rt == 0 && imm != 0) {
19695 /* Unconditional branch */
19696 } else {
19697 bcond_compute = 1;
19698 cond = TCG_COND_NE;
19700 break;
19701 case NM_BGEIC:
19702 if (rt == 0 && imm == 0) {
19703 /* Unconditional branch */
19704 } else {
19705 bcond_compute = 1;
19706 cond = TCG_COND_GE;
19708 break;
19709 case NM_BLTIC:
19710 bcond_compute = 1;
19711 cond = TCG_COND_LT;
19712 break;
19713 case NM_BGEIUC:
19714 if (rt == 0 && imm == 0) {
19715 /* Unconditional branch */
19716 } else {
19717 bcond_compute = 1;
19718 cond = TCG_COND_GEU;
19720 break;
19721 case NM_BLTIUC:
19722 bcond_compute = 1;
19723 cond = TCG_COND_LTU;
19724 break;
19725 default:
19726 MIPS_INVAL("Immediate Value Compact branch");
19727 generate_exception_end(ctx, EXCP_RI);
19728 goto out;
19731 /* branch completion */
19732 clear_branch_hflags(ctx);
19733 ctx->base.is_jmp = DISAS_NORETURN;
19735 if (bcond_compute == 0) {
19736 /* Uncoditional compact branch */
19737 gen_goto_tb(ctx, 0, ctx->btarget);
19738 } else {
19739 /* Conditional compact branch */
19740 TCGLabel *fs = gen_new_label();
19742 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19744 gen_goto_tb(ctx, 1, ctx->btarget);
19745 gen_set_label(fs);
19747 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19750 out:
19751 tcg_temp_free(t0);
19752 tcg_temp_free(t1);
19755 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19756 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19757 int rt)
19759 TCGv t0 = tcg_temp_new();
19760 TCGv t1 = tcg_temp_new();
19762 /* load rs */
19763 gen_load_gpr(t0, rs);
19765 /* link */
19766 if (rt != 0) {
19767 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19770 /* calculate btarget */
19771 tcg_gen_shli_tl(t0, t0, 1);
19772 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19773 gen_op_addr_add(ctx, btarget, t1, t0);
19775 /* branch completion */
19776 clear_branch_hflags(ctx);
19777 ctx->base.is_jmp = DISAS_NORETURN;
19779 /* unconditional branch to register */
19780 tcg_gen_mov_tl(cpu_PC, btarget);
19781 tcg_gen_lookup_and_goto_ptr();
19783 tcg_temp_free(t0);
19784 tcg_temp_free(t1);
19787 /* nanoMIPS Branches */
19788 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19789 int rs, int rt, int32_t offset)
19791 int bcond_compute = 0;
19792 TCGv t0 = tcg_temp_new();
19793 TCGv t1 = tcg_temp_new();
19795 /* Load needed operands and calculate btarget */
19796 switch (opc) {
19797 /* compact branch */
19798 case OPC_BGEC:
19799 case OPC_BLTC:
19800 gen_load_gpr(t0, rs);
19801 gen_load_gpr(t1, rt);
19802 bcond_compute = 1;
19803 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19804 break;
19805 case OPC_BGEUC:
19806 case OPC_BLTUC:
19807 if (rs == 0 || rs == rt) {
19808 /* OPC_BLEZALC, OPC_BGEZALC */
19809 /* OPC_BGTZALC, OPC_BLTZALC */
19810 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19812 gen_load_gpr(t0, rs);
19813 gen_load_gpr(t1, rt);
19814 bcond_compute = 1;
19815 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19816 break;
19817 case OPC_BC:
19818 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19819 break;
19820 case OPC_BEQZC:
19821 if (rs != 0) {
19822 /* OPC_BEQZC, OPC_BNEZC */
19823 gen_load_gpr(t0, rs);
19824 bcond_compute = 1;
19825 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19826 } else {
19827 /* OPC_JIC, OPC_JIALC */
19828 TCGv tbase = tcg_temp_new();
19829 TCGv toffset = tcg_temp_new();
19831 gen_load_gpr(tbase, rt);
19832 tcg_gen_movi_tl(toffset, offset);
19833 gen_op_addr_add(ctx, btarget, tbase, toffset);
19834 tcg_temp_free(tbase);
19835 tcg_temp_free(toffset);
19837 break;
19838 default:
19839 MIPS_INVAL("Compact branch/jump");
19840 generate_exception_end(ctx, EXCP_RI);
19841 goto out;
19844 if (bcond_compute == 0) {
19845 /* Uncoditional compact branch */
19846 switch (opc) {
19847 case OPC_BC:
19848 gen_goto_tb(ctx, 0, ctx->btarget);
19849 break;
19850 default:
19851 MIPS_INVAL("Compact branch/jump");
19852 generate_exception_end(ctx, EXCP_RI);
19853 goto out;
19855 } else {
19856 /* Conditional compact branch */
19857 TCGLabel *fs = gen_new_label();
19859 switch (opc) {
19860 case OPC_BGEUC:
19861 if (rs == 0 && rt != 0) {
19862 /* OPC_BLEZALC */
19863 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19864 } else if (rs != 0 && rt != 0 && rs == rt) {
19865 /* OPC_BGEZALC */
19866 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19867 } else {
19868 /* OPC_BGEUC */
19869 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19871 break;
19872 case OPC_BLTUC:
19873 if (rs == 0 && rt != 0) {
19874 /* OPC_BGTZALC */
19875 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19876 } else if (rs != 0 && rt != 0 && rs == rt) {
19877 /* OPC_BLTZALC */
19878 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19879 } else {
19880 /* OPC_BLTUC */
19881 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19883 break;
19884 case OPC_BGEC:
19885 if (rs == 0 && rt != 0) {
19886 /* OPC_BLEZC */
19887 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19888 } else if (rs != 0 && rt != 0 && rs == rt) {
19889 /* OPC_BGEZC */
19890 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19891 } else {
19892 /* OPC_BGEC */
19893 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19895 break;
19896 case OPC_BLTC:
19897 if (rs == 0 && rt != 0) {
19898 /* OPC_BGTZC */
19899 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19900 } else if (rs != 0 && rt != 0 && rs == rt) {
19901 /* OPC_BLTZC */
19902 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19903 } else {
19904 /* OPC_BLTC */
19905 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19907 break;
19908 case OPC_BEQZC:
19909 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19910 break;
19911 default:
19912 MIPS_INVAL("Compact conditional branch/jump");
19913 generate_exception_end(ctx, EXCP_RI);
19914 goto out;
19917 /* branch completion */
19918 clear_branch_hflags(ctx);
19919 ctx->base.is_jmp = DISAS_NORETURN;
19921 /* Generating branch here as compact branches don't have delay slot */
19922 gen_goto_tb(ctx, 1, ctx->btarget);
19923 gen_set_label(fs);
19925 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19928 out:
19929 tcg_temp_free(t0);
19930 tcg_temp_free(t1);
19934 /* nanoMIPS CP1 Branches */
19935 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19936 int32_t ft, int32_t offset)
19938 target_ulong btarget;
19939 TCGv_i64 t0 = tcg_temp_new_i64();
19941 gen_load_fpr64(ctx, t0, ft);
19942 tcg_gen_andi_i64(t0, t0, 1);
19944 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19946 switch (op) {
19947 case NM_BC1EQZC:
19948 tcg_gen_xori_i64(t0, t0, 1);
19949 ctx->hflags |= MIPS_HFLAG_BC;
19950 break;
19951 case NM_BC1NEZC:
19952 /* t0 already set */
19953 ctx->hflags |= MIPS_HFLAG_BC;
19954 break;
19955 default:
19956 MIPS_INVAL("cp1 cond branch");
19957 generate_exception_end(ctx, EXCP_RI);
19958 goto out;
19961 tcg_gen_trunc_i64_tl(bcond, t0);
19963 ctx->btarget = btarget;
19965 out:
19966 tcg_temp_free_i64(t0);
19970 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19972 TCGv t0, t1;
19973 t0 = tcg_temp_new();
19974 t1 = tcg_temp_new();
19976 gen_load_gpr(t0, rs);
19977 gen_load_gpr(t1, rt);
19979 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19980 /* PP.LSXS instructions require shifting */
19981 switch (extract32(ctx->opcode, 7, 4)) {
19982 case NM_SHXS:
19983 check_nms(ctx);
19984 case NM_LHXS:
19985 case NM_LHUXS:
19986 tcg_gen_shli_tl(t0, t0, 1);
19987 break;
19988 case NM_SWXS:
19989 check_nms(ctx);
19990 case NM_LWXS:
19991 case NM_LWC1XS:
19992 case NM_SWC1XS:
19993 tcg_gen_shli_tl(t0, t0, 2);
19994 break;
19995 case NM_LDC1XS:
19996 case NM_SDC1XS:
19997 tcg_gen_shli_tl(t0, t0, 3);
19998 break;
20001 gen_op_addr_add(ctx, t0, t0, t1);
20003 switch (extract32(ctx->opcode, 7, 4)) {
20004 case NM_LBX:
20005 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20006 MO_SB);
20007 gen_store_gpr(t0, rd);
20008 break;
20009 case NM_LHX:
20010 /*case NM_LHXS:*/
20011 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20012 MO_TESW);
20013 gen_store_gpr(t0, rd);
20014 break;
20015 case NM_LWX:
20016 /*case NM_LWXS:*/
20017 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20018 MO_TESL);
20019 gen_store_gpr(t0, rd);
20020 break;
20021 case NM_LBUX:
20022 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20023 MO_UB);
20024 gen_store_gpr(t0, rd);
20025 break;
20026 case NM_LHUX:
20027 /*case NM_LHUXS:*/
20028 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20029 MO_TEUW);
20030 gen_store_gpr(t0, rd);
20031 break;
20032 case NM_SBX:
20033 check_nms(ctx);
20034 gen_load_gpr(t1, rd);
20035 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20036 MO_8);
20037 break;
20038 case NM_SHX:
20039 /*case NM_SHXS:*/
20040 check_nms(ctx);
20041 gen_load_gpr(t1, rd);
20042 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20043 MO_TEUW);
20044 break;
20045 case NM_SWX:
20046 /*case NM_SWXS:*/
20047 check_nms(ctx);
20048 gen_load_gpr(t1, rd);
20049 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20050 MO_TEUL);
20051 break;
20052 case NM_LWC1X:
20053 /*case NM_LWC1XS:*/
20054 case NM_LDC1X:
20055 /*case NM_LDC1XS:*/
20056 case NM_SWC1X:
20057 /*case NM_SWC1XS:*/
20058 case NM_SDC1X:
20059 /*case NM_SDC1XS:*/
20060 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20061 check_cp1_enabled(ctx);
20062 switch (extract32(ctx->opcode, 7, 4)) {
20063 case NM_LWC1X:
20064 /*case NM_LWC1XS:*/
20065 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20066 break;
20067 case NM_LDC1X:
20068 /*case NM_LDC1XS:*/
20069 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20070 break;
20071 case NM_SWC1X:
20072 /*case NM_SWC1XS:*/
20073 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20074 break;
20075 case NM_SDC1X:
20076 /*case NM_SDC1XS:*/
20077 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20078 break;
20080 } else {
20081 generate_exception_err(ctx, EXCP_CpU, 1);
20083 break;
20084 default:
20085 generate_exception_end(ctx, EXCP_RI);
20086 break;
20089 tcg_temp_free(t0);
20090 tcg_temp_free(t1);
20093 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20095 int rt, rs, rd;
20097 rt = extract32(ctx->opcode, 21, 5);
20098 rs = extract32(ctx->opcode, 16, 5);
20099 rd = extract32(ctx->opcode, 11, 5);
20101 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20102 generate_exception_end(ctx, EXCP_RI);
20103 return;
20105 check_cp1_enabled(ctx);
20106 switch (extract32(ctx->opcode, 0, 3)) {
20107 case NM_POOL32F_0:
20108 switch (extract32(ctx->opcode, 3, 7)) {
20109 case NM_RINT_S:
20110 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20111 break;
20112 case NM_RINT_D:
20113 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20114 break;
20115 case NM_CLASS_S:
20116 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20117 break;
20118 case NM_CLASS_D:
20119 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20120 break;
20121 case NM_ADD_S:
20122 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20123 break;
20124 case NM_ADD_D:
20125 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20126 break;
20127 case NM_SUB_S:
20128 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20129 break;
20130 case NM_SUB_D:
20131 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20132 break;
20133 case NM_MUL_S:
20134 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20135 break;
20136 case NM_MUL_D:
20137 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20138 break;
20139 case NM_DIV_S:
20140 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20141 break;
20142 case NM_DIV_D:
20143 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20144 break;
20145 case NM_SELEQZ_S:
20146 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20147 break;
20148 case NM_SELEQZ_D:
20149 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20150 break;
20151 case NM_SELNEZ_S:
20152 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20153 break;
20154 case NM_SELNEZ_D:
20155 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20156 break;
20157 case NM_SEL_S:
20158 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20159 break;
20160 case NM_SEL_D:
20161 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20162 break;
20163 case NM_MADDF_S:
20164 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20165 break;
20166 case NM_MADDF_D:
20167 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20168 break;
20169 case NM_MSUBF_S:
20170 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20171 break;
20172 case NM_MSUBF_D:
20173 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20174 break;
20175 default:
20176 generate_exception_end(ctx, EXCP_RI);
20177 break;
20179 break;
20180 case NM_POOL32F_3:
20181 switch (extract32(ctx->opcode, 3, 3)) {
20182 case NM_MIN_FMT:
20183 switch (extract32(ctx->opcode, 9, 1)) {
20184 case FMT_SDPS_S:
20185 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20186 break;
20187 case FMT_SDPS_D:
20188 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20189 break;
20191 break;
20192 case NM_MAX_FMT:
20193 switch (extract32(ctx->opcode, 9, 1)) {
20194 case FMT_SDPS_S:
20195 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20196 break;
20197 case FMT_SDPS_D:
20198 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20199 break;
20201 break;
20202 case NM_MINA_FMT:
20203 switch (extract32(ctx->opcode, 9, 1)) {
20204 case FMT_SDPS_S:
20205 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20206 break;
20207 case FMT_SDPS_D:
20208 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20209 break;
20211 break;
20212 case NM_MAXA_FMT:
20213 switch (extract32(ctx->opcode, 9, 1)) {
20214 case FMT_SDPS_S:
20215 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20216 break;
20217 case FMT_SDPS_D:
20218 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20219 break;
20221 break;
20222 case NM_POOL32FXF:
20223 switch (extract32(ctx->opcode, 6, 8)) {
20224 case NM_CFC1:
20225 gen_cp1(ctx, OPC_CFC1, rt, rs);
20226 break;
20227 case NM_CTC1:
20228 gen_cp1(ctx, OPC_CTC1, rt, rs);
20229 break;
20230 case NM_MFC1:
20231 gen_cp1(ctx, OPC_MFC1, rt, rs);
20232 break;
20233 case NM_MTC1:
20234 gen_cp1(ctx, OPC_MTC1, rt, rs);
20235 break;
20236 case NM_MFHC1:
20237 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20238 break;
20239 case NM_MTHC1:
20240 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20241 break;
20242 case NM_CVT_S_PL:
20243 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20244 break;
20245 case NM_CVT_S_PU:
20246 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20247 break;
20248 default:
20249 switch (extract32(ctx->opcode, 6, 9)) {
20250 case NM_CVT_L_S:
20251 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20252 break;
20253 case NM_CVT_L_D:
20254 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20255 break;
20256 case NM_CVT_W_S:
20257 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20258 break;
20259 case NM_CVT_W_D:
20260 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20261 break;
20262 case NM_RSQRT_S:
20263 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20264 break;
20265 case NM_RSQRT_D:
20266 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20267 break;
20268 case NM_SQRT_S:
20269 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20270 break;
20271 case NM_SQRT_D:
20272 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20273 break;
20274 case NM_RECIP_S:
20275 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20276 break;
20277 case NM_RECIP_D:
20278 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20279 break;
20280 case NM_FLOOR_L_S:
20281 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20282 break;
20283 case NM_FLOOR_L_D:
20284 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20285 break;
20286 case NM_FLOOR_W_S:
20287 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20288 break;
20289 case NM_FLOOR_W_D:
20290 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20291 break;
20292 case NM_CEIL_L_S:
20293 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20294 break;
20295 case NM_CEIL_L_D:
20296 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20297 break;
20298 case NM_CEIL_W_S:
20299 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20300 break;
20301 case NM_CEIL_W_D:
20302 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20303 break;
20304 case NM_TRUNC_L_S:
20305 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20306 break;
20307 case NM_TRUNC_L_D:
20308 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20309 break;
20310 case NM_TRUNC_W_S:
20311 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20312 break;
20313 case NM_TRUNC_W_D:
20314 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20315 break;
20316 case NM_ROUND_L_S:
20317 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20318 break;
20319 case NM_ROUND_L_D:
20320 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20321 break;
20322 case NM_ROUND_W_S:
20323 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20324 break;
20325 case NM_ROUND_W_D:
20326 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20327 break;
20328 case NM_MOV_S:
20329 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20330 break;
20331 case NM_MOV_D:
20332 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20333 break;
20334 case NM_ABS_S:
20335 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20336 break;
20337 case NM_ABS_D:
20338 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20339 break;
20340 case NM_NEG_S:
20341 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20342 break;
20343 case NM_NEG_D:
20344 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20345 break;
20346 case NM_CVT_D_S:
20347 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20348 break;
20349 case NM_CVT_D_W:
20350 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20351 break;
20352 case NM_CVT_D_L:
20353 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20354 break;
20355 case NM_CVT_S_D:
20356 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20357 break;
20358 case NM_CVT_S_W:
20359 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20360 break;
20361 case NM_CVT_S_L:
20362 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20363 break;
20364 default:
20365 generate_exception_end(ctx, EXCP_RI);
20366 break;
20368 break;
20370 break;
20372 break;
20373 case NM_POOL32F_5:
20374 switch (extract32(ctx->opcode, 3, 3)) {
20375 case NM_CMP_CONDN_S:
20376 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20377 break;
20378 case NM_CMP_CONDN_D:
20379 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20380 break;
20381 default:
20382 generate_exception_end(ctx, EXCP_RI);
20383 break;
20385 break;
20386 default:
20387 generate_exception_end(ctx, EXCP_RI);
20388 break;
20392 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20393 int rd, int rs, int rt)
20395 int ret = rd;
20396 TCGv t0 = tcg_temp_new();
20397 TCGv v1_t = tcg_temp_new();
20398 TCGv v2_t = tcg_temp_new();
20400 gen_load_gpr(v1_t, rs);
20401 gen_load_gpr(v2_t, rt);
20403 switch (opc) {
20404 case NM_CMP_EQ_PH:
20405 check_dsp(ctx);
20406 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20407 break;
20408 case NM_CMP_LT_PH:
20409 check_dsp(ctx);
20410 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20411 break;
20412 case NM_CMP_LE_PH:
20413 check_dsp(ctx);
20414 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20415 break;
20416 case NM_CMPU_EQ_QB:
20417 check_dsp(ctx);
20418 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20419 break;
20420 case NM_CMPU_LT_QB:
20421 check_dsp(ctx);
20422 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20423 break;
20424 case NM_CMPU_LE_QB:
20425 check_dsp(ctx);
20426 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20427 break;
20428 case NM_CMPGU_EQ_QB:
20429 check_dsp(ctx);
20430 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20431 gen_store_gpr(v1_t, ret);
20432 break;
20433 case NM_CMPGU_LT_QB:
20434 check_dsp(ctx);
20435 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20436 gen_store_gpr(v1_t, ret);
20437 break;
20438 case NM_CMPGU_LE_QB:
20439 check_dsp(ctx);
20440 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20441 gen_store_gpr(v1_t, ret);
20442 break;
20443 case NM_CMPGDU_EQ_QB:
20444 check_dsp_r2(ctx);
20445 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20446 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20447 gen_store_gpr(v1_t, ret);
20448 break;
20449 case NM_CMPGDU_LT_QB:
20450 check_dsp_r2(ctx);
20451 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20452 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20453 gen_store_gpr(v1_t, ret);
20454 break;
20455 case NM_CMPGDU_LE_QB:
20456 check_dsp_r2(ctx);
20457 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20458 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20459 gen_store_gpr(v1_t, ret);
20460 break;
20461 case NM_PACKRL_PH:
20462 check_dsp(ctx);
20463 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20464 gen_store_gpr(v1_t, ret);
20465 break;
20466 case NM_PICK_QB:
20467 check_dsp(ctx);
20468 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20469 gen_store_gpr(v1_t, ret);
20470 break;
20471 case NM_PICK_PH:
20472 check_dsp(ctx);
20473 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20474 gen_store_gpr(v1_t, ret);
20475 break;
20476 case NM_ADDQ_S_W:
20477 check_dsp(ctx);
20478 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20479 gen_store_gpr(v1_t, ret);
20480 break;
20481 case NM_SUBQ_S_W:
20482 check_dsp(ctx);
20483 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20484 gen_store_gpr(v1_t, ret);
20485 break;
20486 case NM_ADDSC:
20487 check_dsp(ctx);
20488 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20489 gen_store_gpr(v1_t, ret);
20490 break;
20491 case NM_ADDWC:
20492 check_dsp(ctx);
20493 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20494 gen_store_gpr(v1_t, ret);
20495 break;
20496 case NM_ADDQ_S_PH:
20497 check_dsp(ctx);
20498 switch (extract32(ctx->opcode, 10, 1)) {
20499 case 0:
20500 /* ADDQ_PH */
20501 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20502 gen_store_gpr(v1_t, ret);
20503 break;
20504 case 1:
20505 /* ADDQ_S_PH */
20506 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20507 gen_store_gpr(v1_t, ret);
20508 break;
20510 break;
20511 case NM_ADDQH_R_PH:
20512 check_dsp_r2(ctx);
20513 switch (extract32(ctx->opcode, 10, 1)) {
20514 case 0:
20515 /* ADDQH_PH */
20516 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20517 gen_store_gpr(v1_t, ret);
20518 break;
20519 case 1:
20520 /* ADDQH_R_PH */
20521 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20522 gen_store_gpr(v1_t, ret);
20523 break;
20525 break;
20526 case NM_ADDQH_R_W:
20527 check_dsp_r2(ctx);
20528 switch (extract32(ctx->opcode, 10, 1)) {
20529 case 0:
20530 /* ADDQH_W */
20531 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20532 gen_store_gpr(v1_t, ret);
20533 break;
20534 case 1:
20535 /* ADDQH_R_W */
20536 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20537 gen_store_gpr(v1_t, ret);
20538 break;
20540 break;
20541 case NM_ADDU_S_QB:
20542 check_dsp(ctx);
20543 switch (extract32(ctx->opcode, 10, 1)) {
20544 case 0:
20545 /* ADDU_QB */
20546 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20547 gen_store_gpr(v1_t, ret);
20548 break;
20549 case 1:
20550 /* ADDU_S_QB */
20551 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20552 gen_store_gpr(v1_t, ret);
20553 break;
20555 break;
20556 case NM_ADDU_S_PH:
20557 check_dsp_r2(ctx);
20558 switch (extract32(ctx->opcode, 10, 1)) {
20559 case 0:
20560 /* ADDU_PH */
20561 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20562 gen_store_gpr(v1_t, ret);
20563 break;
20564 case 1:
20565 /* ADDU_S_PH */
20566 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20567 gen_store_gpr(v1_t, ret);
20568 break;
20570 break;
20571 case NM_ADDUH_R_QB:
20572 check_dsp_r2(ctx);
20573 switch (extract32(ctx->opcode, 10, 1)) {
20574 case 0:
20575 /* ADDUH_QB */
20576 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20577 gen_store_gpr(v1_t, ret);
20578 break;
20579 case 1:
20580 /* ADDUH_R_QB */
20581 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20582 gen_store_gpr(v1_t, ret);
20583 break;
20585 break;
20586 case NM_SHRAV_R_PH:
20587 check_dsp(ctx);
20588 switch (extract32(ctx->opcode, 10, 1)) {
20589 case 0:
20590 /* SHRAV_PH */
20591 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20592 gen_store_gpr(v1_t, ret);
20593 break;
20594 case 1:
20595 /* SHRAV_R_PH */
20596 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20597 gen_store_gpr(v1_t, ret);
20598 break;
20600 break;
20601 case NM_SHRAV_R_QB:
20602 check_dsp_r2(ctx);
20603 switch (extract32(ctx->opcode, 10, 1)) {
20604 case 0:
20605 /* SHRAV_QB */
20606 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20607 gen_store_gpr(v1_t, ret);
20608 break;
20609 case 1:
20610 /* SHRAV_R_QB */
20611 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20612 gen_store_gpr(v1_t, ret);
20613 break;
20615 break;
20616 case NM_SUBQ_S_PH:
20617 check_dsp(ctx);
20618 switch (extract32(ctx->opcode, 10, 1)) {
20619 case 0:
20620 /* SUBQ_PH */
20621 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20622 gen_store_gpr(v1_t, ret);
20623 break;
20624 case 1:
20625 /* SUBQ_S_PH */
20626 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20627 gen_store_gpr(v1_t, ret);
20628 break;
20630 break;
20631 case NM_SUBQH_R_PH:
20632 check_dsp_r2(ctx);
20633 switch (extract32(ctx->opcode, 10, 1)) {
20634 case 0:
20635 /* SUBQH_PH */
20636 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20637 gen_store_gpr(v1_t, ret);
20638 break;
20639 case 1:
20640 /* SUBQH_R_PH */
20641 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20642 gen_store_gpr(v1_t, ret);
20643 break;
20645 break;
20646 case NM_SUBQH_R_W:
20647 check_dsp_r2(ctx);
20648 switch (extract32(ctx->opcode, 10, 1)) {
20649 case 0:
20650 /* SUBQH_W */
20651 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20652 gen_store_gpr(v1_t, ret);
20653 break;
20654 case 1:
20655 /* SUBQH_R_W */
20656 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20657 gen_store_gpr(v1_t, ret);
20658 break;
20660 break;
20661 case NM_SUBU_S_QB:
20662 check_dsp(ctx);
20663 switch (extract32(ctx->opcode, 10, 1)) {
20664 case 0:
20665 /* SUBU_QB */
20666 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20667 gen_store_gpr(v1_t, ret);
20668 break;
20669 case 1:
20670 /* SUBU_S_QB */
20671 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20672 gen_store_gpr(v1_t, ret);
20673 break;
20675 break;
20676 case NM_SUBU_S_PH:
20677 check_dsp_r2(ctx);
20678 switch (extract32(ctx->opcode, 10, 1)) {
20679 case 0:
20680 /* SUBU_PH */
20681 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20682 gen_store_gpr(v1_t, ret);
20683 break;
20684 case 1:
20685 /* SUBU_S_PH */
20686 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20687 gen_store_gpr(v1_t, ret);
20688 break;
20690 break;
20691 case NM_SUBUH_R_QB:
20692 check_dsp_r2(ctx);
20693 switch (extract32(ctx->opcode, 10, 1)) {
20694 case 0:
20695 /* SUBUH_QB */
20696 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20697 gen_store_gpr(v1_t, ret);
20698 break;
20699 case 1:
20700 /* SUBUH_R_QB */
20701 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20702 gen_store_gpr(v1_t, ret);
20703 break;
20705 break;
20706 case NM_SHLLV_S_PH:
20707 check_dsp(ctx);
20708 switch (extract32(ctx->opcode, 10, 1)) {
20709 case 0:
20710 /* SHLLV_PH */
20711 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20712 gen_store_gpr(v1_t, ret);
20713 break;
20714 case 1:
20715 /* SHLLV_S_PH */
20716 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20717 gen_store_gpr(v1_t, ret);
20718 break;
20720 break;
20721 case NM_PRECR_SRA_R_PH_W:
20722 check_dsp_r2(ctx);
20723 switch (extract32(ctx->opcode, 10, 1)) {
20724 case 0:
20725 /* PRECR_SRA_PH_W */
20727 TCGv_i32 sa_t = tcg_const_i32(rd);
20728 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20729 cpu_gpr[rt]);
20730 gen_store_gpr(v1_t, rt);
20731 tcg_temp_free_i32(sa_t);
20733 break;
20734 case 1:
20735 /* PRECR_SRA_R_PH_W */
20737 TCGv_i32 sa_t = tcg_const_i32(rd);
20738 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20739 cpu_gpr[rt]);
20740 gen_store_gpr(v1_t, rt);
20741 tcg_temp_free_i32(sa_t);
20743 break;
20745 break;
20746 case NM_MULEU_S_PH_QBL:
20747 check_dsp(ctx);
20748 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20749 gen_store_gpr(v1_t, ret);
20750 break;
20751 case NM_MULEU_S_PH_QBR:
20752 check_dsp(ctx);
20753 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20754 gen_store_gpr(v1_t, ret);
20755 break;
20756 case NM_MULQ_RS_PH:
20757 check_dsp(ctx);
20758 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20759 gen_store_gpr(v1_t, ret);
20760 break;
20761 case NM_MULQ_S_PH:
20762 check_dsp_r2(ctx);
20763 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20764 gen_store_gpr(v1_t, ret);
20765 break;
20766 case NM_MULQ_RS_W:
20767 check_dsp_r2(ctx);
20768 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20769 gen_store_gpr(v1_t, ret);
20770 break;
20771 case NM_MULQ_S_W:
20772 check_dsp_r2(ctx);
20773 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20774 gen_store_gpr(v1_t, ret);
20775 break;
20776 case NM_APPEND:
20777 check_dsp_r2(ctx);
20778 gen_load_gpr(t0, rs);
20779 if (rd != 0) {
20780 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20782 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20783 break;
20784 case NM_MODSUB:
20785 check_dsp(ctx);
20786 gen_helper_modsub(v1_t, v1_t, v2_t);
20787 gen_store_gpr(v1_t, ret);
20788 break;
20789 case NM_SHRAV_R_W:
20790 check_dsp(ctx);
20791 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20792 gen_store_gpr(v1_t, ret);
20793 break;
20794 case NM_SHRLV_PH:
20795 check_dsp_r2(ctx);
20796 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20797 gen_store_gpr(v1_t, ret);
20798 break;
20799 case NM_SHRLV_QB:
20800 check_dsp(ctx);
20801 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20802 gen_store_gpr(v1_t, ret);
20803 break;
20804 case NM_SHLLV_QB:
20805 check_dsp(ctx);
20806 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20807 gen_store_gpr(v1_t, ret);
20808 break;
20809 case NM_SHLLV_S_W:
20810 check_dsp(ctx);
20811 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20812 gen_store_gpr(v1_t, ret);
20813 break;
20814 case NM_SHILO:
20815 check_dsp(ctx);
20817 TCGv tv0 = tcg_temp_new();
20818 TCGv tv1 = tcg_temp_new();
20819 int16_t imm = extract32(ctx->opcode, 16, 7);
20821 tcg_gen_movi_tl(tv0, rd >> 3);
20822 tcg_gen_movi_tl(tv1, imm);
20823 gen_helper_shilo(tv0, tv1, cpu_env);
20825 break;
20826 case NM_MULEQ_S_W_PHL:
20827 check_dsp(ctx);
20828 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20829 gen_store_gpr(v1_t, ret);
20830 break;
20831 case NM_MULEQ_S_W_PHR:
20832 check_dsp(ctx);
20833 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20834 gen_store_gpr(v1_t, ret);
20835 break;
20836 case NM_MUL_S_PH:
20837 check_dsp_r2(ctx);
20838 switch (extract32(ctx->opcode, 10, 1)) {
20839 case 0:
20840 /* MUL_PH */
20841 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20842 gen_store_gpr(v1_t, ret);
20843 break;
20844 case 1:
20845 /* MUL_S_PH */
20846 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20847 gen_store_gpr(v1_t, ret);
20848 break;
20850 break;
20851 case NM_PRECR_QB_PH:
20852 check_dsp_r2(ctx);
20853 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20854 gen_store_gpr(v1_t, ret);
20855 break;
20856 case NM_PRECRQ_QB_PH:
20857 check_dsp(ctx);
20858 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20859 gen_store_gpr(v1_t, ret);
20860 break;
20861 case NM_PRECRQ_PH_W:
20862 check_dsp(ctx);
20863 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20864 gen_store_gpr(v1_t, ret);
20865 break;
20866 case NM_PRECRQ_RS_PH_W:
20867 check_dsp(ctx);
20868 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20869 gen_store_gpr(v1_t, ret);
20870 break;
20871 case NM_PRECRQU_S_QB_PH:
20872 check_dsp(ctx);
20873 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20874 gen_store_gpr(v1_t, ret);
20875 break;
20876 case NM_SHRA_R_W:
20877 check_dsp(ctx);
20878 tcg_gen_movi_tl(t0, rd);
20879 gen_helper_shra_r_w(v1_t, t0, v1_t);
20880 gen_store_gpr(v1_t, rt);
20881 break;
20882 case NM_SHRA_R_PH:
20883 check_dsp(ctx);
20884 tcg_gen_movi_tl(t0, rd >> 1);
20885 switch (extract32(ctx->opcode, 10, 1)) {
20886 case 0:
20887 /* SHRA_PH */
20888 gen_helper_shra_ph(v1_t, t0, v1_t);
20889 gen_store_gpr(v1_t, rt);
20890 break;
20891 case 1:
20892 /* SHRA_R_PH */
20893 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20894 gen_store_gpr(v1_t, rt);
20895 break;
20897 break;
20898 case NM_SHLL_S_PH:
20899 check_dsp(ctx);
20900 tcg_gen_movi_tl(t0, rd >> 1);
20901 switch (extract32(ctx->opcode, 10, 2)) {
20902 case 0:
20903 /* SHLL_PH */
20904 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20905 gen_store_gpr(v1_t, rt);
20906 break;
20907 case 2:
20908 /* SHLL_S_PH */
20909 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20910 gen_store_gpr(v1_t, rt);
20911 break;
20912 default:
20913 generate_exception_end(ctx, EXCP_RI);
20914 break;
20916 break;
20917 case NM_SHLL_S_W:
20918 check_dsp(ctx);
20919 tcg_gen_movi_tl(t0, rd);
20920 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20921 gen_store_gpr(v1_t, rt);
20922 break;
20923 case NM_REPL_PH:
20924 check_dsp(ctx);
20926 int16_t imm;
20927 imm = sextract32(ctx->opcode, 11, 11);
20928 imm = (int16_t)(imm << 6) >> 6;
20929 if (rt != 0) {
20930 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20933 break;
20934 default:
20935 generate_exception_end(ctx, EXCP_RI);
20936 break;
20940 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20942 uint16_t insn;
20943 uint32_t op;
20944 int rt, rs, rd;
20945 int offset;
20946 int imm;
20948 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20949 ctx->opcode = (ctx->opcode << 16) | insn;
20951 rt = extract32(ctx->opcode, 21, 5);
20952 rs = extract32(ctx->opcode, 16, 5);
20953 rd = extract32(ctx->opcode, 11, 5);
20955 op = extract32(ctx->opcode, 26, 6);
20956 switch (op) {
20957 case NM_P_ADDIU:
20958 if (rt == 0) {
20959 /* P.RI */
20960 switch (extract32(ctx->opcode, 19, 2)) {
20961 case NM_SIGRIE:
20962 default:
20963 generate_exception_end(ctx, EXCP_RI);
20964 break;
20965 case NM_P_SYSCALL:
20966 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20967 generate_exception_end(ctx, EXCP_SYSCALL);
20968 } else {
20969 generate_exception_end(ctx, EXCP_RI);
20971 break;
20972 case NM_BREAK:
20973 generate_exception_end(ctx, EXCP_BREAK);
20974 break;
20975 case NM_SDBBP:
20976 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20977 gen_helper_do_semihosting(cpu_env);
20978 } else {
20979 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20980 generate_exception_end(ctx, EXCP_RI);
20981 } else {
20982 generate_exception_end(ctx, EXCP_DBp);
20985 break;
20987 } else {
20988 /* NM_ADDIU */
20989 imm = extract32(ctx->opcode, 0, 16);
20990 if (rs != 0) {
20991 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20992 } else {
20993 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20995 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20997 break;
20998 case NM_ADDIUPC:
20999 if (rt != 0) {
21000 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21001 extract32(ctx->opcode, 1, 20) << 1;
21002 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21003 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21005 break;
21006 case NM_POOL32A:
21007 switch (ctx->opcode & 0x07) {
21008 case NM_POOL32A0:
21009 gen_pool32a0_nanomips_insn(env, ctx);
21010 break;
21011 case NM_POOL32A5:
21013 int32_t op1 = extract32(ctx->opcode, 3, 7);
21014 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21016 break;
21017 case NM_POOL32A7:
21018 switch (extract32(ctx->opcode, 3, 3)) {
21019 case NM_P_LSX:
21020 gen_p_lsx(ctx, rd, rs, rt);
21021 break;
21022 case NM_LSA:
21023 /* In nanoMIPS, the shift field directly encodes the shift
21024 * amount, meaning that the supported shift values are in
21025 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
21026 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21027 extract32(ctx->opcode, 9, 2) - 1);
21028 break;
21029 case NM_EXTW:
21030 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21031 break;
21032 case NM_POOL32AXF:
21033 gen_pool32axf_nanomips_insn(env, ctx);
21034 break;
21035 default:
21036 generate_exception_end(ctx, EXCP_RI);
21037 break;
21039 break;
21040 default:
21041 generate_exception_end(ctx, EXCP_RI);
21042 break;
21044 break;
21045 case NM_P_GP_W:
21046 switch (ctx->opcode & 0x03) {
21047 case NM_ADDIUGP_W:
21048 if (rt != 0) {
21049 offset = extract32(ctx->opcode, 0, 21);
21050 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21052 break;
21053 case NM_LWGP:
21054 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21055 break;
21056 case NM_SWGP:
21057 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21058 break;
21059 default:
21060 generate_exception_end(ctx, EXCP_RI);
21061 break;
21063 break;
21064 case NM_P48I:
21066 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21067 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21068 switch (extract32(ctx->opcode, 16, 5)) {
21069 case NM_LI48:
21070 check_nms(ctx);
21071 if (rt != 0) {
21072 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21074 break;
21075 case NM_ADDIU48:
21076 check_nms(ctx);
21077 if (rt != 0) {
21078 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21079 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21081 break;
21082 case NM_ADDIUGP48:
21083 check_nms(ctx);
21084 if (rt != 0) {
21085 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21087 break;
21088 case NM_ADDIUPC48:
21089 check_nms(ctx);
21090 if (rt != 0) {
21091 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21092 addr_off);
21094 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21096 break;
21097 case NM_LWPC48:
21098 check_nms(ctx);
21099 if (rt != 0) {
21100 TCGv t0;
21101 t0 = tcg_temp_new();
21103 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21104 addr_off);
21106 tcg_gen_movi_tl(t0, addr);
21107 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21108 tcg_temp_free(t0);
21110 break;
21111 case NM_SWPC48:
21112 check_nms(ctx);
21114 TCGv t0, t1;
21115 t0 = tcg_temp_new();
21116 t1 = tcg_temp_new();
21118 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21119 addr_off);
21121 tcg_gen_movi_tl(t0, addr);
21122 gen_load_gpr(t1, rt);
21124 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21126 tcg_temp_free(t0);
21127 tcg_temp_free(t1);
21129 break;
21130 default:
21131 generate_exception_end(ctx, EXCP_RI);
21132 break;
21134 return 6;
21136 case NM_P_U12:
21137 switch (extract32(ctx->opcode, 12, 4)) {
21138 case NM_ORI:
21139 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21140 break;
21141 case NM_XORI:
21142 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21143 break;
21144 case NM_ANDI:
21145 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21146 break;
21147 case NM_P_SR:
21148 switch (extract32(ctx->opcode, 20, 1)) {
21149 case NM_PP_SR:
21150 switch (ctx->opcode & 3) {
21151 case NM_SAVE:
21152 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21153 extract32(ctx->opcode, 2, 1),
21154 extract32(ctx->opcode, 3, 9) << 3);
21155 break;
21156 case NM_RESTORE:
21157 case NM_RESTORE_JRC:
21158 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21159 extract32(ctx->opcode, 2, 1),
21160 extract32(ctx->opcode, 3, 9) << 3);
21161 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21162 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21164 break;
21165 default:
21166 generate_exception_end(ctx, EXCP_RI);
21167 break;
21169 break;
21170 case NM_P_SR_F:
21171 generate_exception_end(ctx, EXCP_RI);
21172 break;
21174 break;
21175 case NM_SLTI:
21176 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21177 break;
21178 case NM_SLTIU:
21179 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21180 break;
21181 case NM_SEQI:
21183 TCGv t0 = tcg_temp_new();
21185 imm = extract32(ctx->opcode, 0, 12);
21186 gen_load_gpr(t0, rs);
21187 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21188 gen_store_gpr(t0, rt);
21190 tcg_temp_free(t0);
21192 break;
21193 case NM_ADDIUNEG:
21194 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21195 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21196 break;
21197 case NM_P_SHIFT:
21199 int shift = extract32(ctx->opcode, 0, 5);
21200 switch (extract32(ctx->opcode, 5, 4)) {
21201 case NM_P_SLL:
21202 if (rt == 0 && shift == 0) {
21203 /* NOP */
21204 } else if (rt == 0 && shift == 3) {
21205 /* EHB - treat as NOP */
21206 } else if (rt == 0 && shift == 5) {
21207 /* PAUSE - treat as NOP */
21208 } else if (rt == 0 && shift == 6) {
21209 /* SYNC */
21210 gen_sync(extract32(ctx->opcode, 16, 5));
21211 } else {
21212 /* SLL */
21213 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21214 extract32(ctx->opcode, 0, 5));
21216 break;
21217 case NM_SRL:
21218 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21219 extract32(ctx->opcode, 0, 5));
21220 break;
21221 case NM_SRA:
21222 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21223 extract32(ctx->opcode, 0, 5));
21224 break;
21225 case NM_ROTR:
21226 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21227 extract32(ctx->opcode, 0, 5));
21228 break;
21231 break;
21232 case NM_P_ROTX:
21233 check_nms(ctx);
21234 if (rt != 0) {
21235 TCGv t0 = tcg_temp_new();
21236 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21237 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21238 << 1);
21239 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21241 gen_load_gpr(t0, rs);
21242 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21243 tcg_temp_free(t0);
21245 tcg_temp_free_i32(shift);
21246 tcg_temp_free_i32(shiftx);
21247 tcg_temp_free_i32(stripe);
21249 break;
21250 case NM_P_INS:
21251 switch (((ctx->opcode >> 10) & 2) |
21252 (extract32(ctx->opcode, 5, 1))) {
21253 case NM_INS:
21254 check_nms(ctx);
21255 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21256 extract32(ctx->opcode, 6, 5));
21257 break;
21258 default:
21259 generate_exception_end(ctx, EXCP_RI);
21260 break;
21262 break;
21263 case NM_P_EXT:
21264 switch (((ctx->opcode >> 10) & 2) |
21265 (extract32(ctx->opcode, 5, 1))) {
21266 case NM_EXT:
21267 check_nms(ctx);
21268 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21269 extract32(ctx->opcode, 6, 5));
21270 break;
21271 default:
21272 generate_exception_end(ctx, EXCP_RI);
21273 break;
21275 break;
21276 default:
21277 generate_exception_end(ctx, EXCP_RI);
21278 break;
21280 break;
21281 case NM_POOL32F:
21282 gen_pool32f_nanomips_insn(ctx);
21283 break;
21284 case NM_POOL32S:
21285 break;
21286 case NM_P_LUI:
21287 switch (extract32(ctx->opcode, 1, 1)) {
21288 case NM_LUI:
21289 if (rt != 0) {
21290 tcg_gen_movi_tl(cpu_gpr[rt],
21291 sextract32(ctx->opcode, 0, 1) << 31 |
21292 extract32(ctx->opcode, 2, 10) << 21 |
21293 extract32(ctx->opcode, 12, 9) << 12);
21295 break;
21296 case NM_ALUIPC:
21297 if (rt != 0) {
21298 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21299 extract32(ctx->opcode, 2, 10) << 21 |
21300 extract32(ctx->opcode, 12, 9) << 12;
21301 target_long addr;
21302 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21303 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21305 break;
21307 break;
21308 case NM_P_GP_BH:
21310 uint32_t u = extract32(ctx->opcode, 0, 18);
21312 switch (extract32(ctx->opcode, 18, 3)) {
21313 case NM_LBGP:
21314 gen_ld(ctx, OPC_LB, rt, 28, u);
21315 break;
21316 case NM_SBGP:
21317 gen_st(ctx, OPC_SB, rt, 28, u);
21318 break;
21319 case NM_LBUGP:
21320 gen_ld(ctx, OPC_LBU, rt, 28, u);
21321 break;
21322 case NM_ADDIUGP_B:
21323 if (rt != 0) {
21324 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21326 break;
21327 case NM_P_GP_LH:
21328 u &= ~1;
21329 switch (ctx->opcode & 1) {
21330 case NM_LHGP:
21331 gen_ld(ctx, OPC_LH, rt, 28, u);
21332 break;
21333 case NM_LHUGP:
21334 gen_ld(ctx, OPC_LHU, rt, 28, u);
21335 break;
21337 break;
21338 case NM_P_GP_SH:
21339 u &= ~1;
21340 switch (ctx->opcode & 1) {
21341 case NM_SHGP:
21342 gen_st(ctx, OPC_SH, rt, 28, u);
21343 break;
21344 default:
21345 generate_exception_end(ctx, EXCP_RI);
21346 break;
21348 break;
21349 case NM_P_GP_CP1:
21350 u &= ~0x3;
21351 switch (ctx->opcode & 0x3) {
21352 case NM_LWC1GP:
21353 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21354 break;
21355 case NM_LDC1GP:
21356 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21357 break;
21358 case NM_SWC1GP:
21359 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21360 break;
21361 case NM_SDC1GP:
21362 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21363 break;
21365 break;
21366 default:
21367 generate_exception_end(ctx, EXCP_RI);
21368 break;
21371 break;
21372 case NM_P_LS_U12:
21374 uint32_t u = extract32(ctx->opcode, 0, 12);
21376 switch (extract32(ctx->opcode, 12, 4)) {
21377 case NM_P_PREFU12:
21378 if (rt == 31) {
21379 /* SYNCI */
21380 /* Break the TB to be able to sync copied instructions
21381 immediately */
21382 ctx->base.is_jmp = DISAS_STOP;
21383 } else {
21384 /* PREF */
21385 /* Treat as NOP. */
21387 break;
21388 case NM_LB:
21389 gen_ld(ctx, OPC_LB, rt, rs, u);
21390 break;
21391 case NM_LH:
21392 gen_ld(ctx, OPC_LH, rt, rs, u);
21393 break;
21394 case NM_LW:
21395 gen_ld(ctx, OPC_LW, rt, rs, u);
21396 break;
21397 case NM_LBU:
21398 gen_ld(ctx, OPC_LBU, rt, rs, u);
21399 break;
21400 case NM_LHU:
21401 gen_ld(ctx, OPC_LHU, rt, rs, u);
21402 break;
21403 case NM_SB:
21404 gen_st(ctx, OPC_SB, rt, rs, u);
21405 break;
21406 case NM_SH:
21407 gen_st(ctx, OPC_SH, rt, rs, u);
21408 break;
21409 case NM_SW:
21410 gen_st(ctx, OPC_SW, rt, rs, u);
21411 break;
21412 case NM_LWC1:
21413 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21414 break;
21415 case NM_LDC1:
21416 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21417 break;
21418 case NM_SWC1:
21419 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21420 break;
21421 case NM_SDC1:
21422 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21423 break;
21424 default:
21425 generate_exception_end(ctx, EXCP_RI);
21426 break;
21429 break;
21430 case NM_P_LS_S9:
21432 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21433 extract32(ctx->opcode, 0, 8);
21435 switch (extract32(ctx->opcode, 8, 3)) {
21436 case NM_P_LS_S0:
21437 switch (extract32(ctx->opcode, 11, 4)) {
21438 case NM_LBS9:
21439 gen_ld(ctx, OPC_LB, rt, rs, s);
21440 break;
21441 case NM_LHS9:
21442 gen_ld(ctx, OPC_LH, rt, rs, s);
21443 break;
21444 case NM_LWS9:
21445 gen_ld(ctx, OPC_LW, rt, rs, s);
21446 break;
21447 case NM_LBUS9:
21448 gen_ld(ctx, OPC_LBU, rt, rs, s);
21449 break;
21450 case NM_LHUS9:
21451 gen_ld(ctx, OPC_LHU, rt, rs, s);
21452 break;
21453 case NM_SBS9:
21454 gen_st(ctx, OPC_SB, rt, rs, s);
21455 break;
21456 case NM_SHS9:
21457 gen_st(ctx, OPC_SH, rt, rs, s);
21458 break;
21459 case NM_SWS9:
21460 gen_st(ctx, OPC_SW, rt, rs, s);
21461 break;
21462 case NM_LWC1S9:
21463 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21464 break;
21465 case NM_LDC1S9:
21466 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21467 break;
21468 case NM_SWC1S9:
21469 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21470 break;
21471 case NM_SDC1S9:
21472 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21473 break;
21474 case NM_P_PREFS9:
21475 if (rt == 31) {
21476 /* SYNCI */
21477 /* Break the TB to be able to sync copied instructions
21478 immediately */
21479 ctx->base.is_jmp = DISAS_STOP;
21480 } else {
21481 /* PREF */
21482 /* Treat as NOP. */
21484 break;
21485 default:
21486 generate_exception_end(ctx, EXCP_RI);
21487 break;
21489 break;
21490 case NM_P_LS_S1:
21491 switch (extract32(ctx->opcode, 11, 4)) {
21492 case NM_UALH:
21493 case NM_UASH:
21494 check_nms(ctx);
21496 TCGv t0 = tcg_temp_new();
21497 TCGv t1 = tcg_temp_new();
21499 gen_base_offset_addr(ctx, t0, rs, s);
21501 switch (extract32(ctx->opcode, 11, 4)) {
21502 case NM_UALH:
21503 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21504 MO_UNALN);
21505 gen_store_gpr(t0, rt);
21506 break;
21507 case NM_UASH:
21508 gen_load_gpr(t1, rt);
21509 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21510 MO_UNALN);
21511 break;
21513 tcg_temp_free(t0);
21514 tcg_temp_free(t1);
21516 break;
21517 case NM_P_LL:
21518 switch (ctx->opcode & 0x03) {
21519 case NM_LL:
21520 gen_ld(ctx, OPC_LL, rt, rs, s);
21521 break;
21522 case NM_LLWP:
21523 check_xnp(ctx);
21524 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21525 break;
21527 break;
21528 case NM_P_SC:
21529 switch (ctx->opcode & 0x03) {
21530 case NM_SC:
21531 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21532 break;
21533 case NM_SCWP:
21534 check_xnp(ctx);
21535 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21536 false);
21537 break;
21539 break;
21540 case NM_CACHE:
21541 check_cp0_enabled(ctx);
21542 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21543 gen_cache_operation(ctx, rt, rs, s);
21545 break;
21547 break;
21548 case NM_P_LS_E0:
21549 switch (extract32(ctx->opcode, 11, 4)) {
21550 case NM_LBE:
21551 check_eva(ctx);
21552 check_cp0_enabled(ctx);
21553 gen_ld(ctx, OPC_LBE, rt, rs, s);
21554 break;
21555 case NM_SBE:
21556 check_eva(ctx);
21557 check_cp0_enabled(ctx);
21558 gen_st(ctx, OPC_SBE, rt, rs, s);
21559 break;
21560 case NM_LBUE:
21561 check_eva(ctx);
21562 check_cp0_enabled(ctx);
21563 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21564 break;
21565 case NM_P_PREFE:
21566 if (rt == 31) {
21567 /* case NM_SYNCIE */
21568 check_eva(ctx);
21569 check_cp0_enabled(ctx);
21570 /* Break the TB to be able to sync copied instructions
21571 immediately */
21572 ctx->base.is_jmp = DISAS_STOP;
21573 } else {
21574 /* case NM_PREFE */
21575 check_eva(ctx);
21576 check_cp0_enabled(ctx);
21577 /* Treat as NOP. */
21579 break;
21580 case NM_LHE:
21581 check_eva(ctx);
21582 check_cp0_enabled(ctx);
21583 gen_ld(ctx, OPC_LHE, rt, rs, s);
21584 break;
21585 case NM_SHE:
21586 check_eva(ctx);
21587 check_cp0_enabled(ctx);
21588 gen_st(ctx, OPC_SHE, rt, rs, s);
21589 break;
21590 case NM_LHUE:
21591 check_eva(ctx);
21592 check_cp0_enabled(ctx);
21593 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21594 break;
21595 case NM_CACHEE:
21596 check_nms_dl_il_sl_tl_l2c(ctx);
21597 gen_cache_operation(ctx, rt, rs, s);
21598 break;
21599 case NM_LWE:
21600 check_eva(ctx);
21601 check_cp0_enabled(ctx);
21602 gen_ld(ctx, OPC_LWE, rt, rs, s);
21603 break;
21604 case NM_SWE:
21605 check_eva(ctx);
21606 check_cp0_enabled(ctx);
21607 gen_st(ctx, OPC_SWE, rt, rs, s);
21608 break;
21609 case NM_P_LLE:
21610 switch (extract32(ctx->opcode, 2, 2)) {
21611 case NM_LLE:
21612 check_xnp(ctx);
21613 check_eva(ctx);
21614 check_cp0_enabled(ctx);
21615 gen_ld(ctx, OPC_LLE, rt, rs, s);
21616 break;
21617 case NM_LLWPE:
21618 check_xnp(ctx);
21619 check_eva(ctx);
21620 check_cp0_enabled(ctx);
21621 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21622 break;
21623 default:
21624 generate_exception_end(ctx, EXCP_RI);
21625 break;
21627 break;
21628 case NM_P_SCE:
21629 switch (extract32(ctx->opcode, 2, 2)) {
21630 case NM_SCE:
21631 check_xnp(ctx);
21632 check_eva(ctx);
21633 check_cp0_enabled(ctx);
21634 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21635 break;
21636 case NM_SCWPE:
21637 check_xnp(ctx);
21638 check_eva(ctx);
21639 check_cp0_enabled(ctx);
21640 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21641 true);
21642 break;
21643 default:
21644 generate_exception_end(ctx, EXCP_RI);
21645 break;
21647 break;
21649 break;
21650 case NM_P_LS_WM:
21651 case NM_P_LS_UAWM:
21652 check_nms(ctx);
21654 int count = extract32(ctx->opcode, 12, 3);
21655 int counter = 0;
21657 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21658 extract32(ctx->opcode, 0, 8);
21659 TCGv va = tcg_temp_new();
21660 TCGv t1 = tcg_temp_new();
21661 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21662 NM_P_LS_UAWM ? MO_UNALN : 0;
21664 count = (count == 0) ? 8 : count;
21665 while (counter != count) {
21666 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21667 int this_offset = offset + (counter << 2);
21669 gen_base_offset_addr(ctx, va, rs, this_offset);
21671 switch (extract32(ctx->opcode, 11, 1)) {
21672 case NM_LWM:
21673 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21674 memop | MO_TESL);
21675 gen_store_gpr(t1, this_rt);
21676 if ((this_rt == rs) &&
21677 (counter != (count - 1))) {
21678 /* UNPREDICTABLE */
21680 break;
21681 case NM_SWM:
21682 this_rt = (rt == 0) ? 0 : this_rt;
21683 gen_load_gpr(t1, this_rt);
21684 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21685 memop | MO_TEUL);
21686 break;
21688 counter++;
21690 tcg_temp_free(va);
21691 tcg_temp_free(t1);
21693 break;
21694 default:
21695 generate_exception_end(ctx, EXCP_RI);
21696 break;
21699 break;
21700 case NM_MOVE_BALC:
21701 check_nms(ctx);
21703 TCGv t0 = tcg_temp_new();
21704 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21705 extract32(ctx->opcode, 1, 20) << 1;
21706 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21707 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21708 extract32(ctx->opcode, 21, 3));
21709 gen_load_gpr(t0, rt);
21710 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21711 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21712 tcg_temp_free(t0);
21714 break;
21715 case NM_P_BAL:
21717 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21718 extract32(ctx->opcode, 1, 24) << 1;
21720 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21721 /* BC */
21722 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21723 } else {
21724 /* BALC */
21725 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21728 break;
21729 case NM_P_J:
21730 switch (extract32(ctx->opcode, 12, 4)) {
21731 case NM_JALRC:
21732 case NM_JALRC_HB:
21733 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21734 break;
21735 case NM_P_BALRSC:
21736 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21737 break;
21738 default:
21739 generate_exception_end(ctx, EXCP_RI);
21740 break;
21742 break;
21743 case NM_P_BR1:
21745 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21746 extract32(ctx->opcode, 1, 13) << 1;
21747 switch (extract32(ctx->opcode, 14, 2)) {
21748 case NM_BEQC:
21749 check_nms(ctx);
21750 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21751 break;
21752 case NM_P_BR3A:
21753 s = sextract32(ctx->opcode, 0, 1) << 14 |
21754 extract32(ctx->opcode, 1, 13) << 1;
21755 check_cp1_enabled(ctx);
21756 switch (extract32(ctx->opcode, 16, 5)) {
21757 case NM_BC1EQZC:
21758 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21759 break;
21760 case NM_BC1NEZC:
21761 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21762 break;
21763 case NM_BPOSGE32C:
21764 check_dsp_r3(ctx);
21766 int32_t imm = extract32(ctx->opcode, 1, 13) |
21767 extract32(ctx->opcode, 0, 1) << 13;
21769 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21770 imm);
21772 break;
21773 default:
21774 generate_exception_end(ctx, EXCP_RI);
21775 break;
21777 break;
21778 case NM_BGEC:
21779 if (rs == rt) {
21780 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21781 } else {
21782 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21784 break;
21785 case NM_BGEUC:
21786 if (rs == rt || rt == 0) {
21787 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21788 } else if (rs == 0) {
21789 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21790 } else {
21791 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21793 break;
21796 break;
21797 case NM_P_BR2:
21799 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21800 extract32(ctx->opcode, 1, 13) << 1;
21801 switch (extract32(ctx->opcode, 14, 2)) {
21802 case NM_BNEC:
21803 check_nms(ctx);
21804 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21805 break;
21806 case NM_BLTC:
21807 if (rs != 0 && rt != 0 && rs == rt) {
21808 /* NOP */
21809 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21810 } else {
21811 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21813 break;
21814 case NM_BLTUC:
21815 if (rs == 0 || rs == rt) {
21816 /* NOP */
21817 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21818 } else {
21819 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21821 break;
21822 default:
21823 generate_exception_end(ctx, EXCP_RI);
21824 break;
21827 break;
21828 case NM_P_BRI:
21830 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21831 extract32(ctx->opcode, 1, 10) << 1;
21832 uint32_t u = extract32(ctx->opcode, 11, 7);
21834 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21835 rt, u, s);
21837 break;
21838 default:
21839 generate_exception_end(ctx, EXCP_RI);
21840 break;
21842 return 4;
21845 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21847 uint32_t op;
21848 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21849 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21850 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21851 int offset;
21852 int imm;
21854 /* make sure instructions are on a halfword boundary */
21855 if (ctx->base.pc_next & 0x1) {
21856 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21857 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21858 tcg_temp_free(tmp);
21859 generate_exception_end(ctx, EXCP_AdEL);
21860 return 2;
21863 op = extract32(ctx->opcode, 10, 6);
21864 switch (op) {
21865 case NM_P16_MV:
21866 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21867 if (rt != 0) {
21868 /* MOVE */
21869 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21870 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21871 } else {
21872 /* P16.RI */
21873 switch (extract32(ctx->opcode, 3, 2)) {
21874 case NM_P16_SYSCALL:
21875 if (extract32(ctx->opcode, 2, 1) == 0) {
21876 generate_exception_end(ctx, EXCP_SYSCALL);
21877 } else {
21878 generate_exception_end(ctx, EXCP_RI);
21880 break;
21881 case NM_BREAK16:
21882 generate_exception_end(ctx, EXCP_BREAK);
21883 break;
21884 case NM_SDBBP16:
21885 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21886 gen_helper_do_semihosting(cpu_env);
21887 } else {
21888 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21889 generate_exception_end(ctx, EXCP_RI);
21890 } else {
21891 generate_exception_end(ctx, EXCP_DBp);
21894 break;
21895 default:
21896 generate_exception_end(ctx, EXCP_RI);
21897 break;
21900 break;
21901 case NM_P16_SHIFT:
21903 int shift = extract32(ctx->opcode, 0, 3);
21904 uint32_t opc = 0;
21905 shift = (shift == 0) ? 8 : shift;
21907 switch (extract32(ctx->opcode, 3, 1)) {
21908 case NM_SLL16:
21909 opc = OPC_SLL;
21910 break;
21911 case NM_SRL16:
21912 opc = OPC_SRL;
21913 break;
21915 gen_shift_imm(ctx, opc, rt, rs, shift);
21917 break;
21918 case NM_P16C:
21919 switch (ctx->opcode & 1) {
21920 case NM_POOL16C_0:
21921 gen_pool16c_nanomips_insn(ctx);
21922 break;
21923 case NM_LWXS16:
21924 gen_ldxs(ctx, rt, rs, rd);
21925 break;
21927 break;
21928 case NM_P16_A1:
21929 switch (extract32(ctx->opcode, 6, 1)) {
21930 case NM_ADDIUR1SP:
21931 imm = extract32(ctx->opcode, 0, 6) << 2;
21932 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21933 break;
21934 default:
21935 generate_exception_end(ctx, EXCP_RI);
21936 break;
21938 break;
21939 case NM_P16_A2:
21940 switch (extract32(ctx->opcode, 3, 1)) {
21941 case NM_ADDIUR2:
21942 imm = extract32(ctx->opcode, 0, 3) << 2;
21943 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21944 break;
21945 case NM_P_ADDIURS5:
21946 rt = extract32(ctx->opcode, 5, 5);
21947 if (rt != 0) {
21948 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21949 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21950 (extract32(ctx->opcode, 0, 3));
21951 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21953 break;
21955 break;
21956 case NM_P16_ADDU:
21957 switch (ctx->opcode & 0x1) {
21958 case NM_ADDU16:
21959 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21960 break;
21961 case NM_SUBU16:
21962 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21963 break;
21965 break;
21966 case NM_P16_4X4:
21967 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21968 extract32(ctx->opcode, 5, 3);
21969 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21970 extract32(ctx->opcode, 0, 3);
21971 rt = decode_gpr_gpr4(rt);
21972 rs = decode_gpr_gpr4(rs);
21973 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21974 (extract32(ctx->opcode, 3, 1))) {
21975 case NM_ADDU4X4:
21976 check_nms(ctx);
21977 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21978 break;
21979 case NM_MUL4X4:
21980 check_nms(ctx);
21981 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21982 break;
21983 default:
21984 generate_exception_end(ctx, EXCP_RI);
21985 break;
21987 break;
21988 case NM_LI16:
21990 int imm = extract32(ctx->opcode, 0, 7);
21991 imm = (imm == 0x7f ? -1 : imm);
21992 if (rt != 0) {
21993 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21996 break;
21997 case NM_ANDI16:
21999 uint32_t u = extract32(ctx->opcode, 0, 4);
22000 u = (u == 12) ? 0xff :
22001 (u == 13) ? 0xffff : u;
22002 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22004 break;
22005 case NM_P16_LB:
22006 offset = extract32(ctx->opcode, 0, 2);
22007 switch (extract32(ctx->opcode, 2, 2)) {
22008 case NM_LB16:
22009 gen_ld(ctx, OPC_LB, rt, rs, offset);
22010 break;
22011 case NM_SB16:
22012 rt = decode_gpr_gpr3_src_store(
22013 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22014 gen_st(ctx, OPC_SB, rt, rs, offset);
22015 break;
22016 case NM_LBU16:
22017 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22018 break;
22019 default:
22020 generate_exception_end(ctx, EXCP_RI);
22021 break;
22023 break;
22024 case NM_P16_LH:
22025 offset = extract32(ctx->opcode, 1, 2) << 1;
22026 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22027 case NM_LH16:
22028 gen_ld(ctx, OPC_LH, rt, rs, offset);
22029 break;
22030 case NM_SH16:
22031 rt = decode_gpr_gpr3_src_store(
22032 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22033 gen_st(ctx, OPC_SH, rt, rs, offset);
22034 break;
22035 case NM_LHU16:
22036 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22037 break;
22038 default:
22039 generate_exception_end(ctx, EXCP_RI);
22040 break;
22042 break;
22043 case NM_LW16:
22044 offset = extract32(ctx->opcode, 0, 4) << 2;
22045 gen_ld(ctx, OPC_LW, rt, rs, offset);
22046 break;
22047 case NM_LWSP16:
22048 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22049 offset = extract32(ctx->opcode, 0, 5) << 2;
22050 gen_ld(ctx, OPC_LW, rt, 29, offset);
22051 break;
22052 case NM_LW4X4:
22053 check_nms(ctx);
22054 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22055 extract32(ctx->opcode, 5, 3);
22056 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22057 extract32(ctx->opcode, 0, 3);
22058 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22059 (extract32(ctx->opcode, 8, 1) << 2);
22060 rt = decode_gpr_gpr4(rt);
22061 rs = decode_gpr_gpr4(rs);
22062 gen_ld(ctx, OPC_LW, rt, rs, offset);
22063 break;
22064 case NM_SW4X4:
22065 check_nms(ctx);
22066 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22067 extract32(ctx->opcode, 5, 3);
22068 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22069 extract32(ctx->opcode, 0, 3);
22070 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22071 (extract32(ctx->opcode, 8, 1) << 2);
22072 rt = decode_gpr_gpr4_zero(rt);
22073 rs = decode_gpr_gpr4(rs);
22074 gen_st(ctx, OPC_SW, rt, rs, offset);
22075 break;
22076 case NM_LWGP16:
22077 offset = extract32(ctx->opcode, 0, 7) << 2;
22078 gen_ld(ctx, OPC_LW, rt, 28, offset);
22079 break;
22080 case NM_SWSP16:
22081 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22082 offset = extract32(ctx->opcode, 0, 5) << 2;
22083 gen_st(ctx, OPC_SW, rt, 29, offset);
22084 break;
22085 case NM_SW16:
22086 rt = decode_gpr_gpr3_src_store(
22087 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22088 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22089 offset = extract32(ctx->opcode, 0, 4) << 2;
22090 gen_st(ctx, OPC_SW, rt, rs, offset);
22091 break;
22092 case NM_SWGP16:
22093 rt = decode_gpr_gpr3_src_store(
22094 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22095 offset = extract32(ctx->opcode, 0, 7) << 2;
22096 gen_st(ctx, OPC_SW, rt, 28, offset);
22097 break;
22098 case NM_BC16:
22099 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22100 (sextract32(ctx->opcode, 0, 1) << 10) |
22101 (extract32(ctx->opcode, 1, 9) << 1));
22102 break;
22103 case NM_BALC16:
22104 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22105 (sextract32(ctx->opcode, 0, 1) << 10) |
22106 (extract32(ctx->opcode, 1, 9) << 1));
22107 break;
22108 case NM_BEQZC16:
22109 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22110 (sextract32(ctx->opcode, 0, 1) << 7) |
22111 (extract32(ctx->opcode, 1, 6) << 1));
22112 break;
22113 case NM_BNEZC16:
22114 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22115 (sextract32(ctx->opcode, 0, 1) << 7) |
22116 (extract32(ctx->opcode, 1, 6) << 1));
22117 break;
22118 case NM_P16_BR:
22119 switch (ctx->opcode & 0xf) {
22120 case 0:
22121 /* P16.JRC */
22122 switch (extract32(ctx->opcode, 4, 1)) {
22123 case NM_JRC:
22124 gen_compute_branch_nm(ctx, OPC_JR, 2,
22125 extract32(ctx->opcode, 5, 5), 0, 0);
22126 break;
22127 case NM_JALRC16:
22128 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22129 extract32(ctx->opcode, 5, 5), 31, 0);
22130 break;
22132 break;
22133 default:
22135 /* P16.BRI */
22136 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22137 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22138 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22139 extract32(ctx->opcode, 0, 4) << 1);
22141 break;
22143 break;
22144 case NM_P16_SR:
22146 int count = extract32(ctx->opcode, 0, 4);
22147 int u = extract32(ctx->opcode, 4, 4) << 4;
22149 rt = 30 + extract32(ctx->opcode, 9, 1);
22150 switch (extract32(ctx->opcode, 8, 1)) {
22151 case NM_SAVE16:
22152 gen_save(ctx, rt, count, 0, u);
22153 break;
22154 case NM_RESTORE_JRC16:
22155 gen_restore(ctx, rt, count, 0, u);
22156 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22157 break;
22160 break;
22161 case NM_MOVEP:
22162 case NM_MOVEPREV:
22163 check_nms(ctx);
22165 static const int gpr2reg1[] = {4, 5, 6, 7};
22166 static const int gpr2reg2[] = {5, 6, 7, 8};
22167 int re;
22168 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22169 extract32(ctx->opcode, 8, 1);
22170 int r1 = gpr2reg1[rd2];
22171 int r2 = gpr2reg2[rd2];
22172 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22173 extract32(ctx->opcode, 0, 3);
22174 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22175 extract32(ctx->opcode, 5, 3);
22176 TCGv t0 = tcg_temp_new();
22177 TCGv t1 = tcg_temp_new();
22178 if (op == NM_MOVEP) {
22179 rd = r1;
22180 re = r2;
22181 rs = decode_gpr_gpr4_zero(r3);
22182 rt = decode_gpr_gpr4_zero(r4);
22183 } else {
22184 rd = decode_gpr_gpr4(r3);
22185 re = decode_gpr_gpr4(r4);
22186 rs = r1;
22187 rt = r2;
22189 gen_load_gpr(t0, rs);
22190 gen_load_gpr(t1, rt);
22191 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22192 tcg_gen_mov_tl(cpu_gpr[re], t1);
22193 tcg_temp_free(t0);
22194 tcg_temp_free(t1);
22196 break;
22197 default:
22198 return decode_nanomips_32_48_opc(env, ctx);
22201 return 2;
22205 /* SmartMIPS extension to MIPS32 */
22207 #if defined(TARGET_MIPS64)
22209 /* MDMX extension to MIPS64 */
22211 #endif
22213 /* MIPSDSP functions. */
22214 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22215 int rd, int base, int offset)
22217 TCGv t0;
22219 check_dsp(ctx);
22220 t0 = tcg_temp_new();
22222 if (base == 0) {
22223 gen_load_gpr(t0, offset);
22224 } else if (offset == 0) {
22225 gen_load_gpr(t0, base);
22226 } else {
22227 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22230 switch (opc) {
22231 case OPC_LBUX:
22232 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22233 gen_store_gpr(t0, rd);
22234 break;
22235 case OPC_LHX:
22236 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22237 gen_store_gpr(t0, rd);
22238 break;
22239 case OPC_LWX:
22240 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22241 gen_store_gpr(t0, rd);
22242 break;
22243 #if defined(TARGET_MIPS64)
22244 case OPC_LDX:
22245 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22246 gen_store_gpr(t0, rd);
22247 break;
22248 #endif
22250 tcg_temp_free(t0);
22253 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22254 int ret, int v1, int v2)
22256 TCGv v1_t;
22257 TCGv v2_t;
22259 if (ret == 0) {
22260 /* Treat as NOP. */
22261 return;
22264 v1_t = tcg_temp_new();
22265 v2_t = tcg_temp_new();
22267 gen_load_gpr(v1_t, v1);
22268 gen_load_gpr(v2_t, v2);
22270 switch (op1) {
22271 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22272 case OPC_MULT_G_2E:
22273 check_dsp_r2(ctx);
22274 switch (op2) {
22275 case OPC_ADDUH_QB:
22276 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22277 break;
22278 case OPC_ADDUH_R_QB:
22279 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22280 break;
22281 case OPC_ADDQH_PH:
22282 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22283 break;
22284 case OPC_ADDQH_R_PH:
22285 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22286 break;
22287 case OPC_ADDQH_W:
22288 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22289 break;
22290 case OPC_ADDQH_R_W:
22291 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22292 break;
22293 case OPC_SUBUH_QB:
22294 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22295 break;
22296 case OPC_SUBUH_R_QB:
22297 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22298 break;
22299 case OPC_SUBQH_PH:
22300 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22301 break;
22302 case OPC_SUBQH_R_PH:
22303 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22304 break;
22305 case OPC_SUBQH_W:
22306 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22307 break;
22308 case OPC_SUBQH_R_W:
22309 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22310 break;
22312 break;
22313 case OPC_ABSQ_S_PH_DSP:
22314 switch (op2) {
22315 case OPC_ABSQ_S_QB:
22316 check_dsp_r2(ctx);
22317 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22318 break;
22319 case OPC_ABSQ_S_PH:
22320 check_dsp(ctx);
22321 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22322 break;
22323 case OPC_ABSQ_S_W:
22324 check_dsp(ctx);
22325 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22326 break;
22327 case OPC_PRECEQ_W_PHL:
22328 check_dsp(ctx);
22329 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22330 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22331 break;
22332 case OPC_PRECEQ_W_PHR:
22333 check_dsp(ctx);
22334 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22335 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22336 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22337 break;
22338 case OPC_PRECEQU_PH_QBL:
22339 check_dsp(ctx);
22340 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22341 break;
22342 case OPC_PRECEQU_PH_QBR:
22343 check_dsp(ctx);
22344 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22345 break;
22346 case OPC_PRECEQU_PH_QBLA:
22347 check_dsp(ctx);
22348 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22349 break;
22350 case OPC_PRECEQU_PH_QBRA:
22351 check_dsp(ctx);
22352 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22353 break;
22354 case OPC_PRECEU_PH_QBL:
22355 check_dsp(ctx);
22356 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22357 break;
22358 case OPC_PRECEU_PH_QBR:
22359 check_dsp(ctx);
22360 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22361 break;
22362 case OPC_PRECEU_PH_QBLA:
22363 check_dsp(ctx);
22364 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22365 break;
22366 case OPC_PRECEU_PH_QBRA:
22367 check_dsp(ctx);
22368 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22369 break;
22371 break;
22372 case OPC_ADDU_QB_DSP:
22373 switch (op2) {
22374 case OPC_ADDQ_PH:
22375 check_dsp(ctx);
22376 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22377 break;
22378 case OPC_ADDQ_S_PH:
22379 check_dsp(ctx);
22380 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22381 break;
22382 case OPC_ADDQ_S_W:
22383 check_dsp(ctx);
22384 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22385 break;
22386 case OPC_ADDU_QB:
22387 check_dsp(ctx);
22388 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22389 break;
22390 case OPC_ADDU_S_QB:
22391 check_dsp(ctx);
22392 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22393 break;
22394 case OPC_ADDU_PH:
22395 check_dsp_r2(ctx);
22396 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22397 break;
22398 case OPC_ADDU_S_PH:
22399 check_dsp_r2(ctx);
22400 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22401 break;
22402 case OPC_SUBQ_PH:
22403 check_dsp(ctx);
22404 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22405 break;
22406 case OPC_SUBQ_S_PH:
22407 check_dsp(ctx);
22408 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22409 break;
22410 case OPC_SUBQ_S_W:
22411 check_dsp(ctx);
22412 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22413 break;
22414 case OPC_SUBU_QB:
22415 check_dsp(ctx);
22416 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22417 break;
22418 case OPC_SUBU_S_QB:
22419 check_dsp(ctx);
22420 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22421 break;
22422 case OPC_SUBU_PH:
22423 check_dsp_r2(ctx);
22424 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22425 break;
22426 case OPC_SUBU_S_PH:
22427 check_dsp_r2(ctx);
22428 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22429 break;
22430 case OPC_ADDSC:
22431 check_dsp(ctx);
22432 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22433 break;
22434 case OPC_ADDWC:
22435 check_dsp(ctx);
22436 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22437 break;
22438 case OPC_MODSUB:
22439 check_dsp(ctx);
22440 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22441 break;
22442 case OPC_RADDU_W_QB:
22443 check_dsp(ctx);
22444 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22445 break;
22447 break;
22448 case OPC_CMPU_EQ_QB_DSP:
22449 switch (op2) {
22450 case OPC_PRECR_QB_PH:
22451 check_dsp_r2(ctx);
22452 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22453 break;
22454 case OPC_PRECRQ_QB_PH:
22455 check_dsp(ctx);
22456 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22457 break;
22458 case OPC_PRECR_SRA_PH_W:
22459 check_dsp_r2(ctx);
22461 TCGv_i32 sa_t = tcg_const_i32(v2);
22462 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22463 cpu_gpr[ret]);
22464 tcg_temp_free_i32(sa_t);
22465 break;
22467 case OPC_PRECR_SRA_R_PH_W:
22468 check_dsp_r2(ctx);
22470 TCGv_i32 sa_t = tcg_const_i32(v2);
22471 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22472 cpu_gpr[ret]);
22473 tcg_temp_free_i32(sa_t);
22474 break;
22476 case OPC_PRECRQ_PH_W:
22477 check_dsp(ctx);
22478 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22479 break;
22480 case OPC_PRECRQ_RS_PH_W:
22481 check_dsp(ctx);
22482 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22483 break;
22484 case OPC_PRECRQU_S_QB_PH:
22485 check_dsp(ctx);
22486 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22487 break;
22489 break;
22490 #ifdef TARGET_MIPS64
22491 case OPC_ABSQ_S_QH_DSP:
22492 switch (op2) {
22493 case OPC_PRECEQ_L_PWL:
22494 check_dsp(ctx);
22495 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22496 break;
22497 case OPC_PRECEQ_L_PWR:
22498 check_dsp(ctx);
22499 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22500 break;
22501 case OPC_PRECEQ_PW_QHL:
22502 check_dsp(ctx);
22503 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22504 break;
22505 case OPC_PRECEQ_PW_QHR:
22506 check_dsp(ctx);
22507 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22508 break;
22509 case OPC_PRECEQ_PW_QHLA:
22510 check_dsp(ctx);
22511 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22512 break;
22513 case OPC_PRECEQ_PW_QHRA:
22514 check_dsp(ctx);
22515 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22516 break;
22517 case OPC_PRECEQU_QH_OBL:
22518 check_dsp(ctx);
22519 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22520 break;
22521 case OPC_PRECEQU_QH_OBR:
22522 check_dsp(ctx);
22523 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22524 break;
22525 case OPC_PRECEQU_QH_OBLA:
22526 check_dsp(ctx);
22527 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22528 break;
22529 case OPC_PRECEQU_QH_OBRA:
22530 check_dsp(ctx);
22531 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22532 break;
22533 case OPC_PRECEU_QH_OBL:
22534 check_dsp(ctx);
22535 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22536 break;
22537 case OPC_PRECEU_QH_OBR:
22538 check_dsp(ctx);
22539 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22540 break;
22541 case OPC_PRECEU_QH_OBLA:
22542 check_dsp(ctx);
22543 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22544 break;
22545 case OPC_PRECEU_QH_OBRA:
22546 check_dsp(ctx);
22547 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22548 break;
22549 case OPC_ABSQ_S_OB:
22550 check_dsp_r2(ctx);
22551 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22552 break;
22553 case OPC_ABSQ_S_PW:
22554 check_dsp(ctx);
22555 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22556 break;
22557 case OPC_ABSQ_S_QH:
22558 check_dsp(ctx);
22559 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22560 break;
22562 break;
22563 case OPC_ADDU_OB_DSP:
22564 switch (op2) {
22565 case OPC_RADDU_L_OB:
22566 check_dsp(ctx);
22567 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22568 break;
22569 case OPC_SUBQ_PW:
22570 check_dsp(ctx);
22571 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22572 break;
22573 case OPC_SUBQ_S_PW:
22574 check_dsp(ctx);
22575 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22576 break;
22577 case OPC_SUBQ_QH:
22578 check_dsp(ctx);
22579 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22580 break;
22581 case OPC_SUBQ_S_QH:
22582 check_dsp(ctx);
22583 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22584 break;
22585 case OPC_SUBU_OB:
22586 check_dsp(ctx);
22587 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22588 break;
22589 case OPC_SUBU_S_OB:
22590 check_dsp(ctx);
22591 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22592 break;
22593 case OPC_SUBU_QH:
22594 check_dsp_r2(ctx);
22595 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22596 break;
22597 case OPC_SUBU_S_QH:
22598 check_dsp_r2(ctx);
22599 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22600 break;
22601 case OPC_SUBUH_OB:
22602 check_dsp_r2(ctx);
22603 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22604 break;
22605 case OPC_SUBUH_R_OB:
22606 check_dsp_r2(ctx);
22607 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22608 break;
22609 case OPC_ADDQ_PW:
22610 check_dsp(ctx);
22611 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22612 break;
22613 case OPC_ADDQ_S_PW:
22614 check_dsp(ctx);
22615 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22616 break;
22617 case OPC_ADDQ_QH:
22618 check_dsp(ctx);
22619 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22620 break;
22621 case OPC_ADDQ_S_QH:
22622 check_dsp(ctx);
22623 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22624 break;
22625 case OPC_ADDU_OB:
22626 check_dsp(ctx);
22627 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22628 break;
22629 case OPC_ADDU_S_OB:
22630 check_dsp(ctx);
22631 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22632 break;
22633 case OPC_ADDU_QH:
22634 check_dsp_r2(ctx);
22635 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22636 break;
22637 case OPC_ADDU_S_QH:
22638 check_dsp_r2(ctx);
22639 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22640 break;
22641 case OPC_ADDUH_OB:
22642 check_dsp_r2(ctx);
22643 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22644 break;
22645 case OPC_ADDUH_R_OB:
22646 check_dsp_r2(ctx);
22647 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22648 break;
22650 break;
22651 case OPC_CMPU_EQ_OB_DSP:
22652 switch (op2) {
22653 case OPC_PRECR_OB_QH:
22654 check_dsp_r2(ctx);
22655 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22656 break;
22657 case OPC_PRECR_SRA_QH_PW:
22658 check_dsp_r2(ctx);
22660 TCGv_i32 ret_t = tcg_const_i32(ret);
22661 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22662 tcg_temp_free_i32(ret_t);
22663 break;
22665 case OPC_PRECR_SRA_R_QH_PW:
22666 check_dsp_r2(ctx);
22668 TCGv_i32 sa_v = tcg_const_i32(ret);
22669 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22670 tcg_temp_free_i32(sa_v);
22671 break;
22673 case OPC_PRECRQ_OB_QH:
22674 check_dsp(ctx);
22675 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22676 break;
22677 case OPC_PRECRQ_PW_L:
22678 check_dsp(ctx);
22679 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22680 break;
22681 case OPC_PRECRQ_QH_PW:
22682 check_dsp(ctx);
22683 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22684 break;
22685 case OPC_PRECRQ_RS_QH_PW:
22686 check_dsp(ctx);
22687 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22688 break;
22689 case OPC_PRECRQU_S_OB_QH:
22690 check_dsp(ctx);
22691 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22692 break;
22694 break;
22695 #endif
22698 tcg_temp_free(v1_t);
22699 tcg_temp_free(v2_t);
22702 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22703 int ret, int v1, int v2)
22705 uint32_t op2;
22706 TCGv t0;
22707 TCGv v1_t;
22708 TCGv v2_t;
22710 if (ret == 0) {
22711 /* Treat as NOP. */
22712 return;
22715 t0 = tcg_temp_new();
22716 v1_t = tcg_temp_new();
22717 v2_t = tcg_temp_new();
22719 tcg_gen_movi_tl(t0, v1);
22720 gen_load_gpr(v1_t, v1);
22721 gen_load_gpr(v2_t, v2);
22723 switch (opc) {
22724 case OPC_SHLL_QB_DSP:
22726 op2 = MASK_SHLL_QB(ctx->opcode);
22727 switch (op2) {
22728 case OPC_SHLL_QB:
22729 check_dsp(ctx);
22730 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22731 break;
22732 case OPC_SHLLV_QB:
22733 check_dsp(ctx);
22734 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22735 break;
22736 case OPC_SHLL_PH:
22737 check_dsp(ctx);
22738 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22739 break;
22740 case OPC_SHLLV_PH:
22741 check_dsp(ctx);
22742 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22743 break;
22744 case OPC_SHLL_S_PH:
22745 check_dsp(ctx);
22746 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22747 break;
22748 case OPC_SHLLV_S_PH:
22749 check_dsp(ctx);
22750 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22751 break;
22752 case OPC_SHLL_S_W:
22753 check_dsp(ctx);
22754 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22755 break;
22756 case OPC_SHLLV_S_W:
22757 check_dsp(ctx);
22758 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22759 break;
22760 case OPC_SHRL_QB:
22761 check_dsp(ctx);
22762 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22763 break;
22764 case OPC_SHRLV_QB:
22765 check_dsp(ctx);
22766 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22767 break;
22768 case OPC_SHRL_PH:
22769 check_dsp_r2(ctx);
22770 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22771 break;
22772 case OPC_SHRLV_PH:
22773 check_dsp_r2(ctx);
22774 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22775 break;
22776 case OPC_SHRA_QB:
22777 check_dsp_r2(ctx);
22778 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22779 break;
22780 case OPC_SHRA_R_QB:
22781 check_dsp_r2(ctx);
22782 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22783 break;
22784 case OPC_SHRAV_QB:
22785 check_dsp_r2(ctx);
22786 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22787 break;
22788 case OPC_SHRAV_R_QB:
22789 check_dsp_r2(ctx);
22790 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22791 break;
22792 case OPC_SHRA_PH:
22793 check_dsp(ctx);
22794 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22795 break;
22796 case OPC_SHRA_R_PH:
22797 check_dsp(ctx);
22798 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22799 break;
22800 case OPC_SHRAV_PH:
22801 check_dsp(ctx);
22802 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22803 break;
22804 case OPC_SHRAV_R_PH:
22805 check_dsp(ctx);
22806 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22807 break;
22808 case OPC_SHRA_R_W:
22809 check_dsp(ctx);
22810 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22811 break;
22812 case OPC_SHRAV_R_W:
22813 check_dsp(ctx);
22814 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22815 break;
22816 default: /* Invalid */
22817 MIPS_INVAL("MASK SHLL.QB");
22818 generate_exception_end(ctx, EXCP_RI);
22819 break;
22821 break;
22823 #ifdef TARGET_MIPS64
22824 case OPC_SHLL_OB_DSP:
22825 op2 = MASK_SHLL_OB(ctx->opcode);
22826 switch (op2) {
22827 case OPC_SHLL_PW:
22828 check_dsp(ctx);
22829 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22830 break;
22831 case OPC_SHLLV_PW:
22832 check_dsp(ctx);
22833 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22834 break;
22835 case OPC_SHLL_S_PW:
22836 check_dsp(ctx);
22837 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22838 break;
22839 case OPC_SHLLV_S_PW:
22840 check_dsp(ctx);
22841 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22842 break;
22843 case OPC_SHLL_OB:
22844 check_dsp(ctx);
22845 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22846 break;
22847 case OPC_SHLLV_OB:
22848 check_dsp(ctx);
22849 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22850 break;
22851 case OPC_SHLL_QH:
22852 check_dsp(ctx);
22853 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22854 break;
22855 case OPC_SHLLV_QH:
22856 check_dsp(ctx);
22857 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22858 break;
22859 case OPC_SHLL_S_QH:
22860 check_dsp(ctx);
22861 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22862 break;
22863 case OPC_SHLLV_S_QH:
22864 check_dsp(ctx);
22865 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22866 break;
22867 case OPC_SHRA_OB:
22868 check_dsp_r2(ctx);
22869 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22870 break;
22871 case OPC_SHRAV_OB:
22872 check_dsp_r2(ctx);
22873 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22874 break;
22875 case OPC_SHRA_R_OB:
22876 check_dsp_r2(ctx);
22877 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22878 break;
22879 case OPC_SHRAV_R_OB:
22880 check_dsp_r2(ctx);
22881 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22882 break;
22883 case OPC_SHRA_PW:
22884 check_dsp(ctx);
22885 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22886 break;
22887 case OPC_SHRAV_PW:
22888 check_dsp(ctx);
22889 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22890 break;
22891 case OPC_SHRA_R_PW:
22892 check_dsp(ctx);
22893 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22894 break;
22895 case OPC_SHRAV_R_PW:
22896 check_dsp(ctx);
22897 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22898 break;
22899 case OPC_SHRA_QH:
22900 check_dsp(ctx);
22901 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22902 break;
22903 case OPC_SHRAV_QH:
22904 check_dsp(ctx);
22905 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22906 break;
22907 case OPC_SHRA_R_QH:
22908 check_dsp(ctx);
22909 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22910 break;
22911 case OPC_SHRAV_R_QH:
22912 check_dsp(ctx);
22913 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22914 break;
22915 case OPC_SHRL_OB:
22916 check_dsp(ctx);
22917 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22918 break;
22919 case OPC_SHRLV_OB:
22920 check_dsp(ctx);
22921 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22922 break;
22923 case OPC_SHRL_QH:
22924 check_dsp_r2(ctx);
22925 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22926 break;
22927 case OPC_SHRLV_QH:
22928 check_dsp_r2(ctx);
22929 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22930 break;
22931 default: /* Invalid */
22932 MIPS_INVAL("MASK SHLL.OB");
22933 generate_exception_end(ctx, EXCP_RI);
22934 break;
22936 break;
22937 #endif
22940 tcg_temp_free(t0);
22941 tcg_temp_free(v1_t);
22942 tcg_temp_free(v2_t);
22945 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22946 int ret, int v1, int v2, int check_ret)
22948 TCGv_i32 t0;
22949 TCGv v1_t;
22950 TCGv v2_t;
22952 if ((ret == 0) && (check_ret == 1)) {
22953 /* Treat as NOP. */
22954 return;
22957 t0 = tcg_temp_new_i32();
22958 v1_t = tcg_temp_new();
22959 v2_t = tcg_temp_new();
22961 tcg_gen_movi_i32(t0, ret);
22962 gen_load_gpr(v1_t, v1);
22963 gen_load_gpr(v2_t, v2);
22965 switch (op1) {
22966 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22967 * the same mask and op1. */
22968 case OPC_MULT_G_2E:
22969 check_dsp_r2(ctx);
22970 switch (op2) {
22971 case OPC_MUL_PH:
22972 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22973 break;
22974 case OPC_MUL_S_PH:
22975 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22976 break;
22977 case OPC_MULQ_S_W:
22978 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22979 break;
22980 case OPC_MULQ_RS_W:
22981 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22982 break;
22984 break;
22985 case OPC_DPA_W_PH_DSP:
22986 switch (op2) {
22987 case OPC_DPAU_H_QBL:
22988 check_dsp(ctx);
22989 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22990 break;
22991 case OPC_DPAU_H_QBR:
22992 check_dsp(ctx);
22993 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22994 break;
22995 case OPC_DPSU_H_QBL:
22996 check_dsp(ctx);
22997 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22998 break;
22999 case OPC_DPSU_H_QBR:
23000 check_dsp(ctx);
23001 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23002 break;
23003 case OPC_DPA_W_PH:
23004 check_dsp_r2(ctx);
23005 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23006 break;
23007 case OPC_DPAX_W_PH:
23008 check_dsp_r2(ctx);
23009 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23010 break;
23011 case OPC_DPAQ_S_W_PH:
23012 check_dsp(ctx);
23013 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23014 break;
23015 case OPC_DPAQX_S_W_PH:
23016 check_dsp_r2(ctx);
23017 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23018 break;
23019 case OPC_DPAQX_SA_W_PH:
23020 check_dsp_r2(ctx);
23021 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23022 break;
23023 case OPC_DPS_W_PH:
23024 check_dsp_r2(ctx);
23025 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23026 break;
23027 case OPC_DPSX_W_PH:
23028 check_dsp_r2(ctx);
23029 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23030 break;
23031 case OPC_DPSQ_S_W_PH:
23032 check_dsp(ctx);
23033 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23034 break;
23035 case OPC_DPSQX_S_W_PH:
23036 check_dsp_r2(ctx);
23037 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23038 break;
23039 case OPC_DPSQX_SA_W_PH:
23040 check_dsp_r2(ctx);
23041 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23042 break;
23043 case OPC_MULSAQ_S_W_PH:
23044 check_dsp(ctx);
23045 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23046 break;
23047 case OPC_DPAQ_SA_L_W:
23048 check_dsp(ctx);
23049 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23050 break;
23051 case OPC_DPSQ_SA_L_W:
23052 check_dsp(ctx);
23053 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23054 break;
23055 case OPC_MAQ_S_W_PHL:
23056 check_dsp(ctx);
23057 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23058 break;
23059 case OPC_MAQ_S_W_PHR:
23060 check_dsp(ctx);
23061 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23062 break;
23063 case OPC_MAQ_SA_W_PHL:
23064 check_dsp(ctx);
23065 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23066 break;
23067 case OPC_MAQ_SA_W_PHR:
23068 check_dsp(ctx);
23069 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23070 break;
23071 case OPC_MULSA_W_PH:
23072 check_dsp_r2(ctx);
23073 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23074 break;
23076 break;
23077 #ifdef TARGET_MIPS64
23078 case OPC_DPAQ_W_QH_DSP:
23080 int ac = ret & 0x03;
23081 tcg_gen_movi_i32(t0, ac);
23083 switch (op2) {
23084 case OPC_DMADD:
23085 check_dsp(ctx);
23086 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23087 break;
23088 case OPC_DMADDU:
23089 check_dsp(ctx);
23090 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23091 break;
23092 case OPC_DMSUB:
23093 check_dsp(ctx);
23094 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23095 break;
23096 case OPC_DMSUBU:
23097 check_dsp(ctx);
23098 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23099 break;
23100 case OPC_DPA_W_QH:
23101 check_dsp_r2(ctx);
23102 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23103 break;
23104 case OPC_DPAQ_S_W_QH:
23105 check_dsp(ctx);
23106 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23107 break;
23108 case OPC_DPAQ_SA_L_PW:
23109 check_dsp(ctx);
23110 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23111 break;
23112 case OPC_DPAU_H_OBL:
23113 check_dsp(ctx);
23114 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23115 break;
23116 case OPC_DPAU_H_OBR:
23117 check_dsp(ctx);
23118 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23119 break;
23120 case OPC_DPS_W_QH:
23121 check_dsp_r2(ctx);
23122 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23123 break;
23124 case OPC_DPSQ_S_W_QH:
23125 check_dsp(ctx);
23126 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23127 break;
23128 case OPC_DPSQ_SA_L_PW:
23129 check_dsp(ctx);
23130 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23131 break;
23132 case OPC_DPSU_H_OBL:
23133 check_dsp(ctx);
23134 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23135 break;
23136 case OPC_DPSU_H_OBR:
23137 check_dsp(ctx);
23138 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23139 break;
23140 case OPC_MAQ_S_L_PWL:
23141 check_dsp(ctx);
23142 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23143 break;
23144 case OPC_MAQ_S_L_PWR:
23145 check_dsp(ctx);
23146 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23147 break;
23148 case OPC_MAQ_S_W_QHLL:
23149 check_dsp(ctx);
23150 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23151 break;
23152 case OPC_MAQ_SA_W_QHLL:
23153 check_dsp(ctx);
23154 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23155 break;
23156 case OPC_MAQ_S_W_QHLR:
23157 check_dsp(ctx);
23158 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23159 break;
23160 case OPC_MAQ_SA_W_QHLR:
23161 check_dsp(ctx);
23162 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23163 break;
23164 case OPC_MAQ_S_W_QHRL:
23165 check_dsp(ctx);
23166 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23167 break;
23168 case OPC_MAQ_SA_W_QHRL:
23169 check_dsp(ctx);
23170 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23171 break;
23172 case OPC_MAQ_S_W_QHRR:
23173 check_dsp(ctx);
23174 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23175 break;
23176 case OPC_MAQ_SA_W_QHRR:
23177 check_dsp(ctx);
23178 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23179 break;
23180 case OPC_MULSAQ_S_L_PW:
23181 check_dsp(ctx);
23182 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23183 break;
23184 case OPC_MULSAQ_S_W_QH:
23185 check_dsp(ctx);
23186 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23187 break;
23190 break;
23191 #endif
23192 case OPC_ADDU_QB_DSP:
23193 switch (op2) {
23194 case OPC_MULEU_S_PH_QBL:
23195 check_dsp(ctx);
23196 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23197 break;
23198 case OPC_MULEU_S_PH_QBR:
23199 check_dsp(ctx);
23200 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23201 break;
23202 case OPC_MULQ_RS_PH:
23203 check_dsp(ctx);
23204 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23205 break;
23206 case OPC_MULEQ_S_W_PHL:
23207 check_dsp(ctx);
23208 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23209 break;
23210 case OPC_MULEQ_S_W_PHR:
23211 check_dsp(ctx);
23212 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23213 break;
23214 case OPC_MULQ_S_PH:
23215 check_dsp_r2(ctx);
23216 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23217 break;
23219 break;
23220 #ifdef TARGET_MIPS64
23221 case OPC_ADDU_OB_DSP:
23222 switch (op2) {
23223 case OPC_MULEQ_S_PW_QHL:
23224 check_dsp(ctx);
23225 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23226 break;
23227 case OPC_MULEQ_S_PW_QHR:
23228 check_dsp(ctx);
23229 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23230 break;
23231 case OPC_MULEU_S_QH_OBL:
23232 check_dsp(ctx);
23233 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23234 break;
23235 case OPC_MULEU_S_QH_OBR:
23236 check_dsp(ctx);
23237 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23238 break;
23239 case OPC_MULQ_RS_QH:
23240 check_dsp(ctx);
23241 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23242 break;
23244 break;
23245 #endif
23248 tcg_temp_free_i32(t0);
23249 tcg_temp_free(v1_t);
23250 tcg_temp_free(v2_t);
23253 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23254 int ret, int val)
23256 int16_t imm;
23257 TCGv t0;
23258 TCGv val_t;
23260 if (ret == 0) {
23261 /* Treat as NOP. */
23262 return;
23265 t0 = tcg_temp_new();
23266 val_t = tcg_temp_new();
23267 gen_load_gpr(val_t, val);
23269 switch (op1) {
23270 case OPC_ABSQ_S_PH_DSP:
23271 switch (op2) {
23272 case OPC_BITREV:
23273 check_dsp(ctx);
23274 gen_helper_bitrev(cpu_gpr[ret], val_t);
23275 break;
23276 case OPC_REPL_QB:
23277 check_dsp(ctx);
23279 target_long result;
23280 imm = (ctx->opcode >> 16) & 0xFF;
23281 result = (uint32_t)imm << 24 |
23282 (uint32_t)imm << 16 |
23283 (uint32_t)imm << 8 |
23284 (uint32_t)imm;
23285 result = (int32_t)result;
23286 tcg_gen_movi_tl(cpu_gpr[ret], result);
23288 break;
23289 case OPC_REPLV_QB:
23290 check_dsp(ctx);
23291 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23292 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23293 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23294 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23295 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23296 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23297 break;
23298 case OPC_REPL_PH:
23299 check_dsp(ctx);
23301 imm = (ctx->opcode >> 16) & 0x03FF;
23302 imm = (int16_t)(imm << 6) >> 6;
23303 tcg_gen_movi_tl(cpu_gpr[ret], \
23304 (target_long)((int32_t)imm << 16 | \
23305 (uint16_t)imm));
23307 break;
23308 case OPC_REPLV_PH:
23309 check_dsp(ctx);
23310 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23311 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23312 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23313 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23314 break;
23316 break;
23317 #ifdef TARGET_MIPS64
23318 case OPC_ABSQ_S_QH_DSP:
23319 switch (op2) {
23320 case OPC_REPL_OB:
23321 check_dsp(ctx);
23323 target_long temp;
23325 imm = (ctx->opcode >> 16) & 0xFF;
23326 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23327 temp = (temp << 16) | temp;
23328 temp = (temp << 32) | temp;
23329 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23330 break;
23332 case OPC_REPL_PW:
23333 check_dsp(ctx);
23335 target_long temp;
23337 imm = (ctx->opcode >> 16) & 0x03FF;
23338 imm = (int16_t)(imm << 6) >> 6;
23339 temp = ((target_long)imm << 32) \
23340 | ((target_long)imm & 0xFFFFFFFF);
23341 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23342 break;
23344 case OPC_REPL_QH:
23345 check_dsp(ctx);
23347 target_long temp;
23349 imm = (ctx->opcode >> 16) & 0x03FF;
23350 imm = (int16_t)(imm << 6) >> 6;
23352 temp = ((uint64_t)(uint16_t)imm << 48) |
23353 ((uint64_t)(uint16_t)imm << 32) |
23354 ((uint64_t)(uint16_t)imm << 16) |
23355 (uint64_t)(uint16_t)imm;
23356 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23357 break;
23359 case OPC_REPLV_OB:
23360 check_dsp(ctx);
23361 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23362 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23363 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23364 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23365 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23366 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23367 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23368 break;
23369 case OPC_REPLV_PW:
23370 check_dsp(ctx);
23371 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23372 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23373 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23374 break;
23375 case OPC_REPLV_QH:
23376 check_dsp(ctx);
23377 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23378 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23379 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23380 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23381 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23382 break;
23384 break;
23385 #endif
23387 tcg_temp_free(t0);
23388 tcg_temp_free(val_t);
23391 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23392 uint32_t op1, uint32_t op2,
23393 int ret, int v1, int v2, int check_ret)
23395 TCGv t1;
23396 TCGv v1_t;
23397 TCGv v2_t;
23399 if ((ret == 0) && (check_ret == 1)) {
23400 /* Treat as NOP. */
23401 return;
23404 t1 = tcg_temp_new();
23405 v1_t = tcg_temp_new();
23406 v2_t = tcg_temp_new();
23408 gen_load_gpr(v1_t, v1);
23409 gen_load_gpr(v2_t, v2);
23411 switch (op1) {
23412 case OPC_CMPU_EQ_QB_DSP:
23413 switch (op2) {
23414 case OPC_CMPU_EQ_QB:
23415 check_dsp(ctx);
23416 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23417 break;
23418 case OPC_CMPU_LT_QB:
23419 check_dsp(ctx);
23420 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23421 break;
23422 case OPC_CMPU_LE_QB:
23423 check_dsp(ctx);
23424 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23425 break;
23426 case OPC_CMPGU_EQ_QB:
23427 check_dsp(ctx);
23428 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23429 break;
23430 case OPC_CMPGU_LT_QB:
23431 check_dsp(ctx);
23432 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23433 break;
23434 case OPC_CMPGU_LE_QB:
23435 check_dsp(ctx);
23436 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23437 break;
23438 case OPC_CMPGDU_EQ_QB:
23439 check_dsp_r2(ctx);
23440 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23441 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23442 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23443 tcg_gen_shli_tl(t1, t1, 24);
23444 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23445 break;
23446 case OPC_CMPGDU_LT_QB:
23447 check_dsp_r2(ctx);
23448 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23449 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23450 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23451 tcg_gen_shli_tl(t1, t1, 24);
23452 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23453 break;
23454 case OPC_CMPGDU_LE_QB:
23455 check_dsp_r2(ctx);
23456 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23457 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23458 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23459 tcg_gen_shli_tl(t1, t1, 24);
23460 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23461 break;
23462 case OPC_CMP_EQ_PH:
23463 check_dsp(ctx);
23464 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23465 break;
23466 case OPC_CMP_LT_PH:
23467 check_dsp(ctx);
23468 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23469 break;
23470 case OPC_CMP_LE_PH:
23471 check_dsp(ctx);
23472 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23473 break;
23474 case OPC_PICK_QB:
23475 check_dsp(ctx);
23476 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23477 break;
23478 case OPC_PICK_PH:
23479 check_dsp(ctx);
23480 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23481 break;
23482 case OPC_PACKRL_PH:
23483 check_dsp(ctx);
23484 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23485 break;
23487 break;
23488 #ifdef TARGET_MIPS64
23489 case OPC_CMPU_EQ_OB_DSP:
23490 switch (op2) {
23491 case OPC_CMP_EQ_PW:
23492 check_dsp(ctx);
23493 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23494 break;
23495 case OPC_CMP_LT_PW:
23496 check_dsp(ctx);
23497 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23498 break;
23499 case OPC_CMP_LE_PW:
23500 check_dsp(ctx);
23501 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23502 break;
23503 case OPC_CMP_EQ_QH:
23504 check_dsp(ctx);
23505 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23506 break;
23507 case OPC_CMP_LT_QH:
23508 check_dsp(ctx);
23509 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23510 break;
23511 case OPC_CMP_LE_QH:
23512 check_dsp(ctx);
23513 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23514 break;
23515 case OPC_CMPGDU_EQ_OB:
23516 check_dsp_r2(ctx);
23517 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23518 break;
23519 case OPC_CMPGDU_LT_OB:
23520 check_dsp_r2(ctx);
23521 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23522 break;
23523 case OPC_CMPGDU_LE_OB:
23524 check_dsp_r2(ctx);
23525 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23526 break;
23527 case OPC_CMPGU_EQ_OB:
23528 check_dsp(ctx);
23529 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23530 break;
23531 case OPC_CMPGU_LT_OB:
23532 check_dsp(ctx);
23533 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23534 break;
23535 case OPC_CMPGU_LE_OB:
23536 check_dsp(ctx);
23537 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23538 break;
23539 case OPC_CMPU_EQ_OB:
23540 check_dsp(ctx);
23541 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23542 break;
23543 case OPC_CMPU_LT_OB:
23544 check_dsp(ctx);
23545 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23546 break;
23547 case OPC_CMPU_LE_OB:
23548 check_dsp(ctx);
23549 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23550 break;
23551 case OPC_PACKRL_PW:
23552 check_dsp(ctx);
23553 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23554 break;
23555 case OPC_PICK_OB:
23556 check_dsp(ctx);
23557 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23558 break;
23559 case OPC_PICK_PW:
23560 check_dsp(ctx);
23561 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23562 break;
23563 case OPC_PICK_QH:
23564 check_dsp(ctx);
23565 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23566 break;
23568 break;
23569 #endif
23572 tcg_temp_free(t1);
23573 tcg_temp_free(v1_t);
23574 tcg_temp_free(v2_t);
23577 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23578 uint32_t op1, int rt, int rs, int sa)
23580 TCGv t0;
23582 check_dsp_r2(ctx);
23584 if (rt == 0) {
23585 /* Treat as NOP. */
23586 return;
23589 t0 = tcg_temp_new();
23590 gen_load_gpr(t0, rs);
23592 switch (op1) {
23593 case OPC_APPEND_DSP:
23594 switch (MASK_APPEND(ctx->opcode)) {
23595 case OPC_APPEND:
23596 if (sa != 0) {
23597 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23599 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23600 break;
23601 case OPC_PREPEND:
23602 if (sa != 0) {
23603 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23604 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23605 tcg_gen_shli_tl(t0, t0, 32 - sa);
23606 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23608 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23609 break;
23610 case OPC_BALIGN:
23611 sa &= 3;
23612 if (sa != 0 && sa != 2) {
23613 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23614 tcg_gen_ext32u_tl(t0, t0);
23615 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23616 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23618 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23619 break;
23620 default: /* Invalid */
23621 MIPS_INVAL("MASK APPEND");
23622 generate_exception_end(ctx, EXCP_RI);
23623 break;
23625 break;
23626 #ifdef TARGET_MIPS64
23627 case OPC_DAPPEND_DSP:
23628 switch (MASK_DAPPEND(ctx->opcode)) {
23629 case OPC_DAPPEND:
23630 if (sa != 0) {
23631 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23633 break;
23634 case OPC_PREPENDD:
23635 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23636 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23637 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23638 break;
23639 case OPC_PREPENDW:
23640 if (sa != 0) {
23641 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23642 tcg_gen_shli_tl(t0, t0, 64 - sa);
23643 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23645 break;
23646 case OPC_DBALIGN:
23647 sa &= 7;
23648 if (sa != 0 && sa != 2 && sa != 4) {
23649 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23650 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23651 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23653 break;
23654 default: /* Invalid */
23655 MIPS_INVAL("MASK DAPPEND");
23656 generate_exception_end(ctx, EXCP_RI);
23657 break;
23659 break;
23660 #endif
23662 tcg_temp_free(t0);
23665 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23666 int ret, int v1, int v2, int check_ret)
23669 TCGv t0;
23670 TCGv t1;
23671 TCGv v1_t;
23672 TCGv v2_t;
23673 int16_t imm;
23675 if ((ret == 0) && (check_ret == 1)) {
23676 /* Treat as NOP. */
23677 return;
23680 t0 = tcg_temp_new();
23681 t1 = tcg_temp_new();
23682 v1_t = tcg_temp_new();
23683 v2_t = tcg_temp_new();
23685 gen_load_gpr(v1_t, v1);
23686 gen_load_gpr(v2_t, v2);
23688 switch (op1) {
23689 case OPC_EXTR_W_DSP:
23690 check_dsp(ctx);
23691 switch (op2) {
23692 case OPC_EXTR_W:
23693 tcg_gen_movi_tl(t0, v2);
23694 tcg_gen_movi_tl(t1, v1);
23695 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23696 break;
23697 case OPC_EXTR_R_W:
23698 tcg_gen_movi_tl(t0, v2);
23699 tcg_gen_movi_tl(t1, v1);
23700 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23701 break;
23702 case OPC_EXTR_RS_W:
23703 tcg_gen_movi_tl(t0, v2);
23704 tcg_gen_movi_tl(t1, v1);
23705 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23706 break;
23707 case OPC_EXTR_S_H:
23708 tcg_gen_movi_tl(t0, v2);
23709 tcg_gen_movi_tl(t1, v1);
23710 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23711 break;
23712 case OPC_EXTRV_S_H:
23713 tcg_gen_movi_tl(t0, v2);
23714 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23715 break;
23716 case OPC_EXTRV_W:
23717 tcg_gen_movi_tl(t0, v2);
23718 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23719 break;
23720 case OPC_EXTRV_R_W:
23721 tcg_gen_movi_tl(t0, v2);
23722 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23723 break;
23724 case OPC_EXTRV_RS_W:
23725 tcg_gen_movi_tl(t0, v2);
23726 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23727 break;
23728 case OPC_EXTP:
23729 tcg_gen_movi_tl(t0, v2);
23730 tcg_gen_movi_tl(t1, v1);
23731 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23732 break;
23733 case OPC_EXTPV:
23734 tcg_gen_movi_tl(t0, v2);
23735 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23736 break;
23737 case OPC_EXTPDP:
23738 tcg_gen_movi_tl(t0, v2);
23739 tcg_gen_movi_tl(t1, v1);
23740 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23741 break;
23742 case OPC_EXTPDPV:
23743 tcg_gen_movi_tl(t0, v2);
23744 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23745 break;
23746 case OPC_SHILO:
23747 imm = (ctx->opcode >> 20) & 0x3F;
23748 tcg_gen_movi_tl(t0, ret);
23749 tcg_gen_movi_tl(t1, imm);
23750 gen_helper_shilo(t0, t1, cpu_env);
23751 break;
23752 case OPC_SHILOV:
23753 tcg_gen_movi_tl(t0, ret);
23754 gen_helper_shilo(t0, v1_t, cpu_env);
23755 break;
23756 case OPC_MTHLIP:
23757 tcg_gen_movi_tl(t0, ret);
23758 gen_helper_mthlip(t0, v1_t, cpu_env);
23759 break;
23760 case OPC_WRDSP:
23761 imm = (ctx->opcode >> 11) & 0x3FF;
23762 tcg_gen_movi_tl(t0, imm);
23763 gen_helper_wrdsp(v1_t, t0, cpu_env);
23764 break;
23765 case OPC_RDDSP:
23766 imm = (ctx->opcode >> 16) & 0x03FF;
23767 tcg_gen_movi_tl(t0, imm);
23768 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23769 break;
23771 break;
23772 #ifdef TARGET_MIPS64
23773 case OPC_DEXTR_W_DSP:
23774 check_dsp(ctx);
23775 switch (op2) {
23776 case OPC_DMTHLIP:
23777 tcg_gen_movi_tl(t0, ret);
23778 gen_helper_dmthlip(v1_t, t0, cpu_env);
23779 break;
23780 case OPC_DSHILO:
23782 int shift = (ctx->opcode >> 19) & 0x7F;
23783 int ac = (ctx->opcode >> 11) & 0x03;
23784 tcg_gen_movi_tl(t0, shift);
23785 tcg_gen_movi_tl(t1, ac);
23786 gen_helper_dshilo(t0, t1, cpu_env);
23787 break;
23789 case OPC_DSHILOV:
23791 int ac = (ctx->opcode >> 11) & 0x03;
23792 tcg_gen_movi_tl(t0, ac);
23793 gen_helper_dshilo(v1_t, t0, cpu_env);
23794 break;
23796 case OPC_DEXTP:
23797 tcg_gen_movi_tl(t0, v2);
23798 tcg_gen_movi_tl(t1, v1);
23800 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23801 break;
23802 case OPC_DEXTPV:
23803 tcg_gen_movi_tl(t0, v2);
23804 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23805 break;
23806 case OPC_DEXTPDP:
23807 tcg_gen_movi_tl(t0, v2);
23808 tcg_gen_movi_tl(t1, v1);
23809 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23810 break;
23811 case OPC_DEXTPDPV:
23812 tcg_gen_movi_tl(t0, v2);
23813 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23814 break;
23815 case OPC_DEXTR_L:
23816 tcg_gen_movi_tl(t0, v2);
23817 tcg_gen_movi_tl(t1, v1);
23818 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23819 break;
23820 case OPC_DEXTR_R_L:
23821 tcg_gen_movi_tl(t0, v2);
23822 tcg_gen_movi_tl(t1, v1);
23823 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23824 break;
23825 case OPC_DEXTR_RS_L:
23826 tcg_gen_movi_tl(t0, v2);
23827 tcg_gen_movi_tl(t1, v1);
23828 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23829 break;
23830 case OPC_DEXTR_W:
23831 tcg_gen_movi_tl(t0, v2);
23832 tcg_gen_movi_tl(t1, v1);
23833 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23834 break;
23835 case OPC_DEXTR_R_W:
23836 tcg_gen_movi_tl(t0, v2);
23837 tcg_gen_movi_tl(t1, v1);
23838 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23839 break;
23840 case OPC_DEXTR_RS_W:
23841 tcg_gen_movi_tl(t0, v2);
23842 tcg_gen_movi_tl(t1, v1);
23843 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23844 break;
23845 case OPC_DEXTR_S_H:
23846 tcg_gen_movi_tl(t0, v2);
23847 tcg_gen_movi_tl(t1, v1);
23848 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23849 break;
23850 case OPC_DEXTRV_S_H:
23851 tcg_gen_movi_tl(t0, v2);
23852 tcg_gen_movi_tl(t1, v1);
23853 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23854 break;
23855 case OPC_DEXTRV_L:
23856 tcg_gen_movi_tl(t0, v2);
23857 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23858 break;
23859 case OPC_DEXTRV_R_L:
23860 tcg_gen_movi_tl(t0, v2);
23861 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23862 break;
23863 case OPC_DEXTRV_RS_L:
23864 tcg_gen_movi_tl(t0, v2);
23865 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23866 break;
23867 case OPC_DEXTRV_W:
23868 tcg_gen_movi_tl(t0, v2);
23869 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23870 break;
23871 case OPC_DEXTRV_R_W:
23872 tcg_gen_movi_tl(t0, v2);
23873 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23874 break;
23875 case OPC_DEXTRV_RS_W:
23876 tcg_gen_movi_tl(t0, v2);
23877 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23878 break;
23880 break;
23881 #endif
23884 tcg_temp_free(t0);
23885 tcg_temp_free(t1);
23886 tcg_temp_free(v1_t);
23887 tcg_temp_free(v2_t);
23890 /* End MIPSDSP functions. */
23892 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23894 int rs, rt, rd, sa;
23895 uint32_t op1, op2;
23897 rs = (ctx->opcode >> 21) & 0x1f;
23898 rt = (ctx->opcode >> 16) & 0x1f;
23899 rd = (ctx->opcode >> 11) & 0x1f;
23900 sa = (ctx->opcode >> 6) & 0x1f;
23902 op1 = MASK_SPECIAL(ctx->opcode);
23903 switch (op1) {
23904 case OPC_LSA:
23905 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23906 break;
23907 case OPC_MULT:
23908 case OPC_MULTU:
23909 case OPC_DIV:
23910 case OPC_DIVU:
23911 op2 = MASK_R6_MULDIV(ctx->opcode);
23912 switch (op2) {
23913 case R6_OPC_MUL:
23914 case R6_OPC_MUH:
23915 case R6_OPC_MULU:
23916 case R6_OPC_MUHU:
23917 case R6_OPC_DIV:
23918 case R6_OPC_MOD:
23919 case R6_OPC_DIVU:
23920 case R6_OPC_MODU:
23921 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23922 break;
23923 default:
23924 MIPS_INVAL("special_r6 muldiv");
23925 generate_exception_end(ctx, EXCP_RI);
23926 break;
23928 break;
23929 case OPC_SELEQZ:
23930 case OPC_SELNEZ:
23931 gen_cond_move(ctx, op1, rd, rs, rt);
23932 break;
23933 case R6_OPC_CLO:
23934 case R6_OPC_CLZ:
23935 if (rt == 0 && sa == 1) {
23936 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23937 We need additionally to check other fields */
23938 gen_cl(ctx, op1, rd, rs);
23939 } else {
23940 generate_exception_end(ctx, EXCP_RI);
23942 break;
23943 case R6_OPC_SDBBP:
23944 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23945 gen_helper_do_semihosting(cpu_env);
23946 } else {
23947 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23948 generate_exception_end(ctx, EXCP_RI);
23949 } else {
23950 generate_exception_end(ctx, EXCP_DBp);
23953 break;
23954 #if defined(TARGET_MIPS64)
23955 case OPC_DLSA:
23956 check_mips_64(ctx);
23957 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23958 break;
23959 case R6_OPC_DCLO:
23960 case R6_OPC_DCLZ:
23961 if (rt == 0 && sa == 1) {
23962 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23963 We need additionally to check other fields */
23964 check_mips_64(ctx);
23965 gen_cl(ctx, op1, rd, rs);
23966 } else {
23967 generate_exception_end(ctx, EXCP_RI);
23969 break;
23970 case OPC_DMULT:
23971 case OPC_DMULTU:
23972 case OPC_DDIV:
23973 case OPC_DDIVU:
23975 op2 = MASK_R6_MULDIV(ctx->opcode);
23976 switch (op2) {
23977 case R6_OPC_DMUL:
23978 case R6_OPC_DMUH:
23979 case R6_OPC_DMULU:
23980 case R6_OPC_DMUHU:
23981 case R6_OPC_DDIV:
23982 case R6_OPC_DMOD:
23983 case R6_OPC_DDIVU:
23984 case R6_OPC_DMODU:
23985 check_mips_64(ctx);
23986 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23987 break;
23988 default:
23989 MIPS_INVAL("special_r6 muldiv");
23990 generate_exception_end(ctx, EXCP_RI);
23991 break;
23993 break;
23994 #endif
23995 default: /* Invalid */
23996 MIPS_INVAL("special_r6");
23997 generate_exception_end(ctx, EXCP_RI);
23998 break;
24002 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24004 int rs = extract32(ctx->opcode, 21, 5);
24005 int rt = extract32(ctx->opcode, 16, 5);
24006 int rd = extract32(ctx->opcode, 11, 5);
24007 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24009 switch (op1) {
24010 case OPC_MOVN: /* Conditional move */
24011 case OPC_MOVZ:
24012 gen_cond_move(ctx, op1, rd, rs, rt);
24013 break;
24014 case OPC_MFHI: /* Move from HI/LO */
24015 case OPC_MFLO:
24016 gen_HILO(ctx, op1, 0, rd);
24017 break;
24018 case OPC_MTHI:
24019 case OPC_MTLO: /* Move to HI/LO */
24020 gen_HILO(ctx, op1, 0, rs);
24021 break;
24022 case OPC_MULT:
24023 case OPC_MULTU:
24024 gen_mul_txx9(ctx, op1, rd, rs, rt);
24025 break;
24026 case OPC_DIV:
24027 case OPC_DIVU:
24028 gen_muldiv(ctx, op1, 0, rs, rt);
24029 break;
24030 #if defined(TARGET_MIPS64)
24031 case OPC_DMULT:
24032 case OPC_DMULTU:
24033 case OPC_DDIV:
24034 case OPC_DDIVU:
24035 check_insn_opc_user_only(ctx, INSN_R5900);
24036 gen_muldiv(ctx, op1, 0, rs, rt);
24037 break;
24038 #endif
24039 case OPC_JR:
24040 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24041 break;
24042 default: /* Invalid */
24043 MIPS_INVAL("special_tx79");
24044 generate_exception_end(ctx, EXCP_RI);
24045 break;
24049 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24051 int rs, rt, rd, sa;
24052 uint32_t op1;
24054 rs = (ctx->opcode >> 21) & 0x1f;
24055 rt = (ctx->opcode >> 16) & 0x1f;
24056 rd = (ctx->opcode >> 11) & 0x1f;
24057 sa = (ctx->opcode >> 6) & 0x1f;
24059 op1 = MASK_SPECIAL(ctx->opcode);
24060 switch (op1) {
24061 case OPC_MOVN: /* Conditional move */
24062 case OPC_MOVZ:
24063 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24064 INSN_LOONGSON2E | INSN_LOONGSON2F);
24065 gen_cond_move(ctx, op1, rd, rs, rt);
24066 break;
24067 case OPC_MFHI: /* Move from HI/LO */
24068 case OPC_MFLO:
24069 gen_HILO(ctx, op1, rs & 3, rd);
24070 break;
24071 case OPC_MTHI:
24072 case OPC_MTLO: /* Move to HI/LO */
24073 gen_HILO(ctx, op1, rd & 3, rs);
24074 break;
24075 case OPC_MOVCI:
24076 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24077 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24078 check_cp1_enabled(ctx);
24079 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24080 (ctx->opcode >> 16) & 1);
24081 } else {
24082 generate_exception_err(ctx, EXCP_CpU, 1);
24084 break;
24085 case OPC_MULT:
24086 case OPC_MULTU:
24087 if (sa) {
24088 check_insn(ctx, INSN_VR54XX);
24089 op1 = MASK_MUL_VR54XX(ctx->opcode);
24090 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24091 } else {
24092 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24094 break;
24095 case OPC_DIV:
24096 case OPC_DIVU:
24097 gen_muldiv(ctx, op1, 0, rs, rt);
24098 break;
24099 #if defined(TARGET_MIPS64)
24100 case OPC_DMULT:
24101 case OPC_DMULTU:
24102 case OPC_DDIV:
24103 case OPC_DDIVU:
24104 check_insn(ctx, ISA_MIPS3);
24105 check_mips_64(ctx);
24106 gen_muldiv(ctx, op1, 0, rs, rt);
24107 break;
24108 #endif
24109 case OPC_JR:
24110 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24111 break;
24112 case OPC_SPIM:
24113 #ifdef MIPS_STRICT_STANDARD
24114 MIPS_INVAL("SPIM");
24115 generate_exception_end(ctx, EXCP_RI);
24116 #else
24117 /* Implemented as RI exception for now. */
24118 MIPS_INVAL("spim (unofficial)");
24119 generate_exception_end(ctx, EXCP_RI);
24120 #endif
24121 break;
24122 default: /* Invalid */
24123 MIPS_INVAL("special_legacy");
24124 generate_exception_end(ctx, EXCP_RI);
24125 break;
24129 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24131 int rs, rt, rd, sa;
24132 uint32_t op1;
24134 rs = (ctx->opcode >> 21) & 0x1f;
24135 rt = (ctx->opcode >> 16) & 0x1f;
24136 rd = (ctx->opcode >> 11) & 0x1f;
24137 sa = (ctx->opcode >> 6) & 0x1f;
24139 op1 = MASK_SPECIAL(ctx->opcode);
24140 switch (op1) {
24141 case OPC_SLL: /* Shift with immediate */
24142 if (sa == 5 && rd == 0 &&
24143 rs == 0 && rt == 0) { /* PAUSE */
24144 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24145 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24146 generate_exception_end(ctx, EXCP_RI);
24147 break;
24150 /* Fallthrough */
24151 case OPC_SRA:
24152 gen_shift_imm(ctx, op1, rd, rt, sa);
24153 break;
24154 case OPC_SRL:
24155 switch ((ctx->opcode >> 21) & 0x1f) {
24156 case 1:
24157 /* rotr is decoded as srl on non-R2 CPUs */
24158 if (ctx->insn_flags & ISA_MIPS32R2) {
24159 op1 = OPC_ROTR;
24161 /* Fallthrough */
24162 case 0:
24163 gen_shift_imm(ctx, op1, rd, rt, sa);
24164 break;
24165 default:
24166 generate_exception_end(ctx, EXCP_RI);
24167 break;
24169 break;
24170 case OPC_ADD:
24171 case OPC_ADDU:
24172 case OPC_SUB:
24173 case OPC_SUBU:
24174 gen_arith(ctx, op1, rd, rs, rt);
24175 break;
24176 case OPC_SLLV: /* Shifts */
24177 case OPC_SRAV:
24178 gen_shift(ctx, op1, rd, rs, rt);
24179 break;
24180 case OPC_SRLV:
24181 switch ((ctx->opcode >> 6) & 0x1f) {
24182 case 1:
24183 /* rotrv is decoded as srlv on non-R2 CPUs */
24184 if (ctx->insn_flags & ISA_MIPS32R2) {
24185 op1 = OPC_ROTRV;
24187 /* Fallthrough */
24188 case 0:
24189 gen_shift(ctx, op1, rd, rs, rt);
24190 break;
24191 default:
24192 generate_exception_end(ctx, EXCP_RI);
24193 break;
24195 break;
24196 case OPC_SLT: /* Set on less than */
24197 case OPC_SLTU:
24198 gen_slt(ctx, op1, rd, rs, rt);
24199 break;
24200 case OPC_AND: /* Logic*/
24201 case OPC_OR:
24202 case OPC_NOR:
24203 case OPC_XOR:
24204 gen_logic(ctx, op1, rd, rs, rt);
24205 break;
24206 case OPC_JALR:
24207 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24208 break;
24209 case OPC_TGE: /* Traps */
24210 case OPC_TGEU:
24211 case OPC_TLT:
24212 case OPC_TLTU:
24213 case OPC_TEQ:
24214 case OPC_TNE:
24215 check_insn(ctx, ISA_MIPS2);
24216 gen_trap(ctx, op1, rs, rt, -1);
24217 break;
24218 case OPC_LSA: /* OPC_PMON */
24219 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24220 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24221 decode_opc_special_r6(env, ctx);
24222 } else {
24223 /* Pmon entry point, also R4010 selsl */
24224 #ifdef MIPS_STRICT_STANDARD
24225 MIPS_INVAL("PMON / selsl");
24226 generate_exception_end(ctx, EXCP_RI);
24227 #else
24228 gen_helper_0e0i(pmon, sa);
24229 #endif
24231 break;
24232 case OPC_SYSCALL:
24233 generate_exception_end(ctx, EXCP_SYSCALL);
24234 break;
24235 case OPC_BREAK:
24236 generate_exception_end(ctx, EXCP_BREAK);
24237 break;
24238 case OPC_SYNC:
24239 check_insn(ctx, ISA_MIPS2);
24240 gen_sync(extract32(ctx->opcode, 6, 5));
24241 break;
24243 #if defined(TARGET_MIPS64)
24244 /* MIPS64 specific opcodes */
24245 case OPC_DSLL:
24246 case OPC_DSRA:
24247 case OPC_DSLL32:
24248 case OPC_DSRA32:
24249 check_insn(ctx, ISA_MIPS3);
24250 check_mips_64(ctx);
24251 gen_shift_imm(ctx, op1, rd, rt, sa);
24252 break;
24253 case OPC_DSRL:
24254 switch ((ctx->opcode >> 21) & 0x1f) {
24255 case 1:
24256 /* drotr is decoded as dsrl on non-R2 CPUs */
24257 if (ctx->insn_flags & ISA_MIPS32R2) {
24258 op1 = OPC_DROTR;
24260 /* Fallthrough */
24261 case 0:
24262 check_insn(ctx, ISA_MIPS3);
24263 check_mips_64(ctx);
24264 gen_shift_imm(ctx, op1, rd, rt, sa);
24265 break;
24266 default:
24267 generate_exception_end(ctx, EXCP_RI);
24268 break;
24270 break;
24271 case OPC_DSRL32:
24272 switch ((ctx->opcode >> 21) & 0x1f) {
24273 case 1:
24274 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24275 if (ctx->insn_flags & ISA_MIPS32R2) {
24276 op1 = OPC_DROTR32;
24278 /* Fallthrough */
24279 case 0:
24280 check_insn(ctx, ISA_MIPS3);
24281 check_mips_64(ctx);
24282 gen_shift_imm(ctx, op1, rd, rt, sa);
24283 break;
24284 default:
24285 generate_exception_end(ctx, EXCP_RI);
24286 break;
24288 break;
24289 case OPC_DADD:
24290 case OPC_DADDU:
24291 case OPC_DSUB:
24292 case OPC_DSUBU:
24293 check_insn(ctx, ISA_MIPS3);
24294 check_mips_64(ctx);
24295 gen_arith(ctx, op1, rd, rs, rt);
24296 break;
24297 case OPC_DSLLV:
24298 case OPC_DSRAV:
24299 check_insn(ctx, ISA_MIPS3);
24300 check_mips_64(ctx);
24301 gen_shift(ctx, op1, rd, rs, rt);
24302 break;
24303 case OPC_DSRLV:
24304 switch ((ctx->opcode >> 6) & 0x1f) {
24305 case 1:
24306 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24307 if (ctx->insn_flags & ISA_MIPS32R2) {
24308 op1 = OPC_DROTRV;
24310 /* Fallthrough */
24311 case 0:
24312 check_insn(ctx, ISA_MIPS3);
24313 check_mips_64(ctx);
24314 gen_shift(ctx, op1, rd, rs, rt);
24315 break;
24316 default:
24317 generate_exception_end(ctx, EXCP_RI);
24318 break;
24320 break;
24321 case OPC_DLSA:
24322 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24323 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24324 decode_opc_special_r6(env, ctx);
24326 break;
24327 #endif
24328 default:
24329 if (ctx->insn_flags & ISA_MIPS32R6) {
24330 decode_opc_special_r6(env, ctx);
24331 } else if (ctx->insn_flags & INSN_R5900) {
24332 decode_opc_special_tx79(env, ctx);
24333 } else {
24334 decode_opc_special_legacy(env, ctx);
24340 #if defined(TARGET_MIPS64)
24344 * MMI (MultiMedia Interface) ASE instructions
24345 * ===========================================
24349 * MMI instructions category: data communication
24350 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24352 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24353 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24354 * PCPYUD PEXEH PEXTLW PPACW
24355 * PEXEW PEXTUB
24356 * PEXTUH
24357 * PEXTUW
24361 * PCPYH rd, rt
24363 * Parallel Copy Halfword
24365 * 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
24366 * +-----------+---------+---------+---------+---------+-----------+
24367 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24368 * +-----------+---------+---------+---------+---------+-----------+
24370 static void gen_mmi_pcpyh(DisasContext *ctx)
24372 uint32_t pd, rt, rd;
24373 uint32_t opcode;
24375 opcode = ctx->opcode;
24377 pd = extract32(opcode, 21, 5);
24378 rt = extract32(opcode, 16, 5);
24379 rd = extract32(opcode, 11, 5);
24381 if (unlikely(pd != 0)) {
24382 generate_exception_end(ctx, EXCP_RI);
24383 } else if (rd == 0) {
24384 /* nop */
24385 } else if (rt == 0) {
24386 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24387 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24388 } else {
24389 TCGv_i64 t0 = tcg_temp_new();
24390 TCGv_i64 t1 = tcg_temp_new();
24391 uint64_t mask = (1ULL << 16) - 1;
24393 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24394 tcg_gen_movi_i64(t1, 0);
24395 tcg_gen_or_i64(t1, t0, t1);
24396 tcg_gen_shli_i64(t0, t0, 16);
24397 tcg_gen_or_i64(t1, t0, t1);
24398 tcg_gen_shli_i64(t0, t0, 16);
24399 tcg_gen_or_i64(t1, t0, t1);
24400 tcg_gen_shli_i64(t0, t0, 16);
24401 tcg_gen_or_i64(t1, t0, t1);
24403 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24405 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24406 tcg_gen_movi_i64(t1, 0);
24407 tcg_gen_or_i64(t1, t0, t1);
24408 tcg_gen_shli_i64(t0, t0, 16);
24409 tcg_gen_or_i64(t1, t0, t1);
24410 tcg_gen_shli_i64(t0, t0, 16);
24411 tcg_gen_or_i64(t1, t0, t1);
24412 tcg_gen_shli_i64(t0, t0, 16);
24413 tcg_gen_or_i64(t1, t0, t1);
24415 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24417 tcg_temp_free(t0);
24418 tcg_temp_free(t1);
24423 * PCPYLD rd, rs, rt
24425 * Parallel Copy Lower Doubleword
24427 * 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
24428 * +-----------+---------+---------+---------+---------+-----------+
24429 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24430 * +-----------+---------+---------+---------+---------+-----------+
24432 static void gen_mmi_pcpyld(DisasContext *ctx)
24434 uint32_t rs, rt, rd;
24435 uint32_t opcode;
24437 opcode = ctx->opcode;
24439 rs = extract32(opcode, 21, 5);
24440 rt = extract32(opcode, 16, 5);
24441 rd = extract32(opcode, 11, 5);
24443 if (rd == 0) {
24444 /* nop */
24445 } else {
24446 if (rs == 0) {
24447 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24448 } else {
24449 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24451 if (rt == 0) {
24452 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24453 } else {
24454 if (rd != rt) {
24455 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24462 * PCPYUD rd, rs, rt
24464 * Parallel Copy Upper Doubleword
24466 * 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
24467 * +-----------+---------+---------+---------+---------+-----------+
24468 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24469 * +-----------+---------+---------+---------+---------+-----------+
24471 static void gen_mmi_pcpyud(DisasContext *ctx)
24473 uint32_t rs, rt, rd;
24474 uint32_t opcode;
24476 opcode = ctx->opcode;
24478 rs = extract32(opcode, 21, 5);
24479 rt = extract32(opcode, 16, 5);
24480 rd = extract32(opcode, 11, 5);
24482 if (rd == 0) {
24483 /* nop */
24484 } else {
24485 if (rs == 0) {
24486 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24487 } else {
24488 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24490 if (rt == 0) {
24491 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24492 } else {
24493 if (rd != rt) {
24494 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24500 #endif
24503 #if !defined(TARGET_MIPS64)
24505 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24506 #define MXU_APTN1_A 0
24507 #define MXU_APTN1_S 1
24509 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24510 #define MXU_APTN2_AA 0
24511 #define MXU_APTN2_AS 1
24512 #define MXU_APTN2_SA 2
24513 #define MXU_APTN2_SS 3
24515 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24516 #define MXU_EPTN2_AA 0
24517 #define MXU_EPTN2_AS 1
24518 #define MXU_EPTN2_SA 2
24519 #define MXU_EPTN2_SS 3
24521 /* MXU operand getting pattern 'optn2' */
24522 #define MXU_OPTN2_PTN0 0
24523 #define MXU_OPTN2_PTN1 1
24524 #define MXU_OPTN2_PTN2 2
24525 #define MXU_OPTN2_PTN3 3
24526 /* alternative naming scheme for 'optn2' */
24527 #define MXU_OPTN2_WW 0
24528 #define MXU_OPTN2_LW 1
24529 #define MXU_OPTN2_HW 2
24530 #define MXU_OPTN2_XW 3
24532 /* MXU operand getting pattern 'optn3' */
24533 #define MXU_OPTN3_PTN0 0
24534 #define MXU_OPTN3_PTN1 1
24535 #define MXU_OPTN3_PTN2 2
24536 #define MXU_OPTN3_PTN3 3
24537 #define MXU_OPTN3_PTN4 4
24538 #define MXU_OPTN3_PTN5 5
24539 #define MXU_OPTN3_PTN6 6
24540 #define MXU_OPTN3_PTN7 7
24544 * S32I2M XRa, rb - Register move from GRF to XRF
24546 static void gen_mxu_s32i2m(DisasContext *ctx)
24548 TCGv t0;
24549 uint32_t XRa, Rb;
24551 t0 = tcg_temp_new();
24553 XRa = extract32(ctx->opcode, 6, 5);
24554 Rb = extract32(ctx->opcode, 16, 5);
24556 gen_load_gpr(t0, Rb);
24557 if (XRa <= 15) {
24558 gen_store_mxu_gpr(t0, XRa);
24559 } else if (XRa == 16) {
24560 gen_store_mxu_cr(t0);
24563 tcg_temp_free(t0);
24567 * S32M2I XRa, rb - Register move from XRF to GRF
24569 static void gen_mxu_s32m2i(DisasContext *ctx)
24571 TCGv t0;
24572 uint32_t XRa, Rb;
24574 t0 = tcg_temp_new();
24576 XRa = extract32(ctx->opcode, 6, 5);
24577 Rb = extract32(ctx->opcode, 16, 5);
24579 if (XRa <= 15) {
24580 gen_load_mxu_gpr(t0, XRa);
24581 } else if (XRa == 16) {
24582 gen_load_mxu_cr(t0);
24585 gen_store_gpr(t0, Rb);
24587 tcg_temp_free(t0);
24591 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24593 static void gen_mxu_s8ldd(DisasContext *ctx)
24595 TCGv t0, t1;
24596 uint32_t XRa, Rb, s8, optn3;
24598 t0 = tcg_temp_new();
24599 t1 = tcg_temp_new();
24601 XRa = extract32(ctx->opcode, 6, 4);
24602 s8 = extract32(ctx->opcode, 10, 8);
24603 optn3 = extract32(ctx->opcode, 18, 3);
24604 Rb = extract32(ctx->opcode, 21, 5);
24606 gen_load_gpr(t0, Rb);
24607 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24609 switch (optn3) {
24610 /* XRa[7:0] = tmp8 */
24611 case MXU_OPTN3_PTN0:
24612 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24613 gen_load_mxu_gpr(t0, XRa);
24614 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24615 break;
24616 /* XRa[15:8] = tmp8 */
24617 case MXU_OPTN3_PTN1:
24618 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24619 gen_load_mxu_gpr(t0, XRa);
24620 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24621 break;
24622 /* XRa[23:16] = tmp8 */
24623 case MXU_OPTN3_PTN2:
24624 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24625 gen_load_mxu_gpr(t0, XRa);
24626 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24627 break;
24628 /* XRa[31:24] = tmp8 */
24629 case MXU_OPTN3_PTN3:
24630 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24631 gen_load_mxu_gpr(t0, XRa);
24632 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24633 break;
24634 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24635 case MXU_OPTN3_PTN4:
24636 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24637 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24638 break;
24639 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24640 case MXU_OPTN3_PTN5:
24641 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24642 tcg_gen_shli_tl(t1, t1, 8);
24643 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24644 break;
24645 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24646 case MXU_OPTN3_PTN6:
24647 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24648 tcg_gen_mov_tl(t0, t1);
24649 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24650 tcg_gen_shli_tl(t1, t1, 16);
24651 tcg_gen_or_tl(t0, t0, t1);
24652 break;
24653 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24654 case MXU_OPTN3_PTN7:
24655 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24656 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24657 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24658 break;
24661 gen_store_mxu_gpr(t0, XRa);
24663 tcg_temp_free(t0);
24664 tcg_temp_free(t1);
24668 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24670 static void gen_mxu_d16mul(DisasContext *ctx)
24672 TCGv t0, t1, t2, t3;
24673 uint32_t XRa, XRb, XRc, XRd, optn2;
24675 t0 = tcg_temp_new();
24676 t1 = tcg_temp_new();
24677 t2 = tcg_temp_new();
24678 t3 = tcg_temp_new();
24680 XRa = extract32(ctx->opcode, 6, 4);
24681 XRb = extract32(ctx->opcode, 10, 4);
24682 XRc = extract32(ctx->opcode, 14, 4);
24683 XRd = extract32(ctx->opcode, 18, 4);
24684 optn2 = extract32(ctx->opcode, 22, 2);
24686 gen_load_mxu_gpr(t1, XRb);
24687 tcg_gen_sextract_tl(t0, t1, 0, 16);
24688 tcg_gen_sextract_tl(t1, t1, 16, 16);
24689 gen_load_mxu_gpr(t3, XRc);
24690 tcg_gen_sextract_tl(t2, t3, 0, 16);
24691 tcg_gen_sextract_tl(t3, t3, 16, 16);
24693 switch (optn2) {
24694 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24695 tcg_gen_mul_tl(t3, t1, t3);
24696 tcg_gen_mul_tl(t2, t0, t2);
24697 break;
24698 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24699 tcg_gen_mul_tl(t3, t0, t3);
24700 tcg_gen_mul_tl(t2, t0, t2);
24701 break;
24702 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24703 tcg_gen_mul_tl(t3, t1, t3);
24704 tcg_gen_mul_tl(t2, t1, t2);
24705 break;
24706 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24707 tcg_gen_mul_tl(t3, t0, t3);
24708 tcg_gen_mul_tl(t2, t1, t2);
24709 break;
24711 gen_store_mxu_gpr(t3, XRa);
24712 gen_store_mxu_gpr(t2, XRd);
24714 tcg_temp_free(t0);
24715 tcg_temp_free(t1);
24716 tcg_temp_free(t2);
24717 tcg_temp_free(t3);
24721 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24722 * and accumulate
24724 static void gen_mxu_d16mac(DisasContext *ctx)
24726 TCGv t0, t1, t2, t3;
24727 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24729 t0 = tcg_temp_new();
24730 t1 = tcg_temp_new();
24731 t2 = tcg_temp_new();
24732 t3 = tcg_temp_new();
24734 XRa = extract32(ctx->opcode, 6, 4);
24735 XRb = extract32(ctx->opcode, 10, 4);
24736 XRc = extract32(ctx->opcode, 14, 4);
24737 XRd = extract32(ctx->opcode, 18, 4);
24738 optn2 = extract32(ctx->opcode, 22, 2);
24739 aptn2 = extract32(ctx->opcode, 24, 2);
24741 gen_load_mxu_gpr(t1, XRb);
24742 tcg_gen_sextract_tl(t0, t1, 0, 16);
24743 tcg_gen_sextract_tl(t1, t1, 16, 16);
24745 gen_load_mxu_gpr(t3, XRc);
24746 tcg_gen_sextract_tl(t2, t3, 0, 16);
24747 tcg_gen_sextract_tl(t3, t3, 16, 16);
24749 switch (optn2) {
24750 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24751 tcg_gen_mul_tl(t3, t1, t3);
24752 tcg_gen_mul_tl(t2, t0, t2);
24753 break;
24754 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24755 tcg_gen_mul_tl(t3, t0, t3);
24756 tcg_gen_mul_tl(t2, t0, t2);
24757 break;
24758 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24759 tcg_gen_mul_tl(t3, t1, t3);
24760 tcg_gen_mul_tl(t2, t1, t2);
24761 break;
24762 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24763 tcg_gen_mul_tl(t3, t0, t3);
24764 tcg_gen_mul_tl(t2, t1, t2);
24765 break;
24767 gen_load_mxu_gpr(t0, XRa);
24768 gen_load_mxu_gpr(t1, XRd);
24770 switch (aptn2) {
24771 case MXU_APTN2_AA:
24772 tcg_gen_add_tl(t3, t0, t3);
24773 tcg_gen_add_tl(t2, t1, t2);
24774 break;
24775 case MXU_APTN2_AS:
24776 tcg_gen_add_tl(t3, t0, t3);
24777 tcg_gen_sub_tl(t2, t1, t2);
24778 break;
24779 case MXU_APTN2_SA:
24780 tcg_gen_sub_tl(t3, t0, t3);
24781 tcg_gen_add_tl(t2, t1, t2);
24782 break;
24783 case MXU_APTN2_SS:
24784 tcg_gen_sub_tl(t3, t0, t3);
24785 tcg_gen_sub_tl(t2, t1, t2);
24786 break;
24788 gen_store_mxu_gpr(t3, XRa);
24789 gen_store_mxu_gpr(t2, XRd);
24791 tcg_temp_free(t0);
24792 tcg_temp_free(t1);
24793 tcg_temp_free(t2);
24794 tcg_temp_free(t3);
24798 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24799 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24801 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24803 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24804 uint32_t XRa, XRb, XRc, XRd, sel;
24806 t0 = tcg_temp_new();
24807 t1 = tcg_temp_new();
24808 t2 = tcg_temp_new();
24809 t3 = tcg_temp_new();
24810 t4 = tcg_temp_new();
24811 t5 = tcg_temp_new();
24812 t6 = tcg_temp_new();
24813 t7 = tcg_temp_new();
24815 XRa = extract32(ctx->opcode, 6, 4);
24816 XRb = extract32(ctx->opcode, 10, 4);
24817 XRc = extract32(ctx->opcode, 14, 4);
24818 XRd = extract32(ctx->opcode, 18, 4);
24819 sel = extract32(ctx->opcode, 22, 2);
24821 gen_load_mxu_gpr(t3, XRb);
24822 gen_load_mxu_gpr(t7, XRc);
24824 if (sel == 0x2) {
24825 /* Q8MULSU */
24826 tcg_gen_ext8s_tl(t0, t3);
24827 tcg_gen_shri_tl(t3, t3, 8);
24828 tcg_gen_ext8s_tl(t1, t3);
24829 tcg_gen_shri_tl(t3, t3, 8);
24830 tcg_gen_ext8s_tl(t2, t3);
24831 tcg_gen_shri_tl(t3, t3, 8);
24832 tcg_gen_ext8s_tl(t3, t3);
24833 } else {
24834 /* Q8MUL */
24835 tcg_gen_ext8u_tl(t0, t3);
24836 tcg_gen_shri_tl(t3, t3, 8);
24837 tcg_gen_ext8u_tl(t1, t3);
24838 tcg_gen_shri_tl(t3, t3, 8);
24839 tcg_gen_ext8u_tl(t2, t3);
24840 tcg_gen_shri_tl(t3, t3, 8);
24841 tcg_gen_ext8u_tl(t3, t3);
24844 tcg_gen_ext8u_tl(t4, t7);
24845 tcg_gen_shri_tl(t7, t7, 8);
24846 tcg_gen_ext8u_tl(t5, t7);
24847 tcg_gen_shri_tl(t7, t7, 8);
24848 tcg_gen_ext8u_tl(t6, t7);
24849 tcg_gen_shri_tl(t7, t7, 8);
24850 tcg_gen_ext8u_tl(t7, t7);
24852 tcg_gen_mul_tl(t0, t0, t4);
24853 tcg_gen_mul_tl(t1, t1, t5);
24854 tcg_gen_mul_tl(t2, t2, t6);
24855 tcg_gen_mul_tl(t3, t3, t7);
24857 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24858 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24859 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24860 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24862 tcg_gen_shli_tl(t1, t1, 16);
24863 tcg_gen_shli_tl(t3, t3, 16);
24865 tcg_gen_or_tl(t0, t0, t1);
24866 tcg_gen_or_tl(t1, t2, t3);
24868 gen_store_mxu_gpr(t0, XRd);
24869 gen_store_mxu_gpr(t1, XRa);
24871 tcg_temp_free(t0);
24872 tcg_temp_free(t1);
24873 tcg_temp_free(t2);
24874 tcg_temp_free(t3);
24875 tcg_temp_free(t4);
24876 tcg_temp_free(t5);
24877 tcg_temp_free(t6);
24878 tcg_temp_free(t7);
24882 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24883 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24885 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24887 TCGv t0, t1;
24888 uint32_t XRa, Rb, s12, sel;
24890 t0 = tcg_temp_new();
24891 t1 = tcg_temp_new();
24893 XRa = extract32(ctx->opcode, 6, 4);
24894 s12 = extract32(ctx->opcode, 10, 10);
24895 sel = extract32(ctx->opcode, 20, 1);
24896 Rb = extract32(ctx->opcode, 21, 5);
24898 gen_load_gpr(t0, Rb);
24900 tcg_gen_movi_tl(t1, s12);
24901 tcg_gen_shli_tl(t1, t1, 2);
24902 if (s12 & 0x200) {
24903 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24905 tcg_gen_add_tl(t1, t0, t1);
24906 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24908 if (sel == 1) {
24909 /* S32LDDR */
24910 tcg_gen_bswap32_tl(t1, t1);
24912 gen_store_mxu_gpr(t1, XRa);
24914 tcg_temp_free(t0);
24915 tcg_temp_free(t1);
24920 * MXU instruction category: logic
24921 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24923 * S32NOR S32AND S32OR S32XOR
24927 * S32NOR XRa, XRb, XRc
24928 * Update XRa with the result of logical bitwise 'nor' operation
24929 * applied to the content of XRb and XRc.
24931 * 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
24932 * +-----------+---------+-----+-------+-------+-------+-----------+
24933 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24934 * +-----------+---------+-----+-------+-------+-------+-----------+
24936 static void gen_mxu_S32NOR(DisasContext *ctx)
24938 uint32_t pad, XRc, XRb, XRa;
24940 pad = extract32(ctx->opcode, 21, 5);
24941 XRc = extract32(ctx->opcode, 14, 4);
24942 XRb = extract32(ctx->opcode, 10, 4);
24943 XRa = extract32(ctx->opcode, 6, 4);
24945 if (unlikely(pad != 0)) {
24946 /* opcode padding incorrect -> do nothing */
24947 } else if (unlikely(XRa == 0)) {
24948 /* destination is zero register -> do nothing */
24949 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24950 /* both operands zero registers -> just set destination to all 1s */
24951 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
24952 } else if (unlikely(XRb == 0)) {
24953 /* XRb zero register -> just set destination to the negation of XRc */
24954 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24955 } else if (unlikely(XRc == 0)) {
24956 /* XRa zero register -> just set destination to the negation of XRb */
24957 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24958 } else if (unlikely(XRb == XRc)) {
24959 /* both operands same -> just set destination to the negation of XRb */
24960 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24961 } else {
24962 /* the most general case */
24963 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24968 * S32AND XRa, XRb, XRc
24969 * Update XRa with the result of logical bitwise 'and' operation
24970 * applied to the content of XRb and XRc.
24972 * 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
24973 * +-----------+---------+-----+-------+-------+-------+-----------+
24974 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24975 * +-----------+---------+-----+-------+-------+-------+-----------+
24977 static void gen_mxu_S32AND(DisasContext *ctx)
24979 uint32_t pad, XRc, XRb, XRa;
24981 pad = extract32(ctx->opcode, 21, 5);
24982 XRc = extract32(ctx->opcode, 14, 4);
24983 XRb = extract32(ctx->opcode, 10, 4);
24984 XRa = extract32(ctx->opcode, 6, 4);
24986 if (unlikely(pad != 0)) {
24987 /* opcode padding incorrect -> do nothing */
24988 } else if (unlikely(XRa == 0)) {
24989 /* destination is zero register -> do nothing */
24990 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24991 /* one of operands zero register -> just set destination to all 0s */
24992 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24993 } else if (unlikely(XRb == XRc)) {
24994 /* both operands same -> just set destination to one of them */
24995 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24996 } else {
24997 /* the most general case */
24998 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25003 * S32OR XRa, XRb, XRc
25004 * Update XRa with the result of logical bitwise 'or' operation
25005 * applied to the content of XRb and XRc.
25007 * 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
25008 * +-----------+---------+-----+-------+-------+-------+-----------+
25009 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25010 * +-----------+---------+-----+-------+-------+-------+-----------+
25012 static void gen_mxu_S32OR(DisasContext *ctx)
25014 uint32_t pad, XRc, XRb, XRa;
25016 pad = extract32(ctx->opcode, 21, 5);
25017 XRc = extract32(ctx->opcode, 14, 4);
25018 XRb = extract32(ctx->opcode, 10, 4);
25019 XRa = extract32(ctx->opcode, 6, 4);
25021 if (unlikely(pad != 0)) {
25022 /* opcode padding incorrect -> do nothing */
25023 } else if (unlikely(XRa == 0)) {
25024 /* destination is zero register -> do nothing */
25025 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25026 /* both operands zero registers -> just set destination to all 0s */
25027 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25028 } else if (unlikely(XRb == 0)) {
25029 /* XRb zero register -> just set destination to the content of XRc */
25030 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25031 } else if (unlikely(XRc == 0)) {
25032 /* XRc zero register -> just set destination to the content of XRb */
25033 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25034 } else if (unlikely(XRb == XRc)) {
25035 /* both operands same -> just set destination to one of them */
25036 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25037 } else {
25038 /* the most general case */
25039 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25044 * S32XOR XRa, XRb, XRc
25045 * Update XRa with the result of logical bitwise 'xor' operation
25046 * applied to the content of XRb and XRc.
25048 * 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
25049 * +-----------+---------+-----+-------+-------+-------+-----------+
25050 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25051 * +-----------+---------+-----+-------+-------+-------+-----------+
25053 static void gen_mxu_S32XOR(DisasContext *ctx)
25055 uint32_t pad, XRc, XRb, XRa;
25057 pad = extract32(ctx->opcode, 21, 5);
25058 XRc = extract32(ctx->opcode, 14, 4);
25059 XRb = extract32(ctx->opcode, 10, 4);
25060 XRa = extract32(ctx->opcode, 6, 4);
25062 if (unlikely(pad != 0)) {
25063 /* opcode padding incorrect -> do nothing */
25064 } else if (unlikely(XRa == 0)) {
25065 /* destination is zero register -> do nothing */
25066 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25067 /* both operands zero registers -> just set destination to all 0s */
25068 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25069 } else if (unlikely(XRb == 0)) {
25070 /* XRb zero register -> just set destination to the content of XRc */
25071 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25072 } else if (unlikely(XRc == 0)) {
25073 /* XRc zero register -> just set destination to the content of XRb */
25074 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25075 } else if (unlikely(XRb == XRc)) {
25076 /* both operands same -> just set destination to all 0s */
25077 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25078 } else {
25079 /* the most general case */
25080 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25086 * MXU instruction category max/min
25087 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25089 * S32MAX D16MAX Q8MAX
25090 * S32MIN D16MIN Q8MIN
25094 * S32MAX XRa, XRb, XRc
25095 * Update XRa with the maximum of signed 32-bit integers contained
25096 * in XRb and XRc.
25098 * S32MIN XRa, XRb, XRc
25099 * Update XRa with the minimum of signed 32-bit integers contained
25100 * in XRb and XRc.
25102 * 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
25103 * +-----------+---------+-----+-------+-------+-------+-----------+
25104 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25105 * +-----------+---------+-----+-------+-------+-------+-----------+
25107 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25109 uint32_t pad, opc, XRc, XRb, XRa;
25111 pad = extract32(ctx->opcode, 21, 5);
25112 opc = extract32(ctx->opcode, 18, 3);
25113 XRc = extract32(ctx->opcode, 14, 4);
25114 XRb = extract32(ctx->opcode, 10, 4);
25115 XRa = extract32(ctx->opcode, 6, 4);
25117 if (unlikely(pad != 0)) {
25118 /* opcode padding incorrect -> do nothing */
25119 } else if (unlikely(XRa == 0)) {
25120 /* destination is zero register -> do nothing */
25121 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25122 /* both operands zero registers -> just set destination to zero */
25123 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25124 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25125 /* exactly one operand is zero register - find which one is not...*/
25126 uint32_t XRx = XRb ? XRb : XRc;
25127 /* ...and do max/min operation with one operand 0 */
25128 if (opc == OPC_MXU_S32MAX) {
25129 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25130 } else {
25131 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25133 } else if (unlikely(XRb == XRc)) {
25134 /* both operands same -> just set destination to one of them */
25135 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25136 } else {
25137 /* the most general case */
25138 if (opc == OPC_MXU_S32MAX) {
25139 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25140 mxu_gpr[XRc - 1]);
25141 } else {
25142 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25143 mxu_gpr[XRc - 1]);
25149 * D16MAX
25150 * Update XRa with the 16-bit-wise maximums of signed integers
25151 * contained in XRb and XRc.
25153 * D16MIN
25154 * Update XRa with the 16-bit-wise minimums of signed integers
25155 * contained in XRb and XRc.
25157 * 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
25158 * +-----------+---------+-----+-------+-------+-------+-----------+
25159 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25160 * +-----------+---------+-----+-------+-------+-------+-----------+
25162 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25164 uint32_t pad, opc, XRc, XRb, XRa;
25166 pad = extract32(ctx->opcode, 21, 5);
25167 opc = extract32(ctx->opcode, 18, 3);
25168 XRc = extract32(ctx->opcode, 14, 4);
25169 XRb = extract32(ctx->opcode, 10, 4);
25170 XRa = extract32(ctx->opcode, 6, 4);
25172 if (unlikely(pad != 0)) {
25173 /* opcode padding incorrect -> do nothing */
25174 } else if (unlikely(XRc == 0)) {
25175 /* destination is zero register -> do nothing */
25176 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25177 /* both operands zero registers -> just set destination to zero */
25178 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25179 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25180 /* exactly one operand is zero register - find which one is not...*/
25181 uint32_t XRx = XRb ? XRb : XRc;
25182 /* ...and do half-word-wise max/min with one operand 0 */
25183 TCGv_i32 t0 = tcg_temp_new();
25184 TCGv_i32 t1 = tcg_const_i32(0);
25186 /* the left half-word first */
25187 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25188 if (opc == OPC_MXU_D16MAX) {
25189 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25190 } else {
25191 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25194 /* the right half-word */
25195 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25196 /* move half-words to the leftmost position */
25197 tcg_gen_shli_i32(t0, t0, 16);
25198 /* t0 will be max/min of t0 and t1 */
25199 if (opc == OPC_MXU_D16MAX) {
25200 tcg_gen_smax_i32(t0, t0, t1);
25201 } else {
25202 tcg_gen_smin_i32(t0, t0, t1);
25204 /* return resulting half-words to its original position */
25205 tcg_gen_shri_i32(t0, t0, 16);
25206 /* finaly update the destination */
25207 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25209 tcg_temp_free(t1);
25210 tcg_temp_free(t0);
25211 } else if (unlikely(XRb == XRc)) {
25212 /* both operands same -> just set destination to one of them */
25213 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25214 } else {
25215 /* the most general case */
25216 TCGv_i32 t0 = tcg_temp_new();
25217 TCGv_i32 t1 = tcg_temp_new();
25219 /* the left half-word first */
25220 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25221 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25222 if (opc == OPC_MXU_D16MAX) {
25223 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25224 } else {
25225 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25228 /* the right half-word */
25229 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25230 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25231 /* move half-words to the leftmost position */
25232 tcg_gen_shli_i32(t0, t0, 16);
25233 tcg_gen_shli_i32(t1, t1, 16);
25234 /* t0 will be max/min of t0 and t1 */
25235 if (opc == OPC_MXU_D16MAX) {
25236 tcg_gen_smax_i32(t0, t0, t1);
25237 } else {
25238 tcg_gen_smin_i32(t0, t0, t1);
25240 /* return resulting half-words to its original position */
25241 tcg_gen_shri_i32(t0, t0, 16);
25242 /* finaly update the destination */
25243 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25245 tcg_temp_free(t1);
25246 tcg_temp_free(t0);
25251 * Q8MAX
25252 * Update XRa with the 8-bit-wise maximums of signed integers
25253 * contained in XRb and XRc.
25255 * Q8MIN
25256 * Update XRa with the 8-bit-wise minimums of signed integers
25257 * contained in XRb and XRc.
25259 * 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
25260 * +-----------+---------+-----+-------+-------+-------+-----------+
25261 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25262 * +-----------+---------+-----+-------+-------+-------+-----------+
25264 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25266 uint32_t pad, opc, XRc, XRb, XRa;
25268 pad = extract32(ctx->opcode, 21, 5);
25269 opc = extract32(ctx->opcode, 18, 3);
25270 XRc = extract32(ctx->opcode, 14, 4);
25271 XRb = extract32(ctx->opcode, 10, 4);
25272 XRa = extract32(ctx->opcode, 6, 4);
25274 if (unlikely(pad != 0)) {
25275 /* opcode padding incorrect -> do nothing */
25276 } else if (unlikely(XRa == 0)) {
25277 /* destination is zero register -> do nothing */
25278 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25279 /* both operands zero registers -> just set destination to zero */
25280 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25281 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25282 /* exactly one operand is zero register - make it be the first...*/
25283 uint32_t XRx = XRb ? XRb : XRc;
25284 /* ...and do byte-wise max/min with one operand 0 */
25285 TCGv_i32 t0 = tcg_temp_new();
25286 TCGv_i32 t1 = tcg_const_i32(0);
25287 int32_t i;
25289 /* the leftmost byte (byte 3) first */
25290 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25291 if (opc == OPC_MXU_Q8MAX) {
25292 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25293 } else {
25294 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25297 /* bytes 2, 1, 0 */
25298 for (i = 2; i >= 0; i--) {
25299 /* extract the byte */
25300 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25301 /* move the byte to the leftmost position */
25302 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25303 /* t0 will be max/min of t0 and t1 */
25304 if (opc == OPC_MXU_Q8MAX) {
25305 tcg_gen_smax_i32(t0, t0, t1);
25306 } else {
25307 tcg_gen_smin_i32(t0, t0, t1);
25309 /* return resulting byte to its original position */
25310 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25311 /* finaly update the destination */
25312 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25315 tcg_temp_free(t1);
25316 tcg_temp_free(t0);
25317 } else if (unlikely(XRb == XRc)) {
25318 /* both operands same -> just set destination to one of them */
25319 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25320 } else {
25321 /* the most general case */
25322 TCGv_i32 t0 = tcg_temp_new();
25323 TCGv_i32 t1 = tcg_temp_new();
25324 int32_t i;
25326 /* the leftmost bytes (bytes 3) first */
25327 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25328 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25329 if (opc == OPC_MXU_Q8MAX) {
25330 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25331 } else {
25332 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25335 /* bytes 2, 1, 0 */
25336 for (i = 2; i >= 0; i--) {
25337 /* extract corresponding bytes */
25338 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25339 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25340 /* move the bytes to the leftmost position */
25341 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25342 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25343 /* t0 will be max/min of t0 and t1 */
25344 if (opc == OPC_MXU_Q8MAX) {
25345 tcg_gen_smax_i32(t0, t0, t1);
25346 } else {
25347 tcg_gen_smin_i32(t0, t0, t1);
25349 /* return resulting byte to its original position */
25350 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25351 /* finaly update the destination */
25352 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25355 tcg_temp_free(t1);
25356 tcg_temp_free(t0);
25362 * MXU instruction category: align
25363 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25365 * S32ALN S32ALNI
25369 * S32ALNI XRc, XRb, XRa, optn3
25370 * Arrange bytes from XRb and XRc according to one of five sets of
25371 * rules determined by optn3, and place the result in XRa.
25373 * 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
25374 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25375 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25376 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25379 static void gen_mxu_S32ALNI(DisasContext *ctx)
25381 uint32_t optn3, pad, XRc, XRb, XRa;
25383 optn3 = extract32(ctx->opcode, 23, 3);
25384 pad = extract32(ctx->opcode, 21, 2);
25385 XRc = extract32(ctx->opcode, 14, 4);
25386 XRb = extract32(ctx->opcode, 10, 4);
25387 XRa = extract32(ctx->opcode, 6, 4);
25389 if (unlikely(pad != 0)) {
25390 /* opcode padding incorrect -> do nothing */
25391 } else if (unlikely(XRa == 0)) {
25392 /* destination is zero register -> do nothing */
25393 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25394 /* both operands zero registers -> just set destination to all 0s */
25395 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25396 } else if (unlikely(XRb == 0)) {
25397 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25398 switch (optn3) {
25399 case MXU_OPTN3_PTN0:
25400 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25401 break;
25402 case MXU_OPTN3_PTN1:
25403 case MXU_OPTN3_PTN2:
25404 case MXU_OPTN3_PTN3:
25405 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25406 8 * (4 - optn3));
25407 break;
25408 case MXU_OPTN3_PTN4:
25409 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25410 break;
25412 } else if (unlikely(XRc == 0)) {
25413 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25414 switch (optn3) {
25415 case MXU_OPTN3_PTN0:
25416 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25417 break;
25418 case MXU_OPTN3_PTN1:
25419 case MXU_OPTN3_PTN2:
25420 case MXU_OPTN3_PTN3:
25421 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25422 break;
25423 case MXU_OPTN3_PTN4:
25424 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25425 break;
25427 } else if (unlikely(XRb == XRc)) {
25428 /* both operands same -> just rotation or moving from any of them */
25429 switch (optn3) {
25430 case MXU_OPTN3_PTN0:
25431 case MXU_OPTN3_PTN4:
25432 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25433 break;
25434 case MXU_OPTN3_PTN1:
25435 case MXU_OPTN3_PTN2:
25436 case MXU_OPTN3_PTN3:
25437 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25438 break;
25440 } else {
25441 /* the most general case */
25442 switch (optn3) {
25443 case MXU_OPTN3_PTN0:
25445 /* */
25446 /* XRb XRc */
25447 /* +---------------+ */
25448 /* | A B C D | E F G H */
25449 /* +-------+-------+ */
25450 /* | */
25451 /* XRa */
25452 /* */
25454 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25456 break;
25457 case MXU_OPTN3_PTN1:
25459 /* */
25460 /* XRb XRc */
25461 /* +-------------------+ */
25462 /* A | B C D E | F G H */
25463 /* +---------+---------+ */
25464 /* | */
25465 /* XRa */
25466 /* */
25468 TCGv_i32 t0 = tcg_temp_new();
25469 TCGv_i32 t1 = tcg_temp_new();
25471 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25472 tcg_gen_shli_i32(t0, t0, 8);
25474 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25475 tcg_gen_shri_i32(t1, t1, 24);
25477 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25479 tcg_temp_free(t1);
25480 tcg_temp_free(t0);
25482 break;
25483 case MXU_OPTN3_PTN2:
25485 /* */
25486 /* XRb XRc */
25487 /* +-------------------+ */
25488 /* A B | C D E F | G H */
25489 /* +---------+---------+ */
25490 /* | */
25491 /* XRa */
25492 /* */
25494 TCGv_i32 t0 = tcg_temp_new();
25495 TCGv_i32 t1 = tcg_temp_new();
25497 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25498 tcg_gen_shli_i32(t0, t0, 16);
25500 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25501 tcg_gen_shri_i32(t1, t1, 16);
25503 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25505 tcg_temp_free(t1);
25506 tcg_temp_free(t0);
25508 break;
25509 case MXU_OPTN3_PTN3:
25511 /* */
25512 /* XRb XRc */
25513 /* +-------------------+ */
25514 /* A B C | D E F G | H */
25515 /* +---------+---------+ */
25516 /* | */
25517 /* XRa */
25518 /* */
25520 TCGv_i32 t0 = tcg_temp_new();
25521 TCGv_i32 t1 = tcg_temp_new();
25523 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25524 tcg_gen_shli_i32(t0, t0, 24);
25526 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25527 tcg_gen_shri_i32(t1, t1, 8);
25529 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25531 tcg_temp_free(t1);
25532 tcg_temp_free(t0);
25534 break;
25535 case MXU_OPTN3_PTN4:
25537 /* */
25538 /* XRb XRc */
25539 /* +---------------+ */
25540 /* A B C D | E F G H | */
25541 /* +-------+-------+ */
25542 /* | */
25543 /* XRa */
25544 /* */
25546 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25548 break;
25555 * Decoding engine for MXU
25556 * =======================
25561 * Decode MXU pool00
25563 * 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
25564 * +-----------+---------+-----+-------+-------+-------+-----------+
25565 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25566 * +-----------+---------+-----+-------+-------+-------+-----------+
25569 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25571 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25573 switch (opcode) {
25574 case OPC_MXU_S32MAX:
25575 case OPC_MXU_S32MIN:
25576 gen_mxu_S32MAX_S32MIN(ctx);
25577 break;
25578 case OPC_MXU_D16MAX:
25579 case OPC_MXU_D16MIN:
25580 gen_mxu_D16MAX_D16MIN(ctx);
25581 break;
25582 case OPC_MXU_Q8MAX:
25583 case OPC_MXU_Q8MIN:
25584 gen_mxu_Q8MAX_Q8MIN(ctx);
25585 break;
25586 case OPC_MXU_Q8SLT:
25587 /* TODO: Implement emulation of Q8SLT instruction. */
25588 MIPS_INVAL("OPC_MXU_Q8SLT");
25589 generate_exception_end(ctx, EXCP_RI);
25590 break;
25591 case OPC_MXU_Q8SLTU:
25592 /* TODO: Implement emulation of Q8SLTU instruction. */
25593 MIPS_INVAL("OPC_MXU_Q8SLTU");
25594 generate_exception_end(ctx, EXCP_RI);
25595 break;
25596 default:
25597 MIPS_INVAL("decode_opc_mxu");
25598 generate_exception_end(ctx, EXCP_RI);
25599 break;
25605 * Decode MXU pool01
25607 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25608 * 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
25609 * +-----------+---------+-----+-------+-------+-------+-----------+
25610 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25611 * +-----------+---------+-----+-------+-------+-------+-----------+
25613 * Q8ADD:
25614 * 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
25615 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25616 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25617 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25620 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25622 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25624 switch (opcode) {
25625 case OPC_MXU_S32SLT:
25626 /* TODO: Implement emulation of S32SLT instruction. */
25627 MIPS_INVAL("OPC_MXU_S32SLT");
25628 generate_exception_end(ctx, EXCP_RI);
25629 break;
25630 case OPC_MXU_D16SLT:
25631 /* TODO: Implement emulation of D16SLT instruction. */
25632 MIPS_INVAL("OPC_MXU_D16SLT");
25633 generate_exception_end(ctx, EXCP_RI);
25634 break;
25635 case OPC_MXU_D16AVG:
25636 /* TODO: Implement emulation of D16AVG instruction. */
25637 MIPS_INVAL("OPC_MXU_D16AVG");
25638 generate_exception_end(ctx, EXCP_RI);
25639 break;
25640 case OPC_MXU_D16AVGR:
25641 /* TODO: Implement emulation of D16AVGR instruction. */
25642 MIPS_INVAL("OPC_MXU_D16AVGR");
25643 generate_exception_end(ctx, EXCP_RI);
25644 break;
25645 case OPC_MXU_Q8AVG:
25646 /* TODO: Implement emulation of Q8AVG instruction. */
25647 MIPS_INVAL("OPC_MXU_Q8AVG");
25648 generate_exception_end(ctx, EXCP_RI);
25649 break;
25650 case OPC_MXU_Q8AVGR:
25651 /* TODO: Implement emulation of Q8AVGR instruction. */
25652 MIPS_INVAL("OPC_MXU_Q8AVGR");
25653 generate_exception_end(ctx, EXCP_RI);
25654 break;
25655 case OPC_MXU_Q8ADD:
25656 /* TODO: Implement emulation of Q8ADD instruction. */
25657 MIPS_INVAL("OPC_MXU_Q8ADD");
25658 generate_exception_end(ctx, EXCP_RI);
25659 break;
25660 default:
25661 MIPS_INVAL("decode_opc_mxu");
25662 generate_exception_end(ctx, EXCP_RI);
25663 break;
25669 * Decode MXU pool02
25671 * 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
25672 * +-----------+---------+-----+-------+-------+-------+-----------+
25673 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25674 * +-----------+---------+-----+-------+-------+-------+-----------+
25677 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25679 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25681 switch (opcode) {
25682 case OPC_MXU_S32CPS:
25683 /* TODO: Implement emulation of S32CPS instruction. */
25684 MIPS_INVAL("OPC_MXU_S32CPS");
25685 generate_exception_end(ctx, EXCP_RI);
25686 break;
25687 case OPC_MXU_D16CPS:
25688 /* TODO: Implement emulation of D16CPS instruction. */
25689 MIPS_INVAL("OPC_MXU_D16CPS");
25690 generate_exception_end(ctx, EXCP_RI);
25691 break;
25692 case OPC_MXU_Q8ABD:
25693 /* TODO: Implement emulation of Q8ABD instruction. */
25694 MIPS_INVAL("OPC_MXU_Q8ABD");
25695 generate_exception_end(ctx, EXCP_RI);
25696 break;
25697 case OPC_MXU_Q16SAT:
25698 /* TODO: Implement emulation of Q16SAT instruction. */
25699 MIPS_INVAL("OPC_MXU_Q16SAT");
25700 generate_exception_end(ctx, EXCP_RI);
25701 break;
25702 default:
25703 MIPS_INVAL("decode_opc_mxu");
25704 generate_exception_end(ctx, EXCP_RI);
25705 break;
25711 * Decode MXU pool03
25713 * D16MULF:
25714 * 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
25715 * +-----------+---+---+-------+-------+-------+-------+-----------+
25716 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25717 * +-----------+---+---+-------+-------+-------+-------+-----------+
25719 * D16MULE:
25720 * 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
25721 * +-----------+---+---+-------+-------+-------+-------+-----------+
25722 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25723 * +-----------+---+---+-------+-------+-------+-------+-----------+
25726 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25728 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25730 switch (opcode) {
25731 case OPC_MXU_D16MULF:
25732 /* TODO: Implement emulation of D16MULF instruction. */
25733 MIPS_INVAL("OPC_MXU_D16MULF");
25734 generate_exception_end(ctx, EXCP_RI);
25735 break;
25736 case OPC_MXU_D16MULE:
25737 /* TODO: Implement emulation of D16MULE instruction. */
25738 MIPS_INVAL("OPC_MXU_D16MULE");
25739 generate_exception_end(ctx, EXCP_RI);
25740 break;
25741 default:
25742 MIPS_INVAL("decode_opc_mxu");
25743 generate_exception_end(ctx, EXCP_RI);
25744 break;
25750 * Decode MXU pool04
25752 * 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
25753 * +-----------+---------+-+-------------------+-------+-----------+
25754 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25755 * +-----------+---------+-+-------------------+-------+-----------+
25758 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25760 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25762 switch (opcode) {
25763 case OPC_MXU_S32LDD:
25764 case OPC_MXU_S32LDDR:
25765 gen_mxu_s32ldd_s32lddr(ctx);
25766 break;
25767 default:
25768 MIPS_INVAL("decode_opc_mxu");
25769 generate_exception_end(ctx, EXCP_RI);
25770 break;
25776 * Decode MXU pool05
25778 * 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
25779 * +-----------+---------+-+-------------------+-------+-----------+
25780 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25781 * +-----------+---------+-+-------------------+-------+-----------+
25784 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25786 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25788 switch (opcode) {
25789 case OPC_MXU_S32STD:
25790 /* TODO: Implement emulation of S32STD instruction. */
25791 MIPS_INVAL("OPC_MXU_S32STD");
25792 generate_exception_end(ctx, EXCP_RI);
25793 break;
25794 case OPC_MXU_S32STDR:
25795 /* TODO: Implement emulation of S32STDR instruction. */
25796 MIPS_INVAL("OPC_MXU_S32STDR");
25797 generate_exception_end(ctx, EXCP_RI);
25798 break;
25799 default:
25800 MIPS_INVAL("decode_opc_mxu");
25801 generate_exception_end(ctx, EXCP_RI);
25802 break;
25808 * Decode MXU pool06
25810 * 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
25811 * +-----------+---------+---------+---+-------+-------+-----------+
25812 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25813 * +-----------+---------+---------+---+-------+-------+-----------+
25816 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25818 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25820 switch (opcode) {
25821 case OPC_MXU_S32LDDV:
25822 /* TODO: Implement emulation of S32LDDV instruction. */
25823 MIPS_INVAL("OPC_MXU_S32LDDV");
25824 generate_exception_end(ctx, EXCP_RI);
25825 break;
25826 case OPC_MXU_S32LDDVR:
25827 /* TODO: Implement emulation of S32LDDVR instruction. */
25828 MIPS_INVAL("OPC_MXU_S32LDDVR");
25829 generate_exception_end(ctx, EXCP_RI);
25830 break;
25831 default:
25832 MIPS_INVAL("decode_opc_mxu");
25833 generate_exception_end(ctx, EXCP_RI);
25834 break;
25840 * Decode MXU pool07
25842 * 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
25843 * +-----------+---------+---------+---+-------+-------+-----------+
25844 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
25845 * +-----------+---------+---------+---+-------+-------+-----------+
25848 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
25850 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25852 switch (opcode) {
25853 case OPC_MXU_S32STDV:
25854 /* TODO: Implement emulation of S32TDV instruction. */
25855 MIPS_INVAL("OPC_MXU_S32TDV");
25856 generate_exception_end(ctx, EXCP_RI);
25857 break;
25858 case OPC_MXU_S32STDVR:
25859 /* TODO: Implement emulation of S32TDVR instruction. */
25860 MIPS_INVAL("OPC_MXU_S32TDVR");
25861 generate_exception_end(ctx, EXCP_RI);
25862 break;
25863 default:
25864 MIPS_INVAL("decode_opc_mxu");
25865 generate_exception_end(ctx, EXCP_RI);
25866 break;
25872 * Decode MXU pool08
25874 * 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
25875 * +-----------+---------+-+-------------------+-------+-----------+
25876 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
25877 * +-----------+---------+-+-------------------+-------+-----------+
25880 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
25882 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25884 switch (opcode) {
25885 case OPC_MXU_S32LDI:
25886 /* TODO: Implement emulation of S32LDI instruction. */
25887 MIPS_INVAL("OPC_MXU_S32LDI");
25888 generate_exception_end(ctx, EXCP_RI);
25889 break;
25890 case OPC_MXU_S32LDIR:
25891 /* TODO: Implement emulation of S32LDIR instruction. */
25892 MIPS_INVAL("OPC_MXU_S32LDIR");
25893 generate_exception_end(ctx, EXCP_RI);
25894 break;
25895 default:
25896 MIPS_INVAL("decode_opc_mxu");
25897 generate_exception_end(ctx, EXCP_RI);
25898 break;
25904 * Decode MXU pool09
25906 * 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
25907 * +-----------+---------+-+-------------------+-------+-----------+
25908 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
25909 * +-----------+---------+-+-------------------+-------+-----------+
25912 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
25914 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25916 switch (opcode) {
25917 case OPC_MXU_S32SDI:
25918 /* TODO: Implement emulation of S32SDI instruction. */
25919 MIPS_INVAL("OPC_MXU_S32SDI");
25920 generate_exception_end(ctx, EXCP_RI);
25921 break;
25922 case OPC_MXU_S32SDIR:
25923 /* TODO: Implement emulation of S32SDIR instruction. */
25924 MIPS_INVAL("OPC_MXU_S32SDIR");
25925 generate_exception_end(ctx, EXCP_RI);
25926 break;
25927 default:
25928 MIPS_INVAL("decode_opc_mxu");
25929 generate_exception_end(ctx, EXCP_RI);
25930 break;
25936 * Decode MXU pool10
25938 * 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
25939 * +-----------+---------+---------+---+-------+-------+-----------+
25940 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
25941 * +-----------+---------+---------+---+-------+-------+-----------+
25944 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
25946 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25948 switch (opcode) {
25949 case OPC_MXU_S32LDIV:
25950 /* TODO: Implement emulation of S32LDIV instruction. */
25951 MIPS_INVAL("OPC_MXU_S32LDIV");
25952 generate_exception_end(ctx, EXCP_RI);
25953 break;
25954 case OPC_MXU_S32LDIVR:
25955 /* TODO: Implement emulation of S32LDIVR instruction. */
25956 MIPS_INVAL("OPC_MXU_S32LDIVR");
25957 generate_exception_end(ctx, EXCP_RI);
25958 break;
25959 default:
25960 MIPS_INVAL("decode_opc_mxu");
25961 generate_exception_end(ctx, EXCP_RI);
25962 break;
25968 * Decode MXU pool11
25970 * 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
25971 * +-----------+---------+---------+---+-------+-------+-----------+
25972 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
25973 * +-----------+---------+---------+---+-------+-------+-----------+
25976 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
25978 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25980 switch (opcode) {
25981 case OPC_MXU_S32SDIV:
25982 /* TODO: Implement emulation of S32SDIV instruction. */
25983 MIPS_INVAL("OPC_MXU_S32SDIV");
25984 generate_exception_end(ctx, EXCP_RI);
25985 break;
25986 case OPC_MXU_S32SDIVR:
25987 /* TODO: Implement emulation of S32SDIVR instruction. */
25988 MIPS_INVAL("OPC_MXU_S32SDIVR");
25989 generate_exception_end(ctx, EXCP_RI);
25990 break;
25991 default:
25992 MIPS_INVAL("decode_opc_mxu");
25993 generate_exception_end(ctx, EXCP_RI);
25994 break;
26000 * Decode MXU pool12
26002 * 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
26003 * +-----------+---+---+-------+-------+-------+-------+-----------+
26004 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26005 * +-----------+---+---+-------+-------+-------+-------+-----------+
26008 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26010 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26012 switch (opcode) {
26013 case OPC_MXU_D32ACC:
26014 /* TODO: Implement emulation of D32ACC instruction. */
26015 MIPS_INVAL("OPC_MXU_D32ACC");
26016 generate_exception_end(ctx, EXCP_RI);
26017 break;
26018 case OPC_MXU_D32ACCM:
26019 /* TODO: Implement emulation of D32ACCM instruction. */
26020 MIPS_INVAL("OPC_MXU_D32ACCM");
26021 generate_exception_end(ctx, EXCP_RI);
26022 break;
26023 case OPC_MXU_D32ASUM:
26024 /* TODO: Implement emulation of D32ASUM instruction. */
26025 MIPS_INVAL("OPC_MXU_D32ASUM");
26026 generate_exception_end(ctx, EXCP_RI);
26027 break;
26028 default:
26029 MIPS_INVAL("decode_opc_mxu");
26030 generate_exception_end(ctx, EXCP_RI);
26031 break;
26037 * Decode MXU pool13
26039 * 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
26040 * +-----------+---+---+-------+-------+-------+-------+-----------+
26041 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26042 * +-----------+---+---+-------+-------+-------+-------+-----------+
26045 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26047 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26049 switch (opcode) {
26050 case OPC_MXU_Q16ACC:
26051 /* TODO: Implement emulation of Q16ACC instruction. */
26052 MIPS_INVAL("OPC_MXU_Q16ACC");
26053 generate_exception_end(ctx, EXCP_RI);
26054 break;
26055 case OPC_MXU_Q16ACCM:
26056 /* TODO: Implement emulation of Q16ACCM instruction. */
26057 MIPS_INVAL("OPC_MXU_Q16ACCM");
26058 generate_exception_end(ctx, EXCP_RI);
26059 break;
26060 case OPC_MXU_Q16ASUM:
26061 /* TODO: Implement emulation of Q16ASUM instruction. */
26062 MIPS_INVAL("OPC_MXU_Q16ASUM");
26063 generate_exception_end(ctx, EXCP_RI);
26064 break;
26065 default:
26066 MIPS_INVAL("decode_opc_mxu");
26067 generate_exception_end(ctx, EXCP_RI);
26068 break;
26074 * Decode MXU pool14
26076 * Q8ADDE, Q8ACCE:
26077 * 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
26078 * +-----------+---+---+-------+-------+-------+-------+-----------+
26079 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26080 * +-----------+---+---+-------+-------+-------+-------+-----------+
26082 * D8SUM, D8SUMC:
26083 * 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
26084 * +-----------+---+---+-------+-------+-------+-------+-----------+
26085 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26086 * +-----------+---+---+-------+-------+-------+-------+-----------+
26089 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26091 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26093 switch (opcode) {
26094 case OPC_MXU_Q8ADDE:
26095 /* TODO: Implement emulation of Q8ADDE instruction. */
26096 MIPS_INVAL("OPC_MXU_Q8ADDE");
26097 generate_exception_end(ctx, EXCP_RI);
26098 break;
26099 case OPC_MXU_D8SUM:
26100 /* TODO: Implement emulation of D8SUM instruction. */
26101 MIPS_INVAL("OPC_MXU_D8SUM");
26102 generate_exception_end(ctx, EXCP_RI);
26103 break;
26104 case OPC_MXU_D8SUMC:
26105 /* TODO: Implement emulation of D8SUMC instruction. */
26106 MIPS_INVAL("OPC_MXU_D8SUMC");
26107 generate_exception_end(ctx, EXCP_RI);
26108 break;
26109 default:
26110 MIPS_INVAL("decode_opc_mxu");
26111 generate_exception_end(ctx, EXCP_RI);
26112 break;
26118 * Decode MXU pool15
26120 * S32MUL, S32MULU, S32EXTRV:
26121 * 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
26122 * +-----------+---------+---------+---+-------+-------+-----------+
26123 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26124 * +-----------+---------+---------+---+-------+-------+-----------+
26126 * S32EXTR:
26127 * 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
26128 * +-----------+---------+---------+---+-------+-------+-----------+
26129 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26130 * +-----------+---------+---------+---+-------+-------+-----------+
26133 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26135 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26137 switch (opcode) {
26138 case OPC_MXU_S32MUL:
26139 /* TODO: Implement emulation of S32MUL instruction. */
26140 MIPS_INVAL("OPC_MXU_S32MUL");
26141 generate_exception_end(ctx, EXCP_RI);
26142 break;
26143 case OPC_MXU_S32MULU:
26144 /* TODO: Implement emulation of S32MULU instruction. */
26145 MIPS_INVAL("OPC_MXU_S32MULU");
26146 generate_exception_end(ctx, EXCP_RI);
26147 break;
26148 case OPC_MXU_S32EXTR:
26149 /* TODO: Implement emulation of S32EXTR instruction. */
26150 MIPS_INVAL("OPC_MXU_S32EXTR");
26151 generate_exception_end(ctx, EXCP_RI);
26152 break;
26153 case OPC_MXU_S32EXTRV:
26154 /* TODO: Implement emulation of S32EXTRV instruction. */
26155 MIPS_INVAL("OPC_MXU_S32EXTRV");
26156 generate_exception_end(ctx, EXCP_RI);
26157 break;
26158 default:
26159 MIPS_INVAL("decode_opc_mxu");
26160 generate_exception_end(ctx, EXCP_RI);
26161 break;
26167 * Decode MXU pool16
26169 * D32SARW:
26170 * 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
26171 * +-----------+---------+-----+-------+-------+-------+-----------+
26172 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26173 * +-----------+---------+-----+-------+-------+-------+-----------+
26175 * S32ALN:
26176 * 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
26177 * +-----------+---------+-----+-------+-------+-------+-----------+
26178 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26179 * +-----------+---------+-----+-------+-------+-------+-----------+
26181 * S32ALNI:
26182 * 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
26183 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26184 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26185 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26187 * S32LUI:
26188 * 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
26189 * +-----------+-----+---+-----+-------+---------------+-----------+
26190 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26191 * +-----------+-----+---+-----+-------+---------------+-----------+
26193 * S32NOR, S32AND, S32OR, S32XOR:
26194 * 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
26195 * +-----------+---------+-----+-------+-------+-------+-----------+
26196 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26197 * +-----------+---------+-----+-------+-------+-------+-----------+
26200 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26202 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26204 switch (opcode) {
26205 case OPC_MXU_D32SARW:
26206 /* TODO: Implement emulation of D32SARW instruction. */
26207 MIPS_INVAL("OPC_MXU_D32SARW");
26208 generate_exception_end(ctx, EXCP_RI);
26209 break;
26210 case OPC_MXU_S32ALN:
26211 /* TODO: Implement emulation of S32ALN instruction. */
26212 MIPS_INVAL("OPC_MXU_S32ALN");
26213 generate_exception_end(ctx, EXCP_RI);
26214 break;
26215 case OPC_MXU_S32ALNI:
26216 gen_mxu_S32ALNI(ctx);
26217 break;
26218 case OPC_MXU_S32LUI:
26219 /* TODO: Implement emulation of S32LUI instruction. */
26220 MIPS_INVAL("OPC_MXU_S32LUI");
26221 generate_exception_end(ctx, EXCP_RI);
26222 break;
26223 case OPC_MXU_S32NOR:
26224 gen_mxu_S32NOR(ctx);
26225 break;
26226 case OPC_MXU_S32AND:
26227 gen_mxu_S32AND(ctx);
26228 break;
26229 case OPC_MXU_S32OR:
26230 gen_mxu_S32OR(ctx);
26231 break;
26232 case OPC_MXU_S32XOR:
26233 gen_mxu_S32XOR(ctx);
26234 break;
26235 default:
26236 MIPS_INVAL("decode_opc_mxu");
26237 generate_exception_end(ctx, EXCP_RI);
26238 break;
26244 * Decode MXU pool17
26246 * 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
26247 * +-----------+---------+---------+---+---------+-----+-----------+
26248 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26249 * +-----------+---------+---------+---+---------+-----+-----------+
26252 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26254 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26256 switch (opcode) {
26257 case OPC_MXU_LXW:
26258 /* TODO: Implement emulation of LXW instruction. */
26259 MIPS_INVAL("OPC_MXU_LXW");
26260 generate_exception_end(ctx, EXCP_RI);
26261 break;
26262 case OPC_MXU_LXH:
26263 /* TODO: Implement emulation of LXH instruction. */
26264 MIPS_INVAL("OPC_MXU_LXH");
26265 generate_exception_end(ctx, EXCP_RI);
26266 break;
26267 case OPC_MXU_LXHU:
26268 /* TODO: Implement emulation of LXHU instruction. */
26269 MIPS_INVAL("OPC_MXU_LXHU");
26270 generate_exception_end(ctx, EXCP_RI);
26271 break;
26272 case OPC_MXU_LXB:
26273 /* TODO: Implement emulation of LXB instruction. */
26274 MIPS_INVAL("OPC_MXU_LXB");
26275 generate_exception_end(ctx, EXCP_RI);
26276 break;
26277 case OPC_MXU_LXBU:
26278 /* TODO: Implement emulation of LXBU instruction. */
26279 MIPS_INVAL("OPC_MXU_LXBU");
26280 generate_exception_end(ctx, EXCP_RI);
26281 break;
26282 default:
26283 MIPS_INVAL("decode_opc_mxu");
26284 generate_exception_end(ctx, EXCP_RI);
26285 break;
26290 * Decode MXU pool18
26292 * 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
26293 * +-----------+---------+-----+-------+-------+-------+-----------+
26294 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26295 * +-----------+---------+-----+-------+-------+-------+-----------+
26298 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26300 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26302 switch (opcode) {
26303 case OPC_MXU_D32SLLV:
26304 /* TODO: Implement emulation of D32SLLV instruction. */
26305 MIPS_INVAL("OPC_MXU_D32SLLV");
26306 generate_exception_end(ctx, EXCP_RI);
26307 break;
26308 case OPC_MXU_D32SLRV:
26309 /* TODO: Implement emulation of D32SLRV instruction. */
26310 MIPS_INVAL("OPC_MXU_D32SLRV");
26311 generate_exception_end(ctx, EXCP_RI);
26312 break;
26313 case OPC_MXU_D32SARV:
26314 /* TODO: Implement emulation of D32SARV instruction. */
26315 MIPS_INVAL("OPC_MXU_D32SARV");
26316 generate_exception_end(ctx, EXCP_RI);
26317 break;
26318 case OPC_MXU_Q16SLLV:
26319 /* TODO: Implement emulation of Q16SLLV instruction. */
26320 MIPS_INVAL("OPC_MXU_Q16SLLV");
26321 generate_exception_end(ctx, EXCP_RI);
26322 break;
26323 case OPC_MXU_Q16SLRV:
26324 /* TODO: Implement emulation of Q16SLRV instruction. */
26325 MIPS_INVAL("OPC_MXU_Q16SLRV");
26326 generate_exception_end(ctx, EXCP_RI);
26327 break;
26328 case OPC_MXU_Q16SARV:
26329 /* TODO: Implement emulation of Q16SARV instruction. */
26330 MIPS_INVAL("OPC_MXU_Q16SARV");
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 pool19
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 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26347 * +-----------+---+---+-------+-------+-------+-------+-----------+
26350 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26352 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26354 switch (opcode) {
26355 case OPC_MXU_Q8MUL:
26356 case OPC_MXU_Q8MULSU:
26357 gen_mxu_q8mul_q8mulsu(ctx);
26358 break;
26359 default:
26360 MIPS_INVAL("decode_opc_mxu");
26361 generate_exception_end(ctx, EXCP_RI);
26362 break;
26368 * Decode MXU pool20
26370 * 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
26371 * +-----------+---------+-----+-------+-------+-------+-----------+
26372 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26373 * +-----------+---------+-----+-------+-------+-------+-----------+
26376 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26378 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26380 switch (opcode) {
26381 case OPC_MXU_Q8MOVZ:
26382 /* TODO: Implement emulation of Q8MOVZ instruction. */
26383 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26384 generate_exception_end(ctx, EXCP_RI);
26385 break;
26386 case OPC_MXU_Q8MOVN:
26387 /* TODO: Implement emulation of Q8MOVN instruction. */
26388 MIPS_INVAL("OPC_MXU_Q8MOVN");
26389 generate_exception_end(ctx, EXCP_RI);
26390 break;
26391 case OPC_MXU_D16MOVZ:
26392 /* TODO: Implement emulation of D16MOVZ instruction. */
26393 MIPS_INVAL("OPC_MXU_D16MOVZ");
26394 generate_exception_end(ctx, EXCP_RI);
26395 break;
26396 case OPC_MXU_D16MOVN:
26397 /* TODO: Implement emulation of D16MOVN instruction. */
26398 MIPS_INVAL("OPC_MXU_D16MOVN");
26399 generate_exception_end(ctx, EXCP_RI);
26400 break;
26401 case OPC_MXU_S32MOVZ:
26402 /* TODO: Implement emulation of S32MOVZ instruction. */
26403 MIPS_INVAL("OPC_MXU_S32MOVZ");
26404 generate_exception_end(ctx, EXCP_RI);
26405 break;
26406 case OPC_MXU_S32MOVN:
26407 /* TODO: Implement emulation of S32MOVN instruction. */
26408 MIPS_INVAL("OPC_MXU_S32MOVN");
26409 generate_exception_end(ctx, EXCP_RI);
26410 break;
26411 default:
26412 MIPS_INVAL("decode_opc_mxu");
26413 generate_exception_end(ctx, EXCP_RI);
26414 break;
26420 * Decode MXU pool21
26422 * 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
26423 * +-----------+---+---+-------+-------+-------+-------+-----------+
26424 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26425 * +-----------+---+---+-------+-------+-------+-------+-----------+
26428 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26430 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26432 switch (opcode) {
26433 case OPC_MXU_Q8MAC:
26434 /* TODO: Implement emulation of Q8MAC instruction. */
26435 MIPS_INVAL("OPC_MXU_Q8MAC");
26436 generate_exception_end(ctx, EXCP_RI);
26437 break;
26438 case OPC_MXU_Q8MACSU:
26439 /* TODO: Implement emulation of Q8MACSU instruction. */
26440 MIPS_INVAL("OPC_MXU_Q8MACSU");
26441 generate_exception_end(ctx, EXCP_RI);
26442 break;
26443 default:
26444 MIPS_INVAL("decode_opc_mxu");
26445 generate_exception_end(ctx, EXCP_RI);
26446 break;
26452 * Main MXU decoding function
26454 * 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
26455 * +-----------+---------------------------------------+-----------+
26456 * | SPECIAL2 | |x x x x x x|
26457 * +-----------+---------------------------------------+-----------+
26460 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26463 * TODO: Investigate necessity of including handling of
26464 * CLZ, CLO, SDBB in this function, as they belong to
26465 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26467 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26469 if (opcode == OPC__MXU_MUL) {
26470 uint32_t rs, rt, rd, op1;
26472 rs = extract32(ctx->opcode, 21, 5);
26473 rt = extract32(ctx->opcode, 16, 5);
26474 rd = extract32(ctx->opcode, 11, 5);
26475 op1 = MASK_SPECIAL2(ctx->opcode);
26477 gen_arith(ctx, op1, rd, rs, rt);
26479 return;
26482 if (opcode == OPC_MXU_S32M2I) {
26483 gen_mxu_s32m2i(ctx);
26484 return;
26487 if (opcode == OPC_MXU_S32I2M) {
26488 gen_mxu_s32i2m(ctx);
26489 return;
26493 TCGv t_mxu_cr = tcg_temp_new();
26494 TCGLabel *l_exit = gen_new_label();
26496 gen_load_mxu_cr(t_mxu_cr);
26497 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26498 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26500 switch (opcode) {
26501 case OPC_MXU_S32MADD:
26502 /* TODO: Implement emulation of S32MADD instruction. */
26503 MIPS_INVAL("OPC_MXU_S32MADD");
26504 generate_exception_end(ctx, EXCP_RI);
26505 break;
26506 case OPC_MXU_S32MADDU:
26507 /* TODO: Implement emulation of S32MADDU instruction. */
26508 MIPS_INVAL("OPC_MXU_S32MADDU");
26509 generate_exception_end(ctx, EXCP_RI);
26510 break;
26511 case OPC_MXU__POOL00:
26512 decode_opc_mxu__pool00(env, ctx);
26513 break;
26514 case OPC_MXU_S32MSUB:
26515 /* TODO: Implement emulation of S32MSUB instruction. */
26516 MIPS_INVAL("OPC_MXU_S32MSUB");
26517 generate_exception_end(ctx, EXCP_RI);
26518 break;
26519 case OPC_MXU_S32MSUBU:
26520 /* TODO: Implement emulation of S32MSUBU instruction. */
26521 MIPS_INVAL("OPC_MXU_S32MSUBU");
26522 generate_exception_end(ctx, EXCP_RI);
26523 break;
26524 case OPC_MXU__POOL01:
26525 decode_opc_mxu__pool01(env, ctx);
26526 break;
26527 case OPC_MXU__POOL02:
26528 decode_opc_mxu__pool02(env, ctx);
26529 break;
26530 case OPC_MXU_D16MUL:
26531 gen_mxu_d16mul(ctx);
26532 break;
26533 case OPC_MXU__POOL03:
26534 decode_opc_mxu__pool03(env, ctx);
26535 break;
26536 case OPC_MXU_D16MAC:
26537 gen_mxu_d16mac(ctx);
26538 break;
26539 case OPC_MXU_D16MACF:
26540 /* TODO: Implement emulation of D16MACF instruction. */
26541 MIPS_INVAL("OPC_MXU_D16MACF");
26542 generate_exception_end(ctx, EXCP_RI);
26543 break;
26544 case OPC_MXU_D16MADL:
26545 /* TODO: Implement emulation of D16MADL instruction. */
26546 MIPS_INVAL("OPC_MXU_D16MADL");
26547 generate_exception_end(ctx, EXCP_RI);
26548 break;
26549 case OPC_MXU_S16MAD:
26550 /* TODO: Implement emulation of S16MAD instruction. */
26551 MIPS_INVAL("OPC_MXU_S16MAD");
26552 generate_exception_end(ctx, EXCP_RI);
26553 break;
26554 case OPC_MXU_Q16ADD:
26555 /* TODO: Implement emulation of Q16ADD instruction. */
26556 MIPS_INVAL("OPC_MXU_Q16ADD");
26557 generate_exception_end(ctx, EXCP_RI);
26558 break;
26559 case OPC_MXU_D16MACE:
26560 /* TODO: Implement emulation of D16MACE instruction. */
26561 MIPS_INVAL("OPC_MXU_D16MACE");
26562 generate_exception_end(ctx, EXCP_RI);
26563 break;
26564 case OPC_MXU__POOL04:
26565 decode_opc_mxu__pool04(env, ctx);
26566 break;
26567 case OPC_MXU__POOL05:
26568 decode_opc_mxu__pool05(env, ctx);
26569 break;
26570 case OPC_MXU__POOL06:
26571 decode_opc_mxu__pool06(env, ctx);
26572 break;
26573 case OPC_MXU__POOL07:
26574 decode_opc_mxu__pool07(env, ctx);
26575 break;
26576 case OPC_MXU__POOL08:
26577 decode_opc_mxu__pool08(env, ctx);
26578 break;
26579 case OPC_MXU__POOL09:
26580 decode_opc_mxu__pool09(env, ctx);
26581 break;
26582 case OPC_MXU__POOL10:
26583 decode_opc_mxu__pool10(env, ctx);
26584 break;
26585 case OPC_MXU__POOL11:
26586 decode_opc_mxu__pool11(env, ctx);
26587 break;
26588 case OPC_MXU_D32ADD:
26589 /* TODO: Implement emulation of D32ADD instruction. */
26590 MIPS_INVAL("OPC_MXU_D32ADD");
26591 generate_exception_end(ctx, EXCP_RI);
26592 break;
26593 case OPC_MXU__POOL12:
26594 decode_opc_mxu__pool12(env, ctx);
26595 break;
26596 case OPC_MXU__POOL13:
26597 decode_opc_mxu__pool13(env, ctx);
26598 break;
26599 case OPC_MXU__POOL14:
26600 decode_opc_mxu__pool14(env, ctx);
26601 break;
26602 case OPC_MXU_Q8ACCE:
26603 /* TODO: Implement emulation of Q8ACCE instruction. */
26604 MIPS_INVAL("OPC_MXU_Q8ACCE");
26605 generate_exception_end(ctx, EXCP_RI);
26606 break;
26607 case OPC_MXU_S8LDD:
26608 gen_mxu_s8ldd(ctx);
26609 break;
26610 case OPC_MXU_S8STD:
26611 /* TODO: Implement emulation of S8STD instruction. */
26612 MIPS_INVAL("OPC_MXU_S8STD");
26613 generate_exception_end(ctx, EXCP_RI);
26614 break;
26615 case OPC_MXU_S8LDI:
26616 /* TODO: Implement emulation of S8LDI instruction. */
26617 MIPS_INVAL("OPC_MXU_S8LDI");
26618 generate_exception_end(ctx, EXCP_RI);
26619 break;
26620 case OPC_MXU_S8SDI:
26621 /* TODO: Implement emulation of S8SDI instruction. */
26622 MIPS_INVAL("OPC_MXU_S8SDI");
26623 generate_exception_end(ctx, EXCP_RI);
26624 break;
26625 case OPC_MXU__POOL15:
26626 decode_opc_mxu__pool15(env, ctx);
26627 break;
26628 case OPC_MXU__POOL16:
26629 decode_opc_mxu__pool16(env, ctx);
26630 break;
26631 case OPC_MXU__POOL17:
26632 decode_opc_mxu__pool17(env, ctx);
26633 break;
26634 case OPC_MXU_S16LDD:
26635 /* TODO: Implement emulation of S16LDD instruction. */
26636 MIPS_INVAL("OPC_MXU_S16LDD");
26637 generate_exception_end(ctx, EXCP_RI);
26638 break;
26639 case OPC_MXU_S16STD:
26640 /* TODO: Implement emulation of S16STD instruction. */
26641 MIPS_INVAL("OPC_MXU_S16STD");
26642 generate_exception_end(ctx, EXCP_RI);
26643 break;
26644 case OPC_MXU_S16LDI:
26645 /* TODO: Implement emulation of S16LDI instruction. */
26646 MIPS_INVAL("OPC_MXU_S16LDI");
26647 generate_exception_end(ctx, EXCP_RI);
26648 break;
26649 case OPC_MXU_S16SDI:
26650 /* TODO: Implement emulation of S16SDI instruction. */
26651 MIPS_INVAL("OPC_MXU_S16SDI");
26652 generate_exception_end(ctx, EXCP_RI);
26653 break;
26654 case OPC_MXU_D32SLL:
26655 /* TODO: Implement emulation of D32SLL instruction. */
26656 MIPS_INVAL("OPC_MXU_D32SLL");
26657 generate_exception_end(ctx, EXCP_RI);
26658 break;
26659 case OPC_MXU_D32SLR:
26660 /* TODO: Implement emulation of D32SLR instruction. */
26661 MIPS_INVAL("OPC_MXU_D32SLR");
26662 generate_exception_end(ctx, EXCP_RI);
26663 break;
26664 case OPC_MXU_D32SARL:
26665 /* TODO: Implement emulation of D32SARL instruction. */
26666 MIPS_INVAL("OPC_MXU_D32SARL");
26667 generate_exception_end(ctx, EXCP_RI);
26668 break;
26669 case OPC_MXU_D32SAR:
26670 /* TODO: Implement emulation of D32SAR instruction. */
26671 MIPS_INVAL("OPC_MXU_D32SAR");
26672 generate_exception_end(ctx, EXCP_RI);
26673 break;
26674 case OPC_MXU_Q16SLL:
26675 /* TODO: Implement emulation of Q16SLL instruction. */
26676 MIPS_INVAL("OPC_MXU_Q16SLL");
26677 generate_exception_end(ctx, EXCP_RI);
26678 break;
26679 case OPC_MXU_Q16SLR:
26680 /* TODO: Implement emulation of Q16SLR instruction. */
26681 MIPS_INVAL("OPC_MXU_Q16SLR");
26682 generate_exception_end(ctx, EXCP_RI);
26683 break;
26684 case OPC_MXU__POOL18:
26685 decode_opc_mxu__pool18(env, ctx);
26686 break;
26687 case OPC_MXU_Q16SAR:
26688 /* TODO: Implement emulation of Q16SAR instruction. */
26689 MIPS_INVAL("OPC_MXU_Q16SAR");
26690 generate_exception_end(ctx, EXCP_RI);
26691 break;
26692 case OPC_MXU__POOL19:
26693 decode_opc_mxu__pool19(env, ctx);
26694 break;
26695 case OPC_MXU__POOL20:
26696 decode_opc_mxu__pool20(env, ctx);
26697 break;
26698 case OPC_MXU__POOL21:
26699 decode_opc_mxu__pool21(env, ctx);
26700 break;
26701 case OPC_MXU_Q16SCOP:
26702 /* TODO: Implement emulation of Q16SCOP instruction. */
26703 MIPS_INVAL("OPC_MXU_Q16SCOP");
26704 generate_exception_end(ctx, EXCP_RI);
26705 break;
26706 case OPC_MXU_Q8MADL:
26707 /* TODO: Implement emulation of Q8MADL instruction. */
26708 MIPS_INVAL("OPC_MXU_Q8MADL");
26709 generate_exception_end(ctx, EXCP_RI);
26710 break;
26711 case OPC_MXU_S32SFL:
26712 /* TODO: Implement emulation of S32SFL instruction. */
26713 MIPS_INVAL("OPC_MXU_S32SFL");
26714 generate_exception_end(ctx, EXCP_RI);
26715 break;
26716 case OPC_MXU_Q8SAD:
26717 /* TODO: Implement emulation of Q8SAD instruction. */
26718 MIPS_INVAL("OPC_MXU_Q8SAD");
26719 generate_exception_end(ctx, EXCP_RI);
26720 break;
26721 default:
26722 MIPS_INVAL("decode_opc_mxu");
26723 generate_exception_end(ctx, EXCP_RI);
26726 gen_set_label(l_exit);
26727 tcg_temp_free(t_mxu_cr);
26731 #endif /* !defined(TARGET_MIPS64) */
26734 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26736 int rs, rt, rd;
26737 uint32_t op1;
26739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26741 rs = (ctx->opcode >> 21) & 0x1f;
26742 rt = (ctx->opcode >> 16) & 0x1f;
26743 rd = (ctx->opcode >> 11) & 0x1f;
26745 op1 = MASK_SPECIAL2(ctx->opcode);
26746 switch (op1) {
26747 case OPC_MADD: /* Multiply and add/sub */
26748 case OPC_MADDU:
26749 case OPC_MSUB:
26750 case OPC_MSUBU:
26751 check_insn(ctx, ISA_MIPS32);
26752 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26753 break;
26754 case OPC_MUL:
26755 gen_arith(ctx, op1, rd, rs, rt);
26756 break;
26757 case OPC_DIV_G_2F:
26758 case OPC_DIVU_G_2F:
26759 case OPC_MULT_G_2F:
26760 case OPC_MULTU_G_2F:
26761 case OPC_MOD_G_2F:
26762 case OPC_MODU_G_2F:
26763 check_insn(ctx, INSN_LOONGSON2F);
26764 gen_loongson_integer(ctx, op1, rd, rs, rt);
26765 break;
26766 case OPC_CLO:
26767 case OPC_CLZ:
26768 check_insn(ctx, ISA_MIPS32);
26769 gen_cl(ctx, op1, rd, rs);
26770 break;
26771 case OPC_SDBBP:
26772 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26773 gen_helper_do_semihosting(cpu_env);
26774 } else {
26775 /* XXX: not clear which exception should be raised
26776 * when in debug mode...
26778 check_insn(ctx, ISA_MIPS32);
26779 generate_exception_end(ctx, EXCP_DBp);
26781 break;
26782 #if defined(TARGET_MIPS64)
26783 case OPC_DCLO:
26784 case OPC_DCLZ:
26785 check_insn(ctx, ISA_MIPS64);
26786 check_mips_64(ctx);
26787 gen_cl(ctx, op1, rd, rs);
26788 break;
26789 case OPC_DMULT_G_2F:
26790 case OPC_DMULTU_G_2F:
26791 case OPC_DDIV_G_2F:
26792 case OPC_DDIVU_G_2F:
26793 case OPC_DMOD_G_2F:
26794 case OPC_DMODU_G_2F:
26795 check_insn(ctx, INSN_LOONGSON2F);
26796 gen_loongson_integer(ctx, op1, rd, rs, rt);
26797 break;
26798 #endif
26799 default: /* Invalid */
26800 MIPS_INVAL("special2_legacy");
26801 generate_exception_end(ctx, EXCP_RI);
26802 break;
26806 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26808 int rs, rt, rd, sa;
26809 uint32_t op1, op2;
26810 int16_t imm;
26812 rs = (ctx->opcode >> 21) & 0x1f;
26813 rt = (ctx->opcode >> 16) & 0x1f;
26814 rd = (ctx->opcode >> 11) & 0x1f;
26815 sa = (ctx->opcode >> 6) & 0x1f;
26816 imm = (int16_t)ctx->opcode >> 7;
26818 op1 = MASK_SPECIAL3(ctx->opcode);
26819 switch (op1) {
26820 case R6_OPC_PREF:
26821 if (rt >= 24) {
26822 /* hint codes 24-31 are reserved and signal RI */
26823 generate_exception_end(ctx, EXCP_RI);
26825 /* Treat as NOP. */
26826 break;
26827 case R6_OPC_CACHE:
26828 check_cp0_enabled(ctx);
26829 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26830 gen_cache_operation(ctx, rt, rs, imm);
26832 break;
26833 case R6_OPC_SC:
26834 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
26835 break;
26836 case R6_OPC_LL:
26837 gen_ld(ctx, op1, rt, rs, imm);
26838 break;
26839 case OPC_BSHFL:
26841 if (rd == 0) {
26842 /* Treat as NOP. */
26843 break;
26845 op2 = MASK_BSHFL(ctx->opcode);
26846 switch (op2) {
26847 case OPC_ALIGN:
26848 case OPC_ALIGN_1:
26849 case OPC_ALIGN_2:
26850 case OPC_ALIGN_3:
26851 gen_align(ctx, 32, rd, rs, rt, sa & 3);
26852 break;
26853 case OPC_BITSWAP:
26854 gen_bitswap(ctx, op2, rd, rt);
26855 break;
26858 break;
26859 #if defined(TARGET_MIPS64)
26860 case R6_OPC_SCD:
26861 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
26862 break;
26863 case R6_OPC_LLD:
26864 gen_ld(ctx, op1, rt, rs, imm);
26865 break;
26866 case OPC_DBSHFL:
26867 check_mips_64(ctx);
26869 if (rd == 0) {
26870 /* Treat as NOP. */
26871 break;
26873 op2 = MASK_DBSHFL(ctx->opcode);
26874 switch (op2) {
26875 case OPC_DALIGN:
26876 case OPC_DALIGN_1:
26877 case OPC_DALIGN_2:
26878 case OPC_DALIGN_3:
26879 case OPC_DALIGN_4:
26880 case OPC_DALIGN_5:
26881 case OPC_DALIGN_6:
26882 case OPC_DALIGN_7:
26883 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26884 break;
26885 case OPC_DBITSWAP:
26886 gen_bitswap(ctx, op2, rd, rt);
26887 break;
26891 break;
26892 #endif
26893 default: /* Invalid */
26894 MIPS_INVAL("special3_r6");
26895 generate_exception_end(ctx, EXCP_RI);
26896 break;
26900 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26902 int rs, rt, rd;
26903 uint32_t op1, op2;
26905 rs = (ctx->opcode >> 21) & 0x1f;
26906 rt = (ctx->opcode >> 16) & 0x1f;
26907 rd = (ctx->opcode >> 11) & 0x1f;
26909 op1 = MASK_SPECIAL3(ctx->opcode);
26910 switch (op1) {
26911 case OPC_DIV_G_2E:
26912 case OPC_DIVU_G_2E:
26913 case OPC_MOD_G_2E:
26914 case OPC_MODU_G_2E:
26915 case OPC_MULT_G_2E:
26916 case OPC_MULTU_G_2E:
26917 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26918 * the same mask and op1. */
26919 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26920 op2 = MASK_ADDUH_QB(ctx->opcode);
26921 switch (op2) {
26922 case OPC_ADDUH_QB:
26923 case OPC_ADDUH_R_QB:
26924 case OPC_ADDQH_PH:
26925 case OPC_ADDQH_R_PH:
26926 case OPC_ADDQH_W:
26927 case OPC_ADDQH_R_W:
26928 case OPC_SUBUH_QB:
26929 case OPC_SUBUH_R_QB:
26930 case OPC_SUBQH_PH:
26931 case OPC_SUBQH_R_PH:
26932 case OPC_SUBQH_W:
26933 case OPC_SUBQH_R_W:
26934 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26935 break;
26936 case OPC_MUL_PH:
26937 case OPC_MUL_S_PH:
26938 case OPC_MULQ_S_W:
26939 case OPC_MULQ_RS_W:
26940 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26941 break;
26942 default:
26943 MIPS_INVAL("MASK ADDUH.QB");
26944 generate_exception_end(ctx, EXCP_RI);
26945 break;
26947 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26948 gen_loongson_integer(ctx, op1, rd, rs, rt);
26949 } else {
26950 generate_exception_end(ctx, EXCP_RI);
26952 break;
26953 case OPC_LX_DSP:
26954 op2 = MASK_LX(ctx->opcode);
26955 switch (op2) {
26956 #if defined(TARGET_MIPS64)
26957 case OPC_LDX:
26958 #endif
26959 case OPC_LBUX:
26960 case OPC_LHX:
26961 case OPC_LWX:
26962 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26963 break;
26964 default: /* Invalid */
26965 MIPS_INVAL("MASK LX");
26966 generate_exception_end(ctx, EXCP_RI);
26967 break;
26969 break;
26970 case OPC_ABSQ_S_PH_DSP:
26971 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26972 switch (op2) {
26973 case OPC_ABSQ_S_QB:
26974 case OPC_ABSQ_S_PH:
26975 case OPC_ABSQ_S_W:
26976 case OPC_PRECEQ_W_PHL:
26977 case OPC_PRECEQ_W_PHR:
26978 case OPC_PRECEQU_PH_QBL:
26979 case OPC_PRECEQU_PH_QBR:
26980 case OPC_PRECEQU_PH_QBLA:
26981 case OPC_PRECEQU_PH_QBRA:
26982 case OPC_PRECEU_PH_QBL:
26983 case OPC_PRECEU_PH_QBR:
26984 case OPC_PRECEU_PH_QBLA:
26985 case OPC_PRECEU_PH_QBRA:
26986 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26987 break;
26988 case OPC_BITREV:
26989 case OPC_REPL_QB:
26990 case OPC_REPLV_QB:
26991 case OPC_REPL_PH:
26992 case OPC_REPLV_PH:
26993 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26994 break;
26995 default:
26996 MIPS_INVAL("MASK ABSQ_S.PH");
26997 generate_exception_end(ctx, EXCP_RI);
26998 break;
27000 break;
27001 case OPC_ADDU_QB_DSP:
27002 op2 = MASK_ADDU_QB(ctx->opcode);
27003 switch (op2) {
27004 case OPC_ADDQ_PH:
27005 case OPC_ADDQ_S_PH:
27006 case OPC_ADDQ_S_W:
27007 case OPC_ADDU_QB:
27008 case OPC_ADDU_S_QB:
27009 case OPC_ADDU_PH:
27010 case OPC_ADDU_S_PH:
27011 case OPC_SUBQ_PH:
27012 case OPC_SUBQ_S_PH:
27013 case OPC_SUBQ_S_W:
27014 case OPC_SUBU_QB:
27015 case OPC_SUBU_S_QB:
27016 case OPC_SUBU_PH:
27017 case OPC_SUBU_S_PH:
27018 case OPC_ADDSC:
27019 case OPC_ADDWC:
27020 case OPC_MODSUB:
27021 case OPC_RADDU_W_QB:
27022 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27023 break;
27024 case OPC_MULEU_S_PH_QBL:
27025 case OPC_MULEU_S_PH_QBR:
27026 case OPC_MULQ_RS_PH:
27027 case OPC_MULEQ_S_W_PHL:
27028 case OPC_MULEQ_S_W_PHR:
27029 case OPC_MULQ_S_PH:
27030 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27031 break;
27032 default: /* Invalid */
27033 MIPS_INVAL("MASK ADDU.QB");
27034 generate_exception_end(ctx, EXCP_RI);
27035 break;
27038 break;
27039 case OPC_CMPU_EQ_QB_DSP:
27040 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27041 switch (op2) {
27042 case OPC_PRECR_SRA_PH_W:
27043 case OPC_PRECR_SRA_R_PH_W:
27044 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27045 break;
27046 case OPC_PRECR_QB_PH:
27047 case OPC_PRECRQ_QB_PH:
27048 case OPC_PRECRQ_PH_W:
27049 case OPC_PRECRQ_RS_PH_W:
27050 case OPC_PRECRQU_S_QB_PH:
27051 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27052 break;
27053 case OPC_CMPU_EQ_QB:
27054 case OPC_CMPU_LT_QB:
27055 case OPC_CMPU_LE_QB:
27056 case OPC_CMP_EQ_PH:
27057 case OPC_CMP_LT_PH:
27058 case OPC_CMP_LE_PH:
27059 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27060 break;
27061 case OPC_CMPGU_EQ_QB:
27062 case OPC_CMPGU_LT_QB:
27063 case OPC_CMPGU_LE_QB:
27064 case OPC_CMPGDU_EQ_QB:
27065 case OPC_CMPGDU_LT_QB:
27066 case OPC_CMPGDU_LE_QB:
27067 case OPC_PICK_QB:
27068 case OPC_PICK_PH:
27069 case OPC_PACKRL_PH:
27070 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27071 break;
27072 default: /* Invalid */
27073 MIPS_INVAL("MASK CMPU.EQ.QB");
27074 generate_exception_end(ctx, EXCP_RI);
27075 break;
27077 break;
27078 case OPC_SHLL_QB_DSP:
27079 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27080 break;
27081 case OPC_DPA_W_PH_DSP:
27082 op2 = MASK_DPA_W_PH(ctx->opcode);
27083 switch (op2) {
27084 case OPC_DPAU_H_QBL:
27085 case OPC_DPAU_H_QBR:
27086 case OPC_DPSU_H_QBL:
27087 case OPC_DPSU_H_QBR:
27088 case OPC_DPA_W_PH:
27089 case OPC_DPAX_W_PH:
27090 case OPC_DPAQ_S_W_PH:
27091 case OPC_DPAQX_S_W_PH:
27092 case OPC_DPAQX_SA_W_PH:
27093 case OPC_DPS_W_PH:
27094 case OPC_DPSX_W_PH:
27095 case OPC_DPSQ_S_W_PH:
27096 case OPC_DPSQX_S_W_PH:
27097 case OPC_DPSQX_SA_W_PH:
27098 case OPC_MULSAQ_S_W_PH:
27099 case OPC_DPAQ_SA_L_W:
27100 case OPC_DPSQ_SA_L_W:
27101 case OPC_MAQ_S_W_PHL:
27102 case OPC_MAQ_S_W_PHR:
27103 case OPC_MAQ_SA_W_PHL:
27104 case OPC_MAQ_SA_W_PHR:
27105 case OPC_MULSA_W_PH:
27106 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27107 break;
27108 default: /* Invalid */
27109 MIPS_INVAL("MASK DPAW.PH");
27110 generate_exception_end(ctx, EXCP_RI);
27111 break;
27113 break;
27114 case OPC_INSV_DSP:
27115 op2 = MASK_INSV(ctx->opcode);
27116 switch (op2) {
27117 case OPC_INSV:
27118 check_dsp(ctx);
27120 TCGv t0, t1;
27122 if (rt == 0) {
27123 break;
27126 t0 = tcg_temp_new();
27127 t1 = tcg_temp_new();
27129 gen_load_gpr(t0, rt);
27130 gen_load_gpr(t1, rs);
27132 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27134 tcg_temp_free(t0);
27135 tcg_temp_free(t1);
27136 break;
27138 default: /* Invalid */
27139 MIPS_INVAL("MASK INSV");
27140 generate_exception_end(ctx, EXCP_RI);
27141 break;
27143 break;
27144 case OPC_APPEND_DSP:
27145 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27146 break;
27147 case OPC_EXTR_W_DSP:
27148 op2 = MASK_EXTR_W(ctx->opcode);
27149 switch (op2) {
27150 case OPC_EXTR_W:
27151 case OPC_EXTR_R_W:
27152 case OPC_EXTR_RS_W:
27153 case OPC_EXTR_S_H:
27154 case OPC_EXTRV_S_H:
27155 case OPC_EXTRV_W:
27156 case OPC_EXTRV_R_W:
27157 case OPC_EXTRV_RS_W:
27158 case OPC_EXTP:
27159 case OPC_EXTPV:
27160 case OPC_EXTPDP:
27161 case OPC_EXTPDPV:
27162 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27163 break;
27164 case OPC_RDDSP:
27165 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27166 break;
27167 case OPC_SHILO:
27168 case OPC_SHILOV:
27169 case OPC_MTHLIP:
27170 case OPC_WRDSP:
27171 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27172 break;
27173 default: /* Invalid */
27174 MIPS_INVAL("MASK EXTR.W");
27175 generate_exception_end(ctx, EXCP_RI);
27176 break;
27178 break;
27179 #if defined(TARGET_MIPS64)
27180 case OPC_DDIV_G_2E:
27181 case OPC_DDIVU_G_2E:
27182 case OPC_DMULT_G_2E:
27183 case OPC_DMULTU_G_2E:
27184 case OPC_DMOD_G_2E:
27185 case OPC_DMODU_G_2E:
27186 check_insn(ctx, INSN_LOONGSON2E);
27187 gen_loongson_integer(ctx, op1, rd, rs, rt);
27188 break;
27189 case OPC_ABSQ_S_QH_DSP:
27190 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27191 switch (op2) {
27192 case OPC_PRECEQ_L_PWL:
27193 case OPC_PRECEQ_L_PWR:
27194 case OPC_PRECEQ_PW_QHL:
27195 case OPC_PRECEQ_PW_QHR:
27196 case OPC_PRECEQ_PW_QHLA:
27197 case OPC_PRECEQ_PW_QHRA:
27198 case OPC_PRECEQU_QH_OBL:
27199 case OPC_PRECEQU_QH_OBR:
27200 case OPC_PRECEQU_QH_OBLA:
27201 case OPC_PRECEQU_QH_OBRA:
27202 case OPC_PRECEU_QH_OBL:
27203 case OPC_PRECEU_QH_OBR:
27204 case OPC_PRECEU_QH_OBLA:
27205 case OPC_PRECEU_QH_OBRA:
27206 case OPC_ABSQ_S_OB:
27207 case OPC_ABSQ_S_PW:
27208 case OPC_ABSQ_S_QH:
27209 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27210 break;
27211 case OPC_REPL_OB:
27212 case OPC_REPL_PW:
27213 case OPC_REPL_QH:
27214 case OPC_REPLV_OB:
27215 case OPC_REPLV_PW:
27216 case OPC_REPLV_QH:
27217 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27218 break;
27219 default: /* Invalid */
27220 MIPS_INVAL("MASK ABSQ_S.QH");
27221 generate_exception_end(ctx, EXCP_RI);
27222 break;
27224 break;
27225 case OPC_ADDU_OB_DSP:
27226 op2 = MASK_ADDU_OB(ctx->opcode);
27227 switch (op2) {
27228 case OPC_RADDU_L_OB:
27229 case OPC_SUBQ_PW:
27230 case OPC_SUBQ_S_PW:
27231 case OPC_SUBQ_QH:
27232 case OPC_SUBQ_S_QH:
27233 case OPC_SUBU_OB:
27234 case OPC_SUBU_S_OB:
27235 case OPC_SUBU_QH:
27236 case OPC_SUBU_S_QH:
27237 case OPC_SUBUH_OB:
27238 case OPC_SUBUH_R_OB:
27239 case OPC_ADDQ_PW:
27240 case OPC_ADDQ_S_PW:
27241 case OPC_ADDQ_QH:
27242 case OPC_ADDQ_S_QH:
27243 case OPC_ADDU_OB:
27244 case OPC_ADDU_S_OB:
27245 case OPC_ADDU_QH:
27246 case OPC_ADDU_S_QH:
27247 case OPC_ADDUH_OB:
27248 case OPC_ADDUH_R_OB:
27249 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27250 break;
27251 case OPC_MULEQ_S_PW_QHL:
27252 case OPC_MULEQ_S_PW_QHR:
27253 case OPC_MULEU_S_QH_OBL:
27254 case OPC_MULEU_S_QH_OBR:
27255 case OPC_MULQ_RS_QH:
27256 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27257 break;
27258 default: /* Invalid */
27259 MIPS_INVAL("MASK ADDU.OB");
27260 generate_exception_end(ctx, EXCP_RI);
27261 break;
27263 break;
27264 case OPC_CMPU_EQ_OB_DSP:
27265 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27266 switch (op2) {
27267 case OPC_PRECR_SRA_QH_PW:
27268 case OPC_PRECR_SRA_R_QH_PW:
27269 /* Return value is rt. */
27270 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27271 break;
27272 case OPC_PRECR_OB_QH:
27273 case OPC_PRECRQ_OB_QH:
27274 case OPC_PRECRQ_PW_L:
27275 case OPC_PRECRQ_QH_PW:
27276 case OPC_PRECRQ_RS_QH_PW:
27277 case OPC_PRECRQU_S_OB_QH:
27278 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27279 break;
27280 case OPC_CMPU_EQ_OB:
27281 case OPC_CMPU_LT_OB:
27282 case OPC_CMPU_LE_OB:
27283 case OPC_CMP_EQ_QH:
27284 case OPC_CMP_LT_QH:
27285 case OPC_CMP_LE_QH:
27286 case OPC_CMP_EQ_PW:
27287 case OPC_CMP_LT_PW:
27288 case OPC_CMP_LE_PW:
27289 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27290 break;
27291 case OPC_CMPGDU_EQ_OB:
27292 case OPC_CMPGDU_LT_OB:
27293 case OPC_CMPGDU_LE_OB:
27294 case OPC_CMPGU_EQ_OB:
27295 case OPC_CMPGU_LT_OB:
27296 case OPC_CMPGU_LE_OB:
27297 case OPC_PACKRL_PW:
27298 case OPC_PICK_OB:
27299 case OPC_PICK_PW:
27300 case OPC_PICK_QH:
27301 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27302 break;
27303 default: /* Invalid */
27304 MIPS_INVAL("MASK CMPU_EQ.OB");
27305 generate_exception_end(ctx, EXCP_RI);
27306 break;
27308 break;
27309 case OPC_DAPPEND_DSP:
27310 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27311 break;
27312 case OPC_DEXTR_W_DSP:
27313 op2 = MASK_DEXTR_W(ctx->opcode);
27314 switch (op2) {
27315 case OPC_DEXTP:
27316 case OPC_DEXTPDP:
27317 case OPC_DEXTPDPV:
27318 case OPC_DEXTPV:
27319 case OPC_DEXTR_L:
27320 case OPC_DEXTR_R_L:
27321 case OPC_DEXTR_RS_L:
27322 case OPC_DEXTR_W:
27323 case OPC_DEXTR_R_W:
27324 case OPC_DEXTR_RS_W:
27325 case OPC_DEXTR_S_H:
27326 case OPC_DEXTRV_L:
27327 case OPC_DEXTRV_R_L:
27328 case OPC_DEXTRV_RS_L:
27329 case OPC_DEXTRV_S_H:
27330 case OPC_DEXTRV_W:
27331 case OPC_DEXTRV_R_W:
27332 case OPC_DEXTRV_RS_W:
27333 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27334 break;
27335 case OPC_DMTHLIP:
27336 case OPC_DSHILO:
27337 case OPC_DSHILOV:
27338 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27339 break;
27340 default: /* Invalid */
27341 MIPS_INVAL("MASK EXTR.W");
27342 generate_exception_end(ctx, EXCP_RI);
27343 break;
27345 break;
27346 case OPC_DPAQ_W_QH_DSP:
27347 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27348 switch (op2) {
27349 case OPC_DPAU_H_OBL:
27350 case OPC_DPAU_H_OBR:
27351 case OPC_DPSU_H_OBL:
27352 case OPC_DPSU_H_OBR:
27353 case OPC_DPA_W_QH:
27354 case OPC_DPAQ_S_W_QH:
27355 case OPC_DPS_W_QH:
27356 case OPC_DPSQ_S_W_QH:
27357 case OPC_MULSAQ_S_W_QH:
27358 case OPC_DPAQ_SA_L_PW:
27359 case OPC_DPSQ_SA_L_PW:
27360 case OPC_MULSAQ_S_L_PW:
27361 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27362 break;
27363 case OPC_MAQ_S_W_QHLL:
27364 case OPC_MAQ_S_W_QHLR:
27365 case OPC_MAQ_S_W_QHRL:
27366 case OPC_MAQ_S_W_QHRR:
27367 case OPC_MAQ_SA_W_QHLL:
27368 case OPC_MAQ_SA_W_QHLR:
27369 case OPC_MAQ_SA_W_QHRL:
27370 case OPC_MAQ_SA_W_QHRR:
27371 case OPC_MAQ_S_L_PWL:
27372 case OPC_MAQ_S_L_PWR:
27373 case OPC_DMADD:
27374 case OPC_DMADDU:
27375 case OPC_DMSUB:
27376 case OPC_DMSUBU:
27377 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27378 break;
27379 default: /* Invalid */
27380 MIPS_INVAL("MASK DPAQ.W.QH");
27381 generate_exception_end(ctx, EXCP_RI);
27382 break;
27384 break;
27385 case OPC_DINSV_DSP:
27386 op2 = MASK_INSV(ctx->opcode);
27387 switch (op2) {
27388 case OPC_DINSV:
27390 TCGv t0, t1;
27392 if (rt == 0) {
27393 break;
27395 check_dsp(ctx);
27397 t0 = tcg_temp_new();
27398 t1 = tcg_temp_new();
27400 gen_load_gpr(t0, rt);
27401 gen_load_gpr(t1, rs);
27403 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27405 tcg_temp_free(t0);
27406 tcg_temp_free(t1);
27407 break;
27409 default: /* Invalid */
27410 MIPS_INVAL("MASK DINSV");
27411 generate_exception_end(ctx, EXCP_RI);
27412 break;
27414 break;
27415 case OPC_SHLL_OB_DSP:
27416 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27417 break;
27418 #endif
27419 default: /* Invalid */
27420 MIPS_INVAL("special3_legacy");
27421 generate_exception_end(ctx, EXCP_RI);
27422 break;
27427 #if defined(TARGET_MIPS64)
27429 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27431 uint32_t opc = MASK_MMI0(ctx->opcode);
27433 switch (opc) {
27434 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27435 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27436 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27437 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27438 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27439 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27440 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27441 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27442 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27443 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27444 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27445 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27446 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27447 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27448 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27449 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27450 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27451 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27452 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27453 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27454 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27455 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27456 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27457 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27458 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27459 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27460 break;
27461 default:
27462 MIPS_INVAL("TX79 MMI class MMI0");
27463 generate_exception_end(ctx, EXCP_RI);
27464 break;
27468 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27470 uint32_t opc = MASK_MMI1(ctx->opcode);
27472 switch (opc) {
27473 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27474 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27475 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27476 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27477 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27478 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27479 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27480 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27481 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27482 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27483 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27484 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27485 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27486 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27487 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27488 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27489 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27490 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27491 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27492 break;
27493 default:
27494 MIPS_INVAL("TX79 MMI class MMI1");
27495 generate_exception_end(ctx, EXCP_RI);
27496 break;
27500 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27502 uint32_t opc = MASK_MMI2(ctx->opcode);
27504 switch (opc) {
27505 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27506 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27507 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27508 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27509 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27510 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27511 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27512 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27513 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27514 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27515 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27516 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27517 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27518 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27519 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27520 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27521 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27522 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27523 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27524 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27525 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27526 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27527 break;
27528 case MMI_OPC_2_PCPYLD:
27529 gen_mmi_pcpyld(ctx);
27530 break;
27531 default:
27532 MIPS_INVAL("TX79 MMI class MMI2");
27533 generate_exception_end(ctx, EXCP_RI);
27534 break;
27538 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27540 uint32_t opc = MASK_MMI3(ctx->opcode);
27542 switch (opc) {
27543 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27544 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27545 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27546 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27547 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27548 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27549 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27550 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27551 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27552 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27553 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27554 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27555 break;
27556 case MMI_OPC_3_PCPYH:
27557 gen_mmi_pcpyh(ctx);
27558 break;
27559 case MMI_OPC_3_PCPYUD:
27560 gen_mmi_pcpyud(ctx);
27561 break;
27562 default:
27563 MIPS_INVAL("TX79 MMI class MMI3");
27564 generate_exception_end(ctx, EXCP_RI);
27565 break;
27569 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27571 uint32_t opc = MASK_MMI(ctx->opcode);
27572 int rs = extract32(ctx->opcode, 21, 5);
27573 int rt = extract32(ctx->opcode, 16, 5);
27574 int rd = extract32(ctx->opcode, 11, 5);
27576 switch (opc) {
27577 case MMI_OPC_CLASS_MMI0:
27578 decode_mmi0(env, ctx);
27579 break;
27580 case MMI_OPC_CLASS_MMI1:
27581 decode_mmi1(env, ctx);
27582 break;
27583 case MMI_OPC_CLASS_MMI2:
27584 decode_mmi2(env, ctx);
27585 break;
27586 case MMI_OPC_CLASS_MMI3:
27587 decode_mmi3(env, ctx);
27588 break;
27589 case MMI_OPC_MULT1:
27590 case MMI_OPC_MULTU1:
27591 case MMI_OPC_MADD:
27592 case MMI_OPC_MADDU:
27593 case MMI_OPC_MADD1:
27594 case MMI_OPC_MADDU1:
27595 gen_mul_txx9(ctx, opc, rd, rs, rt);
27596 break;
27597 case MMI_OPC_DIV1:
27598 case MMI_OPC_DIVU1:
27599 gen_div1_tx79(ctx, opc, rs, rt);
27600 break;
27601 case MMI_OPC_MTLO1:
27602 case MMI_OPC_MTHI1:
27603 gen_HILO1_tx79(ctx, opc, rs);
27604 break;
27605 case MMI_OPC_MFLO1:
27606 case MMI_OPC_MFHI1:
27607 gen_HILO1_tx79(ctx, opc, rd);
27608 break;
27609 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27610 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27611 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27612 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27613 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27614 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27615 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27616 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27617 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27618 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27619 break;
27620 default:
27621 MIPS_INVAL("TX79 MMI class");
27622 generate_exception_end(ctx, EXCP_RI);
27623 break;
27627 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27629 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27632 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27634 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27638 * The TX79-specific instruction Store Quadword
27640 * +--------+-------+-------+------------------------+
27641 * | 011111 | base | rt | offset | SQ
27642 * +--------+-------+-------+------------------------+
27643 * 6 5 5 16
27645 * has the same opcode as the Read Hardware Register instruction
27647 * +--------+-------+-------+-------+-------+--------+
27648 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27649 * +--------+-------+-------+-------+-------+--------+
27650 * 6 5 5 5 5 6
27652 * that is required, trapped and emulated by the Linux kernel. However, all
27653 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27654 * offset is odd. Therefore all valid SQ instructions can execute normally.
27655 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27656 * between SQ and RDHWR, as the Linux kernel does.
27658 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27660 int base = extract32(ctx->opcode, 21, 5);
27661 int rt = extract32(ctx->opcode, 16, 5);
27662 int offset = extract32(ctx->opcode, 0, 16);
27664 #ifdef CONFIG_USER_ONLY
27665 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27666 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27668 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27669 int rd = extract32(ctx->opcode, 11, 5);
27671 gen_rdhwr(ctx, rt, rd, 0);
27672 return;
27674 #endif
27676 gen_mmi_sq(ctx, base, rt, offset);
27679 #endif
27681 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27683 int rs, rt, rd, sa;
27684 uint32_t op1, op2;
27685 int16_t imm;
27687 rs = (ctx->opcode >> 21) & 0x1f;
27688 rt = (ctx->opcode >> 16) & 0x1f;
27689 rd = (ctx->opcode >> 11) & 0x1f;
27690 sa = (ctx->opcode >> 6) & 0x1f;
27691 imm = sextract32(ctx->opcode, 7, 9);
27693 op1 = MASK_SPECIAL3(ctx->opcode);
27696 * EVA loads and stores overlap Loongson 2E instructions decoded by
27697 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27698 * EVA is absent.
27700 if (ctx->eva) {
27701 switch (op1) {
27702 case OPC_LWLE:
27703 case OPC_LWRE:
27704 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27705 /* fall through */
27706 case OPC_LBUE:
27707 case OPC_LHUE:
27708 case OPC_LBE:
27709 case OPC_LHE:
27710 case OPC_LLE:
27711 case OPC_LWE:
27712 check_cp0_enabled(ctx);
27713 gen_ld(ctx, op1, rt, rs, imm);
27714 return;
27715 case OPC_SWLE:
27716 case OPC_SWRE:
27717 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27718 /* fall through */
27719 case OPC_SBE:
27720 case OPC_SHE:
27721 case OPC_SWE:
27722 check_cp0_enabled(ctx);
27723 gen_st(ctx, op1, rt, rs, imm);
27724 return;
27725 case OPC_SCE:
27726 check_cp0_enabled(ctx);
27727 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
27728 return;
27729 case OPC_CACHEE:
27730 check_cp0_enabled(ctx);
27731 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27732 gen_cache_operation(ctx, rt, rs, imm);
27734 /* Treat as NOP. */
27735 return;
27736 case OPC_PREFE:
27737 check_cp0_enabled(ctx);
27738 /* Treat as NOP. */
27739 return;
27743 switch (op1) {
27744 case OPC_EXT:
27745 case OPC_INS:
27746 check_insn(ctx, ISA_MIPS32R2);
27747 gen_bitops(ctx, op1, rt, rs, sa, rd);
27748 break;
27749 case OPC_BSHFL:
27750 op2 = MASK_BSHFL(ctx->opcode);
27751 switch (op2) {
27752 case OPC_ALIGN:
27753 case OPC_ALIGN_1:
27754 case OPC_ALIGN_2:
27755 case OPC_ALIGN_3:
27756 case OPC_BITSWAP:
27757 check_insn(ctx, ISA_MIPS32R6);
27758 decode_opc_special3_r6(env, ctx);
27759 break;
27760 default:
27761 check_insn(ctx, ISA_MIPS32R2);
27762 gen_bshfl(ctx, op2, rt, rd);
27763 break;
27765 break;
27766 #if defined(TARGET_MIPS64)
27767 case OPC_DEXTM:
27768 case OPC_DEXTU:
27769 case OPC_DEXT:
27770 case OPC_DINSM:
27771 case OPC_DINSU:
27772 case OPC_DINS:
27773 check_insn(ctx, ISA_MIPS64R2);
27774 check_mips_64(ctx);
27775 gen_bitops(ctx, op1, rt, rs, sa, rd);
27776 break;
27777 case OPC_DBSHFL:
27778 op2 = MASK_DBSHFL(ctx->opcode);
27779 switch (op2) {
27780 case OPC_DALIGN:
27781 case OPC_DALIGN_1:
27782 case OPC_DALIGN_2:
27783 case OPC_DALIGN_3:
27784 case OPC_DALIGN_4:
27785 case OPC_DALIGN_5:
27786 case OPC_DALIGN_6:
27787 case OPC_DALIGN_7:
27788 case OPC_DBITSWAP:
27789 check_insn(ctx, ISA_MIPS32R6);
27790 decode_opc_special3_r6(env, ctx);
27791 break;
27792 default:
27793 check_insn(ctx, ISA_MIPS64R2);
27794 check_mips_64(ctx);
27795 op2 = MASK_DBSHFL(ctx->opcode);
27796 gen_bshfl(ctx, op2, rt, rd);
27797 break;
27799 break;
27800 #endif
27801 case OPC_RDHWR:
27802 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27803 break;
27804 case OPC_FORK:
27805 check_mt(ctx);
27807 TCGv t0 = tcg_temp_new();
27808 TCGv t1 = tcg_temp_new();
27810 gen_load_gpr(t0, rt);
27811 gen_load_gpr(t1, rs);
27812 gen_helper_fork(t0, t1);
27813 tcg_temp_free(t0);
27814 tcg_temp_free(t1);
27816 break;
27817 case OPC_YIELD:
27818 check_mt(ctx);
27820 TCGv t0 = tcg_temp_new();
27822 gen_load_gpr(t0, rs);
27823 gen_helper_yield(t0, cpu_env, t0);
27824 gen_store_gpr(t0, rd);
27825 tcg_temp_free(t0);
27827 break;
27828 default:
27829 if (ctx->insn_flags & ISA_MIPS32R6) {
27830 decode_opc_special3_r6(env, ctx);
27831 } else {
27832 decode_opc_special3_legacy(env, ctx);
27837 /* MIPS SIMD Architecture (MSA) */
27838 static inline int check_msa_access(DisasContext *ctx)
27840 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
27841 !(ctx->hflags & MIPS_HFLAG_F64))) {
27842 generate_exception_end(ctx, EXCP_RI);
27843 return 0;
27846 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
27847 if (ctx->insn_flags & ASE_MSA) {
27848 generate_exception_end(ctx, EXCP_MSADIS);
27849 return 0;
27850 } else {
27851 generate_exception_end(ctx, EXCP_RI);
27852 return 0;
27855 return 1;
27858 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
27860 /* generates tcg ops to check if any element is 0 */
27861 /* Note this function only works with MSA_WRLEN = 128 */
27862 uint64_t eval_zero_or_big = 0;
27863 uint64_t eval_big = 0;
27864 TCGv_i64 t0 = tcg_temp_new_i64();
27865 TCGv_i64 t1 = tcg_temp_new_i64();
27866 switch (df) {
27867 case DF_BYTE:
27868 eval_zero_or_big = 0x0101010101010101ULL;
27869 eval_big = 0x8080808080808080ULL;
27870 break;
27871 case DF_HALF:
27872 eval_zero_or_big = 0x0001000100010001ULL;
27873 eval_big = 0x8000800080008000ULL;
27874 break;
27875 case DF_WORD:
27876 eval_zero_or_big = 0x0000000100000001ULL;
27877 eval_big = 0x8000000080000000ULL;
27878 break;
27879 case DF_DOUBLE:
27880 eval_zero_or_big = 0x0000000000000001ULL;
27881 eval_big = 0x8000000000000000ULL;
27882 break;
27884 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
27885 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
27886 tcg_gen_andi_i64(t0, t0, eval_big);
27887 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
27888 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
27889 tcg_gen_andi_i64(t1, t1, eval_big);
27890 tcg_gen_or_i64(t0, t0, t1);
27891 /* if all bits are zero then all elements are not zero */
27892 /* if some bit is non-zero then some element is zero */
27893 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
27894 tcg_gen_trunc_i64_tl(tresult, t0);
27895 tcg_temp_free_i64(t0);
27896 tcg_temp_free_i64(t1);
27899 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
27901 uint8_t df = (ctx->opcode >> 21) & 0x3;
27902 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27903 int64_t s16 = (int16_t)ctx->opcode;
27905 check_msa_access(ctx);
27907 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27908 generate_exception_end(ctx, EXCP_RI);
27909 return;
27911 switch (op1) {
27912 case OPC_BZ_V:
27913 case OPC_BNZ_V:
27915 TCGv_i64 t0 = tcg_temp_new_i64();
27916 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
27917 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
27918 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
27919 tcg_gen_trunc_i64_tl(bcond, t0);
27920 tcg_temp_free_i64(t0);
27922 break;
27923 case OPC_BZ_B:
27924 case OPC_BZ_H:
27925 case OPC_BZ_W:
27926 case OPC_BZ_D:
27927 gen_check_zero_element(bcond, df, wt);
27928 break;
27929 case OPC_BNZ_B:
27930 case OPC_BNZ_H:
27931 case OPC_BNZ_W:
27932 case OPC_BNZ_D:
27933 gen_check_zero_element(bcond, df, wt);
27934 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
27935 break;
27938 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
27940 ctx->hflags |= MIPS_HFLAG_BC;
27941 ctx->hflags |= MIPS_HFLAG_BDS32;
27944 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
27946 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
27947 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
27948 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27949 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27951 TCGv_i32 twd = tcg_const_i32(wd);
27952 TCGv_i32 tws = tcg_const_i32(ws);
27953 TCGv_i32 ti8 = tcg_const_i32(i8);
27955 switch (MASK_MSA_I8(ctx->opcode)) {
27956 case OPC_ANDI_B:
27957 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
27958 break;
27959 case OPC_ORI_B:
27960 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
27961 break;
27962 case OPC_NORI_B:
27963 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
27964 break;
27965 case OPC_XORI_B:
27966 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
27967 break;
27968 case OPC_BMNZI_B:
27969 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
27970 break;
27971 case OPC_BMZI_B:
27972 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
27973 break;
27974 case OPC_BSELI_B:
27975 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
27976 break;
27977 case OPC_SHF_B:
27978 case OPC_SHF_H:
27979 case OPC_SHF_W:
27981 uint8_t df = (ctx->opcode >> 24) & 0x3;
27982 if (df == DF_DOUBLE) {
27983 generate_exception_end(ctx, EXCP_RI);
27984 } else {
27985 TCGv_i32 tdf = tcg_const_i32(df);
27986 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
27987 tcg_temp_free_i32(tdf);
27990 break;
27991 default:
27992 MIPS_INVAL("MSA instruction");
27993 generate_exception_end(ctx, EXCP_RI);
27994 break;
27997 tcg_temp_free_i32(twd);
27998 tcg_temp_free_i32(tws);
27999 tcg_temp_free_i32(ti8);
28002 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28004 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28005 uint8_t df = (ctx->opcode >> 21) & 0x3;
28006 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28007 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28008 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28009 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28011 TCGv_i32 tdf = tcg_const_i32(df);
28012 TCGv_i32 twd = tcg_const_i32(wd);
28013 TCGv_i32 tws = tcg_const_i32(ws);
28014 TCGv_i32 timm = tcg_temp_new_i32();
28015 tcg_gen_movi_i32(timm, u5);
28017 switch (MASK_MSA_I5(ctx->opcode)) {
28018 case OPC_ADDVI_df:
28019 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28020 break;
28021 case OPC_SUBVI_df:
28022 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28023 break;
28024 case OPC_MAXI_S_df:
28025 tcg_gen_movi_i32(timm, s5);
28026 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28027 break;
28028 case OPC_MAXI_U_df:
28029 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28030 break;
28031 case OPC_MINI_S_df:
28032 tcg_gen_movi_i32(timm, s5);
28033 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28034 break;
28035 case OPC_MINI_U_df:
28036 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28037 break;
28038 case OPC_CEQI_df:
28039 tcg_gen_movi_i32(timm, s5);
28040 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28041 break;
28042 case OPC_CLTI_S_df:
28043 tcg_gen_movi_i32(timm, s5);
28044 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28045 break;
28046 case OPC_CLTI_U_df:
28047 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28048 break;
28049 case OPC_CLEI_S_df:
28050 tcg_gen_movi_i32(timm, s5);
28051 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28052 break;
28053 case OPC_CLEI_U_df:
28054 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28055 break;
28056 case OPC_LDI_df:
28058 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28059 tcg_gen_movi_i32(timm, s10);
28060 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28062 break;
28063 default:
28064 MIPS_INVAL("MSA instruction");
28065 generate_exception_end(ctx, EXCP_RI);
28066 break;
28069 tcg_temp_free_i32(tdf);
28070 tcg_temp_free_i32(twd);
28071 tcg_temp_free_i32(tws);
28072 tcg_temp_free_i32(timm);
28075 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28077 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28078 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28079 uint32_t df = 0, m = 0;
28080 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28081 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28083 TCGv_i32 tdf;
28084 TCGv_i32 tm;
28085 TCGv_i32 twd;
28086 TCGv_i32 tws;
28088 if ((dfm & 0x40) == 0x00) {
28089 m = dfm & 0x3f;
28090 df = DF_DOUBLE;
28091 } else if ((dfm & 0x60) == 0x40) {
28092 m = dfm & 0x1f;
28093 df = DF_WORD;
28094 } else if ((dfm & 0x70) == 0x60) {
28095 m = dfm & 0x0f;
28096 df = DF_HALF;
28097 } else if ((dfm & 0x78) == 0x70) {
28098 m = dfm & 0x7;
28099 df = DF_BYTE;
28100 } else {
28101 generate_exception_end(ctx, EXCP_RI);
28102 return;
28105 tdf = tcg_const_i32(df);
28106 tm = tcg_const_i32(m);
28107 twd = tcg_const_i32(wd);
28108 tws = tcg_const_i32(ws);
28110 switch (MASK_MSA_BIT(ctx->opcode)) {
28111 case OPC_SLLI_df:
28112 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28113 break;
28114 case OPC_SRAI_df:
28115 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28116 break;
28117 case OPC_SRLI_df:
28118 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28119 break;
28120 case OPC_BCLRI_df:
28121 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28122 break;
28123 case OPC_BSETI_df:
28124 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28125 break;
28126 case OPC_BNEGI_df:
28127 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28128 break;
28129 case OPC_BINSLI_df:
28130 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28131 break;
28132 case OPC_BINSRI_df:
28133 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28134 break;
28135 case OPC_SAT_S_df:
28136 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28137 break;
28138 case OPC_SAT_U_df:
28139 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28140 break;
28141 case OPC_SRARI_df:
28142 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28143 break;
28144 case OPC_SRLRI_df:
28145 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28146 break;
28147 default:
28148 MIPS_INVAL("MSA instruction");
28149 generate_exception_end(ctx, EXCP_RI);
28150 break;
28153 tcg_temp_free_i32(tdf);
28154 tcg_temp_free_i32(tm);
28155 tcg_temp_free_i32(twd);
28156 tcg_temp_free_i32(tws);
28159 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28161 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28162 uint8_t df = (ctx->opcode >> 21) & 0x3;
28163 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28164 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28165 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28167 TCGv_i32 tdf = tcg_const_i32(df);
28168 TCGv_i32 twd = tcg_const_i32(wd);
28169 TCGv_i32 tws = tcg_const_i32(ws);
28170 TCGv_i32 twt = tcg_const_i32(wt);
28172 switch (MASK_MSA_3R(ctx->opcode)) {
28173 case OPC_SLL_df:
28174 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28175 break;
28176 case OPC_ADDV_df:
28177 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28178 break;
28179 case OPC_CEQ_df:
28180 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28181 break;
28182 case OPC_ADD_A_df:
28183 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28184 break;
28185 case OPC_SUBS_S_df:
28186 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28187 break;
28188 case OPC_MULV_df:
28189 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28190 break;
28191 case OPC_SLD_df:
28192 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28193 break;
28194 case OPC_VSHF_df:
28195 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28196 break;
28197 case OPC_SRA_df:
28198 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28199 break;
28200 case OPC_SUBV_df:
28201 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28202 break;
28203 case OPC_ADDS_A_df:
28204 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28205 break;
28206 case OPC_SUBS_U_df:
28207 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28208 break;
28209 case OPC_MADDV_df:
28210 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28211 break;
28212 case OPC_SPLAT_df:
28213 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28214 break;
28215 case OPC_SRAR_df:
28216 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28217 break;
28218 case OPC_SRL_df:
28219 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28220 break;
28221 case OPC_MAX_S_df:
28222 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28223 break;
28224 case OPC_CLT_S_df:
28225 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28226 break;
28227 case OPC_ADDS_S_df:
28228 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28229 break;
28230 case OPC_SUBSUS_U_df:
28231 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28232 break;
28233 case OPC_MSUBV_df:
28234 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28235 break;
28236 case OPC_PCKEV_df:
28237 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28238 break;
28239 case OPC_SRLR_df:
28240 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28241 break;
28242 case OPC_BCLR_df:
28243 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28244 break;
28245 case OPC_MAX_U_df:
28246 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28247 break;
28248 case OPC_CLT_U_df:
28249 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28250 break;
28251 case OPC_ADDS_U_df:
28252 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28253 break;
28254 case OPC_SUBSUU_S_df:
28255 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28256 break;
28257 case OPC_PCKOD_df:
28258 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28259 break;
28260 case OPC_BSET_df:
28261 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28262 break;
28263 case OPC_MIN_S_df:
28264 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28265 break;
28266 case OPC_CLE_S_df:
28267 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28268 break;
28269 case OPC_AVE_S_df:
28270 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28271 break;
28272 case OPC_ASUB_S_df:
28273 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28274 break;
28275 case OPC_DIV_S_df:
28276 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28277 break;
28278 case OPC_ILVL_df:
28279 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28280 break;
28281 case OPC_BNEG_df:
28282 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28283 break;
28284 case OPC_MIN_U_df:
28285 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28286 break;
28287 case OPC_CLE_U_df:
28288 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28289 break;
28290 case OPC_AVE_U_df:
28291 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28292 break;
28293 case OPC_ASUB_U_df:
28294 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28295 break;
28296 case OPC_DIV_U_df:
28297 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28298 break;
28299 case OPC_ILVR_df:
28300 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28301 break;
28302 case OPC_BINSL_df:
28303 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28304 break;
28305 case OPC_MAX_A_df:
28306 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28307 break;
28308 case OPC_AVER_S_df:
28309 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28310 break;
28311 case OPC_MOD_S_df:
28312 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28313 break;
28314 case OPC_ILVEV_df:
28315 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28316 break;
28317 case OPC_BINSR_df:
28318 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28319 break;
28320 case OPC_MIN_A_df:
28321 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28322 break;
28323 case OPC_AVER_U_df:
28324 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28325 break;
28326 case OPC_MOD_U_df:
28327 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28328 break;
28329 case OPC_ILVOD_df:
28330 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28331 break;
28333 case OPC_DOTP_S_df:
28334 case OPC_DOTP_U_df:
28335 case OPC_DPADD_S_df:
28336 case OPC_DPADD_U_df:
28337 case OPC_DPSUB_S_df:
28338 case OPC_HADD_S_df:
28339 case OPC_DPSUB_U_df:
28340 case OPC_HADD_U_df:
28341 case OPC_HSUB_S_df:
28342 case OPC_HSUB_U_df:
28343 if (df == DF_BYTE) {
28344 generate_exception_end(ctx, EXCP_RI);
28345 break;
28347 switch (MASK_MSA_3R(ctx->opcode)) {
28348 case OPC_DOTP_S_df:
28349 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28350 break;
28351 case OPC_DOTP_U_df:
28352 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28353 break;
28354 case OPC_DPADD_S_df:
28355 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28356 break;
28357 case OPC_DPADD_U_df:
28358 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28359 break;
28360 case OPC_DPSUB_S_df:
28361 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28362 break;
28363 case OPC_HADD_S_df:
28364 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28365 break;
28366 case OPC_DPSUB_U_df:
28367 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28368 break;
28369 case OPC_HADD_U_df:
28370 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28371 break;
28372 case OPC_HSUB_S_df:
28373 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28374 break;
28375 case OPC_HSUB_U_df:
28376 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28377 break;
28379 break;
28380 default:
28381 MIPS_INVAL("MSA instruction");
28382 generate_exception_end(ctx, EXCP_RI);
28383 break;
28385 tcg_temp_free_i32(twd);
28386 tcg_temp_free_i32(tws);
28387 tcg_temp_free_i32(twt);
28388 tcg_temp_free_i32(tdf);
28391 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28393 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28394 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28395 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28396 TCGv telm = tcg_temp_new();
28397 TCGv_i32 tsr = tcg_const_i32(source);
28398 TCGv_i32 tdt = tcg_const_i32(dest);
28400 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28401 case OPC_CTCMSA:
28402 gen_load_gpr(telm, source);
28403 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28404 break;
28405 case OPC_CFCMSA:
28406 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28407 gen_store_gpr(telm, dest);
28408 break;
28409 case OPC_MOVE_V:
28410 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28411 break;
28412 default:
28413 MIPS_INVAL("MSA instruction");
28414 generate_exception_end(ctx, EXCP_RI);
28415 break;
28418 tcg_temp_free(telm);
28419 tcg_temp_free_i32(tdt);
28420 tcg_temp_free_i32(tsr);
28423 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28424 uint32_t n)
28426 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28427 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28428 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28430 TCGv_i32 tws = tcg_const_i32(ws);
28431 TCGv_i32 twd = tcg_const_i32(wd);
28432 TCGv_i32 tn = tcg_const_i32(n);
28433 TCGv_i32 tdf = tcg_const_i32(df);
28435 switch (MASK_MSA_ELM(ctx->opcode)) {
28436 case OPC_SLDI_df:
28437 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28438 break;
28439 case OPC_SPLATI_df:
28440 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28441 break;
28442 case OPC_INSVE_df:
28443 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28444 break;
28445 case OPC_COPY_S_df:
28446 case OPC_COPY_U_df:
28447 case OPC_INSERT_df:
28448 #if !defined(TARGET_MIPS64)
28449 /* Double format valid only for MIPS64 */
28450 if (df == DF_DOUBLE) {
28451 generate_exception_end(ctx, EXCP_RI);
28452 break;
28454 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
28455 (df == DF_WORD)) {
28456 generate_exception_end(ctx, EXCP_RI);
28457 break;
28459 #endif
28460 switch (MASK_MSA_ELM(ctx->opcode)) {
28461 case OPC_COPY_S_df:
28462 if (likely(wd != 0)) {
28463 switch (df) {
28464 case DF_BYTE:
28465 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
28466 break;
28467 case DF_HALF:
28468 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
28469 break;
28470 case DF_WORD:
28471 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
28472 break;
28473 #if defined(TARGET_MIPS64)
28474 case DF_DOUBLE:
28475 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
28476 break;
28477 #endif
28478 default:
28479 assert(0);
28482 break;
28483 case OPC_COPY_U_df:
28484 if (likely(wd != 0)) {
28485 switch (df) {
28486 case DF_BYTE:
28487 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
28488 break;
28489 case DF_HALF:
28490 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
28491 break;
28492 #if defined(TARGET_MIPS64)
28493 case DF_WORD:
28494 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
28495 break;
28496 #endif
28497 default:
28498 assert(0);
28501 break;
28502 case OPC_INSERT_df:
28503 switch (df) {
28504 case DF_BYTE:
28505 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
28506 break;
28507 case DF_HALF:
28508 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
28509 break;
28510 case DF_WORD:
28511 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
28512 break;
28513 #if defined(TARGET_MIPS64)
28514 case DF_DOUBLE:
28515 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
28516 break;
28517 #endif
28518 default:
28519 assert(0);
28521 break;
28523 break;
28524 default:
28525 MIPS_INVAL("MSA instruction");
28526 generate_exception_end(ctx, EXCP_RI);
28528 tcg_temp_free_i32(twd);
28529 tcg_temp_free_i32(tws);
28530 tcg_temp_free_i32(tn);
28531 tcg_temp_free_i32(tdf);
28534 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28536 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28537 uint32_t df = 0, n = 0;
28539 if ((dfn & 0x30) == 0x00) {
28540 n = dfn & 0x0f;
28541 df = DF_BYTE;
28542 } else if ((dfn & 0x38) == 0x20) {
28543 n = dfn & 0x07;
28544 df = DF_HALF;
28545 } else if ((dfn & 0x3c) == 0x30) {
28546 n = dfn & 0x03;
28547 df = DF_WORD;
28548 } else if ((dfn & 0x3e) == 0x38) {
28549 n = dfn & 0x01;
28550 df = DF_DOUBLE;
28551 } else if (dfn == 0x3E) {
28552 /* CTCMSA, CFCMSA, MOVE.V */
28553 gen_msa_elm_3e(env, ctx);
28554 return;
28555 } else {
28556 generate_exception_end(ctx, EXCP_RI);
28557 return;
28560 gen_msa_elm_df(env, ctx, df, n);
28563 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28565 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28566 uint8_t df = (ctx->opcode >> 21) & 0x1;
28567 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28568 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28569 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28571 TCGv_i32 twd = tcg_const_i32(wd);
28572 TCGv_i32 tws = tcg_const_i32(ws);
28573 TCGv_i32 twt = tcg_const_i32(wt);
28574 TCGv_i32 tdf = tcg_temp_new_i32();
28576 /* adjust df value for floating-point instruction */
28577 tcg_gen_movi_i32(tdf, df + 2);
28579 switch (MASK_MSA_3RF(ctx->opcode)) {
28580 case OPC_FCAF_df:
28581 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28582 break;
28583 case OPC_FADD_df:
28584 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28585 break;
28586 case OPC_FCUN_df:
28587 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28588 break;
28589 case OPC_FSUB_df:
28590 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28591 break;
28592 case OPC_FCOR_df:
28593 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28594 break;
28595 case OPC_FCEQ_df:
28596 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28597 break;
28598 case OPC_FMUL_df:
28599 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28600 break;
28601 case OPC_FCUNE_df:
28602 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28603 break;
28604 case OPC_FCUEQ_df:
28605 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28606 break;
28607 case OPC_FDIV_df:
28608 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28609 break;
28610 case OPC_FCNE_df:
28611 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28612 break;
28613 case OPC_FCLT_df:
28614 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28615 break;
28616 case OPC_FMADD_df:
28617 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28618 break;
28619 case OPC_MUL_Q_df:
28620 tcg_gen_movi_i32(tdf, df + 1);
28621 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28622 break;
28623 case OPC_FCULT_df:
28624 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28625 break;
28626 case OPC_FMSUB_df:
28627 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28628 break;
28629 case OPC_MADD_Q_df:
28630 tcg_gen_movi_i32(tdf, df + 1);
28631 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28632 break;
28633 case OPC_FCLE_df:
28634 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28635 break;
28636 case OPC_MSUB_Q_df:
28637 tcg_gen_movi_i32(tdf, df + 1);
28638 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28639 break;
28640 case OPC_FCULE_df:
28641 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28642 break;
28643 case OPC_FEXP2_df:
28644 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28645 break;
28646 case OPC_FSAF_df:
28647 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28648 break;
28649 case OPC_FEXDO_df:
28650 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28651 break;
28652 case OPC_FSUN_df:
28653 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28654 break;
28655 case OPC_FSOR_df:
28656 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28657 break;
28658 case OPC_FSEQ_df:
28659 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28660 break;
28661 case OPC_FTQ_df:
28662 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28663 break;
28664 case OPC_FSUNE_df:
28665 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28666 break;
28667 case OPC_FSUEQ_df:
28668 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28669 break;
28670 case OPC_FSNE_df:
28671 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28672 break;
28673 case OPC_FSLT_df:
28674 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28675 break;
28676 case OPC_FMIN_df:
28677 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28678 break;
28679 case OPC_MULR_Q_df:
28680 tcg_gen_movi_i32(tdf, df + 1);
28681 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28682 break;
28683 case OPC_FSULT_df:
28684 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28685 break;
28686 case OPC_FMIN_A_df:
28687 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28688 break;
28689 case OPC_MADDR_Q_df:
28690 tcg_gen_movi_i32(tdf, df + 1);
28691 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28692 break;
28693 case OPC_FSLE_df:
28694 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28695 break;
28696 case OPC_FMAX_df:
28697 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28698 break;
28699 case OPC_MSUBR_Q_df:
28700 tcg_gen_movi_i32(tdf, df + 1);
28701 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28702 break;
28703 case OPC_FSULE_df:
28704 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28705 break;
28706 case OPC_FMAX_A_df:
28707 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28708 break;
28709 default:
28710 MIPS_INVAL("MSA instruction");
28711 generate_exception_end(ctx, EXCP_RI);
28712 break;
28715 tcg_temp_free_i32(twd);
28716 tcg_temp_free_i32(tws);
28717 tcg_temp_free_i32(twt);
28718 tcg_temp_free_i32(tdf);
28721 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28723 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28724 (op & (0x7 << 18)))
28725 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28726 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28727 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28728 uint8_t df = (ctx->opcode >> 16) & 0x3;
28729 TCGv_i32 twd = tcg_const_i32(wd);
28730 TCGv_i32 tws = tcg_const_i32(ws);
28731 TCGv_i32 twt = tcg_const_i32(wt);
28732 TCGv_i32 tdf = tcg_const_i32(df);
28734 switch (MASK_MSA_2R(ctx->opcode)) {
28735 case OPC_FILL_df:
28736 #if !defined(TARGET_MIPS64)
28737 /* Double format valid only for MIPS64 */
28738 if (df == DF_DOUBLE) {
28739 generate_exception_end(ctx, EXCP_RI);
28740 break;
28742 #endif
28743 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28744 break;
28745 case OPC_PCNT_df:
28746 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28747 break;
28748 case OPC_NLOC_df:
28749 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28750 break;
28751 case OPC_NLZC_df:
28752 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28753 break;
28754 default:
28755 MIPS_INVAL("MSA instruction");
28756 generate_exception_end(ctx, EXCP_RI);
28757 break;
28760 tcg_temp_free_i32(twd);
28761 tcg_temp_free_i32(tws);
28762 tcg_temp_free_i32(twt);
28763 tcg_temp_free_i32(tdf);
28766 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28768 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28769 (op & (0xf << 17)))
28770 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28771 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28772 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28773 uint8_t df = (ctx->opcode >> 16) & 0x1;
28774 TCGv_i32 twd = tcg_const_i32(wd);
28775 TCGv_i32 tws = tcg_const_i32(ws);
28776 TCGv_i32 twt = tcg_const_i32(wt);
28777 /* adjust df value for floating-point instruction */
28778 TCGv_i32 tdf = tcg_const_i32(df + 2);
28780 switch (MASK_MSA_2RF(ctx->opcode)) {
28781 case OPC_FCLASS_df:
28782 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28783 break;
28784 case OPC_FTRUNC_S_df:
28785 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28786 break;
28787 case OPC_FTRUNC_U_df:
28788 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28789 break;
28790 case OPC_FSQRT_df:
28791 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28792 break;
28793 case OPC_FRSQRT_df:
28794 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28795 break;
28796 case OPC_FRCP_df:
28797 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28798 break;
28799 case OPC_FRINT_df:
28800 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28801 break;
28802 case OPC_FLOG2_df:
28803 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28804 break;
28805 case OPC_FEXUPL_df:
28806 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28807 break;
28808 case OPC_FEXUPR_df:
28809 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28810 break;
28811 case OPC_FFQL_df:
28812 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28813 break;
28814 case OPC_FFQR_df:
28815 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28816 break;
28817 case OPC_FTINT_S_df:
28818 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28819 break;
28820 case OPC_FTINT_U_df:
28821 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
28822 break;
28823 case OPC_FFINT_S_df:
28824 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
28825 break;
28826 case OPC_FFINT_U_df:
28827 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
28828 break;
28831 tcg_temp_free_i32(twd);
28832 tcg_temp_free_i32(tws);
28833 tcg_temp_free_i32(twt);
28834 tcg_temp_free_i32(tdf);
28837 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
28839 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
28840 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28841 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28842 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28843 TCGv_i32 twd = tcg_const_i32(wd);
28844 TCGv_i32 tws = tcg_const_i32(ws);
28845 TCGv_i32 twt = tcg_const_i32(wt);
28847 switch (MASK_MSA_VEC(ctx->opcode)) {
28848 case OPC_AND_V:
28849 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
28850 break;
28851 case OPC_OR_V:
28852 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
28853 break;
28854 case OPC_NOR_V:
28855 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
28856 break;
28857 case OPC_XOR_V:
28858 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
28859 break;
28860 case OPC_BMNZ_V:
28861 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
28862 break;
28863 case OPC_BMZ_V:
28864 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
28865 break;
28866 case OPC_BSEL_V:
28867 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
28868 break;
28869 default:
28870 MIPS_INVAL("MSA instruction");
28871 generate_exception_end(ctx, EXCP_RI);
28872 break;
28875 tcg_temp_free_i32(twd);
28876 tcg_temp_free_i32(tws);
28877 tcg_temp_free_i32(twt);
28880 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
28882 switch (MASK_MSA_VEC(ctx->opcode)) {
28883 case OPC_AND_V:
28884 case OPC_OR_V:
28885 case OPC_NOR_V:
28886 case OPC_XOR_V:
28887 case OPC_BMNZ_V:
28888 case OPC_BMZ_V:
28889 case OPC_BSEL_V:
28890 gen_msa_vec_v(env, ctx);
28891 break;
28892 case OPC_MSA_2R:
28893 gen_msa_2r(env, ctx);
28894 break;
28895 case OPC_MSA_2RF:
28896 gen_msa_2rf(env, ctx);
28897 break;
28898 default:
28899 MIPS_INVAL("MSA instruction");
28900 generate_exception_end(ctx, EXCP_RI);
28901 break;
28905 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
28907 uint32_t opcode = ctx->opcode;
28908 check_insn(ctx, ASE_MSA);
28909 check_msa_access(ctx);
28911 switch (MASK_MSA_MINOR(opcode)) {
28912 case OPC_MSA_I8_00:
28913 case OPC_MSA_I8_01:
28914 case OPC_MSA_I8_02:
28915 gen_msa_i8(env, ctx);
28916 break;
28917 case OPC_MSA_I5_06:
28918 case OPC_MSA_I5_07:
28919 gen_msa_i5(env, ctx);
28920 break;
28921 case OPC_MSA_BIT_09:
28922 case OPC_MSA_BIT_0A:
28923 gen_msa_bit(env, ctx);
28924 break;
28925 case OPC_MSA_3R_0D:
28926 case OPC_MSA_3R_0E:
28927 case OPC_MSA_3R_0F:
28928 case OPC_MSA_3R_10:
28929 case OPC_MSA_3R_11:
28930 case OPC_MSA_3R_12:
28931 case OPC_MSA_3R_13:
28932 case OPC_MSA_3R_14:
28933 case OPC_MSA_3R_15:
28934 gen_msa_3r(env, ctx);
28935 break;
28936 case OPC_MSA_ELM:
28937 gen_msa_elm(env, ctx);
28938 break;
28939 case OPC_MSA_3RF_1A:
28940 case OPC_MSA_3RF_1B:
28941 case OPC_MSA_3RF_1C:
28942 gen_msa_3rf(env, ctx);
28943 break;
28944 case OPC_MSA_VEC:
28945 gen_msa_vec(env, ctx);
28946 break;
28947 case OPC_LD_B:
28948 case OPC_LD_H:
28949 case OPC_LD_W:
28950 case OPC_LD_D:
28951 case OPC_ST_B:
28952 case OPC_ST_H:
28953 case OPC_ST_W:
28954 case OPC_ST_D:
28956 int32_t s10 = sextract32(ctx->opcode, 16, 10);
28957 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
28958 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28959 uint8_t df = (ctx->opcode >> 0) & 0x3;
28961 TCGv_i32 twd = tcg_const_i32(wd);
28962 TCGv taddr = tcg_temp_new();
28963 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
28965 switch (MASK_MSA_MINOR(opcode)) {
28966 case OPC_LD_B:
28967 gen_helper_msa_ld_b(cpu_env, twd, taddr);
28968 break;
28969 case OPC_LD_H:
28970 gen_helper_msa_ld_h(cpu_env, twd, taddr);
28971 break;
28972 case OPC_LD_W:
28973 gen_helper_msa_ld_w(cpu_env, twd, taddr);
28974 break;
28975 case OPC_LD_D:
28976 gen_helper_msa_ld_d(cpu_env, twd, taddr);
28977 break;
28978 case OPC_ST_B:
28979 gen_helper_msa_st_b(cpu_env, twd, taddr);
28980 break;
28981 case OPC_ST_H:
28982 gen_helper_msa_st_h(cpu_env, twd, taddr);
28983 break;
28984 case OPC_ST_W:
28985 gen_helper_msa_st_w(cpu_env, twd, taddr);
28986 break;
28987 case OPC_ST_D:
28988 gen_helper_msa_st_d(cpu_env, twd, taddr);
28989 break;
28992 tcg_temp_free_i32(twd);
28993 tcg_temp_free(taddr);
28995 break;
28996 default:
28997 MIPS_INVAL("MSA instruction");
28998 generate_exception_end(ctx, EXCP_RI);
28999 break;
29004 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
29006 int32_t offset;
29007 int rs, rt, rd, sa;
29008 uint32_t op, op1;
29009 int16_t imm;
29011 /* make sure instructions are on a word boundary */
29012 if (ctx->base.pc_next & 0x3) {
29013 env->CP0_BadVAddr = ctx->base.pc_next;
29014 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
29015 return;
29018 /* Handle blikely not taken case */
29019 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
29020 TCGLabel *l1 = gen_new_label();
29022 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29023 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
29024 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
29025 gen_set_label(l1);
29028 op = MASK_OP_MAJOR(ctx->opcode);
29029 rs = (ctx->opcode >> 21) & 0x1f;
29030 rt = (ctx->opcode >> 16) & 0x1f;
29031 rd = (ctx->opcode >> 11) & 0x1f;
29032 sa = (ctx->opcode >> 6) & 0x1f;
29033 imm = (int16_t)ctx->opcode;
29034 switch (op) {
29035 case OPC_SPECIAL:
29036 decode_opc_special(env, ctx);
29037 break;
29038 case OPC_SPECIAL2:
29039 #if defined(TARGET_MIPS64)
29040 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
29041 decode_mmi(env, ctx);
29042 #else
29043 if (ctx->insn_flags & ASE_MXU) {
29044 decode_opc_mxu(env, ctx);
29045 #endif
29046 } else {
29047 decode_opc_special2_legacy(env, ctx);
29049 break;
29050 case OPC_SPECIAL3:
29051 #if defined(TARGET_MIPS64)
29052 if (ctx->insn_flags & INSN_R5900) {
29053 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
29054 } else {
29055 decode_opc_special3(env, ctx);
29057 #else
29058 decode_opc_special3(env, ctx);
29059 #endif
29060 break;
29061 case OPC_REGIMM:
29062 op1 = MASK_REGIMM(ctx->opcode);
29063 switch (op1) {
29064 case OPC_BLTZL: /* REGIMM branches */
29065 case OPC_BGEZL:
29066 case OPC_BLTZALL:
29067 case OPC_BGEZALL:
29068 check_insn(ctx, ISA_MIPS2);
29069 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29070 /* Fallthrough */
29071 case OPC_BLTZ:
29072 case OPC_BGEZ:
29073 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29074 break;
29075 case OPC_BLTZAL:
29076 case OPC_BGEZAL:
29077 if (ctx->insn_flags & ISA_MIPS32R6) {
29078 if (rs == 0) {
29079 /* OPC_NAL, OPC_BAL */
29080 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
29081 } else {
29082 generate_exception_end(ctx, EXCP_RI);
29084 } else {
29085 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29087 break;
29088 case OPC_TGEI: /* REGIMM traps */
29089 case OPC_TGEIU:
29090 case OPC_TLTI:
29091 case OPC_TLTIU:
29092 case OPC_TEQI:
29094 case OPC_TNEI:
29095 check_insn(ctx, ISA_MIPS2);
29096 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29097 gen_trap(ctx, op1, rs, -1, imm);
29098 break;
29099 case OPC_SIGRIE:
29100 check_insn(ctx, ISA_MIPS32R6);
29101 generate_exception_end(ctx, EXCP_RI);
29102 break;
29103 case OPC_SYNCI:
29104 check_insn(ctx, ISA_MIPS32R2);
29105 /* Break the TB to be able to sync copied instructions
29106 immediately */
29107 ctx->base.is_jmp = DISAS_STOP;
29108 break;
29109 case OPC_BPOSGE32: /* MIPS DSP branch */
29110 #if defined(TARGET_MIPS64)
29111 case OPC_BPOSGE64:
29112 #endif
29113 check_dsp(ctx);
29114 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
29115 break;
29116 #if defined(TARGET_MIPS64)
29117 case OPC_DAHI:
29118 check_insn(ctx, ISA_MIPS32R6);
29119 check_mips_64(ctx);
29120 if (rs != 0) {
29121 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
29123 break;
29124 case OPC_DATI:
29125 check_insn(ctx, ISA_MIPS32R6);
29126 check_mips_64(ctx);
29127 if (rs != 0) {
29128 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
29130 break;
29131 #endif
29132 default: /* Invalid */
29133 MIPS_INVAL("regimm");
29134 generate_exception_end(ctx, EXCP_RI);
29135 break;
29137 break;
29138 case OPC_CP0:
29139 check_cp0_enabled(ctx);
29140 op1 = MASK_CP0(ctx->opcode);
29141 switch (op1) {
29142 case OPC_MFC0:
29143 case OPC_MTC0:
29144 case OPC_MFTR:
29145 case OPC_MTTR:
29146 case OPC_MFHC0:
29147 case OPC_MTHC0:
29148 #if defined(TARGET_MIPS64)
29149 case OPC_DMFC0:
29150 case OPC_DMTC0:
29151 #endif
29152 #ifndef CONFIG_USER_ONLY
29153 gen_cp0(env, ctx, op1, rt, rd);
29154 #endif /* !CONFIG_USER_ONLY */
29155 break;
29156 case OPC_C0:
29157 case OPC_C0_1:
29158 case OPC_C0_2:
29159 case OPC_C0_3:
29160 case OPC_C0_4:
29161 case OPC_C0_5:
29162 case OPC_C0_6:
29163 case OPC_C0_7:
29164 case OPC_C0_8:
29165 case OPC_C0_9:
29166 case OPC_C0_A:
29167 case OPC_C0_B:
29168 case OPC_C0_C:
29169 case OPC_C0_D:
29170 case OPC_C0_E:
29171 case OPC_C0_F:
29172 #ifndef CONFIG_USER_ONLY
29173 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
29174 #endif /* !CONFIG_USER_ONLY */
29175 break;
29176 case OPC_MFMC0:
29177 #ifndef CONFIG_USER_ONLY
29179 uint32_t op2;
29180 TCGv t0 = tcg_temp_new();
29182 op2 = MASK_MFMC0(ctx->opcode);
29183 switch (op2) {
29184 case OPC_DMT:
29185 check_cp0_mt(ctx);
29186 gen_helper_dmt(t0);
29187 gen_store_gpr(t0, rt);
29188 break;
29189 case OPC_EMT:
29190 check_cp0_mt(ctx);
29191 gen_helper_emt(t0);
29192 gen_store_gpr(t0, rt);
29193 break;
29194 case OPC_DVPE:
29195 check_cp0_mt(ctx);
29196 gen_helper_dvpe(t0, cpu_env);
29197 gen_store_gpr(t0, rt);
29198 break;
29199 case OPC_EVPE:
29200 check_cp0_mt(ctx);
29201 gen_helper_evpe(t0, cpu_env);
29202 gen_store_gpr(t0, rt);
29203 break;
29204 case OPC_DVP:
29205 check_insn(ctx, ISA_MIPS32R6);
29206 if (ctx->vp) {
29207 gen_helper_dvp(t0, cpu_env);
29208 gen_store_gpr(t0, rt);
29210 break;
29211 case OPC_EVP:
29212 check_insn(ctx, ISA_MIPS32R6);
29213 if (ctx->vp) {
29214 gen_helper_evp(t0, cpu_env);
29215 gen_store_gpr(t0, rt);
29217 break;
29218 case OPC_DI:
29219 check_insn(ctx, ISA_MIPS32R2);
29220 save_cpu_state(ctx, 1);
29221 gen_helper_di(t0, cpu_env);
29222 gen_store_gpr(t0, rt);
29223 /* Stop translation as we may have switched
29224 the execution mode. */
29225 ctx->base.is_jmp = DISAS_STOP;
29226 break;
29227 case OPC_EI:
29228 check_insn(ctx, ISA_MIPS32R2);
29229 save_cpu_state(ctx, 1);
29230 gen_helper_ei(t0, cpu_env);
29231 gen_store_gpr(t0, rt);
29232 /* DISAS_STOP isn't sufficient, we need to ensure we break
29233 out of translated code to check for pending interrupts */
29234 gen_save_pc(ctx->base.pc_next + 4);
29235 ctx->base.is_jmp = DISAS_EXIT;
29236 break;
29237 default: /* Invalid */
29238 MIPS_INVAL("mfmc0");
29239 generate_exception_end(ctx, EXCP_RI);
29240 break;
29242 tcg_temp_free(t0);
29244 #endif /* !CONFIG_USER_ONLY */
29245 break;
29246 case OPC_RDPGPR:
29247 check_insn(ctx, ISA_MIPS32R2);
29248 gen_load_srsgpr(rt, rd);
29249 break;
29250 case OPC_WRPGPR:
29251 check_insn(ctx, ISA_MIPS32R2);
29252 gen_store_srsgpr(rt, rd);
29253 break;
29254 default:
29255 MIPS_INVAL("cp0");
29256 generate_exception_end(ctx, EXCP_RI);
29257 break;
29259 break;
29260 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29261 if (ctx->insn_flags & ISA_MIPS32R6) {
29262 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29263 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29264 } else {
29265 /* OPC_ADDI */
29266 /* Arithmetic with immediate opcode */
29267 gen_arith_imm(ctx, op, rt, rs, imm);
29269 break;
29270 case OPC_ADDIU:
29271 gen_arith_imm(ctx, op, rt, rs, imm);
29272 break;
29273 case OPC_SLTI: /* Set on less than with immediate opcode */
29274 case OPC_SLTIU:
29275 gen_slt_imm(ctx, op, rt, rs, imm);
29276 break;
29277 case OPC_ANDI: /* Arithmetic with immediate opcode */
29278 case OPC_LUI: /* OPC_AUI */
29279 case OPC_ORI:
29280 case OPC_XORI:
29281 gen_logic_imm(ctx, op, rt, rs, imm);
29282 break;
29283 case OPC_J: /* Jump */
29284 case OPC_JAL:
29285 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29286 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29287 break;
29288 /* Branch */
29289 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29290 if (ctx->insn_flags & ISA_MIPS32R6) {
29291 if (rt == 0) {
29292 generate_exception_end(ctx, EXCP_RI);
29293 break;
29295 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29296 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29297 } else {
29298 /* OPC_BLEZL */
29299 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29301 break;
29302 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29303 if (ctx->insn_flags & ISA_MIPS32R6) {
29304 if (rt == 0) {
29305 generate_exception_end(ctx, EXCP_RI);
29306 break;
29308 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29309 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29310 } else {
29311 /* OPC_BGTZL */
29312 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29314 break;
29315 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29316 if (rt == 0) {
29317 /* OPC_BLEZ */
29318 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29319 } else {
29320 check_insn(ctx, ISA_MIPS32R6);
29321 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29322 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29324 break;
29325 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29326 if (rt == 0) {
29327 /* OPC_BGTZ */
29328 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29329 } else {
29330 check_insn(ctx, ISA_MIPS32R6);
29331 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29332 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29334 break;
29335 case OPC_BEQL:
29336 case OPC_BNEL:
29337 check_insn(ctx, ISA_MIPS2);
29338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29339 /* Fallthrough */
29340 case OPC_BEQ:
29341 case OPC_BNE:
29342 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29343 break;
29344 case OPC_LL: /* Load and stores */
29345 check_insn(ctx, ISA_MIPS2);
29346 if (ctx->insn_flags & INSN_R5900) {
29347 check_insn_opc_user_only(ctx, INSN_R5900);
29349 /* Fallthrough */
29350 case OPC_LWL:
29351 case OPC_LWR:
29352 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29353 /* Fallthrough */
29354 case OPC_LB:
29355 case OPC_LH:
29356 case OPC_LW:
29357 case OPC_LWPC:
29358 case OPC_LBU:
29359 case OPC_LHU:
29360 gen_ld(ctx, op, rt, rs, imm);
29361 break;
29362 case OPC_SWL:
29363 case OPC_SWR:
29364 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29365 /* fall through */
29366 case OPC_SB:
29367 case OPC_SH:
29368 case OPC_SW:
29369 gen_st(ctx, op, rt, rs, imm);
29370 break;
29371 case OPC_SC:
29372 check_insn(ctx, ISA_MIPS2);
29373 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29374 if (ctx->insn_flags & INSN_R5900) {
29375 check_insn_opc_user_only(ctx, INSN_R5900);
29377 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29378 break;
29379 case OPC_CACHE:
29380 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29381 check_cp0_enabled(ctx);
29382 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29383 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29384 gen_cache_operation(ctx, rt, rs, imm);
29386 /* Treat as NOP. */
29387 break;
29388 case OPC_PREF:
29389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29390 if (ctx->insn_flags & INSN_R5900) {
29391 /* Treat as NOP. */
29392 } else {
29393 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29394 /* Treat as NOP. */
29396 break;
29398 /* Floating point (COP1). */
29399 case OPC_LWC1:
29400 case OPC_LDC1:
29401 case OPC_SWC1:
29402 case OPC_SDC1:
29403 gen_cop1_ldst(ctx, op, rt, rs, imm);
29404 break;
29406 case OPC_CP1:
29407 op1 = MASK_CP1(ctx->opcode);
29409 switch (op1) {
29410 case OPC_MFHC1:
29411 case OPC_MTHC1:
29412 check_cp1_enabled(ctx);
29413 check_insn(ctx, ISA_MIPS32R2);
29414 /* fall through */
29415 case OPC_MFC1:
29416 case OPC_CFC1:
29417 case OPC_MTC1:
29418 case OPC_CTC1:
29419 check_cp1_enabled(ctx);
29420 gen_cp1(ctx, op1, rt, rd);
29421 break;
29422 #if defined(TARGET_MIPS64)
29423 case OPC_DMFC1:
29424 case OPC_DMTC1:
29425 check_cp1_enabled(ctx);
29426 check_insn(ctx, ISA_MIPS3);
29427 check_mips_64(ctx);
29428 gen_cp1(ctx, op1, rt, rd);
29429 break;
29430 #endif
29431 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29432 check_cp1_enabled(ctx);
29433 if (ctx->insn_flags & ISA_MIPS32R6) {
29434 /* OPC_BC1EQZ */
29435 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29436 rt, imm << 2, 4);
29437 } else {
29438 /* OPC_BC1ANY2 */
29439 check_cop1x(ctx);
29440 check_insn(ctx, ASE_MIPS3D);
29441 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29442 (rt >> 2) & 0x7, imm << 2);
29444 break;
29445 case OPC_BC1NEZ:
29446 check_cp1_enabled(ctx);
29447 check_insn(ctx, ISA_MIPS32R6);
29448 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29449 rt, imm << 2, 4);
29450 break;
29451 case OPC_BC1ANY4:
29452 check_cp1_enabled(ctx);
29453 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29454 check_cop1x(ctx);
29455 check_insn(ctx, ASE_MIPS3D);
29456 /* fall through */
29457 case OPC_BC1:
29458 check_cp1_enabled(ctx);
29459 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29460 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29461 (rt >> 2) & 0x7, imm << 2);
29462 break;
29463 case OPC_PS_FMT:
29464 check_ps(ctx);
29465 /* fall through */
29466 case OPC_S_FMT:
29467 case OPC_D_FMT:
29468 check_cp1_enabled(ctx);
29469 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29470 (imm >> 8) & 0x7);
29471 break;
29472 case OPC_W_FMT:
29473 case OPC_L_FMT:
29475 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29476 check_cp1_enabled(ctx);
29477 if (ctx->insn_flags & ISA_MIPS32R6) {
29478 switch (r6_op) {
29479 case R6_OPC_CMP_AF_S:
29480 case R6_OPC_CMP_UN_S:
29481 case R6_OPC_CMP_EQ_S:
29482 case R6_OPC_CMP_UEQ_S:
29483 case R6_OPC_CMP_LT_S:
29484 case R6_OPC_CMP_ULT_S:
29485 case R6_OPC_CMP_LE_S:
29486 case R6_OPC_CMP_ULE_S:
29487 case R6_OPC_CMP_SAF_S:
29488 case R6_OPC_CMP_SUN_S:
29489 case R6_OPC_CMP_SEQ_S:
29490 case R6_OPC_CMP_SEUQ_S:
29491 case R6_OPC_CMP_SLT_S:
29492 case R6_OPC_CMP_SULT_S:
29493 case R6_OPC_CMP_SLE_S:
29494 case R6_OPC_CMP_SULE_S:
29495 case R6_OPC_CMP_OR_S:
29496 case R6_OPC_CMP_UNE_S:
29497 case R6_OPC_CMP_NE_S:
29498 case R6_OPC_CMP_SOR_S:
29499 case R6_OPC_CMP_SUNE_S:
29500 case R6_OPC_CMP_SNE_S:
29501 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29502 break;
29503 case R6_OPC_CMP_AF_D:
29504 case R6_OPC_CMP_UN_D:
29505 case R6_OPC_CMP_EQ_D:
29506 case R6_OPC_CMP_UEQ_D:
29507 case R6_OPC_CMP_LT_D:
29508 case R6_OPC_CMP_ULT_D:
29509 case R6_OPC_CMP_LE_D:
29510 case R6_OPC_CMP_ULE_D:
29511 case R6_OPC_CMP_SAF_D:
29512 case R6_OPC_CMP_SUN_D:
29513 case R6_OPC_CMP_SEQ_D:
29514 case R6_OPC_CMP_SEUQ_D:
29515 case R6_OPC_CMP_SLT_D:
29516 case R6_OPC_CMP_SULT_D:
29517 case R6_OPC_CMP_SLE_D:
29518 case R6_OPC_CMP_SULE_D:
29519 case R6_OPC_CMP_OR_D:
29520 case R6_OPC_CMP_UNE_D:
29521 case R6_OPC_CMP_NE_D:
29522 case R6_OPC_CMP_SOR_D:
29523 case R6_OPC_CMP_SUNE_D:
29524 case R6_OPC_CMP_SNE_D:
29525 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29526 break;
29527 default:
29528 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29529 rt, rd, sa, (imm >> 8) & 0x7);
29531 break;
29533 } else {
29534 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29535 (imm >> 8) & 0x7);
29537 break;
29539 case OPC_BZ_V:
29540 case OPC_BNZ_V:
29541 case OPC_BZ_B:
29542 case OPC_BZ_H:
29543 case OPC_BZ_W:
29544 case OPC_BZ_D:
29545 case OPC_BNZ_B:
29546 case OPC_BNZ_H:
29547 case OPC_BNZ_W:
29548 case OPC_BNZ_D:
29549 check_insn(ctx, ASE_MSA);
29550 gen_msa_branch(env, ctx, op1);
29551 break;
29552 default:
29553 MIPS_INVAL("cp1");
29554 generate_exception_end(ctx, EXCP_RI);
29555 break;
29557 break;
29559 /* Compact branches [R6] and COP2 [non-R6] */
29560 case OPC_BC: /* OPC_LWC2 */
29561 case OPC_BALC: /* OPC_SWC2 */
29562 if (ctx->insn_flags & ISA_MIPS32R6) {
29563 /* OPC_BC, OPC_BALC */
29564 gen_compute_compact_branch(ctx, op, 0, 0,
29565 sextract32(ctx->opcode << 2, 0, 28));
29566 } else {
29567 /* OPC_LWC2, OPC_SWC2 */
29568 /* COP2: Not implemented. */
29569 generate_exception_err(ctx, EXCP_CpU, 2);
29571 break;
29572 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29573 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29574 if (ctx->insn_flags & ISA_MIPS32R6) {
29575 if (rs != 0) {
29576 /* OPC_BEQZC, OPC_BNEZC */
29577 gen_compute_compact_branch(ctx, op, rs, 0,
29578 sextract32(ctx->opcode << 2, 0, 23));
29579 } else {
29580 /* OPC_JIC, OPC_JIALC */
29581 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29583 } else {
29584 /* OPC_LWC2, OPC_SWC2 */
29585 /* COP2: Not implemented. */
29586 generate_exception_err(ctx, EXCP_CpU, 2);
29588 break;
29589 case OPC_CP2:
29590 check_insn(ctx, INSN_LOONGSON2F);
29591 /* Note that these instructions use different fields. */
29592 gen_loongson_multimedia(ctx, sa, rd, rt);
29593 break;
29595 case OPC_CP3:
29596 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29597 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29598 check_cp1_enabled(ctx);
29599 op1 = MASK_CP3(ctx->opcode);
29600 switch (op1) {
29601 case OPC_LUXC1:
29602 case OPC_SUXC1:
29603 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29604 /* Fallthrough */
29605 case OPC_LWXC1:
29606 case OPC_LDXC1:
29607 case OPC_SWXC1:
29608 case OPC_SDXC1:
29609 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29610 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29611 break;
29612 case OPC_PREFX:
29613 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29614 /* Treat as NOP. */
29615 break;
29616 case OPC_ALNV_PS:
29617 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29618 /* Fallthrough */
29619 case OPC_MADD_S:
29620 case OPC_MADD_D:
29621 case OPC_MADD_PS:
29622 case OPC_MSUB_S:
29623 case OPC_MSUB_D:
29624 case OPC_MSUB_PS:
29625 case OPC_NMADD_S:
29626 case OPC_NMADD_D:
29627 case OPC_NMADD_PS:
29628 case OPC_NMSUB_S:
29629 case OPC_NMSUB_D:
29630 case OPC_NMSUB_PS:
29631 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29632 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29633 break;
29634 default:
29635 MIPS_INVAL("cp3");
29636 generate_exception_end(ctx, EXCP_RI);
29637 break;
29639 } else {
29640 generate_exception_err(ctx, EXCP_CpU, 1);
29642 break;
29644 #if defined(TARGET_MIPS64)
29645 /* MIPS64 opcodes */
29646 case OPC_LLD:
29647 if (ctx->insn_flags & INSN_R5900) {
29648 check_insn_opc_user_only(ctx, INSN_R5900);
29650 /* fall through */
29651 case OPC_LDL:
29652 case OPC_LDR:
29653 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29654 /* fall through */
29655 case OPC_LWU:
29656 case OPC_LD:
29657 check_insn(ctx, ISA_MIPS3);
29658 check_mips_64(ctx);
29659 gen_ld(ctx, op, rt, rs, imm);
29660 break;
29661 case OPC_SDL:
29662 case OPC_SDR:
29663 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29664 /* fall through */
29665 case OPC_SD:
29666 check_insn(ctx, ISA_MIPS3);
29667 check_mips_64(ctx);
29668 gen_st(ctx, op, rt, rs, imm);
29669 break;
29670 case OPC_SCD:
29671 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29672 check_insn(ctx, ISA_MIPS3);
29673 if (ctx->insn_flags & INSN_R5900) {
29674 check_insn_opc_user_only(ctx, INSN_R5900);
29676 check_mips_64(ctx);
29677 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
29678 break;
29679 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29680 if (ctx->insn_flags & ISA_MIPS32R6) {
29681 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29682 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29683 } else {
29684 /* OPC_DADDI */
29685 check_insn(ctx, ISA_MIPS3);
29686 check_mips_64(ctx);
29687 gen_arith_imm(ctx, op, rt, rs, imm);
29689 break;
29690 case OPC_DADDIU:
29691 check_insn(ctx, ISA_MIPS3);
29692 check_mips_64(ctx);
29693 gen_arith_imm(ctx, op, rt, rs, imm);
29694 break;
29695 #else
29696 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29697 if (ctx->insn_flags & ISA_MIPS32R6) {
29698 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29699 } else {
29700 MIPS_INVAL("major opcode");
29701 generate_exception_end(ctx, EXCP_RI);
29703 break;
29704 #endif
29705 case OPC_DAUI: /* OPC_JALX */
29706 if (ctx->insn_flags & ISA_MIPS32R6) {
29707 #if defined(TARGET_MIPS64)
29708 /* OPC_DAUI */
29709 check_mips_64(ctx);
29710 if (rs == 0) {
29711 generate_exception(ctx, EXCP_RI);
29712 } else if (rt != 0) {
29713 TCGv t0 = tcg_temp_new();
29714 gen_load_gpr(t0, rs);
29715 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29716 tcg_temp_free(t0);
29718 #else
29719 generate_exception_end(ctx, EXCP_RI);
29720 MIPS_INVAL("major opcode");
29721 #endif
29722 } else {
29723 /* OPC_JALX */
29724 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29725 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29726 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29728 break;
29729 case OPC_MSA: /* OPC_MDMX */
29730 if (ctx->insn_flags & INSN_R5900) {
29731 #if defined(TARGET_MIPS64)
29732 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29733 #endif
29734 } else {
29735 /* MDMX: Not implemented. */
29736 gen_msa(env, ctx);
29738 break;
29739 case OPC_PCREL:
29740 check_insn(ctx, ISA_MIPS32R6);
29741 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29742 break;
29743 default: /* Invalid */
29744 MIPS_INVAL("major opcode");
29745 generate_exception_end(ctx, EXCP_RI);
29746 break;
29750 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29752 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29753 CPUMIPSState *env = cs->env_ptr;
29755 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29756 ctx->saved_pc = -1;
29757 ctx->insn_flags = env->insn_flags;
29758 ctx->CP0_Config1 = env->CP0_Config1;
29759 ctx->CP0_Config2 = env->CP0_Config2;
29760 ctx->CP0_Config3 = env->CP0_Config3;
29761 ctx->CP0_Config5 = env->CP0_Config5;
29762 ctx->btarget = 0;
29763 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29764 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29765 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29766 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29767 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29768 ctx->PAMask = env->PAMask;
29769 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29770 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29771 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29772 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29773 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29774 /* Restore delay slot state from the tb context. */
29775 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29776 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29777 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29778 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29779 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29780 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29781 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29782 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29783 restore_cpu_state(env, ctx);
29784 #ifdef CONFIG_USER_ONLY
29785 ctx->mem_idx = MIPS_HFLAG_UM;
29786 #else
29787 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29788 #endif
29789 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29790 MO_UNALN : MO_ALIGN;
29792 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29793 ctx->hflags);
29796 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29800 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29802 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29804 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29805 ctx->btarget);
29808 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29809 const CPUBreakpoint *bp)
29811 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29813 save_cpu_state(ctx, 1);
29814 ctx->base.is_jmp = DISAS_NORETURN;
29815 gen_helper_raise_exception_debug(cpu_env);
29816 /* The address covered by the breakpoint must be included in
29817 [tb->pc, tb->pc + tb->size) in order to for it to be
29818 properly cleared -- thus we increment the PC here so that
29819 the logic setting tb->size below does the right thing. */
29820 ctx->base.pc_next += 4;
29821 return true;
29824 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29826 CPUMIPSState *env = cs->env_ptr;
29827 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29828 int insn_bytes;
29829 int is_slot;
29831 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29832 if (ctx->insn_flags & ISA_NANOMIPS32) {
29833 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29834 insn_bytes = decode_nanomips_opc(env, ctx);
29835 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29836 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
29837 insn_bytes = 4;
29838 decode_opc(env, ctx);
29839 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29840 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29841 insn_bytes = decode_micromips_opc(env, ctx);
29842 } else if (ctx->insn_flags & ASE_MIPS16) {
29843 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29844 insn_bytes = decode_mips16_opc(env, ctx);
29845 } else {
29846 generate_exception_end(ctx, EXCP_RI);
29847 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29848 return;
29851 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29852 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29853 MIPS_HFLAG_FBNSLOT))) {
29854 /* force to generate branch as there is neither delay nor
29855 forbidden slot */
29856 is_slot = 1;
29858 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29859 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29860 /* Force to generate branch as microMIPS R6 doesn't restrict
29861 branches in the forbidden slot. */
29862 is_slot = 1;
29865 if (is_slot) {
29866 gen_branch(ctx, insn_bytes);
29868 ctx->base.pc_next += insn_bytes;
29870 if (ctx->base.is_jmp != DISAS_NEXT) {
29871 return;
29873 /* Execute a branch and its delay slot as a single instruction.
29874 This is what GDB expects and is consistent with what the
29875 hardware does (e.g. if a delay slot instruction faults, the
29876 reported PC is the PC of the branch). */
29877 if (ctx->base.singlestep_enabled &&
29878 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29879 ctx->base.is_jmp = DISAS_TOO_MANY;
29881 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29882 ctx->base.is_jmp = DISAS_TOO_MANY;
29886 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29888 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29890 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29891 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29892 gen_helper_raise_exception_debug(cpu_env);
29893 } else {
29894 switch (ctx->base.is_jmp) {
29895 case DISAS_STOP:
29896 gen_save_pc(ctx->base.pc_next);
29897 tcg_gen_lookup_and_goto_ptr();
29898 break;
29899 case DISAS_NEXT:
29900 case DISAS_TOO_MANY:
29901 save_cpu_state(ctx, 0);
29902 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29903 break;
29904 case DISAS_EXIT:
29905 tcg_gen_exit_tb(NULL, 0);
29906 break;
29907 case DISAS_NORETURN:
29908 break;
29909 default:
29910 g_assert_not_reached();
29915 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29917 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29918 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29921 static const TranslatorOps mips_tr_ops = {
29922 .init_disas_context = mips_tr_init_disas_context,
29923 .tb_start = mips_tr_tb_start,
29924 .insn_start = mips_tr_insn_start,
29925 .breakpoint_check = mips_tr_breakpoint_check,
29926 .translate_insn = mips_tr_translate_insn,
29927 .tb_stop = mips_tr_tb_stop,
29928 .disas_log = mips_tr_disas_log,
29931 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
29933 DisasContext ctx;
29935 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
29938 static void fpu_dump_state(CPUMIPSState *env, FILE *f, int flags)
29940 int i;
29941 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
29943 #define printfpr(fp) \
29944 do { \
29945 if (is_fpu64) \
29946 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
29947 " fd:%13g fs:%13g psu: %13g\n", \
29948 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29949 (double)(fp)->fd, \
29950 (double)(fp)->fs[FP_ENDIAN_IDX], \
29951 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29952 else { \
29953 fpr_t tmp; \
29954 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29955 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29956 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
29957 " fd:%13g fs:%13g psu:%13g\n", \
29958 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29959 (double)tmp.fd, \
29960 (double)tmp.fs[FP_ENDIAN_IDX], \
29961 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29963 } while(0)
29966 qemu_fprintf(f,
29967 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29968 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
29969 get_float_exception_flags(&env->active_fpu.fp_status));
29970 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29971 qemu_fprintf(f, "%3s: ", fregnames[i]);
29972 printfpr(&env->active_fpu.fpr[i]);
29975 #undef printfpr
29978 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
29980 MIPSCPU *cpu = MIPS_CPU(cs);
29981 CPUMIPSState *env = &cpu->env;
29982 int i;
29984 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29985 " LO=0x" TARGET_FMT_lx " ds %04x "
29986 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
29987 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29988 env->hflags, env->btarget, env->bcond);
29989 for (i = 0; i < 32; i++) {
29990 if ((i & 3) == 0)
29991 qemu_fprintf(f, "GPR%02d:", i);
29992 qemu_fprintf(f, " %s " TARGET_FMT_lx,
29993 regnames[i], env->active_tc.gpr[i]);
29994 if ((i & 3) == 3)
29995 qemu_fprintf(f, "\n");
29998 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
29999 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30000 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30001 PRIx64 "\n",
30002 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30003 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30004 env->CP0_Config2, env->CP0_Config3);
30005 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30006 env->CP0_Config4, env->CP0_Config5);
30007 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
30008 fpu_dump_state(env, f, flags);
30012 void mips_tcg_init(void)
30014 int i;
30016 cpu_gpr[0] = NULL;
30017 for (i = 1; i < 32; i++)
30018 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
30019 offsetof(CPUMIPSState, active_tc.gpr[i]),
30020 regnames[i]);
30022 for (i = 0; i < 32; i++) {
30023 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30024 msa_wr_d[i * 2] =
30025 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
30026 /* The scalar floating-point unit (FPU) registers are mapped on
30027 * the MSA vector registers. */
30028 fpu_f64[i] = msa_wr_d[i * 2];
30029 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30030 msa_wr_d[i * 2 + 1] =
30031 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
30034 cpu_PC = tcg_global_mem_new(cpu_env,
30035 offsetof(CPUMIPSState, active_tc.PC), "PC");
30036 for (i = 0; i < MIPS_DSP_ACC; i++) {
30037 cpu_HI[i] = tcg_global_mem_new(cpu_env,
30038 offsetof(CPUMIPSState, active_tc.HI[i]),
30039 regnames_HI[i]);
30040 cpu_LO[i] = tcg_global_mem_new(cpu_env,
30041 offsetof(CPUMIPSState, active_tc.LO[i]),
30042 regnames_LO[i]);
30044 cpu_dspctrl = tcg_global_mem_new(cpu_env,
30045 offsetof(CPUMIPSState, active_tc.DSPControl),
30046 "DSPControl");
30047 bcond = tcg_global_mem_new(cpu_env,
30048 offsetof(CPUMIPSState, bcond), "bcond");
30049 btarget = tcg_global_mem_new(cpu_env,
30050 offsetof(CPUMIPSState, btarget), "btarget");
30051 hflags = tcg_global_mem_new_i32(cpu_env,
30052 offsetof(CPUMIPSState, hflags), "hflags");
30054 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
30055 offsetof(CPUMIPSState, active_fpu.fcr0),
30056 "fcr0");
30057 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
30058 offsetof(CPUMIPSState, active_fpu.fcr31),
30059 "fcr31");
30060 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
30061 "lladdr");
30062 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
30063 "llval");
30065 #if defined(TARGET_MIPS64)
30066 cpu_mmr[0] = NULL;
30067 for (i = 1; i < 32; i++) {
30068 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
30069 offsetof(CPUMIPSState,
30070 active_tc.mmr[i]),
30071 regnames[i]);
30073 #endif
30075 #if !defined(TARGET_MIPS64)
30076 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
30077 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
30078 offsetof(CPUMIPSState,
30079 active_tc.mxu_gpr[i]),
30080 mxuregnames[i]);
30083 mxu_CR = tcg_global_mem_new(cpu_env,
30084 offsetof(CPUMIPSState, active_tc.mxu_cr),
30085 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
30086 #endif
30089 #include "translate_init.inc.c"
30091 void cpu_mips_realize_env(CPUMIPSState *env)
30093 env->exception_base = (int32_t)0xBFC00000;
30095 #ifndef CONFIG_USER_ONLY
30096 mmu_init(env, env->cpu_model);
30097 #endif
30098 fpu_init(env, env->cpu_model);
30099 mvp_init(env, env->cpu_model);
30102 bool cpu_supports_cps_smp(const char *cpu_type)
30104 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30105 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
30108 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
30110 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30111 return (mcc->cpu_def->insn_flags & isa) != 0;
30114 void cpu_set_exception_base(int vp_index, target_ulong address)
30116 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
30117 vp->env.exception_base = address;
30120 void cpu_state_reset(CPUMIPSState *env)
30122 CPUState *cs = env_cpu(env);
30124 /* Reset registers to their default values */
30125 env->CP0_PRid = env->cpu_model->CP0_PRid;
30126 env->CP0_Config0 = env->cpu_model->CP0_Config0;
30127 #ifdef TARGET_WORDS_BIGENDIAN
30128 env->CP0_Config0 |= (1 << CP0C0_BE);
30129 #endif
30130 env->CP0_Config1 = env->cpu_model->CP0_Config1;
30131 env->CP0_Config2 = env->cpu_model->CP0_Config2;
30132 env->CP0_Config3 = env->cpu_model->CP0_Config3;
30133 env->CP0_Config4 = env->cpu_model->CP0_Config4;
30134 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
30135 env->CP0_Config5 = env->cpu_model->CP0_Config5;
30136 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
30137 env->CP0_Config6 = env->cpu_model->CP0_Config6;
30138 env->CP0_Config7 = env->cpu_model->CP0_Config7;
30139 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
30140 << env->cpu_model->CP0_LLAddr_shift;
30141 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
30142 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
30143 env->CCRes = env->cpu_model->CCRes;
30144 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
30145 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
30146 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
30147 env->current_tc = 0;
30148 env->SEGBITS = env->cpu_model->SEGBITS;
30149 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
30150 #if defined(TARGET_MIPS64)
30151 if (env->cpu_model->insn_flags & ISA_MIPS3) {
30152 env->SEGMask |= 3ULL << 62;
30154 #endif
30155 env->PABITS = env->cpu_model->PABITS;
30156 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
30157 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
30158 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
30159 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
30160 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
30161 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
30162 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
30163 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
30164 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
30165 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
30166 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
30167 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
30168 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
30169 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
30170 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
30171 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
30172 env->msair = env->cpu_model->MSAIR;
30173 env->insn_flags = env->cpu_model->insn_flags;
30175 #if defined(CONFIG_USER_ONLY)
30176 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
30177 # ifdef TARGET_MIPS64
30178 /* Enable 64-bit register mode. */
30179 env->CP0_Status |= (1 << CP0St_PX);
30180 # endif
30181 # ifdef TARGET_ABI_MIPSN64
30182 /* Enable 64-bit address mode. */
30183 env->CP0_Status |= (1 << CP0St_UX);
30184 # endif
30185 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
30186 hardware registers. */
30187 env->CP0_HWREna |= 0x0000000F;
30188 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
30189 env->CP0_Status |= (1 << CP0St_CU1);
30191 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
30192 env->CP0_Status |= (1 << CP0St_MX);
30194 # if defined(TARGET_MIPS64)
30195 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
30196 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
30197 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
30198 env->CP0_Status |= (1 << CP0St_FR);
30200 # endif
30201 #else
30202 if (env->hflags & MIPS_HFLAG_BMASK) {
30203 /* If the exception was raised from a delay slot,
30204 come back to the jump. */
30205 env->CP0_ErrorEPC = (env->active_tc.PC
30206 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
30207 } else {
30208 env->CP0_ErrorEPC = env->active_tc.PC;
30210 env->active_tc.PC = env->exception_base;
30211 env->CP0_Random = env->tlb->nb_tlb - 1;
30212 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30213 env->CP0_Wired = 0;
30214 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30215 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30216 if (mips_um_ksegs_enabled()) {
30217 env->CP0_EBase |= 0x40000000;
30218 } else {
30219 env->CP0_EBase |= (int32_t)0x80000000;
30221 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30222 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30224 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30225 0x3ff : 0xff;
30226 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30227 /* vectored interrupts not implemented, timer on int 7,
30228 no performance counters. */
30229 env->CP0_IntCtl = 0xe0000000;
30231 int i;
30233 for (i = 0; i < 7; i++) {
30234 env->CP0_WatchLo[i] = 0;
30235 env->CP0_WatchHi[i] = 0x80000000;
30237 env->CP0_WatchLo[7] = 0;
30238 env->CP0_WatchHi[7] = 0;
30240 /* Count register increments in debug mode, EJTAG version 1 */
30241 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30243 cpu_mips_store_count(env, 1);
30245 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30246 int i;
30248 /* Only TC0 on VPE 0 starts as active. */
30249 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30250 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30251 env->tcs[i].CP0_TCHalt = 1;
30253 env->active_tc.CP0_TCHalt = 1;
30254 cs->halted = 1;
30256 if (cs->cpu_index == 0) {
30257 /* VPE0 starts up enabled. */
30258 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30259 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30261 /* TC0 starts up unhalted. */
30262 cs->halted = 0;
30263 env->active_tc.CP0_TCHalt = 0;
30264 env->tcs[0].CP0_TCHalt = 0;
30265 /* With thread 0 active. */
30266 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30267 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30272 * Configure default legacy segmentation control. We use this regardless of
30273 * whether segmentation control is presented to the guest.
30275 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30276 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30277 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30278 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30279 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30280 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30281 (2 << CP0SC_C);
30282 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30283 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30284 (3 << CP0SC_C)) << 16;
30285 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30286 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30287 (1 << CP0SC_EU) | (2 << CP0SC_C);
30288 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30289 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30290 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30291 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30292 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30293 #endif
30294 if ((env->insn_flags & ISA_MIPS32R6) &&
30295 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30296 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30297 env->CP0_Status |= (1 << CP0St_FR);
30300 if (env->insn_flags & ISA_MIPS32R6) {
30301 /* PTW = 1 */
30302 env->CP0_PWSize = 0x40;
30303 /* GDI = 12 */
30304 /* UDI = 12 */
30305 /* MDI = 12 */
30306 /* PRI = 12 */
30307 /* PTEI = 2 */
30308 env->CP0_PWField = 0x0C30C302;
30309 } else {
30310 /* GDI = 0 */
30311 /* UDI = 0 */
30312 /* MDI = 0 */
30313 /* PRI = 0 */
30314 /* PTEI = 2 */
30315 env->CP0_PWField = 0x02;
30318 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30319 /* microMIPS on reset when Config3.ISA is 3 */
30320 env->hflags |= MIPS_HFLAG_M16;
30323 /* MSA */
30324 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30325 msa_reset(env);
30328 compute_hflags(env);
30329 restore_fp_status(env);
30330 restore_pamask(env);
30331 cs->exception_index = EXCP_NONE;
30333 if (semihosting_get_argc()) {
30334 /* UHI interface can be used to obtain argc and argv */
30335 env->active_tc.gpr[4] = -1;
30339 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30340 target_ulong *data)
30342 env->active_tc.PC = data[0];
30343 env->hflags &= ~MIPS_HFLAG_BMASK;
30344 env->hflags |= data[1];
30345 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30346 case MIPS_HFLAG_BR:
30347 break;
30348 case MIPS_HFLAG_BC:
30349 case MIPS_HFLAG_BL:
30350 case MIPS_HFLAG_B:
30351 env->btarget = data[2];
30352 break;