ar7: Update board code for latest QEMU API
[qemu/ar7.git] / target / mips / translate.c
blob364bd6dc4fd59db9ed11096bce0ac400cd7aa48c
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 "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
467 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
468 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
469 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
470 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
473 /* DBSHFL opcodes */
474 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
476 enum {
477 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
478 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
479 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
480 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
481 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
482 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
483 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
484 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
485 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
486 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
487 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
490 /* MIPS DSP REGIMM opcodes */
491 enum {
492 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
493 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
496 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497 /* MIPS DSP Load */
498 enum {
499 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
500 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
501 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
502 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
505 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
522 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
525 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
526 /* MIPS DSP Multiply Sub-class insns */
527 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
535 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
536 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
537 enum {
538 /* MIPS DSP Arithmetic Sub-class */
539 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
553 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
558 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
559 enum {
560 /* MIPS DSP Arithmetic Sub-class */
561 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
574 /* DSP Bit/Manipulation Sub-class */
575 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
582 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
592 /* DSP Compare-Pick Sub-class */
593 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
610 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
611 enum {
612 /* MIPS DSP GPR-Based Shift Sub-class */
613 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
637 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
638 enum {
639 /* MIPS DSP Multiply Sub-class insns */
640 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
664 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665 enum {
666 /* DSP Bit/Manipulation Sub-class */
667 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
670 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Append Sub-class */
673 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
674 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
675 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
678 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679 enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
693 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
695 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
696 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
697 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
700 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Arithmetic Sub-class */
703 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
720 /* DSP Bit/Manipulation Sub-class */
721 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
729 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* MIPS DSP Multiply Sub-class insns */
732 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
733 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
737 /* MIPS DSP Arithmetic Sub-class */
738 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
761 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
762 enum {
763 /* DSP Compare-Pick Sub-class */
764 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
794 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795 enum {
796 /* DSP Append Sub-class */
797 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
798 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
800 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
803 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
806 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
807 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
829 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* DSP Bit/Manipulation Sub-class */
832 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
835 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP Multiply Sub-class insns */
838 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
866 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
867 enum {
868 /* MIPS DSP GPR-Based Shift Sub-class */
869 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
897 /* Coprocessor 0 (rs field) */
898 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
900 enum {
901 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
902 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
903 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
904 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
905 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
906 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
907 OPC_MFTR = (0x08 << 21) | OPC_CP0,
908 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
909 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
910 OPC_MTTR = (0x0C << 21) | OPC_CP0,
911 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
912 OPC_C0 = (0x10 << 21) | OPC_CP0,
913 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
914 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
915 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
916 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
917 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
918 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
919 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
920 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
921 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
922 OPC_C0_A = (0x1A << 21) | OPC_CP0,
923 OPC_C0_B = (0x1B << 21) | OPC_CP0,
924 OPC_C0_C = (0x1C << 21) | OPC_CP0,
925 OPC_C0_D = (0x1D << 21) | OPC_CP0,
926 OPC_C0_E = (0x1E << 21) | OPC_CP0,
927 OPC_C0_F = (0x1F << 21) | OPC_CP0,
930 /* MFMC0 opcodes */
931 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
933 enum {
934 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
935 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
937 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
938 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
939 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
941 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
944 /* Coprocessor 0 (with rs == C0) */
945 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
947 enum {
948 OPC_TLBR = 0x01 | OPC_C0,
949 OPC_TLBWI = 0x02 | OPC_C0,
950 OPC_TLBINV = 0x03 | OPC_C0,
951 OPC_TLBINVF = 0x04 | OPC_C0,
952 OPC_TLBWR = 0x06 | OPC_C0,
953 OPC_TLBP = 0x08 | OPC_C0,
954 OPC_RFE = 0x10 | OPC_C0,
955 OPC_ERET = 0x18 | OPC_C0,
956 OPC_DERET = 0x1F | OPC_C0,
957 OPC_WAIT = 0x20 | OPC_C0,
960 /* Coprocessor 1 (rs field) */
961 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
963 /* Values for the fmt field in FP instructions */
964 enum {
965 /* 0 - 15 are reserved */
966 FMT_S = 16, /* single fp */
967 FMT_D = 17, /* double fp */
968 FMT_E = 18, /* extended fp */
969 FMT_Q = 19, /* quad fp */
970 FMT_W = 20, /* 32-bit fixed */
971 FMT_L = 21, /* 64-bit fixed */
972 FMT_PS = 22, /* paired single fp */
973 /* 23 - 31 are reserved */
976 enum {
977 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
978 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
979 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
980 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
981 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
982 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
983 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
984 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
985 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
986 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
987 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
988 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
989 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
990 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
991 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
992 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
993 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
994 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
995 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
996 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
997 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
998 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
999 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1000 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1001 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1002 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1003 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1004 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1005 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1006 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1009 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1010 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1012 enum {
1013 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1014 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1015 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1016 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1019 enum {
1020 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1021 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1024 enum {
1025 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1026 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1029 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1031 enum {
1032 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1033 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1034 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1035 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1036 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1037 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1038 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1039 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1040 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1041 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1042 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1045 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1047 enum {
1048 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1049 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1057 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1067 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1070 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1071 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1072 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1073 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1075 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1076 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1079 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1084 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1085 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1086 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1091 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1092 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1098 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1099 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1106 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1112 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1113 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1114 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1115 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1116 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1120 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1121 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1122 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1123 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1127 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1128 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1130 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1134 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1135 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1136 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1137 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1138 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1142 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1144 enum {
1145 OPC_LWXC1 = 0x00 | OPC_CP3,
1146 OPC_LDXC1 = 0x01 | OPC_CP3,
1147 OPC_LUXC1 = 0x05 | OPC_CP3,
1148 OPC_SWXC1 = 0x08 | OPC_CP3,
1149 OPC_SDXC1 = 0x09 | OPC_CP3,
1150 OPC_SUXC1 = 0x0D | OPC_CP3,
1151 OPC_PREFX = 0x0F | OPC_CP3,
1152 OPC_ALNV_PS = 0x1E | OPC_CP3,
1153 OPC_MADD_S = 0x20 | OPC_CP3,
1154 OPC_MADD_D = 0x21 | OPC_CP3,
1155 OPC_MADD_PS = 0x26 | OPC_CP3,
1156 OPC_MSUB_S = 0x28 | OPC_CP3,
1157 OPC_MSUB_D = 0x29 | OPC_CP3,
1158 OPC_MSUB_PS = 0x2E | OPC_CP3,
1159 OPC_NMADD_S = 0x30 | OPC_CP3,
1160 OPC_NMADD_D = 0x31 | OPC_CP3,
1161 OPC_NMADD_PS= 0x36 | OPC_CP3,
1162 OPC_NMSUB_S = 0x38 | OPC_CP3,
1163 OPC_NMSUB_D = 0x39 | OPC_CP3,
1164 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1167 /* MSA Opcodes */
1168 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1169 enum {
1170 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1171 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1172 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1173 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1174 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1175 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1176 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1177 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1178 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1179 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1180 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1181 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1182 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1183 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1184 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1185 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1186 OPC_MSA_ELM = 0x19 | OPC_MSA,
1187 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1188 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1189 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1190 OPC_MSA_VEC = 0x1E | OPC_MSA,
1192 /* MI10 instruction */
1193 OPC_LD_B = (0x20) | OPC_MSA,
1194 OPC_LD_H = (0x21) | OPC_MSA,
1195 OPC_LD_W = (0x22) | OPC_MSA,
1196 OPC_LD_D = (0x23) | OPC_MSA,
1197 OPC_ST_B = (0x24) | OPC_MSA,
1198 OPC_ST_H = (0x25) | OPC_MSA,
1199 OPC_ST_W = (0x26) | OPC_MSA,
1200 OPC_ST_D = (0x27) | OPC_MSA,
1203 enum {
1204 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1205 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1206 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1207 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1208 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1209 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1210 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1211 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1212 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1213 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1214 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1215 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1216 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1218 /* I8 instruction */
1219 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1220 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1221 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1222 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1223 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1225 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1226 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1228 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1230 /* VEC/2R/2RF instruction */
1231 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1232 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1233 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1234 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1235 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1236 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1237 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1239 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1242 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1243 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1244 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1245 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1246 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1248 /* 2RF instruction df(bit 16) = _w, _d */
1249 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1250 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1252 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1253 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1254 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1255 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1256 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1257 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1259 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1260 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1261 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1263 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1266 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1267 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1268 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1269 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1270 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1272 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1274 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1275 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1276 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1277 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1278 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1279 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1280 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1281 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1282 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1283 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1284 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1285 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1286 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1287 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1288 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1289 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1290 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1292 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1293 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1294 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1295 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1296 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1297 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1298 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1299 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1300 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1301 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1302 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1303 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1304 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1305 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1306 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1307 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1308 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1309 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1310 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1311 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1312 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1313 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1314 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1315 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1316 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1317 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1318 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1319 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1320 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1321 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1322 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1323 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1324 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1325 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1326 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1327 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1328 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1329 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1331 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1332 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1334 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1335 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1336 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 /* 3RF instruction _df(bit 21) = _w, _d */
1343 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1346 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1347 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1348 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1356 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1361 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1362 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1363 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1364 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1365 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1366 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1369 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1372 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1373 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1374 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1375 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1378 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1381 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1385 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1386 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1387 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1388 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1389 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1390 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1391 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1392 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1393 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1394 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1395 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1396 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1403 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1404 * ============================================
1407 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1408 * instructions set. It is designed to fit the needs of signal, graphical and
1409 * video processing applications. MXU instruction set is used in Xburst family
1410 * of microprocessors by Ingenic.
1412 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1413 * the control register.
1416 * The notation used in MXU assembler mnemonics
1417 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1419 * Register operands:
1421 * XRa, XRb, XRc, XRd - MXU registers
1422 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1424 * Non-register operands:
1426 * aptn1 - 1-bit accumulate add/subtract pattern
1427 * aptn2 - 2-bit accumulate add/subtract pattern
1428 * eptn2 - 2-bit execute add/subtract pattern
1429 * optn2 - 2-bit operand pattern
1430 * optn3 - 3-bit operand pattern
1431 * sft4 - 4-bit shift amount
1432 * strd2 - 2-bit stride amount
1434 * Prefixes:
1436 * Level of parallelism: Operand size:
1437 * S - single operation at a time 32 - word
1438 * D - two operations in parallel 16 - half word
1439 * Q - four operations in parallel 8 - byte
1441 * Operations:
1443 * ADD - Add or subtract
1444 * ADDC - Add with carry-in
1445 * ACC - Accumulate
1446 * ASUM - Sum together then accumulate (add or subtract)
1447 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1448 * AVG - Average between 2 operands
1449 * ABD - Absolute difference
1450 * ALN - Align data
1451 * AND - Logical bitwise 'and' operation
1452 * CPS - Copy sign
1453 * EXTR - Extract bits
1454 * I2M - Move from GPR register to MXU register
1455 * LDD - Load data from memory to XRF
1456 * LDI - Load data from memory to XRF (and increase the address base)
1457 * LUI - Load unsigned immediate
1458 * MUL - Multiply
1459 * MULU - Unsigned multiply
1460 * MADD - 64-bit operand add 32x32 product
1461 * MSUB - 64-bit operand subtract 32x32 product
1462 * MAC - Multiply and accumulate (add or subtract)
1463 * MAD - Multiply and add or subtract
1464 * MAX - Maximum between 2 operands
1465 * MIN - Minimum between 2 operands
1466 * M2I - Move from MXU register to GPR register
1467 * MOVZ - Move if zero
1468 * MOVN - Move if non-zero
1469 * NOR - Logical bitwise 'nor' operation
1470 * OR - Logical bitwise 'or' operation
1471 * STD - Store data from XRF to memory
1472 * SDI - Store data from XRF to memory (and increase the address base)
1473 * SLT - Set of less than comparison
1474 * SAD - Sum of absolute differences
1475 * SLL - Logical shift left
1476 * SLR - Logical shift right
1477 * SAR - Arithmetic shift right
1478 * SAT - Saturation
1479 * SFL - Shuffle
1480 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1481 * XOR - Logical bitwise 'exclusive or' operation
1483 * Suffixes:
1485 * E - Expand results
1486 * F - Fixed point multiplication
1487 * L - Low part result
1488 * R - Doing rounding
1489 * V - Variable instead of immediate
1490 * W - Combine above L and V
1493 * The list of MXU instructions grouped by functionality
1494 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1496 * Load/Store instructions Multiplication instructions
1497 * ----------------------- ---------------------------
1499 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1500 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1501 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1502 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1503 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1504 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1505 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1506 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1507 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1508 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1509 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1510 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1511 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1513 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1514 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1515 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1516 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1517 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1518 * S16SDI XRa, Rb, s10, eptn2
1519 * S8LDD XRa, Rb, s8, eptn3
1520 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1521 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1522 * S8SDI XRa, Rb, s8, eptn3
1523 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1524 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1525 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1526 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1527 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1528 * S32CPS XRa, XRb, XRc
1529 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1530 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1531 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1532 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1533 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1534 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1535 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1536 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1537 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1538 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1539 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1540 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1541 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1542 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1543 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1544 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1545 * Q8SLT XRa, XRb, XRc
1546 * Q8SLTU XRa, XRb, XRc
1547 * Q8MOVZ XRa, XRb, XRc Shift instructions
1548 * Q8MOVN XRa, XRb, XRc ------------------
1550 * D32SLL XRa, XRb, XRc, XRd, sft4
1551 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1552 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1553 * D32SARL XRa, XRb, XRc, sft4
1554 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1555 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1556 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1557 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1558 * Q16SLL XRa, XRb, XRc, XRd, sft4
1559 * Q16SLR XRa, XRb, XRc, XRd, sft4
1560 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1561 * ------------------------- Q16SLLV XRa, XRb, Rb
1562 * Q16SLRV XRa, XRb, Rb
1563 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1564 * S32ALN XRa, XRb, XRc, Rb
1565 * S32ALNI XRa, XRb, XRc, s3
1566 * S32LUI XRa, s8, optn3 Move instructions
1567 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1568 * S32EXTRV XRa, XRb, Rs, Rt
1569 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1570 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1573 * The opcode organization of MXU instructions
1574 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1576 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1577 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1578 * other bits up to the instruction level is as follows:
1580 * bits
1581 * 05..00
1583 * ┌─ 000000 ─ OPC_MXU_S32MADD
1584 * ├─ 000001 ─ OPC_MXU_S32MADDU
1585 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1586 * │
1587 * │ 20..18
1588 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1589 * │ ├─ 001 ─ OPC_MXU_S32MIN
1590 * │ ├─ 010 ─ OPC_MXU_D16MAX
1591 * │ ├─ 011 ─ OPC_MXU_D16MIN
1592 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1593 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1594 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1595 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1596 * ├─ 000100 ─ OPC_MXU_S32MSUB
1597 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1598 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1599 * │ ├─ 001 ─ OPC_MXU_D16SLT
1600 * │ ├─ 010 ─ OPC_MXU_D16AVG
1601 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1602 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1603 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1604 * │ └─ 111 ─ OPC_MXU_Q8ADD
1605 * │
1606 * │ 20..18
1607 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1608 * │ ├─ 010 ─ OPC_MXU_D16CPS
1609 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1610 * │ └─ 110 ─ OPC_MXU_Q16SAT
1611 * ├─ 001000 ─ OPC_MXU_D16MUL
1612 * │ 25..24
1613 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1614 * │ └─ 01 ─ OPC_MXU_D16MULE
1615 * ├─ 001010 ─ OPC_MXU_D16MAC
1616 * ├─ 001011 ─ OPC_MXU_D16MACF
1617 * ├─ 001100 ─ OPC_MXU_D16MADL
1618 * ├─ 001101 ─ OPC_MXU_S16MAD
1619 * ├─ 001110 ─ OPC_MXU_Q16ADD
1620 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1621 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1622 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1623 * │
1624 * │ 23
1625 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1626 * │ └─ 1 ─ OPC_MXU_S32STDR
1627 * │
1628 * │ 13..10
1629 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1630 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1631 * │
1632 * │ 13..10
1633 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1634 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1635 * │
1636 * │ 23
1637 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1638 * │ └─ 1 ─ OPC_MXU_S32LDIR
1639 * │
1640 * │ 23
1641 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1642 * │ └─ 1 ─ OPC_MXU_S32SDIR
1643 * │
1644 * │ 13..10
1645 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1646 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1647 * │
1648 * │ 13..10
1649 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1650 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1651 * ├─ 011000 ─ OPC_MXU_D32ADD
1652 * │ 23..22
1653 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1654 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1655 * │ └─ 10 ─ OPC_MXU_D32ASUM
1656 * ├─ 011010 ─ <not assigned>
1657 * │ 23..22
1658 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1659 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1660 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1661 * │
1662 * │ 23..22
1663 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1664 * │ ├─ 01 ─ OPC_MXU_D8SUM
1665 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1666 * ├─ 011110 ─ <not assigned>
1667 * ├─ 011111 ─ <not assigned>
1668 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1669 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1670 * ├─ 100010 ─ OPC_MXU_S8LDD
1671 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1672 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1673 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1674 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1675 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1676 * │
1677 * │ 20..18
1678 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1679 * │ ├─ 001 ─ OPC_MXU_S32ALN
1680 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1681 * │ ├─ 011 ─ OPC_MXU_S32LUI
1682 * │ ├─ 100 ─ OPC_MXU_S32NOR
1683 * │ ├─ 101 ─ OPC_MXU_S32AND
1684 * │ ├─ 110 ─ OPC_MXU_S32OR
1685 * │ └─ 111 ─ OPC_MXU_S32XOR
1686 * │
1687 * │ 7..5
1688 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1689 * │ ├─ 001 ─ OPC_MXU_LXH
1690 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1691 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1692 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1693 * ├─ 101100 ─ OPC_MXU_S16LDI
1694 * ├─ 101101 ─ OPC_MXU_S16SDI
1695 * ├─ 101110 ─ OPC_MXU_S32M2I
1696 * ├─ 101111 ─ OPC_MXU_S32I2M
1697 * ├─ 110000 ─ OPC_MXU_D32SLL
1698 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1699 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1700 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1701 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1702 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1703 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1704 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1705 * │
1706 * ├─ 110111 ─ OPC_MXU_Q16SAR
1707 * │ 23..22
1708 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1709 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1710 * │
1711 * │ 20..18
1712 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1713 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1714 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1715 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1716 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1717 * │ └─ 101 ─ OPC_MXU_S32MOVN
1718 * │
1719 * │ 23..22
1720 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1721 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1722 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1723 * ├─ 111100 ─ OPC_MXU_Q8MADL
1724 * ├─ 111101 ─ OPC_MXU_S32SFL
1725 * ├─ 111110 ─ OPC_MXU_Q8SAD
1726 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1729 * Compiled after:
1731 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1732 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1735 enum {
1736 OPC_MXU_S32MADD = 0x00,
1737 OPC_MXU_S32MADDU = 0x01,
1738 OPC__MXU_MUL = 0x02,
1739 OPC_MXU__POOL00 = 0x03,
1740 OPC_MXU_S32MSUB = 0x04,
1741 OPC_MXU_S32MSUBU = 0x05,
1742 OPC_MXU__POOL01 = 0x06,
1743 OPC_MXU__POOL02 = 0x07,
1744 OPC_MXU_D16MUL = 0x08,
1745 OPC_MXU__POOL03 = 0x09,
1746 OPC_MXU_D16MAC = 0x0A,
1747 OPC_MXU_D16MACF = 0x0B,
1748 OPC_MXU_D16MADL = 0x0C,
1749 OPC_MXU_S16MAD = 0x0D,
1750 OPC_MXU_Q16ADD = 0x0E,
1751 OPC_MXU_D16MACE = 0x0F,
1752 OPC_MXU__POOL04 = 0x10,
1753 OPC_MXU__POOL05 = 0x11,
1754 OPC_MXU__POOL06 = 0x12,
1755 OPC_MXU__POOL07 = 0x13,
1756 OPC_MXU__POOL08 = 0x14,
1757 OPC_MXU__POOL09 = 0x15,
1758 OPC_MXU__POOL10 = 0x16,
1759 OPC_MXU__POOL11 = 0x17,
1760 OPC_MXU_D32ADD = 0x18,
1761 OPC_MXU__POOL12 = 0x19,
1762 /* not assigned 0x1A */
1763 OPC_MXU__POOL13 = 0x1B,
1764 OPC_MXU__POOL14 = 0x1C,
1765 OPC_MXU_Q8ACCE = 0x1D,
1766 /* not assigned 0x1E */
1767 /* not assigned 0x1F */
1768 /* not assigned 0x20 */
1769 /* not assigned 0x21 */
1770 OPC_MXU_S8LDD = 0x22,
1771 OPC_MXU_S8STD = 0x23,
1772 OPC_MXU_S8LDI = 0x24,
1773 OPC_MXU_S8SDI = 0x25,
1774 OPC_MXU__POOL15 = 0x26,
1775 OPC_MXU__POOL16 = 0x27,
1776 OPC_MXU__POOL17 = 0x28,
1777 /* not assigned 0x29 */
1778 OPC_MXU_S16LDD = 0x2A,
1779 OPC_MXU_S16STD = 0x2B,
1780 OPC_MXU_S16LDI = 0x2C,
1781 OPC_MXU_S16SDI = 0x2D,
1782 OPC_MXU_S32M2I = 0x2E,
1783 OPC_MXU_S32I2M = 0x2F,
1784 OPC_MXU_D32SLL = 0x30,
1785 OPC_MXU_D32SLR = 0x31,
1786 OPC_MXU_D32SARL = 0x32,
1787 OPC_MXU_D32SAR = 0x33,
1788 OPC_MXU_Q16SLL = 0x34,
1789 OPC_MXU_Q16SLR = 0x35,
1790 OPC_MXU__POOL18 = 0x36,
1791 OPC_MXU_Q16SAR = 0x37,
1792 OPC_MXU__POOL19 = 0x38,
1793 OPC_MXU__POOL20 = 0x39,
1794 OPC_MXU__POOL21 = 0x3A,
1795 OPC_MXU_Q16SCOP = 0x3B,
1796 OPC_MXU_Q8MADL = 0x3C,
1797 OPC_MXU_S32SFL = 0x3D,
1798 OPC_MXU_Q8SAD = 0x3E,
1799 /* not assigned 0x3F */
1804 * MXU pool 00
1806 enum {
1807 OPC_MXU_S32MAX = 0x00,
1808 OPC_MXU_S32MIN = 0x01,
1809 OPC_MXU_D16MAX = 0x02,
1810 OPC_MXU_D16MIN = 0x03,
1811 OPC_MXU_Q8MAX = 0x04,
1812 OPC_MXU_Q8MIN = 0x05,
1813 OPC_MXU_Q8SLT = 0x06,
1814 OPC_MXU_Q8SLTU = 0x07,
1818 * MXU pool 01
1820 enum {
1821 OPC_MXU_S32SLT = 0x00,
1822 OPC_MXU_D16SLT = 0x01,
1823 OPC_MXU_D16AVG = 0x02,
1824 OPC_MXU_D16AVGR = 0x03,
1825 OPC_MXU_Q8AVG = 0x04,
1826 OPC_MXU_Q8AVGR = 0x05,
1827 OPC_MXU_Q8ADD = 0x07,
1831 * MXU pool 02
1833 enum {
1834 OPC_MXU_S32CPS = 0x00,
1835 OPC_MXU_D16CPS = 0x02,
1836 OPC_MXU_Q8ABD = 0x04,
1837 OPC_MXU_Q16SAT = 0x06,
1841 * MXU pool 03
1843 enum {
1844 OPC_MXU_D16MULF = 0x00,
1845 OPC_MXU_D16MULE = 0x01,
1849 * MXU pool 04
1851 enum {
1852 OPC_MXU_S32LDD = 0x00,
1853 OPC_MXU_S32LDDR = 0x01,
1857 * MXU pool 05
1859 enum {
1860 OPC_MXU_S32STD = 0x00,
1861 OPC_MXU_S32STDR = 0x01,
1865 * MXU pool 06
1867 enum {
1868 OPC_MXU_S32LDDV = 0x00,
1869 OPC_MXU_S32LDDVR = 0x01,
1873 * MXU pool 07
1875 enum {
1876 OPC_MXU_S32STDV = 0x00,
1877 OPC_MXU_S32STDVR = 0x01,
1881 * MXU pool 08
1883 enum {
1884 OPC_MXU_S32LDI = 0x00,
1885 OPC_MXU_S32LDIR = 0x01,
1889 * MXU pool 09
1891 enum {
1892 OPC_MXU_S32SDI = 0x00,
1893 OPC_MXU_S32SDIR = 0x01,
1897 * MXU pool 10
1899 enum {
1900 OPC_MXU_S32LDIV = 0x00,
1901 OPC_MXU_S32LDIVR = 0x01,
1905 * MXU pool 11
1907 enum {
1908 OPC_MXU_S32SDIV = 0x00,
1909 OPC_MXU_S32SDIVR = 0x01,
1913 * MXU pool 12
1915 enum {
1916 OPC_MXU_D32ACC = 0x00,
1917 OPC_MXU_D32ACCM = 0x01,
1918 OPC_MXU_D32ASUM = 0x02,
1922 * MXU pool 13
1924 enum {
1925 OPC_MXU_Q16ACC = 0x00,
1926 OPC_MXU_Q16ACCM = 0x01,
1927 OPC_MXU_Q16ASUM = 0x02,
1931 * MXU pool 14
1933 enum {
1934 OPC_MXU_Q8ADDE = 0x00,
1935 OPC_MXU_D8SUM = 0x01,
1936 OPC_MXU_D8SUMC = 0x02,
1940 * MXU pool 15
1942 enum {
1943 OPC_MXU_S32MUL = 0x00,
1944 OPC_MXU_S32MULU = 0x01,
1945 OPC_MXU_S32EXTR = 0x02,
1946 OPC_MXU_S32EXTRV = 0x03,
1950 * MXU pool 16
1952 enum {
1953 OPC_MXU_D32SARW = 0x00,
1954 OPC_MXU_S32ALN = 0x01,
1955 OPC_MXU_S32ALNI = 0x02,
1956 OPC_MXU_S32LUI = 0x03,
1957 OPC_MXU_S32NOR = 0x04,
1958 OPC_MXU_S32AND = 0x05,
1959 OPC_MXU_S32OR = 0x06,
1960 OPC_MXU_S32XOR = 0x07,
1964 * MXU pool 17
1966 enum {
1967 OPC_MXU_LXB = 0x00,
1968 OPC_MXU_LXH = 0x01,
1969 OPC_MXU_LXW = 0x03,
1970 OPC_MXU_LXBU = 0x04,
1971 OPC_MXU_LXHU = 0x05,
1975 * MXU pool 18
1977 enum {
1978 OPC_MXU_D32SLLV = 0x00,
1979 OPC_MXU_D32SLRV = 0x01,
1980 OPC_MXU_D32SARV = 0x03,
1981 OPC_MXU_Q16SLLV = 0x04,
1982 OPC_MXU_Q16SLRV = 0x05,
1983 OPC_MXU_Q16SARV = 0x07,
1987 * MXU pool 19
1989 enum {
1990 OPC_MXU_Q8MUL = 0x00,
1991 OPC_MXU_Q8MULSU = 0x01,
1995 * MXU pool 20
1997 enum {
1998 OPC_MXU_Q8MOVZ = 0x00,
1999 OPC_MXU_Q8MOVN = 0x01,
2000 OPC_MXU_D16MOVZ = 0x02,
2001 OPC_MXU_D16MOVN = 0x03,
2002 OPC_MXU_S32MOVZ = 0x04,
2003 OPC_MXU_S32MOVN = 0x05,
2007 * MXU pool 21
2009 enum {
2010 OPC_MXU_Q8MAC = 0x00,
2011 OPC_MXU_Q8MACSU = 0x01,
2015 * Overview of the TX79-specific instruction set
2016 * =============================================
2018 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2019 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2020 * instructions and certain multimedia instructions (MMIs). These MMIs
2021 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2022 * or sixteen 8-bit paths.
2024 * Reference:
2026 * The Toshiba TX System RISC TX79 Core Architecture manual,
2027 * https://wiki.qemu.org/File:C790.pdf
2029 * Three-Operand Multiply and Multiply-Add (4 instructions)
2030 * --------------------------------------------------------
2031 * MADD [rd,] rs, rt Multiply/Add
2032 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2033 * MULT [rd,] rs, rt Multiply (3-operand)
2034 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2036 * Multiply Instructions for Pipeline 1 (10 instructions)
2037 * ------------------------------------------------------
2038 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2039 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2040 * DIV1 rs, rt Divide Pipeline 1
2041 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2042 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2043 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2044 * MFHI1 rd Move From HI1 Register
2045 * MFLO1 rd Move From LO1 Register
2046 * MTHI1 rs Move To HI1 Register
2047 * MTLO1 rs Move To LO1 Register
2049 * Arithmetic (19 instructions)
2050 * ----------------------------
2051 * PADDB rd, rs, rt Parallel Add Byte
2052 * PSUBB rd, rs, rt Parallel Subtract Byte
2053 * PADDH rd, rs, rt Parallel Add Halfword
2054 * PSUBH rd, rs, rt Parallel Subtract Halfword
2055 * PADDW rd, rs, rt Parallel Add Word
2056 * PSUBW rd, rs, rt Parallel Subtract Word
2057 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2058 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2059 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2060 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2061 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2062 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2063 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2064 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2065 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2066 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2067 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2068 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2069 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2071 * Min/Max (4 instructions)
2072 * ------------------------
2073 * PMAXH rd, rs, rt Parallel Maximum Halfword
2074 * PMINH rd, rs, rt Parallel Minimum Halfword
2075 * PMAXW rd, rs, rt Parallel Maximum Word
2076 * PMINW rd, rs, rt Parallel Minimum Word
2078 * Absolute (2 instructions)
2079 * -------------------------
2080 * PABSH rd, rt Parallel Absolute Halfword
2081 * PABSW rd, rt Parallel Absolute Word
2083 * Logical (4 instructions)
2084 * ------------------------
2085 * PAND rd, rs, rt Parallel AND
2086 * POR rd, rs, rt Parallel OR
2087 * PXOR rd, rs, rt Parallel XOR
2088 * PNOR rd, rs, rt Parallel NOR
2090 * Shift (9 instructions)
2091 * ----------------------
2092 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2093 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2094 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2095 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2096 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2097 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2098 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2099 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2100 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2102 * Compare (6 instructions)
2103 * ------------------------
2104 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2105 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2106 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2107 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2108 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2109 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2111 * LZC (1 instruction)
2112 * -------------------
2113 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2115 * Quadword Load and Store (2 instructions)
2116 * ----------------------------------------
2117 * LQ rt, offset(base) Load Quadword
2118 * SQ rt, offset(base) Store Quadword
2120 * Multiply and Divide (19 instructions)
2121 * -------------------------------------
2122 * PMULTW rd, rs, rt Parallel Multiply Word
2123 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2124 * PDIVW rs, rt Parallel Divide Word
2125 * PDIVUW rs, rt Parallel Divide Unsigned Word
2126 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2127 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2128 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2129 * PMULTH rd, rs, rt Parallel Multiply Halfword
2130 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2131 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2132 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2133 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2134 * PDIVBW rs, rt Parallel Divide Broadcast Word
2135 * PMFHI rd Parallel Move From HI Register
2136 * PMFLO rd Parallel Move From LO Register
2137 * PMTHI rs Parallel Move To HI Register
2138 * PMTLO rs Parallel Move To LO Register
2139 * PMFHL rd Parallel Move From HI/LO Register
2140 * PMTHL rs Parallel Move To HI/LO Register
2142 * Pack/Extend (11 instructions)
2143 * -----------------------------
2144 * PPAC5 rd, rt Parallel Pack to 5 bits
2145 * PPACB rd, rs, rt Parallel Pack to Byte
2146 * PPACH rd, rs, rt Parallel Pack to Halfword
2147 * PPACW rd, rs, rt Parallel Pack to Word
2148 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2149 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2150 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2151 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2152 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2153 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2154 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2156 * Others (16 instructions)
2157 * ------------------------
2158 * PCPYH rd, rt Parallel Copy Halfword
2159 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2160 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2161 * PREVH rd, rt Parallel Reverse Halfword
2162 * PINTH rd, rs, rt Parallel Interleave Halfword
2163 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2164 * PEXEH rd, rt Parallel Exchange Even Halfword
2165 * PEXCH rd, rt Parallel Exchange Center Halfword
2166 * PEXEW rd, rt Parallel Exchange Even Word
2167 * PEXCW rd, rt Parallel Exchange Center Word
2168 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2169 * MFSA rd Move from Shift Amount Register
2170 * MTSA rs Move to Shift Amount Register
2171 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2172 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2173 * PROT3W rd, rt Parallel Rotate 3 Words
2175 * MMI (MultiMedia Instruction) encodings
2176 * ======================================
2178 * MMI instructions encoding table keys:
2180 * * This code is reserved for future use. An attempt to execute it
2181 * causes a Reserved Instruction exception.
2182 * % This code indicates an instruction class. The instruction word
2183 * must be further decoded by examining additional tables that show
2184 * the values for other instruction fields.
2185 * # This code is reserved for the unsupported instructions DMULT,
2186 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2187 * to execute it causes a Reserved Instruction exception.
2189 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2191 * 31 26 0
2192 * +--------+----------------------------------------+
2193 * | opcode | |
2194 * +--------+----------------------------------------+
2196 * opcode bits 28..26
2197 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2198 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2199 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2200 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2201 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2202 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2203 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2204 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2205 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2206 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2207 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2210 enum {
2211 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2212 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2213 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2217 * MMI instructions with opcode field = MMI:
2219 * 31 26 5 0
2220 * +--------+-------------------------------+--------+
2221 * | MMI | |function|
2222 * +--------+-------------------------------+--------+
2224 * function bits 2..0
2225 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2226 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2227 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2228 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2229 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2230 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2231 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2232 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2233 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2234 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2235 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2238 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2239 enum {
2240 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2241 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2242 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2243 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2244 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2245 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2246 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2247 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2248 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2249 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2250 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2251 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2252 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2253 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2254 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2255 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2256 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2268 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2270 * 31 26 10 6 5 0
2271 * +--------+----------------------+--------+--------+
2272 * | MMI | |function| MMI0 |
2273 * +--------+----------------------+--------+--------+
2275 * function bits 7..6
2276 * bits | 0 | 1 | 2 | 3
2277 * 10..8 | 00 | 01 | 10 | 11
2278 * -------+-------+-------+-------+-------
2279 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2280 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2281 * 2 010 | PADDB | PSUBB | PCGTB | *
2282 * 3 011 | * | * | * | *
2283 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2284 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2285 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2286 * 7 111 | * | * | PEXT5 | PPAC5
2289 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2290 enum {
2291 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2292 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2293 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2294 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2319 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2321 * 31 26 10 6 5 0
2322 * +--------+----------------------+--------+--------+
2323 * | MMI | |function| MMI1 |
2324 * +--------+----------------------+--------+--------+
2326 * function bits 7..6
2327 * bits | 0 | 1 | 2 | 3
2328 * 10..8 | 00 | 01 | 10 | 11
2329 * -------+-------+-------+-------+-------
2330 * 0 000 | * | PABSW | PCEQW | PMINW
2331 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2332 * 2 010 | * | * | PCEQB | *
2333 * 3 011 | * | * | * | *
2334 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2335 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2336 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2337 * 7 111 | * | * | * | *
2340 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2341 enum {
2342 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2343 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2344 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2345 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2363 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2365 * 31 26 10 6 5 0
2366 * +--------+----------------------+--------+--------+
2367 * | MMI | |function| MMI2 |
2368 * +--------+----------------------+--------+--------+
2370 * function bits 7..6
2371 * bits | 0 | 1 | 2 | 3
2372 * 10..8 | 00 | 01 | 10 | 11
2373 * -------+-------+-------+-------+-------
2374 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2375 * 1 001 | PMSUBW| * | * | *
2376 * 2 010 | PMFHI | PMFLO | PINTH | *
2377 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2378 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2379 * 5 101 | PMSUBH| PHMSBH| * | *
2380 * 6 110 | * | * | PEXEH | PREVH
2381 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2384 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2385 enum {
2386 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2387 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2388 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2389 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2411 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2413 * 31 26 10 6 5 0
2414 * +--------+----------------------+--------+--------+
2415 * | MMI | |function| MMI3 |
2416 * +--------+----------------------+--------+--------+
2418 * function bits 7..6
2419 * bits | 0 | 1 | 2 | 3
2420 * 10..8 | 00 | 01 | 10 | 11
2421 * -------+-------+-------+-------+-------
2422 * 0 000 |PMADDUW| * | * | PSRAVW
2423 * 1 001 | * | * | * | *
2424 * 2 010 | PMTHI | PMTLO | PINTEH| *
2425 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2426 * 4 100 | * | * | POR | PNOR
2427 * 5 101 | * | * | * | *
2428 * 6 110 | * | * | PEXCH | PCPYH
2429 * 7 111 | * | * | PEXCW | *
2432 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2433 enum {
2434 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2435 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2436 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2437 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2449 /* global register indices */
2450 static TCGv cpu_gpr[32], cpu_PC;
2451 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2452 static TCGv cpu_dspctrl, btarget, bcond;
2453 static TCGv cpu_lladdr, cpu_llval;
2454 static TCGv_i32 hflags;
2455 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2456 static TCGv_i64 fpu_f64[32];
2457 static TCGv_i64 msa_wr_d[64];
2459 #if defined(TARGET_MIPS64)
2460 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2461 static TCGv_i64 cpu_mmr[32];
2462 #endif
2464 #if !defined(TARGET_MIPS64)
2465 /* MXU registers */
2466 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2467 static TCGv mxu_CR;
2468 #endif
2470 #include "exec/gen-icount.h"
2472 #define gen_helper_0e0i(name, arg) do { \
2473 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2474 gen_helper_##name(cpu_env, helper_tmp); \
2475 tcg_temp_free_i32(helper_tmp); \
2476 } while(0)
2478 #define gen_helper_0e1i(name, arg1, arg2) do { \
2479 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2480 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2481 tcg_temp_free_i32(helper_tmp); \
2482 } while(0)
2484 #define gen_helper_1e0i(name, ret, arg1) do { \
2485 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2486 gen_helper_##name(ret, cpu_env, helper_tmp); \
2487 tcg_temp_free_i32(helper_tmp); \
2488 } while(0)
2490 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2491 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2492 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2493 tcg_temp_free_i32(helper_tmp); \
2494 } while(0)
2496 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2497 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2498 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2499 tcg_temp_free_i32(helper_tmp); \
2500 } while(0)
2502 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2503 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2504 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2505 tcg_temp_free_i32(helper_tmp); \
2506 } while(0)
2508 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2509 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2510 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2511 tcg_temp_free_i32(helper_tmp); \
2512 } while(0)
2514 typedef struct DisasContext {
2515 DisasContextBase base;
2516 target_ulong saved_pc;
2517 target_ulong page_start;
2518 uint32_t opcode;
2519 uint64_t insn_flags;
2520 int32_t CP0_Config1;
2521 int32_t CP0_Config2;
2522 int32_t CP0_Config3;
2523 int32_t CP0_Config5;
2524 /* Routine used to access memory */
2525 int mem_idx;
2526 TCGMemOp default_tcg_memop_mask;
2527 uint32_t hflags, saved_hflags;
2528 target_ulong btarget;
2529 bool ulri;
2530 int kscrexist;
2531 bool rxi;
2532 int ie;
2533 bool bi;
2534 bool bp;
2535 uint64_t PAMask;
2536 bool mvh;
2537 bool eva;
2538 bool sc;
2539 int CP0_LLAddr_shift;
2540 bool ps;
2541 bool vp;
2542 bool cmgcr;
2543 bool mrp;
2544 bool nan2008;
2545 bool abs2008;
2546 bool saar;
2547 } DisasContext;
2549 #define DISAS_STOP DISAS_TARGET_0
2550 #define DISAS_EXIT DISAS_TARGET_1
2552 static const char * const regnames[] = {
2553 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2554 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2555 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2556 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2559 static const char * const regnames_HI[] = {
2560 "HI0", "HI1", "HI2", "HI3",
2563 static const char * const regnames_LO[] = {
2564 "LO0", "LO1", "LO2", "LO3",
2567 static const char * const fregnames[] = {
2568 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2569 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2570 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2571 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2574 static const char * const msaregnames[] = {
2575 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2576 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2577 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2578 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2579 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2580 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2581 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2582 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2583 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2584 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2585 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2586 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2587 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2588 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2589 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2590 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2593 #if !defined(TARGET_MIPS64)
2594 static const char * const mxuregnames[] = {
2595 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2596 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2598 #endif
2600 #define LOG_DISAS(...) \
2601 do { \
2602 if (MIPS_DEBUG_DISAS) { \
2603 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2605 } while (0)
2607 #define MIPS_INVAL(op) \
2608 do { \
2609 if (MIPS_DEBUG_DISAS) { \
2610 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2611 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2612 ctx->base.pc_next, ctx->opcode, op, \
2613 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2614 ((ctx->opcode >> 16) & 0x1F)); \
2616 } while (0)
2618 /* General purpose registers moves. */
2619 static inline void gen_load_gpr (TCGv t, int reg)
2621 if (reg == 0)
2622 tcg_gen_movi_tl(t, 0);
2623 else
2624 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2627 static inline void gen_store_gpr (TCGv t, int reg)
2629 if (reg != 0)
2630 tcg_gen_mov_tl(cpu_gpr[reg], t);
2633 /* Moves to/from shadow registers. */
2634 static inline void gen_load_srsgpr (int from, int to)
2636 TCGv t0 = tcg_temp_new();
2638 if (from == 0)
2639 tcg_gen_movi_tl(t0, 0);
2640 else {
2641 TCGv_i32 t2 = tcg_temp_new_i32();
2642 TCGv_ptr addr = tcg_temp_new_ptr();
2644 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2645 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2646 tcg_gen_andi_i32(t2, t2, 0xf);
2647 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2648 tcg_gen_ext_i32_ptr(addr, t2);
2649 tcg_gen_add_ptr(addr, cpu_env, addr);
2651 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2652 tcg_temp_free_ptr(addr);
2653 tcg_temp_free_i32(t2);
2655 gen_store_gpr(t0, to);
2656 tcg_temp_free(t0);
2659 static inline void gen_store_srsgpr (int from, int to)
2661 if (to != 0) {
2662 TCGv t0 = tcg_temp_new();
2663 TCGv_i32 t2 = tcg_temp_new_i32();
2664 TCGv_ptr addr = tcg_temp_new_ptr();
2666 gen_load_gpr(t0, from);
2667 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2668 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2669 tcg_gen_andi_i32(t2, t2, 0xf);
2670 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2671 tcg_gen_ext_i32_ptr(addr, t2);
2672 tcg_gen_add_ptr(addr, cpu_env, addr);
2674 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2675 tcg_temp_free_ptr(addr);
2676 tcg_temp_free_i32(t2);
2677 tcg_temp_free(t0);
2681 #if !defined(TARGET_MIPS64)
2682 /* MXU General purpose registers moves. */
2683 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2685 if (reg == 0) {
2686 tcg_gen_movi_tl(t, 0);
2687 } else if (reg <= 15) {
2688 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2692 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2694 if (reg > 0 && reg <= 15) {
2695 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2699 /* MXU control register moves. */
2700 static inline void gen_load_mxu_cr(TCGv t)
2702 tcg_gen_mov_tl(t, mxu_CR);
2705 static inline void gen_store_mxu_cr(TCGv t)
2707 /* TODO: Add handling of RW rules for MXU_CR. */
2708 tcg_gen_mov_tl(mxu_CR, t);
2710 #endif
2713 /* Tests */
2714 static inline void gen_save_pc(target_ulong pc)
2716 tcg_gen_movi_tl(cpu_PC, pc);
2719 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2721 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2722 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2723 gen_save_pc(ctx->base.pc_next);
2724 ctx->saved_pc = ctx->base.pc_next;
2726 if (ctx->hflags != ctx->saved_hflags) {
2727 tcg_gen_movi_i32(hflags, ctx->hflags);
2728 ctx->saved_hflags = ctx->hflags;
2729 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2730 case MIPS_HFLAG_BR:
2731 break;
2732 case MIPS_HFLAG_BC:
2733 case MIPS_HFLAG_BL:
2734 case MIPS_HFLAG_B:
2735 tcg_gen_movi_tl(btarget, ctx->btarget);
2736 break;
2741 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2743 ctx->saved_hflags = ctx->hflags;
2744 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2745 case MIPS_HFLAG_BR:
2746 break;
2747 case MIPS_HFLAG_BC:
2748 case MIPS_HFLAG_BL:
2749 case MIPS_HFLAG_B:
2750 ctx->btarget = env->btarget;
2751 break;
2755 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2757 TCGv_i32 texcp = tcg_const_i32(excp);
2758 TCGv_i32 terr = tcg_const_i32(err);
2759 save_cpu_state(ctx, 1);
2760 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2761 tcg_temp_free_i32(terr);
2762 tcg_temp_free_i32(texcp);
2763 ctx->base.is_jmp = DISAS_NORETURN;
2766 static inline void generate_exception(DisasContext *ctx, int excp)
2768 gen_helper_0e0i(raise_exception, excp);
2771 static inline void generate_exception_end(DisasContext *ctx, int excp)
2773 generate_exception_err(ctx, excp, 0);
2776 /* Floating point register moves. */
2777 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2779 if (ctx->hflags & MIPS_HFLAG_FRE) {
2780 generate_exception(ctx, EXCP_RI);
2782 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2785 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2787 TCGv_i64 t64;
2788 if (ctx->hflags & MIPS_HFLAG_FRE) {
2789 generate_exception(ctx, EXCP_RI);
2791 t64 = tcg_temp_new_i64();
2792 tcg_gen_extu_i32_i64(t64, t);
2793 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2794 tcg_temp_free_i64(t64);
2797 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2799 if (ctx->hflags & MIPS_HFLAG_F64) {
2800 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2801 } else {
2802 gen_load_fpr32(ctx, t, reg | 1);
2806 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2808 if (ctx->hflags & MIPS_HFLAG_F64) {
2809 TCGv_i64 t64 = tcg_temp_new_i64();
2810 tcg_gen_extu_i32_i64(t64, t);
2811 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2812 tcg_temp_free_i64(t64);
2813 } else {
2814 gen_store_fpr32(ctx, t, reg | 1);
2818 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2820 if (ctx->hflags & MIPS_HFLAG_F64) {
2821 tcg_gen_mov_i64(t, fpu_f64[reg]);
2822 } else {
2823 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2827 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2829 if (ctx->hflags & MIPS_HFLAG_F64) {
2830 tcg_gen_mov_i64(fpu_f64[reg], t);
2831 } else {
2832 TCGv_i64 t0;
2833 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2834 t0 = tcg_temp_new_i64();
2835 tcg_gen_shri_i64(t0, t, 32);
2836 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2837 tcg_temp_free_i64(t0);
2841 static inline int get_fp_bit (int cc)
2843 if (cc)
2844 return 24 + cc;
2845 else
2846 return 23;
2849 /* Addresses computation */
2850 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2852 tcg_gen_add_tl(ret, arg0, arg1);
2854 #if defined(TARGET_MIPS64)
2855 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2856 tcg_gen_ext32s_i64(ret, ret);
2858 #endif
2861 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2862 target_long ofs)
2864 tcg_gen_addi_tl(ret, base, ofs);
2866 #if defined(TARGET_MIPS64)
2867 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2868 tcg_gen_ext32s_i64(ret, ret);
2870 #endif
2873 /* Addresses computation (translation time) */
2874 static target_long addr_add(DisasContext *ctx, target_long base,
2875 target_long offset)
2877 target_long sum = base + offset;
2879 #if defined(TARGET_MIPS64)
2880 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2881 sum = (int32_t)sum;
2883 #endif
2884 return sum;
2887 /* Sign-extract the low 32-bits to a target_long. */
2888 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2890 #if defined(TARGET_MIPS64)
2891 tcg_gen_ext32s_i64(ret, arg);
2892 #else
2893 tcg_gen_extrl_i64_i32(ret, arg);
2894 #endif
2897 /* Sign-extract the high 32-bits to a target_long. */
2898 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2900 #if defined(TARGET_MIPS64)
2901 tcg_gen_sari_i64(ret, arg, 32);
2902 #else
2903 tcg_gen_extrh_i64_i32(ret, arg);
2904 #endif
2907 static inline void check_cp0_enabled(DisasContext *ctx)
2909 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2910 generate_exception_err(ctx, EXCP_CpU, 0);
2913 static inline void check_cp1_enabled(DisasContext *ctx)
2915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2916 generate_exception_err(ctx, EXCP_CpU, 1);
2919 /* Verify that the processor is running with COP1X instructions enabled.
2920 This is associated with the nabla symbol in the MIPS32 and MIPS64
2921 opcode tables. */
2923 static inline void check_cop1x(DisasContext *ctx)
2925 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2926 generate_exception_end(ctx, EXCP_RI);
2929 /* Verify that the processor is running with 64-bit floating-point
2930 operations enabled. */
2932 static inline void check_cp1_64bitmode(DisasContext *ctx)
2934 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2935 generate_exception_end(ctx, EXCP_RI);
2939 * Verify if floating point register is valid; an operation is not defined
2940 * if bit 0 of any register specification is set and the FR bit in the
2941 * Status register equals zero, since the register numbers specify an
2942 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2943 * in the Status register equals one, both even and odd register numbers
2944 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2946 * Multiple 64 bit wide registers can be checked by calling
2947 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2949 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2951 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2952 generate_exception_end(ctx, EXCP_RI);
2955 /* Verify that the processor is running with DSP instructions enabled.
2956 This is enabled by CP0 Status register MX(24) bit.
2959 static inline void check_dsp(DisasContext *ctx)
2961 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2962 if (ctx->insn_flags & ASE_DSP) {
2963 generate_exception_end(ctx, EXCP_DSPDIS);
2964 } else {
2965 generate_exception_end(ctx, EXCP_RI);
2970 static inline void check_dsp_r2(DisasContext *ctx)
2972 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2973 if (ctx->insn_flags & ASE_DSP) {
2974 generate_exception_end(ctx, EXCP_DSPDIS);
2975 } else {
2976 generate_exception_end(ctx, EXCP_RI);
2981 static inline void check_dsp_r3(DisasContext *ctx)
2983 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2984 if (ctx->insn_flags & ASE_DSP) {
2985 generate_exception_end(ctx, EXCP_DSPDIS);
2986 } else {
2987 generate_exception_end(ctx, EXCP_RI);
2992 /* This code generates a "reserved instruction" exception if the
2993 CPU does not support the instruction set corresponding to flags. */
2994 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2996 if (unlikely(!(ctx->insn_flags & flags))) {
2997 generate_exception_end(ctx, EXCP_RI);
3001 /* This code generates a "reserved instruction" exception if the
3002 CPU has corresponding flag set which indicates that the instruction
3003 has been removed. */
3004 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3006 if (unlikely(ctx->insn_flags & flags)) {
3007 generate_exception_end(ctx, EXCP_RI);
3012 * The Linux kernel traps certain reserved instruction exceptions to
3013 * emulate the corresponding instructions. QEMU is the kernel in user
3014 * mode, so those traps are emulated by accepting the instructions.
3016 * A reserved instruction exception is generated for flagged CPUs if
3017 * QEMU runs in system mode.
3019 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3021 #ifndef CONFIG_USER_ONLY
3022 check_insn_opc_removed(ctx, flags);
3023 #endif
3026 /* This code generates a "reserved instruction" exception if the
3027 CPU does not support 64-bit paired-single (PS) floating point data type */
3028 static inline void check_ps(DisasContext *ctx)
3030 if (unlikely(!ctx->ps)) {
3031 generate_exception(ctx, EXCP_RI);
3033 check_cp1_64bitmode(ctx);
3036 #ifdef TARGET_MIPS64
3037 /* This code generates a "reserved instruction" exception if 64-bit
3038 instructions are not enabled. */
3039 static inline void check_mips_64(DisasContext *ctx)
3041 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
3042 generate_exception_end(ctx, EXCP_RI);
3044 #endif
3046 #ifndef CONFIG_USER_ONLY
3047 static inline void check_mvh(DisasContext *ctx)
3049 if (unlikely(!ctx->mvh)) {
3050 generate_exception(ctx, EXCP_RI);
3053 #endif
3056 * This code generates a "reserved instruction" exception if the
3057 * Config5 XNP bit is set.
3059 static inline void check_xnp(DisasContext *ctx)
3061 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3062 generate_exception_end(ctx, EXCP_RI);
3066 #ifndef CONFIG_USER_ONLY
3068 * This code generates a "reserved instruction" exception if the
3069 * Config3 PW bit is NOT set.
3071 static inline void check_pw(DisasContext *ctx)
3073 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3074 generate_exception_end(ctx, EXCP_RI);
3077 #endif
3080 * This code generates a "reserved instruction" exception if the
3081 * Config3 MT bit is NOT set.
3083 static inline void check_mt(DisasContext *ctx)
3085 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3086 generate_exception_end(ctx, EXCP_RI);
3090 #ifndef CONFIG_USER_ONLY
3092 * This code generates a "coprocessor unusable" exception if CP0 is not
3093 * available, and, if that is not the case, generates a "reserved instruction"
3094 * exception if the Config5 MT bit is NOT set. This is needed for availability
3095 * control of some of MT ASE instructions.
3097 static inline void check_cp0_mt(DisasContext *ctx)
3099 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3100 generate_exception_err(ctx, EXCP_CpU, 0);
3101 } else {
3102 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3103 generate_exception_err(ctx, EXCP_RI, 0);
3107 #endif
3110 * This code generates a "reserved instruction" exception if the
3111 * Config5 NMS bit is set.
3113 static inline void check_nms(DisasContext *ctx)
3115 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3116 generate_exception_end(ctx, EXCP_RI);
3121 * This code generates a "reserved instruction" exception if the
3122 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3123 * Config2 TL, and Config5 L2C are unset.
3125 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3127 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3128 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3129 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3130 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3131 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3132 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3134 generate_exception_end(ctx, EXCP_RI);
3139 * This code generates a "reserved instruction" exception if the
3140 * Config5 EVA bit is NOT set.
3142 static inline void check_eva(DisasContext *ctx)
3144 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3145 generate_exception_end(ctx, EXCP_RI);
3150 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3151 calling interface for 32 and 64-bit FPRs. No sense in changing
3152 all callers for gen_load_fpr32 when we need the CTX parameter for
3153 this one use. */
3154 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3155 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3156 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3157 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3158 int ft, int fs, int cc) \
3160 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3161 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3162 switch (ifmt) { \
3163 case FMT_PS: \
3164 check_ps(ctx); \
3165 break; \
3166 case FMT_D: \
3167 if (abs) { \
3168 check_cop1x(ctx); \
3170 check_cp1_registers(ctx, fs | ft); \
3171 break; \
3172 case FMT_S: \
3173 if (abs) { \
3174 check_cop1x(ctx); \
3176 break; \
3178 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3179 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3180 switch (n) { \
3181 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3182 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3183 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3184 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3185 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3186 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3187 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3188 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3189 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3190 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3191 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3192 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3193 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3194 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3195 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3196 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3197 default: abort(); \
3199 tcg_temp_free_i##bits (fp0); \
3200 tcg_temp_free_i##bits (fp1); \
3203 FOP_CONDS(, 0, d, FMT_D, 64)
3204 FOP_CONDS(abs, 1, d, FMT_D, 64)
3205 FOP_CONDS(, 0, s, FMT_S, 32)
3206 FOP_CONDS(abs, 1, s, FMT_S, 32)
3207 FOP_CONDS(, 0, ps, FMT_PS, 64)
3208 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3209 #undef FOP_CONDS
3211 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3212 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3213 int ft, int fs, int fd) \
3215 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3216 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3217 if (ifmt == FMT_D) { \
3218 check_cp1_registers(ctx, fs | ft | fd); \
3220 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3221 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3222 switch (n) { \
3223 case 0: \
3224 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3225 break; \
3226 case 1: \
3227 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3228 break; \
3229 case 2: \
3230 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3231 break; \
3232 case 3: \
3233 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3234 break; \
3235 case 4: \
3236 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3237 break; \
3238 case 5: \
3239 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3240 break; \
3241 case 6: \
3242 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3243 break; \
3244 case 7: \
3245 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3246 break; \
3247 case 8: \
3248 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3249 break; \
3250 case 9: \
3251 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3252 break; \
3253 case 10: \
3254 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3255 break; \
3256 case 11: \
3257 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3258 break; \
3259 case 12: \
3260 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3261 break; \
3262 case 13: \
3263 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3264 break; \
3265 case 14: \
3266 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3267 break; \
3268 case 15: \
3269 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3270 break; \
3271 case 17: \
3272 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3273 break; \
3274 case 18: \
3275 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3276 break; \
3277 case 19: \
3278 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3279 break; \
3280 case 25: \
3281 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3282 break; \
3283 case 26: \
3284 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 27: \
3287 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 default: \
3290 abort(); \
3292 STORE; \
3293 tcg_temp_free_i ## bits (fp0); \
3294 tcg_temp_free_i ## bits (fp1); \
3297 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3298 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3299 #undef FOP_CONDNS
3300 #undef gen_ldcmp_fpr32
3301 #undef gen_ldcmp_fpr64
3303 /* load/store instructions. */
3304 #ifdef CONFIG_USER_ONLY
3305 #define OP_LD_ATOMIC(insn,fname) \
3306 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3307 DisasContext *ctx) \
3309 TCGv t0 = tcg_temp_new(); \
3310 tcg_gen_mov_tl(t0, arg1); \
3311 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3312 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3313 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3314 tcg_temp_free(t0); \
3316 #else
3317 #define OP_LD_ATOMIC(insn,fname) \
3318 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3319 DisasContext *ctx) \
3321 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3323 #endif
3324 OP_LD_ATOMIC(ll,ld32s);
3325 #if defined(TARGET_MIPS64)
3326 OP_LD_ATOMIC(lld,ld64);
3327 #endif
3328 #undef OP_LD_ATOMIC
3330 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3331 int base, int offset)
3333 if (base == 0) {
3334 tcg_gen_movi_tl(addr, offset);
3335 } else if (offset == 0) {
3336 gen_load_gpr(addr, base);
3337 } else {
3338 tcg_gen_movi_tl(addr, offset);
3339 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3343 static target_ulong pc_relative_pc (DisasContext *ctx)
3345 target_ulong pc = ctx->base.pc_next;
3347 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3348 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3350 pc -= branch_bytes;
3353 pc &= ~(target_ulong)3;
3354 return pc;
3357 /* Load */
3358 static void gen_ld(DisasContext *ctx, uint32_t opc,
3359 int rt, int base, int offset)
3361 TCGv t0, t1, t2;
3362 int mem_idx = ctx->mem_idx;
3364 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3365 /* Loongson CPU uses a load to zero register for prefetch.
3366 We emulate it as a NOP. On other CPU we must perform the
3367 actual memory access. */
3368 return;
3371 t0 = tcg_temp_new();
3372 gen_base_offset_addr(ctx, t0, base, offset);
3374 switch (opc) {
3375 #if defined(TARGET_MIPS64)
3376 case OPC_LWU:
3377 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3378 ctx->default_tcg_memop_mask);
3379 gen_store_gpr(t0, rt);
3380 break;
3381 case OPC_LD:
3382 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3383 ctx->default_tcg_memop_mask);
3384 gen_store_gpr(t0, rt);
3385 break;
3386 case OPC_LLD:
3387 case R6_OPC_LLD:
3388 op_ld_lld(t0, t0, mem_idx, ctx);
3389 gen_store_gpr(t0, rt);
3390 break;
3391 case OPC_LDL:
3392 t1 = tcg_temp_new();
3393 /* Do a byte access to possibly trigger a page
3394 fault with the unaligned address. */
3395 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3396 tcg_gen_andi_tl(t1, t0, 7);
3397 #ifndef TARGET_WORDS_BIGENDIAN
3398 tcg_gen_xori_tl(t1, t1, 7);
3399 #endif
3400 tcg_gen_shli_tl(t1, t1, 3);
3401 tcg_gen_andi_tl(t0, t0, ~7);
3402 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3403 tcg_gen_shl_tl(t0, t0, t1);
3404 t2 = tcg_const_tl(-1);
3405 tcg_gen_shl_tl(t2, t2, t1);
3406 gen_load_gpr(t1, rt);
3407 tcg_gen_andc_tl(t1, t1, t2);
3408 tcg_temp_free(t2);
3409 tcg_gen_or_tl(t0, t0, t1);
3410 tcg_temp_free(t1);
3411 gen_store_gpr(t0, rt);
3412 break;
3413 case OPC_LDR:
3414 t1 = tcg_temp_new();
3415 /* Do a byte access to possibly trigger a page
3416 fault with the unaligned address. */
3417 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3418 tcg_gen_andi_tl(t1, t0, 7);
3419 #ifdef TARGET_WORDS_BIGENDIAN
3420 tcg_gen_xori_tl(t1, t1, 7);
3421 #endif
3422 tcg_gen_shli_tl(t1, t1, 3);
3423 tcg_gen_andi_tl(t0, t0, ~7);
3424 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3425 tcg_gen_shr_tl(t0, t0, t1);
3426 tcg_gen_xori_tl(t1, t1, 63);
3427 t2 = tcg_const_tl(0xfffffffffffffffeull);
3428 tcg_gen_shl_tl(t2, t2, t1);
3429 gen_load_gpr(t1, rt);
3430 tcg_gen_and_tl(t1, t1, t2);
3431 tcg_temp_free(t2);
3432 tcg_gen_or_tl(t0, t0, t1);
3433 tcg_temp_free(t1);
3434 gen_store_gpr(t0, rt);
3435 break;
3436 case OPC_LDPC:
3437 t1 = tcg_const_tl(pc_relative_pc(ctx));
3438 gen_op_addr_add(ctx, t0, t0, t1);
3439 tcg_temp_free(t1);
3440 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3441 gen_store_gpr(t0, rt);
3442 break;
3443 #endif
3444 case OPC_LWPC:
3445 t1 = tcg_const_tl(pc_relative_pc(ctx));
3446 gen_op_addr_add(ctx, t0, t0, t1);
3447 tcg_temp_free(t1);
3448 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3449 gen_store_gpr(t0, rt);
3450 break;
3451 case OPC_LWE:
3452 mem_idx = MIPS_HFLAG_UM;
3453 /* fall through */
3454 case OPC_LW:
3455 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3456 ctx->default_tcg_memop_mask);
3457 gen_store_gpr(t0, rt);
3458 break;
3459 case OPC_LHE:
3460 mem_idx = MIPS_HFLAG_UM;
3461 /* fall through */
3462 case OPC_LH:
3463 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3464 ctx->default_tcg_memop_mask);
3465 gen_store_gpr(t0, rt);
3466 break;
3467 case OPC_LHUE:
3468 mem_idx = MIPS_HFLAG_UM;
3469 /* fall through */
3470 case OPC_LHU:
3471 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3472 ctx->default_tcg_memop_mask);
3473 gen_store_gpr(t0, rt);
3474 break;
3475 case OPC_LBE:
3476 mem_idx = MIPS_HFLAG_UM;
3477 /* fall through */
3478 case OPC_LB:
3479 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3480 gen_store_gpr(t0, rt);
3481 break;
3482 case OPC_LBUE:
3483 mem_idx = MIPS_HFLAG_UM;
3484 /* fall through */
3485 case OPC_LBU:
3486 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3487 gen_store_gpr(t0, rt);
3488 break;
3489 case OPC_LWLE:
3490 mem_idx = MIPS_HFLAG_UM;
3491 /* fall through */
3492 case OPC_LWL:
3493 t1 = tcg_temp_new();
3494 /* Do a byte access to possibly trigger a page
3495 fault with the unaligned address. */
3496 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3497 tcg_gen_andi_tl(t1, t0, 3);
3498 #ifndef TARGET_WORDS_BIGENDIAN
3499 tcg_gen_xori_tl(t1, t1, 3);
3500 #endif
3501 tcg_gen_shli_tl(t1, t1, 3);
3502 tcg_gen_andi_tl(t0, t0, ~3);
3503 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3504 tcg_gen_shl_tl(t0, t0, t1);
3505 t2 = tcg_const_tl(-1);
3506 tcg_gen_shl_tl(t2, t2, t1);
3507 gen_load_gpr(t1, rt);
3508 tcg_gen_andc_tl(t1, t1, t2);
3509 tcg_temp_free(t2);
3510 tcg_gen_or_tl(t0, t0, t1);
3511 tcg_temp_free(t1);
3512 tcg_gen_ext32s_tl(t0, t0);
3513 gen_store_gpr(t0, rt);
3514 break;
3515 case OPC_LWRE:
3516 mem_idx = MIPS_HFLAG_UM;
3517 /* fall through */
3518 case OPC_LWR:
3519 t1 = tcg_temp_new();
3520 /* Do a byte access to possibly trigger a page
3521 fault with the unaligned address. */
3522 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3523 tcg_gen_andi_tl(t1, t0, 3);
3524 #ifdef TARGET_WORDS_BIGENDIAN
3525 tcg_gen_xori_tl(t1, t1, 3);
3526 #endif
3527 tcg_gen_shli_tl(t1, t1, 3);
3528 tcg_gen_andi_tl(t0, t0, ~3);
3529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3530 tcg_gen_shr_tl(t0, t0, t1);
3531 tcg_gen_xori_tl(t1, t1, 31);
3532 t2 = tcg_const_tl(0xfffffffeull);
3533 tcg_gen_shl_tl(t2, t2, t1);
3534 gen_load_gpr(t1, rt);
3535 tcg_gen_and_tl(t1, t1, t2);
3536 tcg_temp_free(t2);
3537 tcg_gen_or_tl(t0, t0, t1);
3538 tcg_temp_free(t1);
3539 tcg_gen_ext32s_tl(t0, t0);
3540 gen_store_gpr(t0, rt);
3541 break;
3542 case OPC_LLE:
3543 mem_idx = MIPS_HFLAG_UM;
3544 /* fall through */
3545 case OPC_LL:
3546 case R6_OPC_LL:
3547 op_ld_ll(t0, t0, mem_idx, ctx);
3548 gen_store_gpr(t0, rt);
3549 break;
3551 tcg_temp_free(t0);
3554 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3555 uint32_t reg1, uint32_t reg2)
3557 TCGv taddr = tcg_temp_new();
3558 TCGv_i64 tval = tcg_temp_new_i64();
3559 TCGv tmp1 = tcg_temp_new();
3560 TCGv tmp2 = tcg_temp_new();
3562 gen_base_offset_addr(ctx, taddr, base, offset);
3563 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3564 #ifdef TARGET_WORDS_BIGENDIAN
3565 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3566 #else
3567 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3568 #endif
3569 gen_store_gpr(tmp1, reg1);
3570 tcg_temp_free(tmp1);
3571 gen_store_gpr(tmp2, reg2);
3572 tcg_temp_free(tmp2);
3573 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3574 tcg_temp_free_i64(tval);
3575 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3576 tcg_temp_free(taddr);
3579 /* Store */
3580 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3581 int base, int offset)
3583 TCGv t0 = tcg_temp_new();
3584 TCGv t1 = tcg_temp_new();
3585 int mem_idx = ctx->mem_idx;
3587 gen_base_offset_addr(ctx, t0, base, offset);
3588 gen_load_gpr(t1, rt);
3589 switch (opc) {
3590 #if defined(TARGET_MIPS64)
3591 case OPC_SD:
3592 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3593 ctx->default_tcg_memop_mask);
3594 break;
3595 case OPC_SDL:
3596 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3597 break;
3598 case OPC_SDR:
3599 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3600 break;
3601 #endif
3602 case OPC_SWE:
3603 mem_idx = MIPS_HFLAG_UM;
3604 /* fall through */
3605 case OPC_SW:
3606 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3607 ctx->default_tcg_memop_mask);
3608 break;
3609 case OPC_SHE:
3610 mem_idx = MIPS_HFLAG_UM;
3611 /* fall through */
3612 case OPC_SH:
3613 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3614 ctx->default_tcg_memop_mask);
3615 break;
3616 case OPC_SBE:
3617 mem_idx = MIPS_HFLAG_UM;
3618 /* fall through */
3619 case OPC_SB:
3620 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3621 break;
3622 case OPC_SWLE:
3623 mem_idx = MIPS_HFLAG_UM;
3624 /* fall through */
3625 case OPC_SWL:
3626 gen_helper_0e2i(swl, t1, t0, mem_idx);
3627 break;
3628 case OPC_SWRE:
3629 mem_idx = MIPS_HFLAG_UM;
3630 /* fall through */
3631 case OPC_SWR:
3632 gen_helper_0e2i(swr, t1, t0, mem_idx);
3633 break;
3635 tcg_temp_free(t0);
3636 tcg_temp_free(t1);
3640 /* Store conditional */
3641 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3642 TCGMemOp tcg_mo, bool eva)
3644 TCGv addr, t0, val;
3645 TCGLabel *l1 = gen_new_label();
3646 TCGLabel *done = gen_new_label();
3648 t0 = tcg_temp_new();
3649 addr = tcg_temp_new();
3650 /* compare the address against that of the preceeding LL */
3651 gen_base_offset_addr(ctx, addr, base, offset);
3652 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3653 tcg_temp_free(addr);
3654 tcg_gen_movi_tl(t0, 0);
3655 gen_store_gpr(t0, rt);
3656 tcg_gen_br(done);
3658 gen_set_label(l1);
3659 /* generate cmpxchg */
3660 val = tcg_temp_new();
3661 gen_load_gpr(val, rt);
3662 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3663 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3664 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3665 gen_store_gpr(t0, rt);
3666 tcg_temp_free(val);
3668 gen_set_label(done);
3669 tcg_temp_free(t0);
3673 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3674 uint32_t reg1, uint32_t reg2, bool eva)
3676 TCGv taddr = tcg_temp_local_new();
3677 TCGv lladdr = tcg_temp_local_new();
3678 TCGv_i64 tval = tcg_temp_new_i64();
3679 TCGv_i64 llval = tcg_temp_new_i64();
3680 TCGv_i64 val = tcg_temp_new_i64();
3681 TCGv tmp1 = tcg_temp_new();
3682 TCGv tmp2 = tcg_temp_new();
3683 TCGLabel *lab_fail = gen_new_label();
3684 TCGLabel *lab_done = gen_new_label();
3686 gen_base_offset_addr(ctx, taddr, base, offset);
3688 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3689 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3691 gen_load_gpr(tmp1, reg1);
3692 gen_load_gpr(tmp2, reg2);
3694 #ifdef TARGET_WORDS_BIGENDIAN
3695 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3696 #else
3697 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3698 #endif
3700 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3701 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3702 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3703 if (reg1 != 0) {
3704 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3706 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3708 gen_set_label(lab_fail);
3710 if (reg1 != 0) {
3711 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3713 gen_set_label(lab_done);
3714 tcg_gen_movi_tl(lladdr, -1);
3715 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3718 /* Load and store */
3719 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3720 TCGv t0)
3722 /* Don't do NOP if destination is zero: we must perform the actual
3723 memory access. */
3724 switch (opc) {
3725 case OPC_LWC1:
3727 TCGv_i32 fp0 = tcg_temp_new_i32();
3728 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3729 ctx->default_tcg_memop_mask);
3730 gen_store_fpr32(ctx, fp0, ft);
3731 tcg_temp_free_i32(fp0);
3733 break;
3734 case OPC_SWC1:
3736 TCGv_i32 fp0 = tcg_temp_new_i32();
3737 gen_load_fpr32(ctx, fp0, ft);
3738 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3739 ctx->default_tcg_memop_mask);
3740 tcg_temp_free_i32(fp0);
3742 break;
3743 case OPC_LDC1:
3745 TCGv_i64 fp0 = tcg_temp_new_i64();
3746 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3747 ctx->default_tcg_memop_mask);
3748 gen_store_fpr64(ctx, fp0, ft);
3749 tcg_temp_free_i64(fp0);
3751 break;
3752 case OPC_SDC1:
3754 TCGv_i64 fp0 = tcg_temp_new_i64();
3755 gen_load_fpr64(ctx, fp0, ft);
3756 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3757 ctx->default_tcg_memop_mask);
3758 tcg_temp_free_i64(fp0);
3760 break;
3761 default:
3762 MIPS_INVAL("flt_ldst");
3763 generate_exception_end(ctx, EXCP_RI);
3764 break;
3768 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3769 int rs, int16_t imm)
3771 TCGv t0 = tcg_temp_new();
3773 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3774 check_cp1_enabled(ctx);
3775 switch (op) {
3776 case OPC_LDC1:
3777 case OPC_SDC1:
3778 check_insn(ctx, ISA_MIPS2);
3779 /* Fallthrough */
3780 default:
3781 gen_base_offset_addr(ctx, t0, rs, imm);
3782 gen_flt_ldst(ctx, op, rt, t0);
3784 } else {
3785 generate_exception_err(ctx, EXCP_CpU, 1);
3787 tcg_temp_free(t0);
3790 /* Arithmetic with immediate operand */
3791 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3792 int rt, int rs, int imm)
3794 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3796 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3797 /* If no destination, treat it as a NOP.
3798 For addi, we must generate the overflow exception when needed. */
3799 return;
3801 switch (opc) {
3802 case OPC_ADDI:
3804 TCGv t0 = tcg_temp_local_new();
3805 TCGv t1 = tcg_temp_new();
3806 TCGv t2 = tcg_temp_new();
3807 TCGLabel *l1 = gen_new_label();
3809 gen_load_gpr(t1, rs);
3810 tcg_gen_addi_tl(t0, t1, uimm);
3811 tcg_gen_ext32s_tl(t0, t0);
3813 tcg_gen_xori_tl(t1, t1, ~uimm);
3814 tcg_gen_xori_tl(t2, t0, uimm);
3815 tcg_gen_and_tl(t1, t1, t2);
3816 tcg_temp_free(t2);
3817 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3818 tcg_temp_free(t1);
3819 /* operands of same sign, result different sign */
3820 generate_exception(ctx, EXCP_OVERFLOW);
3821 gen_set_label(l1);
3822 tcg_gen_ext32s_tl(t0, t0);
3823 gen_store_gpr(t0, rt);
3824 tcg_temp_free(t0);
3826 break;
3827 case OPC_ADDIU:
3828 if (rs != 0) {
3829 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3830 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3831 } else {
3832 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3834 break;
3835 #if defined(TARGET_MIPS64)
3836 case OPC_DADDI:
3838 TCGv t0 = tcg_temp_local_new();
3839 TCGv t1 = tcg_temp_new();
3840 TCGv t2 = tcg_temp_new();
3841 TCGLabel *l1 = gen_new_label();
3843 gen_load_gpr(t1, rs);
3844 tcg_gen_addi_tl(t0, t1, uimm);
3846 tcg_gen_xori_tl(t1, t1, ~uimm);
3847 tcg_gen_xori_tl(t2, t0, uimm);
3848 tcg_gen_and_tl(t1, t1, t2);
3849 tcg_temp_free(t2);
3850 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3851 tcg_temp_free(t1);
3852 /* operands of same sign, result different sign */
3853 generate_exception(ctx, EXCP_OVERFLOW);
3854 gen_set_label(l1);
3855 gen_store_gpr(t0, rt);
3856 tcg_temp_free(t0);
3858 break;
3859 case OPC_DADDIU:
3860 if (rs != 0) {
3861 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3862 } else {
3863 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3865 break;
3866 #endif
3870 /* Logic with immediate operand */
3871 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3872 int rt, int rs, int16_t imm)
3874 target_ulong uimm;
3876 if (rt == 0) {
3877 /* If no destination, treat it as a NOP. */
3878 return;
3880 uimm = (uint16_t)imm;
3881 switch (opc) {
3882 case OPC_ANDI:
3883 if (likely(rs != 0))
3884 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3885 else
3886 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3887 break;
3888 case OPC_ORI:
3889 if (rs != 0)
3890 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3891 else
3892 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3893 break;
3894 case OPC_XORI:
3895 if (likely(rs != 0))
3896 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3897 else
3898 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3899 break;
3900 case OPC_LUI:
3901 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3902 /* OPC_AUI */
3903 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3904 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3908 break;
3910 default:
3911 break;
3915 /* Set on less than with immediate operand */
3916 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3917 int rt, int rs, int16_t imm)
3919 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3920 TCGv t0;
3922 if (rt == 0) {
3923 /* If no destination, treat it as a NOP. */
3924 return;
3926 t0 = tcg_temp_new();
3927 gen_load_gpr(t0, rs);
3928 switch (opc) {
3929 case OPC_SLTI:
3930 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3931 break;
3932 case OPC_SLTIU:
3933 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3934 break;
3936 tcg_temp_free(t0);
3939 /* Shifts with immediate operand */
3940 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3941 int rt, int rs, int16_t imm)
3943 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3944 TCGv t0;
3946 if (rt == 0) {
3947 /* If no destination, treat it as a NOP. */
3948 return;
3951 t0 = tcg_temp_new();
3952 gen_load_gpr(t0, rs);
3953 switch (opc) {
3954 case OPC_SLL:
3955 tcg_gen_shli_tl(t0, t0, uimm);
3956 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3957 break;
3958 case OPC_SRA:
3959 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3960 break;
3961 case OPC_SRL:
3962 if (uimm != 0) {
3963 tcg_gen_ext32u_tl(t0, t0);
3964 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3965 } else {
3966 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3968 break;
3969 case OPC_ROTR:
3970 if (uimm != 0) {
3971 TCGv_i32 t1 = tcg_temp_new_i32();
3973 tcg_gen_trunc_tl_i32(t1, t0);
3974 tcg_gen_rotri_i32(t1, t1, uimm);
3975 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3976 tcg_temp_free_i32(t1);
3977 } else {
3978 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3980 break;
3981 #if defined(TARGET_MIPS64)
3982 case OPC_DSLL:
3983 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3984 break;
3985 case OPC_DSRA:
3986 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3987 break;
3988 case OPC_DSRL:
3989 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3990 break;
3991 case OPC_DROTR:
3992 if (uimm != 0) {
3993 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3994 } else {
3995 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3997 break;
3998 case OPC_DSLL32:
3999 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4000 break;
4001 case OPC_DSRA32:
4002 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4003 break;
4004 case OPC_DSRL32:
4005 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4006 break;
4007 case OPC_DROTR32:
4008 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4009 break;
4010 #endif
4012 tcg_temp_free(t0);
4015 /* Arithmetic */
4016 static void gen_arith(DisasContext *ctx, uint32_t opc,
4017 int rd, int rs, int rt)
4019 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4020 && opc != OPC_DADD && opc != OPC_DSUB) {
4021 /* If no destination, treat it as a NOP.
4022 For add & sub, we must generate the overflow exception when needed. */
4023 return;
4026 switch (opc) {
4027 case OPC_ADD:
4029 TCGv t0 = tcg_temp_local_new();
4030 TCGv t1 = tcg_temp_new();
4031 TCGv t2 = tcg_temp_new();
4032 TCGLabel *l1 = gen_new_label();
4034 gen_load_gpr(t1, rs);
4035 gen_load_gpr(t2, rt);
4036 tcg_gen_add_tl(t0, t1, t2);
4037 tcg_gen_ext32s_tl(t0, t0);
4038 tcg_gen_xor_tl(t1, t1, t2);
4039 tcg_gen_xor_tl(t2, t0, t2);
4040 tcg_gen_andc_tl(t1, t2, t1);
4041 tcg_temp_free(t2);
4042 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4043 tcg_temp_free(t1);
4044 /* operands of same sign, result different sign */
4045 generate_exception(ctx, EXCP_OVERFLOW);
4046 gen_set_label(l1);
4047 gen_store_gpr(t0, rd);
4048 tcg_temp_free(t0);
4050 break;
4051 case OPC_ADDU:
4052 if (rs != 0 && rt != 0) {
4053 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4054 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4055 } else if (rs == 0 && rt != 0) {
4056 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4057 } else if (rs != 0 && rt == 0) {
4058 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4059 } else {
4060 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4062 break;
4063 case OPC_SUB:
4065 TCGv t0 = tcg_temp_local_new();
4066 TCGv t1 = tcg_temp_new();
4067 TCGv t2 = tcg_temp_new();
4068 TCGLabel *l1 = gen_new_label();
4070 gen_load_gpr(t1, rs);
4071 gen_load_gpr(t2, rt);
4072 tcg_gen_sub_tl(t0, t1, t2);
4073 tcg_gen_ext32s_tl(t0, t0);
4074 tcg_gen_xor_tl(t2, t1, t2);
4075 tcg_gen_xor_tl(t1, t0, t1);
4076 tcg_gen_and_tl(t1, t1, t2);
4077 tcg_temp_free(t2);
4078 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4079 tcg_temp_free(t1);
4080 /* operands of different sign, first operand and result different sign */
4081 generate_exception(ctx, EXCP_OVERFLOW);
4082 gen_set_label(l1);
4083 gen_store_gpr(t0, rd);
4084 tcg_temp_free(t0);
4086 break;
4087 case OPC_SUBU:
4088 if (rs != 0 && rt != 0) {
4089 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4090 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4091 } else if (rs == 0 && rt != 0) {
4092 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4093 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4094 } else if (rs != 0 && rt == 0) {
4095 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4096 } else {
4097 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4099 break;
4100 #if defined(TARGET_MIPS64)
4101 case OPC_DADD:
4103 TCGv t0 = tcg_temp_local_new();
4104 TCGv t1 = tcg_temp_new();
4105 TCGv t2 = tcg_temp_new();
4106 TCGLabel *l1 = gen_new_label();
4108 gen_load_gpr(t1, rs);
4109 gen_load_gpr(t2, rt);
4110 tcg_gen_add_tl(t0, t1, t2);
4111 tcg_gen_xor_tl(t1, t1, t2);
4112 tcg_gen_xor_tl(t2, t0, t2);
4113 tcg_gen_andc_tl(t1, t2, t1);
4114 tcg_temp_free(t2);
4115 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4116 tcg_temp_free(t1);
4117 /* operands of same sign, result different sign */
4118 generate_exception(ctx, EXCP_OVERFLOW);
4119 gen_set_label(l1);
4120 gen_store_gpr(t0, rd);
4121 tcg_temp_free(t0);
4123 break;
4124 case OPC_DADDU:
4125 if (rs != 0 && rt != 0) {
4126 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4127 } else if (rs == 0 && rt != 0) {
4128 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4129 } else if (rs != 0 && rt == 0) {
4130 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4131 } else {
4132 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4134 break;
4135 case OPC_DSUB:
4137 TCGv t0 = tcg_temp_local_new();
4138 TCGv t1 = tcg_temp_new();
4139 TCGv t2 = tcg_temp_new();
4140 TCGLabel *l1 = gen_new_label();
4142 gen_load_gpr(t1, rs);
4143 gen_load_gpr(t2, rt);
4144 tcg_gen_sub_tl(t0, t1, t2);
4145 tcg_gen_xor_tl(t2, t1, t2);
4146 tcg_gen_xor_tl(t1, t0, t1);
4147 tcg_gen_and_tl(t1, t1, t2);
4148 tcg_temp_free(t2);
4149 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4150 tcg_temp_free(t1);
4151 /* operands of different sign, first operand and result different sign */
4152 generate_exception(ctx, EXCP_OVERFLOW);
4153 gen_set_label(l1);
4154 gen_store_gpr(t0, rd);
4155 tcg_temp_free(t0);
4157 break;
4158 case OPC_DSUBU:
4159 if (rs != 0 && rt != 0) {
4160 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4161 } else if (rs == 0 && rt != 0) {
4162 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4163 } else if (rs != 0 && rt == 0) {
4164 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4165 } else {
4166 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4168 break;
4169 #endif
4170 case OPC_MUL:
4171 if (likely(rs != 0 && rt != 0)) {
4172 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4173 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4174 } else {
4175 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4177 break;
4181 /* Conditional move */
4182 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4183 int rd, int rs, int rt)
4185 TCGv t0, t1, t2;
4187 if (rd == 0) {
4188 /* If no destination, treat it as a NOP. */
4189 return;
4192 t0 = tcg_temp_new();
4193 gen_load_gpr(t0, rt);
4194 t1 = tcg_const_tl(0);
4195 t2 = tcg_temp_new();
4196 gen_load_gpr(t2, rs);
4197 switch (opc) {
4198 case OPC_MOVN:
4199 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4200 break;
4201 case OPC_MOVZ:
4202 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4203 break;
4204 case OPC_SELNEZ:
4205 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4206 break;
4207 case OPC_SELEQZ:
4208 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4209 break;
4211 tcg_temp_free(t2);
4212 tcg_temp_free(t1);
4213 tcg_temp_free(t0);
4216 /* Logic */
4217 static void gen_logic(DisasContext *ctx, uint32_t opc,
4218 int rd, int rs, int rt)
4220 if (rd == 0) {
4221 /* If no destination, treat it as a NOP. */
4222 return;
4225 switch (opc) {
4226 case OPC_AND:
4227 if (likely(rs != 0 && rt != 0)) {
4228 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4229 } else {
4230 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4232 break;
4233 case OPC_NOR:
4234 if (rs != 0 && rt != 0) {
4235 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4236 } else if (rs == 0 && rt != 0) {
4237 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4238 } else if (rs != 0 && rt == 0) {
4239 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4240 } else {
4241 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4243 break;
4244 case OPC_OR:
4245 if (likely(rs != 0 && rt != 0)) {
4246 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4247 } else if (rs == 0 && rt != 0) {
4248 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4249 } else if (rs != 0 && rt == 0) {
4250 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4251 } else {
4252 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4254 break;
4255 case OPC_XOR:
4256 if (likely(rs != 0 && rt != 0)) {
4257 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4258 } else if (rs == 0 && rt != 0) {
4259 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4260 } else if (rs != 0 && rt == 0) {
4261 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4262 } else {
4263 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4265 break;
4269 /* Set on lower than */
4270 static void gen_slt(DisasContext *ctx, uint32_t opc,
4271 int rd, int rs, int rt)
4273 TCGv t0, t1;
4275 if (rd == 0) {
4276 /* If no destination, treat it as a NOP. */
4277 return;
4280 t0 = tcg_temp_new();
4281 t1 = tcg_temp_new();
4282 gen_load_gpr(t0, rs);
4283 gen_load_gpr(t1, rt);
4284 switch (opc) {
4285 case OPC_SLT:
4286 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4287 break;
4288 case OPC_SLTU:
4289 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4290 break;
4292 tcg_temp_free(t0);
4293 tcg_temp_free(t1);
4296 /* Shifts */
4297 static void gen_shift(DisasContext *ctx, uint32_t opc,
4298 int rd, int rs, int rt)
4300 TCGv t0, t1;
4302 if (rd == 0) {
4303 /* If no destination, treat it as a NOP.
4304 For add & sub, we must generate the overflow exception when needed. */
4305 return;
4308 t0 = tcg_temp_new();
4309 t1 = tcg_temp_new();
4310 gen_load_gpr(t0, rs);
4311 gen_load_gpr(t1, rt);
4312 switch (opc) {
4313 case OPC_SLLV:
4314 tcg_gen_andi_tl(t0, t0, 0x1f);
4315 tcg_gen_shl_tl(t0, t1, t0);
4316 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4317 break;
4318 case OPC_SRAV:
4319 tcg_gen_andi_tl(t0, t0, 0x1f);
4320 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4321 break;
4322 case OPC_SRLV:
4323 tcg_gen_ext32u_tl(t1, t1);
4324 tcg_gen_andi_tl(t0, t0, 0x1f);
4325 tcg_gen_shr_tl(t0, t1, t0);
4326 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4327 break;
4328 case OPC_ROTRV:
4330 TCGv_i32 t2 = tcg_temp_new_i32();
4331 TCGv_i32 t3 = tcg_temp_new_i32();
4333 tcg_gen_trunc_tl_i32(t2, t0);
4334 tcg_gen_trunc_tl_i32(t3, t1);
4335 tcg_gen_andi_i32(t2, t2, 0x1f);
4336 tcg_gen_rotr_i32(t2, t3, t2);
4337 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4338 tcg_temp_free_i32(t2);
4339 tcg_temp_free_i32(t3);
4341 break;
4342 #if defined(TARGET_MIPS64)
4343 case OPC_DSLLV:
4344 tcg_gen_andi_tl(t0, t0, 0x3f);
4345 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4346 break;
4347 case OPC_DSRAV:
4348 tcg_gen_andi_tl(t0, t0, 0x3f);
4349 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4350 break;
4351 case OPC_DSRLV:
4352 tcg_gen_andi_tl(t0, t0, 0x3f);
4353 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4354 break;
4355 case OPC_DROTRV:
4356 tcg_gen_andi_tl(t0, t0, 0x3f);
4357 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4358 break;
4359 #endif
4361 tcg_temp_free(t0);
4362 tcg_temp_free(t1);
4365 #if defined(TARGET_MIPS64)
4366 /* Copy GPR to and from TX79 HI1/LO1 register. */
4367 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4369 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4370 /* Treat as NOP. */
4371 return;
4374 switch (opc) {
4375 case MMI_OPC_MFHI1:
4376 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4377 break;
4378 case MMI_OPC_MFLO1:
4379 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4380 break;
4381 case MMI_OPC_MTHI1:
4382 if (reg != 0) {
4383 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4384 } else {
4385 tcg_gen_movi_tl(cpu_HI[1], 0);
4387 break;
4388 case MMI_OPC_MTLO1:
4389 if (reg != 0) {
4390 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4391 } else {
4392 tcg_gen_movi_tl(cpu_LO[1], 0);
4394 break;
4395 default:
4396 MIPS_INVAL("mfthilo1 TX79");
4397 generate_exception_end(ctx, EXCP_RI);
4398 break;
4401 #endif
4403 /* Arithmetic on HI/LO registers */
4404 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4406 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4407 /* Treat as NOP. */
4408 return;
4411 if (acc != 0) {
4412 check_dsp(ctx);
4415 switch (opc) {
4416 case OPC_MFHI:
4417 #if defined(TARGET_MIPS64)
4418 if (acc != 0) {
4419 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4420 } else
4421 #endif
4423 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4425 break;
4426 case OPC_MFLO:
4427 #if defined(TARGET_MIPS64)
4428 if (acc != 0) {
4429 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4430 } else
4431 #endif
4433 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4435 break;
4436 case OPC_MTHI:
4437 if (reg != 0) {
4438 #if defined(TARGET_MIPS64)
4439 if (acc != 0) {
4440 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4441 } else
4442 #endif
4444 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4446 } else {
4447 tcg_gen_movi_tl(cpu_HI[acc], 0);
4449 break;
4450 case OPC_MTLO:
4451 if (reg != 0) {
4452 #if defined(TARGET_MIPS64)
4453 if (acc != 0) {
4454 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4455 } else
4456 #endif
4458 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4460 } else {
4461 tcg_gen_movi_tl(cpu_LO[acc], 0);
4463 break;
4467 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4468 TCGMemOp memop)
4470 TCGv t0 = tcg_const_tl(addr);
4471 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4472 gen_store_gpr(t0, reg);
4473 tcg_temp_free(t0);
4476 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4477 int rs)
4479 target_long offset;
4480 target_long addr;
4482 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4483 case OPC_ADDIUPC:
4484 if (rs != 0) {
4485 offset = sextract32(ctx->opcode << 2, 0, 21);
4486 addr = addr_add(ctx, pc, offset);
4487 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4489 break;
4490 case R6_OPC_LWPC:
4491 offset = sextract32(ctx->opcode << 2, 0, 21);
4492 addr = addr_add(ctx, pc, offset);
4493 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4494 break;
4495 #if defined(TARGET_MIPS64)
4496 case OPC_LWUPC:
4497 check_mips_64(ctx);
4498 offset = sextract32(ctx->opcode << 2, 0, 21);
4499 addr = addr_add(ctx, pc, offset);
4500 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4501 break;
4502 #endif
4503 default:
4504 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4505 case OPC_AUIPC:
4506 if (rs != 0) {
4507 offset = sextract32(ctx->opcode, 0, 16) << 16;
4508 addr = addr_add(ctx, pc, offset);
4509 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4511 break;
4512 case OPC_ALUIPC:
4513 if (rs != 0) {
4514 offset = sextract32(ctx->opcode, 0, 16) << 16;
4515 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4516 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4518 break;
4519 #if defined(TARGET_MIPS64)
4520 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4521 case R6_OPC_LDPC + (1 << 16):
4522 case R6_OPC_LDPC + (2 << 16):
4523 case R6_OPC_LDPC + (3 << 16):
4524 check_mips_64(ctx);
4525 offset = sextract32(ctx->opcode << 3, 0, 21);
4526 addr = addr_add(ctx, (pc & ~0x7), offset);
4527 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4528 break;
4529 #endif
4530 default:
4531 MIPS_INVAL("OPC_PCREL");
4532 generate_exception_end(ctx, EXCP_RI);
4533 break;
4535 break;
4539 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4541 TCGv t0, t1;
4543 if (rd == 0) {
4544 /* Treat as NOP. */
4545 return;
4548 t0 = tcg_temp_new();
4549 t1 = tcg_temp_new();
4551 gen_load_gpr(t0, rs);
4552 gen_load_gpr(t1, rt);
4554 switch (opc) {
4555 case R6_OPC_DIV:
4557 TCGv t2 = tcg_temp_new();
4558 TCGv t3 = tcg_temp_new();
4559 tcg_gen_ext32s_tl(t0, t0);
4560 tcg_gen_ext32s_tl(t1, t1);
4561 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4562 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4563 tcg_gen_and_tl(t2, t2, t3);
4564 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4565 tcg_gen_or_tl(t2, t2, t3);
4566 tcg_gen_movi_tl(t3, 0);
4567 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4568 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4569 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4570 tcg_temp_free(t3);
4571 tcg_temp_free(t2);
4573 break;
4574 case R6_OPC_MOD:
4576 TCGv t2 = tcg_temp_new();
4577 TCGv t3 = tcg_temp_new();
4578 tcg_gen_ext32s_tl(t0, t0);
4579 tcg_gen_ext32s_tl(t1, t1);
4580 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4581 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4582 tcg_gen_and_tl(t2, t2, t3);
4583 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4584 tcg_gen_or_tl(t2, t2, t3);
4585 tcg_gen_movi_tl(t3, 0);
4586 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4587 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4588 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4589 tcg_temp_free(t3);
4590 tcg_temp_free(t2);
4592 break;
4593 case R6_OPC_DIVU:
4595 TCGv t2 = tcg_const_tl(0);
4596 TCGv t3 = tcg_const_tl(1);
4597 tcg_gen_ext32u_tl(t0, t0);
4598 tcg_gen_ext32u_tl(t1, t1);
4599 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4600 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4601 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4602 tcg_temp_free(t3);
4603 tcg_temp_free(t2);
4605 break;
4606 case R6_OPC_MODU:
4608 TCGv t2 = tcg_const_tl(0);
4609 TCGv t3 = tcg_const_tl(1);
4610 tcg_gen_ext32u_tl(t0, t0);
4611 tcg_gen_ext32u_tl(t1, t1);
4612 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4613 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4614 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4615 tcg_temp_free(t3);
4616 tcg_temp_free(t2);
4618 break;
4619 case R6_OPC_MUL:
4621 TCGv_i32 t2 = tcg_temp_new_i32();
4622 TCGv_i32 t3 = tcg_temp_new_i32();
4623 tcg_gen_trunc_tl_i32(t2, t0);
4624 tcg_gen_trunc_tl_i32(t3, t1);
4625 tcg_gen_mul_i32(t2, t2, t3);
4626 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4627 tcg_temp_free_i32(t2);
4628 tcg_temp_free_i32(t3);
4630 break;
4631 case R6_OPC_MUH:
4633 TCGv_i32 t2 = tcg_temp_new_i32();
4634 TCGv_i32 t3 = tcg_temp_new_i32();
4635 tcg_gen_trunc_tl_i32(t2, t0);
4636 tcg_gen_trunc_tl_i32(t3, t1);
4637 tcg_gen_muls2_i32(t2, t3, t2, t3);
4638 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4639 tcg_temp_free_i32(t2);
4640 tcg_temp_free_i32(t3);
4642 break;
4643 case R6_OPC_MULU:
4645 TCGv_i32 t2 = tcg_temp_new_i32();
4646 TCGv_i32 t3 = tcg_temp_new_i32();
4647 tcg_gen_trunc_tl_i32(t2, t0);
4648 tcg_gen_trunc_tl_i32(t3, t1);
4649 tcg_gen_mul_i32(t2, t2, t3);
4650 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4651 tcg_temp_free_i32(t2);
4652 tcg_temp_free_i32(t3);
4654 break;
4655 case R6_OPC_MUHU:
4657 TCGv_i32 t2 = tcg_temp_new_i32();
4658 TCGv_i32 t3 = tcg_temp_new_i32();
4659 tcg_gen_trunc_tl_i32(t2, t0);
4660 tcg_gen_trunc_tl_i32(t3, t1);
4661 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4662 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4663 tcg_temp_free_i32(t2);
4664 tcg_temp_free_i32(t3);
4666 break;
4667 #if defined(TARGET_MIPS64)
4668 case R6_OPC_DDIV:
4670 TCGv t2 = tcg_temp_new();
4671 TCGv t3 = tcg_temp_new();
4672 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4673 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4674 tcg_gen_and_tl(t2, t2, t3);
4675 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4676 tcg_gen_or_tl(t2, t2, t3);
4677 tcg_gen_movi_tl(t3, 0);
4678 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4679 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4680 tcg_temp_free(t3);
4681 tcg_temp_free(t2);
4683 break;
4684 case R6_OPC_DMOD:
4686 TCGv t2 = tcg_temp_new();
4687 TCGv t3 = tcg_temp_new();
4688 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4689 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4690 tcg_gen_and_tl(t2, t2, t3);
4691 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4692 tcg_gen_or_tl(t2, t2, t3);
4693 tcg_gen_movi_tl(t3, 0);
4694 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4695 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4696 tcg_temp_free(t3);
4697 tcg_temp_free(t2);
4699 break;
4700 case R6_OPC_DDIVU:
4702 TCGv t2 = tcg_const_tl(0);
4703 TCGv t3 = tcg_const_tl(1);
4704 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4705 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4706 tcg_temp_free(t3);
4707 tcg_temp_free(t2);
4709 break;
4710 case R6_OPC_DMODU:
4712 TCGv t2 = tcg_const_tl(0);
4713 TCGv t3 = tcg_const_tl(1);
4714 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4715 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4716 tcg_temp_free(t3);
4717 tcg_temp_free(t2);
4719 break;
4720 case R6_OPC_DMUL:
4721 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4722 break;
4723 case R6_OPC_DMUH:
4725 TCGv t2 = tcg_temp_new();
4726 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4727 tcg_temp_free(t2);
4729 break;
4730 case R6_OPC_DMULU:
4731 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4732 break;
4733 case R6_OPC_DMUHU:
4735 TCGv t2 = tcg_temp_new();
4736 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4737 tcg_temp_free(t2);
4739 break;
4740 #endif
4741 default:
4742 MIPS_INVAL("r6 mul/div");
4743 generate_exception_end(ctx, EXCP_RI);
4744 goto out;
4746 out:
4747 tcg_temp_free(t0);
4748 tcg_temp_free(t1);
4751 #if defined(TARGET_MIPS64)
4752 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4754 TCGv t0, t1;
4756 t0 = tcg_temp_new();
4757 t1 = tcg_temp_new();
4759 gen_load_gpr(t0, rs);
4760 gen_load_gpr(t1, rt);
4762 switch (opc) {
4763 case MMI_OPC_DIV1:
4765 TCGv t2 = tcg_temp_new();
4766 TCGv t3 = tcg_temp_new();
4767 tcg_gen_ext32s_tl(t0, t0);
4768 tcg_gen_ext32s_tl(t1, t1);
4769 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4770 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4771 tcg_gen_and_tl(t2, t2, t3);
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4773 tcg_gen_or_tl(t2, t2, t3);
4774 tcg_gen_movi_tl(t3, 0);
4775 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4776 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4777 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4778 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4779 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4780 tcg_temp_free(t3);
4781 tcg_temp_free(t2);
4783 break;
4784 case MMI_OPC_DIVU1:
4786 TCGv t2 = tcg_const_tl(0);
4787 TCGv t3 = tcg_const_tl(1);
4788 tcg_gen_ext32u_tl(t0, t0);
4789 tcg_gen_ext32u_tl(t1, t1);
4790 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4791 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4792 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4793 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4794 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4795 tcg_temp_free(t3);
4796 tcg_temp_free(t2);
4798 break;
4799 default:
4800 MIPS_INVAL("div1 TX79");
4801 generate_exception_end(ctx, EXCP_RI);
4802 goto out;
4804 out:
4805 tcg_temp_free(t0);
4806 tcg_temp_free(t1);
4808 #endif
4810 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4811 int acc, int rs, int rt)
4813 TCGv t0, t1;
4815 t0 = tcg_temp_new();
4816 t1 = tcg_temp_new();
4818 gen_load_gpr(t0, rs);
4819 gen_load_gpr(t1, rt);
4821 if (acc != 0) {
4822 check_dsp(ctx);
4825 switch (opc) {
4826 case OPC_DIV:
4828 TCGv t2 = tcg_temp_new();
4829 TCGv t3 = tcg_temp_new();
4830 tcg_gen_ext32s_tl(t0, t0);
4831 tcg_gen_ext32s_tl(t1, t1);
4832 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4833 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4834 tcg_gen_and_tl(t2, t2, t3);
4835 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4836 tcg_gen_or_tl(t2, t2, t3);
4837 tcg_gen_movi_tl(t3, 0);
4838 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4839 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4840 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4841 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4842 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4843 tcg_temp_free(t3);
4844 tcg_temp_free(t2);
4846 break;
4847 case OPC_DIVU:
4849 TCGv t2 = tcg_const_tl(0);
4850 TCGv t3 = tcg_const_tl(1);
4851 tcg_gen_ext32u_tl(t0, t0);
4852 tcg_gen_ext32u_tl(t1, t1);
4853 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4854 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4855 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4856 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4857 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4858 tcg_temp_free(t3);
4859 tcg_temp_free(t2);
4861 break;
4862 case OPC_MULT:
4864 TCGv_i32 t2 = tcg_temp_new_i32();
4865 TCGv_i32 t3 = tcg_temp_new_i32();
4866 tcg_gen_trunc_tl_i32(t2, t0);
4867 tcg_gen_trunc_tl_i32(t3, t1);
4868 tcg_gen_muls2_i32(t2, t3, t2, t3);
4869 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4870 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4871 tcg_temp_free_i32(t2);
4872 tcg_temp_free_i32(t3);
4874 break;
4875 case OPC_MULTU:
4877 TCGv_i32 t2 = tcg_temp_new_i32();
4878 TCGv_i32 t3 = tcg_temp_new_i32();
4879 tcg_gen_trunc_tl_i32(t2, t0);
4880 tcg_gen_trunc_tl_i32(t3, t1);
4881 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4882 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4883 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4884 tcg_temp_free_i32(t2);
4885 tcg_temp_free_i32(t3);
4887 break;
4888 #if defined(TARGET_MIPS64)
4889 case OPC_DDIV:
4891 TCGv t2 = tcg_temp_new();
4892 TCGv t3 = tcg_temp_new();
4893 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4894 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4895 tcg_gen_and_tl(t2, t2, t3);
4896 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4897 tcg_gen_or_tl(t2, t2, t3);
4898 tcg_gen_movi_tl(t3, 0);
4899 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4900 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4901 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4902 tcg_temp_free(t3);
4903 tcg_temp_free(t2);
4905 break;
4906 case OPC_DDIVU:
4908 TCGv t2 = tcg_const_tl(0);
4909 TCGv t3 = tcg_const_tl(1);
4910 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4911 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4912 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4913 tcg_temp_free(t3);
4914 tcg_temp_free(t2);
4916 break;
4917 case OPC_DMULT:
4918 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4919 break;
4920 case OPC_DMULTU:
4921 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4922 break;
4923 #endif
4924 case OPC_MADD:
4926 TCGv_i64 t2 = tcg_temp_new_i64();
4927 TCGv_i64 t3 = tcg_temp_new_i64();
4929 tcg_gen_ext_tl_i64(t2, t0);
4930 tcg_gen_ext_tl_i64(t3, t1);
4931 tcg_gen_mul_i64(t2, t2, t3);
4932 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4933 tcg_gen_add_i64(t2, t2, t3);
4934 tcg_temp_free_i64(t3);
4935 gen_move_low32(cpu_LO[acc], t2);
4936 gen_move_high32(cpu_HI[acc], t2);
4937 tcg_temp_free_i64(t2);
4939 break;
4940 case OPC_MADDU:
4942 TCGv_i64 t2 = tcg_temp_new_i64();
4943 TCGv_i64 t3 = tcg_temp_new_i64();
4945 tcg_gen_ext32u_tl(t0, t0);
4946 tcg_gen_ext32u_tl(t1, t1);
4947 tcg_gen_extu_tl_i64(t2, t0);
4948 tcg_gen_extu_tl_i64(t3, t1);
4949 tcg_gen_mul_i64(t2, t2, t3);
4950 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4951 tcg_gen_add_i64(t2, t2, t3);
4952 tcg_temp_free_i64(t3);
4953 gen_move_low32(cpu_LO[acc], t2);
4954 gen_move_high32(cpu_HI[acc], t2);
4955 tcg_temp_free_i64(t2);
4957 break;
4958 case OPC_MSUB:
4960 TCGv_i64 t2 = tcg_temp_new_i64();
4961 TCGv_i64 t3 = tcg_temp_new_i64();
4963 tcg_gen_ext_tl_i64(t2, t0);
4964 tcg_gen_ext_tl_i64(t3, t1);
4965 tcg_gen_mul_i64(t2, t2, t3);
4966 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4967 tcg_gen_sub_i64(t2, t3, t2);
4968 tcg_temp_free_i64(t3);
4969 gen_move_low32(cpu_LO[acc], t2);
4970 gen_move_high32(cpu_HI[acc], t2);
4971 tcg_temp_free_i64(t2);
4973 break;
4974 case OPC_MSUBU:
4976 TCGv_i64 t2 = tcg_temp_new_i64();
4977 TCGv_i64 t3 = tcg_temp_new_i64();
4979 tcg_gen_ext32u_tl(t0, t0);
4980 tcg_gen_ext32u_tl(t1, t1);
4981 tcg_gen_extu_tl_i64(t2, t0);
4982 tcg_gen_extu_tl_i64(t3, t1);
4983 tcg_gen_mul_i64(t2, t2, t3);
4984 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4985 tcg_gen_sub_i64(t2, t3, t2);
4986 tcg_temp_free_i64(t3);
4987 gen_move_low32(cpu_LO[acc], t2);
4988 gen_move_high32(cpu_HI[acc], t2);
4989 tcg_temp_free_i64(t2);
4991 break;
4992 default:
4993 MIPS_INVAL("mul/div");
4994 generate_exception_end(ctx, EXCP_RI);
4995 goto out;
4997 out:
4998 tcg_temp_free(t0);
4999 tcg_temp_free(t1);
5003 * These MULT[U] and MADD[U] instructions implemented in for example
5004 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5005 * architectures are special three-operand variants with the syntax
5007 * MULT[U][1] rd, rs, rt
5009 * such that
5011 * (rd, LO, HI) <- rs * rt
5013 * and
5015 * MADD[U][1] rd, rs, rt
5017 * such that
5019 * (rd, LO, HI) <- (LO, HI) + rs * rt
5021 * where the low-order 32-bits of the result is placed into both the
5022 * GPR rd and the special register LO. The high-order 32-bits of the
5023 * result is placed into the special register HI.
5025 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5026 * which is the zero register that always reads as 0.
5028 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5029 int rd, int rs, int rt)
5031 TCGv t0 = tcg_temp_new();
5032 TCGv t1 = tcg_temp_new();
5033 int acc = 0;
5035 gen_load_gpr(t0, rs);
5036 gen_load_gpr(t1, rt);
5038 switch (opc) {
5039 case MMI_OPC_MULT1:
5040 acc = 1;
5041 /* Fall through */
5042 case OPC_MULT:
5044 TCGv_i32 t2 = tcg_temp_new_i32();
5045 TCGv_i32 t3 = tcg_temp_new_i32();
5046 tcg_gen_trunc_tl_i32(t2, t0);
5047 tcg_gen_trunc_tl_i32(t3, t1);
5048 tcg_gen_muls2_i32(t2, t3, t2, t3);
5049 if (rd) {
5050 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5052 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5053 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5054 tcg_temp_free_i32(t2);
5055 tcg_temp_free_i32(t3);
5057 break;
5058 case MMI_OPC_MULTU1:
5059 acc = 1;
5060 /* Fall through */
5061 case OPC_MULTU:
5063 TCGv_i32 t2 = tcg_temp_new_i32();
5064 TCGv_i32 t3 = tcg_temp_new_i32();
5065 tcg_gen_trunc_tl_i32(t2, t0);
5066 tcg_gen_trunc_tl_i32(t3, t1);
5067 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5068 if (rd) {
5069 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5071 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5072 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5073 tcg_temp_free_i32(t2);
5074 tcg_temp_free_i32(t3);
5076 break;
5077 case MMI_OPC_MADD1:
5078 acc = 1;
5079 /* Fall through */
5080 case MMI_OPC_MADD:
5082 TCGv_i64 t2 = tcg_temp_new_i64();
5083 TCGv_i64 t3 = tcg_temp_new_i64();
5085 tcg_gen_ext_tl_i64(t2, t0);
5086 tcg_gen_ext_tl_i64(t3, t1);
5087 tcg_gen_mul_i64(t2, t2, t3);
5088 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5089 tcg_gen_add_i64(t2, t2, t3);
5090 tcg_temp_free_i64(t3);
5091 gen_move_low32(cpu_LO[acc], t2);
5092 gen_move_high32(cpu_HI[acc], t2);
5093 if (rd) {
5094 gen_move_low32(cpu_gpr[rd], t2);
5096 tcg_temp_free_i64(t2);
5098 break;
5099 case MMI_OPC_MADDU1:
5100 acc = 1;
5101 /* Fall through */
5102 case MMI_OPC_MADDU:
5104 TCGv_i64 t2 = tcg_temp_new_i64();
5105 TCGv_i64 t3 = tcg_temp_new_i64();
5107 tcg_gen_ext32u_tl(t0, t0);
5108 tcg_gen_ext32u_tl(t1, t1);
5109 tcg_gen_extu_tl_i64(t2, t0);
5110 tcg_gen_extu_tl_i64(t3, t1);
5111 tcg_gen_mul_i64(t2, t2, t3);
5112 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5113 tcg_gen_add_i64(t2, t2, t3);
5114 tcg_temp_free_i64(t3);
5115 gen_move_low32(cpu_LO[acc], t2);
5116 gen_move_high32(cpu_HI[acc], t2);
5117 if (rd) {
5118 gen_move_low32(cpu_gpr[rd], t2);
5120 tcg_temp_free_i64(t2);
5122 break;
5123 default:
5124 MIPS_INVAL("mul/madd TXx9");
5125 generate_exception_end(ctx, EXCP_RI);
5126 goto out;
5129 out:
5130 tcg_temp_free(t0);
5131 tcg_temp_free(t1);
5134 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
5135 int rd, int rs, int rt)
5137 TCGv t0 = tcg_temp_new();
5138 TCGv t1 = tcg_temp_new();
5140 gen_load_gpr(t0, rs);
5141 gen_load_gpr(t1, rt);
5143 switch (opc) {
5144 case OPC_VR54XX_MULS:
5145 gen_helper_muls(t0, cpu_env, t0, t1);
5146 break;
5147 case OPC_VR54XX_MULSU:
5148 gen_helper_mulsu(t0, cpu_env, t0, t1);
5149 break;
5150 case OPC_VR54XX_MACC:
5151 gen_helper_macc(t0, cpu_env, t0, t1);
5152 break;
5153 case OPC_VR54XX_MACCU:
5154 gen_helper_maccu(t0, cpu_env, t0, t1);
5155 break;
5156 case OPC_VR54XX_MSAC:
5157 gen_helper_msac(t0, cpu_env, t0, t1);
5158 break;
5159 case OPC_VR54XX_MSACU:
5160 gen_helper_msacu(t0, cpu_env, t0, t1);
5161 break;
5162 case OPC_VR54XX_MULHI:
5163 gen_helper_mulhi(t0, cpu_env, t0, t1);
5164 break;
5165 case OPC_VR54XX_MULHIU:
5166 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5167 break;
5168 case OPC_VR54XX_MULSHI:
5169 gen_helper_mulshi(t0, cpu_env, t0, t1);
5170 break;
5171 case OPC_VR54XX_MULSHIU:
5172 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5173 break;
5174 case OPC_VR54XX_MACCHI:
5175 gen_helper_macchi(t0, cpu_env, t0, t1);
5176 break;
5177 case OPC_VR54XX_MACCHIU:
5178 gen_helper_macchiu(t0, cpu_env, t0, t1);
5179 break;
5180 case OPC_VR54XX_MSACHI:
5181 gen_helper_msachi(t0, cpu_env, t0, t1);
5182 break;
5183 case OPC_VR54XX_MSACHIU:
5184 gen_helper_msachiu(t0, cpu_env, t0, t1);
5185 break;
5186 default:
5187 MIPS_INVAL("mul vr54xx");
5188 generate_exception_end(ctx, EXCP_RI);
5189 goto out;
5191 gen_store_gpr(t0, rd);
5193 out:
5194 tcg_temp_free(t0);
5195 tcg_temp_free(t1);
5198 static void gen_cl (DisasContext *ctx, uint32_t opc,
5199 int rd, int rs)
5201 TCGv t0;
5203 if (rd == 0) {
5204 /* Treat as NOP. */
5205 return;
5207 t0 = cpu_gpr[rd];
5208 gen_load_gpr(t0, rs);
5210 switch (opc) {
5211 case OPC_CLO:
5212 case R6_OPC_CLO:
5213 #if defined(TARGET_MIPS64)
5214 case OPC_DCLO:
5215 case R6_OPC_DCLO:
5216 #endif
5217 tcg_gen_not_tl(t0, t0);
5218 break;
5221 switch (opc) {
5222 case OPC_CLO:
5223 case R6_OPC_CLO:
5224 case OPC_CLZ:
5225 case R6_OPC_CLZ:
5226 tcg_gen_ext32u_tl(t0, t0);
5227 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5228 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5229 break;
5230 #if defined(TARGET_MIPS64)
5231 case OPC_DCLO:
5232 case R6_OPC_DCLO:
5233 case OPC_DCLZ:
5234 case R6_OPC_DCLZ:
5235 tcg_gen_clzi_i64(t0, t0, 64);
5236 break;
5237 #endif
5241 /* Godson integer instructions */
5242 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5243 int rd, int rs, int rt)
5245 TCGv t0, t1;
5247 if (rd == 0) {
5248 /* Treat as NOP. */
5249 return;
5252 switch (opc) {
5253 case OPC_MULT_G_2E:
5254 case OPC_MULT_G_2F:
5255 case OPC_MULTU_G_2E:
5256 case OPC_MULTU_G_2F:
5257 #if defined(TARGET_MIPS64)
5258 case OPC_DMULT_G_2E:
5259 case OPC_DMULT_G_2F:
5260 case OPC_DMULTU_G_2E:
5261 case OPC_DMULTU_G_2F:
5262 #endif
5263 t0 = tcg_temp_new();
5264 t1 = tcg_temp_new();
5265 break;
5266 default:
5267 t0 = tcg_temp_local_new();
5268 t1 = tcg_temp_local_new();
5269 break;
5272 gen_load_gpr(t0, rs);
5273 gen_load_gpr(t1, rt);
5275 switch (opc) {
5276 case OPC_MULT_G_2E:
5277 case OPC_MULT_G_2F:
5278 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5279 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5280 break;
5281 case OPC_MULTU_G_2E:
5282 case OPC_MULTU_G_2F:
5283 tcg_gen_ext32u_tl(t0, t0);
5284 tcg_gen_ext32u_tl(t1, t1);
5285 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5286 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5287 break;
5288 case OPC_DIV_G_2E:
5289 case OPC_DIV_G_2F:
5291 TCGLabel *l1 = gen_new_label();
5292 TCGLabel *l2 = gen_new_label();
5293 TCGLabel *l3 = gen_new_label();
5294 tcg_gen_ext32s_tl(t0, t0);
5295 tcg_gen_ext32s_tl(t1, t1);
5296 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5297 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5298 tcg_gen_br(l3);
5299 gen_set_label(l1);
5300 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5301 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5302 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5303 tcg_gen_br(l3);
5304 gen_set_label(l2);
5305 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5306 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5307 gen_set_label(l3);
5309 break;
5310 case OPC_DIVU_G_2E:
5311 case OPC_DIVU_G_2F:
5313 TCGLabel *l1 = gen_new_label();
5314 TCGLabel *l2 = gen_new_label();
5315 tcg_gen_ext32u_tl(t0, t0);
5316 tcg_gen_ext32u_tl(t1, t1);
5317 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5318 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5319 tcg_gen_br(l2);
5320 gen_set_label(l1);
5321 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5322 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5323 gen_set_label(l2);
5325 break;
5326 case OPC_MOD_G_2E:
5327 case OPC_MOD_G_2F:
5329 TCGLabel *l1 = gen_new_label();
5330 TCGLabel *l2 = gen_new_label();
5331 TCGLabel *l3 = gen_new_label();
5332 tcg_gen_ext32u_tl(t0, t0);
5333 tcg_gen_ext32u_tl(t1, t1);
5334 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5335 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5336 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5337 gen_set_label(l1);
5338 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5339 tcg_gen_br(l3);
5340 gen_set_label(l2);
5341 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5342 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5343 gen_set_label(l3);
5345 break;
5346 case OPC_MODU_G_2E:
5347 case OPC_MODU_G_2F:
5349 TCGLabel *l1 = gen_new_label();
5350 TCGLabel *l2 = gen_new_label();
5351 tcg_gen_ext32u_tl(t0, t0);
5352 tcg_gen_ext32u_tl(t1, t1);
5353 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5354 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5355 tcg_gen_br(l2);
5356 gen_set_label(l1);
5357 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5358 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5359 gen_set_label(l2);
5361 break;
5362 #if defined(TARGET_MIPS64)
5363 case OPC_DMULT_G_2E:
5364 case OPC_DMULT_G_2F:
5365 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5366 break;
5367 case OPC_DMULTU_G_2E:
5368 case OPC_DMULTU_G_2F:
5369 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5370 break;
5371 case OPC_DDIV_G_2E:
5372 case OPC_DDIV_G_2F:
5374 TCGLabel *l1 = gen_new_label();
5375 TCGLabel *l2 = gen_new_label();
5376 TCGLabel *l3 = gen_new_label();
5377 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5378 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5379 tcg_gen_br(l3);
5380 gen_set_label(l1);
5381 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5382 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5383 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5384 tcg_gen_br(l3);
5385 gen_set_label(l2);
5386 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5387 gen_set_label(l3);
5389 break;
5390 case OPC_DDIVU_G_2E:
5391 case OPC_DDIVU_G_2F:
5393 TCGLabel *l1 = gen_new_label();
5394 TCGLabel *l2 = gen_new_label();
5395 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5396 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5397 tcg_gen_br(l2);
5398 gen_set_label(l1);
5399 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5400 gen_set_label(l2);
5402 break;
5403 case OPC_DMOD_G_2E:
5404 case OPC_DMOD_G_2F:
5406 TCGLabel *l1 = gen_new_label();
5407 TCGLabel *l2 = gen_new_label();
5408 TCGLabel *l3 = gen_new_label();
5409 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5410 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5411 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5412 gen_set_label(l1);
5413 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5414 tcg_gen_br(l3);
5415 gen_set_label(l2);
5416 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5417 gen_set_label(l3);
5419 break;
5420 case OPC_DMODU_G_2E:
5421 case OPC_DMODU_G_2F:
5423 TCGLabel *l1 = gen_new_label();
5424 TCGLabel *l2 = gen_new_label();
5425 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5426 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5427 tcg_gen_br(l2);
5428 gen_set_label(l1);
5429 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5430 gen_set_label(l2);
5432 break;
5433 #endif
5436 tcg_temp_free(t0);
5437 tcg_temp_free(t1);
5440 /* Loongson multimedia instructions */
5441 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5443 uint32_t opc, shift_max;
5444 TCGv_i64 t0, t1;
5446 opc = MASK_LMI(ctx->opcode);
5447 switch (opc) {
5448 case OPC_ADD_CP2:
5449 case OPC_SUB_CP2:
5450 case OPC_DADD_CP2:
5451 case OPC_DSUB_CP2:
5452 t0 = tcg_temp_local_new_i64();
5453 t1 = tcg_temp_local_new_i64();
5454 break;
5455 default:
5456 t0 = tcg_temp_new_i64();
5457 t1 = tcg_temp_new_i64();
5458 break;
5461 check_cp1_enabled(ctx);
5462 gen_load_fpr64(ctx, t0, rs);
5463 gen_load_fpr64(ctx, t1, rt);
5465 #define LMI_HELPER(UP, LO) \
5466 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5467 #define LMI_HELPER_1(UP, LO) \
5468 case OPC_##UP: gen_helper_##LO(t0, t0); break
5469 #define LMI_DIRECT(UP, LO, OP) \
5470 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5472 switch (opc) {
5473 LMI_HELPER(PADDSH, paddsh);
5474 LMI_HELPER(PADDUSH, paddush);
5475 LMI_HELPER(PADDH, paddh);
5476 LMI_HELPER(PADDW, paddw);
5477 LMI_HELPER(PADDSB, paddsb);
5478 LMI_HELPER(PADDUSB, paddusb);
5479 LMI_HELPER(PADDB, paddb);
5481 LMI_HELPER(PSUBSH, psubsh);
5482 LMI_HELPER(PSUBUSH, psubush);
5483 LMI_HELPER(PSUBH, psubh);
5484 LMI_HELPER(PSUBW, psubw);
5485 LMI_HELPER(PSUBSB, psubsb);
5486 LMI_HELPER(PSUBUSB, psubusb);
5487 LMI_HELPER(PSUBB, psubb);
5489 LMI_HELPER(PSHUFH, pshufh);
5490 LMI_HELPER(PACKSSWH, packsswh);
5491 LMI_HELPER(PACKSSHB, packsshb);
5492 LMI_HELPER(PACKUSHB, packushb);
5494 LMI_HELPER(PUNPCKLHW, punpcklhw);
5495 LMI_HELPER(PUNPCKHHW, punpckhhw);
5496 LMI_HELPER(PUNPCKLBH, punpcklbh);
5497 LMI_HELPER(PUNPCKHBH, punpckhbh);
5498 LMI_HELPER(PUNPCKLWD, punpcklwd);
5499 LMI_HELPER(PUNPCKHWD, punpckhwd);
5501 LMI_HELPER(PAVGH, pavgh);
5502 LMI_HELPER(PAVGB, pavgb);
5503 LMI_HELPER(PMAXSH, pmaxsh);
5504 LMI_HELPER(PMINSH, pminsh);
5505 LMI_HELPER(PMAXUB, pmaxub);
5506 LMI_HELPER(PMINUB, pminub);
5508 LMI_HELPER(PCMPEQW, pcmpeqw);
5509 LMI_HELPER(PCMPGTW, pcmpgtw);
5510 LMI_HELPER(PCMPEQH, pcmpeqh);
5511 LMI_HELPER(PCMPGTH, pcmpgth);
5512 LMI_HELPER(PCMPEQB, pcmpeqb);
5513 LMI_HELPER(PCMPGTB, pcmpgtb);
5515 LMI_HELPER(PSLLW, psllw);
5516 LMI_HELPER(PSLLH, psllh);
5517 LMI_HELPER(PSRLW, psrlw);
5518 LMI_HELPER(PSRLH, psrlh);
5519 LMI_HELPER(PSRAW, psraw);
5520 LMI_HELPER(PSRAH, psrah);
5522 LMI_HELPER(PMULLH, pmullh);
5523 LMI_HELPER(PMULHH, pmulhh);
5524 LMI_HELPER(PMULHUH, pmulhuh);
5525 LMI_HELPER(PMADDHW, pmaddhw);
5527 LMI_HELPER(PASUBUB, pasubub);
5528 LMI_HELPER_1(BIADD, biadd);
5529 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5531 LMI_DIRECT(PADDD, paddd, add);
5532 LMI_DIRECT(PSUBD, psubd, sub);
5533 LMI_DIRECT(XOR_CP2, xor, xor);
5534 LMI_DIRECT(NOR_CP2, nor, nor);
5535 LMI_DIRECT(AND_CP2, and, and);
5536 LMI_DIRECT(OR_CP2, or, or);
5538 case OPC_PANDN:
5539 tcg_gen_andc_i64(t0, t1, t0);
5540 break;
5542 case OPC_PINSRH_0:
5543 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5544 break;
5545 case OPC_PINSRH_1:
5546 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5547 break;
5548 case OPC_PINSRH_2:
5549 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5550 break;
5551 case OPC_PINSRH_3:
5552 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5553 break;
5555 case OPC_PEXTRH:
5556 tcg_gen_andi_i64(t1, t1, 3);
5557 tcg_gen_shli_i64(t1, t1, 4);
5558 tcg_gen_shr_i64(t0, t0, t1);
5559 tcg_gen_ext16u_i64(t0, t0);
5560 break;
5562 case OPC_ADDU_CP2:
5563 tcg_gen_add_i64(t0, t0, t1);
5564 tcg_gen_ext32s_i64(t0, t0);
5565 break;
5566 case OPC_SUBU_CP2:
5567 tcg_gen_sub_i64(t0, t0, t1);
5568 tcg_gen_ext32s_i64(t0, t0);
5569 break;
5571 case OPC_SLL_CP2:
5572 shift_max = 32;
5573 goto do_shift;
5574 case OPC_SRL_CP2:
5575 shift_max = 32;
5576 goto do_shift;
5577 case OPC_SRA_CP2:
5578 shift_max = 32;
5579 goto do_shift;
5580 case OPC_DSLL_CP2:
5581 shift_max = 64;
5582 goto do_shift;
5583 case OPC_DSRL_CP2:
5584 shift_max = 64;
5585 goto do_shift;
5586 case OPC_DSRA_CP2:
5587 shift_max = 64;
5588 goto do_shift;
5589 do_shift:
5590 /* Make sure shift count isn't TCG undefined behaviour. */
5591 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5593 switch (opc) {
5594 case OPC_SLL_CP2:
5595 case OPC_DSLL_CP2:
5596 tcg_gen_shl_i64(t0, t0, t1);
5597 break;
5598 case OPC_SRA_CP2:
5599 case OPC_DSRA_CP2:
5600 /* Since SRA is UndefinedResult without sign-extended inputs,
5601 we can treat SRA and DSRA the same. */
5602 tcg_gen_sar_i64(t0, t0, t1);
5603 break;
5604 case OPC_SRL_CP2:
5605 /* We want to shift in zeros for SRL; zero-extend first. */
5606 tcg_gen_ext32u_i64(t0, t0);
5607 /* FALLTHRU */
5608 case OPC_DSRL_CP2:
5609 tcg_gen_shr_i64(t0, t0, t1);
5610 break;
5613 if (shift_max == 32) {
5614 tcg_gen_ext32s_i64(t0, t0);
5617 /* Shifts larger than MAX produce zero. */
5618 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5619 tcg_gen_neg_i64(t1, t1);
5620 tcg_gen_and_i64(t0, t0, t1);
5621 break;
5623 case OPC_ADD_CP2:
5624 case OPC_DADD_CP2:
5626 TCGv_i64 t2 = tcg_temp_new_i64();
5627 TCGLabel *lab = gen_new_label();
5629 tcg_gen_mov_i64(t2, t0);
5630 tcg_gen_add_i64(t0, t1, t2);
5631 if (opc == OPC_ADD_CP2) {
5632 tcg_gen_ext32s_i64(t0, t0);
5634 tcg_gen_xor_i64(t1, t1, t2);
5635 tcg_gen_xor_i64(t2, t2, t0);
5636 tcg_gen_andc_i64(t1, t2, t1);
5637 tcg_temp_free_i64(t2);
5638 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5639 generate_exception(ctx, EXCP_OVERFLOW);
5640 gen_set_label(lab);
5641 break;
5644 case OPC_SUB_CP2:
5645 case OPC_DSUB_CP2:
5647 TCGv_i64 t2 = tcg_temp_new_i64();
5648 TCGLabel *lab = gen_new_label();
5650 tcg_gen_mov_i64(t2, t0);
5651 tcg_gen_sub_i64(t0, t1, t2);
5652 if (opc == OPC_SUB_CP2) {
5653 tcg_gen_ext32s_i64(t0, t0);
5655 tcg_gen_xor_i64(t1, t1, t2);
5656 tcg_gen_xor_i64(t2, t2, t0);
5657 tcg_gen_and_i64(t1, t1, t2);
5658 tcg_temp_free_i64(t2);
5659 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5660 generate_exception(ctx, EXCP_OVERFLOW);
5661 gen_set_label(lab);
5662 break;
5665 case OPC_PMULUW:
5666 tcg_gen_ext32u_i64(t0, t0);
5667 tcg_gen_ext32u_i64(t1, t1);
5668 tcg_gen_mul_i64(t0, t0, t1);
5669 break;
5671 case OPC_SEQU_CP2:
5672 case OPC_SEQ_CP2:
5673 case OPC_SLTU_CP2:
5674 case OPC_SLT_CP2:
5675 case OPC_SLEU_CP2:
5676 case OPC_SLE_CP2:
5677 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5678 FD field is the CC field? */
5679 default:
5680 MIPS_INVAL("loongson_cp2");
5681 generate_exception_end(ctx, EXCP_RI);
5682 return;
5685 #undef LMI_HELPER
5686 #undef LMI_DIRECT
5688 gen_store_fpr64(ctx, t0, rd);
5690 tcg_temp_free_i64(t0);
5691 tcg_temp_free_i64(t1);
5694 /* Traps */
5695 static void gen_trap (DisasContext *ctx, uint32_t opc,
5696 int rs, int rt, int16_t imm)
5698 int cond;
5699 TCGv t0 = tcg_temp_new();
5700 TCGv t1 = tcg_temp_new();
5702 cond = 0;
5703 /* Load needed operands */
5704 switch (opc) {
5705 case OPC_TEQ:
5706 case OPC_TGE:
5707 case OPC_TGEU:
5708 case OPC_TLT:
5709 case OPC_TLTU:
5710 case OPC_TNE:
5711 /* Compare two registers */
5712 if (rs != rt) {
5713 gen_load_gpr(t0, rs);
5714 gen_load_gpr(t1, rt);
5715 cond = 1;
5717 break;
5718 case OPC_TEQI:
5719 case OPC_TGEI:
5720 case OPC_TGEIU:
5721 case OPC_TLTI:
5722 case OPC_TLTIU:
5723 case OPC_TNEI:
5724 /* Compare register to immediate */
5725 if (rs != 0 || imm != 0) {
5726 gen_load_gpr(t0, rs);
5727 tcg_gen_movi_tl(t1, (int32_t)imm);
5728 cond = 1;
5730 break;
5732 if (cond == 0) {
5733 switch (opc) {
5734 case OPC_TEQ: /* rs == rs */
5735 case OPC_TEQI: /* r0 == 0 */
5736 case OPC_TGE: /* rs >= rs */
5737 case OPC_TGEI: /* r0 >= 0 */
5738 case OPC_TGEU: /* rs >= rs unsigned */
5739 case OPC_TGEIU: /* r0 >= 0 unsigned */
5740 /* Always trap */
5741 generate_exception_end(ctx, EXCP_TRAP);
5742 break;
5743 case OPC_TLT: /* rs < rs */
5744 case OPC_TLTI: /* r0 < 0 */
5745 case OPC_TLTU: /* rs < rs unsigned */
5746 case OPC_TLTIU: /* r0 < 0 unsigned */
5747 case OPC_TNE: /* rs != rs */
5748 case OPC_TNEI: /* r0 != 0 */
5749 /* Never trap: treat as NOP. */
5750 break;
5752 } else {
5753 TCGLabel *l1 = gen_new_label();
5755 switch (opc) {
5756 case OPC_TEQ:
5757 case OPC_TEQI:
5758 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5759 break;
5760 case OPC_TGE:
5761 case OPC_TGEI:
5762 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5763 break;
5764 case OPC_TGEU:
5765 case OPC_TGEIU:
5766 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5767 break;
5768 case OPC_TLT:
5769 case OPC_TLTI:
5770 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5771 break;
5772 case OPC_TLTU:
5773 case OPC_TLTIU:
5774 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5775 break;
5776 case OPC_TNE:
5777 case OPC_TNEI:
5778 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5779 break;
5781 generate_exception(ctx, EXCP_TRAP);
5782 gen_set_label(l1);
5784 tcg_temp_free(t0);
5785 tcg_temp_free(t1);
5788 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5790 if (unlikely(ctx->base.singlestep_enabled)) {
5791 return false;
5794 #ifndef CONFIG_USER_ONLY
5795 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5796 #else
5797 return true;
5798 #endif
5801 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5803 if (use_goto_tb(ctx, dest)) {
5804 tcg_gen_goto_tb(n);
5805 gen_save_pc(dest);
5806 tcg_gen_exit_tb(ctx->base.tb, n);
5807 } else {
5808 gen_save_pc(dest);
5809 if (ctx->base.singlestep_enabled) {
5810 save_cpu_state(ctx, 0);
5811 gen_helper_raise_exception_debug(cpu_env);
5813 tcg_gen_lookup_and_goto_ptr();
5817 /* Branches (before delay slot) */
5818 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5819 int insn_bytes,
5820 int rs, int rt, int32_t offset,
5821 int delayslot_size)
5823 target_ulong btgt = -1;
5824 int blink = 0;
5825 int bcond_compute = 0;
5826 TCGv t0 = tcg_temp_new();
5827 TCGv t1 = tcg_temp_new();
5829 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5830 #ifdef MIPS_DEBUG_DISAS
5831 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5832 TARGET_FMT_lx "\n", ctx->base.pc_next);
5833 #endif
5834 generate_exception_end(ctx, EXCP_RI);
5835 goto out;
5838 /* Load needed operands */
5839 switch (opc) {
5840 case OPC_BEQ:
5841 case OPC_BEQL:
5842 case OPC_BNE:
5843 case OPC_BNEL:
5844 /* Compare two registers */
5845 if (rs != rt) {
5846 gen_load_gpr(t0, rs);
5847 gen_load_gpr(t1, rt);
5848 bcond_compute = 1;
5850 btgt = ctx->base.pc_next + insn_bytes + offset;
5851 break;
5852 case OPC_BGEZ:
5853 case OPC_BGEZAL:
5854 case OPC_BGEZALL:
5855 case OPC_BGEZL:
5856 case OPC_BGTZ:
5857 case OPC_BGTZL:
5858 case OPC_BLEZ:
5859 case OPC_BLEZL:
5860 case OPC_BLTZ:
5861 case OPC_BLTZAL:
5862 case OPC_BLTZALL:
5863 case OPC_BLTZL:
5864 /* Compare to zero */
5865 if (rs != 0) {
5866 gen_load_gpr(t0, rs);
5867 bcond_compute = 1;
5869 btgt = ctx->base.pc_next + insn_bytes + offset;
5870 break;
5871 case OPC_BPOSGE32:
5872 #if defined(TARGET_MIPS64)
5873 case OPC_BPOSGE64:
5874 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5875 #else
5876 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5877 #endif
5878 bcond_compute = 1;
5879 btgt = ctx->base.pc_next + insn_bytes + offset;
5880 break;
5881 case OPC_J:
5882 case OPC_JAL:
5883 case OPC_JALX:
5884 /* Jump to immediate */
5885 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5886 (uint32_t)offset;
5887 break;
5888 case OPC_JR:
5889 case OPC_JALR:
5890 /* Jump to register */
5891 if (offset != 0 && offset != 16) {
5892 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5893 others are reserved. */
5894 MIPS_INVAL("jump hint");
5895 generate_exception_end(ctx, EXCP_RI);
5896 goto out;
5898 gen_load_gpr(btarget, rs);
5899 break;
5900 default:
5901 MIPS_INVAL("branch/jump");
5902 generate_exception_end(ctx, EXCP_RI);
5903 goto out;
5905 if (bcond_compute == 0) {
5906 /* No condition to be computed */
5907 switch (opc) {
5908 case OPC_BEQ: /* rx == rx */
5909 case OPC_BEQL: /* rx == rx likely */
5910 case OPC_BGEZ: /* 0 >= 0 */
5911 case OPC_BGEZL: /* 0 >= 0 likely */
5912 case OPC_BLEZ: /* 0 <= 0 */
5913 case OPC_BLEZL: /* 0 <= 0 likely */
5914 /* Always take */
5915 ctx->hflags |= MIPS_HFLAG_B;
5916 break;
5917 case OPC_BGEZAL: /* 0 >= 0 */
5918 case OPC_BGEZALL: /* 0 >= 0 likely */
5919 /* Always take and link */
5920 blink = 31;
5921 ctx->hflags |= MIPS_HFLAG_B;
5922 break;
5923 case OPC_BNE: /* rx != rx */
5924 case OPC_BGTZ: /* 0 > 0 */
5925 case OPC_BLTZ: /* 0 < 0 */
5926 /* Treat as NOP. */
5927 goto out;
5928 case OPC_BLTZAL: /* 0 < 0 */
5929 /* Handle as an unconditional branch to get correct delay
5930 slot checking. */
5931 blink = 31;
5932 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5933 ctx->hflags |= MIPS_HFLAG_B;
5934 break;
5935 case OPC_BLTZALL: /* 0 < 0 likely */
5936 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5937 /* Skip the instruction in the delay slot */
5938 ctx->base.pc_next += 4;
5939 goto out;
5940 case OPC_BNEL: /* rx != rx likely */
5941 case OPC_BGTZL: /* 0 > 0 likely */
5942 case OPC_BLTZL: /* 0 < 0 likely */
5943 /* Skip the instruction in the delay slot */
5944 ctx->base.pc_next += 4;
5945 goto out;
5946 case OPC_J:
5947 ctx->hflags |= MIPS_HFLAG_B;
5948 break;
5949 case OPC_JALX:
5950 ctx->hflags |= MIPS_HFLAG_BX;
5951 /* Fallthrough */
5952 case OPC_JAL:
5953 blink = 31;
5954 ctx->hflags |= MIPS_HFLAG_B;
5955 break;
5956 case OPC_JR:
5957 ctx->hflags |= MIPS_HFLAG_BR;
5958 break;
5959 case OPC_JALR:
5960 blink = rt;
5961 ctx->hflags |= MIPS_HFLAG_BR;
5962 break;
5963 default:
5964 MIPS_INVAL("branch/jump");
5965 generate_exception_end(ctx, EXCP_RI);
5966 goto out;
5968 } else {
5969 switch (opc) {
5970 case OPC_BEQ:
5971 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5972 goto not_likely;
5973 case OPC_BEQL:
5974 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5975 goto likely;
5976 case OPC_BNE:
5977 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5978 goto not_likely;
5979 case OPC_BNEL:
5980 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5981 goto likely;
5982 case OPC_BGEZ:
5983 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5984 goto not_likely;
5985 case OPC_BGEZL:
5986 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5987 goto likely;
5988 case OPC_BGEZAL:
5989 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5990 blink = 31;
5991 goto not_likely;
5992 case OPC_BGEZALL:
5993 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5994 blink = 31;
5995 goto likely;
5996 case OPC_BGTZ:
5997 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5998 goto not_likely;
5999 case OPC_BGTZL:
6000 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6001 goto likely;
6002 case OPC_BLEZ:
6003 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6004 goto not_likely;
6005 case OPC_BLEZL:
6006 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6007 goto likely;
6008 case OPC_BLTZ:
6009 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6010 goto not_likely;
6011 case OPC_BLTZL:
6012 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6013 goto likely;
6014 case OPC_BPOSGE32:
6015 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6016 goto not_likely;
6017 #if defined(TARGET_MIPS64)
6018 case OPC_BPOSGE64:
6019 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6020 goto not_likely;
6021 #endif
6022 case OPC_BLTZAL:
6023 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6024 blink = 31;
6025 not_likely:
6026 ctx->hflags |= MIPS_HFLAG_BC;
6027 break;
6028 case OPC_BLTZALL:
6029 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6030 blink = 31;
6031 likely:
6032 ctx->hflags |= MIPS_HFLAG_BL;
6033 break;
6034 default:
6035 MIPS_INVAL("conditional branch/jump");
6036 generate_exception_end(ctx, EXCP_RI);
6037 goto out;
6041 ctx->btarget = btgt;
6043 switch (delayslot_size) {
6044 case 2:
6045 ctx->hflags |= MIPS_HFLAG_BDS16;
6046 break;
6047 case 4:
6048 ctx->hflags |= MIPS_HFLAG_BDS32;
6049 break;
6052 if (blink > 0) {
6053 int post_delay = insn_bytes + delayslot_size;
6054 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6056 tcg_gen_movi_tl(cpu_gpr[blink],
6057 ctx->base.pc_next + post_delay + lowbit);
6060 out:
6061 if (insn_bytes == 2)
6062 ctx->hflags |= MIPS_HFLAG_B16;
6063 tcg_temp_free(t0);
6064 tcg_temp_free(t1);
6068 /* nanoMIPS Branches */
6069 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6070 int insn_bytes,
6071 int rs, int rt, int32_t offset)
6073 target_ulong btgt = -1;
6074 int bcond_compute = 0;
6075 TCGv t0 = tcg_temp_new();
6076 TCGv t1 = tcg_temp_new();
6078 /* Load needed operands */
6079 switch (opc) {
6080 case OPC_BEQ:
6081 case OPC_BNE:
6082 /* Compare two registers */
6083 if (rs != rt) {
6084 gen_load_gpr(t0, rs);
6085 gen_load_gpr(t1, rt);
6086 bcond_compute = 1;
6088 btgt = ctx->base.pc_next + insn_bytes + offset;
6089 break;
6090 case OPC_BGEZAL:
6091 /* Compare to zero */
6092 if (rs != 0) {
6093 gen_load_gpr(t0, rs);
6094 bcond_compute = 1;
6096 btgt = ctx->base.pc_next + insn_bytes + offset;
6097 break;
6098 case OPC_BPOSGE32:
6099 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6100 bcond_compute = 1;
6101 btgt = ctx->base.pc_next + insn_bytes + offset;
6102 break;
6103 case OPC_JR:
6104 case OPC_JALR:
6105 /* Jump to register */
6106 if (offset != 0 && offset != 16) {
6107 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6108 others are reserved. */
6109 MIPS_INVAL("jump hint");
6110 generate_exception_end(ctx, EXCP_RI);
6111 goto out;
6113 gen_load_gpr(btarget, rs);
6114 break;
6115 default:
6116 MIPS_INVAL("branch/jump");
6117 generate_exception_end(ctx, EXCP_RI);
6118 goto out;
6120 if (bcond_compute == 0) {
6121 /* No condition to be computed */
6122 switch (opc) {
6123 case OPC_BEQ: /* rx == rx */
6124 /* Always take */
6125 ctx->hflags |= MIPS_HFLAG_B;
6126 break;
6127 case OPC_BGEZAL: /* 0 >= 0 */
6128 /* Always take and link */
6129 tcg_gen_movi_tl(cpu_gpr[31],
6130 ctx->base.pc_next + insn_bytes);
6131 ctx->hflags |= MIPS_HFLAG_B;
6132 break;
6133 case OPC_BNE: /* rx != rx */
6134 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6135 /* Skip the instruction in the delay slot */
6136 ctx->base.pc_next += 4;
6137 goto out;
6138 case OPC_JR:
6139 ctx->hflags |= MIPS_HFLAG_BR;
6140 break;
6141 case OPC_JALR:
6142 if (rt > 0) {
6143 tcg_gen_movi_tl(cpu_gpr[rt],
6144 ctx->base.pc_next + insn_bytes);
6146 ctx->hflags |= MIPS_HFLAG_BR;
6147 break;
6148 default:
6149 MIPS_INVAL("branch/jump");
6150 generate_exception_end(ctx, EXCP_RI);
6151 goto out;
6153 } else {
6154 switch (opc) {
6155 case OPC_BEQ:
6156 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6157 goto not_likely;
6158 case OPC_BNE:
6159 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6160 goto not_likely;
6161 case OPC_BGEZAL:
6162 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6163 tcg_gen_movi_tl(cpu_gpr[31],
6164 ctx->base.pc_next + insn_bytes);
6165 goto not_likely;
6166 case OPC_BPOSGE32:
6167 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6168 not_likely:
6169 ctx->hflags |= MIPS_HFLAG_BC;
6170 break;
6171 default:
6172 MIPS_INVAL("conditional branch/jump");
6173 generate_exception_end(ctx, EXCP_RI);
6174 goto out;
6178 ctx->btarget = btgt;
6180 out:
6181 if (insn_bytes == 2) {
6182 ctx->hflags |= MIPS_HFLAG_B16;
6184 tcg_temp_free(t0);
6185 tcg_temp_free(t1);
6189 /* special3 bitfield operations */
6190 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
6191 int rs, int lsb, int msb)
6193 TCGv t0 = tcg_temp_new();
6194 TCGv t1 = tcg_temp_new();
6196 gen_load_gpr(t1, rs);
6197 switch (opc) {
6198 case OPC_EXT:
6199 if (lsb + msb > 31) {
6200 goto fail;
6202 if (msb != 31) {
6203 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6204 } else {
6205 /* The two checks together imply that lsb == 0,
6206 so this is a simple sign-extension. */
6207 tcg_gen_ext32s_tl(t0, t1);
6209 break;
6210 #if defined(TARGET_MIPS64)
6211 case OPC_DEXTU:
6212 lsb += 32;
6213 goto do_dext;
6214 case OPC_DEXTM:
6215 msb += 32;
6216 goto do_dext;
6217 case OPC_DEXT:
6218 do_dext:
6219 if (lsb + msb > 63) {
6220 goto fail;
6222 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6223 break;
6224 #endif
6225 case OPC_INS:
6226 if (lsb > msb) {
6227 goto fail;
6229 gen_load_gpr(t0, rt);
6230 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6231 tcg_gen_ext32s_tl(t0, t0);
6232 break;
6233 #if defined(TARGET_MIPS64)
6234 case OPC_DINSU:
6235 lsb += 32;
6236 /* FALLTHRU */
6237 case OPC_DINSM:
6238 msb += 32;
6239 /* FALLTHRU */
6240 case OPC_DINS:
6241 if (lsb > msb) {
6242 goto fail;
6244 gen_load_gpr(t0, rt);
6245 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6246 break;
6247 #endif
6248 default:
6249 fail:
6250 MIPS_INVAL("bitops");
6251 generate_exception_end(ctx, EXCP_RI);
6252 tcg_temp_free(t0);
6253 tcg_temp_free(t1);
6254 return;
6256 gen_store_gpr(t0, rt);
6257 tcg_temp_free(t0);
6258 tcg_temp_free(t1);
6261 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6263 TCGv t0;
6265 if (rd == 0) {
6266 /* If no destination, treat it as a NOP. */
6267 return;
6270 t0 = tcg_temp_new();
6271 gen_load_gpr(t0, rt);
6272 switch (op2) {
6273 case OPC_WSBH:
6275 TCGv t1 = tcg_temp_new();
6276 TCGv t2 = tcg_const_tl(0x00FF00FF);
6278 tcg_gen_shri_tl(t1, t0, 8);
6279 tcg_gen_and_tl(t1, t1, t2);
6280 tcg_gen_and_tl(t0, t0, t2);
6281 tcg_gen_shli_tl(t0, t0, 8);
6282 tcg_gen_or_tl(t0, t0, t1);
6283 tcg_temp_free(t2);
6284 tcg_temp_free(t1);
6285 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6287 break;
6288 case OPC_SEB:
6289 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6290 break;
6291 case OPC_SEH:
6292 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6293 break;
6294 #if defined(TARGET_MIPS64)
6295 case OPC_DSBH:
6297 TCGv t1 = tcg_temp_new();
6298 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6300 tcg_gen_shri_tl(t1, t0, 8);
6301 tcg_gen_and_tl(t1, t1, t2);
6302 tcg_gen_and_tl(t0, t0, t2);
6303 tcg_gen_shli_tl(t0, t0, 8);
6304 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6305 tcg_temp_free(t2);
6306 tcg_temp_free(t1);
6308 break;
6309 case OPC_DSHD:
6311 TCGv t1 = tcg_temp_new();
6312 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6314 tcg_gen_shri_tl(t1, t0, 16);
6315 tcg_gen_and_tl(t1, t1, t2);
6316 tcg_gen_and_tl(t0, t0, t2);
6317 tcg_gen_shli_tl(t0, t0, 16);
6318 tcg_gen_or_tl(t0, t0, t1);
6319 tcg_gen_shri_tl(t1, t0, 32);
6320 tcg_gen_shli_tl(t0, t0, 32);
6321 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6322 tcg_temp_free(t2);
6323 tcg_temp_free(t1);
6325 break;
6326 #endif
6327 default:
6328 MIPS_INVAL("bsfhl");
6329 generate_exception_end(ctx, EXCP_RI);
6330 tcg_temp_free(t0);
6331 return;
6333 tcg_temp_free(t0);
6336 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6337 int imm2)
6339 TCGv t0;
6340 TCGv t1;
6341 if (rd == 0) {
6342 /* Treat as NOP. */
6343 return;
6345 t0 = tcg_temp_new();
6346 t1 = tcg_temp_new();
6347 gen_load_gpr(t0, rs);
6348 gen_load_gpr(t1, rt);
6349 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6350 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6351 if (opc == OPC_LSA) {
6352 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6355 tcg_temp_free(t1);
6356 tcg_temp_free(t0);
6358 return;
6361 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6362 int rt, int bits)
6364 TCGv t0;
6365 if (rd == 0) {
6366 /* Treat as NOP. */
6367 return;
6369 t0 = tcg_temp_new();
6370 if (bits == 0 || bits == wordsz) {
6371 if (bits == 0) {
6372 gen_load_gpr(t0, rt);
6373 } else {
6374 gen_load_gpr(t0, rs);
6376 switch (wordsz) {
6377 case 32:
6378 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6379 break;
6380 #if defined(TARGET_MIPS64)
6381 case 64:
6382 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6383 break;
6384 #endif
6386 } else {
6387 TCGv t1 = tcg_temp_new();
6388 gen_load_gpr(t0, rt);
6389 gen_load_gpr(t1, rs);
6390 switch (wordsz) {
6391 case 32:
6393 TCGv_i64 t2 = tcg_temp_new_i64();
6394 tcg_gen_concat_tl_i64(t2, t1, t0);
6395 tcg_gen_shri_i64(t2, t2, 32 - bits);
6396 gen_move_low32(cpu_gpr[rd], t2);
6397 tcg_temp_free_i64(t2);
6399 break;
6400 #if defined(TARGET_MIPS64)
6401 case 64:
6402 tcg_gen_shli_tl(t0, t0, bits);
6403 tcg_gen_shri_tl(t1, t1, 64 - bits);
6404 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6405 break;
6406 #endif
6408 tcg_temp_free(t1);
6411 tcg_temp_free(t0);
6414 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6415 int bp)
6417 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6420 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6421 int shift)
6423 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6426 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6428 TCGv t0;
6429 if (rd == 0) {
6430 /* Treat as NOP. */
6431 return;
6433 t0 = tcg_temp_new();
6434 gen_load_gpr(t0, rt);
6435 switch (opc) {
6436 case OPC_BITSWAP:
6437 gen_helper_bitswap(cpu_gpr[rd], t0);
6438 break;
6439 #if defined(TARGET_MIPS64)
6440 case OPC_DBITSWAP:
6441 gen_helper_dbitswap(cpu_gpr[rd], t0);
6442 break;
6443 #endif
6445 tcg_temp_free(t0);
6448 #ifndef CONFIG_USER_ONLY
6449 /* CP0 (MMU and control) */
6450 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6452 TCGv_i64 t0 = tcg_temp_new_i64();
6453 TCGv_i64 t1 = tcg_temp_new_i64();
6455 tcg_gen_ext_tl_i64(t0, arg);
6456 tcg_gen_ld_i64(t1, cpu_env, off);
6457 #if defined(TARGET_MIPS64)
6458 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6459 #else
6460 tcg_gen_concat32_i64(t1, t1, t0);
6461 #endif
6462 tcg_gen_st_i64(t1, cpu_env, off);
6463 tcg_temp_free_i64(t1);
6464 tcg_temp_free_i64(t0);
6467 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6469 TCGv_i64 t0 = tcg_temp_new_i64();
6470 TCGv_i64 t1 = tcg_temp_new_i64();
6472 tcg_gen_ext_tl_i64(t0, arg);
6473 tcg_gen_ld_i64(t1, cpu_env, off);
6474 tcg_gen_concat32_i64(t1, t1, t0);
6475 tcg_gen_st_i64(t1, cpu_env, off);
6476 tcg_temp_free_i64(t1);
6477 tcg_temp_free_i64(t0);
6480 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6482 TCGv_i64 t0 = tcg_temp_new_i64();
6484 tcg_gen_ld_i64(t0, cpu_env, off);
6485 #if defined(TARGET_MIPS64)
6486 tcg_gen_shri_i64(t0, t0, 30);
6487 #else
6488 tcg_gen_shri_i64(t0, t0, 32);
6489 #endif
6490 gen_move_low32(arg, t0);
6491 tcg_temp_free_i64(t0);
6494 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6496 TCGv_i64 t0 = tcg_temp_new_i64();
6498 tcg_gen_ld_i64(t0, cpu_env, off);
6499 tcg_gen_shri_i64(t0, t0, 32 + shift);
6500 gen_move_low32(arg, t0);
6501 tcg_temp_free_i64(t0);
6504 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6506 TCGv_i32 t0 = tcg_temp_new_i32();
6508 tcg_gen_ld_i32(t0, cpu_env, off);
6509 tcg_gen_ext_i32_tl(arg, t0);
6510 tcg_temp_free_i32(t0);
6513 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6515 tcg_gen_ld_tl(arg, cpu_env, off);
6516 tcg_gen_ext32s_tl(arg, arg);
6519 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6521 TCGv_i32 t0 = tcg_temp_new_i32();
6523 tcg_gen_trunc_tl_i32(t0, arg);
6524 tcg_gen_st_i32(t0, cpu_env, off);
6525 tcg_temp_free_i32(t0);
6528 #define CP0_CHECK(c) \
6529 do { \
6530 if (!(c)) { \
6531 goto cp0_unimplemented; \
6533 } while (0)
6535 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6537 const char *register_name = "invalid";
6539 switch (reg) {
6540 case CP0_REGISTER_02:
6541 switch (sel) {
6542 case 0:
6543 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6544 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6545 register_name = "EntryLo0";
6546 break;
6547 default:
6548 goto cp0_unimplemented;
6550 break;
6551 case CP0_REGISTER_03:
6552 switch (sel) {
6553 case 0:
6554 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6555 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6556 register_name = "EntryLo1";
6557 break;
6558 default:
6559 goto cp0_unimplemented;
6561 break;
6562 case CP0_REGISTER_09:
6563 switch (sel) {
6564 case 7:
6565 CP0_CHECK(ctx->saar);
6566 gen_helper_mfhc0_saar(arg, cpu_env);
6567 register_name = "SAAR";
6568 break;
6569 default:
6570 goto cp0_unimplemented;
6572 break;
6573 case CP0_REGISTER_17:
6574 switch (sel) {
6575 case 0:
6576 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6577 ctx->CP0_LLAddr_shift);
6578 register_name = "LLAddr";
6579 break;
6580 case 1:
6581 CP0_CHECK(ctx->mrp);
6582 gen_helper_mfhc0_maar(arg, cpu_env);
6583 register_name = "MAAR";
6584 break;
6585 default:
6586 goto cp0_unimplemented;
6588 break;
6589 case CP0_REGISTER_28:
6590 switch (sel) {
6591 case 0:
6592 case 2:
6593 case 4:
6594 case 6:
6595 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6596 register_name = "TagLo";
6597 break;
6598 default:
6599 goto cp0_unimplemented;
6601 break;
6602 default:
6603 goto cp0_unimplemented;
6605 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6606 return;
6608 cp0_unimplemented:
6609 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6610 register_name, reg, sel);
6611 tcg_gen_movi_tl(arg, 0);
6614 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6616 const char *register_name = "invalid";
6617 uint64_t mask = ctx->PAMask >> 36;
6619 switch (reg) {
6620 case CP0_REGISTER_02:
6621 switch (sel) {
6622 case 0:
6623 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6624 tcg_gen_andi_tl(arg, arg, mask);
6625 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6626 register_name = "EntryLo0";
6627 break;
6628 default:
6629 goto cp0_unimplemented;
6631 break;
6632 case CP0_REGISTER_03:
6633 switch (sel) {
6634 case 0:
6635 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6636 tcg_gen_andi_tl(arg, arg, mask);
6637 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6638 register_name = "EntryLo1";
6639 break;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case CP0_REGISTER_09:
6645 switch (sel) {
6646 case 7:
6647 CP0_CHECK(ctx->saar);
6648 gen_helper_mthc0_saar(cpu_env, arg);
6649 register_name = "SAAR";
6650 break;
6651 default:
6652 goto cp0_unimplemented;
6654 case CP0_REGISTER_17:
6655 switch (sel) {
6656 case 0:
6657 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6658 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6659 relevant for modern MIPS cores supporting MTHC0, therefore
6660 treating MTHC0 to LLAddr as NOP. */
6661 register_name = "LLAddr";
6662 break;
6663 case 1:
6664 CP0_CHECK(ctx->mrp);
6665 gen_helper_mthc0_maar(cpu_env, arg);
6666 register_name = "MAAR";
6667 break;
6668 default:
6669 goto cp0_unimplemented;
6671 break;
6672 case CP0_REGISTER_28:
6673 switch (sel) {
6674 case 0:
6675 case 2:
6676 case 4:
6677 case 6:
6678 tcg_gen_andi_tl(arg, arg, mask);
6679 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6680 register_name = "TagLo";
6681 break;
6682 default:
6683 goto cp0_unimplemented;
6685 break;
6686 default:
6687 goto cp0_unimplemented;
6689 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6691 cp0_unimplemented:
6692 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6693 register_name, reg, sel);
6696 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6698 if (ctx->insn_flags & ISA_MIPS32R6) {
6699 tcg_gen_movi_tl(arg, 0);
6700 } else {
6701 tcg_gen_movi_tl(arg, ~0);
6705 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6707 const char *register_name = "invalid";
6709 if (sel != 0)
6710 check_insn(ctx, ISA_MIPS32);
6712 switch (reg) {
6713 case CP0_REGISTER_00:
6714 switch (sel) {
6715 case 0:
6716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6717 register_name = "Index";
6718 break;
6719 case 1:
6720 CP0_CHECK(ctx->insn_flags & ASE_MT);
6721 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6722 register_name = "MVPControl";
6723 break;
6724 case 2:
6725 CP0_CHECK(ctx->insn_flags & ASE_MT);
6726 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6727 register_name = "MVPConf0";
6728 break;
6729 case 3:
6730 CP0_CHECK(ctx->insn_flags & ASE_MT);
6731 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6732 register_name = "MVPConf1";
6733 break;
6734 case 4:
6735 CP0_CHECK(ctx->vp);
6736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6737 register_name = "VPControl";
6738 break;
6739 default:
6740 goto cp0_unimplemented;
6742 break;
6743 case CP0_REGISTER_01:
6744 switch (sel) {
6745 case 0:
6746 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6747 gen_helper_mfc0_random(arg, cpu_env);
6748 register_name = "Random";
6749 break;
6750 case 1:
6751 CP0_CHECK(ctx->insn_flags & ASE_MT);
6752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6753 register_name = "VPEControl";
6754 break;
6755 case 2:
6756 CP0_CHECK(ctx->insn_flags & ASE_MT);
6757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6758 register_name = "VPEConf0";
6759 break;
6760 case 3:
6761 CP0_CHECK(ctx->insn_flags & ASE_MT);
6762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6763 register_name = "VPEConf1";
6764 break;
6765 case 4:
6766 CP0_CHECK(ctx->insn_flags & ASE_MT);
6767 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6768 register_name = "YQMask";
6769 break;
6770 case 5:
6771 CP0_CHECK(ctx->insn_flags & ASE_MT);
6772 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6773 register_name = "VPESchedule";
6774 break;
6775 case 6:
6776 CP0_CHECK(ctx->insn_flags & ASE_MT);
6777 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6778 register_name = "VPEScheFBack";
6779 break;
6780 case 7:
6781 CP0_CHECK(ctx->insn_flags & ASE_MT);
6782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6783 register_name = "VPEOpt";
6784 break;
6785 default:
6786 goto cp0_unimplemented;
6788 break;
6789 case CP0_REGISTER_02:
6790 switch (sel) {
6791 case 0:
6793 TCGv_i64 tmp = tcg_temp_new_i64();
6794 tcg_gen_ld_i64(tmp, cpu_env,
6795 offsetof(CPUMIPSState, CP0_EntryLo0));
6796 #if defined(TARGET_MIPS64)
6797 if (ctx->rxi) {
6798 /* Move RI/XI fields to bits 31:30 */
6799 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6800 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6802 #endif
6803 gen_move_low32(arg, tmp);
6804 tcg_temp_free_i64(tmp);
6806 register_name = "EntryLo0";
6807 break;
6808 case 1:
6809 CP0_CHECK(ctx->insn_flags & ASE_MT);
6810 gen_helper_mfc0_tcstatus(arg, cpu_env);
6811 register_name = "TCStatus";
6812 break;
6813 case 2:
6814 CP0_CHECK(ctx->insn_flags & ASE_MT);
6815 gen_helper_mfc0_tcbind(arg, cpu_env);
6816 register_name = "TCBind";
6817 break;
6818 case 3:
6819 CP0_CHECK(ctx->insn_flags & ASE_MT);
6820 gen_helper_mfc0_tcrestart(arg, cpu_env);
6821 register_name = "TCRestart";
6822 break;
6823 case 4:
6824 CP0_CHECK(ctx->insn_flags & ASE_MT);
6825 gen_helper_mfc0_tchalt(arg, cpu_env);
6826 register_name = "TCHalt";
6827 break;
6828 case 5:
6829 CP0_CHECK(ctx->insn_flags & ASE_MT);
6830 gen_helper_mfc0_tccontext(arg, cpu_env);
6831 register_name = "TCContext";
6832 break;
6833 case 6:
6834 CP0_CHECK(ctx->insn_flags & ASE_MT);
6835 gen_helper_mfc0_tcschedule(arg, cpu_env);
6836 register_name = "TCSchedule";
6837 break;
6838 case 7:
6839 CP0_CHECK(ctx->insn_flags & ASE_MT);
6840 gen_helper_mfc0_tcschefback(arg, cpu_env);
6841 register_name = "TCScheFBack";
6842 break;
6843 default:
6844 goto cp0_unimplemented;
6846 break;
6847 case CP0_REGISTER_03:
6848 switch (sel) {
6849 case 0:
6851 TCGv_i64 tmp = tcg_temp_new_i64();
6852 tcg_gen_ld_i64(tmp, cpu_env,
6853 offsetof(CPUMIPSState, CP0_EntryLo1));
6854 #if defined(TARGET_MIPS64)
6855 if (ctx->rxi) {
6856 /* Move RI/XI fields to bits 31:30 */
6857 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6858 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6860 #endif
6861 gen_move_low32(arg, tmp);
6862 tcg_temp_free_i64(tmp);
6864 register_name = "EntryLo1";
6865 break;
6866 case 1:
6867 CP0_CHECK(ctx->vp);
6868 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6869 register_name = "GlobalNumber";
6870 break;
6871 default:
6872 goto cp0_unimplemented;
6874 break;
6875 case CP0_REGISTER_04:
6876 switch (sel) {
6877 case 0:
6878 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6879 tcg_gen_ext32s_tl(arg, arg);
6880 register_name = "Context";
6881 break;
6882 case 1:
6883 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6884 register_name = "ContextConfig";
6885 goto cp0_unimplemented;
6886 case 2:
6887 CP0_CHECK(ctx->ulri);
6888 tcg_gen_ld_tl(arg, cpu_env,
6889 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6890 tcg_gen_ext32s_tl(arg, arg);
6891 register_name = "UserLocal";
6892 break;
6893 default:
6894 goto cp0_unimplemented;
6896 break;
6897 case CP0_REGISTER_05:
6898 switch (sel) {
6899 case 0:
6900 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6901 register_name = "PageMask";
6902 break;
6903 case 1:
6904 check_insn(ctx, ISA_MIPS32R2);
6905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6906 register_name = "PageGrain";
6907 break;
6908 case 2:
6909 CP0_CHECK(ctx->sc);
6910 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6911 tcg_gen_ext32s_tl(arg, arg);
6912 register_name = "SegCtl0";
6913 break;
6914 case 3:
6915 CP0_CHECK(ctx->sc);
6916 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6917 tcg_gen_ext32s_tl(arg, arg);
6918 register_name = "SegCtl1";
6919 break;
6920 case 4:
6921 CP0_CHECK(ctx->sc);
6922 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6923 tcg_gen_ext32s_tl(arg, arg);
6924 register_name = "SegCtl2";
6925 break;
6926 case 5:
6927 check_pw(ctx);
6928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6929 register_name = "PWBase";
6930 break;
6931 case 6:
6932 check_pw(ctx);
6933 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6934 register_name = "PWField";
6935 break;
6936 case 7:
6937 check_pw(ctx);
6938 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6939 register_name = "PWSize";
6940 break;
6941 default:
6942 goto cp0_unimplemented;
6944 break;
6945 case CP0_REGISTER_06:
6946 switch (sel) {
6947 case 0:
6948 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6949 register_name = "Wired";
6950 break;
6951 case 1:
6952 check_insn(ctx, ISA_MIPS32R2);
6953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6954 register_name = "SRSConf0";
6955 break;
6956 case 2:
6957 check_insn(ctx, ISA_MIPS32R2);
6958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6959 register_name = "SRSConf1";
6960 break;
6961 case 3:
6962 check_insn(ctx, ISA_MIPS32R2);
6963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6964 register_name = "SRSConf2";
6965 break;
6966 case 4:
6967 check_insn(ctx, ISA_MIPS32R2);
6968 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6969 register_name = "SRSConf3";
6970 break;
6971 case 5:
6972 check_insn(ctx, ISA_MIPS32R2);
6973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6974 register_name = "SRSConf4";
6975 break;
6976 case 6:
6977 check_pw(ctx);
6978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6979 register_name = "PWCtl";
6980 break;
6981 default:
6982 goto cp0_unimplemented;
6984 break;
6985 case CP0_REGISTER_07:
6986 switch (sel) {
6987 case 0:
6988 check_insn(ctx, ISA_MIPS32R2);
6989 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6990 register_name = "HWREna";
6991 break;
6992 default:
6993 goto cp0_unimplemented;
6995 break;
6996 case CP0_REGISTER_08:
6997 switch (sel) {
6998 case 0:
6999 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7000 tcg_gen_ext32s_tl(arg, arg);
7001 register_name = "BadVAddr";
7002 break;
7003 case 1:
7004 CP0_CHECK(ctx->bi);
7005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7006 register_name = "BadInstr";
7007 break;
7008 case 2:
7009 CP0_CHECK(ctx->bp);
7010 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7011 register_name = "BadInstrP";
7012 break;
7013 case 3:
7014 CP0_CHECK(ctx->bi);
7015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7016 tcg_gen_andi_tl(arg, arg, ~0xffff);
7017 register_name = "BadInstrX";
7018 break;
7019 default:
7020 goto cp0_unimplemented;
7022 break;
7023 case CP0_REGISTER_09:
7024 switch (sel) {
7025 case 0:
7026 /* Mark as an IO operation because we read the time. */
7027 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7028 gen_io_start();
7030 gen_helper_mfc0_count(arg, cpu_env);
7031 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7032 gen_io_end();
7034 /* Break the TB to be able to take timer interrupts immediately
7035 after reading count. DISAS_STOP isn't sufficient, we need to
7036 ensure we break completely out of translated code. */
7037 gen_save_pc(ctx->base.pc_next + 4);
7038 ctx->base.is_jmp = DISAS_EXIT;
7039 register_name = "Count";
7040 break;
7041 case 6:
7042 CP0_CHECK(ctx->saar);
7043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7044 register_name = "SAARI";
7045 break;
7046 case 7:
7047 CP0_CHECK(ctx->saar);
7048 gen_helper_mfc0_saar(arg, cpu_env);
7049 register_name = "SAAR";
7050 break;
7051 default:
7052 goto cp0_unimplemented;
7054 break;
7055 case CP0_REGISTER_10:
7056 switch (sel) {
7057 case 0:
7058 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7059 tcg_gen_ext32s_tl(arg, arg);
7060 register_name = "EntryHi";
7061 break;
7062 default:
7063 goto cp0_unimplemented;
7065 break;
7066 case CP0_REGISTER_11:
7067 switch (sel) {
7068 case 0:
7069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7070 register_name = "Compare";
7071 break;
7072 /* 6,7 are implementation dependent */
7073 default:
7074 goto cp0_unimplemented;
7076 break;
7077 case CP0_REGISTER_12:
7078 switch (sel) {
7079 case 0:
7080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7081 register_name = "Status";
7082 break;
7083 case 1:
7084 check_insn(ctx, ISA_MIPS32R2);
7085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7086 register_name = "IntCtl";
7087 break;
7088 case 2:
7089 check_insn(ctx, ISA_MIPS32R2);
7090 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7091 register_name = "SRSCtl";
7092 break;
7093 case 3:
7094 check_insn(ctx, ISA_MIPS32R2);
7095 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7096 register_name = "SRSMap";
7097 break;
7098 default:
7099 goto cp0_unimplemented;
7101 break;
7102 case CP0_REGISTER_13:
7103 switch (sel) {
7104 case 0:
7105 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7106 register_name = "Cause";
7107 break;
7108 default:
7109 goto cp0_unimplemented;
7111 break;
7112 case CP0_REGISTER_14:
7113 switch (sel) {
7114 case 0:
7115 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7116 tcg_gen_ext32s_tl(arg, arg);
7117 register_name = "EPC";
7118 break;
7119 default:
7120 goto cp0_unimplemented;
7122 break;
7123 case CP0_REGISTER_15:
7124 switch (sel) {
7125 case 0:
7126 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7127 register_name = "PRid";
7128 break;
7129 case 1:
7130 check_insn(ctx, ISA_MIPS32R2);
7131 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7132 tcg_gen_ext32s_tl(arg, arg);
7133 register_name = "EBase";
7134 break;
7135 case 3:
7136 check_insn(ctx, ISA_MIPS32R2);
7137 CP0_CHECK(ctx->cmgcr);
7138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7139 tcg_gen_ext32s_tl(arg, arg);
7140 register_name = "CMGCRBase";
7141 break;
7142 default:
7143 goto cp0_unimplemented;
7145 break;
7146 case CP0_REGISTER_16:
7147 switch (sel) {
7148 case 0:
7149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7150 register_name = "Config";
7151 break;
7152 case 1:
7153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7154 register_name = "Config1";
7155 break;
7156 case 2:
7157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7158 register_name = "Config2";
7159 break;
7160 case 3:
7161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7162 register_name = "Config3";
7163 break;
7164 case 4:
7165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7166 register_name = "Config4";
7167 break;
7168 case 5:
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7170 register_name = "Config5";
7171 break;
7172 /* 6,7 are implementation dependent */
7173 case 6:
7174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7175 register_name = "Config6";
7176 break;
7177 case 7:
7178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7179 register_name = "Config7";
7180 break;
7181 default:
7182 goto cp0_unimplemented;
7184 break;
7185 case CP0_REGISTER_17:
7186 switch (sel) {
7187 case 0:
7188 gen_helper_mfc0_lladdr(arg, cpu_env);
7189 register_name = "LLAddr";
7190 break;
7191 case 1:
7192 CP0_CHECK(ctx->mrp);
7193 gen_helper_mfc0_maar(arg, cpu_env);
7194 register_name = "MAAR";
7195 break;
7196 case 2:
7197 CP0_CHECK(ctx->mrp);
7198 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7199 register_name = "MAARI";
7200 break;
7201 default:
7202 goto cp0_unimplemented;
7204 break;
7205 case CP0_REGISTER_18:
7206 switch (sel) {
7207 case 0:
7208 case 1:
7209 case 2:
7210 case 3:
7211 case 4:
7212 case 5:
7213 case 6:
7214 case 7:
7215 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7216 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7217 register_name = "WatchLo";
7218 break;
7219 default:
7220 goto cp0_unimplemented;
7222 break;
7223 case CP0_REGISTER_19:
7224 switch (sel) {
7225 case 0:
7226 case 1:
7227 case 2:
7228 case 3:
7229 case 4:
7230 case 5:
7231 case 6:
7232 case 7:
7233 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7234 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7235 register_name = "WatchHi";
7236 break;
7237 default:
7238 goto cp0_unimplemented;
7240 break;
7241 case CP0_REGISTER_20:
7242 switch (sel) {
7243 case 0:
7244 #if defined(TARGET_MIPS64)
7245 check_insn(ctx, ISA_MIPS3);
7246 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7247 tcg_gen_ext32s_tl(arg, arg);
7248 register_name = "XContext";
7249 break;
7250 #endif
7251 default:
7252 goto cp0_unimplemented;
7254 break;
7255 case CP0_REGISTER_21:
7256 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7257 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7258 switch (sel) {
7259 case 0:
7260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7261 register_name = "Framemask";
7262 break;
7263 default:
7264 goto cp0_unimplemented;
7266 break;
7267 case CP0_REGISTER_22:
7268 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7269 register_name = "'Diagnostic"; /* implementation dependent */
7270 break;
7271 case CP0_REGISTER_23:
7272 switch (sel) {
7273 case 0:
7274 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7275 register_name = "Debug";
7276 break;
7277 case 1:
7278 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7279 register_name = "TraceControl";
7280 goto cp0_unimplemented;
7281 case 2:
7282 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7283 register_name = "TraceControl2";
7284 goto cp0_unimplemented;
7285 case 3:
7286 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7287 register_name = "UserTraceData";
7288 goto cp0_unimplemented;
7289 case 4:
7290 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7291 register_name = "TraceBPC";
7292 goto cp0_unimplemented;
7293 default:
7294 goto cp0_unimplemented;
7296 break;
7297 case CP0_REGISTER_24:
7298 switch (sel) {
7299 case 0:
7300 /* EJTAG support */
7301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7302 tcg_gen_ext32s_tl(arg, arg);
7303 register_name = "DEPC";
7304 break;
7305 default:
7306 goto cp0_unimplemented;
7308 break;
7309 case CP0_REGISTER_25:
7310 switch (sel) {
7311 case 0:
7312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7313 register_name = "Performance0";
7314 break;
7315 case 1:
7316 // gen_helper_mfc0_performance1(arg);
7317 register_name = "Performance1";
7318 goto cp0_unimplemented;
7319 case 2:
7320 // gen_helper_mfc0_performance2(arg);
7321 register_name = "Performance2";
7322 goto cp0_unimplemented;
7323 case 3:
7324 // gen_helper_mfc0_performance3(arg);
7325 register_name = "Performance3";
7326 goto cp0_unimplemented;
7327 case 4:
7328 // gen_helper_mfc0_performance4(arg);
7329 register_name = "Performance4";
7330 goto cp0_unimplemented;
7331 case 5:
7332 // gen_helper_mfc0_performance5(arg);
7333 register_name = "Performance5";
7334 goto cp0_unimplemented;
7335 case 6:
7336 // gen_helper_mfc0_performance6(arg);
7337 register_name = "Performance6";
7338 goto cp0_unimplemented;
7339 case 7:
7340 // gen_helper_mfc0_performance7(arg);
7341 register_name = "Performance7";
7342 goto cp0_unimplemented;
7343 default:
7344 goto cp0_unimplemented;
7346 break;
7347 case CP0_REGISTER_26:
7348 switch (sel) {
7349 case 0:
7350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7351 register_name = "ErrCtl";
7352 break;
7353 default:
7354 goto cp0_unimplemented;
7356 break;
7357 case CP0_REGISTER_27:
7358 switch (sel) {
7359 case 0:
7360 case 1:
7361 case 2:
7362 case 3:
7363 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7364 register_name = "CacheErr";
7365 break;
7366 default:
7367 goto cp0_unimplemented;
7369 break;
7370 case CP0_REGISTER_28:
7371 switch (sel) {
7372 case 0:
7373 case 2:
7374 case 4:
7375 case 6:
7377 TCGv_i64 tmp = tcg_temp_new_i64();
7378 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7379 gen_move_low32(arg, tmp);
7380 tcg_temp_free_i64(tmp);
7382 register_name = "TagLo";
7383 break;
7384 case 1:
7385 case 3:
7386 case 5:
7387 case 7:
7388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7389 register_name = "DataLo";
7390 break;
7391 default:
7392 goto cp0_unimplemented;
7394 break;
7395 case CP0_REGISTER_29:
7396 switch (sel) {
7397 case 0:
7398 case 2:
7399 case 4:
7400 case 6:
7401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7402 register_name = "TagHi";
7403 break;
7404 case 1:
7405 case 3:
7406 case 5:
7407 case 7:
7408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7409 register_name = "DataHi";
7410 break;
7411 default:
7412 goto cp0_unimplemented;
7414 break;
7415 case CP0_REGISTER_30:
7416 switch (sel) {
7417 case 0:
7418 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7419 tcg_gen_ext32s_tl(arg, arg);
7420 register_name = "ErrorEPC";
7421 break;
7422 default:
7423 goto cp0_unimplemented;
7425 break;
7426 case CP0_REGISTER_31:
7427 switch (sel) {
7428 case 0:
7429 /* EJTAG support */
7430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7431 register_name = "DESAVE";
7432 break;
7433 case 2:
7434 case 3:
7435 case 4:
7436 case 5:
7437 case 6:
7438 case 7:
7439 CP0_CHECK(ctx->kscrexist & (1 << sel));
7440 tcg_gen_ld_tl(arg, cpu_env,
7441 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7442 tcg_gen_ext32s_tl(arg, arg);
7443 register_name = "KScratch";
7444 break;
7445 default:
7446 goto cp0_unimplemented;
7448 break;
7449 default:
7450 goto cp0_unimplemented;
7452 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7453 return;
7455 cp0_unimplemented:
7456 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7457 register_name, reg, sel);
7458 gen_mfc0_unimplemented(ctx, arg);
7461 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7463 const char *register_name = "invalid";
7465 if (sel != 0)
7466 check_insn(ctx, ISA_MIPS32);
7468 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7469 gen_io_start();
7472 switch (reg) {
7473 case CP0_REGISTER_00:
7474 switch (sel) {
7475 case 0:
7476 gen_helper_mtc0_index(cpu_env, arg);
7477 register_name = "Index";
7478 break;
7479 case 1:
7480 CP0_CHECK(ctx->insn_flags & ASE_MT);
7481 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7482 register_name = "MVPControl";
7483 break;
7484 case 2:
7485 CP0_CHECK(ctx->insn_flags & ASE_MT);
7486 /* ignored */
7487 register_name = "MVPConf0";
7488 break;
7489 case 3:
7490 CP0_CHECK(ctx->insn_flags & ASE_MT);
7491 /* ignored */
7492 register_name = "MVPConf1";
7493 break;
7494 case 4:
7495 CP0_CHECK(ctx->vp);
7496 /* ignored */
7497 register_name = "VPControl";
7498 break;
7499 default:
7500 goto cp0_unimplemented;
7502 break;
7503 case CP0_REGISTER_01:
7504 switch (sel) {
7505 case 0:
7506 /* ignored */
7507 register_name = "Random";
7508 break;
7509 case 1:
7510 CP0_CHECK(ctx->insn_flags & ASE_MT);
7511 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7512 register_name = "VPEControl";
7513 break;
7514 case 2:
7515 CP0_CHECK(ctx->insn_flags & ASE_MT);
7516 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7517 register_name = "VPEConf0";
7518 break;
7519 case 3:
7520 CP0_CHECK(ctx->insn_flags & ASE_MT);
7521 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7522 register_name = "VPEConf1";
7523 break;
7524 case 4:
7525 CP0_CHECK(ctx->insn_flags & ASE_MT);
7526 gen_helper_mtc0_yqmask(cpu_env, arg);
7527 register_name = "YQMask";
7528 break;
7529 case 5:
7530 CP0_CHECK(ctx->insn_flags & ASE_MT);
7531 tcg_gen_st_tl(arg, cpu_env,
7532 offsetof(CPUMIPSState, CP0_VPESchedule));
7533 register_name = "VPESchedule";
7534 break;
7535 case 6:
7536 CP0_CHECK(ctx->insn_flags & ASE_MT);
7537 tcg_gen_st_tl(arg, cpu_env,
7538 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7539 register_name = "VPEScheFBack";
7540 break;
7541 case 7:
7542 CP0_CHECK(ctx->insn_flags & ASE_MT);
7543 gen_helper_mtc0_vpeopt(cpu_env, arg);
7544 register_name = "VPEOpt";
7545 break;
7546 default:
7547 goto cp0_unimplemented;
7549 break;
7550 case CP0_REGISTER_02:
7551 switch (sel) {
7552 case 0:
7553 gen_helper_mtc0_entrylo0(cpu_env, arg);
7554 register_name = "EntryLo0";
7555 break;
7556 case 1:
7557 CP0_CHECK(ctx->insn_flags & ASE_MT);
7558 gen_helper_mtc0_tcstatus(cpu_env, arg);
7559 register_name = "TCStatus";
7560 break;
7561 case 2:
7562 CP0_CHECK(ctx->insn_flags & ASE_MT);
7563 gen_helper_mtc0_tcbind(cpu_env, arg);
7564 register_name = "TCBind";
7565 break;
7566 case 3:
7567 CP0_CHECK(ctx->insn_flags & ASE_MT);
7568 gen_helper_mtc0_tcrestart(cpu_env, arg);
7569 register_name = "TCRestart";
7570 break;
7571 case 4:
7572 CP0_CHECK(ctx->insn_flags & ASE_MT);
7573 gen_helper_mtc0_tchalt(cpu_env, arg);
7574 register_name = "TCHalt";
7575 break;
7576 case 5:
7577 CP0_CHECK(ctx->insn_flags & ASE_MT);
7578 gen_helper_mtc0_tccontext(cpu_env, arg);
7579 register_name = "TCContext";
7580 break;
7581 case 6:
7582 CP0_CHECK(ctx->insn_flags & ASE_MT);
7583 gen_helper_mtc0_tcschedule(cpu_env, arg);
7584 register_name = "TCSchedule";
7585 break;
7586 case 7:
7587 CP0_CHECK(ctx->insn_flags & ASE_MT);
7588 gen_helper_mtc0_tcschefback(cpu_env, arg);
7589 register_name = "TCScheFBack";
7590 break;
7591 default:
7592 goto cp0_unimplemented;
7594 break;
7595 case CP0_REGISTER_03:
7596 switch (sel) {
7597 case 0:
7598 gen_helper_mtc0_entrylo1(cpu_env, arg);
7599 register_name = "EntryLo1";
7600 break;
7601 case 1:
7602 CP0_CHECK(ctx->vp);
7603 /* ignored */
7604 register_name = "GlobalNumber";
7605 break;
7606 default:
7607 goto cp0_unimplemented;
7609 break;
7610 case CP0_REGISTER_04:
7611 switch (sel) {
7612 case 0:
7613 gen_helper_mtc0_context(cpu_env, arg);
7614 register_name = "Context";
7615 break;
7616 case 1:
7617 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7618 register_name = "ContextConfig";
7619 goto cp0_unimplemented;
7620 case 2:
7621 CP0_CHECK(ctx->ulri);
7622 tcg_gen_st_tl(arg, cpu_env,
7623 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7624 register_name = "UserLocal";
7625 break;
7626 default:
7627 goto cp0_unimplemented;
7629 break;
7630 case CP0_REGISTER_05:
7631 switch (sel) {
7632 case 0:
7633 gen_helper_mtc0_pagemask(cpu_env, arg);
7634 register_name = "PageMask";
7635 break;
7636 case 1:
7637 check_insn(ctx, ISA_MIPS32R2);
7638 gen_helper_mtc0_pagegrain(cpu_env, arg);
7639 register_name = "PageGrain";
7640 ctx->base.is_jmp = DISAS_STOP;
7641 break;
7642 case 2:
7643 CP0_CHECK(ctx->sc);
7644 gen_helper_mtc0_segctl0(cpu_env, arg);
7645 register_name = "SegCtl0";
7646 break;
7647 case 3:
7648 CP0_CHECK(ctx->sc);
7649 gen_helper_mtc0_segctl1(cpu_env, arg);
7650 register_name = "SegCtl1";
7651 break;
7652 case 4:
7653 CP0_CHECK(ctx->sc);
7654 gen_helper_mtc0_segctl2(cpu_env, arg);
7655 register_name = "SegCtl2";
7656 break;
7657 case 5:
7658 check_pw(ctx);
7659 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7660 register_name = "PWBase";
7661 break;
7662 case 6:
7663 check_pw(ctx);
7664 gen_helper_mtc0_pwfield(cpu_env, arg);
7665 register_name = "PWField";
7666 break;
7667 case 7:
7668 check_pw(ctx);
7669 gen_helper_mtc0_pwsize(cpu_env, arg);
7670 register_name = "PWSize";
7671 break;
7672 default:
7673 goto cp0_unimplemented;
7675 break;
7676 case CP0_REGISTER_06:
7677 switch (sel) {
7678 case 0:
7679 gen_helper_mtc0_wired(cpu_env, arg);
7680 register_name = "Wired";
7681 break;
7682 case 1:
7683 check_insn(ctx, ISA_MIPS32R2);
7684 gen_helper_mtc0_srsconf0(cpu_env, arg);
7685 register_name = "SRSConf0";
7686 break;
7687 case 2:
7688 check_insn(ctx, ISA_MIPS32R2);
7689 gen_helper_mtc0_srsconf1(cpu_env, arg);
7690 register_name = "SRSConf1";
7691 break;
7692 case 3:
7693 check_insn(ctx, ISA_MIPS32R2);
7694 gen_helper_mtc0_srsconf2(cpu_env, arg);
7695 register_name = "SRSConf2";
7696 break;
7697 case 4:
7698 check_insn(ctx, ISA_MIPS32R2);
7699 gen_helper_mtc0_srsconf3(cpu_env, arg);
7700 register_name = "SRSConf3";
7701 break;
7702 case 5:
7703 check_insn(ctx, ISA_MIPS32R2);
7704 gen_helper_mtc0_srsconf4(cpu_env, arg);
7705 register_name = "SRSConf4";
7706 break;
7707 case 6:
7708 check_pw(ctx);
7709 gen_helper_mtc0_pwctl(cpu_env, arg);
7710 register_name = "PWCtl";
7711 break;
7712 default:
7713 goto cp0_unimplemented;
7715 break;
7716 case CP0_REGISTER_07:
7717 switch (sel) {
7718 case 0:
7719 check_insn(ctx, ISA_MIPS32R2);
7720 gen_helper_mtc0_hwrena(cpu_env, arg);
7721 ctx->base.is_jmp = DISAS_STOP;
7722 register_name = "HWREna";
7723 break;
7724 default:
7725 goto cp0_unimplemented;
7727 break;
7728 case CP0_REGISTER_08:
7729 switch (sel) {
7730 case 0:
7731 /* ignored */
7732 register_name = "BadVAddr";
7733 break;
7734 case 1:
7735 /* ignored */
7736 register_name = "BadInstr";
7737 break;
7738 case 2:
7739 /* ignored */
7740 register_name = "BadInstrP";
7741 break;
7742 case 3:
7743 /* ignored */
7744 register_name = "BadInstrX";
7745 break;
7746 default:
7747 goto cp0_unimplemented;
7749 break;
7750 case CP0_REGISTER_09:
7751 switch (sel) {
7752 case 0:
7753 gen_helper_mtc0_count(cpu_env, arg);
7754 register_name = "Count";
7755 break;
7756 case 6:
7757 CP0_CHECK(ctx->saar);
7758 gen_helper_mtc0_saari(cpu_env, arg);
7759 register_name = "SAARI";
7760 break;
7761 case 7:
7762 CP0_CHECK(ctx->saar);
7763 gen_helper_mtc0_saar(cpu_env, arg);
7764 register_name = "SAAR";
7765 break;
7766 default:
7767 goto cp0_unimplemented;
7769 break;
7770 case CP0_REGISTER_10:
7771 switch (sel) {
7772 case 0:
7773 gen_helper_mtc0_entryhi(cpu_env, arg);
7774 register_name = "EntryHi";
7775 break;
7776 default:
7777 goto cp0_unimplemented;
7779 break;
7780 case CP0_REGISTER_11:
7781 switch (sel) {
7782 case 0:
7783 gen_helper_mtc0_compare(cpu_env, arg);
7784 register_name = "Compare";
7785 break;
7786 /* 6,7 are implementation dependent */
7787 default:
7788 goto cp0_unimplemented;
7790 break;
7791 case CP0_REGISTER_12:
7792 switch (sel) {
7793 case 0:
7794 save_cpu_state(ctx, 1);
7795 gen_helper_mtc0_status(cpu_env, arg);
7796 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7797 gen_save_pc(ctx->base.pc_next + 4);
7798 ctx->base.is_jmp = DISAS_EXIT;
7799 register_name = "Status";
7800 break;
7801 case 1:
7802 check_insn(ctx, ISA_MIPS32R2);
7803 gen_helper_mtc0_intctl(cpu_env, arg);
7804 /* Stop translation as we may have switched the execution mode */
7805 ctx->base.is_jmp = DISAS_STOP;
7806 register_name = "IntCtl";
7807 break;
7808 case 2:
7809 check_insn(ctx, ISA_MIPS32R2);
7810 gen_helper_mtc0_srsctl(cpu_env, arg);
7811 /* Stop translation as we may have switched the execution mode */
7812 ctx->base.is_jmp = DISAS_STOP;
7813 register_name = "SRSCtl";
7814 break;
7815 case 3:
7816 check_insn(ctx, ISA_MIPS32R2);
7817 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7818 /* Stop translation as we may have switched the execution mode */
7819 ctx->base.is_jmp = DISAS_STOP;
7820 register_name = "SRSMap";
7821 break;
7822 default:
7823 goto cp0_unimplemented;
7825 break;
7826 case CP0_REGISTER_13:
7827 switch (sel) {
7828 case 0:
7829 save_cpu_state(ctx, 1);
7830 gen_helper_mtc0_cause(cpu_env, arg);
7831 /* Stop translation as we may have triggered an interrupt.
7832 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7833 * translated code to check for pending interrupts. */
7834 gen_save_pc(ctx->base.pc_next + 4);
7835 ctx->base.is_jmp = DISAS_EXIT;
7836 register_name = "Cause";
7837 break;
7838 default:
7839 goto cp0_unimplemented;
7841 break;
7842 case CP0_REGISTER_14:
7843 switch (sel) {
7844 case 0:
7845 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7846 register_name = "EPC";
7847 break;
7848 default:
7849 goto cp0_unimplemented;
7851 break;
7852 case CP0_REGISTER_15:
7853 switch (sel) {
7854 case 0:
7855 /* ignored */
7856 register_name = "PRid";
7857 break;
7858 case 1:
7859 check_insn(ctx, ISA_MIPS32R2);
7860 gen_helper_mtc0_ebase(cpu_env, arg);
7861 register_name = "EBase";
7862 break;
7863 default:
7864 goto cp0_unimplemented;
7866 break;
7867 case CP0_REGISTER_16:
7868 switch (sel) {
7869 case 0:
7870 gen_helper_mtc0_config0(cpu_env, arg);
7871 register_name = "Config";
7872 /* Stop translation as we may have switched the execution mode */
7873 ctx->base.is_jmp = DISAS_STOP;
7874 break;
7875 case 1:
7876 /* ignored, read only */
7877 register_name = "Config1";
7878 break;
7879 case 2:
7880 gen_helper_mtc0_config2(cpu_env, arg);
7881 register_name = "Config2";
7882 /* Stop translation as we may have switched the execution mode */
7883 ctx->base.is_jmp = DISAS_STOP;
7884 break;
7885 case 3:
7886 gen_helper_mtc0_config3(cpu_env, arg);
7887 register_name = "Config3";
7888 /* Stop translation as we may have switched the execution mode */
7889 ctx->base.is_jmp = DISAS_STOP;
7890 break;
7891 case 4:
7892 gen_helper_mtc0_config4(cpu_env, arg);
7893 register_name = "Config4";
7894 ctx->base.is_jmp = DISAS_STOP;
7895 break;
7896 case 5:
7897 gen_helper_mtc0_config5(cpu_env, arg);
7898 register_name = "Config5";
7899 /* Stop translation as we may have switched the execution mode */
7900 ctx->base.is_jmp = DISAS_STOP;
7901 break;
7902 /* 6,7 are implementation dependent */
7903 case 6:
7904 /* ignored */
7905 register_name = "Config6";
7906 break;
7907 case 7:
7908 /* ignored */
7909 register_name = "Config7";
7910 break;
7911 default:
7912 register_name = "Invalid config selector";
7913 goto cp0_unimplemented;
7915 break;
7916 case CP0_REGISTER_17:
7917 switch (sel) {
7918 case 0:
7919 gen_helper_mtc0_lladdr(cpu_env, arg);
7920 register_name = "LLAddr";
7921 break;
7922 case 1:
7923 CP0_CHECK(ctx->mrp);
7924 gen_helper_mtc0_maar(cpu_env, arg);
7925 register_name = "MAAR";
7926 break;
7927 case 2:
7928 CP0_CHECK(ctx->mrp);
7929 gen_helper_mtc0_maari(cpu_env, arg);
7930 register_name = "MAARI";
7931 break;
7932 default:
7933 goto cp0_unimplemented;
7935 break;
7936 case CP0_REGISTER_18:
7937 switch (sel) {
7938 case 0:
7939 case 1:
7940 case 2:
7941 case 3:
7942 case 4:
7943 case 5:
7944 case 6:
7945 case 7:
7946 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7947 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7948 register_name = "WatchLo";
7949 break;
7950 default:
7951 goto cp0_unimplemented;
7953 break;
7954 case CP0_REGISTER_19:
7955 switch (sel) {
7956 case 0:
7957 case 1:
7958 case 2:
7959 case 3:
7960 case 4:
7961 case 5:
7962 case 6:
7963 case 7:
7964 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7965 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7966 register_name = "WatchHi";
7967 break;
7968 default:
7969 goto cp0_unimplemented;
7971 break;
7972 case CP0_REGISTER_20:
7973 switch (sel) {
7974 case 0:
7975 #if defined(TARGET_MIPS64)
7976 check_insn(ctx, ISA_MIPS3);
7977 gen_helper_mtc0_xcontext(cpu_env, arg);
7978 register_name = "XContext";
7979 break;
7980 #endif
7981 default:
7982 goto cp0_unimplemented;
7984 break;
7985 case CP0_REGISTER_21:
7986 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7987 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7988 switch (sel) {
7989 case 0:
7990 gen_helper_mtc0_framemask(cpu_env, arg);
7991 register_name = "Framemask";
7992 break;
7993 default:
7994 goto cp0_unimplemented;
7996 break;
7997 case CP0_REGISTER_22:
7998 /* ignored */
7999 register_name = "Diagnostic"; /* implementation dependent */
8000 break;
8001 case CP0_REGISTER_23:
8002 switch (sel) {
8003 case 0:
8004 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8005 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8006 gen_save_pc(ctx->base.pc_next + 4);
8007 ctx->base.is_jmp = DISAS_EXIT;
8008 register_name = "Debug";
8009 break;
8010 case 1:
8011 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8012 register_name = "TraceControl";
8013 /* Stop translation as we may have switched the execution mode */
8014 ctx->base.is_jmp = DISAS_STOP;
8015 goto cp0_unimplemented;
8016 case 2:
8017 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8018 register_name = "TraceControl2";
8019 /* Stop translation as we may have switched the execution mode */
8020 ctx->base.is_jmp = DISAS_STOP;
8021 goto cp0_unimplemented;
8022 case 3:
8023 /* Stop translation as we may have switched the execution mode */
8024 ctx->base.is_jmp = DISAS_STOP;
8025 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8026 register_name = "UserTraceData";
8027 /* Stop translation as we may have switched the execution mode */
8028 ctx->base.is_jmp = DISAS_STOP;
8029 goto cp0_unimplemented;
8030 case 4:
8031 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8032 /* Stop translation as we may have switched the execution mode */
8033 ctx->base.is_jmp = DISAS_STOP;
8034 register_name = "TraceBPC";
8035 goto cp0_unimplemented;
8036 default:
8037 goto cp0_unimplemented;
8039 break;
8040 case CP0_REGISTER_24:
8041 switch (sel) {
8042 case 0:
8043 /* EJTAG support */
8044 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8045 register_name = "DEPC";
8046 break;
8047 default:
8048 goto cp0_unimplemented;
8050 break;
8051 case CP0_REGISTER_25:
8052 switch (sel) {
8053 case 0:
8054 gen_helper_mtc0_performance0(cpu_env, arg);
8055 register_name = "Performance0";
8056 break;
8057 case 1:
8058 // gen_helper_mtc0_performance1(arg);
8059 register_name = "Performance1";
8060 goto cp0_unimplemented;
8061 case 2:
8062 // gen_helper_mtc0_performance2(arg);
8063 register_name = "Performance2";
8064 goto cp0_unimplemented;
8065 case 3:
8066 // gen_helper_mtc0_performance3(arg);
8067 register_name = "Performance3";
8068 goto cp0_unimplemented;
8069 case 4:
8070 // gen_helper_mtc0_performance4(arg);
8071 register_name = "Performance4";
8072 goto cp0_unimplemented;
8073 case 5:
8074 // gen_helper_mtc0_performance5(arg);
8075 register_name = "Performance5";
8076 goto cp0_unimplemented;
8077 case 6:
8078 // gen_helper_mtc0_performance6(arg);
8079 register_name = "Performance6";
8080 goto cp0_unimplemented;
8081 case 7:
8082 // gen_helper_mtc0_performance7(arg);
8083 register_name = "Performance7";
8084 goto cp0_unimplemented;
8085 default:
8086 goto cp0_unimplemented;
8088 break;
8089 case CP0_REGISTER_26:
8090 switch (sel) {
8091 case 0:
8092 gen_helper_mtc0_errctl(cpu_env, arg);
8093 ctx->base.is_jmp = DISAS_STOP;
8094 register_name = "ErrCtl";
8095 break;
8096 default:
8097 goto cp0_unimplemented;
8099 break;
8100 case CP0_REGISTER_27:
8101 switch (sel) {
8102 case 0:
8103 case 1:
8104 case 2:
8105 case 3:
8106 /* ignored */
8107 register_name = "CacheErr";
8108 break;
8109 default:
8110 goto cp0_unimplemented;
8112 break;
8113 case CP0_REGISTER_28:
8114 switch (sel) {
8115 case 0:
8116 case 2:
8117 case 4:
8118 case 6:
8119 gen_helper_mtc0_taglo(cpu_env, arg);
8120 register_name = "TagLo";
8121 break;
8122 case 1:
8123 case 3:
8124 case 5:
8125 case 7:
8126 gen_helper_mtc0_datalo(cpu_env, arg);
8127 register_name = "DataLo";
8128 break;
8129 default:
8130 goto cp0_unimplemented;
8132 break;
8133 case CP0_REGISTER_29:
8134 switch (sel) {
8135 case 0:
8136 case 2:
8137 case 4:
8138 case 6:
8139 gen_helper_mtc0_taghi(cpu_env, arg);
8140 register_name = "TagHi";
8141 break;
8142 case 1:
8143 case 3:
8144 case 5:
8145 case 7:
8146 gen_helper_mtc0_datahi(cpu_env, arg);
8147 register_name = "DataHi";
8148 break;
8149 default:
8150 register_name = "invalid sel";
8151 goto cp0_unimplemented;
8153 break;
8154 case CP0_REGISTER_30:
8155 switch (sel) {
8156 case 0:
8157 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8158 register_name = "ErrorEPC";
8159 break;
8160 default:
8161 goto cp0_unimplemented;
8163 break;
8164 case CP0_REGISTER_31:
8165 switch (sel) {
8166 case 0:
8167 /* EJTAG support */
8168 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8169 register_name = "DESAVE";
8170 break;
8171 case 2:
8172 case 3:
8173 case 4:
8174 case 5:
8175 case 6:
8176 case 7:
8177 CP0_CHECK(ctx->kscrexist & (1 << sel));
8178 tcg_gen_st_tl(arg, cpu_env,
8179 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8180 register_name = "KScratch";
8181 break;
8182 default:
8183 goto cp0_unimplemented;
8185 break;
8186 default:
8187 goto cp0_unimplemented;
8189 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8191 /* For simplicity assume that all writes can cause interrupts. */
8192 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8193 gen_io_end();
8194 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8195 * translated code to check for pending interrupts. */
8196 gen_save_pc(ctx->base.pc_next + 4);
8197 ctx->base.is_jmp = DISAS_EXIT;
8199 return;
8201 cp0_unimplemented:
8202 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8203 register_name, reg, sel);
8206 #if defined(TARGET_MIPS64)
8207 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8209 const char *register_name = "invalid";
8211 if (sel != 0)
8212 check_insn(ctx, ISA_MIPS64);
8214 switch (reg) {
8215 case CP0_REGISTER_00:
8216 switch (sel) {
8217 case 0:
8218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8219 register_name = "Index";
8220 break;
8221 case 1:
8222 CP0_CHECK(ctx->insn_flags & ASE_MT);
8223 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8224 register_name = "MVPControl";
8225 break;
8226 case 2:
8227 CP0_CHECK(ctx->insn_flags & ASE_MT);
8228 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8229 register_name = "MVPConf0";
8230 break;
8231 case 3:
8232 CP0_CHECK(ctx->insn_flags & ASE_MT);
8233 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8234 register_name = "MVPConf1";
8235 break;
8236 case 4:
8237 CP0_CHECK(ctx->vp);
8238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8239 register_name = "VPControl";
8240 break;
8241 default:
8242 goto cp0_unimplemented;
8244 break;
8245 case CP0_REGISTER_01:
8246 switch (sel) {
8247 case 0:
8248 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8249 gen_helper_mfc0_random(arg, cpu_env);
8250 register_name = "Random";
8251 break;
8252 case 1:
8253 CP0_CHECK(ctx->insn_flags & ASE_MT);
8254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8255 register_name = "VPEControl";
8256 break;
8257 case 2:
8258 CP0_CHECK(ctx->insn_flags & ASE_MT);
8259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8260 register_name = "VPEConf0";
8261 break;
8262 case 3:
8263 CP0_CHECK(ctx->insn_flags & ASE_MT);
8264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8265 register_name = "VPEConf1";
8266 break;
8267 case 4:
8268 CP0_CHECK(ctx->insn_flags & ASE_MT);
8269 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8270 register_name = "YQMask";
8271 break;
8272 case 5:
8273 CP0_CHECK(ctx->insn_flags & ASE_MT);
8274 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8275 register_name = "VPESchedule";
8276 break;
8277 case 6:
8278 CP0_CHECK(ctx->insn_flags & ASE_MT);
8279 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8280 register_name = "VPEScheFBack";
8281 break;
8282 case 7:
8283 CP0_CHECK(ctx->insn_flags & ASE_MT);
8284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8285 register_name = "VPEOpt";
8286 break;
8287 default:
8288 goto cp0_unimplemented;
8290 break;
8291 case CP0_REGISTER_02:
8292 switch (sel) {
8293 case 0:
8294 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8295 register_name = "EntryLo0";
8296 break;
8297 case 1:
8298 CP0_CHECK(ctx->insn_flags & ASE_MT);
8299 gen_helper_mfc0_tcstatus(arg, cpu_env);
8300 register_name = "TCStatus";
8301 break;
8302 case 2:
8303 CP0_CHECK(ctx->insn_flags & ASE_MT);
8304 gen_helper_mfc0_tcbind(arg, cpu_env);
8305 register_name = "TCBind";
8306 break;
8307 case 3:
8308 CP0_CHECK(ctx->insn_flags & ASE_MT);
8309 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8310 register_name = "TCRestart";
8311 break;
8312 case 4:
8313 CP0_CHECK(ctx->insn_flags & ASE_MT);
8314 gen_helper_dmfc0_tchalt(arg, cpu_env);
8315 register_name = "TCHalt";
8316 break;
8317 case 5:
8318 CP0_CHECK(ctx->insn_flags & ASE_MT);
8319 gen_helper_dmfc0_tccontext(arg, cpu_env);
8320 register_name = "TCContext";
8321 break;
8322 case 6:
8323 CP0_CHECK(ctx->insn_flags & ASE_MT);
8324 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8325 register_name = "TCSchedule";
8326 break;
8327 case 7:
8328 CP0_CHECK(ctx->insn_flags & ASE_MT);
8329 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8330 register_name = "TCScheFBack";
8331 break;
8332 default:
8333 goto cp0_unimplemented;
8335 break;
8336 case CP0_REGISTER_03:
8337 switch (sel) {
8338 case 0:
8339 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8340 register_name = "EntryLo1";
8341 break;
8342 case 1:
8343 CP0_CHECK(ctx->vp);
8344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8345 register_name = "GlobalNumber";
8346 break;
8347 default:
8348 goto cp0_unimplemented;
8350 break;
8351 case CP0_REGISTER_04:
8352 switch (sel) {
8353 case 0:
8354 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8355 register_name = "Context";
8356 break;
8357 case 1:
8358 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8359 register_name = "ContextConfig";
8360 goto cp0_unimplemented;
8361 case 2:
8362 CP0_CHECK(ctx->ulri);
8363 tcg_gen_ld_tl(arg, cpu_env,
8364 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8365 register_name = "UserLocal";
8366 break;
8367 default:
8368 goto cp0_unimplemented;
8370 break;
8371 case CP0_REGISTER_05:
8372 switch (sel) {
8373 case 0:
8374 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8375 register_name = "PageMask";
8376 break;
8377 case 1:
8378 check_insn(ctx, ISA_MIPS32R2);
8379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8380 register_name = "PageGrain";
8381 break;
8382 case 2:
8383 CP0_CHECK(ctx->sc);
8384 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8385 register_name = "SegCtl0";
8386 break;
8387 case 3:
8388 CP0_CHECK(ctx->sc);
8389 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8390 register_name = "SegCtl1";
8391 break;
8392 case 4:
8393 CP0_CHECK(ctx->sc);
8394 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8395 register_name = "SegCtl2";
8396 break;
8397 case 5:
8398 check_pw(ctx);
8399 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8400 register_name = "PWBase";
8401 break;
8402 case 6:
8403 check_pw(ctx);
8404 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8405 register_name = "PWField";
8406 break;
8407 case 7:
8408 check_pw(ctx);
8409 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8410 register_name = "PWSize";
8411 break;
8412 default:
8413 goto cp0_unimplemented;
8415 break;
8416 case CP0_REGISTER_06:
8417 switch (sel) {
8418 case 0:
8419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8420 register_name = "Wired";
8421 break;
8422 case 1:
8423 check_insn(ctx, ISA_MIPS32R2);
8424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8425 register_name = "SRSConf0";
8426 break;
8427 case 2:
8428 check_insn(ctx, ISA_MIPS32R2);
8429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8430 register_name = "SRSConf1";
8431 break;
8432 case 3:
8433 check_insn(ctx, ISA_MIPS32R2);
8434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8435 register_name = "SRSConf2";
8436 break;
8437 case 4:
8438 check_insn(ctx, ISA_MIPS32R2);
8439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8440 register_name = "SRSConf3";
8441 break;
8442 case 5:
8443 check_insn(ctx, ISA_MIPS32R2);
8444 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8445 register_name = "SRSConf4";
8446 break;
8447 case 6:
8448 check_pw(ctx);
8449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8450 register_name = "PWCtl";
8451 break;
8452 default:
8453 goto cp0_unimplemented;
8455 break;
8456 case CP0_REGISTER_07:
8457 switch (sel) {
8458 case 0:
8459 check_insn(ctx, ISA_MIPS32R2);
8460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8461 register_name = "HWREna";
8462 break;
8463 default:
8464 goto cp0_unimplemented;
8466 break;
8467 case CP0_REGISTER_08:
8468 switch (sel) {
8469 case 0:
8470 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8471 register_name = "BadVAddr";
8472 break;
8473 case 1:
8474 CP0_CHECK(ctx->bi);
8475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8476 register_name = "BadInstr";
8477 break;
8478 case 2:
8479 CP0_CHECK(ctx->bp);
8480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8481 register_name = "BadInstrP";
8482 break;
8483 case 3:
8484 CP0_CHECK(ctx->bi);
8485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8486 tcg_gen_andi_tl(arg, arg, ~0xffff);
8487 register_name = "BadInstrX";
8488 break;
8489 default:
8490 goto cp0_unimplemented;
8492 break;
8493 case CP0_REGISTER_09:
8494 switch (sel) {
8495 case 0:
8496 /* Mark as an IO operation because we read the time. */
8497 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8498 gen_io_start();
8500 gen_helper_mfc0_count(arg, cpu_env);
8501 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8502 gen_io_end();
8504 /* Break the TB to be able to take timer interrupts immediately
8505 after reading count. DISAS_STOP isn't sufficient, we need to
8506 ensure we break completely out of translated code. */
8507 gen_save_pc(ctx->base.pc_next + 4);
8508 ctx->base.is_jmp = DISAS_EXIT;
8509 register_name = "Count";
8510 break;
8511 case 6:
8512 CP0_CHECK(ctx->saar);
8513 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8514 register_name = "SAARI";
8515 break;
8516 case 7:
8517 CP0_CHECK(ctx->saar);
8518 gen_helper_dmfc0_saar(arg, cpu_env);
8519 register_name = "SAAR";
8520 break;
8521 default:
8522 goto cp0_unimplemented;
8524 break;
8525 case CP0_REGISTER_10:
8526 switch (sel) {
8527 case 0:
8528 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8529 register_name = "EntryHi";
8530 break;
8531 default:
8532 goto cp0_unimplemented;
8534 break;
8535 case CP0_REGISTER_11:
8536 switch (sel) {
8537 case 0:
8538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8539 register_name = "Compare";
8540 break;
8541 /* 6,7 are implementation dependent */
8542 default:
8543 goto cp0_unimplemented;
8545 break;
8546 case CP0_REGISTER_12:
8547 switch (sel) {
8548 case 0:
8549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8550 register_name = "Status";
8551 break;
8552 case 1:
8553 check_insn(ctx, ISA_MIPS32R2);
8554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8555 register_name = "IntCtl";
8556 break;
8557 case 2:
8558 check_insn(ctx, ISA_MIPS32R2);
8559 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8560 register_name = "SRSCtl";
8561 break;
8562 case 3:
8563 check_insn(ctx, ISA_MIPS32R2);
8564 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8565 register_name = "SRSMap";
8566 break;
8567 default:
8568 goto cp0_unimplemented;
8570 break;
8571 case CP0_REGISTER_13:
8572 switch (sel) {
8573 case 0:
8574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8575 register_name = "Cause";
8576 break;
8577 default:
8578 goto cp0_unimplemented;
8580 break;
8581 case CP0_REGISTER_14:
8582 switch (sel) {
8583 case 0:
8584 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8585 register_name = "EPC";
8586 break;
8587 default:
8588 goto cp0_unimplemented;
8590 break;
8591 case CP0_REGISTER_15:
8592 switch (sel) {
8593 case 0:
8594 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8595 register_name = "PRid";
8596 break;
8597 case 1:
8598 check_insn(ctx, ISA_MIPS32R2);
8599 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8600 register_name = "EBase";
8601 break;
8602 case 3:
8603 check_insn(ctx, ISA_MIPS32R2);
8604 CP0_CHECK(ctx->cmgcr);
8605 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8606 register_name = "CMGCRBase";
8607 break;
8608 default:
8609 goto cp0_unimplemented;
8611 break;
8612 case CP0_REGISTER_16:
8613 switch (sel) {
8614 case 0:
8615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8616 register_name = "Config";
8617 break;
8618 case 1:
8619 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8620 register_name = "Config1";
8621 break;
8622 case 2:
8623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8624 register_name = "Config2";
8625 break;
8626 case 3:
8627 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8628 register_name = "Config3";
8629 break;
8630 case 4:
8631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8632 register_name = "Config4";
8633 break;
8634 case 5:
8635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8636 register_name = "Config5";
8637 break;
8638 /* 6,7 are implementation dependent */
8639 case 6:
8640 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8641 register_name = "Config6";
8642 break;
8643 case 7:
8644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8645 register_name = "Config7";
8646 break;
8647 default:
8648 goto cp0_unimplemented;
8650 break;
8651 case CP0_REGISTER_17:
8652 switch (sel) {
8653 case 0:
8654 gen_helper_dmfc0_lladdr(arg, cpu_env);
8655 register_name = "LLAddr";
8656 break;
8657 case 1:
8658 CP0_CHECK(ctx->mrp);
8659 gen_helper_dmfc0_maar(arg, cpu_env);
8660 register_name = "MAAR";
8661 break;
8662 case 2:
8663 CP0_CHECK(ctx->mrp);
8664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8665 register_name = "MAARI";
8666 break;
8667 default:
8668 goto cp0_unimplemented;
8670 break;
8671 case CP0_REGISTER_18:
8672 switch (sel) {
8673 case 0:
8674 case 1:
8675 case 2:
8676 case 3:
8677 case 4:
8678 case 5:
8679 case 6:
8680 case 7:
8681 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8682 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8683 register_name = "WatchLo";
8684 break;
8685 default:
8686 goto cp0_unimplemented;
8688 break;
8689 case CP0_REGISTER_19:
8690 switch (sel) {
8691 case 0:
8692 case 1:
8693 case 2:
8694 case 3:
8695 case 4:
8696 case 5:
8697 case 6:
8698 case 7:
8699 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8700 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8701 register_name = "WatchHi";
8702 break;
8703 default:
8704 goto cp0_unimplemented;
8706 break;
8707 case CP0_REGISTER_20:
8708 switch (sel) {
8709 case 0:
8710 check_insn(ctx, ISA_MIPS3);
8711 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8712 register_name = "XContext";
8713 break;
8714 default:
8715 goto cp0_unimplemented;
8717 break;
8718 case CP0_REGISTER_21:
8719 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8720 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8721 switch (sel) {
8722 case 0:
8723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8724 register_name = "Framemask";
8725 break;
8726 default:
8727 goto cp0_unimplemented;
8729 break;
8730 case CP0_REGISTER_22:
8731 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8732 register_name = "'Diagnostic"; /* implementation dependent */
8733 break;
8734 case CP0_REGISTER_23:
8735 switch (sel) {
8736 case 0:
8737 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8738 register_name = "Debug";
8739 break;
8740 case 1:
8741 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8742 register_name = "TraceControl";
8743 goto cp0_unimplemented;
8744 case 2:
8745 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8746 register_name = "TraceControl2";
8747 goto cp0_unimplemented;
8748 case 3:
8749 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8750 register_name = "UserTraceData";
8751 goto cp0_unimplemented;
8752 case 4:
8753 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8754 register_name = "TraceBPC";
8755 goto cp0_unimplemented;
8756 default:
8757 goto cp0_unimplemented;
8759 break;
8760 case CP0_REGISTER_24:
8761 switch (sel) {
8762 case 0:
8763 /* EJTAG support */
8764 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8765 register_name = "DEPC";
8766 break;
8767 default:
8768 goto cp0_unimplemented;
8770 break;
8771 case CP0_REGISTER_25:
8772 switch (sel) {
8773 case 0:
8774 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8775 register_name = "Performance0";
8776 break;
8777 case 1:
8778 // gen_helper_dmfc0_performance1(arg);
8779 register_name = "Performance1";
8780 goto cp0_unimplemented;
8781 case 2:
8782 // gen_helper_dmfc0_performance2(arg);
8783 register_name = "Performance2";
8784 goto cp0_unimplemented;
8785 case 3:
8786 // gen_helper_dmfc0_performance3(arg);
8787 register_name = "Performance3";
8788 goto cp0_unimplemented;
8789 case 4:
8790 // gen_helper_dmfc0_performance4(arg);
8791 register_name = "Performance4";
8792 goto cp0_unimplemented;
8793 case 5:
8794 // gen_helper_dmfc0_performance5(arg);
8795 register_name = "Performance5";
8796 goto cp0_unimplemented;
8797 case 6:
8798 // gen_helper_dmfc0_performance6(arg);
8799 register_name = "Performance6";
8800 goto cp0_unimplemented;
8801 case 7:
8802 // gen_helper_dmfc0_performance7(arg);
8803 register_name = "Performance7";
8804 goto cp0_unimplemented;
8805 default:
8806 goto cp0_unimplemented;
8808 break;
8809 case CP0_REGISTER_26:
8810 switch (sel) {
8811 case 0:
8812 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8813 register_name = "ErrCtl";
8814 break;
8815 default:
8816 goto cp0_unimplemented;
8818 break;
8819 case CP0_REGISTER_27:
8820 switch (sel) {
8821 /* ignored */
8822 case 0:
8823 case 1:
8824 case 2:
8825 case 3:
8826 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8827 register_name = "CacheErr";
8828 break;
8829 default:
8830 goto cp0_unimplemented;
8832 break;
8833 case CP0_REGISTER_28:
8834 switch (sel) {
8835 case 0:
8836 case 2:
8837 case 4:
8838 case 6:
8839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8840 register_name = "TagLo";
8841 break;
8842 case 1:
8843 case 3:
8844 case 5:
8845 case 7:
8846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8847 register_name = "DataLo";
8848 break;
8849 default:
8850 goto cp0_unimplemented;
8852 break;
8853 case CP0_REGISTER_29:
8854 switch (sel) {
8855 case 0:
8856 case 2:
8857 case 4:
8858 case 6:
8859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8860 register_name = "TagHi";
8861 break;
8862 case 1:
8863 case 3:
8864 case 5:
8865 case 7:
8866 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8867 register_name = "DataHi";
8868 break;
8869 default:
8870 goto cp0_unimplemented;
8872 break;
8873 case CP0_REGISTER_30:
8874 switch (sel) {
8875 case 0:
8876 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8877 register_name = "ErrorEPC";
8878 break;
8879 default:
8880 goto cp0_unimplemented;
8882 break;
8883 case CP0_REGISTER_31:
8884 switch (sel) {
8885 case 0:
8886 /* EJTAG support */
8887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8888 register_name = "DESAVE";
8889 break;
8890 case 2:
8891 case 3:
8892 case 4:
8893 case 5:
8894 case 6:
8895 case 7:
8896 CP0_CHECK(ctx->kscrexist & (1 << sel));
8897 tcg_gen_ld_tl(arg, cpu_env,
8898 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8899 register_name = "KScratch";
8900 break;
8901 default:
8902 goto cp0_unimplemented;
8904 break;
8905 default:
8906 goto cp0_unimplemented;
8908 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8909 return;
8911 cp0_unimplemented:
8912 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8913 register_name, reg, sel);
8914 gen_mfc0_unimplemented(ctx, arg);
8917 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8919 const char *register_name = "invalid";
8921 if (sel != 0)
8922 check_insn(ctx, ISA_MIPS64);
8924 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8925 gen_io_start();
8928 switch (reg) {
8929 case CP0_REGISTER_00:
8930 switch (sel) {
8931 case 0:
8932 gen_helper_mtc0_index(cpu_env, arg);
8933 register_name = "Index";
8934 break;
8935 case 1:
8936 CP0_CHECK(ctx->insn_flags & ASE_MT);
8937 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8938 register_name = "MVPControl";
8939 break;
8940 case 2:
8941 CP0_CHECK(ctx->insn_flags & ASE_MT);
8942 /* ignored */
8943 register_name = "MVPConf0";
8944 break;
8945 case 3:
8946 CP0_CHECK(ctx->insn_flags & ASE_MT);
8947 /* ignored */
8948 register_name = "MVPConf1";
8949 break;
8950 case 4:
8951 CP0_CHECK(ctx->vp);
8952 /* ignored */
8953 register_name = "VPControl";
8954 break;
8955 default:
8956 goto cp0_unimplemented;
8958 break;
8959 case CP0_REGISTER_01:
8960 switch (sel) {
8961 case 0:
8962 /* ignored */
8963 register_name = "Random";
8964 break;
8965 case 1:
8966 CP0_CHECK(ctx->insn_flags & ASE_MT);
8967 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8968 register_name = "VPEControl";
8969 break;
8970 case 2:
8971 CP0_CHECK(ctx->insn_flags & ASE_MT);
8972 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8973 register_name = "VPEConf0";
8974 break;
8975 case 3:
8976 CP0_CHECK(ctx->insn_flags & ASE_MT);
8977 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8978 register_name = "VPEConf1";
8979 break;
8980 case 4:
8981 CP0_CHECK(ctx->insn_flags & ASE_MT);
8982 gen_helper_mtc0_yqmask(cpu_env, arg);
8983 register_name = "YQMask";
8984 break;
8985 case 5:
8986 CP0_CHECK(ctx->insn_flags & ASE_MT);
8987 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8988 register_name = "VPESchedule";
8989 break;
8990 case 6:
8991 CP0_CHECK(ctx->insn_flags & ASE_MT);
8992 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8993 register_name = "VPEScheFBack";
8994 break;
8995 case 7:
8996 CP0_CHECK(ctx->insn_flags & ASE_MT);
8997 gen_helper_mtc0_vpeopt(cpu_env, arg);
8998 register_name = "VPEOpt";
8999 break;
9000 default:
9001 goto cp0_unimplemented;
9003 break;
9004 case CP0_REGISTER_02:
9005 switch (sel) {
9006 case 0:
9007 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9008 register_name = "EntryLo0";
9009 break;
9010 case 1:
9011 CP0_CHECK(ctx->insn_flags & ASE_MT);
9012 gen_helper_mtc0_tcstatus(cpu_env, arg);
9013 register_name = "TCStatus";
9014 break;
9015 case 2:
9016 CP0_CHECK(ctx->insn_flags & ASE_MT);
9017 gen_helper_mtc0_tcbind(cpu_env, arg);
9018 register_name = "TCBind";
9019 break;
9020 case 3:
9021 CP0_CHECK(ctx->insn_flags & ASE_MT);
9022 gen_helper_mtc0_tcrestart(cpu_env, arg);
9023 register_name = "TCRestart";
9024 break;
9025 case 4:
9026 CP0_CHECK(ctx->insn_flags & ASE_MT);
9027 gen_helper_mtc0_tchalt(cpu_env, arg);
9028 register_name = "TCHalt";
9029 break;
9030 case 5:
9031 CP0_CHECK(ctx->insn_flags & ASE_MT);
9032 gen_helper_mtc0_tccontext(cpu_env, arg);
9033 register_name = "TCContext";
9034 break;
9035 case 6:
9036 CP0_CHECK(ctx->insn_flags & ASE_MT);
9037 gen_helper_mtc0_tcschedule(cpu_env, arg);
9038 register_name = "TCSchedule";
9039 break;
9040 case 7:
9041 CP0_CHECK(ctx->insn_flags & ASE_MT);
9042 gen_helper_mtc0_tcschefback(cpu_env, arg);
9043 register_name = "TCScheFBack";
9044 break;
9045 default:
9046 goto cp0_unimplemented;
9048 break;
9049 case CP0_REGISTER_03:
9050 switch (sel) {
9051 case 0:
9052 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9053 register_name = "EntryLo1";
9054 break;
9055 case 1:
9056 CP0_CHECK(ctx->vp);
9057 /* ignored */
9058 register_name = "GlobalNumber";
9059 break;
9060 default:
9061 goto cp0_unimplemented;
9063 break;
9064 case CP0_REGISTER_04:
9065 switch (sel) {
9066 case 0:
9067 gen_helper_mtc0_context(cpu_env, arg);
9068 register_name = "Context";
9069 break;
9070 case 1:
9071 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
9072 register_name = "ContextConfig";
9073 goto cp0_unimplemented;
9074 case 2:
9075 CP0_CHECK(ctx->ulri);
9076 tcg_gen_st_tl(arg, cpu_env,
9077 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9078 register_name = "UserLocal";
9079 break;
9080 default:
9081 goto cp0_unimplemented;
9083 break;
9084 case CP0_REGISTER_05:
9085 switch (sel) {
9086 case 0:
9087 gen_helper_mtc0_pagemask(cpu_env, arg);
9088 register_name = "PageMask";
9089 break;
9090 case 1:
9091 check_insn(ctx, ISA_MIPS32R2);
9092 gen_helper_mtc0_pagegrain(cpu_env, arg);
9093 register_name = "PageGrain";
9094 break;
9095 case 2:
9096 CP0_CHECK(ctx->sc);
9097 gen_helper_mtc0_segctl0(cpu_env, arg);
9098 register_name = "SegCtl0";
9099 break;
9100 case 3:
9101 CP0_CHECK(ctx->sc);
9102 gen_helper_mtc0_segctl1(cpu_env, arg);
9103 register_name = "SegCtl1";
9104 break;
9105 case 4:
9106 CP0_CHECK(ctx->sc);
9107 gen_helper_mtc0_segctl2(cpu_env, arg);
9108 register_name = "SegCtl2";
9109 break;
9110 case 5:
9111 check_pw(ctx);
9112 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9113 register_name = "PWBase";
9114 break;
9115 case 6:
9116 check_pw(ctx);
9117 gen_helper_mtc0_pwfield(cpu_env, arg);
9118 register_name = "PWField";
9119 break;
9120 case 7:
9121 check_pw(ctx);
9122 gen_helper_mtc0_pwsize(cpu_env, arg);
9123 register_name = "PWSize";
9124 break;
9125 default:
9126 goto cp0_unimplemented;
9128 break;
9129 case CP0_REGISTER_06:
9130 switch (sel) {
9131 case 0:
9132 gen_helper_mtc0_wired(cpu_env, arg);
9133 register_name = "Wired";
9134 break;
9135 case 1:
9136 check_insn(ctx, ISA_MIPS32R2);
9137 gen_helper_mtc0_srsconf0(cpu_env, arg);
9138 register_name = "SRSConf0";
9139 break;
9140 case 2:
9141 check_insn(ctx, ISA_MIPS32R2);
9142 gen_helper_mtc0_srsconf1(cpu_env, arg);
9143 register_name = "SRSConf1";
9144 break;
9145 case 3:
9146 check_insn(ctx, ISA_MIPS32R2);
9147 gen_helper_mtc0_srsconf2(cpu_env, arg);
9148 register_name = "SRSConf2";
9149 break;
9150 case 4:
9151 check_insn(ctx, ISA_MIPS32R2);
9152 gen_helper_mtc0_srsconf3(cpu_env, arg);
9153 register_name = "SRSConf3";
9154 break;
9155 case 5:
9156 check_insn(ctx, ISA_MIPS32R2);
9157 gen_helper_mtc0_srsconf4(cpu_env, arg);
9158 register_name = "SRSConf4";
9159 break;
9160 case 6:
9161 check_pw(ctx);
9162 gen_helper_mtc0_pwctl(cpu_env, arg);
9163 register_name = "PWCtl";
9164 break;
9165 default:
9166 goto cp0_unimplemented;
9168 break;
9169 case CP0_REGISTER_07:
9170 switch (sel) {
9171 case 0:
9172 check_insn(ctx, ISA_MIPS32R2);
9173 gen_helper_mtc0_hwrena(cpu_env, arg);
9174 ctx->base.is_jmp = DISAS_STOP;
9175 register_name = "HWREna";
9176 break;
9177 default:
9178 goto cp0_unimplemented;
9180 break;
9181 case CP0_REGISTER_08:
9182 switch (sel) {
9183 case 0:
9184 /* ignored */
9185 register_name = "BadVAddr";
9186 break;
9187 case 1:
9188 /* ignored */
9189 register_name = "BadInstr";
9190 break;
9191 case 2:
9192 /* ignored */
9193 register_name = "BadInstrP";
9194 break;
9195 case 3:
9196 /* ignored */
9197 register_name = "BadInstrX";
9198 break;
9199 default:
9200 goto cp0_unimplemented;
9202 break;
9203 case CP0_REGISTER_09:
9204 switch (sel) {
9205 case 0:
9206 gen_helper_mtc0_count(cpu_env, arg);
9207 register_name = "Count";
9208 break;
9209 case 6:
9210 CP0_CHECK(ctx->saar);
9211 gen_helper_mtc0_saari(cpu_env, arg);
9212 register_name = "SAARI";
9213 break;
9214 case 7:
9215 CP0_CHECK(ctx->saar);
9216 gen_helper_mtc0_saar(cpu_env, arg);
9217 register_name = "SAAR";
9218 break;
9219 default:
9220 goto cp0_unimplemented;
9222 /* Stop translation as we may have switched the execution mode */
9223 ctx->base.is_jmp = DISAS_STOP;
9224 break;
9225 case CP0_REGISTER_10:
9226 switch (sel) {
9227 case 0:
9228 gen_helper_mtc0_entryhi(cpu_env, arg);
9229 register_name = "EntryHi";
9230 break;
9231 default:
9232 goto cp0_unimplemented;
9234 break;
9235 case CP0_REGISTER_11:
9236 switch (sel) {
9237 case 0:
9238 gen_helper_mtc0_compare(cpu_env, arg);
9239 register_name = "Compare";
9240 break;
9241 /* 6,7 are implementation dependent */
9242 default:
9243 goto cp0_unimplemented;
9245 /* Stop translation as we may have switched the execution mode */
9246 ctx->base.is_jmp = DISAS_STOP;
9247 break;
9248 case CP0_REGISTER_12:
9249 switch (sel) {
9250 case 0:
9251 save_cpu_state(ctx, 1);
9252 gen_helper_mtc0_status(cpu_env, arg);
9253 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9254 gen_save_pc(ctx->base.pc_next + 4);
9255 ctx->base.is_jmp = DISAS_EXIT;
9256 register_name = "Status";
9257 break;
9258 case 1:
9259 check_insn(ctx, ISA_MIPS32R2);
9260 gen_helper_mtc0_intctl(cpu_env, arg);
9261 /* Stop translation as we may have switched the execution mode */
9262 ctx->base.is_jmp = DISAS_STOP;
9263 register_name = "IntCtl";
9264 break;
9265 case 2:
9266 check_insn(ctx, ISA_MIPS32R2);
9267 gen_helper_mtc0_srsctl(cpu_env, arg);
9268 /* Stop translation as we may have switched the execution mode */
9269 ctx->base.is_jmp = DISAS_STOP;
9270 register_name = "SRSCtl";
9271 break;
9272 case 3:
9273 check_insn(ctx, ISA_MIPS32R2);
9274 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9275 /* Stop translation as we may have switched the execution mode */
9276 ctx->base.is_jmp = DISAS_STOP;
9277 register_name = "SRSMap";
9278 break;
9279 default:
9280 goto cp0_unimplemented;
9282 break;
9283 case CP0_REGISTER_13:
9284 switch (sel) {
9285 case 0:
9286 save_cpu_state(ctx, 1);
9287 gen_helper_mtc0_cause(cpu_env, arg);
9288 /* Stop translation as we may have triggered an interrupt.
9289 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9290 * translated code to check for pending interrupts. */
9291 gen_save_pc(ctx->base.pc_next + 4);
9292 ctx->base.is_jmp = DISAS_EXIT;
9293 register_name = "Cause";
9294 break;
9295 default:
9296 goto cp0_unimplemented;
9298 break;
9299 case CP0_REGISTER_14:
9300 switch (sel) {
9301 case 0:
9302 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9303 register_name = "EPC";
9304 break;
9305 default:
9306 goto cp0_unimplemented;
9308 break;
9309 case CP0_REGISTER_15:
9310 switch (sel) {
9311 case 0:
9312 /* ignored */
9313 register_name = "PRid";
9314 break;
9315 case 1:
9316 check_insn(ctx, ISA_MIPS32R2);
9317 gen_helper_mtc0_ebase(cpu_env, arg);
9318 register_name = "EBase";
9319 break;
9320 default:
9321 goto cp0_unimplemented;
9323 break;
9324 case CP0_REGISTER_16:
9325 switch (sel) {
9326 case 0:
9327 gen_helper_mtc0_config0(cpu_env, arg);
9328 register_name = "Config";
9329 /* Stop translation as we may have switched the execution mode */
9330 ctx->base.is_jmp = DISAS_STOP;
9331 break;
9332 case 1:
9333 /* ignored, read only */
9334 register_name = "Config1";
9335 break;
9336 case 2:
9337 gen_helper_mtc0_config2(cpu_env, arg);
9338 register_name = "Config2";
9339 /* Stop translation as we may have switched the execution mode */
9340 ctx->base.is_jmp = DISAS_STOP;
9341 break;
9342 case 3:
9343 gen_helper_mtc0_config3(cpu_env, arg);
9344 register_name = "Config3";
9345 /* Stop translation as we may have switched the execution mode */
9346 ctx->base.is_jmp = DISAS_STOP;
9347 break;
9348 case 4:
9349 /* currently ignored */
9350 register_name = "Config4";
9351 break;
9352 case 5:
9353 gen_helper_mtc0_config5(cpu_env, arg);
9354 register_name = "Config5";
9355 /* Stop translation as we may have switched the execution mode */
9356 ctx->base.is_jmp = DISAS_STOP;
9357 break;
9358 /* 6,7 are implementation dependent */
9359 default:
9360 register_name = "Invalid config selector";
9361 goto cp0_unimplemented;
9363 break;
9364 case CP0_REGISTER_17:
9365 switch (sel) {
9366 case 0:
9367 gen_helper_mtc0_lladdr(cpu_env, arg);
9368 register_name = "LLAddr";
9369 break;
9370 case 1:
9371 CP0_CHECK(ctx->mrp);
9372 gen_helper_mtc0_maar(cpu_env, arg);
9373 register_name = "MAAR";
9374 break;
9375 case 2:
9376 CP0_CHECK(ctx->mrp);
9377 gen_helper_mtc0_maari(cpu_env, arg);
9378 register_name = "MAARI";
9379 break;
9380 default:
9381 goto cp0_unimplemented;
9383 break;
9384 case CP0_REGISTER_18:
9385 switch (sel) {
9386 case 0:
9387 case 1:
9388 case 2:
9389 case 3:
9390 case 4:
9391 case 5:
9392 case 6:
9393 case 7:
9394 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9395 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9396 register_name = "WatchLo";
9397 break;
9398 default:
9399 goto cp0_unimplemented;
9401 break;
9402 case CP0_REGISTER_19:
9403 switch (sel) {
9404 case 0:
9405 case 1:
9406 case 2:
9407 case 3:
9408 case 4:
9409 case 5:
9410 case 6:
9411 case 7:
9412 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9413 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9414 register_name = "WatchHi";
9415 break;
9416 default:
9417 goto cp0_unimplemented;
9419 break;
9420 case CP0_REGISTER_20:
9421 switch (sel) {
9422 case 0:
9423 check_insn(ctx, ISA_MIPS3);
9424 gen_helper_mtc0_xcontext(cpu_env, arg);
9425 register_name = "XContext";
9426 break;
9427 default:
9428 goto cp0_unimplemented;
9430 break;
9431 case CP0_REGISTER_21:
9432 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9433 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9434 switch (sel) {
9435 case 0:
9436 gen_helper_mtc0_framemask(cpu_env, arg);
9437 register_name = "Framemask";
9438 break;
9439 default:
9440 goto cp0_unimplemented;
9442 break;
9443 case CP0_REGISTER_22:
9444 /* ignored */
9445 register_name = "Diagnostic"; /* implementation dependent */
9446 break;
9447 case CP0_REGISTER_23:
9448 switch (sel) {
9449 case 0:
9450 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9451 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9452 gen_save_pc(ctx->base.pc_next + 4);
9453 ctx->base.is_jmp = DISAS_EXIT;
9454 register_name = "Debug";
9455 break;
9456 case 1:
9457 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9458 /* Stop translation as we may have switched the execution mode */
9459 ctx->base.is_jmp = DISAS_STOP;
9460 register_name = "TraceControl";
9461 goto cp0_unimplemented;
9462 case 2:
9463 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9464 /* Stop translation as we may have switched the execution mode */
9465 ctx->base.is_jmp = DISAS_STOP;
9466 register_name = "TraceControl2";
9467 goto cp0_unimplemented;
9468 case 3:
9469 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9470 /* Stop translation as we may have switched the execution mode */
9471 ctx->base.is_jmp = DISAS_STOP;
9472 register_name = "UserTraceData";
9473 goto cp0_unimplemented;
9474 case 4:
9475 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9476 /* Stop translation as we may have switched the execution mode */
9477 ctx->base.is_jmp = DISAS_STOP;
9478 register_name = "TraceBPC";
9479 goto cp0_unimplemented;
9480 default:
9481 goto cp0_unimplemented;
9483 break;
9484 case CP0_REGISTER_24:
9485 switch (sel) {
9486 case 0:
9487 /* EJTAG support */
9488 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9489 register_name = "DEPC";
9490 break;
9491 default:
9492 goto cp0_unimplemented;
9494 break;
9495 case CP0_REGISTER_25:
9496 switch (sel) {
9497 case 0:
9498 gen_helper_mtc0_performance0(cpu_env, arg);
9499 register_name = "Performance0";
9500 break;
9501 case 1:
9502 // gen_helper_mtc0_performance1(cpu_env, arg);
9503 register_name = "Performance1";
9504 goto cp0_unimplemented;
9505 case 2:
9506 // gen_helper_mtc0_performance2(cpu_env, arg);
9507 register_name = "Performance2";
9508 goto cp0_unimplemented;
9509 case 3:
9510 // gen_helper_mtc0_performance3(cpu_env, arg);
9511 register_name = "Performance3";
9512 goto cp0_unimplemented;
9513 case 4:
9514 // gen_helper_mtc0_performance4(cpu_env, arg);
9515 register_name = "Performance4";
9516 goto cp0_unimplemented;
9517 case 5:
9518 // gen_helper_mtc0_performance5(cpu_env, arg);
9519 register_name = "Performance5";
9520 goto cp0_unimplemented;
9521 case 6:
9522 // gen_helper_mtc0_performance6(cpu_env, arg);
9523 register_name = "Performance6";
9524 goto cp0_unimplemented;
9525 case 7:
9526 // gen_helper_mtc0_performance7(cpu_env, arg);
9527 register_name = "Performance7";
9528 goto cp0_unimplemented;
9529 default:
9530 goto cp0_unimplemented;
9532 break;
9533 case CP0_REGISTER_26:
9534 switch (sel) {
9535 case 0:
9536 gen_helper_mtc0_errctl(cpu_env, arg);
9537 ctx->base.is_jmp = DISAS_STOP;
9538 register_name = "ErrCtl";
9539 break;
9540 default:
9541 goto cp0_unimplemented;
9543 break;
9544 case CP0_REGISTER_27:
9545 switch (sel) {
9546 case 0:
9547 case 1:
9548 case 2:
9549 case 3:
9550 /* ignored */
9551 register_name = "CacheErr";
9552 break;
9553 default:
9554 goto cp0_unimplemented;
9556 break;
9557 case CP0_REGISTER_28:
9558 switch (sel) {
9559 case 0:
9560 case 2:
9561 case 4:
9562 case 6:
9563 gen_helper_mtc0_taglo(cpu_env, arg);
9564 register_name = "TagLo";
9565 break;
9566 case 1:
9567 case 3:
9568 case 5:
9569 case 7:
9570 gen_helper_mtc0_datalo(cpu_env, arg);
9571 register_name = "DataLo";
9572 break;
9573 default:
9574 goto cp0_unimplemented;
9576 break;
9577 case CP0_REGISTER_29:
9578 switch (sel) {
9579 case 0:
9580 case 2:
9581 case 4:
9582 case 6:
9583 gen_helper_mtc0_taghi(cpu_env, arg);
9584 register_name = "TagHi";
9585 break;
9586 case 1:
9587 case 3:
9588 case 5:
9589 case 7:
9590 gen_helper_mtc0_datahi(cpu_env, arg);
9591 register_name = "DataHi";
9592 break;
9593 default:
9594 register_name = "invalid sel";
9595 goto cp0_unimplemented;
9597 break;
9598 case CP0_REGISTER_30:
9599 switch (sel) {
9600 case 0:
9601 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9602 register_name = "ErrorEPC";
9603 break;
9604 default:
9605 goto cp0_unimplemented;
9607 break;
9608 case CP0_REGISTER_31:
9609 switch (sel) {
9610 case 0:
9611 /* EJTAG support */
9612 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9613 register_name = "DESAVE";
9614 break;
9615 case 2:
9616 case 3:
9617 case 4:
9618 case 5:
9619 case 6:
9620 case 7:
9621 CP0_CHECK(ctx->kscrexist & (1 << sel));
9622 tcg_gen_st_tl(arg, cpu_env,
9623 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9624 register_name = "KScratch";
9625 break;
9626 default:
9627 goto cp0_unimplemented;
9629 break;
9630 default:
9631 goto cp0_unimplemented;
9633 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9635 /* For simplicity assume that all writes can cause interrupts. */
9636 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9637 gen_io_end();
9638 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9639 * translated code to check for pending interrupts. */
9640 gen_save_pc(ctx->base.pc_next + 4);
9641 ctx->base.is_jmp = DISAS_EXIT;
9643 return;
9645 cp0_unimplemented:
9646 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9647 register_name, reg, sel);
9649 #endif /* TARGET_MIPS64 */
9651 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9652 int u, int sel, int h)
9654 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9655 TCGv t0 = tcg_temp_local_new();
9657 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9658 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9659 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9660 tcg_gen_movi_tl(t0, -1);
9661 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9662 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9663 tcg_gen_movi_tl(t0, -1);
9664 else if (u == 0) {
9665 switch (rt) {
9666 case 1:
9667 switch (sel) {
9668 case 1:
9669 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9670 break;
9671 case 2:
9672 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9673 break;
9674 default:
9675 goto die;
9676 break;
9678 break;
9679 case 2:
9680 switch (sel) {
9681 case 1:
9682 gen_helper_mftc0_tcstatus(t0, cpu_env);
9683 break;
9684 case 2:
9685 gen_helper_mftc0_tcbind(t0, cpu_env);
9686 break;
9687 case 3:
9688 gen_helper_mftc0_tcrestart(t0, cpu_env);
9689 break;
9690 case 4:
9691 gen_helper_mftc0_tchalt(t0, cpu_env);
9692 break;
9693 case 5:
9694 gen_helper_mftc0_tccontext(t0, cpu_env);
9695 break;
9696 case 6:
9697 gen_helper_mftc0_tcschedule(t0, cpu_env);
9698 break;
9699 case 7:
9700 gen_helper_mftc0_tcschefback(t0, cpu_env);
9701 break;
9702 default:
9703 gen_mfc0(ctx, t0, rt, sel);
9704 break;
9706 break;
9707 case 10:
9708 switch (sel) {
9709 case 0:
9710 gen_helper_mftc0_entryhi(t0, cpu_env);
9711 break;
9712 default:
9713 gen_mfc0(ctx, t0, rt, sel);
9714 break;
9716 case 12:
9717 switch (sel) {
9718 case 0:
9719 gen_helper_mftc0_status(t0, cpu_env);
9720 break;
9721 default:
9722 gen_mfc0(ctx, t0, rt, sel);
9723 break;
9725 case 13:
9726 switch (sel) {
9727 case 0:
9728 gen_helper_mftc0_cause(t0, cpu_env);
9729 break;
9730 default:
9731 goto die;
9732 break;
9734 break;
9735 case 14:
9736 switch (sel) {
9737 case 0:
9738 gen_helper_mftc0_epc(t0, cpu_env);
9739 break;
9740 default:
9741 goto die;
9742 break;
9744 break;
9745 case 15:
9746 switch (sel) {
9747 case 1:
9748 gen_helper_mftc0_ebase(t0, cpu_env);
9749 break;
9750 default:
9751 goto die;
9752 break;
9754 break;
9755 case 16:
9756 switch (sel) {
9757 case 0:
9758 case 1:
9759 case 2:
9760 case 3:
9761 case 4:
9762 case 5:
9763 case 6:
9764 case 7:
9765 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9766 break;
9767 default:
9768 goto die;
9769 break;
9771 break;
9772 case 23:
9773 switch (sel) {
9774 case 0:
9775 gen_helper_mftc0_debug(t0, cpu_env);
9776 break;
9777 default:
9778 gen_mfc0(ctx, t0, rt, sel);
9779 break;
9781 break;
9782 default:
9783 gen_mfc0(ctx, t0, rt, sel);
9785 } else switch (sel) {
9786 /* GPR registers. */
9787 case 0:
9788 gen_helper_1e0i(mftgpr, t0, rt);
9789 break;
9790 /* Auxiliary CPU registers */
9791 case 1:
9792 switch (rt) {
9793 case 0:
9794 gen_helper_1e0i(mftlo, t0, 0);
9795 break;
9796 case 1:
9797 gen_helper_1e0i(mfthi, t0, 0);
9798 break;
9799 case 2:
9800 gen_helper_1e0i(mftacx, t0, 0);
9801 break;
9802 case 4:
9803 gen_helper_1e0i(mftlo, t0, 1);
9804 break;
9805 case 5:
9806 gen_helper_1e0i(mfthi, t0, 1);
9807 break;
9808 case 6:
9809 gen_helper_1e0i(mftacx, t0, 1);
9810 break;
9811 case 8:
9812 gen_helper_1e0i(mftlo, t0, 2);
9813 break;
9814 case 9:
9815 gen_helper_1e0i(mfthi, t0, 2);
9816 break;
9817 case 10:
9818 gen_helper_1e0i(mftacx, t0, 2);
9819 break;
9820 case 12:
9821 gen_helper_1e0i(mftlo, t0, 3);
9822 break;
9823 case 13:
9824 gen_helper_1e0i(mfthi, t0, 3);
9825 break;
9826 case 14:
9827 gen_helper_1e0i(mftacx, t0, 3);
9828 break;
9829 case 16:
9830 gen_helper_mftdsp(t0, cpu_env);
9831 break;
9832 default:
9833 goto die;
9835 break;
9836 /* Floating point (COP1). */
9837 case 2:
9838 /* XXX: For now we support only a single FPU context. */
9839 if (h == 0) {
9840 TCGv_i32 fp0 = tcg_temp_new_i32();
9842 gen_load_fpr32(ctx, fp0, rt);
9843 tcg_gen_ext_i32_tl(t0, fp0);
9844 tcg_temp_free_i32(fp0);
9845 } else {
9846 TCGv_i32 fp0 = tcg_temp_new_i32();
9848 gen_load_fpr32h(ctx, fp0, rt);
9849 tcg_gen_ext_i32_tl(t0, fp0);
9850 tcg_temp_free_i32(fp0);
9852 break;
9853 case 3:
9854 /* XXX: For now we support only a single FPU context. */
9855 gen_helper_1e0i(cfc1, t0, rt);
9856 break;
9857 /* COP2: Not implemented. */
9858 case 4:
9859 case 5:
9860 /* fall through */
9861 default:
9862 goto die;
9864 trace_mips_translate_tr("mftr", rt, u, sel, h);
9865 gen_store_gpr(t0, rd);
9866 tcg_temp_free(t0);
9867 return;
9869 die:
9870 tcg_temp_free(t0);
9871 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9872 generate_exception_end(ctx, EXCP_RI);
9875 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9876 int u, int sel, int h)
9878 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9879 TCGv t0 = tcg_temp_local_new();
9881 gen_load_gpr(t0, rt);
9882 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9883 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9884 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9885 /* NOP */ ;
9886 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9887 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9888 /* NOP */ ;
9889 else if (u == 0) {
9890 switch (rd) {
9891 case 1:
9892 switch (sel) {
9893 case 1:
9894 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9895 break;
9896 case 2:
9897 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9898 break;
9899 default:
9900 goto die;
9901 break;
9903 break;
9904 case 2:
9905 switch (sel) {
9906 case 1:
9907 gen_helper_mttc0_tcstatus(cpu_env, t0);
9908 break;
9909 case 2:
9910 gen_helper_mttc0_tcbind(cpu_env, t0);
9911 break;
9912 case 3:
9913 gen_helper_mttc0_tcrestart(cpu_env, t0);
9914 break;
9915 case 4:
9916 gen_helper_mttc0_tchalt(cpu_env, t0);
9917 break;
9918 case 5:
9919 gen_helper_mttc0_tccontext(cpu_env, t0);
9920 break;
9921 case 6:
9922 gen_helper_mttc0_tcschedule(cpu_env, t0);
9923 break;
9924 case 7:
9925 gen_helper_mttc0_tcschefback(cpu_env, t0);
9926 break;
9927 default:
9928 gen_mtc0(ctx, t0, rd, sel);
9929 break;
9931 break;
9932 case 10:
9933 switch (sel) {
9934 case 0:
9935 gen_helper_mttc0_entryhi(cpu_env, t0);
9936 break;
9937 default:
9938 gen_mtc0(ctx, t0, rd, sel);
9939 break;
9941 case 12:
9942 switch (sel) {
9943 case 0:
9944 gen_helper_mttc0_status(cpu_env, t0);
9945 break;
9946 default:
9947 gen_mtc0(ctx, t0, rd, sel);
9948 break;
9950 case 13:
9951 switch (sel) {
9952 case 0:
9953 gen_helper_mttc0_cause(cpu_env, t0);
9954 break;
9955 default:
9956 goto die;
9957 break;
9959 break;
9960 case 15:
9961 switch (sel) {
9962 case 1:
9963 gen_helper_mttc0_ebase(cpu_env, t0);
9964 break;
9965 default:
9966 goto die;
9967 break;
9969 break;
9970 case 23:
9971 switch (sel) {
9972 case 0:
9973 gen_helper_mttc0_debug(cpu_env, t0);
9974 break;
9975 default:
9976 gen_mtc0(ctx, t0, rd, sel);
9977 break;
9979 break;
9980 default:
9981 gen_mtc0(ctx, t0, rd, sel);
9983 } else switch (sel) {
9984 /* GPR registers. */
9985 case 0:
9986 gen_helper_0e1i(mttgpr, t0, rd);
9987 break;
9988 /* Auxiliary CPU registers */
9989 case 1:
9990 switch (rd) {
9991 case 0:
9992 gen_helper_0e1i(mttlo, t0, 0);
9993 break;
9994 case 1:
9995 gen_helper_0e1i(mtthi, t0, 0);
9996 break;
9997 case 2:
9998 gen_helper_0e1i(mttacx, t0, 0);
9999 break;
10000 case 4:
10001 gen_helper_0e1i(mttlo, t0, 1);
10002 break;
10003 case 5:
10004 gen_helper_0e1i(mtthi, t0, 1);
10005 break;
10006 case 6:
10007 gen_helper_0e1i(mttacx, t0, 1);
10008 break;
10009 case 8:
10010 gen_helper_0e1i(mttlo, t0, 2);
10011 break;
10012 case 9:
10013 gen_helper_0e1i(mtthi, t0, 2);
10014 break;
10015 case 10:
10016 gen_helper_0e1i(mttacx, t0, 2);
10017 break;
10018 case 12:
10019 gen_helper_0e1i(mttlo, t0, 3);
10020 break;
10021 case 13:
10022 gen_helper_0e1i(mtthi, t0, 3);
10023 break;
10024 case 14:
10025 gen_helper_0e1i(mttacx, t0, 3);
10026 break;
10027 case 16:
10028 gen_helper_mttdsp(cpu_env, t0);
10029 break;
10030 default:
10031 goto die;
10033 break;
10034 /* Floating point (COP1). */
10035 case 2:
10036 /* XXX: For now we support only a single FPU context. */
10037 if (h == 0) {
10038 TCGv_i32 fp0 = tcg_temp_new_i32();
10040 tcg_gen_trunc_tl_i32(fp0, t0);
10041 gen_store_fpr32(ctx, fp0, rd);
10042 tcg_temp_free_i32(fp0);
10043 } else {
10044 TCGv_i32 fp0 = tcg_temp_new_i32();
10046 tcg_gen_trunc_tl_i32(fp0, t0);
10047 gen_store_fpr32h(ctx, fp0, rd);
10048 tcg_temp_free_i32(fp0);
10050 break;
10051 case 3:
10052 /* XXX: For now we support only a single FPU context. */
10054 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10056 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10057 tcg_temp_free_i32(fs_tmp);
10059 /* Stop translation as we may have changed hflags */
10060 ctx->base.is_jmp = DISAS_STOP;
10061 break;
10062 /* COP2: Not implemented. */
10063 case 4:
10064 case 5:
10065 /* fall through */
10066 default:
10067 goto die;
10069 trace_mips_translate_tr("mttr", rd, u, sel, h);
10070 tcg_temp_free(t0);
10071 return;
10073 die:
10074 tcg_temp_free(t0);
10075 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10076 generate_exception_end(ctx, EXCP_RI);
10079 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
10081 const char *opn = "ldst";
10083 check_cp0_enabled(ctx);
10084 switch (opc) {
10085 case OPC_MFC0:
10086 if (rt == 0) {
10087 /* Treat as NOP. */
10088 return;
10090 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10091 opn = "mfc0";
10092 break;
10093 case OPC_MTC0:
10095 TCGv t0 = tcg_temp_new();
10097 gen_load_gpr(t0, rt);
10098 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10099 tcg_temp_free(t0);
10101 opn = "mtc0";
10102 break;
10103 #if defined(TARGET_MIPS64)
10104 case OPC_DMFC0:
10105 check_insn(ctx, ISA_MIPS3);
10106 if (rt == 0) {
10107 /* Treat as NOP. */
10108 return;
10110 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10111 opn = "dmfc0";
10112 break;
10113 case OPC_DMTC0:
10114 check_insn(ctx, ISA_MIPS3);
10116 TCGv t0 = tcg_temp_new();
10118 gen_load_gpr(t0, rt);
10119 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10120 tcg_temp_free(t0);
10122 opn = "dmtc0";
10123 break;
10124 #endif
10125 case OPC_MFHC0:
10126 check_mvh(ctx);
10127 if (rt == 0) {
10128 /* Treat as NOP. */
10129 return;
10131 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10132 opn = "mfhc0";
10133 break;
10134 case OPC_MTHC0:
10135 check_mvh(ctx);
10137 TCGv t0 = tcg_temp_new();
10138 gen_load_gpr(t0, rt);
10139 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10140 tcg_temp_free(t0);
10142 opn = "mthc0";
10143 break;
10144 case OPC_MFTR:
10145 check_cp0_enabled(ctx);
10146 if (rd == 0) {
10147 /* Treat as NOP. */
10148 return;
10150 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10151 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10152 opn = "mftr";
10153 break;
10154 case OPC_MTTR:
10155 check_cp0_enabled(ctx);
10156 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10157 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10158 opn = "mttr";
10159 break;
10160 case OPC_TLBWI:
10161 opn = "tlbwi";
10162 if (!env->tlb->helper_tlbwi)
10163 goto die;
10164 gen_helper_tlbwi(cpu_env);
10165 break;
10166 case OPC_TLBINV:
10167 opn = "tlbinv";
10168 if (ctx->ie >= 2) {
10169 if (!env->tlb->helper_tlbinv) {
10170 goto die;
10172 gen_helper_tlbinv(cpu_env);
10173 } /* treat as nop if TLBINV not supported */
10174 break;
10175 case OPC_TLBINVF:
10176 opn = "tlbinvf";
10177 if (ctx->ie >= 2) {
10178 if (!env->tlb->helper_tlbinvf) {
10179 goto die;
10181 gen_helper_tlbinvf(cpu_env);
10182 } /* treat as nop if TLBINV not supported */
10183 break;
10184 case OPC_TLBWR:
10185 opn = "tlbwr";
10186 if (!env->tlb->helper_tlbwr)
10187 goto die;
10188 gen_helper_tlbwr(cpu_env);
10189 break;
10190 case OPC_TLBP:
10191 opn = "tlbp";
10192 if (!env->tlb->helper_tlbp)
10193 goto die;
10194 gen_helper_tlbp(cpu_env);
10195 break;
10196 case OPC_TLBR:
10197 opn = "tlbr";
10198 if (!env->tlb->helper_tlbr)
10199 goto die;
10200 gen_helper_tlbr(cpu_env);
10201 break;
10202 case OPC_ERET: /* OPC_ERETNC */
10203 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10204 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10205 goto die;
10206 } else {
10207 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10208 if (ctx->opcode & (1 << bit_shift)) {
10209 /* OPC_ERETNC */
10210 opn = "eretnc";
10211 check_insn(ctx, ISA_MIPS32R5);
10212 gen_helper_eretnc(cpu_env);
10213 } else {
10214 /* OPC_ERET */
10215 opn = "eret";
10216 check_insn(ctx, ISA_MIPS2);
10217 gen_helper_eret(cpu_env);
10219 ctx->base.is_jmp = DISAS_EXIT;
10221 break;
10222 case OPC_DERET:
10223 opn = "deret";
10224 check_insn(ctx, ISA_MIPS32);
10225 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10226 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10227 goto die;
10229 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10230 MIPS_INVAL(opn);
10231 generate_exception_end(ctx, EXCP_RI);
10232 } else {
10233 gen_helper_deret(cpu_env);
10234 ctx->base.is_jmp = DISAS_EXIT;
10236 break;
10237 case OPC_WAIT:
10238 opn = "wait";
10239 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10240 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10241 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10242 goto die;
10244 /* If we get an exception, we want to restart at next instruction */
10245 ctx->base.pc_next += 4;
10246 save_cpu_state(ctx, 1);
10247 ctx->base.pc_next -= 4;
10248 gen_helper_wait(cpu_env);
10249 ctx->base.is_jmp = DISAS_NORETURN;
10250 break;
10251 default:
10252 die:
10253 MIPS_INVAL(opn);
10254 generate_exception_end(ctx, EXCP_RI);
10255 return;
10257 (void)opn; /* avoid a compiler warning */
10259 #endif /* !CONFIG_USER_ONLY */
10261 /* CP1 Branches (before delay slot) */
10262 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10263 int32_t cc, int32_t offset)
10265 target_ulong btarget;
10266 TCGv_i32 t0 = tcg_temp_new_i32();
10268 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10269 generate_exception_end(ctx, EXCP_RI);
10270 goto out;
10273 if (cc != 0)
10274 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10276 btarget = ctx->base.pc_next + 4 + offset;
10278 switch (op) {
10279 case OPC_BC1F:
10280 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10281 tcg_gen_not_i32(t0, t0);
10282 tcg_gen_andi_i32(t0, t0, 1);
10283 tcg_gen_extu_i32_tl(bcond, t0);
10284 goto not_likely;
10285 case OPC_BC1FL:
10286 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10287 tcg_gen_not_i32(t0, t0);
10288 tcg_gen_andi_i32(t0, t0, 1);
10289 tcg_gen_extu_i32_tl(bcond, t0);
10290 goto likely;
10291 case OPC_BC1T:
10292 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10293 tcg_gen_andi_i32(t0, t0, 1);
10294 tcg_gen_extu_i32_tl(bcond, t0);
10295 goto not_likely;
10296 case OPC_BC1TL:
10297 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10298 tcg_gen_andi_i32(t0, t0, 1);
10299 tcg_gen_extu_i32_tl(bcond, t0);
10300 likely:
10301 ctx->hflags |= MIPS_HFLAG_BL;
10302 break;
10303 case OPC_BC1FANY2:
10305 TCGv_i32 t1 = tcg_temp_new_i32();
10306 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10307 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10308 tcg_gen_nand_i32(t0, t0, t1);
10309 tcg_temp_free_i32(t1);
10310 tcg_gen_andi_i32(t0, t0, 1);
10311 tcg_gen_extu_i32_tl(bcond, t0);
10313 goto not_likely;
10314 case OPC_BC1TANY2:
10316 TCGv_i32 t1 = tcg_temp_new_i32();
10317 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10318 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10319 tcg_gen_or_i32(t0, t0, t1);
10320 tcg_temp_free_i32(t1);
10321 tcg_gen_andi_i32(t0, t0, 1);
10322 tcg_gen_extu_i32_tl(bcond, t0);
10324 goto not_likely;
10325 case OPC_BC1FANY4:
10327 TCGv_i32 t1 = tcg_temp_new_i32();
10328 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10329 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10330 tcg_gen_and_i32(t0, t0, t1);
10331 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10332 tcg_gen_and_i32(t0, t0, t1);
10333 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10334 tcg_gen_nand_i32(t0, t0, t1);
10335 tcg_temp_free_i32(t1);
10336 tcg_gen_andi_i32(t0, t0, 1);
10337 tcg_gen_extu_i32_tl(bcond, t0);
10339 goto not_likely;
10340 case OPC_BC1TANY4:
10342 TCGv_i32 t1 = tcg_temp_new_i32();
10343 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10344 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10345 tcg_gen_or_i32(t0, t0, t1);
10346 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10347 tcg_gen_or_i32(t0, t0, t1);
10348 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10349 tcg_gen_or_i32(t0, t0, t1);
10350 tcg_temp_free_i32(t1);
10351 tcg_gen_andi_i32(t0, t0, 1);
10352 tcg_gen_extu_i32_tl(bcond, t0);
10354 not_likely:
10355 ctx->hflags |= MIPS_HFLAG_BC;
10356 break;
10357 default:
10358 MIPS_INVAL("cp1 cond branch");
10359 generate_exception_end(ctx, EXCP_RI);
10360 goto out;
10362 ctx->btarget = btarget;
10363 ctx->hflags |= MIPS_HFLAG_BDS32;
10364 out:
10365 tcg_temp_free_i32(t0);
10368 /* R6 CP1 Branches */
10369 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10370 int32_t ft, int32_t offset,
10371 int delayslot_size)
10373 target_ulong btarget;
10374 TCGv_i64 t0 = tcg_temp_new_i64();
10376 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10377 #ifdef MIPS_DEBUG_DISAS
10378 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10379 "\n", ctx->base.pc_next);
10380 #endif
10381 generate_exception_end(ctx, EXCP_RI);
10382 goto out;
10385 gen_load_fpr64(ctx, t0, ft);
10386 tcg_gen_andi_i64(t0, t0, 1);
10388 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10390 switch (op) {
10391 case OPC_BC1EQZ:
10392 tcg_gen_xori_i64(t0, t0, 1);
10393 ctx->hflags |= MIPS_HFLAG_BC;
10394 break;
10395 case OPC_BC1NEZ:
10396 /* t0 already set */
10397 ctx->hflags |= MIPS_HFLAG_BC;
10398 break;
10399 default:
10400 MIPS_INVAL("cp1 cond branch");
10401 generate_exception_end(ctx, EXCP_RI);
10402 goto out;
10405 tcg_gen_trunc_i64_tl(bcond, t0);
10407 ctx->btarget = btarget;
10409 switch (delayslot_size) {
10410 case 2:
10411 ctx->hflags |= MIPS_HFLAG_BDS16;
10412 break;
10413 case 4:
10414 ctx->hflags |= MIPS_HFLAG_BDS32;
10415 break;
10418 out:
10419 tcg_temp_free_i64(t0);
10422 /* Coprocessor 1 (FPU) */
10424 #define FOP(func, fmt) (((fmt) << 21) | (func))
10426 enum fopcode {
10427 OPC_ADD_S = FOP(0, FMT_S),
10428 OPC_SUB_S = FOP(1, FMT_S),
10429 OPC_MUL_S = FOP(2, FMT_S),
10430 OPC_DIV_S = FOP(3, FMT_S),
10431 OPC_SQRT_S = FOP(4, FMT_S),
10432 OPC_ABS_S = FOP(5, FMT_S),
10433 OPC_MOV_S = FOP(6, FMT_S),
10434 OPC_NEG_S = FOP(7, FMT_S),
10435 OPC_ROUND_L_S = FOP(8, FMT_S),
10436 OPC_TRUNC_L_S = FOP(9, FMT_S),
10437 OPC_CEIL_L_S = FOP(10, FMT_S),
10438 OPC_FLOOR_L_S = FOP(11, FMT_S),
10439 OPC_ROUND_W_S = FOP(12, FMT_S),
10440 OPC_TRUNC_W_S = FOP(13, FMT_S),
10441 OPC_CEIL_W_S = FOP(14, FMT_S),
10442 OPC_FLOOR_W_S = FOP(15, FMT_S),
10443 OPC_SEL_S = FOP(16, FMT_S),
10444 OPC_MOVCF_S = FOP(17, FMT_S),
10445 OPC_MOVZ_S = FOP(18, FMT_S),
10446 OPC_MOVN_S = FOP(19, FMT_S),
10447 OPC_SELEQZ_S = FOP(20, FMT_S),
10448 OPC_RECIP_S = FOP(21, FMT_S),
10449 OPC_RSQRT_S = FOP(22, FMT_S),
10450 OPC_SELNEZ_S = FOP(23, FMT_S),
10451 OPC_MADDF_S = FOP(24, FMT_S),
10452 OPC_MSUBF_S = FOP(25, FMT_S),
10453 OPC_RINT_S = FOP(26, FMT_S),
10454 OPC_CLASS_S = FOP(27, FMT_S),
10455 OPC_MIN_S = FOP(28, FMT_S),
10456 OPC_RECIP2_S = FOP(28, FMT_S),
10457 OPC_MINA_S = FOP(29, FMT_S),
10458 OPC_RECIP1_S = FOP(29, FMT_S),
10459 OPC_MAX_S = FOP(30, FMT_S),
10460 OPC_RSQRT1_S = FOP(30, FMT_S),
10461 OPC_MAXA_S = FOP(31, FMT_S),
10462 OPC_RSQRT2_S = FOP(31, FMT_S),
10463 OPC_CVT_D_S = FOP(33, FMT_S),
10464 OPC_CVT_W_S = FOP(36, FMT_S),
10465 OPC_CVT_L_S = FOP(37, FMT_S),
10466 OPC_CVT_PS_S = FOP(38, FMT_S),
10467 OPC_CMP_F_S = FOP (48, FMT_S),
10468 OPC_CMP_UN_S = FOP (49, FMT_S),
10469 OPC_CMP_EQ_S = FOP (50, FMT_S),
10470 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10471 OPC_CMP_OLT_S = FOP (52, FMT_S),
10472 OPC_CMP_ULT_S = FOP (53, FMT_S),
10473 OPC_CMP_OLE_S = FOP (54, FMT_S),
10474 OPC_CMP_ULE_S = FOP (55, FMT_S),
10475 OPC_CMP_SF_S = FOP (56, FMT_S),
10476 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10477 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10478 OPC_CMP_NGL_S = FOP (59, FMT_S),
10479 OPC_CMP_LT_S = FOP (60, FMT_S),
10480 OPC_CMP_NGE_S = FOP (61, FMT_S),
10481 OPC_CMP_LE_S = FOP (62, FMT_S),
10482 OPC_CMP_NGT_S = FOP (63, FMT_S),
10484 OPC_ADD_D = FOP(0, FMT_D),
10485 OPC_SUB_D = FOP(1, FMT_D),
10486 OPC_MUL_D = FOP(2, FMT_D),
10487 OPC_DIV_D = FOP(3, FMT_D),
10488 OPC_SQRT_D = FOP(4, FMT_D),
10489 OPC_ABS_D = FOP(5, FMT_D),
10490 OPC_MOV_D = FOP(6, FMT_D),
10491 OPC_NEG_D = FOP(7, FMT_D),
10492 OPC_ROUND_L_D = FOP(8, FMT_D),
10493 OPC_TRUNC_L_D = FOP(9, FMT_D),
10494 OPC_CEIL_L_D = FOP(10, FMT_D),
10495 OPC_FLOOR_L_D = FOP(11, FMT_D),
10496 OPC_ROUND_W_D = FOP(12, FMT_D),
10497 OPC_TRUNC_W_D = FOP(13, FMT_D),
10498 OPC_CEIL_W_D = FOP(14, FMT_D),
10499 OPC_FLOOR_W_D = FOP(15, FMT_D),
10500 OPC_SEL_D = FOP(16, FMT_D),
10501 OPC_MOVCF_D = FOP(17, FMT_D),
10502 OPC_MOVZ_D = FOP(18, FMT_D),
10503 OPC_MOVN_D = FOP(19, FMT_D),
10504 OPC_SELEQZ_D = FOP(20, FMT_D),
10505 OPC_RECIP_D = FOP(21, FMT_D),
10506 OPC_RSQRT_D = FOP(22, FMT_D),
10507 OPC_SELNEZ_D = FOP(23, FMT_D),
10508 OPC_MADDF_D = FOP(24, FMT_D),
10509 OPC_MSUBF_D = FOP(25, FMT_D),
10510 OPC_RINT_D = FOP(26, FMT_D),
10511 OPC_CLASS_D = FOP(27, FMT_D),
10512 OPC_MIN_D = FOP(28, FMT_D),
10513 OPC_RECIP2_D = FOP(28, FMT_D),
10514 OPC_MINA_D = FOP(29, FMT_D),
10515 OPC_RECIP1_D = FOP(29, FMT_D),
10516 OPC_MAX_D = FOP(30, FMT_D),
10517 OPC_RSQRT1_D = FOP(30, FMT_D),
10518 OPC_MAXA_D = FOP(31, FMT_D),
10519 OPC_RSQRT2_D = FOP(31, FMT_D),
10520 OPC_CVT_S_D = FOP(32, FMT_D),
10521 OPC_CVT_W_D = FOP(36, FMT_D),
10522 OPC_CVT_L_D = FOP(37, FMT_D),
10523 OPC_CMP_F_D = FOP (48, FMT_D),
10524 OPC_CMP_UN_D = FOP (49, FMT_D),
10525 OPC_CMP_EQ_D = FOP (50, FMT_D),
10526 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10527 OPC_CMP_OLT_D = FOP (52, FMT_D),
10528 OPC_CMP_ULT_D = FOP (53, FMT_D),
10529 OPC_CMP_OLE_D = FOP (54, FMT_D),
10530 OPC_CMP_ULE_D = FOP (55, FMT_D),
10531 OPC_CMP_SF_D = FOP (56, FMT_D),
10532 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10533 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10534 OPC_CMP_NGL_D = FOP (59, FMT_D),
10535 OPC_CMP_LT_D = FOP (60, FMT_D),
10536 OPC_CMP_NGE_D = FOP (61, FMT_D),
10537 OPC_CMP_LE_D = FOP (62, FMT_D),
10538 OPC_CMP_NGT_D = FOP (63, FMT_D),
10540 OPC_CVT_S_W = FOP(32, FMT_W),
10541 OPC_CVT_D_W = FOP(33, FMT_W),
10542 OPC_CVT_S_L = FOP(32, FMT_L),
10543 OPC_CVT_D_L = FOP(33, FMT_L),
10544 OPC_CVT_PS_PW = FOP(38, FMT_W),
10546 OPC_ADD_PS = FOP(0, FMT_PS),
10547 OPC_SUB_PS = FOP(1, FMT_PS),
10548 OPC_MUL_PS = FOP(2, FMT_PS),
10549 OPC_DIV_PS = FOP(3, FMT_PS),
10550 OPC_ABS_PS = FOP(5, FMT_PS),
10551 OPC_MOV_PS = FOP(6, FMT_PS),
10552 OPC_NEG_PS = FOP(7, FMT_PS),
10553 OPC_MOVCF_PS = FOP(17, FMT_PS),
10554 OPC_MOVZ_PS = FOP(18, FMT_PS),
10555 OPC_MOVN_PS = FOP(19, FMT_PS),
10556 OPC_ADDR_PS = FOP(24, FMT_PS),
10557 OPC_MULR_PS = FOP(26, FMT_PS),
10558 OPC_RECIP2_PS = FOP(28, FMT_PS),
10559 OPC_RECIP1_PS = FOP(29, FMT_PS),
10560 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10561 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10563 OPC_CVT_S_PU = FOP(32, FMT_PS),
10564 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10565 OPC_CVT_S_PL = FOP(40, FMT_PS),
10566 OPC_PLL_PS = FOP(44, FMT_PS),
10567 OPC_PLU_PS = FOP(45, FMT_PS),
10568 OPC_PUL_PS = FOP(46, FMT_PS),
10569 OPC_PUU_PS = FOP(47, FMT_PS),
10570 OPC_CMP_F_PS = FOP (48, FMT_PS),
10571 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10572 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10573 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10574 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10575 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10576 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10577 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10578 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10579 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10580 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10581 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10582 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10583 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10584 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10585 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10588 enum r6_f_cmp_op {
10589 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10590 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10591 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10592 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10593 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10594 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10595 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10596 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10597 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10598 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10599 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10600 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10601 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10602 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10603 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10604 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10605 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10606 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10607 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10608 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10609 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10610 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10612 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10613 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10614 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10615 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10616 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10617 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10618 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10619 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10620 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10621 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10622 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10623 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10624 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10625 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10626 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10627 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10628 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10629 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10630 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10631 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10632 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10633 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10635 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10637 TCGv t0 = tcg_temp_new();
10639 switch (opc) {
10640 case OPC_MFC1:
10642 TCGv_i32 fp0 = tcg_temp_new_i32();
10644 gen_load_fpr32(ctx, fp0, fs);
10645 tcg_gen_ext_i32_tl(t0, fp0);
10646 tcg_temp_free_i32(fp0);
10648 gen_store_gpr(t0, rt);
10649 break;
10650 case OPC_MTC1:
10651 gen_load_gpr(t0, rt);
10653 TCGv_i32 fp0 = tcg_temp_new_i32();
10655 tcg_gen_trunc_tl_i32(fp0, t0);
10656 gen_store_fpr32(ctx, fp0, fs);
10657 tcg_temp_free_i32(fp0);
10659 break;
10660 case OPC_CFC1:
10661 gen_helper_1e0i(cfc1, t0, fs);
10662 gen_store_gpr(t0, rt);
10663 break;
10664 case OPC_CTC1:
10665 gen_load_gpr(t0, rt);
10666 save_cpu_state(ctx, 0);
10668 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10670 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10671 tcg_temp_free_i32(fs_tmp);
10673 /* Stop translation as we may have changed hflags */
10674 ctx->base.is_jmp = DISAS_STOP;
10675 break;
10676 #if defined(TARGET_MIPS64)
10677 case OPC_DMFC1:
10678 gen_load_fpr64(ctx, t0, fs);
10679 gen_store_gpr(t0, rt);
10680 break;
10681 case OPC_DMTC1:
10682 gen_load_gpr(t0, rt);
10683 gen_store_fpr64(ctx, t0, fs);
10684 break;
10685 #endif
10686 case OPC_MFHC1:
10688 TCGv_i32 fp0 = tcg_temp_new_i32();
10690 gen_load_fpr32h(ctx, fp0, fs);
10691 tcg_gen_ext_i32_tl(t0, fp0);
10692 tcg_temp_free_i32(fp0);
10694 gen_store_gpr(t0, rt);
10695 break;
10696 case OPC_MTHC1:
10697 gen_load_gpr(t0, rt);
10699 TCGv_i32 fp0 = tcg_temp_new_i32();
10701 tcg_gen_trunc_tl_i32(fp0, t0);
10702 gen_store_fpr32h(ctx, fp0, fs);
10703 tcg_temp_free_i32(fp0);
10705 break;
10706 default:
10707 MIPS_INVAL("cp1 move");
10708 generate_exception_end(ctx, EXCP_RI);
10709 goto out;
10712 out:
10713 tcg_temp_free(t0);
10716 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10718 TCGLabel *l1;
10719 TCGCond cond;
10720 TCGv_i32 t0;
10722 if (rd == 0) {
10723 /* Treat as NOP. */
10724 return;
10727 if (tf)
10728 cond = TCG_COND_EQ;
10729 else
10730 cond = TCG_COND_NE;
10732 l1 = gen_new_label();
10733 t0 = tcg_temp_new_i32();
10734 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10735 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10736 tcg_temp_free_i32(t0);
10737 if (rs == 0) {
10738 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10739 } else {
10740 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10742 gen_set_label(l1);
10745 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10746 int tf)
10748 int cond;
10749 TCGv_i32 t0 = tcg_temp_new_i32();
10750 TCGLabel *l1 = gen_new_label();
10752 if (tf)
10753 cond = TCG_COND_EQ;
10754 else
10755 cond = TCG_COND_NE;
10757 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10758 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10759 gen_load_fpr32(ctx, t0, fs);
10760 gen_store_fpr32(ctx, t0, fd);
10761 gen_set_label(l1);
10762 tcg_temp_free_i32(t0);
10765 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10767 int cond;
10768 TCGv_i32 t0 = tcg_temp_new_i32();
10769 TCGv_i64 fp0;
10770 TCGLabel *l1 = gen_new_label();
10772 if (tf)
10773 cond = TCG_COND_EQ;
10774 else
10775 cond = TCG_COND_NE;
10777 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10778 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10779 tcg_temp_free_i32(t0);
10780 fp0 = tcg_temp_new_i64();
10781 gen_load_fpr64(ctx, fp0, fs);
10782 gen_store_fpr64(ctx, fp0, fd);
10783 tcg_temp_free_i64(fp0);
10784 gen_set_label(l1);
10787 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10788 int cc, int tf)
10790 int cond;
10791 TCGv_i32 t0 = tcg_temp_new_i32();
10792 TCGLabel *l1 = gen_new_label();
10793 TCGLabel *l2 = gen_new_label();
10795 if (tf)
10796 cond = TCG_COND_EQ;
10797 else
10798 cond = TCG_COND_NE;
10800 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10801 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10802 gen_load_fpr32(ctx, t0, fs);
10803 gen_store_fpr32(ctx, t0, fd);
10804 gen_set_label(l1);
10806 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10807 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10808 gen_load_fpr32h(ctx, t0, fs);
10809 gen_store_fpr32h(ctx, t0, fd);
10810 tcg_temp_free_i32(t0);
10811 gen_set_label(l2);
10814 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10815 int fs)
10817 TCGv_i32 t1 = tcg_const_i32(0);
10818 TCGv_i32 fp0 = tcg_temp_new_i32();
10819 TCGv_i32 fp1 = tcg_temp_new_i32();
10820 TCGv_i32 fp2 = tcg_temp_new_i32();
10821 gen_load_fpr32(ctx, fp0, fd);
10822 gen_load_fpr32(ctx, fp1, ft);
10823 gen_load_fpr32(ctx, fp2, fs);
10825 switch (op1) {
10826 case OPC_SEL_S:
10827 tcg_gen_andi_i32(fp0, fp0, 1);
10828 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10829 break;
10830 case OPC_SELEQZ_S:
10831 tcg_gen_andi_i32(fp1, fp1, 1);
10832 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10833 break;
10834 case OPC_SELNEZ_S:
10835 tcg_gen_andi_i32(fp1, fp1, 1);
10836 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10837 break;
10838 default:
10839 MIPS_INVAL("gen_sel_s");
10840 generate_exception_end(ctx, EXCP_RI);
10841 break;
10844 gen_store_fpr32(ctx, fp0, fd);
10845 tcg_temp_free_i32(fp2);
10846 tcg_temp_free_i32(fp1);
10847 tcg_temp_free_i32(fp0);
10848 tcg_temp_free_i32(t1);
10851 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10852 int fs)
10854 TCGv_i64 t1 = tcg_const_i64(0);
10855 TCGv_i64 fp0 = tcg_temp_new_i64();
10856 TCGv_i64 fp1 = tcg_temp_new_i64();
10857 TCGv_i64 fp2 = tcg_temp_new_i64();
10858 gen_load_fpr64(ctx, fp0, fd);
10859 gen_load_fpr64(ctx, fp1, ft);
10860 gen_load_fpr64(ctx, fp2, fs);
10862 switch (op1) {
10863 case OPC_SEL_D:
10864 tcg_gen_andi_i64(fp0, fp0, 1);
10865 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10866 break;
10867 case OPC_SELEQZ_D:
10868 tcg_gen_andi_i64(fp1, fp1, 1);
10869 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10870 break;
10871 case OPC_SELNEZ_D:
10872 tcg_gen_andi_i64(fp1, fp1, 1);
10873 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10874 break;
10875 default:
10876 MIPS_INVAL("gen_sel_d");
10877 generate_exception_end(ctx, EXCP_RI);
10878 break;
10881 gen_store_fpr64(ctx, fp0, fd);
10882 tcg_temp_free_i64(fp2);
10883 tcg_temp_free_i64(fp1);
10884 tcg_temp_free_i64(fp0);
10885 tcg_temp_free_i64(t1);
10888 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10889 int ft, int fs, int fd, int cc)
10891 uint32_t func = ctx->opcode & 0x3f;
10892 switch (op1) {
10893 case OPC_ADD_S:
10895 TCGv_i32 fp0 = tcg_temp_new_i32();
10896 TCGv_i32 fp1 = tcg_temp_new_i32();
10898 gen_load_fpr32(ctx, fp0, fs);
10899 gen_load_fpr32(ctx, fp1, ft);
10900 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10901 tcg_temp_free_i32(fp1);
10902 gen_store_fpr32(ctx, fp0, fd);
10903 tcg_temp_free_i32(fp0);
10905 break;
10906 case OPC_SUB_S:
10908 TCGv_i32 fp0 = tcg_temp_new_i32();
10909 TCGv_i32 fp1 = tcg_temp_new_i32();
10911 gen_load_fpr32(ctx, fp0, fs);
10912 gen_load_fpr32(ctx, fp1, ft);
10913 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10914 tcg_temp_free_i32(fp1);
10915 gen_store_fpr32(ctx, fp0, fd);
10916 tcg_temp_free_i32(fp0);
10918 break;
10919 case OPC_MUL_S:
10921 TCGv_i32 fp0 = tcg_temp_new_i32();
10922 TCGv_i32 fp1 = tcg_temp_new_i32();
10924 gen_load_fpr32(ctx, fp0, fs);
10925 gen_load_fpr32(ctx, fp1, ft);
10926 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10927 tcg_temp_free_i32(fp1);
10928 gen_store_fpr32(ctx, fp0, fd);
10929 tcg_temp_free_i32(fp0);
10931 break;
10932 case OPC_DIV_S:
10934 TCGv_i32 fp0 = tcg_temp_new_i32();
10935 TCGv_i32 fp1 = tcg_temp_new_i32();
10937 gen_load_fpr32(ctx, fp0, fs);
10938 gen_load_fpr32(ctx, fp1, ft);
10939 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10940 tcg_temp_free_i32(fp1);
10941 gen_store_fpr32(ctx, fp0, fd);
10942 tcg_temp_free_i32(fp0);
10944 break;
10945 case OPC_SQRT_S:
10947 TCGv_i32 fp0 = tcg_temp_new_i32();
10949 gen_load_fpr32(ctx, fp0, fs);
10950 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10951 gen_store_fpr32(ctx, fp0, fd);
10952 tcg_temp_free_i32(fp0);
10954 break;
10955 case OPC_ABS_S:
10957 TCGv_i32 fp0 = tcg_temp_new_i32();
10959 gen_load_fpr32(ctx, fp0, fs);
10960 if (ctx->abs2008) {
10961 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10962 } else {
10963 gen_helper_float_abs_s(fp0, fp0);
10965 gen_store_fpr32(ctx, fp0, fd);
10966 tcg_temp_free_i32(fp0);
10968 break;
10969 case OPC_MOV_S:
10971 TCGv_i32 fp0 = tcg_temp_new_i32();
10973 gen_load_fpr32(ctx, fp0, fs);
10974 gen_store_fpr32(ctx, fp0, fd);
10975 tcg_temp_free_i32(fp0);
10977 break;
10978 case OPC_NEG_S:
10980 TCGv_i32 fp0 = tcg_temp_new_i32();
10982 gen_load_fpr32(ctx, fp0, fs);
10983 if (ctx->abs2008) {
10984 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10985 } else {
10986 gen_helper_float_chs_s(fp0, fp0);
10988 gen_store_fpr32(ctx, fp0, fd);
10989 tcg_temp_free_i32(fp0);
10991 break;
10992 case OPC_ROUND_L_S:
10993 check_cp1_64bitmode(ctx);
10995 TCGv_i32 fp32 = tcg_temp_new_i32();
10996 TCGv_i64 fp64 = tcg_temp_new_i64();
10998 gen_load_fpr32(ctx, fp32, fs);
10999 if (ctx->nan2008) {
11000 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11001 } else {
11002 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11004 tcg_temp_free_i32(fp32);
11005 gen_store_fpr64(ctx, fp64, fd);
11006 tcg_temp_free_i64(fp64);
11008 break;
11009 case OPC_TRUNC_L_S:
11010 check_cp1_64bitmode(ctx);
11012 TCGv_i32 fp32 = tcg_temp_new_i32();
11013 TCGv_i64 fp64 = tcg_temp_new_i64();
11015 gen_load_fpr32(ctx, fp32, fs);
11016 if (ctx->nan2008) {
11017 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11018 } else {
11019 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11021 tcg_temp_free_i32(fp32);
11022 gen_store_fpr64(ctx, fp64, fd);
11023 tcg_temp_free_i64(fp64);
11025 break;
11026 case OPC_CEIL_L_S:
11027 check_cp1_64bitmode(ctx);
11029 TCGv_i32 fp32 = tcg_temp_new_i32();
11030 TCGv_i64 fp64 = tcg_temp_new_i64();
11032 gen_load_fpr32(ctx, fp32, fs);
11033 if (ctx->nan2008) {
11034 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11035 } else {
11036 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11038 tcg_temp_free_i32(fp32);
11039 gen_store_fpr64(ctx, fp64, fd);
11040 tcg_temp_free_i64(fp64);
11042 break;
11043 case OPC_FLOOR_L_S:
11044 check_cp1_64bitmode(ctx);
11046 TCGv_i32 fp32 = tcg_temp_new_i32();
11047 TCGv_i64 fp64 = tcg_temp_new_i64();
11049 gen_load_fpr32(ctx, fp32, fs);
11050 if (ctx->nan2008) {
11051 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11052 } else {
11053 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11055 tcg_temp_free_i32(fp32);
11056 gen_store_fpr64(ctx, fp64, fd);
11057 tcg_temp_free_i64(fp64);
11059 break;
11060 case OPC_ROUND_W_S:
11062 TCGv_i32 fp0 = tcg_temp_new_i32();
11064 gen_load_fpr32(ctx, fp0, fs);
11065 if (ctx->nan2008) {
11066 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11067 } else {
11068 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11070 gen_store_fpr32(ctx, fp0, fd);
11071 tcg_temp_free_i32(fp0);
11073 break;
11074 case OPC_TRUNC_W_S:
11076 TCGv_i32 fp0 = tcg_temp_new_i32();
11078 gen_load_fpr32(ctx, fp0, fs);
11079 if (ctx->nan2008) {
11080 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11081 } else {
11082 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11084 gen_store_fpr32(ctx, fp0, fd);
11085 tcg_temp_free_i32(fp0);
11087 break;
11088 case OPC_CEIL_W_S:
11090 TCGv_i32 fp0 = tcg_temp_new_i32();
11092 gen_load_fpr32(ctx, fp0, fs);
11093 if (ctx->nan2008) {
11094 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11095 } else {
11096 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11098 gen_store_fpr32(ctx, fp0, fd);
11099 tcg_temp_free_i32(fp0);
11101 break;
11102 case OPC_FLOOR_W_S:
11104 TCGv_i32 fp0 = tcg_temp_new_i32();
11106 gen_load_fpr32(ctx, fp0, fs);
11107 if (ctx->nan2008) {
11108 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11109 } else {
11110 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11112 gen_store_fpr32(ctx, fp0, fd);
11113 tcg_temp_free_i32(fp0);
11115 break;
11116 case OPC_SEL_S:
11117 check_insn(ctx, ISA_MIPS32R6);
11118 gen_sel_s(ctx, op1, fd, ft, fs);
11119 break;
11120 case OPC_SELEQZ_S:
11121 check_insn(ctx, ISA_MIPS32R6);
11122 gen_sel_s(ctx, op1, fd, ft, fs);
11123 break;
11124 case OPC_SELNEZ_S:
11125 check_insn(ctx, ISA_MIPS32R6);
11126 gen_sel_s(ctx, op1, fd, ft, fs);
11127 break;
11128 case OPC_MOVCF_S:
11129 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11130 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11131 break;
11132 case OPC_MOVZ_S:
11133 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11135 TCGLabel *l1 = gen_new_label();
11136 TCGv_i32 fp0;
11138 if (ft != 0) {
11139 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11141 fp0 = tcg_temp_new_i32();
11142 gen_load_fpr32(ctx, fp0, fs);
11143 gen_store_fpr32(ctx, fp0, fd);
11144 tcg_temp_free_i32(fp0);
11145 gen_set_label(l1);
11147 break;
11148 case OPC_MOVN_S:
11149 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11151 TCGLabel *l1 = gen_new_label();
11152 TCGv_i32 fp0;
11154 if (ft != 0) {
11155 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11156 fp0 = tcg_temp_new_i32();
11157 gen_load_fpr32(ctx, fp0, fs);
11158 gen_store_fpr32(ctx, fp0, fd);
11159 tcg_temp_free_i32(fp0);
11160 gen_set_label(l1);
11163 break;
11164 case OPC_RECIP_S:
11166 TCGv_i32 fp0 = tcg_temp_new_i32();
11168 gen_load_fpr32(ctx, fp0, fs);
11169 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11170 gen_store_fpr32(ctx, fp0, fd);
11171 tcg_temp_free_i32(fp0);
11173 break;
11174 case OPC_RSQRT_S:
11176 TCGv_i32 fp0 = tcg_temp_new_i32();
11178 gen_load_fpr32(ctx, fp0, fs);
11179 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11180 gen_store_fpr32(ctx, fp0, fd);
11181 tcg_temp_free_i32(fp0);
11183 break;
11184 case OPC_MADDF_S:
11185 check_insn(ctx, ISA_MIPS32R6);
11187 TCGv_i32 fp0 = tcg_temp_new_i32();
11188 TCGv_i32 fp1 = tcg_temp_new_i32();
11189 TCGv_i32 fp2 = tcg_temp_new_i32();
11190 gen_load_fpr32(ctx, fp0, fs);
11191 gen_load_fpr32(ctx, fp1, ft);
11192 gen_load_fpr32(ctx, fp2, fd);
11193 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11194 gen_store_fpr32(ctx, fp2, fd);
11195 tcg_temp_free_i32(fp2);
11196 tcg_temp_free_i32(fp1);
11197 tcg_temp_free_i32(fp0);
11199 break;
11200 case OPC_MSUBF_S:
11201 check_insn(ctx, ISA_MIPS32R6);
11203 TCGv_i32 fp0 = tcg_temp_new_i32();
11204 TCGv_i32 fp1 = tcg_temp_new_i32();
11205 TCGv_i32 fp2 = tcg_temp_new_i32();
11206 gen_load_fpr32(ctx, fp0, fs);
11207 gen_load_fpr32(ctx, fp1, ft);
11208 gen_load_fpr32(ctx, fp2, fd);
11209 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11210 gen_store_fpr32(ctx, fp2, fd);
11211 tcg_temp_free_i32(fp2);
11212 tcg_temp_free_i32(fp1);
11213 tcg_temp_free_i32(fp0);
11215 break;
11216 case OPC_RINT_S:
11217 check_insn(ctx, ISA_MIPS32R6);
11219 TCGv_i32 fp0 = tcg_temp_new_i32();
11220 gen_load_fpr32(ctx, fp0, fs);
11221 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11222 gen_store_fpr32(ctx, fp0, fd);
11223 tcg_temp_free_i32(fp0);
11225 break;
11226 case OPC_CLASS_S:
11227 check_insn(ctx, ISA_MIPS32R6);
11229 TCGv_i32 fp0 = tcg_temp_new_i32();
11230 gen_load_fpr32(ctx, fp0, fs);
11231 gen_helper_float_class_s(fp0, cpu_env, fp0);
11232 gen_store_fpr32(ctx, fp0, fd);
11233 tcg_temp_free_i32(fp0);
11235 break;
11236 case OPC_MIN_S: /* OPC_RECIP2_S */
11237 if (ctx->insn_flags & ISA_MIPS32R6) {
11238 /* OPC_MIN_S */
11239 TCGv_i32 fp0 = tcg_temp_new_i32();
11240 TCGv_i32 fp1 = tcg_temp_new_i32();
11241 TCGv_i32 fp2 = tcg_temp_new_i32();
11242 gen_load_fpr32(ctx, fp0, fs);
11243 gen_load_fpr32(ctx, fp1, ft);
11244 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11245 gen_store_fpr32(ctx, fp2, fd);
11246 tcg_temp_free_i32(fp2);
11247 tcg_temp_free_i32(fp1);
11248 tcg_temp_free_i32(fp0);
11249 } else {
11250 /* OPC_RECIP2_S */
11251 check_cp1_64bitmode(ctx);
11253 TCGv_i32 fp0 = tcg_temp_new_i32();
11254 TCGv_i32 fp1 = tcg_temp_new_i32();
11256 gen_load_fpr32(ctx, fp0, fs);
11257 gen_load_fpr32(ctx, fp1, ft);
11258 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11259 tcg_temp_free_i32(fp1);
11260 gen_store_fpr32(ctx, fp0, fd);
11261 tcg_temp_free_i32(fp0);
11264 break;
11265 case OPC_MINA_S: /* OPC_RECIP1_S */
11266 if (ctx->insn_flags & ISA_MIPS32R6) {
11267 /* OPC_MINA_S */
11268 TCGv_i32 fp0 = tcg_temp_new_i32();
11269 TCGv_i32 fp1 = tcg_temp_new_i32();
11270 TCGv_i32 fp2 = tcg_temp_new_i32();
11271 gen_load_fpr32(ctx, fp0, fs);
11272 gen_load_fpr32(ctx, fp1, ft);
11273 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11274 gen_store_fpr32(ctx, fp2, fd);
11275 tcg_temp_free_i32(fp2);
11276 tcg_temp_free_i32(fp1);
11277 tcg_temp_free_i32(fp0);
11278 } else {
11279 /* OPC_RECIP1_S */
11280 check_cp1_64bitmode(ctx);
11282 TCGv_i32 fp0 = tcg_temp_new_i32();
11284 gen_load_fpr32(ctx, fp0, fs);
11285 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11286 gen_store_fpr32(ctx, fp0, fd);
11287 tcg_temp_free_i32(fp0);
11290 break;
11291 case OPC_MAX_S: /* OPC_RSQRT1_S */
11292 if (ctx->insn_flags & ISA_MIPS32R6) {
11293 /* OPC_MAX_S */
11294 TCGv_i32 fp0 = tcg_temp_new_i32();
11295 TCGv_i32 fp1 = tcg_temp_new_i32();
11296 gen_load_fpr32(ctx, fp0, fs);
11297 gen_load_fpr32(ctx, fp1, ft);
11298 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11299 gen_store_fpr32(ctx, fp1, fd);
11300 tcg_temp_free_i32(fp1);
11301 tcg_temp_free_i32(fp0);
11302 } else {
11303 /* OPC_RSQRT1_S */
11304 check_cp1_64bitmode(ctx);
11306 TCGv_i32 fp0 = tcg_temp_new_i32();
11308 gen_load_fpr32(ctx, fp0, fs);
11309 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11310 gen_store_fpr32(ctx, fp0, fd);
11311 tcg_temp_free_i32(fp0);
11314 break;
11315 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11316 if (ctx->insn_flags & ISA_MIPS32R6) {
11317 /* OPC_MAXA_S */
11318 TCGv_i32 fp0 = tcg_temp_new_i32();
11319 TCGv_i32 fp1 = tcg_temp_new_i32();
11320 gen_load_fpr32(ctx, fp0, fs);
11321 gen_load_fpr32(ctx, fp1, ft);
11322 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11323 gen_store_fpr32(ctx, fp1, fd);
11324 tcg_temp_free_i32(fp1);
11325 tcg_temp_free_i32(fp0);
11326 } else {
11327 /* OPC_RSQRT2_S */
11328 check_cp1_64bitmode(ctx);
11330 TCGv_i32 fp0 = tcg_temp_new_i32();
11331 TCGv_i32 fp1 = tcg_temp_new_i32();
11333 gen_load_fpr32(ctx, fp0, fs);
11334 gen_load_fpr32(ctx, fp1, ft);
11335 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11336 tcg_temp_free_i32(fp1);
11337 gen_store_fpr32(ctx, fp0, fd);
11338 tcg_temp_free_i32(fp0);
11341 break;
11342 case OPC_CVT_D_S:
11343 check_cp1_registers(ctx, fd);
11345 TCGv_i32 fp32 = tcg_temp_new_i32();
11346 TCGv_i64 fp64 = tcg_temp_new_i64();
11348 gen_load_fpr32(ctx, fp32, fs);
11349 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11350 tcg_temp_free_i32(fp32);
11351 gen_store_fpr64(ctx, fp64, fd);
11352 tcg_temp_free_i64(fp64);
11354 break;
11355 case OPC_CVT_W_S:
11357 TCGv_i32 fp0 = tcg_temp_new_i32();
11359 gen_load_fpr32(ctx, fp0, fs);
11360 if (ctx->nan2008) {
11361 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11362 } else {
11363 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11365 gen_store_fpr32(ctx, fp0, fd);
11366 tcg_temp_free_i32(fp0);
11368 break;
11369 case OPC_CVT_L_S:
11370 check_cp1_64bitmode(ctx);
11372 TCGv_i32 fp32 = tcg_temp_new_i32();
11373 TCGv_i64 fp64 = tcg_temp_new_i64();
11375 gen_load_fpr32(ctx, fp32, fs);
11376 if (ctx->nan2008) {
11377 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11378 } else {
11379 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11381 tcg_temp_free_i32(fp32);
11382 gen_store_fpr64(ctx, fp64, fd);
11383 tcg_temp_free_i64(fp64);
11385 break;
11386 case OPC_CVT_PS_S:
11387 check_ps(ctx);
11389 TCGv_i64 fp64 = tcg_temp_new_i64();
11390 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11391 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11393 gen_load_fpr32(ctx, fp32_0, fs);
11394 gen_load_fpr32(ctx, fp32_1, ft);
11395 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11396 tcg_temp_free_i32(fp32_1);
11397 tcg_temp_free_i32(fp32_0);
11398 gen_store_fpr64(ctx, fp64, fd);
11399 tcg_temp_free_i64(fp64);
11401 break;
11402 case OPC_CMP_F_S:
11403 case OPC_CMP_UN_S:
11404 case OPC_CMP_EQ_S:
11405 case OPC_CMP_UEQ_S:
11406 case OPC_CMP_OLT_S:
11407 case OPC_CMP_ULT_S:
11408 case OPC_CMP_OLE_S:
11409 case OPC_CMP_ULE_S:
11410 case OPC_CMP_SF_S:
11411 case OPC_CMP_NGLE_S:
11412 case OPC_CMP_SEQ_S:
11413 case OPC_CMP_NGL_S:
11414 case OPC_CMP_LT_S:
11415 case OPC_CMP_NGE_S:
11416 case OPC_CMP_LE_S:
11417 case OPC_CMP_NGT_S:
11418 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11419 if (ctx->opcode & (1 << 6)) {
11420 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11421 } else {
11422 gen_cmp_s(ctx, func-48, ft, fs, cc);
11424 break;
11425 case OPC_ADD_D:
11426 check_cp1_registers(ctx, fs | ft | fd);
11428 TCGv_i64 fp0 = tcg_temp_new_i64();
11429 TCGv_i64 fp1 = tcg_temp_new_i64();
11431 gen_load_fpr64(ctx, fp0, fs);
11432 gen_load_fpr64(ctx, fp1, ft);
11433 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11434 tcg_temp_free_i64(fp1);
11435 gen_store_fpr64(ctx, fp0, fd);
11436 tcg_temp_free_i64(fp0);
11438 break;
11439 case OPC_SUB_D:
11440 check_cp1_registers(ctx, fs | ft | fd);
11442 TCGv_i64 fp0 = tcg_temp_new_i64();
11443 TCGv_i64 fp1 = tcg_temp_new_i64();
11445 gen_load_fpr64(ctx, fp0, fs);
11446 gen_load_fpr64(ctx, fp1, ft);
11447 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11448 tcg_temp_free_i64(fp1);
11449 gen_store_fpr64(ctx, fp0, fd);
11450 tcg_temp_free_i64(fp0);
11452 break;
11453 case OPC_MUL_D:
11454 check_cp1_registers(ctx, fs | ft | fd);
11456 TCGv_i64 fp0 = tcg_temp_new_i64();
11457 TCGv_i64 fp1 = tcg_temp_new_i64();
11459 gen_load_fpr64(ctx, fp0, fs);
11460 gen_load_fpr64(ctx, fp1, ft);
11461 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11462 tcg_temp_free_i64(fp1);
11463 gen_store_fpr64(ctx, fp0, fd);
11464 tcg_temp_free_i64(fp0);
11466 break;
11467 case OPC_DIV_D:
11468 check_cp1_registers(ctx, fs | ft | fd);
11470 TCGv_i64 fp0 = tcg_temp_new_i64();
11471 TCGv_i64 fp1 = tcg_temp_new_i64();
11473 gen_load_fpr64(ctx, fp0, fs);
11474 gen_load_fpr64(ctx, fp1, ft);
11475 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11476 tcg_temp_free_i64(fp1);
11477 gen_store_fpr64(ctx, fp0, fd);
11478 tcg_temp_free_i64(fp0);
11480 break;
11481 case OPC_SQRT_D:
11482 check_cp1_registers(ctx, fs | fd);
11484 TCGv_i64 fp0 = tcg_temp_new_i64();
11486 gen_load_fpr64(ctx, fp0, fs);
11487 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11488 gen_store_fpr64(ctx, fp0, fd);
11489 tcg_temp_free_i64(fp0);
11491 break;
11492 case OPC_ABS_D:
11493 check_cp1_registers(ctx, fs | fd);
11495 TCGv_i64 fp0 = tcg_temp_new_i64();
11497 gen_load_fpr64(ctx, fp0, fs);
11498 if (ctx->abs2008) {
11499 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11500 } else {
11501 gen_helper_float_abs_d(fp0, fp0);
11503 gen_store_fpr64(ctx, fp0, fd);
11504 tcg_temp_free_i64(fp0);
11506 break;
11507 case OPC_MOV_D:
11508 check_cp1_registers(ctx, fs | fd);
11510 TCGv_i64 fp0 = tcg_temp_new_i64();
11512 gen_load_fpr64(ctx, fp0, fs);
11513 gen_store_fpr64(ctx, fp0, fd);
11514 tcg_temp_free_i64(fp0);
11516 break;
11517 case OPC_NEG_D:
11518 check_cp1_registers(ctx, fs | fd);
11520 TCGv_i64 fp0 = tcg_temp_new_i64();
11522 gen_load_fpr64(ctx, fp0, fs);
11523 if (ctx->abs2008) {
11524 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11525 } else {
11526 gen_helper_float_chs_d(fp0, fp0);
11528 gen_store_fpr64(ctx, fp0, fd);
11529 tcg_temp_free_i64(fp0);
11531 break;
11532 case OPC_ROUND_L_D:
11533 check_cp1_64bitmode(ctx);
11535 TCGv_i64 fp0 = tcg_temp_new_i64();
11537 gen_load_fpr64(ctx, fp0, fs);
11538 if (ctx->nan2008) {
11539 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11540 } else {
11541 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11543 gen_store_fpr64(ctx, fp0, fd);
11544 tcg_temp_free_i64(fp0);
11546 break;
11547 case OPC_TRUNC_L_D:
11548 check_cp1_64bitmode(ctx);
11550 TCGv_i64 fp0 = tcg_temp_new_i64();
11552 gen_load_fpr64(ctx, fp0, fs);
11553 if (ctx->nan2008) {
11554 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11555 } else {
11556 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11558 gen_store_fpr64(ctx, fp0, fd);
11559 tcg_temp_free_i64(fp0);
11561 break;
11562 case OPC_CEIL_L_D:
11563 check_cp1_64bitmode(ctx);
11565 TCGv_i64 fp0 = tcg_temp_new_i64();
11567 gen_load_fpr64(ctx, fp0, fs);
11568 if (ctx->nan2008) {
11569 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11570 } else {
11571 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11573 gen_store_fpr64(ctx, fp0, fd);
11574 tcg_temp_free_i64(fp0);
11576 break;
11577 case OPC_FLOOR_L_D:
11578 check_cp1_64bitmode(ctx);
11580 TCGv_i64 fp0 = tcg_temp_new_i64();
11582 gen_load_fpr64(ctx, fp0, fs);
11583 if (ctx->nan2008) {
11584 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11585 } else {
11586 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11588 gen_store_fpr64(ctx, fp0, fd);
11589 tcg_temp_free_i64(fp0);
11591 break;
11592 case OPC_ROUND_W_D:
11593 check_cp1_registers(ctx, fs);
11595 TCGv_i32 fp32 = tcg_temp_new_i32();
11596 TCGv_i64 fp64 = tcg_temp_new_i64();
11598 gen_load_fpr64(ctx, fp64, fs);
11599 if (ctx->nan2008) {
11600 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11601 } else {
11602 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11604 tcg_temp_free_i64(fp64);
11605 gen_store_fpr32(ctx, fp32, fd);
11606 tcg_temp_free_i32(fp32);
11608 break;
11609 case OPC_TRUNC_W_D:
11610 check_cp1_registers(ctx, fs);
11612 TCGv_i32 fp32 = tcg_temp_new_i32();
11613 TCGv_i64 fp64 = tcg_temp_new_i64();
11615 gen_load_fpr64(ctx, fp64, fs);
11616 if (ctx->nan2008) {
11617 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11618 } else {
11619 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11621 tcg_temp_free_i64(fp64);
11622 gen_store_fpr32(ctx, fp32, fd);
11623 tcg_temp_free_i32(fp32);
11625 break;
11626 case OPC_CEIL_W_D:
11627 check_cp1_registers(ctx, fs);
11629 TCGv_i32 fp32 = tcg_temp_new_i32();
11630 TCGv_i64 fp64 = tcg_temp_new_i64();
11632 gen_load_fpr64(ctx, fp64, fs);
11633 if (ctx->nan2008) {
11634 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11635 } else {
11636 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11638 tcg_temp_free_i64(fp64);
11639 gen_store_fpr32(ctx, fp32, fd);
11640 tcg_temp_free_i32(fp32);
11642 break;
11643 case OPC_FLOOR_W_D:
11644 check_cp1_registers(ctx, fs);
11646 TCGv_i32 fp32 = tcg_temp_new_i32();
11647 TCGv_i64 fp64 = tcg_temp_new_i64();
11649 gen_load_fpr64(ctx, fp64, fs);
11650 if (ctx->nan2008) {
11651 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11652 } else {
11653 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11655 tcg_temp_free_i64(fp64);
11656 gen_store_fpr32(ctx, fp32, fd);
11657 tcg_temp_free_i32(fp32);
11659 break;
11660 case OPC_SEL_D:
11661 check_insn(ctx, ISA_MIPS32R6);
11662 gen_sel_d(ctx, op1, fd, ft, fs);
11663 break;
11664 case OPC_SELEQZ_D:
11665 check_insn(ctx, ISA_MIPS32R6);
11666 gen_sel_d(ctx, op1, fd, ft, fs);
11667 break;
11668 case OPC_SELNEZ_D:
11669 check_insn(ctx, ISA_MIPS32R6);
11670 gen_sel_d(ctx, op1, fd, ft, fs);
11671 break;
11672 case OPC_MOVCF_D:
11673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11674 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11675 break;
11676 case OPC_MOVZ_D:
11677 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11679 TCGLabel *l1 = gen_new_label();
11680 TCGv_i64 fp0;
11682 if (ft != 0) {
11683 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11685 fp0 = tcg_temp_new_i64();
11686 gen_load_fpr64(ctx, fp0, fs);
11687 gen_store_fpr64(ctx, fp0, fd);
11688 tcg_temp_free_i64(fp0);
11689 gen_set_label(l1);
11691 break;
11692 case OPC_MOVN_D:
11693 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11695 TCGLabel *l1 = gen_new_label();
11696 TCGv_i64 fp0;
11698 if (ft != 0) {
11699 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11700 fp0 = tcg_temp_new_i64();
11701 gen_load_fpr64(ctx, fp0, fs);
11702 gen_store_fpr64(ctx, fp0, fd);
11703 tcg_temp_free_i64(fp0);
11704 gen_set_label(l1);
11707 break;
11708 case OPC_RECIP_D:
11709 check_cp1_registers(ctx, fs | fd);
11711 TCGv_i64 fp0 = tcg_temp_new_i64();
11713 gen_load_fpr64(ctx, fp0, fs);
11714 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11715 gen_store_fpr64(ctx, fp0, fd);
11716 tcg_temp_free_i64(fp0);
11718 break;
11719 case OPC_RSQRT_D:
11720 check_cp1_registers(ctx, fs | fd);
11722 TCGv_i64 fp0 = tcg_temp_new_i64();
11724 gen_load_fpr64(ctx, fp0, fs);
11725 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11726 gen_store_fpr64(ctx, fp0, fd);
11727 tcg_temp_free_i64(fp0);
11729 break;
11730 case OPC_MADDF_D:
11731 check_insn(ctx, ISA_MIPS32R6);
11733 TCGv_i64 fp0 = tcg_temp_new_i64();
11734 TCGv_i64 fp1 = tcg_temp_new_i64();
11735 TCGv_i64 fp2 = tcg_temp_new_i64();
11736 gen_load_fpr64(ctx, fp0, fs);
11737 gen_load_fpr64(ctx, fp1, ft);
11738 gen_load_fpr64(ctx, fp2, fd);
11739 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11740 gen_store_fpr64(ctx, fp2, fd);
11741 tcg_temp_free_i64(fp2);
11742 tcg_temp_free_i64(fp1);
11743 tcg_temp_free_i64(fp0);
11745 break;
11746 case OPC_MSUBF_D:
11747 check_insn(ctx, ISA_MIPS32R6);
11749 TCGv_i64 fp0 = tcg_temp_new_i64();
11750 TCGv_i64 fp1 = tcg_temp_new_i64();
11751 TCGv_i64 fp2 = tcg_temp_new_i64();
11752 gen_load_fpr64(ctx, fp0, fs);
11753 gen_load_fpr64(ctx, fp1, ft);
11754 gen_load_fpr64(ctx, fp2, fd);
11755 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11756 gen_store_fpr64(ctx, fp2, fd);
11757 tcg_temp_free_i64(fp2);
11758 tcg_temp_free_i64(fp1);
11759 tcg_temp_free_i64(fp0);
11761 break;
11762 case OPC_RINT_D:
11763 check_insn(ctx, ISA_MIPS32R6);
11765 TCGv_i64 fp0 = tcg_temp_new_i64();
11766 gen_load_fpr64(ctx, fp0, fs);
11767 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11768 gen_store_fpr64(ctx, fp0, fd);
11769 tcg_temp_free_i64(fp0);
11771 break;
11772 case OPC_CLASS_D:
11773 check_insn(ctx, ISA_MIPS32R6);
11775 TCGv_i64 fp0 = tcg_temp_new_i64();
11776 gen_load_fpr64(ctx, fp0, fs);
11777 gen_helper_float_class_d(fp0, cpu_env, fp0);
11778 gen_store_fpr64(ctx, fp0, fd);
11779 tcg_temp_free_i64(fp0);
11781 break;
11782 case OPC_MIN_D: /* OPC_RECIP2_D */
11783 if (ctx->insn_flags & ISA_MIPS32R6) {
11784 /* OPC_MIN_D */
11785 TCGv_i64 fp0 = tcg_temp_new_i64();
11786 TCGv_i64 fp1 = tcg_temp_new_i64();
11787 gen_load_fpr64(ctx, fp0, fs);
11788 gen_load_fpr64(ctx, fp1, ft);
11789 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11790 gen_store_fpr64(ctx, fp1, fd);
11791 tcg_temp_free_i64(fp1);
11792 tcg_temp_free_i64(fp0);
11793 } else {
11794 /* OPC_RECIP2_D */
11795 check_cp1_64bitmode(ctx);
11797 TCGv_i64 fp0 = tcg_temp_new_i64();
11798 TCGv_i64 fp1 = tcg_temp_new_i64();
11800 gen_load_fpr64(ctx, fp0, fs);
11801 gen_load_fpr64(ctx, fp1, ft);
11802 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11803 tcg_temp_free_i64(fp1);
11804 gen_store_fpr64(ctx, fp0, fd);
11805 tcg_temp_free_i64(fp0);
11808 break;
11809 case OPC_MINA_D: /* OPC_RECIP1_D */
11810 if (ctx->insn_flags & ISA_MIPS32R6) {
11811 /* OPC_MINA_D */
11812 TCGv_i64 fp0 = tcg_temp_new_i64();
11813 TCGv_i64 fp1 = tcg_temp_new_i64();
11814 gen_load_fpr64(ctx, fp0, fs);
11815 gen_load_fpr64(ctx, fp1, ft);
11816 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11817 gen_store_fpr64(ctx, fp1, fd);
11818 tcg_temp_free_i64(fp1);
11819 tcg_temp_free_i64(fp0);
11820 } else {
11821 /* OPC_RECIP1_D */
11822 check_cp1_64bitmode(ctx);
11824 TCGv_i64 fp0 = tcg_temp_new_i64();
11826 gen_load_fpr64(ctx, fp0, fs);
11827 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11828 gen_store_fpr64(ctx, fp0, fd);
11829 tcg_temp_free_i64(fp0);
11832 break;
11833 case OPC_MAX_D: /* OPC_RSQRT1_D */
11834 if (ctx->insn_flags & ISA_MIPS32R6) {
11835 /* OPC_MAX_D */
11836 TCGv_i64 fp0 = tcg_temp_new_i64();
11837 TCGv_i64 fp1 = tcg_temp_new_i64();
11838 gen_load_fpr64(ctx, fp0, fs);
11839 gen_load_fpr64(ctx, fp1, ft);
11840 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11841 gen_store_fpr64(ctx, fp1, fd);
11842 tcg_temp_free_i64(fp1);
11843 tcg_temp_free_i64(fp0);
11844 } else {
11845 /* OPC_RSQRT1_D */
11846 check_cp1_64bitmode(ctx);
11848 TCGv_i64 fp0 = tcg_temp_new_i64();
11850 gen_load_fpr64(ctx, fp0, fs);
11851 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11852 gen_store_fpr64(ctx, fp0, fd);
11853 tcg_temp_free_i64(fp0);
11856 break;
11857 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11858 if (ctx->insn_flags & ISA_MIPS32R6) {
11859 /* OPC_MAXA_D */
11860 TCGv_i64 fp0 = tcg_temp_new_i64();
11861 TCGv_i64 fp1 = tcg_temp_new_i64();
11862 gen_load_fpr64(ctx, fp0, fs);
11863 gen_load_fpr64(ctx, fp1, ft);
11864 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11865 gen_store_fpr64(ctx, fp1, fd);
11866 tcg_temp_free_i64(fp1);
11867 tcg_temp_free_i64(fp0);
11868 } else {
11869 /* OPC_RSQRT2_D */
11870 check_cp1_64bitmode(ctx);
11872 TCGv_i64 fp0 = tcg_temp_new_i64();
11873 TCGv_i64 fp1 = tcg_temp_new_i64();
11875 gen_load_fpr64(ctx, fp0, fs);
11876 gen_load_fpr64(ctx, fp1, ft);
11877 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11878 tcg_temp_free_i64(fp1);
11879 gen_store_fpr64(ctx, fp0, fd);
11880 tcg_temp_free_i64(fp0);
11883 break;
11884 case OPC_CMP_F_D:
11885 case OPC_CMP_UN_D:
11886 case OPC_CMP_EQ_D:
11887 case OPC_CMP_UEQ_D:
11888 case OPC_CMP_OLT_D:
11889 case OPC_CMP_ULT_D:
11890 case OPC_CMP_OLE_D:
11891 case OPC_CMP_ULE_D:
11892 case OPC_CMP_SF_D:
11893 case OPC_CMP_NGLE_D:
11894 case OPC_CMP_SEQ_D:
11895 case OPC_CMP_NGL_D:
11896 case OPC_CMP_LT_D:
11897 case OPC_CMP_NGE_D:
11898 case OPC_CMP_LE_D:
11899 case OPC_CMP_NGT_D:
11900 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11901 if (ctx->opcode & (1 << 6)) {
11902 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11903 } else {
11904 gen_cmp_d(ctx, func-48, ft, fs, cc);
11906 break;
11907 case OPC_CVT_S_D:
11908 check_cp1_registers(ctx, fs);
11910 TCGv_i32 fp32 = tcg_temp_new_i32();
11911 TCGv_i64 fp64 = tcg_temp_new_i64();
11913 gen_load_fpr64(ctx, fp64, fs);
11914 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11915 tcg_temp_free_i64(fp64);
11916 gen_store_fpr32(ctx, fp32, fd);
11917 tcg_temp_free_i32(fp32);
11919 break;
11920 case OPC_CVT_W_D:
11921 check_cp1_registers(ctx, fs);
11923 TCGv_i32 fp32 = tcg_temp_new_i32();
11924 TCGv_i64 fp64 = tcg_temp_new_i64();
11926 gen_load_fpr64(ctx, fp64, fs);
11927 if (ctx->nan2008) {
11928 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11929 } else {
11930 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11932 tcg_temp_free_i64(fp64);
11933 gen_store_fpr32(ctx, fp32, fd);
11934 tcg_temp_free_i32(fp32);
11936 break;
11937 case OPC_CVT_L_D:
11938 check_cp1_64bitmode(ctx);
11940 TCGv_i64 fp0 = tcg_temp_new_i64();
11942 gen_load_fpr64(ctx, fp0, fs);
11943 if (ctx->nan2008) {
11944 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11945 } else {
11946 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11948 gen_store_fpr64(ctx, fp0, fd);
11949 tcg_temp_free_i64(fp0);
11951 break;
11952 case OPC_CVT_S_W:
11954 TCGv_i32 fp0 = tcg_temp_new_i32();
11956 gen_load_fpr32(ctx, fp0, fs);
11957 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11958 gen_store_fpr32(ctx, fp0, fd);
11959 tcg_temp_free_i32(fp0);
11961 break;
11962 case OPC_CVT_D_W:
11963 check_cp1_registers(ctx, fd);
11965 TCGv_i32 fp32 = tcg_temp_new_i32();
11966 TCGv_i64 fp64 = tcg_temp_new_i64();
11968 gen_load_fpr32(ctx, fp32, fs);
11969 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11970 tcg_temp_free_i32(fp32);
11971 gen_store_fpr64(ctx, fp64, fd);
11972 tcg_temp_free_i64(fp64);
11974 break;
11975 case OPC_CVT_S_L:
11976 check_cp1_64bitmode(ctx);
11978 TCGv_i32 fp32 = tcg_temp_new_i32();
11979 TCGv_i64 fp64 = tcg_temp_new_i64();
11981 gen_load_fpr64(ctx, fp64, fs);
11982 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11983 tcg_temp_free_i64(fp64);
11984 gen_store_fpr32(ctx, fp32, fd);
11985 tcg_temp_free_i32(fp32);
11987 break;
11988 case OPC_CVT_D_L:
11989 check_cp1_64bitmode(ctx);
11991 TCGv_i64 fp0 = tcg_temp_new_i64();
11993 gen_load_fpr64(ctx, fp0, fs);
11994 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11995 gen_store_fpr64(ctx, fp0, fd);
11996 tcg_temp_free_i64(fp0);
11998 break;
11999 case OPC_CVT_PS_PW:
12000 check_ps(ctx);
12002 TCGv_i64 fp0 = tcg_temp_new_i64();
12004 gen_load_fpr64(ctx, fp0, fs);
12005 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12006 gen_store_fpr64(ctx, fp0, fd);
12007 tcg_temp_free_i64(fp0);
12009 break;
12010 case OPC_ADD_PS:
12011 check_ps(ctx);
12013 TCGv_i64 fp0 = tcg_temp_new_i64();
12014 TCGv_i64 fp1 = tcg_temp_new_i64();
12016 gen_load_fpr64(ctx, fp0, fs);
12017 gen_load_fpr64(ctx, fp1, ft);
12018 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12019 tcg_temp_free_i64(fp1);
12020 gen_store_fpr64(ctx, fp0, fd);
12021 tcg_temp_free_i64(fp0);
12023 break;
12024 case OPC_SUB_PS:
12025 check_ps(ctx);
12027 TCGv_i64 fp0 = tcg_temp_new_i64();
12028 TCGv_i64 fp1 = tcg_temp_new_i64();
12030 gen_load_fpr64(ctx, fp0, fs);
12031 gen_load_fpr64(ctx, fp1, ft);
12032 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12033 tcg_temp_free_i64(fp1);
12034 gen_store_fpr64(ctx, fp0, fd);
12035 tcg_temp_free_i64(fp0);
12037 break;
12038 case OPC_MUL_PS:
12039 check_ps(ctx);
12041 TCGv_i64 fp0 = tcg_temp_new_i64();
12042 TCGv_i64 fp1 = tcg_temp_new_i64();
12044 gen_load_fpr64(ctx, fp0, fs);
12045 gen_load_fpr64(ctx, fp1, ft);
12046 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12047 tcg_temp_free_i64(fp1);
12048 gen_store_fpr64(ctx, fp0, fd);
12049 tcg_temp_free_i64(fp0);
12051 break;
12052 case OPC_ABS_PS:
12053 check_ps(ctx);
12055 TCGv_i64 fp0 = tcg_temp_new_i64();
12057 gen_load_fpr64(ctx, fp0, fs);
12058 gen_helper_float_abs_ps(fp0, fp0);
12059 gen_store_fpr64(ctx, fp0, fd);
12060 tcg_temp_free_i64(fp0);
12062 break;
12063 case OPC_MOV_PS:
12064 check_ps(ctx);
12066 TCGv_i64 fp0 = tcg_temp_new_i64();
12068 gen_load_fpr64(ctx, fp0, fs);
12069 gen_store_fpr64(ctx, fp0, fd);
12070 tcg_temp_free_i64(fp0);
12072 break;
12073 case OPC_NEG_PS:
12074 check_ps(ctx);
12076 TCGv_i64 fp0 = tcg_temp_new_i64();
12078 gen_load_fpr64(ctx, fp0, fs);
12079 gen_helper_float_chs_ps(fp0, fp0);
12080 gen_store_fpr64(ctx, fp0, fd);
12081 tcg_temp_free_i64(fp0);
12083 break;
12084 case OPC_MOVCF_PS:
12085 check_ps(ctx);
12086 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12087 break;
12088 case OPC_MOVZ_PS:
12089 check_ps(ctx);
12091 TCGLabel *l1 = gen_new_label();
12092 TCGv_i64 fp0;
12094 if (ft != 0)
12095 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12096 fp0 = tcg_temp_new_i64();
12097 gen_load_fpr64(ctx, fp0, fs);
12098 gen_store_fpr64(ctx, fp0, fd);
12099 tcg_temp_free_i64(fp0);
12100 gen_set_label(l1);
12102 break;
12103 case OPC_MOVN_PS:
12104 check_ps(ctx);
12106 TCGLabel *l1 = gen_new_label();
12107 TCGv_i64 fp0;
12109 if (ft != 0) {
12110 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12111 fp0 = tcg_temp_new_i64();
12112 gen_load_fpr64(ctx, fp0, fs);
12113 gen_store_fpr64(ctx, fp0, fd);
12114 tcg_temp_free_i64(fp0);
12115 gen_set_label(l1);
12118 break;
12119 case OPC_ADDR_PS:
12120 check_ps(ctx);
12122 TCGv_i64 fp0 = tcg_temp_new_i64();
12123 TCGv_i64 fp1 = tcg_temp_new_i64();
12125 gen_load_fpr64(ctx, fp0, ft);
12126 gen_load_fpr64(ctx, fp1, fs);
12127 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12128 tcg_temp_free_i64(fp1);
12129 gen_store_fpr64(ctx, fp0, fd);
12130 tcg_temp_free_i64(fp0);
12132 break;
12133 case OPC_MULR_PS:
12134 check_ps(ctx);
12136 TCGv_i64 fp0 = tcg_temp_new_i64();
12137 TCGv_i64 fp1 = tcg_temp_new_i64();
12139 gen_load_fpr64(ctx, fp0, ft);
12140 gen_load_fpr64(ctx, fp1, fs);
12141 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12142 tcg_temp_free_i64(fp1);
12143 gen_store_fpr64(ctx, fp0, fd);
12144 tcg_temp_free_i64(fp0);
12146 break;
12147 case OPC_RECIP2_PS:
12148 check_ps(ctx);
12150 TCGv_i64 fp0 = tcg_temp_new_i64();
12151 TCGv_i64 fp1 = tcg_temp_new_i64();
12153 gen_load_fpr64(ctx, fp0, fs);
12154 gen_load_fpr64(ctx, fp1, ft);
12155 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12156 tcg_temp_free_i64(fp1);
12157 gen_store_fpr64(ctx, fp0, fd);
12158 tcg_temp_free_i64(fp0);
12160 break;
12161 case OPC_RECIP1_PS:
12162 check_ps(ctx);
12164 TCGv_i64 fp0 = tcg_temp_new_i64();
12166 gen_load_fpr64(ctx, fp0, fs);
12167 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12168 gen_store_fpr64(ctx, fp0, fd);
12169 tcg_temp_free_i64(fp0);
12171 break;
12172 case OPC_RSQRT1_PS:
12173 check_ps(ctx);
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12177 gen_load_fpr64(ctx, fp0, fs);
12178 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12179 gen_store_fpr64(ctx, fp0, fd);
12180 tcg_temp_free_i64(fp0);
12182 break;
12183 case OPC_RSQRT2_PS:
12184 check_ps(ctx);
12186 TCGv_i64 fp0 = tcg_temp_new_i64();
12187 TCGv_i64 fp1 = tcg_temp_new_i64();
12189 gen_load_fpr64(ctx, fp0, fs);
12190 gen_load_fpr64(ctx, fp1, ft);
12191 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12192 tcg_temp_free_i64(fp1);
12193 gen_store_fpr64(ctx, fp0, fd);
12194 tcg_temp_free_i64(fp0);
12196 break;
12197 case OPC_CVT_S_PU:
12198 check_cp1_64bitmode(ctx);
12200 TCGv_i32 fp0 = tcg_temp_new_i32();
12202 gen_load_fpr32h(ctx, fp0, fs);
12203 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12204 gen_store_fpr32(ctx, fp0, fd);
12205 tcg_temp_free_i32(fp0);
12207 break;
12208 case OPC_CVT_PW_PS:
12209 check_ps(ctx);
12211 TCGv_i64 fp0 = tcg_temp_new_i64();
12213 gen_load_fpr64(ctx, fp0, fs);
12214 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12215 gen_store_fpr64(ctx, fp0, fd);
12216 tcg_temp_free_i64(fp0);
12218 break;
12219 case OPC_CVT_S_PL:
12220 check_cp1_64bitmode(ctx);
12222 TCGv_i32 fp0 = tcg_temp_new_i32();
12224 gen_load_fpr32(ctx, fp0, fs);
12225 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12226 gen_store_fpr32(ctx, fp0, fd);
12227 tcg_temp_free_i32(fp0);
12229 break;
12230 case OPC_PLL_PS:
12231 check_ps(ctx);
12233 TCGv_i32 fp0 = tcg_temp_new_i32();
12234 TCGv_i32 fp1 = tcg_temp_new_i32();
12236 gen_load_fpr32(ctx, fp0, fs);
12237 gen_load_fpr32(ctx, fp1, ft);
12238 gen_store_fpr32h(ctx, fp0, fd);
12239 gen_store_fpr32(ctx, fp1, fd);
12240 tcg_temp_free_i32(fp0);
12241 tcg_temp_free_i32(fp1);
12243 break;
12244 case OPC_PLU_PS:
12245 check_ps(ctx);
12247 TCGv_i32 fp0 = tcg_temp_new_i32();
12248 TCGv_i32 fp1 = tcg_temp_new_i32();
12250 gen_load_fpr32(ctx, fp0, fs);
12251 gen_load_fpr32h(ctx, fp1, ft);
12252 gen_store_fpr32(ctx, fp1, fd);
12253 gen_store_fpr32h(ctx, fp0, fd);
12254 tcg_temp_free_i32(fp0);
12255 tcg_temp_free_i32(fp1);
12257 break;
12258 case OPC_PUL_PS:
12259 check_ps(ctx);
12261 TCGv_i32 fp0 = tcg_temp_new_i32();
12262 TCGv_i32 fp1 = tcg_temp_new_i32();
12264 gen_load_fpr32h(ctx, fp0, fs);
12265 gen_load_fpr32(ctx, fp1, ft);
12266 gen_store_fpr32(ctx, fp1, fd);
12267 gen_store_fpr32h(ctx, fp0, fd);
12268 tcg_temp_free_i32(fp0);
12269 tcg_temp_free_i32(fp1);
12271 break;
12272 case OPC_PUU_PS:
12273 check_ps(ctx);
12275 TCGv_i32 fp0 = tcg_temp_new_i32();
12276 TCGv_i32 fp1 = tcg_temp_new_i32();
12278 gen_load_fpr32h(ctx, fp0, fs);
12279 gen_load_fpr32h(ctx, fp1, ft);
12280 gen_store_fpr32(ctx, fp1, fd);
12281 gen_store_fpr32h(ctx, fp0, fd);
12282 tcg_temp_free_i32(fp0);
12283 tcg_temp_free_i32(fp1);
12285 break;
12286 case OPC_CMP_F_PS:
12287 case OPC_CMP_UN_PS:
12288 case OPC_CMP_EQ_PS:
12289 case OPC_CMP_UEQ_PS:
12290 case OPC_CMP_OLT_PS:
12291 case OPC_CMP_ULT_PS:
12292 case OPC_CMP_OLE_PS:
12293 case OPC_CMP_ULE_PS:
12294 case OPC_CMP_SF_PS:
12295 case OPC_CMP_NGLE_PS:
12296 case OPC_CMP_SEQ_PS:
12297 case OPC_CMP_NGL_PS:
12298 case OPC_CMP_LT_PS:
12299 case OPC_CMP_NGE_PS:
12300 case OPC_CMP_LE_PS:
12301 case OPC_CMP_NGT_PS:
12302 if (ctx->opcode & (1 << 6)) {
12303 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12304 } else {
12305 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12307 break;
12308 default:
12309 MIPS_INVAL("farith");
12310 generate_exception_end(ctx, EXCP_RI);
12311 return;
12315 /* Coprocessor 3 (FPU) */
12316 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12317 int fd, int fs, int base, int index)
12319 TCGv t0 = tcg_temp_new();
12321 if (base == 0) {
12322 gen_load_gpr(t0, index);
12323 } else if (index == 0) {
12324 gen_load_gpr(t0, base);
12325 } else {
12326 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12328 /* Don't do NOP if destination is zero: we must perform the actual
12329 memory access. */
12330 switch (opc) {
12331 case OPC_LWXC1:
12332 check_cop1x(ctx);
12334 TCGv_i32 fp0 = tcg_temp_new_i32();
12336 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12337 tcg_gen_trunc_tl_i32(fp0, t0);
12338 gen_store_fpr32(ctx, fp0, fd);
12339 tcg_temp_free_i32(fp0);
12341 break;
12342 case OPC_LDXC1:
12343 check_cop1x(ctx);
12344 check_cp1_registers(ctx, fd);
12346 TCGv_i64 fp0 = tcg_temp_new_i64();
12347 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12348 gen_store_fpr64(ctx, fp0, fd);
12349 tcg_temp_free_i64(fp0);
12351 break;
12352 case OPC_LUXC1:
12353 check_cp1_64bitmode(ctx);
12354 tcg_gen_andi_tl(t0, t0, ~0x7);
12356 TCGv_i64 fp0 = tcg_temp_new_i64();
12358 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12359 gen_store_fpr64(ctx, fp0, fd);
12360 tcg_temp_free_i64(fp0);
12362 break;
12363 case OPC_SWXC1:
12364 check_cop1x(ctx);
12366 TCGv_i32 fp0 = tcg_temp_new_i32();
12367 gen_load_fpr32(ctx, fp0, fs);
12368 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12369 tcg_temp_free_i32(fp0);
12371 break;
12372 case OPC_SDXC1:
12373 check_cop1x(ctx);
12374 check_cp1_registers(ctx, fs);
12376 TCGv_i64 fp0 = tcg_temp_new_i64();
12377 gen_load_fpr64(ctx, fp0, fs);
12378 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12379 tcg_temp_free_i64(fp0);
12381 break;
12382 case OPC_SUXC1:
12383 check_cp1_64bitmode(ctx);
12384 tcg_gen_andi_tl(t0, t0, ~0x7);
12386 TCGv_i64 fp0 = tcg_temp_new_i64();
12387 gen_load_fpr64(ctx, fp0, fs);
12388 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12389 tcg_temp_free_i64(fp0);
12391 break;
12393 tcg_temp_free(t0);
12396 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12397 int fd, int fr, int fs, int ft)
12399 switch (opc) {
12400 case OPC_ALNV_PS:
12401 check_ps(ctx);
12403 TCGv t0 = tcg_temp_local_new();
12404 TCGv_i32 fp = tcg_temp_new_i32();
12405 TCGv_i32 fph = tcg_temp_new_i32();
12406 TCGLabel *l1 = gen_new_label();
12407 TCGLabel *l2 = gen_new_label();
12409 gen_load_gpr(t0, fr);
12410 tcg_gen_andi_tl(t0, t0, 0x7);
12412 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12413 gen_load_fpr32(ctx, fp, fs);
12414 gen_load_fpr32h(ctx, fph, fs);
12415 gen_store_fpr32(ctx, fp, fd);
12416 gen_store_fpr32h(ctx, fph, fd);
12417 tcg_gen_br(l2);
12418 gen_set_label(l1);
12419 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12420 tcg_temp_free(t0);
12421 #ifdef TARGET_WORDS_BIGENDIAN
12422 gen_load_fpr32(ctx, fp, fs);
12423 gen_load_fpr32h(ctx, fph, ft);
12424 gen_store_fpr32h(ctx, fp, fd);
12425 gen_store_fpr32(ctx, fph, fd);
12426 #else
12427 gen_load_fpr32h(ctx, fph, fs);
12428 gen_load_fpr32(ctx, fp, ft);
12429 gen_store_fpr32(ctx, fph, fd);
12430 gen_store_fpr32h(ctx, fp, fd);
12431 #endif
12432 gen_set_label(l2);
12433 tcg_temp_free_i32(fp);
12434 tcg_temp_free_i32(fph);
12436 break;
12437 case OPC_MADD_S:
12438 check_cop1x(ctx);
12440 TCGv_i32 fp0 = tcg_temp_new_i32();
12441 TCGv_i32 fp1 = tcg_temp_new_i32();
12442 TCGv_i32 fp2 = tcg_temp_new_i32();
12444 gen_load_fpr32(ctx, fp0, fs);
12445 gen_load_fpr32(ctx, fp1, ft);
12446 gen_load_fpr32(ctx, fp2, fr);
12447 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12448 tcg_temp_free_i32(fp0);
12449 tcg_temp_free_i32(fp1);
12450 gen_store_fpr32(ctx, fp2, fd);
12451 tcg_temp_free_i32(fp2);
12453 break;
12454 case OPC_MADD_D:
12455 check_cop1x(ctx);
12456 check_cp1_registers(ctx, fd | fs | ft | fr);
12458 TCGv_i64 fp0 = tcg_temp_new_i64();
12459 TCGv_i64 fp1 = tcg_temp_new_i64();
12460 TCGv_i64 fp2 = tcg_temp_new_i64();
12462 gen_load_fpr64(ctx, fp0, fs);
12463 gen_load_fpr64(ctx, fp1, ft);
12464 gen_load_fpr64(ctx, fp2, fr);
12465 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12466 tcg_temp_free_i64(fp0);
12467 tcg_temp_free_i64(fp1);
12468 gen_store_fpr64(ctx, fp2, fd);
12469 tcg_temp_free_i64(fp2);
12471 break;
12472 case OPC_MADD_PS:
12473 check_ps(ctx);
12475 TCGv_i64 fp0 = tcg_temp_new_i64();
12476 TCGv_i64 fp1 = tcg_temp_new_i64();
12477 TCGv_i64 fp2 = tcg_temp_new_i64();
12479 gen_load_fpr64(ctx, fp0, fs);
12480 gen_load_fpr64(ctx, fp1, ft);
12481 gen_load_fpr64(ctx, fp2, fr);
12482 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12483 tcg_temp_free_i64(fp0);
12484 tcg_temp_free_i64(fp1);
12485 gen_store_fpr64(ctx, fp2, fd);
12486 tcg_temp_free_i64(fp2);
12488 break;
12489 case OPC_MSUB_S:
12490 check_cop1x(ctx);
12492 TCGv_i32 fp0 = tcg_temp_new_i32();
12493 TCGv_i32 fp1 = tcg_temp_new_i32();
12494 TCGv_i32 fp2 = tcg_temp_new_i32();
12496 gen_load_fpr32(ctx, fp0, fs);
12497 gen_load_fpr32(ctx, fp1, ft);
12498 gen_load_fpr32(ctx, fp2, fr);
12499 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12500 tcg_temp_free_i32(fp0);
12501 tcg_temp_free_i32(fp1);
12502 gen_store_fpr32(ctx, fp2, fd);
12503 tcg_temp_free_i32(fp2);
12505 break;
12506 case OPC_MSUB_D:
12507 check_cop1x(ctx);
12508 check_cp1_registers(ctx, fd | fs | ft | fr);
12510 TCGv_i64 fp0 = tcg_temp_new_i64();
12511 TCGv_i64 fp1 = tcg_temp_new_i64();
12512 TCGv_i64 fp2 = tcg_temp_new_i64();
12514 gen_load_fpr64(ctx, fp0, fs);
12515 gen_load_fpr64(ctx, fp1, ft);
12516 gen_load_fpr64(ctx, fp2, fr);
12517 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12518 tcg_temp_free_i64(fp0);
12519 tcg_temp_free_i64(fp1);
12520 gen_store_fpr64(ctx, fp2, fd);
12521 tcg_temp_free_i64(fp2);
12523 break;
12524 case OPC_MSUB_PS:
12525 check_ps(ctx);
12527 TCGv_i64 fp0 = tcg_temp_new_i64();
12528 TCGv_i64 fp1 = tcg_temp_new_i64();
12529 TCGv_i64 fp2 = tcg_temp_new_i64();
12531 gen_load_fpr64(ctx, fp0, fs);
12532 gen_load_fpr64(ctx, fp1, ft);
12533 gen_load_fpr64(ctx, fp2, fr);
12534 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12535 tcg_temp_free_i64(fp0);
12536 tcg_temp_free_i64(fp1);
12537 gen_store_fpr64(ctx, fp2, fd);
12538 tcg_temp_free_i64(fp2);
12540 break;
12541 case OPC_NMADD_S:
12542 check_cop1x(ctx);
12544 TCGv_i32 fp0 = tcg_temp_new_i32();
12545 TCGv_i32 fp1 = tcg_temp_new_i32();
12546 TCGv_i32 fp2 = tcg_temp_new_i32();
12548 gen_load_fpr32(ctx, fp0, fs);
12549 gen_load_fpr32(ctx, fp1, ft);
12550 gen_load_fpr32(ctx, fp2, fr);
12551 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12552 tcg_temp_free_i32(fp0);
12553 tcg_temp_free_i32(fp1);
12554 gen_store_fpr32(ctx, fp2, fd);
12555 tcg_temp_free_i32(fp2);
12557 break;
12558 case OPC_NMADD_D:
12559 check_cop1x(ctx);
12560 check_cp1_registers(ctx, fd | fs | ft | fr);
12562 TCGv_i64 fp0 = tcg_temp_new_i64();
12563 TCGv_i64 fp1 = tcg_temp_new_i64();
12564 TCGv_i64 fp2 = tcg_temp_new_i64();
12566 gen_load_fpr64(ctx, fp0, fs);
12567 gen_load_fpr64(ctx, fp1, ft);
12568 gen_load_fpr64(ctx, fp2, fr);
12569 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12570 tcg_temp_free_i64(fp0);
12571 tcg_temp_free_i64(fp1);
12572 gen_store_fpr64(ctx, fp2, fd);
12573 tcg_temp_free_i64(fp2);
12575 break;
12576 case OPC_NMADD_PS:
12577 check_ps(ctx);
12579 TCGv_i64 fp0 = tcg_temp_new_i64();
12580 TCGv_i64 fp1 = tcg_temp_new_i64();
12581 TCGv_i64 fp2 = tcg_temp_new_i64();
12583 gen_load_fpr64(ctx, fp0, fs);
12584 gen_load_fpr64(ctx, fp1, ft);
12585 gen_load_fpr64(ctx, fp2, fr);
12586 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12587 tcg_temp_free_i64(fp0);
12588 tcg_temp_free_i64(fp1);
12589 gen_store_fpr64(ctx, fp2, fd);
12590 tcg_temp_free_i64(fp2);
12592 break;
12593 case OPC_NMSUB_S:
12594 check_cop1x(ctx);
12596 TCGv_i32 fp0 = tcg_temp_new_i32();
12597 TCGv_i32 fp1 = tcg_temp_new_i32();
12598 TCGv_i32 fp2 = tcg_temp_new_i32();
12600 gen_load_fpr32(ctx, fp0, fs);
12601 gen_load_fpr32(ctx, fp1, ft);
12602 gen_load_fpr32(ctx, fp2, fr);
12603 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12604 tcg_temp_free_i32(fp0);
12605 tcg_temp_free_i32(fp1);
12606 gen_store_fpr32(ctx, fp2, fd);
12607 tcg_temp_free_i32(fp2);
12609 break;
12610 case OPC_NMSUB_D:
12611 check_cop1x(ctx);
12612 check_cp1_registers(ctx, fd | fs | ft | fr);
12614 TCGv_i64 fp0 = tcg_temp_new_i64();
12615 TCGv_i64 fp1 = tcg_temp_new_i64();
12616 TCGv_i64 fp2 = tcg_temp_new_i64();
12618 gen_load_fpr64(ctx, fp0, fs);
12619 gen_load_fpr64(ctx, fp1, ft);
12620 gen_load_fpr64(ctx, fp2, fr);
12621 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12622 tcg_temp_free_i64(fp0);
12623 tcg_temp_free_i64(fp1);
12624 gen_store_fpr64(ctx, fp2, fd);
12625 tcg_temp_free_i64(fp2);
12627 break;
12628 case OPC_NMSUB_PS:
12629 check_ps(ctx);
12631 TCGv_i64 fp0 = tcg_temp_new_i64();
12632 TCGv_i64 fp1 = tcg_temp_new_i64();
12633 TCGv_i64 fp2 = tcg_temp_new_i64();
12635 gen_load_fpr64(ctx, fp0, fs);
12636 gen_load_fpr64(ctx, fp1, ft);
12637 gen_load_fpr64(ctx, fp2, fr);
12638 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12639 tcg_temp_free_i64(fp0);
12640 tcg_temp_free_i64(fp1);
12641 gen_store_fpr64(ctx, fp2, fd);
12642 tcg_temp_free_i64(fp2);
12644 break;
12645 default:
12646 MIPS_INVAL("flt3_arith");
12647 generate_exception_end(ctx, EXCP_RI);
12648 return;
12652 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12654 TCGv t0;
12656 #if !defined(CONFIG_USER_ONLY)
12657 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12658 Therefore only check the ISA in system mode. */
12659 check_insn(ctx, ISA_MIPS32R2);
12660 #endif
12661 t0 = tcg_temp_new();
12663 switch (rd) {
12664 case 0:
12665 gen_helper_rdhwr_cpunum(t0, cpu_env);
12666 gen_store_gpr(t0, rt);
12667 break;
12668 case 1:
12669 gen_helper_rdhwr_synci_step(t0, cpu_env);
12670 gen_store_gpr(t0, rt);
12671 break;
12672 case 2:
12673 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12674 gen_io_start();
12676 gen_helper_rdhwr_cc(t0, cpu_env);
12677 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12678 gen_io_end();
12680 gen_store_gpr(t0, rt);
12681 /* Break the TB to be able to take timer interrupts immediately
12682 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12683 we break completely out of translated code. */
12684 gen_save_pc(ctx->base.pc_next + 4);
12685 ctx->base.is_jmp = DISAS_EXIT;
12686 break;
12687 case 3:
12688 gen_helper_rdhwr_ccres(t0, cpu_env);
12689 gen_store_gpr(t0, rt);
12690 break;
12691 case 4:
12692 check_insn(ctx, ISA_MIPS32R6);
12693 if (sel != 0) {
12694 /* Performance counter registers are not implemented other than
12695 * control register 0.
12697 generate_exception(ctx, EXCP_RI);
12699 gen_helper_rdhwr_performance(t0, cpu_env);
12700 gen_store_gpr(t0, rt);
12701 break;
12702 case 5:
12703 check_insn(ctx, ISA_MIPS32R6);
12704 gen_helper_rdhwr_xnp(t0, cpu_env);
12705 gen_store_gpr(t0, rt);
12706 break;
12707 case 29:
12708 #if defined(CONFIG_USER_ONLY)
12709 tcg_gen_ld_tl(t0, cpu_env,
12710 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12711 gen_store_gpr(t0, rt);
12712 break;
12713 #else
12714 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12715 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12716 tcg_gen_ld_tl(t0, cpu_env,
12717 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12718 gen_store_gpr(t0, rt);
12719 } else {
12720 generate_exception_end(ctx, EXCP_RI);
12722 break;
12723 #endif
12724 default: /* Invalid */
12725 MIPS_INVAL("rdhwr");
12726 generate_exception_end(ctx, EXCP_RI);
12727 break;
12729 tcg_temp_free(t0);
12732 static inline void clear_branch_hflags(DisasContext *ctx)
12734 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12735 if (ctx->base.is_jmp == DISAS_NEXT) {
12736 save_cpu_state(ctx, 0);
12737 } else {
12738 /* it is not safe to save ctx->hflags as hflags may be changed
12739 in execution time by the instruction in delay / forbidden slot. */
12740 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12744 static void gen_branch(DisasContext *ctx, int insn_bytes)
12746 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12747 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12748 /* Branches completion */
12749 clear_branch_hflags(ctx);
12750 ctx->base.is_jmp = DISAS_NORETURN;
12751 /* FIXME: Need to clear can_do_io. */
12752 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12753 case MIPS_HFLAG_FBNSLOT:
12754 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12755 break;
12756 case MIPS_HFLAG_B:
12757 /* unconditional branch */
12758 if (proc_hflags & MIPS_HFLAG_BX) {
12759 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12761 gen_goto_tb(ctx, 0, ctx->btarget);
12762 break;
12763 case MIPS_HFLAG_BL:
12764 /* blikely taken case */
12765 gen_goto_tb(ctx, 0, ctx->btarget);
12766 break;
12767 case MIPS_HFLAG_BC:
12768 /* Conditional branch */
12770 TCGLabel *l1 = gen_new_label();
12772 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12773 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12774 gen_set_label(l1);
12775 gen_goto_tb(ctx, 0, ctx->btarget);
12777 break;
12778 case MIPS_HFLAG_BR:
12779 /* unconditional branch to register */
12780 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12781 TCGv t0 = tcg_temp_new();
12782 TCGv_i32 t1 = tcg_temp_new_i32();
12784 tcg_gen_andi_tl(t0, btarget, 0x1);
12785 tcg_gen_trunc_tl_i32(t1, t0);
12786 tcg_temp_free(t0);
12787 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12788 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12789 tcg_gen_or_i32(hflags, hflags, t1);
12790 tcg_temp_free_i32(t1);
12792 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12793 } else {
12794 tcg_gen_mov_tl(cpu_PC, btarget);
12796 if (ctx->base.singlestep_enabled) {
12797 save_cpu_state(ctx, 0);
12798 gen_helper_raise_exception_debug(cpu_env);
12800 tcg_gen_lookup_and_goto_ptr();
12801 break;
12802 default:
12803 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12804 abort();
12809 /* Compact Branches */
12810 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12811 int rs, int rt, int32_t offset)
12813 int bcond_compute = 0;
12814 TCGv t0 = tcg_temp_new();
12815 TCGv t1 = tcg_temp_new();
12816 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12818 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12819 #ifdef MIPS_DEBUG_DISAS
12820 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12821 "\n", ctx->base.pc_next);
12822 #endif
12823 generate_exception_end(ctx, EXCP_RI);
12824 goto out;
12827 /* Load needed operands and calculate btarget */
12828 switch (opc) {
12829 /* compact branch */
12830 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12831 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12832 gen_load_gpr(t0, rs);
12833 gen_load_gpr(t1, rt);
12834 bcond_compute = 1;
12835 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12836 if (rs <= rt && rs == 0) {
12837 /* OPC_BEQZALC, OPC_BNEZALC */
12838 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12840 break;
12841 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12842 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12843 gen_load_gpr(t0, rs);
12844 gen_load_gpr(t1, rt);
12845 bcond_compute = 1;
12846 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12847 break;
12848 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12849 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12850 if (rs == 0 || rs == rt) {
12851 /* OPC_BLEZALC, OPC_BGEZALC */
12852 /* OPC_BGTZALC, OPC_BLTZALC */
12853 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12855 gen_load_gpr(t0, rs);
12856 gen_load_gpr(t1, rt);
12857 bcond_compute = 1;
12858 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12859 break;
12860 case OPC_BC:
12861 case OPC_BALC:
12862 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12863 break;
12864 case OPC_BEQZC:
12865 case OPC_BNEZC:
12866 if (rs != 0) {
12867 /* OPC_BEQZC, OPC_BNEZC */
12868 gen_load_gpr(t0, rs);
12869 bcond_compute = 1;
12870 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12871 } else {
12872 /* OPC_JIC, OPC_JIALC */
12873 TCGv tbase = tcg_temp_new();
12874 TCGv toffset = tcg_temp_new();
12876 gen_load_gpr(tbase, rt);
12877 tcg_gen_movi_tl(toffset, offset);
12878 gen_op_addr_add(ctx, btarget, tbase, toffset);
12879 tcg_temp_free(tbase);
12880 tcg_temp_free(toffset);
12882 break;
12883 default:
12884 MIPS_INVAL("Compact branch/jump");
12885 generate_exception_end(ctx, EXCP_RI);
12886 goto out;
12889 if (bcond_compute == 0) {
12890 /* Uncoditional compact branch */
12891 switch (opc) {
12892 case OPC_JIALC:
12893 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12894 /* Fallthrough */
12895 case OPC_JIC:
12896 ctx->hflags |= MIPS_HFLAG_BR;
12897 break;
12898 case OPC_BALC:
12899 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12900 /* Fallthrough */
12901 case OPC_BC:
12902 ctx->hflags |= MIPS_HFLAG_B;
12903 break;
12904 default:
12905 MIPS_INVAL("Compact branch/jump");
12906 generate_exception_end(ctx, EXCP_RI);
12907 goto out;
12910 /* Generating branch here as compact branches don't have delay slot */
12911 gen_branch(ctx, 4);
12912 } else {
12913 /* Conditional compact branch */
12914 TCGLabel *fs = gen_new_label();
12915 save_cpu_state(ctx, 0);
12917 switch (opc) {
12918 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12919 if (rs == 0 && rt != 0) {
12920 /* OPC_BLEZALC */
12921 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12922 } else if (rs != 0 && rt != 0 && rs == rt) {
12923 /* OPC_BGEZALC */
12924 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12925 } else {
12926 /* OPC_BGEUC */
12927 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12929 break;
12930 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12931 if (rs == 0 && rt != 0) {
12932 /* OPC_BGTZALC */
12933 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12934 } else if (rs != 0 && rt != 0 && rs == rt) {
12935 /* OPC_BLTZALC */
12936 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12937 } else {
12938 /* OPC_BLTUC */
12939 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12941 break;
12942 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12943 if (rs == 0 && rt != 0) {
12944 /* OPC_BLEZC */
12945 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12946 } else if (rs != 0 && rt != 0 && rs == rt) {
12947 /* OPC_BGEZC */
12948 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12949 } else {
12950 /* OPC_BGEC */
12951 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12953 break;
12954 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12955 if (rs == 0 && rt != 0) {
12956 /* OPC_BGTZC */
12957 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12958 } else if (rs != 0 && rt != 0 && rs == rt) {
12959 /* OPC_BLTZC */
12960 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12961 } else {
12962 /* OPC_BLTC */
12963 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12965 break;
12966 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12967 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12968 if (rs >= rt) {
12969 /* OPC_BOVC, OPC_BNVC */
12970 TCGv t2 = tcg_temp_new();
12971 TCGv t3 = tcg_temp_new();
12972 TCGv t4 = tcg_temp_new();
12973 TCGv input_overflow = tcg_temp_new();
12975 gen_load_gpr(t0, rs);
12976 gen_load_gpr(t1, rt);
12977 tcg_gen_ext32s_tl(t2, t0);
12978 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12979 tcg_gen_ext32s_tl(t3, t1);
12980 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12981 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12983 tcg_gen_add_tl(t4, t2, t3);
12984 tcg_gen_ext32s_tl(t4, t4);
12985 tcg_gen_xor_tl(t2, t2, t3);
12986 tcg_gen_xor_tl(t3, t4, t3);
12987 tcg_gen_andc_tl(t2, t3, t2);
12988 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12989 tcg_gen_or_tl(t4, t4, input_overflow);
12990 if (opc == OPC_BOVC) {
12991 /* OPC_BOVC */
12992 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12993 } else {
12994 /* OPC_BNVC */
12995 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12997 tcg_temp_free(input_overflow);
12998 tcg_temp_free(t4);
12999 tcg_temp_free(t3);
13000 tcg_temp_free(t2);
13001 } else if (rs < rt && rs == 0) {
13002 /* OPC_BEQZALC, OPC_BNEZALC */
13003 if (opc == OPC_BEQZALC) {
13004 /* OPC_BEQZALC */
13005 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13006 } else {
13007 /* OPC_BNEZALC */
13008 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13010 } else {
13011 /* OPC_BEQC, OPC_BNEC */
13012 if (opc == OPC_BEQC) {
13013 /* OPC_BEQC */
13014 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13015 } else {
13016 /* OPC_BNEC */
13017 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13020 break;
13021 case OPC_BEQZC:
13022 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13023 break;
13024 case OPC_BNEZC:
13025 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13026 break;
13027 default:
13028 MIPS_INVAL("Compact conditional branch/jump");
13029 generate_exception_end(ctx, EXCP_RI);
13030 goto out;
13033 /* Generating branch here as compact branches don't have delay slot */
13034 gen_goto_tb(ctx, 1, ctx->btarget);
13035 gen_set_label(fs);
13037 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13040 out:
13041 tcg_temp_free(t0);
13042 tcg_temp_free(t1);
13045 /* ISA extensions (ASEs) */
13046 /* MIPS16 extension to MIPS32 */
13048 /* MIPS16 major opcodes */
13049 enum {
13050 M16_OPC_ADDIUSP = 0x00,
13051 M16_OPC_ADDIUPC = 0x01,
13052 M16_OPC_B = 0x02,
13053 M16_OPC_JAL = 0x03,
13054 M16_OPC_BEQZ = 0x04,
13055 M16_OPC_BNEQZ = 0x05,
13056 M16_OPC_SHIFT = 0x06,
13057 M16_OPC_LD = 0x07,
13058 M16_OPC_RRIA = 0x08,
13059 M16_OPC_ADDIU8 = 0x09,
13060 M16_OPC_SLTI = 0x0a,
13061 M16_OPC_SLTIU = 0x0b,
13062 M16_OPC_I8 = 0x0c,
13063 M16_OPC_LI = 0x0d,
13064 M16_OPC_CMPI = 0x0e,
13065 M16_OPC_SD = 0x0f,
13066 M16_OPC_LB = 0x10,
13067 M16_OPC_LH = 0x11,
13068 M16_OPC_LWSP = 0x12,
13069 M16_OPC_LW = 0x13,
13070 M16_OPC_LBU = 0x14,
13071 M16_OPC_LHU = 0x15,
13072 M16_OPC_LWPC = 0x16,
13073 M16_OPC_LWU = 0x17,
13074 M16_OPC_SB = 0x18,
13075 M16_OPC_SH = 0x19,
13076 M16_OPC_SWSP = 0x1a,
13077 M16_OPC_SW = 0x1b,
13078 M16_OPC_RRR = 0x1c,
13079 M16_OPC_RR = 0x1d,
13080 M16_OPC_EXTEND = 0x1e,
13081 M16_OPC_I64 = 0x1f
13084 /* I8 funct field */
13085 enum {
13086 I8_BTEQZ = 0x0,
13087 I8_BTNEZ = 0x1,
13088 I8_SWRASP = 0x2,
13089 I8_ADJSP = 0x3,
13090 I8_SVRS = 0x4,
13091 I8_MOV32R = 0x5,
13092 I8_MOVR32 = 0x7
13095 /* RRR f field */
13096 enum {
13097 RRR_DADDU = 0x0,
13098 RRR_ADDU = 0x1,
13099 RRR_DSUBU = 0x2,
13100 RRR_SUBU = 0x3
13103 /* RR funct field */
13104 enum {
13105 RR_JR = 0x00,
13106 RR_SDBBP = 0x01,
13107 RR_SLT = 0x02,
13108 RR_SLTU = 0x03,
13109 RR_SLLV = 0x04,
13110 RR_BREAK = 0x05,
13111 RR_SRLV = 0x06,
13112 RR_SRAV = 0x07,
13113 RR_DSRL = 0x08,
13114 RR_CMP = 0x0a,
13115 RR_NEG = 0x0b,
13116 RR_AND = 0x0c,
13117 RR_OR = 0x0d,
13118 RR_XOR = 0x0e,
13119 RR_NOT = 0x0f,
13120 RR_MFHI = 0x10,
13121 RR_CNVT = 0x11,
13122 RR_MFLO = 0x12,
13123 RR_DSRA = 0x13,
13124 RR_DSLLV = 0x14,
13125 RR_DSRLV = 0x16,
13126 RR_DSRAV = 0x17,
13127 RR_MULT = 0x18,
13128 RR_MULTU = 0x19,
13129 RR_DIV = 0x1a,
13130 RR_DIVU = 0x1b,
13131 RR_DMULT = 0x1c,
13132 RR_DMULTU = 0x1d,
13133 RR_DDIV = 0x1e,
13134 RR_DDIVU = 0x1f
13137 /* I64 funct field */
13138 enum {
13139 I64_LDSP = 0x0,
13140 I64_SDSP = 0x1,
13141 I64_SDRASP = 0x2,
13142 I64_DADJSP = 0x3,
13143 I64_LDPC = 0x4,
13144 I64_DADDIU5 = 0x5,
13145 I64_DADDIUPC = 0x6,
13146 I64_DADDIUSP = 0x7
13149 /* RR ry field for CNVT */
13150 enum {
13151 RR_RY_CNVT_ZEB = 0x0,
13152 RR_RY_CNVT_ZEH = 0x1,
13153 RR_RY_CNVT_ZEW = 0x2,
13154 RR_RY_CNVT_SEB = 0x4,
13155 RR_RY_CNVT_SEH = 0x5,
13156 RR_RY_CNVT_SEW = 0x6,
13159 static int xlat (int r)
13161 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13163 return map[r];
13166 static void gen_mips16_save (DisasContext *ctx,
13167 int xsregs, int aregs,
13168 int do_ra, int do_s0, int do_s1,
13169 int framesize)
13171 TCGv t0 = tcg_temp_new();
13172 TCGv t1 = tcg_temp_new();
13173 TCGv t2 = tcg_temp_new();
13174 int args, astatic;
13176 switch (aregs) {
13177 case 0:
13178 case 1:
13179 case 2:
13180 case 3:
13181 case 11:
13182 args = 0;
13183 break;
13184 case 4:
13185 case 5:
13186 case 6:
13187 case 7:
13188 args = 1;
13189 break;
13190 case 8:
13191 case 9:
13192 case 10:
13193 args = 2;
13194 break;
13195 case 12:
13196 case 13:
13197 args = 3;
13198 break;
13199 case 14:
13200 args = 4;
13201 break;
13202 default:
13203 generate_exception_end(ctx, EXCP_RI);
13204 return;
13207 switch (args) {
13208 case 4:
13209 gen_base_offset_addr(ctx, t0, 29, 12);
13210 gen_load_gpr(t1, 7);
13211 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13212 /* Fall through */
13213 case 3:
13214 gen_base_offset_addr(ctx, t0, 29, 8);
13215 gen_load_gpr(t1, 6);
13216 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13217 /* Fall through */
13218 case 2:
13219 gen_base_offset_addr(ctx, t0, 29, 4);
13220 gen_load_gpr(t1, 5);
13221 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13222 /* Fall through */
13223 case 1:
13224 gen_base_offset_addr(ctx, t0, 29, 0);
13225 gen_load_gpr(t1, 4);
13226 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13229 gen_load_gpr(t0, 29);
13231 #define DECR_AND_STORE(reg) do { \
13232 tcg_gen_movi_tl(t2, -4); \
13233 gen_op_addr_add(ctx, t0, t0, t2); \
13234 gen_load_gpr(t1, reg); \
13235 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13236 } while (0)
13238 if (do_ra) {
13239 DECR_AND_STORE(31);
13242 switch (xsregs) {
13243 case 7:
13244 DECR_AND_STORE(30);
13245 /* Fall through */
13246 case 6:
13247 DECR_AND_STORE(23);
13248 /* Fall through */
13249 case 5:
13250 DECR_AND_STORE(22);
13251 /* Fall through */
13252 case 4:
13253 DECR_AND_STORE(21);
13254 /* Fall through */
13255 case 3:
13256 DECR_AND_STORE(20);
13257 /* Fall through */
13258 case 2:
13259 DECR_AND_STORE(19);
13260 /* Fall through */
13261 case 1:
13262 DECR_AND_STORE(18);
13265 if (do_s1) {
13266 DECR_AND_STORE(17);
13268 if (do_s0) {
13269 DECR_AND_STORE(16);
13272 switch (aregs) {
13273 case 0:
13274 case 4:
13275 case 8:
13276 case 12:
13277 case 14:
13278 astatic = 0;
13279 break;
13280 case 1:
13281 case 5:
13282 case 9:
13283 case 13:
13284 astatic = 1;
13285 break;
13286 case 2:
13287 case 6:
13288 case 10:
13289 astatic = 2;
13290 break;
13291 case 3:
13292 case 7:
13293 astatic = 3;
13294 break;
13295 case 11:
13296 astatic = 4;
13297 break;
13298 default:
13299 generate_exception_end(ctx, EXCP_RI);
13300 return;
13303 if (astatic > 0) {
13304 DECR_AND_STORE(7);
13305 if (astatic > 1) {
13306 DECR_AND_STORE(6);
13307 if (astatic > 2) {
13308 DECR_AND_STORE(5);
13309 if (astatic > 3) {
13310 DECR_AND_STORE(4);
13315 #undef DECR_AND_STORE
13317 tcg_gen_movi_tl(t2, -framesize);
13318 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13319 tcg_temp_free(t0);
13320 tcg_temp_free(t1);
13321 tcg_temp_free(t2);
13324 static void gen_mips16_restore (DisasContext *ctx,
13325 int xsregs, int aregs,
13326 int do_ra, int do_s0, int do_s1,
13327 int framesize)
13329 int astatic;
13330 TCGv t0 = tcg_temp_new();
13331 TCGv t1 = tcg_temp_new();
13332 TCGv t2 = tcg_temp_new();
13334 tcg_gen_movi_tl(t2, framesize);
13335 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13337 #define DECR_AND_LOAD(reg) do { \
13338 tcg_gen_movi_tl(t2, -4); \
13339 gen_op_addr_add(ctx, t0, t0, t2); \
13340 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13341 gen_store_gpr(t1, reg); \
13342 } while (0)
13344 if (do_ra) {
13345 DECR_AND_LOAD(31);
13348 switch (xsregs) {
13349 case 7:
13350 DECR_AND_LOAD(30);
13351 /* Fall through */
13352 case 6:
13353 DECR_AND_LOAD(23);
13354 /* Fall through */
13355 case 5:
13356 DECR_AND_LOAD(22);
13357 /* Fall through */
13358 case 4:
13359 DECR_AND_LOAD(21);
13360 /* Fall through */
13361 case 3:
13362 DECR_AND_LOAD(20);
13363 /* Fall through */
13364 case 2:
13365 DECR_AND_LOAD(19);
13366 /* Fall through */
13367 case 1:
13368 DECR_AND_LOAD(18);
13371 if (do_s1) {
13372 DECR_AND_LOAD(17);
13374 if (do_s0) {
13375 DECR_AND_LOAD(16);
13378 switch (aregs) {
13379 case 0:
13380 case 4:
13381 case 8:
13382 case 12:
13383 case 14:
13384 astatic = 0;
13385 break;
13386 case 1:
13387 case 5:
13388 case 9:
13389 case 13:
13390 astatic = 1;
13391 break;
13392 case 2:
13393 case 6:
13394 case 10:
13395 astatic = 2;
13396 break;
13397 case 3:
13398 case 7:
13399 astatic = 3;
13400 break;
13401 case 11:
13402 astatic = 4;
13403 break;
13404 default:
13405 generate_exception_end(ctx, EXCP_RI);
13406 return;
13409 if (astatic > 0) {
13410 DECR_AND_LOAD(7);
13411 if (astatic > 1) {
13412 DECR_AND_LOAD(6);
13413 if (astatic > 2) {
13414 DECR_AND_LOAD(5);
13415 if (astatic > 3) {
13416 DECR_AND_LOAD(4);
13421 #undef DECR_AND_LOAD
13423 tcg_gen_movi_tl(t2, framesize);
13424 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13425 tcg_temp_free(t0);
13426 tcg_temp_free(t1);
13427 tcg_temp_free(t2);
13430 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13431 int is_64_bit, int extended)
13433 TCGv t0;
13435 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13436 generate_exception_end(ctx, EXCP_RI);
13437 return;
13440 t0 = tcg_temp_new();
13442 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13443 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13444 if (!is_64_bit) {
13445 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13448 tcg_temp_free(t0);
13451 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13452 int16_t offset)
13454 TCGv_i32 t0 = tcg_const_i32(op);
13455 TCGv t1 = tcg_temp_new();
13456 gen_base_offset_addr(ctx, t1, base, offset);
13457 gen_helper_cache(cpu_env, t1, t0);
13460 #if defined(TARGET_MIPS64)
13461 static void decode_i64_mips16 (DisasContext *ctx,
13462 int ry, int funct, int16_t offset,
13463 int extended)
13465 switch (funct) {
13466 case I64_LDSP:
13467 check_insn(ctx, ISA_MIPS3);
13468 check_mips_64(ctx);
13469 offset = extended ? offset : offset << 3;
13470 gen_ld(ctx, OPC_LD, ry, 29, offset);
13471 break;
13472 case I64_SDSP:
13473 check_insn(ctx, ISA_MIPS3);
13474 check_mips_64(ctx);
13475 offset = extended ? offset : offset << 3;
13476 gen_st(ctx, OPC_SD, ry, 29, offset);
13477 break;
13478 case I64_SDRASP:
13479 check_insn(ctx, ISA_MIPS3);
13480 check_mips_64(ctx);
13481 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13482 gen_st(ctx, OPC_SD, 31, 29, offset);
13483 break;
13484 case I64_DADJSP:
13485 check_insn(ctx, ISA_MIPS3);
13486 check_mips_64(ctx);
13487 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13488 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13489 break;
13490 case I64_LDPC:
13491 check_insn(ctx, ISA_MIPS3);
13492 check_mips_64(ctx);
13493 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13494 generate_exception_end(ctx, EXCP_RI);
13495 } else {
13496 offset = extended ? offset : offset << 3;
13497 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13499 break;
13500 case I64_DADDIU5:
13501 check_insn(ctx, ISA_MIPS3);
13502 check_mips_64(ctx);
13503 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13504 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13505 break;
13506 case I64_DADDIUPC:
13507 check_insn(ctx, ISA_MIPS3);
13508 check_mips_64(ctx);
13509 offset = extended ? offset : offset << 2;
13510 gen_addiupc(ctx, ry, offset, 1, extended);
13511 break;
13512 case I64_DADDIUSP:
13513 check_insn(ctx, ISA_MIPS3);
13514 check_mips_64(ctx);
13515 offset = extended ? offset : offset << 2;
13516 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13517 break;
13520 #endif
13522 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13524 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13525 int op, rx, ry, funct, sa;
13526 int16_t imm, offset;
13528 ctx->opcode = (ctx->opcode << 16) | extend;
13529 op = (ctx->opcode >> 11) & 0x1f;
13530 sa = (ctx->opcode >> 22) & 0x1f;
13531 funct = (ctx->opcode >> 8) & 0x7;
13532 rx = xlat((ctx->opcode >> 8) & 0x7);
13533 ry = xlat((ctx->opcode >> 5) & 0x7);
13534 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13535 | ((ctx->opcode >> 21) & 0x3f) << 5
13536 | (ctx->opcode & 0x1f));
13538 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13539 counterparts. */
13540 switch (op) {
13541 case M16_OPC_ADDIUSP:
13542 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13543 break;
13544 case M16_OPC_ADDIUPC:
13545 gen_addiupc(ctx, rx, imm, 0, 1);
13546 break;
13547 case M16_OPC_B:
13548 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13549 /* No delay slot, so just process as a normal instruction */
13550 break;
13551 case M16_OPC_BEQZ:
13552 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13553 /* No delay slot, so just process as a normal instruction */
13554 break;
13555 case M16_OPC_BNEQZ:
13556 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13557 /* No delay slot, so just process as a normal instruction */
13558 break;
13559 case M16_OPC_SHIFT:
13560 switch (ctx->opcode & 0x3) {
13561 case 0x0:
13562 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13563 break;
13564 case 0x1:
13565 #if defined(TARGET_MIPS64)
13566 check_mips_64(ctx);
13567 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13568 #else
13569 generate_exception_end(ctx, EXCP_RI);
13570 #endif
13571 break;
13572 case 0x2:
13573 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13574 break;
13575 case 0x3:
13576 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13577 break;
13579 break;
13580 #if defined(TARGET_MIPS64)
13581 case M16_OPC_LD:
13582 check_insn(ctx, ISA_MIPS3);
13583 check_mips_64(ctx);
13584 gen_ld(ctx, OPC_LD, ry, rx, offset);
13585 break;
13586 #endif
13587 case M16_OPC_RRIA:
13588 imm = ctx->opcode & 0xf;
13589 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13590 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13591 imm = (int16_t) (imm << 1) >> 1;
13592 if ((ctx->opcode >> 4) & 0x1) {
13593 #if defined(TARGET_MIPS64)
13594 check_mips_64(ctx);
13595 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13596 #else
13597 generate_exception_end(ctx, EXCP_RI);
13598 #endif
13599 } else {
13600 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13602 break;
13603 case M16_OPC_ADDIU8:
13604 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13605 break;
13606 case M16_OPC_SLTI:
13607 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13608 break;
13609 case M16_OPC_SLTIU:
13610 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13611 break;
13612 case M16_OPC_I8:
13613 switch (funct) {
13614 case I8_BTEQZ:
13615 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13616 break;
13617 case I8_BTNEZ:
13618 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13619 break;
13620 case I8_SWRASP:
13621 gen_st(ctx, OPC_SW, 31, 29, imm);
13622 break;
13623 case I8_ADJSP:
13624 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13625 break;
13626 case I8_SVRS:
13627 check_insn(ctx, ISA_MIPS32);
13629 int xsregs = (ctx->opcode >> 24) & 0x7;
13630 int aregs = (ctx->opcode >> 16) & 0xf;
13631 int do_ra = (ctx->opcode >> 6) & 0x1;
13632 int do_s0 = (ctx->opcode >> 5) & 0x1;
13633 int do_s1 = (ctx->opcode >> 4) & 0x1;
13634 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13635 | (ctx->opcode & 0xf)) << 3;
13637 if (ctx->opcode & (1 << 7)) {
13638 gen_mips16_save(ctx, xsregs, aregs,
13639 do_ra, do_s0, do_s1,
13640 framesize);
13641 } else {
13642 gen_mips16_restore(ctx, xsregs, aregs,
13643 do_ra, do_s0, do_s1,
13644 framesize);
13647 break;
13648 default:
13649 generate_exception_end(ctx, EXCP_RI);
13650 break;
13652 break;
13653 case M16_OPC_LI:
13654 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13655 break;
13656 case M16_OPC_CMPI:
13657 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13658 break;
13659 #if defined(TARGET_MIPS64)
13660 case M16_OPC_SD:
13661 check_insn(ctx, ISA_MIPS3);
13662 check_mips_64(ctx);
13663 gen_st(ctx, OPC_SD, ry, rx, offset);
13664 break;
13665 #endif
13666 case M16_OPC_LB:
13667 gen_ld(ctx, OPC_LB, ry, rx, offset);
13668 break;
13669 case M16_OPC_LH:
13670 gen_ld(ctx, OPC_LH, ry, rx, offset);
13671 break;
13672 case M16_OPC_LWSP:
13673 gen_ld(ctx, OPC_LW, rx, 29, offset);
13674 break;
13675 case M16_OPC_LW:
13676 gen_ld(ctx, OPC_LW, ry, rx, offset);
13677 break;
13678 case M16_OPC_LBU:
13679 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13680 break;
13681 case M16_OPC_LHU:
13682 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13683 break;
13684 case M16_OPC_LWPC:
13685 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13686 break;
13687 #if defined(TARGET_MIPS64)
13688 case M16_OPC_LWU:
13689 check_insn(ctx, ISA_MIPS3);
13690 check_mips_64(ctx);
13691 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13692 break;
13693 #endif
13694 case M16_OPC_SB:
13695 gen_st(ctx, OPC_SB, ry, rx, offset);
13696 break;
13697 case M16_OPC_SH:
13698 gen_st(ctx, OPC_SH, ry, rx, offset);
13699 break;
13700 case M16_OPC_SWSP:
13701 gen_st(ctx, OPC_SW, rx, 29, offset);
13702 break;
13703 case M16_OPC_SW:
13704 gen_st(ctx, OPC_SW, ry, rx, offset);
13705 break;
13706 #if defined(TARGET_MIPS64)
13707 case M16_OPC_I64:
13708 decode_i64_mips16(ctx, ry, funct, offset, 1);
13709 break;
13710 #endif
13711 default:
13712 generate_exception_end(ctx, EXCP_RI);
13713 break;
13716 return 4;
13719 static inline bool is_uhi(int sdbbp_code)
13721 #ifdef CONFIG_USER_ONLY
13722 return false;
13723 #else
13724 return semihosting_enabled() && sdbbp_code == 1;
13725 #endif
13728 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13730 int rx, ry;
13731 int sa;
13732 int op, cnvt_op, op1, offset;
13733 int funct;
13734 int n_bytes;
13736 op = (ctx->opcode >> 11) & 0x1f;
13737 sa = (ctx->opcode >> 2) & 0x7;
13738 sa = sa == 0 ? 8 : sa;
13739 rx = xlat((ctx->opcode >> 8) & 0x7);
13740 cnvt_op = (ctx->opcode >> 5) & 0x7;
13741 ry = xlat((ctx->opcode >> 5) & 0x7);
13742 op1 = offset = ctx->opcode & 0x1f;
13744 n_bytes = 2;
13746 switch (op) {
13747 case M16_OPC_ADDIUSP:
13749 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13751 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13753 break;
13754 case M16_OPC_ADDIUPC:
13755 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13756 break;
13757 case M16_OPC_B:
13758 offset = (ctx->opcode & 0x7ff) << 1;
13759 offset = (int16_t)(offset << 4) >> 4;
13760 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13761 /* No delay slot, so just process as a normal instruction */
13762 break;
13763 case M16_OPC_JAL:
13764 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13765 offset = (((ctx->opcode & 0x1f) << 21)
13766 | ((ctx->opcode >> 5) & 0x1f) << 16
13767 | offset) << 2;
13768 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13769 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13770 n_bytes = 4;
13771 break;
13772 case M16_OPC_BEQZ:
13773 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13774 ((int8_t)ctx->opcode) << 1, 0);
13775 /* No delay slot, so just process as a normal instruction */
13776 break;
13777 case M16_OPC_BNEQZ:
13778 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13779 ((int8_t)ctx->opcode) << 1, 0);
13780 /* No delay slot, so just process as a normal instruction */
13781 break;
13782 case M16_OPC_SHIFT:
13783 switch (ctx->opcode & 0x3) {
13784 case 0x0:
13785 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13786 break;
13787 case 0x1:
13788 #if defined(TARGET_MIPS64)
13789 check_insn(ctx, ISA_MIPS3);
13790 check_mips_64(ctx);
13791 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13792 #else
13793 generate_exception_end(ctx, EXCP_RI);
13794 #endif
13795 break;
13796 case 0x2:
13797 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13798 break;
13799 case 0x3:
13800 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13801 break;
13803 break;
13804 #if defined(TARGET_MIPS64)
13805 case M16_OPC_LD:
13806 check_insn(ctx, ISA_MIPS3);
13807 check_mips_64(ctx);
13808 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13809 break;
13810 #endif
13811 case M16_OPC_RRIA:
13813 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13815 if ((ctx->opcode >> 4) & 1) {
13816 #if defined(TARGET_MIPS64)
13817 check_insn(ctx, ISA_MIPS3);
13818 check_mips_64(ctx);
13819 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13820 #else
13821 generate_exception_end(ctx, EXCP_RI);
13822 #endif
13823 } else {
13824 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13827 break;
13828 case M16_OPC_ADDIU8:
13830 int16_t imm = (int8_t) ctx->opcode;
13832 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13834 break;
13835 case M16_OPC_SLTI:
13837 int16_t imm = (uint8_t) ctx->opcode;
13838 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13840 break;
13841 case M16_OPC_SLTIU:
13843 int16_t imm = (uint8_t) ctx->opcode;
13844 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13846 break;
13847 case M16_OPC_I8:
13849 int reg32;
13851 funct = (ctx->opcode >> 8) & 0x7;
13852 switch (funct) {
13853 case I8_BTEQZ:
13854 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13855 ((int8_t)ctx->opcode) << 1, 0);
13856 break;
13857 case I8_BTNEZ:
13858 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13859 ((int8_t)ctx->opcode) << 1, 0);
13860 break;
13861 case I8_SWRASP:
13862 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13863 break;
13864 case I8_ADJSP:
13865 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13866 ((int8_t)ctx->opcode) << 3);
13867 break;
13868 case I8_SVRS:
13869 check_insn(ctx, ISA_MIPS32);
13871 int do_ra = ctx->opcode & (1 << 6);
13872 int do_s0 = ctx->opcode & (1 << 5);
13873 int do_s1 = ctx->opcode & (1 << 4);
13874 int framesize = ctx->opcode & 0xf;
13876 if (framesize == 0) {
13877 framesize = 128;
13878 } else {
13879 framesize = framesize << 3;
13882 if (ctx->opcode & (1 << 7)) {
13883 gen_mips16_save(ctx, 0, 0,
13884 do_ra, do_s0, do_s1, framesize);
13885 } else {
13886 gen_mips16_restore(ctx, 0, 0,
13887 do_ra, do_s0, do_s1, framesize);
13890 break;
13891 case I8_MOV32R:
13893 int rz = xlat(ctx->opcode & 0x7);
13895 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13896 ((ctx->opcode >> 5) & 0x7);
13897 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13899 break;
13900 case I8_MOVR32:
13901 reg32 = ctx->opcode & 0x1f;
13902 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13903 break;
13904 default:
13905 generate_exception_end(ctx, EXCP_RI);
13906 break;
13909 break;
13910 case M16_OPC_LI:
13912 int16_t imm = (uint8_t) ctx->opcode;
13914 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13916 break;
13917 case M16_OPC_CMPI:
13919 int16_t imm = (uint8_t) ctx->opcode;
13920 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13922 break;
13923 #if defined(TARGET_MIPS64)
13924 case M16_OPC_SD:
13925 check_insn(ctx, ISA_MIPS3);
13926 check_mips_64(ctx);
13927 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13928 break;
13929 #endif
13930 case M16_OPC_LB:
13931 gen_ld(ctx, OPC_LB, ry, rx, offset);
13932 break;
13933 case M16_OPC_LH:
13934 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13935 break;
13936 case M16_OPC_LWSP:
13937 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13938 break;
13939 case M16_OPC_LW:
13940 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13941 break;
13942 case M16_OPC_LBU:
13943 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13944 break;
13945 case M16_OPC_LHU:
13946 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13947 break;
13948 case M16_OPC_LWPC:
13949 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13950 break;
13951 #if defined (TARGET_MIPS64)
13952 case M16_OPC_LWU:
13953 check_insn(ctx, ISA_MIPS3);
13954 check_mips_64(ctx);
13955 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13956 break;
13957 #endif
13958 case M16_OPC_SB:
13959 gen_st(ctx, OPC_SB, ry, rx, offset);
13960 break;
13961 case M16_OPC_SH:
13962 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13963 break;
13964 case M16_OPC_SWSP:
13965 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13966 break;
13967 case M16_OPC_SW:
13968 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13969 break;
13970 case M16_OPC_RRR:
13972 int rz = xlat((ctx->opcode >> 2) & 0x7);
13973 int mips32_op;
13975 switch (ctx->opcode & 0x3) {
13976 case RRR_ADDU:
13977 mips32_op = OPC_ADDU;
13978 break;
13979 case RRR_SUBU:
13980 mips32_op = OPC_SUBU;
13981 break;
13982 #if defined(TARGET_MIPS64)
13983 case RRR_DADDU:
13984 mips32_op = OPC_DADDU;
13985 check_insn(ctx, ISA_MIPS3);
13986 check_mips_64(ctx);
13987 break;
13988 case RRR_DSUBU:
13989 mips32_op = OPC_DSUBU;
13990 check_insn(ctx, ISA_MIPS3);
13991 check_mips_64(ctx);
13992 break;
13993 #endif
13994 default:
13995 generate_exception_end(ctx, EXCP_RI);
13996 goto done;
13999 gen_arith(ctx, mips32_op, rz, rx, ry);
14000 done:
14003 break;
14004 case M16_OPC_RR:
14005 switch (op1) {
14006 case RR_JR:
14008 int nd = (ctx->opcode >> 7) & 0x1;
14009 int link = (ctx->opcode >> 6) & 0x1;
14010 int ra = (ctx->opcode >> 5) & 0x1;
14012 if (nd) {
14013 check_insn(ctx, ISA_MIPS32);
14016 if (link) {
14017 op = OPC_JALR;
14018 } else {
14019 op = OPC_JR;
14022 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14023 (nd ? 0 : 2));
14025 break;
14026 case RR_SDBBP:
14027 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14028 gen_helper_do_semihosting(cpu_env);
14029 } else {
14030 /* XXX: not clear which exception should be raised
14031 * when in debug mode...
14033 check_insn(ctx, ISA_MIPS32);
14034 generate_exception_end(ctx, EXCP_DBp);
14036 break;
14037 case RR_SLT:
14038 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14039 break;
14040 case RR_SLTU:
14041 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14042 break;
14043 case RR_BREAK:
14044 generate_exception_end(ctx, EXCP_BREAK);
14045 break;
14046 case RR_SLLV:
14047 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14048 break;
14049 case RR_SRLV:
14050 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14051 break;
14052 case RR_SRAV:
14053 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14054 break;
14055 #if defined (TARGET_MIPS64)
14056 case RR_DSRL:
14057 check_insn(ctx, ISA_MIPS3);
14058 check_mips_64(ctx);
14059 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14060 break;
14061 #endif
14062 case RR_CMP:
14063 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14064 break;
14065 case RR_NEG:
14066 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14067 break;
14068 case RR_AND:
14069 gen_logic(ctx, OPC_AND, rx, rx, ry);
14070 break;
14071 case RR_OR:
14072 gen_logic(ctx, OPC_OR, rx, rx, ry);
14073 break;
14074 case RR_XOR:
14075 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14076 break;
14077 case RR_NOT:
14078 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14079 break;
14080 case RR_MFHI:
14081 gen_HILO(ctx, OPC_MFHI, 0, rx);
14082 break;
14083 case RR_CNVT:
14084 check_insn(ctx, ISA_MIPS32);
14085 switch (cnvt_op) {
14086 case RR_RY_CNVT_ZEB:
14087 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14088 break;
14089 case RR_RY_CNVT_ZEH:
14090 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14091 break;
14092 case RR_RY_CNVT_SEB:
14093 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14094 break;
14095 case RR_RY_CNVT_SEH:
14096 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14097 break;
14098 #if defined (TARGET_MIPS64)
14099 case RR_RY_CNVT_ZEW:
14100 check_insn(ctx, ISA_MIPS64);
14101 check_mips_64(ctx);
14102 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14103 break;
14104 case RR_RY_CNVT_SEW:
14105 check_insn(ctx, ISA_MIPS64);
14106 check_mips_64(ctx);
14107 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14108 break;
14109 #endif
14110 default:
14111 generate_exception_end(ctx, EXCP_RI);
14112 break;
14114 break;
14115 case RR_MFLO:
14116 gen_HILO(ctx, OPC_MFLO, 0, rx);
14117 break;
14118 #if defined (TARGET_MIPS64)
14119 case RR_DSRA:
14120 check_insn(ctx, ISA_MIPS3);
14121 check_mips_64(ctx);
14122 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14123 break;
14124 case RR_DSLLV:
14125 check_insn(ctx, ISA_MIPS3);
14126 check_mips_64(ctx);
14127 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14128 break;
14129 case RR_DSRLV:
14130 check_insn(ctx, ISA_MIPS3);
14131 check_mips_64(ctx);
14132 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14133 break;
14134 case RR_DSRAV:
14135 check_insn(ctx, ISA_MIPS3);
14136 check_mips_64(ctx);
14137 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14138 break;
14139 #endif
14140 case RR_MULT:
14141 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14142 break;
14143 case RR_MULTU:
14144 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14145 break;
14146 case RR_DIV:
14147 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14148 break;
14149 case RR_DIVU:
14150 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14151 break;
14152 #if defined (TARGET_MIPS64)
14153 case RR_DMULT:
14154 check_insn(ctx, ISA_MIPS3);
14155 check_mips_64(ctx);
14156 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14157 break;
14158 case RR_DMULTU:
14159 check_insn(ctx, ISA_MIPS3);
14160 check_mips_64(ctx);
14161 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14162 break;
14163 case RR_DDIV:
14164 check_insn(ctx, ISA_MIPS3);
14165 check_mips_64(ctx);
14166 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14167 break;
14168 case RR_DDIVU:
14169 check_insn(ctx, ISA_MIPS3);
14170 check_mips_64(ctx);
14171 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14172 break;
14173 #endif
14174 default:
14175 generate_exception_end(ctx, EXCP_RI);
14176 break;
14178 break;
14179 case M16_OPC_EXTEND:
14180 decode_extended_mips16_opc(env, ctx);
14181 n_bytes = 4;
14182 break;
14183 #if defined(TARGET_MIPS64)
14184 case M16_OPC_I64:
14185 funct = (ctx->opcode >> 8) & 0x7;
14186 decode_i64_mips16(ctx, ry, funct, offset, 0);
14187 break;
14188 #endif
14189 default:
14190 generate_exception_end(ctx, EXCP_RI);
14191 break;
14194 return n_bytes;
14197 /* microMIPS extension to MIPS32/MIPS64 */
14200 * microMIPS32/microMIPS64 major opcodes
14202 * 1. MIPS Architecture for Programmers Volume II-B:
14203 * The microMIPS32 Instruction Set (Revision 3.05)
14205 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14207 * 2. MIPS Architecture For Programmers Volume II-A:
14208 * The MIPS64 Instruction Set (Revision 3.51)
14211 enum {
14212 POOL32A = 0x00,
14213 POOL16A = 0x01,
14214 LBU16 = 0x02,
14215 MOVE16 = 0x03,
14216 ADDI32 = 0x04,
14217 R6_LUI = 0x04,
14218 AUI = 0x04,
14219 LBU32 = 0x05,
14220 SB32 = 0x06,
14221 LB32 = 0x07,
14223 POOL32B = 0x08,
14224 POOL16B = 0x09,
14225 LHU16 = 0x0a,
14226 ANDI16 = 0x0b,
14227 ADDIU32 = 0x0c,
14228 LHU32 = 0x0d,
14229 SH32 = 0x0e,
14230 LH32 = 0x0f,
14232 POOL32I = 0x10,
14233 POOL16C = 0x11,
14234 LWSP16 = 0x12,
14235 POOL16D = 0x13,
14236 ORI32 = 0x14,
14237 POOL32F = 0x15,
14238 POOL32S = 0x16, /* MIPS64 */
14239 DADDIU32 = 0x17, /* MIPS64 */
14241 POOL32C = 0x18,
14242 LWGP16 = 0x19,
14243 LW16 = 0x1a,
14244 POOL16E = 0x1b,
14245 XORI32 = 0x1c,
14246 JALS32 = 0x1d,
14247 BOVC = 0x1d,
14248 BEQC = 0x1d,
14249 BEQZALC = 0x1d,
14250 ADDIUPC = 0x1e,
14251 PCREL = 0x1e,
14252 BNVC = 0x1f,
14253 BNEC = 0x1f,
14254 BNEZALC = 0x1f,
14256 R6_BEQZC = 0x20,
14257 JIC = 0x20,
14258 POOL16F = 0x21,
14259 SB16 = 0x22,
14260 BEQZ16 = 0x23,
14261 BEQZC16 = 0x23,
14262 SLTI32 = 0x24,
14263 BEQ32 = 0x25,
14264 BC = 0x25,
14265 SWC132 = 0x26,
14266 LWC132 = 0x27,
14268 /* 0x29 is reserved */
14269 RES_29 = 0x29,
14270 R6_BNEZC = 0x28,
14271 JIALC = 0x28,
14272 SH16 = 0x2a,
14273 BNEZ16 = 0x2b,
14274 BNEZC16 = 0x2b,
14275 SLTIU32 = 0x2c,
14276 BNE32 = 0x2d,
14277 BALC = 0x2d,
14278 SDC132 = 0x2e,
14279 LDC132 = 0x2f,
14281 /* 0x31 is reserved */
14282 RES_31 = 0x31,
14283 BLEZALC = 0x30,
14284 BGEZALC = 0x30,
14285 BGEUC = 0x30,
14286 SWSP16 = 0x32,
14287 B16 = 0x33,
14288 BC16 = 0x33,
14289 ANDI32 = 0x34,
14290 J32 = 0x35,
14291 BGTZC = 0x35,
14292 BLTZC = 0x35,
14293 BLTC = 0x35,
14294 SD32 = 0x36, /* MIPS64 */
14295 LD32 = 0x37, /* MIPS64 */
14297 /* 0x39 is reserved */
14298 RES_39 = 0x39,
14299 BGTZALC = 0x38,
14300 BLTZALC = 0x38,
14301 BLTUC = 0x38,
14302 SW16 = 0x3a,
14303 LI16 = 0x3b,
14304 JALX32 = 0x3c,
14305 JAL32 = 0x3d,
14306 BLEZC = 0x3d,
14307 BGEZC = 0x3d,
14308 BGEC = 0x3d,
14309 SW32 = 0x3e,
14310 LW32 = 0x3f
14313 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14314 enum {
14315 ADDIUPC_00 = 0x00,
14316 ADDIUPC_01 = 0x01,
14317 ADDIUPC_02 = 0x02,
14318 ADDIUPC_03 = 0x03,
14319 ADDIUPC_04 = 0x04,
14320 ADDIUPC_05 = 0x05,
14321 ADDIUPC_06 = 0x06,
14322 ADDIUPC_07 = 0x07,
14323 AUIPC = 0x1e,
14324 ALUIPC = 0x1f,
14325 LWPC_08 = 0x08,
14326 LWPC_09 = 0x09,
14327 LWPC_0A = 0x0A,
14328 LWPC_0B = 0x0B,
14329 LWPC_0C = 0x0C,
14330 LWPC_0D = 0x0D,
14331 LWPC_0E = 0x0E,
14332 LWPC_0F = 0x0F,
14335 /* POOL32A encoding of minor opcode field */
14337 enum {
14338 /* These opcodes are distinguished only by bits 9..6; those bits are
14339 * what are recorded below. */
14340 SLL32 = 0x0,
14341 SRL32 = 0x1,
14342 SRA = 0x2,
14343 ROTR = 0x3,
14344 SELEQZ = 0x5,
14345 SELNEZ = 0x6,
14346 R6_RDHWR = 0x7,
14348 SLLV = 0x0,
14349 SRLV = 0x1,
14350 SRAV = 0x2,
14351 ROTRV = 0x3,
14352 ADD = 0x4,
14353 ADDU32 = 0x5,
14354 SUB = 0x6,
14355 SUBU32 = 0x7,
14356 MUL = 0x8,
14357 AND = 0x9,
14358 OR32 = 0xa,
14359 NOR = 0xb,
14360 XOR32 = 0xc,
14361 SLT = 0xd,
14362 SLTU = 0xe,
14364 MOVN = 0x0,
14365 R6_MUL = 0x0,
14366 MOVZ = 0x1,
14367 MUH = 0x1,
14368 MULU = 0x2,
14369 MUHU = 0x3,
14370 LWXS = 0x4,
14371 R6_DIV = 0x4,
14372 MOD = 0x5,
14373 R6_DIVU = 0x6,
14374 MODU = 0x7,
14376 /* The following can be distinguished by their lower 6 bits. */
14377 BREAK32 = 0x07,
14378 INS = 0x0c,
14379 LSA = 0x0f,
14380 ALIGN = 0x1f,
14381 EXT = 0x2c,
14382 POOL32AXF = 0x3c,
14383 SIGRIE = 0x3f
14386 /* POOL32AXF encoding of minor opcode field extension */
14389 * 1. MIPS Architecture for Programmers Volume II-B:
14390 * The microMIPS32 Instruction Set (Revision 3.05)
14392 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14394 * 2. MIPS Architecture for Programmers VolumeIV-e:
14395 * The MIPS DSP Application-Specific Extension
14396 * to the microMIPS32 Architecture (Revision 2.34)
14398 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14401 enum {
14402 /* bits 11..6 */
14403 TEQ = 0x00,
14404 TGE = 0x08,
14405 TGEU = 0x10,
14406 TLT = 0x20,
14407 TLTU = 0x28,
14408 TNE = 0x30,
14410 MFC0 = 0x03,
14411 MTC0 = 0x0b,
14413 /* begin of microMIPS32 DSP */
14415 /* bits 13..12 for 0x01 */
14416 MFHI_ACC = 0x0,
14417 MFLO_ACC = 0x1,
14418 MTHI_ACC = 0x2,
14419 MTLO_ACC = 0x3,
14421 /* bits 13..12 for 0x2a */
14422 MADD_ACC = 0x0,
14423 MADDU_ACC = 0x1,
14424 MSUB_ACC = 0x2,
14425 MSUBU_ACC = 0x3,
14427 /* bits 13..12 for 0x32 */
14428 MULT_ACC = 0x0,
14429 MULTU_ACC = 0x1,
14431 /* end of microMIPS32 DSP */
14433 /* bits 15..12 for 0x2c */
14434 BITSWAP = 0x0,
14435 SEB = 0x2,
14436 SEH = 0x3,
14437 CLO = 0x4,
14438 CLZ = 0x5,
14439 RDHWR = 0x6,
14440 WSBH = 0x7,
14441 MULT = 0x8,
14442 MULTU = 0x9,
14443 DIV = 0xa,
14444 DIVU = 0xb,
14445 MADD = 0xc,
14446 MADDU = 0xd,
14447 MSUB = 0xe,
14448 MSUBU = 0xf,
14450 /* bits 15..12 for 0x34 */
14451 MFC2 = 0x4,
14452 MTC2 = 0x5,
14453 MFHC2 = 0x8,
14454 MTHC2 = 0x9,
14455 CFC2 = 0xc,
14456 CTC2 = 0xd,
14458 /* bits 15..12 for 0x3c */
14459 JALR = 0x0,
14460 JR = 0x0, /* alias */
14461 JALRC = 0x0,
14462 JRC = 0x0,
14463 JALR_HB = 0x1,
14464 JALRC_HB = 0x1,
14465 JALRS = 0x4,
14466 JALRS_HB = 0x5,
14468 /* bits 15..12 for 0x05 */
14469 RDPGPR = 0xe,
14470 WRPGPR = 0xf,
14472 /* bits 15..12 for 0x0d */
14473 TLBP = 0x0,
14474 TLBR = 0x1,
14475 TLBWI = 0x2,
14476 TLBWR = 0x3,
14477 TLBINV = 0x4,
14478 TLBINVF = 0x5,
14479 WAIT = 0x9,
14480 IRET = 0xd,
14481 DERET = 0xe,
14482 ERET = 0xf,
14484 /* bits 15..12 for 0x15 */
14485 DMT = 0x0,
14486 DVPE = 0x1,
14487 EMT = 0x2,
14488 EVPE = 0x3,
14490 /* bits 15..12 for 0x1d */
14491 DI = 0x4,
14492 EI = 0x5,
14494 /* bits 15..12 for 0x2d */
14495 SYNC = 0x6,
14496 SYSCALL = 0x8,
14497 SDBBP = 0xd,
14499 /* bits 15..12 for 0x35 */
14500 MFHI32 = 0x0,
14501 MFLO32 = 0x1,
14502 MTHI32 = 0x2,
14503 MTLO32 = 0x3,
14506 /* POOL32B encoding of minor opcode field (bits 15..12) */
14508 enum {
14509 LWC2 = 0x0,
14510 LWP = 0x1,
14511 LDP = 0x4,
14512 LWM32 = 0x5,
14513 CACHE = 0x6,
14514 LDM = 0x7,
14515 SWC2 = 0x8,
14516 SWP = 0x9,
14517 SDP = 0xc,
14518 SWM32 = 0xd,
14519 SDM = 0xf
14522 /* POOL32C encoding of minor opcode field (bits 15..12) */
14524 enum {
14525 LWL = 0x0,
14526 SWL = 0x8,
14527 LWR = 0x1,
14528 SWR = 0x9,
14529 PREF = 0x2,
14530 ST_EVA = 0xa,
14531 LL = 0x3,
14532 SC = 0xb,
14533 LDL = 0x4,
14534 SDL = 0xc,
14535 LDR = 0x5,
14536 SDR = 0xd,
14537 LD_EVA = 0x6,
14538 LWU = 0xe,
14539 LLD = 0x7,
14540 SCD = 0xf
14543 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14545 enum {
14546 LBUE = 0x0,
14547 LHUE = 0x1,
14548 LWLE = 0x2,
14549 LWRE = 0x3,
14550 LBE = 0x4,
14551 LHE = 0x5,
14552 LLE = 0x6,
14553 LWE = 0x7,
14556 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14558 enum {
14559 SWLE = 0x0,
14560 SWRE = 0x1,
14561 PREFE = 0x2,
14562 CACHEE = 0x3,
14563 SBE = 0x4,
14564 SHE = 0x5,
14565 SCE = 0x6,
14566 SWE = 0x7,
14569 /* POOL32F encoding of minor opcode field (bits 5..0) */
14571 enum {
14572 /* These are the bit 7..6 values */
14573 ADD_FMT = 0x0,
14575 SUB_FMT = 0x1,
14577 MUL_FMT = 0x2,
14579 DIV_FMT = 0x3,
14581 /* These are the bit 8..6 values */
14582 MOVN_FMT = 0x0,
14583 RSQRT2_FMT = 0x0,
14584 MOVF_FMT = 0x0,
14585 RINT_FMT = 0x0,
14586 SELNEZ_FMT = 0x0,
14588 MOVZ_FMT = 0x1,
14589 LWXC1 = 0x1,
14590 MOVT_FMT = 0x1,
14591 CLASS_FMT = 0x1,
14592 SELEQZ_FMT = 0x1,
14594 PLL_PS = 0x2,
14595 SWXC1 = 0x2,
14596 SEL_FMT = 0x2,
14598 PLU_PS = 0x3,
14599 LDXC1 = 0x3,
14601 MOVN_FMT_04 = 0x4,
14602 PUL_PS = 0x4,
14603 SDXC1 = 0x4,
14604 RECIP2_FMT = 0x4,
14606 MOVZ_FMT_05 = 0x05,
14607 PUU_PS = 0x5,
14608 LUXC1 = 0x5,
14610 CVT_PS_S = 0x6,
14611 SUXC1 = 0x6,
14612 ADDR_PS = 0x6,
14613 PREFX = 0x6,
14614 MADDF_FMT = 0x6,
14616 MULR_PS = 0x7,
14617 MSUBF_FMT = 0x7,
14619 MADD_S = 0x01,
14620 MADD_D = 0x09,
14621 MADD_PS = 0x11,
14622 ALNV_PS = 0x19,
14623 MSUB_S = 0x21,
14624 MSUB_D = 0x29,
14625 MSUB_PS = 0x31,
14627 NMADD_S = 0x02,
14628 NMADD_D = 0x0a,
14629 NMADD_PS = 0x12,
14630 NMSUB_S = 0x22,
14631 NMSUB_D = 0x2a,
14632 NMSUB_PS = 0x32,
14634 MIN_FMT = 0x3,
14635 MAX_FMT = 0xb,
14636 MINA_FMT = 0x23,
14637 MAXA_FMT = 0x2b,
14638 POOL32FXF = 0x3b,
14640 CABS_COND_FMT = 0x1c, /* MIPS3D */
14641 C_COND_FMT = 0x3c,
14643 CMP_CONDN_S = 0x5,
14644 CMP_CONDN_D = 0x15
14647 /* POOL32Fxf encoding of minor opcode extension field */
14649 enum {
14650 CVT_L = 0x04,
14651 RSQRT_FMT = 0x08,
14652 FLOOR_L = 0x0c,
14653 CVT_PW_PS = 0x1c,
14654 CVT_W = 0x24,
14655 SQRT_FMT = 0x28,
14656 FLOOR_W = 0x2c,
14657 CVT_PS_PW = 0x3c,
14658 CFC1 = 0x40,
14659 RECIP_FMT = 0x48,
14660 CEIL_L = 0x4c,
14661 CTC1 = 0x60,
14662 CEIL_W = 0x6c,
14663 MFC1 = 0x80,
14664 CVT_S_PL = 0x84,
14665 TRUNC_L = 0x8c,
14666 MTC1 = 0xa0,
14667 CVT_S_PU = 0xa4,
14668 TRUNC_W = 0xac,
14669 MFHC1 = 0xc0,
14670 ROUND_L = 0xcc,
14671 MTHC1 = 0xe0,
14672 ROUND_W = 0xec,
14674 MOV_FMT = 0x01,
14675 MOVF = 0x05,
14676 ABS_FMT = 0x0d,
14677 RSQRT1_FMT = 0x1d,
14678 MOVT = 0x25,
14679 NEG_FMT = 0x2d,
14680 CVT_D = 0x4d,
14681 RECIP1_FMT = 0x5d,
14682 CVT_S = 0x6d
14685 /* POOL32I encoding of minor opcode field (bits 25..21) */
14687 enum {
14688 BLTZ = 0x00,
14689 BLTZAL = 0x01,
14690 BGEZ = 0x02,
14691 BGEZAL = 0x03,
14692 BLEZ = 0x04,
14693 BNEZC = 0x05,
14694 BGTZ = 0x06,
14695 BEQZC = 0x07,
14696 TLTI = 0x08,
14697 BC1EQZC = 0x08,
14698 TGEI = 0x09,
14699 BC1NEZC = 0x09,
14700 TLTIU = 0x0a,
14701 BC2EQZC = 0x0a,
14702 TGEIU = 0x0b,
14703 BC2NEZC = 0x0a,
14704 TNEI = 0x0c,
14705 R6_SYNCI = 0x0c,
14706 LUI = 0x0d,
14707 TEQI = 0x0e,
14708 SYNCI = 0x10,
14709 BLTZALS = 0x11,
14710 BGEZALS = 0x13,
14711 BC2F = 0x14,
14712 BC2T = 0x15,
14713 BPOSGE64 = 0x1a,
14714 BPOSGE32 = 0x1b,
14715 /* These overlap and are distinguished by bit16 of the instruction */
14716 BC1F = 0x1c,
14717 BC1T = 0x1d,
14718 BC1ANY2F = 0x1c,
14719 BC1ANY2T = 0x1d,
14720 BC1ANY4F = 0x1e,
14721 BC1ANY4T = 0x1f
14724 /* POOL16A encoding of minor opcode field */
14726 enum {
14727 ADDU16 = 0x0,
14728 SUBU16 = 0x1
14731 /* POOL16B encoding of minor opcode field */
14733 enum {
14734 SLL16 = 0x0,
14735 SRL16 = 0x1
14738 /* POOL16C encoding of minor opcode field */
14740 enum {
14741 NOT16 = 0x00,
14742 XOR16 = 0x04,
14743 AND16 = 0x08,
14744 OR16 = 0x0c,
14745 LWM16 = 0x10,
14746 SWM16 = 0x14,
14747 JR16 = 0x18,
14748 JRC16 = 0x1a,
14749 JALR16 = 0x1c,
14750 JALR16S = 0x1e,
14751 MFHI16 = 0x20,
14752 MFLO16 = 0x24,
14753 BREAK16 = 0x28,
14754 SDBBP16 = 0x2c,
14755 JRADDIUSP = 0x30
14758 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14760 enum {
14761 R6_NOT16 = 0x00,
14762 R6_AND16 = 0x01,
14763 R6_LWM16 = 0x02,
14764 R6_JRC16 = 0x03,
14765 MOVEP = 0x04,
14766 MOVEP_05 = 0x05,
14767 MOVEP_06 = 0x06,
14768 MOVEP_07 = 0x07,
14769 R6_XOR16 = 0x08,
14770 R6_OR16 = 0x09,
14771 R6_SWM16 = 0x0a,
14772 JALRC16 = 0x0b,
14773 MOVEP_0C = 0x0c,
14774 MOVEP_0D = 0x0d,
14775 MOVEP_0E = 0x0e,
14776 MOVEP_0F = 0x0f,
14777 JRCADDIUSP = 0x13,
14778 R6_BREAK16 = 0x1b,
14779 R6_SDBBP16 = 0x3b
14782 /* POOL16D encoding of minor opcode field */
14784 enum {
14785 ADDIUS5 = 0x0,
14786 ADDIUSP = 0x1
14789 /* POOL16E encoding of minor opcode field */
14791 enum {
14792 ADDIUR2 = 0x0,
14793 ADDIUR1SP = 0x1
14796 static int mmreg (int r)
14798 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14800 return map[r];
14803 /* Used for 16-bit store instructions. */
14804 static int mmreg2 (int r)
14806 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14808 return map[r];
14811 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14812 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14813 #define uMIPS_RS2(op) uMIPS_RS(op)
14814 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14815 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14816 #define uMIPS_RS5(op) (op & 0x1f)
14818 /* Signed immediate */
14819 #define SIMM(op, start, width) \
14820 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14821 << (32-width)) \
14822 >> (32-width))
14823 /* Zero-extended immediate */
14824 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14826 static void gen_addiur1sp(DisasContext *ctx)
14828 int rd = mmreg(uMIPS_RD(ctx->opcode));
14830 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14833 static void gen_addiur2(DisasContext *ctx)
14835 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14836 int rd = mmreg(uMIPS_RD(ctx->opcode));
14837 int rs = mmreg(uMIPS_RS(ctx->opcode));
14839 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14842 static void gen_addiusp(DisasContext *ctx)
14844 int encoded = ZIMM(ctx->opcode, 1, 9);
14845 int decoded;
14847 if (encoded <= 1) {
14848 decoded = 256 + encoded;
14849 } else if (encoded <= 255) {
14850 decoded = encoded;
14851 } else if (encoded <= 509) {
14852 decoded = encoded - 512;
14853 } else {
14854 decoded = encoded - 768;
14857 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14860 static void gen_addius5(DisasContext *ctx)
14862 int imm = SIMM(ctx->opcode, 1, 4);
14863 int rd = (ctx->opcode >> 5) & 0x1f;
14865 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14868 static void gen_andi16(DisasContext *ctx)
14870 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14871 31, 32, 63, 64, 255, 32768, 65535 };
14872 int rd = mmreg(uMIPS_RD(ctx->opcode));
14873 int rs = mmreg(uMIPS_RS(ctx->opcode));
14874 int encoded = ZIMM(ctx->opcode, 0, 4);
14876 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14879 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14880 int base, int16_t offset)
14882 TCGv t0, t1;
14883 TCGv_i32 t2;
14885 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14886 generate_exception_end(ctx, EXCP_RI);
14887 return;
14890 t0 = tcg_temp_new();
14892 gen_base_offset_addr(ctx, t0, base, offset);
14894 t1 = tcg_const_tl(reglist);
14895 t2 = tcg_const_i32(ctx->mem_idx);
14897 save_cpu_state(ctx, 1);
14898 switch (opc) {
14899 case LWM32:
14900 gen_helper_lwm(cpu_env, t0, t1, t2);
14901 break;
14902 case SWM32:
14903 gen_helper_swm(cpu_env, t0, t1, t2);
14904 break;
14905 #ifdef TARGET_MIPS64
14906 case LDM:
14907 gen_helper_ldm(cpu_env, t0, t1, t2);
14908 break;
14909 case SDM:
14910 gen_helper_sdm(cpu_env, t0, t1, t2);
14911 break;
14912 #endif
14914 tcg_temp_free(t0);
14915 tcg_temp_free(t1);
14916 tcg_temp_free_i32(t2);
14920 static void gen_pool16c_insn(DisasContext *ctx)
14922 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14923 int rs = mmreg(ctx->opcode & 0x7);
14925 switch (((ctx->opcode) >> 4) & 0x3f) {
14926 case NOT16 + 0:
14927 case NOT16 + 1:
14928 case NOT16 + 2:
14929 case NOT16 + 3:
14930 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14931 break;
14932 case XOR16 + 0:
14933 case XOR16 + 1:
14934 case XOR16 + 2:
14935 case XOR16 + 3:
14936 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14937 break;
14938 case AND16 + 0:
14939 case AND16 + 1:
14940 case AND16 + 2:
14941 case AND16 + 3:
14942 gen_logic(ctx, OPC_AND, rd, rd, rs);
14943 break;
14944 case OR16 + 0:
14945 case OR16 + 1:
14946 case OR16 + 2:
14947 case OR16 + 3:
14948 gen_logic(ctx, OPC_OR, rd, rd, rs);
14949 break;
14950 case LWM16 + 0:
14951 case LWM16 + 1:
14952 case LWM16 + 2:
14953 case LWM16 + 3:
14955 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14956 int offset = ZIMM(ctx->opcode, 0, 4);
14958 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14959 29, offset << 2);
14961 break;
14962 case SWM16 + 0:
14963 case SWM16 + 1:
14964 case SWM16 + 2:
14965 case SWM16 + 3:
14967 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14968 int offset = ZIMM(ctx->opcode, 0, 4);
14970 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14971 29, offset << 2);
14973 break;
14974 case JR16 + 0:
14975 case JR16 + 1:
14977 int reg = ctx->opcode & 0x1f;
14979 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14981 break;
14982 case JRC16 + 0:
14983 case JRC16 + 1:
14985 int reg = ctx->opcode & 0x1f;
14986 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14987 /* Let normal delay slot handling in our caller take us
14988 to the branch target. */
14990 break;
14991 case JALR16 + 0:
14992 case JALR16 + 1:
14993 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14994 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14995 break;
14996 case JALR16S + 0:
14997 case JALR16S + 1:
14998 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14999 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15000 break;
15001 case MFHI16 + 0:
15002 case MFHI16 + 1:
15003 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15004 break;
15005 case MFLO16 + 0:
15006 case MFLO16 + 1:
15007 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15008 break;
15009 case BREAK16:
15010 generate_exception_end(ctx, EXCP_BREAK);
15011 break;
15012 case SDBBP16:
15013 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15014 gen_helper_do_semihosting(cpu_env);
15015 } else {
15016 /* XXX: not clear which exception should be raised
15017 * when in debug mode...
15019 check_insn(ctx, ISA_MIPS32);
15020 generate_exception_end(ctx, EXCP_DBp);
15022 break;
15023 case JRADDIUSP + 0:
15024 case JRADDIUSP + 1:
15026 int imm = ZIMM(ctx->opcode, 0, 5);
15027 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15028 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15029 /* Let normal delay slot handling in our caller take us
15030 to the branch target. */
15032 break;
15033 default:
15034 generate_exception_end(ctx, EXCP_RI);
15035 break;
15039 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15040 int enc_rs)
15042 int rd, rs, re, rt;
15043 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15044 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15045 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15046 rd = rd_enc[enc_dest];
15047 re = re_enc[enc_dest];
15048 rs = rs_rt_enc[enc_rs];
15049 rt = rs_rt_enc[enc_rt];
15050 if (rs) {
15051 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15052 } else {
15053 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15055 if (rt) {
15056 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15057 } else {
15058 tcg_gen_movi_tl(cpu_gpr[re], 0);
15062 static void gen_pool16c_r6_insn(DisasContext *ctx)
15064 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15065 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15067 switch (ctx->opcode & 0xf) {
15068 case R6_NOT16:
15069 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15070 break;
15071 case R6_AND16:
15072 gen_logic(ctx, OPC_AND, rt, rt, rs);
15073 break;
15074 case R6_LWM16:
15076 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15077 int offset = extract32(ctx->opcode, 4, 4);
15078 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15080 break;
15081 case R6_JRC16: /* JRCADDIUSP */
15082 if ((ctx->opcode >> 4) & 1) {
15083 /* JRCADDIUSP */
15084 int imm = extract32(ctx->opcode, 5, 5);
15085 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15086 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15087 } else {
15088 /* JRC16 */
15089 rs = extract32(ctx->opcode, 5, 5);
15090 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15092 break;
15093 case MOVEP:
15094 case MOVEP_05:
15095 case MOVEP_06:
15096 case MOVEP_07:
15097 case MOVEP_0C:
15098 case MOVEP_0D:
15099 case MOVEP_0E:
15100 case MOVEP_0F:
15102 int enc_dest = uMIPS_RD(ctx->opcode);
15103 int enc_rt = uMIPS_RS2(ctx->opcode);
15104 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15105 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15107 break;
15108 case R6_XOR16:
15109 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15110 break;
15111 case R6_OR16:
15112 gen_logic(ctx, OPC_OR, rt, rt, rs);
15113 break;
15114 case R6_SWM16:
15116 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15117 int offset = extract32(ctx->opcode, 4, 4);
15118 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15120 break;
15121 case JALRC16: /* BREAK16, SDBBP16 */
15122 switch (ctx->opcode & 0x3f) {
15123 case JALRC16:
15124 case JALRC16 + 0x20:
15125 /* JALRC16 */
15126 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15127 31, 0, 0);
15128 break;
15129 case R6_BREAK16:
15130 /* BREAK16 */
15131 generate_exception(ctx, EXCP_BREAK);
15132 break;
15133 case R6_SDBBP16:
15134 /* SDBBP16 */
15135 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15136 gen_helper_do_semihosting(cpu_env);
15137 } else {
15138 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15139 generate_exception(ctx, EXCP_RI);
15140 } else {
15141 generate_exception(ctx, EXCP_DBp);
15144 break;
15146 break;
15147 default:
15148 generate_exception(ctx, EXCP_RI);
15149 break;
15153 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
15155 TCGv t0 = tcg_temp_new();
15156 TCGv t1 = tcg_temp_new();
15158 gen_load_gpr(t0, base);
15160 if (index != 0) {
15161 gen_load_gpr(t1, index);
15162 tcg_gen_shli_tl(t1, t1, 2);
15163 gen_op_addr_add(ctx, t0, t1, t0);
15166 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15167 gen_store_gpr(t1, rd);
15169 tcg_temp_free(t0);
15170 tcg_temp_free(t1);
15173 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
15174 int base, int16_t offset)
15176 TCGv t0, t1;
15178 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15179 generate_exception_end(ctx, EXCP_RI);
15180 return;
15183 t0 = tcg_temp_new();
15184 t1 = tcg_temp_new();
15186 gen_base_offset_addr(ctx, t0, base, offset);
15188 switch (opc) {
15189 case LWP:
15190 if (rd == base) {
15191 generate_exception_end(ctx, EXCP_RI);
15192 return;
15194 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15195 gen_store_gpr(t1, rd);
15196 tcg_gen_movi_tl(t1, 4);
15197 gen_op_addr_add(ctx, t0, t0, t1);
15198 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15199 gen_store_gpr(t1, rd+1);
15200 break;
15201 case SWP:
15202 gen_load_gpr(t1, rd);
15203 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15204 tcg_gen_movi_tl(t1, 4);
15205 gen_op_addr_add(ctx, t0, t0, t1);
15206 gen_load_gpr(t1, rd+1);
15207 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15208 break;
15209 #ifdef TARGET_MIPS64
15210 case LDP:
15211 if (rd == base) {
15212 generate_exception_end(ctx, EXCP_RI);
15213 return;
15215 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15216 gen_store_gpr(t1, rd);
15217 tcg_gen_movi_tl(t1, 8);
15218 gen_op_addr_add(ctx, t0, t0, t1);
15219 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15220 gen_store_gpr(t1, rd+1);
15221 break;
15222 case SDP:
15223 gen_load_gpr(t1, rd);
15224 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15225 tcg_gen_movi_tl(t1, 8);
15226 gen_op_addr_add(ctx, t0, t0, t1);
15227 gen_load_gpr(t1, rd+1);
15228 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15229 break;
15230 #endif
15232 tcg_temp_free(t0);
15233 tcg_temp_free(t1);
15236 static void gen_sync(int stype)
15238 TCGBar tcg_mo = TCG_BAR_SC;
15240 switch (stype) {
15241 case 0x4: /* SYNC_WMB */
15242 tcg_mo |= TCG_MO_ST_ST;
15243 break;
15244 case 0x10: /* SYNC_MB */
15245 tcg_mo |= TCG_MO_ALL;
15246 break;
15247 case 0x11: /* SYNC_ACQUIRE */
15248 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15249 break;
15250 case 0x12: /* SYNC_RELEASE */
15251 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15252 break;
15253 case 0x13: /* SYNC_RMB */
15254 tcg_mo |= TCG_MO_LD_LD;
15255 break;
15256 default:
15257 tcg_mo |= TCG_MO_ALL;
15258 break;
15261 tcg_gen_mb(tcg_mo);
15264 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15266 int extension = (ctx->opcode >> 6) & 0x3f;
15267 int minor = (ctx->opcode >> 12) & 0xf;
15268 uint32_t mips32_op;
15270 switch (extension) {
15271 case TEQ:
15272 mips32_op = OPC_TEQ;
15273 goto do_trap;
15274 case TGE:
15275 mips32_op = OPC_TGE;
15276 goto do_trap;
15277 case TGEU:
15278 mips32_op = OPC_TGEU;
15279 goto do_trap;
15280 case TLT:
15281 mips32_op = OPC_TLT;
15282 goto do_trap;
15283 case TLTU:
15284 mips32_op = OPC_TLTU;
15285 goto do_trap;
15286 case TNE:
15287 mips32_op = OPC_TNE;
15288 do_trap:
15289 gen_trap(ctx, mips32_op, rs, rt, -1);
15290 break;
15291 #ifndef CONFIG_USER_ONLY
15292 case MFC0:
15293 case MFC0 + 32:
15294 check_cp0_enabled(ctx);
15295 if (rt == 0) {
15296 /* Treat as NOP. */
15297 break;
15299 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15300 break;
15301 case MTC0:
15302 case MTC0 + 32:
15303 check_cp0_enabled(ctx);
15305 TCGv t0 = tcg_temp_new();
15307 gen_load_gpr(t0, rt);
15308 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15309 tcg_temp_free(t0);
15311 break;
15312 #endif
15313 case 0x2a:
15314 switch (minor & 3) {
15315 case MADD_ACC:
15316 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15317 break;
15318 case MADDU_ACC:
15319 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15320 break;
15321 case MSUB_ACC:
15322 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15323 break;
15324 case MSUBU_ACC:
15325 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15326 break;
15327 default:
15328 goto pool32axf_invalid;
15330 break;
15331 case 0x32:
15332 switch (minor & 3) {
15333 case MULT_ACC:
15334 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15335 break;
15336 case MULTU_ACC:
15337 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15338 break;
15339 default:
15340 goto pool32axf_invalid;
15342 break;
15343 case 0x2c:
15344 switch (minor) {
15345 case BITSWAP:
15346 check_insn(ctx, ISA_MIPS32R6);
15347 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15348 break;
15349 case SEB:
15350 gen_bshfl(ctx, OPC_SEB, rs, rt);
15351 break;
15352 case SEH:
15353 gen_bshfl(ctx, OPC_SEH, rs, rt);
15354 break;
15355 case CLO:
15356 mips32_op = OPC_CLO;
15357 goto do_cl;
15358 case CLZ:
15359 mips32_op = OPC_CLZ;
15360 do_cl:
15361 check_insn(ctx, ISA_MIPS32);
15362 gen_cl(ctx, mips32_op, rt, rs);
15363 break;
15364 case RDHWR:
15365 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15366 gen_rdhwr(ctx, rt, rs, 0);
15367 break;
15368 case WSBH:
15369 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15370 break;
15371 case MULT:
15372 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15373 mips32_op = OPC_MULT;
15374 goto do_mul;
15375 case MULTU:
15376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15377 mips32_op = OPC_MULTU;
15378 goto do_mul;
15379 case DIV:
15380 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15381 mips32_op = OPC_DIV;
15382 goto do_div;
15383 case DIVU:
15384 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15385 mips32_op = OPC_DIVU;
15386 goto do_div;
15387 do_div:
15388 check_insn(ctx, ISA_MIPS32);
15389 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15390 break;
15391 case MADD:
15392 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15393 mips32_op = OPC_MADD;
15394 goto do_mul;
15395 case MADDU:
15396 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15397 mips32_op = OPC_MADDU;
15398 goto do_mul;
15399 case MSUB:
15400 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15401 mips32_op = OPC_MSUB;
15402 goto do_mul;
15403 case MSUBU:
15404 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15405 mips32_op = OPC_MSUBU;
15406 do_mul:
15407 check_insn(ctx, ISA_MIPS32);
15408 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15409 break;
15410 default:
15411 goto pool32axf_invalid;
15413 break;
15414 case 0x34:
15415 switch (minor) {
15416 case MFC2:
15417 case MTC2:
15418 case MFHC2:
15419 case MTHC2:
15420 case CFC2:
15421 case CTC2:
15422 generate_exception_err(ctx, EXCP_CpU, 2);
15423 break;
15424 default:
15425 goto pool32axf_invalid;
15427 break;
15428 case 0x3c:
15429 switch (minor) {
15430 case JALR: /* JALRC */
15431 case JALR_HB: /* JALRC_HB */
15432 if (ctx->insn_flags & ISA_MIPS32R6) {
15433 /* JALRC, JALRC_HB */
15434 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15435 } else {
15436 /* JALR, JALR_HB */
15437 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15438 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15440 break;
15441 case JALRS:
15442 case JALRS_HB:
15443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15444 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15445 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15446 break;
15447 default:
15448 goto pool32axf_invalid;
15450 break;
15451 case 0x05:
15452 switch (minor) {
15453 case RDPGPR:
15454 check_cp0_enabled(ctx);
15455 check_insn(ctx, ISA_MIPS32R2);
15456 gen_load_srsgpr(rs, rt);
15457 break;
15458 case WRPGPR:
15459 check_cp0_enabled(ctx);
15460 check_insn(ctx, ISA_MIPS32R2);
15461 gen_store_srsgpr(rs, rt);
15462 break;
15463 default:
15464 goto pool32axf_invalid;
15466 break;
15467 #ifndef CONFIG_USER_ONLY
15468 case 0x0d:
15469 switch (minor) {
15470 case TLBP:
15471 mips32_op = OPC_TLBP;
15472 goto do_cp0;
15473 case TLBR:
15474 mips32_op = OPC_TLBR;
15475 goto do_cp0;
15476 case TLBWI:
15477 mips32_op = OPC_TLBWI;
15478 goto do_cp0;
15479 case TLBWR:
15480 mips32_op = OPC_TLBWR;
15481 goto do_cp0;
15482 case TLBINV:
15483 mips32_op = OPC_TLBINV;
15484 goto do_cp0;
15485 case TLBINVF:
15486 mips32_op = OPC_TLBINVF;
15487 goto do_cp0;
15488 case WAIT:
15489 mips32_op = OPC_WAIT;
15490 goto do_cp0;
15491 case DERET:
15492 mips32_op = OPC_DERET;
15493 goto do_cp0;
15494 case ERET:
15495 mips32_op = OPC_ERET;
15496 do_cp0:
15497 gen_cp0(env, ctx, mips32_op, rt, rs);
15498 break;
15499 default:
15500 goto pool32axf_invalid;
15502 break;
15503 case 0x1d:
15504 switch (minor) {
15505 case DI:
15506 check_cp0_enabled(ctx);
15508 TCGv t0 = tcg_temp_new();
15510 save_cpu_state(ctx, 1);
15511 gen_helper_di(t0, cpu_env);
15512 gen_store_gpr(t0, rs);
15513 /* Stop translation as we may have switched the execution mode */
15514 ctx->base.is_jmp = DISAS_STOP;
15515 tcg_temp_free(t0);
15517 break;
15518 case EI:
15519 check_cp0_enabled(ctx);
15521 TCGv t0 = tcg_temp_new();
15523 save_cpu_state(ctx, 1);
15524 gen_helper_ei(t0, cpu_env);
15525 gen_store_gpr(t0, rs);
15526 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15527 of translated code to check for pending interrupts. */
15528 gen_save_pc(ctx->base.pc_next + 4);
15529 ctx->base.is_jmp = DISAS_EXIT;
15530 tcg_temp_free(t0);
15532 break;
15533 default:
15534 goto pool32axf_invalid;
15536 break;
15537 #endif
15538 case 0x2d:
15539 switch (minor) {
15540 case SYNC:
15541 gen_sync(extract32(ctx->opcode, 16, 5));
15542 break;
15543 case SYSCALL:
15544 generate_exception_end(ctx, EXCP_SYSCALL);
15545 break;
15546 case SDBBP:
15547 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15548 gen_helper_do_semihosting(cpu_env);
15549 } else {
15550 check_insn(ctx, ISA_MIPS32);
15551 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15552 generate_exception_end(ctx, EXCP_RI);
15553 } else {
15554 generate_exception_end(ctx, EXCP_DBp);
15557 break;
15558 default:
15559 goto pool32axf_invalid;
15561 break;
15562 case 0x01:
15563 switch (minor & 3) {
15564 case MFHI_ACC:
15565 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15566 break;
15567 case MFLO_ACC:
15568 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15569 break;
15570 case MTHI_ACC:
15571 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15572 break;
15573 case MTLO_ACC:
15574 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15575 break;
15576 default:
15577 goto pool32axf_invalid;
15579 break;
15580 case 0x35:
15581 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15582 switch (minor) {
15583 case MFHI32:
15584 gen_HILO(ctx, OPC_MFHI, 0, rs);
15585 break;
15586 case MFLO32:
15587 gen_HILO(ctx, OPC_MFLO, 0, rs);
15588 break;
15589 case MTHI32:
15590 gen_HILO(ctx, OPC_MTHI, 0, rs);
15591 break;
15592 case MTLO32:
15593 gen_HILO(ctx, OPC_MTLO, 0, rs);
15594 break;
15595 default:
15596 goto pool32axf_invalid;
15598 break;
15599 default:
15600 pool32axf_invalid:
15601 MIPS_INVAL("pool32axf");
15602 generate_exception_end(ctx, EXCP_RI);
15603 break;
15607 /* Values for microMIPS fmt field. Variable-width, depending on which
15608 formats the instruction supports. */
15610 enum {
15611 FMT_SD_S = 0,
15612 FMT_SD_D = 1,
15614 FMT_SDPS_S = 0,
15615 FMT_SDPS_D = 1,
15616 FMT_SDPS_PS = 2,
15618 FMT_SWL_S = 0,
15619 FMT_SWL_W = 1,
15620 FMT_SWL_L = 2,
15622 FMT_DWL_D = 0,
15623 FMT_DWL_W = 1,
15624 FMT_DWL_L = 2
15627 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15629 int extension = (ctx->opcode >> 6) & 0x3ff;
15630 uint32_t mips32_op;
15632 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15633 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15634 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15636 switch (extension) {
15637 case FLOAT_1BIT_FMT(CFC1, 0):
15638 mips32_op = OPC_CFC1;
15639 goto do_cp1;
15640 case FLOAT_1BIT_FMT(CTC1, 0):
15641 mips32_op = OPC_CTC1;
15642 goto do_cp1;
15643 case FLOAT_1BIT_FMT(MFC1, 0):
15644 mips32_op = OPC_MFC1;
15645 goto do_cp1;
15646 case FLOAT_1BIT_FMT(MTC1, 0):
15647 mips32_op = OPC_MTC1;
15648 goto do_cp1;
15649 case FLOAT_1BIT_FMT(MFHC1, 0):
15650 mips32_op = OPC_MFHC1;
15651 goto do_cp1;
15652 case FLOAT_1BIT_FMT(MTHC1, 0):
15653 mips32_op = OPC_MTHC1;
15654 do_cp1:
15655 gen_cp1(ctx, mips32_op, rt, rs);
15656 break;
15658 /* Reciprocal square root */
15659 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15660 mips32_op = OPC_RSQRT_S;
15661 goto do_unaryfp;
15662 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15663 mips32_op = OPC_RSQRT_D;
15664 goto do_unaryfp;
15666 /* Square root */
15667 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15668 mips32_op = OPC_SQRT_S;
15669 goto do_unaryfp;
15670 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15671 mips32_op = OPC_SQRT_D;
15672 goto do_unaryfp;
15674 /* Reciprocal */
15675 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15676 mips32_op = OPC_RECIP_S;
15677 goto do_unaryfp;
15678 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15679 mips32_op = OPC_RECIP_D;
15680 goto do_unaryfp;
15682 /* Floor */
15683 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15684 mips32_op = OPC_FLOOR_L_S;
15685 goto do_unaryfp;
15686 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15687 mips32_op = OPC_FLOOR_L_D;
15688 goto do_unaryfp;
15689 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15690 mips32_op = OPC_FLOOR_W_S;
15691 goto do_unaryfp;
15692 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15693 mips32_op = OPC_FLOOR_W_D;
15694 goto do_unaryfp;
15696 /* Ceiling */
15697 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15698 mips32_op = OPC_CEIL_L_S;
15699 goto do_unaryfp;
15700 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15701 mips32_op = OPC_CEIL_L_D;
15702 goto do_unaryfp;
15703 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15704 mips32_op = OPC_CEIL_W_S;
15705 goto do_unaryfp;
15706 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15707 mips32_op = OPC_CEIL_W_D;
15708 goto do_unaryfp;
15710 /* Truncation */
15711 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15712 mips32_op = OPC_TRUNC_L_S;
15713 goto do_unaryfp;
15714 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15715 mips32_op = OPC_TRUNC_L_D;
15716 goto do_unaryfp;
15717 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15718 mips32_op = OPC_TRUNC_W_S;
15719 goto do_unaryfp;
15720 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15721 mips32_op = OPC_TRUNC_W_D;
15722 goto do_unaryfp;
15724 /* Round */
15725 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15726 mips32_op = OPC_ROUND_L_S;
15727 goto do_unaryfp;
15728 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15729 mips32_op = OPC_ROUND_L_D;
15730 goto do_unaryfp;
15731 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15732 mips32_op = OPC_ROUND_W_S;
15733 goto do_unaryfp;
15734 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15735 mips32_op = OPC_ROUND_W_D;
15736 goto do_unaryfp;
15738 /* Integer to floating-point conversion */
15739 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15740 mips32_op = OPC_CVT_L_S;
15741 goto do_unaryfp;
15742 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15743 mips32_op = OPC_CVT_L_D;
15744 goto do_unaryfp;
15745 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15746 mips32_op = OPC_CVT_W_S;
15747 goto do_unaryfp;
15748 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15749 mips32_op = OPC_CVT_W_D;
15750 goto do_unaryfp;
15752 /* Paired-foo conversions */
15753 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15754 mips32_op = OPC_CVT_S_PL;
15755 goto do_unaryfp;
15756 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15757 mips32_op = OPC_CVT_S_PU;
15758 goto do_unaryfp;
15759 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15760 mips32_op = OPC_CVT_PW_PS;
15761 goto do_unaryfp;
15762 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15763 mips32_op = OPC_CVT_PS_PW;
15764 goto do_unaryfp;
15766 /* Floating-point moves */
15767 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15768 mips32_op = OPC_MOV_S;
15769 goto do_unaryfp;
15770 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15771 mips32_op = OPC_MOV_D;
15772 goto do_unaryfp;
15773 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15774 mips32_op = OPC_MOV_PS;
15775 goto do_unaryfp;
15777 /* Absolute value */
15778 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15779 mips32_op = OPC_ABS_S;
15780 goto do_unaryfp;
15781 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15782 mips32_op = OPC_ABS_D;
15783 goto do_unaryfp;
15784 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15785 mips32_op = OPC_ABS_PS;
15786 goto do_unaryfp;
15788 /* Negation */
15789 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15790 mips32_op = OPC_NEG_S;
15791 goto do_unaryfp;
15792 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15793 mips32_op = OPC_NEG_D;
15794 goto do_unaryfp;
15795 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15796 mips32_op = OPC_NEG_PS;
15797 goto do_unaryfp;
15799 /* Reciprocal square root step */
15800 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15801 mips32_op = OPC_RSQRT1_S;
15802 goto do_unaryfp;
15803 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15804 mips32_op = OPC_RSQRT1_D;
15805 goto do_unaryfp;
15806 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15807 mips32_op = OPC_RSQRT1_PS;
15808 goto do_unaryfp;
15810 /* Reciprocal step */
15811 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15812 mips32_op = OPC_RECIP1_S;
15813 goto do_unaryfp;
15814 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15815 mips32_op = OPC_RECIP1_S;
15816 goto do_unaryfp;
15817 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15818 mips32_op = OPC_RECIP1_PS;
15819 goto do_unaryfp;
15821 /* Conversions from double */
15822 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15823 mips32_op = OPC_CVT_D_S;
15824 goto do_unaryfp;
15825 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15826 mips32_op = OPC_CVT_D_W;
15827 goto do_unaryfp;
15828 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15829 mips32_op = OPC_CVT_D_L;
15830 goto do_unaryfp;
15832 /* Conversions from single */
15833 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15834 mips32_op = OPC_CVT_S_D;
15835 goto do_unaryfp;
15836 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15837 mips32_op = OPC_CVT_S_W;
15838 goto do_unaryfp;
15839 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15840 mips32_op = OPC_CVT_S_L;
15841 do_unaryfp:
15842 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15843 break;
15845 /* Conditional moves on floating-point codes */
15846 case COND_FLOAT_MOV(MOVT, 0):
15847 case COND_FLOAT_MOV(MOVT, 1):
15848 case COND_FLOAT_MOV(MOVT, 2):
15849 case COND_FLOAT_MOV(MOVT, 3):
15850 case COND_FLOAT_MOV(MOVT, 4):
15851 case COND_FLOAT_MOV(MOVT, 5):
15852 case COND_FLOAT_MOV(MOVT, 6):
15853 case COND_FLOAT_MOV(MOVT, 7):
15854 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15855 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15856 break;
15857 case COND_FLOAT_MOV(MOVF, 0):
15858 case COND_FLOAT_MOV(MOVF, 1):
15859 case COND_FLOAT_MOV(MOVF, 2):
15860 case COND_FLOAT_MOV(MOVF, 3):
15861 case COND_FLOAT_MOV(MOVF, 4):
15862 case COND_FLOAT_MOV(MOVF, 5):
15863 case COND_FLOAT_MOV(MOVF, 6):
15864 case COND_FLOAT_MOV(MOVF, 7):
15865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15866 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15867 break;
15868 default:
15869 MIPS_INVAL("pool32fxf");
15870 generate_exception_end(ctx, EXCP_RI);
15871 break;
15875 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15877 int32_t offset;
15878 uint16_t insn;
15879 int rt, rs, rd, rr;
15880 int16_t imm;
15881 uint32_t op, minor, minor2, mips32_op;
15882 uint32_t cond, fmt, cc;
15884 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15885 ctx->opcode = (ctx->opcode << 16) | insn;
15887 rt = (ctx->opcode >> 21) & 0x1f;
15888 rs = (ctx->opcode >> 16) & 0x1f;
15889 rd = (ctx->opcode >> 11) & 0x1f;
15890 rr = (ctx->opcode >> 6) & 0x1f;
15891 imm = (int16_t) ctx->opcode;
15893 op = (ctx->opcode >> 26) & 0x3f;
15894 switch (op) {
15895 case POOL32A:
15896 minor = ctx->opcode & 0x3f;
15897 switch (minor) {
15898 case 0x00:
15899 minor = (ctx->opcode >> 6) & 0xf;
15900 switch (minor) {
15901 case SLL32:
15902 mips32_op = OPC_SLL;
15903 goto do_shifti;
15904 case SRA:
15905 mips32_op = OPC_SRA;
15906 goto do_shifti;
15907 case SRL32:
15908 mips32_op = OPC_SRL;
15909 goto do_shifti;
15910 case ROTR:
15911 mips32_op = OPC_ROTR;
15912 do_shifti:
15913 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15914 break;
15915 case SELEQZ:
15916 check_insn(ctx, ISA_MIPS32R6);
15917 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15918 break;
15919 case SELNEZ:
15920 check_insn(ctx, ISA_MIPS32R6);
15921 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15922 break;
15923 case R6_RDHWR:
15924 check_insn(ctx, ISA_MIPS32R6);
15925 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15926 break;
15927 default:
15928 goto pool32a_invalid;
15930 break;
15931 case 0x10:
15932 minor = (ctx->opcode >> 6) & 0xf;
15933 switch (minor) {
15934 /* Arithmetic */
15935 case ADD:
15936 mips32_op = OPC_ADD;
15937 goto do_arith;
15938 case ADDU32:
15939 mips32_op = OPC_ADDU;
15940 goto do_arith;
15941 case SUB:
15942 mips32_op = OPC_SUB;
15943 goto do_arith;
15944 case SUBU32:
15945 mips32_op = OPC_SUBU;
15946 goto do_arith;
15947 case MUL:
15948 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15949 mips32_op = OPC_MUL;
15950 do_arith:
15951 gen_arith(ctx, mips32_op, rd, rs, rt);
15952 break;
15953 /* Shifts */
15954 case SLLV:
15955 mips32_op = OPC_SLLV;
15956 goto do_shift;
15957 case SRLV:
15958 mips32_op = OPC_SRLV;
15959 goto do_shift;
15960 case SRAV:
15961 mips32_op = OPC_SRAV;
15962 goto do_shift;
15963 case ROTRV:
15964 mips32_op = OPC_ROTRV;
15965 do_shift:
15966 gen_shift(ctx, mips32_op, rd, rs, rt);
15967 break;
15968 /* Logical operations */
15969 case AND:
15970 mips32_op = OPC_AND;
15971 goto do_logic;
15972 case OR32:
15973 mips32_op = OPC_OR;
15974 goto do_logic;
15975 case NOR:
15976 mips32_op = OPC_NOR;
15977 goto do_logic;
15978 case XOR32:
15979 mips32_op = OPC_XOR;
15980 do_logic:
15981 gen_logic(ctx, mips32_op, rd, rs, rt);
15982 break;
15983 /* Set less than */
15984 case SLT:
15985 mips32_op = OPC_SLT;
15986 goto do_slt;
15987 case SLTU:
15988 mips32_op = OPC_SLTU;
15989 do_slt:
15990 gen_slt(ctx, mips32_op, rd, rs, rt);
15991 break;
15992 default:
15993 goto pool32a_invalid;
15995 break;
15996 case 0x18:
15997 minor = (ctx->opcode >> 6) & 0xf;
15998 switch (minor) {
15999 /* Conditional moves */
16000 case MOVN: /* MUL */
16001 if (ctx->insn_flags & ISA_MIPS32R6) {
16002 /* MUL */
16003 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16004 } else {
16005 /* MOVN */
16006 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16008 break;
16009 case MOVZ: /* MUH */
16010 if (ctx->insn_flags & ISA_MIPS32R6) {
16011 /* MUH */
16012 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16013 } else {
16014 /* MOVZ */
16015 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16017 break;
16018 case MULU:
16019 check_insn(ctx, ISA_MIPS32R6);
16020 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16021 break;
16022 case MUHU:
16023 check_insn(ctx, ISA_MIPS32R6);
16024 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16025 break;
16026 case LWXS: /* DIV */
16027 if (ctx->insn_flags & ISA_MIPS32R6) {
16028 /* DIV */
16029 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16030 } else {
16031 /* LWXS */
16032 gen_ldxs(ctx, rs, rt, rd);
16034 break;
16035 case MOD:
16036 check_insn(ctx, ISA_MIPS32R6);
16037 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16038 break;
16039 case R6_DIVU:
16040 check_insn(ctx, ISA_MIPS32R6);
16041 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16042 break;
16043 case MODU:
16044 check_insn(ctx, ISA_MIPS32R6);
16045 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16046 break;
16047 default:
16048 goto pool32a_invalid;
16050 break;
16051 case INS:
16052 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16053 return;
16054 case LSA:
16055 check_insn(ctx, ISA_MIPS32R6);
16056 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16057 extract32(ctx->opcode, 9, 2));
16058 break;
16059 case ALIGN:
16060 check_insn(ctx, ISA_MIPS32R6);
16061 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16062 break;
16063 case EXT:
16064 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16065 return;
16066 case POOL32AXF:
16067 gen_pool32axf(env, ctx, rt, rs);
16068 break;
16069 case BREAK32:
16070 generate_exception_end(ctx, EXCP_BREAK);
16071 break;
16072 case SIGRIE:
16073 check_insn(ctx, ISA_MIPS32R6);
16074 generate_exception_end(ctx, EXCP_RI);
16075 break;
16076 default:
16077 pool32a_invalid:
16078 MIPS_INVAL("pool32a");
16079 generate_exception_end(ctx, EXCP_RI);
16080 break;
16082 break;
16083 case POOL32B:
16084 minor = (ctx->opcode >> 12) & 0xf;
16085 switch (minor) {
16086 case CACHE:
16087 check_cp0_enabled(ctx);
16088 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16089 gen_cache_operation(ctx, rt, rs, imm);
16091 break;
16092 case LWC2:
16093 case SWC2:
16094 /* COP2: Not implemented. */
16095 generate_exception_err(ctx, EXCP_CpU, 2);
16096 break;
16097 #ifdef TARGET_MIPS64
16098 case LDP:
16099 case SDP:
16100 check_insn(ctx, ISA_MIPS3);
16101 check_mips_64(ctx);
16102 #endif
16103 /* fall through */
16104 case LWP:
16105 case SWP:
16106 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16107 break;
16108 #ifdef TARGET_MIPS64
16109 case LDM:
16110 case SDM:
16111 check_insn(ctx, ISA_MIPS3);
16112 check_mips_64(ctx);
16113 #endif
16114 /* fall through */
16115 case LWM32:
16116 case SWM32:
16117 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16118 break;
16119 default:
16120 MIPS_INVAL("pool32b");
16121 generate_exception_end(ctx, EXCP_RI);
16122 break;
16124 break;
16125 case POOL32F:
16126 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16127 minor = ctx->opcode & 0x3f;
16128 check_cp1_enabled(ctx);
16129 switch (minor) {
16130 case ALNV_PS:
16131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16132 mips32_op = OPC_ALNV_PS;
16133 goto do_madd;
16134 case MADD_S:
16135 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16136 mips32_op = OPC_MADD_S;
16137 goto do_madd;
16138 case MADD_D:
16139 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16140 mips32_op = OPC_MADD_D;
16141 goto do_madd;
16142 case MADD_PS:
16143 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16144 mips32_op = OPC_MADD_PS;
16145 goto do_madd;
16146 case MSUB_S:
16147 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16148 mips32_op = OPC_MSUB_S;
16149 goto do_madd;
16150 case MSUB_D:
16151 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16152 mips32_op = OPC_MSUB_D;
16153 goto do_madd;
16154 case MSUB_PS:
16155 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16156 mips32_op = OPC_MSUB_PS;
16157 goto do_madd;
16158 case NMADD_S:
16159 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16160 mips32_op = OPC_NMADD_S;
16161 goto do_madd;
16162 case NMADD_D:
16163 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16164 mips32_op = OPC_NMADD_D;
16165 goto do_madd;
16166 case NMADD_PS:
16167 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16168 mips32_op = OPC_NMADD_PS;
16169 goto do_madd;
16170 case NMSUB_S:
16171 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16172 mips32_op = OPC_NMSUB_S;
16173 goto do_madd;
16174 case NMSUB_D:
16175 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16176 mips32_op = OPC_NMSUB_D;
16177 goto do_madd;
16178 case NMSUB_PS:
16179 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16180 mips32_op = OPC_NMSUB_PS;
16181 do_madd:
16182 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16183 break;
16184 case CABS_COND_FMT:
16185 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16186 cond = (ctx->opcode >> 6) & 0xf;
16187 cc = (ctx->opcode >> 13) & 0x7;
16188 fmt = (ctx->opcode >> 10) & 0x3;
16189 switch (fmt) {
16190 case 0x0:
16191 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16192 break;
16193 case 0x1:
16194 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16195 break;
16196 case 0x2:
16197 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16198 break;
16199 default:
16200 goto pool32f_invalid;
16202 break;
16203 case C_COND_FMT:
16204 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16205 cond = (ctx->opcode >> 6) & 0xf;
16206 cc = (ctx->opcode >> 13) & 0x7;
16207 fmt = (ctx->opcode >> 10) & 0x3;
16208 switch (fmt) {
16209 case 0x0:
16210 gen_cmp_s(ctx, cond, rt, rs, cc);
16211 break;
16212 case 0x1:
16213 gen_cmp_d(ctx, cond, rt, rs, cc);
16214 break;
16215 case 0x2:
16216 gen_cmp_ps(ctx, cond, rt, rs, cc);
16217 break;
16218 default:
16219 goto pool32f_invalid;
16221 break;
16222 case CMP_CONDN_S:
16223 check_insn(ctx, ISA_MIPS32R6);
16224 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16225 break;
16226 case CMP_CONDN_D:
16227 check_insn(ctx, ISA_MIPS32R6);
16228 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16229 break;
16230 case POOL32FXF:
16231 gen_pool32fxf(ctx, rt, rs);
16232 break;
16233 case 0x00:
16234 /* PLL foo */
16235 switch ((ctx->opcode >> 6) & 0x7) {
16236 case PLL_PS:
16237 mips32_op = OPC_PLL_PS;
16238 goto do_ps;
16239 case PLU_PS:
16240 mips32_op = OPC_PLU_PS;
16241 goto do_ps;
16242 case PUL_PS:
16243 mips32_op = OPC_PUL_PS;
16244 goto do_ps;
16245 case PUU_PS:
16246 mips32_op = OPC_PUU_PS;
16247 goto do_ps;
16248 case CVT_PS_S:
16249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16250 mips32_op = OPC_CVT_PS_S;
16251 do_ps:
16252 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16253 break;
16254 default:
16255 goto pool32f_invalid;
16257 break;
16258 case MIN_FMT:
16259 check_insn(ctx, ISA_MIPS32R6);
16260 switch ((ctx->opcode >> 9) & 0x3) {
16261 case FMT_SDPS_S:
16262 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16263 break;
16264 case FMT_SDPS_D:
16265 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16266 break;
16267 default:
16268 goto pool32f_invalid;
16270 break;
16271 case 0x08:
16272 /* [LS][WDU]XC1 */
16273 switch ((ctx->opcode >> 6) & 0x7) {
16274 case LWXC1:
16275 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16276 mips32_op = OPC_LWXC1;
16277 goto do_ldst_cp1;
16278 case SWXC1:
16279 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16280 mips32_op = OPC_SWXC1;
16281 goto do_ldst_cp1;
16282 case LDXC1:
16283 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16284 mips32_op = OPC_LDXC1;
16285 goto do_ldst_cp1;
16286 case SDXC1:
16287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16288 mips32_op = OPC_SDXC1;
16289 goto do_ldst_cp1;
16290 case LUXC1:
16291 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16292 mips32_op = OPC_LUXC1;
16293 goto do_ldst_cp1;
16294 case SUXC1:
16295 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16296 mips32_op = OPC_SUXC1;
16297 do_ldst_cp1:
16298 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16299 break;
16300 default:
16301 goto pool32f_invalid;
16303 break;
16304 case MAX_FMT:
16305 check_insn(ctx, ISA_MIPS32R6);
16306 switch ((ctx->opcode >> 9) & 0x3) {
16307 case FMT_SDPS_S:
16308 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16309 break;
16310 case FMT_SDPS_D:
16311 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16312 break;
16313 default:
16314 goto pool32f_invalid;
16316 break;
16317 case 0x18:
16318 /* 3D insns */
16319 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16320 fmt = (ctx->opcode >> 9) & 0x3;
16321 switch ((ctx->opcode >> 6) & 0x7) {
16322 case RSQRT2_FMT:
16323 switch (fmt) {
16324 case FMT_SDPS_S:
16325 mips32_op = OPC_RSQRT2_S;
16326 goto do_3d;
16327 case FMT_SDPS_D:
16328 mips32_op = OPC_RSQRT2_D;
16329 goto do_3d;
16330 case FMT_SDPS_PS:
16331 mips32_op = OPC_RSQRT2_PS;
16332 goto do_3d;
16333 default:
16334 goto pool32f_invalid;
16336 break;
16337 case RECIP2_FMT:
16338 switch (fmt) {
16339 case FMT_SDPS_S:
16340 mips32_op = OPC_RECIP2_S;
16341 goto do_3d;
16342 case FMT_SDPS_D:
16343 mips32_op = OPC_RECIP2_D;
16344 goto do_3d;
16345 case FMT_SDPS_PS:
16346 mips32_op = OPC_RECIP2_PS;
16347 goto do_3d;
16348 default:
16349 goto pool32f_invalid;
16351 break;
16352 case ADDR_PS:
16353 mips32_op = OPC_ADDR_PS;
16354 goto do_3d;
16355 case MULR_PS:
16356 mips32_op = OPC_MULR_PS;
16357 do_3d:
16358 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16359 break;
16360 default:
16361 goto pool32f_invalid;
16363 break;
16364 case 0x20:
16365 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16366 cc = (ctx->opcode >> 13) & 0x7;
16367 fmt = (ctx->opcode >> 9) & 0x3;
16368 switch ((ctx->opcode >> 6) & 0x7) {
16369 case MOVF_FMT: /* RINT_FMT */
16370 if (ctx->insn_flags & ISA_MIPS32R6) {
16371 /* RINT_FMT */
16372 switch (fmt) {
16373 case FMT_SDPS_S:
16374 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16375 break;
16376 case FMT_SDPS_D:
16377 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16378 break;
16379 default:
16380 goto pool32f_invalid;
16382 } else {
16383 /* MOVF_FMT */
16384 switch (fmt) {
16385 case FMT_SDPS_S:
16386 gen_movcf_s(ctx, rs, rt, cc, 0);
16387 break;
16388 case FMT_SDPS_D:
16389 gen_movcf_d(ctx, rs, rt, cc, 0);
16390 break;
16391 case FMT_SDPS_PS:
16392 check_ps(ctx);
16393 gen_movcf_ps(ctx, rs, rt, cc, 0);
16394 break;
16395 default:
16396 goto pool32f_invalid;
16399 break;
16400 case MOVT_FMT: /* CLASS_FMT */
16401 if (ctx->insn_flags & ISA_MIPS32R6) {
16402 /* CLASS_FMT */
16403 switch (fmt) {
16404 case FMT_SDPS_S:
16405 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16406 break;
16407 case FMT_SDPS_D:
16408 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16409 break;
16410 default:
16411 goto pool32f_invalid;
16413 } else {
16414 /* MOVT_FMT */
16415 switch (fmt) {
16416 case FMT_SDPS_S:
16417 gen_movcf_s(ctx, rs, rt, cc, 1);
16418 break;
16419 case FMT_SDPS_D:
16420 gen_movcf_d(ctx, rs, rt, cc, 1);
16421 break;
16422 case FMT_SDPS_PS:
16423 check_ps(ctx);
16424 gen_movcf_ps(ctx, rs, rt, cc, 1);
16425 break;
16426 default:
16427 goto pool32f_invalid;
16430 break;
16431 case PREFX:
16432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16433 break;
16434 default:
16435 goto pool32f_invalid;
16437 break;
16438 #define FINSN_3ARG_SDPS(prfx) \
16439 switch ((ctx->opcode >> 8) & 0x3) { \
16440 case FMT_SDPS_S: \
16441 mips32_op = OPC_##prfx##_S; \
16442 goto do_fpop; \
16443 case FMT_SDPS_D: \
16444 mips32_op = OPC_##prfx##_D; \
16445 goto do_fpop; \
16446 case FMT_SDPS_PS: \
16447 check_ps(ctx); \
16448 mips32_op = OPC_##prfx##_PS; \
16449 goto do_fpop; \
16450 default: \
16451 goto pool32f_invalid; \
16453 case MINA_FMT:
16454 check_insn(ctx, ISA_MIPS32R6);
16455 switch ((ctx->opcode >> 9) & 0x3) {
16456 case FMT_SDPS_S:
16457 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16458 break;
16459 case FMT_SDPS_D:
16460 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16461 break;
16462 default:
16463 goto pool32f_invalid;
16465 break;
16466 case MAXA_FMT:
16467 check_insn(ctx, ISA_MIPS32R6);
16468 switch ((ctx->opcode >> 9) & 0x3) {
16469 case FMT_SDPS_S:
16470 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16471 break;
16472 case FMT_SDPS_D:
16473 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16474 break;
16475 default:
16476 goto pool32f_invalid;
16478 break;
16479 case 0x30:
16480 /* regular FP ops */
16481 switch ((ctx->opcode >> 6) & 0x3) {
16482 case ADD_FMT:
16483 FINSN_3ARG_SDPS(ADD);
16484 break;
16485 case SUB_FMT:
16486 FINSN_3ARG_SDPS(SUB);
16487 break;
16488 case MUL_FMT:
16489 FINSN_3ARG_SDPS(MUL);
16490 break;
16491 case DIV_FMT:
16492 fmt = (ctx->opcode >> 8) & 0x3;
16493 if (fmt == 1) {
16494 mips32_op = OPC_DIV_D;
16495 } else if (fmt == 0) {
16496 mips32_op = OPC_DIV_S;
16497 } else {
16498 goto pool32f_invalid;
16500 goto do_fpop;
16501 default:
16502 goto pool32f_invalid;
16504 break;
16505 case 0x38:
16506 /* cmovs */
16507 switch ((ctx->opcode >> 6) & 0x7) {
16508 case MOVN_FMT: /* SELEQZ_FMT */
16509 if (ctx->insn_flags & ISA_MIPS32R6) {
16510 /* SELEQZ_FMT */
16511 switch ((ctx->opcode >> 9) & 0x3) {
16512 case FMT_SDPS_S:
16513 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16514 break;
16515 case FMT_SDPS_D:
16516 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16517 break;
16518 default:
16519 goto pool32f_invalid;
16521 } else {
16522 /* MOVN_FMT */
16523 FINSN_3ARG_SDPS(MOVN);
16525 break;
16526 case MOVN_FMT_04:
16527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16528 FINSN_3ARG_SDPS(MOVN);
16529 break;
16530 case MOVZ_FMT: /* SELNEZ_FMT */
16531 if (ctx->insn_flags & ISA_MIPS32R6) {
16532 /* SELNEZ_FMT */
16533 switch ((ctx->opcode >> 9) & 0x3) {
16534 case FMT_SDPS_S:
16535 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16536 break;
16537 case FMT_SDPS_D:
16538 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16539 break;
16540 default:
16541 goto pool32f_invalid;
16543 } else {
16544 /* MOVZ_FMT */
16545 FINSN_3ARG_SDPS(MOVZ);
16547 break;
16548 case MOVZ_FMT_05:
16549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16550 FINSN_3ARG_SDPS(MOVZ);
16551 break;
16552 case SEL_FMT:
16553 check_insn(ctx, ISA_MIPS32R6);
16554 switch ((ctx->opcode >> 9) & 0x3) {
16555 case FMT_SDPS_S:
16556 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16557 break;
16558 case FMT_SDPS_D:
16559 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16560 break;
16561 default:
16562 goto pool32f_invalid;
16564 break;
16565 case MADDF_FMT:
16566 check_insn(ctx, ISA_MIPS32R6);
16567 switch ((ctx->opcode >> 9) & 0x3) {
16568 case FMT_SDPS_S:
16569 mips32_op = OPC_MADDF_S;
16570 goto do_fpop;
16571 case FMT_SDPS_D:
16572 mips32_op = OPC_MADDF_D;
16573 goto do_fpop;
16574 default:
16575 goto pool32f_invalid;
16577 break;
16578 case MSUBF_FMT:
16579 check_insn(ctx, ISA_MIPS32R6);
16580 switch ((ctx->opcode >> 9) & 0x3) {
16581 case FMT_SDPS_S:
16582 mips32_op = OPC_MSUBF_S;
16583 goto do_fpop;
16584 case FMT_SDPS_D:
16585 mips32_op = OPC_MSUBF_D;
16586 goto do_fpop;
16587 default:
16588 goto pool32f_invalid;
16590 break;
16591 default:
16592 goto pool32f_invalid;
16594 break;
16595 do_fpop:
16596 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16597 break;
16598 default:
16599 pool32f_invalid:
16600 MIPS_INVAL("pool32f");
16601 generate_exception_end(ctx, EXCP_RI);
16602 break;
16604 } else {
16605 generate_exception_err(ctx, EXCP_CpU, 1);
16607 break;
16608 case POOL32I:
16609 minor = (ctx->opcode >> 21) & 0x1f;
16610 switch (minor) {
16611 case BLTZ:
16612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16613 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16614 break;
16615 case BLTZAL:
16616 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16617 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16618 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16619 break;
16620 case BLTZALS:
16621 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16622 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16623 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16624 break;
16625 case BGEZ:
16626 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16627 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16628 break;
16629 case BGEZAL:
16630 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16631 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16632 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16633 break;
16634 case BGEZALS:
16635 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16636 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16637 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16638 break;
16639 case BLEZ:
16640 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16641 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16642 break;
16643 case BGTZ:
16644 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16645 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16646 break;
16648 /* Traps */
16649 case TLTI: /* BC1EQZC */
16650 if (ctx->insn_flags & ISA_MIPS32R6) {
16651 /* BC1EQZC */
16652 check_cp1_enabled(ctx);
16653 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16654 } else {
16655 /* TLTI */
16656 mips32_op = OPC_TLTI;
16657 goto do_trapi;
16659 break;
16660 case TGEI: /* BC1NEZC */
16661 if (ctx->insn_flags & ISA_MIPS32R6) {
16662 /* BC1NEZC */
16663 check_cp1_enabled(ctx);
16664 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16665 } else {
16666 /* TGEI */
16667 mips32_op = OPC_TGEI;
16668 goto do_trapi;
16670 break;
16671 case TLTIU:
16672 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16673 mips32_op = OPC_TLTIU;
16674 goto do_trapi;
16675 case TGEIU:
16676 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16677 mips32_op = OPC_TGEIU;
16678 goto do_trapi;
16679 case TNEI: /* SYNCI */
16680 if (ctx->insn_flags & ISA_MIPS32R6) {
16681 /* SYNCI */
16682 /* Break the TB to be able to sync copied instructions
16683 immediately */
16684 ctx->base.is_jmp = DISAS_STOP;
16685 } else {
16686 /* TNEI */
16687 mips32_op = OPC_TNEI;
16688 goto do_trapi;
16690 break;
16691 case TEQI:
16692 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16693 mips32_op = OPC_TEQI;
16694 do_trapi:
16695 gen_trap(ctx, mips32_op, rs, -1, imm);
16696 break;
16698 case BNEZC:
16699 case BEQZC:
16700 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16701 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16702 4, rs, 0, imm << 1, 0);
16703 /* Compact branches don't have a delay slot, so just let
16704 the normal delay slot handling take us to the branch
16705 target. */
16706 break;
16707 case LUI:
16708 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16709 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16710 break;
16711 case SYNCI:
16712 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16713 /* Break the TB to be able to sync copied instructions
16714 immediately */
16715 ctx->base.is_jmp = DISAS_STOP;
16716 break;
16717 case BC2F:
16718 case BC2T:
16719 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16720 /* COP2: Not implemented. */
16721 generate_exception_err(ctx, EXCP_CpU, 2);
16722 break;
16723 case BC1F:
16724 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16725 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16726 goto do_cp1branch;
16727 case BC1T:
16728 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16729 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16730 goto do_cp1branch;
16731 case BC1ANY4F:
16732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16733 mips32_op = OPC_BC1FANY4;
16734 goto do_cp1mips3d;
16735 case BC1ANY4T:
16736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16737 mips32_op = OPC_BC1TANY4;
16738 do_cp1mips3d:
16739 check_cop1x(ctx);
16740 check_insn(ctx, ASE_MIPS3D);
16741 /* Fall through */
16742 do_cp1branch:
16743 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16744 check_cp1_enabled(ctx);
16745 gen_compute_branch1(ctx, mips32_op,
16746 (ctx->opcode >> 18) & 0x7, imm << 1);
16747 } else {
16748 generate_exception_err(ctx, EXCP_CpU, 1);
16750 break;
16751 case BPOSGE64:
16752 case BPOSGE32:
16753 /* MIPS DSP: not implemented */
16754 /* Fall through */
16755 default:
16756 MIPS_INVAL("pool32i");
16757 generate_exception_end(ctx, EXCP_RI);
16758 break;
16760 break;
16761 case POOL32C:
16762 minor = (ctx->opcode >> 12) & 0xf;
16763 offset = sextract32(ctx->opcode, 0,
16764 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16765 switch (minor) {
16766 case LWL:
16767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16768 mips32_op = OPC_LWL;
16769 goto do_ld_lr;
16770 case SWL:
16771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16772 mips32_op = OPC_SWL;
16773 goto do_st_lr;
16774 case LWR:
16775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16776 mips32_op = OPC_LWR;
16777 goto do_ld_lr;
16778 case SWR:
16779 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16780 mips32_op = OPC_SWR;
16781 goto do_st_lr;
16782 #if defined(TARGET_MIPS64)
16783 case LDL:
16784 check_insn(ctx, ISA_MIPS3);
16785 check_mips_64(ctx);
16786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16787 mips32_op = OPC_LDL;
16788 goto do_ld_lr;
16789 case SDL:
16790 check_insn(ctx, ISA_MIPS3);
16791 check_mips_64(ctx);
16792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16793 mips32_op = OPC_SDL;
16794 goto do_st_lr;
16795 case LDR:
16796 check_insn(ctx, ISA_MIPS3);
16797 check_mips_64(ctx);
16798 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16799 mips32_op = OPC_LDR;
16800 goto do_ld_lr;
16801 case SDR:
16802 check_insn(ctx, ISA_MIPS3);
16803 check_mips_64(ctx);
16804 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16805 mips32_op = OPC_SDR;
16806 goto do_st_lr;
16807 case LWU:
16808 check_insn(ctx, ISA_MIPS3);
16809 check_mips_64(ctx);
16810 mips32_op = OPC_LWU;
16811 goto do_ld_lr;
16812 case LLD:
16813 check_insn(ctx, ISA_MIPS3);
16814 check_mips_64(ctx);
16815 mips32_op = OPC_LLD;
16816 goto do_ld_lr;
16817 #endif
16818 case LL:
16819 mips32_op = OPC_LL;
16820 goto do_ld_lr;
16821 do_ld_lr:
16822 gen_ld(ctx, mips32_op, rt, rs, offset);
16823 break;
16824 do_st_lr:
16825 gen_st(ctx, mips32_op, rt, rs, offset);
16826 break;
16827 case SC:
16828 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16829 break;
16830 #if defined(TARGET_MIPS64)
16831 case SCD:
16832 check_insn(ctx, ISA_MIPS3);
16833 check_mips_64(ctx);
16834 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16835 break;
16836 #endif
16837 case LD_EVA:
16838 if (!ctx->eva) {
16839 MIPS_INVAL("pool32c ld-eva");
16840 generate_exception_end(ctx, EXCP_RI);
16841 break;
16843 check_cp0_enabled(ctx);
16845 minor2 = (ctx->opcode >> 9) & 0x7;
16846 offset = sextract32(ctx->opcode, 0, 9);
16847 switch (minor2) {
16848 case LBUE:
16849 mips32_op = OPC_LBUE;
16850 goto do_ld_lr;
16851 case LHUE:
16852 mips32_op = OPC_LHUE;
16853 goto do_ld_lr;
16854 case LWLE:
16855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16856 mips32_op = OPC_LWLE;
16857 goto do_ld_lr;
16858 case LWRE:
16859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16860 mips32_op = OPC_LWRE;
16861 goto do_ld_lr;
16862 case LBE:
16863 mips32_op = OPC_LBE;
16864 goto do_ld_lr;
16865 case LHE:
16866 mips32_op = OPC_LHE;
16867 goto do_ld_lr;
16868 case LLE:
16869 mips32_op = OPC_LLE;
16870 goto do_ld_lr;
16871 case LWE:
16872 mips32_op = OPC_LWE;
16873 goto do_ld_lr;
16875 break;
16876 case ST_EVA:
16877 if (!ctx->eva) {
16878 MIPS_INVAL("pool32c st-eva");
16879 generate_exception_end(ctx, EXCP_RI);
16880 break;
16882 check_cp0_enabled(ctx);
16884 minor2 = (ctx->opcode >> 9) & 0x7;
16885 offset = sextract32(ctx->opcode, 0, 9);
16886 switch (minor2) {
16887 case SWLE:
16888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16889 mips32_op = OPC_SWLE;
16890 goto do_st_lr;
16891 case SWRE:
16892 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16893 mips32_op = OPC_SWRE;
16894 goto do_st_lr;
16895 case PREFE:
16896 /* Treat as no-op */
16897 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16898 /* hint codes 24-31 are reserved and signal RI */
16899 generate_exception(ctx, EXCP_RI);
16901 break;
16902 case CACHEE:
16903 /* Treat as no-op */
16904 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16905 gen_cache_operation(ctx, rt, rs, offset);
16907 break;
16908 case SBE:
16909 mips32_op = OPC_SBE;
16910 goto do_st_lr;
16911 case SHE:
16912 mips32_op = OPC_SHE;
16913 goto do_st_lr;
16914 case SCE:
16915 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16916 break;
16917 case SWE:
16918 mips32_op = OPC_SWE;
16919 goto do_st_lr;
16921 break;
16922 case PREF:
16923 /* Treat as no-op */
16924 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16925 /* hint codes 24-31 are reserved and signal RI */
16926 generate_exception(ctx, EXCP_RI);
16928 break;
16929 default:
16930 MIPS_INVAL("pool32c");
16931 generate_exception_end(ctx, EXCP_RI);
16932 break;
16934 break;
16935 case ADDI32: /* AUI, LUI */
16936 if (ctx->insn_flags & ISA_MIPS32R6) {
16937 /* AUI, LUI */
16938 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16939 } else {
16940 /* ADDI32 */
16941 mips32_op = OPC_ADDI;
16942 goto do_addi;
16944 break;
16945 case ADDIU32:
16946 mips32_op = OPC_ADDIU;
16947 do_addi:
16948 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16949 break;
16951 /* Logical operations */
16952 case ORI32:
16953 mips32_op = OPC_ORI;
16954 goto do_logici;
16955 case XORI32:
16956 mips32_op = OPC_XORI;
16957 goto do_logici;
16958 case ANDI32:
16959 mips32_op = OPC_ANDI;
16960 do_logici:
16961 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16962 break;
16964 /* Set less than immediate */
16965 case SLTI32:
16966 mips32_op = OPC_SLTI;
16967 goto do_slti;
16968 case SLTIU32:
16969 mips32_op = OPC_SLTIU;
16970 do_slti:
16971 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16972 break;
16973 case JALX32:
16974 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16975 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16976 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16977 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16978 break;
16979 case JALS32: /* BOVC, BEQC, BEQZALC */
16980 if (ctx->insn_flags & ISA_MIPS32R6) {
16981 if (rs >= rt) {
16982 /* BOVC */
16983 mips32_op = OPC_BOVC;
16984 } else if (rs < rt && rs == 0) {
16985 /* BEQZALC */
16986 mips32_op = OPC_BEQZALC;
16987 } else {
16988 /* BEQC */
16989 mips32_op = OPC_BEQC;
16991 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16992 } else {
16993 /* JALS32 */
16994 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16995 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16996 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16998 break;
16999 case BEQ32: /* BC */
17000 if (ctx->insn_flags & ISA_MIPS32R6) {
17001 /* BC */
17002 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17003 sextract32(ctx->opcode << 1, 0, 27));
17004 } else {
17005 /* BEQ32 */
17006 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17008 break;
17009 case BNE32: /* BALC */
17010 if (ctx->insn_flags & ISA_MIPS32R6) {
17011 /* BALC */
17012 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17013 sextract32(ctx->opcode << 1, 0, 27));
17014 } else {
17015 /* BNE32 */
17016 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17018 break;
17019 case J32: /* BGTZC, BLTZC, BLTC */
17020 if (ctx->insn_flags & ISA_MIPS32R6) {
17021 if (rs == 0 && rt != 0) {
17022 /* BGTZC */
17023 mips32_op = OPC_BGTZC;
17024 } else if (rs != 0 && rt != 0 && rs == rt) {
17025 /* BLTZC */
17026 mips32_op = OPC_BLTZC;
17027 } else {
17028 /* BLTC */
17029 mips32_op = OPC_BLTC;
17031 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17032 } else {
17033 /* J32 */
17034 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17035 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17037 break;
17038 case JAL32: /* BLEZC, BGEZC, BGEC */
17039 if (ctx->insn_flags & ISA_MIPS32R6) {
17040 if (rs == 0 && rt != 0) {
17041 /* BLEZC */
17042 mips32_op = OPC_BLEZC;
17043 } else if (rs != 0 && rt != 0 && rs == rt) {
17044 /* BGEZC */
17045 mips32_op = OPC_BGEZC;
17046 } else {
17047 /* BGEC */
17048 mips32_op = OPC_BGEC;
17050 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17051 } else {
17052 /* JAL32 */
17053 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17054 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17055 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17057 break;
17058 /* Floating point (COP1) */
17059 case LWC132:
17060 mips32_op = OPC_LWC1;
17061 goto do_cop1;
17062 case LDC132:
17063 mips32_op = OPC_LDC1;
17064 goto do_cop1;
17065 case SWC132:
17066 mips32_op = OPC_SWC1;
17067 goto do_cop1;
17068 case SDC132:
17069 mips32_op = OPC_SDC1;
17070 do_cop1:
17071 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17072 break;
17073 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17074 if (ctx->insn_flags & ISA_MIPS32R6) {
17075 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17076 switch ((ctx->opcode >> 16) & 0x1f) {
17077 case ADDIUPC_00:
17078 case ADDIUPC_01:
17079 case ADDIUPC_02:
17080 case ADDIUPC_03:
17081 case ADDIUPC_04:
17082 case ADDIUPC_05:
17083 case ADDIUPC_06:
17084 case ADDIUPC_07:
17085 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17086 break;
17087 case AUIPC:
17088 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17089 break;
17090 case ALUIPC:
17091 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17092 break;
17093 case LWPC_08:
17094 case LWPC_09:
17095 case LWPC_0A:
17096 case LWPC_0B:
17097 case LWPC_0C:
17098 case LWPC_0D:
17099 case LWPC_0E:
17100 case LWPC_0F:
17101 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17102 break;
17103 default:
17104 generate_exception(ctx, EXCP_RI);
17105 break;
17107 } else {
17108 /* ADDIUPC */
17109 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17110 offset = SIMM(ctx->opcode, 0, 23) << 2;
17112 gen_addiupc(ctx, reg, offset, 0, 0);
17114 break;
17115 case BNVC: /* BNEC, BNEZALC */
17116 check_insn(ctx, ISA_MIPS32R6);
17117 if (rs >= rt) {
17118 /* BNVC */
17119 mips32_op = OPC_BNVC;
17120 } else if (rs < rt && rs == 0) {
17121 /* BNEZALC */
17122 mips32_op = OPC_BNEZALC;
17123 } else {
17124 /* BNEC */
17125 mips32_op = OPC_BNEC;
17127 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17128 break;
17129 case R6_BNEZC: /* JIALC */
17130 check_insn(ctx, ISA_MIPS32R6);
17131 if (rt != 0) {
17132 /* BNEZC */
17133 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17134 sextract32(ctx->opcode << 1, 0, 22));
17135 } else {
17136 /* JIALC */
17137 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17139 break;
17140 case R6_BEQZC: /* JIC */
17141 check_insn(ctx, ISA_MIPS32R6);
17142 if (rt != 0) {
17143 /* BEQZC */
17144 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17145 sextract32(ctx->opcode << 1, 0, 22));
17146 } else {
17147 /* JIC */
17148 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17150 break;
17151 case BLEZALC: /* BGEZALC, BGEUC */
17152 check_insn(ctx, ISA_MIPS32R6);
17153 if (rs == 0 && rt != 0) {
17154 /* BLEZALC */
17155 mips32_op = OPC_BLEZALC;
17156 } else if (rs != 0 && rt != 0 && rs == rt) {
17157 /* BGEZALC */
17158 mips32_op = OPC_BGEZALC;
17159 } else {
17160 /* BGEUC */
17161 mips32_op = OPC_BGEUC;
17163 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17164 break;
17165 case BGTZALC: /* BLTZALC, BLTUC */
17166 check_insn(ctx, ISA_MIPS32R6);
17167 if (rs == 0 && rt != 0) {
17168 /* BGTZALC */
17169 mips32_op = OPC_BGTZALC;
17170 } else if (rs != 0 && rt != 0 && rs == rt) {
17171 /* BLTZALC */
17172 mips32_op = OPC_BLTZALC;
17173 } else {
17174 /* BLTUC */
17175 mips32_op = OPC_BLTUC;
17177 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17178 break;
17179 /* Loads and stores */
17180 case LB32:
17181 mips32_op = OPC_LB;
17182 goto do_ld;
17183 case LBU32:
17184 mips32_op = OPC_LBU;
17185 goto do_ld;
17186 case LH32:
17187 mips32_op = OPC_LH;
17188 goto do_ld;
17189 case LHU32:
17190 mips32_op = OPC_LHU;
17191 goto do_ld;
17192 case LW32:
17193 mips32_op = OPC_LW;
17194 goto do_ld;
17195 #ifdef TARGET_MIPS64
17196 case LD32:
17197 check_insn(ctx, ISA_MIPS3);
17198 check_mips_64(ctx);
17199 mips32_op = OPC_LD;
17200 goto do_ld;
17201 case SD32:
17202 check_insn(ctx, ISA_MIPS3);
17203 check_mips_64(ctx);
17204 mips32_op = OPC_SD;
17205 goto do_st;
17206 #endif
17207 case SB32:
17208 mips32_op = OPC_SB;
17209 goto do_st;
17210 case SH32:
17211 mips32_op = OPC_SH;
17212 goto do_st;
17213 case SW32:
17214 mips32_op = OPC_SW;
17215 goto do_st;
17216 do_ld:
17217 gen_ld(ctx, mips32_op, rt, rs, imm);
17218 break;
17219 do_st:
17220 gen_st(ctx, mips32_op, rt, rs, imm);
17221 break;
17222 default:
17223 generate_exception_end(ctx, EXCP_RI);
17224 break;
17228 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
17230 uint32_t op;
17232 /* make sure instructions are on a halfword boundary */
17233 if (ctx->base.pc_next & 0x1) {
17234 env->CP0_BadVAddr = ctx->base.pc_next;
17235 generate_exception_end(ctx, EXCP_AdEL);
17236 return 2;
17239 op = (ctx->opcode >> 10) & 0x3f;
17240 /* Enforce properly-sized instructions in a delay slot */
17241 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17242 switch (op & 0x7) { /* MSB-3..MSB-5 */
17243 case 0:
17244 /* POOL32A, POOL32B, POOL32I, POOL32C */
17245 case 4:
17246 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17247 case 5:
17248 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17249 case 6:
17250 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17251 case 7:
17252 /* LB32, LH32, LWC132, LDC132, LW32 */
17253 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17254 generate_exception_end(ctx, EXCP_RI);
17255 return 2;
17257 break;
17258 case 1:
17259 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17260 case 2:
17261 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17262 case 3:
17263 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17264 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17265 generate_exception_end(ctx, EXCP_RI);
17266 return 2;
17268 break;
17272 switch (op) {
17273 case POOL16A:
17275 int rd = mmreg(uMIPS_RD(ctx->opcode));
17276 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17277 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17278 uint32_t opc = 0;
17280 switch (ctx->opcode & 0x1) {
17281 case ADDU16:
17282 opc = OPC_ADDU;
17283 break;
17284 case SUBU16:
17285 opc = OPC_SUBU;
17286 break;
17288 if (ctx->insn_flags & ISA_MIPS32R6) {
17289 /* In the Release 6 the register number location in
17290 * the instruction encoding has changed.
17292 gen_arith(ctx, opc, rs1, rd, rs2);
17293 } else {
17294 gen_arith(ctx, opc, rd, rs1, rs2);
17297 break;
17298 case POOL16B:
17300 int rd = mmreg(uMIPS_RD(ctx->opcode));
17301 int rs = mmreg(uMIPS_RS(ctx->opcode));
17302 int amount = (ctx->opcode >> 1) & 0x7;
17303 uint32_t opc = 0;
17304 amount = amount == 0 ? 8 : amount;
17306 switch (ctx->opcode & 0x1) {
17307 case SLL16:
17308 opc = OPC_SLL;
17309 break;
17310 case SRL16:
17311 opc = OPC_SRL;
17312 break;
17315 gen_shift_imm(ctx, opc, rd, rs, amount);
17317 break;
17318 case POOL16C:
17319 if (ctx->insn_flags & ISA_MIPS32R6) {
17320 gen_pool16c_r6_insn(ctx);
17321 } else {
17322 gen_pool16c_insn(ctx);
17324 break;
17325 case LWGP16:
17327 int rd = mmreg(uMIPS_RD(ctx->opcode));
17328 int rb = 28; /* GP */
17329 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17331 gen_ld(ctx, OPC_LW, rd, rb, offset);
17333 break;
17334 case POOL16F:
17335 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17336 if (ctx->opcode & 1) {
17337 generate_exception_end(ctx, EXCP_RI);
17338 } else {
17339 /* MOVEP */
17340 int enc_dest = uMIPS_RD(ctx->opcode);
17341 int enc_rt = uMIPS_RS2(ctx->opcode);
17342 int enc_rs = uMIPS_RS1(ctx->opcode);
17343 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17345 break;
17346 case LBU16:
17348 int rd = mmreg(uMIPS_RD(ctx->opcode));
17349 int rb = mmreg(uMIPS_RS(ctx->opcode));
17350 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17351 offset = (offset == 0xf ? -1 : offset);
17353 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17355 break;
17356 case LHU16:
17358 int rd = mmreg(uMIPS_RD(ctx->opcode));
17359 int rb = mmreg(uMIPS_RS(ctx->opcode));
17360 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17362 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17364 break;
17365 case LWSP16:
17367 int rd = (ctx->opcode >> 5) & 0x1f;
17368 int rb = 29; /* SP */
17369 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17371 gen_ld(ctx, OPC_LW, rd, rb, offset);
17373 break;
17374 case LW16:
17376 int rd = mmreg(uMIPS_RD(ctx->opcode));
17377 int rb = mmreg(uMIPS_RS(ctx->opcode));
17378 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17380 gen_ld(ctx, OPC_LW, rd, rb, offset);
17382 break;
17383 case SB16:
17385 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17386 int rb = mmreg(uMIPS_RS(ctx->opcode));
17387 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17389 gen_st(ctx, OPC_SB, rd, rb, offset);
17391 break;
17392 case SH16:
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) << 1;
17398 gen_st(ctx, OPC_SH, rd, rb, offset);
17400 break;
17401 case SWSP16:
17403 int rd = (ctx->opcode >> 5) & 0x1f;
17404 int rb = 29; /* SP */
17405 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17407 gen_st(ctx, OPC_SW, rd, rb, offset);
17409 break;
17410 case SW16:
17412 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17413 int rb = mmreg(uMIPS_RS(ctx->opcode));
17414 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17416 gen_st(ctx, OPC_SW, rd, rb, offset);
17418 break;
17419 case MOVE16:
17421 int rd = uMIPS_RD5(ctx->opcode);
17422 int rs = uMIPS_RS5(ctx->opcode);
17424 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17426 break;
17427 case ANDI16:
17428 gen_andi16(ctx);
17429 break;
17430 case POOL16D:
17431 switch (ctx->opcode & 0x1) {
17432 case ADDIUS5:
17433 gen_addius5(ctx);
17434 break;
17435 case ADDIUSP:
17436 gen_addiusp(ctx);
17437 break;
17439 break;
17440 case POOL16E:
17441 switch (ctx->opcode & 0x1) {
17442 case ADDIUR2:
17443 gen_addiur2(ctx);
17444 break;
17445 case ADDIUR1SP:
17446 gen_addiur1sp(ctx);
17447 break;
17449 break;
17450 case B16: /* BC16 */
17451 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17452 sextract32(ctx->opcode, 0, 10) << 1,
17453 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17454 break;
17455 case BNEZ16: /* BNEZC16 */
17456 case BEQZ16: /* BEQZC16 */
17457 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17458 mmreg(uMIPS_RD(ctx->opcode)),
17459 0, sextract32(ctx->opcode, 0, 7) << 1,
17460 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17462 break;
17463 case LI16:
17465 int reg = mmreg(uMIPS_RD(ctx->opcode));
17466 int imm = ZIMM(ctx->opcode, 0, 7);
17468 imm = (imm == 0x7f ? -1 : imm);
17469 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17471 break;
17472 case RES_29:
17473 case RES_31:
17474 case RES_39:
17475 generate_exception_end(ctx, EXCP_RI);
17476 break;
17477 default:
17478 decode_micromips32_opc(env, ctx);
17479 return 4;
17482 return 2;
17487 * nanoMIPS opcodes
17491 /* MAJOR, P16, and P32 pools opcodes */
17492 enum {
17493 NM_P_ADDIU = 0x00,
17494 NM_ADDIUPC = 0x01,
17495 NM_MOVE_BALC = 0x02,
17496 NM_P16_MV = 0x04,
17497 NM_LW16 = 0x05,
17498 NM_BC16 = 0x06,
17499 NM_P16_SR = 0x07,
17501 NM_POOL32A = 0x08,
17502 NM_P_BAL = 0x0a,
17503 NM_P16_SHIFT = 0x0c,
17504 NM_LWSP16 = 0x0d,
17505 NM_BALC16 = 0x0e,
17506 NM_P16_4X4 = 0x0f,
17508 NM_P_GP_W = 0x10,
17509 NM_P_GP_BH = 0x11,
17510 NM_P_J = 0x12,
17511 NM_P16C = 0x14,
17512 NM_LWGP16 = 0x15,
17513 NM_P16_LB = 0x17,
17515 NM_P48I = 0x18,
17516 NM_P16_A1 = 0x1c,
17517 NM_LW4X4 = 0x1d,
17518 NM_P16_LH = 0x1f,
17520 NM_P_U12 = 0x20,
17521 NM_P_LS_U12 = 0x21,
17522 NM_P_BR1 = 0x22,
17523 NM_P16_A2 = 0x24,
17524 NM_SW16 = 0x25,
17525 NM_BEQZC16 = 0x26,
17527 NM_POOL32F = 0x28,
17528 NM_P_LS_S9 = 0x29,
17529 NM_P_BR2 = 0x2a,
17531 NM_P16_ADDU = 0x2c,
17532 NM_SWSP16 = 0x2d,
17533 NM_BNEZC16 = 0x2e,
17534 NM_MOVEP = 0x2f,
17536 NM_POOL32S = 0x30,
17537 NM_P_BRI = 0x32,
17538 NM_LI16 = 0x34,
17539 NM_SWGP16 = 0x35,
17540 NM_P16_BR = 0x36,
17542 NM_P_LUI = 0x38,
17543 NM_ANDI16 = 0x3c,
17544 NM_SW4X4 = 0x3d,
17545 NM_MOVEPREV = 0x3f,
17548 /* POOL32A instruction pool */
17549 enum {
17550 NM_POOL32A0 = 0x00,
17551 NM_SPECIAL2 = 0x01,
17552 NM_COP2_1 = 0x02,
17553 NM_UDI = 0x03,
17554 NM_POOL32A5 = 0x05,
17555 NM_POOL32A7 = 0x07,
17558 /* P.GP.W instruction pool */
17559 enum {
17560 NM_ADDIUGP_W = 0x00,
17561 NM_LWGP = 0x02,
17562 NM_SWGP = 0x03,
17565 /* P48I instruction pool */
17566 enum {
17567 NM_LI48 = 0x00,
17568 NM_ADDIU48 = 0x01,
17569 NM_ADDIUGP48 = 0x02,
17570 NM_ADDIUPC48 = 0x03,
17571 NM_LWPC48 = 0x0b,
17572 NM_SWPC48 = 0x0f,
17575 /* P.U12 instruction pool */
17576 enum {
17577 NM_ORI = 0x00,
17578 NM_XORI = 0x01,
17579 NM_ANDI = 0x02,
17580 NM_P_SR = 0x03,
17581 NM_SLTI = 0x04,
17582 NM_SLTIU = 0x05,
17583 NM_SEQI = 0x06,
17584 NM_ADDIUNEG = 0x08,
17585 NM_P_SHIFT = 0x0c,
17586 NM_P_ROTX = 0x0d,
17587 NM_P_INS = 0x0e,
17588 NM_P_EXT = 0x0f,
17591 /* POOL32F instruction pool */
17592 enum {
17593 NM_POOL32F_0 = 0x00,
17594 NM_POOL32F_3 = 0x03,
17595 NM_POOL32F_5 = 0x05,
17598 /* POOL32S instruction pool */
17599 enum {
17600 NM_POOL32S_0 = 0x00,
17601 NM_POOL32S_4 = 0x04,
17604 /* P.LUI instruction pool */
17605 enum {
17606 NM_LUI = 0x00,
17607 NM_ALUIPC = 0x01,
17610 /* P.GP.BH instruction pool */
17611 enum {
17612 NM_LBGP = 0x00,
17613 NM_SBGP = 0x01,
17614 NM_LBUGP = 0x02,
17615 NM_ADDIUGP_B = 0x03,
17616 NM_P_GP_LH = 0x04,
17617 NM_P_GP_SH = 0x05,
17618 NM_P_GP_CP1 = 0x06,
17621 /* P.LS.U12 instruction pool */
17622 enum {
17623 NM_LB = 0x00,
17624 NM_SB = 0x01,
17625 NM_LBU = 0x02,
17626 NM_P_PREFU12 = 0x03,
17627 NM_LH = 0x04,
17628 NM_SH = 0x05,
17629 NM_LHU = 0x06,
17630 NM_LWU = 0x07,
17631 NM_LW = 0x08,
17632 NM_SW = 0x09,
17633 NM_LWC1 = 0x0a,
17634 NM_SWC1 = 0x0b,
17635 NM_LDC1 = 0x0e,
17636 NM_SDC1 = 0x0f,
17639 /* P.LS.S9 instruction pool */
17640 enum {
17641 NM_P_LS_S0 = 0x00,
17642 NM_P_LS_S1 = 0x01,
17643 NM_P_LS_E0 = 0x02,
17644 NM_P_LS_WM = 0x04,
17645 NM_P_LS_UAWM = 0x05,
17648 /* P.BAL instruction pool */
17649 enum {
17650 NM_BC = 0x00,
17651 NM_BALC = 0x01,
17654 /* P.J instruction pool */
17655 enum {
17656 NM_JALRC = 0x00,
17657 NM_JALRC_HB = 0x01,
17658 NM_P_BALRSC = 0x08,
17661 /* P.BR1 instruction pool */
17662 enum {
17663 NM_BEQC = 0x00,
17664 NM_P_BR3A = 0x01,
17665 NM_BGEC = 0x02,
17666 NM_BGEUC = 0x03,
17669 /* P.BR2 instruction pool */
17670 enum {
17671 NM_BNEC = 0x00,
17672 NM_BLTC = 0x02,
17673 NM_BLTUC = 0x03,
17676 /* P.BRI instruction pool */
17677 enum {
17678 NM_BEQIC = 0x00,
17679 NM_BBEQZC = 0x01,
17680 NM_BGEIC = 0x02,
17681 NM_BGEIUC = 0x03,
17682 NM_BNEIC = 0x04,
17683 NM_BBNEZC = 0x05,
17684 NM_BLTIC = 0x06,
17685 NM_BLTIUC = 0x07,
17688 /* P16.SHIFT instruction pool */
17689 enum {
17690 NM_SLL16 = 0x00,
17691 NM_SRL16 = 0x01,
17694 /* POOL16C instruction pool */
17695 enum {
17696 NM_POOL16C_0 = 0x00,
17697 NM_LWXS16 = 0x01,
17700 /* P16.A1 instruction pool */
17701 enum {
17702 NM_ADDIUR1SP = 0x01,
17705 /* P16.A2 instruction pool */
17706 enum {
17707 NM_ADDIUR2 = 0x00,
17708 NM_P_ADDIURS5 = 0x01,
17711 /* P16.ADDU instruction pool */
17712 enum {
17713 NM_ADDU16 = 0x00,
17714 NM_SUBU16 = 0x01,
17717 /* P16.SR instruction pool */
17718 enum {
17719 NM_SAVE16 = 0x00,
17720 NM_RESTORE_JRC16 = 0x01,
17723 /* P16.4X4 instruction pool */
17724 enum {
17725 NM_ADDU4X4 = 0x00,
17726 NM_MUL4X4 = 0x01,
17729 /* P16.LB instruction pool */
17730 enum {
17731 NM_LB16 = 0x00,
17732 NM_SB16 = 0x01,
17733 NM_LBU16 = 0x02,
17736 /* P16.LH instruction pool */
17737 enum {
17738 NM_LH16 = 0x00,
17739 NM_SH16 = 0x01,
17740 NM_LHU16 = 0x02,
17743 /* P.RI instruction pool */
17744 enum {
17745 NM_SIGRIE = 0x00,
17746 NM_P_SYSCALL = 0x01,
17747 NM_BREAK = 0x02,
17748 NM_SDBBP = 0x03,
17751 /* POOL32A0 instruction pool */
17752 enum {
17753 NM_P_TRAP = 0x00,
17754 NM_SEB = 0x01,
17755 NM_SLLV = 0x02,
17756 NM_MUL = 0x03,
17757 NM_MFC0 = 0x06,
17758 NM_MFHC0 = 0x07,
17759 NM_SEH = 0x09,
17760 NM_SRLV = 0x0a,
17761 NM_MUH = 0x0b,
17762 NM_MTC0 = 0x0e,
17763 NM_MTHC0 = 0x0f,
17764 NM_SRAV = 0x12,
17765 NM_MULU = 0x13,
17766 NM_ROTRV = 0x1a,
17767 NM_MUHU = 0x1b,
17768 NM_ADD = 0x22,
17769 NM_DIV = 0x23,
17770 NM_ADDU = 0x2a,
17771 NM_MOD = 0x2b,
17772 NM_SUB = 0x32,
17773 NM_DIVU = 0x33,
17774 NM_RDHWR = 0x38,
17775 NM_SUBU = 0x3a,
17776 NM_MODU = 0x3b,
17777 NM_P_CMOVE = 0x42,
17778 NM_FORK = 0x45,
17779 NM_MFTR = 0x46,
17780 NM_MFHTR = 0x47,
17781 NM_AND = 0x4a,
17782 NM_YIELD = 0x4d,
17783 NM_MTTR = 0x4e,
17784 NM_MTHTR = 0x4f,
17785 NM_OR = 0x52,
17786 NM_D_E_MT_VPE = 0x56,
17787 NM_NOR = 0x5a,
17788 NM_XOR = 0x62,
17789 NM_SLT = 0x6a,
17790 NM_P_SLTU = 0x72,
17791 NM_SOV = 0x7a,
17794 /* CRC32 instruction pool */
17795 enum {
17796 NM_CRC32B = 0x00,
17797 NM_CRC32H = 0x01,
17798 NM_CRC32W = 0x02,
17799 NM_CRC32CB = 0x04,
17800 NM_CRC32CH = 0x05,
17801 NM_CRC32CW = 0x06,
17804 /* POOL32A5 instruction pool */
17805 enum {
17806 NM_CMP_EQ_PH = 0x00,
17807 NM_CMP_LT_PH = 0x08,
17808 NM_CMP_LE_PH = 0x10,
17809 NM_CMPGU_EQ_QB = 0x18,
17810 NM_CMPGU_LT_QB = 0x20,
17811 NM_CMPGU_LE_QB = 0x28,
17812 NM_CMPGDU_EQ_QB = 0x30,
17813 NM_CMPGDU_LT_QB = 0x38,
17814 NM_CMPGDU_LE_QB = 0x40,
17815 NM_CMPU_EQ_QB = 0x48,
17816 NM_CMPU_LT_QB = 0x50,
17817 NM_CMPU_LE_QB = 0x58,
17818 NM_ADDQ_S_W = 0x60,
17819 NM_SUBQ_S_W = 0x68,
17820 NM_ADDSC = 0x70,
17821 NM_ADDWC = 0x78,
17823 NM_ADDQ_S_PH = 0x01,
17824 NM_ADDQH_R_PH = 0x09,
17825 NM_ADDQH_R_W = 0x11,
17826 NM_ADDU_S_QB = 0x19,
17827 NM_ADDU_S_PH = 0x21,
17828 NM_ADDUH_R_QB = 0x29,
17829 NM_SHRAV_R_PH = 0x31,
17830 NM_SHRAV_R_QB = 0x39,
17831 NM_SUBQ_S_PH = 0x41,
17832 NM_SUBQH_R_PH = 0x49,
17833 NM_SUBQH_R_W = 0x51,
17834 NM_SUBU_S_QB = 0x59,
17835 NM_SUBU_S_PH = 0x61,
17836 NM_SUBUH_R_QB = 0x69,
17837 NM_SHLLV_S_PH = 0x71,
17838 NM_PRECR_SRA_R_PH_W = 0x79,
17840 NM_MULEU_S_PH_QBL = 0x12,
17841 NM_MULEU_S_PH_QBR = 0x1a,
17842 NM_MULQ_RS_PH = 0x22,
17843 NM_MULQ_S_PH = 0x2a,
17844 NM_MULQ_RS_W = 0x32,
17845 NM_MULQ_S_W = 0x3a,
17846 NM_APPEND = 0x42,
17847 NM_MODSUB = 0x52,
17848 NM_SHRAV_R_W = 0x5a,
17849 NM_SHRLV_PH = 0x62,
17850 NM_SHRLV_QB = 0x6a,
17851 NM_SHLLV_QB = 0x72,
17852 NM_SHLLV_S_W = 0x7a,
17854 NM_SHILO = 0x03,
17856 NM_MULEQ_S_W_PHL = 0x04,
17857 NM_MULEQ_S_W_PHR = 0x0c,
17859 NM_MUL_S_PH = 0x05,
17860 NM_PRECR_QB_PH = 0x0d,
17861 NM_PRECRQ_QB_PH = 0x15,
17862 NM_PRECRQ_PH_W = 0x1d,
17863 NM_PRECRQ_RS_PH_W = 0x25,
17864 NM_PRECRQU_S_QB_PH = 0x2d,
17865 NM_PACKRL_PH = 0x35,
17866 NM_PICK_QB = 0x3d,
17867 NM_PICK_PH = 0x45,
17869 NM_SHRA_R_W = 0x5e,
17870 NM_SHRA_R_PH = 0x66,
17871 NM_SHLL_S_PH = 0x76,
17872 NM_SHLL_S_W = 0x7e,
17874 NM_REPL_PH = 0x07
17877 /* POOL32A7 instruction pool */
17878 enum {
17879 NM_P_LSX = 0x00,
17880 NM_LSA = 0x01,
17881 NM_EXTW = 0x03,
17882 NM_POOL32AXF = 0x07,
17885 /* P.SR instruction pool */
17886 enum {
17887 NM_PP_SR = 0x00,
17888 NM_P_SR_F = 0x01,
17891 /* P.SHIFT instruction pool */
17892 enum {
17893 NM_P_SLL = 0x00,
17894 NM_SRL = 0x02,
17895 NM_SRA = 0x04,
17896 NM_ROTR = 0x06,
17899 /* P.ROTX instruction pool */
17900 enum {
17901 NM_ROTX = 0x00,
17904 /* P.INS instruction pool */
17905 enum {
17906 NM_INS = 0x00,
17909 /* P.EXT instruction pool */
17910 enum {
17911 NM_EXT = 0x00,
17914 /* POOL32F_0 (fmt) instruction pool */
17915 enum {
17916 NM_RINT_S = 0x04,
17917 NM_RINT_D = 0x44,
17918 NM_ADD_S = 0x06,
17919 NM_SELEQZ_S = 0x07,
17920 NM_SELEQZ_D = 0x47,
17921 NM_CLASS_S = 0x0c,
17922 NM_CLASS_D = 0x4c,
17923 NM_SUB_S = 0x0e,
17924 NM_SELNEZ_S = 0x0f,
17925 NM_SELNEZ_D = 0x4f,
17926 NM_MUL_S = 0x16,
17927 NM_SEL_S = 0x17,
17928 NM_SEL_D = 0x57,
17929 NM_DIV_S = 0x1e,
17930 NM_ADD_D = 0x26,
17931 NM_SUB_D = 0x2e,
17932 NM_MUL_D = 0x36,
17933 NM_MADDF_S = 0x37,
17934 NM_MADDF_D = 0x77,
17935 NM_DIV_D = 0x3e,
17936 NM_MSUBF_S = 0x3f,
17937 NM_MSUBF_D = 0x7f,
17940 /* POOL32F_3 instruction pool */
17941 enum {
17942 NM_MIN_FMT = 0x00,
17943 NM_MAX_FMT = 0x01,
17944 NM_MINA_FMT = 0x04,
17945 NM_MAXA_FMT = 0x05,
17946 NM_POOL32FXF = 0x07,
17949 /* POOL32F_5 instruction pool */
17950 enum {
17951 NM_CMP_CONDN_S = 0x00,
17952 NM_CMP_CONDN_D = 0x02,
17955 /* P.GP.LH instruction pool */
17956 enum {
17957 NM_LHGP = 0x00,
17958 NM_LHUGP = 0x01,
17961 /* P.GP.SH instruction pool */
17962 enum {
17963 NM_SHGP = 0x00,
17966 /* P.GP.CP1 instruction pool */
17967 enum {
17968 NM_LWC1GP = 0x00,
17969 NM_SWC1GP = 0x01,
17970 NM_LDC1GP = 0x02,
17971 NM_SDC1GP = 0x03,
17974 /* P.LS.S0 instruction pool */
17975 enum {
17976 NM_LBS9 = 0x00,
17977 NM_LHS9 = 0x04,
17978 NM_LWS9 = 0x08,
17979 NM_LDS9 = 0x0c,
17981 NM_SBS9 = 0x01,
17982 NM_SHS9 = 0x05,
17983 NM_SWS9 = 0x09,
17984 NM_SDS9 = 0x0d,
17986 NM_LBUS9 = 0x02,
17987 NM_LHUS9 = 0x06,
17988 NM_LWC1S9 = 0x0a,
17989 NM_LDC1S9 = 0x0e,
17991 NM_P_PREFS9 = 0x03,
17992 NM_LWUS9 = 0x07,
17993 NM_SWC1S9 = 0x0b,
17994 NM_SDC1S9 = 0x0f,
17997 /* P.LS.S1 instruction pool */
17998 enum {
17999 NM_ASET_ACLR = 0x02,
18000 NM_UALH = 0x04,
18001 NM_UASH = 0x05,
18002 NM_CACHE = 0x07,
18003 NM_P_LL = 0x0a,
18004 NM_P_SC = 0x0b,
18007 /* P.LS.E0 instruction pool */
18008 enum {
18009 NM_LBE = 0x00,
18010 NM_SBE = 0x01,
18011 NM_LBUE = 0x02,
18012 NM_P_PREFE = 0x03,
18013 NM_LHE = 0x04,
18014 NM_SHE = 0x05,
18015 NM_LHUE = 0x06,
18016 NM_CACHEE = 0x07,
18017 NM_LWE = 0x08,
18018 NM_SWE = 0x09,
18019 NM_P_LLE = 0x0a,
18020 NM_P_SCE = 0x0b,
18023 /* P.PREFE instruction pool */
18024 enum {
18025 NM_SYNCIE = 0x00,
18026 NM_PREFE = 0x01,
18029 /* P.LLE instruction pool */
18030 enum {
18031 NM_LLE = 0x00,
18032 NM_LLWPE = 0x01,
18035 /* P.SCE instruction pool */
18036 enum {
18037 NM_SCE = 0x00,
18038 NM_SCWPE = 0x01,
18041 /* P.LS.WM instruction pool */
18042 enum {
18043 NM_LWM = 0x00,
18044 NM_SWM = 0x01,
18047 /* P.LS.UAWM instruction pool */
18048 enum {
18049 NM_UALWM = 0x00,
18050 NM_UASWM = 0x01,
18053 /* P.BR3A instruction pool */
18054 enum {
18055 NM_BC1EQZC = 0x00,
18056 NM_BC1NEZC = 0x01,
18057 NM_BC2EQZC = 0x02,
18058 NM_BC2NEZC = 0x03,
18059 NM_BPOSGE32C = 0x04,
18062 /* P16.RI instruction pool */
18063 enum {
18064 NM_P16_SYSCALL = 0x01,
18065 NM_BREAK16 = 0x02,
18066 NM_SDBBP16 = 0x03,
18069 /* POOL16C_0 instruction pool */
18070 enum {
18071 NM_POOL16C_00 = 0x00,
18074 /* P16.JRC instruction pool */
18075 enum {
18076 NM_JRC = 0x00,
18077 NM_JALRC16 = 0x01,
18080 /* P.SYSCALL instruction pool */
18081 enum {
18082 NM_SYSCALL = 0x00,
18083 NM_HYPCALL = 0x01,
18086 /* P.TRAP instruction pool */
18087 enum {
18088 NM_TEQ = 0x00,
18089 NM_TNE = 0x01,
18092 /* P.CMOVE instruction pool */
18093 enum {
18094 NM_MOVZ = 0x00,
18095 NM_MOVN = 0x01,
18098 /* POOL32Axf instruction pool */
18099 enum {
18100 NM_POOL32AXF_1 = 0x01,
18101 NM_POOL32AXF_2 = 0x02,
18102 NM_POOL32AXF_4 = 0x04,
18103 NM_POOL32AXF_5 = 0x05,
18104 NM_POOL32AXF_7 = 0x07,
18107 /* POOL32Axf_1 instruction pool */
18108 enum {
18109 NM_POOL32AXF_1_0 = 0x00,
18110 NM_POOL32AXF_1_1 = 0x01,
18111 NM_POOL32AXF_1_3 = 0x03,
18112 NM_POOL32AXF_1_4 = 0x04,
18113 NM_POOL32AXF_1_5 = 0x05,
18114 NM_POOL32AXF_1_7 = 0x07,
18117 /* POOL32Axf_2 instruction pool */
18118 enum {
18119 NM_POOL32AXF_2_0_7 = 0x00,
18120 NM_POOL32AXF_2_8_15 = 0x01,
18121 NM_POOL32AXF_2_16_23 = 0x02,
18122 NM_POOL32AXF_2_24_31 = 0x03,
18125 /* POOL32Axf_7 instruction pool */
18126 enum {
18127 NM_SHRA_R_QB = 0x0,
18128 NM_SHRL_PH = 0x1,
18129 NM_REPL_QB = 0x2,
18132 /* POOL32Axf_1_0 instruction pool */
18133 enum {
18134 NM_MFHI = 0x0,
18135 NM_MFLO = 0x1,
18136 NM_MTHI = 0x2,
18137 NM_MTLO = 0x3,
18140 /* POOL32Axf_1_1 instruction pool */
18141 enum {
18142 NM_MTHLIP = 0x0,
18143 NM_SHILOV = 0x1,
18146 /* POOL32Axf_1_3 instruction pool */
18147 enum {
18148 NM_RDDSP = 0x0,
18149 NM_WRDSP = 0x1,
18150 NM_EXTP = 0x2,
18151 NM_EXTPDP = 0x3,
18154 /* POOL32Axf_1_4 instruction pool */
18155 enum {
18156 NM_SHLL_QB = 0x0,
18157 NM_SHRL_QB = 0x1,
18160 /* POOL32Axf_1_5 instruction pool */
18161 enum {
18162 NM_MAQ_S_W_PHR = 0x0,
18163 NM_MAQ_S_W_PHL = 0x1,
18164 NM_MAQ_SA_W_PHR = 0x2,
18165 NM_MAQ_SA_W_PHL = 0x3,
18168 /* POOL32Axf_1_7 instruction pool */
18169 enum {
18170 NM_EXTR_W = 0x0,
18171 NM_EXTR_R_W = 0x1,
18172 NM_EXTR_RS_W = 0x2,
18173 NM_EXTR_S_H = 0x3,
18176 /* POOL32Axf_2_0_7 instruction pool */
18177 enum {
18178 NM_DPA_W_PH = 0x0,
18179 NM_DPAQ_S_W_PH = 0x1,
18180 NM_DPS_W_PH = 0x2,
18181 NM_DPSQ_S_W_PH = 0x3,
18182 NM_BALIGN = 0x4,
18183 NM_MADD = 0x5,
18184 NM_MULT = 0x6,
18185 NM_EXTRV_W = 0x7,
18188 /* POOL32Axf_2_8_15 instruction pool */
18189 enum {
18190 NM_DPAX_W_PH = 0x0,
18191 NM_DPAQ_SA_L_W = 0x1,
18192 NM_DPSX_W_PH = 0x2,
18193 NM_DPSQ_SA_L_W = 0x3,
18194 NM_MADDU = 0x5,
18195 NM_MULTU = 0x6,
18196 NM_EXTRV_R_W = 0x7,
18199 /* POOL32Axf_2_16_23 instruction pool */
18200 enum {
18201 NM_DPAU_H_QBL = 0x0,
18202 NM_DPAQX_S_W_PH = 0x1,
18203 NM_DPSU_H_QBL = 0x2,
18204 NM_DPSQX_S_W_PH = 0x3,
18205 NM_EXTPV = 0x4,
18206 NM_MSUB = 0x5,
18207 NM_MULSA_W_PH = 0x6,
18208 NM_EXTRV_RS_W = 0x7,
18211 /* POOL32Axf_2_24_31 instruction pool */
18212 enum {
18213 NM_DPAU_H_QBR = 0x0,
18214 NM_DPAQX_SA_W_PH = 0x1,
18215 NM_DPSU_H_QBR = 0x2,
18216 NM_DPSQX_SA_W_PH = 0x3,
18217 NM_EXTPDPV = 0x4,
18218 NM_MSUBU = 0x5,
18219 NM_MULSAQ_S_W_PH = 0x6,
18220 NM_EXTRV_S_H = 0x7,
18223 /* POOL32Axf_{4, 5} instruction pool */
18224 enum {
18225 NM_CLO = 0x25,
18226 NM_CLZ = 0x2d,
18228 NM_TLBP = 0x01,
18229 NM_TLBR = 0x09,
18230 NM_TLBWI = 0x11,
18231 NM_TLBWR = 0x19,
18232 NM_TLBINV = 0x03,
18233 NM_TLBINVF = 0x0b,
18234 NM_DI = 0x23,
18235 NM_EI = 0x2b,
18236 NM_RDPGPR = 0x70,
18237 NM_WRPGPR = 0x78,
18238 NM_WAIT = 0x61,
18239 NM_DERET = 0x71,
18240 NM_ERETX = 0x79,
18242 /* nanoMIPS DSP instructions */
18243 NM_ABSQ_S_QB = 0x00,
18244 NM_ABSQ_S_PH = 0x08,
18245 NM_ABSQ_S_W = 0x10,
18246 NM_PRECEQ_W_PHL = 0x28,
18247 NM_PRECEQ_W_PHR = 0x30,
18248 NM_PRECEQU_PH_QBL = 0x38,
18249 NM_PRECEQU_PH_QBR = 0x48,
18250 NM_PRECEU_PH_QBL = 0x58,
18251 NM_PRECEU_PH_QBR = 0x68,
18252 NM_PRECEQU_PH_QBLA = 0x39,
18253 NM_PRECEQU_PH_QBRA = 0x49,
18254 NM_PRECEU_PH_QBLA = 0x59,
18255 NM_PRECEU_PH_QBRA = 0x69,
18256 NM_REPLV_PH = 0x01,
18257 NM_REPLV_QB = 0x09,
18258 NM_BITREV = 0x18,
18259 NM_INSV = 0x20,
18260 NM_RADDU_W_QB = 0x78,
18262 NM_BITSWAP = 0x05,
18263 NM_WSBH = 0x3d,
18266 /* PP.SR instruction pool */
18267 enum {
18268 NM_SAVE = 0x00,
18269 NM_RESTORE = 0x02,
18270 NM_RESTORE_JRC = 0x03,
18273 /* P.SR.F instruction pool */
18274 enum {
18275 NM_SAVEF = 0x00,
18276 NM_RESTOREF = 0x01,
18279 /* P16.SYSCALL instruction pool */
18280 enum {
18281 NM_SYSCALL16 = 0x00,
18282 NM_HYPCALL16 = 0x01,
18285 /* POOL16C_00 instruction pool */
18286 enum {
18287 NM_NOT16 = 0x00,
18288 NM_XOR16 = 0x01,
18289 NM_AND16 = 0x02,
18290 NM_OR16 = 0x03,
18293 /* PP.LSX and PP.LSXS instruction pool */
18294 enum {
18295 NM_LBX = 0x00,
18296 NM_LHX = 0x04,
18297 NM_LWX = 0x08,
18298 NM_LDX = 0x0c,
18300 NM_SBX = 0x01,
18301 NM_SHX = 0x05,
18302 NM_SWX = 0x09,
18303 NM_SDX = 0x0d,
18305 NM_LBUX = 0x02,
18306 NM_LHUX = 0x06,
18307 NM_LWC1X = 0x0a,
18308 NM_LDC1X = 0x0e,
18310 NM_LWUX = 0x07,
18311 NM_SWC1X = 0x0b,
18312 NM_SDC1X = 0x0f,
18314 NM_LHXS = 0x04,
18315 NM_LWXS = 0x08,
18316 NM_LDXS = 0x0c,
18318 NM_SHXS = 0x05,
18319 NM_SWXS = 0x09,
18320 NM_SDXS = 0x0d,
18322 NM_LHUXS = 0x06,
18323 NM_LWC1XS = 0x0a,
18324 NM_LDC1XS = 0x0e,
18326 NM_LWUXS = 0x07,
18327 NM_SWC1XS = 0x0b,
18328 NM_SDC1XS = 0x0f,
18331 /* ERETx instruction pool */
18332 enum {
18333 NM_ERET = 0x00,
18334 NM_ERETNC = 0x01,
18337 /* POOL32FxF_{0, 1} insturction pool */
18338 enum {
18339 NM_CFC1 = 0x40,
18340 NM_CTC1 = 0x60,
18341 NM_MFC1 = 0x80,
18342 NM_MTC1 = 0xa0,
18343 NM_MFHC1 = 0xc0,
18344 NM_MTHC1 = 0xe0,
18346 NM_CVT_S_PL = 0x84,
18347 NM_CVT_S_PU = 0xa4,
18349 NM_CVT_L_S = 0x004,
18350 NM_CVT_L_D = 0x104,
18351 NM_CVT_W_S = 0x024,
18352 NM_CVT_W_D = 0x124,
18354 NM_RSQRT_S = 0x008,
18355 NM_RSQRT_D = 0x108,
18357 NM_SQRT_S = 0x028,
18358 NM_SQRT_D = 0x128,
18360 NM_RECIP_S = 0x048,
18361 NM_RECIP_D = 0x148,
18363 NM_FLOOR_L_S = 0x00c,
18364 NM_FLOOR_L_D = 0x10c,
18366 NM_FLOOR_W_S = 0x02c,
18367 NM_FLOOR_W_D = 0x12c,
18369 NM_CEIL_L_S = 0x04c,
18370 NM_CEIL_L_D = 0x14c,
18371 NM_CEIL_W_S = 0x06c,
18372 NM_CEIL_W_D = 0x16c,
18373 NM_TRUNC_L_S = 0x08c,
18374 NM_TRUNC_L_D = 0x18c,
18375 NM_TRUNC_W_S = 0x0ac,
18376 NM_TRUNC_W_D = 0x1ac,
18377 NM_ROUND_L_S = 0x0cc,
18378 NM_ROUND_L_D = 0x1cc,
18379 NM_ROUND_W_S = 0x0ec,
18380 NM_ROUND_W_D = 0x1ec,
18382 NM_MOV_S = 0x01,
18383 NM_MOV_D = 0x81,
18384 NM_ABS_S = 0x0d,
18385 NM_ABS_D = 0x8d,
18386 NM_NEG_S = 0x2d,
18387 NM_NEG_D = 0xad,
18388 NM_CVT_D_S = 0x04d,
18389 NM_CVT_D_W = 0x0cd,
18390 NM_CVT_D_L = 0x14d,
18391 NM_CVT_S_D = 0x06d,
18392 NM_CVT_S_W = 0x0ed,
18393 NM_CVT_S_L = 0x16d,
18396 /* P.LL instruction pool */
18397 enum {
18398 NM_LL = 0x00,
18399 NM_LLWP = 0x01,
18402 /* P.SC instruction pool */
18403 enum {
18404 NM_SC = 0x00,
18405 NM_SCWP = 0x01,
18408 /* P.DVP instruction pool */
18409 enum {
18410 NM_DVP = 0x00,
18411 NM_EVP = 0x01,
18417 * nanoMIPS decoding engine
18422 /* extraction utilities */
18424 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18425 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18426 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18427 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18428 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18430 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18431 static inline int decode_gpr_gpr3(int r)
18433 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18435 return map[r & 0x7];
18438 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18439 static inline int decode_gpr_gpr3_src_store(int r)
18441 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18443 return map[r & 0x7];
18446 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18447 static inline int decode_gpr_gpr4(int r)
18449 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18450 16, 17, 18, 19, 20, 21, 22, 23 };
18452 return map[r & 0xf];
18455 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18456 static inline int decode_gpr_gpr4_zero(int r)
18458 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18459 16, 17, 18, 19, 20, 21, 22, 23 };
18461 return map[r & 0xf];
18465 static void gen_adjust_sp(DisasContext *ctx, int u)
18467 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18470 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18471 uint8_t gp, uint16_t u)
18473 int counter = 0;
18474 TCGv va = tcg_temp_new();
18475 TCGv t0 = tcg_temp_new();
18477 while (counter != count) {
18478 bool use_gp = gp && (counter == count - 1);
18479 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18480 int this_offset = -((counter + 1) << 2);
18481 gen_base_offset_addr(ctx, va, 29, this_offset);
18482 gen_load_gpr(t0, this_rt);
18483 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18484 (MO_TEUL | ctx->default_tcg_memop_mask));
18485 counter++;
18488 /* adjust stack pointer */
18489 gen_adjust_sp(ctx, -u);
18491 tcg_temp_free(t0);
18492 tcg_temp_free(va);
18495 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18496 uint8_t gp, uint16_t u)
18498 int counter = 0;
18499 TCGv va = tcg_temp_new();
18500 TCGv t0 = tcg_temp_new();
18502 while (counter != count) {
18503 bool use_gp = gp && (counter == count - 1);
18504 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18505 int this_offset = u - ((counter + 1) << 2);
18506 gen_base_offset_addr(ctx, va, 29, this_offset);
18507 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18508 ctx->default_tcg_memop_mask);
18509 tcg_gen_ext32s_tl(t0, t0);
18510 gen_store_gpr(t0, this_rt);
18511 counter++;
18514 /* adjust stack pointer */
18515 gen_adjust_sp(ctx, u);
18517 tcg_temp_free(t0);
18518 tcg_temp_free(va);
18521 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18523 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18524 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18526 switch (extract32(ctx->opcode, 2, 2)) {
18527 case NM_NOT16:
18528 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18529 break;
18530 case NM_AND16:
18531 gen_logic(ctx, OPC_AND, rt, rt, rs);
18532 break;
18533 case NM_XOR16:
18534 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18535 break;
18536 case NM_OR16:
18537 gen_logic(ctx, OPC_OR, rt, rt, rs);
18538 break;
18542 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18544 int rt = extract32(ctx->opcode, 21, 5);
18545 int rs = extract32(ctx->opcode, 16, 5);
18546 int rd = extract32(ctx->opcode, 11, 5);
18548 switch (extract32(ctx->opcode, 3, 7)) {
18549 case NM_P_TRAP:
18550 switch (extract32(ctx->opcode, 10, 1)) {
18551 case NM_TEQ:
18552 check_nms(ctx);
18553 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18554 break;
18555 case NM_TNE:
18556 check_nms(ctx);
18557 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18558 break;
18560 break;
18561 case NM_RDHWR:
18562 check_nms(ctx);
18563 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18564 break;
18565 case NM_SEB:
18566 check_nms(ctx);
18567 gen_bshfl(ctx, OPC_SEB, rs, rt);
18568 break;
18569 case NM_SEH:
18570 gen_bshfl(ctx, OPC_SEH, rs, rt);
18571 break;
18572 case NM_SLLV:
18573 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18574 break;
18575 case NM_SRLV:
18576 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18577 break;
18578 case NM_SRAV:
18579 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18580 break;
18581 case NM_ROTRV:
18582 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18583 break;
18584 case NM_ADD:
18585 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18586 break;
18587 case NM_ADDU:
18588 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18589 break;
18590 case NM_SUB:
18591 check_nms(ctx);
18592 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18593 break;
18594 case NM_SUBU:
18595 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18596 break;
18597 case NM_P_CMOVE:
18598 switch (extract32(ctx->opcode, 10, 1)) {
18599 case NM_MOVZ:
18600 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18601 break;
18602 case NM_MOVN:
18603 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18604 break;
18606 break;
18607 case NM_AND:
18608 gen_logic(ctx, OPC_AND, rd, rs, rt);
18609 break;
18610 case NM_OR:
18611 gen_logic(ctx, OPC_OR, rd, rs, rt);
18612 break;
18613 case NM_NOR:
18614 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18615 break;
18616 case NM_XOR:
18617 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18618 break;
18619 case NM_SLT:
18620 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18621 break;
18622 case NM_P_SLTU:
18623 if (rd == 0) {
18624 /* P_DVP */
18625 #ifndef CONFIG_USER_ONLY
18626 TCGv t0 = tcg_temp_new();
18627 switch (extract32(ctx->opcode, 10, 1)) {
18628 case NM_DVP:
18629 if (ctx->vp) {
18630 check_cp0_enabled(ctx);
18631 gen_helper_dvp(t0, cpu_env);
18632 gen_store_gpr(t0, rt);
18634 break;
18635 case NM_EVP:
18636 if (ctx->vp) {
18637 check_cp0_enabled(ctx);
18638 gen_helper_evp(t0, cpu_env);
18639 gen_store_gpr(t0, rt);
18641 break;
18643 tcg_temp_free(t0);
18644 #endif
18645 } else {
18646 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18648 break;
18649 case NM_SOV:
18651 TCGv t0 = tcg_temp_new();
18652 TCGv t1 = tcg_temp_new();
18653 TCGv t2 = tcg_temp_new();
18655 gen_load_gpr(t1, rs);
18656 gen_load_gpr(t2, rt);
18657 tcg_gen_add_tl(t0, t1, t2);
18658 tcg_gen_ext32s_tl(t0, t0);
18659 tcg_gen_xor_tl(t1, t1, t2);
18660 tcg_gen_xor_tl(t2, t0, t2);
18661 tcg_gen_andc_tl(t1, t2, t1);
18663 /* operands of same sign, result different sign */
18664 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18665 gen_store_gpr(t0, rd);
18667 tcg_temp_free(t0);
18668 tcg_temp_free(t1);
18669 tcg_temp_free(t2);
18671 break;
18672 case NM_MUL:
18673 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18674 break;
18675 case NM_MUH:
18676 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18677 break;
18678 case NM_MULU:
18679 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18680 break;
18681 case NM_MUHU:
18682 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18683 break;
18684 case NM_DIV:
18685 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18686 break;
18687 case NM_MOD:
18688 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18689 break;
18690 case NM_DIVU:
18691 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18692 break;
18693 case NM_MODU:
18694 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18695 break;
18696 #ifndef CONFIG_USER_ONLY
18697 case NM_MFC0:
18698 check_cp0_enabled(ctx);
18699 if (rt == 0) {
18700 /* Treat as NOP. */
18701 break;
18703 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18704 break;
18705 case NM_MTC0:
18706 check_cp0_enabled(ctx);
18708 TCGv t0 = tcg_temp_new();
18710 gen_load_gpr(t0, rt);
18711 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18712 tcg_temp_free(t0);
18714 break;
18715 case NM_D_E_MT_VPE:
18717 uint8_t sc = extract32(ctx->opcode, 10, 1);
18718 TCGv t0 = tcg_temp_new();
18720 switch (sc) {
18721 case 0:
18722 if (rs == 1) {
18723 /* DMT */
18724 check_cp0_mt(ctx);
18725 gen_helper_dmt(t0);
18726 gen_store_gpr(t0, rt);
18727 } else if (rs == 0) {
18728 /* DVPE */
18729 check_cp0_mt(ctx);
18730 gen_helper_dvpe(t0, cpu_env);
18731 gen_store_gpr(t0, rt);
18732 } else {
18733 generate_exception_end(ctx, EXCP_RI);
18735 break;
18736 case 1:
18737 if (rs == 1) {
18738 /* EMT */
18739 check_cp0_mt(ctx);
18740 gen_helper_emt(t0);
18741 gen_store_gpr(t0, rt);
18742 } else if (rs == 0) {
18743 /* EVPE */
18744 check_cp0_mt(ctx);
18745 gen_helper_evpe(t0, cpu_env);
18746 gen_store_gpr(t0, rt);
18747 } else {
18748 generate_exception_end(ctx, EXCP_RI);
18750 break;
18753 tcg_temp_free(t0);
18755 break;
18756 case NM_FORK:
18757 check_mt(ctx);
18759 TCGv t0 = tcg_temp_new();
18760 TCGv t1 = tcg_temp_new();
18762 gen_load_gpr(t0, rt);
18763 gen_load_gpr(t1, rs);
18764 gen_helper_fork(t0, t1);
18765 tcg_temp_free(t0);
18766 tcg_temp_free(t1);
18768 break;
18769 case NM_MFTR:
18770 case NM_MFHTR:
18771 check_cp0_enabled(ctx);
18772 if (rd == 0) {
18773 /* Treat as NOP. */
18774 return;
18776 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18777 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18778 break;
18779 case NM_MTTR:
18780 case NM_MTHTR:
18781 check_cp0_enabled(ctx);
18782 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18783 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18784 break;
18785 case NM_YIELD:
18786 check_mt(ctx);
18788 TCGv t0 = tcg_temp_new();
18790 gen_load_gpr(t0, rs);
18791 gen_helper_yield(t0, cpu_env, t0);
18792 gen_store_gpr(t0, rt);
18793 tcg_temp_free(t0);
18795 break;
18796 #endif
18797 default:
18798 generate_exception_end(ctx, EXCP_RI);
18799 break;
18803 /* dsp */
18804 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18805 int ret, int v1, int v2)
18807 TCGv_i32 t0;
18808 TCGv v0_t;
18809 TCGv v1_t;
18811 t0 = tcg_temp_new_i32();
18813 v0_t = tcg_temp_new();
18814 v1_t = tcg_temp_new();
18816 tcg_gen_movi_i32(t0, v2 >> 3);
18818 gen_load_gpr(v0_t, ret);
18819 gen_load_gpr(v1_t, v1);
18821 switch (opc) {
18822 case NM_MAQ_S_W_PHR:
18823 check_dsp(ctx);
18824 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18825 break;
18826 case NM_MAQ_S_W_PHL:
18827 check_dsp(ctx);
18828 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18829 break;
18830 case NM_MAQ_SA_W_PHR:
18831 check_dsp(ctx);
18832 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18833 break;
18834 case NM_MAQ_SA_W_PHL:
18835 check_dsp(ctx);
18836 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18837 break;
18838 default:
18839 generate_exception_end(ctx, EXCP_RI);
18840 break;
18843 tcg_temp_free_i32(t0);
18845 tcg_temp_free(v0_t);
18846 tcg_temp_free(v1_t);
18850 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18851 int ret, int v1, int v2)
18853 int16_t imm;
18854 TCGv t0 = tcg_temp_new();
18855 TCGv t1 = tcg_temp_new();
18856 TCGv v0_t = tcg_temp_new();
18858 gen_load_gpr(v0_t, v1);
18860 switch (opc) {
18861 case NM_POOL32AXF_1_0:
18862 check_dsp(ctx);
18863 switch (extract32(ctx->opcode, 12, 2)) {
18864 case NM_MFHI:
18865 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18866 break;
18867 case NM_MFLO:
18868 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18869 break;
18870 case NM_MTHI:
18871 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18872 break;
18873 case NM_MTLO:
18874 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18875 break;
18877 break;
18878 case NM_POOL32AXF_1_1:
18879 check_dsp(ctx);
18880 switch (extract32(ctx->opcode, 12, 2)) {
18881 case NM_MTHLIP:
18882 tcg_gen_movi_tl(t0, v2);
18883 gen_helper_mthlip(t0, v0_t, cpu_env);
18884 break;
18885 case NM_SHILOV:
18886 tcg_gen_movi_tl(t0, v2 >> 3);
18887 gen_helper_shilo(t0, v0_t, cpu_env);
18888 break;
18889 default:
18890 generate_exception_end(ctx, EXCP_RI);
18891 break;
18893 break;
18894 case NM_POOL32AXF_1_3:
18895 check_dsp(ctx);
18896 imm = extract32(ctx->opcode, 14, 7);
18897 switch (extract32(ctx->opcode, 12, 2)) {
18898 case NM_RDDSP:
18899 tcg_gen_movi_tl(t0, imm);
18900 gen_helper_rddsp(t0, t0, cpu_env);
18901 gen_store_gpr(t0, ret);
18902 break;
18903 case NM_WRDSP:
18904 gen_load_gpr(t0, ret);
18905 tcg_gen_movi_tl(t1, imm);
18906 gen_helper_wrdsp(t0, t1, cpu_env);
18907 break;
18908 case NM_EXTP:
18909 tcg_gen_movi_tl(t0, v2 >> 3);
18910 tcg_gen_movi_tl(t1, v1);
18911 gen_helper_extp(t0, t0, t1, cpu_env);
18912 gen_store_gpr(t0, ret);
18913 break;
18914 case NM_EXTPDP:
18915 tcg_gen_movi_tl(t0, v2 >> 3);
18916 tcg_gen_movi_tl(t1, v1);
18917 gen_helper_extpdp(t0, t0, t1, cpu_env);
18918 gen_store_gpr(t0, ret);
18919 break;
18921 break;
18922 case NM_POOL32AXF_1_4:
18923 check_dsp(ctx);
18924 tcg_gen_movi_tl(t0, v2 >> 2);
18925 switch (extract32(ctx->opcode, 12, 1)) {
18926 case NM_SHLL_QB:
18927 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18928 gen_store_gpr(t0, ret);
18929 break;
18930 case NM_SHRL_QB:
18931 gen_helper_shrl_qb(t0, t0, v0_t);
18932 gen_store_gpr(t0, ret);
18933 break;
18935 break;
18936 case NM_POOL32AXF_1_5:
18937 opc = extract32(ctx->opcode, 12, 2);
18938 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18939 break;
18940 case NM_POOL32AXF_1_7:
18941 check_dsp(ctx);
18942 tcg_gen_movi_tl(t0, v2 >> 3);
18943 tcg_gen_movi_tl(t1, v1);
18944 switch (extract32(ctx->opcode, 12, 2)) {
18945 case NM_EXTR_W:
18946 gen_helper_extr_w(t0, t0, t1, cpu_env);
18947 gen_store_gpr(t0, ret);
18948 break;
18949 case NM_EXTR_R_W:
18950 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18951 gen_store_gpr(t0, ret);
18952 break;
18953 case NM_EXTR_RS_W:
18954 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18955 gen_store_gpr(t0, ret);
18956 break;
18957 case NM_EXTR_S_H:
18958 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18959 gen_store_gpr(t0, ret);
18960 break;
18962 break;
18963 default:
18964 generate_exception_end(ctx, EXCP_RI);
18965 break;
18968 tcg_temp_free(t0);
18969 tcg_temp_free(t1);
18970 tcg_temp_free(v0_t);
18973 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18974 TCGv v0, TCGv v1, int rd)
18976 TCGv_i32 t0;
18978 t0 = tcg_temp_new_i32();
18980 tcg_gen_movi_i32(t0, rd >> 3);
18982 switch (opc) {
18983 case NM_POOL32AXF_2_0_7:
18984 switch (extract32(ctx->opcode, 9, 3)) {
18985 case NM_DPA_W_PH:
18986 check_dsp_r2(ctx);
18987 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18988 break;
18989 case NM_DPAQ_S_W_PH:
18990 check_dsp(ctx);
18991 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18992 break;
18993 case NM_DPS_W_PH:
18994 check_dsp_r2(ctx);
18995 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18996 break;
18997 case NM_DPSQ_S_W_PH:
18998 check_dsp(ctx);
18999 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19000 break;
19001 default:
19002 generate_exception_end(ctx, EXCP_RI);
19003 break;
19005 break;
19006 case NM_POOL32AXF_2_8_15:
19007 switch (extract32(ctx->opcode, 9, 3)) {
19008 case NM_DPAX_W_PH:
19009 check_dsp_r2(ctx);
19010 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19011 break;
19012 case NM_DPAQ_SA_L_W:
19013 check_dsp(ctx);
19014 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19015 break;
19016 case NM_DPSX_W_PH:
19017 check_dsp_r2(ctx);
19018 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19019 break;
19020 case NM_DPSQ_SA_L_W:
19021 check_dsp(ctx);
19022 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19023 break;
19024 default:
19025 generate_exception_end(ctx, EXCP_RI);
19026 break;
19028 break;
19029 case NM_POOL32AXF_2_16_23:
19030 switch (extract32(ctx->opcode, 9, 3)) {
19031 case NM_DPAU_H_QBL:
19032 check_dsp(ctx);
19033 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19034 break;
19035 case NM_DPAQX_S_W_PH:
19036 check_dsp_r2(ctx);
19037 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19038 break;
19039 case NM_DPSU_H_QBL:
19040 check_dsp(ctx);
19041 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19042 break;
19043 case NM_DPSQX_S_W_PH:
19044 check_dsp_r2(ctx);
19045 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19046 break;
19047 case NM_MULSA_W_PH:
19048 check_dsp_r2(ctx);
19049 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19050 break;
19051 default:
19052 generate_exception_end(ctx, EXCP_RI);
19053 break;
19055 break;
19056 case NM_POOL32AXF_2_24_31:
19057 switch (extract32(ctx->opcode, 9, 3)) {
19058 case NM_DPAU_H_QBR:
19059 check_dsp(ctx);
19060 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19061 break;
19062 case NM_DPAQX_SA_W_PH:
19063 check_dsp_r2(ctx);
19064 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19065 break;
19066 case NM_DPSU_H_QBR:
19067 check_dsp(ctx);
19068 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19069 break;
19070 case NM_DPSQX_SA_W_PH:
19071 check_dsp_r2(ctx);
19072 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19073 break;
19074 case NM_MULSAQ_S_W_PH:
19075 check_dsp(ctx);
19076 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19077 break;
19078 default:
19079 generate_exception_end(ctx, EXCP_RI);
19080 break;
19082 break;
19083 default:
19084 generate_exception_end(ctx, EXCP_RI);
19085 break;
19088 tcg_temp_free_i32(t0);
19091 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19092 int rt, int rs, int rd)
19094 int ret = rt;
19095 TCGv t0 = tcg_temp_new();
19096 TCGv t1 = tcg_temp_new();
19097 TCGv v0_t = tcg_temp_new();
19098 TCGv v1_t = tcg_temp_new();
19100 gen_load_gpr(v0_t, rt);
19101 gen_load_gpr(v1_t, rs);
19103 switch (opc) {
19104 case NM_POOL32AXF_2_0_7:
19105 switch (extract32(ctx->opcode, 9, 3)) {
19106 case NM_DPA_W_PH:
19107 case NM_DPAQ_S_W_PH:
19108 case NM_DPS_W_PH:
19109 case NM_DPSQ_S_W_PH:
19110 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19111 break;
19112 case NM_BALIGN:
19113 check_dsp_r2(ctx);
19114 if (rt != 0) {
19115 gen_load_gpr(t0, rs);
19116 rd &= 3;
19117 if (rd != 0 && rd != 2) {
19118 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19119 tcg_gen_ext32u_tl(t0, t0);
19120 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19121 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19123 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19125 break;
19126 case NM_MADD:
19127 check_dsp(ctx);
19129 int acc = extract32(ctx->opcode, 14, 2);
19130 TCGv_i64 t2 = tcg_temp_new_i64();
19131 TCGv_i64 t3 = tcg_temp_new_i64();
19133 gen_load_gpr(t0, rt);
19134 gen_load_gpr(t1, rs);
19135 tcg_gen_ext_tl_i64(t2, t0);
19136 tcg_gen_ext_tl_i64(t3, t1);
19137 tcg_gen_mul_i64(t2, t2, t3);
19138 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19139 tcg_gen_add_i64(t2, t2, t3);
19140 tcg_temp_free_i64(t3);
19141 gen_move_low32(cpu_LO[acc], t2);
19142 gen_move_high32(cpu_HI[acc], t2);
19143 tcg_temp_free_i64(t2);
19145 break;
19146 case NM_MULT:
19147 check_dsp(ctx);
19149 int acc = extract32(ctx->opcode, 14, 2);
19150 TCGv_i32 t2 = tcg_temp_new_i32();
19151 TCGv_i32 t3 = tcg_temp_new_i32();
19153 gen_load_gpr(t0, rs);
19154 gen_load_gpr(t1, rt);
19155 tcg_gen_trunc_tl_i32(t2, t0);
19156 tcg_gen_trunc_tl_i32(t3, t1);
19157 tcg_gen_muls2_i32(t2, t3, t2, t3);
19158 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19159 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19160 tcg_temp_free_i32(t2);
19161 tcg_temp_free_i32(t3);
19163 break;
19164 case NM_EXTRV_W:
19165 check_dsp(ctx);
19166 gen_load_gpr(v1_t, rs);
19167 tcg_gen_movi_tl(t0, rd >> 3);
19168 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19169 gen_store_gpr(t0, ret);
19170 break;
19172 break;
19173 case NM_POOL32AXF_2_8_15:
19174 switch (extract32(ctx->opcode, 9, 3)) {
19175 case NM_DPAX_W_PH:
19176 case NM_DPAQ_SA_L_W:
19177 case NM_DPSX_W_PH:
19178 case NM_DPSQ_SA_L_W:
19179 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19180 break;
19181 case NM_MADDU:
19182 check_dsp(ctx);
19184 int acc = extract32(ctx->opcode, 14, 2);
19185 TCGv_i64 t2 = tcg_temp_new_i64();
19186 TCGv_i64 t3 = tcg_temp_new_i64();
19188 gen_load_gpr(t0, rs);
19189 gen_load_gpr(t1, rt);
19190 tcg_gen_ext32u_tl(t0, t0);
19191 tcg_gen_ext32u_tl(t1, t1);
19192 tcg_gen_extu_tl_i64(t2, t0);
19193 tcg_gen_extu_tl_i64(t3, t1);
19194 tcg_gen_mul_i64(t2, t2, t3);
19195 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19196 tcg_gen_add_i64(t2, t2, t3);
19197 tcg_temp_free_i64(t3);
19198 gen_move_low32(cpu_LO[acc], t2);
19199 gen_move_high32(cpu_HI[acc], t2);
19200 tcg_temp_free_i64(t2);
19202 break;
19203 case NM_MULTU:
19204 check_dsp(ctx);
19206 int acc = extract32(ctx->opcode, 14, 2);
19207 TCGv_i32 t2 = tcg_temp_new_i32();
19208 TCGv_i32 t3 = tcg_temp_new_i32();
19210 gen_load_gpr(t0, rs);
19211 gen_load_gpr(t1, rt);
19212 tcg_gen_trunc_tl_i32(t2, t0);
19213 tcg_gen_trunc_tl_i32(t3, t1);
19214 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19215 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19216 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19217 tcg_temp_free_i32(t2);
19218 tcg_temp_free_i32(t3);
19220 break;
19221 case NM_EXTRV_R_W:
19222 check_dsp(ctx);
19223 tcg_gen_movi_tl(t0, rd >> 3);
19224 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19225 gen_store_gpr(t0, ret);
19226 break;
19227 default:
19228 generate_exception_end(ctx, EXCP_RI);
19229 break;
19231 break;
19232 case NM_POOL32AXF_2_16_23:
19233 switch (extract32(ctx->opcode, 9, 3)) {
19234 case NM_DPAU_H_QBL:
19235 case NM_DPAQX_S_W_PH:
19236 case NM_DPSU_H_QBL:
19237 case NM_DPSQX_S_W_PH:
19238 case NM_MULSA_W_PH:
19239 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19240 break;
19241 case NM_EXTPV:
19242 check_dsp(ctx);
19243 tcg_gen_movi_tl(t0, rd >> 3);
19244 gen_helper_extp(t0, t0, v1_t, cpu_env);
19245 gen_store_gpr(t0, ret);
19246 break;
19247 case NM_MSUB:
19248 check_dsp(ctx);
19250 int acc = extract32(ctx->opcode, 14, 2);
19251 TCGv_i64 t2 = tcg_temp_new_i64();
19252 TCGv_i64 t3 = tcg_temp_new_i64();
19254 gen_load_gpr(t0, rs);
19255 gen_load_gpr(t1, rt);
19256 tcg_gen_ext_tl_i64(t2, t0);
19257 tcg_gen_ext_tl_i64(t3, t1);
19258 tcg_gen_mul_i64(t2, t2, t3);
19259 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19260 tcg_gen_sub_i64(t2, t3, t2);
19261 tcg_temp_free_i64(t3);
19262 gen_move_low32(cpu_LO[acc], t2);
19263 gen_move_high32(cpu_HI[acc], t2);
19264 tcg_temp_free_i64(t2);
19266 break;
19267 case NM_EXTRV_RS_W:
19268 check_dsp(ctx);
19269 tcg_gen_movi_tl(t0, rd >> 3);
19270 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19271 gen_store_gpr(t0, ret);
19272 break;
19274 break;
19275 case NM_POOL32AXF_2_24_31:
19276 switch (extract32(ctx->opcode, 9, 3)) {
19277 case NM_DPAU_H_QBR:
19278 case NM_DPAQX_SA_W_PH:
19279 case NM_DPSU_H_QBR:
19280 case NM_DPSQX_SA_W_PH:
19281 case NM_MULSAQ_S_W_PH:
19282 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19283 break;
19284 case NM_EXTPDPV:
19285 check_dsp(ctx);
19286 tcg_gen_movi_tl(t0, rd >> 3);
19287 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19288 gen_store_gpr(t0, ret);
19289 break;
19290 case NM_MSUBU:
19291 check_dsp(ctx);
19293 int acc = extract32(ctx->opcode, 14, 2);
19294 TCGv_i64 t2 = tcg_temp_new_i64();
19295 TCGv_i64 t3 = tcg_temp_new_i64();
19297 gen_load_gpr(t0, rs);
19298 gen_load_gpr(t1, rt);
19299 tcg_gen_ext32u_tl(t0, t0);
19300 tcg_gen_ext32u_tl(t1, t1);
19301 tcg_gen_extu_tl_i64(t2, t0);
19302 tcg_gen_extu_tl_i64(t3, t1);
19303 tcg_gen_mul_i64(t2, t2, t3);
19304 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19305 tcg_gen_sub_i64(t2, t3, t2);
19306 tcg_temp_free_i64(t3);
19307 gen_move_low32(cpu_LO[acc], t2);
19308 gen_move_high32(cpu_HI[acc], t2);
19309 tcg_temp_free_i64(t2);
19311 break;
19312 case NM_EXTRV_S_H:
19313 check_dsp(ctx);
19314 tcg_gen_movi_tl(t0, rd >> 3);
19315 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19316 gen_store_gpr(t0, ret);
19317 break;
19319 break;
19320 default:
19321 generate_exception_end(ctx, EXCP_RI);
19322 break;
19325 tcg_temp_free(t0);
19326 tcg_temp_free(t1);
19328 tcg_temp_free(v0_t);
19329 tcg_temp_free(v1_t);
19332 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19333 int rt, int rs)
19335 int ret = rt;
19336 TCGv t0 = tcg_temp_new();
19337 TCGv v0_t = tcg_temp_new();
19339 gen_load_gpr(v0_t, rs);
19341 switch (opc) {
19342 case NM_ABSQ_S_QB:
19343 check_dsp_r2(ctx);
19344 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19345 gen_store_gpr(v0_t, ret);
19346 break;
19347 case NM_ABSQ_S_PH:
19348 check_dsp(ctx);
19349 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19350 gen_store_gpr(v0_t, ret);
19351 break;
19352 case NM_ABSQ_S_W:
19353 check_dsp(ctx);
19354 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19355 gen_store_gpr(v0_t, ret);
19356 break;
19357 case NM_PRECEQ_W_PHL:
19358 check_dsp(ctx);
19359 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19360 tcg_gen_ext32s_tl(v0_t, v0_t);
19361 gen_store_gpr(v0_t, ret);
19362 break;
19363 case NM_PRECEQ_W_PHR:
19364 check_dsp(ctx);
19365 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19366 tcg_gen_shli_tl(v0_t, v0_t, 16);
19367 tcg_gen_ext32s_tl(v0_t, v0_t);
19368 gen_store_gpr(v0_t, ret);
19369 break;
19370 case NM_PRECEQU_PH_QBL:
19371 check_dsp(ctx);
19372 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19373 gen_store_gpr(v0_t, ret);
19374 break;
19375 case NM_PRECEQU_PH_QBR:
19376 check_dsp(ctx);
19377 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19378 gen_store_gpr(v0_t, ret);
19379 break;
19380 case NM_PRECEQU_PH_QBLA:
19381 check_dsp(ctx);
19382 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19383 gen_store_gpr(v0_t, ret);
19384 break;
19385 case NM_PRECEQU_PH_QBRA:
19386 check_dsp(ctx);
19387 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19388 gen_store_gpr(v0_t, ret);
19389 break;
19390 case NM_PRECEU_PH_QBL:
19391 check_dsp(ctx);
19392 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19393 gen_store_gpr(v0_t, ret);
19394 break;
19395 case NM_PRECEU_PH_QBR:
19396 check_dsp(ctx);
19397 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19398 gen_store_gpr(v0_t, ret);
19399 break;
19400 case NM_PRECEU_PH_QBLA:
19401 check_dsp(ctx);
19402 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19403 gen_store_gpr(v0_t, ret);
19404 break;
19405 case NM_PRECEU_PH_QBRA:
19406 check_dsp(ctx);
19407 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19408 gen_store_gpr(v0_t, ret);
19409 break;
19410 case NM_REPLV_PH:
19411 check_dsp(ctx);
19412 tcg_gen_ext16u_tl(v0_t, v0_t);
19413 tcg_gen_shli_tl(t0, v0_t, 16);
19414 tcg_gen_or_tl(v0_t, v0_t, t0);
19415 tcg_gen_ext32s_tl(v0_t, v0_t);
19416 gen_store_gpr(v0_t, ret);
19417 break;
19418 case NM_REPLV_QB:
19419 check_dsp(ctx);
19420 tcg_gen_ext8u_tl(v0_t, v0_t);
19421 tcg_gen_shli_tl(t0, v0_t, 8);
19422 tcg_gen_or_tl(v0_t, v0_t, t0);
19423 tcg_gen_shli_tl(t0, v0_t, 16);
19424 tcg_gen_or_tl(v0_t, v0_t, t0);
19425 tcg_gen_ext32s_tl(v0_t, v0_t);
19426 gen_store_gpr(v0_t, ret);
19427 break;
19428 case NM_BITREV:
19429 check_dsp(ctx);
19430 gen_helper_bitrev(v0_t, v0_t);
19431 gen_store_gpr(v0_t, ret);
19432 break;
19433 case NM_INSV:
19434 check_dsp(ctx);
19436 TCGv tv0 = tcg_temp_new();
19438 gen_load_gpr(tv0, rt);
19439 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19440 gen_store_gpr(v0_t, ret);
19441 tcg_temp_free(tv0);
19443 break;
19444 case NM_RADDU_W_QB:
19445 check_dsp(ctx);
19446 gen_helper_raddu_w_qb(v0_t, v0_t);
19447 gen_store_gpr(v0_t, ret);
19448 break;
19449 case NM_BITSWAP:
19450 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19451 break;
19452 case NM_CLO:
19453 check_nms(ctx);
19454 gen_cl(ctx, OPC_CLO, ret, rs);
19455 break;
19456 case NM_CLZ:
19457 check_nms(ctx);
19458 gen_cl(ctx, OPC_CLZ, ret, rs);
19459 break;
19460 case NM_WSBH:
19461 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19462 break;
19463 default:
19464 generate_exception_end(ctx, EXCP_RI);
19465 break;
19468 tcg_temp_free(v0_t);
19469 tcg_temp_free(t0);
19472 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19473 int rt, int rs, int rd)
19475 TCGv t0 = tcg_temp_new();
19476 TCGv rs_t = tcg_temp_new();
19478 gen_load_gpr(rs_t, rs);
19480 switch (opc) {
19481 case NM_SHRA_R_QB:
19482 check_dsp_r2(ctx);
19483 tcg_gen_movi_tl(t0, rd >> 2);
19484 switch (extract32(ctx->opcode, 12, 1)) {
19485 case 0:
19486 /* NM_SHRA_QB */
19487 gen_helper_shra_qb(t0, t0, rs_t);
19488 gen_store_gpr(t0, rt);
19489 break;
19490 case 1:
19491 /* NM_SHRA_R_QB */
19492 gen_helper_shra_r_qb(t0, t0, rs_t);
19493 gen_store_gpr(t0, rt);
19494 break;
19496 break;
19497 case NM_SHRL_PH:
19498 check_dsp_r2(ctx);
19499 tcg_gen_movi_tl(t0, rd >> 1);
19500 gen_helper_shrl_ph(t0, t0, rs_t);
19501 gen_store_gpr(t0, rt);
19502 break;
19503 case NM_REPL_QB:
19504 check_dsp(ctx);
19506 int16_t imm;
19507 target_long result;
19508 imm = extract32(ctx->opcode, 13, 8);
19509 result = (uint32_t)imm << 24 |
19510 (uint32_t)imm << 16 |
19511 (uint32_t)imm << 8 |
19512 (uint32_t)imm;
19513 result = (int32_t)result;
19514 tcg_gen_movi_tl(t0, result);
19515 gen_store_gpr(t0, rt);
19517 break;
19518 default:
19519 generate_exception_end(ctx, EXCP_RI);
19520 break;
19522 tcg_temp_free(t0);
19523 tcg_temp_free(rs_t);
19527 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19529 int rt = extract32(ctx->opcode, 21, 5);
19530 int rs = extract32(ctx->opcode, 16, 5);
19531 int rd = extract32(ctx->opcode, 11, 5);
19533 switch (extract32(ctx->opcode, 6, 3)) {
19534 case NM_POOL32AXF_1:
19536 int32_t op1 = extract32(ctx->opcode, 9, 3);
19537 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19539 break;
19540 case NM_POOL32AXF_2:
19542 int32_t op1 = extract32(ctx->opcode, 12, 2);
19543 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19545 break;
19546 case NM_POOL32AXF_4:
19548 int32_t op1 = extract32(ctx->opcode, 9, 7);
19549 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19551 break;
19552 case NM_POOL32AXF_5:
19553 switch (extract32(ctx->opcode, 9, 7)) {
19554 #ifndef CONFIG_USER_ONLY
19555 case NM_TLBP:
19556 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19557 break;
19558 case NM_TLBR:
19559 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19560 break;
19561 case NM_TLBWI:
19562 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19563 break;
19564 case NM_TLBWR:
19565 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19566 break;
19567 case NM_TLBINV:
19568 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19569 break;
19570 case NM_TLBINVF:
19571 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19572 break;
19573 case NM_DI:
19574 check_cp0_enabled(ctx);
19576 TCGv t0 = tcg_temp_new();
19578 save_cpu_state(ctx, 1);
19579 gen_helper_di(t0, cpu_env);
19580 gen_store_gpr(t0, rt);
19581 /* Stop translation as we may have switched the execution mode */
19582 ctx->base.is_jmp = DISAS_STOP;
19583 tcg_temp_free(t0);
19585 break;
19586 case NM_EI:
19587 check_cp0_enabled(ctx);
19589 TCGv t0 = tcg_temp_new();
19591 save_cpu_state(ctx, 1);
19592 gen_helper_ei(t0, cpu_env);
19593 gen_store_gpr(t0, rt);
19594 /* Stop translation as we may have switched the execution mode */
19595 ctx->base.is_jmp = DISAS_STOP;
19596 tcg_temp_free(t0);
19598 break;
19599 case NM_RDPGPR:
19600 gen_load_srsgpr(rs, rt);
19601 break;
19602 case NM_WRPGPR:
19603 gen_store_srsgpr(rs, rt);
19604 break;
19605 case NM_WAIT:
19606 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19607 break;
19608 case NM_DERET:
19609 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19610 break;
19611 case NM_ERETX:
19612 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19613 break;
19614 #endif
19615 default:
19616 generate_exception_end(ctx, EXCP_RI);
19617 break;
19619 break;
19620 case NM_POOL32AXF_7:
19622 int32_t op1 = extract32(ctx->opcode, 9, 3);
19623 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19625 break;
19626 default:
19627 generate_exception_end(ctx, EXCP_RI);
19628 break;
19632 /* Immediate Value Compact Branches */
19633 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19634 int rt, int32_t imm, int32_t offset)
19636 TCGCond cond;
19637 int bcond_compute = 0;
19638 TCGv t0 = tcg_temp_new();
19639 TCGv t1 = tcg_temp_new();
19641 gen_load_gpr(t0, rt);
19642 tcg_gen_movi_tl(t1, imm);
19643 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19645 /* Load needed operands and calculate btarget */
19646 switch (opc) {
19647 case NM_BEQIC:
19648 if (rt == 0 && imm == 0) {
19649 /* Unconditional branch */
19650 } else if (rt == 0 && imm != 0) {
19651 /* Treat as NOP */
19652 goto out;
19653 } else {
19654 bcond_compute = 1;
19655 cond = TCG_COND_EQ;
19657 break;
19658 case NM_BBEQZC:
19659 case NM_BBNEZC:
19660 check_nms(ctx);
19661 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19662 generate_exception_end(ctx, EXCP_RI);
19663 goto out;
19664 } else if (rt == 0 && opc == NM_BBEQZC) {
19665 /* Unconditional branch */
19666 } else if (rt == 0 && opc == NM_BBNEZC) {
19667 /* Treat as NOP */
19668 goto out;
19669 } else {
19670 tcg_gen_shri_tl(t0, t0, imm);
19671 tcg_gen_andi_tl(t0, t0, 1);
19672 tcg_gen_movi_tl(t1, 0);
19673 bcond_compute = 1;
19674 if (opc == NM_BBEQZC) {
19675 cond = TCG_COND_EQ;
19676 } else {
19677 cond = TCG_COND_NE;
19680 break;
19681 case NM_BNEIC:
19682 if (rt == 0 && imm == 0) {
19683 /* Treat as NOP */
19684 goto out;
19685 } else if (rt == 0 && imm != 0) {
19686 /* Unconditional branch */
19687 } else {
19688 bcond_compute = 1;
19689 cond = TCG_COND_NE;
19691 break;
19692 case NM_BGEIC:
19693 if (rt == 0 && imm == 0) {
19694 /* Unconditional branch */
19695 } else {
19696 bcond_compute = 1;
19697 cond = TCG_COND_GE;
19699 break;
19700 case NM_BLTIC:
19701 bcond_compute = 1;
19702 cond = TCG_COND_LT;
19703 break;
19704 case NM_BGEIUC:
19705 if (rt == 0 && imm == 0) {
19706 /* Unconditional branch */
19707 } else {
19708 bcond_compute = 1;
19709 cond = TCG_COND_GEU;
19711 break;
19712 case NM_BLTIUC:
19713 bcond_compute = 1;
19714 cond = TCG_COND_LTU;
19715 break;
19716 default:
19717 MIPS_INVAL("Immediate Value Compact branch");
19718 generate_exception_end(ctx, EXCP_RI);
19719 goto out;
19722 /* branch completion */
19723 clear_branch_hflags(ctx);
19724 ctx->base.is_jmp = DISAS_NORETURN;
19726 if (bcond_compute == 0) {
19727 /* Uncoditional compact branch */
19728 gen_goto_tb(ctx, 0, ctx->btarget);
19729 } else {
19730 /* Conditional compact branch */
19731 TCGLabel *fs = gen_new_label();
19733 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19735 gen_goto_tb(ctx, 1, ctx->btarget);
19736 gen_set_label(fs);
19738 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19741 out:
19742 tcg_temp_free(t0);
19743 tcg_temp_free(t1);
19746 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19747 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19748 int rt)
19750 TCGv t0 = tcg_temp_new();
19751 TCGv t1 = tcg_temp_new();
19753 /* load rs */
19754 gen_load_gpr(t0, rs);
19756 /* link */
19757 if (rt != 0) {
19758 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19761 /* calculate btarget */
19762 tcg_gen_shli_tl(t0, t0, 1);
19763 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19764 gen_op_addr_add(ctx, btarget, t1, t0);
19766 /* branch completion */
19767 clear_branch_hflags(ctx);
19768 ctx->base.is_jmp = DISAS_NORETURN;
19770 /* unconditional branch to register */
19771 tcg_gen_mov_tl(cpu_PC, btarget);
19772 tcg_gen_lookup_and_goto_ptr();
19774 tcg_temp_free(t0);
19775 tcg_temp_free(t1);
19778 /* nanoMIPS Branches */
19779 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19780 int rs, int rt, int32_t offset)
19782 int bcond_compute = 0;
19783 TCGv t0 = tcg_temp_new();
19784 TCGv t1 = tcg_temp_new();
19786 /* Load needed operands and calculate btarget */
19787 switch (opc) {
19788 /* compact branch */
19789 case OPC_BGEC:
19790 case OPC_BLTC:
19791 gen_load_gpr(t0, rs);
19792 gen_load_gpr(t1, rt);
19793 bcond_compute = 1;
19794 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19795 break;
19796 case OPC_BGEUC:
19797 case OPC_BLTUC:
19798 if (rs == 0 || rs == rt) {
19799 /* OPC_BLEZALC, OPC_BGEZALC */
19800 /* OPC_BGTZALC, OPC_BLTZALC */
19801 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19803 gen_load_gpr(t0, rs);
19804 gen_load_gpr(t1, rt);
19805 bcond_compute = 1;
19806 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19807 break;
19808 case OPC_BC:
19809 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19810 break;
19811 case OPC_BEQZC:
19812 if (rs != 0) {
19813 /* OPC_BEQZC, OPC_BNEZC */
19814 gen_load_gpr(t0, rs);
19815 bcond_compute = 1;
19816 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19817 } else {
19818 /* OPC_JIC, OPC_JIALC */
19819 TCGv tbase = tcg_temp_new();
19820 TCGv toffset = tcg_temp_new();
19822 gen_load_gpr(tbase, rt);
19823 tcg_gen_movi_tl(toffset, offset);
19824 gen_op_addr_add(ctx, btarget, tbase, toffset);
19825 tcg_temp_free(tbase);
19826 tcg_temp_free(toffset);
19828 break;
19829 default:
19830 MIPS_INVAL("Compact branch/jump");
19831 generate_exception_end(ctx, EXCP_RI);
19832 goto out;
19835 if (bcond_compute == 0) {
19836 /* Uncoditional compact branch */
19837 switch (opc) {
19838 case OPC_BC:
19839 gen_goto_tb(ctx, 0, ctx->btarget);
19840 break;
19841 default:
19842 MIPS_INVAL("Compact branch/jump");
19843 generate_exception_end(ctx, EXCP_RI);
19844 goto out;
19846 } else {
19847 /* Conditional compact branch */
19848 TCGLabel *fs = gen_new_label();
19850 switch (opc) {
19851 case OPC_BGEUC:
19852 if (rs == 0 && rt != 0) {
19853 /* OPC_BLEZALC */
19854 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19855 } else if (rs != 0 && rt != 0 && rs == rt) {
19856 /* OPC_BGEZALC */
19857 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19858 } else {
19859 /* OPC_BGEUC */
19860 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19862 break;
19863 case OPC_BLTUC:
19864 if (rs == 0 && rt != 0) {
19865 /* OPC_BGTZALC */
19866 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19867 } else if (rs != 0 && rt != 0 && rs == rt) {
19868 /* OPC_BLTZALC */
19869 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19870 } else {
19871 /* OPC_BLTUC */
19872 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19874 break;
19875 case OPC_BGEC:
19876 if (rs == 0 && rt != 0) {
19877 /* OPC_BLEZC */
19878 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19879 } else if (rs != 0 && rt != 0 && rs == rt) {
19880 /* OPC_BGEZC */
19881 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19882 } else {
19883 /* OPC_BGEC */
19884 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19886 break;
19887 case OPC_BLTC:
19888 if (rs == 0 && rt != 0) {
19889 /* OPC_BGTZC */
19890 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19891 } else if (rs != 0 && rt != 0 && rs == rt) {
19892 /* OPC_BLTZC */
19893 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19894 } else {
19895 /* OPC_BLTC */
19896 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19898 break;
19899 case OPC_BEQZC:
19900 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19901 break;
19902 default:
19903 MIPS_INVAL("Compact conditional branch/jump");
19904 generate_exception_end(ctx, EXCP_RI);
19905 goto out;
19908 /* branch completion */
19909 clear_branch_hflags(ctx);
19910 ctx->base.is_jmp = DISAS_NORETURN;
19912 /* Generating branch here as compact branches don't have delay slot */
19913 gen_goto_tb(ctx, 1, ctx->btarget);
19914 gen_set_label(fs);
19916 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19919 out:
19920 tcg_temp_free(t0);
19921 tcg_temp_free(t1);
19925 /* nanoMIPS CP1 Branches */
19926 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19927 int32_t ft, int32_t offset)
19929 target_ulong btarget;
19930 TCGv_i64 t0 = tcg_temp_new_i64();
19932 gen_load_fpr64(ctx, t0, ft);
19933 tcg_gen_andi_i64(t0, t0, 1);
19935 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19937 switch (op) {
19938 case NM_BC1EQZC:
19939 tcg_gen_xori_i64(t0, t0, 1);
19940 ctx->hflags |= MIPS_HFLAG_BC;
19941 break;
19942 case NM_BC1NEZC:
19943 /* t0 already set */
19944 ctx->hflags |= MIPS_HFLAG_BC;
19945 break;
19946 default:
19947 MIPS_INVAL("cp1 cond branch");
19948 generate_exception_end(ctx, EXCP_RI);
19949 goto out;
19952 tcg_gen_trunc_i64_tl(bcond, t0);
19954 ctx->btarget = btarget;
19956 out:
19957 tcg_temp_free_i64(t0);
19961 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19963 TCGv t0, t1;
19964 t0 = tcg_temp_new();
19965 t1 = tcg_temp_new();
19967 gen_load_gpr(t0, rs);
19968 gen_load_gpr(t1, rt);
19970 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19971 /* PP.LSXS instructions require shifting */
19972 switch (extract32(ctx->opcode, 7, 4)) {
19973 case NM_SHXS:
19974 check_nms(ctx);
19975 case NM_LHXS:
19976 case NM_LHUXS:
19977 tcg_gen_shli_tl(t0, t0, 1);
19978 break;
19979 case NM_SWXS:
19980 check_nms(ctx);
19981 case NM_LWXS:
19982 case NM_LWC1XS:
19983 case NM_SWC1XS:
19984 tcg_gen_shli_tl(t0, t0, 2);
19985 break;
19986 case NM_LDC1XS:
19987 case NM_SDC1XS:
19988 tcg_gen_shli_tl(t0, t0, 3);
19989 break;
19992 gen_op_addr_add(ctx, t0, t0, t1);
19994 switch (extract32(ctx->opcode, 7, 4)) {
19995 case NM_LBX:
19996 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19997 MO_SB);
19998 gen_store_gpr(t0, rd);
19999 break;
20000 case NM_LHX:
20001 /*case NM_LHXS:*/
20002 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20003 MO_TESW);
20004 gen_store_gpr(t0, rd);
20005 break;
20006 case NM_LWX:
20007 /*case NM_LWXS:*/
20008 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20009 MO_TESL);
20010 gen_store_gpr(t0, rd);
20011 break;
20012 case NM_LBUX:
20013 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20014 MO_UB);
20015 gen_store_gpr(t0, rd);
20016 break;
20017 case NM_LHUX:
20018 /*case NM_LHUXS:*/
20019 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20020 MO_TEUW);
20021 gen_store_gpr(t0, rd);
20022 break;
20023 case NM_SBX:
20024 check_nms(ctx);
20025 gen_load_gpr(t1, rd);
20026 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20027 MO_8);
20028 break;
20029 case NM_SHX:
20030 /*case NM_SHXS:*/
20031 check_nms(ctx);
20032 gen_load_gpr(t1, rd);
20033 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20034 MO_TEUW);
20035 break;
20036 case NM_SWX:
20037 /*case NM_SWXS:*/
20038 check_nms(ctx);
20039 gen_load_gpr(t1, rd);
20040 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20041 MO_TEUL);
20042 break;
20043 case NM_LWC1X:
20044 /*case NM_LWC1XS:*/
20045 case NM_LDC1X:
20046 /*case NM_LDC1XS:*/
20047 case NM_SWC1X:
20048 /*case NM_SWC1XS:*/
20049 case NM_SDC1X:
20050 /*case NM_SDC1XS:*/
20051 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20052 check_cp1_enabled(ctx);
20053 switch (extract32(ctx->opcode, 7, 4)) {
20054 case NM_LWC1X:
20055 /*case NM_LWC1XS:*/
20056 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20057 break;
20058 case NM_LDC1X:
20059 /*case NM_LDC1XS:*/
20060 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20061 break;
20062 case NM_SWC1X:
20063 /*case NM_SWC1XS:*/
20064 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20065 break;
20066 case NM_SDC1X:
20067 /*case NM_SDC1XS:*/
20068 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20069 break;
20071 } else {
20072 generate_exception_err(ctx, EXCP_CpU, 1);
20074 break;
20075 default:
20076 generate_exception_end(ctx, EXCP_RI);
20077 break;
20080 tcg_temp_free(t0);
20081 tcg_temp_free(t1);
20084 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20086 int rt, rs, rd;
20088 rt = extract32(ctx->opcode, 21, 5);
20089 rs = extract32(ctx->opcode, 16, 5);
20090 rd = extract32(ctx->opcode, 11, 5);
20092 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20093 generate_exception_end(ctx, EXCP_RI);
20094 return;
20096 check_cp1_enabled(ctx);
20097 switch (extract32(ctx->opcode, 0, 3)) {
20098 case NM_POOL32F_0:
20099 switch (extract32(ctx->opcode, 3, 7)) {
20100 case NM_RINT_S:
20101 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20102 break;
20103 case NM_RINT_D:
20104 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20105 break;
20106 case NM_CLASS_S:
20107 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20108 break;
20109 case NM_CLASS_D:
20110 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20111 break;
20112 case NM_ADD_S:
20113 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20114 break;
20115 case NM_ADD_D:
20116 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20117 break;
20118 case NM_SUB_S:
20119 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20120 break;
20121 case NM_SUB_D:
20122 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20123 break;
20124 case NM_MUL_S:
20125 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20126 break;
20127 case NM_MUL_D:
20128 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20129 break;
20130 case NM_DIV_S:
20131 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20132 break;
20133 case NM_DIV_D:
20134 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20135 break;
20136 case NM_SELEQZ_S:
20137 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20138 break;
20139 case NM_SELEQZ_D:
20140 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20141 break;
20142 case NM_SELNEZ_S:
20143 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20144 break;
20145 case NM_SELNEZ_D:
20146 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20147 break;
20148 case NM_SEL_S:
20149 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20150 break;
20151 case NM_SEL_D:
20152 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20153 break;
20154 case NM_MADDF_S:
20155 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20156 break;
20157 case NM_MADDF_D:
20158 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20159 break;
20160 case NM_MSUBF_S:
20161 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20162 break;
20163 case NM_MSUBF_D:
20164 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20165 break;
20166 default:
20167 generate_exception_end(ctx, EXCP_RI);
20168 break;
20170 break;
20171 case NM_POOL32F_3:
20172 switch (extract32(ctx->opcode, 3, 3)) {
20173 case NM_MIN_FMT:
20174 switch (extract32(ctx->opcode, 9, 1)) {
20175 case FMT_SDPS_S:
20176 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20177 break;
20178 case FMT_SDPS_D:
20179 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20180 break;
20182 break;
20183 case NM_MAX_FMT:
20184 switch (extract32(ctx->opcode, 9, 1)) {
20185 case FMT_SDPS_S:
20186 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20187 break;
20188 case FMT_SDPS_D:
20189 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20190 break;
20192 break;
20193 case NM_MINA_FMT:
20194 switch (extract32(ctx->opcode, 9, 1)) {
20195 case FMT_SDPS_S:
20196 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20197 break;
20198 case FMT_SDPS_D:
20199 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20200 break;
20202 break;
20203 case NM_MAXA_FMT:
20204 switch (extract32(ctx->opcode, 9, 1)) {
20205 case FMT_SDPS_S:
20206 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20207 break;
20208 case FMT_SDPS_D:
20209 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20210 break;
20212 break;
20213 case NM_POOL32FXF:
20214 switch (extract32(ctx->opcode, 6, 8)) {
20215 case NM_CFC1:
20216 gen_cp1(ctx, OPC_CFC1, rt, rs);
20217 break;
20218 case NM_CTC1:
20219 gen_cp1(ctx, OPC_CTC1, rt, rs);
20220 break;
20221 case NM_MFC1:
20222 gen_cp1(ctx, OPC_MFC1, rt, rs);
20223 break;
20224 case NM_MTC1:
20225 gen_cp1(ctx, OPC_MTC1, rt, rs);
20226 break;
20227 case NM_MFHC1:
20228 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20229 break;
20230 case NM_MTHC1:
20231 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20232 break;
20233 case NM_CVT_S_PL:
20234 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20235 break;
20236 case NM_CVT_S_PU:
20237 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20238 break;
20239 default:
20240 switch (extract32(ctx->opcode, 6, 9)) {
20241 case NM_CVT_L_S:
20242 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20243 break;
20244 case NM_CVT_L_D:
20245 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20246 break;
20247 case NM_CVT_W_S:
20248 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20249 break;
20250 case NM_CVT_W_D:
20251 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20252 break;
20253 case NM_RSQRT_S:
20254 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20255 break;
20256 case NM_RSQRT_D:
20257 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20258 break;
20259 case NM_SQRT_S:
20260 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20261 break;
20262 case NM_SQRT_D:
20263 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20264 break;
20265 case NM_RECIP_S:
20266 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20267 break;
20268 case NM_RECIP_D:
20269 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20270 break;
20271 case NM_FLOOR_L_S:
20272 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20273 break;
20274 case NM_FLOOR_L_D:
20275 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20276 break;
20277 case NM_FLOOR_W_S:
20278 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20279 break;
20280 case NM_FLOOR_W_D:
20281 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20282 break;
20283 case NM_CEIL_L_S:
20284 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20285 break;
20286 case NM_CEIL_L_D:
20287 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20288 break;
20289 case NM_CEIL_W_S:
20290 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20291 break;
20292 case NM_CEIL_W_D:
20293 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20294 break;
20295 case NM_TRUNC_L_S:
20296 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20297 break;
20298 case NM_TRUNC_L_D:
20299 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20300 break;
20301 case NM_TRUNC_W_S:
20302 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20303 break;
20304 case NM_TRUNC_W_D:
20305 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20306 break;
20307 case NM_ROUND_L_S:
20308 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20309 break;
20310 case NM_ROUND_L_D:
20311 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20312 break;
20313 case NM_ROUND_W_S:
20314 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20315 break;
20316 case NM_ROUND_W_D:
20317 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20318 break;
20319 case NM_MOV_S:
20320 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20321 break;
20322 case NM_MOV_D:
20323 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20324 break;
20325 case NM_ABS_S:
20326 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20327 break;
20328 case NM_ABS_D:
20329 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20330 break;
20331 case NM_NEG_S:
20332 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20333 break;
20334 case NM_NEG_D:
20335 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20336 break;
20337 case NM_CVT_D_S:
20338 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20339 break;
20340 case NM_CVT_D_W:
20341 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20342 break;
20343 case NM_CVT_D_L:
20344 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20345 break;
20346 case NM_CVT_S_D:
20347 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20348 break;
20349 case NM_CVT_S_W:
20350 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20351 break;
20352 case NM_CVT_S_L:
20353 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20354 break;
20355 default:
20356 generate_exception_end(ctx, EXCP_RI);
20357 break;
20359 break;
20361 break;
20363 break;
20364 case NM_POOL32F_5:
20365 switch (extract32(ctx->opcode, 3, 3)) {
20366 case NM_CMP_CONDN_S:
20367 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20368 break;
20369 case NM_CMP_CONDN_D:
20370 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20371 break;
20372 default:
20373 generate_exception_end(ctx, EXCP_RI);
20374 break;
20376 break;
20377 default:
20378 generate_exception_end(ctx, EXCP_RI);
20379 break;
20383 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20384 int rd, int rs, int rt)
20386 int ret = rd;
20387 TCGv t0 = tcg_temp_new();
20388 TCGv v1_t = tcg_temp_new();
20389 TCGv v2_t = tcg_temp_new();
20391 gen_load_gpr(v1_t, rs);
20392 gen_load_gpr(v2_t, rt);
20394 switch (opc) {
20395 case NM_CMP_EQ_PH:
20396 check_dsp(ctx);
20397 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20398 break;
20399 case NM_CMP_LT_PH:
20400 check_dsp(ctx);
20401 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20402 break;
20403 case NM_CMP_LE_PH:
20404 check_dsp(ctx);
20405 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20406 break;
20407 case NM_CMPU_EQ_QB:
20408 check_dsp(ctx);
20409 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20410 break;
20411 case NM_CMPU_LT_QB:
20412 check_dsp(ctx);
20413 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20414 break;
20415 case NM_CMPU_LE_QB:
20416 check_dsp(ctx);
20417 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20418 break;
20419 case NM_CMPGU_EQ_QB:
20420 check_dsp(ctx);
20421 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20422 gen_store_gpr(v1_t, ret);
20423 break;
20424 case NM_CMPGU_LT_QB:
20425 check_dsp(ctx);
20426 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20427 gen_store_gpr(v1_t, ret);
20428 break;
20429 case NM_CMPGU_LE_QB:
20430 check_dsp(ctx);
20431 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20432 gen_store_gpr(v1_t, ret);
20433 break;
20434 case NM_CMPGDU_EQ_QB:
20435 check_dsp_r2(ctx);
20436 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20437 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20438 gen_store_gpr(v1_t, ret);
20439 break;
20440 case NM_CMPGDU_LT_QB:
20441 check_dsp_r2(ctx);
20442 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20443 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20444 gen_store_gpr(v1_t, ret);
20445 break;
20446 case NM_CMPGDU_LE_QB:
20447 check_dsp_r2(ctx);
20448 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20449 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20450 gen_store_gpr(v1_t, ret);
20451 break;
20452 case NM_PACKRL_PH:
20453 check_dsp(ctx);
20454 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20455 gen_store_gpr(v1_t, ret);
20456 break;
20457 case NM_PICK_QB:
20458 check_dsp(ctx);
20459 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20460 gen_store_gpr(v1_t, ret);
20461 break;
20462 case NM_PICK_PH:
20463 check_dsp(ctx);
20464 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20465 gen_store_gpr(v1_t, ret);
20466 break;
20467 case NM_ADDQ_S_W:
20468 check_dsp(ctx);
20469 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20470 gen_store_gpr(v1_t, ret);
20471 break;
20472 case NM_SUBQ_S_W:
20473 check_dsp(ctx);
20474 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20475 gen_store_gpr(v1_t, ret);
20476 break;
20477 case NM_ADDSC:
20478 check_dsp(ctx);
20479 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20480 gen_store_gpr(v1_t, ret);
20481 break;
20482 case NM_ADDWC:
20483 check_dsp(ctx);
20484 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20485 gen_store_gpr(v1_t, ret);
20486 break;
20487 case NM_ADDQ_S_PH:
20488 check_dsp(ctx);
20489 switch (extract32(ctx->opcode, 10, 1)) {
20490 case 0:
20491 /* ADDQ_PH */
20492 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20493 gen_store_gpr(v1_t, ret);
20494 break;
20495 case 1:
20496 /* ADDQ_S_PH */
20497 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20498 gen_store_gpr(v1_t, ret);
20499 break;
20501 break;
20502 case NM_ADDQH_R_PH:
20503 check_dsp_r2(ctx);
20504 switch (extract32(ctx->opcode, 10, 1)) {
20505 case 0:
20506 /* ADDQH_PH */
20507 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20508 gen_store_gpr(v1_t, ret);
20509 break;
20510 case 1:
20511 /* ADDQH_R_PH */
20512 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20513 gen_store_gpr(v1_t, ret);
20514 break;
20516 break;
20517 case NM_ADDQH_R_W:
20518 check_dsp_r2(ctx);
20519 switch (extract32(ctx->opcode, 10, 1)) {
20520 case 0:
20521 /* ADDQH_W */
20522 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20523 gen_store_gpr(v1_t, ret);
20524 break;
20525 case 1:
20526 /* ADDQH_R_W */
20527 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20528 gen_store_gpr(v1_t, ret);
20529 break;
20531 break;
20532 case NM_ADDU_S_QB:
20533 check_dsp(ctx);
20534 switch (extract32(ctx->opcode, 10, 1)) {
20535 case 0:
20536 /* ADDU_QB */
20537 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20538 gen_store_gpr(v1_t, ret);
20539 break;
20540 case 1:
20541 /* ADDU_S_QB */
20542 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20543 gen_store_gpr(v1_t, ret);
20544 break;
20546 break;
20547 case NM_ADDU_S_PH:
20548 check_dsp_r2(ctx);
20549 switch (extract32(ctx->opcode, 10, 1)) {
20550 case 0:
20551 /* ADDU_PH */
20552 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20553 gen_store_gpr(v1_t, ret);
20554 break;
20555 case 1:
20556 /* ADDU_S_PH */
20557 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20558 gen_store_gpr(v1_t, ret);
20559 break;
20561 break;
20562 case NM_ADDUH_R_QB:
20563 check_dsp_r2(ctx);
20564 switch (extract32(ctx->opcode, 10, 1)) {
20565 case 0:
20566 /* ADDUH_QB */
20567 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20568 gen_store_gpr(v1_t, ret);
20569 break;
20570 case 1:
20571 /* ADDUH_R_QB */
20572 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20573 gen_store_gpr(v1_t, ret);
20574 break;
20576 break;
20577 case NM_SHRAV_R_PH:
20578 check_dsp(ctx);
20579 switch (extract32(ctx->opcode, 10, 1)) {
20580 case 0:
20581 /* SHRAV_PH */
20582 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20583 gen_store_gpr(v1_t, ret);
20584 break;
20585 case 1:
20586 /* SHRAV_R_PH */
20587 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20588 gen_store_gpr(v1_t, ret);
20589 break;
20591 break;
20592 case NM_SHRAV_R_QB:
20593 check_dsp_r2(ctx);
20594 switch (extract32(ctx->opcode, 10, 1)) {
20595 case 0:
20596 /* SHRAV_QB */
20597 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20598 gen_store_gpr(v1_t, ret);
20599 break;
20600 case 1:
20601 /* SHRAV_R_QB */
20602 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20603 gen_store_gpr(v1_t, ret);
20604 break;
20606 break;
20607 case NM_SUBQ_S_PH:
20608 check_dsp(ctx);
20609 switch (extract32(ctx->opcode, 10, 1)) {
20610 case 0:
20611 /* SUBQ_PH */
20612 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20613 gen_store_gpr(v1_t, ret);
20614 break;
20615 case 1:
20616 /* SUBQ_S_PH */
20617 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20618 gen_store_gpr(v1_t, ret);
20619 break;
20621 break;
20622 case NM_SUBQH_R_PH:
20623 check_dsp_r2(ctx);
20624 switch (extract32(ctx->opcode, 10, 1)) {
20625 case 0:
20626 /* SUBQH_PH */
20627 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20628 gen_store_gpr(v1_t, ret);
20629 break;
20630 case 1:
20631 /* SUBQH_R_PH */
20632 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20633 gen_store_gpr(v1_t, ret);
20634 break;
20636 break;
20637 case NM_SUBQH_R_W:
20638 check_dsp_r2(ctx);
20639 switch (extract32(ctx->opcode, 10, 1)) {
20640 case 0:
20641 /* SUBQH_W */
20642 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20643 gen_store_gpr(v1_t, ret);
20644 break;
20645 case 1:
20646 /* SUBQH_R_W */
20647 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20648 gen_store_gpr(v1_t, ret);
20649 break;
20651 break;
20652 case NM_SUBU_S_QB:
20653 check_dsp(ctx);
20654 switch (extract32(ctx->opcode, 10, 1)) {
20655 case 0:
20656 /* SUBU_QB */
20657 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20658 gen_store_gpr(v1_t, ret);
20659 break;
20660 case 1:
20661 /* SUBU_S_QB */
20662 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20663 gen_store_gpr(v1_t, ret);
20664 break;
20666 break;
20667 case NM_SUBU_S_PH:
20668 check_dsp_r2(ctx);
20669 switch (extract32(ctx->opcode, 10, 1)) {
20670 case 0:
20671 /* SUBU_PH */
20672 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20673 gen_store_gpr(v1_t, ret);
20674 break;
20675 case 1:
20676 /* SUBU_S_PH */
20677 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20678 gen_store_gpr(v1_t, ret);
20679 break;
20681 break;
20682 case NM_SUBUH_R_QB:
20683 check_dsp_r2(ctx);
20684 switch (extract32(ctx->opcode, 10, 1)) {
20685 case 0:
20686 /* SUBUH_QB */
20687 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20688 gen_store_gpr(v1_t, ret);
20689 break;
20690 case 1:
20691 /* SUBUH_R_QB */
20692 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20693 gen_store_gpr(v1_t, ret);
20694 break;
20696 break;
20697 case NM_SHLLV_S_PH:
20698 check_dsp(ctx);
20699 switch (extract32(ctx->opcode, 10, 1)) {
20700 case 0:
20701 /* SHLLV_PH */
20702 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20703 gen_store_gpr(v1_t, ret);
20704 break;
20705 case 1:
20706 /* SHLLV_S_PH */
20707 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20708 gen_store_gpr(v1_t, ret);
20709 break;
20711 break;
20712 case NM_PRECR_SRA_R_PH_W:
20713 check_dsp_r2(ctx);
20714 switch (extract32(ctx->opcode, 10, 1)) {
20715 case 0:
20716 /* PRECR_SRA_PH_W */
20718 TCGv_i32 sa_t = tcg_const_i32(rd);
20719 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20720 cpu_gpr[rt]);
20721 gen_store_gpr(v1_t, rt);
20722 tcg_temp_free_i32(sa_t);
20724 break;
20725 case 1:
20726 /* PRECR_SRA_R_PH_W */
20728 TCGv_i32 sa_t = tcg_const_i32(rd);
20729 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20730 cpu_gpr[rt]);
20731 gen_store_gpr(v1_t, rt);
20732 tcg_temp_free_i32(sa_t);
20734 break;
20736 break;
20737 case NM_MULEU_S_PH_QBL:
20738 check_dsp(ctx);
20739 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20740 gen_store_gpr(v1_t, ret);
20741 break;
20742 case NM_MULEU_S_PH_QBR:
20743 check_dsp(ctx);
20744 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20745 gen_store_gpr(v1_t, ret);
20746 break;
20747 case NM_MULQ_RS_PH:
20748 check_dsp(ctx);
20749 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20750 gen_store_gpr(v1_t, ret);
20751 break;
20752 case NM_MULQ_S_PH:
20753 check_dsp_r2(ctx);
20754 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20755 gen_store_gpr(v1_t, ret);
20756 break;
20757 case NM_MULQ_RS_W:
20758 check_dsp_r2(ctx);
20759 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20760 gen_store_gpr(v1_t, ret);
20761 break;
20762 case NM_MULQ_S_W:
20763 check_dsp_r2(ctx);
20764 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20765 gen_store_gpr(v1_t, ret);
20766 break;
20767 case NM_APPEND:
20768 check_dsp_r2(ctx);
20769 gen_load_gpr(t0, rs);
20770 if (rd != 0) {
20771 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20773 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20774 break;
20775 case NM_MODSUB:
20776 check_dsp(ctx);
20777 gen_helper_modsub(v1_t, v1_t, v2_t);
20778 gen_store_gpr(v1_t, ret);
20779 break;
20780 case NM_SHRAV_R_W:
20781 check_dsp(ctx);
20782 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20783 gen_store_gpr(v1_t, ret);
20784 break;
20785 case NM_SHRLV_PH:
20786 check_dsp_r2(ctx);
20787 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20788 gen_store_gpr(v1_t, ret);
20789 break;
20790 case NM_SHRLV_QB:
20791 check_dsp(ctx);
20792 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20793 gen_store_gpr(v1_t, ret);
20794 break;
20795 case NM_SHLLV_QB:
20796 check_dsp(ctx);
20797 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20798 gen_store_gpr(v1_t, ret);
20799 break;
20800 case NM_SHLLV_S_W:
20801 check_dsp(ctx);
20802 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20803 gen_store_gpr(v1_t, ret);
20804 break;
20805 case NM_SHILO:
20806 check_dsp(ctx);
20808 TCGv tv0 = tcg_temp_new();
20809 TCGv tv1 = tcg_temp_new();
20810 int16_t imm = extract32(ctx->opcode, 16, 7);
20812 tcg_gen_movi_tl(tv0, rd >> 3);
20813 tcg_gen_movi_tl(tv1, imm);
20814 gen_helper_shilo(tv0, tv1, cpu_env);
20816 break;
20817 case NM_MULEQ_S_W_PHL:
20818 check_dsp(ctx);
20819 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20820 gen_store_gpr(v1_t, ret);
20821 break;
20822 case NM_MULEQ_S_W_PHR:
20823 check_dsp(ctx);
20824 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20825 gen_store_gpr(v1_t, ret);
20826 break;
20827 case NM_MUL_S_PH:
20828 check_dsp_r2(ctx);
20829 switch (extract32(ctx->opcode, 10, 1)) {
20830 case 0:
20831 /* MUL_PH */
20832 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20833 gen_store_gpr(v1_t, ret);
20834 break;
20835 case 1:
20836 /* MUL_S_PH */
20837 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20838 gen_store_gpr(v1_t, ret);
20839 break;
20841 break;
20842 case NM_PRECR_QB_PH:
20843 check_dsp_r2(ctx);
20844 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20845 gen_store_gpr(v1_t, ret);
20846 break;
20847 case NM_PRECRQ_QB_PH:
20848 check_dsp(ctx);
20849 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20850 gen_store_gpr(v1_t, ret);
20851 break;
20852 case NM_PRECRQ_PH_W:
20853 check_dsp(ctx);
20854 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20855 gen_store_gpr(v1_t, ret);
20856 break;
20857 case NM_PRECRQ_RS_PH_W:
20858 check_dsp(ctx);
20859 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20860 gen_store_gpr(v1_t, ret);
20861 break;
20862 case NM_PRECRQU_S_QB_PH:
20863 check_dsp(ctx);
20864 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20865 gen_store_gpr(v1_t, ret);
20866 break;
20867 case NM_SHRA_R_W:
20868 check_dsp(ctx);
20869 tcg_gen_movi_tl(t0, rd);
20870 gen_helper_shra_r_w(v1_t, t0, v1_t);
20871 gen_store_gpr(v1_t, rt);
20872 break;
20873 case NM_SHRA_R_PH:
20874 check_dsp(ctx);
20875 tcg_gen_movi_tl(t0, rd >> 1);
20876 switch (extract32(ctx->opcode, 10, 1)) {
20877 case 0:
20878 /* SHRA_PH */
20879 gen_helper_shra_ph(v1_t, t0, v1_t);
20880 gen_store_gpr(v1_t, rt);
20881 break;
20882 case 1:
20883 /* SHRA_R_PH */
20884 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20885 gen_store_gpr(v1_t, rt);
20886 break;
20888 break;
20889 case NM_SHLL_S_PH:
20890 check_dsp(ctx);
20891 tcg_gen_movi_tl(t0, rd >> 1);
20892 switch (extract32(ctx->opcode, 10, 2)) {
20893 case 0:
20894 /* SHLL_PH */
20895 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20896 gen_store_gpr(v1_t, rt);
20897 break;
20898 case 2:
20899 /* SHLL_S_PH */
20900 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20901 gen_store_gpr(v1_t, rt);
20902 break;
20903 default:
20904 generate_exception_end(ctx, EXCP_RI);
20905 break;
20907 break;
20908 case NM_SHLL_S_W:
20909 check_dsp(ctx);
20910 tcg_gen_movi_tl(t0, rd);
20911 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20912 gen_store_gpr(v1_t, rt);
20913 break;
20914 case NM_REPL_PH:
20915 check_dsp(ctx);
20917 int16_t imm;
20918 imm = sextract32(ctx->opcode, 11, 11);
20919 imm = (int16_t)(imm << 6) >> 6;
20920 if (rt != 0) {
20921 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20924 break;
20925 default:
20926 generate_exception_end(ctx, EXCP_RI);
20927 break;
20931 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20933 uint16_t insn;
20934 uint32_t op;
20935 int rt, rs, rd;
20936 int offset;
20937 int imm;
20939 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20940 ctx->opcode = (ctx->opcode << 16) | insn;
20942 rt = extract32(ctx->opcode, 21, 5);
20943 rs = extract32(ctx->opcode, 16, 5);
20944 rd = extract32(ctx->opcode, 11, 5);
20946 op = extract32(ctx->opcode, 26, 6);
20947 switch (op) {
20948 case NM_P_ADDIU:
20949 if (rt == 0) {
20950 /* P.RI */
20951 switch (extract32(ctx->opcode, 19, 2)) {
20952 case NM_SIGRIE:
20953 default:
20954 generate_exception_end(ctx, EXCP_RI);
20955 break;
20956 case NM_P_SYSCALL:
20957 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20958 generate_exception_end(ctx, EXCP_SYSCALL);
20959 } else {
20960 generate_exception_end(ctx, EXCP_RI);
20962 break;
20963 case NM_BREAK:
20964 generate_exception_end(ctx, EXCP_BREAK);
20965 break;
20966 case NM_SDBBP:
20967 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20968 gen_helper_do_semihosting(cpu_env);
20969 } else {
20970 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20971 generate_exception_end(ctx, EXCP_RI);
20972 } else {
20973 generate_exception_end(ctx, EXCP_DBp);
20976 break;
20978 } else {
20979 /* NM_ADDIU */
20980 imm = extract32(ctx->opcode, 0, 16);
20981 if (rs != 0) {
20982 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20983 } else {
20984 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20986 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20988 break;
20989 case NM_ADDIUPC:
20990 if (rt != 0) {
20991 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20992 extract32(ctx->opcode, 1, 20) << 1;
20993 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20994 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20996 break;
20997 case NM_POOL32A:
20998 switch (ctx->opcode & 0x07) {
20999 case NM_POOL32A0:
21000 gen_pool32a0_nanomips_insn(env, ctx);
21001 break;
21002 case NM_POOL32A5:
21004 int32_t op1 = extract32(ctx->opcode, 3, 7);
21005 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21007 break;
21008 case NM_POOL32A7:
21009 switch (extract32(ctx->opcode, 3, 3)) {
21010 case NM_P_LSX:
21011 gen_p_lsx(ctx, rd, rs, rt);
21012 break;
21013 case NM_LSA:
21014 /* In nanoMIPS, the shift field directly encodes the shift
21015 * amount, meaning that the supported shift values are in
21016 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
21017 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21018 extract32(ctx->opcode, 9, 2) - 1);
21019 break;
21020 case NM_EXTW:
21021 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21022 break;
21023 case NM_POOL32AXF:
21024 gen_pool32axf_nanomips_insn(env, ctx);
21025 break;
21026 default:
21027 generate_exception_end(ctx, EXCP_RI);
21028 break;
21030 break;
21031 default:
21032 generate_exception_end(ctx, EXCP_RI);
21033 break;
21035 break;
21036 case NM_P_GP_W:
21037 switch (ctx->opcode & 0x03) {
21038 case NM_ADDIUGP_W:
21039 if (rt != 0) {
21040 offset = extract32(ctx->opcode, 0, 21);
21041 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21043 break;
21044 case NM_LWGP:
21045 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21046 break;
21047 case NM_SWGP:
21048 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21049 break;
21050 default:
21051 generate_exception_end(ctx, EXCP_RI);
21052 break;
21054 break;
21055 case NM_P48I:
21057 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21058 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21059 switch (extract32(ctx->opcode, 16, 5)) {
21060 case NM_LI48:
21061 check_nms(ctx);
21062 if (rt != 0) {
21063 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21065 break;
21066 case NM_ADDIU48:
21067 check_nms(ctx);
21068 if (rt != 0) {
21069 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21070 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21072 break;
21073 case NM_ADDIUGP48:
21074 check_nms(ctx);
21075 if (rt != 0) {
21076 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21078 break;
21079 case NM_ADDIUPC48:
21080 check_nms(ctx);
21081 if (rt != 0) {
21082 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21083 addr_off);
21085 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21087 break;
21088 case NM_LWPC48:
21089 check_nms(ctx);
21090 if (rt != 0) {
21091 TCGv t0;
21092 t0 = tcg_temp_new();
21094 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21095 addr_off);
21097 tcg_gen_movi_tl(t0, addr);
21098 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21099 tcg_temp_free(t0);
21101 break;
21102 case NM_SWPC48:
21103 check_nms(ctx);
21105 TCGv t0, t1;
21106 t0 = tcg_temp_new();
21107 t1 = tcg_temp_new();
21109 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21110 addr_off);
21112 tcg_gen_movi_tl(t0, addr);
21113 gen_load_gpr(t1, rt);
21115 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21117 tcg_temp_free(t0);
21118 tcg_temp_free(t1);
21120 break;
21121 default:
21122 generate_exception_end(ctx, EXCP_RI);
21123 break;
21125 return 6;
21127 case NM_P_U12:
21128 switch (extract32(ctx->opcode, 12, 4)) {
21129 case NM_ORI:
21130 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21131 break;
21132 case NM_XORI:
21133 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21134 break;
21135 case NM_ANDI:
21136 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21137 break;
21138 case NM_P_SR:
21139 switch (extract32(ctx->opcode, 20, 1)) {
21140 case NM_PP_SR:
21141 switch (ctx->opcode & 3) {
21142 case NM_SAVE:
21143 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21144 extract32(ctx->opcode, 2, 1),
21145 extract32(ctx->opcode, 3, 9) << 3);
21146 break;
21147 case NM_RESTORE:
21148 case NM_RESTORE_JRC:
21149 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21150 extract32(ctx->opcode, 2, 1),
21151 extract32(ctx->opcode, 3, 9) << 3);
21152 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21153 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21155 break;
21156 default:
21157 generate_exception_end(ctx, EXCP_RI);
21158 break;
21160 break;
21161 case NM_P_SR_F:
21162 generate_exception_end(ctx, EXCP_RI);
21163 break;
21165 break;
21166 case NM_SLTI:
21167 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21168 break;
21169 case NM_SLTIU:
21170 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21171 break;
21172 case NM_SEQI:
21174 TCGv t0 = tcg_temp_new();
21176 imm = extract32(ctx->opcode, 0, 12);
21177 gen_load_gpr(t0, rs);
21178 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21179 gen_store_gpr(t0, rt);
21181 tcg_temp_free(t0);
21183 break;
21184 case NM_ADDIUNEG:
21185 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21186 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21187 break;
21188 case NM_P_SHIFT:
21190 int shift = extract32(ctx->opcode, 0, 5);
21191 switch (extract32(ctx->opcode, 5, 4)) {
21192 case NM_P_SLL:
21193 if (rt == 0 && shift == 0) {
21194 /* NOP */
21195 } else if (rt == 0 && shift == 3) {
21196 /* EHB - treat as NOP */
21197 } else if (rt == 0 && shift == 5) {
21198 /* PAUSE - treat as NOP */
21199 } else if (rt == 0 && shift == 6) {
21200 /* SYNC */
21201 gen_sync(extract32(ctx->opcode, 16, 5));
21202 } else {
21203 /* SLL */
21204 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21205 extract32(ctx->opcode, 0, 5));
21207 break;
21208 case NM_SRL:
21209 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21210 extract32(ctx->opcode, 0, 5));
21211 break;
21212 case NM_SRA:
21213 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21214 extract32(ctx->opcode, 0, 5));
21215 break;
21216 case NM_ROTR:
21217 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21218 extract32(ctx->opcode, 0, 5));
21219 break;
21222 break;
21223 case NM_P_ROTX:
21224 check_nms(ctx);
21225 if (rt != 0) {
21226 TCGv t0 = tcg_temp_new();
21227 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21228 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21229 << 1);
21230 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21232 gen_load_gpr(t0, rs);
21233 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21234 tcg_temp_free(t0);
21236 tcg_temp_free_i32(shift);
21237 tcg_temp_free_i32(shiftx);
21238 tcg_temp_free_i32(stripe);
21240 break;
21241 case NM_P_INS:
21242 switch (((ctx->opcode >> 10) & 2) |
21243 (extract32(ctx->opcode, 5, 1))) {
21244 case NM_INS:
21245 check_nms(ctx);
21246 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21247 extract32(ctx->opcode, 6, 5));
21248 break;
21249 default:
21250 generate_exception_end(ctx, EXCP_RI);
21251 break;
21253 break;
21254 case NM_P_EXT:
21255 switch (((ctx->opcode >> 10) & 2) |
21256 (extract32(ctx->opcode, 5, 1))) {
21257 case NM_EXT:
21258 check_nms(ctx);
21259 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21260 extract32(ctx->opcode, 6, 5));
21261 break;
21262 default:
21263 generate_exception_end(ctx, EXCP_RI);
21264 break;
21266 break;
21267 default:
21268 generate_exception_end(ctx, EXCP_RI);
21269 break;
21271 break;
21272 case NM_POOL32F:
21273 gen_pool32f_nanomips_insn(ctx);
21274 break;
21275 case NM_POOL32S:
21276 break;
21277 case NM_P_LUI:
21278 switch (extract32(ctx->opcode, 1, 1)) {
21279 case NM_LUI:
21280 if (rt != 0) {
21281 tcg_gen_movi_tl(cpu_gpr[rt],
21282 sextract32(ctx->opcode, 0, 1) << 31 |
21283 extract32(ctx->opcode, 2, 10) << 21 |
21284 extract32(ctx->opcode, 12, 9) << 12);
21286 break;
21287 case NM_ALUIPC:
21288 if (rt != 0) {
21289 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21290 extract32(ctx->opcode, 2, 10) << 21 |
21291 extract32(ctx->opcode, 12, 9) << 12;
21292 target_long addr;
21293 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21294 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21296 break;
21298 break;
21299 case NM_P_GP_BH:
21301 uint32_t u = extract32(ctx->opcode, 0, 18);
21303 switch (extract32(ctx->opcode, 18, 3)) {
21304 case NM_LBGP:
21305 gen_ld(ctx, OPC_LB, rt, 28, u);
21306 break;
21307 case NM_SBGP:
21308 gen_st(ctx, OPC_SB, rt, 28, u);
21309 break;
21310 case NM_LBUGP:
21311 gen_ld(ctx, OPC_LBU, rt, 28, u);
21312 break;
21313 case NM_ADDIUGP_B:
21314 if (rt != 0) {
21315 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21317 break;
21318 case NM_P_GP_LH:
21319 u &= ~1;
21320 switch (ctx->opcode & 1) {
21321 case NM_LHGP:
21322 gen_ld(ctx, OPC_LH, rt, 28, u);
21323 break;
21324 case NM_LHUGP:
21325 gen_ld(ctx, OPC_LHU, rt, 28, u);
21326 break;
21328 break;
21329 case NM_P_GP_SH:
21330 u &= ~1;
21331 switch (ctx->opcode & 1) {
21332 case NM_SHGP:
21333 gen_st(ctx, OPC_SH, rt, 28, u);
21334 break;
21335 default:
21336 generate_exception_end(ctx, EXCP_RI);
21337 break;
21339 break;
21340 case NM_P_GP_CP1:
21341 u &= ~0x3;
21342 switch (ctx->opcode & 0x3) {
21343 case NM_LWC1GP:
21344 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21345 break;
21346 case NM_LDC1GP:
21347 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21348 break;
21349 case NM_SWC1GP:
21350 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21351 break;
21352 case NM_SDC1GP:
21353 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21354 break;
21356 break;
21357 default:
21358 generate_exception_end(ctx, EXCP_RI);
21359 break;
21362 break;
21363 case NM_P_LS_U12:
21365 uint32_t u = extract32(ctx->opcode, 0, 12);
21367 switch (extract32(ctx->opcode, 12, 4)) {
21368 case NM_P_PREFU12:
21369 if (rt == 31) {
21370 /* SYNCI */
21371 /* Break the TB to be able to sync copied instructions
21372 immediately */
21373 ctx->base.is_jmp = DISAS_STOP;
21374 } else {
21375 /* PREF */
21376 /* Treat as NOP. */
21378 break;
21379 case NM_LB:
21380 gen_ld(ctx, OPC_LB, rt, rs, u);
21381 break;
21382 case NM_LH:
21383 gen_ld(ctx, OPC_LH, rt, rs, u);
21384 break;
21385 case NM_LW:
21386 gen_ld(ctx, OPC_LW, rt, rs, u);
21387 break;
21388 case NM_LBU:
21389 gen_ld(ctx, OPC_LBU, rt, rs, u);
21390 break;
21391 case NM_LHU:
21392 gen_ld(ctx, OPC_LHU, rt, rs, u);
21393 break;
21394 case NM_SB:
21395 gen_st(ctx, OPC_SB, rt, rs, u);
21396 break;
21397 case NM_SH:
21398 gen_st(ctx, OPC_SH, rt, rs, u);
21399 break;
21400 case NM_SW:
21401 gen_st(ctx, OPC_SW, rt, rs, u);
21402 break;
21403 case NM_LWC1:
21404 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21405 break;
21406 case NM_LDC1:
21407 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21408 break;
21409 case NM_SWC1:
21410 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21411 break;
21412 case NM_SDC1:
21413 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21414 break;
21415 default:
21416 generate_exception_end(ctx, EXCP_RI);
21417 break;
21420 break;
21421 case NM_P_LS_S9:
21423 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21424 extract32(ctx->opcode, 0, 8);
21426 switch (extract32(ctx->opcode, 8, 3)) {
21427 case NM_P_LS_S0:
21428 switch (extract32(ctx->opcode, 11, 4)) {
21429 case NM_LBS9:
21430 gen_ld(ctx, OPC_LB, rt, rs, s);
21431 break;
21432 case NM_LHS9:
21433 gen_ld(ctx, OPC_LH, rt, rs, s);
21434 break;
21435 case NM_LWS9:
21436 gen_ld(ctx, OPC_LW, rt, rs, s);
21437 break;
21438 case NM_LBUS9:
21439 gen_ld(ctx, OPC_LBU, rt, rs, s);
21440 break;
21441 case NM_LHUS9:
21442 gen_ld(ctx, OPC_LHU, rt, rs, s);
21443 break;
21444 case NM_SBS9:
21445 gen_st(ctx, OPC_SB, rt, rs, s);
21446 break;
21447 case NM_SHS9:
21448 gen_st(ctx, OPC_SH, rt, rs, s);
21449 break;
21450 case NM_SWS9:
21451 gen_st(ctx, OPC_SW, rt, rs, s);
21452 break;
21453 case NM_LWC1S9:
21454 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21455 break;
21456 case NM_LDC1S9:
21457 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21458 break;
21459 case NM_SWC1S9:
21460 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21461 break;
21462 case NM_SDC1S9:
21463 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21464 break;
21465 case NM_P_PREFS9:
21466 if (rt == 31) {
21467 /* SYNCI */
21468 /* Break the TB to be able to sync copied instructions
21469 immediately */
21470 ctx->base.is_jmp = DISAS_STOP;
21471 } else {
21472 /* PREF */
21473 /* Treat as NOP. */
21475 break;
21476 default:
21477 generate_exception_end(ctx, EXCP_RI);
21478 break;
21480 break;
21481 case NM_P_LS_S1:
21482 switch (extract32(ctx->opcode, 11, 4)) {
21483 case NM_UALH:
21484 case NM_UASH:
21485 check_nms(ctx);
21487 TCGv t0 = tcg_temp_new();
21488 TCGv t1 = tcg_temp_new();
21490 gen_base_offset_addr(ctx, t0, rs, s);
21492 switch (extract32(ctx->opcode, 11, 4)) {
21493 case NM_UALH:
21494 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21495 MO_UNALN);
21496 gen_store_gpr(t0, rt);
21497 break;
21498 case NM_UASH:
21499 gen_load_gpr(t1, rt);
21500 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21501 MO_UNALN);
21502 break;
21504 tcg_temp_free(t0);
21505 tcg_temp_free(t1);
21507 break;
21508 case NM_P_LL:
21509 switch (ctx->opcode & 0x03) {
21510 case NM_LL:
21511 gen_ld(ctx, OPC_LL, rt, rs, s);
21512 break;
21513 case NM_LLWP:
21514 check_xnp(ctx);
21515 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21516 break;
21518 break;
21519 case NM_P_SC:
21520 switch (ctx->opcode & 0x03) {
21521 case NM_SC:
21522 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21523 break;
21524 case NM_SCWP:
21525 check_xnp(ctx);
21526 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21527 false);
21528 break;
21530 break;
21531 case NM_CACHE:
21532 check_cp0_enabled(ctx);
21533 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21534 gen_cache_operation(ctx, rt, rs, s);
21536 break;
21538 break;
21539 case NM_P_LS_E0:
21540 switch (extract32(ctx->opcode, 11, 4)) {
21541 case NM_LBE:
21542 check_eva(ctx);
21543 check_cp0_enabled(ctx);
21544 gen_ld(ctx, OPC_LBE, rt, rs, s);
21545 break;
21546 case NM_SBE:
21547 check_eva(ctx);
21548 check_cp0_enabled(ctx);
21549 gen_st(ctx, OPC_SBE, rt, rs, s);
21550 break;
21551 case NM_LBUE:
21552 check_eva(ctx);
21553 check_cp0_enabled(ctx);
21554 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21555 break;
21556 case NM_P_PREFE:
21557 if (rt == 31) {
21558 /* case NM_SYNCIE */
21559 check_eva(ctx);
21560 check_cp0_enabled(ctx);
21561 /* Break the TB to be able to sync copied instructions
21562 immediately */
21563 ctx->base.is_jmp = DISAS_STOP;
21564 } else {
21565 /* case NM_PREFE */
21566 check_eva(ctx);
21567 check_cp0_enabled(ctx);
21568 /* Treat as NOP. */
21570 break;
21571 case NM_LHE:
21572 check_eva(ctx);
21573 check_cp0_enabled(ctx);
21574 gen_ld(ctx, OPC_LHE, rt, rs, s);
21575 break;
21576 case NM_SHE:
21577 check_eva(ctx);
21578 check_cp0_enabled(ctx);
21579 gen_st(ctx, OPC_SHE, rt, rs, s);
21580 break;
21581 case NM_LHUE:
21582 check_eva(ctx);
21583 check_cp0_enabled(ctx);
21584 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21585 break;
21586 case NM_CACHEE:
21587 check_nms_dl_il_sl_tl_l2c(ctx);
21588 gen_cache_operation(ctx, rt, rs, s);
21589 break;
21590 case NM_LWE:
21591 check_eva(ctx);
21592 check_cp0_enabled(ctx);
21593 gen_ld(ctx, OPC_LWE, rt, rs, s);
21594 break;
21595 case NM_SWE:
21596 check_eva(ctx);
21597 check_cp0_enabled(ctx);
21598 gen_st(ctx, OPC_SWE, rt, rs, s);
21599 break;
21600 case NM_P_LLE:
21601 switch (extract32(ctx->opcode, 2, 2)) {
21602 case NM_LLE:
21603 check_xnp(ctx);
21604 check_eva(ctx);
21605 check_cp0_enabled(ctx);
21606 gen_ld(ctx, OPC_LLE, rt, rs, s);
21607 break;
21608 case NM_LLWPE:
21609 check_xnp(ctx);
21610 check_eva(ctx);
21611 check_cp0_enabled(ctx);
21612 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21613 break;
21614 default:
21615 generate_exception_end(ctx, EXCP_RI);
21616 break;
21618 break;
21619 case NM_P_SCE:
21620 switch (extract32(ctx->opcode, 2, 2)) {
21621 case NM_SCE:
21622 check_xnp(ctx);
21623 check_eva(ctx);
21624 check_cp0_enabled(ctx);
21625 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21626 break;
21627 case NM_SCWPE:
21628 check_xnp(ctx);
21629 check_eva(ctx);
21630 check_cp0_enabled(ctx);
21631 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21632 true);
21633 break;
21634 default:
21635 generate_exception_end(ctx, EXCP_RI);
21636 break;
21638 break;
21640 break;
21641 case NM_P_LS_WM:
21642 case NM_P_LS_UAWM:
21643 check_nms(ctx);
21645 int count = extract32(ctx->opcode, 12, 3);
21646 int counter = 0;
21648 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21649 extract32(ctx->opcode, 0, 8);
21650 TCGv va = tcg_temp_new();
21651 TCGv t1 = tcg_temp_new();
21652 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21653 NM_P_LS_UAWM ? MO_UNALN : 0;
21655 count = (count == 0) ? 8 : count;
21656 while (counter != count) {
21657 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21658 int this_offset = offset + (counter << 2);
21660 gen_base_offset_addr(ctx, va, rs, this_offset);
21662 switch (extract32(ctx->opcode, 11, 1)) {
21663 case NM_LWM:
21664 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21665 memop | MO_TESL);
21666 gen_store_gpr(t1, this_rt);
21667 if ((this_rt == rs) &&
21668 (counter != (count - 1))) {
21669 /* UNPREDICTABLE */
21671 break;
21672 case NM_SWM:
21673 this_rt = (rt == 0) ? 0 : this_rt;
21674 gen_load_gpr(t1, this_rt);
21675 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21676 memop | MO_TEUL);
21677 break;
21679 counter++;
21681 tcg_temp_free(va);
21682 tcg_temp_free(t1);
21684 break;
21685 default:
21686 generate_exception_end(ctx, EXCP_RI);
21687 break;
21690 break;
21691 case NM_MOVE_BALC:
21692 check_nms(ctx);
21694 TCGv t0 = tcg_temp_new();
21695 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21696 extract32(ctx->opcode, 1, 20) << 1;
21697 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21698 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21699 extract32(ctx->opcode, 21, 3));
21700 gen_load_gpr(t0, rt);
21701 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21702 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21703 tcg_temp_free(t0);
21705 break;
21706 case NM_P_BAL:
21708 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21709 extract32(ctx->opcode, 1, 24) << 1;
21711 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21712 /* BC */
21713 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21714 } else {
21715 /* BALC */
21716 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21719 break;
21720 case NM_P_J:
21721 switch (extract32(ctx->opcode, 12, 4)) {
21722 case NM_JALRC:
21723 case NM_JALRC_HB:
21724 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21725 break;
21726 case NM_P_BALRSC:
21727 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21728 break;
21729 default:
21730 generate_exception_end(ctx, EXCP_RI);
21731 break;
21733 break;
21734 case NM_P_BR1:
21736 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21737 extract32(ctx->opcode, 1, 13) << 1;
21738 switch (extract32(ctx->opcode, 14, 2)) {
21739 case NM_BEQC:
21740 check_nms(ctx);
21741 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21742 break;
21743 case NM_P_BR3A:
21744 s = sextract32(ctx->opcode, 0, 1) << 14 |
21745 extract32(ctx->opcode, 1, 13) << 1;
21746 check_cp1_enabled(ctx);
21747 switch (extract32(ctx->opcode, 16, 5)) {
21748 case NM_BC1EQZC:
21749 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21750 break;
21751 case NM_BC1NEZC:
21752 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21753 break;
21754 case NM_BPOSGE32C:
21755 check_dsp_r3(ctx);
21757 int32_t imm = extract32(ctx->opcode, 1, 13) |
21758 extract32(ctx->opcode, 0, 1) << 13;
21760 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21761 imm);
21763 break;
21764 default:
21765 generate_exception_end(ctx, EXCP_RI);
21766 break;
21768 break;
21769 case NM_BGEC:
21770 if (rs == rt) {
21771 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21772 } else {
21773 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21775 break;
21776 case NM_BGEUC:
21777 if (rs == rt || rt == 0) {
21778 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21779 } else if (rs == 0) {
21780 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21781 } else {
21782 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21784 break;
21787 break;
21788 case NM_P_BR2:
21790 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21791 extract32(ctx->opcode, 1, 13) << 1;
21792 switch (extract32(ctx->opcode, 14, 2)) {
21793 case NM_BNEC:
21794 check_nms(ctx);
21795 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21796 break;
21797 case NM_BLTC:
21798 if (rs != 0 && rt != 0 && rs == rt) {
21799 /* NOP */
21800 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21801 } else {
21802 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21804 break;
21805 case NM_BLTUC:
21806 if (rs == 0 || rs == rt) {
21807 /* NOP */
21808 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21809 } else {
21810 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21812 break;
21813 default:
21814 generate_exception_end(ctx, EXCP_RI);
21815 break;
21818 break;
21819 case NM_P_BRI:
21821 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21822 extract32(ctx->opcode, 1, 10) << 1;
21823 uint32_t u = extract32(ctx->opcode, 11, 7);
21825 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21826 rt, u, s);
21828 break;
21829 default:
21830 generate_exception_end(ctx, EXCP_RI);
21831 break;
21833 return 4;
21836 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21838 uint32_t op;
21839 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21840 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21841 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21842 int offset;
21843 int imm;
21845 /* make sure instructions are on a halfword boundary */
21846 if (ctx->base.pc_next & 0x1) {
21847 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21848 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21849 tcg_temp_free(tmp);
21850 generate_exception_end(ctx, EXCP_AdEL);
21851 return 2;
21854 op = extract32(ctx->opcode, 10, 6);
21855 switch (op) {
21856 case NM_P16_MV:
21857 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21858 if (rt != 0) {
21859 /* MOVE */
21860 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21861 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21862 } else {
21863 /* P16.RI */
21864 switch (extract32(ctx->opcode, 3, 2)) {
21865 case NM_P16_SYSCALL:
21866 if (extract32(ctx->opcode, 2, 1) == 0) {
21867 generate_exception_end(ctx, EXCP_SYSCALL);
21868 } else {
21869 generate_exception_end(ctx, EXCP_RI);
21871 break;
21872 case NM_BREAK16:
21873 generate_exception_end(ctx, EXCP_BREAK);
21874 break;
21875 case NM_SDBBP16:
21876 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21877 gen_helper_do_semihosting(cpu_env);
21878 } else {
21879 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21880 generate_exception_end(ctx, EXCP_RI);
21881 } else {
21882 generate_exception_end(ctx, EXCP_DBp);
21885 break;
21886 default:
21887 generate_exception_end(ctx, EXCP_RI);
21888 break;
21891 break;
21892 case NM_P16_SHIFT:
21894 int shift = extract32(ctx->opcode, 0, 3);
21895 uint32_t opc = 0;
21896 shift = (shift == 0) ? 8 : shift;
21898 switch (extract32(ctx->opcode, 3, 1)) {
21899 case NM_SLL16:
21900 opc = OPC_SLL;
21901 break;
21902 case NM_SRL16:
21903 opc = OPC_SRL;
21904 break;
21906 gen_shift_imm(ctx, opc, rt, rs, shift);
21908 break;
21909 case NM_P16C:
21910 switch (ctx->opcode & 1) {
21911 case NM_POOL16C_0:
21912 gen_pool16c_nanomips_insn(ctx);
21913 break;
21914 case NM_LWXS16:
21915 gen_ldxs(ctx, rt, rs, rd);
21916 break;
21918 break;
21919 case NM_P16_A1:
21920 switch (extract32(ctx->opcode, 6, 1)) {
21921 case NM_ADDIUR1SP:
21922 imm = extract32(ctx->opcode, 0, 6) << 2;
21923 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21924 break;
21925 default:
21926 generate_exception_end(ctx, EXCP_RI);
21927 break;
21929 break;
21930 case NM_P16_A2:
21931 switch (extract32(ctx->opcode, 3, 1)) {
21932 case NM_ADDIUR2:
21933 imm = extract32(ctx->opcode, 0, 3) << 2;
21934 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21935 break;
21936 case NM_P_ADDIURS5:
21937 rt = extract32(ctx->opcode, 5, 5);
21938 if (rt != 0) {
21939 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21940 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21941 (extract32(ctx->opcode, 0, 3));
21942 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21944 break;
21946 break;
21947 case NM_P16_ADDU:
21948 switch (ctx->opcode & 0x1) {
21949 case NM_ADDU16:
21950 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21951 break;
21952 case NM_SUBU16:
21953 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21954 break;
21956 break;
21957 case NM_P16_4X4:
21958 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21959 extract32(ctx->opcode, 5, 3);
21960 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21961 extract32(ctx->opcode, 0, 3);
21962 rt = decode_gpr_gpr4(rt);
21963 rs = decode_gpr_gpr4(rs);
21964 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21965 (extract32(ctx->opcode, 3, 1))) {
21966 case NM_ADDU4X4:
21967 check_nms(ctx);
21968 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21969 break;
21970 case NM_MUL4X4:
21971 check_nms(ctx);
21972 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21973 break;
21974 default:
21975 generate_exception_end(ctx, EXCP_RI);
21976 break;
21978 break;
21979 case NM_LI16:
21981 int imm = extract32(ctx->opcode, 0, 7);
21982 imm = (imm == 0x7f ? -1 : imm);
21983 if (rt != 0) {
21984 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21987 break;
21988 case NM_ANDI16:
21990 uint32_t u = extract32(ctx->opcode, 0, 4);
21991 u = (u == 12) ? 0xff :
21992 (u == 13) ? 0xffff : u;
21993 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21995 break;
21996 case NM_P16_LB:
21997 offset = extract32(ctx->opcode, 0, 2);
21998 switch (extract32(ctx->opcode, 2, 2)) {
21999 case NM_LB16:
22000 gen_ld(ctx, OPC_LB, rt, rs, offset);
22001 break;
22002 case NM_SB16:
22003 rt = decode_gpr_gpr3_src_store(
22004 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22005 gen_st(ctx, OPC_SB, rt, rs, offset);
22006 break;
22007 case NM_LBU16:
22008 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22009 break;
22010 default:
22011 generate_exception_end(ctx, EXCP_RI);
22012 break;
22014 break;
22015 case NM_P16_LH:
22016 offset = extract32(ctx->opcode, 1, 2) << 1;
22017 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22018 case NM_LH16:
22019 gen_ld(ctx, OPC_LH, rt, rs, offset);
22020 break;
22021 case NM_SH16:
22022 rt = decode_gpr_gpr3_src_store(
22023 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22024 gen_st(ctx, OPC_SH, rt, rs, offset);
22025 break;
22026 case NM_LHU16:
22027 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22028 break;
22029 default:
22030 generate_exception_end(ctx, EXCP_RI);
22031 break;
22033 break;
22034 case NM_LW16:
22035 offset = extract32(ctx->opcode, 0, 4) << 2;
22036 gen_ld(ctx, OPC_LW, rt, rs, offset);
22037 break;
22038 case NM_LWSP16:
22039 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22040 offset = extract32(ctx->opcode, 0, 5) << 2;
22041 gen_ld(ctx, OPC_LW, rt, 29, offset);
22042 break;
22043 case NM_LW4X4:
22044 check_nms(ctx);
22045 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22046 extract32(ctx->opcode, 5, 3);
22047 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22048 extract32(ctx->opcode, 0, 3);
22049 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22050 (extract32(ctx->opcode, 8, 1) << 2);
22051 rt = decode_gpr_gpr4(rt);
22052 rs = decode_gpr_gpr4(rs);
22053 gen_ld(ctx, OPC_LW, rt, rs, offset);
22054 break;
22055 case NM_SW4X4:
22056 check_nms(ctx);
22057 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22058 extract32(ctx->opcode, 5, 3);
22059 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22060 extract32(ctx->opcode, 0, 3);
22061 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22062 (extract32(ctx->opcode, 8, 1) << 2);
22063 rt = decode_gpr_gpr4_zero(rt);
22064 rs = decode_gpr_gpr4(rs);
22065 gen_st(ctx, OPC_SW, rt, rs, offset);
22066 break;
22067 case NM_LWGP16:
22068 offset = extract32(ctx->opcode, 0, 7) << 2;
22069 gen_ld(ctx, OPC_LW, rt, 28, offset);
22070 break;
22071 case NM_SWSP16:
22072 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22073 offset = extract32(ctx->opcode, 0, 5) << 2;
22074 gen_st(ctx, OPC_SW, rt, 29, offset);
22075 break;
22076 case NM_SW16:
22077 rt = decode_gpr_gpr3_src_store(
22078 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22079 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22080 offset = extract32(ctx->opcode, 0, 4) << 2;
22081 gen_st(ctx, OPC_SW, rt, rs, offset);
22082 break;
22083 case NM_SWGP16:
22084 rt = decode_gpr_gpr3_src_store(
22085 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22086 offset = extract32(ctx->opcode, 0, 7) << 2;
22087 gen_st(ctx, OPC_SW, rt, 28, offset);
22088 break;
22089 case NM_BC16:
22090 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22091 (sextract32(ctx->opcode, 0, 1) << 10) |
22092 (extract32(ctx->opcode, 1, 9) << 1));
22093 break;
22094 case NM_BALC16:
22095 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22096 (sextract32(ctx->opcode, 0, 1) << 10) |
22097 (extract32(ctx->opcode, 1, 9) << 1));
22098 break;
22099 case NM_BEQZC16:
22100 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22101 (sextract32(ctx->opcode, 0, 1) << 7) |
22102 (extract32(ctx->opcode, 1, 6) << 1));
22103 break;
22104 case NM_BNEZC16:
22105 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22106 (sextract32(ctx->opcode, 0, 1) << 7) |
22107 (extract32(ctx->opcode, 1, 6) << 1));
22108 break;
22109 case NM_P16_BR:
22110 switch (ctx->opcode & 0xf) {
22111 case 0:
22112 /* P16.JRC */
22113 switch (extract32(ctx->opcode, 4, 1)) {
22114 case NM_JRC:
22115 gen_compute_branch_nm(ctx, OPC_JR, 2,
22116 extract32(ctx->opcode, 5, 5), 0, 0);
22117 break;
22118 case NM_JALRC16:
22119 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22120 extract32(ctx->opcode, 5, 5), 31, 0);
22121 break;
22123 break;
22124 default:
22126 /* P16.BRI */
22127 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22128 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22129 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22130 extract32(ctx->opcode, 0, 4) << 1);
22132 break;
22134 break;
22135 case NM_P16_SR:
22137 int count = extract32(ctx->opcode, 0, 4);
22138 int u = extract32(ctx->opcode, 4, 4) << 4;
22140 rt = 30 + extract32(ctx->opcode, 9, 1);
22141 switch (extract32(ctx->opcode, 8, 1)) {
22142 case NM_SAVE16:
22143 gen_save(ctx, rt, count, 0, u);
22144 break;
22145 case NM_RESTORE_JRC16:
22146 gen_restore(ctx, rt, count, 0, u);
22147 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22148 break;
22151 break;
22152 case NM_MOVEP:
22153 case NM_MOVEPREV:
22154 check_nms(ctx);
22156 static const int gpr2reg1[] = {4, 5, 6, 7};
22157 static const int gpr2reg2[] = {5, 6, 7, 8};
22158 int re;
22159 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22160 extract32(ctx->opcode, 8, 1);
22161 int r1 = gpr2reg1[rd2];
22162 int r2 = gpr2reg2[rd2];
22163 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22164 extract32(ctx->opcode, 0, 3);
22165 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22166 extract32(ctx->opcode, 5, 3);
22167 TCGv t0 = tcg_temp_new();
22168 TCGv t1 = tcg_temp_new();
22169 if (op == NM_MOVEP) {
22170 rd = r1;
22171 re = r2;
22172 rs = decode_gpr_gpr4_zero(r3);
22173 rt = decode_gpr_gpr4_zero(r4);
22174 } else {
22175 rd = decode_gpr_gpr4(r3);
22176 re = decode_gpr_gpr4(r4);
22177 rs = r1;
22178 rt = r2;
22180 gen_load_gpr(t0, rs);
22181 gen_load_gpr(t1, rt);
22182 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22183 tcg_gen_mov_tl(cpu_gpr[re], t1);
22184 tcg_temp_free(t0);
22185 tcg_temp_free(t1);
22187 break;
22188 default:
22189 return decode_nanomips_32_48_opc(env, ctx);
22192 return 2;
22196 /* SmartMIPS extension to MIPS32 */
22198 #if defined(TARGET_MIPS64)
22200 /* MDMX extension to MIPS64 */
22202 #endif
22204 /* MIPSDSP functions. */
22205 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22206 int rd, int base, int offset)
22208 TCGv t0;
22210 check_dsp(ctx);
22211 t0 = tcg_temp_new();
22213 if (base == 0) {
22214 gen_load_gpr(t0, offset);
22215 } else if (offset == 0) {
22216 gen_load_gpr(t0, base);
22217 } else {
22218 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22221 switch (opc) {
22222 case OPC_LBUX:
22223 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22224 gen_store_gpr(t0, rd);
22225 break;
22226 case OPC_LHX:
22227 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22228 gen_store_gpr(t0, rd);
22229 break;
22230 case OPC_LWX:
22231 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22232 gen_store_gpr(t0, rd);
22233 break;
22234 #if defined(TARGET_MIPS64)
22235 case OPC_LDX:
22236 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22237 gen_store_gpr(t0, rd);
22238 break;
22239 #endif
22241 tcg_temp_free(t0);
22244 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22245 int ret, int v1, int v2)
22247 TCGv v1_t;
22248 TCGv v2_t;
22250 if (ret == 0) {
22251 /* Treat as NOP. */
22252 return;
22255 v1_t = tcg_temp_new();
22256 v2_t = tcg_temp_new();
22258 gen_load_gpr(v1_t, v1);
22259 gen_load_gpr(v2_t, v2);
22261 switch (op1) {
22262 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22263 case OPC_MULT_G_2E:
22264 check_dsp_r2(ctx);
22265 switch (op2) {
22266 case OPC_ADDUH_QB:
22267 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22268 break;
22269 case OPC_ADDUH_R_QB:
22270 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22271 break;
22272 case OPC_ADDQH_PH:
22273 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22274 break;
22275 case OPC_ADDQH_R_PH:
22276 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22277 break;
22278 case OPC_ADDQH_W:
22279 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22280 break;
22281 case OPC_ADDQH_R_W:
22282 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22283 break;
22284 case OPC_SUBUH_QB:
22285 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22286 break;
22287 case OPC_SUBUH_R_QB:
22288 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22289 break;
22290 case OPC_SUBQH_PH:
22291 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22292 break;
22293 case OPC_SUBQH_R_PH:
22294 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22295 break;
22296 case OPC_SUBQH_W:
22297 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22298 break;
22299 case OPC_SUBQH_R_W:
22300 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22301 break;
22303 break;
22304 case OPC_ABSQ_S_PH_DSP:
22305 switch (op2) {
22306 case OPC_ABSQ_S_QB:
22307 check_dsp_r2(ctx);
22308 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22309 break;
22310 case OPC_ABSQ_S_PH:
22311 check_dsp(ctx);
22312 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22313 break;
22314 case OPC_ABSQ_S_W:
22315 check_dsp(ctx);
22316 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22317 break;
22318 case OPC_PRECEQ_W_PHL:
22319 check_dsp(ctx);
22320 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22321 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22322 break;
22323 case OPC_PRECEQ_W_PHR:
22324 check_dsp(ctx);
22325 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22326 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22327 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22328 break;
22329 case OPC_PRECEQU_PH_QBL:
22330 check_dsp(ctx);
22331 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22332 break;
22333 case OPC_PRECEQU_PH_QBR:
22334 check_dsp(ctx);
22335 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22336 break;
22337 case OPC_PRECEQU_PH_QBLA:
22338 check_dsp(ctx);
22339 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22340 break;
22341 case OPC_PRECEQU_PH_QBRA:
22342 check_dsp(ctx);
22343 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22344 break;
22345 case OPC_PRECEU_PH_QBL:
22346 check_dsp(ctx);
22347 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22348 break;
22349 case OPC_PRECEU_PH_QBR:
22350 check_dsp(ctx);
22351 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22352 break;
22353 case OPC_PRECEU_PH_QBLA:
22354 check_dsp(ctx);
22355 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22356 break;
22357 case OPC_PRECEU_PH_QBRA:
22358 check_dsp(ctx);
22359 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22360 break;
22362 break;
22363 case OPC_ADDU_QB_DSP:
22364 switch (op2) {
22365 case OPC_ADDQ_PH:
22366 check_dsp(ctx);
22367 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22368 break;
22369 case OPC_ADDQ_S_PH:
22370 check_dsp(ctx);
22371 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22372 break;
22373 case OPC_ADDQ_S_W:
22374 check_dsp(ctx);
22375 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22376 break;
22377 case OPC_ADDU_QB:
22378 check_dsp(ctx);
22379 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22380 break;
22381 case OPC_ADDU_S_QB:
22382 check_dsp(ctx);
22383 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22384 break;
22385 case OPC_ADDU_PH:
22386 check_dsp_r2(ctx);
22387 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22388 break;
22389 case OPC_ADDU_S_PH:
22390 check_dsp_r2(ctx);
22391 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22392 break;
22393 case OPC_SUBQ_PH:
22394 check_dsp(ctx);
22395 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22396 break;
22397 case OPC_SUBQ_S_PH:
22398 check_dsp(ctx);
22399 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22400 break;
22401 case OPC_SUBQ_S_W:
22402 check_dsp(ctx);
22403 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22404 break;
22405 case OPC_SUBU_QB:
22406 check_dsp(ctx);
22407 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22408 break;
22409 case OPC_SUBU_S_QB:
22410 check_dsp(ctx);
22411 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22412 break;
22413 case OPC_SUBU_PH:
22414 check_dsp_r2(ctx);
22415 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22416 break;
22417 case OPC_SUBU_S_PH:
22418 check_dsp_r2(ctx);
22419 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22420 break;
22421 case OPC_ADDSC:
22422 check_dsp(ctx);
22423 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22424 break;
22425 case OPC_ADDWC:
22426 check_dsp(ctx);
22427 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22428 break;
22429 case OPC_MODSUB:
22430 check_dsp(ctx);
22431 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22432 break;
22433 case OPC_RADDU_W_QB:
22434 check_dsp(ctx);
22435 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22436 break;
22438 break;
22439 case OPC_CMPU_EQ_QB_DSP:
22440 switch (op2) {
22441 case OPC_PRECR_QB_PH:
22442 check_dsp_r2(ctx);
22443 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22444 break;
22445 case OPC_PRECRQ_QB_PH:
22446 check_dsp(ctx);
22447 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22448 break;
22449 case OPC_PRECR_SRA_PH_W:
22450 check_dsp_r2(ctx);
22452 TCGv_i32 sa_t = tcg_const_i32(v2);
22453 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22454 cpu_gpr[ret]);
22455 tcg_temp_free_i32(sa_t);
22456 break;
22458 case OPC_PRECR_SRA_R_PH_W:
22459 check_dsp_r2(ctx);
22461 TCGv_i32 sa_t = tcg_const_i32(v2);
22462 gen_helper_precr_sra_r_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_PRECRQ_PH_W:
22468 check_dsp(ctx);
22469 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22470 break;
22471 case OPC_PRECRQ_RS_PH_W:
22472 check_dsp(ctx);
22473 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22474 break;
22475 case OPC_PRECRQU_S_QB_PH:
22476 check_dsp(ctx);
22477 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22478 break;
22480 break;
22481 #ifdef TARGET_MIPS64
22482 case OPC_ABSQ_S_QH_DSP:
22483 switch (op2) {
22484 case OPC_PRECEQ_L_PWL:
22485 check_dsp(ctx);
22486 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22487 break;
22488 case OPC_PRECEQ_L_PWR:
22489 check_dsp(ctx);
22490 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22491 break;
22492 case OPC_PRECEQ_PW_QHL:
22493 check_dsp(ctx);
22494 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22495 break;
22496 case OPC_PRECEQ_PW_QHR:
22497 check_dsp(ctx);
22498 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22499 break;
22500 case OPC_PRECEQ_PW_QHLA:
22501 check_dsp(ctx);
22502 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22503 break;
22504 case OPC_PRECEQ_PW_QHRA:
22505 check_dsp(ctx);
22506 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22507 break;
22508 case OPC_PRECEQU_QH_OBL:
22509 check_dsp(ctx);
22510 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22511 break;
22512 case OPC_PRECEQU_QH_OBR:
22513 check_dsp(ctx);
22514 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22515 break;
22516 case OPC_PRECEQU_QH_OBLA:
22517 check_dsp(ctx);
22518 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22519 break;
22520 case OPC_PRECEQU_QH_OBRA:
22521 check_dsp(ctx);
22522 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22523 break;
22524 case OPC_PRECEU_QH_OBL:
22525 check_dsp(ctx);
22526 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22527 break;
22528 case OPC_PRECEU_QH_OBR:
22529 check_dsp(ctx);
22530 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22531 break;
22532 case OPC_PRECEU_QH_OBLA:
22533 check_dsp(ctx);
22534 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22535 break;
22536 case OPC_PRECEU_QH_OBRA:
22537 check_dsp(ctx);
22538 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22539 break;
22540 case OPC_ABSQ_S_OB:
22541 check_dsp_r2(ctx);
22542 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22543 break;
22544 case OPC_ABSQ_S_PW:
22545 check_dsp(ctx);
22546 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22547 break;
22548 case OPC_ABSQ_S_QH:
22549 check_dsp(ctx);
22550 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22551 break;
22553 break;
22554 case OPC_ADDU_OB_DSP:
22555 switch (op2) {
22556 case OPC_RADDU_L_OB:
22557 check_dsp(ctx);
22558 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22559 break;
22560 case OPC_SUBQ_PW:
22561 check_dsp(ctx);
22562 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22563 break;
22564 case OPC_SUBQ_S_PW:
22565 check_dsp(ctx);
22566 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22567 break;
22568 case OPC_SUBQ_QH:
22569 check_dsp(ctx);
22570 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22571 break;
22572 case OPC_SUBQ_S_QH:
22573 check_dsp(ctx);
22574 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22575 break;
22576 case OPC_SUBU_OB:
22577 check_dsp(ctx);
22578 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22579 break;
22580 case OPC_SUBU_S_OB:
22581 check_dsp(ctx);
22582 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22583 break;
22584 case OPC_SUBU_QH:
22585 check_dsp_r2(ctx);
22586 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22587 break;
22588 case OPC_SUBU_S_QH:
22589 check_dsp_r2(ctx);
22590 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22591 break;
22592 case OPC_SUBUH_OB:
22593 check_dsp_r2(ctx);
22594 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22595 break;
22596 case OPC_SUBUH_R_OB:
22597 check_dsp_r2(ctx);
22598 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22599 break;
22600 case OPC_ADDQ_PW:
22601 check_dsp(ctx);
22602 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22603 break;
22604 case OPC_ADDQ_S_PW:
22605 check_dsp(ctx);
22606 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22607 break;
22608 case OPC_ADDQ_QH:
22609 check_dsp(ctx);
22610 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22611 break;
22612 case OPC_ADDQ_S_QH:
22613 check_dsp(ctx);
22614 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22615 break;
22616 case OPC_ADDU_OB:
22617 check_dsp(ctx);
22618 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22619 break;
22620 case OPC_ADDU_S_OB:
22621 check_dsp(ctx);
22622 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22623 break;
22624 case OPC_ADDU_QH:
22625 check_dsp_r2(ctx);
22626 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22627 break;
22628 case OPC_ADDU_S_QH:
22629 check_dsp_r2(ctx);
22630 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22631 break;
22632 case OPC_ADDUH_OB:
22633 check_dsp_r2(ctx);
22634 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22635 break;
22636 case OPC_ADDUH_R_OB:
22637 check_dsp_r2(ctx);
22638 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22639 break;
22641 break;
22642 case OPC_CMPU_EQ_OB_DSP:
22643 switch (op2) {
22644 case OPC_PRECR_OB_QH:
22645 check_dsp_r2(ctx);
22646 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22647 break;
22648 case OPC_PRECR_SRA_QH_PW:
22649 check_dsp_r2(ctx);
22651 TCGv_i32 ret_t = tcg_const_i32(ret);
22652 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22653 tcg_temp_free_i32(ret_t);
22654 break;
22656 case OPC_PRECR_SRA_R_QH_PW:
22657 check_dsp_r2(ctx);
22659 TCGv_i32 sa_v = tcg_const_i32(ret);
22660 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22661 tcg_temp_free_i32(sa_v);
22662 break;
22664 case OPC_PRECRQ_OB_QH:
22665 check_dsp(ctx);
22666 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22667 break;
22668 case OPC_PRECRQ_PW_L:
22669 check_dsp(ctx);
22670 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22671 break;
22672 case OPC_PRECRQ_QH_PW:
22673 check_dsp(ctx);
22674 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22675 break;
22676 case OPC_PRECRQ_RS_QH_PW:
22677 check_dsp(ctx);
22678 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22679 break;
22680 case OPC_PRECRQU_S_OB_QH:
22681 check_dsp(ctx);
22682 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22683 break;
22685 break;
22686 #endif
22689 tcg_temp_free(v1_t);
22690 tcg_temp_free(v2_t);
22693 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22694 int ret, int v1, int v2)
22696 uint32_t op2;
22697 TCGv t0;
22698 TCGv v1_t;
22699 TCGv v2_t;
22701 if (ret == 0) {
22702 /* Treat as NOP. */
22703 return;
22706 t0 = tcg_temp_new();
22707 v1_t = tcg_temp_new();
22708 v2_t = tcg_temp_new();
22710 tcg_gen_movi_tl(t0, v1);
22711 gen_load_gpr(v1_t, v1);
22712 gen_load_gpr(v2_t, v2);
22714 switch (opc) {
22715 case OPC_SHLL_QB_DSP:
22717 op2 = MASK_SHLL_QB(ctx->opcode);
22718 switch (op2) {
22719 case OPC_SHLL_QB:
22720 check_dsp(ctx);
22721 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22722 break;
22723 case OPC_SHLLV_QB:
22724 check_dsp(ctx);
22725 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22726 break;
22727 case OPC_SHLL_PH:
22728 check_dsp(ctx);
22729 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22730 break;
22731 case OPC_SHLLV_PH:
22732 check_dsp(ctx);
22733 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22734 break;
22735 case OPC_SHLL_S_PH:
22736 check_dsp(ctx);
22737 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22738 break;
22739 case OPC_SHLLV_S_PH:
22740 check_dsp(ctx);
22741 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22742 break;
22743 case OPC_SHLL_S_W:
22744 check_dsp(ctx);
22745 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22746 break;
22747 case OPC_SHLLV_S_W:
22748 check_dsp(ctx);
22749 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22750 break;
22751 case OPC_SHRL_QB:
22752 check_dsp(ctx);
22753 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22754 break;
22755 case OPC_SHRLV_QB:
22756 check_dsp(ctx);
22757 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22758 break;
22759 case OPC_SHRL_PH:
22760 check_dsp_r2(ctx);
22761 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22762 break;
22763 case OPC_SHRLV_PH:
22764 check_dsp_r2(ctx);
22765 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22766 break;
22767 case OPC_SHRA_QB:
22768 check_dsp_r2(ctx);
22769 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22770 break;
22771 case OPC_SHRA_R_QB:
22772 check_dsp_r2(ctx);
22773 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22774 break;
22775 case OPC_SHRAV_QB:
22776 check_dsp_r2(ctx);
22777 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22778 break;
22779 case OPC_SHRAV_R_QB:
22780 check_dsp_r2(ctx);
22781 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22782 break;
22783 case OPC_SHRA_PH:
22784 check_dsp(ctx);
22785 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22786 break;
22787 case OPC_SHRA_R_PH:
22788 check_dsp(ctx);
22789 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22790 break;
22791 case OPC_SHRAV_PH:
22792 check_dsp(ctx);
22793 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22794 break;
22795 case OPC_SHRAV_R_PH:
22796 check_dsp(ctx);
22797 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22798 break;
22799 case OPC_SHRA_R_W:
22800 check_dsp(ctx);
22801 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22802 break;
22803 case OPC_SHRAV_R_W:
22804 check_dsp(ctx);
22805 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22806 break;
22807 default: /* Invalid */
22808 MIPS_INVAL("MASK SHLL.QB");
22809 generate_exception_end(ctx, EXCP_RI);
22810 break;
22812 break;
22814 #ifdef TARGET_MIPS64
22815 case OPC_SHLL_OB_DSP:
22816 op2 = MASK_SHLL_OB(ctx->opcode);
22817 switch (op2) {
22818 case OPC_SHLL_PW:
22819 check_dsp(ctx);
22820 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22821 break;
22822 case OPC_SHLLV_PW:
22823 check_dsp(ctx);
22824 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22825 break;
22826 case OPC_SHLL_S_PW:
22827 check_dsp(ctx);
22828 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22829 break;
22830 case OPC_SHLLV_S_PW:
22831 check_dsp(ctx);
22832 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22833 break;
22834 case OPC_SHLL_OB:
22835 check_dsp(ctx);
22836 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22837 break;
22838 case OPC_SHLLV_OB:
22839 check_dsp(ctx);
22840 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22841 break;
22842 case OPC_SHLL_QH:
22843 check_dsp(ctx);
22844 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22845 break;
22846 case OPC_SHLLV_QH:
22847 check_dsp(ctx);
22848 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22849 break;
22850 case OPC_SHLL_S_QH:
22851 check_dsp(ctx);
22852 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22853 break;
22854 case OPC_SHLLV_S_QH:
22855 check_dsp(ctx);
22856 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22857 break;
22858 case OPC_SHRA_OB:
22859 check_dsp_r2(ctx);
22860 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22861 break;
22862 case OPC_SHRAV_OB:
22863 check_dsp_r2(ctx);
22864 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22865 break;
22866 case OPC_SHRA_R_OB:
22867 check_dsp_r2(ctx);
22868 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22869 break;
22870 case OPC_SHRAV_R_OB:
22871 check_dsp_r2(ctx);
22872 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22873 break;
22874 case OPC_SHRA_PW:
22875 check_dsp(ctx);
22876 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22877 break;
22878 case OPC_SHRAV_PW:
22879 check_dsp(ctx);
22880 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22881 break;
22882 case OPC_SHRA_R_PW:
22883 check_dsp(ctx);
22884 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22885 break;
22886 case OPC_SHRAV_R_PW:
22887 check_dsp(ctx);
22888 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22889 break;
22890 case OPC_SHRA_QH:
22891 check_dsp(ctx);
22892 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22893 break;
22894 case OPC_SHRAV_QH:
22895 check_dsp(ctx);
22896 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22897 break;
22898 case OPC_SHRA_R_QH:
22899 check_dsp(ctx);
22900 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22901 break;
22902 case OPC_SHRAV_R_QH:
22903 check_dsp(ctx);
22904 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22905 break;
22906 case OPC_SHRL_OB:
22907 check_dsp(ctx);
22908 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22909 break;
22910 case OPC_SHRLV_OB:
22911 check_dsp(ctx);
22912 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22913 break;
22914 case OPC_SHRL_QH:
22915 check_dsp_r2(ctx);
22916 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22917 break;
22918 case OPC_SHRLV_QH:
22919 check_dsp_r2(ctx);
22920 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22921 break;
22922 default: /* Invalid */
22923 MIPS_INVAL("MASK SHLL.OB");
22924 generate_exception_end(ctx, EXCP_RI);
22925 break;
22927 break;
22928 #endif
22931 tcg_temp_free(t0);
22932 tcg_temp_free(v1_t);
22933 tcg_temp_free(v2_t);
22936 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22937 int ret, int v1, int v2, int check_ret)
22939 TCGv_i32 t0;
22940 TCGv v1_t;
22941 TCGv v2_t;
22943 if ((ret == 0) && (check_ret == 1)) {
22944 /* Treat as NOP. */
22945 return;
22948 t0 = tcg_temp_new_i32();
22949 v1_t = tcg_temp_new();
22950 v2_t = tcg_temp_new();
22952 tcg_gen_movi_i32(t0, ret);
22953 gen_load_gpr(v1_t, v1);
22954 gen_load_gpr(v2_t, v2);
22956 switch (op1) {
22957 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22958 * the same mask and op1. */
22959 case OPC_MULT_G_2E:
22960 check_dsp_r2(ctx);
22961 switch (op2) {
22962 case OPC_MUL_PH:
22963 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22964 break;
22965 case OPC_MUL_S_PH:
22966 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22967 break;
22968 case OPC_MULQ_S_W:
22969 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22970 break;
22971 case OPC_MULQ_RS_W:
22972 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22973 break;
22975 break;
22976 case OPC_DPA_W_PH_DSP:
22977 switch (op2) {
22978 case OPC_DPAU_H_QBL:
22979 check_dsp(ctx);
22980 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22981 break;
22982 case OPC_DPAU_H_QBR:
22983 check_dsp(ctx);
22984 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22985 break;
22986 case OPC_DPSU_H_QBL:
22987 check_dsp(ctx);
22988 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22989 break;
22990 case OPC_DPSU_H_QBR:
22991 check_dsp(ctx);
22992 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22993 break;
22994 case OPC_DPA_W_PH:
22995 check_dsp_r2(ctx);
22996 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22997 break;
22998 case OPC_DPAX_W_PH:
22999 check_dsp_r2(ctx);
23000 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23001 break;
23002 case OPC_DPAQ_S_W_PH:
23003 check_dsp(ctx);
23004 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23005 break;
23006 case OPC_DPAQX_S_W_PH:
23007 check_dsp_r2(ctx);
23008 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23009 break;
23010 case OPC_DPAQX_SA_W_PH:
23011 check_dsp_r2(ctx);
23012 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23013 break;
23014 case OPC_DPS_W_PH:
23015 check_dsp_r2(ctx);
23016 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23017 break;
23018 case OPC_DPSX_W_PH:
23019 check_dsp_r2(ctx);
23020 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23021 break;
23022 case OPC_DPSQ_S_W_PH:
23023 check_dsp(ctx);
23024 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23025 break;
23026 case OPC_DPSQX_S_W_PH:
23027 check_dsp_r2(ctx);
23028 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23029 break;
23030 case OPC_DPSQX_SA_W_PH:
23031 check_dsp_r2(ctx);
23032 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23033 break;
23034 case OPC_MULSAQ_S_W_PH:
23035 check_dsp(ctx);
23036 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23037 break;
23038 case OPC_DPAQ_SA_L_W:
23039 check_dsp(ctx);
23040 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23041 break;
23042 case OPC_DPSQ_SA_L_W:
23043 check_dsp(ctx);
23044 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23045 break;
23046 case OPC_MAQ_S_W_PHL:
23047 check_dsp(ctx);
23048 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23049 break;
23050 case OPC_MAQ_S_W_PHR:
23051 check_dsp(ctx);
23052 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23053 break;
23054 case OPC_MAQ_SA_W_PHL:
23055 check_dsp(ctx);
23056 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23057 break;
23058 case OPC_MAQ_SA_W_PHR:
23059 check_dsp(ctx);
23060 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23061 break;
23062 case OPC_MULSA_W_PH:
23063 check_dsp_r2(ctx);
23064 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23065 break;
23067 break;
23068 #ifdef TARGET_MIPS64
23069 case OPC_DPAQ_W_QH_DSP:
23071 int ac = ret & 0x03;
23072 tcg_gen_movi_i32(t0, ac);
23074 switch (op2) {
23075 case OPC_DMADD:
23076 check_dsp(ctx);
23077 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23078 break;
23079 case OPC_DMADDU:
23080 check_dsp(ctx);
23081 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23082 break;
23083 case OPC_DMSUB:
23084 check_dsp(ctx);
23085 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23086 break;
23087 case OPC_DMSUBU:
23088 check_dsp(ctx);
23089 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23090 break;
23091 case OPC_DPA_W_QH:
23092 check_dsp_r2(ctx);
23093 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23094 break;
23095 case OPC_DPAQ_S_W_QH:
23096 check_dsp(ctx);
23097 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23098 break;
23099 case OPC_DPAQ_SA_L_PW:
23100 check_dsp(ctx);
23101 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23102 break;
23103 case OPC_DPAU_H_OBL:
23104 check_dsp(ctx);
23105 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23106 break;
23107 case OPC_DPAU_H_OBR:
23108 check_dsp(ctx);
23109 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23110 break;
23111 case OPC_DPS_W_QH:
23112 check_dsp_r2(ctx);
23113 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23114 break;
23115 case OPC_DPSQ_S_W_QH:
23116 check_dsp(ctx);
23117 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23118 break;
23119 case OPC_DPSQ_SA_L_PW:
23120 check_dsp(ctx);
23121 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23122 break;
23123 case OPC_DPSU_H_OBL:
23124 check_dsp(ctx);
23125 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23126 break;
23127 case OPC_DPSU_H_OBR:
23128 check_dsp(ctx);
23129 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23130 break;
23131 case OPC_MAQ_S_L_PWL:
23132 check_dsp(ctx);
23133 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23134 break;
23135 case OPC_MAQ_S_L_PWR:
23136 check_dsp(ctx);
23137 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23138 break;
23139 case OPC_MAQ_S_W_QHLL:
23140 check_dsp(ctx);
23141 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23142 break;
23143 case OPC_MAQ_SA_W_QHLL:
23144 check_dsp(ctx);
23145 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23146 break;
23147 case OPC_MAQ_S_W_QHLR:
23148 check_dsp(ctx);
23149 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23150 break;
23151 case OPC_MAQ_SA_W_QHLR:
23152 check_dsp(ctx);
23153 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23154 break;
23155 case OPC_MAQ_S_W_QHRL:
23156 check_dsp(ctx);
23157 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23158 break;
23159 case OPC_MAQ_SA_W_QHRL:
23160 check_dsp(ctx);
23161 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23162 break;
23163 case OPC_MAQ_S_W_QHRR:
23164 check_dsp(ctx);
23165 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23166 break;
23167 case OPC_MAQ_SA_W_QHRR:
23168 check_dsp(ctx);
23169 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23170 break;
23171 case OPC_MULSAQ_S_L_PW:
23172 check_dsp(ctx);
23173 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23174 break;
23175 case OPC_MULSAQ_S_W_QH:
23176 check_dsp(ctx);
23177 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23178 break;
23181 break;
23182 #endif
23183 case OPC_ADDU_QB_DSP:
23184 switch (op2) {
23185 case OPC_MULEU_S_PH_QBL:
23186 check_dsp(ctx);
23187 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23188 break;
23189 case OPC_MULEU_S_PH_QBR:
23190 check_dsp(ctx);
23191 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23192 break;
23193 case OPC_MULQ_RS_PH:
23194 check_dsp(ctx);
23195 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23196 break;
23197 case OPC_MULEQ_S_W_PHL:
23198 check_dsp(ctx);
23199 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23200 break;
23201 case OPC_MULEQ_S_W_PHR:
23202 check_dsp(ctx);
23203 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23204 break;
23205 case OPC_MULQ_S_PH:
23206 check_dsp_r2(ctx);
23207 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23208 break;
23210 break;
23211 #ifdef TARGET_MIPS64
23212 case OPC_ADDU_OB_DSP:
23213 switch (op2) {
23214 case OPC_MULEQ_S_PW_QHL:
23215 check_dsp(ctx);
23216 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23217 break;
23218 case OPC_MULEQ_S_PW_QHR:
23219 check_dsp(ctx);
23220 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23221 break;
23222 case OPC_MULEU_S_QH_OBL:
23223 check_dsp(ctx);
23224 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23225 break;
23226 case OPC_MULEU_S_QH_OBR:
23227 check_dsp(ctx);
23228 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23229 break;
23230 case OPC_MULQ_RS_QH:
23231 check_dsp(ctx);
23232 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23233 break;
23235 break;
23236 #endif
23239 tcg_temp_free_i32(t0);
23240 tcg_temp_free(v1_t);
23241 tcg_temp_free(v2_t);
23244 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23245 int ret, int val)
23247 int16_t imm;
23248 TCGv t0;
23249 TCGv val_t;
23251 if (ret == 0) {
23252 /* Treat as NOP. */
23253 return;
23256 t0 = tcg_temp_new();
23257 val_t = tcg_temp_new();
23258 gen_load_gpr(val_t, val);
23260 switch (op1) {
23261 case OPC_ABSQ_S_PH_DSP:
23262 switch (op2) {
23263 case OPC_BITREV:
23264 check_dsp(ctx);
23265 gen_helper_bitrev(cpu_gpr[ret], val_t);
23266 break;
23267 case OPC_REPL_QB:
23268 check_dsp(ctx);
23270 target_long result;
23271 imm = (ctx->opcode >> 16) & 0xFF;
23272 result = (uint32_t)imm << 24 |
23273 (uint32_t)imm << 16 |
23274 (uint32_t)imm << 8 |
23275 (uint32_t)imm;
23276 result = (int32_t)result;
23277 tcg_gen_movi_tl(cpu_gpr[ret], result);
23279 break;
23280 case OPC_REPLV_QB:
23281 check_dsp(ctx);
23282 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23283 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23284 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23285 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23286 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23287 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23288 break;
23289 case OPC_REPL_PH:
23290 check_dsp(ctx);
23292 imm = (ctx->opcode >> 16) & 0x03FF;
23293 imm = (int16_t)(imm << 6) >> 6;
23294 tcg_gen_movi_tl(cpu_gpr[ret], \
23295 (target_long)((int32_t)imm << 16 | \
23296 (uint16_t)imm));
23298 break;
23299 case OPC_REPLV_PH:
23300 check_dsp(ctx);
23301 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23302 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23303 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23304 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23305 break;
23307 break;
23308 #ifdef TARGET_MIPS64
23309 case OPC_ABSQ_S_QH_DSP:
23310 switch (op2) {
23311 case OPC_REPL_OB:
23312 check_dsp(ctx);
23314 target_long temp;
23316 imm = (ctx->opcode >> 16) & 0xFF;
23317 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23318 temp = (temp << 16) | temp;
23319 temp = (temp << 32) | temp;
23320 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23321 break;
23323 case OPC_REPL_PW:
23324 check_dsp(ctx);
23326 target_long temp;
23328 imm = (ctx->opcode >> 16) & 0x03FF;
23329 imm = (int16_t)(imm << 6) >> 6;
23330 temp = ((target_long)imm << 32) \
23331 | ((target_long)imm & 0xFFFFFFFF);
23332 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23333 break;
23335 case OPC_REPL_QH:
23336 check_dsp(ctx);
23338 target_long temp;
23340 imm = (ctx->opcode >> 16) & 0x03FF;
23341 imm = (int16_t)(imm << 6) >> 6;
23343 temp = ((uint64_t)(uint16_t)imm << 48) |
23344 ((uint64_t)(uint16_t)imm << 32) |
23345 ((uint64_t)(uint16_t)imm << 16) |
23346 (uint64_t)(uint16_t)imm;
23347 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23348 break;
23350 case OPC_REPLV_OB:
23351 check_dsp(ctx);
23352 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23353 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23354 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23355 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23356 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23357 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23358 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23359 break;
23360 case OPC_REPLV_PW:
23361 check_dsp(ctx);
23362 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23363 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23364 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23365 break;
23366 case OPC_REPLV_QH:
23367 check_dsp(ctx);
23368 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23369 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23370 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23371 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23372 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23373 break;
23375 break;
23376 #endif
23378 tcg_temp_free(t0);
23379 tcg_temp_free(val_t);
23382 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23383 uint32_t op1, uint32_t op2,
23384 int ret, int v1, int v2, int check_ret)
23386 TCGv t1;
23387 TCGv v1_t;
23388 TCGv v2_t;
23390 if ((ret == 0) && (check_ret == 1)) {
23391 /* Treat as NOP. */
23392 return;
23395 t1 = tcg_temp_new();
23396 v1_t = tcg_temp_new();
23397 v2_t = tcg_temp_new();
23399 gen_load_gpr(v1_t, v1);
23400 gen_load_gpr(v2_t, v2);
23402 switch (op1) {
23403 case OPC_CMPU_EQ_QB_DSP:
23404 switch (op2) {
23405 case OPC_CMPU_EQ_QB:
23406 check_dsp(ctx);
23407 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23408 break;
23409 case OPC_CMPU_LT_QB:
23410 check_dsp(ctx);
23411 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23412 break;
23413 case OPC_CMPU_LE_QB:
23414 check_dsp(ctx);
23415 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23416 break;
23417 case OPC_CMPGU_EQ_QB:
23418 check_dsp(ctx);
23419 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23420 break;
23421 case OPC_CMPGU_LT_QB:
23422 check_dsp(ctx);
23423 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23424 break;
23425 case OPC_CMPGU_LE_QB:
23426 check_dsp(ctx);
23427 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23428 break;
23429 case OPC_CMPGDU_EQ_QB:
23430 check_dsp_r2(ctx);
23431 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23432 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23433 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23434 tcg_gen_shli_tl(t1, t1, 24);
23435 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23436 break;
23437 case OPC_CMPGDU_LT_QB:
23438 check_dsp_r2(ctx);
23439 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23440 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23441 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23442 tcg_gen_shli_tl(t1, t1, 24);
23443 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23444 break;
23445 case OPC_CMPGDU_LE_QB:
23446 check_dsp_r2(ctx);
23447 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23448 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23449 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23450 tcg_gen_shli_tl(t1, t1, 24);
23451 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23452 break;
23453 case OPC_CMP_EQ_PH:
23454 check_dsp(ctx);
23455 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23456 break;
23457 case OPC_CMP_LT_PH:
23458 check_dsp(ctx);
23459 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23460 break;
23461 case OPC_CMP_LE_PH:
23462 check_dsp(ctx);
23463 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23464 break;
23465 case OPC_PICK_QB:
23466 check_dsp(ctx);
23467 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23468 break;
23469 case OPC_PICK_PH:
23470 check_dsp(ctx);
23471 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23472 break;
23473 case OPC_PACKRL_PH:
23474 check_dsp(ctx);
23475 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23476 break;
23478 break;
23479 #ifdef TARGET_MIPS64
23480 case OPC_CMPU_EQ_OB_DSP:
23481 switch (op2) {
23482 case OPC_CMP_EQ_PW:
23483 check_dsp(ctx);
23484 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23485 break;
23486 case OPC_CMP_LT_PW:
23487 check_dsp(ctx);
23488 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23489 break;
23490 case OPC_CMP_LE_PW:
23491 check_dsp(ctx);
23492 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23493 break;
23494 case OPC_CMP_EQ_QH:
23495 check_dsp(ctx);
23496 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23497 break;
23498 case OPC_CMP_LT_QH:
23499 check_dsp(ctx);
23500 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23501 break;
23502 case OPC_CMP_LE_QH:
23503 check_dsp(ctx);
23504 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23505 break;
23506 case OPC_CMPGDU_EQ_OB:
23507 check_dsp_r2(ctx);
23508 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23509 break;
23510 case OPC_CMPGDU_LT_OB:
23511 check_dsp_r2(ctx);
23512 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23513 break;
23514 case OPC_CMPGDU_LE_OB:
23515 check_dsp_r2(ctx);
23516 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23517 break;
23518 case OPC_CMPGU_EQ_OB:
23519 check_dsp(ctx);
23520 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23521 break;
23522 case OPC_CMPGU_LT_OB:
23523 check_dsp(ctx);
23524 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23525 break;
23526 case OPC_CMPGU_LE_OB:
23527 check_dsp(ctx);
23528 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23529 break;
23530 case OPC_CMPU_EQ_OB:
23531 check_dsp(ctx);
23532 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23533 break;
23534 case OPC_CMPU_LT_OB:
23535 check_dsp(ctx);
23536 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23537 break;
23538 case OPC_CMPU_LE_OB:
23539 check_dsp(ctx);
23540 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23541 break;
23542 case OPC_PACKRL_PW:
23543 check_dsp(ctx);
23544 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23545 break;
23546 case OPC_PICK_OB:
23547 check_dsp(ctx);
23548 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23549 break;
23550 case OPC_PICK_PW:
23551 check_dsp(ctx);
23552 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23553 break;
23554 case OPC_PICK_QH:
23555 check_dsp(ctx);
23556 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23557 break;
23559 break;
23560 #endif
23563 tcg_temp_free(t1);
23564 tcg_temp_free(v1_t);
23565 tcg_temp_free(v2_t);
23568 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23569 uint32_t op1, int rt, int rs, int sa)
23571 TCGv t0;
23573 check_dsp_r2(ctx);
23575 if (rt == 0) {
23576 /* Treat as NOP. */
23577 return;
23580 t0 = tcg_temp_new();
23581 gen_load_gpr(t0, rs);
23583 switch (op1) {
23584 case OPC_APPEND_DSP:
23585 switch (MASK_APPEND(ctx->opcode)) {
23586 case OPC_APPEND:
23587 if (sa != 0) {
23588 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23590 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23591 break;
23592 case OPC_PREPEND:
23593 if (sa != 0) {
23594 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23595 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23596 tcg_gen_shli_tl(t0, t0, 32 - sa);
23597 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23599 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23600 break;
23601 case OPC_BALIGN:
23602 sa &= 3;
23603 if (sa != 0 && sa != 2) {
23604 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23605 tcg_gen_ext32u_tl(t0, t0);
23606 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23607 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23609 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23610 break;
23611 default: /* Invalid */
23612 MIPS_INVAL("MASK APPEND");
23613 generate_exception_end(ctx, EXCP_RI);
23614 break;
23616 break;
23617 #ifdef TARGET_MIPS64
23618 case OPC_DAPPEND_DSP:
23619 switch (MASK_DAPPEND(ctx->opcode)) {
23620 case OPC_DAPPEND:
23621 if (sa != 0) {
23622 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23624 break;
23625 case OPC_PREPENDD:
23626 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23627 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23628 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23629 break;
23630 case OPC_PREPENDW:
23631 if (sa != 0) {
23632 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23633 tcg_gen_shli_tl(t0, t0, 64 - sa);
23634 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23636 break;
23637 case OPC_DBALIGN:
23638 sa &= 7;
23639 if (sa != 0 && sa != 2 && sa != 4) {
23640 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23641 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23642 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23644 break;
23645 default: /* Invalid */
23646 MIPS_INVAL("MASK DAPPEND");
23647 generate_exception_end(ctx, EXCP_RI);
23648 break;
23650 break;
23651 #endif
23653 tcg_temp_free(t0);
23656 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23657 int ret, int v1, int v2, int check_ret)
23660 TCGv t0;
23661 TCGv t1;
23662 TCGv v1_t;
23663 TCGv v2_t;
23664 int16_t imm;
23666 if ((ret == 0) && (check_ret == 1)) {
23667 /* Treat as NOP. */
23668 return;
23671 t0 = tcg_temp_new();
23672 t1 = tcg_temp_new();
23673 v1_t = tcg_temp_new();
23674 v2_t = tcg_temp_new();
23676 gen_load_gpr(v1_t, v1);
23677 gen_load_gpr(v2_t, v2);
23679 switch (op1) {
23680 case OPC_EXTR_W_DSP:
23681 check_dsp(ctx);
23682 switch (op2) {
23683 case OPC_EXTR_W:
23684 tcg_gen_movi_tl(t0, v2);
23685 tcg_gen_movi_tl(t1, v1);
23686 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23687 break;
23688 case OPC_EXTR_R_W:
23689 tcg_gen_movi_tl(t0, v2);
23690 tcg_gen_movi_tl(t1, v1);
23691 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23692 break;
23693 case OPC_EXTR_RS_W:
23694 tcg_gen_movi_tl(t0, v2);
23695 tcg_gen_movi_tl(t1, v1);
23696 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23697 break;
23698 case OPC_EXTR_S_H:
23699 tcg_gen_movi_tl(t0, v2);
23700 tcg_gen_movi_tl(t1, v1);
23701 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23702 break;
23703 case OPC_EXTRV_S_H:
23704 tcg_gen_movi_tl(t0, v2);
23705 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23706 break;
23707 case OPC_EXTRV_W:
23708 tcg_gen_movi_tl(t0, v2);
23709 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23710 break;
23711 case OPC_EXTRV_R_W:
23712 tcg_gen_movi_tl(t0, v2);
23713 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23714 break;
23715 case OPC_EXTRV_RS_W:
23716 tcg_gen_movi_tl(t0, v2);
23717 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23718 break;
23719 case OPC_EXTP:
23720 tcg_gen_movi_tl(t0, v2);
23721 tcg_gen_movi_tl(t1, v1);
23722 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23723 break;
23724 case OPC_EXTPV:
23725 tcg_gen_movi_tl(t0, v2);
23726 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23727 break;
23728 case OPC_EXTPDP:
23729 tcg_gen_movi_tl(t0, v2);
23730 tcg_gen_movi_tl(t1, v1);
23731 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23732 break;
23733 case OPC_EXTPDPV:
23734 tcg_gen_movi_tl(t0, v2);
23735 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23736 break;
23737 case OPC_SHILO:
23738 imm = (ctx->opcode >> 20) & 0x3F;
23739 tcg_gen_movi_tl(t0, ret);
23740 tcg_gen_movi_tl(t1, imm);
23741 gen_helper_shilo(t0, t1, cpu_env);
23742 break;
23743 case OPC_SHILOV:
23744 tcg_gen_movi_tl(t0, ret);
23745 gen_helper_shilo(t0, v1_t, cpu_env);
23746 break;
23747 case OPC_MTHLIP:
23748 tcg_gen_movi_tl(t0, ret);
23749 gen_helper_mthlip(t0, v1_t, cpu_env);
23750 break;
23751 case OPC_WRDSP:
23752 imm = (ctx->opcode >> 11) & 0x3FF;
23753 tcg_gen_movi_tl(t0, imm);
23754 gen_helper_wrdsp(v1_t, t0, cpu_env);
23755 break;
23756 case OPC_RDDSP:
23757 imm = (ctx->opcode >> 16) & 0x03FF;
23758 tcg_gen_movi_tl(t0, imm);
23759 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23760 break;
23762 break;
23763 #ifdef TARGET_MIPS64
23764 case OPC_DEXTR_W_DSP:
23765 check_dsp(ctx);
23766 switch (op2) {
23767 case OPC_DMTHLIP:
23768 tcg_gen_movi_tl(t0, ret);
23769 gen_helper_dmthlip(v1_t, t0, cpu_env);
23770 break;
23771 case OPC_DSHILO:
23773 int shift = (ctx->opcode >> 19) & 0x7F;
23774 int ac = (ctx->opcode >> 11) & 0x03;
23775 tcg_gen_movi_tl(t0, shift);
23776 tcg_gen_movi_tl(t1, ac);
23777 gen_helper_dshilo(t0, t1, cpu_env);
23778 break;
23780 case OPC_DSHILOV:
23782 int ac = (ctx->opcode >> 11) & 0x03;
23783 tcg_gen_movi_tl(t0, ac);
23784 gen_helper_dshilo(v1_t, t0, cpu_env);
23785 break;
23787 case OPC_DEXTP:
23788 tcg_gen_movi_tl(t0, v2);
23789 tcg_gen_movi_tl(t1, v1);
23791 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23792 break;
23793 case OPC_DEXTPV:
23794 tcg_gen_movi_tl(t0, v2);
23795 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23796 break;
23797 case OPC_DEXTPDP:
23798 tcg_gen_movi_tl(t0, v2);
23799 tcg_gen_movi_tl(t1, v1);
23800 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23801 break;
23802 case OPC_DEXTPDPV:
23803 tcg_gen_movi_tl(t0, v2);
23804 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23805 break;
23806 case OPC_DEXTR_L:
23807 tcg_gen_movi_tl(t0, v2);
23808 tcg_gen_movi_tl(t1, v1);
23809 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23810 break;
23811 case OPC_DEXTR_R_L:
23812 tcg_gen_movi_tl(t0, v2);
23813 tcg_gen_movi_tl(t1, v1);
23814 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23815 break;
23816 case OPC_DEXTR_RS_L:
23817 tcg_gen_movi_tl(t0, v2);
23818 tcg_gen_movi_tl(t1, v1);
23819 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23820 break;
23821 case OPC_DEXTR_W:
23822 tcg_gen_movi_tl(t0, v2);
23823 tcg_gen_movi_tl(t1, v1);
23824 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23825 break;
23826 case OPC_DEXTR_R_W:
23827 tcg_gen_movi_tl(t0, v2);
23828 tcg_gen_movi_tl(t1, v1);
23829 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23830 break;
23831 case OPC_DEXTR_RS_W:
23832 tcg_gen_movi_tl(t0, v2);
23833 tcg_gen_movi_tl(t1, v1);
23834 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23835 break;
23836 case OPC_DEXTR_S_H:
23837 tcg_gen_movi_tl(t0, v2);
23838 tcg_gen_movi_tl(t1, v1);
23839 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23840 break;
23841 case OPC_DEXTRV_S_H:
23842 tcg_gen_movi_tl(t0, v2);
23843 tcg_gen_movi_tl(t1, v1);
23844 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23845 break;
23846 case OPC_DEXTRV_L:
23847 tcg_gen_movi_tl(t0, v2);
23848 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23849 break;
23850 case OPC_DEXTRV_R_L:
23851 tcg_gen_movi_tl(t0, v2);
23852 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23853 break;
23854 case OPC_DEXTRV_RS_L:
23855 tcg_gen_movi_tl(t0, v2);
23856 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23857 break;
23858 case OPC_DEXTRV_W:
23859 tcg_gen_movi_tl(t0, v2);
23860 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23861 break;
23862 case OPC_DEXTRV_R_W:
23863 tcg_gen_movi_tl(t0, v2);
23864 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23865 break;
23866 case OPC_DEXTRV_RS_W:
23867 tcg_gen_movi_tl(t0, v2);
23868 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23869 break;
23871 break;
23872 #endif
23875 tcg_temp_free(t0);
23876 tcg_temp_free(t1);
23877 tcg_temp_free(v1_t);
23878 tcg_temp_free(v2_t);
23881 /* End MIPSDSP functions. */
23883 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23885 int rs, rt, rd, sa;
23886 uint32_t op1, op2;
23888 rs = (ctx->opcode >> 21) & 0x1f;
23889 rt = (ctx->opcode >> 16) & 0x1f;
23890 rd = (ctx->opcode >> 11) & 0x1f;
23891 sa = (ctx->opcode >> 6) & 0x1f;
23893 op1 = MASK_SPECIAL(ctx->opcode);
23894 switch (op1) {
23895 case OPC_LSA:
23896 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23897 break;
23898 case OPC_MULT:
23899 case OPC_MULTU:
23900 case OPC_DIV:
23901 case OPC_DIVU:
23902 op2 = MASK_R6_MULDIV(ctx->opcode);
23903 switch (op2) {
23904 case R6_OPC_MUL:
23905 case R6_OPC_MUH:
23906 case R6_OPC_MULU:
23907 case R6_OPC_MUHU:
23908 case R6_OPC_DIV:
23909 case R6_OPC_MOD:
23910 case R6_OPC_DIVU:
23911 case R6_OPC_MODU:
23912 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23913 break;
23914 default:
23915 MIPS_INVAL("special_r6 muldiv");
23916 generate_exception_end(ctx, EXCP_RI);
23917 break;
23919 break;
23920 case OPC_SELEQZ:
23921 case OPC_SELNEZ:
23922 gen_cond_move(ctx, op1, rd, rs, rt);
23923 break;
23924 case R6_OPC_CLO:
23925 case R6_OPC_CLZ:
23926 if (rt == 0 && sa == 1) {
23927 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23928 We need additionally to check other fields */
23929 gen_cl(ctx, op1, rd, rs);
23930 } else {
23931 generate_exception_end(ctx, EXCP_RI);
23933 break;
23934 case R6_OPC_SDBBP:
23935 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23936 gen_helper_do_semihosting(cpu_env);
23937 } else {
23938 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23939 generate_exception_end(ctx, EXCP_RI);
23940 } else {
23941 generate_exception_end(ctx, EXCP_DBp);
23944 break;
23945 #if defined(TARGET_MIPS64)
23946 case OPC_DLSA:
23947 check_mips_64(ctx);
23948 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23949 break;
23950 case R6_OPC_DCLO:
23951 case R6_OPC_DCLZ:
23952 if (rt == 0 && sa == 1) {
23953 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23954 We need additionally to check other fields */
23955 check_mips_64(ctx);
23956 gen_cl(ctx, op1, rd, rs);
23957 } else {
23958 generate_exception_end(ctx, EXCP_RI);
23960 break;
23961 case OPC_DMULT:
23962 case OPC_DMULTU:
23963 case OPC_DDIV:
23964 case OPC_DDIVU:
23966 op2 = MASK_R6_MULDIV(ctx->opcode);
23967 switch (op2) {
23968 case R6_OPC_DMUL:
23969 case R6_OPC_DMUH:
23970 case R6_OPC_DMULU:
23971 case R6_OPC_DMUHU:
23972 case R6_OPC_DDIV:
23973 case R6_OPC_DMOD:
23974 case R6_OPC_DDIVU:
23975 case R6_OPC_DMODU:
23976 check_mips_64(ctx);
23977 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23978 break;
23979 default:
23980 MIPS_INVAL("special_r6 muldiv");
23981 generate_exception_end(ctx, EXCP_RI);
23982 break;
23984 break;
23985 #endif
23986 default: /* Invalid */
23987 MIPS_INVAL("special_r6");
23988 generate_exception_end(ctx, EXCP_RI);
23989 break;
23993 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23995 int rs = extract32(ctx->opcode, 21, 5);
23996 int rt = extract32(ctx->opcode, 16, 5);
23997 int rd = extract32(ctx->opcode, 11, 5);
23998 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24000 switch (op1) {
24001 case OPC_MOVN: /* Conditional move */
24002 case OPC_MOVZ:
24003 gen_cond_move(ctx, op1, rd, rs, rt);
24004 break;
24005 case OPC_MFHI: /* Move from HI/LO */
24006 case OPC_MFLO:
24007 gen_HILO(ctx, op1, 0, rd);
24008 break;
24009 case OPC_MTHI:
24010 case OPC_MTLO: /* Move to HI/LO */
24011 gen_HILO(ctx, op1, 0, rs);
24012 break;
24013 case OPC_MULT:
24014 case OPC_MULTU:
24015 gen_mul_txx9(ctx, op1, rd, rs, rt);
24016 break;
24017 case OPC_DIV:
24018 case OPC_DIVU:
24019 gen_muldiv(ctx, op1, 0, rs, rt);
24020 break;
24021 #if defined(TARGET_MIPS64)
24022 case OPC_DMULT:
24023 case OPC_DMULTU:
24024 case OPC_DDIV:
24025 case OPC_DDIVU:
24026 check_insn_opc_user_only(ctx, INSN_R5900);
24027 gen_muldiv(ctx, op1, 0, rs, rt);
24028 break;
24029 #endif
24030 case OPC_JR:
24031 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24032 break;
24033 default: /* Invalid */
24034 MIPS_INVAL("special_tx79");
24035 generate_exception_end(ctx, EXCP_RI);
24036 break;
24040 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24042 int rs, rt, rd, sa;
24043 uint32_t op1;
24045 rs = (ctx->opcode >> 21) & 0x1f;
24046 rt = (ctx->opcode >> 16) & 0x1f;
24047 rd = (ctx->opcode >> 11) & 0x1f;
24048 sa = (ctx->opcode >> 6) & 0x1f;
24050 op1 = MASK_SPECIAL(ctx->opcode);
24051 switch (op1) {
24052 case OPC_MOVN: /* Conditional move */
24053 case OPC_MOVZ:
24054 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24055 INSN_LOONGSON2E | INSN_LOONGSON2F);
24056 gen_cond_move(ctx, op1, rd, rs, rt);
24057 break;
24058 case OPC_MFHI: /* Move from HI/LO */
24059 case OPC_MFLO:
24060 gen_HILO(ctx, op1, rs & 3, rd);
24061 break;
24062 case OPC_MTHI:
24063 case OPC_MTLO: /* Move to HI/LO */
24064 gen_HILO(ctx, op1, rd & 3, rs);
24065 break;
24066 case OPC_MOVCI:
24067 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24068 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24069 check_cp1_enabled(ctx);
24070 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24071 (ctx->opcode >> 16) & 1);
24072 } else {
24073 generate_exception_err(ctx, EXCP_CpU, 1);
24075 break;
24076 case OPC_MULT:
24077 case OPC_MULTU:
24078 if (sa) {
24079 check_insn(ctx, INSN_VR54XX);
24080 op1 = MASK_MUL_VR54XX(ctx->opcode);
24081 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24082 } else {
24083 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24085 break;
24086 case OPC_DIV:
24087 case OPC_DIVU:
24088 gen_muldiv(ctx, op1, 0, rs, rt);
24089 break;
24090 #if defined(TARGET_MIPS64)
24091 case OPC_DMULT:
24092 case OPC_DMULTU:
24093 case OPC_DDIV:
24094 case OPC_DDIVU:
24095 check_insn(ctx, ISA_MIPS3);
24096 check_mips_64(ctx);
24097 gen_muldiv(ctx, op1, 0, rs, rt);
24098 break;
24099 #endif
24100 case OPC_JR:
24101 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24102 break;
24103 case OPC_SPIM:
24104 #ifdef MIPS_STRICT_STANDARD
24105 MIPS_INVAL("SPIM");
24106 generate_exception_end(ctx, EXCP_RI);
24107 #else
24108 /* Implemented as RI exception for now. */
24109 MIPS_INVAL("spim (unofficial)");
24110 generate_exception_end(ctx, EXCP_RI);
24111 #endif
24112 break;
24113 default: /* Invalid */
24114 MIPS_INVAL("special_legacy");
24115 generate_exception_end(ctx, EXCP_RI);
24116 break;
24120 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24122 int rs, rt, rd, sa;
24123 uint32_t op1;
24125 rs = (ctx->opcode >> 21) & 0x1f;
24126 rt = (ctx->opcode >> 16) & 0x1f;
24127 rd = (ctx->opcode >> 11) & 0x1f;
24128 sa = (ctx->opcode >> 6) & 0x1f;
24130 op1 = MASK_SPECIAL(ctx->opcode);
24131 switch (op1) {
24132 case OPC_SLL: /* Shift with immediate */
24133 if (sa == 5 && rd == 0 &&
24134 rs == 0 && rt == 0) { /* PAUSE */
24135 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24136 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24137 generate_exception_end(ctx, EXCP_RI);
24138 break;
24141 /* Fallthrough */
24142 case OPC_SRA:
24143 gen_shift_imm(ctx, op1, rd, rt, sa);
24144 break;
24145 case OPC_SRL:
24146 switch ((ctx->opcode >> 21) & 0x1f) {
24147 case 1:
24148 /* rotr is decoded as srl on non-R2 CPUs */
24149 if (ctx->insn_flags & ISA_MIPS32R2) {
24150 op1 = OPC_ROTR;
24152 /* Fallthrough */
24153 case 0:
24154 gen_shift_imm(ctx, op1, rd, rt, sa);
24155 break;
24156 default:
24157 generate_exception_end(ctx, EXCP_RI);
24158 break;
24160 break;
24161 case OPC_ADD:
24162 case OPC_ADDU:
24163 case OPC_SUB:
24164 case OPC_SUBU:
24165 gen_arith(ctx, op1, rd, rs, rt);
24166 break;
24167 case OPC_SLLV: /* Shifts */
24168 case OPC_SRAV:
24169 gen_shift(ctx, op1, rd, rs, rt);
24170 break;
24171 case OPC_SRLV:
24172 switch ((ctx->opcode >> 6) & 0x1f) {
24173 case 1:
24174 /* rotrv is decoded as srlv on non-R2 CPUs */
24175 if (ctx->insn_flags & ISA_MIPS32R2) {
24176 op1 = OPC_ROTRV;
24178 /* Fallthrough */
24179 case 0:
24180 gen_shift(ctx, op1, rd, rs, rt);
24181 break;
24182 default:
24183 generate_exception_end(ctx, EXCP_RI);
24184 break;
24186 break;
24187 case OPC_SLT: /* Set on less than */
24188 case OPC_SLTU:
24189 gen_slt(ctx, op1, rd, rs, rt);
24190 break;
24191 case OPC_AND: /* Logic*/
24192 case OPC_OR:
24193 case OPC_NOR:
24194 case OPC_XOR:
24195 gen_logic(ctx, op1, rd, rs, rt);
24196 break;
24197 case OPC_JALR:
24198 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24199 break;
24200 case OPC_TGE: /* Traps */
24201 case OPC_TGEU:
24202 case OPC_TLT:
24203 case OPC_TLTU:
24204 case OPC_TEQ:
24205 case OPC_TNE:
24206 check_insn(ctx, ISA_MIPS2);
24207 gen_trap(ctx, op1, rs, rt, -1);
24208 break;
24209 case OPC_LSA: /* OPC_PMON */
24210 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24211 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24212 decode_opc_special_r6(env, ctx);
24213 } else {
24214 /* Pmon entry point, also R4010 selsl */
24215 #ifdef MIPS_STRICT_STANDARD
24216 MIPS_INVAL("PMON / selsl");
24217 generate_exception_end(ctx, EXCP_RI);
24218 #else
24219 gen_helper_0e0i(pmon, sa);
24220 #endif
24222 break;
24223 case OPC_SYSCALL:
24224 generate_exception_end(ctx, EXCP_SYSCALL);
24225 break;
24226 case OPC_BREAK:
24227 generate_exception_end(ctx, EXCP_BREAK);
24228 break;
24229 case OPC_SYNC:
24230 check_insn(ctx, ISA_MIPS2);
24231 gen_sync(extract32(ctx->opcode, 6, 5));
24232 break;
24234 #if defined(TARGET_MIPS64)
24235 /* MIPS64 specific opcodes */
24236 case OPC_DSLL:
24237 case OPC_DSRA:
24238 case OPC_DSLL32:
24239 case OPC_DSRA32:
24240 check_insn(ctx, ISA_MIPS3);
24241 check_mips_64(ctx);
24242 gen_shift_imm(ctx, op1, rd, rt, sa);
24243 break;
24244 case OPC_DSRL:
24245 switch ((ctx->opcode >> 21) & 0x1f) {
24246 case 1:
24247 /* drotr is decoded as dsrl on non-R2 CPUs */
24248 if (ctx->insn_flags & ISA_MIPS32R2) {
24249 op1 = OPC_DROTR;
24251 /* Fallthrough */
24252 case 0:
24253 check_insn(ctx, ISA_MIPS3);
24254 check_mips_64(ctx);
24255 gen_shift_imm(ctx, op1, rd, rt, sa);
24256 break;
24257 default:
24258 generate_exception_end(ctx, EXCP_RI);
24259 break;
24261 break;
24262 case OPC_DSRL32:
24263 switch ((ctx->opcode >> 21) & 0x1f) {
24264 case 1:
24265 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24266 if (ctx->insn_flags & ISA_MIPS32R2) {
24267 op1 = OPC_DROTR32;
24269 /* Fallthrough */
24270 case 0:
24271 check_insn(ctx, ISA_MIPS3);
24272 check_mips_64(ctx);
24273 gen_shift_imm(ctx, op1, rd, rt, sa);
24274 break;
24275 default:
24276 generate_exception_end(ctx, EXCP_RI);
24277 break;
24279 break;
24280 case OPC_DADD:
24281 case OPC_DADDU:
24282 case OPC_DSUB:
24283 case OPC_DSUBU:
24284 check_insn(ctx, ISA_MIPS3);
24285 check_mips_64(ctx);
24286 gen_arith(ctx, op1, rd, rs, rt);
24287 break;
24288 case OPC_DSLLV:
24289 case OPC_DSRAV:
24290 check_insn(ctx, ISA_MIPS3);
24291 check_mips_64(ctx);
24292 gen_shift(ctx, op1, rd, rs, rt);
24293 break;
24294 case OPC_DSRLV:
24295 switch ((ctx->opcode >> 6) & 0x1f) {
24296 case 1:
24297 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24298 if (ctx->insn_flags & ISA_MIPS32R2) {
24299 op1 = OPC_DROTRV;
24301 /* Fallthrough */
24302 case 0:
24303 check_insn(ctx, ISA_MIPS3);
24304 check_mips_64(ctx);
24305 gen_shift(ctx, op1, rd, rs, rt);
24306 break;
24307 default:
24308 generate_exception_end(ctx, EXCP_RI);
24309 break;
24311 break;
24312 case OPC_DLSA:
24313 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24314 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24315 decode_opc_special_r6(env, ctx);
24317 break;
24318 #endif
24319 default:
24320 if (ctx->insn_flags & ISA_MIPS32R6) {
24321 decode_opc_special_r6(env, ctx);
24322 } else if (ctx->insn_flags & INSN_R5900) {
24323 decode_opc_special_tx79(env, ctx);
24324 } else {
24325 decode_opc_special_legacy(env, ctx);
24331 #if defined(TARGET_MIPS64)
24335 * MMI (MultiMedia Interface) ASE instructions
24336 * ===========================================
24340 * MMI instructions category: data communication
24341 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24343 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24344 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24345 * PCPYUD PEXEH PEXTLW PPACW
24346 * PEXEW PEXTUB
24347 * PEXTUH
24348 * PEXTUW
24351 #endif
24354 #if !defined(TARGET_MIPS64)
24356 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24357 #define MXU_APTN1_A 0
24358 #define MXU_APTN1_S 1
24360 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24361 #define MXU_APTN2_AA 0
24362 #define MXU_APTN2_AS 1
24363 #define MXU_APTN2_SA 2
24364 #define MXU_APTN2_SS 3
24366 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24367 #define MXU_EPTN2_AA 0
24368 #define MXU_EPTN2_AS 1
24369 #define MXU_EPTN2_SA 2
24370 #define MXU_EPTN2_SS 3
24372 /* MXU operand getting pattern 'optn2' */
24373 #define MXU_OPTN2_PTN0 0
24374 #define MXU_OPTN2_PTN1 1
24375 #define MXU_OPTN2_PTN2 2
24376 #define MXU_OPTN2_PTN3 3
24377 /* alternative naming scheme for 'optn2' */
24378 #define MXU_OPTN2_WW 0
24379 #define MXU_OPTN2_LW 1
24380 #define MXU_OPTN2_HW 2
24381 #define MXU_OPTN2_XW 3
24383 /* MXU operand getting pattern 'optn3' */
24384 #define MXU_OPTN3_PTN0 0
24385 #define MXU_OPTN3_PTN1 1
24386 #define MXU_OPTN3_PTN2 2
24387 #define MXU_OPTN3_PTN3 3
24388 #define MXU_OPTN3_PTN4 4
24389 #define MXU_OPTN3_PTN5 5
24390 #define MXU_OPTN3_PTN6 6
24391 #define MXU_OPTN3_PTN7 7
24395 * S32I2M XRa, rb - Register move from GRF to XRF
24397 static void gen_mxu_s32i2m(DisasContext *ctx)
24399 TCGv t0;
24400 uint32_t XRa, Rb;
24402 t0 = tcg_temp_new();
24404 XRa = extract32(ctx->opcode, 6, 5);
24405 Rb = extract32(ctx->opcode, 16, 5);
24407 gen_load_gpr(t0, Rb);
24408 if (XRa <= 15) {
24409 gen_store_mxu_gpr(t0, XRa);
24410 } else if (XRa == 16) {
24411 gen_store_mxu_cr(t0);
24414 tcg_temp_free(t0);
24418 * S32M2I XRa, rb - Register move from XRF to GRF
24420 static void gen_mxu_s32m2i(DisasContext *ctx)
24422 TCGv t0;
24423 uint32_t XRa, Rb;
24425 t0 = tcg_temp_new();
24427 XRa = extract32(ctx->opcode, 6, 5);
24428 Rb = extract32(ctx->opcode, 16, 5);
24430 if (XRa <= 15) {
24431 gen_load_mxu_gpr(t0, XRa);
24432 } else if (XRa == 16) {
24433 gen_load_mxu_cr(t0);
24436 gen_store_gpr(t0, Rb);
24438 tcg_temp_free(t0);
24442 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24444 static void gen_mxu_s8ldd(DisasContext *ctx)
24446 TCGv t0, t1;
24447 uint32_t XRa, Rb, s8, optn3;
24449 t0 = tcg_temp_new();
24450 t1 = tcg_temp_new();
24452 XRa = extract32(ctx->opcode, 6, 4);
24453 s8 = extract32(ctx->opcode, 10, 8);
24454 optn3 = extract32(ctx->opcode, 18, 3);
24455 Rb = extract32(ctx->opcode, 21, 5);
24457 gen_load_gpr(t0, Rb);
24458 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24460 switch (optn3) {
24461 /* XRa[7:0] = tmp8 */
24462 case MXU_OPTN3_PTN0:
24463 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24464 gen_load_mxu_gpr(t0, XRa);
24465 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24466 break;
24467 /* XRa[15:8] = tmp8 */
24468 case MXU_OPTN3_PTN1:
24469 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24470 gen_load_mxu_gpr(t0, XRa);
24471 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24472 break;
24473 /* XRa[23:16] = tmp8 */
24474 case MXU_OPTN3_PTN2:
24475 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24476 gen_load_mxu_gpr(t0, XRa);
24477 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24478 break;
24479 /* XRa[31:24] = tmp8 */
24480 case MXU_OPTN3_PTN3:
24481 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24482 gen_load_mxu_gpr(t0, XRa);
24483 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24484 break;
24485 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24486 case MXU_OPTN3_PTN4:
24487 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24488 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24489 break;
24490 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24491 case MXU_OPTN3_PTN5:
24492 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24493 tcg_gen_shli_tl(t1, t1, 8);
24494 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24495 break;
24496 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24497 case MXU_OPTN3_PTN6:
24498 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24499 tcg_gen_mov_tl(t0, t1);
24500 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24501 tcg_gen_shli_tl(t1, t1, 16);
24502 tcg_gen_or_tl(t0, t0, t1);
24503 break;
24504 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24505 case MXU_OPTN3_PTN7:
24506 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24507 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24508 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24509 break;
24512 gen_store_mxu_gpr(t0, XRa);
24514 tcg_temp_free(t0);
24515 tcg_temp_free(t1);
24519 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24521 static void gen_mxu_d16mul(DisasContext *ctx)
24523 TCGv t0, t1, t2, t3;
24524 uint32_t XRa, XRb, XRc, XRd, optn2;
24526 t0 = tcg_temp_new();
24527 t1 = tcg_temp_new();
24528 t2 = tcg_temp_new();
24529 t3 = tcg_temp_new();
24531 XRa = extract32(ctx->opcode, 6, 4);
24532 XRb = extract32(ctx->opcode, 10, 4);
24533 XRc = extract32(ctx->opcode, 14, 4);
24534 XRd = extract32(ctx->opcode, 18, 4);
24535 optn2 = extract32(ctx->opcode, 22, 2);
24537 gen_load_mxu_gpr(t1, XRb);
24538 tcg_gen_sextract_tl(t0, t1, 0, 16);
24539 tcg_gen_sextract_tl(t1, t1, 16, 16);
24540 gen_load_mxu_gpr(t3, XRc);
24541 tcg_gen_sextract_tl(t2, t3, 0, 16);
24542 tcg_gen_sextract_tl(t3, t3, 16, 16);
24544 switch (optn2) {
24545 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24546 tcg_gen_mul_tl(t3, t1, t3);
24547 tcg_gen_mul_tl(t2, t0, t2);
24548 break;
24549 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24550 tcg_gen_mul_tl(t3, t0, t3);
24551 tcg_gen_mul_tl(t2, t0, t2);
24552 break;
24553 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24554 tcg_gen_mul_tl(t3, t1, t3);
24555 tcg_gen_mul_tl(t2, t1, t2);
24556 break;
24557 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24558 tcg_gen_mul_tl(t3, t0, t3);
24559 tcg_gen_mul_tl(t2, t1, t2);
24560 break;
24562 gen_store_mxu_gpr(t3, XRa);
24563 gen_store_mxu_gpr(t2, XRd);
24565 tcg_temp_free(t0);
24566 tcg_temp_free(t1);
24567 tcg_temp_free(t2);
24568 tcg_temp_free(t3);
24572 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24573 * and accumulate
24575 static void gen_mxu_d16mac(DisasContext *ctx)
24577 TCGv t0, t1, t2, t3;
24578 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24580 t0 = tcg_temp_new();
24581 t1 = tcg_temp_new();
24582 t2 = tcg_temp_new();
24583 t3 = tcg_temp_new();
24585 XRa = extract32(ctx->opcode, 6, 4);
24586 XRb = extract32(ctx->opcode, 10, 4);
24587 XRc = extract32(ctx->opcode, 14, 4);
24588 XRd = extract32(ctx->opcode, 18, 4);
24589 optn2 = extract32(ctx->opcode, 22, 2);
24590 aptn2 = extract32(ctx->opcode, 24, 2);
24592 gen_load_mxu_gpr(t1, XRb);
24593 tcg_gen_sextract_tl(t0, t1, 0, 16);
24594 tcg_gen_sextract_tl(t1, t1, 16, 16);
24596 gen_load_mxu_gpr(t3, XRc);
24597 tcg_gen_sextract_tl(t2, t3, 0, 16);
24598 tcg_gen_sextract_tl(t3, t3, 16, 16);
24600 switch (optn2) {
24601 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24602 tcg_gen_mul_tl(t3, t1, t3);
24603 tcg_gen_mul_tl(t2, t0, t2);
24604 break;
24605 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24606 tcg_gen_mul_tl(t3, t0, t3);
24607 tcg_gen_mul_tl(t2, t0, t2);
24608 break;
24609 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24610 tcg_gen_mul_tl(t3, t1, t3);
24611 tcg_gen_mul_tl(t2, t1, t2);
24612 break;
24613 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24614 tcg_gen_mul_tl(t3, t0, t3);
24615 tcg_gen_mul_tl(t2, t1, t2);
24616 break;
24618 gen_load_mxu_gpr(t0, XRa);
24619 gen_load_mxu_gpr(t1, XRd);
24621 switch (aptn2) {
24622 case MXU_APTN2_AA:
24623 tcg_gen_add_tl(t3, t0, t3);
24624 tcg_gen_add_tl(t2, t1, t2);
24625 break;
24626 case MXU_APTN2_AS:
24627 tcg_gen_add_tl(t3, t0, t3);
24628 tcg_gen_sub_tl(t2, t1, t2);
24629 break;
24630 case MXU_APTN2_SA:
24631 tcg_gen_sub_tl(t3, t0, t3);
24632 tcg_gen_add_tl(t2, t1, t2);
24633 break;
24634 case MXU_APTN2_SS:
24635 tcg_gen_sub_tl(t3, t0, t3);
24636 tcg_gen_sub_tl(t2, t1, t2);
24637 break;
24639 gen_store_mxu_gpr(t3, XRa);
24640 gen_store_mxu_gpr(t2, XRd);
24642 tcg_temp_free(t0);
24643 tcg_temp_free(t1);
24644 tcg_temp_free(t2);
24645 tcg_temp_free(t3);
24649 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24650 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24652 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24654 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24655 uint32_t XRa, XRb, XRc, XRd, sel;
24657 t0 = tcg_temp_new();
24658 t1 = tcg_temp_new();
24659 t2 = tcg_temp_new();
24660 t3 = tcg_temp_new();
24661 t4 = tcg_temp_new();
24662 t5 = tcg_temp_new();
24663 t6 = tcg_temp_new();
24664 t7 = tcg_temp_new();
24666 XRa = extract32(ctx->opcode, 6, 4);
24667 XRb = extract32(ctx->opcode, 10, 4);
24668 XRc = extract32(ctx->opcode, 14, 4);
24669 XRd = extract32(ctx->opcode, 18, 4);
24670 sel = extract32(ctx->opcode, 22, 2);
24672 gen_load_mxu_gpr(t3, XRb);
24673 gen_load_mxu_gpr(t7, XRc);
24675 if (sel == 0x2) {
24676 /* Q8MULSU */
24677 tcg_gen_ext8s_tl(t0, t3);
24678 tcg_gen_shri_tl(t3, t3, 8);
24679 tcg_gen_ext8s_tl(t1, t3);
24680 tcg_gen_shri_tl(t3, t3, 8);
24681 tcg_gen_ext8s_tl(t2, t3);
24682 tcg_gen_shri_tl(t3, t3, 8);
24683 tcg_gen_ext8s_tl(t3, t3);
24684 } else {
24685 /* Q8MUL */
24686 tcg_gen_ext8u_tl(t0, t3);
24687 tcg_gen_shri_tl(t3, t3, 8);
24688 tcg_gen_ext8u_tl(t1, t3);
24689 tcg_gen_shri_tl(t3, t3, 8);
24690 tcg_gen_ext8u_tl(t2, t3);
24691 tcg_gen_shri_tl(t3, t3, 8);
24692 tcg_gen_ext8u_tl(t3, t3);
24695 tcg_gen_ext8u_tl(t4, t7);
24696 tcg_gen_shri_tl(t7, t7, 8);
24697 tcg_gen_ext8u_tl(t5, t7);
24698 tcg_gen_shri_tl(t7, t7, 8);
24699 tcg_gen_ext8u_tl(t6, t7);
24700 tcg_gen_shri_tl(t7, t7, 8);
24701 tcg_gen_ext8u_tl(t7, t7);
24703 tcg_gen_mul_tl(t0, t0, t4);
24704 tcg_gen_mul_tl(t1, t1, t5);
24705 tcg_gen_mul_tl(t2, t2, t6);
24706 tcg_gen_mul_tl(t3, t3, t7);
24708 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24709 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24710 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24711 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24713 tcg_gen_shli_tl(t1, t1, 16);
24714 tcg_gen_shli_tl(t3, t3, 16);
24716 tcg_gen_or_tl(t0, t0, t1);
24717 tcg_gen_or_tl(t1, t2, t3);
24719 gen_store_mxu_gpr(t0, XRd);
24720 gen_store_mxu_gpr(t1, XRa);
24722 tcg_temp_free(t0);
24723 tcg_temp_free(t1);
24724 tcg_temp_free(t2);
24725 tcg_temp_free(t3);
24726 tcg_temp_free(t4);
24727 tcg_temp_free(t5);
24728 tcg_temp_free(t6);
24729 tcg_temp_free(t7);
24733 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24734 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24736 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24738 TCGv t0, t1;
24739 uint32_t XRa, Rb, s12, sel;
24741 t0 = tcg_temp_new();
24742 t1 = tcg_temp_new();
24744 XRa = extract32(ctx->opcode, 6, 4);
24745 s12 = extract32(ctx->opcode, 10, 10);
24746 sel = extract32(ctx->opcode, 20, 1);
24747 Rb = extract32(ctx->opcode, 21, 5);
24749 gen_load_gpr(t0, Rb);
24751 tcg_gen_movi_tl(t1, s12);
24752 tcg_gen_shli_tl(t1, t1, 2);
24753 if (s12 & 0x200) {
24754 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24756 tcg_gen_add_tl(t1, t0, t1);
24757 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24759 if (sel == 1) {
24760 /* S32LDDR */
24761 tcg_gen_bswap32_tl(t1, t1);
24763 gen_store_mxu_gpr(t1, XRa);
24765 tcg_temp_free(t0);
24766 tcg_temp_free(t1);
24771 * MXU instruction category: logic
24772 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24774 * S32NOR S32AND S32OR S32XOR
24778 * S32NOR XRa, XRb, XRc
24779 * Update XRa with the result of logical bitwise 'nor' operation
24780 * applied to the content of XRb and XRc.
24782 * 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
24783 * +-----------+---------+-----+-------+-------+-------+-----------+
24784 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24785 * +-----------+---------+-----+-------+-------+-------+-----------+
24787 static void gen_mxu_S32NOR(DisasContext *ctx)
24789 uint32_t pad, XRc, XRb, XRa;
24791 pad = extract32(ctx->opcode, 21, 5);
24792 XRc = extract32(ctx->opcode, 14, 4);
24793 XRb = extract32(ctx->opcode, 10, 4);
24794 XRa = extract32(ctx->opcode, 6, 4);
24796 if (unlikely(pad != 0)) {
24797 /* opcode padding incorrect -> do nothing */
24798 } else if (unlikely(XRa == 0)) {
24799 /* destination is zero register -> do nothing */
24800 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24801 /* both operands zero registers -> just set destination to all 1s */
24802 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
24803 } else if (unlikely(XRb == 0)) {
24804 /* XRb zero register -> just set destination to the negation of XRc */
24805 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24806 } else if (unlikely(XRc == 0)) {
24807 /* XRa zero register -> just set destination to the negation of XRb */
24808 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24809 } else if (unlikely(XRb == XRc)) {
24810 /* both operands same -> just set destination to the negation of XRb */
24811 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24812 } else {
24813 /* the most general case */
24814 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24819 * S32AND XRa, XRb, XRc
24820 * Update XRa with the result of logical bitwise 'and' operation
24821 * applied to the content of XRb and XRc.
24823 * 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
24824 * +-----------+---------+-----+-------+-------+-------+-----------+
24825 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24826 * +-----------+---------+-----+-------+-------+-------+-----------+
24828 static void gen_mxu_S32AND(DisasContext *ctx)
24830 uint32_t pad, XRc, XRb, XRa;
24832 pad = extract32(ctx->opcode, 21, 5);
24833 XRc = extract32(ctx->opcode, 14, 4);
24834 XRb = extract32(ctx->opcode, 10, 4);
24835 XRa = extract32(ctx->opcode, 6, 4);
24837 if (unlikely(pad != 0)) {
24838 /* opcode padding incorrect -> do nothing */
24839 } else if (unlikely(XRa == 0)) {
24840 /* destination is zero register -> do nothing */
24841 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24842 /* one of operands zero register -> just set destination to all 0s */
24843 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24844 } else if (unlikely(XRb == XRc)) {
24845 /* both operands same -> just set destination to one of them */
24846 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24847 } else {
24848 /* the most general case */
24849 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24854 * S32OR XRa, XRb, XRc
24855 * Update XRa with the result of logical bitwise 'or' operation
24856 * applied to the content of XRb and XRc.
24858 * 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
24859 * +-----------+---------+-----+-------+-------+-------+-----------+
24860 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24861 * +-----------+---------+-----+-------+-------+-------+-----------+
24863 static void gen_mxu_S32OR(DisasContext *ctx)
24865 uint32_t pad, XRc, XRb, XRa;
24867 pad = extract32(ctx->opcode, 21, 5);
24868 XRc = extract32(ctx->opcode, 14, 4);
24869 XRb = extract32(ctx->opcode, 10, 4);
24870 XRa = extract32(ctx->opcode, 6, 4);
24872 if (unlikely(pad != 0)) {
24873 /* opcode padding incorrect -> do nothing */
24874 } else if (unlikely(XRa == 0)) {
24875 /* destination is zero register -> do nothing */
24876 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24877 /* both operands zero registers -> just set destination to all 0s */
24878 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24879 } else if (unlikely(XRb == 0)) {
24880 /* XRb zero register -> just set destination to the content of XRc */
24881 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24882 } else if (unlikely(XRc == 0)) {
24883 /* XRc zero register -> just set destination to the content of XRb */
24884 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24885 } else if (unlikely(XRb == XRc)) {
24886 /* both operands same -> just set destination to one of them */
24887 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24888 } else {
24889 /* the most general case */
24890 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24895 * S32XOR XRa, XRb, XRc
24896 * Update XRa with the result of logical bitwise 'xor' operation
24897 * applied to the content of XRb and XRc.
24899 * 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
24900 * +-----------+---------+-----+-------+-------+-------+-----------+
24901 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24902 * +-----------+---------+-----+-------+-------+-------+-----------+
24904 static void gen_mxu_S32XOR(DisasContext *ctx)
24906 uint32_t pad, XRc, XRb, XRa;
24908 pad = extract32(ctx->opcode, 21, 5);
24909 XRc = extract32(ctx->opcode, 14, 4);
24910 XRb = extract32(ctx->opcode, 10, 4);
24911 XRa = extract32(ctx->opcode, 6, 4);
24913 if (unlikely(pad != 0)) {
24914 /* opcode padding incorrect -> do nothing */
24915 } else if (unlikely(XRa == 0)) {
24916 /* destination is zero register -> do nothing */
24917 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24918 /* both operands zero registers -> just set destination to all 0s */
24919 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24920 } else if (unlikely(XRb == 0)) {
24921 /* XRb zero register -> just set destination to the content of XRc */
24922 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24923 } else if (unlikely(XRc == 0)) {
24924 /* XRc zero register -> just set destination to the content of XRb */
24925 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24926 } else if (unlikely(XRb == XRc)) {
24927 /* both operands same -> just set destination to all 0s */
24928 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24929 } else {
24930 /* the most general case */
24931 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24937 * MXU instruction category max/min
24938 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24940 * S32MAX D16MAX Q8MAX
24941 * S32MIN D16MIN Q8MIN
24945 * S32MAX XRa, XRb, XRc
24946 * Update XRa with the maximum of signed 32-bit integers contained
24947 * in XRb and XRc.
24949 * S32MIN XRa, XRb, XRc
24950 * Update XRa with the minimum of signed 32-bit integers contained
24951 * in XRb and XRc.
24953 * 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
24954 * +-----------+---------+-----+-------+-------+-------+-----------+
24955 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
24956 * +-----------+---------+-----+-------+-------+-------+-----------+
24958 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
24960 uint32_t pad, opc, XRc, XRb, XRa;
24962 pad = extract32(ctx->opcode, 21, 5);
24963 opc = extract32(ctx->opcode, 18, 3);
24964 XRc = extract32(ctx->opcode, 14, 4);
24965 XRb = extract32(ctx->opcode, 10, 4);
24966 XRa = extract32(ctx->opcode, 6, 4);
24968 if (unlikely(pad != 0)) {
24969 /* opcode padding incorrect -> do nothing */
24970 } else if (unlikely(XRa == 0)) {
24971 /* destination is zero register -> do nothing */
24972 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24973 /* both operands zero registers -> just set destination to zero */
24974 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24975 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24976 /* exactly one operand is zero register - find which one is not...*/
24977 uint32_t XRx = XRb ? XRb : XRc;
24978 /* ...and do max/min operation with one operand 0 */
24979 if (opc == OPC_MXU_S32MAX) {
24980 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24981 } else {
24982 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24984 } else if (unlikely(XRb == XRc)) {
24985 /* both operands same -> just set destination to one of them */
24986 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24987 } else {
24988 /* the most general case */
24989 if (opc == OPC_MXU_S32MAX) {
24990 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
24991 mxu_gpr[XRc - 1]);
24992 } else {
24993 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
24994 mxu_gpr[XRc - 1]);
25000 * D16MAX
25001 * Update XRa with the 16-bit-wise maximums of signed integers
25002 * contained in XRb and XRc.
25004 * D16MIN
25005 * Update XRa with the 16-bit-wise minimums of signed integers
25006 * contained in XRb and XRc.
25008 * 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
25009 * +-----------+---------+-----+-------+-------+-------+-----------+
25010 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25011 * +-----------+---------+-----+-------+-------+-------+-----------+
25013 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25015 uint32_t pad, opc, XRc, XRb, XRa;
25017 pad = extract32(ctx->opcode, 21, 5);
25018 opc = extract32(ctx->opcode, 18, 3);
25019 XRc = extract32(ctx->opcode, 14, 4);
25020 XRb = extract32(ctx->opcode, 10, 4);
25021 XRa = extract32(ctx->opcode, 6, 4);
25023 if (unlikely(pad != 0)) {
25024 /* opcode padding incorrect -> do nothing */
25025 } else if (unlikely(XRc == 0)) {
25026 /* destination is zero register -> do nothing */
25027 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25028 /* both operands zero registers -> just set destination to zero */
25029 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25030 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25031 /* exactly one operand is zero register - find which one is not...*/
25032 uint32_t XRx = XRb ? XRb : XRc;
25033 /* ...and do half-word-wise max/min with one operand 0 */
25034 TCGv_i32 t0 = tcg_temp_new();
25035 TCGv_i32 t1 = tcg_const_i32(0);
25037 /* the left half-word first */
25038 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25039 if (opc == OPC_MXU_D16MAX) {
25040 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25041 } else {
25042 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25045 /* the right half-word */
25046 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25047 /* move half-words to the leftmost position */
25048 tcg_gen_shli_i32(t0, t0, 16);
25049 /* t0 will be max/min of t0 and t1 */
25050 if (opc == OPC_MXU_D16MAX) {
25051 tcg_gen_smax_i32(t0, t0, t1);
25052 } else {
25053 tcg_gen_smin_i32(t0, t0, t1);
25055 /* return resulting half-words to its original position */
25056 tcg_gen_shri_i32(t0, t0, 16);
25057 /* finaly update the destination */
25058 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25060 tcg_temp_free(t1);
25061 tcg_temp_free(t0);
25062 } else if (unlikely(XRb == XRc)) {
25063 /* both operands same -> just set destination to one of them */
25064 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25065 } else {
25066 /* the most general case */
25067 TCGv_i32 t0 = tcg_temp_new();
25068 TCGv_i32 t1 = tcg_temp_new();
25070 /* the left half-word first */
25071 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25072 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25073 if (opc == OPC_MXU_D16MAX) {
25074 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25075 } else {
25076 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25079 /* the right half-word */
25080 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25081 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25082 /* move half-words to the leftmost position */
25083 tcg_gen_shli_i32(t0, t0, 16);
25084 tcg_gen_shli_i32(t1, t1, 16);
25085 /* t0 will be max/min of t0 and t1 */
25086 if (opc == OPC_MXU_D16MAX) {
25087 tcg_gen_smax_i32(t0, t0, t1);
25088 } else {
25089 tcg_gen_smin_i32(t0, t0, t1);
25091 /* return resulting half-words to its original position */
25092 tcg_gen_shri_i32(t0, t0, 16);
25093 /* finaly update the destination */
25094 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25096 tcg_temp_free(t1);
25097 tcg_temp_free(t0);
25102 * Q8MAX
25103 * Update XRa with the 8-bit-wise maximums of signed integers
25104 * contained in XRb and XRc.
25106 * Q8MIN
25107 * Update XRa with the 8-bit-wise minimums of signed integers
25108 * contained in XRb and XRc.
25110 * 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
25111 * +-----------+---------+-----+-------+-------+-------+-----------+
25112 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25113 * +-----------+---------+-----+-------+-------+-------+-----------+
25115 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25117 uint32_t pad, opc, XRc, XRb, XRa;
25119 pad = extract32(ctx->opcode, 21, 5);
25120 opc = extract32(ctx->opcode, 18, 3);
25121 XRc = extract32(ctx->opcode, 14, 4);
25122 XRb = extract32(ctx->opcode, 10, 4);
25123 XRa = extract32(ctx->opcode, 6, 4);
25125 if (unlikely(pad != 0)) {
25126 /* opcode padding incorrect -> do nothing */
25127 } else if (unlikely(XRa == 0)) {
25128 /* destination is zero register -> do nothing */
25129 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25130 /* both operands zero registers -> just set destination to zero */
25131 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25132 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25133 /* exactly one operand is zero register - make it be the first...*/
25134 uint32_t XRx = XRb ? XRb : XRc;
25135 /* ...and do byte-wise max/min with one operand 0 */
25136 TCGv_i32 t0 = tcg_temp_new();
25137 TCGv_i32 t1 = tcg_const_i32(0);
25138 int32_t i;
25140 /* the leftmost byte (byte 3) first */
25141 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25142 if (opc == OPC_MXU_Q8MAX) {
25143 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25144 } else {
25145 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25148 /* bytes 2, 1, 0 */
25149 for (i = 2; i >= 0; i--) {
25150 /* extract the byte */
25151 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25152 /* move the byte to the leftmost position */
25153 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25154 /* t0 will be max/min of t0 and t1 */
25155 if (opc == OPC_MXU_Q8MAX) {
25156 tcg_gen_smax_i32(t0, t0, t1);
25157 } else {
25158 tcg_gen_smin_i32(t0, t0, t1);
25160 /* return resulting byte to its original position */
25161 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25162 /* finaly update the destination */
25163 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25166 tcg_temp_free(t1);
25167 tcg_temp_free(t0);
25168 } else if (unlikely(XRb == XRc)) {
25169 /* both operands same -> just set destination to one of them */
25170 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25171 } else {
25172 /* the most general case */
25173 TCGv_i32 t0 = tcg_temp_new();
25174 TCGv_i32 t1 = tcg_temp_new();
25175 int32_t i;
25177 /* the leftmost bytes (bytes 3) first */
25178 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25179 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25180 if (opc == OPC_MXU_Q8MAX) {
25181 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25182 } else {
25183 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25186 /* bytes 2, 1, 0 */
25187 for (i = 2; i >= 0; i--) {
25188 /* extract corresponding bytes */
25189 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25190 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25191 /* move the bytes to the leftmost position */
25192 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25193 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25194 /* t0 will be max/min of t0 and t1 */
25195 if (opc == OPC_MXU_Q8MAX) {
25196 tcg_gen_smax_i32(t0, t0, t1);
25197 } else {
25198 tcg_gen_smin_i32(t0, t0, t1);
25200 /* return resulting byte to its original position */
25201 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25202 /* finaly update the destination */
25203 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25206 tcg_temp_free(t1);
25207 tcg_temp_free(t0);
25213 * MXU instruction category: align
25214 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25216 * S32ALN S32ALNI
25220 * S32ALNI XRc, XRb, XRa, optn3
25221 * Arrange bytes from XRb and XRc according to one of five sets of
25222 * rules determined by optn3, and place the result in XRa.
25224 * 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
25225 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25226 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25227 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25230 static void gen_mxu_S32ALNI(DisasContext *ctx)
25232 uint32_t optn3, pad, XRc, XRb, XRa;
25234 optn3 = extract32(ctx->opcode, 23, 3);
25235 pad = extract32(ctx->opcode, 21, 2);
25236 XRc = extract32(ctx->opcode, 14, 4);
25237 XRb = extract32(ctx->opcode, 10, 4);
25238 XRa = extract32(ctx->opcode, 6, 4);
25240 if (unlikely(pad != 0)) {
25241 /* opcode padding incorrect -> do nothing */
25242 } else if (unlikely(XRa == 0)) {
25243 /* destination is zero register -> do nothing */
25244 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25245 /* both operands zero registers -> just set destination to all 0s */
25246 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25247 } else if (unlikely(XRb == 0)) {
25248 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25249 switch (optn3) {
25250 case MXU_OPTN3_PTN0:
25251 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25252 break;
25253 case MXU_OPTN3_PTN1:
25254 case MXU_OPTN3_PTN2:
25255 case MXU_OPTN3_PTN3:
25256 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25257 8 * (4 - optn3));
25258 break;
25259 case MXU_OPTN3_PTN4:
25260 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25261 break;
25263 } else if (unlikely(XRc == 0)) {
25264 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25265 switch (optn3) {
25266 case MXU_OPTN3_PTN0:
25267 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25268 break;
25269 case MXU_OPTN3_PTN1:
25270 case MXU_OPTN3_PTN2:
25271 case MXU_OPTN3_PTN3:
25272 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25273 break;
25274 case MXU_OPTN3_PTN4:
25275 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25276 break;
25278 } else if (unlikely(XRb == XRc)) {
25279 /* both operands same -> just rotation or moving from any of them */
25280 switch (optn3) {
25281 case MXU_OPTN3_PTN0:
25282 case MXU_OPTN3_PTN4:
25283 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25284 break;
25285 case MXU_OPTN3_PTN1:
25286 case MXU_OPTN3_PTN2:
25287 case MXU_OPTN3_PTN3:
25288 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25289 break;
25291 } else {
25292 /* the most general case */
25293 switch (optn3) {
25294 case MXU_OPTN3_PTN0:
25296 /* */
25297 /* XRb XRc */
25298 /* +---------------+ */
25299 /* | A B C D | E F G H */
25300 /* +-------+-------+ */
25301 /* | */
25302 /* XRa */
25303 /* */
25305 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25307 break;
25308 case MXU_OPTN3_PTN1:
25310 /* */
25311 /* XRb XRc */
25312 /* +-------------------+ */
25313 /* A | B C D E | F G H */
25314 /* +---------+---------+ */
25315 /* | */
25316 /* XRa */
25317 /* */
25319 TCGv_i32 t0 = tcg_temp_new();
25320 TCGv_i32 t1 = tcg_temp_new();
25322 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25323 tcg_gen_shli_i32(t0, t0, 8);
25325 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25326 tcg_gen_shri_i32(t1, t1, 24);
25328 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25330 tcg_temp_free(t1);
25331 tcg_temp_free(t0);
25333 break;
25334 case MXU_OPTN3_PTN2:
25336 /* */
25337 /* XRb XRc */
25338 /* +-------------------+ */
25339 /* A B | C D E F | G H */
25340 /* +---------+---------+ */
25341 /* | */
25342 /* XRa */
25343 /* */
25345 TCGv_i32 t0 = tcg_temp_new();
25346 TCGv_i32 t1 = tcg_temp_new();
25348 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25349 tcg_gen_shli_i32(t0, t0, 16);
25351 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25352 tcg_gen_shri_i32(t1, t1, 16);
25354 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25356 tcg_temp_free(t1);
25357 tcg_temp_free(t0);
25359 break;
25360 case MXU_OPTN3_PTN3:
25362 /* */
25363 /* XRb XRc */
25364 /* +-------------------+ */
25365 /* A B C | D E F G | H */
25366 /* +---------+---------+ */
25367 /* | */
25368 /* XRa */
25369 /* */
25371 TCGv_i32 t0 = tcg_temp_new();
25372 TCGv_i32 t1 = tcg_temp_new();
25374 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25375 tcg_gen_shli_i32(t0, t0, 24);
25377 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25378 tcg_gen_shri_i32(t1, t1, 8);
25380 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25382 tcg_temp_free(t1);
25383 tcg_temp_free(t0);
25385 break;
25386 case MXU_OPTN3_PTN4:
25388 /* */
25389 /* XRb XRc */
25390 /* +---------------+ */
25391 /* A B C D | E F G H | */
25392 /* +-------+-------+ */
25393 /* | */
25394 /* XRa */
25395 /* */
25397 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25399 break;
25406 * Decoding engine for MXU
25407 * =======================
25412 * Decode MXU pool00
25414 * 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
25415 * +-----------+---------+-----+-------+-------+-------+-----------+
25416 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25417 * +-----------+---------+-----+-------+-------+-------+-----------+
25420 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25422 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25424 switch (opcode) {
25425 case OPC_MXU_S32MAX:
25426 case OPC_MXU_S32MIN:
25427 gen_mxu_S32MAX_S32MIN(ctx);
25428 break;
25429 case OPC_MXU_D16MAX:
25430 case OPC_MXU_D16MIN:
25431 gen_mxu_D16MAX_D16MIN(ctx);
25432 break;
25433 case OPC_MXU_Q8MAX:
25434 case OPC_MXU_Q8MIN:
25435 gen_mxu_Q8MAX_Q8MIN(ctx);
25436 break;
25437 case OPC_MXU_Q8SLT:
25438 /* TODO: Implement emulation of Q8SLT instruction. */
25439 MIPS_INVAL("OPC_MXU_Q8SLT");
25440 generate_exception_end(ctx, EXCP_RI);
25441 break;
25442 case OPC_MXU_Q8SLTU:
25443 /* TODO: Implement emulation of Q8SLTU instruction. */
25444 MIPS_INVAL("OPC_MXU_Q8SLTU");
25445 generate_exception_end(ctx, EXCP_RI);
25446 break;
25447 default:
25448 MIPS_INVAL("decode_opc_mxu");
25449 generate_exception_end(ctx, EXCP_RI);
25450 break;
25456 * Decode MXU pool01
25458 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25459 * 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
25460 * +-----------+---------+-----+-------+-------+-------+-----------+
25461 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25462 * +-----------+---------+-----+-------+-------+-------+-----------+
25464 * Q8ADD:
25465 * 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
25466 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25467 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25468 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25471 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25473 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25475 switch (opcode) {
25476 case OPC_MXU_S32SLT:
25477 /* TODO: Implement emulation of S32SLT instruction. */
25478 MIPS_INVAL("OPC_MXU_S32SLT");
25479 generate_exception_end(ctx, EXCP_RI);
25480 break;
25481 case OPC_MXU_D16SLT:
25482 /* TODO: Implement emulation of D16SLT instruction. */
25483 MIPS_INVAL("OPC_MXU_D16SLT");
25484 generate_exception_end(ctx, EXCP_RI);
25485 break;
25486 case OPC_MXU_D16AVG:
25487 /* TODO: Implement emulation of D16AVG instruction. */
25488 MIPS_INVAL("OPC_MXU_D16AVG");
25489 generate_exception_end(ctx, EXCP_RI);
25490 break;
25491 case OPC_MXU_D16AVGR:
25492 /* TODO: Implement emulation of D16AVGR instruction. */
25493 MIPS_INVAL("OPC_MXU_D16AVGR");
25494 generate_exception_end(ctx, EXCP_RI);
25495 break;
25496 case OPC_MXU_Q8AVG:
25497 /* TODO: Implement emulation of Q8AVG instruction. */
25498 MIPS_INVAL("OPC_MXU_Q8AVG");
25499 generate_exception_end(ctx, EXCP_RI);
25500 break;
25501 case OPC_MXU_Q8AVGR:
25502 /* TODO: Implement emulation of Q8AVGR instruction. */
25503 MIPS_INVAL("OPC_MXU_Q8AVGR");
25504 generate_exception_end(ctx, EXCP_RI);
25505 break;
25506 case OPC_MXU_Q8ADD:
25507 /* TODO: Implement emulation of Q8ADD instruction. */
25508 MIPS_INVAL("OPC_MXU_Q8ADD");
25509 generate_exception_end(ctx, EXCP_RI);
25510 break;
25511 default:
25512 MIPS_INVAL("decode_opc_mxu");
25513 generate_exception_end(ctx, EXCP_RI);
25514 break;
25520 * Decode MXU pool02
25522 * 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
25523 * +-----------+---------+-----+-------+-------+-------+-----------+
25524 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25525 * +-----------+---------+-----+-------+-------+-------+-----------+
25528 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25530 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25532 switch (opcode) {
25533 case OPC_MXU_S32CPS:
25534 /* TODO: Implement emulation of S32CPS instruction. */
25535 MIPS_INVAL("OPC_MXU_S32CPS");
25536 generate_exception_end(ctx, EXCP_RI);
25537 break;
25538 case OPC_MXU_D16CPS:
25539 /* TODO: Implement emulation of D16CPS instruction. */
25540 MIPS_INVAL("OPC_MXU_D16CPS");
25541 generate_exception_end(ctx, EXCP_RI);
25542 break;
25543 case OPC_MXU_Q8ABD:
25544 /* TODO: Implement emulation of Q8ABD instruction. */
25545 MIPS_INVAL("OPC_MXU_Q8ABD");
25546 generate_exception_end(ctx, EXCP_RI);
25547 break;
25548 case OPC_MXU_Q16SAT:
25549 /* TODO: Implement emulation of Q16SAT instruction. */
25550 MIPS_INVAL("OPC_MXU_Q16SAT");
25551 generate_exception_end(ctx, EXCP_RI);
25552 break;
25553 default:
25554 MIPS_INVAL("decode_opc_mxu");
25555 generate_exception_end(ctx, EXCP_RI);
25556 break;
25562 * Decode MXU pool03
25564 * D16MULF:
25565 * 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
25566 * +-----------+---+---+-------+-------+-------+-------+-----------+
25567 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25568 * +-----------+---+---+-------+-------+-------+-------+-----------+
25570 * D16MULE:
25571 * 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
25572 * +-----------+---+---+-------+-------+-------+-------+-----------+
25573 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25574 * +-----------+---+---+-------+-------+-------+-------+-----------+
25577 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25579 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25581 switch (opcode) {
25582 case OPC_MXU_D16MULF:
25583 /* TODO: Implement emulation of D16MULF instruction. */
25584 MIPS_INVAL("OPC_MXU_D16MULF");
25585 generate_exception_end(ctx, EXCP_RI);
25586 break;
25587 case OPC_MXU_D16MULE:
25588 /* TODO: Implement emulation of D16MULE instruction. */
25589 MIPS_INVAL("OPC_MXU_D16MULE");
25590 generate_exception_end(ctx, EXCP_RI);
25591 break;
25592 default:
25593 MIPS_INVAL("decode_opc_mxu");
25594 generate_exception_end(ctx, EXCP_RI);
25595 break;
25601 * Decode MXU pool04
25603 * 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
25604 * +-----------+---------+-+-------------------+-------+-----------+
25605 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25606 * +-----------+---------+-+-------------------+-------+-----------+
25609 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25611 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25613 switch (opcode) {
25614 case OPC_MXU_S32LDD:
25615 case OPC_MXU_S32LDDR:
25616 gen_mxu_s32ldd_s32lddr(ctx);
25617 break;
25618 default:
25619 MIPS_INVAL("decode_opc_mxu");
25620 generate_exception_end(ctx, EXCP_RI);
25621 break;
25627 * Decode MXU pool05
25629 * 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
25630 * +-----------+---------+-+-------------------+-------+-----------+
25631 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25632 * +-----------+---------+-+-------------------+-------+-----------+
25635 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25637 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25639 switch (opcode) {
25640 case OPC_MXU_S32STD:
25641 /* TODO: Implement emulation of S32STD instruction. */
25642 MIPS_INVAL("OPC_MXU_S32STD");
25643 generate_exception_end(ctx, EXCP_RI);
25644 break;
25645 case OPC_MXU_S32STDR:
25646 /* TODO: Implement emulation of S32STDR instruction. */
25647 MIPS_INVAL("OPC_MXU_S32STDR");
25648 generate_exception_end(ctx, EXCP_RI);
25649 break;
25650 default:
25651 MIPS_INVAL("decode_opc_mxu");
25652 generate_exception_end(ctx, EXCP_RI);
25653 break;
25659 * Decode MXU pool06
25661 * 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
25662 * +-----------+---------+---------+---+-------+-------+-----------+
25663 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25664 * +-----------+---------+---------+---+-------+-------+-----------+
25667 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25669 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25671 switch (opcode) {
25672 case OPC_MXU_S32LDDV:
25673 /* TODO: Implement emulation of S32LDDV instruction. */
25674 MIPS_INVAL("OPC_MXU_S32LDDV");
25675 generate_exception_end(ctx, EXCP_RI);
25676 break;
25677 case OPC_MXU_S32LDDVR:
25678 /* TODO: Implement emulation of S32LDDVR instruction. */
25679 MIPS_INVAL("OPC_MXU_S32LDDVR");
25680 generate_exception_end(ctx, EXCP_RI);
25681 break;
25682 default:
25683 MIPS_INVAL("decode_opc_mxu");
25684 generate_exception_end(ctx, EXCP_RI);
25685 break;
25691 * Decode MXU pool07
25693 * 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
25694 * +-----------+---------+---------+---+-------+-------+-----------+
25695 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
25696 * +-----------+---------+---------+---+-------+-------+-----------+
25699 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
25701 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25703 switch (opcode) {
25704 case OPC_MXU_S32STDV:
25705 /* TODO: Implement emulation of S32TDV instruction. */
25706 MIPS_INVAL("OPC_MXU_S32TDV");
25707 generate_exception_end(ctx, EXCP_RI);
25708 break;
25709 case OPC_MXU_S32STDVR:
25710 /* TODO: Implement emulation of S32TDVR instruction. */
25711 MIPS_INVAL("OPC_MXU_S32TDVR");
25712 generate_exception_end(ctx, EXCP_RI);
25713 break;
25714 default:
25715 MIPS_INVAL("decode_opc_mxu");
25716 generate_exception_end(ctx, EXCP_RI);
25717 break;
25723 * Decode MXU pool08
25725 * 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
25726 * +-----------+---------+-+-------------------+-------+-----------+
25727 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
25728 * +-----------+---------+-+-------------------+-------+-----------+
25731 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
25733 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25735 switch (opcode) {
25736 case OPC_MXU_S32LDI:
25737 /* TODO: Implement emulation of S32LDI instruction. */
25738 MIPS_INVAL("OPC_MXU_S32LDI");
25739 generate_exception_end(ctx, EXCP_RI);
25740 break;
25741 case OPC_MXU_S32LDIR:
25742 /* TODO: Implement emulation of S32LDIR instruction. */
25743 MIPS_INVAL("OPC_MXU_S32LDIR");
25744 generate_exception_end(ctx, EXCP_RI);
25745 break;
25746 default:
25747 MIPS_INVAL("decode_opc_mxu");
25748 generate_exception_end(ctx, EXCP_RI);
25749 break;
25755 * Decode MXU pool09
25757 * 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
25758 * +-----------+---------+-+-------------------+-------+-----------+
25759 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
25760 * +-----------+---------+-+-------------------+-------+-----------+
25763 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
25765 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25767 switch (opcode) {
25768 case OPC_MXU_S32SDI:
25769 /* TODO: Implement emulation of S32SDI instruction. */
25770 MIPS_INVAL("OPC_MXU_S32SDI");
25771 generate_exception_end(ctx, EXCP_RI);
25772 break;
25773 case OPC_MXU_S32SDIR:
25774 /* TODO: Implement emulation of S32SDIR instruction. */
25775 MIPS_INVAL("OPC_MXU_S32SDIR");
25776 generate_exception_end(ctx, EXCP_RI);
25777 break;
25778 default:
25779 MIPS_INVAL("decode_opc_mxu");
25780 generate_exception_end(ctx, EXCP_RI);
25781 break;
25787 * Decode MXU pool10
25789 * 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
25790 * +-----------+---------+---------+---+-------+-------+-----------+
25791 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
25792 * +-----------+---------+---------+---+-------+-------+-----------+
25795 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
25797 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25799 switch (opcode) {
25800 case OPC_MXU_S32LDIV:
25801 /* TODO: Implement emulation of S32LDIV instruction. */
25802 MIPS_INVAL("OPC_MXU_S32LDIV");
25803 generate_exception_end(ctx, EXCP_RI);
25804 break;
25805 case OPC_MXU_S32LDIVR:
25806 /* TODO: Implement emulation of S32LDIVR instruction. */
25807 MIPS_INVAL("OPC_MXU_S32LDIVR");
25808 generate_exception_end(ctx, EXCP_RI);
25809 break;
25810 default:
25811 MIPS_INVAL("decode_opc_mxu");
25812 generate_exception_end(ctx, EXCP_RI);
25813 break;
25819 * Decode MXU pool11
25821 * 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
25822 * +-----------+---------+---------+---+-------+-------+-----------+
25823 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
25824 * +-----------+---------+---------+---+-------+-------+-----------+
25827 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
25829 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25831 switch (opcode) {
25832 case OPC_MXU_S32SDIV:
25833 /* TODO: Implement emulation of S32SDIV instruction. */
25834 MIPS_INVAL("OPC_MXU_S32SDIV");
25835 generate_exception_end(ctx, EXCP_RI);
25836 break;
25837 case OPC_MXU_S32SDIVR:
25838 /* TODO: Implement emulation of S32SDIVR instruction. */
25839 MIPS_INVAL("OPC_MXU_S32SDIVR");
25840 generate_exception_end(ctx, EXCP_RI);
25841 break;
25842 default:
25843 MIPS_INVAL("decode_opc_mxu");
25844 generate_exception_end(ctx, EXCP_RI);
25845 break;
25851 * Decode MXU pool12
25853 * 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
25854 * +-----------+---+---+-------+-------+-------+-------+-----------+
25855 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
25856 * +-----------+---+---+-------+-------+-------+-------+-----------+
25859 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
25861 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25863 switch (opcode) {
25864 case OPC_MXU_D32ACC:
25865 /* TODO: Implement emulation of D32ACC instruction. */
25866 MIPS_INVAL("OPC_MXU_D32ACC");
25867 generate_exception_end(ctx, EXCP_RI);
25868 break;
25869 case OPC_MXU_D32ACCM:
25870 /* TODO: Implement emulation of D32ACCM instruction. */
25871 MIPS_INVAL("OPC_MXU_D32ACCM");
25872 generate_exception_end(ctx, EXCP_RI);
25873 break;
25874 case OPC_MXU_D32ASUM:
25875 /* TODO: Implement emulation of D32ASUM instruction. */
25876 MIPS_INVAL("OPC_MXU_D32ASUM");
25877 generate_exception_end(ctx, EXCP_RI);
25878 break;
25879 default:
25880 MIPS_INVAL("decode_opc_mxu");
25881 generate_exception_end(ctx, EXCP_RI);
25882 break;
25888 * Decode MXU pool13
25890 * 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
25891 * +-----------+---+---+-------+-------+-------+-------+-----------+
25892 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
25893 * +-----------+---+---+-------+-------+-------+-------+-----------+
25896 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
25898 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25900 switch (opcode) {
25901 case OPC_MXU_Q16ACC:
25902 /* TODO: Implement emulation of Q16ACC instruction. */
25903 MIPS_INVAL("OPC_MXU_Q16ACC");
25904 generate_exception_end(ctx, EXCP_RI);
25905 break;
25906 case OPC_MXU_Q16ACCM:
25907 /* TODO: Implement emulation of Q16ACCM instruction. */
25908 MIPS_INVAL("OPC_MXU_Q16ACCM");
25909 generate_exception_end(ctx, EXCP_RI);
25910 break;
25911 case OPC_MXU_Q16ASUM:
25912 /* TODO: Implement emulation of Q16ASUM instruction. */
25913 MIPS_INVAL("OPC_MXU_Q16ASUM");
25914 generate_exception_end(ctx, EXCP_RI);
25915 break;
25916 default:
25917 MIPS_INVAL("decode_opc_mxu");
25918 generate_exception_end(ctx, EXCP_RI);
25919 break;
25925 * Decode MXU pool14
25927 * Q8ADDE, Q8ACCE:
25928 * 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
25929 * +-----------+---+---+-------+-------+-------+-------+-----------+
25930 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
25931 * +-----------+---+---+-------+-------+-------+-------+-----------+
25933 * D8SUM, D8SUMC:
25934 * 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
25935 * +-----------+---+---+-------+-------+-------+-------+-----------+
25936 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
25937 * +-----------+---+---+-------+-------+-------+-------+-----------+
25940 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
25942 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25944 switch (opcode) {
25945 case OPC_MXU_Q8ADDE:
25946 /* TODO: Implement emulation of Q8ADDE instruction. */
25947 MIPS_INVAL("OPC_MXU_Q8ADDE");
25948 generate_exception_end(ctx, EXCP_RI);
25949 break;
25950 case OPC_MXU_D8SUM:
25951 /* TODO: Implement emulation of D8SUM instruction. */
25952 MIPS_INVAL("OPC_MXU_D8SUM");
25953 generate_exception_end(ctx, EXCP_RI);
25954 break;
25955 case OPC_MXU_D8SUMC:
25956 /* TODO: Implement emulation of D8SUMC instruction. */
25957 MIPS_INVAL("OPC_MXU_D8SUMC");
25958 generate_exception_end(ctx, EXCP_RI);
25959 break;
25960 default:
25961 MIPS_INVAL("decode_opc_mxu");
25962 generate_exception_end(ctx, EXCP_RI);
25963 break;
25969 * Decode MXU pool15
25971 * S32MUL, S32MULU, S32EXTRV:
25972 * 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
25973 * +-----------+---------+---------+---+-------+-------+-----------+
25974 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
25975 * +-----------+---------+---------+---+-------+-------+-----------+
25977 * S32EXTR:
25978 * 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
25979 * +-----------+---------+---------+---+-------+-------+-----------+
25980 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
25981 * +-----------+---------+---------+---+-------+-------+-----------+
25984 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
25986 uint32_t opcode = extract32(ctx->opcode, 14, 2);
25988 switch (opcode) {
25989 case OPC_MXU_S32MUL:
25990 /* TODO: Implement emulation of S32MUL instruction. */
25991 MIPS_INVAL("OPC_MXU_S32MUL");
25992 generate_exception_end(ctx, EXCP_RI);
25993 break;
25994 case OPC_MXU_S32MULU:
25995 /* TODO: Implement emulation of S32MULU instruction. */
25996 MIPS_INVAL("OPC_MXU_S32MULU");
25997 generate_exception_end(ctx, EXCP_RI);
25998 break;
25999 case OPC_MXU_S32EXTR:
26000 /* TODO: Implement emulation of S32EXTR instruction. */
26001 MIPS_INVAL("OPC_MXU_S32EXTR");
26002 generate_exception_end(ctx, EXCP_RI);
26003 break;
26004 case OPC_MXU_S32EXTRV:
26005 /* TODO: Implement emulation of S32EXTRV instruction. */
26006 MIPS_INVAL("OPC_MXU_S32EXTRV");
26007 generate_exception_end(ctx, EXCP_RI);
26008 break;
26009 default:
26010 MIPS_INVAL("decode_opc_mxu");
26011 generate_exception_end(ctx, EXCP_RI);
26012 break;
26018 * Decode MXU pool16
26020 * D32SARW:
26021 * 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
26022 * +-----------+---------+-----+-------+-------+-------+-----------+
26023 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26024 * +-----------+---------+-----+-------+-------+-------+-----------+
26026 * S32ALN:
26027 * 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
26028 * +-----------+---------+-----+-------+-------+-------+-----------+
26029 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26030 * +-----------+---------+-----+-------+-------+-------+-----------+
26032 * S32ALNI:
26033 * 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
26034 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26035 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26036 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26038 * S32LUI:
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 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26042 * +-----------+-----+---+-----+-------+---------------+-----------+
26044 * S32NOR, S32AND, S32OR, S32XOR:
26045 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26046 * +-----------+---------+-----+-------+-------+-------+-----------+
26047 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26048 * +-----------+---------+-----+-------+-------+-------+-----------+
26051 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26053 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26055 switch (opcode) {
26056 case OPC_MXU_D32SARW:
26057 /* TODO: Implement emulation of D32SARW instruction. */
26058 MIPS_INVAL("OPC_MXU_D32SARW");
26059 generate_exception_end(ctx, EXCP_RI);
26060 break;
26061 case OPC_MXU_S32ALN:
26062 /* TODO: Implement emulation of S32ALN instruction. */
26063 MIPS_INVAL("OPC_MXU_S32ALN");
26064 generate_exception_end(ctx, EXCP_RI);
26065 break;
26066 case OPC_MXU_S32ALNI:
26067 gen_mxu_S32ALNI(ctx);
26068 break;
26069 case OPC_MXU_S32LUI:
26070 /* TODO: Implement emulation of S32LUI instruction. */
26071 MIPS_INVAL("OPC_MXU_S32LUI");
26072 generate_exception_end(ctx, EXCP_RI);
26073 break;
26074 case OPC_MXU_S32NOR:
26075 gen_mxu_S32NOR(ctx);
26076 break;
26077 case OPC_MXU_S32AND:
26078 gen_mxu_S32AND(ctx);
26079 break;
26080 case OPC_MXU_S32OR:
26081 gen_mxu_S32OR(ctx);
26082 break;
26083 case OPC_MXU_S32XOR:
26084 gen_mxu_S32XOR(ctx);
26085 break;
26086 default:
26087 MIPS_INVAL("decode_opc_mxu");
26088 generate_exception_end(ctx, EXCP_RI);
26089 break;
26095 * Decode MXU pool17
26097 * 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
26098 * +-----------+---------+---------+---+---------+-----+-----------+
26099 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26100 * +-----------+---------+---------+---+---------+-----+-----------+
26103 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26105 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26107 switch (opcode) {
26108 case OPC_MXU_LXW:
26109 /* TODO: Implement emulation of LXW instruction. */
26110 MIPS_INVAL("OPC_MXU_LXW");
26111 generate_exception_end(ctx, EXCP_RI);
26112 break;
26113 case OPC_MXU_LXH:
26114 /* TODO: Implement emulation of LXH instruction. */
26115 MIPS_INVAL("OPC_MXU_LXH");
26116 generate_exception_end(ctx, EXCP_RI);
26117 break;
26118 case OPC_MXU_LXHU:
26119 /* TODO: Implement emulation of LXHU instruction. */
26120 MIPS_INVAL("OPC_MXU_LXHU");
26121 generate_exception_end(ctx, EXCP_RI);
26122 break;
26123 case OPC_MXU_LXB:
26124 /* TODO: Implement emulation of LXB instruction. */
26125 MIPS_INVAL("OPC_MXU_LXB");
26126 generate_exception_end(ctx, EXCP_RI);
26127 break;
26128 case OPC_MXU_LXBU:
26129 /* TODO: Implement emulation of LXBU instruction. */
26130 MIPS_INVAL("OPC_MXU_LXBU");
26131 generate_exception_end(ctx, EXCP_RI);
26132 break;
26133 default:
26134 MIPS_INVAL("decode_opc_mxu");
26135 generate_exception_end(ctx, EXCP_RI);
26136 break;
26141 * Decode MXU pool18
26143 * 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
26144 * +-----------+---------+-----+-------+-------+-------+-----------+
26145 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26146 * +-----------+---------+-----+-------+-------+-------+-----------+
26149 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26151 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26153 switch (opcode) {
26154 case OPC_MXU_D32SLLV:
26155 /* TODO: Implement emulation of D32SLLV instruction. */
26156 MIPS_INVAL("OPC_MXU_D32SLLV");
26157 generate_exception_end(ctx, EXCP_RI);
26158 break;
26159 case OPC_MXU_D32SLRV:
26160 /* TODO: Implement emulation of D32SLRV instruction. */
26161 MIPS_INVAL("OPC_MXU_D32SLRV");
26162 generate_exception_end(ctx, EXCP_RI);
26163 break;
26164 case OPC_MXU_D32SARV:
26165 /* TODO: Implement emulation of D32SARV instruction. */
26166 MIPS_INVAL("OPC_MXU_D32SARV");
26167 generate_exception_end(ctx, EXCP_RI);
26168 break;
26169 case OPC_MXU_Q16SLLV:
26170 /* TODO: Implement emulation of Q16SLLV instruction. */
26171 MIPS_INVAL("OPC_MXU_Q16SLLV");
26172 generate_exception_end(ctx, EXCP_RI);
26173 break;
26174 case OPC_MXU_Q16SLRV:
26175 /* TODO: Implement emulation of Q16SLRV instruction. */
26176 MIPS_INVAL("OPC_MXU_Q16SLRV");
26177 generate_exception_end(ctx, EXCP_RI);
26178 break;
26179 case OPC_MXU_Q16SARV:
26180 /* TODO: Implement emulation of Q16SARV instruction. */
26181 MIPS_INVAL("OPC_MXU_Q16SARV");
26182 generate_exception_end(ctx, EXCP_RI);
26183 break;
26184 default:
26185 MIPS_INVAL("decode_opc_mxu");
26186 generate_exception_end(ctx, EXCP_RI);
26187 break;
26193 * Decode MXU pool19
26195 * 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
26196 * +-----------+---+---+-------+-------+-------+-------+-----------+
26197 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26198 * +-----------+---+---+-------+-------+-------+-------+-----------+
26201 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26203 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26205 switch (opcode) {
26206 case OPC_MXU_Q8MUL:
26207 case OPC_MXU_Q8MULSU:
26208 gen_mxu_q8mul_q8mulsu(ctx);
26209 break;
26210 default:
26211 MIPS_INVAL("decode_opc_mxu");
26212 generate_exception_end(ctx, EXCP_RI);
26213 break;
26219 * Decode MXU pool20
26221 * 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
26222 * +-----------+---------+-----+-------+-------+-------+-----------+
26223 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26224 * +-----------+---------+-----+-------+-------+-------+-----------+
26227 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26229 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26231 switch (opcode) {
26232 case OPC_MXU_Q8MOVZ:
26233 /* TODO: Implement emulation of Q8MOVZ instruction. */
26234 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26235 generate_exception_end(ctx, EXCP_RI);
26236 break;
26237 case OPC_MXU_Q8MOVN:
26238 /* TODO: Implement emulation of Q8MOVN instruction. */
26239 MIPS_INVAL("OPC_MXU_Q8MOVN");
26240 generate_exception_end(ctx, EXCP_RI);
26241 break;
26242 case OPC_MXU_D16MOVZ:
26243 /* TODO: Implement emulation of D16MOVZ instruction. */
26244 MIPS_INVAL("OPC_MXU_D16MOVZ");
26245 generate_exception_end(ctx, EXCP_RI);
26246 break;
26247 case OPC_MXU_D16MOVN:
26248 /* TODO: Implement emulation of D16MOVN instruction. */
26249 MIPS_INVAL("OPC_MXU_D16MOVN");
26250 generate_exception_end(ctx, EXCP_RI);
26251 break;
26252 case OPC_MXU_S32MOVZ:
26253 /* TODO: Implement emulation of S32MOVZ instruction. */
26254 MIPS_INVAL("OPC_MXU_S32MOVZ");
26255 generate_exception_end(ctx, EXCP_RI);
26256 break;
26257 case OPC_MXU_S32MOVN:
26258 /* TODO: Implement emulation of S32MOVN instruction. */
26259 MIPS_INVAL("OPC_MXU_S32MOVN");
26260 generate_exception_end(ctx, EXCP_RI);
26261 break;
26262 default:
26263 MIPS_INVAL("decode_opc_mxu");
26264 generate_exception_end(ctx, EXCP_RI);
26265 break;
26271 * Decode MXU pool21
26273 * 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
26274 * +-----------+---+---+-------+-------+-------+-------+-----------+
26275 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26276 * +-----------+---+---+-------+-------+-------+-------+-----------+
26279 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26281 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26283 switch (opcode) {
26284 case OPC_MXU_Q8MAC:
26285 /* TODO: Implement emulation of Q8MAC instruction. */
26286 MIPS_INVAL("OPC_MXU_Q8MAC");
26287 generate_exception_end(ctx, EXCP_RI);
26288 break;
26289 case OPC_MXU_Q8MACSU:
26290 /* TODO: Implement emulation of Q8MACSU instruction. */
26291 MIPS_INVAL("OPC_MXU_Q8MACSU");
26292 generate_exception_end(ctx, EXCP_RI);
26293 break;
26294 default:
26295 MIPS_INVAL("decode_opc_mxu");
26296 generate_exception_end(ctx, EXCP_RI);
26297 break;
26303 * Main MXU decoding function
26305 * 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
26306 * +-----------+---------------------------------------+-----------+
26307 * | SPECIAL2 | |x x x x x x|
26308 * +-----------+---------------------------------------+-----------+
26311 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26314 * TODO: Investigate necessity of including handling of
26315 * CLZ, CLO, SDBB in this function, as they belong to
26316 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26318 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26320 if (opcode == OPC__MXU_MUL) {
26321 uint32_t rs, rt, rd, op1;
26323 rs = extract32(ctx->opcode, 21, 5);
26324 rt = extract32(ctx->opcode, 16, 5);
26325 rd = extract32(ctx->opcode, 11, 5);
26326 op1 = MASK_SPECIAL2(ctx->opcode);
26328 gen_arith(ctx, op1, rd, rs, rt);
26330 return;
26333 if (opcode == OPC_MXU_S32M2I) {
26334 gen_mxu_s32m2i(ctx);
26335 return;
26338 if (opcode == OPC_MXU_S32I2M) {
26339 gen_mxu_s32i2m(ctx);
26340 return;
26344 TCGv t_mxu_cr = tcg_temp_new();
26345 TCGLabel *l_exit = gen_new_label();
26347 gen_load_mxu_cr(t_mxu_cr);
26348 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26349 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26351 switch (opcode) {
26352 case OPC_MXU_S32MADD:
26353 /* TODO: Implement emulation of S32MADD instruction. */
26354 MIPS_INVAL("OPC_MXU_S32MADD");
26355 generate_exception_end(ctx, EXCP_RI);
26356 break;
26357 case OPC_MXU_S32MADDU:
26358 /* TODO: Implement emulation of S32MADDU instruction. */
26359 MIPS_INVAL("OPC_MXU_S32MADDU");
26360 generate_exception_end(ctx, EXCP_RI);
26361 break;
26362 case OPC_MXU__POOL00:
26363 decode_opc_mxu__pool00(env, ctx);
26364 break;
26365 case OPC_MXU_S32MSUB:
26366 /* TODO: Implement emulation of S32MSUB instruction. */
26367 MIPS_INVAL("OPC_MXU_S32MSUB");
26368 generate_exception_end(ctx, EXCP_RI);
26369 break;
26370 case OPC_MXU_S32MSUBU:
26371 /* TODO: Implement emulation of S32MSUBU instruction. */
26372 MIPS_INVAL("OPC_MXU_S32MSUBU");
26373 generate_exception_end(ctx, EXCP_RI);
26374 break;
26375 case OPC_MXU__POOL01:
26376 decode_opc_mxu__pool01(env, ctx);
26377 break;
26378 case OPC_MXU__POOL02:
26379 decode_opc_mxu__pool02(env, ctx);
26380 break;
26381 case OPC_MXU_D16MUL:
26382 gen_mxu_d16mul(ctx);
26383 break;
26384 case OPC_MXU__POOL03:
26385 decode_opc_mxu__pool03(env, ctx);
26386 break;
26387 case OPC_MXU_D16MAC:
26388 gen_mxu_d16mac(ctx);
26389 break;
26390 case OPC_MXU_D16MACF:
26391 /* TODO: Implement emulation of D16MACF instruction. */
26392 MIPS_INVAL("OPC_MXU_D16MACF");
26393 generate_exception_end(ctx, EXCP_RI);
26394 break;
26395 case OPC_MXU_D16MADL:
26396 /* TODO: Implement emulation of D16MADL instruction. */
26397 MIPS_INVAL("OPC_MXU_D16MADL");
26398 generate_exception_end(ctx, EXCP_RI);
26399 break;
26400 case OPC_MXU_S16MAD:
26401 /* TODO: Implement emulation of S16MAD instruction. */
26402 MIPS_INVAL("OPC_MXU_S16MAD");
26403 generate_exception_end(ctx, EXCP_RI);
26404 break;
26405 case OPC_MXU_Q16ADD:
26406 /* TODO: Implement emulation of Q16ADD instruction. */
26407 MIPS_INVAL("OPC_MXU_Q16ADD");
26408 generate_exception_end(ctx, EXCP_RI);
26409 break;
26410 case OPC_MXU_D16MACE:
26411 /* TODO: Implement emulation of D16MACE instruction. */
26412 MIPS_INVAL("OPC_MXU_D16MACE");
26413 generate_exception_end(ctx, EXCP_RI);
26414 break;
26415 case OPC_MXU__POOL04:
26416 decode_opc_mxu__pool04(env, ctx);
26417 break;
26418 case OPC_MXU__POOL05:
26419 decode_opc_mxu__pool05(env, ctx);
26420 break;
26421 case OPC_MXU__POOL06:
26422 decode_opc_mxu__pool06(env, ctx);
26423 break;
26424 case OPC_MXU__POOL07:
26425 decode_opc_mxu__pool07(env, ctx);
26426 break;
26427 case OPC_MXU__POOL08:
26428 decode_opc_mxu__pool08(env, ctx);
26429 break;
26430 case OPC_MXU__POOL09:
26431 decode_opc_mxu__pool09(env, ctx);
26432 break;
26433 case OPC_MXU__POOL10:
26434 decode_opc_mxu__pool10(env, ctx);
26435 break;
26436 case OPC_MXU__POOL11:
26437 decode_opc_mxu__pool11(env, ctx);
26438 break;
26439 case OPC_MXU_D32ADD:
26440 /* TODO: Implement emulation of D32ADD instruction. */
26441 MIPS_INVAL("OPC_MXU_D32ADD");
26442 generate_exception_end(ctx, EXCP_RI);
26443 break;
26444 case OPC_MXU__POOL12:
26445 decode_opc_mxu__pool12(env, ctx);
26446 break;
26447 case OPC_MXU__POOL13:
26448 decode_opc_mxu__pool13(env, ctx);
26449 break;
26450 case OPC_MXU__POOL14:
26451 decode_opc_mxu__pool14(env, ctx);
26452 break;
26453 case OPC_MXU_Q8ACCE:
26454 /* TODO: Implement emulation of Q8ACCE instruction. */
26455 MIPS_INVAL("OPC_MXU_Q8ACCE");
26456 generate_exception_end(ctx, EXCP_RI);
26457 break;
26458 case OPC_MXU_S8LDD:
26459 gen_mxu_s8ldd(ctx);
26460 break;
26461 case OPC_MXU_S8STD:
26462 /* TODO: Implement emulation of S8STD instruction. */
26463 MIPS_INVAL("OPC_MXU_S8STD");
26464 generate_exception_end(ctx, EXCP_RI);
26465 break;
26466 case OPC_MXU_S8LDI:
26467 /* TODO: Implement emulation of S8LDI instruction. */
26468 MIPS_INVAL("OPC_MXU_S8LDI");
26469 generate_exception_end(ctx, EXCP_RI);
26470 break;
26471 case OPC_MXU_S8SDI:
26472 /* TODO: Implement emulation of S8SDI instruction. */
26473 MIPS_INVAL("OPC_MXU_S8SDI");
26474 generate_exception_end(ctx, EXCP_RI);
26475 break;
26476 case OPC_MXU__POOL15:
26477 decode_opc_mxu__pool15(env, ctx);
26478 break;
26479 case OPC_MXU__POOL16:
26480 decode_opc_mxu__pool16(env, ctx);
26481 break;
26482 case OPC_MXU__POOL17:
26483 decode_opc_mxu__pool17(env, ctx);
26484 break;
26485 case OPC_MXU_S16LDD:
26486 /* TODO: Implement emulation of S16LDD instruction. */
26487 MIPS_INVAL("OPC_MXU_S16LDD");
26488 generate_exception_end(ctx, EXCP_RI);
26489 break;
26490 case OPC_MXU_S16STD:
26491 /* TODO: Implement emulation of S16STD instruction. */
26492 MIPS_INVAL("OPC_MXU_S16STD");
26493 generate_exception_end(ctx, EXCP_RI);
26494 break;
26495 case OPC_MXU_S16LDI:
26496 /* TODO: Implement emulation of S16LDI instruction. */
26497 MIPS_INVAL("OPC_MXU_S16LDI");
26498 generate_exception_end(ctx, EXCP_RI);
26499 break;
26500 case OPC_MXU_S16SDI:
26501 /* TODO: Implement emulation of S16SDI instruction. */
26502 MIPS_INVAL("OPC_MXU_S16SDI");
26503 generate_exception_end(ctx, EXCP_RI);
26504 break;
26505 case OPC_MXU_D32SLL:
26506 /* TODO: Implement emulation of D32SLL instruction. */
26507 MIPS_INVAL("OPC_MXU_D32SLL");
26508 generate_exception_end(ctx, EXCP_RI);
26509 break;
26510 case OPC_MXU_D32SLR:
26511 /* TODO: Implement emulation of D32SLR instruction. */
26512 MIPS_INVAL("OPC_MXU_D32SLR");
26513 generate_exception_end(ctx, EXCP_RI);
26514 break;
26515 case OPC_MXU_D32SARL:
26516 /* TODO: Implement emulation of D32SARL instruction. */
26517 MIPS_INVAL("OPC_MXU_D32SARL");
26518 generate_exception_end(ctx, EXCP_RI);
26519 break;
26520 case OPC_MXU_D32SAR:
26521 /* TODO: Implement emulation of D32SAR instruction. */
26522 MIPS_INVAL("OPC_MXU_D32SAR");
26523 generate_exception_end(ctx, EXCP_RI);
26524 break;
26525 case OPC_MXU_Q16SLL:
26526 /* TODO: Implement emulation of Q16SLL instruction. */
26527 MIPS_INVAL("OPC_MXU_Q16SLL");
26528 generate_exception_end(ctx, EXCP_RI);
26529 break;
26530 case OPC_MXU_Q16SLR:
26531 /* TODO: Implement emulation of Q16SLR instruction. */
26532 MIPS_INVAL("OPC_MXU_Q16SLR");
26533 generate_exception_end(ctx, EXCP_RI);
26534 break;
26535 case OPC_MXU__POOL18:
26536 decode_opc_mxu__pool18(env, ctx);
26537 break;
26538 case OPC_MXU_Q16SAR:
26539 /* TODO: Implement emulation of Q16SAR instruction. */
26540 MIPS_INVAL("OPC_MXU_Q16SAR");
26541 generate_exception_end(ctx, EXCP_RI);
26542 break;
26543 case OPC_MXU__POOL19:
26544 decode_opc_mxu__pool19(env, ctx);
26545 break;
26546 case OPC_MXU__POOL20:
26547 decode_opc_mxu__pool20(env, ctx);
26548 break;
26549 case OPC_MXU__POOL21:
26550 decode_opc_mxu__pool21(env, ctx);
26551 break;
26552 case OPC_MXU_Q16SCOP:
26553 /* TODO: Implement emulation of Q16SCOP instruction. */
26554 MIPS_INVAL("OPC_MXU_Q16SCOP");
26555 generate_exception_end(ctx, EXCP_RI);
26556 break;
26557 case OPC_MXU_Q8MADL:
26558 /* TODO: Implement emulation of Q8MADL instruction. */
26559 MIPS_INVAL("OPC_MXU_Q8MADL");
26560 generate_exception_end(ctx, EXCP_RI);
26561 break;
26562 case OPC_MXU_S32SFL:
26563 /* TODO: Implement emulation of S32SFL instruction. */
26564 MIPS_INVAL("OPC_MXU_S32SFL");
26565 generate_exception_end(ctx, EXCP_RI);
26566 break;
26567 case OPC_MXU_Q8SAD:
26568 /* TODO: Implement emulation of Q8SAD instruction. */
26569 MIPS_INVAL("OPC_MXU_Q8SAD");
26570 generate_exception_end(ctx, EXCP_RI);
26571 break;
26572 default:
26573 MIPS_INVAL("decode_opc_mxu");
26574 generate_exception_end(ctx, EXCP_RI);
26577 gen_set_label(l_exit);
26578 tcg_temp_free(t_mxu_cr);
26582 #endif /* !defined(TARGET_MIPS64) */
26585 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26587 int rs, rt, rd;
26588 uint32_t op1;
26590 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26592 rs = (ctx->opcode >> 21) & 0x1f;
26593 rt = (ctx->opcode >> 16) & 0x1f;
26594 rd = (ctx->opcode >> 11) & 0x1f;
26596 op1 = MASK_SPECIAL2(ctx->opcode);
26597 switch (op1) {
26598 case OPC_MADD: /* Multiply and add/sub */
26599 case OPC_MADDU:
26600 case OPC_MSUB:
26601 case OPC_MSUBU:
26602 check_insn(ctx, ISA_MIPS32);
26603 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26604 break;
26605 case OPC_MUL:
26606 gen_arith(ctx, op1, rd, rs, rt);
26607 break;
26608 case OPC_DIV_G_2F:
26609 case OPC_DIVU_G_2F:
26610 case OPC_MULT_G_2F:
26611 case OPC_MULTU_G_2F:
26612 case OPC_MOD_G_2F:
26613 case OPC_MODU_G_2F:
26614 check_insn(ctx, INSN_LOONGSON2F);
26615 gen_loongson_integer(ctx, op1, rd, rs, rt);
26616 break;
26617 case OPC_CLO:
26618 case OPC_CLZ:
26619 check_insn(ctx, ISA_MIPS32);
26620 gen_cl(ctx, op1, rd, rs);
26621 break;
26622 case OPC_SDBBP:
26623 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26624 gen_helper_do_semihosting(cpu_env);
26625 } else {
26626 /* XXX: not clear which exception should be raised
26627 * when in debug mode...
26629 check_insn(ctx, ISA_MIPS32);
26630 generate_exception_end(ctx, EXCP_DBp);
26632 break;
26633 #if defined(TARGET_MIPS64)
26634 case OPC_DCLO:
26635 case OPC_DCLZ:
26636 check_insn(ctx, ISA_MIPS64);
26637 check_mips_64(ctx);
26638 gen_cl(ctx, op1, rd, rs);
26639 break;
26640 case OPC_DMULT_G_2F:
26641 case OPC_DMULTU_G_2F:
26642 case OPC_DDIV_G_2F:
26643 case OPC_DDIVU_G_2F:
26644 case OPC_DMOD_G_2F:
26645 case OPC_DMODU_G_2F:
26646 check_insn(ctx, INSN_LOONGSON2F);
26647 gen_loongson_integer(ctx, op1, rd, rs, rt);
26648 break;
26649 #endif
26650 default: /* Invalid */
26651 MIPS_INVAL("special2_legacy");
26652 generate_exception_end(ctx, EXCP_RI);
26653 break;
26657 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26659 int rs, rt, rd, sa;
26660 uint32_t op1, op2;
26661 int16_t imm;
26663 rs = (ctx->opcode >> 21) & 0x1f;
26664 rt = (ctx->opcode >> 16) & 0x1f;
26665 rd = (ctx->opcode >> 11) & 0x1f;
26666 sa = (ctx->opcode >> 6) & 0x1f;
26667 imm = (int16_t)ctx->opcode >> 7;
26669 op1 = MASK_SPECIAL3(ctx->opcode);
26670 switch (op1) {
26671 case R6_OPC_PREF:
26672 if (rt >= 24) {
26673 /* hint codes 24-31 are reserved and signal RI */
26674 generate_exception_end(ctx, EXCP_RI);
26676 /* Treat as NOP. */
26677 break;
26678 case R6_OPC_CACHE:
26679 check_cp0_enabled(ctx);
26680 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26681 gen_cache_operation(ctx, rt, rs, imm);
26683 break;
26684 case R6_OPC_SC:
26685 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
26686 break;
26687 case R6_OPC_LL:
26688 gen_ld(ctx, op1, rt, rs, imm);
26689 break;
26690 case OPC_BSHFL:
26692 if (rd == 0) {
26693 /* Treat as NOP. */
26694 break;
26696 op2 = MASK_BSHFL(ctx->opcode);
26697 switch (op2) {
26698 case OPC_ALIGN:
26699 case OPC_ALIGN_1:
26700 case OPC_ALIGN_2:
26701 case OPC_ALIGN_3:
26702 gen_align(ctx, 32, rd, rs, rt, sa & 3);
26703 break;
26704 case OPC_BITSWAP:
26705 gen_bitswap(ctx, op2, rd, rt);
26706 break;
26709 break;
26710 #if defined(TARGET_MIPS64)
26711 case R6_OPC_SCD:
26712 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
26713 break;
26714 case R6_OPC_LLD:
26715 gen_ld(ctx, op1, rt, rs, imm);
26716 break;
26717 case OPC_DBSHFL:
26718 check_mips_64(ctx);
26720 if (rd == 0) {
26721 /* Treat as NOP. */
26722 break;
26724 op2 = MASK_DBSHFL(ctx->opcode);
26725 switch (op2) {
26726 case OPC_DALIGN:
26727 case OPC_DALIGN_1:
26728 case OPC_DALIGN_2:
26729 case OPC_DALIGN_3:
26730 case OPC_DALIGN_4:
26731 case OPC_DALIGN_5:
26732 case OPC_DALIGN_6:
26733 case OPC_DALIGN_7:
26734 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26735 break;
26736 case OPC_DBITSWAP:
26737 gen_bitswap(ctx, op2, rd, rt);
26738 break;
26742 break;
26743 #endif
26744 default: /* Invalid */
26745 MIPS_INVAL("special3_r6");
26746 generate_exception_end(ctx, EXCP_RI);
26747 break;
26751 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26753 int rs, rt, rd;
26754 uint32_t op1, op2;
26756 rs = (ctx->opcode >> 21) & 0x1f;
26757 rt = (ctx->opcode >> 16) & 0x1f;
26758 rd = (ctx->opcode >> 11) & 0x1f;
26760 op1 = MASK_SPECIAL3(ctx->opcode);
26761 switch (op1) {
26762 case OPC_DIV_G_2E:
26763 case OPC_DIVU_G_2E:
26764 case OPC_MOD_G_2E:
26765 case OPC_MODU_G_2E:
26766 case OPC_MULT_G_2E:
26767 case OPC_MULTU_G_2E:
26768 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26769 * the same mask and op1. */
26770 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26771 op2 = MASK_ADDUH_QB(ctx->opcode);
26772 switch (op2) {
26773 case OPC_ADDUH_QB:
26774 case OPC_ADDUH_R_QB:
26775 case OPC_ADDQH_PH:
26776 case OPC_ADDQH_R_PH:
26777 case OPC_ADDQH_W:
26778 case OPC_ADDQH_R_W:
26779 case OPC_SUBUH_QB:
26780 case OPC_SUBUH_R_QB:
26781 case OPC_SUBQH_PH:
26782 case OPC_SUBQH_R_PH:
26783 case OPC_SUBQH_W:
26784 case OPC_SUBQH_R_W:
26785 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26786 break;
26787 case OPC_MUL_PH:
26788 case OPC_MUL_S_PH:
26789 case OPC_MULQ_S_W:
26790 case OPC_MULQ_RS_W:
26791 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26792 break;
26793 default:
26794 MIPS_INVAL("MASK ADDUH.QB");
26795 generate_exception_end(ctx, EXCP_RI);
26796 break;
26798 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26799 gen_loongson_integer(ctx, op1, rd, rs, rt);
26800 } else {
26801 generate_exception_end(ctx, EXCP_RI);
26803 break;
26804 case OPC_LX_DSP:
26805 op2 = MASK_LX(ctx->opcode);
26806 switch (op2) {
26807 #if defined(TARGET_MIPS64)
26808 case OPC_LDX:
26809 #endif
26810 case OPC_LBUX:
26811 case OPC_LHX:
26812 case OPC_LWX:
26813 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26814 break;
26815 default: /* Invalid */
26816 MIPS_INVAL("MASK LX");
26817 generate_exception_end(ctx, EXCP_RI);
26818 break;
26820 break;
26821 case OPC_ABSQ_S_PH_DSP:
26822 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26823 switch (op2) {
26824 case OPC_ABSQ_S_QB:
26825 case OPC_ABSQ_S_PH:
26826 case OPC_ABSQ_S_W:
26827 case OPC_PRECEQ_W_PHL:
26828 case OPC_PRECEQ_W_PHR:
26829 case OPC_PRECEQU_PH_QBL:
26830 case OPC_PRECEQU_PH_QBR:
26831 case OPC_PRECEQU_PH_QBLA:
26832 case OPC_PRECEQU_PH_QBRA:
26833 case OPC_PRECEU_PH_QBL:
26834 case OPC_PRECEU_PH_QBR:
26835 case OPC_PRECEU_PH_QBLA:
26836 case OPC_PRECEU_PH_QBRA:
26837 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26838 break;
26839 case OPC_BITREV:
26840 case OPC_REPL_QB:
26841 case OPC_REPLV_QB:
26842 case OPC_REPL_PH:
26843 case OPC_REPLV_PH:
26844 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26845 break;
26846 default:
26847 MIPS_INVAL("MASK ABSQ_S.PH");
26848 generate_exception_end(ctx, EXCP_RI);
26849 break;
26851 break;
26852 case OPC_ADDU_QB_DSP:
26853 op2 = MASK_ADDU_QB(ctx->opcode);
26854 switch (op2) {
26855 case OPC_ADDQ_PH:
26856 case OPC_ADDQ_S_PH:
26857 case OPC_ADDQ_S_W:
26858 case OPC_ADDU_QB:
26859 case OPC_ADDU_S_QB:
26860 case OPC_ADDU_PH:
26861 case OPC_ADDU_S_PH:
26862 case OPC_SUBQ_PH:
26863 case OPC_SUBQ_S_PH:
26864 case OPC_SUBQ_S_W:
26865 case OPC_SUBU_QB:
26866 case OPC_SUBU_S_QB:
26867 case OPC_SUBU_PH:
26868 case OPC_SUBU_S_PH:
26869 case OPC_ADDSC:
26870 case OPC_ADDWC:
26871 case OPC_MODSUB:
26872 case OPC_RADDU_W_QB:
26873 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26874 break;
26875 case OPC_MULEU_S_PH_QBL:
26876 case OPC_MULEU_S_PH_QBR:
26877 case OPC_MULQ_RS_PH:
26878 case OPC_MULEQ_S_W_PHL:
26879 case OPC_MULEQ_S_W_PHR:
26880 case OPC_MULQ_S_PH:
26881 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26882 break;
26883 default: /* Invalid */
26884 MIPS_INVAL("MASK ADDU.QB");
26885 generate_exception_end(ctx, EXCP_RI);
26886 break;
26889 break;
26890 case OPC_CMPU_EQ_QB_DSP:
26891 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26892 switch (op2) {
26893 case OPC_PRECR_SRA_PH_W:
26894 case OPC_PRECR_SRA_R_PH_W:
26895 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26896 break;
26897 case OPC_PRECR_QB_PH:
26898 case OPC_PRECRQ_QB_PH:
26899 case OPC_PRECRQ_PH_W:
26900 case OPC_PRECRQ_RS_PH_W:
26901 case OPC_PRECRQU_S_QB_PH:
26902 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26903 break;
26904 case OPC_CMPU_EQ_QB:
26905 case OPC_CMPU_LT_QB:
26906 case OPC_CMPU_LE_QB:
26907 case OPC_CMP_EQ_PH:
26908 case OPC_CMP_LT_PH:
26909 case OPC_CMP_LE_PH:
26910 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26911 break;
26912 case OPC_CMPGU_EQ_QB:
26913 case OPC_CMPGU_LT_QB:
26914 case OPC_CMPGU_LE_QB:
26915 case OPC_CMPGDU_EQ_QB:
26916 case OPC_CMPGDU_LT_QB:
26917 case OPC_CMPGDU_LE_QB:
26918 case OPC_PICK_QB:
26919 case OPC_PICK_PH:
26920 case OPC_PACKRL_PH:
26921 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26922 break;
26923 default: /* Invalid */
26924 MIPS_INVAL("MASK CMPU.EQ.QB");
26925 generate_exception_end(ctx, EXCP_RI);
26926 break;
26928 break;
26929 case OPC_SHLL_QB_DSP:
26930 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26931 break;
26932 case OPC_DPA_W_PH_DSP:
26933 op2 = MASK_DPA_W_PH(ctx->opcode);
26934 switch (op2) {
26935 case OPC_DPAU_H_QBL:
26936 case OPC_DPAU_H_QBR:
26937 case OPC_DPSU_H_QBL:
26938 case OPC_DPSU_H_QBR:
26939 case OPC_DPA_W_PH:
26940 case OPC_DPAX_W_PH:
26941 case OPC_DPAQ_S_W_PH:
26942 case OPC_DPAQX_S_W_PH:
26943 case OPC_DPAQX_SA_W_PH:
26944 case OPC_DPS_W_PH:
26945 case OPC_DPSX_W_PH:
26946 case OPC_DPSQ_S_W_PH:
26947 case OPC_DPSQX_S_W_PH:
26948 case OPC_DPSQX_SA_W_PH:
26949 case OPC_MULSAQ_S_W_PH:
26950 case OPC_DPAQ_SA_L_W:
26951 case OPC_DPSQ_SA_L_W:
26952 case OPC_MAQ_S_W_PHL:
26953 case OPC_MAQ_S_W_PHR:
26954 case OPC_MAQ_SA_W_PHL:
26955 case OPC_MAQ_SA_W_PHR:
26956 case OPC_MULSA_W_PH:
26957 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26958 break;
26959 default: /* Invalid */
26960 MIPS_INVAL("MASK DPAW.PH");
26961 generate_exception_end(ctx, EXCP_RI);
26962 break;
26964 break;
26965 case OPC_INSV_DSP:
26966 op2 = MASK_INSV(ctx->opcode);
26967 switch (op2) {
26968 case OPC_INSV:
26969 check_dsp(ctx);
26971 TCGv t0, t1;
26973 if (rt == 0) {
26974 break;
26977 t0 = tcg_temp_new();
26978 t1 = tcg_temp_new();
26980 gen_load_gpr(t0, rt);
26981 gen_load_gpr(t1, rs);
26983 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
26985 tcg_temp_free(t0);
26986 tcg_temp_free(t1);
26987 break;
26989 default: /* Invalid */
26990 MIPS_INVAL("MASK INSV");
26991 generate_exception_end(ctx, EXCP_RI);
26992 break;
26994 break;
26995 case OPC_APPEND_DSP:
26996 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26997 break;
26998 case OPC_EXTR_W_DSP:
26999 op2 = MASK_EXTR_W(ctx->opcode);
27000 switch (op2) {
27001 case OPC_EXTR_W:
27002 case OPC_EXTR_R_W:
27003 case OPC_EXTR_RS_W:
27004 case OPC_EXTR_S_H:
27005 case OPC_EXTRV_S_H:
27006 case OPC_EXTRV_W:
27007 case OPC_EXTRV_R_W:
27008 case OPC_EXTRV_RS_W:
27009 case OPC_EXTP:
27010 case OPC_EXTPV:
27011 case OPC_EXTPDP:
27012 case OPC_EXTPDPV:
27013 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27014 break;
27015 case OPC_RDDSP:
27016 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27017 break;
27018 case OPC_SHILO:
27019 case OPC_SHILOV:
27020 case OPC_MTHLIP:
27021 case OPC_WRDSP:
27022 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27023 break;
27024 default: /* Invalid */
27025 MIPS_INVAL("MASK EXTR.W");
27026 generate_exception_end(ctx, EXCP_RI);
27027 break;
27029 break;
27030 #if defined(TARGET_MIPS64)
27031 case OPC_DDIV_G_2E:
27032 case OPC_DDIVU_G_2E:
27033 case OPC_DMULT_G_2E:
27034 case OPC_DMULTU_G_2E:
27035 case OPC_DMOD_G_2E:
27036 case OPC_DMODU_G_2E:
27037 check_insn(ctx, INSN_LOONGSON2E);
27038 gen_loongson_integer(ctx, op1, rd, rs, rt);
27039 break;
27040 case OPC_ABSQ_S_QH_DSP:
27041 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27042 switch (op2) {
27043 case OPC_PRECEQ_L_PWL:
27044 case OPC_PRECEQ_L_PWR:
27045 case OPC_PRECEQ_PW_QHL:
27046 case OPC_PRECEQ_PW_QHR:
27047 case OPC_PRECEQ_PW_QHLA:
27048 case OPC_PRECEQ_PW_QHRA:
27049 case OPC_PRECEQU_QH_OBL:
27050 case OPC_PRECEQU_QH_OBR:
27051 case OPC_PRECEQU_QH_OBLA:
27052 case OPC_PRECEQU_QH_OBRA:
27053 case OPC_PRECEU_QH_OBL:
27054 case OPC_PRECEU_QH_OBR:
27055 case OPC_PRECEU_QH_OBLA:
27056 case OPC_PRECEU_QH_OBRA:
27057 case OPC_ABSQ_S_OB:
27058 case OPC_ABSQ_S_PW:
27059 case OPC_ABSQ_S_QH:
27060 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27061 break;
27062 case OPC_REPL_OB:
27063 case OPC_REPL_PW:
27064 case OPC_REPL_QH:
27065 case OPC_REPLV_OB:
27066 case OPC_REPLV_PW:
27067 case OPC_REPLV_QH:
27068 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27069 break;
27070 default: /* Invalid */
27071 MIPS_INVAL("MASK ABSQ_S.QH");
27072 generate_exception_end(ctx, EXCP_RI);
27073 break;
27075 break;
27076 case OPC_ADDU_OB_DSP:
27077 op2 = MASK_ADDU_OB(ctx->opcode);
27078 switch (op2) {
27079 case OPC_RADDU_L_OB:
27080 case OPC_SUBQ_PW:
27081 case OPC_SUBQ_S_PW:
27082 case OPC_SUBQ_QH:
27083 case OPC_SUBQ_S_QH:
27084 case OPC_SUBU_OB:
27085 case OPC_SUBU_S_OB:
27086 case OPC_SUBU_QH:
27087 case OPC_SUBU_S_QH:
27088 case OPC_SUBUH_OB:
27089 case OPC_SUBUH_R_OB:
27090 case OPC_ADDQ_PW:
27091 case OPC_ADDQ_S_PW:
27092 case OPC_ADDQ_QH:
27093 case OPC_ADDQ_S_QH:
27094 case OPC_ADDU_OB:
27095 case OPC_ADDU_S_OB:
27096 case OPC_ADDU_QH:
27097 case OPC_ADDU_S_QH:
27098 case OPC_ADDUH_OB:
27099 case OPC_ADDUH_R_OB:
27100 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27101 break;
27102 case OPC_MULEQ_S_PW_QHL:
27103 case OPC_MULEQ_S_PW_QHR:
27104 case OPC_MULEU_S_QH_OBL:
27105 case OPC_MULEU_S_QH_OBR:
27106 case OPC_MULQ_RS_QH:
27107 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27108 break;
27109 default: /* Invalid */
27110 MIPS_INVAL("MASK ADDU.OB");
27111 generate_exception_end(ctx, EXCP_RI);
27112 break;
27114 break;
27115 case OPC_CMPU_EQ_OB_DSP:
27116 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27117 switch (op2) {
27118 case OPC_PRECR_SRA_QH_PW:
27119 case OPC_PRECR_SRA_R_QH_PW:
27120 /* Return value is rt. */
27121 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27122 break;
27123 case OPC_PRECR_OB_QH:
27124 case OPC_PRECRQ_OB_QH:
27125 case OPC_PRECRQ_PW_L:
27126 case OPC_PRECRQ_QH_PW:
27127 case OPC_PRECRQ_RS_QH_PW:
27128 case OPC_PRECRQU_S_OB_QH:
27129 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27130 break;
27131 case OPC_CMPU_EQ_OB:
27132 case OPC_CMPU_LT_OB:
27133 case OPC_CMPU_LE_OB:
27134 case OPC_CMP_EQ_QH:
27135 case OPC_CMP_LT_QH:
27136 case OPC_CMP_LE_QH:
27137 case OPC_CMP_EQ_PW:
27138 case OPC_CMP_LT_PW:
27139 case OPC_CMP_LE_PW:
27140 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27141 break;
27142 case OPC_CMPGDU_EQ_OB:
27143 case OPC_CMPGDU_LT_OB:
27144 case OPC_CMPGDU_LE_OB:
27145 case OPC_CMPGU_EQ_OB:
27146 case OPC_CMPGU_LT_OB:
27147 case OPC_CMPGU_LE_OB:
27148 case OPC_PACKRL_PW:
27149 case OPC_PICK_OB:
27150 case OPC_PICK_PW:
27151 case OPC_PICK_QH:
27152 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27153 break;
27154 default: /* Invalid */
27155 MIPS_INVAL("MASK CMPU_EQ.OB");
27156 generate_exception_end(ctx, EXCP_RI);
27157 break;
27159 break;
27160 case OPC_DAPPEND_DSP:
27161 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27162 break;
27163 case OPC_DEXTR_W_DSP:
27164 op2 = MASK_DEXTR_W(ctx->opcode);
27165 switch (op2) {
27166 case OPC_DEXTP:
27167 case OPC_DEXTPDP:
27168 case OPC_DEXTPDPV:
27169 case OPC_DEXTPV:
27170 case OPC_DEXTR_L:
27171 case OPC_DEXTR_R_L:
27172 case OPC_DEXTR_RS_L:
27173 case OPC_DEXTR_W:
27174 case OPC_DEXTR_R_W:
27175 case OPC_DEXTR_RS_W:
27176 case OPC_DEXTR_S_H:
27177 case OPC_DEXTRV_L:
27178 case OPC_DEXTRV_R_L:
27179 case OPC_DEXTRV_RS_L:
27180 case OPC_DEXTRV_S_H:
27181 case OPC_DEXTRV_W:
27182 case OPC_DEXTRV_R_W:
27183 case OPC_DEXTRV_RS_W:
27184 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27185 break;
27186 case OPC_DMTHLIP:
27187 case OPC_DSHILO:
27188 case OPC_DSHILOV:
27189 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27190 break;
27191 default: /* Invalid */
27192 MIPS_INVAL("MASK EXTR.W");
27193 generate_exception_end(ctx, EXCP_RI);
27194 break;
27196 break;
27197 case OPC_DPAQ_W_QH_DSP:
27198 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27199 switch (op2) {
27200 case OPC_DPAU_H_OBL:
27201 case OPC_DPAU_H_OBR:
27202 case OPC_DPSU_H_OBL:
27203 case OPC_DPSU_H_OBR:
27204 case OPC_DPA_W_QH:
27205 case OPC_DPAQ_S_W_QH:
27206 case OPC_DPS_W_QH:
27207 case OPC_DPSQ_S_W_QH:
27208 case OPC_MULSAQ_S_W_QH:
27209 case OPC_DPAQ_SA_L_PW:
27210 case OPC_DPSQ_SA_L_PW:
27211 case OPC_MULSAQ_S_L_PW:
27212 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27213 break;
27214 case OPC_MAQ_S_W_QHLL:
27215 case OPC_MAQ_S_W_QHLR:
27216 case OPC_MAQ_S_W_QHRL:
27217 case OPC_MAQ_S_W_QHRR:
27218 case OPC_MAQ_SA_W_QHLL:
27219 case OPC_MAQ_SA_W_QHLR:
27220 case OPC_MAQ_SA_W_QHRL:
27221 case OPC_MAQ_SA_W_QHRR:
27222 case OPC_MAQ_S_L_PWL:
27223 case OPC_MAQ_S_L_PWR:
27224 case OPC_DMADD:
27225 case OPC_DMADDU:
27226 case OPC_DMSUB:
27227 case OPC_DMSUBU:
27228 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27229 break;
27230 default: /* Invalid */
27231 MIPS_INVAL("MASK DPAQ.W.QH");
27232 generate_exception_end(ctx, EXCP_RI);
27233 break;
27235 break;
27236 case OPC_DINSV_DSP:
27237 op2 = MASK_INSV(ctx->opcode);
27238 switch (op2) {
27239 case OPC_DINSV:
27241 TCGv t0, t1;
27243 if (rt == 0) {
27244 break;
27246 check_dsp(ctx);
27248 t0 = tcg_temp_new();
27249 t1 = tcg_temp_new();
27251 gen_load_gpr(t0, rt);
27252 gen_load_gpr(t1, rs);
27254 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27256 tcg_temp_free(t0);
27257 tcg_temp_free(t1);
27258 break;
27260 default: /* Invalid */
27261 MIPS_INVAL("MASK DINSV");
27262 generate_exception_end(ctx, EXCP_RI);
27263 break;
27265 break;
27266 case OPC_SHLL_OB_DSP:
27267 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27268 break;
27269 #endif
27270 default: /* Invalid */
27271 MIPS_INVAL("special3_legacy");
27272 generate_exception_end(ctx, EXCP_RI);
27273 break;
27278 #if defined(TARGET_MIPS64)
27280 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27282 uint32_t opc = MASK_MMI0(ctx->opcode);
27284 switch (opc) {
27285 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27286 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27287 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27288 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27289 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27290 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27291 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27292 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27293 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27294 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27295 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27296 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27297 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27298 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27299 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27300 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27301 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27302 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27303 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27304 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27305 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27306 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27307 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27308 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27309 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27310 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27311 break;
27312 default:
27313 MIPS_INVAL("TX79 MMI class MMI0");
27314 generate_exception_end(ctx, EXCP_RI);
27315 break;
27319 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27321 uint32_t opc = MASK_MMI1(ctx->opcode);
27323 switch (opc) {
27324 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27325 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27326 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27327 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27328 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27329 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27330 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27331 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27332 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27333 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27334 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27335 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27336 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27337 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27338 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27339 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27340 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27341 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27342 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27343 break;
27344 default:
27345 MIPS_INVAL("TX79 MMI class MMI1");
27346 generate_exception_end(ctx, EXCP_RI);
27347 break;
27351 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27353 uint32_t opc = MASK_MMI2(ctx->opcode);
27355 switch (opc) {
27356 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27357 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27358 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27359 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27360 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27361 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27362 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27363 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27364 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27365 case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */
27366 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27367 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27368 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27369 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27370 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27371 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27372 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27373 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27374 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27375 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27376 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27377 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27378 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27379 break;
27380 default:
27381 MIPS_INVAL("TX79 MMI class MMI2");
27382 generate_exception_end(ctx, EXCP_RI);
27383 break;
27387 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27389 uint32_t opc = MASK_MMI3(ctx->opcode);
27391 switch (opc) {
27392 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27393 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27394 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27395 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27396 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27397 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27398 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27399 case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */
27400 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27401 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27402 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27403 case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */
27404 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27405 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27406 break;
27407 default:
27408 MIPS_INVAL("TX79 MMI class MMI3");
27409 generate_exception_end(ctx, EXCP_RI);
27410 break;
27414 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27416 uint32_t opc = MASK_MMI(ctx->opcode);
27417 int rs = extract32(ctx->opcode, 21, 5);
27418 int rt = extract32(ctx->opcode, 16, 5);
27419 int rd = extract32(ctx->opcode, 11, 5);
27421 switch (opc) {
27422 case MMI_OPC_CLASS_MMI0:
27423 decode_mmi0(env, ctx);
27424 break;
27425 case MMI_OPC_CLASS_MMI1:
27426 decode_mmi1(env, ctx);
27427 break;
27428 case MMI_OPC_CLASS_MMI2:
27429 decode_mmi2(env, ctx);
27430 break;
27431 case MMI_OPC_CLASS_MMI3:
27432 decode_mmi3(env, ctx);
27433 break;
27434 case MMI_OPC_MULT1:
27435 case MMI_OPC_MULTU1:
27436 case MMI_OPC_MADD:
27437 case MMI_OPC_MADDU:
27438 case MMI_OPC_MADD1:
27439 case MMI_OPC_MADDU1:
27440 gen_mul_txx9(ctx, opc, rd, rs, rt);
27441 break;
27442 case MMI_OPC_DIV1:
27443 case MMI_OPC_DIVU1:
27444 gen_div1_tx79(ctx, opc, rs, rt);
27445 break;
27446 case MMI_OPC_MTLO1:
27447 case MMI_OPC_MTHI1:
27448 gen_HILO1_tx79(ctx, opc, rs);
27449 break;
27450 case MMI_OPC_MFLO1:
27451 case MMI_OPC_MFHI1:
27452 gen_HILO1_tx79(ctx, opc, rd);
27453 break;
27454 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27455 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27456 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27457 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27458 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27459 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27460 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27461 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27462 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27463 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27464 break;
27465 default:
27466 MIPS_INVAL("TX79 MMI class");
27467 generate_exception_end(ctx, EXCP_RI);
27468 break;
27472 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27474 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27477 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27479 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27483 * The TX79-specific instruction Store Quadword
27485 * +--------+-------+-------+------------------------+
27486 * | 011111 | base | rt | offset | SQ
27487 * +--------+-------+-------+------------------------+
27488 * 6 5 5 16
27490 * has the same opcode as the Read Hardware Register instruction
27492 * +--------+-------+-------+-------+-------+--------+
27493 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27494 * +--------+-------+-------+-------+-------+--------+
27495 * 6 5 5 5 5 6
27497 * that is required, trapped and emulated by the Linux kernel. However, all
27498 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27499 * offset is odd. Therefore all valid SQ instructions can execute normally.
27500 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27501 * between SQ and RDHWR, as the Linux kernel does.
27503 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27505 int base = extract32(ctx->opcode, 21, 5);
27506 int rt = extract32(ctx->opcode, 16, 5);
27507 int offset = extract32(ctx->opcode, 0, 16);
27509 #ifdef CONFIG_USER_ONLY
27510 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27511 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27513 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27514 int rd = extract32(ctx->opcode, 11, 5);
27516 gen_rdhwr(ctx, rt, rd, 0);
27517 return;
27519 #endif
27521 gen_mmi_sq(ctx, base, rt, offset);
27524 #endif
27526 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27528 int rs, rt, rd, sa;
27529 uint32_t op1, op2;
27530 int16_t imm;
27532 rs = (ctx->opcode >> 21) & 0x1f;
27533 rt = (ctx->opcode >> 16) & 0x1f;
27534 rd = (ctx->opcode >> 11) & 0x1f;
27535 sa = (ctx->opcode >> 6) & 0x1f;
27536 imm = sextract32(ctx->opcode, 7, 9);
27538 op1 = MASK_SPECIAL3(ctx->opcode);
27541 * EVA loads and stores overlap Loongson 2E instructions decoded by
27542 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27543 * EVA is absent.
27545 if (ctx->eva) {
27546 switch (op1) {
27547 case OPC_LWLE:
27548 case OPC_LWRE:
27549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27550 /* fall through */
27551 case OPC_LBUE:
27552 case OPC_LHUE:
27553 case OPC_LBE:
27554 case OPC_LHE:
27555 case OPC_LLE:
27556 case OPC_LWE:
27557 check_cp0_enabled(ctx);
27558 gen_ld(ctx, op1, rt, rs, imm);
27559 return;
27560 case OPC_SWLE:
27561 case OPC_SWRE:
27562 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27563 /* fall through */
27564 case OPC_SBE:
27565 case OPC_SHE:
27566 case OPC_SWE:
27567 check_cp0_enabled(ctx);
27568 gen_st(ctx, op1, rt, rs, imm);
27569 return;
27570 case OPC_SCE:
27571 check_cp0_enabled(ctx);
27572 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
27573 return;
27574 case OPC_CACHEE:
27575 check_cp0_enabled(ctx);
27576 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27577 gen_cache_operation(ctx, rt, rs, imm);
27579 /* Treat as NOP. */
27580 return;
27581 case OPC_PREFE:
27582 check_cp0_enabled(ctx);
27583 /* Treat as NOP. */
27584 return;
27588 switch (op1) {
27589 case OPC_EXT:
27590 case OPC_INS:
27591 check_insn(ctx, ISA_MIPS32R2);
27592 gen_bitops(ctx, op1, rt, rs, sa, rd);
27593 break;
27594 case OPC_BSHFL:
27595 op2 = MASK_BSHFL(ctx->opcode);
27596 switch (op2) {
27597 case OPC_ALIGN:
27598 case OPC_ALIGN_1:
27599 case OPC_ALIGN_2:
27600 case OPC_ALIGN_3:
27601 case OPC_BITSWAP:
27602 check_insn(ctx, ISA_MIPS32R6);
27603 decode_opc_special3_r6(env, ctx);
27604 break;
27605 default:
27606 check_insn(ctx, ISA_MIPS32R2);
27607 gen_bshfl(ctx, op2, rt, rd);
27608 break;
27610 break;
27611 #if defined(TARGET_MIPS64)
27612 case OPC_DEXTM:
27613 case OPC_DEXTU:
27614 case OPC_DEXT:
27615 case OPC_DINSM:
27616 case OPC_DINSU:
27617 case OPC_DINS:
27618 check_insn(ctx, ISA_MIPS64R2);
27619 check_mips_64(ctx);
27620 gen_bitops(ctx, op1, rt, rs, sa, rd);
27621 break;
27622 case OPC_DBSHFL:
27623 op2 = MASK_DBSHFL(ctx->opcode);
27624 switch (op2) {
27625 case OPC_DALIGN:
27626 case OPC_DALIGN_1:
27627 case OPC_DALIGN_2:
27628 case OPC_DALIGN_3:
27629 case OPC_DALIGN_4:
27630 case OPC_DALIGN_5:
27631 case OPC_DALIGN_6:
27632 case OPC_DALIGN_7:
27633 case OPC_DBITSWAP:
27634 check_insn(ctx, ISA_MIPS32R6);
27635 decode_opc_special3_r6(env, ctx);
27636 break;
27637 default:
27638 check_insn(ctx, ISA_MIPS64R2);
27639 check_mips_64(ctx);
27640 op2 = MASK_DBSHFL(ctx->opcode);
27641 gen_bshfl(ctx, op2, rt, rd);
27642 break;
27644 break;
27645 #endif
27646 case OPC_RDHWR:
27647 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27648 break;
27649 case OPC_FORK:
27650 check_mt(ctx);
27652 TCGv t0 = tcg_temp_new();
27653 TCGv t1 = tcg_temp_new();
27655 gen_load_gpr(t0, rt);
27656 gen_load_gpr(t1, rs);
27657 gen_helper_fork(t0, t1);
27658 tcg_temp_free(t0);
27659 tcg_temp_free(t1);
27661 break;
27662 case OPC_YIELD:
27663 check_mt(ctx);
27665 TCGv t0 = tcg_temp_new();
27667 gen_load_gpr(t0, rs);
27668 gen_helper_yield(t0, cpu_env, t0);
27669 gen_store_gpr(t0, rd);
27670 tcg_temp_free(t0);
27672 break;
27673 default:
27674 if (ctx->insn_flags & ISA_MIPS32R6) {
27675 decode_opc_special3_r6(env, ctx);
27676 } else {
27677 decode_opc_special3_legacy(env, ctx);
27682 /* MIPS SIMD Architecture (MSA) */
27683 static inline int check_msa_access(DisasContext *ctx)
27685 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
27686 !(ctx->hflags & MIPS_HFLAG_F64))) {
27687 generate_exception_end(ctx, EXCP_RI);
27688 return 0;
27691 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
27692 if (ctx->insn_flags & ASE_MSA) {
27693 generate_exception_end(ctx, EXCP_MSADIS);
27694 return 0;
27695 } else {
27696 generate_exception_end(ctx, EXCP_RI);
27697 return 0;
27700 return 1;
27703 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
27705 /* generates tcg ops to check if any element is 0 */
27706 /* Note this function only works with MSA_WRLEN = 128 */
27707 uint64_t eval_zero_or_big = 0;
27708 uint64_t eval_big = 0;
27709 TCGv_i64 t0 = tcg_temp_new_i64();
27710 TCGv_i64 t1 = tcg_temp_new_i64();
27711 switch (df) {
27712 case DF_BYTE:
27713 eval_zero_or_big = 0x0101010101010101ULL;
27714 eval_big = 0x8080808080808080ULL;
27715 break;
27716 case DF_HALF:
27717 eval_zero_or_big = 0x0001000100010001ULL;
27718 eval_big = 0x8000800080008000ULL;
27719 break;
27720 case DF_WORD:
27721 eval_zero_or_big = 0x0000000100000001ULL;
27722 eval_big = 0x8000000080000000ULL;
27723 break;
27724 case DF_DOUBLE:
27725 eval_zero_or_big = 0x0000000000000001ULL;
27726 eval_big = 0x8000000000000000ULL;
27727 break;
27729 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
27730 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
27731 tcg_gen_andi_i64(t0, t0, eval_big);
27732 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
27733 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
27734 tcg_gen_andi_i64(t1, t1, eval_big);
27735 tcg_gen_or_i64(t0, t0, t1);
27736 /* if all bits are zero then all elements are not zero */
27737 /* if some bit is non-zero then some element is zero */
27738 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
27739 tcg_gen_trunc_i64_tl(tresult, t0);
27740 tcg_temp_free_i64(t0);
27741 tcg_temp_free_i64(t1);
27744 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
27746 uint8_t df = (ctx->opcode >> 21) & 0x3;
27747 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27748 int64_t s16 = (int16_t)ctx->opcode;
27750 check_msa_access(ctx);
27752 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27753 generate_exception_end(ctx, EXCP_RI);
27754 return;
27756 switch (op1) {
27757 case OPC_BZ_V:
27758 case OPC_BNZ_V:
27760 TCGv_i64 t0 = tcg_temp_new_i64();
27761 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
27762 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
27763 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
27764 tcg_gen_trunc_i64_tl(bcond, t0);
27765 tcg_temp_free_i64(t0);
27767 break;
27768 case OPC_BZ_B:
27769 case OPC_BZ_H:
27770 case OPC_BZ_W:
27771 case OPC_BZ_D:
27772 gen_check_zero_element(bcond, df, wt);
27773 break;
27774 case OPC_BNZ_B:
27775 case OPC_BNZ_H:
27776 case OPC_BNZ_W:
27777 case OPC_BNZ_D:
27778 gen_check_zero_element(bcond, df, wt);
27779 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
27780 break;
27783 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
27785 ctx->hflags |= MIPS_HFLAG_BC;
27786 ctx->hflags |= MIPS_HFLAG_BDS32;
27789 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
27791 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
27792 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
27793 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27794 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27796 TCGv_i32 twd = tcg_const_i32(wd);
27797 TCGv_i32 tws = tcg_const_i32(ws);
27798 TCGv_i32 ti8 = tcg_const_i32(i8);
27800 switch (MASK_MSA_I8(ctx->opcode)) {
27801 case OPC_ANDI_B:
27802 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
27803 break;
27804 case OPC_ORI_B:
27805 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
27806 break;
27807 case OPC_NORI_B:
27808 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
27809 break;
27810 case OPC_XORI_B:
27811 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
27812 break;
27813 case OPC_BMNZI_B:
27814 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
27815 break;
27816 case OPC_BMZI_B:
27817 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
27818 break;
27819 case OPC_BSELI_B:
27820 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
27821 break;
27822 case OPC_SHF_B:
27823 case OPC_SHF_H:
27824 case OPC_SHF_W:
27826 uint8_t df = (ctx->opcode >> 24) & 0x3;
27827 if (df == DF_DOUBLE) {
27828 generate_exception_end(ctx, EXCP_RI);
27829 } else {
27830 TCGv_i32 tdf = tcg_const_i32(df);
27831 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
27832 tcg_temp_free_i32(tdf);
27835 break;
27836 default:
27837 MIPS_INVAL("MSA instruction");
27838 generate_exception_end(ctx, EXCP_RI);
27839 break;
27842 tcg_temp_free_i32(twd);
27843 tcg_temp_free_i32(tws);
27844 tcg_temp_free_i32(ti8);
27847 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
27849 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27850 uint8_t df = (ctx->opcode >> 21) & 0x3;
27851 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
27852 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
27853 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27854 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27856 TCGv_i32 tdf = tcg_const_i32(df);
27857 TCGv_i32 twd = tcg_const_i32(wd);
27858 TCGv_i32 tws = tcg_const_i32(ws);
27859 TCGv_i32 timm = tcg_temp_new_i32();
27860 tcg_gen_movi_i32(timm, u5);
27862 switch (MASK_MSA_I5(ctx->opcode)) {
27863 case OPC_ADDVI_df:
27864 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
27865 break;
27866 case OPC_SUBVI_df:
27867 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
27868 break;
27869 case OPC_MAXI_S_df:
27870 tcg_gen_movi_i32(timm, s5);
27871 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
27872 break;
27873 case OPC_MAXI_U_df:
27874 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
27875 break;
27876 case OPC_MINI_S_df:
27877 tcg_gen_movi_i32(timm, s5);
27878 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
27879 break;
27880 case OPC_MINI_U_df:
27881 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
27882 break;
27883 case OPC_CEQI_df:
27884 tcg_gen_movi_i32(timm, s5);
27885 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
27886 break;
27887 case OPC_CLTI_S_df:
27888 tcg_gen_movi_i32(timm, s5);
27889 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
27890 break;
27891 case OPC_CLTI_U_df:
27892 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
27893 break;
27894 case OPC_CLEI_S_df:
27895 tcg_gen_movi_i32(timm, s5);
27896 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
27897 break;
27898 case OPC_CLEI_U_df:
27899 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
27900 break;
27901 case OPC_LDI_df:
27903 int32_t s10 = sextract32(ctx->opcode, 11, 10);
27904 tcg_gen_movi_i32(timm, s10);
27905 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
27907 break;
27908 default:
27909 MIPS_INVAL("MSA instruction");
27910 generate_exception_end(ctx, EXCP_RI);
27911 break;
27914 tcg_temp_free_i32(tdf);
27915 tcg_temp_free_i32(twd);
27916 tcg_temp_free_i32(tws);
27917 tcg_temp_free_i32(timm);
27920 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
27922 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27923 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
27924 uint32_t df = 0, m = 0;
27925 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27926 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27928 TCGv_i32 tdf;
27929 TCGv_i32 tm;
27930 TCGv_i32 twd;
27931 TCGv_i32 tws;
27933 if ((dfm & 0x40) == 0x00) {
27934 m = dfm & 0x3f;
27935 df = DF_DOUBLE;
27936 } else if ((dfm & 0x60) == 0x40) {
27937 m = dfm & 0x1f;
27938 df = DF_WORD;
27939 } else if ((dfm & 0x70) == 0x60) {
27940 m = dfm & 0x0f;
27941 df = DF_HALF;
27942 } else if ((dfm & 0x78) == 0x70) {
27943 m = dfm & 0x7;
27944 df = DF_BYTE;
27945 } else {
27946 generate_exception_end(ctx, EXCP_RI);
27947 return;
27950 tdf = tcg_const_i32(df);
27951 tm = tcg_const_i32(m);
27952 twd = tcg_const_i32(wd);
27953 tws = tcg_const_i32(ws);
27955 switch (MASK_MSA_BIT(ctx->opcode)) {
27956 case OPC_SLLI_df:
27957 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
27958 break;
27959 case OPC_SRAI_df:
27960 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
27961 break;
27962 case OPC_SRLI_df:
27963 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
27964 break;
27965 case OPC_BCLRI_df:
27966 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
27967 break;
27968 case OPC_BSETI_df:
27969 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
27970 break;
27971 case OPC_BNEGI_df:
27972 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
27973 break;
27974 case OPC_BINSLI_df:
27975 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
27976 break;
27977 case OPC_BINSRI_df:
27978 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
27979 break;
27980 case OPC_SAT_S_df:
27981 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
27982 break;
27983 case OPC_SAT_U_df:
27984 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
27985 break;
27986 case OPC_SRARI_df:
27987 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
27988 break;
27989 case OPC_SRLRI_df:
27990 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
27991 break;
27992 default:
27993 MIPS_INVAL("MSA instruction");
27994 generate_exception_end(ctx, EXCP_RI);
27995 break;
27998 tcg_temp_free_i32(tdf);
27999 tcg_temp_free_i32(tm);
28000 tcg_temp_free_i32(twd);
28001 tcg_temp_free_i32(tws);
28004 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28006 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28007 uint8_t df = (ctx->opcode >> 21) & 0x3;
28008 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28009 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28010 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28012 TCGv_i32 tdf = tcg_const_i32(df);
28013 TCGv_i32 twd = tcg_const_i32(wd);
28014 TCGv_i32 tws = tcg_const_i32(ws);
28015 TCGv_i32 twt = tcg_const_i32(wt);
28017 switch (MASK_MSA_3R(ctx->opcode)) {
28018 case OPC_SLL_df:
28019 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28020 break;
28021 case OPC_ADDV_df:
28022 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28023 break;
28024 case OPC_CEQ_df:
28025 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28026 break;
28027 case OPC_ADD_A_df:
28028 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28029 break;
28030 case OPC_SUBS_S_df:
28031 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28032 break;
28033 case OPC_MULV_df:
28034 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28035 break;
28036 case OPC_SLD_df:
28037 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28038 break;
28039 case OPC_VSHF_df:
28040 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28041 break;
28042 case OPC_SRA_df:
28043 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28044 break;
28045 case OPC_SUBV_df:
28046 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28047 break;
28048 case OPC_ADDS_A_df:
28049 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28050 break;
28051 case OPC_SUBS_U_df:
28052 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28053 break;
28054 case OPC_MADDV_df:
28055 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28056 break;
28057 case OPC_SPLAT_df:
28058 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28059 break;
28060 case OPC_SRAR_df:
28061 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28062 break;
28063 case OPC_SRL_df:
28064 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28065 break;
28066 case OPC_MAX_S_df:
28067 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28068 break;
28069 case OPC_CLT_S_df:
28070 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28071 break;
28072 case OPC_ADDS_S_df:
28073 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28074 break;
28075 case OPC_SUBSUS_U_df:
28076 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28077 break;
28078 case OPC_MSUBV_df:
28079 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28080 break;
28081 case OPC_PCKEV_df:
28082 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28083 break;
28084 case OPC_SRLR_df:
28085 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28086 break;
28087 case OPC_BCLR_df:
28088 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28089 break;
28090 case OPC_MAX_U_df:
28091 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28092 break;
28093 case OPC_CLT_U_df:
28094 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28095 break;
28096 case OPC_ADDS_U_df:
28097 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28098 break;
28099 case OPC_SUBSUU_S_df:
28100 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28101 break;
28102 case OPC_PCKOD_df:
28103 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28104 break;
28105 case OPC_BSET_df:
28106 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28107 break;
28108 case OPC_MIN_S_df:
28109 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28110 break;
28111 case OPC_CLE_S_df:
28112 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28113 break;
28114 case OPC_AVE_S_df:
28115 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28116 break;
28117 case OPC_ASUB_S_df:
28118 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28119 break;
28120 case OPC_DIV_S_df:
28121 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28122 break;
28123 case OPC_ILVL_df:
28124 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28125 break;
28126 case OPC_BNEG_df:
28127 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28128 break;
28129 case OPC_MIN_U_df:
28130 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28131 break;
28132 case OPC_CLE_U_df:
28133 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28134 break;
28135 case OPC_AVE_U_df:
28136 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28137 break;
28138 case OPC_ASUB_U_df:
28139 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28140 break;
28141 case OPC_DIV_U_df:
28142 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28143 break;
28144 case OPC_ILVR_df:
28145 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28146 break;
28147 case OPC_BINSL_df:
28148 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28149 break;
28150 case OPC_MAX_A_df:
28151 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28152 break;
28153 case OPC_AVER_S_df:
28154 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28155 break;
28156 case OPC_MOD_S_df:
28157 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28158 break;
28159 case OPC_ILVEV_df:
28160 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28161 break;
28162 case OPC_BINSR_df:
28163 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28164 break;
28165 case OPC_MIN_A_df:
28166 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28167 break;
28168 case OPC_AVER_U_df:
28169 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28170 break;
28171 case OPC_MOD_U_df:
28172 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28173 break;
28174 case OPC_ILVOD_df:
28175 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28176 break;
28178 case OPC_DOTP_S_df:
28179 case OPC_DOTP_U_df:
28180 case OPC_DPADD_S_df:
28181 case OPC_DPADD_U_df:
28182 case OPC_DPSUB_S_df:
28183 case OPC_HADD_S_df:
28184 case OPC_DPSUB_U_df:
28185 case OPC_HADD_U_df:
28186 case OPC_HSUB_S_df:
28187 case OPC_HSUB_U_df:
28188 if (df == DF_BYTE) {
28189 generate_exception_end(ctx, EXCP_RI);
28190 break;
28192 switch (MASK_MSA_3R(ctx->opcode)) {
28193 case OPC_DOTP_S_df:
28194 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28195 break;
28196 case OPC_DOTP_U_df:
28197 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28198 break;
28199 case OPC_DPADD_S_df:
28200 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28201 break;
28202 case OPC_DPADD_U_df:
28203 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28204 break;
28205 case OPC_DPSUB_S_df:
28206 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28207 break;
28208 case OPC_HADD_S_df:
28209 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28210 break;
28211 case OPC_DPSUB_U_df:
28212 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28213 break;
28214 case OPC_HADD_U_df:
28215 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28216 break;
28217 case OPC_HSUB_S_df:
28218 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28219 break;
28220 case OPC_HSUB_U_df:
28221 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28222 break;
28224 break;
28225 default:
28226 MIPS_INVAL("MSA instruction");
28227 generate_exception_end(ctx, EXCP_RI);
28228 break;
28230 tcg_temp_free_i32(twd);
28231 tcg_temp_free_i32(tws);
28232 tcg_temp_free_i32(twt);
28233 tcg_temp_free_i32(tdf);
28236 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28238 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28239 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28240 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28241 TCGv telm = tcg_temp_new();
28242 TCGv_i32 tsr = tcg_const_i32(source);
28243 TCGv_i32 tdt = tcg_const_i32(dest);
28245 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28246 case OPC_CTCMSA:
28247 gen_load_gpr(telm, source);
28248 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28249 break;
28250 case OPC_CFCMSA:
28251 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28252 gen_store_gpr(telm, dest);
28253 break;
28254 case OPC_MOVE_V:
28255 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28256 break;
28257 default:
28258 MIPS_INVAL("MSA instruction");
28259 generate_exception_end(ctx, EXCP_RI);
28260 break;
28263 tcg_temp_free(telm);
28264 tcg_temp_free_i32(tdt);
28265 tcg_temp_free_i32(tsr);
28268 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28269 uint32_t n)
28271 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28272 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28273 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28275 TCGv_i32 tws = tcg_const_i32(ws);
28276 TCGv_i32 twd = tcg_const_i32(wd);
28277 TCGv_i32 tn = tcg_const_i32(n);
28278 TCGv_i32 tdf = tcg_const_i32(df);
28280 switch (MASK_MSA_ELM(ctx->opcode)) {
28281 case OPC_SLDI_df:
28282 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28283 break;
28284 case OPC_SPLATI_df:
28285 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28286 break;
28287 case OPC_INSVE_df:
28288 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28289 break;
28290 case OPC_COPY_S_df:
28291 case OPC_COPY_U_df:
28292 case OPC_INSERT_df:
28293 #if !defined(TARGET_MIPS64)
28294 /* Double format valid only for MIPS64 */
28295 if (df == DF_DOUBLE) {
28296 generate_exception_end(ctx, EXCP_RI);
28297 break;
28299 #endif
28300 switch (MASK_MSA_ELM(ctx->opcode)) {
28301 case OPC_COPY_S_df:
28302 if (likely(wd != 0)) {
28303 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
28305 break;
28306 case OPC_COPY_U_df:
28307 if (likely(wd != 0)) {
28308 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
28310 break;
28311 case OPC_INSERT_df:
28312 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
28313 break;
28315 break;
28316 default:
28317 MIPS_INVAL("MSA instruction");
28318 generate_exception_end(ctx, EXCP_RI);
28320 tcg_temp_free_i32(twd);
28321 tcg_temp_free_i32(tws);
28322 tcg_temp_free_i32(tn);
28323 tcg_temp_free_i32(tdf);
28326 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28328 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28329 uint32_t df = 0, n = 0;
28331 if ((dfn & 0x30) == 0x00) {
28332 n = dfn & 0x0f;
28333 df = DF_BYTE;
28334 } else if ((dfn & 0x38) == 0x20) {
28335 n = dfn & 0x07;
28336 df = DF_HALF;
28337 } else if ((dfn & 0x3c) == 0x30) {
28338 n = dfn & 0x03;
28339 df = DF_WORD;
28340 } else if ((dfn & 0x3e) == 0x38) {
28341 n = dfn & 0x01;
28342 df = DF_DOUBLE;
28343 } else if (dfn == 0x3E) {
28344 /* CTCMSA, CFCMSA, MOVE.V */
28345 gen_msa_elm_3e(env, ctx);
28346 return;
28347 } else {
28348 generate_exception_end(ctx, EXCP_RI);
28349 return;
28352 gen_msa_elm_df(env, ctx, df, n);
28355 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28357 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28358 uint8_t df = (ctx->opcode >> 21) & 0x1;
28359 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28360 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28361 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28363 TCGv_i32 twd = tcg_const_i32(wd);
28364 TCGv_i32 tws = tcg_const_i32(ws);
28365 TCGv_i32 twt = tcg_const_i32(wt);
28366 TCGv_i32 tdf = tcg_temp_new_i32();
28368 /* adjust df value for floating-point instruction */
28369 tcg_gen_movi_i32(tdf, df + 2);
28371 switch (MASK_MSA_3RF(ctx->opcode)) {
28372 case OPC_FCAF_df:
28373 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28374 break;
28375 case OPC_FADD_df:
28376 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28377 break;
28378 case OPC_FCUN_df:
28379 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28380 break;
28381 case OPC_FSUB_df:
28382 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28383 break;
28384 case OPC_FCOR_df:
28385 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28386 break;
28387 case OPC_FCEQ_df:
28388 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28389 break;
28390 case OPC_FMUL_df:
28391 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28392 break;
28393 case OPC_FCUNE_df:
28394 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28395 break;
28396 case OPC_FCUEQ_df:
28397 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28398 break;
28399 case OPC_FDIV_df:
28400 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28401 break;
28402 case OPC_FCNE_df:
28403 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28404 break;
28405 case OPC_FCLT_df:
28406 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28407 break;
28408 case OPC_FMADD_df:
28409 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28410 break;
28411 case OPC_MUL_Q_df:
28412 tcg_gen_movi_i32(tdf, df + 1);
28413 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28414 break;
28415 case OPC_FCULT_df:
28416 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28417 break;
28418 case OPC_FMSUB_df:
28419 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28420 break;
28421 case OPC_MADD_Q_df:
28422 tcg_gen_movi_i32(tdf, df + 1);
28423 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28424 break;
28425 case OPC_FCLE_df:
28426 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28427 break;
28428 case OPC_MSUB_Q_df:
28429 tcg_gen_movi_i32(tdf, df + 1);
28430 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28431 break;
28432 case OPC_FCULE_df:
28433 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28434 break;
28435 case OPC_FEXP2_df:
28436 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28437 break;
28438 case OPC_FSAF_df:
28439 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28440 break;
28441 case OPC_FEXDO_df:
28442 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28443 break;
28444 case OPC_FSUN_df:
28445 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28446 break;
28447 case OPC_FSOR_df:
28448 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28449 break;
28450 case OPC_FSEQ_df:
28451 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28452 break;
28453 case OPC_FTQ_df:
28454 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28455 break;
28456 case OPC_FSUNE_df:
28457 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28458 break;
28459 case OPC_FSUEQ_df:
28460 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28461 break;
28462 case OPC_FSNE_df:
28463 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28464 break;
28465 case OPC_FSLT_df:
28466 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28467 break;
28468 case OPC_FMIN_df:
28469 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28470 break;
28471 case OPC_MULR_Q_df:
28472 tcg_gen_movi_i32(tdf, df + 1);
28473 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28474 break;
28475 case OPC_FSULT_df:
28476 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28477 break;
28478 case OPC_FMIN_A_df:
28479 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28480 break;
28481 case OPC_MADDR_Q_df:
28482 tcg_gen_movi_i32(tdf, df + 1);
28483 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28484 break;
28485 case OPC_FSLE_df:
28486 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28487 break;
28488 case OPC_FMAX_df:
28489 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28490 break;
28491 case OPC_MSUBR_Q_df:
28492 tcg_gen_movi_i32(tdf, df + 1);
28493 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28494 break;
28495 case OPC_FSULE_df:
28496 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28497 break;
28498 case OPC_FMAX_A_df:
28499 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28500 break;
28501 default:
28502 MIPS_INVAL("MSA instruction");
28503 generate_exception_end(ctx, EXCP_RI);
28504 break;
28507 tcg_temp_free_i32(twd);
28508 tcg_temp_free_i32(tws);
28509 tcg_temp_free_i32(twt);
28510 tcg_temp_free_i32(tdf);
28513 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28515 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28516 (op & (0x7 << 18)))
28517 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28518 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28519 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28520 uint8_t df = (ctx->opcode >> 16) & 0x3;
28521 TCGv_i32 twd = tcg_const_i32(wd);
28522 TCGv_i32 tws = tcg_const_i32(ws);
28523 TCGv_i32 twt = tcg_const_i32(wt);
28524 TCGv_i32 tdf = tcg_const_i32(df);
28526 switch (MASK_MSA_2R(ctx->opcode)) {
28527 case OPC_FILL_df:
28528 #if !defined(TARGET_MIPS64)
28529 /* Double format valid only for MIPS64 */
28530 if (df == DF_DOUBLE) {
28531 generate_exception_end(ctx, EXCP_RI);
28532 break;
28534 #endif
28535 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28536 break;
28537 case OPC_PCNT_df:
28538 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28539 break;
28540 case OPC_NLOC_df:
28541 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28542 break;
28543 case OPC_NLZC_df:
28544 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28545 break;
28546 default:
28547 MIPS_INVAL("MSA instruction");
28548 generate_exception_end(ctx, EXCP_RI);
28549 break;
28552 tcg_temp_free_i32(twd);
28553 tcg_temp_free_i32(tws);
28554 tcg_temp_free_i32(twt);
28555 tcg_temp_free_i32(tdf);
28558 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28560 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28561 (op & (0xf << 17)))
28562 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28563 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28564 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28565 uint8_t df = (ctx->opcode >> 16) & 0x1;
28566 TCGv_i32 twd = tcg_const_i32(wd);
28567 TCGv_i32 tws = tcg_const_i32(ws);
28568 TCGv_i32 twt = tcg_const_i32(wt);
28569 /* adjust df value for floating-point instruction */
28570 TCGv_i32 tdf = tcg_const_i32(df + 2);
28572 switch (MASK_MSA_2RF(ctx->opcode)) {
28573 case OPC_FCLASS_df:
28574 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28575 break;
28576 case OPC_FTRUNC_S_df:
28577 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28578 break;
28579 case OPC_FTRUNC_U_df:
28580 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28581 break;
28582 case OPC_FSQRT_df:
28583 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28584 break;
28585 case OPC_FRSQRT_df:
28586 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28587 break;
28588 case OPC_FRCP_df:
28589 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28590 break;
28591 case OPC_FRINT_df:
28592 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28593 break;
28594 case OPC_FLOG2_df:
28595 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28596 break;
28597 case OPC_FEXUPL_df:
28598 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28599 break;
28600 case OPC_FEXUPR_df:
28601 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28602 break;
28603 case OPC_FFQL_df:
28604 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28605 break;
28606 case OPC_FFQR_df:
28607 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28608 break;
28609 case OPC_FTINT_S_df:
28610 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28611 break;
28612 case OPC_FTINT_U_df:
28613 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
28614 break;
28615 case OPC_FFINT_S_df:
28616 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
28617 break;
28618 case OPC_FFINT_U_df:
28619 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
28620 break;
28623 tcg_temp_free_i32(twd);
28624 tcg_temp_free_i32(tws);
28625 tcg_temp_free_i32(twt);
28626 tcg_temp_free_i32(tdf);
28629 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
28631 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
28632 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28633 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28634 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28635 TCGv_i32 twd = tcg_const_i32(wd);
28636 TCGv_i32 tws = tcg_const_i32(ws);
28637 TCGv_i32 twt = tcg_const_i32(wt);
28639 switch (MASK_MSA_VEC(ctx->opcode)) {
28640 case OPC_AND_V:
28641 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
28642 break;
28643 case OPC_OR_V:
28644 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
28645 break;
28646 case OPC_NOR_V:
28647 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
28648 break;
28649 case OPC_XOR_V:
28650 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
28651 break;
28652 case OPC_BMNZ_V:
28653 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
28654 break;
28655 case OPC_BMZ_V:
28656 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
28657 break;
28658 case OPC_BSEL_V:
28659 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
28660 break;
28661 default:
28662 MIPS_INVAL("MSA instruction");
28663 generate_exception_end(ctx, EXCP_RI);
28664 break;
28667 tcg_temp_free_i32(twd);
28668 tcg_temp_free_i32(tws);
28669 tcg_temp_free_i32(twt);
28672 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
28674 switch (MASK_MSA_VEC(ctx->opcode)) {
28675 case OPC_AND_V:
28676 case OPC_OR_V:
28677 case OPC_NOR_V:
28678 case OPC_XOR_V:
28679 case OPC_BMNZ_V:
28680 case OPC_BMZ_V:
28681 case OPC_BSEL_V:
28682 gen_msa_vec_v(env, ctx);
28683 break;
28684 case OPC_MSA_2R:
28685 gen_msa_2r(env, ctx);
28686 break;
28687 case OPC_MSA_2RF:
28688 gen_msa_2rf(env, ctx);
28689 break;
28690 default:
28691 MIPS_INVAL("MSA instruction");
28692 generate_exception_end(ctx, EXCP_RI);
28693 break;
28697 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
28699 uint32_t opcode = ctx->opcode;
28700 check_insn(ctx, ASE_MSA);
28701 check_msa_access(ctx);
28703 switch (MASK_MSA_MINOR(opcode)) {
28704 case OPC_MSA_I8_00:
28705 case OPC_MSA_I8_01:
28706 case OPC_MSA_I8_02:
28707 gen_msa_i8(env, ctx);
28708 break;
28709 case OPC_MSA_I5_06:
28710 case OPC_MSA_I5_07:
28711 gen_msa_i5(env, ctx);
28712 break;
28713 case OPC_MSA_BIT_09:
28714 case OPC_MSA_BIT_0A:
28715 gen_msa_bit(env, ctx);
28716 break;
28717 case OPC_MSA_3R_0D:
28718 case OPC_MSA_3R_0E:
28719 case OPC_MSA_3R_0F:
28720 case OPC_MSA_3R_10:
28721 case OPC_MSA_3R_11:
28722 case OPC_MSA_3R_12:
28723 case OPC_MSA_3R_13:
28724 case OPC_MSA_3R_14:
28725 case OPC_MSA_3R_15:
28726 gen_msa_3r(env, ctx);
28727 break;
28728 case OPC_MSA_ELM:
28729 gen_msa_elm(env, ctx);
28730 break;
28731 case OPC_MSA_3RF_1A:
28732 case OPC_MSA_3RF_1B:
28733 case OPC_MSA_3RF_1C:
28734 gen_msa_3rf(env, ctx);
28735 break;
28736 case OPC_MSA_VEC:
28737 gen_msa_vec(env, ctx);
28738 break;
28739 case OPC_LD_B:
28740 case OPC_LD_H:
28741 case OPC_LD_W:
28742 case OPC_LD_D:
28743 case OPC_ST_B:
28744 case OPC_ST_H:
28745 case OPC_ST_W:
28746 case OPC_ST_D:
28748 int32_t s10 = sextract32(ctx->opcode, 16, 10);
28749 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
28750 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28751 uint8_t df = (ctx->opcode >> 0) & 0x3;
28753 TCGv_i32 twd = tcg_const_i32(wd);
28754 TCGv taddr = tcg_temp_new();
28755 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
28757 switch (MASK_MSA_MINOR(opcode)) {
28758 case OPC_LD_B:
28759 gen_helper_msa_ld_b(cpu_env, twd, taddr);
28760 break;
28761 case OPC_LD_H:
28762 gen_helper_msa_ld_h(cpu_env, twd, taddr);
28763 break;
28764 case OPC_LD_W:
28765 gen_helper_msa_ld_w(cpu_env, twd, taddr);
28766 break;
28767 case OPC_LD_D:
28768 gen_helper_msa_ld_d(cpu_env, twd, taddr);
28769 break;
28770 case OPC_ST_B:
28771 gen_helper_msa_st_b(cpu_env, twd, taddr);
28772 break;
28773 case OPC_ST_H:
28774 gen_helper_msa_st_h(cpu_env, twd, taddr);
28775 break;
28776 case OPC_ST_W:
28777 gen_helper_msa_st_w(cpu_env, twd, taddr);
28778 break;
28779 case OPC_ST_D:
28780 gen_helper_msa_st_d(cpu_env, twd, taddr);
28781 break;
28784 tcg_temp_free_i32(twd);
28785 tcg_temp_free(taddr);
28787 break;
28788 default:
28789 MIPS_INVAL("MSA instruction");
28790 generate_exception_end(ctx, EXCP_RI);
28791 break;
28796 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
28798 int32_t offset;
28799 int rs, rt, rd, sa;
28800 uint32_t op, op1;
28801 int16_t imm;
28803 /* make sure instructions are on a word boundary */
28804 if (ctx->base.pc_next & 0x3) {
28805 env->CP0_BadVAddr = ctx->base.pc_next;
28806 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
28807 return;
28810 /* Handle blikely not taken case */
28811 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
28812 TCGLabel *l1 = gen_new_label();
28814 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28815 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
28816 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
28817 gen_set_label(l1);
28820 op = MASK_OP_MAJOR(ctx->opcode);
28821 rs = (ctx->opcode >> 21) & 0x1f;
28822 rt = (ctx->opcode >> 16) & 0x1f;
28823 rd = (ctx->opcode >> 11) & 0x1f;
28824 sa = (ctx->opcode >> 6) & 0x1f;
28825 imm = (int16_t)ctx->opcode;
28826 switch (op) {
28827 case OPC_SPECIAL:
28828 decode_opc_special(env, ctx);
28829 break;
28830 case OPC_SPECIAL2:
28831 #if defined(TARGET_MIPS64)
28832 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
28833 decode_mmi(env, ctx);
28834 #else
28835 if (ctx->insn_flags & ASE_MXU) {
28836 decode_opc_mxu(env, ctx);
28837 #endif
28838 } else {
28839 decode_opc_special2_legacy(env, ctx);
28841 break;
28842 case OPC_SPECIAL3:
28843 #if defined(TARGET_MIPS64)
28844 if (ctx->insn_flags & INSN_R5900) {
28845 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
28846 } else {
28847 decode_opc_special3(env, ctx);
28849 #else
28850 decode_opc_special3(env, ctx);
28851 #endif
28852 break;
28853 case OPC_REGIMM:
28854 op1 = MASK_REGIMM(ctx->opcode);
28855 switch (op1) {
28856 case OPC_BLTZL: /* REGIMM branches */
28857 case OPC_BGEZL:
28858 case OPC_BLTZALL:
28859 case OPC_BGEZALL:
28860 check_insn(ctx, ISA_MIPS2);
28861 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28862 /* Fallthrough */
28863 case OPC_BLTZ:
28864 case OPC_BGEZ:
28865 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28866 break;
28867 case OPC_BLTZAL:
28868 case OPC_BGEZAL:
28869 if (ctx->insn_flags & ISA_MIPS32R6) {
28870 if (rs == 0) {
28871 /* OPC_NAL, OPC_BAL */
28872 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
28873 } else {
28874 generate_exception_end(ctx, EXCP_RI);
28876 } else {
28877 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28879 break;
28880 case OPC_TGEI: /* REGIMM traps */
28881 case OPC_TGEIU:
28882 case OPC_TLTI:
28883 case OPC_TLTIU:
28884 case OPC_TEQI:
28886 case OPC_TNEI:
28887 check_insn(ctx, ISA_MIPS2);
28888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28889 gen_trap(ctx, op1, rs, -1, imm);
28890 break;
28891 case OPC_SIGRIE:
28892 check_insn(ctx, ISA_MIPS32R6);
28893 generate_exception_end(ctx, EXCP_RI);
28894 break;
28895 case OPC_SYNCI:
28896 check_insn(ctx, ISA_MIPS32R2);
28897 /* Break the TB to be able to sync copied instructions
28898 immediately */
28899 ctx->base.is_jmp = DISAS_STOP;
28900 break;
28901 case OPC_BPOSGE32: /* MIPS DSP branch */
28902 #if defined(TARGET_MIPS64)
28903 case OPC_BPOSGE64:
28904 #endif
28905 check_dsp(ctx);
28906 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
28907 break;
28908 #if defined(TARGET_MIPS64)
28909 case OPC_DAHI:
28910 check_insn(ctx, ISA_MIPS32R6);
28911 check_mips_64(ctx);
28912 if (rs != 0) {
28913 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28915 break;
28916 case OPC_DATI:
28917 check_insn(ctx, ISA_MIPS32R6);
28918 check_mips_64(ctx);
28919 if (rs != 0) {
28920 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28922 break;
28923 #endif
28924 default: /* Invalid */
28925 MIPS_INVAL("regimm");
28926 generate_exception_end(ctx, EXCP_RI);
28927 break;
28929 break;
28930 case OPC_CP0:
28931 check_cp0_enabled(ctx);
28932 op1 = MASK_CP0(ctx->opcode);
28933 switch (op1) {
28934 case OPC_MFC0:
28935 case OPC_MTC0:
28936 case OPC_MFTR:
28937 case OPC_MTTR:
28938 case OPC_MFHC0:
28939 case OPC_MTHC0:
28940 #if defined(TARGET_MIPS64)
28941 case OPC_DMFC0:
28942 case OPC_DMTC0:
28943 #endif
28944 #ifndef CONFIG_USER_ONLY
28945 gen_cp0(env, ctx, op1, rt, rd);
28946 #endif /* !CONFIG_USER_ONLY */
28947 break;
28948 case OPC_C0:
28949 case OPC_C0_1:
28950 case OPC_C0_2:
28951 case OPC_C0_3:
28952 case OPC_C0_4:
28953 case OPC_C0_5:
28954 case OPC_C0_6:
28955 case OPC_C0_7:
28956 case OPC_C0_8:
28957 case OPC_C0_9:
28958 case OPC_C0_A:
28959 case OPC_C0_B:
28960 case OPC_C0_C:
28961 case OPC_C0_D:
28962 case OPC_C0_E:
28963 case OPC_C0_F:
28964 #ifndef CONFIG_USER_ONLY
28965 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
28966 #endif /* !CONFIG_USER_ONLY */
28967 break;
28968 case OPC_MFMC0:
28969 #ifndef CONFIG_USER_ONLY
28971 uint32_t op2;
28972 TCGv t0 = tcg_temp_new();
28974 op2 = MASK_MFMC0(ctx->opcode);
28975 switch (op2) {
28976 case OPC_DMT:
28977 check_cp0_mt(ctx);
28978 gen_helper_dmt(t0);
28979 gen_store_gpr(t0, rt);
28980 break;
28981 case OPC_EMT:
28982 check_cp0_mt(ctx);
28983 gen_helper_emt(t0);
28984 gen_store_gpr(t0, rt);
28985 break;
28986 case OPC_DVPE:
28987 check_cp0_mt(ctx);
28988 gen_helper_dvpe(t0, cpu_env);
28989 gen_store_gpr(t0, rt);
28990 break;
28991 case OPC_EVPE:
28992 check_cp0_mt(ctx);
28993 gen_helper_evpe(t0, cpu_env);
28994 gen_store_gpr(t0, rt);
28995 break;
28996 case OPC_DVP:
28997 check_insn(ctx, ISA_MIPS32R6);
28998 if (ctx->vp) {
28999 gen_helper_dvp(t0, cpu_env);
29000 gen_store_gpr(t0, rt);
29002 break;
29003 case OPC_EVP:
29004 check_insn(ctx, ISA_MIPS32R6);
29005 if (ctx->vp) {
29006 gen_helper_evp(t0, cpu_env);
29007 gen_store_gpr(t0, rt);
29009 break;
29010 case OPC_DI:
29011 check_insn(ctx, ISA_MIPS32R2);
29012 save_cpu_state(ctx, 1);
29013 gen_helper_di(t0, cpu_env);
29014 gen_store_gpr(t0, rt);
29015 /* Stop translation as we may have switched
29016 the execution mode. */
29017 ctx->base.is_jmp = DISAS_STOP;
29018 break;
29019 case OPC_EI:
29020 check_insn(ctx, ISA_MIPS32R2);
29021 save_cpu_state(ctx, 1);
29022 gen_helper_ei(t0, cpu_env);
29023 gen_store_gpr(t0, rt);
29024 /* DISAS_STOP isn't sufficient, we need to ensure we break
29025 out of translated code to check for pending interrupts */
29026 gen_save_pc(ctx->base.pc_next + 4);
29027 ctx->base.is_jmp = DISAS_EXIT;
29028 break;
29029 default: /* Invalid */
29030 MIPS_INVAL("mfmc0");
29031 generate_exception_end(ctx, EXCP_RI);
29032 break;
29034 tcg_temp_free(t0);
29036 #endif /* !CONFIG_USER_ONLY */
29037 break;
29038 case OPC_RDPGPR:
29039 check_insn(ctx, ISA_MIPS32R2);
29040 gen_load_srsgpr(rt, rd);
29041 break;
29042 case OPC_WRPGPR:
29043 check_insn(ctx, ISA_MIPS32R2);
29044 gen_store_srsgpr(rt, rd);
29045 break;
29046 default:
29047 MIPS_INVAL("cp0");
29048 generate_exception_end(ctx, EXCP_RI);
29049 break;
29051 break;
29052 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29053 if (ctx->insn_flags & ISA_MIPS32R6) {
29054 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29055 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29056 } else {
29057 /* OPC_ADDI */
29058 /* Arithmetic with immediate opcode */
29059 gen_arith_imm(ctx, op, rt, rs, imm);
29061 break;
29062 case OPC_ADDIU:
29063 gen_arith_imm(ctx, op, rt, rs, imm);
29064 break;
29065 case OPC_SLTI: /* Set on less than with immediate opcode */
29066 case OPC_SLTIU:
29067 gen_slt_imm(ctx, op, rt, rs, imm);
29068 break;
29069 case OPC_ANDI: /* Arithmetic with immediate opcode */
29070 case OPC_LUI: /* OPC_AUI */
29071 case OPC_ORI:
29072 case OPC_XORI:
29073 gen_logic_imm(ctx, op, rt, rs, imm);
29074 break;
29075 case OPC_J: /* Jump */
29076 case OPC_JAL:
29077 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29078 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29079 break;
29080 /* Branch */
29081 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29082 if (ctx->insn_flags & ISA_MIPS32R6) {
29083 if (rt == 0) {
29084 generate_exception_end(ctx, EXCP_RI);
29085 break;
29087 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29088 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29089 } else {
29090 /* OPC_BLEZL */
29091 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29093 break;
29094 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29095 if (ctx->insn_flags & ISA_MIPS32R6) {
29096 if (rt == 0) {
29097 generate_exception_end(ctx, EXCP_RI);
29098 break;
29100 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29101 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29102 } else {
29103 /* OPC_BGTZL */
29104 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29106 break;
29107 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29108 if (rt == 0) {
29109 /* OPC_BLEZ */
29110 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29111 } else {
29112 check_insn(ctx, ISA_MIPS32R6);
29113 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29114 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29116 break;
29117 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29118 if (rt == 0) {
29119 /* OPC_BGTZ */
29120 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29121 } else {
29122 check_insn(ctx, ISA_MIPS32R6);
29123 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29124 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29126 break;
29127 case OPC_BEQL:
29128 case OPC_BNEL:
29129 check_insn(ctx, ISA_MIPS2);
29130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29131 /* Fallthrough */
29132 case OPC_BEQ:
29133 case OPC_BNE:
29134 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29135 break;
29136 case OPC_LL: /* Load and stores */
29137 check_insn(ctx, ISA_MIPS2);
29138 if (ctx->insn_flags & INSN_R5900) {
29139 check_insn_opc_user_only(ctx, INSN_R5900);
29141 /* Fallthrough */
29142 case OPC_LWL:
29143 case OPC_LWR:
29144 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29145 /* Fallthrough */
29146 case OPC_LB:
29147 case OPC_LH:
29148 case OPC_LW:
29149 case OPC_LWPC:
29150 case OPC_LBU:
29151 case OPC_LHU:
29152 gen_ld(ctx, op, rt, rs, imm);
29153 break;
29154 case OPC_SWL:
29155 case OPC_SWR:
29156 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29157 /* fall through */
29158 case OPC_SB:
29159 case OPC_SH:
29160 case OPC_SW:
29161 gen_st(ctx, op, rt, rs, imm);
29162 break;
29163 case OPC_SC:
29164 check_insn(ctx, ISA_MIPS2);
29165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29166 if (ctx->insn_flags & INSN_R5900) {
29167 check_insn_opc_user_only(ctx, INSN_R5900);
29169 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29170 break;
29171 case OPC_CACHE:
29172 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29173 check_cp0_enabled(ctx);
29174 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29175 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29176 gen_cache_operation(ctx, rt, rs, imm);
29178 /* Treat as NOP. */
29179 break;
29180 case OPC_PREF:
29181 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29182 if (ctx->insn_flags & INSN_R5900) {
29183 /* Treat as NOP. */
29184 } else {
29185 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29186 /* Treat as NOP. */
29188 break;
29190 /* Floating point (COP1). */
29191 case OPC_LWC1:
29192 case OPC_LDC1:
29193 case OPC_SWC1:
29194 case OPC_SDC1:
29195 gen_cop1_ldst(ctx, op, rt, rs, imm);
29196 break;
29198 case OPC_CP1:
29199 op1 = MASK_CP1(ctx->opcode);
29201 switch (op1) {
29202 case OPC_MFHC1:
29203 case OPC_MTHC1:
29204 check_cp1_enabled(ctx);
29205 check_insn(ctx, ISA_MIPS32R2);
29206 /* fall through */
29207 case OPC_MFC1:
29208 case OPC_CFC1:
29209 case OPC_MTC1:
29210 case OPC_CTC1:
29211 check_cp1_enabled(ctx);
29212 gen_cp1(ctx, op1, rt, rd);
29213 break;
29214 #if defined(TARGET_MIPS64)
29215 case OPC_DMFC1:
29216 case OPC_DMTC1:
29217 check_cp1_enabled(ctx);
29218 check_insn(ctx, ISA_MIPS3);
29219 check_mips_64(ctx);
29220 gen_cp1(ctx, op1, rt, rd);
29221 break;
29222 #endif
29223 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29224 check_cp1_enabled(ctx);
29225 if (ctx->insn_flags & ISA_MIPS32R6) {
29226 /* OPC_BC1EQZ */
29227 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29228 rt, imm << 2, 4);
29229 } else {
29230 /* OPC_BC1ANY2 */
29231 check_cop1x(ctx);
29232 check_insn(ctx, ASE_MIPS3D);
29233 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29234 (rt >> 2) & 0x7, imm << 2);
29236 break;
29237 case OPC_BC1NEZ:
29238 check_cp1_enabled(ctx);
29239 check_insn(ctx, ISA_MIPS32R6);
29240 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29241 rt, imm << 2, 4);
29242 break;
29243 case OPC_BC1ANY4:
29244 check_cp1_enabled(ctx);
29245 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29246 check_cop1x(ctx);
29247 check_insn(ctx, ASE_MIPS3D);
29248 /* fall through */
29249 case OPC_BC1:
29250 check_cp1_enabled(ctx);
29251 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29252 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29253 (rt >> 2) & 0x7, imm << 2);
29254 break;
29255 case OPC_PS_FMT:
29256 check_ps(ctx);
29257 /* fall through */
29258 case OPC_S_FMT:
29259 case OPC_D_FMT:
29260 check_cp1_enabled(ctx);
29261 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29262 (imm >> 8) & 0x7);
29263 break;
29264 case OPC_W_FMT:
29265 case OPC_L_FMT:
29267 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29268 check_cp1_enabled(ctx);
29269 if (ctx->insn_flags & ISA_MIPS32R6) {
29270 switch (r6_op) {
29271 case R6_OPC_CMP_AF_S:
29272 case R6_OPC_CMP_UN_S:
29273 case R6_OPC_CMP_EQ_S:
29274 case R6_OPC_CMP_UEQ_S:
29275 case R6_OPC_CMP_LT_S:
29276 case R6_OPC_CMP_ULT_S:
29277 case R6_OPC_CMP_LE_S:
29278 case R6_OPC_CMP_ULE_S:
29279 case R6_OPC_CMP_SAF_S:
29280 case R6_OPC_CMP_SUN_S:
29281 case R6_OPC_CMP_SEQ_S:
29282 case R6_OPC_CMP_SEUQ_S:
29283 case R6_OPC_CMP_SLT_S:
29284 case R6_OPC_CMP_SULT_S:
29285 case R6_OPC_CMP_SLE_S:
29286 case R6_OPC_CMP_SULE_S:
29287 case R6_OPC_CMP_OR_S:
29288 case R6_OPC_CMP_UNE_S:
29289 case R6_OPC_CMP_NE_S:
29290 case R6_OPC_CMP_SOR_S:
29291 case R6_OPC_CMP_SUNE_S:
29292 case R6_OPC_CMP_SNE_S:
29293 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29294 break;
29295 case R6_OPC_CMP_AF_D:
29296 case R6_OPC_CMP_UN_D:
29297 case R6_OPC_CMP_EQ_D:
29298 case R6_OPC_CMP_UEQ_D:
29299 case R6_OPC_CMP_LT_D:
29300 case R6_OPC_CMP_ULT_D:
29301 case R6_OPC_CMP_LE_D:
29302 case R6_OPC_CMP_ULE_D:
29303 case R6_OPC_CMP_SAF_D:
29304 case R6_OPC_CMP_SUN_D:
29305 case R6_OPC_CMP_SEQ_D:
29306 case R6_OPC_CMP_SEUQ_D:
29307 case R6_OPC_CMP_SLT_D:
29308 case R6_OPC_CMP_SULT_D:
29309 case R6_OPC_CMP_SLE_D:
29310 case R6_OPC_CMP_SULE_D:
29311 case R6_OPC_CMP_OR_D:
29312 case R6_OPC_CMP_UNE_D:
29313 case R6_OPC_CMP_NE_D:
29314 case R6_OPC_CMP_SOR_D:
29315 case R6_OPC_CMP_SUNE_D:
29316 case R6_OPC_CMP_SNE_D:
29317 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29318 break;
29319 default:
29320 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29321 rt, rd, sa, (imm >> 8) & 0x7);
29323 break;
29325 } else {
29326 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29327 (imm >> 8) & 0x7);
29329 break;
29331 case OPC_BZ_V:
29332 case OPC_BNZ_V:
29333 case OPC_BZ_B:
29334 case OPC_BZ_H:
29335 case OPC_BZ_W:
29336 case OPC_BZ_D:
29337 case OPC_BNZ_B:
29338 case OPC_BNZ_H:
29339 case OPC_BNZ_W:
29340 case OPC_BNZ_D:
29341 check_insn(ctx, ASE_MSA);
29342 gen_msa_branch(env, ctx, op1);
29343 break;
29344 default:
29345 MIPS_INVAL("cp1");
29346 generate_exception_end(ctx, EXCP_RI);
29347 break;
29349 break;
29351 /* Compact branches [R6] and COP2 [non-R6] */
29352 case OPC_BC: /* OPC_LWC2 */
29353 case OPC_BALC: /* OPC_SWC2 */
29354 if (ctx->insn_flags & ISA_MIPS32R6) {
29355 /* OPC_BC, OPC_BALC */
29356 gen_compute_compact_branch(ctx, op, 0, 0,
29357 sextract32(ctx->opcode << 2, 0, 28));
29358 } else {
29359 /* OPC_LWC2, OPC_SWC2 */
29360 /* COP2: Not implemented. */
29361 generate_exception_err(ctx, EXCP_CpU, 2);
29363 break;
29364 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29365 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29366 if (ctx->insn_flags & ISA_MIPS32R6) {
29367 if (rs != 0) {
29368 /* OPC_BEQZC, OPC_BNEZC */
29369 gen_compute_compact_branch(ctx, op, rs, 0,
29370 sextract32(ctx->opcode << 2, 0, 23));
29371 } else {
29372 /* OPC_JIC, OPC_JIALC */
29373 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29375 } else {
29376 /* OPC_LWC2, OPC_SWC2 */
29377 /* COP2: Not implemented. */
29378 generate_exception_err(ctx, EXCP_CpU, 2);
29380 break;
29381 case OPC_CP2:
29382 check_insn(ctx, INSN_LOONGSON2F);
29383 /* Note that these instructions use different fields. */
29384 gen_loongson_multimedia(ctx, sa, rd, rt);
29385 break;
29387 case OPC_CP3:
29388 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29389 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29390 check_cp1_enabled(ctx);
29391 op1 = MASK_CP3(ctx->opcode);
29392 switch (op1) {
29393 case OPC_LUXC1:
29394 case OPC_SUXC1:
29395 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29396 /* Fallthrough */
29397 case OPC_LWXC1:
29398 case OPC_LDXC1:
29399 case OPC_SWXC1:
29400 case OPC_SDXC1:
29401 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29402 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29403 break;
29404 case OPC_PREFX:
29405 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29406 /* Treat as NOP. */
29407 break;
29408 case OPC_ALNV_PS:
29409 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29410 /* Fallthrough */
29411 case OPC_MADD_S:
29412 case OPC_MADD_D:
29413 case OPC_MADD_PS:
29414 case OPC_MSUB_S:
29415 case OPC_MSUB_D:
29416 case OPC_MSUB_PS:
29417 case OPC_NMADD_S:
29418 case OPC_NMADD_D:
29419 case OPC_NMADD_PS:
29420 case OPC_NMSUB_S:
29421 case OPC_NMSUB_D:
29422 case OPC_NMSUB_PS:
29423 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29424 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29425 break;
29426 default:
29427 MIPS_INVAL("cp3");
29428 generate_exception_end(ctx, EXCP_RI);
29429 break;
29431 } else {
29432 generate_exception_err(ctx, EXCP_CpU, 1);
29434 break;
29436 #if defined(TARGET_MIPS64)
29437 /* MIPS64 opcodes */
29438 case OPC_LLD:
29439 if (ctx->insn_flags & INSN_R5900) {
29440 check_insn_opc_user_only(ctx, INSN_R5900);
29442 /* fall through */
29443 case OPC_LDL:
29444 case OPC_LDR:
29445 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29446 /* fall through */
29447 case OPC_LWU:
29448 case OPC_LD:
29449 check_insn(ctx, ISA_MIPS3);
29450 check_mips_64(ctx);
29451 gen_ld(ctx, op, rt, rs, imm);
29452 break;
29453 case OPC_SDL:
29454 case OPC_SDR:
29455 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29456 /* fall through */
29457 case OPC_SD:
29458 check_insn(ctx, ISA_MIPS3);
29459 check_mips_64(ctx);
29460 gen_st(ctx, op, rt, rs, imm);
29461 break;
29462 case OPC_SCD:
29463 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29464 check_insn(ctx, ISA_MIPS3);
29465 if (ctx->insn_flags & INSN_R5900) {
29466 check_insn_opc_user_only(ctx, INSN_R5900);
29468 check_mips_64(ctx);
29469 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
29470 break;
29471 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29472 if (ctx->insn_flags & ISA_MIPS32R6) {
29473 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29474 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29475 } else {
29476 /* OPC_DADDI */
29477 check_insn(ctx, ISA_MIPS3);
29478 check_mips_64(ctx);
29479 gen_arith_imm(ctx, op, rt, rs, imm);
29481 break;
29482 case OPC_DADDIU:
29483 check_insn(ctx, ISA_MIPS3);
29484 check_mips_64(ctx);
29485 gen_arith_imm(ctx, op, rt, rs, imm);
29486 break;
29487 #else
29488 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29489 if (ctx->insn_flags & ISA_MIPS32R6) {
29490 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29491 } else {
29492 MIPS_INVAL("major opcode");
29493 generate_exception_end(ctx, EXCP_RI);
29495 break;
29496 #endif
29497 case OPC_DAUI: /* OPC_JALX */
29498 if (ctx->insn_flags & ISA_MIPS32R6) {
29499 #if defined(TARGET_MIPS64)
29500 /* OPC_DAUI */
29501 check_mips_64(ctx);
29502 if (rs == 0) {
29503 generate_exception(ctx, EXCP_RI);
29504 } else if (rt != 0) {
29505 TCGv t0 = tcg_temp_new();
29506 gen_load_gpr(t0, rs);
29507 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29508 tcg_temp_free(t0);
29510 #else
29511 generate_exception_end(ctx, EXCP_RI);
29512 MIPS_INVAL("major opcode");
29513 #endif
29514 } else {
29515 /* OPC_JALX */
29516 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29517 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29518 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29520 break;
29521 case OPC_MSA: /* OPC_MDMX */
29522 if (ctx->insn_flags & INSN_R5900) {
29523 #if defined(TARGET_MIPS64)
29524 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29525 #endif
29526 } else {
29527 /* MDMX: Not implemented. */
29528 gen_msa(env, ctx);
29530 break;
29531 case OPC_PCREL:
29532 check_insn(ctx, ISA_MIPS32R6);
29533 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29534 break;
29535 default: /* Invalid */
29536 MIPS_INVAL("major opcode");
29537 generate_exception_end(ctx, EXCP_RI);
29538 break;
29542 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29544 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29545 CPUMIPSState *env = cs->env_ptr;
29547 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29548 ctx->saved_pc = -1;
29549 ctx->insn_flags = env->insn_flags;
29550 ctx->CP0_Config1 = env->CP0_Config1;
29551 ctx->CP0_Config2 = env->CP0_Config2;
29552 ctx->CP0_Config3 = env->CP0_Config3;
29553 ctx->CP0_Config5 = env->CP0_Config5;
29554 ctx->btarget = 0;
29555 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29556 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29557 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29558 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29559 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29560 ctx->PAMask = env->PAMask;
29561 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29562 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29563 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29564 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29565 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29566 /* Restore delay slot state from the tb context. */
29567 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29568 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29569 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29570 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29571 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29572 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29573 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29574 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29575 restore_cpu_state(env, ctx);
29576 #ifdef CONFIG_USER_ONLY
29577 ctx->mem_idx = MIPS_HFLAG_UM;
29578 #else
29579 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29580 #endif
29581 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29582 MO_UNALN : MO_ALIGN;
29584 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29585 ctx->hflags);
29588 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29592 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29594 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29596 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29597 ctx->btarget);
29600 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29601 const CPUBreakpoint *bp)
29603 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29605 save_cpu_state(ctx, 1);
29606 ctx->base.is_jmp = DISAS_NORETURN;
29607 gen_helper_raise_exception_debug(cpu_env);
29608 /* The address covered by the breakpoint must be included in
29609 [tb->pc, tb->pc + tb->size) in order to for it to be
29610 properly cleared -- thus we increment the PC here so that
29611 the logic setting tb->size below does the right thing. */
29612 ctx->base.pc_next += 4;
29613 return true;
29616 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29618 CPUMIPSState *env = cs->env_ptr;
29619 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29620 int insn_bytes;
29621 int is_slot;
29623 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29624 if (ctx->insn_flags & ISA_NANOMIPS32) {
29625 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29626 insn_bytes = decode_nanomips_opc(env, ctx);
29627 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29628 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
29629 insn_bytes = 4;
29630 decode_opc(env, ctx);
29631 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29632 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29633 insn_bytes = decode_micromips_opc(env, ctx);
29634 } else if (ctx->insn_flags & ASE_MIPS16) {
29635 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29636 insn_bytes = decode_mips16_opc(env, ctx);
29637 } else {
29638 generate_exception_end(ctx, EXCP_RI);
29639 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29640 return;
29643 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29644 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29645 MIPS_HFLAG_FBNSLOT))) {
29646 /* force to generate branch as there is neither delay nor
29647 forbidden slot */
29648 is_slot = 1;
29650 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29651 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29652 /* Force to generate branch as microMIPS R6 doesn't restrict
29653 branches in the forbidden slot. */
29654 is_slot = 1;
29657 if (is_slot) {
29658 gen_branch(ctx, insn_bytes);
29660 ctx->base.pc_next += insn_bytes;
29662 if (ctx->base.is_jmp != DISAS_NEXT) {
29663 return;
29665 /* Execute a branch and its delay slot as a single instruction.
29666 This is what GDB expects and is consistent with what the
29667 hardware does (e.g. if a delay slot instruction faults, the
29668 reported PC is the PC of the branch). */
29669 if (ctx->base.singlestep_enabled &&
29670 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29671 ctx->base.is_jmp = DISAS_TOO_MANY;
29673 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29674 ctx->base.is_jmp = DISAS_TOO_MANY;
29678 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29680 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29682 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29683 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29684 gen_helper_raise_exception_debug(cpu_env);
29685 } else {
29686 switch (ctx->base.is_jmp) {
29687 case DISAS_STOP:
29688 gen_save_pc(ctx->base.pc_next);
29689 tcg_gen_lookup_and_goto_ptr();
29690 break;
29691 case DISAS_NEXT:
29692 case DISAS_TOO_MANY:
29693 save_cpu_state(ctx, 0);
29694 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29695 break;
29696 case DISAS_EXIT:
29697 tcg_gen_exit_tb(NULL, 0);
29698 break;
29699 case DISAS_NORETURN:
29700 break;
29701 default:
29702 g_assert_not_reached();
29707 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29709 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29710 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29713 static const TranslatorOps mips_tr_ops = {
29714 .init_disas_context = mips_tr_init_disas_context,
29715 .tb_start = mips_tr_tb_start,
29716 .insn_start = mips_tr_insn_start,
29717 .breakpoint_check = mips_tr_breakpoint_check,
29718 .translate_insn = mips_tr_translate_insn,
29719 .tb_stop = mips_tr_tb_stop,
29720 .disas_log = mips_tr_disas_log,
29723 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
29725 DisasContext ctx;
29727 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
29730 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
29731 int flags)
29733 int i;
29734 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
29736 #define printfpr(fp) \
29737 do { \
29738 if (is_fpu64) \
29739 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29740 " fd:%13g fs:%13g psu: %13g\n", \
29741 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29742 (double)(fp)->fd, \
29743 (double)(fp)->fs[FP_ENDIAN_IDX], \
29744 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29745 else { \
29746 fpr_t tmp; \
29747 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29748 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29749 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29750 " fd:%13g fs:%13g psu:%13g\n", \
29751 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29752 (double)tmp.fd, \
29753 (double)tmp.fs[FP_ENDIAN_IDX], \
29754 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29756 } while(0)
29759 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29760 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
29761 get_float_exception_flags(&env->active_fpu.fp_status));
29762 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29763 fpu_fprintf(f, "%3s: ", fregnames[i]);
29764 printfpr(&env->active_fpu.fpr[i]);
29767 #undef printfpr
29770 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
29771 int flags)
29773 MIPSCPU *cpu = MIPS_CPU(cs);
29774 CPUMIPSState *env = &cpu->env;
29775 int i;
29777 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29778 " LO=0x" TARGET_FMT_lx " ds %04x "
29779 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
29780 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29781 env->hflags, env->btarget, env->bcond);
29782 for (i = 0; i < 32; i++) {
29783 if ((i & 3) == 0)
29784 cpu_fprintf(f, "GPR%02d:", i);
29785 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
29786 if ((i & 3) == 3)
29787 cpu_fprintf(f, "\n");
29790 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
29791 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
29792 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
29793 PRIx64 "\n",
29794 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
29795 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
29796 env->CP0_Config2, env->CP0_Config3);
29797 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
29798 env->CP0_Config4, env->CP0_Config5);
29799 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
29800 fpu_dump_state(env, f, cpu_fprintf, flags);
29804 void mips_tcg_init(void)
29806 int i;
29808 cpu_gpr[0] = NULL;
29809 for (i = 1; i < 32; i++)
29810 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
29811 offsetof(CPUMIPSState, active_tc.gpr[i]),
29812 regnames[i]);
29814 for (i = 0; i < 32; i++) {
29815 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
29816 msa_wr_d[i * 2] =
29817 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
29818 /* The scalar floating-point unit (FPU) registers are mapped on
29819 * the MSA vector registers. */
29820 fpu_f64[i] = msa_wr_d[i * 2];
29821 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
29822 msa_wr_d[i * 2 + 1] =
29823 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
29826 cpu_PC = tcg_global_mem_new(cpu_env,
29827 offsetof(CPUMIPSState, active_tc.PC), "PC");
29828 for (i = 0; i < MIPS_DSP_ACC; i++) {
29829 cpu_HI[i] = tcg_global_mem_new(cpu_env,
29830 offsetof(CPUMIPSState, active_tc.HI[i]),
29831 regnames_HI[i]);
29832 cpu_LO[i] = tcg_global_mem_new(cpu_env,
29833 offsetof(CPUMIPSState, active_tc.LO[i]),
29834 regnames_LO[i]);
29836 cpu_dspctrl = tcg_global_mem_new(cpu_env,
29837 offsetof(CPUMIPSState, active_tc.DSPControl),
29838 "DSPControl");
29839 bcond = tcg_global_mem_new(cpu_env,
29840 offsetof(CPUMIPSState, bcond), "bcond");
29841 btarget = tcg_global_mem_new(cpu_env,
29842 offsetof(CPUMIPSState, btarget), "btarget");
29843 hflags = tcg_global_mem_new_i32(cpu_env,
29844 offsetof(CPUMIPSState, hflags), "hflags");
29846 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
29847 offsetof(CPUMIPSState, active_fpu.fcr0),
29848 "fcr0");
29849 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
29850 offsetof(CPUMIPSState, active_fpu.fcr31),
29851 "fcr31");
29852 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
29853 "lladdr");
29854 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
29855 "llval");
29857 #if defined(TARGET_MIPS64)
29858 cpu_mmr[0] = NULL;
29859 for (i = 1; i < 32; i++) {
29860 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
29861 offsetof(CPUMIPSState,
29862 active_tc.mmr[i]),
29863 regnames[i]);
29865 #endif
29867 #if !defined(TARGET_MIPS64)
29868 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29869 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29870 offsetof(CPUMIPSState,
29871 active_tc.mxu_gpr[i]),
29872 mxuregnames[i]);
29875 mxu_CR = tcg_global_mem_new(cpu_env,
29876 offsetof(CPUMIPSState, active_tc.mxu_cr),
29877 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
29878 #endif
29881 #include "translate_init.inc.c"
29883 void cpu_mips_realize_env(CPUMIPSState *env)
29885 env->exception_base = (int32_t)0xBFC00000;
29887 #ifndef CONFIG_USER_ONLY
29888 mmu_init(env, env->cpu_model);
29889 #endif
29890 fpu_init(env, env->cpu_model);
29891 mvp_init(env, env->cpu_model);
29894 bool cpu_supports_cps_smp(const char *cpu_type)
29896 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29897 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
29900 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
29902 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29903 return (mcc->cpu_def->insn_flags & isa) != 0;
29906 void cpu_set_exception_base(int vp_index, target_ulong address)
29908 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
29909 vp->env.exception_base = address;
29912 void cpu_state_reset(CPUMIPSState *env)
29914 MIPSCPU *cpu = mips_env_get_cpu(env);
29915 CPUState *cs = CPU(cpu);
29917 /* Reset registers to their default values */
29918 env->CP0_PRid = env->cpu_model->CP0_PRid;
29919 env->CP0_Config0 = env->cpu_model->CP0_Config0;
29920 #ifdef TARGET_WORDS_BIGENDIAN
29921 env->CP0_Config0 |= (1 << CP0C0_BE);
29922 #endif
29923 env->CP0_Config1 = env->cpu_model->CP0_Config1;
29924 env->CP0_Config2 = env->cpu_model->CP0_Config2;
29925 env->CP0_Config3 = env->cpu_model->CP0_Config3;
29926 env->CP0_Config4 = env->cpu_model->CP0_Config4;
29927 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
29928 env->CP0_Config5 = env->cpu_model->CP0_Config5;
29929 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
29930 env->CP0_Config6 = env->cpu_model->CP0_Config6;
29931 env->CP0_Config7 = env->cpu_model->CP0_Config7;
29932 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
29933 << env->cpu_model->CP0_LLAddr_shift;
29934 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
29935 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
29936 env->CCRes = env->cpu_model->CCRes;
29937 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
29938 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
29939 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
29940 env->current_tc = 0;
29941 env->SEGBITS = env->cpu_model->SEGBITS;
29942 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
29943 #if defined(TARGET_MIPS64)
29944 if (env->cpu_model->insn_flags & ISA_MIPS3) {
29945 env->SEGMask |= 3ULL << 62;
29947 #endif
29948 env->PABITS = env->cpu_model->PABITS;
29949 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
29950 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
29951 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
29952 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
29953 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
29954 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
29955 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
29956 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
29957 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
29958 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
29959 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
29960 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
29961 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
29962 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
29963 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
29964 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
29965 env->msair = env->cpu_model->MSAIR;
29966 env->insn_flags = env->cpu_model->insn_flags;
29968 #if defined(CONFIG_USER_ONLY)
29969 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
29970 # ifdef TARGET_MIPS64
29971 /* Enable 64-bit register mode. */
29972 env->CP0_Status |= (1 << CP0St_PX);
29973 # endif
29974 # ifdef TARGET_ABI_MIPSN64
29975 /* Enable 64-bit address mode. */
29976 env->CP0_Status |= (1 << CP0St_UX);
29977 # endif
29978 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
29979 hardware registers. */
29980 env->CP0_HWREna |= 0x0000000F;
29981 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
29982 env->CP0_Status |= (1 << CP0St_CU1);
29984 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
29985 env->CP0_Status |= (1 << CP0St_MX);
29987 # if defined(TARGET_MIPS64)
29988 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
29989 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
29990 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
29991 env->CP0_Status |= (1 << CP0St_FR);
29993 # endif
29994 #else
29995 if (env->hflags & MIPS_HFLAG_BMASK) {
29996 /* If the exception was raised from a delay slot,
29997 come back to the jump. */
29998 env->CP0_ErrorEPC = (env->active_tc.PC
29999 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
30000 } else {
30001 env->CP0_ErrorEPC = env->active_tc.PC;
30003 env->active_tc.PC = env->exception_base;
30004 env->CP0_Random = env->tlb->nb_tlb - 1;
30005 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30006 env->CP0_Wired = 0;
30007 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30008 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30009 if (mips_um_ksegs_enabled()) {
30010 env->CP0_EBase |= 0x40000000;
30011 } else {
30012 env->CP0_EBase |= (int32_t)0x80000000;
30014 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30015 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30017 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30018 0x3ff : 0xff;
30019 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30020 /* vectored interrupts not implemented, timer on int 7,
30021 no performance counters. */
30022 env->CP0_IntCtl = 0xe0000000;
30024 int i;
30026 for (i = 0; i < 7; i++) {
30027 env->CP0_WatchLo[i] = 0;
30028 env->CP0_WatchHi[i] = 0x80000000;
30030 env->CP0_WatchLo[7] = 0;
30031 env->CP0_WatchHi[7] = 0;
30033 /* Count register increments in debug mode, EJTAG version 1 */
30034 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30036 cpu_mips_store_count(env, 1);
30038 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30039 int i;
30041 /* Only TC0 on VPE 0 starts as active. */
30042 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30043 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30044 env->tcs[i].CP0_TCHalt = 1;
30046 env->active_tc.CP0_TCHalt = 1;
30047 cs->halted = 1;
30049 if (cs->cpu_index == 0) {
30050 /* VPE0 starts up enabled. */
30051 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30052 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30054 /* TC0 starts up unhalted. */
30055 cs->halted = 0;
30056 env->active_tc.CP0_TCHalt = 0;
30057 env->tcs[0].CP0_TCHalt = 0;
30058 /* With thread 0 active. */
30059 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30060 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30065 * Configure default legacy segmentation control. We use this regardless of
30066 * whether segmentation control is presented to the guest.
30068 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30069 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30070 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30071 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30072 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30073 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30074 (2 << CP0SC_C);
30075 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30076 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30077 (3 << CP0SC_C)) << 16;
30078 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30079 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30080 (1 << CP0SC_EU) | (2 << CP0SC_C);
30081 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30082 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30083 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30084 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30085 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30086 #endif
30087 if ((env->insn_flags & ISA_MIPS32R6) &&
30088 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30089 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30090 env->CP0_Status |= (1 << CP0St_FR);
30093 if (env->insn_flags & ISA_MIPS32R6) {
30094 /* PTW = 1 */
30095 env->CP0_PWSize = 0x40;
30096 /* GDI = 12 */
30097 /* UDI = 12 */
30098 /* MDI = 12 */
30099 /* PRI = 12 */
30100 /* PTEI = 2 */
30101 env->CP0_PWField = 0x0C30C302;
30102 } else {
30103 /* GDI = 0 */
30104 /* UDI = 0 */
30105 /* MDI = 0 */
30106 /* PRI = 0 */
30107 /* PTEI = 2 */
30108 env->CP0_PWField = 0x02;
30111 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30112 /* microMIPS on reset when Config3.ISA is 3 */
30113 env->hflags |= MIPS_HFLAG_M16;
30116 /* MSA */
30117 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30118 msa_reset(env);
30121 compute_hflags(env);
30122 restore_fp_status(env);
30123 restore_pamask(env);
30124 cs->exception_index = EXCP_NONE;
30126 if (semihosting_get_argc()) {
30127 /* UHI interface can be used to obtain argc and argv */
30128 env->active_tc.gpr[4] = -1;
30132 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30133 target_ulong *data)
30135 env->active_tc.PC = data[0];
30136 env->hflags &= ~MIPS_HFLAG_BMASK;
30137 env->hflags |= data[1];
30138 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30139 case MIPS_HFLAG_BR:
30140 break;
30141 case MIPS_HFLAG_BC:
30142 case MIPS_HFLAG_BL:
30143 case MIPS_HFLAG_B:
30144 env->btarget = data[2];
30145 break;