target/mips: Introduce 32 R5900 multimedia registers
[qemu/ar7.git] / target / mips / translate.c
blobab307c410ca121b90cd342424ac3256de8096173
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_i32 hflags;
2454 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2455 static TCGv_i64 fpu_f64[32];
2456 static TCGv_i64 msa_wr_d[64];
2458 #if defined(TARGET_MIPS64)
2459 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2460 static TCGv_i64 cpu_mmr[32];
2461 #endif
2463 #if !defined(TARGET_MIPS64)
2464 /* MXU registers */
2465 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2466 static TCGv mxu_CR;
2467 #endif
2469 #include "exec/gen-icount.h"
2471 #define gen_helper_0e0i(name, arg) do { \
2472 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2473 gen_helper_##name(cpu_env, helper_tmp); \
2474 tcg_temp_free_i32(helper_tmp); \
2475 } while(0)
2477 #define gen_helper_0e1i(name, arg1, arg2) do { \
2478 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2479 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2480 tcg_temp_free_i32(helper_tmp); \
2481 } while(0)
2483 #define gen_helper_1e0i(name, ret, arg1) do { \
2484 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2485 gen_helper_##name(ret, cpu_env, helper_tmp); \
2486 tcg_temp_free_i32(helper_tmp); \
2487 } while(0)
2489 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2490 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2491 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2492 tcg_temp_free_i32(helper_tmp); \
2493 } while(0)
2495 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2496 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2497 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2498 tcg_temp_free_i32(helper_tmp); \
2499 } while(0)
2501 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2502 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2503 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2504 tcg_temp_free_i32(helper_tmp); \
2505 } while(0)
2507 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2508 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2509 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2510 tcg_temp_free_i32(helper_tmp); \
2511 } while(0)
2513 typedef struct DisasContext {
2514 DisasContextBase base;
2515 target_ulong saved_pc;
2516 target_ulong page_start;
2517 uint32_t opcode;
2518 uint64_t insn_flags;
2519 int32_t CP0_Config1;
2520 int32_t CP0_Config2;
2521 int32_t CP0_Config3;
2522 int32_t CP0_Config5;
2523 /* Routine used to access memory */
2524 int mem_idx;
2525 TCGMemOp default_tcg_memop_mask;
2526 uint32_t hflags, saved_hflags;
2527 target_ulong btarget;
2528 bool ulri;
2529 int kscrexist;
2530 bool rxi;
2531 int ie;
2532 bool bi;
2533 bool bp;
2534 uint64_t PAMask;
2535 bool mvh;
2536 bool eva;
2537 bool sc;
2538 int CP0_LLAddr_shift;
2539 bool ps;
2540 bool vp;
2541 bool cmgcr;
2542 bool mrp;
2543 bool nan2008;
2544 bool abs2008;
2545 bool saar;
2546 } DisasContext;
2548 #define DISAS_STOP DISAS_TARGET_0
2549 #define DISAS_EXIT DISAS_TARGET_1
2551 static const char * const regnames[] = {
2552 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2553 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2554 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2555 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2558 static const char * const regnames_HI[] = {
2559 "HI0", "HI1", "HI2", "HI3",
2562 static const char * const regnames_LO[] = {
2563 "LO0", "LO1", "LO2", "LO3",
2566 static const char * const fregnames[] = {
2567 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2568 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2569 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2570 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2573 static const char * const msaregnames[] = {
2574 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2575 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2576 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2577 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2578 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2579 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2580 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2581 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2582 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2583 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2584 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2585 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2586 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2587 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2588 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2589 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2592 #if !defined(TARGET_MIPS64)
2593 static const char * const mxuregnames[] = {
2594 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2595 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2597 #endif
2599 #define LOG_DISAS(...) \
2600 do { \
2601 if (MIPS_DEBUG_DISAS) { \
2602 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2604 } while (0)
2606 #define MIPS_INVAL(op) \
2607 do { \
2608 if (MIPS_DEBUG_DISAS) { \
2609 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2610 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2611 ctx->base.pc_next, ctx->opcode, op, \
2612 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2613 ((ctx->opcode >> 16) & 0x1F)); \
2615 } while (0)
2617 /* General purpose registers moves. */
2618 static inline void gen_load_gpr (TCGv t, int reg)
2620 if (reg == 0)
2621 tcg_gen_movi_tl(t, 0);
2622 else
2623 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2626 static inline void gen_store_gpr (TCGv t, int reg)
2628 if (reg != 0)
2629 tcg_gen_mov_tl(cpu_gpr[reg], t);
2632 /* Moves to/from shadow registers. */
2633 static inline void gen_load_srsgpr (int from, int to)
2635 TCGv t0 = tcg_temp_new();
2637 if (from == 0)
2638 tcg_gen_movi_tl(t0, 0);
2639 else {
2640 TCGv_i32 t2 = tcg_temp_new_i32();
2641 TCGv_ptr addr = tcg_temp_new_ptr();
2643 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2644 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2645 tcg_gen_andi_i32(t2, t2, 0xf);
2646 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2647 tcg_gen_ext_i32_ptr(addr, t2);
2648 tcg_gen_add_ptr(addr, cpu_env, addr);
2650 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2651 tcg_temp_free_ptr(addr);
2652 tcg_temp_free_i32(t2);
2654 gen_store_gpr(t0, to);
2655 tcg_temp_free(t0);
2658 static inline void gen_store_srsgpr (int from, int to)
2660 if (to != 0) {
2661 TCGv t0 = tcg_temp_new();
2662 TCGv_i32 t2 = tcg_temp_new_i32();
2663 TCGv_ptr addr = tcg_temp_new_ptr();
2665 gen_load_gpr(t0, from);
2666 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2667 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2668 tcg_gen_andi_i32(t2, t2, 0xf);
2669 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2670 tcg_gen_ext_i32_ptr(addr, t2);
2671 tcg_gen_add_ptr(addr, cpu_env, addr);
2673 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2674 tcg_temp_free_ptr(addr);
2675 tcg_temp_free_i32(t2);
2676 tcg_temp_free(t0);
2680 #if !defined(TARGET_MIPS64)
2681 /* MXU General purpose registers moves. */
2682 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2684 if (reg == 0) {
2685 tcg_gen_movi_tl(t, 0);
2686 } else if (reg <= 15) {
2687 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2691 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2693 if (reg > 0 && reg <= 15) {
2694 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2698 /* MXU control register moves. */
2699 static inline void gen_load_mxu_cr(TCGv t)
2701 tcg_gen_mov_tl(t, mxu_CR);
2704 static inline void gen_store_mxu_cr(TCGv t)
2706 /* TODO: Add handling of RW rules for MXU_CR. */
2707 tcg_gen_mov_tl(mxu_CR, t);
2709 #endif
2712 /* Tests */
2713 static inline void gen_save_pc(target_ulong pc)
2715 tcg_gen_movi_tl(cpu_PC, pc);
2718 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2720 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2721 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2722 gen_save_pc(ctx->base.pc_next);
2723 ctx->saved_pc = ctx->base.pc_next;
2725 if (ctx->hflags != ctx->saved_hflags) {
2726 tcg_gen_movi_i32(hflags, ctx->hflags);
2727 ctx->saved_hflags = ctx->hflags;
2728 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2729 case MIPS_HFLAG_BR:
2730 break;
2731 case MIPS_HFLAG_BC:
2732 case MIPS_HFLAG_BL:
2733 case MIPS_HFLAG_B:
2734 tcg_gen_movi_tl(btarget, ctx->btarget);
2735 break;
2740 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2742 ctx->saved_hflags = ctx->hflags;
2743 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2744 case MIPS_HFLAG_BR:
2745 break;
2746 case MIPS_HFLAG_BC:
2747 case MIPS_HFLAG_BL:
2748 case MIPS_HFLAG_B:
2749 ctx->btarget = env->btarget;
2750 break;
2754 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2756 TCGv_i32 texcp = tcg_const_i32(excp);
2757 TCGv_i32 terr = tcg_const_i32(err);
2758 save_cpu_state(ctx, 1);
2759 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2760 tcg_temp_free_i32(terr);
2761 tcg_temp_free_i32(texcp);
2762 ctx->base.is_jmp = DISAS_NORETURN;
2765 static inline void generate_exception(DisasContext *ctx, int excp)
2767 gen_helper_0e0i(raise_exception, excp);
2770 static inline void generate_exception_end(DisasContext *ctx, int excp)
2772 generate_exception_err(ctx, excp, 0);
2775 /* Floating point register moves. */
2776 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2778 if (ctx->hflags & MIPS_HFLAG_FRE) {
2779 generate_exception(ctx, EXCP_RI);
2781 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2784 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2786 TCGv_i64 t64;
2787 if (ctx->hflags & MIPS_HFLAG_FRE) {
2788 generate_exception(ctx, EXCP_RI);
2790 t64 = tcg_temp_new_i64();
2791 tcg_gen_extu_i32_i64(t64, t);
2792 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2793 tcg_temp_free_i64(t64);
2796 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2798 if (ctx->hflags & MIPS_HFLAG_F64) {
2799 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2800 } else {
2801 gen_load_fpr32(ctx, t, reg | 1);
2805 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2807 if (ctx->hflags & MIPS_HFLAG_F64) {
2808 TCGv_i64 t64 = tcg_temp_new_i64();
2809 tcg_gen_extu_i32_i64(t64, t);
2810 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2811 tcg_temp_free_i64(t64);
2812 } else {
2813 gen_store_fpr32(ctx, t, reg | 1);
2817 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2819 if (ctx->hflags & MIPS_HFLAG_F64) {
2820 tcg_gen_mov_i64(t, fpu_f64[reg]);
2821 } else {
2822 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2826 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2828 if (ctx->hflags & MIPS_HFLAG_F64) {
2829 tcg_gen_mov_i64(fpu_f64[reg], t);
2830 } else {
2831 TCGv_i64 t0;
2832 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2833 t0 = tcg_temp_new_i64();
2834 tcg_gen_shri_i64(t0, t, 32);
2835 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2836 tcg_temp_free_i64(t0);
2840 static inline int get_fp_bit (int cc)
2842 if (cc)
2843 return 24 + cc;
2844 else
2845 return 23;
2848 /* Addresses computation */
2849 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2851 tcg_gen_add_tl(ret, arg0, arg1);
2853 #if defined(TARGET_MIPS64)
2854 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2855 tcg_gen_ext32s_i64(ret, ret);
2857 #endif
2860 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2861 target_long ofs)
2863 tcg_gen_addi_tl(ret, base, ofs);
2865 #if defined(TARGET_MIPS64)
2866 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2867 tcg_gen_ext32s_i64(ret, ret);
2869 #endif
2872 /* Addresses computation (translation time) */
2873 static target_long addr_add(DisasContext *ctx, target_long base,
2874 target_long offset)
2876 target_long sum = base + offset;
2878 #if defined(TARGET_MIPS64)
2879 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2880 sum = (int32_t)sum;
2882 #endif
2883 return sum;
2886 /* Sign-extract the low 32-bits to a target_long. */
2887 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2889 #if defined(TARGET_MIPS64)
2890 tcg_gen_ext32s_i64(ret, arg);
2891 #else
2892 tcg_gen_extrl_i64_i32(ret, arg);
2893 #endif
2896 /* Sign-extract the high 32-bits to a target_long. */
2897 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2899 #if defined(TARGET_MIPS64)
2900 tcg_gen_sari_i64(ret, arg, 32);
2901 #else
2902 tcg_gen_extrh_i64_i32(ret, arg);
2903 #endif
2906 static inline void check_cp0_enabled(DisasContext *ctx)
2908 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2909 generate_exception_err(ctx, EXCP_CpU, 0);
2912 static inline void check_cp1_enabled(DisasContext *ctx)
2914 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2915 generate_exception_err(ctx, EXCP_CpU, 1);
2918 /* Verify that the processor is running with COP1X instructions enabled.
2919 This is associated with the nabla symbol in the MIPS32 and MIPS64
2920 opcode tables. */
2922 static inline void check_cop1x(DisasContext *ctx)
2924 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2925 generate_exception_end(ctx, EXCP_RI);
2928 /* Verify that the processor is running with 64-bit floating-point
2929 operations enabled. */
2931 static inline void check_cp1_64bitmode(DisasContext *ctx)
2933 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2934 generate_exception_end(ctx, EXCP_RI);
2938 * Verify if floating point register is valid; an operation is not defined
2939 * if bit 0 of any register specification is set and the FR bit in the
2940 * Status register equals zero, since the register numbers specify an
2941 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2942 * in the Status register equals one, both even and odd register numbers
2943 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2945 * Multiple 64 bit wide registers can be checked by calling
2946 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2948 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2950 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2951 generate_exception_end(ctx, EXCP_RI);
2954 /* Verify that the processor is running with DSP instructions enabled.
2955 This is enabled by CP0 Status register MX(24) bit.
2958 static inline void check_dsp(DisasContext *ctx)
2960 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2961 if (ctx->insn_flags & ASE_DSP) {
2962 generate_exception_end(ctx, EXCP_DSPDIS);
2963 } else {
2964 generate_exception_end(ctx, EXCP_RI);
2969 static inline void check_dsp_r2(DisasContext *ctx)
2971 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2972 if (ctx->insn_flags & ASE_DSP) {
2973 generate_exception_end(ctx, EXCP_DSPDIS);
2974 } else {
2975 generate_exception_end(ctx, EXCP_RI);
2980 static inline void check_dsp_r3(DisasContext *ctx)
2982 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2983 if (ctx->insn_flags & ASE_DSP) {
2984 generate_exception_end(ctx, EXCP_DSPDIS);
2985 } else {
2986 generate_exception_end(ctx, EXCP_RI);
2991 /* This code generates a "reserved instruction" exception if the
2992 CPU does not support the instruction set corresponding to flags. */
2993 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2995 if (unlikely(!(ctx->insn_flags & flags))) {
2996 generate_exception_end(ctx, EXCP_RI);
3000 /* This code generates a "reserved instruction" exception if the
3001 CPU has corresponding flag set which indicates that the instruction
3002 has been removed. */
3003 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3005 if (unlikely(ctx->insn_flags & flags)) {
3006 generate_exception_end(ctx, EXCP_RI);
3011 * The Linux kernel traps certain reserved instruction exceptions to
3012 * emulate the corresponding instructions. QEMU is the kernel in user
3013 * mode, so those traps are emulated by accepting the instructions.
3015 * A reserved instruction exception is generated for flagged CPUs if
3016 * QEMU runs in system mode.
3018 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3020 #ifndef CONFIG_USER_ONLY
3021 check_insn_opc_removed(ctx, flags);
3022 #endif
3025 /* This code generates a "reserved instruction" exception if the
3026 CPU does not support 64-bit paired-single (PS) floating point data type */
3027 static inline void check_ps(DisasContext *ctx)
3029 if (unlikely(!ctx->ps)) {
3030 generate_exception(ctx, EXCP_RI);
3032 check_cp1_64bitmode(ctx);
3035 #ifdef TARGET_MIPS64
3036 /* This code generates a "reserved instruction" exception if 64-bit
3037 instructions are not enabled. */
3038 static inline void check_mips_64(DisasContext *ctx)
3040 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
3041 generate_exception_end(ctx, EXCP_RI);
3043 #endif
3045 #ifndef CONFIG_USER_ONLY
3046 static inline void check_mvh(DisasContext *ctx)
3048 if (unlikely(!ctx->mvh)) {
3049 generate_exception(ctx, EXCP_RI);
3052 #endif
3055 * This code generates a "reserved instruction" exception if the
3056 * Config5 XNP bit is set.
3058 static inline void check_xnp(DisasContext *ctx)
3060 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3061 generate_exception_end(ctx, EXCP_RI);
3065 #ifndef CONFIG_USER_ONLY
3067 * This code generates a "reserved instruction" exception if the
3068 * Config3 PW bit is NOT set.
3070 static inline void check_pw(DisasContext *ctx)
3072 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3073 generate_exception_end(ctx, EXCP_RI);
3076 #endif
3079 * This code generates a "reserved instruction" exception if the
3080 * Config3 MT bit is NOT set.
3082 static inline void check_mt(DisasContext *ctx)
3084 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3085 generate_exception_end(ctx, EXCP_RI);
3089 #ifndef CONFIG_USER_ONLY
3091 * This code generates a "coprocessor unusable" exception if CP0 is not
3092 * available, and, if that is not the case, generates a "reserved instruction"
3093 * exception if the Config5 MT bit is NOT set. This is needed for availability
3094 * control of some of MT ASE instructions.
3096 static inline void check_cp0_mt(DisasContext *ctx)
3098 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3099 generate_exception_err(ctx, EXCP_CpU, 0);
3100 } else {
3101 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3102 generate_exception_err(ctx, EXCP_RI, 0);
3106 #endif
3109 * This code generates a "reserved instruction" exception if the
3110 * Config5 NMS bit is set.
3112 static inline void check_nms(DisasContext *ctx)
3114 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3115 generate_exception_end(ctx, EXCP_RI);
3120 * This code generates a "reserved instruction" exception if the
3121 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3122 * Config2 TL, and Config5 L2C are unset.
3124 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3126 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3127 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3128 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3129 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3130 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3131 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3133 generate_exception_end(ctx, EXCP_RI);
3138 * This code generates a "reserved instruction" exception if the
3139 * Config5 EVA bit is NOT set.
3141 static inline void check_eva(DisasContext *ctx)
3143 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3144 generate_exception_end(ctx, EXCP_RI);
3149 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3150 calling interface for 32 and 64-bit FPRs. No sense in changing
3151 all callers for gen_load_fpr32 when we need the CTX parameter for
3152 this one use. */
3153 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3154 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3155 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3156 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3157 int ft, int fs, int cc) \
3159 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3160 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3161 switch (ifmt) { \
3162 case FMT_PS: \
3163 check_ps(ctx); \
3164 break; \
3165 case FMT_D: \
3166 if (abs) { \
3167 check_cop1x(ctx); \
3169 check_cp1_registers(ctx, fs | ft); \
3170 break; \
3171 case FMT_S: \
3172 if (abs) { \
3173 check_cop1x(ctx); \
3175 break; \
3177 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3178 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3179 switch (n) { \
3180 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3181 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3182 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3183 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3184 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3185 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3186 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3187 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3188 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3189 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3190 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3191 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3192 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3193 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3194 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3195 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3196 default: abort(); \
3198 tcg_temp_free_i##bits (fp0); \
3199 tcg_temp_free_i##bits (fp1); \
3202 FOP_CONDS(, 0, d, FMT_D, 64)
3203 FOP_CONDS(abs, 1, d, FMT_D, 64)
3204 FOP_CONDS(, 0, s, FMT_S, 32)
3205 FOP_CONDS(abs, 1, s, FMT_S, 32)
3206 FOP_CONDS(, 0, ps, FMT_PS, 64)
3207 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3208 #undef FOP_CONDS
3210 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3211 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3212 int ft, int fs, int fd) \
3214 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3215 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3216 if (ifmt == FMT_D) { \
3217 check_cp1_registers(ctx, fs | ft | fd); \
3219 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3220 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3221 switch (n) { \
3222 case 0: \
3223 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3224 break; \
3225 case 1: \
3226 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3227 break; \
3228 case 2: \
3229 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3230 break; \
3231 case 3: \
3232 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3233 break; \
3234 case 4: \
3235 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3236 break; \
3237 case 5: \
3238 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3239 break; \
3240 case 6: \
3241 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3242 break; \
3243 case 7: \
3244 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3245 break; \
3246 case 8: \
3247 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3248 break; \
3249 case 9: \
3250 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3251 break; \
3252 case 10: \
3253 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3254 break; \
3255 case 11: \
3256 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3257 break; \
3258 case 12: \
3259 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3260 break; \
3261 case 13: \
3262 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3263 break; \
3264 case 14: \
3265 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3266 break; \
3267 case 15: \
3268 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3269 break; \
3270 case 17: \
3271 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3272 break; \
3273 case 18: \
3274 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3275 break; \
3276 case 19: \
3277 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3278 break; \
3279 case 25: \
3280 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3281 break; \
3282 case 26: \
3283 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3284 break; \
3285 case 27: \
3286 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3287 break; \
3288 default: \
3289 abort(); \
3291 STORE; \
3292 tcg_temp_free_i ## bits (fp0); \
3293 tcg_temp_free_i ## bits (fp1); \
3296 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3297 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3298 #undef FOP_CONDNS
3299 #undef gen_ldcmp_fpr32
3300 #undef gen_ldcmp_fpr64
3302 /* load/store instructions. */
3303 #ifdef CONFIG_USER_ONLY
3304 #define OP_LD_ATOMIC(insn,fname) \
3305 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3306 DisasContext *ctx) \
3308 TCGv t0 = tcg_temp_new(); \
3309 tcg_gen_mov_tl(t0, arg1); \
3310 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3311 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3312 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3313 tcg_temp_free(t0); \
3315 #else
3316 #define OP_LD_ATOMIC(insn,fname) \
3317 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3318 DisasContext *ctx) \
3320 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3322 #endif
3323 OP_LD_ATOMIC(ll,ld32s);
3324 #if defined(TARGET_MIPS64)
3325 OP_LD_ATOMIC(lld,ld64);
3326 #endif
3327 #undef OP_LD_ATOMIC
3329 #ifdef CONFIG_USER_ONLY
3330 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3331 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3332 DisasContext *ctx) \
3334 TCGv t0 = tcg_temp_new(); \
3335 TCGLabel *l1 = gen_new_label(); \
3336 TCGLabel *l2 = gen_new_label(); \
3338 tcg_gen_andi_tl(t0, arg2, almask); \
3339 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3340 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3341 generate_exception(ctx, EXCP_AdES); \
3342 gen_set_label(l1); \
3343 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3344 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3345 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3346 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3347 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3348 generate_exception_end(ctx, EXCP_SC); \
3349 gen_set_label(l2); \
3350 tcg_gen_movi_tl(t0, 0); \
3351 gen_store_gpr(t0, rt); \
3352 tcg_temp_free(t0); \
3354 #else
3355 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3356 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3357 DisasContext *ctx) \
3359 TCGv t0 = tcg_temp_new(); \
3360 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3361 gen_store_gpr(t0, rt); \
3362 tcg_temp_free(t0); \
3364 #endif
3365 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3366 #if defined(TARGET_MIPS64)
3367 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3368 #endif
3369 #undef OP_ST_ATOMIC
3371 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3372 int base, int offset)
3374 if (base == 0) {
3375 tcg_gen_movi_tl(addr, offset);
3376 } else if (offset == 0) {
3377 gen_load_gpr(addr, base);
3378 } else {
3379 tcg_gen_movi_tl(addr, offset);
3380 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3384 static target_ulong pc_relative_pc (DisasContext *ctx)
3386 target_ulong pc = ctx->base.pc_next;
3388 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3389 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3391 pc -= branch_bytes;
3394 pc &= ~(target_ulong)3;
3395 return pc;
3398 /* Load */
3399 static void gen_ld(DisasContext *ctx, uint32_t opc,
3400 int rt, int base, int offset)
3402 TCGv t0, t1, t2;
3403 int mem_idx = ctx->mem_idx;
3405 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3406 /* Loongson CPU uses a load to zero register for prefetch.
3407 We emulate it as a NOP. On other CPU we must perform the
3408 actual memory access. */
3409 return;
3412 t0 = tcg_temp_new();
3413 gen_base_offset_addr(ctx, t0, base, offset);
3415 switch (opc) {
3416 #if defined(TARGET_MIPS64)
3417 case OPC_LWU:
3418 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3419 ctx->default_tcg_memop_mask);
3420 gen_store_gpr(t0, rt);
3421 break;
3422 case OPC_LD:
3423 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3424 ctx->default_tcg_memop_mask);
3425 gen_store_gpr(t0, rt);
3426 break;
3427 case OPC_LLD:
3428 case R6_OPC_LLD:
3429 op_ld_lld(t0, t0, mem_idx, ctx);
3430 gen_store_gpr(t0, rt);
3431 break;
3432 case OPC_LDL:
3433 t1 = tcg_temp_new();
3434 /* Do a byte access to possibly trigger a page
3435 fault with the unaligned address. */
3436 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3437 tcg_gen_andi_tl(t1, t0, 7);
3438 #ifndef TARGET_WORDS_BIGENDIAN
3439 tcg_gen_xori_tl(t1, t1, 7);
3440 #endif
3441 tcg_gen_shli_tl(t1, t1, 3);
3442 tcg_gen_andi_tl(t0, t0, ~7);
3443 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3444 tcg_gen_shl_tl(t0, t0, t1);
3445 t2 = tcg_const_tl(-1);
3446 tcg_gen_shl_tl(t2, t2, t1);
3447 gen_load_gpr(t1, rt);
3448 tcg_gen_andc_tl(t1, t1, t2);
3449 tcg_temp_free(t2);
3450 tcg_gen_or_tl(t0, t0, t1);
3451 tcg_temp_free(t1);
3452 gen_store_gpr(t0, rt);
3453 break;
3454 case OPC_LDR:
3455 t1 = tcg_temp_new();
3456 /* Do a byte access to possibly trigger a page
3457 fault with the unaligned address. */
3458 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3459 tcg_gen_andi_tl(t1, t0, 7);
3460 #ifdef TARGET_WORDS_BIGENDIAN
3461 tcg_gen_xori_tl(t1, t1, 7);
3462 #endif
3463 tcg_gen_shli_tl(t1, t1, 3);
3464 tcg_gen_andi_tl(t0, t0, ~7);
3465 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3466 tcg_gen_shr_tl(t0, t0, t1);
3467 tcg_gen_xori_tl(t1, t1, 63);
3468 t2 = tcg_const_tl(0xfffffffffffffffeull);
3469 tcg_gen_shl_tl(t2, t2, t1);
3470 gen_load_gpr(t1, rt);
3471 tcg_gen_and_tl(t1, t1, t2);
3472 tcg_temp_free(t2);
3473 tcg_gen_or_tl(t0, t0, t1);
3474 tcg_temp_free(t1);
3475 gen_store_gpr(t0, rt);
3476 break;
3477 case OPC_LDPC:
3478 t1 = tcg_const_tl(pc_relative_pc(ctx));
3479 gen_op_addr_add(ctx, t0, t0, t1);
3480 tcg_temp_free(t1);
3481 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3482 gen_store_gpr(t0, rt);
3483 break;
3484 #endif
3485 case OPC_LWPC:
3486 t1 = tcg_const_tl(pc_relative_pc(ctx));
3487 gen_op_addr_add(ctx, t0, t0, t1);
3488 tcg_temp_free(t1);
3489 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3490 gen_store_gpr(t0, rt);
3491 break;
3492 case OPC_LWE:
3493 mem_idx = MIPS_HFLAG_UM;
3494 /* fall through */
3495 case OPC_LW:
3496 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3497 ctx->default_tcg_memop_mask);
3498 gen_store_gpr(t0, rt);
3499 break;
3500 case OPC_LHE:
3501 mem_idx = MIPS_HFLAG_UM;
3502 /* fall through */
3503 case OPC_LH:
3504 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3505 ctx->default_tcg_memop_mask);
3506 gen_store_gpr(t0, rt);
3507 break;
3508 case OPC_LHUE:
3509 mem_idx = MIPS_HFLAG_UM;
3510 /* fall through */
3511 case OPC_LHU:
3512 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3513 ctx->default_tcg_memop_mask);
3514 gen_store_gpr(t0, rt);
3515 break;
3516 case OPC_LBE:
3517 mem_idx = MIPS_HFLAG_UM;
3518 /* fall through */
3519 case OPC_LB:
3520 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3521 gen_store_gpr(t0, rt);
3522 break;
3523 case OPC_LBUE:
3524 mem_idx = MIPS_HFLAG_UM;
3525 /* fall through */
3526 case OPC_LBU:
3527 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3528 gen_store_gpr(t0, rt);
3529 break;
3530 case OPC_LWLE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
3533 case OPC_LWL:
3534 t1 = tcg_temp_new();
3535 /* Do a byte access to possibly trigger a page
3536 fault with the unaligned address. */
3537 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3538 tcg_gen_andi_tl(t1, t0, 3);
3539 #ifndef TARGET_WORDS_BIGENDIAN
3540 tcg_gen_xori_tl(t1, t1, 3);
3541 #endif
3542 tcg_gen_shli_tl(t1, t1, 3);
3543 tcg_gen_andi_tl(t0, t0, ~3);
3544 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3545 tcg_gen_shl_tl(t0, t0, t1);
3546 t2 = tcg_const_tl(-1);
3547 tcg_gen_shl_tl(t2, t2, t1);
3548 gen_load_gpr(t1, rt);
3549 tcg_gen_andc_tl(t1, t1, t2);
3550 tcg_temp_free(t2);
3551 tcg_gen_or_tl(t0, t0, t1);
3552 tcg_temp_free(t1);
3553 tcg_gen_ext32s_tl(t0, t0);
3554 gen_store_gpr(t0, rt);
3555 break;
3556 case OPC_LWRE:
3557 mem_idx = MIPS_HFLAG_UM;
3558 /* fall through */
3559 case OPC_LWR:
3560 t1 = tcg_temp_new();
3561 /* Do a byte access to possibly trigger a page
3562 fault with the unaligned address. */
3563 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3564 tcg_gen_andi_tl(t1, t0, 3);
3565 #ifdef TARGET_WORDS_BIGENDIAN
3566 tcg_gen_xori_tl(t1, t1, 3);
3567 #endif
3568 tcg_gen_shli_tl(t1, t1, 3);
3569 tcg_gen_andi_tl(t0, t0, ~3);
3570 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3571 tcg_gen_shr_tl(t0, t0, t1);
3572 tcg_gen_xori_tl(t1, t1, 31);
3573 t2 = tcg_const_tl(0xfffffffeull);
3574 tcg_gen_shl_tl(t2, t2, t1);
3575 gen_load_gpr(t1, rt);
3576 tcg_gen_and_tl(t1, t1, t2);
3577 tcg_temp_free(t2);
3578 tcg_gen_or_tl(t0, t0, t1);
3579 tcg_temp_free(t1);
3580 tcg_gen_ext32s_tl(t0, t0);
3581 gen_store_gpr(t0, rt);
3582 break;
3583 case OPC_LLE:
3584 mem_idx = MIPS_HFLAG_UM;
3585 /* fall through */
3586 case OPC_LL:
3587 case R6_OPC_LL:
3588 op_ld_ll(t0, t0, mem_idx, ctx);
3589 gen_store_gpr(t0, rt);
3590 break;
3592 tcg_temp_free(t0);
3595 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3596 uint32_t reg1, uint32_t reg2)
3598 TCGv taddr = tcg_temp_new();
3599 TCGv_i64 tval = tcg_temp_new_i64();
3600 TCGv tmp1 = tcg_temp_new();
3601 TCGv tmp2 = tcg_temp_new();
3603 gen_base_offset_addr(ctx, taddr, base, offset);
3604 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3605 #ifdef TARGET_WORDS_BIGENDIAN
3606 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3607 #else
3608 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3609 #endif
3610 gen_store_gpr(tmp1, reg1);
3611 tcg_temp_free(tmp1);
3612 gen_store_gpr(tmp2, reg2);
3613 tcg_temp_free(tmp2);
3614 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3615 tcg_temp_free_i64(tval);
3616 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3617 tcg_temp_free(taddr);
3620 /* Store */
3621 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3622 int base, int offset)
3624 TCGv t0 = tcg_temp_new();
3625 TCGv t1 = tcg_temp_new();
3626 int mem_idx = ctx->mem_idx;
3628 gen_base_offset_addr(ctx, t0, base, offset);
3629 gen_load_gpr(t1, rt);
3630 switch (opc) {
3631 #if defined(TARGET_MIPS64)
3632 case OPC_SD:
3633 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3634 ctx->default_tcg_memop_mask);
3635 break;
3636 case OPC_SDL:
3637 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3638 break;
3639 case OPC_SDR:
3640 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3641 break;
3642 #endif
3643 case OPC_SWE:
3644 mem_idx = MIPS_HFLAG_UM;
3645 /* fall through */
3646 case OPC_SW:
3647 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3648 ctx->default_tcg_memop_mask);
3649 break;
3650 case OPC_SHE:
3651 mem_idx = MIPS_HFLAG_UM;
3652 /* fall through */
3653 case OPC_SH:
3654 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3655 ctx->default_tcg_memop_mask);
3656 break;
3657 case OPC_SBE:
3658 mem_idx = MIPS_HFLAG_UM;
3659 /* fall through */
3660 case OPC_SB:
3661 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3662 break;
3663 case OPC_SWLE:
3664 mem_idx = MIPS_HFLAG_UM;
3665 /* fall through */
3666 case OPC_SWL:
3667 gen_helper_0e2i(swl, t1, t0, mem_idx);
3668 break;
3669 case OPC_SWRE:
3670 mem_idx = MIPS_HFLAG_UM;
3671 /* fall through */
3672 case OPC_SWR:
3673 gen_helper_0e2i(swr, t1, t0, mem_idx);
3674 break;
3676 tcg_temp_free(t0);
3677 tcg_temp_free(t1);
3681 /* Store conditional */
3682 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3683 int base, int16_t offset)
3685 TCGv t0, t1;
3686 int mem_idx = ctx->mem_idx;
3688 #ifdef CONFIG_USER_ONLY
3689 t0 = tcg_temp_local_new();
3690 t1 = tcg_temp_local_new();
3691 #else
3692 t0 = tcg_temp_new();
3693 t1 = tcg_temp_new();
3694 #endif
3695 gen_base_offset_addr(ctx, t0, base, offset);
3696 gen_load_gpr(t1, rt);
3697 switch (opc) {
3698 #if defined(TARGET_MIPS64)
3699 case OPC_SCD:
3700 case R6_OPC_SCD:
3701 op_st_scd(t1, t0, rt, mem_idx, ctx);
3702 break;
3703 #endif
3704 case OPC_SCE:
3705 mem_idx = MIPS_HFLAG_UM;
3706 /* fall through */
3707 case OPC_SC:
3708 case R6_OPC_SC:
3709 op_st_sc(t1, t0, rt, mem_idx, ctx);
3710 break;
3712 tcg_temp_free(t1);
3713 tcg_temp_free(t0);
3716 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3717 uint32_t reg1, uint32_t reg2)
3719 TCGv taddr = tcg_temp_local_new();
3720 TCGv lladdr = tcg_temp_local_new();
3721 TCGv_i64 tval = tcg_temp_new_i64();
3722 TCGv_i64 llval = tcg_temp_new_i64();
3723 TCGv_i64 val = tcg_temp_new_i64();
3724 TCGv tmp1 = tcg_temp_new();
3725 TCGv tmp2 = tcg_temp_new();
3726 TCGLabel *lab_fail = gen_new_label();
3727 TCGLabel *lab_done = gen_new_label();
3729 gen_base_offset_addr(ctx, taddr, base, offset);
3731 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3732 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3734 gen_load_gpr(tmp1, reg1);
3735 gen_load_gpr(tmp2, reg2);
3737 #ifdef TARGET_WORDS_BIGENDIAN
3738 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3739 #else
3740 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3741 #endif
3743 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3744 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3745 ctx->mem_idx, MO_64);
3746 if (reg1 != 0) {
3747 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3749 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3751 gen_set_label(lab_fail);
3753 if (reg1 != 0) {
3754 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3756 gen_set_label(lab_done);
3757 tcg_gen_movi_tl(lladdr, -1);
3758 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3761 /* Load and store */
3762 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3763 TCGv t0)
3765 /* Don't do NOP if destination is zero: we must perform the actual
3766 memory access. */
3767 switch (opc) {
3768 case OPC_LWC1:
3770 TCGv_i32 fp0 = tcg_temp_new_i32();
3771 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3772 ctx->default_tcg_memop_mask);
3773 gen_store_fpr32(ctx, fp0, ft);
3774 tcg_temp_free_i32(fp0);
3776 break;
3777 case OPC_SWC1:
3779 TCGv_i32 fp0 = tcg_temp_new_i32();
3780 gen_load_fpr32(ctx, fp0, ft);
3781 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3782 ctx->default_tcg_memop_mask);
3783 tcg_temp_free_i32(fp0);
3785 break;
3786 case OPC_LDC1:
3788 TCGv_i64 fp0 = tcg_temp_new_i64();
3789 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3790 ctx->default_tcg_memop_mask);
3791 gen_store_fpr64(ctx, fp0, ft);
3792 tcg_temp_free_i64(fp0);
3794 break;
3795 case OPC_SDC1:
3797 TCGv_i64 fp0 = tcg_temp_new_i64();
3798 gen_load_fpr64(ctx, fp0, ft);
3799 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3800 ctx->default_tcg_memop_mask);
3801 tcg_temp_free_i64(fp0);
3803 break;
3804 default:
3805 MIPS_INVAL("flt_ldst");
3806 generate_exception_end(ctx, EXCP_RI);
3807 break;
3811 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3812 int rs, int16_t imm)
3814 TCGv t0 = tcg_temp_new();
3816 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3817 check_cp1_enabled(ctx);
3818 switch (op) {
3819 case OPC_LDC1:
3820 case OPC_SDC1:
3821 check_insn(ctx, ISA_MIPS2);
3822 /* Fallthrough */
3823 default:
3824 gen_base_offset_addr(ctx, t0, rs, imm);
3825 gen_flt_ldst(ctx, op, rt, t0);
3827 } else {
3828 generate_exception_err(ctx, EXCP_CpU, 1);
3830 tcg_temp_free(t0);
3833 /* Arithmetic with immediate operand */
3834 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3835 int rt, int rs, int imm)
3837 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3839 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3840 /* If no destination, treat it as a NOP.
3841 For addi, we must generate the overflow exception when needed. */
3842 return;
3844 switch (opc) {
3845 case OPC_ADDI:
3847 TCGv t0 = tcg_temp_local_new();
3848 TCGv t1 = tcg_temp_new();
3849 TCGv t2 = tcg_temp_new();
3850 TCGLabel *l1 = gen_new_label();
3852 gen_load_gpr(t1, rs);
3853 tcg_gen_addi_tl(t0, t1, uimm);
3854 tcg_gen_ext32s_tl(t0, t0);
3856 tcg_gen_xori_tl(t1, t1, ~uimm);
3857 tcg_gen_xori_tl(t2, t0, uimm);
3858 tcg_gen_and_tl(t1, t1, t2);
3859 tcg_temp_free(t2);
3860 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3861 tcg_temp_free(t1);
3862 /* operands of same sign, result different sign */
3863 generate_exception(ctx, EXCP_OVERFLOW);
3864 gen_set_label(l1);
3865 tcg_gen_ext32s_tl(t0, t0);
3866 gen_store_gpr(t0, rt);
3867 tcg_temp_free(t0);
3869 break;
3870 case OPC_ADDIU:
3871 if (rs != 0) {
3872 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3873 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3874 } else {
3875 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3877 break;
3878 #if defined(TARGET_MIPS64)
3879 case OPC_DADDI:
3881 TCGv t0 = tcg_temp_local_new();
3882 TCGv t1 = tcg_temp_new();
3883 TCGv t2 = tcg_temp_new();
3884 TCGLabel *l1 = gen_new_label();
3886 gen_load_gpr(t1, rs);
3887 tcg_gen_addi_tl(t0, t1, uimm);
3889 tcg_gen_xori_tl(t1, t1, ~uimm);
3890 tcg_gen_xori_tl(t2, t0, uimm);
3891 tcg_gen_and_tl(t1, t1, t2);
3892 tcg_temp_free(t2);
3893 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3894 tcg_temp_free(t1);
3895 /* operands of same sign, result different sign */
3896 generate_exception(ctx, EXCP_OVERFLOW);
3897 gen_set_label(l1);
3898 gen_store_gpr(t0, rt);
3899 tcg_temp_free(t0);
3901 break;
3902 case OPC_DADDIU:
3903 if (rs != 0) {
3904 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3908 break;
3909 #endif
3913 /* Logic with immediate operand */
3914 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3915 int rt, int rs, int16_t imm)
3917 target_ulong uimm;
3919 if (rt == 0) {
3920 /* If no destination, treat it as a NOP. */
3921 return;
3923 uimm = (uint16_t)imm;
3924 switch (opc) {
3925 case OPC_ANDI:
3926 if (likely(rs != 0))
3927 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3928 else
3929 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3930 break;
3931 case OPC_ORI:
3932 if (rs != 0)
3933 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3934 else
3935 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3936 break;
3937 case OPC_XORI:
3938 if (likely(rs != 0))
3939 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3940 else
3941 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3942 break;
3943 case OPC_LUI:
3944 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3945 /* OPC_AUI */
3946 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3947 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3948 } else {
3949 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3951 break;
3953 default:
3954 break;
3958 /* Set on less than with immediate operand */
3959 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3960 int rt, int rs, int16_t imm)
3962 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3963 TCGv t0;
3965 if (rt == 0) {
3966 /* If no destination, treat it as a NOP. */
3967 return;
3969 t0 = tcg_temp_new();
3970 gen_load_gpr(t0, rs);
3971 switch (opc) {
3972 case OPC_SLTI:
3973 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3974 break;
3975 case OPC_SLTIU:
3976 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3977 break;
3979 tcg_temp_free(t0);
3982 /* Shifts with immediate operand */
3983 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3984 int rt, int rs, int16_t imm)
3986 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3987 TCGv t0;
3989 if (rt == 0) {
3990 /* If no destination, treat it as a NOP. */
3991 return;
3994 t0 = tcg_temp_new();
3995 gen_load_gpr(t0, rs);
3996 switch (opc) {
3997 case OPC_SLL:
3998 tcg_gen_shli_tl(t0, t0, uimm);
3999 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4000 break;
4001 case OPC_SRA:
4002 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4003 break;
4004 case OPC_SRL:
4005 if (uimm != 0) {
4006 tcg_gen_ext32u_tl(t0, t0);
4007 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4008 } else {
4009 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4011 break;
4012 case OPC_ROTR:
4013 if (uimm != 0) {
4014 TCGv_i32 t1 = tcg_temp_new_i32();
4016 tcg_gen_trunc_tl_i32(t1, t0);
4017 tcg_gen_rotri_i32(t1, t1, uimm);
4018 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4019 tcg_temp_free_i32(t1);
4020 } else {
4021 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4023 break;
4024 #if defined(TARGET_MIPS64)
4025 case OPC_DSLL:
4026 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4027 break;
4028 case OPC_DSRA:
4029 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4030 break;
4031 case OPC_DSRL:
4032 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4033 break;
4034 case OPC_DROTR:
4035 if (uimm != 0) {
4036 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4037 } else {
4038 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4040 break;
4041 case OPC_DSLL32:
4042 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4043 break;
4044 case OPC_DSRA32:
4045 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4046 break;
4047 case OPC_DSRL32:
4048 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4049 break;
4050 case OPC_DROTR32:
4051 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4052 break;
4053 #endif
4055 tcg_temp_free(t0);
4058 /* Arithmetic */
4059 static void gen_arith(DisasContext *ctx, uint32_t opc,
4060 int rd, int rs, int rt)
4062 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4063 && opc != OPC_DADD && opc != OPC_DSUB) {
4064 /* If no destination, treat it as a NOP.
4065 For add & sub, we must generate the overflow exception when needed. */
4066 return;
4069 switch (opc) {
4070 case OPC_ADD:
4072 TCGv t0 = tcg_temp_local_new();
4073 TCGv t1 = tcg_temp_new();
4074 TCGv t2 = tcg_temp_new();
4075 TCGLabel *l1 = gen_new_label();
4077 gen_load_gpr(t1, rs);
4078 gen_load_gpr(t2, rt);
4079 tcg_gen_add_tl(t0, t1, t2);
4080 tcg_gen_ext32s_tl(t0, t0);
4081 tcg_gen_xor_tl(t1, t1, t2);
4082 tcg_gen_xor_tl(t2, t0, t2);
4083 tcg_gen_andc_tl(t1, t2, t1);
4084 tcg_temp_free(t2);
4085 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4086 tcg_temp_free(t1);
4087 /* operands of same sign, result different sign */
4088 generate_exception(ctx, EXCP_OVERFLOW);
4089 gen_set_label(l1);
4090 gen_store_gpr(t0, rd);
4091 tcg_temp_free(t0);
4093 break;
4094 case OPC_ADDU:
4095 if (rs != 0 && rt != 0) {
4096 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4097 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4098 } else if (rs == 0 && rt != 0) {
4099 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4100 } else if (rs != 0 && rt == 0) {
4101 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4102 } else {
4103 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4105 break;
4106 case OPC_SUB:
4108 TCGv t0 = tcg_temp_local_new();
4109 TCGv t1 = tcg_temp_new();
4110 TCGv t2 = tcg_temp_new();
4111 TCGLabel *l1 = gen_new_label();
4113 gen_load_gpr(t1, rs);
4114 gen_load_gpr(t2, rt);
4115 tcg_gen_sub_tl(t0, t1, t2);
4116 tcg_gen_ext32s_tl(t0, t0);
4117 tcg_gen_xor_tl(t2, t1, t2);
4118 tcg_gen_xor_tl(t1, t0, t1);
4119 tcg_gen_and_tl(t1, t1, t2);
4120 tcg_temp_free(t2);
4121 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4122 tcg_temp_free(t1);
4123 /* operands of different sign, first operand and result different sign */
4124 generate_exception(ctx, EXCP_OVERFLOW);
4125 gen_set_label(l1);
4126 gen_store_gpr(t0, rd);
4127 tcg_temp_free(t0);
4129 break;
4130 case OPC_SUBU:
4131 if (rs != 0 && rt != 0) {
4132 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4133 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4134 } else if (rs == 0 && rt != 0) {
4135 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4136 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4137 } else if (rs != 0 && rt == 0) {
4138 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4139 } else {
4140 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4142 break;
4143 #if defined(TARGET_MIPS64)
4144 case OPC_DADD:
4146 TCGv t0 = tcg_temp_local_new();
4147 TCGv t1 = tcg_temp_new();
4148 TCGv t2 = tcg_temp_new();
4149 TCGLabel *l1 = gen_new_label();
4151 gen_load_gpr(t1, rs);
4152 gen_load_gpr(t2, rt);
4153 tcg_gen_add_tl(t0, t1, t2);
4154 tcg_gen_xor_tl(t1, t1, t2);
4155 tcg_gen_xor_tl(t2, t0, t2);
4156 tcg_gen_andc_tl(t1, t2, t1);
4157 tcg_temp_free(t2);
4158 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4159 tcg_temp_free(t1);
4160 /* operands of same sign, result different sign */
4161 generate_exception(ctx, EXCP_OVERFLOW);
4162 gen_set_label(l1);
4163 gen_store_gpr(t0, rd);
4164 tcg_temp_free(t0);
4166 break;
4167 case OPC_DADDU:
4168 if (rs != 0 && rt != 0) {
4169 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4170 } else if (rs == 0 && rt != 0) {
4171 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4172 } else if (rs != 0 && rt == 0) {
4173 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4174 } else {
4175 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4177 break;
4178 case OPC_DSUB:
4180 TCGv t0 = tcg_temp_local_new();
4181 TCGv t1 = tcg_temp_new();
4182 TCGv t2 = tcg_temp_new();
4183 TCGLabel *l1 = gen_new_label();
4185 gen_load_gpr(t1, rs);
4186 gen_load_gpr(t2, rt);
4187 tcg_gen_sub_tl(t0, t1, t2);
4188 tcg_gen_xor_tl(t2, t1, t2);
4189 tcg_gen_xor_tl(t1, t0, t1);
4190 tcg_gen_and_tl(t1, t1, t2);
4191 tcg_temp_free(t2);
4192 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4193 tcg_temp_free(t1);
4194 /* operands of different sign, first operand and result different sign */
4195 generate_exception(ctx, EXCP_OVERFLOW);
4196 gen_set_label(l1);
4197 gen_store_gpr(t0, rd);
4198 tcg_temp_free(t0);
4200 break;
4201 case OPC_DSUBU:
4202 if (rs != 0 && rt != 0) {
4203 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4204 } else if (rs == 0 && rt != 0) {
4205 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4206 } else if (rs != 0 && rt == 0) {
4207 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4208 } else {
4209 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4211 break;
4212 #endif
4213 case OPC_MUL:
4214 if (likely(rs != 0 && rt != 0)) {
4215 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4216 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4217 } else {
4218 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4220 break;
4224 /* Conditional move */
4225 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4226 int rd, int rs, int rt)
4228 TCGv t0, t1, t2;
4230 if (rd == 0) {
4231 /* If no destination, treat it as a NOP. */
4232 return;
4235 t0 = tcg_temp_new();
4236 gen_load_gpr(t0, rt);
4237 t1 = tcg_const_tl(0);
4238 t2 = tcg_temp_new();
4239 gen_load_gpr(t2, rs);
4240 switch (opc) {
4241 case OPC_MOVN:
4242 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4243 break;
4244 case OPC_MOVZ:
4245 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4246 break;
4247 case OPC_SELNEZ:
4248 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4249 break;
4250 case OPC_SELEQZ:
4251 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4252 break;
4254 tcg_temp_free(t2);
4255 tcg_temp_free(t1);
4256 tcg_temp_free(t0);
4259 /* Logic */
4260 static void gen_logic(DisasContext *ctx, uint32_t opc,
4261 int rd, int rs, int rt)
4263 if (rd == 0) {
4264 /* If no destination, treat it as a NOP. */
4265 return;
4268 switch (opc) {
4269 case OPC_AND:
4270 if (likely(rs != 0 && rt != 0)) {
4271 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4272 } else {
4273 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4275 break;
4276 case OPC_NOR:
4277 if (rs != 0 && rt != 0) {
4278 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4279 } else if (rs == 0 && rt != 0) {
4280 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4281 } else if (rs != 0 && rt == 0) {
4282 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4283 } else {
4284 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4286 break;
4287 case OPC_OR:
4288 if (likely(rs != 0 && rt != 0)) {
4289 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4290 } else if (rs == 0 && rt != 0) {
4291 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4292 } else if (rs != 0 && rt == 0) {
4293 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4294 } else {
4295 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4297 break;
4298 case OPC_XOR:
4299 if (likely(rs != 0 && rt != 0)) {
4300 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4301 } else if (rs == 0 && rt != 0) {
4302 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4303 } else if (rs != 0 && rt == 0) {
4304 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4305 } else {
4306 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4308 break;
4312 /* Set on lower than */
4313 static void gen_slt(DisasContext *ctx, uint32_t opc,
4314 int rd, int rs, int rt)
4316 TCGv t0, t1;
4318 if (rd == 0) {
4319 /* If no destination, treat it as a NOP. */
4320 return;
4323 t0 = tcg_temp_new();
4324 t1 = tcg_temp_new();
4325 gen_load_gpr(t0, rs);
4326 gen_load_gpr(t1, rt);
4327 switch (opc) {
4328 case OPC_SLT:
4329 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4330 break;
4331 case OPC_SLTU:
4332 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4333 break;
4335 tcg_temp_free(t0);
4336 tcg_temp_free(t1);
4339 /* Shifts */
4340 static void gen_shift(DisasContext *ctx, uint32_t opc,
4341 int rd, int rs, int rt)
4343 TCGv t0, t1;
4345 if (rd == 0) {
4346 /* If no destination, treat it as a NOP.
4347 For add & sub, we must generate the overflow exception when needed. */
4348 return;
4351 t0 = tcg_temp_new();
4352 t1 = tcg_temp_new();
4353 gen_load_gpr(t0, rs);
4354 gen_load_gpr(t1, rt);
4355 switch (opc) {
4356 case OPC_SLLV:
4357 tcg_gen_andi_tl(t0, t0, 0x1f);
4358 tcg_gen_shl_tl(t0, t1, t0);
4359 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4360 break;
4361 case OPC_SRAV:
4362 tcg_gen_andi_tl(t0, t0, 0x1f);
4363 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4364 break;
4365 case OPC_SRLV:
4366 tcg_gen_ext32u_tl(t1, t1);
4367 tcg_gen_andi_tl(t0, t0, 0x1f);
4368 tcg_gen_shr_tl(t0, t1, t0);
4369 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4370 break;
4371 case OPC_ROTRV:
4373 TCGv_i32 t2 = tcg_temp_new_i32();
4374 TCGv_i32 t3 = tcg_temp_new_i32();
4376 tcg_gen_trunc_tl_i32(t2, t0);
4377 tcg_gen_trunc_tl_i32(t3, t1);
4378 tcg_gen_andi_i32(t2, t2, 0x1f);
4379 tcg_gen_rotr_i32(t2, t3, t2);
4380 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4381 tcg_temp_free_i32(t2);
4382 tcg_temp_free_i32(t3);
4384 break;
4385 #if defined(TARGET_MIPS64)
4386 case OPC_DSLLV:
4387 tcg_gen_andi_tl(t0, t0, 0x3f);
4388 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4389 break;
4390 case OPC_DSRAV:
4391 tcg_gen_andi_tl(t0, t0, 0x3f);
4392 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4393 break;
4394 case OPC_DSRLV:
4395 tcg_gen_andi_tl(t0, t0, 0x3f);
4396 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4397 break;
4398 case OPC_DROTRV:
4399 tcg_gen_andi_tl(t0, t0, 0x3f);
4400 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4401 break;
4402 #endif
4404 tcg_temp_free(t0);
4405 tcg_temp_free(t1);
4408 /* Copy GPR to and from TX79 HI1/LO1 register. */
4409 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4411 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4412 /* Treat as NOP. */
4413 return;
4416 switch (opc) {
4417 case MMI_OPC_MFHI1:
4418 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4419 break;
4420 case MMI_OPC_MFLO1:
4421 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4422 break;
4423 case MMI_OPC_MTHI1:
4424 if (reg != 0) {
4425 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4426 } else {
4427 tcg_gen_movi_tl(cpu_HI[1], 0);
4429 break;
4430 case MMI_OPC_MTLO1:
4431 if (reg != 0) {
4432 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4433 } else {
4434 tcg_gen_movi_tl(cpu_LO[1], 0);
4436 break;
4437 default:
4438 MIPS_INVAL("mfthilo1 TX79");
4439 generate_exception_end(ctx, EXCP_RI);
4440 break;
4444 /* Arithmetic on HI/LO registers */
4445 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4447 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4448 /* Treat as NOP. */
4449 return;
4452 if (acc != 0) {
4453 check_dsp(ctx);
4456 switch (opc) {
4457 case OPC_MFHI:
4458 #if defined(TARGET_MIPS64)
4459 if (acc != 0) {
4460 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4461 } else
4462 #endif
4464 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4466 break;
4467 case OPC_MFLO:
4468 #if defined(TARGET_MIPS64)
4469 if (acc != 0) {
4470 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4471 } else
4472 #endif
4474 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4476 break;
4477 case OPC_MTHI:
4478 if (reg != 0) {
4479 #if defined(TARGET_MIPS64)
4480 if (acc != 0) {
4481 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4482 } else
4483 #endif
4485 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4487 } else {
4488 tcg_gen_movi_tl(cpu_HI[acc], 0);
4490 break;
4491 case OPC_MTLO:
4492 if (reg != 0) {
4493 #if defined(TARGET_MIPS64)
4494 if (acc != 0) {
4495 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4496 } else
4497 #endif
4499 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4501 } else {
4502 tcg_gen_movi_tl(cpu_LO[acc], 0);
4504 break;
4508 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4509 TCGMemOp memop)
4511 TCGv t0 = tcg_const_tl(addr);
4512 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4513 gen_store_gpr(t0, reg);
4514 tcg_temp_free(t0);
4517 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4518 int rs)
4520 target_long offset;
4521 target_long addr;
4523 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4524 case OPC_ADDIUPC:
4525 if (rs != 0) {
4526 offset = sextract32(ctx->opcode << 2, 0, 21);
4527 addr = addr_add(ctx, pc, offset);
4528 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4530 break;
4531 case R6_OPC_LWPC:
4532 offset = sextract32(ctx->opcode << 2, 0, 21);
4533 addr = addr_add(ctx, pc, offset);
4534 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4535 break;
4536 #if defined(TARGET_MIPS64)
4537 case OPC_LWUPC:
4538 check_mips_64(ctx);
4539 offset = sextract32(ctx->opcode << 2, 0, 21);
4540 addr = addr_add(ctx, pc, offset);
4541 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4542 break;
4543 #endif
4544 default:
4545 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4546 case OPC_AUIPC:
4547 if (rs != 0) {
4548 offset = sextract32(ctx->opcode, 0, 16) << 16;
4549 addr = addr_add(ctx, pc, offset);
4550 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4552 break;
4553 case OPC_ALUIPC:
4554 if (rs != 0) {
4555 offset = sextract32(ctx->opcode, 0, 16) << 16;
4556 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4557 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4559 break;
4560 #if defined(TARGET_MIPS64)
4561 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4562 case R6_OPC_LDPC + (1 << 16):
4563 case R6_OPC_LDPC + (2 << 16):
4564 case R6_OPC_LDPC + (3 << 16):
4565 check_mips_64(ctx);
4566 offset = sextract32(ctx->opcode << 3, 0, 21);
4567 addr = addr_add(ctx, (pc & ~0x7), offset);
4568 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4569 break;
4570 #endif
4571 default:
4572 MIPS_INVAL("OPC_PCREL");
4573 generate_exception_end(ctx, EXCP_RI);
4574 break;
4576 break;
4580 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4582 TCGv t0, t1;
4584 if (rd == 0) {
4585 /* Treat as NOP. */
4586 return;
4589 t0 = tcg_temp_new();
4590 t1 = tcg_temp_new();
4592 gen_load_gpr(t0, rs);
4593 gen_load_gpr(t1, rt);
4595 switch (opc) {
4596 case R6_OPC_DIV:
4598 TCGv t2 = tcg_temp_new();
4599 TCGv t3 = tcg_temp_new();
4600 tcg_gen_ext32s_tl(t0, t0);
4601 tcg_gen_ext32s_tl(t1, t1);
4602 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4603 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4604 tcg_gen_and_tl(t2, t2, t3);
4605 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4606 tcg_gen_or_tl(t2, t2, t3);
4607 tcg_gen_movi_tl(t3, 0);
4608 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4609 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4610 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4611 tcg_temp_free(t3);
4612 tcg_temp_free(t2);
4614 break;
4615 case R6_OPC_MOD:
4617 TCGv t2 = tcg_temp_new();
4618 TCGv t3 = tcg_temp_new();
4619 tcg_gen_ext32s_tl(t0, t0);
4620 tcg_gen_ext32s_tl(t1, t1);
4621 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4622 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4623 tcg_gen_and_tl(t2, t2, t3);
4624 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4625 tcg_gen_or_tl(t2, t2, t3);
4626 tcg_gen_movi_tl(t3, 0);
4627 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4628 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4629 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4630 tcg_temp_free(t3);
4631 tcg_temp_free(t2);
4633 break;
4634 case R6_OPC_DIVU:
4636 TCGv t2 = tcg_const_tl(0);
4637 TCGv t3 = tcg_const_tl(1);
4638 tcg_gen_ext32u_tl(t0, t0);
4639 tcg_gen_ext32u_tl(t1, t1);
4640 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4641 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4642 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4643 tcg_temp_free(t3);
4644 tcg_temp_free(t2);
4646 break;
4647 case R6_OPC_MODU:
4649 TCGv t2 = tcg_const_tl(0);
4650 TCGv t3 = tcg_const_tl(1);
4651 tcg_gen_ext32u_tl(t0, t0);
4652 tcg_gen_ext32u_tl(t1, t1);
4653 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4654 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4655 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4656 tcg_temp_free(t3);
4657 tcg_temp_free(t2);
4659 break;
4660 case R6_OPC_MUL:
4662 TCGv_i32 t2 = tcg_temp_new_i32();
4663 TCGv_i32 t3 = tcg_temp_new_i32();
4664 tcg_gen_trunc_tl_i32(t2, t0);
4665 tcg_gen_trunc_tl_i32(t3, t1);
4666 tcg_gen_mul_i32(t2, t2, t3);
4667 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4668 tcg_temp_free_i32(t2);
4669 tcg_temp_free_i32(t3);
4671 break;
4672 case R6_OPC_MUH:
4674 TCGv_i32 t2 = tcg_temp_new_i32();
4675 TCGv_i32 t3 = tcg_temp_new_i32();
4676 tcg_gen_trunc_tl_i32(t2, t0);
4677 tcg_gen_trunc_tl_i32(t3, t1);
4678 tcg_gen_muls2_i32(t2, t3, t2, t3);
4679 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4680 tcg_temp_free_i32(t2);
4681 tcg_temp_free_i32(t3);
4683 break;
4684 case R6_OPC_MULU:
4686 TCGv_i32 t2 = tcg_temp_new_i32();
4687 TCGv_i32 t3 = tcg_temp_new_i32();
4688 tcg_gen_trunc_tl_i32(t2, t0);
4689 tcg_gen_trunc_tl_i32(t3, t1);
4690 tcg_gen_mul_i32(t2, t2, t3);
4691 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4692 tcg_temp_free_i32(t2);
4693 tcg_temp_free_i32(t3);
4695 break;
4696 case R6_OPC_MUHU:
4698 TCGv_i32 t2 = tcg_temp_new_i32();
4699 TCGv_i32 t3 = tcg_temp_new_i32();
4700 tcg_gen_trunc_tl_i32(t2, t0);
4701 tcg_gen_trunc_tl_i32(t3, t1);
4702 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4703 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4704 tcg_temp_free_i32(t2);
4705 tcg_temp_free_i32(t3);
4707 break;
4708 #if defined(TARGET_MIPS64)
4709 case R6_OPC_DDIV:
4711 TCGv t2 = tcg_temp_new();
4712 TCGv t3 = tcg_temp_new();
4713 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4714 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4715 tcg_gen_and_tl(t2, t2, t3);
4716 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4717 tcg_gen_or_tl(t2, t2, t3);
4718 tcg_gen_movi_tl(t3, 0);
4719 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4720 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4721 tcg_temp_free(t3);
4722 tcg_temp_free(t2);
4724 break;
4725 case R6_OPC_DMOD:
4727 TCGv t2 = tcg_temp_new();
4728 TCGv t3 = tcg_temp_new();
4729 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4730 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4731 tcg_gen_and_tl(t2, t2, t3);
4732 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4733 tcg_gen_or_tl(t2, t2, t3);
4734 tcg_gen_movi_tl(t3, 0);
4735 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4736 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4737 tcg_temp_free(t3);
4738 tcg_temp_free(t2);
4740 break;
4741 case R6_OPC_DDIVU:
4743 TCGv t2 = tcg_const_tl(0);
4744 TCGv t3 = tcg_const_tl(1);
4745 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4746 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4747 tcg_temp_free(t3);
4748 tcg_temp_free(t2);
4750 break;
4751 case R6_OPC_DMODU:
4753 TCGv t2 = tcg_const_tl(0);
4754 TCGv t3 = tcg_const_tl(1);
4755 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4756 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4757 tcg_temp_free(t3);
4758 tcg_temp_free(t2);
4760 break;
4761 case R6_OPC_DMUL:
4762 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4763 break;
4764 case R6_OPC_DMUH:
4766 TCGv t2 = tcg_temp_new();
4767 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4768 tcg_temp_free(t2);
4770 break;
4771 case R6_OPC_DMULU:
4772 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4773 break;
4774 case R6_OPC_DMUHU:
4776 TCGv t2 = tcg_temp_new();
4777 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4778 tcg_temp_free(t2);
4780 break;
4781 #endif
4782 default:
4783 MIPS_INVAL("r6 mul/div");
4784 generate_exception_end(ctx, EXCP_RI);
4785 goto out;
4787 out:
4788 tcg_temp_free(t0);
4789 tcg_temp_free(t1);
4792 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4794 TCGv t0, t1;
4796 t0 = tcg_temp_new();
4797 t1 = tcg_temp_new();
4799 gen_load_gpr(t0, rs);
4800 gen_load_gpr(t1, rt);
4802 switch (opc) {
4803 case MMI_OPC_DIV1:
4805 TCGv t2 = tcg_temp_new();
4806 TCGv t3 = tcg_temp_new();
4807 tcg_gen_ext32s_tl(t0, t0);
4808 tcg_gen_ext32s_tl(t1, t1);
4809 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4810 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4811 tcg_gen_and_tl(t2, t2, t3);
4812 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4813 tcg_gen_or_tl(t2, t2, t3);
4814 tcg_gen_movi_tl(t3, 0);
4815 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4816 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4817 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4818 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4819 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4820 tcg_temp_free(t3);
4821 tcg_temp_free(t2);
4823 break;
4824 case MMI_OPC_DIVU1:
4826 TCGv t2 = tcg_const_tl(0);
4827 TCGv t3 = tcg_const_tl(1);
4828 tcg_gen_ext32u_tl(t0, t0);
4829 tcg_gen_ext32u_tl(t1, t1);
4830 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4831 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4832 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4833 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4834 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4835 tcg_temp_free(t3);
4836 tcg_temp_free(t2);
4838 break;
4839 default:
4840 MIPS_INVAL("div1 TX79");
4841 generate_exception_end(ctx, EXCP_RI);
4842 goto out;
4844 out:
4845 tcg_temp_free(t0);
4846 tcg_temp_free(t1);
4849 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4850 int acc, int rs, int rt)
4852 TCGv t0, t1;
4854 t0 = tcg_temp_new();
4855 t1 = tcg_temp_new();
4857 gen_load_gpr(t0, rs);
4858 gen_load_gpr(t1, rt);
4860 if (acc != 0) {
4861 check_dsp(ctx);
4864 switch (opc) {
4865 case OPC_DIV:
4867 TCGv t2 = tcg_temp_new();
4868 TCGv t3 = tcg_temp_new();
4869 tcg_gen_ext32s_tl(t0, t0);
4870 tcg_gen_ext32s_tl(t1, t1);
4871 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4872 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4873 tcg_gen_and_tl(t2, t2, t3);
4874 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4875 tcg_gen_or_tl(t2, t2, t3);
4876 tcg_gen_movi_tl(t3, 0);
4877 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4878 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4879 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4880 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4881 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4882 tcg_temp_free(t3);
4883 tcg_temp_free(t2);
4885 break;
4886 case OPC_DIVU:
4888 TCGv t2 = tcg_const_tl(0);
4889 TCGv t3 = tcg_const_tl(1);
4890 tcg_gen_ext32u_tl(t0, t0);
4891 tcg_gen_ext32u_tl(t1, t1);
4892 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4893 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4894 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4895 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4896 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4897 tcg_temp_free(t3);
4898 tcg_temp_free(t2);
4900 break;
4901 case OPC_MULT:
4903 TCGv_i32 t2 = tcg_temp_new_i32();
4904 TCGv_i32 t3 = tcg_temp_new_i32();
4905 tcg_gen_trunc_tl_i32(t2, t0);
4906 tcg_gen_trunc_tl_i32(t3, t1);
4907 tcg_gen_muls2_i32(t2, t3, t2, t3);
4908 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4909 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4910 tcg_temp_free_i32(t2);
4911 tcg_temp_free_i32(t3);
4913 break;
4914 case OPC_MULTU:
4916 TCGv_i32 t2 = tcg_temp_new_i32();
4917 TCGv_i32 t3 = tcg_temp_new_i32();
4918 tcg_gen_trunc_tl_i32(t2, t0);
4919 tcg_gen_trunc_tl_i32(t3, t1);
4920 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4921 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4922 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4923 tcg_temp_free_i32(t2);
4924 tcg_temp_free_i32(t3);
4926 break;
4927 #if defined(TARGET_MIPS64)
4928 case OPC_DDIV:
4930 TCGv t2 = tcg_temp_new();
4931 TCGv t3 = tcg_temp_new();
4932 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4933 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4934 tcg_gen_and_tl(t2, t2, t3);
4935 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4936 tcg_gen_or_tl(t2, t2, t3);
4937 tcg_gen_movi_tl(t3, 0);
4938 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4939 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4940 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4941 tcg_temp_free(t3);
4942 tcg_temp_free(t2);
4944 break;
4945 case OPC_DDIVU:
4947 TCGv t2 = tcg_const_tl(0);
4948 TCGv t3 = tcg_const_tl(1);
4949 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4950 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4951 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4952 tcg_temp_free(t3);
4953 tcg_temp_free(t2);
4955 break;
4956 case OPC_DMULT:
4957 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4958 break;
4959 case OPC_DMULTU:
4960 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4961 break;
4962 #endif
4963 case OPC_MADD:
4965 TCGv_i64 t2 = tcg_temp_new_i64();
4966 TCGv_i64 t3 = tcg_temp_new_i64();
4968 tcg_gen_ext_tl_i64(t2, t0);
4969 tcg_gen_ext_tl_i64(t3, t1);
4970 tcg_gen_mul_i64(t2, t2, t3);
4971 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4972 tcg_gen_add_i64(t2, t2, t3);
4973 tcg_temp_free_i64(t3);
4974 gen_move_low32(cpu_LO[acc], t2);
4975 gen_move_high32(cpu_HI[acc], t2);
4976 tcg_temp_free_i64(t2);
4978 break;
4979 case OPC_MADDU:
4981 TCGv_i64 t2 = tcg_temp_new_i64();
4982 TCGv_i64 t3 = tcg_temp_new_i64();
4984 tcg_gen_ext32u_tl(t0, t0);
4985 tcg_gen_ext32u_tl(t1, t1);
4986 tcg_gen_extu_tl_i64(t2, t0);
4987 tcg_gen_extu_tl_i64(t3, t1);
4988 tcg_gen_mul_i64(t2, t2, t3);
4989 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4990 tcg_gen_add_i64(t2, t2, t3);
4991 tcg_temp_free_i64(t3);
4992 gen_move_low32(cpu_LO[acc], t2);
4993 gen_move_high32(cpu_HI[acc], t2);
4994 tcg_temp_free_i64(t2);
4996 break;
4997 case OPC_MSUB:
4999 TCGv_i64 t2 = tcg_temp_new_i64();
5000 TCGv_i64 t3 = tcg_temp_new_i64();
5002 tcg_gen_ext_tl_i64(t2, t0);
5003 tcg_gen_ext_tl_i64(t3, t1);
5004 tcg_gen_mul_i64(t2, t2, t3);
5005 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5006 tcg_gen_sub_i64(t2, t3, t2);
5007 tcg_temp_free_i64(t3);
5008 gen_move_low32(cpu_LO[acc], t2);
5009 gen_move_high32(cpu_HI[acc], t2);
5010 tcg_temp_free_i64(t2);
5012 break;
5013 case OPC_MSUBU:
5015 TCGv_i64 t2 = tcg_temp_new_i64();
5016 TCGv_i64 t3 = tcg_temp_new_i64();
5018 tcg_gen_ext32u_tl(t0, t0);
5019 tcg_gen_ext32u_tl(t1, t1);
5020 tcg_gen_extu_tl_i64(t2, t0);
5021 tcg_gen_extu_tl_i64(t3, t1);
5022 tcg_gen_mul_i64(t2, t2, t3);
5023 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5024 tcg_gen_sub_i64(t2, t3, t2);
5025 tcg_temp_free_i64(t3);
5026 gen_move_low32(cpu_LO[acc], t2);
5027 gen_move_high32(cpu_HI[acc], t2);
5028 tcg_temp_free_i64(t2);
5030 break;
5031 default:
5032 MIPS_INVAL("mul/div");
5033 generate_exception_end(ctx, EXCP_RI);
5034 goto out;
5036 out:
5037 tcg_temp_free(t0);
5038 tcg_temp_free(t1);
5042 * These MULT[U] and MADD[U] instructions implemented in for example
5043 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5044 * architectures are special three-operand variants with the syntax
5046 * MULT[U][1] rd, rs, rt
5048 * such that
5050 * (rd, LO, HI) <- rs * rt
5052 * and
5054 * MADD[U][1] rd, rs, rt
5056 * such that
5058 * (rd, LO, HI) <- (LO, HI) + rs * rt
5060 * where the low-order 32-bits of the result is placed into both the
5061 * GPR rd and the special register LO. The high-order 32-bits of the
5062 * result is placed into the special register HI.
5064 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5065 * which is the zero register that always reads as 0.
5067 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5068 int rd, int rs, int rt)
5070 TCGv t0 = tcg_temp_new();
5071 TCGv t1 = tcg_temp_new();
5072 int acc = 0;
5074 gen_load_gpr(t0, rs);
5075 gen_load_gpr(t1, rt);
5077 switch (opc) {
5078 case MMI_OPC_MULT1:
5079 acc = 1;
5080 /* Fall through */
5081 case OPC_MULT:
5083 TCGv_i32 t2 = tcg_temp_new_i32();
5084 TCGv_i32 t3 = tcg_temp_new_i32();
5085 tcg_gen_trunc_tl_i32(t2, t0);
5086 tcg_gen_trunc_tl_i32(t3, t1);
5087 tcg_gen_muls2_i32(t2, t3, t2, t3);
5088 if (rd) {
5089 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5091 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5092 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5093 tcg_temp_free_i32(t2);
5094 tcg_temp_free_i32(t3);
5096 break;
5097 case MMI_OPC_MULTU1:
5098 acc = 1;
5099 /* Fall through */
5100 case OPC_MULTU:
5102 TCGv_i32 t2 = tcg_temp_new_i32();
5103 TCGv_i32 t3 = tcg_temp_new_i32();
5104 tcg_gen_trunc_tl_i32(t2, t0);
5105 tcg_gen_trunc_tl_i32(t3, t1);
5106 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5107 if (rd) {
5108 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5110 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5111 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5112 tcg_temp_free_i32(t2);
5113 tcg_temp_free_i32(t3);
5115 break;
5116 case MMI_OPC_MADD1:
5117 acc = 1;
5118 /* Fall through */
5119 case MMI_OPC_MADD:
5121 TCGv_i64 t2 = tcg_temp_new_i64();
5122 TCGv_i64 t3 = tcg_temp_new_i64();
5124 tcg_gen_ext_tl_i64(t2, t0);
5125 tcg_gen_ext_tl_i64(t3, t1);
5126 tcg_gen_mul_i64(t2, t2, t3);
5127 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5128 tcg_gen_add_i64(t2, t2, t3);
5129 tcg_temp_free_i64(t3);
5130 gen_move_low32(cpu_LO[acc], t2);
5131 gen_move_high32(cpu_HI[acc], t2);
5132 if (rd) {
5133 gen_move_low32(cpu_gpr[rd], t2);
5135 tcg_temp_free_i64(t2);
5137 break;
5138 case MMI_OPC_MADDU1:
5139 acc = 1;
5140 /* Fall through */
5141 case MMI_OPC_MADDU:
5143 TCGv_i64 t2 = tcg_temp_new_i64();
5144 TCGv_i64 t3 = tcg_temp_new_i64();
5146 tcg_gen_ext32u_tl(t0, t0);
5147 tcg_gen_ext32u_tl(t1, t1);
5148 tcg_gen_extu_tl_i64(t2, t0);
5149 tcg_gen_extu_tl_i64(t3, t1);
5150 tcg_gen_mul_i64(t2, t2, t3);
5151 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5152 tcg_gen_add_i64(t2, t2, t3);
5153 tcg_temp_free_i64(t3);
5154 gen_move_low32(cpu_LO[acc], t2);
5155 gen_move_high32(cpu_HI[acc], t2);
5156 if (rd) {
5157 gen_move_low32(cpu_gpr[rd], t2);
5159 tcg_temp_free_i64(t2);
5161 break;
5162 default:
5163 MIPS_INVAL("mul/madd TXx9");
5164 generate_exception_end(ctx, EXCP_RI);
5165 goto out;
5168 out:
5169 tcg_temp_free(t0);
5170 tcg_temp_free(t1);
5173 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
5174 int rd, int rs, int rt)
5176 TCGv t0 = tcg_temp_new();
5177 TCGv t1 = tcg_temp_new();
5179 gen_load_gpr(t0, rs);
5180 gen_load_gpr(t1, rt);
5182 switch (opc) {
5183 case OPC_VR54XX_MULS:
5184 gen_helper_muls(t0, cpu_env, t0, t1);
5185 break;
5186 case OPC_VR54XX_MULSU:
5187 gen_helper_mulsu(t0, cpu_env, t0, t1);
5188 break;
5189 case OPC_VR54XX_MACC:
5190 gen_helper_macc(t0, cpu_env, t0, t1);
5191 break;
5192 case OPC_VR54XX_MACCU:
5193 gen_helper_maccu(t0, cpu_env, t0, t1);
5194 break;
5195 case OPC_VR54XX_MSAC:
5196 gen_helper_msac(t0, cpu_env, t0, t1);
5197 break;
5198 case OPC_VR54XX_MSACU:
5199 gen_helper_msacu(t0, cpu_env, t0, t1);
5200 break;
5201 case OPC_VR54XX_MULHI:
5202 gen_helper_mulhi(t0, cpu_env, t0, t1);
5203 break;
5204 case OPC_VR54XX_MULHIU:
5205 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5206 break;
5207 case OPC_VR54XX_MULSHI:
5208 gen_helper_mulshi(t0, cpu_env, t0, t1);
5209 break;
5210 case OPC_VR54XX_MULSHIU:
5211 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5212 break;
5213 case OPC_VR54XX_MACCHI:
5214 gen_helper_macchi(t0, cpu_env, t0, t1);
5215 break;
5216 case OPC_VR54XX_MACCHIU:
5217 gen_helper_macchiu(t0, cpu_env, t0, t1);
5218 break;
5219 case OPC_VR54XX_MSACHI:
5220 gen_helper_msachi(t0, cpu_env, t0, t1);
5221 break;
5222 case OPC_VR54XX_MSACHIU:
5223 gen_helper_msachiu(t0, cpu_env, t0, t1);
5224 break;
5225 default:
5226 MIPS_INVAL("mul vr54xx");
5227 generate_exception_end(ctx, EXCP_RI);
5228 goto out;
5230 gen_store_gpr(t0, rd);
5232 out:
5233 tcg_temp_free(t0);
5234 tcg_temp_free(t1);
5237 static void gen_cl (DisasContext *ctx, uint32_t opc,
5238 int rd, int rs)
5240 TCGv t0;
5242 if (rd == 0) {
5243 /* Treat as NOP. */
5244 return;
5246 t0 = cpu_gpr[rd];
5247 gen_load_gpr(t0, rs);
5249 switch (opc) {
5250 case OPC_CLO:
5251 case R6_OPC_CLO:
5252 #if defined(TARGET_MIPS64)
5253 case OPC_DCLO:
5254 case R6_OPC_DCLO:
5255 #endif
5256 tcg_gen_not_tl(t0, t0);
5257 break;
5260 switch (opc) {
5261 case OPC_CLO:
5262 case R6_OPC_CLO:
5263 case OPC_CLZ:
5264 case R6_OPC_CLZ:
5265 tcg_gen_ext32u_tl(t0, t0);
5266 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5267 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5268 break;
5269 #if defined(TARGET_MIPS64)
5270 case OPC_DCLO:
5271 case R6_OPC_DCLO:
5272 case OPC_DCLZ:
5273 case R6_OPC_DCLZ:
5274 tcg_gen_clzi_i64(t0, t0, 64);
5275 break;
5276 #endif
5280 /* Godson integer instructions */
5281 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5282 int rd, int rs, int rt)
5284 TCGv t0, t1;
5286 if (rd == 0) {
5287 /* Treat as NOP. */
5288 return;
5291 switch (opc) {
5292 case OPC_MULT_G_2E:
5293 case OPC_MULT_G_2F:
5294 case OPC_MULTU_G_2E:
5295 case OPC_MULTU_G_2F:
5296 #if defined(TARGET_MIPS64)
5297 case OPC_DMULT_G_2E:
5298 case OPC_DMULT_G_2F:
5299 case OPC_DMULTU_G_2E:
5300 case OPC_DMULTU_G_2F:
5301 #endif
5302 t0 = tcg_temp_new();
5303 t1 = tcg_temp_new();
5304 break;
5305 default:
5306 t0 = tcg_temp_local_new();
5307 t1 = tcg_temp_local_new();
5308 break;
5311 gen_load_gpr(t0, rs);
5312 gen_load_gpr(t1, rt);
5314 switch (opc) {
5315 case OPC_MULT_G_2E:
5316 case OPC_MULT_G_2F:
5317 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5318 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5319 break;
5320 case OPC_MULTU_G_2E:
5321 case OPC_MULTU_G_2F:
5322 tcg_gen_ext32u_tl(t0, t0);
5323 tcg_gen_ext32u_tl(t1, t1);
5324 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5325 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5326 break;
5327 case OPC_DIV_G_2E:
5328 case OPC_DIV_G_2F:
5330 TCGLabel *l1 = gen_new_label();
5331 TCGLabel *l2 = gen_new_label();
5332 TCGLabel *l3 = gen_new_label();
5333 tcg_gen_ext32s_tl(t0, t0);
5334 tcg_gen_ext32s_tl(t1, t1);
5335 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5336 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5337 tcg_gen_br(l3);
5338 gen_set_label(l1);
5339 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5340 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5341 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5342 tcg_gen_br(l3);
5343 gen_set_label(l2);
5344 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5345 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5346 gen_set_label(l3);
5348 break;
5349 case OPC_DIVU_G_2E:
5350 case OPC_DIVU_G_2F:
5352 TCGLabel *l1 = gen_new_label();
5353 TCGLabel *l2 = gen_new_label();
5354 tcg_gen_ext32u_tl(t0, t0);
5355 tcg_gen_ext32u_tl(t1, t1);
5356 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5357 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5358 tcg_gen_br(l2);
5359 gen_set_label(l1);
5360 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5361 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5362 gen_set_label(l2);
5364 break;
5365 case OPC_MOD_G_2E:
5366 case OPC_MOD_G_2F:
5368 TCGLabel *l1 = gen_new_label();
5369 TCGLabel *l2 = gen_new_label();
5370 TCGLabel *l3 = gen_new_label();
5371 tcg_gen_ext32u_tl(t0, t0);
5372 tcg_gen_ext32u_tl(t1, t1);
5373 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5374 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5375 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5376 gen_set_label(l1);
5377 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5378 tcg_gen_br(l3);
5379 gen_set_label(l2);
5380 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5381 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5382 gen_set_label(l3);
5384 break;
5385 case OPC_MODU_G_2E:
5386 case OPC_MODU_G_2F:
5388 TCGLabel *l1 = gen_new_label();
5389 TCGLabel *l2 = gen_new_label();
5390 tcg_gen_ext32u_tl(t0, t0);
5391 tcg_gen_ext32u_tl(t1, t1);
5392 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5393 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5394 tcg_gen_br(l2);
5395 gen_set_label(l1);
5396 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5397 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5398 gen_set_label(l2);
5400 break;
5401 #if defined(TARGET_MIPS64)
5402 case OPC_DMULT_G_2E:
5403 case OPC_DMULT_G_2F:
5404 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5405 break;
5406 case OPC_DMULTU_G_2E:
5407 case OPC_DMULTU_G_2F:
5408 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5409 break;
5410 case OPC_DDIV_G_2E:
5411 case OPC_DDIV_G_2F:
5413 TCGLabel *l1 = gen_new_label();
5414 TCGLabel *l2 = gen_new_label();
5415 TCGLabel *l3 = gen_new_label();
5416 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5417 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5418 tcg_gen_br(l3);
5419 gen_set_label(l1);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5421 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5422 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5423 tcg_gen_br(l3);
5424 gen_set_label(l2);
5425 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5426 gen_set_label(l3);
5428 break;
5429 case OPC_DDIVU_G_2E:
5430 case OPC_DDIVU_G_2F:
5432 TCGLabel *l1 = gen_new_label();
5433 TCGLabel *l2 = gen_new_label();
5434 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5435 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5436 tcg_gen_br(l2);
5437 gen_set_label(l1);
5438 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5439 gen_set_label(l2);
5441 break;
5442 case OPC_DMOD_G_2E:
5443 case OPC_DMOD_G_2F:
5445 TCGLabel *l1 = gen_new_label();
5446 TCGLabel *l2 = gen_new_label();
5447 TCGLabel *l3 = gen_new_label();
5448 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5449 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5450 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5451 gen_set_label(l1);
5452 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5453 tcg_gen_br(l3);
5454 gen_set_label(l2);
5455 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5456 gen_set_label(l3);
5458 break;
5459 case OPC_DMODU_G_2E:
5460 case OPC_DMODU_G_2F:
5462 TCGLabel *l1 = gen_new_label();
5463 TCGLabel *l2 = gen_new_label();
5464 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5465 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5466 tcg_gen_br(l2);
5467 gen_set_label(l1);
5468 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5469 gen_set_label(l2);
5471 break;
5472 #endif
5475 tcg_temp_free(t0);
5476 tcg_temp_free(t1);
5479 /* Loongson multimedia instructions */
5480 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5482 uint32_t opc, shift_max;
5483 TCGv_i64 t0, t1;
5485 opc = MASK_LMI(ctx->opcode);
5486 switch (opc) {
5487 case OPC_ADD_CP2:
5488 case OPC_SUB_CP2:
5489 case OPC_DADD_CP2:
5490 case OPC_DSUB_CP2:
5491 t0 = tcg_temp_local_new_i64();
5492 t1 = tcg_temp_local_new_i64();
5493 break;
5494 default:
5495 t0 = tcg_temp_new_i64();
5496 t1 = tcg_temp_new_i64();
5497 break;
5500 check_cp1_enabled(ctx);
5501 gen_load_fpr64(ctx, t0, rs);
5502 gen_load_fpr64(ctx, t1, rt);
5504 #define LMI_HELPER(UP, LO) \
5505 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5506 #define LMI_HELPER_1(UP, LO) \
5507 case OPC_##UP: gen_helper_##LO(t0, t0); break
5508 #define LMI_DIRECT(UP, LO, OP) \
5509 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5511 switch (opc) {
5512 LMI_HELPER(PADDSH, paddsh);
5513 LMI_HELPER(PADDUSH, paddush);
5514 LMI_HELPER(PADDH, paddh);
5515 LMI_HELPER(PADDW, paddw);
5516 LMI_HELPER(PADDSB, paddsb);
5517 LMI_HELPER(PADDUSB, paddusb);
5518 LMI_HELPER(PADDB, paddb);
5520 LMI_HELPER(PSUBSH, psubsh);
5521 LMI_HELPER(PSUBUSH, psubush);
5522 LMI_HELPER(PSUBH, psubh);
5523 LMI_HELPER(PSUBW, psubw);
5524 LMI_HELPER(PSUBSB, psubsb);
5525 LMI_HELPER(PSUBUSB, psubusb);
5526 LMI_HELPER(PSUBB, psubb);
5528 LMI_HELPER(PSHUFH, pshufh);
5529 LMI_HELPER(PACKSSWH, packsswh);
5530 LMI_HELPER(PACKSSHB, packsshb);
5531 LMI_HELPER(PACKUSHB, packushb);
5533 LMI_HELPER(PUNPCKLHW, punpcklhw);
5534 LMI_HELPER(PUNPCKHHW, punpckhhw);
5535 LMI_HELPER(PUNPCKLBH, punpcklbh);
5536 LMI_HELPER(PUNPCKHBH, punpckhbh);
5537 LMI_HELPER(PUNPCKLWD, punpcklwd);
5538 LMI_HELPER(PUNPCKHWD, punpckhwd);
5540 LMI_HELPER(PAVGH, pavgh);
5541 LMI_HELPER(PAVGB, pavgb);
5542 LMI_HELPER(PMAXSH, pmaxsh);
5543 LMI_HELPER(PMINSH, pminsh);
5544 LMI_HELPER(PMAXUB, pmaxub);
5545 LMI_HELPER(PMINUB, pminub);
5547 LMI_HELPER(PCMPEQW, pcmpeqw);
5548 LMI_HELPER(PCMPGTW, pcmpgtw);
5549 LMI_HELPER(PCMPEQH, pcmpeqh);
5550 LMI_HELPER(PCMPGTH, pcmpgth);
5551 LMI_HELPER(PCMPEQB, pcmpeqb);
5552 LMI_HELPER(PCMPGTB, pcmpgtb);
5554 LMI_HELPER(PSLLW, psllw);
5555 LMI_HELPER(PSLLH, psllh);
5556 LMI_HELPER(PSRLW, psrlw);
5557 LMI_HELPER(PSRLH, psrlh);
5558 LMI_HELPER(PSRAW, psraw);
5559 LMI_HELPER(PSRAH, psrah);
5561 LMI_HELPER(PMULLH, pmullh);
5562 LMI_HELPER(PMULHH, pmulhh);
5563 LMI_HELPER(PMULHUH, pmulhuh);
5564 LMI_HELPER(PMADDHW, pmaddhw);
5566 LMI_HELPER(PASUBUB, pasubub);
5567 LMI_HELPER_1(BIADD, biadd);
5568 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5570 LMI_DIRECT(PADDD, paddd, add);
5571 LMI_DIRECT(PSUBD, psubd, sub);
5572 LMI_DIRECT(XOR_CP2, xor, xor);
5573 LMI_DIRECT(NOR_CP2, nor, nor);
5574 LMI_DIRECT(AND_CP2, and, and);
5575 LMI_DIRECT(OR_CP2, or, or);
5577 case OPC_PANDN:
5578 tcg_gen_andc_i64(t0, t1, t0);
5579 break;
5581 case OPC_PINSRH_0:
5582 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5583 break;
5584 case OPC_PINSRH_1:
5585 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5586 break;
5587 case OPC_PINSRH_2:
5588 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5589 break;
5590 case OPC_PINSRH_3:
5591 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5592 break;
5594 case OPC_PEXTRH:
5595 tcg_gen_andi_i64(t1, t1, 3);
5596 tcg_gen_shli_i64(t1, t1, 4);
5597 tcg_gen_shr_i64(t0, t0, t1);
5598 tcg_gen_ext16u_i64(t0, t0);
5599 break;
5601 case OPC_ADDU_CP2:
5602 tcg_gen_add_i64(t0, t0, t1);
5603 tcg_gen_ext32s_i64(t0, t0);
5604 break;
5605 case OPC_SUBU_CP2:
5606 tcg_gen_sub_i64(t0, t0, t1);
5607 tcg_gen_ext32s_i64(t0, t0);
5608 break;
5610 case OPC_SLL_CP2:
5611 shift_max = 32;
5612 goto do_shift;
5613 case OPC_SRL_CP2:
5614 shift_max = 32;
5615 goto do_shift;
5616 case OPC_SRA_CP2:
5617 shift_max = 32;
5618 goto do_shift;
5619 case OPC_DSLL_CP2:
5620 shift_max = 64;
5621 goto do_shift;
5622 case OPC_DSRL_CP2:
5623 shift_max = 64;
5624 goto do_shift;
5625 case OPC_DSRA_CP2:
5626 shift_max = 64;
5627 goto do_shift;
5628 do_shift:
5629 /* Make sure shift count isn't TCG undefined behaviour. */
5630 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5632 switch (opc) {
5633 case OPC_SLL_CP2:
5634 case OPC_DSLL_CP2:
5635 tcg_gen_shl_i64(t0, t0, t1);
5636 break;
5637 case OPC_SRA_CP2:
5638 case OPC_DSRA_CP2:
5639 /* Since SRA is UndefinedResult without sign-extended inputs,
5640 we can treat SRA and DSRA the same. */
5641 tcg_gen_sar_i64(t0, t0, t1);
5642 break;
5643 case OPC_SRL_CP2:
5644 /* We want to shift in zeros for SRL; zero-extend first. */
5645 tcg_gen_ext32u_i64(t0, t0);
5646 /* FALLTHRU */
5647 case OPC_DSRL_CP2:
5648 tcg_gen_shr_i64(t0, t0, t1);
5649 break;
5652 if (shift_max == 32) {
5653 tcg_gen_ext32s_i64(t0, t0);
5656 /* Shifts larger than MAX produce zero. */
5657 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5658 tcg_gen_neg_i64(t1, t1);
5659 tcg_gen_and_i64(t0, t0, t1);
5660 break;
5662 case OPC_ADD_CP2:
5663 case OPC_DADD_CP2:
5665 TCGv_i64 t2 = tcg_temp_new_i64();
5666 TCGLabel *lab = gen_new_label();
5668 tcg_gen_mov_i64(t2, t0);
5669 tcg_gen_add_i64(t0, t1, t2);
5670 if (opc == OPC_ADD_CP2) {
5671 tcg_gen_ext32s_i64(t0, t0);
5673 tcg_gen_xor_i64(t1, t1, t2);
5674 tcg_gen_xor_i64(t2, t2, t0);
5675 tcg_gen_andc_i64(t1, t2, t1);
5676 tcg_temp_free_i64(t2);
5677 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5678 generate_exception(ctx, EXCP_OVERFLOW);
5679 gen_set_label(lab);
5680 break;
5683 case OPC_SUB_CP2:
5684 case OPC_DSUB_CP2:
5686 TCGv_i64 t2 = tcg_temp_new_i64();
5687 TCGLabel *lab = gen_new_label();
5689 tcg_gen_mov_i64(t2, t0);
5690 tcg_gen_sub_i64(t0, t1, t2);
5691 if (opc == OPC_SUB_CP2) {
5692 tcg_gen_ext32s_i64(t0, t0);
5694 tcg_gen_xor_i64(t1, t1, t2);
5695 tcg_gen_xor_i64(t2, t2, t0);
5696 tcg_gen_and_i64(t1, t1, t2);
5697 tcg_temp_free_i64(t2);
5698 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5699 generate_exception(ctx, EXCP_OVERFLOW);
5700 gen_set_label(lab);
5701 break;
5704 case OPC_PMULUW:
5705 tcg_gen_ext32u_i64(t0, t0);
5706 tcg_gen_ext32u_i64(t1, t1);
5707 tcg_gen_mul_i64(t0, t0, t1);
5708 break;
5710 case OPC_SEQU_CP2:
5711 case OPC_SEQ_CP2:
5712 case OPC_SLTU_CP2:
5713 case OPC_SLT_CP2:
5714 case OPC_SLEU_CP2:
5715 case OPC_SLE_CP2:
5716 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5717 FD field is the CC field? */
5718 default:
5719 MIPS_INVAL("loongson_cp2");
5720 generate_exception_end(ctx, EXCP_RI);
5721 return;
5724 #undef LMI_HELPER
5725 #undef LMI_DIRECT
5727 gen_store_fpr64(ctx, t0, rd);
5729 tcg_temp_free_i64(t0);
5730 tcg_temp_free_i64(t1);
5733 /* Traps */
5734 static void gen_trap (DisasContext *ctx, uint32_t opc,
5735 int rs, int rt, int16_t imm)
5737 int cond;
5738 TCGv t0 = tcg_temp_new();
5739 TCGv t1 = tcg_temp_new();
5741 cond = 0;
5742 /* Load needed operands */
5743 switch (opc) {
5744 case OPC_TEQ:
5745 case OPC_TGE:
5746 case OPC_TGEU:
5747 case OPC_TLT:
5748 case OPC_TLTU:
5749 case OPC_TNE:
5750 /* Compare two registers */
5751 if (rs != rt) {
5752 gen_load_gpr(t0, rs);
5753 gen_load_gpr(t1, rt);
5754 cond = 1;
5756 break;
5757 case OPC_TEQI:
5758 case OPC_TGEI:
5759 case OPC_TGEIU:
5760 case OPC_TLTI:
5761 case OPC_TLTIU:
5762 case OPC_TNEI:
5763 /* Compare register to immediate */
5764 if (rs != 0 || imm != 0) {
5765 gen_load_gpr(t0, rs);
5766 tcg_gen_movi_tl(t1, (int32_t)imm);
5767 cond = 1;
5769 break;
5771 if (cond == 0) {
5772 switch (opc) {
5773 case OPC_TEQ: /* rs == rs */
5774 case OPC_TEQI: /* r0 == 0 */
5775 case OPC_TGE: /* rs >= rs */
5776 case OPC_TGEI: /* r0 >= 0 */
5777 case OPC_TGEU: /* rs >= rs unsigned */
5778 case OPC_TGEIU: /* r0 >= 0 unsigned */
5779 /* Always trap */
5780 generate_exception_end(ctx, EXCP_TRAP);
5781 break;
5782 case OPC_TLT: /* rs < rs */
5783 case OPC_TLTI: /* r0 < 0 */
5784 case OPC_TLTU: /* rs < rs unsigned */
5785 case OPC_TLTIU: /* r0 < 0 unsigned */
5786 case OPC_TNE: /* rs != rs */
5787 case OPC_TNEI: /* r0 != 0 */
5788 /* Never trap: treat as NOP. */
5789 break;
5791 } else {
5792 TCGLabel *l1 = gen_new_label();
5794 switch (opc) {
5795 case OPC_TEQ:
5796 case OPC_TEQI:
5797 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5798 break;
5799 case OPC_TGE:
5800 case OPC_TGEI:
5801 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5802 break;
5803 case OPC_TGEU:
5804 case OPC_TGEIU:
5805 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5806 break;
5807 case OPC_TLT:
5808 case OPC_TLTI:
5809 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5810 break;
5811 case OPC_TLTU:
5812 case OPC_TLTIU:
5813 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5814 break;
5815 case OPC_TNE:
5816 case OPC_TNEI:
5817 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5818 break;
5820 generate_exception(ctx, EXCP_TRAP);
5821 gen_set_label(l1);
5823 tcg_temp_free(t0);
5824 tcg_temp_free(t1);
5827 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5829 if (unlikely(ctx->base.singlestep_enabled)) {
5830 return false;
5833 #ifndef CONFIG_USER_ONLY
5834 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5835 #else
5836 return true;
5837 #endif
5840 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5842 if (use_goto_tb(ctx, dest)) {
5843 tcg_gen_goto_tb(n);
5844 gen_save_pc(dest);
5845 tcg_gen_exit_tb(ctx->base.tb, n);
5846 } else {
5847 gen_save_pc(dest);
5848 if (ctx->base.singlestep_enabled) {
5849 save_cpu_state(ctx, 0);
5850 gen_helper_raise_exception_debug(cpu_env);
5852 tcg_gen_lookup_and_goto_ptr();
5856 /* Branches (before delay slot) */
5857 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5858 int insn_bytes,
5859 int rs, int rt, int32_t offset,
5860 int delayslot_size)
5862 target_ulong btgt = -1;
5863 int blink = 0;
5864 int bcond_compute = 0;
5865 TCGv t0 = tcg_temp_new();
5866 TCGv t1 = tcg_temp_new();
5868 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5869 #ifdef MIPS_DEBUG_DISAS
5870 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5871 TARGET_FMT_lx "\n", ctx->base.pc_next);
5872 #endif
5873 generate_exception_end(ctx, EXCP_RI);
5874 goto out;
5877 /* Load needed operands */
5878 switch (opc) {
5879 case OPC_BEQ:
5880 case OPC_BEQL:
5881 case OPC_BNE:
5882 case OPC_BNEL:
5883 /* Compare two registers */
5884 if (rs != rt) {
5885 gen_load_gpr(t0, rs);
5886 gen_load_gpr(t1, rt);
5887 bcond_compute = 1;
5889 btgt = ctx->base.pc_next + insn_bytes + offset;
5890 break;
5891 case OPC_BGEZ:
5892 case OPC_BGEZAL:
5893 case OPC_BGEZALL:
5894 case OPC_BGEZL:
5895 case OPC_BGTZ:
5896 case OPC_BGTZL:
5897 case OPC_BLEZ:
5898 case OPC_BLEZL:
5899 case OPC_BLTZ:
5900 case OPC_BLTZAL:
5901 case OPC_BLTZALL:
5902 case OPC_BLTZL:
5903 /* Compare to zero */
5904 if (rs != 0) {
5905 gen_load_gpr(t0, rs);
5906 bcond_compute = 1;
5908 btgt = ctx->base.pc_next + insn_bytes + offset;
5909 break;
5910 case OPC_BPOSGE32:
5911 #if defined(TARGET_MIPS64)
5912 case OPC_BPOSGE64:
5913 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5914 #else
5915 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5916 #endif
5917 bcond_compute = 1;
5918 btgt = ctx->base.pc_next + insn_bytes + offset;
5919 break;
5920 case OPC_J:
5921 case OPC_JAL:
5922 case OPC_JALX:
5923 /* Jump to immediate */
5924 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5925 (uint32_t)offset;
5926 break;
5927 case OPC_JR:
5928 case OPC_JALR:
5929 /* Jump to register */
5930 if (offset != 0 && offset != 16) {
5931 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5932 others are reserved. */
5933 MIPS_INVAL("jump hint");
5934 generate_exception_end(ctx, EXCP_RI);
5935 goto out;
5937 gen_load_gpr(btarget, rs);
5938 break;
5939 default:
5940 MIPS_INVAL("branch/jump");
5941 generate_exception_end(ctx, EXCP_RI);
5942 goto out;
5944 if (bcond_compute == 0) {
5945 /* No condition to be computed */
5946 switch (opc) {
5947 case OPC_BEQ: /* rx == rx */
5948 case OPC_BEQL: /* rx == rx likely */
5949 case OPC_BGEZ: /* 0 >= 0 */
5950 case OPC_BGEZL: /* 0 >= 0 likely */
5951 case OPC_BLEZ: /* 0 <= 0 */
5952 case OPC_BLEZL: /* 0 <= 0 likely */
5953 /* Always take */
5954 ctx->hflags |= MIPS_HFLAG_B;
5955 break;
5956 case OPC_BGEZAL: /* 0 >= 0 */
5957 case OPC_BGEZALL: /* 0 >= 0 likely */
5958 /* Always take and link */
5959 blink = 31;
5960 ctx->hflags |= MIPS_HFLAG_B;
5961 break;
5962 case OPC_BNE: /* rx != rx */
5963 case OPC_BGTZ: /* 0 > 0 */
5964 case OPC_BLTZ: /* 0 < 0 */
5965 /* Treat as NOP. */
5966 goto out;
5967 case OPC_BLTZAL: /* 0 < 0 */
5968 /* Handle as an unconditional branch to get correct delay
5969 slot checking. */
5970 blink = 31;
5971 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5972 ctx->hflags |= MIPS_HFLAG_B;
5973 break;
5974 case OPC_BLTZALL: /* 0 < 0 likely */
5975 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5976 /* Skip the instruction in the delay slot */
5977 ctx->base.pc_next += 4;
5978 goto out;
5979 case OPC_BNEL: /* rx != rx likely */
5980 case OPC_BGTZL: /* 0 > 0 likely */
5981 case OPC_BLTZL: /* 0 < 0 likely */
5982 /* Skip the instruction in the delay slot */
5983 ctx->base.pc_next += 4;
5984 goto out;
5985 case OPC_J:
5986 ctx->hflags |= MIPS_HFLAG_B;
5987 break;
5988 case OPC_JALX:
5989 ctx->hflags |= MIPS_HFLAG_BX;
5990 /* Fallthrough */
5991 case OPC_JAL:
5992 blink = 31;
5993 ctx->hflags |= MIPS_HFLAG_B;
5994 break;
5995 case OPC_JR:
5996 ctx->hflags |= MIPS_HFLAG_BR;
5997 break;
5998 case OPC_JALR:
5999 blink = rt;
6000 ctx->hflags |= MIPS_HFLAG_BR;
6001 break;
6002 default:
6003 MIPS_INVAL("branch/jump");
6004 generate_exception_end(ctx, EXCP_RI);
6005 goto out;
6007 } else {
6008 switch (opc) {
6009 case OPC_BEQ:
6010 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6011 goto not_likely;
6012 case OPC_BEQL:
6013 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6014 goto likely;
6015 case OPC_BNE:
6016 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6017 goto not_likely;
6018 case OPC_BNEL:
6019 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6020 goto likely;
6021 case OPC_BGEZ:
6022 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6023 goto not_likely;
6024 case OPC_BGEZL:
6025 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6026 goto likely;
6027 case OPC_BGEZAL:
6028 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6029 blink = 31;
6030 goto not_likely;
6031 case OPC_BGEZALL:
6032 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6033 blink = 31;
6034 goto likely;
6035 case OPC_BGTZ:
6036 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6037 goto not_likely;
6038 case OPC_BGTZL:
6039 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6040 goto likely;
6041 case OPC_BLEZ:
6042 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6043 goto not_likely;
6044 case OPC_BLEZL:
6045 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6046 goto likely;
6047 case OPC_BLTZ:
6048 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6049 goto not_likely;
6050 case OPC_BLTZL:
6051 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6052 goto likely;
6053 case OPC_BPOSGE32:
6054 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6055 goto not_likely;
6056 #if defined(TARGET_MIPS64)
6057 case OPC_BPOSGE64:
6058 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6059 goto not_likely;
6060 #endif
6061 case OPC_BLTZAL:
6062 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6063 blink = 31;
6064 not_likely:
6065 ctx->hflags |= MIPS_HFLAG_BC;
6066 break;
6067 case OPC_BLTZALL:
6068 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6069 blink = 31;
6070 likely:
6071 ctx->hflags |= MIPS_HFLAG_BL;
6072 break;
6073 default:
6074 MIPS_INVAL("conditional branch/jump");
6075 generate_exception_end(ctx, EXCP_RI);
6076 goto out;
6080 ctx->btarget = btgt;
6082 switch (delayslot_size) {
6083 case 2:
6084 ctx->hflags |= MIPS_HFLAG_BDS16;
6085 break;
6086 case 4:
6087 ctx->hflags |= MIPS_HFLAG_BDS32;
6088 break;
6091 if (blink > 0) {
6092 int post_delay = insn_bytes + delayslot_size;
6093 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6095 tcg_gen_movi_tl(cpu_gpr[blink],
6096 ctx->base.pc_next + post_delay + lowbit);
6099 out:
6100 if (insn_bytes == 2)
6101 ctx->hflags |= MIPS_HFLAG_B16;
6102 tcg_temp_free(t0);
6103 tcg_temp_free(t1);
6107 /* nanoMIPS Branches */
6108 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6109 int insn_bytes,
6110 int rs, int rt, int32_t offset)
6112 target_ulong btgt = -1;
6113 int bcond_compute = 0;
6114 TCGv t0 = tcg_temp_new();
6115 TCGv t1 = tcg_temp_new();
6117 /* Load needed operands */
6118 switch (opc) {
6119 case OPC_BEQ:
6120 case OPC_BNE:
6121 /* Compare two registers */
6122 if (rs != rt) {
6123 gen_load_gpr(t0, rs);
6124 gen_load_gpr(t1, rt);
6125 bcond_compute = 1;
6127 btgt = ctx->base.pc_next + insn_bytes + offset;
6128 break;
6129 case OPC_BGEZAL:
6130 /* Compare to zero */
6131 if (rs != 0) {
6132 gen_load_gpr(t0, rs);
6133 bcond_compute = 1;
6135 btgt = ctx->base.pc_next + insn_bytes + offset;
6136 break;
6137 case OPC_BPOSGE32:
6138 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6139 bcond_compute = 1;
6140 btgt = ctx->base.pc_next + insn_bytes + offset;
6141 break;
6142 case OPC_JR:
6143 case OPC_JALR:
6144 /* Jump to register */
6145 if (offset != 0 && offset != 16) {
6146 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6147 others are reserved. */
6148 MIPS_INVAL("jump hint");
6149 generate_exception_end(ctx, EXCP_RI);
6150 goto out;
6152 gen_load_gpr(btarget, rs);
6153 break;
6154 default:
6155 MIPS_INVAL("branch/jump");
6156 generate_exception_end(ctx, EXCP_RI);
6157 goto out;
6159 if (bcond_compute == 0) {
6160 /* No condition to be computed */
6161 switch (opc) {
6162 case OPC_BEQ: /* rx == rx */
6163 /* Always take */
6164 ctx->hflags |= MIPS_HFLAG_B;
6165 break;
6166 case OPC_BGEZAL: /* 0 >= 0 */
6167 /* Always take and link */
6168 tcg_gen_movi_tl(cpu_gpr[31],
6169 ctx->base.pc_next + insn_bytes);
6170 ctx->hflags |= MIPS_HFLAG_B;
6171 break;
6172 case OPC_BNE: /* rx != rx */
6173 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6174 /* Skip the instruction in the delay slot */
6175 ctx->base.pc_next += 4;
6176 goto out;
6177 case OPC_JR:
6178 ctx->hflags |= MIPS_HFLAG_BR;
6179 break;
6180 case OPC_JALR:
6181 if (rt > 0) {
6182 tcg_gen_movi_tl(cpu_gpr[rt],
6183 ctx->base.pc_next + insn_bytes);
6185 ctx->hflags |= MIPS_HFLAG_BR;
6186 break;
6187 default:
6188 MIPS_INVAL("branch/jump");
6189 generate_exception_end(ctx, EXCP_RI);
6190 goto out;
6192 } else {
6193 switch (opc) {
6194 case OPC_BEQ:
6195 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6196 goto not_likely;
6197 case OPC_BNE:
6198 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6199 goto not_likely;
6200 case OPC_BGEZAL:
6201 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6202 tcg_gen_movi_tl(cpu_gpr[31],
6203 ctx->base.pc_next + insn_bytes);
6204 goto not_likely;
6205 case OPC_BPOSGE32:
6206 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6207 not_likely:
6208 ctx->hflags |= MIPS_HFLAG_BC;
6209 break;
6210 default:
6211 MIPS_INVAL("conditional branch/jump");
6212 generate_exception_end(ctx, EXCP_RI);
6213 goto out;
6217 ctx->btarget = btgt;
6219 out:
6220 if (insn_bytes == 2) {
6221 ctx->hflags |= MIPS_HFLAG_B16;
6223 tcg_temp_free(t0);
6224 tcg_temp_free(t1);
6228 /* special3 bitfield operations */
6229 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
6230 int rs, int lsb, int msb)
6232 TCGv t0 = tcg_temp_new();
6233 TCGv t1 = tcg_temp_new();
6235 gen_load_gpr(t1, rs);
6236 switch (opc) {
6237 case OPC_EXT:
6238 if (lsb + msb > 31) {
6239 goto fail;
6241 if (msb != 31) {
6242 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6243 } else {
6244 /* The two checks together imply that lsb == 0,
6245 so this is a simple sign-extension. */
6246 tcg_gen_ext32s_tl(t0, t1);
6248 break;
6249 #if defined(TARGET_MIPS64)
6250 case OPC_DEXTU:
6251 lsb += 32;
6252 goto do_dext;
6253 case OPC_DEXTM:
6254 msb += 32;
6255 goto do_dext;
6256 case OPC_DEXT:
6257 do_dext:
6258 if (lsb + msb > 63) {
6259 goto fail;
6261 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6262 break;
6263 #endif
6264 case OPC_INS:
6265 if (lsb > msb) {
6266 goto fail;
6268 gen_load_gpr(t0, rt);
6269 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6270 tcg_gen_ext32s_tl(t0, t0);
6271 break;
6272 #if defined(TARGET_MIPS64)
6273 case OPC_DINSU:
6274 lsb += 32;
6275 /* FALLTHRU */
6276 case OPC_DINSM:
6277 msb += 32;
6278 /* FALLTHRU */
6279 case OPC_DINS:
6280 if (lsb > msb) {
6281 goto fail;
6283 gen_load_gpr(t0, rt);
6284 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6285 break;
6286 #endif
6287 default:
6288 fail:
6289 MIPS_INVAL("bitops");
6290 generate_exception_end(ctx, EXCP_RI);
6291 tcg_temp_free(t0);
6292 tcg_temp_free(t1);
6293 return;
6295 gen_store_gpr(t0, rt);
6296 tcg_temp_free(t0);
6297 tcg_temp_free(t1);
6300 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6302 TCGv t0;
6304 if (rd == 0) {
6305 /* If no destination, treat it as a NOP. */
6306 return;
6309 t0 = tcg_temp_new();
6310 gen_load_gpr(t0, rt);
6311 switch (op2) {
6312 case OPC_WSBH:
6314 TCGv t1 = tcg_temp_new();
6315 TCGv t2 = tcg_const_tl(0x00FF00FF);
6317 tcg_gen_shri_tl(t1, t0, 8);
6318 tcg_gen_and_tl(t1, t1, t2);
6319 tcg_gen_and_tl(t0, t0, t2);
6320 tcg_gen_shli_tl(t0, t0, 8);
6321 tcg_gen_or_tl(t0, t0, t1);
6322 tcg_temp_free(t2);
6323 tcg_temp_free(t1);
6324 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6326 break;
6327 case OPC_SEB:
6328 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6329 break;
6330 case OPC_SEH:
6331 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6332 break;
6333 #if defined(TARGET_MIPS64)
6334 case OPC_DSBH:
6336 TCGv t1 = tcg_temp_new();
6337 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6339 tcg_gen_shri_tl(t1, t0, 8);
6340 tcg_gen_and_tl(t1, t1, t2);
6341 tcg_gen_and_tl(t0, t0, t2);
6342 tcg_gen_shli_tl(t0, t0, 8);
6343 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6344 tcg_temp_free(t2);
6345 tcg_temp_free(t1);
6347 break;
6348 case OPC_DSHD:
6350 TCGv t1 = tcg_temp_new();
6351 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6353 tcg_gen_shri_tl(t1, t0, 16);
6354 tcg_gen_and_tl(t1, t1, t2);
6355 tcg_gen_and_tl(t0, t0, t2);
6356 tcg_gen_shli_tl(t0, t0, 16);
6357 tcg_gen_or_tl(t0, t0, t1);
6358 tcg_gen_shri_tl(t1, t0, 32);
6359 tcg_gen_shli_tl(t0, t0, 32);
6360 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6361 tcg_temp_free(t2);
6362 tcg_temp_free(t1);
6364 break;
6365 #endif
6366 default:
6367 MIPS_INVAL("bsfhl");
6368 generate_exception_end(ctx, EXCP_RI);
6369 tcg_temp_free(t0);
6370 return;
6372 tcg_temp_free(t0);
6375 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6376 int imm2)
6378 TCGv t0;
6379 TCGv t1;
6380 if (rd == 0) {
6381 /* Treat as NOP. */
6382 return;
6384 t0 = tcg_temp_new();
6385 t1 = tcg_temp_new();
6386 gen_load_gpr(t0, rs);
6387 gen_load_gpr(t1, rt);
6388 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6389 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6390 if (opc == OPC_LSA) {
6391 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6394 tcg_temp_free(t1);
6395 tcg_temp_free(t0);
6397 return;
6400 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6401 int rt, int bits)
6403 TCGv t0;
6404 if (rd == 0) {
6405 /* Treat as NOP. */
6406 return;
6408 t0 = tcg_temp_new();
6409 if (bits == 0 || bits == wordsz) {
6410 if (bits == 0) {
6411 gen_load_gpr(t0, rt);
6412 } else {
6413 gen_load_gpr(t0, rs);
6415 switch (wordsz) {
6416 case 32:
6417 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6418 break;
6419 #if defined(TARGET_MIPS64)
6420 case 64:
6421 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6422 break;
6423 #endif
6425 } else {
6426 TCGv t1 = tcg_temp_new();
6427 gen_load_gpr(t0, rt);
6428 gen_load_gpr(t1, rs);
6429 switch (wordsz) {
6430 case 32:
6432 TCGv_i64 t2 = tcg_temp_new_i64();
6433 tcg_gen_concat_tl_i64(t2, t1, t0);
6434 tcg_gen_shri_i64(t2, t2, 32 - bits);
6435 gen_move_low32(cpu_gpr[rd], t2);
6436 tcg_temp_free_i64(t2);
6438 break;
6439 #if defined(TARGET_MIPS64)
6440 case 64:
6441 tcg_gen_shli_tl(t0, t0, bits);
6442 tcg_gen_shri_tl(t1, t1, 64 - bits);
6443 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6444 break;
6445 #endif
6447 tcg_temp_free(t1);
6450 tcg_temp_free(t0);
6453 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6454 int bp)
6456 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6459 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6460 int shift)
6462 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6465 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6467 TCGv t0;
6468 if (rd == 0) {
6469 /* Treat as NOP. */
6470 return;
6472 t0 = tcg_temp_new();
6473 gen_load_gpr(t0, rt);
6474 switch (opc) {
6475 case OPC_BITSWAP:
6476 gen_helper_bitswap(cpu_gpr[rd], t0);
6477 break;
6478 #if defined(TARGET_MIPS64)
6479 case OPC_DBITSWAP:
6480 gen_helper_dbitswap(cpu_gpr[rd], t0);
6481 break;
6482 #endif
6484 tcg_temp_free(t0);
6487 #ifndef CONFIG_USER_ONLY
6488 /* CP0 (MMU and control) */
6489 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6491 TCGv_i64 t0 = tcg_temp_new_i64();
6492 TCGv_i64 t1 = tcg_temp_new_i64();
6494 tcg_gen_ext_tl_i64(t0, arg);
6495 tcg_gen_ld_i64(t1, cpu_env, off);
6496 #if defined(TARGET_MIPS64)
6497 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6498 #else
6499 tcg_gen_concat32_i64(t1, t1, t0);
6500 #endif
6501 tcg_gen_st_i64(t1, cpu_env, off);
6502 tcg_temp_free_i64(t1);
6503 tcg_temp_free_i64(t0);
6506 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6508 TCGv_i64 t0 = tcg_temp_new_i64();
6509 TCGv_i64 t1 = tcg_temp_new_i64();
6511 tcg_gen_ext_tl_i64(t0, arg);
6512 tcg_gen_ld_i64(t1, cpu_env, off);
6513 tcg_gen_concat32_i64(t1, t1, t0);
6514 tcg_gen_st_i64(t1, cpu_env, off);
6515 tcg_temp_free_i64(t1);
6516 tcg_temp_free_i64(t0);
6519 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6521 TCGv_i64 t0 = tcg_temp_new_i64();
6523 tcg_gen_ld_i64(t0, cpu_env, off);
6524 #if defined(TARGET_MIPS64)
6525 tcg_gen_shri_i64(t0, t0, 30);
6526 #else
6527 tcg_gen_shri_i64(t0, t0, 32);
6528 #endif
6529 gen_move_low32(arg, t0);
6530 tcg_temp_free_i64(t0);
6533 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6535 TCGv_i64 t0 = tcg_temp_new_i64();
6537 tcg_gen_ld_i64(t0, cpu_env, off);
6538 tcg_gen_shri_i64(t0, t0, 32 + shift);
6539 gen_move_low32(arg, t0);
6540 tcg_temp_free_i64(t0);
6543 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6545 TCGv_i32 t0 = tcg_temp_new_i32();
6547 tcg_gen_ld_i32(t0, cpu_env, off);
6548 tcg_gen_ext_i32_tl(arg, t0);
6549 tcg_temp_free_i32(t0);
6552 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6554 tcg_gen_ld_tl(arg, cpu_env, off);
6555 tcg_gen_ext32s_tl(arg, arg);
6558 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6560 TCGv_i32 t0 = tcg_temp_new_i32();
6562 tcg_gen_trunc_tl_i32(t0, arg);
6563 tcg_gen_st_i32(t0, cpu_env, off);
6564 tcg_temp_free_i32(t0);
6567 #define CP0_CHECK(c) \
6568 do { \
6569 if (!(c)) { \
6570 goto cp0_unimplemented; \
6572 } while (0)
6574 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6576 const char *register_name = "invalid";
6578 switch (reg) {
6579 case CP0_REGISTER_02:
6580 switch (sel) {
6581 case 0:
6582 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6583 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6584 register_name = "EntryLo0";
6585 break;
6586 default:
6587 goto cp0_unimplemented;
6589 break;
6590 case CP0_REGISTER_03:
6591 switch (sel) {
6592 case 0:
6593 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6594 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6595 register_name = "EntryLo1";
6596 break;
6597 default:
6598 goto cp0_unimplemented;
6600 break;
6601 case CP0_REGISTER_09:
6602 switch (sel) {
6603 case 7:
6604 CP0_CHECK(ctx->saar);
6605 gen_helper_mfhc0_saar(arg, cpu_env);
6606 register_name = "SAAR";
6607 break;
6608 default:
6609 goto cp0_unimplemented;
6611 break;
6612 case CP0_REGISTER_17:
6613 switch (sel) {
6614 case 0:
6615 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6616 ctx->CP0_LLAddr_shift);
6617 register_name = "LLAddr";
6618 break;
6619 case 1:
6620 CP0_CHECK(ctx->mrp);
6621 gen_helper_mfhc0_maar(arg, cpu_env);
6622 register_name = "MAAR";
6623 break;
6624 default:
6625 goto cp0_unimplemented;
6627 break;
6628 case CP0_REGISTER_28:
6629 switch (sel) {
6630 case 0:
6631 case 2:
6632 case 4:
6633 case 6:
6634 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6635 register_name = "TagLo";
6636 break;
6637 default:
6638 goto cp0_unimplemented;
6640 break;
6641 default:
6642 goto cp0_unimplemented;
6644 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6645 return;
6647 cp0_unimplemented:
6648 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6649 register_name, reg, sel);
6650 tcg_gen_movi_tl(arg, 0);
6653 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6655 const char *register_name = "invalid";
6656 uint64_t mask = ctx->PAMask >> 36;
6658 switch (reg) {
6659 case CP0_REGISTER_02:
6660 switch (sel) {
6661 case 0:
6662 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6663 tcg_gen_andi_tl(arg, arg, mask);
6664 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6665 register_name = "EntryLo0";
6666 break;
6667 default:
6668 goto cp0_unimplemented;
6670 break;
6671 case CP0_REGISTER_03:
6672 switch (sel) {
6673 case 0:
6674 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6675 tcg_gen_andi_tl(arg, arg, mask);
6676 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6677 register_name = "EntryLo1";
6678 break;
6679 default:
6680 goto cp0_unimplemented;
6682 break;
6683 case CP0_REGISTER_09:
6684 switch (sel) {
6685 case 7:
6686 CP0_CHECK(ctx->saar);
6687 gen_helper_mthc0_saar(cpu_env, arg);
6688 register_name = "SAAR";
6689 break;
6690 default:
6691 goto cp0_unimplemented;
6693 case CP0_REGISTER_17:
6694 switch (sel) {
6695 case 0:
6696 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6697 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6698 relevant for modern MIPS cores supporting MTHC0, therefore
6699 treating MTHC0 to LLAddr as NOP. */
6700 register_name = "LLAddr";
6701 break;
6702 case 1:
6703 CP0_CHECK(ctx->mrp);
6704 gen_helper_mthc0_maar(cpu_env, arg);
6705 register_name = "MAAR";
6706 break;
6707 default:
6708 goto cp0_unimplemented;
6710 break;
6711 case CP0_REGISTER_28:
6712 switch (sel) {
6713 case 0:
6714 case 2:
6715 case 4:
6716 case 6:
6717 tcg_gen_andi_tl(arg, arg, mask);
6718 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6719 register_name = "TagLo";
6720 break;
6721 default:
6722 goto cp0_unimplemented;
6724 break;
6725 default:
6726 goto cp0_unimplemented;
6728 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6730 cp0_unimplemented:
6731 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6732 register_name, reg, sel);
6735 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6737 if (ctx->insn_flags & ISA_MIPS32R6) {
6738 tcg_gen_movi_tl(arg, 0);
6739 } else {
6740 tcg_gen_movi_tl(arg, ~0);
6744 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6746 const char *register_name = "invalid";
6748 if (sel != 0)
6749 check_insn(ctx, ISA_MIPS32);
6751 switch (reg) {
6752 case CP0_REGISTER_00:
6753 switch (sel) {
6754 case 0:
6755 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6756 register_name = "Index";
6757 break;
6758 case 1:
6759 CP0_CHECK(ctx->insn_flags & ASE_MT);
6760 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6761 register_name = "MVPControl";
6762 break;
6763 case 2:
6764 CP0_CHECK(ctx->insn_flags & ASE_MT);
6765 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6766 register_name = "MVPConf0";
6767 break;
6768 case 3:
6769 CP0_CHECK(ctx->insn_flags & ASE_MT);
6770 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6771 register_name = "MVPConf1";
6772 break;
6773 case 4:
6774 CP0_CHECK(ctx->vp);
6775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6776 register_name = "VPControl";
6777 break;
6778 default:
6779 goto cp0_unimplemented;
6781 break;
6782 case CP0_REGISTER_01:
6783 switch (sel) {
6784 case 0:
6785 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6786 gen_helper_mfc0_random(arg, cpu_env);
6787 register_name = "Random";
6788 break;
6789 case 1:
6790 CP0_CHECK(ctx->insn_flags & ASE_MT);
6791 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6792 register_name = "VPEControl";
6793 break;
6794 case 2:
6795 CP0_CHECK(ctx->insn_flags & ASE_MT);
6796 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6797 register_name = "VPEConf0";
6798 break;
6799 case 3:
6800 CP0_CHECK(ctx->insn_flags & ASE_MT);
6801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6802 register_name = "VPEConf1";
6803 break;
6804 case 4:
6805 CP0_CHECK(ctx->insn_flags & ASE_MT);
6806 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6807 register_name = "YQMask";
6808 break;
6809 case 5:
6810 CP0_CHECK(ctx->insn_flags & ASE_MT);
6811 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6812 register_name = "VPESchedule";
6813 break;
6814 case 6:
6815 CP0_CHECK(ctx->insn_flags & ASE_MT);
6816 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6817 register_name = "VPEScheFBack";
6818 break;
6819 case 7:
6820 CP0_CHECK(ctx->insn_flags & ASE_MT);
6821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6822 register_name = "VPEOpt";
6823 break;
6824 default:
6825 goto cp0_unimplemented;
6827 break;
6828 case CP0_REGISTER_02:
6829 switch (sel) {
6830 case 0:
6832 TCGv_i64 tmp = tcg_temp_new_i64();
6833 tcg_gen_ld_i64(tmp, cpu_env,
6834 offsetof(CPUMIPSState, CP0_EntryLo0));
6835 #if defined(TARGET_MIPS64)
6836 if (ctx->rxi) {
6837 /* Move RI/XI fields to bits 31:30 */
6838 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6839 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6841 #endif
6842 gen_move_low32(arg, tmp);
6843 tcg_temp_free_i64(tmp);
6845 register_name = "EntryLo0";
6846 break;
6847 case 1:
6848 CP0_CHECK(ctx->insn_flags & ASE_MT);
6849 gen_helper_mfc0_tcstatus(arg, cpu_env);
6850 register_name = "TCStatus";
6851 break;
6852 case 2:
6853 CP0_CHECK(ctx->insn_flags & ASE_MT);
6854 gen_helper_mfc0_tcbind(arg, cpu_env);
6855 register_name = "TCBind";
6856 break;
6857 case 3:
6858 CP0_CHECK(ctx->insn_flags & ASE_MT);
6859 gen_helper_mfc0_tcrestart(arg, cpu_env);
6860 register_name = "TCRestart";
6861 break;
6862 case 4:
6863 CP0_CHECK(ctx->insn_flags & ASE_MT);
6864 gen_helper_mfc0_tchalt(arg, cpu_env);
6865 register_name = "TCHalt";
6866 break;
6867 case 5:
6868 CP0_CHECK(ctx->insn_flags & ASE_MT);
6869 gen_helper_mfc0_tccontext(arg, cpu_env);
6870 register_name = "TCContext";
6871 break;
6872 case 6:
6873 CP0_CHECK(ctx->insn_flags & ASE_MT);
6874 gen_helper_mfc0_tcschedule(arg, cpu_env);
6875 register_name = "TCSchedule";
6876 break;
6877 case 7:
6878 CP0_CHECK(ctx->insn_flags & ASE_MT);
6879 gen_helper_mfc0_tcschefback(arg, cpu_env);
6880 register_name = "TCScheFBack";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 case CP0_REGISTER_03:
6887 switch (sel) {
6888 case 0:
6890 TCGv_i64 tmp = tcg_temp_new_i64();
6891 tcg_gen_ld_i64(tmp, cpu_env,
6892 offsetof(CPUMIPSState, CP0_EntryLo1));
6893 #if defined(TARGET_MIPS64)
6894 if (ctx->rxi) {
6895 /* Move RI/XI fields to bits 31:30 */
6896 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6897 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6899 #endif
6900 gen_move_low32(arg, tmp);
6901 tcg_temp_free_i64(tmp);
6903 register_name = "EntryLo1";
6904 break;
6905 case 1:
6906 CP0_CHECK(ctx->vp);
6907 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6908 register_name = "GlobalNumber";
6909 break;
6910 default:
6911 goto cp0_unimplemented;
6913 break;
6914 case CP0_REGISTER_04:
6915 switch (sel) {
6916 case 0:
6917 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6918 tcg_gen_ext32s_tl(arg, arg);
6919 register_name = "Context";
6920 break;
6921 case 1:
6922 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6923 register_name = "ContextConfig";
6924 goto cp0_unimplemented;
6925 case 2:
6926 CP0_CHECK(ctx->ulri);
6927 tcg_gen_ld_tl(arg, cpu_env,
6928 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6929 tcg_gen_ext32s_tl(arg, arg);
6930 register_name = "UserLocal";
6931 break;
6932 default:
6933 goto cp0_unimplemented;
6935 break;
6936 case CP0_REGISTER_05:
6937 switch (sel) {
6938 case 0:
6939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6940 register_name = "PageMask";
6941 break;
6942 case 1:
6943 check_insn(ctx, ISA_MIPS32R2);
6944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6945 register_name = "PageGrain";
6946 break;
6947 case 2:
6948 CP0_CHECK(ctx->sc);
6949 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6950 tcg_gen_ext32s_tl(arg, arg);
6951 register_name = "SegCtl0";
6952 break;
6953 case 3:
6954 CP0_CHECK(ctx->sc);
6955 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6956 tcg_gen_ext32s_tl(arg, arg);
6957 register_name = "SegCtl1";
6958 break;
6959 case 4:
6960 CP0_CHECK(ctx->sc);
6961 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6962 tcg_gen_ext32s_tl(arg, arg);
6963 register_name = "SegCtl2";
6964 break;
6965 case 5:
6966 check_pw(ctx);
6967 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6968 register_name = "PWBase";
6969 break;
6970 case 6:
6971 check_pw(ctx);
6972 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6973 register_name = "PWField";
6974 break;
6975 case 7:
6976 check_pw(ctx);
6977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6978 register_name = "PWSize";
6979 break;
6980 default:
6981 goto cp0_unimplemented;
6983 break;
6984 case CP0_REGISTER_06:
6985 switch (sel) {
6986 case 0:
6987 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6988 register_name = "Wired";
6989 break;
6990 case 1:
6991 check_insn(ctx, ISA_MIPS32R2);
6992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6993 register_name = "SRSConf0";
6994 break;
6995 case 2:
6996 check_insn(ctx, ISA_MIPS32R2);
6997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6998 register_name = "SRSConf1";
6999 break;
7000 case 3:
7001 check_insn(ctx, ISA_MIPS32R2);
7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7003 register_name = "SRSConf2";
7004 break;
7005 case 4:
7006 check_insn(ctx, ISA_MIPS32R2);
7007 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7008 register_name = "SRSConf3";
7009 break;
7010 case 5:
7011 check_insn(ctx, ISA_MIPS32R2);
7012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7013 register_name = "SRSConf4";
7014 break;
7015 case 6:
7016 check_pw(ctx);
7017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7018 register_name = "PWCtl";
7019 break;
7020 default:
7021 goto cp0_unimplemented;
7023 break;
7024 case CP0_REGISTER_07:
7025 switch (sel) {
7026 case 0:
7027 check_insn(ctx, ISA_MIPS32R2);
7028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7029 register_name = "HWREna";
7030 break;
7031 default:
7032 goto cp0_unimplemented;
7034 break;
7035 case CP0_REGISTER_08:
7036 switch (sel) {
7037 case 0:
7038 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7039 tcg_gen_ext32s_tl(arg, arg);
7040 register_name = "BadVAddr";
7041 break;
7042 case 1:
7043 CP0_CHECK(ctx->bi);
7044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7045 register_name = "BadInstr";
7046 break;
7047 case 2:
7048 CP0_CHECK(ctx->bp);
7049 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7050 register_name = "BadInstrP";
7051 break;
7052 case 3:
7053 CP0_CHECK(ctx->bi);
7054 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7055 tcg_gen_andi_tl(arg, arg, ~0xffff);
7056 register_name = "BadInstrX";
7057 break;
7058 default:
7059 goto cp0_unimplemented;
7061 break;
7062 case CP0_REGISTER_09:
7063 switch (sel) {
7064 case 0:
7065 /* Mark as an IO operation because we read the time. */
7066 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7067 gen_io_start();
7069 gen_helper_mfc0_count(arg, cpu_env);
7070 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7071 gen_io_end();
7073 /* Break the TB to be able to take timer interrupts immediately
7074 after reading count. DISAS_STOP isn't sufficient, we need to
7075 ensure we break completely out of translated code. */
7076 gen_save_pc(ctx->base.pc_next + 4);
7077 ctx->base.is_jmp = DISAS_EXIT;
7078 register_name = "Count";
7079 break;
7080 case 6:
7081 CP0_CHECK(ctx->saar);
7082 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7083 register_name = "SAARI";
7084 break;
7085 case 7:
7086 CP0_CHECK(ctx->saar);
7087 gen_helper_mfc0_saar(arg, cpu_env);
7088 register_name = "SAAR";
7089 break;
7090 default:
7091 goto cp0_unimplemented;
7093 break;
7094 case CP0_REGISTER_10:
7095 switch (sel) {
7096 case 0:
7097 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7098 tcg_gen_ext32s_tl(arg, arg);
7099 register_name = "EntryHi";
7100 break;
7101 default:
7102 goto cp0_unimplemented;
7104 break;
7105 case CP0_REGISTER_11:
7106 switch (sel) {
7107 case 0:
7108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7109 register_name = "Compare";
7110 break;
7111 /* 6,7 are implementation dependent */
7112 default:
7113 goto cp0_unimplemented;
7115 break;
7116 case CP0_REGISTER_12:
7117 switch (sel) {
7118 case 0:
7119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7120 register_name = "Status";
7121 break;
7122 case 1:
7123 check_insn(ctx, ISA_MIPS32R2);
7124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7125 register_name = "IntCtl";
7126 break;
7127 case 2:
7128 check_insn(ctx, ISA_MIPS32R2);
7129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7130 register_name = "SRSCtl";
7131 break;
7132 case 3:
7133 check_insn(ctx, ISA_MIPS32R2);
7134 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7135 register_name = "SRSMap";
7136 break;
7137 default:
7138 goto cp0_unimplemented;
7140 break;
7141 case CP0_REGISTER_13:
7142 switch (sel) {
7143 case 0:
7144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7145 register_name = "Cause";
7146 break;
7147 default:
7148 goto cp0_unimplemented;
7150 break;
7151 case CP0_REGISTER_14:
7152 switch (sel) {
7153 case 0:
7154 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7155 tcg_gen_ext32s_tl(arg, arg);
7156 register_name = "EPC";
7157 break;
7158 default:
7159 goto cp0_unimplemented;
7161 break;
7162 case CP0_REGISTER_15:
7163 switch (sel) {
7164 case 0:
7165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7166 register_name = "PRid";
7167 break;
7168 case 1:
7169 check_insn(ctx, ISA_MIPS32R2);
7170 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7171 tcg_gen_ext32s_tl(arg, arg);
7172 register_name = "EBase";
7173 break;
7174 case 3:
7175 check_insn(ctx, ISA_MIPS32R2);
7176 CP0_CHECK(ctx->cmgcr);
7177 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7178 tcg_gen_ext32s_tl(arg, arg);
7179 register_name = "CMGCRBase";
7180 break;
7181 default:
7182 goto cp0_unimplemented;
7184 break;
7185 case CP0_REGISTER_16:
7186 switch (sel) {
7187 case 0:
7188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7189 register_name = "Config";
7190 break;
7191 case 1:
7192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7193 register_name = "Config1";
7194 break;
7195 case 2:
7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7197 register_name = "Config2";
7198 break;
7199 case 3:
7200 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7201 register_name = "Config3";
7202 break;
7203 case 4:
7204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7205 register_name = "Config4";
7206 break;
7207 case 5:
7208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7209 register_name = "Config5";
7210 break;
7211 /* 6,7 are implementation dependent */
7212 case 6:
7213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7214 register_name = "Config6";
7215 break;
7216 case 7:
7217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7218 register_name = "Config7";
7219 break;
7220 default:
7221 goto cp0_unimplemented;
7223 break;
7224 case CP0_REGISTER_17:
7225 switch (sel) {
7226 case 0:
7227 gen_helper_mfc0_lladdr(arg, cpu_env);
7228 register_name = "LLAddr";
7229 break;
7230 case 1:
7231 CP0_CHECK(ctx->mrp);
7232 gen_helper_mfc0_maar(arg, cpu_env);
7233 register_name = "MAAR";
7234 break;
7235 case 2:
7236 CP0_CHECK(ctx->mrp);
7237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7238 register_name = "MAARI";
7239 break;
7240 default:
7241 goto cp0_unimplemented;
7243 break;
7244 case CP0_REGISTER_18:
7245 switch (sel) {
7246 case 0:
7247 case 1:
7248 case 2:
7249 case 3:
7250 case 4:
7251 case 5:
7252 case 6:
7253 case 7:
7254 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7255 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7256 register_name = "WatchLo";
7257 break;
7258 default:
7259 goto cp0_unimplemented;
7261 break;
7262 case CP0_REGISTER_19:
7263 switch (sel) {
7264 case 0:
7265 case 1:
7266 case 2:
7267 case 3:
7268 case 4:
7269 case 5:
7270 case 6:
7271 case 7:
7272 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7273 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7274 register_name = "WatchHi";
7275 break;
7276 default:
7277 goto cp0_unimplemented;
7279 break;
7280 case CP0_REGISTER_20:
7281 switch (sel) {
7282 case 0:
7283 #if defined(TARGET_MIPS64)
7284 check_insn(ctx, ISA_MIPS3);
7285 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7286 tcg_gen_ext32s_tl(arg, arg);
7287 register_name = "XContext";
7288 break;
7289 #endif
7290 default:
7291 goto cp0_unimplemented;
7293 break;
7294 case CP0_REGISTER_21:
7295 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7296 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7297 switch (sel) {
7298 case 0:
7299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7300 register_name = "Framemask";
7301 break;
7302 default:
7303 goto cp0_unimplemented;
7305 break;
7306 case CP0_REGISTER_22:
7307 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7308 register_name = "'Diagnostic"; /* implementation dependent */
7309 break;
7310 case CP0_REGISTER_23:
7311 switch (sel) {
7312 case 0:
7313 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7314 register_name = "Debug";
7315 break;
7316 case 1:
7317 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7318 register_name = "TraceControl";
7319 goto cp0_unimplemented;
7320 case 2:
7321 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7322 register_name = "TraceControl2";
7323 goto cp0_unimplemented;
7324 case 3:
7325 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7326 register_name = "UserTraceData";
7327 goto cp0_unimplemented;
7328 case 4:
7329 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7330 register_name = "TraceBPC";
7331 goto cp0_unimplemented;
7332 default:
7333 goto cp0_unimplemented;
7335 break;
7336 case CP0_REGISTER_24:
7337 switch (sel) {
7338 case 0:
7339 /* EJTAG support */
7340 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7341 tcg_gen_ext32s_tl(arg, arg);
7342 register_name = "DEPC";
7343 break;
7344 default:
7345 goto cp0_unimplemented;
7347 break;
7348 case CP0_REGISTER_25:
7349 switch (sel) {
7350 case 0:
7351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7352 register_name = "Performance0";
7353 break;
7354 case 1:
7355 // gen_helper_mfc0_performance1(arg);
7356 register_name = "Performance1";
7357 goto cp0_unimplemented;
7358 case 2:
7359 // gen_helper_mfc0_performance2(arg);
7360 register_name = "Performance2";
7361 goto cp0_unimplemented;
7362 case 3:
7363 // gen_helper_mfc0_performance3(arg);
7364 register_name = "Performance3";
7365 goto cp0_unimplemented;
7366 case 4:
7367 // gen_helper_mfc0_performance4(arg);
7368 register_name = "Performance4";
7369 goto cp0_unimplemented;
7370 case 5:
7371 // gen_helper_mfc0_performance5(arg);
7372 register_name = "Performance5";
7373 goto cp0_unimplemented;
7374 case 6:
7375 // gen_helper_mfc0_performance6(arg);
7376 register_name = "Performance6";
7377 goto cp0_unimplemented;
7378 case 7:
7379 // gen_helper_mfc0_performance7(arg);
7380 register_name = "Performance7";
7381 goto cp0_unimplemented;
7382 default:
7383 goto cp0_unimplemented;
7385 break;
7386 case CP0_REGISTER_26:
7387 switch (sel) {
7388 case 0:
7389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7390 register_name = "ErrCtl";
7391 break;
7392 default:
7393 goto cp0_unimplemented;
7395 break;
7396 case CP0_REGISTER_27:
7397 switch (sel) {
7398 case 0:
7399 case 1:
7400 case 2:
7401 case 3:
7402 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7403 register_name = "CacheErr";
7404 break;
7405 default:
7406 goto cp0_unimplemented;
7408 break;
7409 case CP0_REGISTER_28:
7410 switch (sel) {
7411 case 0:
7412 case 2:
7413 case 4:
7414 case 6:
7416 TCGv_i64 tmp = tcg_temp_new_i64();
7417 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7418 gen_move_low32(arg, tmp);
7419 tcg_temp_free_i64(tmp);
7421 register_name = "TagLo";
7422 break;
7423 case 1:
7424 case 3:
7425 case 5:
7426 case 7:
7427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7428 register_name = "DataLo";
7429 break;
7430 default:
7431 goto cp0_unimplemented;
7433 break;
7434 case CP0_REGISTER_29:
7435 switch (sel) {
7436 case 0:
7437 case 2:
7438 case 4:
7439 case 6:
7440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7441 register_name = "TagHi";
7442 break;
7443 case 1:
7444 case 3:
7445 case 5:
7446 case 7:
7447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7448 register_name = "DataHi";
7449 break;
7450 default:
7451 goto cp0_unimplemented;
7453 break;
7454 case CP0_REGISTER_30:
7455 switch (sel) {
7456 case 0:
7457 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7458 tcg_gen_ext32s_tl(arg, arg);
7459 register_name = "ErrorEPC";
7460 break;
7461 default:
7462 goto cp0_unimplemented;
7464 break;
7465 case CP0_REGISTER_31:
7466 switch (sel) {
7467 case 0:
7468 /* EJTAG support */
7469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7470 register_name = "DESAVE";
7471 break;
7472 case 2:
7473 case 3:
7474 case 4:
7475 case 5:
7476 case 6:
7477 case 7:
7478 CP0_CHECK(ctx->kscrexist & (1 << sel));
7479 tcg_gen_ld_tl(arg, cpu_env,
7480 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7481 tcg_gen_ext32s_tl(arg, arg);
7482 register_name = "KScratch";
7483 break;
7484 default:
7485 goto cp0_unimplemented;
7487 break;
7488 default:
7489 goto cp0_unimplemented;
7491 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7492 return;
7494 cp0_unimplemented:
7495 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7496 register_name, reg, sel);
7497 gen_mfc0_unimplemented(ctx, arg);
7500 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7502 const char *register_name = "invalid";
7504 if (sel != 0)
7505 check_insn(ctx, ISA_MIPS32);
7507 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7508 gen_io_start();
7511 switch (reg) {
7512 case CP0_REGISTER_00:
7513 switch (sel) {
7514 case 0:
7515 gen_helper_mtc0_index(cpu_env, arg);
7516 register_name = "Index";
7517 break;
7518 case 1:
7519 CP0_CHECK(ctx->insn_flags & ASE_MT);
7520 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7521 register_name = "MVPControl";
7522 break;
7523 case 2:
7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
7525 /* ignored */
7526 register_name = "MVPConf0";
7527 break;
7528 case 3:
7529 CP0_CHECK(ctx->insn_flags & ASE_MT);
7530 /* ignored */
7531 register_name = "MVPConf1";
7532 break;
7533 case 4:
7534 CP0_CHECK(ctx->vp);
7535 /* ignored */
7536 register_name = "VPControl";
7537 break;
7538 default:
7539 goto cp0_unimplemented;
7541 break;
7542 case CP0_REGISTER_01:
7543 switch (sel) {
7544 case 0:
7545 /* ignored */
7546 register_name = "Random";
7547 break;
7548 case 1:
7549 CP0_CHECK(ctx->insn_flags & ASE_MT);
7550 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7551 register_name = "VPEControl";
7552 break;
7553 case 2:
7554 CP0_CHECK(ctx->insn_flags & ASE_MT);
7555 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7556 register_name = "VPEConf0";
7557 break;
7558 case 3:
7559 CP0_CHECK(ctx->insn_flags & ASE_MT);
7560 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7561 register_name = "VPEConf1";
7562 break;
7563 case 4:
7564 CP0_CHECK(ctx->insn_flags & ASE_MT);
7565 gen_helper_mtc0_yqmask(cpu_env, arg);
7566 register_name = "YQMask";
7567 break;
7568 case 5:
7569 CP0_CHECK(ctx->insn_flags & ASE_MT);
7570 tcg_gen_st_tl(arg, cpu_env,
7571 offsetof(CPUMIPSState, CP0_VPESchedule));
7572 register_name = "VPESchedule";
7573 break;
7574 case 6:
7575 CP0_CHECK(ctx->insn_flags & ASE_MT);
7576 tcg_gen_st_tl(arg, cpu_env,
7577 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7578 register_name = "VPEScheFBack";
7579 break;
7580 case 7:
7581 CP0_CHECK(ctx->insn_flags & ASE_MT);
7582 gen_helper_mtc0_vpeopt(cpu_env, arg);
7583 register_name = "VPEOpt";
7584 break;
7585 default:
7586 goto cp0_unimplemented;
7588 break;
7589 case CP0_REGISTER_02:
7590 switch (sel) {
7591 case 0:
7592 gen_helper_mtc0_entrylo0(cpu_env, arg);
7593 register_name = "EntryLo0";
7594 break;
7595 case 1:
7596 CP0_CHECK(ctx->insn_flags & ASE_MT);
7597 gen_helper_mtc0_tcstatus(cpu_env, arg);
7598 register_name = "TCStatus";
7599 break;
7600 case 2:
7601 CP0_CHECK(ctx->insn_flags & ASE_MT);
7602 gen_helper_mtc0_tcbind(cpu_env, arg);
7603 register_name = "TCBind";
7604 break;
7605 case 3:
7606 CP0_CHECK(ctx->insn_flags & ASE_MT);
7607 gen_helper_mtc0_tcrestart(cpu_env, arg);
7608 register_name = "TCRestart";
7609 break;
7610 case 4:
7611 CP0_CHECK(ctx->insn_flags & ASE_MT);
7612 gen_helper_mtc0_tchalt(cpu_env, arg);
7613 register_name = "TCHalt";
7614 break;
7615 case 5:
7616 CP0_CHECK(ctx->insn_flags & ASE_MT);
7617 gen_helper_mtc0_tccontext(cpu_env, arg);
7618 register_name = "TCContext";
7619 break;
7620 case 6:
7621 CP0_CHECK(ctx->insn_flags & ASE_MT);
7622 gen_helper_mtc0_tcschedule(cpu_env, arg);
7623 register_name = "TCSchedule";
7624 break;
7625 case 7:
7626 CP0_CHECK(ctx->insn_flags & ASE_MT);
7627 gen_helper_mtc0_tcschefback(cpu_env, arg);
7628 register_name = "TCScheFBack";
7629 break;
7630 default:
7631 goto cp0_unimplemented;
7633 break;
7634 case CP0_REGISTER_03:
7635 switch (sel) {
7636 case 0:
7637 gen_helper_mtc0_entrylo1(cpu_env, arg);
7638 register_name = "EntryLo1";
7639 break;
7640 case 1:
7641 CP0_CHECK(ctx->vp);
7642 /* ignored */
7643 register_name = "GlobalNumber";
7644 break;
7645 default:
7646 goto cp0_unimplemented;
7648 break;
7649 case CP0_REGISTER_04:
7650 switch (sel) {
7651 case 0:
7652 gen_helper_mtc0_context(cpu_env, arg);
7653 register_name = "Context";
7654 break;
7655 case 1:
7656 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7657 register_name = "ContextConfig";
7658 goto cp0_unimplemented;
7659 case 2:
7660 CP0_CHECK(ctx->ulri);
7661 tcg_gen_st_tl(arg, cpu_env,
7662 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7663 register_name = "UserLocal";
7664 break;
7665 default:
7666 goto cp0_unimplemented;
7668 break;
7669 case CP0_REGISTER_05:
7670 switch (sel) {
7671 case 0:
7672 gen_helper_mtc0_pagemask(cpu_env, arg);
7673 register_name = "PageMask";
7674 break;
7675 case 1:
7676 check_insn(ctx, ISA_MIPS32R2);
7677 gen_helper_mtc0_pagegrain(cpu_env, arg);
7678 register_name = "PageGrain";
7679 ctx->base.is_jmp = DISAS_STOP;
7680 break;
7681 case 2:
7682 CP0_CHECK(ctx->sc);
7683 gen_helper_mtc0_segctl0(cpu_env, arg);
7684 register_name = "SegCtl0";
7685 break;
7686 case 3:
7687 CP0_CHECK(ctx->sc);
7688 gen_helper_mtc0_segctl1(cpu_env, arg);
7689 register_name = "SegCtl1";
7690 break;
7691 case 4:
7692 CP0_CHECK(ctx->sc);
7693 gen_helper_mtc0_segctl2(cpu_env, arg);
7694 register_name = "SegCtl2";
7695 break;
7696 case 5:
7697 check_pw(ctx);
7698 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7699 register_name = "PWBase";
7700 break;
7701 case 6:
7702 check_pw(ctx);
7703 gen_helper_mtc0_pwfield(cpu_env, arg);
7704 register_name = "PWField";
7705 break;
7706 case 7:
7707 check_pw(ctx);
7708 gen_helper_mtc0_pwsize(cpu_env, arg);
7709 register_name = "PWSize";
7710 break;
7711 default:
7712 goto cp0_unimplemented;
7714 break;
7715 case CP0_REGISTER_06:
7716 switch (sel) {
7717 case 0:
7718 gen_helper_mtc0_wired(cpu_env, arg);
7719 register_name = "Wired";
7720 break;
7721 case 1:
7722 check_insn(ctx, ISA_MIPS32R2);
7723 gen_helper_mtc0_srsconf0(cpu_env, arg);
7724 register_name = "SRSConf0";
7725 break;
7726 case 2:
7727 check_insn(ctx, ISA_MIPS32R2);
7728 gen_helper_mtc0_srsconf1(cpu_env, arg);
7729 register_name = "SRSConf1";
7730 break;
7731 case 3:
7732 check_insn(ctx, ISA_MIPS32R2);
7733 gen_helper_mtc0_srsconf2(cpu_env, arg);
7734 register_name = "SRSConf2";
7735 break;
7736 case 4:
7737 check_insn(ctx, ISA_MIPS32R2);
7738 gen_helper_mtc0_srsconf3(cpu_env, arg);
7739 register_name = "SRSConf3";
7740 break;
7741 case 5:
7742 check_insn(ctx, ISA_MIPS32R2);
7743 gen_helper_mtc0_srsconf4(cpu_env, arg);
7744 register_name = "SRSConf4";
7745 break;
7746 case 6:
7747 check_pw(ctx);
7748 gen_helper_mtc0_pwctl(cpu_env, arg);
7749 register_name = "PWCtl";
7750 break;
7751 default:
7752 goto cp0_unimplemented;
7754 break;
7755 case CP0_REGISTER_07:
7756 switch (sel) {
7757 case 0:
7758 check_insn(ctx, ISA_MIPS32R2);
7759 gen_helper_mtc0_hwrena(cpu_env, arg);
7760 ctx->base.is_jmp = DISAS_STOP;
7761 register_name = "HWREna";
7762 break;
7763 default:
7764 goto cp0_unimplemented;
7766 break;
7767 case CP0_REGISTER_08:
7768 switch (sel) {
7769 case 0:
7770 /* ignored */
7771 register_name = "BadVAddr";
7772 break;
7773 case 1:
7774 /* ignored */
7775 register_name = "BadInstr";
7776 break;
7777 case 2:
7778 /* ignored */
7779 register_name = "BadInstrP";
7780 break;
7781 case 3:
7782 /* ignored */
7783 register_name = "BadInstrX";
7784 break;
7785 default:
7786 goto cp0_unimplemented;
7788 break;
7789 case CP0_REGISTER_09:
7790 switch (sel) {
7791 case 0:
7792 gen_helper_mtc0_count(cpu_env, arg);
7793 register_name = "Count";
7794 break;
7795 case 6:
7796 CP0_CHECK(ctx->saar);
7797 gen_helper_mtc0_saari(cpu_env, arg);
7798 register_name = "SAARI";
7799 break;
7800 case 7:
7801 CP0_CHECK(ctx->saar);
7802 gen_helper_mtc0_saar(cpu_env, arg);
7803 register_name = "SAAR";
7804 break;
7805 default:
7806 goto cp0_unimplemented;
7808 break;
7809 case CP0_REGISTER_10:
7810 switch (sel) {
7811 case 0:
7812 gen_helper_mtc0_entryhi(cpu_env, arg);
7813 register_name = "EntryHi";
7814 break;
7815 default:
7816 goto cp0_unimplemented;
7818 break;
7819 case CP0_REGISTER_11:
7820 switch (sel) {
7821 case 0:
7822 gen_helper_mtc0_compare(cpu_env, arg);
7823 register_name = "Compare";
7824 break;
7825 /* 6,7 are implementation dependent */
7826 default:
7827 goto cp0_unimplemented;
7829 break;
7830 case CP0_REGISTER_12:
7831 switch (sel) {
7832 case 0:
7833 save_cpu_state(ctx, 1);
7834 gen_helper_mtc0_status(cpu_env, arg);
7835 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7836 gen_save_pc(ctx->base.pc_next + 4);
7837 ctx->base.is_jmp = DISAS_EXIT;
7838 register_name = "Status";
7839 break;
7840 case 1:
7841 check_insn(ctx, ISA_MIPS32R2);
7842 gen_helper_mtc0_intctl(cpu_env, arg);
7843 /* Stop translation as we may have switched the execution mode */
7844 ctx->base.is_jmp = DISAS_STOP;
7845 register_name = "IntCtl";
7846 break;
7847 case 2:
7848 check_insn(ctx, ISA_MIPS32R2);
7849 gen_helper_mtc0_srsctl(cpu_env, arg);
7850 /* Stop translation as we may have switched the execution mode */
7851 ctx->base.is_jmp = DISAS_STOP;
7852 register_name = "SRSCtl";
7853 break;
7854 case 3:
7855 check_insn(ctx, ISA_MIPS32R2);
7856 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7857 /* Stop translation as we may have switched the execution mode */
7858 ctx->base.is_jmp = DISAS_STOP;
7859 register_name = "SRSMap";
7860 break;
7861 default:
7862 goto cp0_unimplemented;
7864 break;
7865 case CP0_REGISTER_13:
7866 switch (sel) {
7867 case 0:
7868 save_cpu_state(ctx, 1);
7869 gen_helper_mtc0_cause(cpu_env, arg);
7870 /* Stop translation as we may have triggered an interrupt.
7871 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7872 * translated code to check for pending interrupts. */
7873 gen_save_pc(ctx->base.pc_next + 4);
7874 ctx->base.is_jmp = DISAS_EXIT;
7875 register_name = "Cause";
7876 break;
7877 default:
7878 goto cp0_unimplemented;
7880 break;
7881 case CP0_REGISTER_14:
7882 switch (sel) {
7883 case 0:
7884 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7885 register_name = "EPC";
7886 break;
7887 default:
7888 goto cp0_unimplemented;
7890 break;
7891 case CP0_REGISTER_15:
7892 switch (sel) {
7893 case 0:
7894 /* ignored */
7895 register_name = "PRid";
7896 break;
7897 case 1:
7898 check_insn(ctx, ISA_MIPS32R2);
7899 gen_helper_mtc0_ebase(cpu_env, arg);
7900 register_name = "EBase";
7901 break;
7902 default:
7903 goto cp0_unimplemented;
7905 break;
7906 case CP0_REGISTER_16:
7907 switch (sel) {
7908 case 0:
7909 gen_helper_mtc0_config0(cpu_env, arg);
7910 register_name = "Config";
7911 /* Stop translation as we may have switched the execution mode */
7912 ctx->base.is_jmp = DISAS_STOP;
7913 break;
7914 case 1:
7915 /* ignored, read only */
7916 register_name = "Config1";
7917 break;
7918 case 2:
7919 gen_helper_mtc0_config2(cpu_env, arg);
7920 register_name = "Config2";
7921 /* Stop translation as we may have switched the execution mode */
7922 ctx->base.is_jmp = DISAS_STOP;
7923 break;
7924 case 3:
7925 gen_helper_mtc0_config3(cpu_env, arg);
7926 register_name = "Config3";
7927 /* Stop translation as we may have switched the execution mode */
7928 ctx->base.is_jmp = DISAS_STOP;
7929 break;
7930 case 4:
7931 gen_helper_mtc0_config4(cpu_env, arg);
7932 register_name = "Config4";
7933 ctx->base.is_jmp = DISAS_STOP;
7934 break;
7935 case 5:
7936 gen_helper_mtc0_config5(cpu_env, arg);
7937 register_name = "Config5";
7938 /* Stop translation as we may have switched the execution mode */
7939 ctx->base.is_jmp = DISAS_STOP;
7940 break;
7941 /* 6,7 are implementation dependent */
7942 case 6:
7943 /* ignored */
7944 register_name = "Config6";
7945 break;
7946 case 7:
7947 /* ignored */
7948 register_name = "Config7";
7949 break;
7950 default:
7951 register_name = "Invalid config selector";
7952 goto cp0_unimplemented;
7954 break;
7955 case CP0_REGISTER_17:
7956 switch (sel) {
7957 case 0:
7958 gen_helper_mtc0_lladdr(cpu_env, arg);
7959 register_name = "LLAddr";
7960 break;
7961 case 1:
7962 CP0_CHECK(ctx->mrp);
7963 gen_helper_mtc0_maar(cpu_env, arg);
7964 register_name = "MAAR";
7965 break;
7966 case 2:
7967 CP0_CHECK(ctx->mrp);
7968 gen_helper_mtc0_maari(cpu_env, arg);
7969 register_name = "MAARI";
7970 break;
7971 default:
7972 goto cp0_unimplemented;
7974 break;
7975 case CP0_REGISTER_18:
7976 switch (sel) {
7977 case 0:
7978 case 1:
7979 case 2:
7980 case 3:
7981 case 4:
7982 case 5:
7983 case 6:
7984 case 7:
7985 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7986 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7987 register_name = "WatchLo";
7988 break;
7989 default:
7990 goto cp0_unimplemented;
7992 break;
7993 case CP0_REGISTER_19:
7994 switch (sel) {
7995 case 0:
7996 case 1:
7997 case 2:
7998 case 3:
7999 case 4:
8000 case 5:
8001 case 6:
8002 case 7:
8003 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8004 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8005 register_name = "WatchHi";
8006 break;
8007 default:
8008 goto cp0_unimplemented;
8010 break;
8011 case CP0_REGISTER_20:
8012 switch (sel) {
8013 case 0:
8014 #if defined(TARGET_MIPS64)
8015 check_insn(ctx, ISA_MIPS3);
8016 gen_helper_mtc0_xcontext(cpu_env, arg);
8017 register_name = "XContext";
8018 break;
8019 #endif
8020 default:
8021 goto cp0_unimplemented;
8023 break;
8024 case CP0_REGISTER_21:
8025 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8026 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8027 switch (sel) {
8028 case 0:
8029 gen_helper_mtc0_framemask(cpu_env, arg);
8030 register_name = "Framemask";
8031 break;
8032 default:
8033 goto cp0_unimplemented;
8035 break;
8036 case CP0_REGISTER_22:
8037 /* ignored */
8038 register_name = "Diagnostic"; /* implementation dependent */
8039 break;
8040 case CP0_REGISTER_23:
8041 switch (sel) {
8042 case 0:
8043 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8044 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8045 gen_save_pc(ctx->base.pc_next + 4);
8046 ctx->base.is_jmp = DISAS_EXIT;
8047 register_name = "Debug";
8048 break;
8049 case 1:
8050 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8051 register_name = "TraceControl";
8052 /* Stop translation as we may have switched the execution mode */
8053 ctx->base.is_jmp = DISAS_STOP;
8054 goto cp0_unimplemented;
8055 case 2:
8056 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8057 register_name = "TraceControl2";
8058 /* Stop translation as we may have switched the execution mode */
8059 ctx->base.is_jmp = DISAS_STOP;
8060 goto cp0_unimplemented;
8061 case 3:
8062 /* Stop translation as we may have switched the execution mode */
8063 ctx->base.is_jmp = DISAS_STOP;
8064 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8065 register_name = "UserTraceData";
8066 /* Stop translation as we may have switched the execution mode */
8067 ctx->base.is_jmp = DISAS_STOP;
8068 goto cp0_unimplemented;
8069 case 4:
8070 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8071 /* Stop translation as we may have switched the execution mode */
8072 ctx->base.is_jmp = DISAS_STOP;
8073 register_name = "TraceBPC";
8074 goto cp0_unimplemented;
8075 default:
8076 goto cp0_unimplemented;
8078 break;
8079 case CP0_REGISTER_24:
8080 switch (sel) {
8081 case 0:
8082 /* EJTAG support */
8083 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8084 register_name = "DEPC";
8085 break;
8086 default:
8087 goto cp0_unimplemented;
8089 break;
8090 case CP0_REGISTER_25:
8091 switch (sel) {
8092 case 0:
8093 gen_helper_mtc0_performance0(cpu_env, arg);
8094 register_name = "Performance0";
8095 break;
8096 case 1:
8097 // gen_helper_mtc0_performance1(arg);
8098 register_name = "Performance1";
8099 goto cp0_unimplemented;
8100 case 2:
8101 // gen_helper_mtc0_performance2(arg);
8102 register_name = "Performance2";
8103 goto cp0_unimplemented;
8104 case 3:
8105 // gen_helper_mtc0_performance3(arg);
8106 register_name = "Performance3";
8107 goto cp0_unimplemented;
8108 case 4:
8109 // gen_helper_mtc0_performance4(arg);
8110 register_name = "Performance4";
8111 goto cp0_unimplemented;
8112 case 5:
8113 // gen_helper_mtc0_performance5(arg);
8114 register_name = "Performance5";
8115 goto cp0_unimplemented;
8116 case 6:
8117 // gen_helper_mtc0_performance6(arg);
8118 register_name = "Performance6";
8119 goto cp0_unimplemented;
8120 case 7:
8121 // gen_helper_mtc0_performance7(arg);
8122 register_name = "Performance7";
8123 goto cp0_unimplemented;
8124 default:
8125 goto cp0_unimplemented;
8127 break;
8128 case CP0_REGISTER_26:
8129 switch (sel) {
8130 case 0:
8131 gen_helper_mtc0_errctl(cpu_env, arg);
8132 ctx->base.is_jmp = DISAS_STOP;
8133 register_name = "ErrCtl";
8134 break;
8135 default:
8136 goto cp0_unimplemented;
8138 break;
8139 case CP0_REGISTER_27:
8140 switch (sel) {
8141 case 0:
8142 case 1:
8143 case 2:
8144 case 3:
8145 /* ignored */
8146 register_name = "CacheErr";
8147 break;
8148 default:
8149 goto cp0_unimplemented;
8151 break;
8152 case CP0_REGISTER_28:
8153 switch (sel) {
8154 case 0:
8155 case 2:
8156 case 4:
8157 case 6:
8158 gen_helper_mtc0_taglo(cpu_env, arg);
8159 register_name = "TagLo";
8160 break;
8161 case 1:
8162 case 3:
8163 case 5:
8164 case 7:
8165 gen_helper_mtc0_datalo(cpu_env, arg);
8166 register_name = "DataLo";
8167 break;
8168 default:
8169 goto cp0_unimplemented;
8171 break;
8172 case CP0_REGISTER_29:
8173 switch (sel) {
8174 case 0:
8175 case 2:
8176 case 4:
8177 case 6:
8178 gen_helper_mtc0_taghi(cpu_env, arg);
8179 register_name = "TagHi";
8180 break;
8181 case 1:
8182 case 3:
8183 case 5:
8184 case 7:
8185 gen_helper_mtc0_datahi(cpu_env, arg);
8186 register_name = "DataHi";
8187 break;
8188 default:
8189 register_name = "invalid sel";
8190 goto cp0_unimplemented;
8192 break;
8193 case CP0_REGISTER_30:
8194 switch (sel) {
8195 case 0:
8196 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8197 register_name = "ErrorEPC";
8198 break;
8199 default:
8200 goto cp0_unimplemented;
8202 break;
8203 case CP0_REGISTER_31:
8204 switch (sel) {
8205 case 0:
8206 /* EJTAG support */
8207 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8208 register_name = "DESAVE";
8209 break;
8210 case 2:
8211 case 3:
8212 case 4:
8213 case 5:
8214 case 6:
8215 case 7:
8216 CP0_CHECK(ctx->kscrexist & (1 << sel));
8217 tcg_gen_st_tl(arg, cpu_env,
8218 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8219 register_name = "KScratch";
8220 break;
8221 default:
8222 goto cp0_unimplemented;
8224 break;
8225 default:
8226 goto cp0_unimplemented;
8228 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8230 /* For simplicity assume that all writes can cause interrupts. */
8231 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8232 gen_io_end();
8233 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8234 * translated code to check for pending interrupts. */
8235 gen_save_pc(ctx->base.pc_next + 4);
8236 ctx->base.is_jmp = DISAS_EXIT;
8238 return;
8240 cp0_unimplemented:
8241 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8242 register_name, reg, sel);
8245 #if defined(TARGET_MIPS64)
8246 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8248 const char *register_name = "invalid";
8250 if (sel != 0)
8251 check_insn(ctx, ISA_MIPS64);
8253 switch (reg) {
8254 case CP0_REGISTER_00:
8255 switch (sel) {
8256 case 0:
8257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8258 register_name = "Index";
8259 break;
8260 case 1:
8261 CP0_CHECK(ctx->insn_flags & ASE_MT);
8262 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8263 register_name = "MVPControl";
8264 break;
8265 case 2:
8266 CP0_CHECK(ctx->insn_flags & ASE_MT);
8267 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8268 register_name = "MVPConf0";
8269 break;
8270 case 3:
8271 CP0_CHECK(ctx->insn_flags & ASE_MT);
8272 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8273 register_name = "MVPConf1";
8274 break;
8275 case 4:
8276 CP0_CHECK(ctx->vp);
8277 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8278 register_name = "VPControl";
8279 break;
8280 default:
8281 goto cp0_unimplemented;
8283 break;
8284 case CP0_REGISTER_01:
8285 switch (sel) {
8286 case 0:
8287 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8288 gen_helper_mfc0_random(arg, cpu_env);
8289 register_name = "Random";
8290 break;
8291 case 1:
8292 CP0_CHECK(ctx->insn_flags & ASE_MT);
8293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8294 register_name = "VPEControl";
8295 break;
8296 case 2:
8297 CP0_CHECK(ctx->insn_flags & ASE_MT);
8298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8299 register_name = "VPEConf0";
8300 break;
8301 case 3:
8302 CP0_CHECK(ctx->insn_flags & ASE_MT);
8303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8304 register_name = "VPEConf1";
8305 break;
8306 case 4:
8307 CP0_CHECK(ctx->insn_flags & ASE_MT);
8308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8309 register_name = "YQMask";
8310 break;
8311 case 5:
8312 CP0_CHECK(ctx->insn_flags & ASE_MT);
8313 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8314 register_name = "VPESchedule";
8315 break;
8316 case 6:
8317 CP0_CHECK(ctx->insn_flags & ASE_MT);
8318 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8319 register_name = "VPEScheFBack";
8320 break;
8321 case 7:
8322 CP0_CHECK(ctx->insn_flags & ASE_MT);
8323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8324 register_name = "VPEOpt";
8325 break;
8326 default:
8327 goto cp0_unimplemented;
8329 break;
8330 case CP0_REGISTER_02:
8331 switch (sel) {
8332 case 0:
8333 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8334 register_name = "EntryLo0";
8335 break;
8336 case 1:
8337 CP0_CHECK(ctx->insn_flags & ASE_MT);
8338 gen_helper_mfc0_tcstatus(arg, cpu_env);
8339 register_name = "TCStatus";
8340 break;
8341 case 2:
8342 CP0_CHECK(ctx->insn_flags & ASE_MT);
8343 gen_helper_mfc0_tcbind(arg, cpu_env);
8344 register_name = "TCBind";
8345 break;
8346 case 3:
8347 CP0_CHECK(ctx->insn_flags & ASE_MT);
8348 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8349 register_name = "TCRestart";
8350 break;
8351 case 4:
8352 CP0_CHECK(ctx->insn_flags & ASE_MT);
8353 gen_helper_dmfc0_tchalt(arg, cpu_env);
8354 register_name = "TCHalt";
8355 break;
8356 case 5:
8357 CP0_CHECK(ctx->insn_flags & ASE_MT);
8358 gen_helper_dmfc0_tccontext(arg, cpu_env);
8359 register_name = "TCContext";
8360 break;
8361 case 6:
8362 CP0_CHECK(ctx->insn_flags & ASE_MT);
8363 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8364 register_name = "TCSchedule";
8365 break;
8366 case 7:
8367 CP0_CHECK(ctx->insn_flags & ASE_MT);
8368 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8369 register_name = "TCScheFBack";
8370 break;
8371 default:
8372 goto cp0_unimplemented;
8374 break;
8375 case CP0_REGISTER_03:
8376 switch (sel) {
8377 case 0:
8378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8379 register_name = "EntryLo1";
8380 break;
8381 case 1:
8382 CP0_CHECK(ctx->vp);
8383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8384 register_name = "GlobalNumber";
8385 break;
8386 default:
8387 goto cp0_unimplemented;
8389 break;
8390 case CP0_REGISTER_04:
8391 switch (sel) {
8392 case 0:
8393 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8394 register_name = "Context";
8395 break;
8396 case 1:
8397 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8398 register_name = "ContextConfig";
8399 goto cp0_unimplemented;
8400 case 2:
8401 CP0_CHECK(ctx->ulri);
8402 tcg_gen_ld_tl(arg, cpu_env,
8403 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8404 register_name = "UserLocal";
8405 break;
8406 default:
8407 goto cp0_unimplemented;
8409 break;
8410 case CP0_REGISTER_05:
8411 switch (sel) {
8412 case 0:
8413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8414 register_name = "PageMask";
8415 break;
8416 case 1:
8417 check_insn(ctx, ISA_MIPS32R2);
8418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8419 register_name = "PageGrain";
8420 break;
8421 case 2:
8422 CP0_CHECK(ctx->sc);
8423 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8424 register_name = "SegCtl0";
8425 break;
8426 case 3:
8427 CP0_CHECK(ctx->sc);
8428 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8429 register_name = "SegCtl1";
8430 break;
8431 case 4:
8432 CP0_CHECK(ctx->sc);
8433 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8434 register_name = "SegCtl2";
8435 break;
8436 case 5:
8437 check_pw(ctx);
8438 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8439 register_name = "PWBase";
8440 break;
8441 case 6:
8442 check_pw(ctx);
8443 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8444 register_name = "PWField";
8445 break;
8446 case 7:
8447 check_pw(ctx);
8448 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8449 register_name = "PWSize";
8450 break;
8451 default:
8452 goto cp0_unimplemented;
8454 break;
8455 case CP0_REGISTER_06:
8456 switch (sel) {
8457 case 0:
8458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8459 register_name = "Wired";
8460 break;
8461 case 1:
8462 check_insn(ctx, ISA_MIPS32R2);
8463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8464 register_name = "SRSConf0";
8465 break;
8466 case 2:
8467 check_insn(ctx, ISA_MIPS32R2);
8468 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8469 register_name = "SRSConf1";
8470 break;
8471 case 3:
8472 check_insn(ctx, ISA_MIPS32R2);
8473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8474 register_name = "SRSConf2";
8475 break;
8476 case 4:
8477 check_insn(ctx, ISA_MIPS32R2);
8478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8479 register_name = "SRSConf3";
8480 break;
8481 case 5:
8482 check_insn(ctx, ISA_MIPS32R2);
8483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8484 register_name = "SRSConf4";
8485 break;
8486 case 6:
8487 check_pw(ctx);
8488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8489 register_name = "PWCtl";
8490 break;
8491 default:
8492 goto cp0_unimplemented;
8494 break;
8495 case CP0_REGISTER_07:
8496 switch (sel) {
8497 case 0:
8498 check_insn(ctx, ISA_MIPS32R2);
8499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8500 register_name = "HWREna";
8501 break;
8502 default:
8503 goto cp0_unimplemented;
8505 break;
8506 case CP0_REGISTER_08:
8507 switch (sel) {
8508 case 0:
8509 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8510 register_name = "BadVAddr";
8511 break;
8512 case 1:
8513 CP0_CHECK(ctx->bi);
8514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8515 register_name = "BadInstr";
8516 break;
8517 case 2:
8518 CP0_CHECK(ctx->bp);
8519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8520 register_name = "BadInstrP";
8521 break;
8522 case 3:
8523 CP0_CHECK(ctx->bi);
8524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8525 tcg_gen_andi_tl(arg, arg, ~0xffff);
8526 register_name = "BadInstrX";
8527 break;
8528 default:
8529 goto cp0_unimplemented;
8531 break;
8532 case CP0_REGISTER_09:
8533 switch (sel) {
8534 case 0:
8535 /* Mark as an IO operation because we read the time. */
8536 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8537 gen_io_start();
8539 gen_helper_mfc0_count(arg, cpu_env);
8540 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8541 gen_io_end();
8543 /* Break the TB to be able to take timer interrupts immediately
8544 after reading count. DISAS_STOP isn't sufficient, we need to
8545 ensure we break completely out of translated code. */
8546 gen_save_pc(ctx->base.pc_next + 4);
8547 ctx->base.is_jmp = DISAS_EXIT;
8548 register_name = "Count";
8549 break;
8550 case 6:
8551 CP0_CHECK(ctx->saar);
8552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8553 register_name = "SAARI";
8554 break;
8555 case 7:
8556 CP0_CHECK(ctx->saar);
8557 gen_helper_dmfc0_saar(arg, cpu_env);
8558 register_name = "SAAR";
8559 break;
8560 default:
8561 goto cp0_unimplemented;
8563 break;
8564 case CP0_REGISTER_10:
8565 switch (sel) {
8566 case 0:
8567 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8568 register_name = "EntryHi";
8569 break;
8570 default:
8571 goto cp0_unimplemented;
8573 break;
8574 case CP0_REGISTER_11:
8575 switch (sel) {
8576 case 0:
8577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8578 register_name = "Compare";
8579 break;
8580 /* 6,7 are implementation dependent */
8581 default:
8582 goto cp0_unimplemented;
8584 break;
8585 case CP0_REGISTER_12:
8586 switch (sel) {
8587 case 0:
8588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8589 register_name = "Status";
8590 break;
8591 case 1:
8592 check_insn(ctx, ISA_MIPS32R2);
8593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8594 register_name = "IntCtl";
8595 break;
8596 case 2:
8597 check_insn(ctx, ISA_MIPS32R2);
8598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8599 register_name = "SRSCtl";
8600 break;
8601 case 3:
8602 check_insn(ctx, ISA_MIPS32R2);
8603 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8604 register_name = "SRSMap";
8605 break;
8606 default:
8607 goto cp0_unimplemented;
8609 break;
8610 case CP0_REGISTER_13:
8611 switch (sel) {
8612 case 0:
8613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8614 register_name = "Cause";
8615 break;
8616 default:
8617 goto cp0_unimplemented;
8619 break;
8620 case CP0_REGISTER_14:
8621 switch (sel) {
8622 case 0:
8623 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8624 register_name = "EPC";
8625 break;
8626 default:
8627 goto cp0_unimplemented;
8629 break;
8630 case CP0_REGISTER_15:
8631 switch (sel) {
8632 case 0:
8633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8634 register_name = "PRid";
8635 break;
8636 case 1:
8637 check_insn(ctx, ISA_MIPS32R2);
8638 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8639 register_name = "EBase";
8640 break;
8641 case 3:
8642 check_insn(ctx, ISA_MIPS32R2);
8643 CP0_CHECK(ctx->cmgcr);
8644 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8645 register_name = "CMGCRBase";
8646 break;
8647 default:
8648 goto cp0_unimplemented;
8650 break;
8651 case CP0_REGISTER_16:
8652 switch (sel) {
8653 case 0:
8654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8655 register_name = "Config";
8656 break;
8657 case 1:
8658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8659 register_name = "Config1";
8660 break;
8661 case 2:
8662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8663 register_name = "Config2";
8664 break;
8665 case 3:
8666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8667 register_name = "Config3";
8668 break;
8669 case 4:
8670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8671 register_name = "Config4";
8672 break;
8673 case 5:
8674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8675 register_name = "Config5";
8676 break;
8677 /* 6,7 are implementation dependent */
8678 case 6:
8679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8680 register_name = "Config6";
8681 break;
8682 case 7:
8683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8684 register_name = "Config7";
8685 break;
8686 default:
8687 goto cp0_unimplemented;
8689 break;
8690 case CP0_REGISTER_17:
8691 switch (sel) {
8692 case 0:
8693 gen_helper_dmfc0_lladdr(arg, cpu_env);
8694 register_name = "LLAddr";
8695 break;
8696 case 1:
8697 CP0_CHECK(ctx->mrp);
8698 gen_helper_dmfc0_maar(arg, cpu_env);
8699 register_name = "MAAR";
8700 break;
8701 case 2:
8702 CP0_CHECK(ctx->mrp);
8703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8704 register_name = "MAARI";
8705 break;
8706 default:
8707 goto cp0_unimplemented;
8709 break;
8710 case CP0_REGISTER_18:
8711 switch (sel) {
8712 case 0:
8713 case 1:
8714 case 2:
8715 case 3:
8716 case 4:
8717 case 5:
8718 case 6:
8719 case 7:
8720 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8721 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8722 register_name = "WatchLo";
8723 break;
8724 default:
8725 goto cp0_unimplemented;
8727 break;
8728 case CP0_REGISTER_19:
8729 switch (sel) {
8730 case 0:
8731 case 1:
8732 case 2:
8733 case 3:
8734 case 4:
8735 case 5:
8736 case 6:
8737 case 7:
8738 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8739 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8740 register_name = "WatchHi";
8741 break;
8742 default:
8743 goto cp0_unimplemented;
8745 break;
8746 case CP0_REGISTER_20:
8747 switch (sel) {
8748 case 0:
8749 check_insn(ctx, ISA_MIPS3);
8750 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8751 register_name = "XContext";
8752 break;
8753 default:
8754 goto cp0_unimplemented;
8756 break;
8757 case CP0_REGISTER_21:
8758 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8759 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8760 switch (sel) {
8761 case 0:
8762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8763 register_name = "Framemask";
8764 break;
8765 default:
8766 goto cp0_unimplemented;
8768 break;
8769 case CP0_REGISTER_22:
8770 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8771 register_name = "'Diagnostic"; /* implementation dependent */
8772 break;
8773 case CP0_REGISTER_23:
8774 switch (sel) {
8775 case 0:
8776 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8777 register_name = "Debug";
8778 break;
8779 case 1:
8780 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8781 register_name = "TraceControl";
8782 goto cp0_unimplemented;
8783 case 2:
8784 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8785 register_name = "TraceControl2";
8786 goto cp0_unimplemented;
8787 case 3:
8788 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8789 register_name = "UserTraceData";
8790 goto cp0_unimplemented;
8791 case 4:
8792 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8793 register_name = "TraceBPC";
8794 goto cp0_unimplemented;
8795 default:
8796 goto cp0_unimplemented;
8798 break;
8799 case CP0_REGISTER_24:
8800 switch (sel) {
8801 case 0:
8802 /* EJTAG support */
8803 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8804 register_name = "DEPC";
8805 break;
8806 default:
8807 goto cp0_unimplemented;
8809 break;
8810 case CP0_REGISTER_25:
8811 switch (sel) {
8812 case 0:
8813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8814 register_name = "Performance0";
8815 break;
8816 case 1:
8817 // gen_helper_dmfc0_performance1(arg);
8818 register_name = "Performance1";
8819 goto cp0_unimplemented;
8820 case 2:
8821 // gen_helper_dmfc0_performance2(arg);
8822 register_name = "Performance2";
8823 goto cp0_unimplemented;
8824 case 3:
8825 // gen_helper_dmfc0_performance3(arg);
8826 register_name = "Performance3";
8827 goto cp0_unimplemented;
8828 case 4:
8829 // gen_helper_dmfc0_performance4(arg);
8830 register_name = "Performance4";
8831 goto cp0_unimplemented;
8832 case 5:
8833 // gen_helper_dmfc0_performance5(arg);
8834 register_name = "Performance5";
8835 goto cp0_unimplemented;
8836 case 6:
8837 // gen_helper_dmfc0_performance6(arg);
8838 register_name = "Performance6";
8839 goto cp0_unimplemented;
8840 case 7:
8841 // gen_helper_dmfc0_performance7(arg);
8842 register_name = "Performance7";
8843 goto cp0_unimplemented;
8844 default:
8845 goto cp0_unimplemented;
8847 break;
8848 case CP0_REGISTER_26:
8849 switch (sel) {
8850 case 0:
8851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8852 register_name = "ErrCtl";
8853 break;
8854 default:
8855 goto cp0_unimplemented;
8857 break;
8858 case CP0_REGISTER_27:
8859 switch (sel) {
8860 /* ignored */
8861 case 0:
8862 case 1:
8863 case 2:
8864 case 3:
8865 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8866 register_name = "CacheErr";
8867 break;
8868 default:
8869 goto cp0_unimplemented;
8871 break;
8872 case CP0_REGISTER_28:
8873 switch (sel) {
8874 case 0:
8875 case 2:
8876 case 4:
8877 case 6:
8878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8879 register_name = "TagLo";
8880 break;
8881 case 1:
8882 case 3:
8883 case 5:
8884 case 7:
8885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8886 register_name = "DataLo";
8887 break;
8888 default:
8889 goto cp0_unimplemented;
8891 break;
8892 case CP0_REGISTER_29:
8893 switch (sel) {
8894 case 0:
8895 case 2:
8896 case 4:
8897 case 6:
8898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8899 register_name = "TagHi";
8900 break;
8901 case 1:
8902 case 3:
8903 case 5:
8904 case 7:
8905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8906 register_name = "DataHi";
8907 break;
8908 default:
8909 goto cp0_unimplemented;
8911 break;
8912 case CP0_REGISTER_30:
8913 switch (sel) {
8914 case 0:
8915 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8916 register_name = "ErrorEPC";
8917 break;
8918 default:
8919 goto cp0_unimplemented;
8921 break;
8922 case CP0_REGISTER_31:
8923 switch (sel) {
8924 case 0:
8925 /* EJTAG support */
8926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8927 register_name = "DESAVE";
8928 break;
8929 case 2:
8930 case 3:
8931 case 4:
8932 case 5:
8933 case 6:
8934 case 7:
8935 CP0_CHECK(ctx->kscrexist & (1 << sel));
8936 tcg_gen_ld_tl(arg, cpu_env,
8937 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8938 register_name = "KScratch";
8939 break;
8940 default:
8941 goto cp0_unimplemented;
8943 break;
8944 default:
8945 goto cp0_unimplemented;
8947 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8948 return;
8950 cp0_unimplemented:
8951 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8952 register_name, reg, sel);
8953 gen_mfc0_unimplemented(ctx, arg);
8956 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8958 const char *register_name = "invalid";
8960 if (sel != 0)
8961 check_insn(ctx, ISA_MIPS64);
8963 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8964 gen_io_start();
8967 switch (reg) {
8968 case CP0_REGISTER_00:
8969 switch (sel) {
8970 case 0:
8971 gen_helper_mtc0_index(cpu_env, arg);
8972 register_name = "Index";
8973 break;
8974 case 1:
8975 CP0_CHECK(ctx->insn_flags & ASE_MT);
8976 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8977 register_name = "MVPControl";
8978 break;
8979 case 2:
8980 CP0_CHECK(ctx->insn_flags & ASE_MT);
8981 /* ignored */
8982 register_name = "MVPConf0";
8983 break;
8984 case 3:
8985 CP0_CHECK(ctx->insn_flags & ASE_MT);
8986 /* ignored */
8987 register_name = "MVPConf1";
8988 break;
8989 case 4:
8990 CP0_CHECK(ctx->vp);
8991 /* ignored */
8992 register_name = "VPControl";
8993 break;
8994 default:
8995 goto cp0_unimplemented;
8997 break;
8998 case CP0_REGISTER_01:
8999 switch (sel) {
9000 case 0:
9001 /* ignored */
9002 register_name = "Random";
9003 break;
9004 case 1:
9005 CP0_CHECK(ctx->insn_flags & ASE_MT);
9006 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9007 register_name = "VPEControl";
9008 break;
9009 case 2:
9010 CP0_CHECK(ctx->insn_flags & ASE_MT);
9011 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9012 register_name = "VPEConf0";
9013 break;
9014 case 3:
9015 CP0_CHECK(ctx->insn_flags & ASE_MT);
9016 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9017 register_name = "VPEConf1";
9018 break;
9019 case 4:
9020 CP0_CHECK(ctx->insn_flags & ASE_MT);
9021 gen_helper_mtc0_yqmask(cpu_env, arg);
9022 register_name = "YQMask";
9023 break;
9024 case 5:
9025 CP0_CHECK(ctx->insn_flags & ASE_MT);
9026 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9027 register_name = "VPESchedule";
9028 break;
9029 case 6:
9030 CP0_CHECK(ctx->insn_flags & ASE_MT);
9031 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9032 register_name = "VPEScheFBack";
9033 break;
9034 case 7:
9035 CP0_CHECK(ctx->insn_flags & ASE_MT);
9036 gen_helper_mtc0_vpeopt(cpu_env, arg);
9037 register_name = "VPEOpt";
9038 break;
9039 default:
9040 goto cp0_unimplemented;
9042 break;
9043 case CP0_REGISTER_02:
9044 switch (sel) {
9045 case 0:
9046 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9047 register_name = "EntryLo0";
9048 break;
9049 case 1:
9050 CP0_CHECK(ctx->insn_flags & ASE_MT);
9051 gen_helper_mtc0_tcstatus(cpu_env, arg);
9052 register_name = "TCStatus";
9053 break;
9054 case 2:
9055 CP0_CHECK(ctx->insn_flags & ASE_MT);
9056 gen_helper_mtc0_tcbind(cpu_env, arg);
9057 register_name = "TCBind";
9058 break;
9059 case 3:
9060 CP0_CHECK(ctx->insn_flags & ASE_MT);
9061 gen_helper_mtc0_tcrestart(cpu_env, arg);
9062 register_name = "TCRestart";
9063 break;
9064 case 4:
9065 CP0_CHECK(ctx->insn_flags & ASE_MT);
9066 gen_helper_mtc0_tchalt(cpu_env, arg);
9067 register_name = "TCHalt";
9068 break;
9069 case 5:
9070 CP0_CHECK(ctx->insn_flags & ASE_MT);
9071 gen_helper_mtc0_tccontext(cpu_env, arg);
9072 register_name = "TCContext";
9073 break;
9074 case 6:
9075 CP0_CHECK(ctx->insn_flags & ASE_MT);
9076 gen_helper_mtc0_tcschedule(cpu_env, arg);
9077 register_name = "TCSchedule";
9078 break;
9079 case 7:
9080 CP0_CHECK(ctx->insn_flags & ASE_MT);
9081 gen_helper_mtc0_tcschefback(cpu_env, arg);
9082 register_name = "TCScheFBack";
9083 break;
9084 default:
9085 goto cp0_unimplemented;
9087 break;
9088 case CP0_REGISTER_03:
9089 switch (sel) {
9090 case 0:
9091 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9092 register_name = "EntryLo1";
9093 break;
9094 case 1:
9095 CP0_CHECK(ctx->vp);
9096 /* ignored */
9097 register_name = "GlobalNumber";
9098 break;
9099 default:
9100 goto cp0_unimplemented;
9102 break;
9103 case CP0_REGISTER_04:
9104 switch (sel) {
9105 case 0:
9106 gen_helper_mtc0_context(cpu_env, arg);
9107 register_name = "Context";
9108 break;
9109 case 1:
9110 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
9111 register_name = "ContextConfig";
9112 goto cp0_unimplemented;
9113 case 2:
9114 CP0_CHECK(ctx->ulri);
9115 tcg_gen_st_tl(arg, cpu_env,
9116 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9117 register_name = "UserLocal";
9118 break;
9119 default:
9120 goto cp0_unimplemented;
9122 break;
9123 case CP0_REGISTER_05:
9124 switch (sel) {
9125 case 0:
9126 gen_helper_mtc0_pagemask(cpu_env, arg);
9127 register_name = "PageMask";
9128 break;
9129 case 1:
9130 check_insn(ctx, ISA_MIPS32R2);
9131 gen_helper_mtc0_pagegrain(cpu_env, arg);
9132 register_name = "PageGrain";
9133 break;
9134 case 2:
9135 CP0_CHECK(ctx->sc);
9136 gen_helper_mtc0_segctl0(cpu_env, arg);
9137 register_name = "SegCtl0";
9138 break;
9139 case 3:
9140 CP0_CHECK(ctx->sc);
9141 gen_helper_mtc0_segctl1(cpu_env, arg);
9142 register_name = "SegCtl1";
9143 break;
9144 case 4:
9145 CP0_CHECK(ctx->sc);
9146 gen_helper_mtc0_segctl2(cpu_env, arg);
9147 register_name = "SegCtl2";
9148 break;
9149 case 5:
9150 check_pw(ctx);
9151 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9152 register_name = "PWBase";
9153 break;
9154 case 6:
9155 check_pw(ctx);
9156 gen_helper_mtc0_pwfield(cpu_env, arg);
9157 register_name = "PWField";
9158 break;
9159 case 7:
9160 check_pw(ctx);
9161 gen_helper_mtc0_pwsize(cpu_env, arg);
9162 register_name = "PWSize";
9163 break;
9164 default:
9165 goto cp0_unimplemented;
9167 break;
9168 case CP0_REGISTER_06:
9169 switch (sel) {
9170 case 0:
9171 gen_helper_mtc0_wired(cpu_env, arg);
9172 register_name = "Wired";
9173 break;
9174 case 1:
9175 check_insn(ctx, ISA_MIPS32R2);
9176 gen_helper_mtc0_srsconf0(cpu_env, arg);
9177 register_name = "SRSConf0";
9178 break;
9179 case 2:
9180 check_insn(ctx, ISA_MIPS32R2);
9181 gen_helper_mtc0_srsconf1(cpu_env, arg);
9182 register_name = "SRSConf1";
9183 break;
9184 case 3:
9185 check_insn(ctx, ISA_MIPS32R2);
9186 gen_helper_mtc0_srsconf2(cpu_env, arg);
9187 register_name = "SRSConf2";
9188 break;
9189 case 4:
9190 check_insn(ctx, ISA_MIPS32R2);
9191 gen_helper_mtc0_srsconf3(cpu_env, arg);
9192 register_name = "SRSConf3";
9193 break;
9194 case 5:
9195 check_insn(ctx, ISA_MIPS32R2);
9196 gen_helper_mtc0_srsconf4(cpu_env, arg);
9197 register_name = "SRSConf4";
9198 break;
9199 case 6:
9200 check_pw(ctx);
9201 gen_helper_mtc0_pwctl(cpu_env, arg);
9202 register_name = "PWCtl";
9203 break;
9204 default:
9205 goto cp0_unimplemented;
9207 break;
9208 case CP0_REGISTER_07:
9209 switch (sel) {
9210 case 0:
9211 check_insn(ctx, ISA_MIPS32R2);
9212 gen_helper_mtc0_hwrena(cpu_env, arg);
9213 ctx->base.is_jmp = DISAS_STOP;
9214 register_name = "HWREna";
9215 break;
9216 default:
9217 goto cp0_unimplemented;
9219 break;
9220 case CP0_REGISTER_08:
9221 switch (sel) {
9222 case 0:
9223 /* ignored */
9224 register_name = "BadVAddr";
9225 break;
9226 case 1:
9227 /* ignored */
9228 register_name = "BadInstr";
9229 break;
9230 case 2:
9231 /* ignored */
9232 register_name = "BadInstrP";
9233 break;
9234 case 3:
9235 /* ignored */
9236 register_name = "BadInstrX";
9237 break;
9238 default:
9239 goto cp0_unimplemented;
9241 break;
9242 case CP0_REGISTER_09:
9243 switch (sel) {
9244 case 0:
9245 gen_helper_mtc0_count(cpu_env, arg);
9246 register_name = "Count";
9247 break;
9248 case 6:
9249 CP0_CHECK(ctx->saar);
9250 gen_helper_mtc0_saari(cpu_env, arg);
9251 register_name = "SAARI";
9252 break;
9253 case 7:
9254 CP0_CHECK(ctx->saar);
9255 gen_helper_mtc0_saar(cpu_env, arg);
9256 register_name = "SAAR";
9257 break;
9258 default:
9259 goto cp0_unimplemented;
9261 /* Stop translation as we may have switched the execution mode */
9262 ctx->base.is_jmp = DISAS_STOP;
9263 break;
9264 case CP0_REGISTER_10:
9265 switch (sel) {
9266 case 0:
9267 gen_helper_mtc0_entryhi(cpu_env, arg);
9268 register_name = "EntryHi";
9269 break;
9270 default:
9271 goto cp0_unimplemented;
9273 break;
9274 case CP0_REGISTER_11:
9275 switch (sel) {
9276 case 0:
9277 gen_helper_mtc0_compare(cpu_env, arg);
9278 register_name = "Compare";
9279 break;
9280 /* 6,7 are implementation dependent */
9281 default:
9282 goto cp0_unimplemented;
9284 /* Stop translation as we may have switched the execution mode */
9285 ctx->base.is_jmp = DISAS_STOP;
9286 break;
9287 case CP0_REGISTER_12:
9288 switch (sel) {
9289 case 0:
9290 save_cpu_state(ctx, 1);
9291 gen_helper_mtc0_status(cpu_env, arg);
9292 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9293 gen_save_pc(ctx->base.pc_next + 4);
9294 ctx->base.is_jmp = DISAS_EXIT;
9295 register_name = "Status";
9296 break;
9297 case 1:
9298 check_insn(ctx, ISA_MIPS32R2);
9299 gen_helper_mtc0_intctl(cpu_env, arg);
9300 /* Stop translation as we may have switched the execution mode */
9301 ctx->base.is_jmp = DISAS_STOP;
9302 register_name = "IntCtl";
9303 break;
9304 case 2:
9305 check_insn(ctx, ISA_MIPS32R2);
9306 gen_helper_mtc0_srsctl(cpu_env, arg);
9307 /* Stop translation as we may have switched the execution mode */
9308 ctx->base.is_jmp = DISAS_STOP;
9309 register_name = "SRSCtl";
9310 break;
9311 case 3:
9312 check_insn(ctx, ISA_MIPS32R2);
9313 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9314 /* Stop translation as we may have switched the execution mode */
9315 ctx->base.is_jmp = DISAS_STOP;
9316 register_name = "SRSMap";
9317 break;
9318 default:
9319 goto cp0_unimplemented;
9321 break;
9322 case CP0_REGISTER_13:
9323 switch (sel) {
9324 case 0:
9325 save_cpu_state(ctx, 1);
9326 gen_helper_mtc0_cause(cpu_env, arg);
9327 /* Stop translation as we may have triggered an interrupt.
9328 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9329 * translated code to check for pending interrupts. */
9330 gen_save_pc(ctx->base.pc_next + 4);
9331 ctx->base.is_jmp = DISAS_EXIT;
9332 register_name = "Cause";
9333 break;
9334 default:
9335 goto cp0_unimplemented;
9337 break;
9338 case CP0_REGISTER_14:
9339 switch (sel) {
9340 case 0:
9341 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9342 register_name = "EPC";
9343 break;
9344 default:
9345 goto cp0_unimplemented;
9347 break;
9348 case CP0_REGISTER_15:
9349 switch (sel) {
9350 case 0:
9351 /* ignored */
9352 register_name = "PRid";
9353 break;
9354 case 1:
9355 check_insn(ctx, ISA_MIPS32R2);
9356 gen_helper_mtc0_ebase(cpu_env, arg);
9357 register_name = "EBase";
9358 break;
9359 default:
9360 goto cp0_unimplemented;
9362 break;
9363 case CP0_REGISTER_16:
9364 switch (sel) {
9365 case 0:
9366 gen_helper_mtc0_config0(cpu_env, arg);
9367 register_name = "Config";
9368 /* Stop translation as we may have switched the execution mode */
9369 ctx->base.is_jmp = DISAS_STOP;
9370 break;
9371 case 1:
9372 /* ignored, read only */
9373 register_name = "Config1";
9374 break;
9375 case 2:
9376 gen_helper_mtc0_config2(cpu_env, arg);
9377 register_name = "Config2";
9378 /* Stop translation as we may have switched the execution mode */
9379 ctx->base.is_jmp = DISAS_STOP;
9380 break;
9381 case 3:
9382 gen_helper_mtc0_config3(cpu_env, arg);
9383 register_name = "Config3";
9384 /* Stop translation as we may have switched the execution mode */
9385 ctx->base.is_jmp = DISAS_STOP;
9386 break;
9387 case 4:
9388 /* currently ignored */
9389 register_name = "Config4";
9390 break;
9391 case 5:
9392 gen_helper_mtc0_config5(cpu_env, arg);
9393 register_name = "Config5";
9394 /* Stop translation as we may have switched the execution mode */
9395 ctx->base.is_jmp = DISAS_STOP;
9396 break;
9397 /* 6,7 are implementation dependent */
9398 default:
9399 register_name = "Invalid config selector";
9400 goto cp0_unimplemented;
9402 break;
9403 case CP0_REGISTER_17:
9404 switch (sel) {
9405 case 0:
9406 gen_helper_mtc0_lladdr(cpu_env, arg);
9407 register_name = "LLAddr";
9408 break;
9409 case 1:
9410 CP0_CHECK(ctx->mrp);
9411 gen_helper_mtc0_maar(cpu_env, arg);
9412 register_name = "MAAR";
9413 break;
9414 case 2:
9415 CP0_CHECK(ctx->mrp);
9416 gen_helper_mtc0_maari(cpu_env, arg);
9417 register_name = "MAARI";
9418 break;
9419 default:
9420 goto cp0_unimplemented;
9422 break;
9423 case CP0_REGISTER_18:
9424 switch (sel) {
9425 case 0:
9426 case 1:
9427 case 2:
9428 case 3:
9429 case 4:
9430 case 5:
9431 case 6:
9432 case 7:
9433 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9434 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9435 register_name = "WatchLo";
9436 break;
9437 default:
9438 goto cp0_unimplemented;
9440 break;
9441 case CP0_REGISTER_19:
9442 switch (sel) {
9443 case 0:
9444 case 1:
9445 case 2:
9446 case 3:
9447 case 4:
9448 case 5:
9449 case 6:
9450 case 7:
9451 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9452 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9453 register_name = "WatchHi";
9454 break;
9455 default:
9456 goto cp0_unimplemented;
9458 break;
9459 case CP0_REGISTER_20:
9460 switch (sel) {
9461 case 0:
9462 check_insn(ctx, ISA_MIPS3);
9463 gen_helper_mtc0_xcontext(cpu_env, arg);
9464 register_name = "XContext";
9465 break;
9466 default:
9467 goto cp0_unimplemented;
9469 break;
9470 case CP0_REGISTER_21:
9471 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9472 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9473 switch (sel) {
9474 case 0:
9475 gen_helper_mtc0_framemask(cpu_env, arg);
9476 register_name = "Framemask";
9477 break;
9478 default:
9479 goto cp0_unimplemented;
9481 break;
9482 case CP0_REGISTER_22:
9483 /* ignored */
9484 register_name = "Diagnostic"; /* implementation dependent */
9485 break;
9486 case CP0_REGISTER_23:
9487 switch (sel) {
9488 case 0:
9489 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9490 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9491 gen_save_pc(ctx->base.pc_next + 4);
9492 ctx->base.is_jmp = DISAS_EXIT;
9493 register_name = "Debug";
9494 break;
9495 case 1:
9496 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9497 /* Stop translation as we may have switched the execution mode */
9498 ctx->base.is_jmp = DISAS_STOP;
9499 register_name = "TraceControl";
9500 goto cp0_unimplemented;
9501 case 2:
9502 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9503 /* Stop translation as we may have switched the execution mode */
9504 ctx->base.is_jmp = DISAS_STOP;
9505 register_name = "TraceControl2";
9506 goto cp0_unimplemented;
9507 case 3:
9508 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9509 /* Stop translation as we may have switched the execution mode */
9510 ctx->base.is_jmp = DISAS_STOP;
9511 register_name = "UserTraceData";
9512 goto cp0_unimplemented;
9513 case 4:
9514 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9515 /* Stop translation as we may have switched the execution mode */
9516 ctx->base.is_jmp = DISAS_STOP;
9517 register_name = "TraceBPC";
9518 goto cp0_unimplemented;
9519 default:
9520 goto cp0_unimplemented;
9522 break;
9523 case CP0_REGISTER_24:
9524 switch (sel) {
9525 case 0:
9526 /* EJTAG support */
9527 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9528 register_name = "DEPC";
9529 break;
9530 default:
9531 goto cp0_unimplemented;
9533 break;
9534 case CP0_REGISTER_25:
9535 switch (sel) {
9536 case 0:
9537 gen_helper_mtc0_performance0(cpu_env, arg);
9538 register_name = "Performance0";
9539 break;
9540 case 1:
9541 // gen_helper_mtc0_performance1(cpu_env, arg);
9542 register_name = "Performance1";
9543 goto cp0_unimplemented;
9544 case 2:
9545 // gen_helper_mtc0_performance2(cpu_env, arg);
9546 register_name = "Performance2";
9547 goto cp0_unimplemented;
9548 case 3:
9549 // gen_helper_mtc0_performance3(cpu_env, arg);
9550 register_name = "Performance3";
9551 goto cp0_unimplemented;
9552 case 4:
9553 // gen_helper_mtc0_performance4(cpu_env, arg);
9554 register_name = "Performance4";
9555 goto cp0_unimplemented;
9556 case 5:
9557 // gen_helper_mtc0_performance5(cpu_env, arg);
9558 register_name = "Performance5";
9559 goto cp0_unimplemented;
9560 case 6:
9561 // gen_helper_mtc0_performance6(cpu_env, arg);
9562 register_name = "Performance6";
9563 goto cp0_unimplemented;
9564 case 7:
9565 // gen_helper_mtc0_performance7(cpu_env, arg);
9566 register_name = "Performance7";
9567 goto cp0_unimplemented;
9568 default:
9569 goto cp0_unimplemented;
9571 break;
9572 case CP0_REGISTER_26:
9573 switch (sel) {
9574 case 0:
9575 gen_helper_mtc0_errctl(cpu_env, arg);
9576 ctx->base.is_jmp = DISAS_STOP;
9577 register_name = "ErrCtl";
9578 break;
9579 default:
9580 goto cp0_unimplemented;
9582 break;
9583 case CP0_REGISTER_27:
9584 switch (sel) {
9585 case 0:
9586 case 1:
9587 case 2:
9588 case 3:
9589 /* ignored */
9590 register_name = "CacheErr";
9591 break;
9592 default:
9593 goto cp0_unimplemented;
9595 break;
9596 case CP0_REGISTER_28:
9597 switch (sel) {
9598 case 0:
9599 case 2:
9600 case 4:
9601 case 6:
9602 gen_helper_mtc0_taglo(cpu_env, arg);
9603 register_name = "TagLo";
9604 break;
9605 case 1:
9606 case 3:
9607 case 5:
9608 case 7:
9609 gen_helper_mtc0_datalo(cpu_env, arg);
9610 register_name = "DataLo";
9611 break;
9612 default:
9613 goto cp0_unimplemented;
9615 break;
9616 case CP0_REGISTER_29:
9617 switch (sel) {
9618 case 0:
9619 case 2:
9620 case 4:
9621 case 6:
9622 gen_helper_mtc0_taghi(cpu_env, arg);
9623 register_name = "TagHi";
9624 break;
9625 case 1:
9626 case 3:
9627 case 5:
9628 case 7:
9629 gen_helper_mtc0_datahi(cpu_env, arg);
9630 register_name = "DataHi";
9631 break;
9632 default:
9633 register_name = "invalid sel";
9634 goto cp0_unimplemented;
9636 break;
9637 case CP0_REGISTER_30:
9638 switch (sel) {
9639 case 0:
9640 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9641 register_name = "ErrorEPC";
9642 break;
9643 default:
9644 goto cp0_unimplemented;
9646 break;
9647 case CP0_REGISTER_31:
9648 switch (sel) {
9649 case 0:
9650 /* EJTAG support */
9651 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9652 register_name = "DESAVE";
9653 break;
9654 case 2:
9655 case 3:
9656 case 4:
9657 case 5:
9658 case 6:
9659 case 7:
9660 CP0_CHECK(ctx->kscrexist & (1 << sel));
9661 tcg_gen_st_tl(arg, cpu_env,
9662 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9663 register_name = "KScratch";
9664 break;
9665 default:
9666 goto cp0_unimplemented;
9668 break;
9669 default:
9670 goto cp0_unimplemented;
9672 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9674 /* For simplicity assume that all writes can cause interrupts. */
9675 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9676 gen_io_end();
9677 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9678 * translated code to check for pending interrupts. */
9679 gen_save_pc(ctx->base.pc_next + 4);
9680 ctx->base.is_jmp = DISAS_EXIT;
9682 return;
9684 cp0_unimplemented:
9685 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9686 register_name, reg, sel);
9688 #endif /* TARGET_MIPS64 */
9690 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9691 int u, int sel, int h)
9693 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9694 TCGv t0 = tcg_temp_local_new();
9696 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9697 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9698 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9699 tcg_gen_movi_tl(t0, -1);
9700 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9701 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9702 tcg_gen_movi_tl(t0, -1);
9703 else if (u == 0) {
9704 switch (rt) {
9705 case 1:
9706 switch (sel) {
9707 case 1:
9708 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9709 break;
9710 case 2:
9711 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9712 break;
9713 default:
9714 goto die;
9715 break;
9717 break;
9718 case 2:
9719 switch (sel) {
9720 case 1:
9721 gen_helper_mftc0_tcstatus(t0, cpu_env);
9722 break;
9723 case 2:
9724 gen_helper_mftc0_tcbind(t0, cpu_env);
9725 break;
9726 case 3:
9727 gen_helper_mftc0_tcrestart(t0, cpu_env);
9728 break;
9729 case 4:
9730 gen_helper_mftc0_tchalt(t0, cpu_env);
9731 break;
9732 case 5:
9733 gen_helper_mftc0_tccontext(t0, cpu_env);
9734 break;
9735 case 6:
9736 gen_helper_mftc0_tcschedule(t0, cpu_env);
9737 break;
9738 case 7:
9739 gen_helper_mftc0_tcschefback(t0, cpu_env);
9740 break;
9741 default:
9742 gen_mfc0(ctx, t0, rt, sel);
9743 break;
9745 break;
9746 case 10:
9747 switch (sel) {
9748 case 0:
9749 gen_helper_mftc0_entryhi(t0, cpu_env);
9750 break;
9751 default:
9752 gen_mfc0(ctx, t0, rt, sel);
9753 break;
9755 case 12:
9756 switch (sel) {
9757 case 0:
9758 gen_helper_mftc0_status(t0, cpu_env);
9759 break;
9760 default:
9761 gen_mfc0(ctx, t0, rt, sel);
9762 break;
9764 case 13:
9765 switch (sel) {
9766 case 0:
9767 gen_helper_mftc0_cause(t0, cpu_env);
9768 break;
9769 default:
9770 goto die;
9771 break;
9773 break;
9774 case 14:
9775 switch (sel) {
9776 case 0:
9777 gen_helper_mftc0_epc(t0, cpu_env);
9778 break;
9779 default:
9780 goto die;
9781 break;
9783 break;
9784 case 15:
9785 switch (sel) {
9786 case 1:
9787 gen_helper_mftc0_ebase(t0, cpu_env);
9788 break;
9789 default:
9790 goto die;
9791 break;
9793 break;
9794 case 16:
9795 switch (sel) {
9796 case 0:
9797 case 1:
9798 case 2:
9799 case 3:
9800 case 4:
9801 case 5:
9802 case 6:
9803 case 7:
9804 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9805 break;
9806 default:
9807 goto die;
9808 break;
9810 break;
9811 case 23:
9812 switch (sel) {
9813 case 0:
9814 gen_helper_mftc0_debug(t0, cpu_env);
9815 break;
9816 default:
9817 gen_mfc0(ctx, t0, rt, sel);
9818 break;
9820 break;
9821 default:
9822 gen_mfc0(ctx, t0, rt, sel);
9824 } else switch (sel) {
9825 /* GPR registers. */
9826 case 0:
9827 gen_helper_1e0i(mftgpr, t0, rt);
9828 break;
9829 /* Auxiliary CPU registers */
9830 case 1:
9831 switch (rt) {
9832 case 0:
9833 gen_helper_1e0i(mftlo, t0, 0);
9834 break;
9835 case 1:
9836 gen_helper_1e0i(mfthi, t0, 0);
9837 break;
9838 case 2:
9839 gen_helper_1e0i(mftacx, t0, 0);
9840 break;
9841 case 4:
9842 gen_helper_1e0i(mftlo, t0, 1);
9843 break;
9844 case 5:
9845 gen_helper_1e0i(mfthi, t0, 1);
9846 break;
9847 case 6:
9848 gen_helper_1e0i(mftacx, t0, 1);
9849 break;
9850 case 8:
9851 gen_helper_1e0i(mftlo, t0, 2);
9852 break;
9853 case 9:
9854 gen_helper_1e0i(mfthi, t0, 2);
9855 break;
9856 case 10:
9857 gen_helper_1e0i(mftacx, t0, 2);
9858 break;
9859 case 12:
9860 gen_helper_1e0i(mftlo, t0, 3);
9861 break;
9862 case 13:
9863 gen_helper_1e0i(mfthi, t0, 3);
9864 break;
9865 case 14:
9866 gen_helper_1e0i(mftacx, t0, 3);
9867 break;
9868 case 16:
9869 gen_helper_mftdsp(t0, cpu_env);
9870 break;
9871 default:
9872 goto die;
9874 break;
9875 /* Floating point (COP1). */
9876 case 2:
9877 /* XXX: For now we support only a single FPU context. */
9878 if (h == 0) {
9879 TCGv_i32 fp0 = tcg_temp_new_i32();
9881 gen_load_fpr32(ctx, fp0, rt);
9882 tcg_gen_ext_i32_tl(t0, fp0);
9883 tcg_temp_free_i32(fp0);
9884 } else {
9885 TCGv_i32 fp0 = tcg_temp_new_i32();
9887 gen_load_fpr32h(ctx, fp0, rt);
9888 tcg_gen_ext_i32_tl(t0, fp0);
9889 tcg_temp_free_i32(fp0);
9891 break;
9892 case 3:
9893 /* XXX: For now we support only a single FPU context. */
9894 gen_helper_1e0i(cfc1, t0, rt);
9895 break;
9896 /* COP2: Not implemented. */
9897 case 4:
9898 case 5:
9899 /* fall through */
9900 default:
9901 goto die;
9903 trace_mips_translate_tr("mftr", rt, u, sel, h);
9904 gen_store_gpr(t0, rd);
9905 tcg_temp_free(t0);
9906 return;
9908 die:
9909 tcg_temp_free(t0);
9910 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9911 generate_exception_end(ctx, EXCP_RI);
9914 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9915 int u, int sel, int h)
9917 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9918 TCGv t0 = tcg_temp_local_new();
9920 gen_load_gpr(t0, rt);
9921 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9922 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9923 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9924 /* NOP */ ;
9925 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9926 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9927 /* NOP */ ;
9928 else if (u == 0) {
9929 switch (rd) {
9930 case 1:
9931 switch (sel) {
9932 case 1:
9933 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9934 break;
9935 case 2:
9936 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9937 break;
9938 default:
9939 goto die;
9940 break;
9942 break;
9943 case 2:
9944 switch (sel) {
9945 case 1:
9946 gen_helper_mttc0_tcstatus(cpu_env, t0);
9947 break;
9948 case 2:
9949 gen_helper_mttc0_tcbind(cpu_env, t0);
9950 break;
9951 case 3:
9952 gen_helper_mttc0_tcrestart(cpu_env, t0);
9953 break;
9954 case 4:
9955 gen_helper_mttc0_tchalt(cpu_env, t0);
9956 break;
9957 case 5:
9958 gen_helper_mttc0_tccontext(cpu_env, t0);
9959 break;
9960 case 6:
9961 gen_helper_mttc0_tcschedule(cpu_env, t0);
9962 break;
9963 case 7:
9964 gen_helper_mttc0_tcschefback(cpu_env, t0);
9965 break;
9966 default:
9967 gen_mtc0(ctx, t0, rd, sel);
9968 break;
9970 break;
9971 case 10:
9972 switch (sel) {
9973 case 0:
9974 gen_helper_mttc0_entryhi(cpu_env, t0);
9975 break;
9976 default:
9977 gen_mtc0(ctx, t0, rd, sel);
9978 break;
9980 case 12:
9981 switch (sel) {
9982 case 0:
9983 gen_helper_mttc0_status(cpu_env, t0);
9984 break;
9985 default:
9986 gen_mtc0(ctx, t0, rd, sel);
9987 break;
9989 case 13:
9990 switch (sel) {
9991 case 0:
9992 gen_helper_mttc0_cause(cpu_env, t0);
9993 break;
9994 default:
9995 goto die;
9996 break;
9998 break;
9999 case 15:
10000 switch (sel) {
10001 case 1:
10002 gen_helper_mttc0_ebase(cpu_env, t0);
10003 break;
10004 default:
10005 goto die;
10006 break;
10008 break;
10009 case 23:
10010 switch (sel) {
10011 case 0:
10012 gen_helper_mttc0_debug(cpu_env, t0);
10013 break;
10014 default:
10015 gen_mtc0(ctx, t0, rd, sel);
10016 break;
10018 break;
10019 default:
10020 gen_mtc0(ctx, t0, rd, sel);
10022 } else switch (sel) {
10023 /* GPR registers. */
10024 case 0:
10025 gen_helper_0e1i(mttgpr, t0, rd);
10026 break;
10027 /* Auxiliary CPU registers */
10028 case 1:
10029 switch (rd) {
10030 case 0:
10031 gen_helper_0e1i(mttlo, t0, 0);
10032 break;
10033 case 1:
10034 gen_helper_0e1i(mtthi, t0, 0);
10035 break;
10036 case 2:
10037 gen_helper_0e1i(mttacx, t0, 0);
10038 break;
10039 case 4:
10040 gen_helper_0e1i(mttlo, t0, 1);
10041 break;
10042 case 5:
10043 gen_helper_0e1i(mtthi, t0, 1);
10044 break;
10045 case 6:
10046 gen_helper_0e1i(mttacx, t0, 1);
10047 break;
10048 case 8:
10049 gen_helper_0e1i(mttlo, t0, 2);
10050 break;
10051 case 9:
10052 gen_helper_0e1i(mtthi, t0, 2);
10053 break;
10054 case 10:
10055 gen_helper_0e1i(mttacx, t0, 2);
10056 break;
10057 case 12:
10058 gen_helper_0e1i(mttlo, t0, 3);
10059 break;
10060 case 13:
10061 gen_helper_0e1i(mtthi, t0, 3);
10062 break;
10063 case 14:
10064 gen_helper_0e1i(mttacx, t0, 3);
10065 break;
10066 case 16:
10067 gen_helper_mttdsp(cpu_env, t0);
10068 break;
10069 default:
10070 goto die;
10072 break;
10073 /* Floating point (COP1). */
10074 case 2:
10075 /* XXX: For now we support only a single FPU context. */
10076 if (h == 0) {
10077 TCGv_i32 fp0 = tcg_temp_new_i32();
10079 tcg_gen_trunc_tl_i32(fp0, t0);
10080 gen_store_fpr32(ctx, fp0, rd);
10081 tcg_temp_free_i32(fp0);
10082 } else {
10083 TCGv_i32 fp0 = tcg_temp_new_i32();
10085 tcg_gen_trunc_tl_i32(fp0, t0);
10086 gen_store_fpr32h(ctx, fp0, rd);
10087 tcg_temp_free_i32(fp0);
10089 break;
10090 case 3:
10091 /* XXX: For now we support only a single FPU context. */
10093 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10095 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10096 tcg_temp_free_i32(fs_tmp);
10098 /* Stop translation as we may have changed hflags */
10099 ctx->base.is_jmp = DISAS_STOP;
10100 break;
10101 /* COP2: Not implemented. */
10102 case 4:
10103 case 5:
10104 /* fall through */
10105 default:
10106 goto die;
10108 trace_mips_translate_tr("mttr", rd, u, sel, h);
10109 tcg_temp_free(t0);
10110 return;
10112 die:
10113 tcg_temp_free(t0);
10114 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10115 generate_exception_end(ctx, EXCP_RI);
10118 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
10120 const char *opn = "ldst";
10122 check_cp0_enabled(ctx);
10123 switch (opc) {
10124 case OPC_MFC0:
10125 if (rt == 0) {
10126 /* Treat as NOP. */
10127 return;
10129 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10130 opn = "mfc0";
10131 break;
10132 case OPC_MTC0:
10134 TCGv t0 = tcg_temp_new();
10136 gen_load_gpr(t0, rt);
10137 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10138 tcg_temp_free(t0);
10140 opn = "mtc0";
10141 break;
10142 #if defined(TARGET_MIPS64)
10143 case OPC_DMFC0:
10144 check_insn(ctx, ISA_MIPS3);
10145 if (rt == 0) {
10146 /* Treat as NOP. */
10147 return;
10149 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10150 opn = "dmfc0";
10151 break;
10152 case OPC_DMTC0:
10153 check_insn(ctx, ISA_MIPS3);
10155 TCGv t0 = tcg_temp_new();
10157 gen_load_gpr(t0, rt);
10158 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10159 tcg_temp_free(t0);
10161 opn = "dmtc0";
10162 break;
10163 #endif
10164 case OPC_MFHC0:
10165 check_mvh(ctx);
10166 if (rt == 0) {
10167 /* Treat as NOP. */
10168 return;
10170 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10171 opn = "mfhc0";
10172 break;
10173 case OPC_MTHC0:
10174 check_mvh(ctx);
10176 TCGv t0 = tcg_temp_new();
10177 gen_load_gpr(t0, rt);
10178 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10179 tcg_temp_free(t0);
10181 opn = "mthc0";
10182 break;
10183 case OPC_MFTR:
10184 check_cp0_enabled(ctx);
10185 if (rd == 0) {
10186 /* Treat as NOP. */
10187 return;
10189 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10190 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10191 opn = "mftr";
10192 break;
10193 case OPC_MTTR:
10194 check_cp0_enabled(ctx);
10195 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10196 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10197 opn = "mttr";
10198 break;
10199 case OPC_TLBWI:
10200 opn = "tlbwi";
10201 if (!env->tlb->helper_tlbwi)
10202 goto die;
10203 gen_helper_tlbwi(cpu_env);
10204 break;
10205 case OPC_TLBINV:
10206 opn = "tlbinv";
10207 if (ctx->ie >= 2) {
10208 if (!env->tlb->helper_tlbinv) {
10209 goto die;
10211 gen_helper_tlbinv(cpu_env);
10212 } /* treat as nop if TLBINV not supported */
10213 break;
10214 case OPC_TLBINVF:
10215 opn = "tlbinvf";
10216 if (ctx->ie >= 2) {
10217 if (!env->tlb->helper_tlbinvf) {
10218 goto die;
10220 gen_helper_tlbinvf(cpu_env);
10221 } /* treat as nop if TLBINV not supported */
10222 break;
10223 case OPC_TLBWR:
10224 opn = "tlbwr";
10225 if (!env->tlb->helper_tlbwr)
10226 goto die;
10227 gen_helper_tlbwr(cpu_env);
10228 break;
10229 case OPC_TLBP:
10230 opn = "tlbp";
10231 if (!env->tlb->helper_tlbp)
10232 goto die;
10233 gen_helper_tlbp(cpu_env);
10234 break;
10235 case OPC_TLBR:
10236 opn = "tlbr";
10237 if (!env->tlb->helper_tlbr)
10238 goto die;
10239 gen_helper_tlbr(cpu_env);
10240 break;
10241 case OPC_ERET: /* OPC_ERETNC */
10242 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10243 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10244 goto die;
10245 } else {
10246 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10247 if (ctx->opcode & (1 << bit_shift)) {
10248 /* OPC_ERETNC */
10249 opn = "eretnc";
10250 check_insn(ctx, ISA_MIPS32R5);
10251 gen_helper_eretnc(cpu_env);
10252 } else {
10253 /* OPC_ERET */
10254 opn = "eret";
10255 check_insn(ctx, ISA_MIPS2);
10256 gen_helper_eret(cpu_env);
10258 ctx->base.is_jmp = DISAS_EXIT;
10260 break;
10261 case OPC_DERET:
10262 opn = "deret";
10263 check_insn(ctx, ISA_MIPS32);
10264 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10265 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10266 goto die;
10268 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10269 MIPS_INVAL(opn);
10270 generate_exception_end(ctx, EXCP_RI);
10271 } else {
10272 gen_helper_deret(cpu_env);
10273 ctx->base.is_jmp = DISAS_EXIT;
10275 break;
10276 case OPC_WAIT:
10277 opn = "wait";
10278 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10279 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10280 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10281 goto die;
10283 /* If we get an exception, we want to restart at next instruction */
10284 ctx->base.pc_next += 4;
10285 save_cpu_state(ctx, 1);
10286 ctx->base.pc_next -= 4;
10287 gen_helper_wait(cpu_env);
10288 ctx->base.is_jmp = DISAS_NORETURN;
10289 break;
10290 default:
10291 die:
10292 MIPS_INVAL(opn);
10293 generate_exception_end(ctx, EXCP_RI);
10294 return;
10296 (void)opn; /* avoid a compiler warning */
10298 #endif /* !CONFIG_USER_ONLY */
10300 /* CP1 Branches (before delay slot) */
10301 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10302 int32_t cc, int32_t offset)
10304 target_ulong btarget;
10305 TCGv_i32 t0 = tcg_temp_new_i32();
10307 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10308 generate_exception_end(ctx, EXCP_RI);
10309 goto out;
10312 if (cc != 0)
10313 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10315 btarget = ctx->base.pc_next + 4 + offset;
10317 switch (op) {
10318 case OPC_BC1F:
10319 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10320 tcg_gen_not_i32(t0, t0);
10321 tcg_gen_andi_i32(t0, t0, 1);
10322 tcg_gen_extu_i32_tl(bcond, t0);
10323 goto not_likely;
10324 case OPC_BC1FL:
10325 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10326 tcg_gen_not_i32(t0, t0);
10327 tcg_gen_andi_i32(t0, t0, 1);
10328 tcg_gen_extu_i32_tl(bcond, t0);
10329 goto likely;
10330 case OPC_BC1T:
10331 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10332 tcg_gen_andi_i32(t0, t0, 1);
10333 tcg_gen_extu_i32_tl(bcond, t0);
10334 goto not_likely;
10335 case OPC_BC1TL:
10336 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10337 tcg_gen_andi_i32(t0, t0, 1);
10338 tcg_gen_extu_i32_tl(bcond, t0);
10339 likely:
10340 ctx->hflags |= MIPS_HFLAG_BL;
10341 break;
10342 case OPC_BC1FANY2:
10344 TCGv_i32 t1 = tcg_temp_new_i32();
10345 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10346 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10347 tcg_gen_nand_i32(t0, t0, t1);
10348 tcg_temp_free_i32(t1);
10349 tcg_gen_andi_i32(t0, t0, 1);
10350 tcg_gen_extu_i32_tl(bcond, t0);
10352 goto not_likely;
10353 case OPC_BC1TANY2:
10355 TCGv_i32 t1 = tcg_temp_new_i32();
10356 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10357 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10358 tcg_gen_or_i32(t0, t0, t1);
10359 tcg_temp_free_i32(t1);
10360 tcg_gen_andi_i32(t0, t0, 1);
10361 tcg_gen_extu_i32_tl(bcond, t0);
10363 goto not_likely;
10364 case OPC_BC1FANY4:
10366 TCGv_i32 t1 = tcg_temp_new_i32();
10367 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10368 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10369 tcg_gen_and_i32(t0, t0, t1);
10370 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10371 tcg_gen_and_i32(t0, t0, t1);
10372 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10373 tcg_gen_nand_i32(t0, t0, t1);
10374 tcg_temp_free_i32(t1);
10375 tcg_gen_andi_i32(t0, t0, 1);
10376 tcg_gen_extu_i32_tl(bcond, t0);
10378 goto not_likely;
10379 case OPC_BC1TANY4:
10381 TCGv_i32 t1 = tcg_temp_new_i32();
10382 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10383 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10384 tcg_gen_or_i32(t0, t0, t1);
10385 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10386 tcg_gen_or_i32(t0, t0, t1);
10387 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10388 tcg_gen_or_i32(t0, t0, t1);
10389 tcg_temp_free_i32(t1);
10390 tcg_gen_andi_i32(t0, t0, 1);
10391 tcg_gen_extu_i32_tl(bcond, t0);
10393 not_likely:
10394 ctx->hflags |= MIPS_HFLAG_BC;
10395 break;
10396 default:
10397 MIPS_INVAL("cp1 cond branch");
10398 generate_exception_end(ctx, EXCP_RI);
10399 goto out;
10401 ctx->btarget = btarget;
10402 ctx->hflags |= MIPS_HFLAG_BDS32;
10403 out:
10404 tcg_temp_free_i32(t0);
10407 /* R6 CP1 Branches */
10408 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10409 int32_t ft, int32_t offset,
10410 int delayslot_size)
10412 target_ulong btarget;
10413 TCGv_i64 t0 = tcg_temp_new_i64();
10415 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10416 #ifdef MIPS_DEBUG_DISAS
10417 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10418 "\n", ctx->base.pc_next);
10419 #endif
10420 generate_exception_end(ctx, EXCP_RI);
10421 goto out;
10424 gen_load_fpr64(ctx, t0, ft);
10425 tcg_gen_andi_i64(t0, t0, 1);
10427 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10429 switch (op) {
10430 case OPC_BC1EQZ:
10431 tcg_gen_xori_i64(t0, t0, 1);
10432 ctx->hflags |= MIPS_HFLAG_BC;
10433 break;
10434 case OPC_BC1NEZ:
10435 /* t0 already set */
10436 ctx->hflags |= MIPS_HFLAG_BC;
10437 break;
10438 default:
10439 MIPS_INVAL("cp1 cond branch");
10440 generate_exception_end(ctx, EXCP_RI);
10441 goto out;
10444 tcg_gen_trunc_i64_tl(bcond, t0);
10446 ctx->btarget = btarget;
10448 switch (delayslot_size) {
10449 case 2:
10450 ctx->hflags |= MIPS_HFLAG_BDS16;
10451 break;
10452 case 4:
10453 ctx->hflags |= MIPS_HFLAG_BDS32;
10454 break;
10457 out:
10458 tcg_temp_free_i64(t0);
10461 /* Coprocessor 1 (FPU) */
10463 #define FOP(func, fmt) (((fmt) << 21) | (func))
10465 enum fopcode {
10466 OPC_ADD_S = FOP(0, FMT_S),
10467 OPC_SUB_S = FOP(1, FMT_S),
10468 OPC_MUL_S = FOP(2, FMT_S),
10469 OPC_DIV_S = FOP(3, FMT_S),
10470 OPC_SQRT_S = FOP(4, FMT_S),
10471 OPC_ABS_S = FOP(5, FMT_S),
10472 OPC_MOV_S = FOP(6, FMT_S),
10473 OPC_NEG_S = FOP(7, FMT_S),
10474 OPC_ROUND_L_S = FOP(8, FMT_S),
10475 OPC_TRUNC_L_S = FOP(9, FMT_S),
10476 OPC_CEIL_L_S = FOP(10, FMT_S),
10477 OPC_FLOOR_L_S = FOP(11, FMT_S),
10478 OPC_ROUND_W_S = FOP(12, FMT_S),
10479 OPC_TRUNC_W_S = FOP(13, FMT_S),
10480 OPC_CEIL_W_S = FOP(14, FMT_S),
10481 OPC_FLOOR_W_S = FOP(15, FMT_S),
10482 OPC_SEL_S = FOP(16, FMT_S),
10483 OPC_MOVCF_S = FOP(17, FMT_S),
10484 OPC_MOVZ_S = FOP(18, FMT_S),
10485 OPC_MOVN_S = FOP(19, FMT_S),
10486 OPC_SELEQZ_S = FOP(20, FMT_S),
10487 OPC_RECIP_S = FOP(21, FMT_S),
10488 OPC_RSQRT_S = FOP(22, FMT_S),
10489 OPC_SELNEZ_S = FOP(23, FMT_S),
10490 OPC_MADDF_S = FOP(24, FMT_S),
10491 OPC_MSUBF_S = FOP(25, FMT_S),
10492 OPC_RINT_S = FOP(26, FMT_S),
10493 OPC_CLASS_S = FOP(27, FMT_S),
10494 OPC_MIN_S = FOP(28, FMT_S),
10495 OPC_RECIP2_S = FOP(28, FMT_S),
10496 OPC_MINA_S = FOP(29, FMT_S),
10497 OPC_RECIP1_S = FOP(29, FMT_S),
10498 OPC_MAX_S = FOP(30, FMT_S),
10499 OPC_RSQRT1_S = FOP(30, FMT_S),
10500 OPC_MAXA_S = FOP(31, FMT_S),
10501 OPC_RSQRT2_S = FOP(31, FMT_S),
10502 OPC_CVT_D_S = FOP(33, FMT_S),
10503 OPC_CVT_W_S = FOP(36, FMT_S),
10504 OPC_CVT_L_S = FOP(37, FMT_S),
10505 OPC_CVT_PS_S = FOP(38, FMT_S),
10506 OPC_CMP_F_S = FOP (48, FMT_S),
10507 OPC_CMP_UN_S = FOP (49, FMT_S),
10508 OPC_CMP_EQ_S = FOP (50, FMT_S),
10509 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10510 OPC_CMP_OLT_S = FOP (52, FMT_S),
10511 OPC_CMP_ULT_S = FOP (53, FMT_S),
10512 OPC_CMP_OLE_S = FOP (54, FMT_S),
10513 OPC_CMP_ULE_S = FOP (55, FMT_S),
10514 OPC_CMP_SF_S = FOP (56, FMT_S),
10515 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10516 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10517 OPC_CMP_NGL_S = FOP (59, FMT_S),
10518 OPC_CMP_LT_S = FOP (60, FMT_S),
10519 OPC_CMP_NGE_S = FOP (61, FMT_S),
10520 OPC_CMP_LE_S = FOP (62, FMT_S),
10521 OPC_CMP_NGT_S = FOP (63, FMT_S),
10523 OPC_ADD_D = FOP(0, FMT_D),
10524 OPC_SUB_D = FOP(1, FMT_D),
10525 OPC_MUL_D = FOP(2, FMT_D),
10526 OPC_DIV_D = FOP(3, FMT_D),
10527 OPC_SQRT_D = FOP(4, FMT_D),
10528 OPC_ABS_D = FOP(5, FMT_D),
10529 OPC_MOV_D = FOP(6, FMT_D),
10530 OPC_NEG_D = FOP(7, FMT_D),
10531 OPC_ROUND_L_D = FOP(8, FMT_D),
10532 OPC_TRUNC_L_D = FOP(9, FMT_D),
10533 OPC_CEIL_L_D = FOP(10, FMT_D),
10534 OPC_FLOOR_L_D = FOP(11, FMT_D),
10535 OPC_ROUND_W_D = FOP(12, FMT_D),
10536 OPC_TRUNC_W_D = FOP(13, FMT_D),
10537 OPC_CEIL_W_D = FOP(14, FMT_D),
10538 OPC_FLOOR_W_D = FOP(15, FMT_D),
10539 OPC_SEL_D = FOP(16, FMT_D),
10540 OPC_MOVCF_D = FOP(17, FMT_D),
10541 OPC_MOVZ_D = FOP(18, FMT_D),
10542 OPC_MOVN_D = FOP(19, FMT_D),
10543 OPC_SELEQZ_D = FOP(20, FMT_D),
10544 OPC_RECIP_D = FOP(21, FMT_D),
10545 OPC_RSQRT_D = FOP(22, FMT_D),
10546 OPC_SELNEZ_D = FOP(23, FMT_D),
10547 OPC_MADDF_D = FOP(24, FMT_D),
10548 OPC_MSUBF_D = FOP(25, FMT_D),
10549 OPC_RINT_D = FOP(26, FMT_D),
10550 OPC_CLASS_D = FOP(27, FMT_D),
10551 OPC_MIN_D = FOP(28, FMT_D),
10552 OPC_RECIP2_D = FOP(28, FMT_D),
10553 OPC_MINA_D = FOP(29, FMT_D),
10554 OPC_RECIP1_D = FOP(29, FMT_D),
10555 OPC_MAX_D = FOP(30, FMT_D),
10556 OPC_RSQRT1_D = FOP(30, FMT_D),
10557 OPC_MAXA_D = FOP(31, FMT_D),
10558 OPC_RSQRT2_D = FOP(31, FMT_D),
10559 OPC_CVT_S_D = FOP(32, FMT_D),
10560 OPC_CVT_W_D = FOP(36, FMT_D),
10561 OPC_CVT_L_D = FOP(37, FMT_D),
10562 OPC_CMP_F_D = FOP (48, FMT_D),
10563 OPC_CMP_UN_D = FOP (49, FMT_D),
10564 OPC_CMP_EQ_D = FOP (50, FMT_D),
10565 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10566 OPC_CMP_OLT_D = FOP (52, FMT_D),
10567 OPC_CMP_ULT_D = FOP (53, FMT_D),
10568 OPC_CMP_OLE_D = FOP (54, FMT_D),
10569 OPC_CMP_ULE_D = FOP (55, FMT_D),
10570 OPC_CMP_SF_D = FOP (56, FMT_D),
10571 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10572 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10573 OPC_CMP_NGL_D = FOP (59, FMT_D),
10574 OPC_CMP_LT_D = FOP (60, FMT_D),
10575 OPC_CMP_NGE_D = FOP (61, FMT_D),
10576 OPC_CMP_LE_D = FOP (62, FMT_D),
10577 OPC_CMP_NGT_D = FOP (63, FMT_D),
10579 OPC_CVT_S_W = FOP(32, FMT_W),
10580 OPC_CVT_D_W = FOP(33, FMT_W),
10581 OPC_CVT_S_L = FOP(32, FMT_L),
10582 OPC_CVT_D_L = FOP(33, FMT_L),
10583 OPC_CVT_PS_PW = FOP(38, FMT_W),
10585 OPC_ADD_PS = FOP(0, FMT_PS),
10586 OPC_SUB_PS = FOP(1, FMT_PS),
10587 OPC_MUL_PS = FOP(2, FMT_PS),
10588 OPC_DIV_PS = FOP(3, FMT_PS),
10589 OPC_ABS_PS = FOP(5, FMT_PS),
10590 OPC_MOV_PS = FOP(6, FMT_PS),
10591 OPC_NEG_PS = FOP(7, FMT_PS),
10592 OPC_MOVCF_PS = FOP(17, FMT_PS),
10593 OPC_MOVZ_PS = FOP(18, FMT_PS),
10594 OPC_MOVN_PS = FOP(19, FMT_PS),
10595 OPC_ADDR_PS = FOP(24, FMT_PS),
10596 OPC_MULR_PS = FOP(26, FMT_PS),
10597 OPC_RECIP2_PS = FOP(28, FMT_PS),
10598 OPC_RECIP1_PS = FOP(29, FMT_PS),
10599 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10600 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10602 OPC_CVT_S_PU = FOP(32, FMT_PS),
10603 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10604 OPC_CVT_S_PL = FOP(40, FMT_PS),
10605 OPC_PLL_PS = FOP(44, FMT_PS),
10606 OPC_PLU_PS = FOP(45, FMT_PS),
10607 OPC_PUL_PS = FOP(46, FMT_PS),
10608 OPC_PUU_PS = FOP(47, FMT_PS),
10609 OPC_CMP_F_PS = FOP (48, FMT_PS),
10610 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10611 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10612 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10613 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10614 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10615 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10616 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10617 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10618 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10619 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10620 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10621 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10622 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10623 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10624 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10627 enum r6_f_cmp_op {
10628 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10629 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10630 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10631 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10632 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10633 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10634 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10635 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10636 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10637 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10638 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10639 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10640 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10641 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10642 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10643 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10644 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10645 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10646 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10647 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10648 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10649 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10651 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10652 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10653 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10654 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10655 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10656 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10657 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10658 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10659 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10660 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10661 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10662 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10663 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10664 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10665 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10666 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10667 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10668 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10669 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10670 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10671 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10672 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10674 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10676 TCGv t0 = tcg_temp_new();
10678 switch (opc) {
10679 case OPC_MFC1:
10681 TCGv_i32 fp0 = tcg_temp_new_i32();
10683 gen_load_fpr32(ctx, fp0, fs);
10684 tcg_gen_ext_i32_tl(t0, fp0);
10685 tcg_temp_free_i32(fp0);
10687 gen_store_gpr(t0, rt);
10688 break;
10689 case OPC_MTC1:
10690 gen_load_gpr(t0, rt);
10692 TCGv_i32 fp0 = tcg_temp_new_i32();
10694 tcg_gen_trunc_tl_i32(fp0, t0);
10695 gen_store_fpr32(ctx, fp0, fs);
10696 tcg_temp_free_i32(fp0);
10698 break;
10699 case OPC_CFC1:
10700 gen_helper_1e0i(cfc1, t0, fs);
10701 gen_store_gpr(t0, rt);
10702 break;
10703 case OPC_CTC1:
10704 gen_load_gpr(t0, rt);
10705 save_cpu_state(ctx, 0);
10707 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10709 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10710 tcg_temp_free_i32(fs_tmp);
10712 /* Stop translation as we may have changed hflags */
10713 ctx->base.is_jmp = DISAS_STOP;
10714 break;
10715 #if defined(TARGET_MIPS64)
10716 case OPC_DMFC1:
10717 gen_load_fpr64(ctx, t0, fs);
10718 gen_store_gpr(t0, rt);
10719 break;
10720 case OPC_DMTC1:
10721 gen_load_gpr(t0, rt);
10722 gen_store_fpr64(ctx, t0, fs);
10723 break;
10724 #endif
10725 case OPC_MFHC1:
10727 TCGv_i32 fp0 = tcg_temp_new_i32();
10729 gen_load_fpr32h(ctx, fp0, fs);
10730 tcg_gen_ext_i32_tl(t0, fp0);
10731 tcg_temp_free_i32(fp0);
10733 gen_store_gpr(t0, rt);
10734 break;
10735 case OPC_MTHC1:
10736 gen_load_gpr(t0, rt);
10738 TCGv_i32 fp0 = tcg_temp_new_i32();
10740 tcg_gen_trunc_tl_i32(fp0, t0);
10741 gen_store_fpr32h(ctx, fp0, fs);
10742 tcg_temp_free_i32(fp0);
10744 break;
10745 default:
10746 MIPS_INVAL("cp1 move");
10747 generate_exception_end(ctx, EXCP_RI);
10748 goto out;
10751 out:
10752 tcg_temp_free(t0);
10755 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10757 TCGLabel *l1;
10758 TCGCond cond;
10759 TCGv_i32 t0;
10761 if (rd == 0) {
10762 /* Treat as NOP. */
10763 return;
10766 if (tf)
10767 cond = TCG_COND_EQ;
10768 else
10769 cond = TCG_COND_NE;
10771 l1 = gen_new_label();
10772 t0 = tcg_temp_new_i32();
10773 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10774 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10775 tcg_temp_free_i32(t0);
10776 if (rs == 0) {
10777 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10778 } else {
10779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10781 gen_set_label(l1);
10784 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10785 int tf)
10787 int cond;
10788 TCGv_i32 t0 = tcg_temp_new_i32();
10789 TCGLabel *l1 = gen_new_label();
10791 if (tf)
10792 cond = TCG_COND_EQ;
10793 else
10794 cond = TCG_COND_NE;
10796 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10797 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10798 gen_load_fpr32(ctx, t0, fs);
10799 gen_store_fpr32(ctx, t0, fd);
10800 gen_set_label(l1);
10801 tcg_temp_free_i32(t0);
10804 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10806 int cond;
10807 TCGv_i32 t0 = tcg_temp_new_i32();
10808 TCGv_i64 fp0;
10809 TCGLabel *l1 = gen_new_label();
10811 if (tf)
10812 cond = TCG_COND_EQ;
10813 else
10814 cond = TCG_COND_NE;
10816 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10817 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10818 tcg_temp_free_i32(t0);
10819 fp0 = tcg_temp_new_i64();
10820 gen_load_fpr64(ctx, fp0, fs);
10821 gen_store_fpr64(ctx, fp0, fd);
10822 tcg_temp_free_i64(fp0);
10823 gen_set_label(l1);
10826 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10827 int cc, int tf)
10829 int cond;
10830 TCGv_i32 t0 = tcg_temp_new_i32();
10831 TCGLabel *l1 = gen_new_label();
10832 TCGLabel *l2 = gen_new_label();
10834 if (tf)
10835 cond = TCG_COND_EQ;
10836 else
10837 cond = TCG_COND_NE;
10839 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10840 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10841 gen_load_fpr32(ctx, t0, fs);
10842 gen_store_fpr32(ctx, t0, fd);
10843 gen_set_label(l1);
10845 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10846 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10847 gen_load_fpr32h(ctx, t0, fs);
10848 gen_store_fpr32h(ctx, t0, fd);
10849 tcg_temp_free_i32(t0);
10850 gen_set_label(l2);
10853 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10854 int fs)
10856 TCGv_i32 t1 = tcg_const_i32(0);
10857 TCGv_i32 fp0 = tcg_temp_new_i32();
10858 TCGv_i32 fp1 = tcg_temp_new_i32();
10859 TCGv_i32 fp2 = tcg_temp_new_i32();
10860 gen_load_fpr32(ctx, fp0, fd);
10861 gen_load_fpr32(ctx, fp1, ft);
10862 gen_load_fpr32(ctx, fp2, fs);
10864 switch (op1) {
10865 case OPC_SEL_S:
10866 tcg_gen_andi_i32(fp0, fp0, 1);
10867 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10868 break;
10869 case OPC_SELEQZ_S:
10870 tcg_gen_andi_i32(fp1, fp1, 1);
10871 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10872 break;
10873 case OPC_SELNEZ_S:
10874 tcg_gen_andi_i32(fp1, fp1, 1);
10875 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10876 break;
10877 default:
10878 MIPS_INVAL("gen_sel_s");
10879 generate_exception_end(ctx, EXCP_RI);
10880 break;
10883 gen_store_fpr32(ctx, fp0, fd);
10884 tcg_temp_free_i32(fp2);
10885 tcg_temp_free_i32(fp1);
10886 tcg_temp_free_i32(fp0);
10887 tcg_temp_free_i32(t1);
10890 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10891 int fs)
10893 TCGv_i64 t1 = tcg_const_i64(0);
10894 TCGv_i64 fp0 = tcg_temp_new_i64();
10895 TCGv_i64 fp1 = tcg_temp_new_i64();
10896 TCGv_i64 fp2 = tcg_temp_new_i64();
10897 gen_load_fpr64(ctx, fp0, fd);
10898 gen_load_fpr64(ctx, fp1, ft);
10899 gen_load_fpr64(ctx, fp2, fs);
10901 switch (op1) {
10902 case OPC_SEL_D:
10903 tcg_gen_andi_i64(fp0, fp0, 1);
10904 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10905 break;
10906 case OPC_SELEQZ_D:
10907 tcg_gen_andi_i64(fp1, fp1, 1);
10908 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10909 break;
10910 case OPC_SELNEZ_D:
10911 tcg_gen_andi_i64(fp1, fp1, 1);
10912 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10913 break;
10914 default:
10915 MIPS_INVAL("gen_sel_d");
10916 generate_exception_end(ctx, EXCP_RI);
10917 break;
10920 gen_store_fpr64(ctx, fp0, fd);
10921 tcg_temp_free_i64(fp2);
10922 tcg_temp_free_i64(fp1);
10923 tcg_temp_free_i64(fp0);
10924 tcg_temp_free_i64(t1);
10927 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10928 int ft, int fs, int fd, int cc)
10930 uint32_t func = ctx->opcode & 0x3f;
10931 switch (op1) {
10932 case OPC_ADD_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_add_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_SUB_S:
10947 TCGv_i32 fp0 = tcg_temp_new_i32();
10948 TCGv_i32 fp1 = tcg_temp_new_i32();
10950 gen_load_fpr32(ctx, fp0, fs);
10951 gen_load_fpr32(ctx, fp1, ft);
10952 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10953 tcg_temp_free_i32(fp1);
10954 gen_store_fpr32(ctx, fp0, fd);
10955 tcg_temp_free_i32(fp0);
10957 break;
10958 case OPC_MUL_S:
10960 TCGv_i32 fp0 = tcg_temp_new_i32();
10961 TCGv_i32 fp1 = tcg_temp_new_i32();
10963 gen_load_fpr32(ctx, fp0, fs);
10964 gen_load_fpr32(ctx, fp1, ft);
10965 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10966 tcg_temp_free_i32(fp1);
10967 gen_store_fpr32(ctx, fp0, fd);
10968 tcg_temp_free_i32(fp0);
10970 break;
10971 case OPC_DIV_S:
10973 TCGv_i32 fp0 = tcg_temp_new_i32();
10974 TCGv_i32 fp1 = tcg_temp_new_i32();
10976 gen_load_fpr32(ctx, fp0, fs);
10977 gen_load_fpr32(ctx, fp1, ft);
10978 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10979 tcg_temp_free_i32(fp1);
10980 gen_store_fpr32(ctx, fp0, fd);
10981 tcg_temp_free_i32(fp0);
10983 break;
10984 case OPC_SQRT_S:
10986 TCGv_i32 fp0 = tcg_temp_new_i32();
10988 gen_load_fpr32(ctx, fp0, fs);
10989 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10990 gen_store_fpr32(ctx, fp0, fd);
10991 tcg_temp_free_i32(fp0);
10993 break;
10994 case OPC_ABS_S:
10996 TCGv_i32 fp0 = tcg_temp_new_i32();
10998 gen_load_fpr32(ctx, fp0, fs);
10999 if (ctx->abs2008) {
11000 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11001 } else {
11002 gen_helper_float_abs_s(fp0, fp0);
11004 gen_store_fpr32(ctx, fp0, fd);
11005 tcg_temp_free_i32(fp0);
11007 break;
11008 case OPC_MOV_S:
11010 TCGv_i32 fp0 = tcg_temp_new_i32();
11012 gen_load_fpr32(ctx, fp0, fs);
11013 gen_store_fpr32(ctx, fp0, fd);
11014 tcg_temp_free_i32(fp0);
11016 break;
11017 case OPC_NEG_S:
11019 TCGv_i32 fp0 = tcg_temp_new_i32();
11021 gen_load_fpr32(ctx, fp0, fs);
11022 if (ctx->abs2008) {
11023 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11024 } else {
11025 gen_helper_float_chs_s(fp0, fp0);
11027 gen_store_fpr32(ctx, fp0, fd);
11028 tcg_temp_free_i32(fp0);
11030 break;
11031 case OPC_ROUND_L_S:
11032 check_cp1_64bitmode(ctx);
11034 TCGv_i32 fp32 = tcg_temp_new_i32();
11035 TCGv_i64 fp64 = tcg_temp_new_i64();
11037 gen_load_fpr32(ctx, fp32, fs);
11038 if (ctx->nan2008) {
11039 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11040 } else {
11041 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11043 tcg_temp_free_i32(fp32);
11044 gen_store_fpr64(ctx, fp64, fd);
11045 tcg_temp_free_i64(fp64);
11047 break;
11048 case OPC_TRUNC_L_S:
11049 check_cp1_64bitmode(ctx);
11051 TCGv_i32 fp32 = tcg_temp_new_i32();
11052 TCGv_i64 fp64 = tcg_temp_new_i64();
11054 gen_load_fpr32(ctx, fp32, fs);
11055 if (ctx->nan2008) {
11056 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11057 } else {
11058 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11060 tcg_temp_free_i32(fp32);
11061 gen_store_fpr64(ctx, fp64, fd);
11062 tcg_temp_free_i64(fp64);
11064 break;
11065 case OPC_CEIL_L_S:
11066 check_cp1_64bitmode(ctx);
11068 TCGv_i32 fp32 = tcg_temp_new_i32();
11069 TCGv_i64 fp64 = tcg_temp_new_i64();
11071 gen_load_fpr32(ctx, fp32, fs);
11072 if (ctx->nan2008) {
11073 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11074 } else {
11075 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11077 tcg_temp_free_i32(fp32);
11078 gen_store_fpr64(ctx, fp64, fd);
11079 tcg_temp_free_i64(fp64);
11081 break;
11082 case OPC_FLOOR_L_S:
11083 check_cp1_64bitmode(ctx);
11085 TCGv_i32 fp32 = tcg_temp_new_i32();
11086 TCGv_i64 fp64 = tcg_temp_new_i64();
11088 gen_load_fpr32(ctx, fp32, fs);
11089 if (ctx->nan2008) {
11090 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11091 } else {
11092 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11094 tcg_temp_free_i32(fp32);
11095 gen_store_fpr64(ctx, fp64, fd);
11096 tcg_temp_free_i64(fp64);
11098 break;
11099 case OPC_ROUND_W_S:
11101 TCGv_i32 fp0 = tcg_temp_new_i32();
11103 gen_load_fpr32(ctx, fp0, fs);
11104 if (ctx->nan2008) {
11105 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11106 } else {
11107 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11109 gen_store_fpr32(ctx, fp0, fd);
11110 tcg_temp_free_i32(fp0);
11112 break;
11113 case OPC_TRUNC_W_S:
11115 TCGv_i32 fp0 = tcg_temp_new_i32();
11117 gen_load_fpr32(ctx, fp0, fs);
11118 if (ctx->nan2008) {
11119 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11120 } else {
11121 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11123 gen_store_fpr32(ctx, fp0, fd);
11124 tcg_temp_free_i32(fp0);
11126 break;
11127 case OPC_CEIL_W_S:
11129 TCGv_i32 fp0 = tcg_temp_new_i32();
11131 gen_load_fpr32(ctx, fp0, fs);
11132 if (ctx->nan2008) {
11133 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11134 } else {
11135 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11137 gen_store_fpr32(ctx, fp0, fd);
11138 tcg_temp_free_i32(fp0);
11140 break;
11141 case OPC_FLOOR_W_S:
11143 TCGv_i32 fp0 = tcg_temp_new_i32();
11145 gen_load_fpr32(ctx, fp0, fs);
11146 if (ctx->nan2008) {
11147 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11148 } else {
11149 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11151 gen_store_fpr32(ctx, fp0, fd);
11152 tcg_temp_free_i32(fp0);
11154 break;
11155 case OPC_SEL_S:
11156 check_insn(ctx, ISA_MIPS32R6);
11157 gen_sel_s(ctx, op1, fd, ft, fs);
11158 break;
11159 case OPC_SELEQZ_S:
11160 check_insn(ctx, ISA_MIPS32R6);
11161 gen_sel_s(ctx, op1, fd, ft, fs);
11162 break;
11163 case OPC_SELNEZ_S:
11164 check_insn(ctx, ISA_MIPS32R6);
11165 gen_sel_s(ctx, op1, fd, ft, fs);
11166 break;
11167 case OPC_MOVCF_S:
11168 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11169 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11170 break;
11171 case OPC_MOVZ_S:
11172 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11174 TCGLabel *l1 = gen_new_label();
11175 TCGv_i32 fp0;
11177 if (ft != 0) {
11178 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11180 fp0 = tcg_temp_new_i32();
11181 gen_load_fpr32(ctx, fp0, fs);
11182 gen_store_fpr32(ctx, fp0, fd);
11183 tcg_temp_free_i32(fp0);
11184 gen_set_label(l1);
11186 break;
11187 case OPC_MOVN_S:
11188 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11190 TCGLabel *l1 = gen_new_label();
11191 TCGv_i32 fp0;
11193 if (ft != 0) {
11194 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11195 fp0 = tcg_temp_new_i32();
11196 gen_load_fpr32(ctx, fp0, fs);
11197 gen_store_fpr32(ctx, fp0, fd);
11198 tcg_temp_free_i32(fp0);
11199 gen_set_label(l1);
11202 break;
11203 case OPC_RECIP_S:
11205 TCGv_i32 fp0 = tcg_temp_new_i32();
11207 gen_load_fpr32(ctx, fp0, fs);
11208 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11209 gen_store_fpr32(ctx, fp0, fd);
11210 tcg_temp_free_i32(fp0);
11212 break;
11213 case OPC_RSQRT_S:
11215 TCGv_i32 fp0 = tcg_temp_new_i32();
11217 gen_load_fpr32(ctx, fp0, fs);
11218 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11219 gen_store_fpr32(ctx, fp0, fd);
11220 tcg_temp_free_i32(fp0);
11222 break;
11223 case OPC_MADDF_S:
11224 check_insn(ctx, ISA_MIPS32R6);
11226 TCGv_i32 fp0 = tcg_temp_new_i32();
11227 TCGv_i32 fp1 = tcg_temp_new_i32();
11228 TCGv_i32 fp2 = tcg_temp_new_i32();
11229 gen_load_fpr32(ctx, fp0, fs);
11230 gen_load_fpr32(ctx, fp1, ft);
11231 gen_load_fpr32(ctx, fp2, fd);
11232 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11233 gen_store_fpr32(ctx, fp2, fd);
11234 tcg_temp_free_i32(fp2);
11235 tcg_temp_free_i32(fp1);
11236 tcg_temp_free_i32(fp0);
11238 break;
11239 case OPC_MSUBF_S:
11240 check_insn(ctx, ISA_MIPS32R6);
11242 TCGv_i32 fp0 = tcg_temp_new_i32();
11243 TCGv_i32 fp1 = tcg_temp_new_i32();
11244 TCGv_i32 fp2 = tcg_temp_new_i32();
11245 gen_load_fpr32(ctx, fp0, fs);
11246 gen_load_fpr32(ctx, fp1, ft);
11247 gen_load_fpr32(ctx, fp2, fd);
11248 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11249 gen_store_fpr32(ctx, fp2, fd);
11250 tcg_temp_free_i32(fp2);
11251 tcg_temp_free_i32(fp1);
11252 tcg_temp_free_i32(fp0);
11254 break;
11255 case OPC_RINT_S:
11256 check_insn(ctx, ISA_MIPS32R6);
11258 TCGv_i32 fp0 = tcg_temp_new_i32();
11259 gen_load_fpr32(ctx, fp0, fs);
11260 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11261 gen_store_fpr32(ctx, fp0, fd);
11262 tcg_temp_free_i32(fp0);
11264 break;
11265 case OPC_CLASS_S:
11266 check_insn(ctx, ISA_MIPS32R6);
11268 TCGv_i32 fp0 = tcg_temp_new_i32();
11269 gen_load_fpr32(ctx, fp0, fs);
11270 gen_helper_float_class_s(fp0, cpu_env, fp0);
11271 gen_store_fpr32(ctx, fp0, fd);
11272 tcg_temp_free_i32(fp0);
11274 break;
11275 case OPC_MIN_S: /* OPC_RECIP2_S */
11276 if (ctx->insn_flags & ISA_MIPS32R6) {
11277 /* OPC_MIN_S */
11278 TCGv_i32 fp0 = tcg_temp_new_i32();
11279 TCGv_i32 fp1 = tcg_temp_new_i32();
11280 TCGv_i32 fp2 = tcg_temp_new_i32();
11281 gen_load_fpr32(ctx, fp0, fs);
11282 gen_load_fpr32(ctx, fp1, ft);
11283 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11284 gen_store_fpr32(ctx, fp2, fd);
11285 tcg_temp_free_i32(fp2);
11286 tcg_temp_free_i32(fp1);
11287 tcg_temp_free_i32(fp0);
11288 } else {
11289 /* OPC_RECIP2_S */
11290 check_cp1_64bitmode(ctx);
11292 TCGv_i32 fp0 = tcg_temp_new_i32();
11293 TCGv_i32 fp1 = tcg_temp_new_i32();
11295 gen_load_fpr32(ctx, fp0, fs);
11296 gen_load_fpr32(ctx, fp1, ft);
11297 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11298 tcg_temp_free_i32(fp1);
11299 gen_store_fpr32(ctx, fp0, fd);
11300 tcg_temp_free_i32(fp0);
11303 break;
11304 case OPC_MINA_S: /* OPC_RECIP1_S */
11305 if (ctx->insn_flags & ISA_MIPS32R6) {
11306 /* OPC_MINA_S */
11307 TCGv_i32 fp0 = tcg_temp_new_i32();
11308 TCGv_i32 fp1 = tcg_temp_new_i32();
11309 TCGv_i32 fp2 = tcg_temp_new_i32();
11310 gen_load_fpr32(ctx, fp0, fs);
11311 gen_load_fpr32(ctx, fp1, ft);
11312 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11313 gen_store_fpr32(ctx, fp2, fd);
11314 tcg_temp_free_i32(fp2);
11315 tcg_temp_free_i32(fp1);
11316 tcg_temp_free_i32(fp0);
11317 } else {
11318 /* OPC_RECIP1_S */
11319 check_cp1_64bitmode(ctx);
11321 TCGv_i32 fp0 = tcg_temp_new_i32();
11323 gen_load_fpr32(ctx, fp0, fs);
11324 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11325 gen_store_fpr32(ctx, fp0, fd);
11326 tcg_temp_free_i32(fp0);
11329 break;
11330 case OPC_MAX_S: /* OPC_RSQRT1_S */
11331 if (ctx->insn_flags & ISA_MIPS32R6) {
11332 /* OPC_MAX_S */
11333 TCGv_i32 fp0 = tcg_temp_new_i32();
11334 TCGv_i32 fp1 = tcg_temp_new_i32();
11335 gen_load_fpr32(ctx, fp0, fs);
11336 gen_load_fpr32(ctx, fp1, ft);
11337 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11338 gen_store_fpr32(ctx, fp1, fd);
11339 tcg_temp_free_i32(fp1);
11340 tcg_temp_free_i32(fp0);
11341 } else {
11342 /* OPC_RSQRT1_S */
11343 check_cp1_64bitmode(ctx);
11345 TCGv_i32 fp0 = tcg_temp_new_i32();
11347 gen_load_fpr32(ctx, fp0, fs);
11348 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11349 gen_store_fpr32(ctx, fp0, fd);
11350 tcg_temp_free_i32(fp0);
11353 break;
11354 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11355 if (ctx->insn_flags & ISA_MIPS32R6) {
11356 /* OPC_MAXA_S */
11357 TCGv_i32 fp0 = tcg_temp_new_i32();
11358 TCGv_i32 fp1 = tcg_temp_new_i32();
11359 gen_load_fpr32(ctx, fp0, fs);
11360 gen_load_fpr32(ctx, fp1, ft);
11361 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11362 gen_store_fpr32(ctx, fp1, fd);
11363 tcg_temp_free_i32(fp1);
11364 tcg_temp_free_i32(fp0);
11365 } else {
11366 /* OPC_RSQRT2_S */
11367 check_cp1_64bitmode(ctx);
11369 TCGv_i32 fp0 = tcg_temp_new_i32();
11370 TCGv_i32 fp1 = tcg_temp_new_i32();
11372 gen_load_fpr32(ctx, fp0, fs);
11373 gen_load_fpr32(ctx, fp1, ft);
11374 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11375 tcg_temp_free_i32(fp1);
11376 gen_store_fpr32(ctx, fp0, fd);
11377 tcg_temp_free_i32(fp0);
11380 break;
11381 case OPC_CVT_D_S:
11382 check_cp1_registers(ctx, fd);
11384 TCGv_i32 fp32 = tcg_temp_new_i32();
11385 TCGv_i64 fp64 = tcg_temp_new_i64();
11387 gen_load_fpr32(ctx, fp32, fs);
11388 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11389 tcg_temp_free_i32(fp32);
11390 gen_store_fpr64(ctx, fp64, fd);
11391 tcg_temp_free_i64(fp64);
11393 break;
11394 case OPC_CVT_W_S:
11396 TCGv_i32 fp0 = tcg_temp_new_i32();
11398 gen_load_fpr32(ctx, fp0, fs);
11399 if (ctx->nan2008) {
11400 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11401 } else {
11402 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11404 gen_store_fpr32(ctx, fp0, fd);
11405 tcg_temp_free_i32(fp0);
11407 break;
11408 case OPC_CVT_L_S:
11409 check_cp1_64bitmode(ctx);
11411 TCGv_i32 fp32 = tcg_temp_new_i32();
11412 TCGv_i64 fp64 = tcg_temp_new_i64();
11414 gen_load_fpr32(ctx, fp32, fs);
11415 if (ctx->nan2008) {
11416 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11417 } else {
11418 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11420 tcg_temp_free_i32(fp32);
11421 gen_store_fpr64(ctx, fp64, fd);
11422 tcg_temp_free_i64(fp64);
11424 break;
11425 case OPC_CVT_PS_S:
11426 check_ps(ctx);
11428 TCGv_i64 fp64 = tcg_temp_new_i64();
11429 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11430 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11432 gen_load_fpr32(ctx, fp32_0, fs);
11433 gen_load_fpr32(ctx, fp32_1, ft);
11434 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11435 tcg_temp_free_i32(fp32_1);
11436 tcg_temp_free_i32(fp32_0);
11437 gen_store_fpr64(ctx, fp64, fd);
11438 tcg_temp_free_i64(fp64);
11440 break;
11441 case OPC_CMP_F_S:
11442 case OPC_CMP_UN_S:
11443 case OPC_CMP_EQ_S:
11444 case OPC_CMP_UEQ_S:
11445 case OPC_CMP_OLT_S:
11446 case OPC_CMP_ULT_S:
11447 case OPC_CMP_OLE_S:
11448 case OPC_CMP_ULE_S:
11449 case OPC_CMP_SF_S:
11450 case OPC_CMP_NGLE_S:
11451 case OPC_CMP_SEQ_S:
11452 case OPC_CMP_NGL_S:
11453 case OPC_CMP_LT_S:
11454 case OPC_CMP_NGE_S:
11455 case OPC_CMP_LE_S:
11456 case OPC_CMP_NGT_S:
11457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11458 if (ctx->opcode & (1 << 6)) {
11459 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11460 } else {
11461 gen_cmp_s(ctx, func-48, ft, fs, cc);
11463 break;
11464 case OPC_ADD_D:
11465 check_cp1_registers(ctx, fs | ft | fd);
11467 TCGv_i64 fp0 = tcg_temp_new_i64();
11468 TCGv_i64 fp1 = tcg_temp_new_i64();
11470 gen_load_fpr64(ctx, fp0, fs);
11471 gen_load_fpr64(ctx, fp1, ft);
11472 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11473 tcg_temp_free_i64(fp1);
11474 gen_store_fpr64(ctx, fp0, fd);
11475 tcg_temp_free_i64(fp0);
11477 break;
11478 case OPC_SUB_D:
11479 check_cp1_registers(ctx, fs | ft | fd);
11481 TCGv_i64 fp0 = tcg_temp_new_i64();
11482 TCGv_i64 fp1 = tcg_temp_new_i64();
11484 gen_load_fpr64(ctx, fp0, fs);
11485 gen_load_fpr64(ctx, fp1, ft);
11486 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11487 tcg_temp_free_i64(fp1);
11488 gen_store_fpr64(ctx, fp0, fd);
11489 tcg_temp_free_i64(fp0);
11491 break;
11492 case OPC_MUL_D:
11493 check_cp1_registers(ctx, fs | ft | fd);
11495 TCGv_i64 fp0 = tcg_temp_new_i64();
11496 TCGv_i64 fp1 = tcg_temp_new_i64();
11498 gen_load_fpr64(ctx, fp0, fs);
11499 gen_load_fpr64(ctx, fp1, ft);
11500 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11501 tcg_temp_free_i64(fp1);
11502 gen_store_fpr64(ctx, fp0, fd);
11503 tcg_temp_free_i64(fp0);
11505 break;
11506 case OPC_DIV_D:
11507 check_cp1_registers(ctx, fs | ft | fd);
11509 TCGv_i64 fp0 = tcg_temp_new_i64();
11510 TCGv_i64 fp1 = tcg_temp_new_i64();
11512 gen_load_fpr64(ctx, fp0, fs);
11513 gen_load_fpr64(ctx, fp1, ft);
11514 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11515 tcg_temp_free_i64(fp1);
11516 gen_store_fpr64(ctx, fp0, fd);
11517 tcg_temp_free_i64(fp0);
11519 break;
11520 case OPC_SQRT_D:
11521 check_cp1_registers(ctx, fs | fd);
11523 TCGv_i64 fp0 = tcg_temp_new_i64();
11525 gen_load_fpr64(ctx, fp0, fs);
11526 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11527 gen_store_fpr64(ctx, fp0, fd);
11528 tcg_temp_free_i64(fp0);
11530 break;
11531 case OPC_ABS_D:
11532 check_cp1_registers(ctx, fs | fd);
11534 TCGv_i64 fp0 = tcg_temp_new_i64();
11536 gen_load_fpr64(ctx, fp0, fs);
11537 if (ctx->abs2008) {
11538 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11539 } else {
11540 gen_helper_float_abs_d(fp0, fp0);
11542 gen_store_fpr64(ctx, fp0, fd);
11543 tcg_temp_free_i64(fp0);
11545 break;
11546 case OPC_MOV_D:
11547 check_cp1_registers(ctx, fs | fd);
11549 TCGv_i64 fp0 = tcg_temp_new_i64();
11551 gen_load_fpr64(ctx, fp0, fs);
11552 gen_store_fpr64(ctx, fp0, fd);
11553 tcg_temp_free_i64(fp0);
11555 break;
11556 case OPC_NEG_D:
11557 check_cp1_registers(ctx, fs | fd);
11559 TCGv_i64 fp0 = tcg_temp_new_i64();
11561 gen_load_fpr64(ctx, fp0, fs);
11562 if (ctx->abs2008) {
11563 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11564 } else {
11565 gen_helper_float_chs_d(fp0, fp0);
11567 gen_store_fpr64(ctx, fp0, fd);
11568 tcg_temp_free_i64(fp0);
11570 break;
11571 case OPC_ROUND_L_D:
11572 check_cp1_64bitmode(ctx);
11574 TCGv_i64 fp0 = tcg_temp_new_i64();
11576 gen_load_fpr64(ctx, fp0, fs);
11577 if (ctx->nan2008) {
11578 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11579 } else {
11580 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11582 gen_store_fpr64(ctx, fp0, fd);
11583 tcg_temp_free_i64(fp0);
11585 break;
11586 case OPC_TRUNC_L_D:
11587 check_cp1_64bitmode(ctx);
11589 TCGv_i64 fp0 = tcg_temp_new_i64();
11591 gen_load_fpr64(ctx, fp0, fs);
11592 if (ctx->nan2008) {
11593 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11594 } else {
11595 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11597 gen_store_fpr64(ctx, fp0, fd);
11598 tcg_temp_free_i64(fp0);
11600 break;
11601 case OPC_CEIL_L_D:
11602 check_cp1_64bitmode(ctx);
11604 TCGv_i64 fp0 = tcg_temp_new_i64();
11606 gen_load_fpr64(ctx, fp0, fs);
11607 if (ctx->nan2008) {
11608 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11609 } else {
11610 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11612 gen_store_fpr64(ctx, fp0, fd);
11613 tcg_temp_free_i64(fp0);
11615 break;
11616 case OPC_FLOOR_L_D:
11617 check_cp1_64bitmode(ctx);
11619 TCGv_i64 fp0 = tcg_temp_new_i64();
11621 gen_load_fpr64(ctx, fp0, fs);
11622 if (ctx->nan2008) {
11623 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11624 } else {
11625 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11627 gen_store_fpr64(ctx, fp0, fd);
11628 tcg_temp_free_i64(fp0);
11630 break;
11631 case OPC_ROUND_W_D:
11632 check_cp1_registers(ctx, fs);
11634 TCGv_i32 fp32 = tcg_temp_new_i32();
11635 TCGv_i64 fp64 = tcg_temp_new_i64();
11637 gen_load_fpr64(ctx, fp64, fs);
11638 if (ctx->nan2008) {
11639 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11640 } else {
11641 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11643 tcg_temp_free_i64(fp64);
11644 gen_store_fpr32(ctx, fp32, fd);
11645 tcg_temp_free_i32(fp32);
11647 break;
11648 case OPC_TRUNC_W_D:
11649 check_cp1_registers(ctx, fs);
11651 TCGv_i32 fp32 = tcg_temp_new_i32();
11652 TCGv_i64 fp64 = tcg_temp_new_i64();
11654 gen_load_fpr64(ctx, fp64, fs);
11655 if (ctx->nan2008) {
11656 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11657 } else {
11658 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11660 tcg_temp_free_i64(fp64);
11661 gen_store_fpr32(ctx, fp32, fd);
11662 tcg_temp_free_i32(fp32);
11664 break;
11665 case OPC_CEIL_W_D:
11666 check_cp1_registers(ctx, fs);
11668 TCGv_i32 fp32 = tcg_temp_new_i32();
11669 TCGv_i64 fp64 = tcg_temp_new_i64();
11671 gen_load_fpr64(ctx, fp64, fs);
11672 if (ctx->nan2008) {
11673 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11674 } else {
11675 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11677 tcg_temp_free_i64(fp64);
11678 gen_store_fpr32(ctx, fp32, fd);
11679 tcg_temp_free_i32(fp32);
11681 break;
11682 case OPC_FLOOR_W_D:
11683 check_cp1_registers(ctx, fs);
11685 TCGv_i32 fp32 = tcg_temp_new_i32();
11686 TCGv_i64 fp64 = tcg_temp_new_i64();
11688 gen_load_fpr64(ctx, fp64, fs);
11689 if (ctx->nan2008) {
11690 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11691 } else {
11692 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11694 tcg_temp_free_i64(fp64);
11695 gen_store_fpr32(ctx, fp32, fd);
11696 tcg_temp_free_i32(fp32);
11698 break;
11699 case OPC_SEL_D:
11700 check_insn(ctx, ISA_MIPS32R6);
11701 gen_sel_d(ctx, op1, fd, ft, fs);
11702 break;
11703 case OPC_SELEQZ_D:
11704 check_insn(ctx, ISA_MIPS32R6);
11705 gen_sel_d(ctx, op1, fd, ft, fs);
11706 break;
11707 case OPC_SELNEZ_D:
11708 check_insn(ctx, ISA_MIPS32R6);
11709 gen_sel_d(ctx, op1, fd, ft, fs);
11710 break;
11711 case OPC_MOVCF_D:
11712 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11713 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11714 break;
11715 case OPC_MOVZ_D:
11716 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11718 TCGLabel *l1 = gen_new_label();
11719 TCGv_i64 fp0;
11721 if (ft != 0) {
11722 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11724 fp0 = tcg_temp_new_i64();
11725 gen_load_fpr64(ctx, fp0, fs);
11726 gen_store_fpr64(ctx, fp0, fd);
11727 tcg_temp_free_i64(fp0);
11728 gen_set_label(l1);
11730 break;
11731 case OPC_MOVN_D:
11732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11734 TCGLabel *l1 = gen_new_label();
11735 TCGv_i64 fp0;
11737 if (ft != 0) {
11738 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11739 fp0 = tcg_temp_new_i64();
11740 gen_load_fpr64(ctx, fp0, fs);
11741 gen_store_fpr64(ctx, fp0, fd);
11742 tcg_temp_free_i64(fp0);
11743 gen_set_label(l1);
11746 break;
11747 case OPC_RECIP_D:
11748 check_cp1_registers(ctx, fs | fd);
11750 TCGv_i64 fp0 = tcg_temp_new_i64();
11752 gen_load_fpr64(ctx, fp0, fs);
11753 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11754 gen_store_fpr64(ctx, fp0, fd);
11755 tcg_temp_free_i64(fp0);
11757 break;
11758 case OPC_RSQRT_D:
11759 check_cp1_registers(ctx, fs | fd);
11761 TCGv_i64 fp0 = tcg_temp_new_i64();
11763 gen_load_fpr64(ctx, fp0, fs);
11764 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11765 gen_store_fpr64(ctx, fp0, fd);
11766 tcg_temp_free_i64(fp0);
11768 break;
11769 case OPC_MADDF_D:
11770 check_insn(ctx, ISA_MIPS32R6);
11772 TCGv_i64 fp0 = tcg_temp_new_i64();
11773 TCGv_i64 fp1 = tcg_temp_new_i64();
11774 TCGv_i64 fp2 = tcg_temp_new_i64();
11775 gen_load_fpr64(ctx, fp0, fs);
11776 gen_load_fpr64(ctx, fp1, ft);
11777 gen_load_fpr64(ctx, fp2, fd);
11778 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11779 gen_store_fpr64(ctx, fp2, fd);
11780 tcg_temp_free_i64(fp2);
11781 tcg_temp_free_i64(fp1);
11782 tcg_temp_free_i64(fp0);
11784 break;
11785 case OPC_MSUBF_D:
11786 check_insn(ctx, ISA_MIPS32R6);
11788 TCGv_i64 fp0 = tcg_temp_new_i64();
11789 TCGv_i64 fp1 = tcg_temp_new_i64();
11790 TCGv_i64 fp2 = tcg_temp_new_i64();
11791 gen_load_fpr64(ctx, fp0, fs);
11792 gen_load_fpr64(ctx, fp1, ft);
11793 gen_load_fpr64(ctx, fp2, fd);
11794 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11795 gen_store_fpr64(ctx, fp2, fd);
11796 tcg_temp_free_i64(fp2);
11797 tcg_temp_free_i64(fp1);
11798 tcg_temp_free_i64(fp0);
11800 break;
11801 case OPC_RINT_D:
11802 check_insn(ctx, ISA_MIPS32R6);
11804 TCGv_i64 fp0 = tcg_temp_new_i64();
11805 gen_load_fpr64(ctx, fp0, fs);
11806 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11807 gen_store_fpr64(ctx, fp0, fd);
11808 tcg_temp_free_i64(fp0);
11810 break;
11811 case OPC_CLASS_D:
11812 check_insn(ctx, ISA_MIPS32R6);
11814 TCGv_i64 fp0 = tcg_temp_new_i64();
11815 gen_load_fpr64(ctx, fp0, fs);
11816 gen_helper_float_class_d(fp0, cpu_env, fp0);
11817 gen_store_fpr64(ctx, fp0, fd);
11818 tcg_temp_free_i64(fp0);
11820 break;
11821 case OPC_MIN_D: /* OPC_RECIP2_D */
11822 if (ctx->insn_flags & ISA_MIPS32R6) {
11823 /* OPC_MIN_D */
11824 TCGv_i64 fp0 = tcg_temp_new_i64();
11825 TCGv_i64 fp1 = tcg_temp_new_i64();
11826 gen_load_fpr64(ctx, fp0, fs);
11827 gen_load_fpr64(ctx, fp1, ft);
11828 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11829 gen_store_fpr64(ctx, fp1, fd);
11830 tcg_temp_free_i64(fp1);
11831 tcg_temp_free_i64(fp0);
11832 } else {
11833 /* OPC_RECIP2_D */
11834 check_cp1_64bitmode(ctx);
11836 TCGv_i64 fp0 = tcg_temp_new_i64();
11837 TCGv_i64 fp1 = tcg_temp_new_i64();
11839 gen_load_fpr64(ctx, fp0, fs);
11840 gen_load_fpr64(ctx, fp1, ft);
11841 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11842 tcg_temp_free_i64(fp1);
11843 gen_store_fpr64(ctx, fp0, fd);
11844 tcg_temp_free_i64(fp0);
11847 break;
11848 case OPC_MINA_D: /* OPC_RECIP1_D */
11849 if (ctx->insn_flags & ISA_MIPS32R6) {
11850 /* OPC_MINA_D */
11851 TCGv_i64 fp0 = tcg_temp_new_i64();
11852 TCGv_i64 fp1 = tcg_temp_new_i64();
11853 gen_load_fpr64(ctx, fp0, fs);
11854 gen_load_fpr64(ctx, fp1, ft);
11855 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11856 gen_store_fpr64(ctx, fp1, fd);
11857 tcg_temp_free_i64(fp1);
11858 tcg_temp_free_i64(fp0);
11859 } else {
11860 /* OPC_RECIP1_D */
11861 check_cp1_64bitmode(ctx);
11863 TCGv_i64 fp0 = tcg_temp_new_i64();
11865 gen_load_fpr64(ctx, fp0, fs);
11866 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11867 gen_store_fpr64(ctx, fp0, fd);
11868 tcg_temp_free_i64(fp0);
11871 break;
11872 case OPC_MAX_D: /* OPC_RSQRT1_D */
11873 if (ctx->insn_flags & ISA_MIPS32R6) {
11874 /* OPC_MAX_D */
11875 TCGv_i64 fp0 = tcg_temp_new_i64();
11876 TCGv_i64 fp1 = tcg_temp_new_i64();
11877 gen_load_fpr64(ctx, fp0, fs);
11878 gen_load_fpr64(ctx, fp1, ft);
11879 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11880 gen_store_fpr64(ctx, fp1, fd);
11881 tcg_temp_free_i64(fp1);
11882 tcg_temp_free_i64(fp0);
11883 } else {
11884 /* OPC_RSQRT1_D */
11885 check_cp1_64bitmode(ctx);
11887 TCGv_i64 fp0 = tcg_temp_new_i64();
11889 gen_load_fpr64(ctx, fp0, fs);
11890 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11891 gen_store_fpr64(ctx, fp0, fd);
11892 tcg_temp_free_i64(fp0);
11895 break;
11896 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11897 if (ctx->insn_flags & ISA_MIPS32R6) {
11898 /* OPC_MAXA_D */
11899 TCGv_i64 fp0 = tcg_temp_new_i64();
11900 TCGv_i64 fp1 = tcg_temp_new_i64();
11901 gen_load_fpr64(ctx, fp0, fs);
11902 gen_load_fpr64(ctx, fp1, ft);
11903 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11904 gen_store_fpr64(ctx, fp1, fd);
11905 tcg_temp_free_i64(fp1);
11906 tcg_temp_free_i64(fp0);
11907 } else {
11908 /* OPC_RSQRT2_D */
11909 check_cp1_64bitmode(ctx);
11911 TCGv_i64 fp0 = tcg_temp_new_i64();
11912 TCGv_i64 fp1 = tcg_temp_new_i64();
11914 gen_load_fpr64(ctx, fp0, fs);
11915 gen_load_fpr64(ctx, fp1, ft);
11916 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11917 tcg_temp_free_i64(fp1);
11918 gen_store_fpr64(ctx, fp0, fd);
11919 tcg_temp_free_i64(fp0);
11922 break;
11923 case OPC_CMP_F_D:
11924 case OPC_CMP_UN_D:
11925 case OPC_CMP_EQ_D:
11926 case OPC_CMP_UEQ_D:
11927 case OPC_CMP_OLT_D:
11928 case OPC_CMP_ULT_D:
11929 case OPC_CMP_OLE_D:
11930 case OPC_CMP_ULE_D:
11931 case OPC_CMP_SF_D:
11932 case OPC_CMP_NGLE_D:
11933 case OPC_CMP_SEQ_D:
11934 case OPC_CMP_NGL_D:
11935 case OPC_CMP_LT_D:
11936 case OPC_CMP_NGE_D:
11937 case OPC_CMP_LE_D:
11938 case OPC_CMP_NGT_D:
11939 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11940 if (ctx->opcode & (1 << 6)) {
11941 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11942 } else {
11943 gen_cmp_d(ctx, func-48, ft, fs, cc);
11945 break;
11946 case OPC_CVT_S_D:
11947 check_cp1_registers(ctx, fs);
11949 TCGv_i32 fp32 = tcg_temp_new_i32();
11950 TCGv_i64 fp64 = tcg_temp_new_i64();
11952 gen_load_fpr64(ctx, fp64, fs);
11953 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11954 tcg_temp_free_i64(fp64);
11955 gen_store_fpr32(ctx, fp32, fd);
11956 tcg_temp_free_i32(fp32);
11958 break;
11959 case OPC_CVT_W_D:
11960 check_cp1_registers(ctx, fs);
11962 TCGv_i32 fp32 = tcg_temp_new_i32();
11963 TCGv_i64 fp64 = tcg_temp_new_i64();
11965 gen_load_fpr64(ctx, fp64, fs);
11966 if (ctx->nan2008) {
11967 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11968 } else {
11969 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11971 tcg_temp_free_i64(fp64);
11972 gen_store_fpr32(ctx, fp32, fd);
11973 tcg_temp_free_i32(fp32);
11975 break;
11976 case OPC_CVT_L_D:
11977 check_cp1_64bitmode(ctx);
11979 TCGv_i64 fp0 = tcg_temp_new_i64();
11981 gen_load_fpr64(ctx, fp0, fs);
11982 if (ctx->nan2008) {
11983 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11984 } else {
11985 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11987 gen_store_fpr64(ctx, fp0, fd);
11988 tcg_temp_free_i64(fp0);
11990 break;
11991 case OPC_CVT_S_W:
11993 TCGv_i32 fp0 = tcg_temp_new_i32();
11995 gen_load_fpr32(ctx, fp0, fs);
11996 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11997 gen_store_fpr32(ctx, fp0, fd);
11998 tcg_temp_free_i32(fp0);
12000 break;
12001 case OPC_CVT_D_W:
12002 check_cp1_registers(ctx, fd);
12004 TCGv_i32 fp32 = tcg_temp_new_i32();
12005 TCGv_i64 fp64 = tcg_temp_new_i64();
12007 gen_load_fpr32(ctx, fp32, fs);
12008 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12009 tcg_temp_free_i32(fp32);
12010 gen_store_fpr64(ctx, fp64, fd);
12011 tcg_temp_free_i64(fp64);
12013 break;
12014 case OPC_CVT_S_L:
12015 check_cp1_64bitmode(ctx);
12017 TCGv_i32 fp32 = tcg_temp_new_i32();
12018 TCGv_i64 fp64 = tcg_temp_new_i64();
12020 gen_load_fpr64(ctx, fp64, fs);
12021 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12022 tcg_temp_free_i64(fp64);
12023 gen_store_fpr32(ctx, fp32, fd);
12024 tcg_temp_free_i32(fp32);
12026 break;
12027 case OPC_CVT_D_L:
12028 check_cp1_64bitmode(ctx);
12030 TCGv_i64 fp0 = tcg_temp_new_i64();
12032 gen_load_fpr64(ctx, fp0, fs);
12033 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12034 gen_store_fpr64(ctx, fp0, fd);
12035 tcg_temp_free_i64(fp0);
12037 break;
12038 case OPC_CVT_PS_PW:
12039 check_ps(ctx);
12041 TCGv_i64 fp0 = tcg_temp_new_i64();
12043 gen_load_fpr64(ctx, fp0, fs);
12044 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12045 gen_store_fpr64(ctx, fp0, fd);
12046 tcg_temp_free_i64(fp0);
12048 break;
12049 case OPC_ADD_PS:
12050 check_ps(ctx);
12052 TCGv_i64 fp0 = tcg_temp_new_i64();
12053 TCGv_i64 fp1 = tcg_temp_new_i64();
12055 gen_load_fpr64(ctx, fp0, fs);
12056 gen_load_fpr64(ctx, fp1, ft);
12057 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12058 tcg_temp_free_i64(fp1);
12059 gen_store_fpr64(ctx, fp0, fd);
12060 tcg_temp_free_i64(fp0);
12062 break;
12063 case OPC_SUB_PS:
12064 check_ps(ctx);
12066 TCGv_i64 fp0 = tcg_temp_new_i64();
12067 TCGv_i64 fp1 = tcg_temp_new_i64();
12069 gen_load_fpr64(ctx, fp0, fs);
12070 gen_load_fpr64(ctx, fp1, ft);
12071 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12072 tcg_temp_free_i64(fp1);
12073 gen_store_fpr64(ctx, fp0, fd);
12074 tcg_temp_free_i64(fp0);
12076 break;
12077 case OPC_MUL_PS:
12078 check_ps(ctx);
12080 TCGv_i64 fp0 = tcg_temp_new_i64();
12081 TCGv_i64 fp1 = tcg_temp_new_i64();
12083 gen_load_fpr64(ctx, fp0, fs);
12084 gen_load_fpr64(ctx, fp1, ft);
12085 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12086 tcg_temp_free_i64(fp1);
12087 gen_store_fpr64(ctx, fp0, fd);
12088 tcg_temp_free_i64(fp0);
12090 break;
12091 case OPC_ABS_PS:
12092 check_ps(ctx);
12094 TCGv_i64 fp0 = tcg_temp_new_i64();
12096 gen_load_fpr64(ctx, fp0, fs);
12097 gen_helper_float_abs_ps(fp0, fp0);
12098 gen_store_fpr64(ctx, fp0, fd);
12099 tcg_temp_free_i64(fp0);
12101 break;
12102 case OPC_MOV_PS:
12103 check_ps(ctx);
12105 TCGv_i64 fp0 = tcg_temp_new_i64();
12107 gen_load_fpr64(ctx, fp0, fs);
12108 gen_store_fpr64(ctx, fp0, fd);
12109 tcg_temp_free_i64(fp0);
12111 break;
12112 case OPC_NEG_PS:
12113 check_ps(ctx);
12115 TCGv_i64 fp0 = tcg_temp_new_i64();
12117 gen_load_fpr64(ctx, fp0, fs);
12118 gen_helper_float_chs_ps(fp0, fp0);
12119 gen_store_fpr64(ctx, fp0, fd);
12120 tcg_temp_free_i64(fp0);
12122 break;
12123 case OPC_MOVCF_PS:
12124 check_ps(ctx);
12125 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12126 break;
12127 case OPC_MOVZ_PS:
12128 check_ps(ctx);
12130 TCGLabel *l1 = gen_new_label();
12131 TCGv_i64 fp0;
12133 if (ft != 0)
12134 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12135 fp0 = tcg_temp_new_i64();
12136 gen_load_fpr64(ctx, fp0, fs);
12137 gen_store_fpr64(ctx, fp0, fd);
12138 tcg_temp_free_i64(fp0);
12139 gen_set_label(l1);
12141 break;
12142 case OPC_MOVN_PS:
12143 check_ps(ctx);
12145 TCGLabel *l1 = gen_new_label();
12146 TCGv_i64 fp0;
12148 if (ft != 0) {
12149 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12150 fp0 = tcg_temp_new_i64();
12151 gen_load_fpr64(ctx, fp0, fs);
12152 gen_store_fpr64(ctx, fp0, fd);
12153 tcg_temp_free_i64(fp0);
12154 gen_set_label(l1);
12157 break;
12158 case OPC_ADDR_PS:
12159 check_ps(ctx);
12161 TCGv_i64 fp0 = tcg_temp_new_i64();
12162 TCGv_i64 fp1 = tcg_temp_new_i64();
12164 gen_load_fpr64(ctx, fp0, ft);
12165 gen_load_fpr64(ctx, fp1, fs);
12166 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12167 tcg_temp_free_i64(fp1);
12168 gen_store_fpr64(ctx, fp0, fd);
12169 tcg_temp_free_i64(fp0);
12171 break;
12172 case OPC_MULR_PS:
12173 check_ps(ctx);
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12176 TCGv_i64 fp1 = tcg_temp_new_i64();
12178 gen_load_fpr64(ctx, fp0, ft);
12179 gen_load_fpr64(ctx, fp1, fs);
12180 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12181 tcg_temp_free_i64(fp1);
12182 gen_store_fpr64(ctx, fp0, fd);
12183 tcg_temp_free_i64(fp0);
12185 break;
12186 case OPC_RECIP2_PS:
12187 check_ps(ctx);
12189 TCGv_i64 fp0 = tcg_temp_new_i64();
12190 TCGv_i64 fp1 = tcg_temp_new_i64();
12192 gen_load_fpr64(ctx, fp0, fs);
12193 gen_load_fpr64(ctx, fp1, ft);
12194 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12195 tcg_temp_free_i64(fp1);
12196 gen_store_fpr64(ctx, fp0, fd);
12197 tcg_temp_free_i64(fp0);
12199 break;
12200 case OPC_RECIP1_PS:
12201 check_ps(ctx);
12203 TCGv_i64 fp0 = tcg_temp_new_i64();
12205 gen_load_fpr64(ctx, fp0, fs);
12206 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12207 gen_store_fpr64(ctx, fp0, fd);
12208 tcg_temp_free_i64(fp0);
12210 break;
12211 case OPC_RSQRT1_PS:
12212 check_ps(ctx);
12214 TCGv_i64 fp0 = tcg_temp_new_i64();
12216 gen_load_fpr64(ctx, fp0, fs);
12217 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12218 gen_store_fpr64(ctx, fp0, fd);
12219 tcg_temp_free_i64(fp0);
12221 break;
12222 case OPC_RSQRT2_PS:
12223 check_ps(ctx);
12225 TCGv_i64 fp0 = tcg_temp_new_i64();
12226 TCGv_i64 fp1 = tcg_temp_new_i64();
12228 gen_load_fpr64(ctx, fp0, fs);
12229 gen_load_fpr64(ctx, fp1, ft);
12230 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12231 tcg_temp_free_i64(fp1);
12232 gen_store_fpr64(ctx, fp0, fd);
12233 tcg_temp_free_i64(fp0);
12235 break;
12236 case OPC_CVT_S_PU:
12237 check_cp1_64bitmode(ctx);
12239 TCGv_i32 fp0 = tcg_temp_new_i32();
12241 gen_load_fpr32h(ctx, fp0, fs);
12242 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12243 gen_store_fpr32(ctx, fp0, fd);
12244 tcg_temp_free_i32(fp0);
12246 break;
12247 case OPC_CVT_PW_PS:
12248 check_ps(ctx);
12250 TCGv_i64 fp0 = tcg_temp_new_i64();
12252 gen_load_fpr64(ctx, fp0, fs);
12253 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12254 gen_store_fpr64(ctx, fp0, fd);
12255 tcg_temp_free_i64(fp0);
12257 break;
12258 case OPC_CVT_S_PL:
12259 check_cp1_64bitmode(ctx);
12261 TCGv_i32 fp0 = tcg_temp_new_i32();
12263 gen_load_fpr32(ctx, fp0, fs);
12264 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12265 gen_store_fpr32(ctx, fp0, fd);
12266 tcg_temp_free_i32(fp0);
12268 break;
12269 case OPC_PLL_PS:
12270 check_ps(ctx);
12272 TCGv_i32 fp0 = tcg_temp_new_i32();
12273 TCGv_i32 fp1 = tcg_temp_new_i32();
12275 gen_load_fpr32(ctx, fp0, fs);
12276 gen_load_fpr32(ctx, fp1, ft);
12277 gen_store_fpr32h(ctx, fp0, fd);
12278 gen_store_fpr32(ctx, fp1, fd);
12279 tcg_temp_free_i32(fp0);
12280 tcg_temp_free_i32(fp1);
12282 break;
12283 case OPC_PLU_PS:
12284 check_ps(ctx);
12286 TCGv_i32 fp0 = tcg_temp_new_i32();
12287 TCGv_i32 fp1 = tcg_temp_new_i32();
12289 gen_load_fpr32(ctx, fp0, fs);
12290 gen_load_fpr32h(ctx, fp1, ft);
12291 gen_store_fpr32(ctx, fp1, fd);
12292 gen_store_fpr32h(ctx, fp0, fd);
12293 tcg_temp_free_i32(fp0);
12294 tcg_temp_free_i32(fp1);
12296 break;
12297 case OPC_PUL_PS:
12298 check_ps(ctx);
12300 TCGv_i32 fp0 = tcg_temp_new_i32();
12301 TCGv_i32 fp1 = tcg_temp_new_i32();
12303 gen_load_fpr32h(ctx, fp0, fs);
12304 gen_load_fpr32(ctx, fp1, ft);
12305 gen_store_fpr32(ctx, fp1, fd);
12306 gen_store_fpr32h(ctx, fp0, fd);
12307 tcg_temp_free_i32(fp0);
12308 tcg_temp_free_i32(fp1);
12310 break;
12311 case OPC_PUU_PS:
12312 check_ps(ctx);
12314 TCGv_i32 fp0 = tcg_temp_new_i32();
12315 TCGv_i32 fp1 = tcg_temp_new_i32();
12317 gen_load_fpr32h(ctx, fp0, fs);
12318 gen_load_fpr32h(ctx, fp1, ft);
12319 gen_store_fpr32(ctx, fp1, fd);
12320 gen_store_fpr32h(ctx, fp0, fd);
12321 tcg_temp_free_i32(fp0);
12322 tcg_temp_free_i32(fp1);
12324 break;
12325 case OPC_CMP_F_PS:
12326 case OPC_CMP_UN_PS:
12327 case OPC_CMP_EQ_PS:
12328 case OPC_CMP_UEQ_PS:
12329 case OPC_CMP_OLT_PS:
12330 case OPC_CMP_ULT_PS:
12331 case OPC_CMP_OLE_PS:
12332 case OPC_CMP_ULE_PS:
12333 case OPC_CMP_SF_PS:
12334 case OPC_CMP_NGLE_PS:
12335 case OPC_CMP_SEQ_PS:
12336 case OPC_CMP_NGL_PS:
12337 case OPC_CMP_LT_PS:
12338 case OPC_CMP_NGE_PS:
12339 case OPC_CMP_LE_PS:
12340 case OPC_CMP_NGT_PS:
12341 if (ctx->opcode & (1 << 6)) {
12342 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12343 } else {
12344 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12346 break;
12347 default:
12348 MIPS_INVAL("farith");
12349 generate_exception_end(ctx, EXCP_RI);
12350 return;
12354 /* Coprocessor 3 (FPU) */
12355 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12356 int fd, int fs, int base, int index)
12358 TCGv t0 = tcg_temp_new();
12360 if (base == 0) {
12361 gen_load_gpr(t0, index);
12362 } else if (index == 0) {
12363 gen_load_gpr(t0, base);
12364 } else {
12365 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12367 /* Don't do NOP if destination is zero: we must perform the actual
12368 memory access. */
12369 switch (opc) {
12370 case OPC_LWXC1:
12371 check_cop1x(ctx);
12373 TCGv_i32 fp0 = tcg_temp_new_i32();
12375 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12376 tcg_gen_trunc_tl_i32(fp0, t0);
12377 gen_store_fpr32(ctx, fp0, fd);
12378 tcg_temp_free_i32(fp0);
12380 break;
12381 case OPC_LDXC1:
12382 check_cop1x(ctx);
12383 check_cp1_registers(ctx, fd);
12385 TCGv_i64 fp0 = tcg_temp_new_i64();
12386 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12387 gen_store_fpr64(ctx, fp0, fd);
12388 tcg_temp_free_i64(fp0);
12390 break;
12391 case OPC_LUXC1:
12392 check_cp1_64bitmode(ctx);
12393 tcg_gen_andi_tl(t0, t0, ~0x7);
12395 TCGv_i64 fp0 = tcg_temp_new_i64();
12397 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12398 gen_store_fpr64(ctx, fp0, fd);
12399 tcg_temp_free_i64(fp0);
12401 break;
12402 case OPC_SWXC1:
12403 check_cop1x(ctx);
12405 TCGv_i32 fp0 = tcg_temp_new_i32();
12406 gen_load_fpr32(ctx, fp0, fs);
12407 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12408 tcg_temp_free_i32(fp0);
12410 break;
12411 case OPC_SDXC1:
12412 check_cop1x(ctx);
12413 check_cp1_registers(ctx, fs);
12415 TCGv_i64 fp0 = tcg_temp_new_i64();
12416 gen_load_fpr64(ctx, fp0, fs);
12417 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12418 tcg_temp_free_i64(fp0);
12420 break;
12421 case OPC_SUXC1:
12422 check_cp1_64bitmode(ctx);
12423 tcg_gen_andi_tl(t0, t0, ~0x7);
12425 TCGv_i64 fp0 = tcg_temp_new_i64();
12426 gen_load_fpr64(ctx, fp0, fs);
12427 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12428 tcg_temp_free_i64(fp0);
12430 break;
12432 tcg_temp_free(t0);
12435 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12436 int fd, int fr, int fs, int ft)
12438 switch (opc) {
12439 case OPC_ALNV_PS:
12440 check_ps(ctx);
12442 TCGv t0 = tcg_temp_local_new();
12443 TCGv_i32 fp = tcg_temp_new_i32();
12444 TCGv_i32 fph = tcg_temp_new_i32();
12445 TCGLabel *l1 = gen_new_label();
12446 TCGLabel *l2 = gen_new_label();
12448 gen_load_gpr(t0, fr);
12449 tcg_gen_andi_tl(t0, t0, 0x7);
12451 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12452 gen_load_fpr32(ctx, fp, fs);
12453 gen_load_fpr32h(ctx, fph, fs);
12454 gen_store_fpr32(ctx, fp, fd);
12455 gen_store_fpr32h(ctx, fph, fd);
12456 tcg_gen_br(l2);
12457 gen_set_label(l1);
12458 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12459 tcg_temp_free(t0);
12460 #ifdef TARGET_WORDS_BIGENDIAN
12461 gen_load_fpr32(ctx, fp, fs);
12462 gen_load_fpr32h(ctx, fph, ft);
12463 gen_store_fpr32h(ctx, fp, fd);
12464 gen_store_fpr32(ctx, fph, fd);
12465 #else
12466 gen_load_fpr32h(ctx, fph, fs);
12467 gen_load_fpr32(ctx, fp, ft);
12468 gen_store_fpr32(ctx, fph, fd);
12469 gen_store_fpr32h(ctx, fp, fd);
12470 #endif
12471 gen_set_label(l2);
12472 tcg_temp_free_i32(fp);
12473 tcg_temp_free_i32(fph);
12475 break;
12476 case OPC_MADD_S:
12477 check_cop1x(ctx);
12479 TCGv_i32 fp0 = tcg_temp_new_i32();
12480 TCGv_i32 fp1 = tcg_temp_new_i32();
12481 TCGv_i32 fp2 = tcg_temp_new_i32();
12483 gen_load_fpr32(ctx, fp0, fs);
12484 gen_load_fpr32(ctx, fp1, ft);
12485 gen_load_fpr32(ctx, fp2, fr);
12486 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12487 tcg_temp_free_i32(fp0);
12488 tcg_temp_free_i32(fp1);
12489 gen_store_fpr32(ctx, fp2, fd);
12490 tcg_temp_free_i32(fp2);
12492 break;
12493 case OPC_MADD_D:
12494 check_cop1x(ctx);
12495 check_cp1_registers(ctx, fd | fs | ft | fr);
12497 TCGv_i64 fp0 = tcg_temp_new_i64();
12498 TCGv_i64 fp1 = tcg_temp_new_i64();
12499 TCGv_i64 fp2 = tcg_temp_new_i64();
12501 gen_load_fpr64(ctx, fp0, fs);
12502 gen_load_fpr64(ctx, fp1, ft);
12503 gen_load_fpr64(ctx, fp2, fr);
12504 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12505 tcg_temp_free_i64(fp0);
12506 tcg_temp_free_i64(fp1);
12507 gen_store_fpr64(ctx, fp2, fd);
12508 tcg_temp_free_i64(fp2);
12510 break;
12511 case OPC_MADD_PS:
12512 check_ps(ctx);
12514 TCGv_i64 fp0 = tcg_temp_new_i64();
12515 TCGv_i64 fp1 = tcg_temp_new_i64();
12516 TCGv_i64 fp2 = tcg_temp_new_i64();
12518 gen_load_fpr64(ctx, fp0, fs);
12519 gen_load_fpr64(ctx, fp1, ft);
12520 gen_load_fpr64(ctx, fp2, fr);
12521 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12522 tcg_temp_free_i64(fp0);
12523 tcg_temp_free_i64(fp1);
12524 gen_store_fpr64(ctx, fp2, fd);
12525 tcg_temp_free_i64(fp2);
12527 break;
12528 case OPC_MSUB_S:
12529 check_cop1x(ctx);
12531 TCGv_i32 fp0 = tcg_temp_new_i32();
12532 TCGv_i32 fp1 = tcg_temp_new_i32();
12533 TCGv_i32 fp2 = tcg_temp_new_i32();
12535 gen_load_fpr32(ctx, fp0, fs);
12536 gen_load_fpr32(ctx, fp1, ft);
12537 gen_load_fpr32(ctx, fp2, fr);
12538 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12539 tcg_temp_free_i32(fp0);
12540 tcg_temp_free_i32(fp1);
12541 gen_store_fpr32(ctx, fp2, fd);
12542 tcg_temp_free_i32(fp2);
12544 break;
12545 case OPC_MSUB_D:
12546 check_cop1x(ctx);
12547 check_cp1_registers(ctx, fd | fs | ft | fr);
12549 TCGv_i64 fp0 = tcg_temp_new_i64();
12550 TCGv_i64 fp1 = tcg_temp_new_i64();
12551 TCGv_i64 fp2 = tcg_temp_new_i64();
12553 gen_load_fpr64(ctx, fp0, fs);
12554 gen_load_fpr64(ctx, fp1, ft);
12555 gen_load_fpr64(ctx, fp2, fr);
12556 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12557 tcg_temp_free_i64(fp0);
12558 tcg_temp_free_i64(fp1);
12559 gen_store_fpr64(ctx, fp2, fd);
12560 tcg_temp_free_i64(fp2);
12562 break;
12563 case OPC_MSUB_PS:
12564 check_ps(ctx);
12566 TCGv_i64 fp0 = tcg_temp_new_i64();
12567 TCGv_i64 fp1 = tcg_temp_new_i64();
12568 TCGv_i64 fp2 = tcg_temp_new_i64();
12570 gen_load_fpr64(ctx, fp0, fs);
12571 gen_load_fpr64(ctx, fp1, ft);
12572 gen_load_fpr64(ctx, fp2, fr);
12573 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12574 tcg_temp_free_i64(fp0);
12575 tcg_temp_free_i64(fp1);
12576 gen_store_fpr64(ctx, fp2, fd);
12577 tcg_temp_free_i64(fp2);
12579 break;
12580 case OPC_NMADD_S:
12581 check_cop1x(ctx);
12583 TCGv_i32 fp0 = tcg_temp_new_i32();
12584 TCGv_i32 fp1 = tcg_temp_new_i32();
12585 TCGv_i32 fp2 = tcg_temp_new_i32();
12587 gen_load_fpr32(ctx, fp0, fs);
12588 gen_load_fpr32(ctx, fp1, ft);
12589 gen_load_fpr32(ctx, fp2, fr);
12590 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12591 tcg_temp_free_i32(fp0);
12592 tcg_temp_free_i32(fp1);
12593 gen_store_fpr32(ctx, fp2, fd);
12594 tcg_temp_free_i32(fp2);
12596 break;
12597 case OPC_NMADD_D:
12598 check_cop1x(ctx);
12599 check_cp1_registers(ctx, fd | fs | ft | fr);
12601 TCGv_i64 fp0 = tcg_temp_new_i64();
12602 TCGv_i64 fp1 = tcg_temp_new_i64();
12603 TCGv_i64 fp2 = tcg_temp_new_i64();
12605 gen_load_fpr64(ctx, fp0, fs);
12606 gen_load_fpr64(ctx, fp1, ft);
12607 gen_load_fpr64(ctx, fp2, fr);
12608 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12609 tcg_temp_free_i64(fp0);
12610 tcg_temp_free_i64(fp1);
12611 gen_store_fpr64(ctx, fp2, fd);
12612 tcg_temp_free_i64(fp2);
12614 break;
12615 case OPC_NMADD_PS:
12616 check_ps(ctx);
12618 TCGv_i64 fp0 = tcg_temp_new_i64();
12619 TCGv_i64 fp1 = tcg_temp_new_i64();
12620 TCGv_i64 fp2 = tcg_temp_new_i64();
12622 gen_load_fpr64(ctx, fp0, fs);
12623 gen_load_fpr64(ctx, fp1, ft);
12624 gen_load_fpr64(ctx, fp2, fr);
12625 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12626 tcg_temp_free_i64(fp0);
12627 tcg_temp_free_i64(fp1);
12628 gen_store_fpr64(ctx, fp2, fd);
12629 tcg_temp_free_i64(fp2);
12631 break;
12632 case OPC_NMSUB_S:
12633 check_cop1x(ctx);
12635 TCGv_i32 fp0 = tcg_temp_new_i32();
12636 TCGv_i32 fp1 = tcg_temp_new_i32();
12637 TCGv_i32 fp2 = tcg_temp_new_i32();
12639 gen_load_fpr32(ctx, fp0, fs);
12640 gen_load_fpr32(ctx, fp1, ft);
12641 gen_load_fpr32(ctx, fp2, fr);
12642 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12643 tcg_temp_free_i32(fp0);
12644 tcg_temp_free_i32(fp1);
12645 gen_store_fpr32(ctx, fp2, fd);
12646 tcg_temp_free_i32(fp2);
12648 break;
12649 case OPC_NMSUB_D:
12650 check_cop1x(ctx);
12651 check_cp1_registers(ctx, fd | fs | ft | fr);
12653 TCGv_i64 fp0 = tcg_temp_new_i64();
12654 TCGv_i64 fp1 = tcg_temp_new_i64();
12655 TCGv_i64 fp2 = tcg_temp_new_i64();
12657 gen_load_fpr64(ctx, fp0, fs);
12658 gen_load_fpr64(ctx, fp1, ft);
12659 gen_load_fpr64(ctx, fp2, fr);
12660 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12661 tcg_temp_free_i64(fp0);
12662 tcg_temp_free_i64(fp1);
12663 gen_store_fpr64(ctx, fp2, fd);
12664 tcg_temp_free_i64(fp2);
12666 break;
12667 case OPC_NMSUB_PS:
12668 check_ps(ctx);
12670 TCGv_i64 fp0 = tcg_temp_new_i64();
12671 TCGv_i64 fp1 = tcg_temp_new_i64();
12672 TCGv_i64 fp2 = tcg_temp_new_i64();
12674 gen_load_fpr64(ctx, fp0, fs);
12675 gen_load_fpr64(ctx, fp1, ft);
12676 gen_load_fpr64(ctx, fp2, fr);
12677 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12678 tcg_temp_free_i64(fp0);
12679 tcg_temp_free_i64(fp1);
12680 gen_store_fpr64(ctx, fp2, fd);
12681 tcg_temp_free_i64(fp2);
12683 break;
12684 default:
12685 MIPS_INVAL("flt3_arith");
12686 generate_exception_end(ctx, EXCP_RI);
12687 return;
12691 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12693 TCGv t0;
12695 #if !defined(CONFIG_USER_ONLY)
12696 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12697 Therefore only check the ISA in system mode. */
12698 check_insn(ctx, ISA_MIPS32R2);
12699 #endif
12700 t0 = tcg_temp_new();
12702 switch (rd) {
12703 case 0:
12704 gen_helper_rdhwr_cpunum(t0, cpu_env);
12705 gen_store_gpr(t0, rt);
12706 break;
12707 case 1:
12708 gen_helper_rdhwr_synci_step(t0, cpu_env);
12709 gen_store_gpr(t0, rt);
12710 break;
12711 case 2:
12712 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12713 gen_io_start();
12715 gen_helper_rdhwr_cc(t0, cpu_env);
12716 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12717 gen_io_end();
12719 gen_store_gpr(t0, rt);
12720 /* Break the TB to be able to take timer interrupts immediately
12721 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12722 we break completely out of translated code. */
12723 gen_save_pc(ctx->base.pc_next + 4);
12724 ctx->base.is_jmp = DISAS_EXIT;
12725 break;
12726 case 3:
12727 gen_helper_rdhwr_ccres(t0, cpu_env);
12728 gen_store_gpr(t0, rt);
12729 break;
12730 case 4:
12731 check_insn(ctx, ISA_MIPS32R6);
12732 if (sel != 0) {
12733 /* Performance counter registers are not implemented other than
12734 * control register 0.
12736 generate_exception(ctx, EXCP_RI);
12738 gen_helper_rdhwr_performance(t0, cpu_env);
12739 gen_store_gpr(t0, rt);
12740 break;
12741 case 5:
12742 check_insn(ctx, ISA_MIPS32R6);
12743 gen_helper_rdhwr_xnp(t0, cpu_env);
12744 gen_store_gpr(t0, rt);
12745 break;
12746 case 29:
12747 #if defined(CONFIG_USER_ONLY)
12748 tcg_gen_ld_tl(t0, cpu_env,
12749 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12750 gen_store_gpr(t0, rt);
12751 break;
12752 #else
12753 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12754 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12755 tcg_gen_ld_tl(t0, cpu_env,
12756 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12757 gen_store_gpr(t0, rt);
12758 } else {
12759 generate_exception_end(ctx, EXCP_RI);
12761 break;
12762 #endif
12763 default: /* Invalid */
12764 MIPS_INVAL("rdhwr");
12765 generate_exception_end(ctx, EXCP_RI);
12766 break;
12768 tcg_temp_free(t0);
12771 static inline void clear_branch_hflags(DisasContext *ctx)
12773 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12774 if (ctx->base.is_jmp == DISAS_NEXT) {
12775 save_cpu_state(ctx, 0);
12776 } else {
12777 /* it is not safe to save ctx->hflags as hflags may be changed
12778 in execution time by the instruction in delay / forbidden slot. */
12779 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12783 static void gen_branch(DisasContext *ctx, int insn_bytes)
12785 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12786 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12787 /* Branches completion */
12788 clear_branch_hflags(ctx);
12789 ctx->base.is_jmp = DISAS_NORETURN;
12790 /* FIXME: Need to clear can_do_io. */
12791 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12792 case MIPS_HFLAG_FBNSLOT:
12793 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12794 break;
12795 case MIPS_HFLAG_B:
12796 /* unconditional branch */
12797 if (proc_hflags & MIPS_HFLAG_BX) {
12798 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12800 gen_goto_tb(ctx, 0, ctx->btarget);
12801 break;
12802 case MIPS_HFLAG_BL:
12803 /* blikely taken case */
12804 gen_goto_tb(ctx, 0, ctx->btarget);
12805 break;
12806 case MIPS_HFLAG_BC:
12807 /* Conditional branch */
12809 TCGLabel *l1 = gen_new_label();
12811 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12812 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12813 gen_set_label(l1);
12814 gen_goto_tb(ctx, 0, ctx->btarget);
12816 break;
12817 case MIPS_HFLAG_BR:
12818 /* unconditional branch to register */
12819 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12820 TCGv t0 = tcg_temp_new();
12821 TCGv_i32 t1 = tcg_temp_new_i32();
12823 tcg_gen_andi_tl(t0, btarget, 0x1);
12824 tcg_gen_trunc_tl_i32(t1, t0);
12825 tcg_temp_free(t0);
12826 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12827 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12828 tcg_gen_or_i32(hflags, hflags, t1);
12829 tcg_temp_free_i32(t1);
12831 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12832 } else {
12833 tcg_gen_mov_tl(cpu_PC, btarget);
12835 if (ctx->base.singlestep_enabled) {
12836 save_cpu_state(ctx, 0);
12837 gen_helper_raise_exception_debug(cpu_env);
12839 tcg_gen_lookup_and_goto_ptr();
12840 break;
12841 default:
12842 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12843 abort();
12848 /* Compact Branches */
12849 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12850 int rs, int rt, int32_t offset)
12852 int bcond_compute = 0;
12853 TCGv t0 = tcg_temp_new();
12854 TCGv t1 = tcg_temp_new();
12855 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12857 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12858 #ifdef MIPS_DEBUG_DISAS
12859 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12860 "\n", ctx->base.pc_next);
12861 #endif
12862 generate_exception_end(ctx, EXCP_RI);
12863 goto out;
12866 /* Load needed operands and calculate btarget */
12867 switch (opc) {
12868 /* compact branch */
12869 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12870 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12871 gen_load_gpr(t0, rs);
12872 gen_load_gpr(t1, rt);
12873 bcond_compute = 1;
12874 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12875 if (rs <= rt && rs == 0) {
12876 /* OPC_BEQZALC, OPC_BNEZALC */
12877 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12879 break;
12880 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12881 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12882 gen_load_gpr(t0, rs);
12883 gen_load_gpr(t1, rt);
12884 bcond_compute = 1;
12885 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12886 break;
12887 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12888 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12889 if (rs == 0 || rs == rt) {
12890 /* OPC_BLEZALC, OPC_BGEZALC */
12891 /* OPC_BGTZALC, OPC_BLTZALC */
12892 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12894 gen_load_gpr(t0, rs);
12895 gen_load_gpr(t1, rt);
12896 bcond_compute = 1;
12897 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12898 break;
12899 case OPC_BC:
12900 case OPC_BALC:
12901 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12902 break;
12903 case OPC_BEQZC:
12904 case OPC_BNEZC:
12905 if (rs != 0) {
12906 /* OPC_BEQZC, OPC_BNEZC */
12907 gen_load_gpr(t0, rs);
12908 bcond_compute = 1;
12909 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12910 } else {
12911 /* OPC_JIC, OPC_JIALC */
12912 TCGv tbase = tcg_temp_new();
12913 TCGv toffset = tcg_temp_new();
12915 gen_load_gpr(tbase, rt);
12916 tcg_gen_movi_tl(toffset, offset);
12917 gen_op_addr_add(ctx, btarget, tbase, toffset);
12918 tcg_temp_free(tbase);
12919 tcg_temp_free(toffset);
12921 break;
12922 default:
12923 MIPS_INVAL("Compact branch/jump");
12924 generate_exception_end(ctx, EXCP_RI);
12925 goto out;
12928 if (bcond_compute == 0) {
12929 /* Uncoditional compact branch */
12930 switch (opc) {
12931 case OPC_JIALC:
12932 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12933 /* Fallthrough */
12934 case OPC_JIC:
12935 ctx->hflags |= MIPS_HFLAG_BR;
12936 break;
12937 case OPC_BALC:
12938 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12939 /* Fallthrough */
12940 case OPC_BC:
12941 ctx->hflags |= MIPS_HFLAG_B;
12942 break;
12943 default:
12944 MIPS_INVAL("Compact branch/jump");
12945 generate_exception_end(ctx, EXCP_RI);
12946 goto out;
12949 /* Generating branch here as compact branches don't have delay slot */
12950 gen_branch(ctx, 4);
12951 } else {
12952 /* Conditional compact branch */
12953 TCGLabel *fs = gen_new_label();
12954 save_cpu_state(ctx, 0);
12956 switch (opc) {
12957 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12958 if (rs == 0 && rt != 0) {
12959 /* OPC_BLEZALC */
12960 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12961 } else if (rs != 0 && rt != 0 && rs == rt) {
12962 /* OPC_BGEZALC */
12963 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12964 } else {
12965 /* OPC_BGEUC */
12966 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12968 break;
12969 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12970 if (rs == 0 && rt != 0) {
12971 /* OPC_BGTZALC */
12972 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12973 } else if (rs != 0 && rt != 0 && rs == rt) {
12974 /* OPC_BLTZALC */
12975 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12976 } else {
12977 /* OPC_BLTUC */
12978 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12980 break;
12981 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12982 if (rs == 0 && rt != 0) {
12983 /* OPC_BLEZC */
12984 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12985 } else if (rs != 0 && rt != 0 && rs == rt) {
12986 /* OPC_BGEZC */
12987 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12988 } else {
12989 /* OPC_BGEC */
12990 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12992 break;
12993 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12994 if (rs == 0 && rt != 0) {
12995 /* OPC_BGTZC */
12996 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12997 } else if (rs != 0 && rt != 0 && rs == rt) {
12998 /* OPC_BLTZC */
12999 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13000 } else {
13001 /* OPC_BLTC */
13002 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13004 break;
13005 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13006 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13007 if (rs >= rt) {
13008 /* OPC_BOVC, OPC_BNVC */
13009 TCGv t2 = tcg_temp_new();
13010 TCGv t3 = tcg_temp_new();
13011 TCGv t4 = tcg_temp_new();
13012 TCGv input_overflow = tcg_temp_new();
13014 gen_load_gpr(t0, rs);
13015 gen_load_gpr(t1, rt);
13016 tcg_gen_ext32s_tl(t2, t0);
13017 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13018 tcg_gen_ext32s_tl(t3, t1);
13019 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13020 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13022 tcg_gen_add_tl(t4, t2, t3);
13023 tcg_gen_ext32s_tl(t4, t4);
13024 tcg_gen_xor_tl(t2, t2, t3);
13025 tcg_gen_xor_tl(t3, t4, t3);
13026 tcg_gen_andc_tl(t2, t3, t2);
13027 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13028 tcg_gen_or_tl(t4, t4, input_overflow);
13029 if (opc == OPC_BOVC) {
13030 /* OPC_BOVC */
13031 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13032 } else {
13033 /* OPC_BNVC */
13034 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13036 tcg_temp_free(input_overflow);
13037 tcg_temp_free(t4);
13038 tcg_temp_free(t3);
13039 tcg_temp_free(t2);
13040 } else if (rs < rt && rs == 0) {
13041 /* OPC_BEQZALC, OPC_BNEZALC */
13042 if (opc == OPC_BEQZALC) {
13043 /* OPC_BEQZALC */
13044 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13045 } else {
13046 /* OPC_BNEZALC */
13047 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13049 } else {
13050 /* OPC_BEQC, OPC_BNEC */
13051 if (opc == OPC_BEQC) {
13052 /* OPC_BEQC */
13053 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13054 } else {
13055 /* OPC_BNEC */
13056 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13059 break;
13060 case OPC_BEQZC:
13061 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13062 break;
13063 case OPC_BNEZC:
13064 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13065 break;
13066 default:
13067 MIPS_INVAL("Compact conditional branch/jump");
13068 generate_exception_end(ctx, EXCP_RI);
13069 goto out;
13072 /* Generating branch here as compact branches don't have delay slot */
13073 gen_goto_tb(ctx, 1, ctx->btarget);
13074 gen_set_label(fs);
13076 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13079 out:
13080 tcg_temp_free(t0);
13081 tcg_temp_free(t1);
13084 /* ISA extensions (ASEs) */
13085 /* MIPS16 extension to MIPS32 */
13087 /* MIPS16 major opcodes */
13088 enum {
13089 M16_OPC_ADDIUSP = 0x00,
13090 M16_OPC_ADDIUPC = 0x01,
13091 M16_OPC_B = 0x02,
13092 M16_OPC_JAL = 0x03,
13093 M16_OPC_BEQZ = 0x04,
13094 M16_OPC_BNEQZ = 0x05,
13095 M16_OPC_SHIFT = 0x06,
13096 M16_OPC_LD = 0x07,
13097 M16_OPC_RRIA = 0x08,
13098 M16_OPC_ADDIU8 = 0x09,
13099 M16_OPC_SLTI = 0x0a,
13100 M16_OPC_SLTIU = 0x0b,
13101 M16_OPC_I8 = 0x0c,
13102 M16_OPC_LI = 0x0d,
13103 M16_OPC_CMPI = 0x0e,
13104 M16_OPC_SD = 0x0f,
13105 M16_OPC_LB = 0x10,
13106 M16_OPC_LH = 0x11,
13107 M16_OPC_LWSP = 0x12,
13108 M16_OPC_LW = 0x13,
13109 M16_OPC_LBU = 0x14,
13110 M16_OPC_LHU = 0x15,
13111 M16_OPC_LWPC = 0x16,
13112 M16_OPC_LWU = 0x17,
13113 M16_OPC_SB = 0x18,
13114 M16_OPC_SH = 0x19,
13115 M16_OPC_SWSP = 0x1a,
13116 M16_OPC_SW = 0x1b,
13117 M16_OPC_RRR = 0x1c,
13118 M16_OPC_RR = 0x1d,
13119 M16_OPC_EXTEND = 0x1e,
13120 M16_OPC_I64 = 0x1f
13123 /* I8 funct field */
13124 enum {
13125 I8_BTEQZ = 0x0,
13126 I8_BTNEZ = 0x1,
13127 I8_SWRASP = 0x2,
13128 I8_ADJSP = 0x3,
13129 I8_SVRS = 0x4,
13130 I8_MOV32R = 0x5,
13131 I8_MOVR32 = 0x7
13134 /* RRR f field */
13135 enum {
13136 RRR_DADDU = 0x0,
13137 RRR_ADDU = 0x1,
13138 RRR_DSUBU = 0x2,
13139 RRR_SUBU = 0x3
13142 /* RR funct field */
13143 enum {
13144 RR_JR = 0x00,
13145 RR_SDBBP = 0x01,
13146 RR_SLT = 0x02,
13147 RR_SLTU = 0x03,
13148 RR_SLLV = 0x04,
13149 RR_BREAK = 0x05,
13150 RR_SRLV = 0x06,
13151 RR_SRAV = 0x07,
13152 RR_DSRL = 0x08,
13153 RR_CMP = 0x0a,
13154 RR_NEG = 0x0b,
13155 RR_AND = 0x0c,
13156 RR_OR = 0x0d,
13157 RR_XOR = 0x0e,
13158 RR_NOT = 0x0f,
13159 RR_MFHI = 0x10,
13160 RR_CNVT = 0x11,
13161 RR_MFLO = 0x12,
13162 RR_DSRA = 0x13,
13163 RR_DSLLV = 0x14,
13164 RR_DSRLV = 0x16,
13165 RR_DSRAV = 0x17,
13166 RR_MULT = 0x18,
13167 RR_MULTU = 0x19,
13168 RR_DIV = 0x1a,
13169 RR_DIVU = 0x1b,
13170 RR_DMULT = 0x1c,
13171 RR_DMULTU = 0x1d,
13172 RR_DDIV = 0x1e,
13173 RR_DDIVU = 0x1f
13176 /* I64 funct field */
13177 enum {
13178 I64_LDSP = 0x0,
13179 I64_SDSP = 0x1,
13180 I64_SDRASP = 0x2,
13181 I64_DADJSP = 0x3,
13182 I64_LDPC = 0x4,
13183 I64_DADDIU5 = 0x5,
13184 I64_DADDIUPC = 0x6,
13185 I64_DADDIUSP = 0x7
13188 /* RR ry field for CNVT */
13189 enum {
13190 RR_RY_CNVT_ZEB = 0x0,
13191 RR_RY_CNVT_ZEH = 0x1,
13192 RR_RY_CNVT_ZEW = 0x2,
13193 RR_RY_CNVT_SEB = 0x4,
13194 RR_RY_CNVT_SEH = 0x5,
13195 RR_RY_CNVT_SEW = 0x6,
13198 static int xlat (int r)
13200 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13202 return map[r];
13205 static void gen_mips16_save (DisasContext *ctx,
13206 int xsregs, int aregs,
13207 int do_ra, int do_s0, int do_s1,
13208 int framesize)
13210 TCGv t0 = tcg_temp_new();
13211 TCGv t1 = tcg_temp_new();
13212 TCGv t2 = tcg_temp_new();
13213 int args, astatic;
13215 switch (aregs) {
13216 case 0:
13217 case 1:
13218 case 2:
13219 case 3:
13220 case 11:
13221 args = 0;
13222 break;
13223 case 4:
13224 case 5:
13225 case 6:
13226 case 7:
13227 args = 1;
13228 break;
13229 case 8:
13230 case 9:
13231 case 10:
13232 args = 2;
13233 break;
13234 case 12:
13235 case 13:
13236 args = 3;
13237 break;
13238 case 14:
13239 args = 4;
13240 break;
13241 default:
13242 generate_exception_end(ctx, EXCP_RI);
13243 return;
13246 switch (args) {
13247 case 4:
13248 gen_base_offset_addr(ctx, t0, 29, 12);
13249 gen_load_gpr(t1, 7);
13250 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13251 /* Fall through */
13252 case 3:
13253 gen_base_offset_addr(ctx, t0, 29, 8);
13254 gen_load_gpr(t1, 6);
13255 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13256 /* Fall through */
13257 case 2:
13258 gen_base_offset_addr(ctx, t0, 29, 4);
13259 gen_load_gpr(t1, 5);
13260 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13261 /* Fall through */
13262 case 1:
13263 gen_base_offset_addr(ctx, t0, 29, 0);
13264 gen_load_gpr(t1, 4);
13265 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13268 gen_load_gpr(t0, 29);
13270 #define DECR_AND_STORE(reg) do { \
13271 tcg_gen_movi_tl(t2, -4); \
13272 gen_op_addr_add(ctx, t0, t0, t2); \
13273 gen_load_gpr(t1, reg); \
13274 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13275 } while (0)
13277 if (do_ra) {
13278 DECR_AND_STORE(31);
13281 switch (xsregs) {
13282 case 7:
13283 DECR_AND_STORE(30);
13284 /* Fall through */
13285 case 6:
13286 DECR_AND_STORE(23);
13287 /* Fall through */
13288 case 5:
13289 DECR_AND_STORE(22);
13290 /* Fall through */
13291 case 4:
13292 DECR_AND_STORE(21);
13293 /* Fall through */
13294 case 3:
13295 DECR_AND_STORE(20);
13296 /* Fall through */
13297 case 2:
13298 DECR_AND_STORE(19);
13299 /* Fall through */
13300 case 1:
13301 DECR_AND_STORE(18);
13304 if (do_s1) {
13305 DECR_AND_STORE(17);
13307 if (do_s0) {
13308 DECR_AND_STORE(16);
13311 switch (aregs) {
13312 case 0:
13313 case 4:
13314 case 8:
13315 case 12:
13316 case 14:
13317 astatic = 0;
13318 break;
13319 case 1:
13320 case 5:
13321 case 9:
13322 case 13:
13323 astatic = 1;
13324 break;
13325 case 2:
13326 case 6:
13327 case 10:
13328 astatic = 2;
13329 break;
13330 case 3:
13331 case 7:
13332 astatic = 3;
13333 break;
13334 case 11:
13335 astatic = 4;
13336 break;
13337 default:
13338 generate_exception_end(ctx, EXCP_RI);
13339 return;
13342 if (astatic > 0) {
13343 DECR_AND_STORE(7);
13344 if (astatic > 1) {
13345 DECR_AND_STORE(6);
13346 if (astatic > 2) {
13347 DECR_AND_STORE(5);
13348 if (astatic > 3) {
13349 DECR_AND_STORE(4);
13354 #undef DECR_AND_STORE
13356 tcg_gen_movi_tl(t2, -framesize);
13357 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13358 tcg_temp_free(t0);
13359 tcg_temp_free(t1);
13360 tcg_temp_free(t2);
13363 static void gen_mips16_restore (DisasContext *ctx,
13364 int xsregs, int aregs,
13365 int do_ra, int do_s0, int do_s1,
13366 int framesize)
13368 int astatic;
13369 TCGv t0 = tcg_temp_new();
13370 TCGv t1 = tcg_temp_new();
13371 TCGv t2 = tcg_temp_new();
13373 tcg_gen_movi_tl(t2, framesize);
13374 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13376 #define DECR_AND_LOAD(reg) do { \
13377 tcg_gen_movi_tl(t2, -4); \
13378 gen_op_addr_add(ctx, t0, t0, t2); \
13379 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13380 gen_store_gpr(t1, reg); \
13381 } while (0)
13383 if (do_ra) {
13384 DECR_AND_LOAD(31);
13387 switch (xsregs) {
13388 case 7:
13389 DECR_AND_LOAD(30);
13390 /* Fall through */
13391 case 6:
13392 DECR_AND_LOAD(23);
13393 /* Fall through */
13394 case 5:
13395 DECR_AND_LOAD(22);
13396 /* Fall through */
13397 case 4:
13398 DECR_AND_LOAD(21);
13399 /* Fall through */
13400 case 3:
13401 DECR_AND_LOAD(20);
13402 /* Fall through */
13403 case 2:
13404 DECR_AND_LOAD(19);
13405 /* Fall through */
13406 case 1:
13407 DECR_AND_LOAD(18);
13410 if (do_s1) {
13411 DECR_AND_LOAD(17);
13413 if (do_s0) {
13414 DECR_AND_LOAD(16);
13417 switch (aregs) {
13418 case 0:
13419 case 4:
13420 case 8:
13421 case 12:
13422 case 14:
13423 astatic = 0;
13424 break;
13425 case 1:
13426 case 5:
13427 case 9:
13428 case 13:
13429 astatic = 1;
13430 break;
13431 case 2:
13432 case 6:
13433 case 10:
13434 astatic = 2;
13435 break;
13436 case 3:
13437 case 7:
13438 astatic = 3;
13439 break;
13440 case 11:
13441 astatic = 4;
13442 break;
13443 default:
13444 generate_exception_end(ctx, EXCP_RI);
13445 return;
13448 if (astatic > 0) {
13449 DECR_AND_LOAD(7);
13450 if (astatic > 1) {
13451 DECR_AND_LOAD(6);
13452 if (astatic > 2) {
13453 DECR_AND_LOAD(5);
13454 if (astatic > 3) {
13455 DECR_AND_LOAD(4);
13460 #undef DECR_AND_LOAD
13462 tcg_gen_movi_tl(t2, framesize);
13463 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13464 tcg_temp_free(t0);
13465 tcg_temp_free(t1);
13466 tcg_temp_free(t2);
13469 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13470 int is_64_bit, int extended)
13472 TCGv t0;
13474 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13475 generate_exception_end(ctx, EXCP_RI);
13476 return;
13479 t0 = tcg_temp_new();
13481 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13482 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13483 if (!is_64_bit) {
13484 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13487 tcg_temp_free(t0);
13490 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13491 int16_t offset)
13493 TCGv_i32 t0 = tcg_const_i32(op);
13494 TCGv t1 = tcg_temp_new();
13495 gen_base_offset_addr(ctx, t1, base, offset);
13496 gen_helper_cache(cpu_env, t1, t0);
13499 #if defined(TARGET_MIPS64)
13500 static void decode_i64_mips16 (DisasContext *ctx,
13501 int ry, int funct, int16_t offset,
13502 int extended)
13504 switch (funct) {
13505 case I64_LDSP:
13506 check_insn(ctx, ISA_MIPS3);
13507 check_mips_64(ctx);
13508 offset = extended ? offset : offset << 3;
13509 gen_ld(ctx, OPC_LD, ry, 29, offset);
13510 break;
13511 case I64_SDSP:
13512 check_insn(ctx, ISA_MIPS3);
13513 check_mips_64(ctx);
13514 offset = extended ? offset : offset << 3;
13515 gen_st(ctx, OPC_SD, ry, 29, offset);
13516 break;
13517 case I64_SDRASP:
13518 check_insn(ctx, ISA_MIPS3);
13519 check_mips_64(ctx);
13520 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13521 gen_st(ctx, OPC_SD, 31, 29, offset);
13522 break;
13523 case I64_DADJSP:
13524 check_insn(ctx, ISA_MIPS3);
13525 check_mips_64(ctx);
13526 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13527 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13528 break;
13529 case I64_LDPC:
13530 check_insn(ctx, ISA_MIPS3);
13531 check_mips_64(ctx);
13532 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13533 generate_exception_end(ctx, EXCP_RI);
13534 } else {
13535 offset = extended ? offset : offset << 3;
13536 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13538 break;
13539 case I64_DADDIU5:
13540 check_insn(ctx, ISA_MIPS3);
13541 check_mips_64(ctx);
13542 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13543 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13544 break;
13545 case I64_DADDIUPC:
13546 check_insn(ctx, ISA_MIPS3);
13547 check_mips_64(ctx);
13548 offset = extended ? offset : offset << 2;
13549 gen_addiupc(ctx, ry, offset, 1, extended);
13550 break;
13551 case I64_DADDIUSP:
13552 check_insn(ctx, ISA_MIPS3);
13553 check_mips_64(ctx);
13554 offset = extended ? offset : offset << 2;
13555 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13556 break;
13559 #endif
13561 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13563 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13564 int op, rx, ry, funct, sa;
13565 int16_t imm, offset;
13567 ctx->opcode = (ctx->opcode << 16) | extend;
13568 op = (ctx->opcode >> 11) & 0x1f;
13569 sa = (ctx->opcode >> 22) & 0x1f;
13570 funct = (ctx->opcode >> 8) & 0x7;
13571 rx = xlat((ctx->opcode >> 8) & 0x7);
13572 ry = xlat((ctx->opcode >> 5) & 0x7);
13573 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13574 | ((ctx->opcode >> 21) & 0x3f) << 5
13575 | (ctx->opcode & 0x1f));
13577 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13578 counterparts. */
13579 switch (op) {
13580 case M16_OPC_ADDIUSP:
13581 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13582 break;
13583 case M16_OPC_ADDIUPC:
13584 gen_addiupc(ctx, rx, imm, 0, 1);
13585 break;
13586 case M16_OPC_B:
13587 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13588 /* No delay slot, so just process as a normal instruction */
13589 break;
13590 case M16_OPC_BEQZ:
13591 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13592 /* No delay slot, so just process as a normal instruction */
13593 break;
13594 case M16_OPC_BNEQZ:
13595 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13596 /* No delay slot, so just process as a normal instruction */
13597 break;
13598 case M16_OPC_SHIFT:
13599 switch (ctx->opcode & 0x3) {
13600 case 0x0:
13601 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13602 break;
13603 case 0x1:
13604 #if defined(TARGET_MIPS64)
13605 check_mips_64(ctx);
13606 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13607 #else
13608 generate_exception_end(ctx, EXCP_RI);
13609 #endif
13610 break;
13611 case 0x2:
13612 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13613 break;
13614 case 0x3:
13615 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13616 break;
13618 break;
13619 #if defined(TARGET_MIPS64)
13620 case M16_OPC_LD:
13621 check_insn(ctx, ISA_MIPS3);
13622 check_mips_64(ctx);
13623 gen_ld(ctx, OPC_LD, ry, rx, offset);
13624 break;
13625 #endif
13626 case M16_OPC_RRIA:
13627 imm = ctx->opcode & 0xf;
13628 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13629 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13630 imm = (int16_t) (imm << 1) >> 1;
13631 if ((ctx->opcode >> 4) & 0x1) {
13632 #if defined(TARGET_MIPS64)
13633 check_mips_64(ctx);
13634 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13635 #else
13636 generate_exception_end(ctx, EXCP_RI);
13637 #endif
13638 } else {
13639 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13641 break;
13642 case M16_OPC_ADDIU8:
13643 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13644 break;
13645 case M16_OPC_SLTI:
13646 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13647 break;
13648 case M16_OPC_SLTIU:
13649 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13650 break;
13651 case M16_OPC_I8:
13652 switch (funct) {
13653 case I8_BTEQZ:
13654 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13655 break;
13656 case I8_BTNEZ:
13657 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13658 break;
13659 case I8_SWRASP:
13660 gen_st(ctx, OPC_SW, 31, 29, imm);
13661 break;
13662 case I8_ADJSP:
13663 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13664 break;
13665 case I8_SVRS:
13666 check_insn(ctx, ISA_MIPS32);
13668 int xsregs = (ctx->opcode >> 24) & 0x7;
13669 int aregs = (ctx->opcode >> 16) & 0xf;
13670 int do_ra = (ctx->opcode >> 6) & 0x1;
13671 int do_s0 = (ctx->opcode >> 5) & 0x1;
13672 int do_s1 = (ctx->opcode >> 4) & 0x1;
13673 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13674 | (ctx->opcode & 0xf)) << 3;
13676 if (ctx->opcode & (1 << 7)) {
13677 gen_mips16_save(ctx, xsregs, aregs,
13678 do_ra, do_s0, do_s1,
13679 framesize);
13680 } else {
13681 gen_mips16_restore(ctx, xsregs, aregs,
13682 do_ra, do_s0, do_s1,
13683 framesize);
13686 break;
13687 default:
13688 generate_exception_end(ctx, EXCP_RI);
13689 break;
13691 break;
13692 case M16_OPC_LI:
13693 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13694 break;
13695 case M16_OPC_CMPI:
13696 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13697 break;
13698 #if defined(TARGET_MIPS64)
13699 case M16_OPC_SD:
13700 check_insn(ctx, ISA_MIPS3);
13701 check_mips_64(ctx);
13702 gen_st(ctx, OPC_SD, ry, rx, offset);
13703 break;
13704 #endif
13705 case M16_OPC_LB:
13706 gen_ld(ctx, OPC_LB, ry, rx, offset);
13707 break;
13708 case M16_OPC_LH:
13709 gen_ld(ctx, OPC_LH, ry, rx, offset);
13710 break;
13711 case M16_OPC_LWSP:
13712 gen_ld(ctx, OPC_LW, rx, 29, offset);
13713 break;
13714 case M16_OPC_LW:
13715 gen_ld(ctx, OPC_LW, ry, rx, offset);
13716 break;
13717 case M16_OPC_LBU:
13718 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13719 break;
13720 case M16_OPC_LHU:
13721 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13722 break;
13723 case M16_OPC_LWPC:
13724 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13725 break;
13726 #if defined(TARGET_MIPS64)
13727 case M16_OPC_LWU:
13728 check_insn(ctx, ISA_MIPS3);
13729 check_mips_64(ctx);
13730 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13731 break;
13732 #endif
13733 case M16_OPC_SB:
13734 gen_st(ctx, OPC_SB, ry, rx, offset);
13735 break;
13736 case M16_OPC_SH:
13737 gen_st(ctx, OPC_SH, ry, rx, offset);
13738 break;
13739 case M16_OPC_SWSP:
13740 gen_st(ctx, OPC_SW, rx, 29, offset);
13741 break;
13742 case M16_OPC_SW:
13743 gen_st(ctx, OPC_SW, ry, rx, offset);
13744 break;
13745 #if defined(TARGET_MIPS64)
13746 case M16_OPC_I64:
13747 decode_i64_mips16(ctx, ry, funct, offset, 1);
13748 break;
13749 #endif
13750 default:
13751 generate_exception_end(ctx, EXCP_RI);
13752 break;
13755 return 4;
13758 static inline bool is_uhi(int sdbbp_code)
13760 #ifdef CONFIG_USER_ONLY
13761 return false;
13762 #else
13763 return semihosting_enabled() && sdbbp_code == 1;
13764 #endif
13767 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13769 int rx, ry;
13770 int sa;
13771 int op, cnvt_op, op1, offset;
13772 int funct;
13773 int n_bytes;
13775 op = (ctx->opcode >> 11) & 0x1f;
13776 sa = (ctx->opcode >> 2) & 0x7;
13777 sa = sa == 0 ? 8 : sa;
13778 rx = xlat((ctx->opcode >> 8) & 0x7);
13779 cnvt_op = (ctx->opcode >> 5) & 0x7;
13780 ry = xlat((ctx->opcode >> 5) & 0x7);
13781 op1 = offset = ctx->opcode & 0x1f;
13783 n_bytes = 2;
13785 switch (op) {
13786 case M16_OPC_ADDIUSP:
13788 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13790 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13792 break;
13793 case M16_OPC_ADDIUPC:
13794 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13795 break;
13796 case M16_OPC_B:
13797 offset = (ctx->opcode & 0x7ff) << 1;
13798 offset = (int16_t)(offset << 4) >> 4;
13799 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13800 /* No delay slot, so just process as a normal instruction */
13801 break;
13802 case M16_OPC_JAL:
13803 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13804 offset = (((ctx->opcode & 0x1f) << 21)
13805 | ((ctx->opcode >> 5) & 0x1f) << 16
13806 | offset) << 2;
13807 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13808 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13809 n_bytes = 4;
13810 break;
13811 case M16_OPC_BEQZ:
13812 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13813 ((int8_t)ctx->opcode) << 1, 0);
13814 /* No delay slot, so just process as a normal instruction */
13815 break;
13816 case M16_OPC_BNEQZ:
13817 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13818 ((int8_t)ctx->opcode) << 1, 0);
13819 /* No delay slot, so just process as a normal instruction */
13820 break;
13821 case M16_OPC_SHIFT:
13822 switch (ctx->opcode & 0x3) {
13823 case 0x0:
13824 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13825 break;
13826 case 0x1:
13827 #if defined(TARGET_MIPS64)
13828 check_insn(ctx, ISA_MIPS3);
13829 check_mips_64(ctx);
13830 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13831 #else
13832 generate_exception_end(ctx, EXCP_RI);
13833 #endif
13834 break;
13835 case 0x2:
13836 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13837 break;
13838 case 0x3:
13839 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13840 break;
13842 break;
13843 #if defined(TARGET_MIPS64)
13844 case M16_OPC_LD:
13845 check_insn(ctx, ISA_MIPS3);
13846 check_mips_64(ctx);
13847 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13848 break;
13849 #endif
13850 case M16_OPC_RRIA:
13852 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13854 if ((ctx->opcode >> 4) & 1) {
13855 #if defined(TARGET_MIPS64)
13856 check_insn(ctx, ISA_MIPS3);
13857 check_mips_64(ctx);
13858 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13859 #else
13860 generate_exception_end(ctx, EXCP_RI);
13861 #endif
13862 } else {
13863 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13866 break;
13867 case M16_OPC_ADDIU8:
13869 int16_t imm = (int8_t) ctx->opcode;
13871 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13873 break;
13874 case M16_OPC_SLTI:
13876 int16_t imm = (uint8_t) ctx->opcode;
13877 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13879 break;
13880 case M16_OPC_SLTIU:
13882 int16_t imm = (uint8_t) ctx->opcode;
13883 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13885 break;
13886 case M16_OPC_I8:
13888 int reg32;
13890 funct = (ctx->opcode >> 8) & 0x7;
13891 switch (funct) {
13892 case I8_BTEQZ:
13893 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13894 ((int8_t)ctx->opcode) << 1, 0);
13895 break;
13896 case I8_BTNEZ:
13897 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13898 ((int8_t)ctx->opcode) << 1, 0);
13899 break;
13900 case I8_SWRASP:
13901 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13902 break;
13903 case I8_ADJSP:
13904 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13905 ((int8_t)ctx->opcode) << 3);
13906 break;
13907 case I8_SVRS:
13908 check_insn(ctx, ISA_MIPS32);
13910 int do_ra = ctx->opcode & (1 << 6);
13911 int do_s0 = ctx->opcode & (1 << 5);
13912 int do_s1 = ctx->opcode & (1 << 4);
13913 int framesize = ctx->opcode & 0xf;
13915 if (framesize == 0) {
13916 framesize = 128;
13917 } else {
13918 framesize = framesize << 3;
13921 if (ctx->opcode & (1 << 7)) {
13922 gen_mips16_save(ctx, 0, 0,
13923 do_ra, do_s0, do_s1, framesize);
13924 } else {
13925 gen_mips16_restore(ctx, 0, 0,
13926 do_ra, do_s0, do_s1, framesize);
13929 break;
13930 case I8_MOV32R:
13932 int rz = xlat(ctx->opcode & 0x7);
13934 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13935 ((ctx->opcode >> 5) & 0x7);
13936 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13938 break;
13939 case I8_MOVR32:
13940 reg32 = ctx->opcode & 0x1f;
13941 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13942 break;
13943 default:
13944 generate_exception_end(ctx, EXCP_RI);
13945 break;
13948 break;
13949 case M16_OPC_LI:
13951 int16_t imm = (uint8_t) ctx->opcode;
13953 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13955 break;
13956 case M16_OPC_CMPI:
13958 int16_t imm = (uint8_t) ctx->opcode;
13959 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13961 break;
13962 #if defined(TARGET_MIPS64)
13963 case M16_OPC_SD:
13964 check_insn(ctx, ISA_MIPS3);
13965 check_mips_64(ctx);
13966 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13967 break;
13968 #endif
13969 case M16_OPC_LB:
13970 gen_ld(ctx, OPC_LB, ry, rx, offset);
13971 break;
13972 case M16_OPC_LH:
13973 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13974 break;
13975 case M16_OPC_LWSP:
13976 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13977 break;
13978 case M16_OPC_LW:
13979 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13980 break;
13981 case M16_OPC_LBU:
13982 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13983 break;
13984 case M16_OPC_LHU:
13985 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13986 break;
13987 case M16_OPC_LWPC:
13988 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13989 break;
13990 #if defined (TARGET_MIPS64)
13991 case M16_OPC_LWU:
13992 check_insn(ctx, ISA_MIPS3);
13993 check_mips_64(ctx);
13994 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13995 break;
13996 #endif
13997 case M16_OPC_SB:
13998 gen_st(ctx, OPC_SB, ry, rx, offset);
13999 break;
14000 case M16_OPC_SH:
14001 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14002 break;
14003 case M16_OPC_SWSP:
14004 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14005 break;
14006 case M16_OPC_SW:
14007 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14008 break;
14009 case M16_OPC_RRR:
14011 int rz = xlat((ctx->opcode >> 2) & 0x7);
14012 int mips32_op;
14014 switch (ctx->opcode & 0x3) {
14015 case RRR_ADDU:
14016 mips32_op = OPC_ADDU;
14017 break;
14018 case RRR_SUBU:
14019 mips32_op = OPC_SUBU;
14020 break;
14021 #if defined(TARGET_MIPS64)
14022 case RRR_DADDU:
14023 mips32_op = OPC_DADDU;
14024 check_insn(ctx, ISA_MIPS3);
14025 check_mips_64(ctx);
14026 break;
14027 case RRR_DSUBU:
14028 mips32_op = OPC_DSUBU;
14029 check_insn(ctx, ISA_MIPS3);
14030 check_mips_64(ctx);
14031 break;
14032 #endif
14033 default:
14034 generate_exception_end(ctx, EXCP_RI);
14035 goto done;
14038 gen_arith(ctx, mips32_op, rz, rx, ry);
14039 done:
14042 break;
14043 case M16_OPC_RR:
14044 switch (op1) {
14045 case RR_JR:
14047 int nd = (ctx->opcode >> 7) & 0x1;
14048 int link = (ctx->opcode >> 6) & 0x1;
14049 int ra = (ctx->opcode >> 5) & 0x1;
14051 if (nd) {
14052 check_insn(ctx, ISA_MIPS32);
14055 if (link) {
14056 op = OPC_JALR;
14057 } else {
14058 op = OPC_JR;
14061 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14062 (nd ? 0 : 2));
14064 break;
14065 case RR_SDBBP:
14066 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14067 gen_helper_do_semihosting(cpu_env);
14068 } else {
14069 /* XXX: not clear which exception should be raised
14070 * when in debug mode...
14072 check_insn(ctx, ISA_MIPS32);
14073 generate_exception_end(ctx, EXCP_DBp);
14075 break;
14076 case RR_SLT:
14077 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14078 break;
14079 case RR_SLTU:
14080 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14081 break;
14082 case RR_BREAK:
14083 generate_exception_end(ctx, EXCP_BREAK);
14084 break;
14085 case RR_SLLV:
14086 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14087 break;
14088 case RR_SRLV:
14089 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14090 break;
14091 case RR_SRAV:
14092 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14093 break;
14094 #if defined (TARGET_MIPS64)
14095 case RR_DSRL:
14096 check_insn(ctx, ISA_MIPS3);
14097 check_mips_64(ctx);
14098 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14099 break;
14100 #endif
14101 case RR_CMP:
14102 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14103 break;
14104 case RR_NEG:
14105 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14106 break;
14107 case RR_AND:
14108 gen_logic(ctx, OPC_AND, rx, rx, ry);
14109 break;
14110 case RR_OR:
14111 gen_logic(ctx, OPC_OR, rx, rx, ry);
14112 break;
14113 case RR_XOR:
14114 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14115 break;
14116 case RR_NOT:
14117 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14118 break;
14119 case RR_MFHI:
14120 gen_HILO(ctx, OPC_MFHI, 0, rx);
14121 break;
14122 case RR_CNVT:
14123 check_insn(ctx, ISA_MIPS32);
14124 switch (cnvt_op) {
14125 case RR_RY_CNVT_ZEB:
14126 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14127 break;
14128 case RR_RY_CNVT_ZEH:
14129 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14130 break;
14131 case RR_RY_CNVT_SEB:
14132 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14133 break;
14134 case RR_RY_CNVT_SEH:
14135 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14136 break;
14137 #if defined (TARGET_MIPS64)
14138 case RR_RY_CNVT_ZEW:
14139 check_insn(ctx, ISA_MIPS64);
14140 check_mips_64(ctx);
14141 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14142 break;
14143 case RR_RY_CNVT_SEW:
14144 check_insn(ctx, ISA_MIPS64);
14145 check_mips_64(ctx);
14146 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14147 break;
14148 #endif
14149 default:
14150 generate_exception_end(ctx, EXCP_RI);
14151 break;
14153 break;
14154 case RR_MFLO:
14155 gen_HILO(ctx, OPC_MFLO, 0, rx);
14156 break;
14157 #if defined (TARGET_MIPS64)
14158 case RR_DSRA:
14159 check_insn(ctx, ISA_MIPS3);
14160 check_mips_64(ctx);
14161 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14162 break;
14163 case RR_DSLLV:
14164 check_insn(ctx, ISA_MIPS3);
14165 check_mips_64(ctx);
14166 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14167 break;
14168 case RR_DSRLV:
14169 check_insn(ctx, ISA_MIPS3);
14170 check_mips_64(ctx);
14171 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14172 break;
14173 case RR_DSRAV:
14174 check_insn(ctx, ISA_MIPS3);
14175 check_mips_64(ctx);
14176 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14177 break;
14178 #endif
14179 case RR_MULT:
14180 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14181 break;
14182 case RR_MULTU:
14183 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14184 break;
14185 case RR_DIV:
14186 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14187 break;
14188 case RR_DIVU:
14189 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14190 break;
14191 #if defined (TARGET_MIPS64)
14192 case RR_DMULT:
14193 check_insn(ctx, ISA_MIPS3);
14194 check_mips_64(ctx);
14195 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14196 break;
14197 case RR_DMULTU:
14198 check_insn(ctx, ISA_MIPS3);
14199 check_mips_64(ctx);
14200 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14201 break;
14202 case RR_DDIV:
14203 check_insn(ctx, ISA_MIPS3);
14204 check_mips_64(ctx);
14205 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14206 break;
14207 case RR_DDIVU:
14208 check_insn(ctx, ISA_MIPS3);
14209 check_mips_64(ctx);
14210 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14211 break;
14212 #endif
14213 default:
14214 generate_exception_end(ctx, EXCP_RI);
14215 break;
14217 break;
14218 case M16_OPC_EXTEND:
14219 decode_extended_mips16_opc(env, ctx);
14220 n_bytes = 4;
14221 break;
14222 #if defined(TARGET_MIPS64)
14223 case M16_OPC_I64:
14224 funct = (ctx->opcode >> 8) & 0x7;
14225 decode_i64_mips16(ctx, ry, funct, offset, 0);
14226 break;
14227 #endif
14228 default:
14229 generate_exception_end(ctx, EXCP_RI);
14230 break;
14233 return n_bytes;
14236 /* microMIPS extension to MIPS32/MIPS64 */
14239 * microMIPS32/microMIPS64 major opcodes
14241 * 1. MIPS Architecture for Programmers Volume II-B:
14242 * The microMIPS32 Instruction Set (Revision 3.05)
14244 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14246 * 2. MIPS Architecture For Programmers Volume II-A:
14247 * The MIPS64 Instruction Set (Revision 3.51)
14250 enum {
14251 POOL32A = 0x00,
14252 POOL16A = 0x01,
14253 LBU16 = 0x02,
14254 MOVE16 = 0x03,
14255 ADDI32 = 0x04,
14256 R6_LUI = 0x04,
14257 AUI = 0x04,
14258 LBU32 = 0x05,
14259 SB32 = 0x06,
14260 LB32 = 0x07,
14262 POOL32B = 0x08,
14263 POOL16B = 0x09,
14264 LHU16 = 0x0a,
14265 ANDI16 = 0x0b,
14266 ADDIU32 = 0x0c,
14267 LHU32 = 0x0d,
14268 SH32 = 0x0e,
14269 LH32 = 0x0f,
14271 POOL32I = 0x10,
14272 POOL16C = 0x11,
14273 LWSP16 = 0x12,
14274 POOL16D = 0x13,
14275 ORI32 = 0x14,
14276 POOL32F = 0x15,
14277 POOL32S = 0x16, /* MIPS64 */
14278 DADDIU32 = 0x17, /* MIPS64 */
14280 POOL32C = 0x18,
14281 LWGP16 = 0x19,
14282 LW16 = 0x1a,
14283 POOL16E = 0x1b,
14284 XORI32 = 0x1c,
14285 JALS32 = 0x1d,
14286 BOVC = 0x1d,
14287 BEQC = 0x1d,
14288 BEQZALC = 0x1d,
14289 ADDIUPC = 0x1e,
14290 PCREL = 0x1e,
14291 BNVC = 0x1f,
14292 BNEC = 0x1f,
14293 BNEZALC = 0x1f,
14295 R6_BEQZC = 0x20,
14296 JIC = 0x20,
14297 POOL16F = 0x21,
14298 SB16 = 0x22,
14299 BEQZ16 = 0x23,
14300 BEQZC16 = 0x23,
14301 SLTI32 = 0x24,
14302 BEQ32 = 0x25,
14303 BC = 0x25,
14304 SWC132 = 0x26,
14305 LWC132 = 0x27,
14307 /* 0x29 is reserved */
14308 RES_29 = 0x29,
14309 R6_BNEZC = 0x28,
14310 JIALC = 0x28,
14311 SH16 = 0x2a,
14312 BNEZ16 = 0x2b,
14313 BNEZC16 = 0x2b,
14314 SLTIU32 = 0x2c,
14315 BNE32 = 0x2d,
14316 BALC = 0x2d,
14317 SDC132 = 0x2e,
14318 LDC132 = 0x2f,
14320 /* 0x31 is reserved */
14321 RES_31 = 0x31,
14322 BLEZALC = 0x30,
14323 BGEZALC = 0x30,
14324 BGEUC = 0x30,
14325 SWSP16 = 0x32,
14326 B16 = 0x33,
14327 BC16 = 0x33,
14328 ANDI32 = 0x34,
14329 J32 = 0x35,
14330 BGTZC = 0x35,
14331 BLTZC = 0x35,
14332 BLTC = 0x35,
14333 SD32 = 0x36, /* MIPS64 */
14334 LD32 = 0x37, /* MIPS64 */
14336 /* 0x39 is reserved */
14337 RES_39 = 0x39,
14338 BGTZALC = 0x38,
14339 BLTZALC = 0x38,
14340 BLTUC = 0x38,
14341 SW16 = 0x3a,
14342 LI16 = 0x3b,
14343 JALX32 = 0x3c,
14344 JAL32 = 0x3d,
14345 BLEZC = 0x3d,
14346 BGEZC = 0x3d,
14347 BGEC = 0x3d,
14348 SW32 = 0x3e,
14349 LW32 = 0x3f
14352 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14353 enum {
14354 ADDIUPC_00 = 0x00,
14355 ADDIUPC_01 = 0x01,
14356 ADDIUPC_02 = 0x02,
14357 ADDIUPC_03 = 0x03,
14358 ADDIUPC_04 = 0x04,
14359 ADDIUPC_05 = 0x05,
14360 ADDIUPC_06 = 0x06,
14361 ADDIUPC_07 = 0x07,
14362 AUIPC = 0x1e,
14363 ALUIPC = 0x1f,
14364 LWPC_08 = 0x08,
14365 LWPC_09 = 0x09,
14366 LWPC_0A = 0x0A,
14367 LWPC_0B = 0x0B,
14368 LWPC_0C = 0x0C,
14369 LWPC_0D = 0x0D,
14370 LWPC_0E = 0x0E,
14371 LWPC_0F = 0x0F,
14374 /* POOL32A encoding of minor opcode field */
14376 enum {
14377 /* These opcodes are distinguished only by bits 9..6; those bits are
14378 * what are recorded below. */
14379 SLL32 = 0x0,
14380 SRL32 = 0x1,
14381 SRA = 0x2,
14382 ROTR = 0x3,
14383 SELEQZ = 0x5,
14384 SELNEZ = 0x6,
14385 R6_RDHWR = 0x7,
14387 SLLV = 0x0,
14388 SRLV = 0x1,
14389 SRAV = 0x2,
14390 ROTRV = 0x3,
14391 ADD = 0x4,
14392 ADDU32 = 0x5,
14393 SUB = 0x6,
14394 SUBU32 = 0x7,
14395 MUL = 0x8,
14396 AND = 0x9,
14397 OR32 = 0xa,
14398 NOR = 0xb,
14399 XOR32 = 0xc,
14400 SLT = 0xd,
14401 SLTU = 0xe,
14403 MOVN = 0x0,
14404 R6_MUL = 0x0,
14405 MOVZ = 0x1,
14406 MUH = 0x1,
14407 MULU = 0x2,
14408 MUHU = 0x3,
14409 LWXS = 0x4,
14410 R6_DIV = 0x4,
14411 MOD = 0x5,
14412 R6_DIVU = 0x6,
14413 MODU = 0x7,
14415 /* The following can be distinguished by their lower 6 bits. */
14416 BREAK32 = 0x07,
14417 INS = 0x0c,
14418 LSA = 0x0f,
14419 ALIGN = 0x1f,
14420 EXT = 0x2c,
14421 POOL32AXF = 0x3c,
14422 SIGRIE = 0x3f
14425 /* POOL32AXF encoding of minor opcode field extension */
14428 * 1. MIPS Architecture for Programmers Volume II-B:
14429 * The microMIPS32 Instruction Set (Revision 3.05)
14431 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14433 * 2. MIPS Architecture for Programmers VolumeIV-e:
14434 * The MIPS DSP Application-Specific Extension
14435 * to the microMIPS32 Architecture (Revision 2.34)
14437 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14440 enum {
14441 /* bits 11..6 */
14442 TEQ = 0x00,
14443 TGE = 0x08,
14444 TGEU = 0x10,
14445 TLT = 0x20,
14446 TLTU = 0x28,
14447 TNE = 0x30,
14449 MFC0 = 0x03,
14450 MTC0 = 0x0b,
14452 /* begin of microMIPS32 DSP */
14454 /* bits 13..12 for 0x01 */
14455 MFHI_ACC = 0x0,
14456 MFLO_ACC = 0x1,
14457 MTHI_ACC = 0x2,
14458 MTLO_ACC = 0x3,
14460 /* bits 13..12 for 0x2a */
14461 MADD_ACC = 0x0,
14462 MADDU_ACC = 0x1,
14463 MSUB_ACC = 0x2,
14464 MSUBU_ACC = 0x3,
14466 /* bits 13..12 for 0x32 */
14467 MULT_ACC = 0x0,
14468 MULTU_ACC = 0x1,
14470 /* end of microMIPS32 DSP */
14472 /* bits 15..12 for 0x2c */
14473 BITSWAP = 0x0,
14474 SEB = 0x2,
14475 SEH = 0x3,
14476 CLO = 0x4,
14477 CLZ = 0x5,
14478 RDHWR = 0x6,
14479 WSBH = 0x7,
14480 MULT = 0x8,
14481 MULTU = 0x9,
14482 DIV = 0xa,
14483 DIVU = 0xb,
14484 MADD = 0xc,
14485 MADDU = 0xd,
14486 MSUB = 0xe,
14487 MSUBU = 0xf,
14489 /* bits 15..12 for 0x34 */
14490 MFC2 = 0x4,
14491 MTC2 = 0x5,
14492 MFHC2 = 0x8,
14493 MTHC2 = 0x9,
14494 CFC2 = 0xc,
14495 CTC2 = 0xd,
14497 /* bits 15..12 for 0x3c */
14498 JALR = 0x0,
14499 JR = 0x0, /* alias */
14500 JALRC = 0x0,
14501 JRC = 0x0,
14502 JALR_HB = 0x1,
14503 JALRC_HB = 0x1,
14504 JALRS = 0x4,
14505 JALRS_HB = 0x5,
14507 /* bits 15..12 for 0x05 */
14508 RDPGPR = 0xe,
14509 WRPGPR = 0xf,
14511 /* bits 15..12 for 0x0d */
14512 TLBP = 0x0,
14513 TLBR = 0x1,
14514 TLBWI = 0x2,
14515 TLBWR = 0x3,
14516 TLBINV = 0x4,
14517 TLBINVF = 0x5,
14518 WAIT = 0x9,
14519 IRET = 0xd,
14520 DERET = 0xe,
14521 ERET = 0xf,
14523 /* bits 15..12 for 0x15 */
14524 DMT = 0x0,
14525 DVPE = 0x1,
14526 EMT = 0x2,
14527 EVPE = 0x3,
14529 /* bits 15..12 for 0x1d */
14530 DI = 0x4,
14531 EI = 0x5,
14533 /* bits 15..12 for 0x2d */
14534 SYNC = 0x6,
14535 SYSCALL = 0x8,
14536 SDBBP = 0xd,
14538 /* bits 15..12 for 0x35 */
14539 MFHI32 = 0x0,
14540 MFLO32 = 0x1,
14541 MTHI32 = 0x2,
14542 MTLO32 = 0x3,
14545 /* POOL32B encoding of minor opcode field (bits 15..12) */
14547 enum {
14548 LWC2 = 0x0,
14549 LWP = 0x1,
14550 LDP = 0x4,
14551 LWM32 = 0x5,
14552 CACHE = 0x6,
14553 LDM = 0x7,
14554 SWC2 = 0x8,
14555 SWP = 0x9,
14556 SDP = 0xc,
14557 SWM32 = 0xd,
14558 SDM = 0xf
14561 /* POOL32C encoding of minor opcode field (bits 15..12) */
14563 enum {
14564 LWL = 0x0,
14565 SWL = 0x8,
14566 LWR = 0x1,
14567 SWR = 0x9,
14568 PREF = 0x2,
14569 ST_EVA = 0xa,
14570 LL = 0x3,
14571 SC = 0xb,
14572 LDL = 0x4,
14573 SDL = 0xc,
14574 LDR = 0x5,
14575 SDR = 0xd,
14576 LD_EVA = 0x6,
14577 LWU = 0xe,
14578 LLD = 0x7,
14579 SCD = 0xf
14582 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14584 enum {
14585 LBUE = 0x0,
14586 LHUE = 0x1,
14587 LWLE = 0x2,
14588 LWRE = 0x3,
14589 LBE = 0x4,
14590 LHE = 0x5,
14591 LLE = 0x6,
14592 LWE = 0x7,
14595 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14597 enum {
14598 SWLE = 0x0,
14599 SWRE = 0x1,
14600 PREFE = 0x2,
14601 CACHEE = 0x3,
14602 SBE = 0x4,
14603 SHE = 0x5,
14604 SCE = 0x6,
14605 SWE = 0x7,
14608 /* POOL32F encoding of minor opcode field (bits 5..0) */
14610 enum {
14611 /* These are the bit 7..6 values */
14612 ADD_FMT = 0x0,
14614 SUB_FMT = 0x1,
14616 MUL_FMT = 0x2,
14618 DIV_FMT = 0x3,
14620 /* These are the bit 8..6 values */
14621 MOVN_FMT = 0x0,
14622 RSQRT2_FMT = 0x0,
14623 MOVF_FMT = 0x0,
14624 RINT_FMT = 0x0,
14625 SELNEZ_FMT = 0x0,
14627 MOVZ_FMT = 0x1,
14628 LWXC1 = 0x1,
14629 MOVT_FMT = 0x1,
14630 CLASS_FMT = 0x1,
14631 SELEQZ_FMT = 0x1,
14633 PLL_PS = 0x2,
14634 SWXC1 = 0x2,
14635 SEL_FMT = 0x2,
14637 PLU_PS = 0x3,
14638 LDXC1 = 0x3,
14640 MOVN_FMT_04 = 0x4,
14641 PUL_PS = 0x4,
14642 SDXC1 = 0x4,
14643 RECIP2_FMT = 0x4,
14645 MOVZ_FMT_05 = 0x05,
14646 PUU_PS = 0x5,
14647 LUXC1 = 0x5,
14649 CVT_PS_S = 0x6,
14650 SUXC1 = 0x6,
14651 ADDR_PS = 0x6,
14652 PREFX = 0x6,
14653 MADDF_FMT = 0x6,
14655 MULR_PS = 0x7,
14656 MSUBF_FMT = 0x7,
14658 MADD_S = 0x01,
14659 MADD_D = 0x09,
14660 MADD_PS = 0x11,
14661 ALNV_PS = 0x19,
14662 MSUB_S = 0x21,
14663 MSUB_D = 0x29,
14664 MSUB_PS = 0x31,
14666 NMADD_S = 0x02,
14667 NMADD_D = 0x0a,
14668 NMADD_PS = 0x12,
14669 NMSUB_S = 0x22,
14670 NMSUB_D = 0x2a,
14671 NMSUB_PS = 0x32,
14673 MIN_FMT = 0x3,
14674 MAX_FMT = 0xb,
14675 MINA_FMT = 0x23,
14676 MAXA_FMT = 0x2b,
14677 POOL32FXF = 0x3b,
14679 CABS_COND_FMT = 0x1c, /* MIPS3D */
14680 C_COND_FMT = 0x3c,
14682 CMP_CONDN_S = 0x5,
14683 CMP_CONDN_D = 0x15
14686 /* POOL32Fxf encoding of minor opcode extension field */
14688 enum {
14689 CVT_L = 0x04,
14690 RSQRT_FMT = 0x08,
14691 FLOOR_L = 0x0c,
14692 CVT_PW_PS = 0x1c,
14693 CVT_W = 0x24,
14694 SQRT_FMT = 0x28,
14695 FLOOR_W = 0x2c,
14696 CVT_PS_PW = 0x3c,
14697 CFC1 = 0x40,
14698 RECIP_FMT = 0x48,
14699 CEIL_L = 0x4c,
14700 CTC1 = 0x60,
14701 CEIL_W = 0x6c,
14702 MFC1 = 0x80,
14703 CVT_S_PL = 0x84,
14704 TRUNC_L = 0x8c,
14705 MTC1 = 0xa0,
14706 CVT_S_PU = 0xa4,
14707 TRUNC_W = 0xac,
14708 MFHC1 = 0xc0,
14709 ROUND_L = 0xcc,
14710 MTHC1 = 0xe0,
14711 ROUND_W = 0xec,
14713 MOV_FMT = 0x01,
14714 MOVF = 0x05,
14715 ABS_FMT = 0x0d,
14716 RSQRT1_FMT = 0x1d,
14717 MOVT = 0x25,
14718 NEG_FMT = 0x2d,
14719 CVT_D = 0x4d,
14720 RECIP1_FMT = 0x5d,
14721 CVT_S = 0x6d
14724 /* POOL32I encoding of minor opcode field (bits 25..21) */
14726 enum {
14727 BLTZ = 0x00,
14728 BLTZAL = 0x01,
14729 BGEZ = 0x02,
14730 BGEZAL = 0x03,
14731 BLEZ = 0x04,
14732 BNEZC = 0x05,
14733 BGTZ = 0x06,
14734 BEQZC = 0x07,
14735 TLTI = 0x08,
14736 BC1EQZC = 0x08,
14737 TGEI = 0x09,
14738 BC1NEZC = 0x09,
14739 TLTIU = 0x0a,
14740 BC2EQZC = 0x0a,
14741 TGEIU = 0x0b,
14742 BC2NEZC = 0x0a,
14743 TNEI = 0x0c,
14744 R6_SYNCI = 0x0c,
14745 LUI = 0x0d,
14746 TEQI = 0x0e,
14747 SYNCI = 0x10,
14748 BLTZALS = 0x11,
14749 BGEZALS = 0x13,
14750 BC2F = 0x14,
14751 BC2T = 0x15,
14752 BPOSGE64 = 0x1a,
14753 BPOSGE32 = 0x1b,
14754 /* These overlap and are distinguished by bit16 of the instruction */
14755 BC1F = 0x1c,
14756 BC1T = 0x1d,
14757 BC1ANY2F = 0x1c,
14758 BC1ANY2T = 0x1d,
14759 BC1ANY4F = 0x1e,
14760 BC1ANY4T = 0x1f
14763 /* POOL16A encoding of minor opcode field */
14765 enum {
14766 ADDU16 = 0x0,
14767 SUBU16 = 0x1
14770 /* POOL16B encoding of minor opcode field */
14772 enum {
14773 SLL16 = 0x0,
14774 SRL16 = 0x1
14777 /* POOL16C encoding of minor opcode field */
14779 enum {
14780 NOT16 = 0x00,
14781 XOR16 = 0x04,
14782 AND16 = 0x08,
14783 OR16 = 0x0c,
14784 LWM16 = 0x10,
14785 SWM16 = 0x14,
14786 JR16 = 0x18,
14787 JRC16 = 0x1a,
14788 JALR16 = 0x1c,
14789 JALR16S = 0x1e,
14790 MFHI16 = 0x20,
14791 MFLO16 = 0x24,
14792 BREAK16 = 0x28,
14793 SDBBP16 = 0x2c,
14794 JRADDIUSP = 0x30
14797 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14799 enum {
14800 R6_NOT16 = 0x00,
14801 R6_AND16 = 0x01,
14802 R6_LWM16 = 0x02,
14803 R6_JRC16 = 0x03,
14804 MOVEP = 0x04,
14805 MOVEP_05 = 0x05,
14806 MOVEP_06 = 0x06,
14807 MOVEP_07 = 0x07,
14808 R6_XOR16 = 0x08,
14809 R6_OR16 = 0x09,
14810 R6_SWM16 = 0x0a,
14811 JALRC16 = 0x0b,
14812 MOVEP_0C = 0x0c,
14813 MOVEP_0D = 0x0d,
14814 MOVEP_0E = 0x0e,
14815 MOVEP_0F = 0x0f,
14816 JRCADDIUSP = 0x13,
14817 R6_BREAK16 = 0x1b,
14818 R6_SDBBP16 = 0x3b
14821 /* POOL16D encoding of minor opcode field */
14823 enum {
14824 ADDIUS5 = 0x0,
14825 ADDIUSP = 0x1
14828 /* POOL16E encoding of minor opcode field */
14830 enum {
14831 ADDIUR2 = 0x0,
14832 ADDIUR1SP = 0x1
14835 static int mmreg (int r)
14837 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14839 return map[r];
14842 /* Used for 16-bit store instructions. */
14843 static int mmreg2 (int r)
14845 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14847 return map[r];
14850 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14851 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14852 #define uMIPS_RS2(op) uMIPS_RS(op)
14853 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14854 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14855 #define uMIPS_RS5(op) (op & 0x1f)
14857 /* Signed immediate */
14858 #define SIMM(op, start, width) \
14859 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14860 << (32-width)) \
14861 >> (32-width))
14862 /* Zero-extended immediate */
14863 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14865 static void gen_addiur1sp(DisasContext *ctx)
14867 int rd = mmreg(uMIPS_RD(ctx->opcode));
14869 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14872 static void gen_addiur2(DisasContext *ctx)
14874 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14875 int rd = mmreg(uMIPS_RD(ctx->opcode));
14876 int rs = mmreg(uMIPS_RS(ctx->opcode));
14878 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14881 static void gen_addiusp(DisasContext *ctx)
14883 int encoded = ZIMM(ctx->opcode, 1, 9);
14884 int decoded;
14886 if (encoded <= 1) {
14887 decoded = 256 + encoded;
14888 } else if (encoded <= 255) {
14889 decoded = encoded;
14890 } else if (encoded <= 509) {
14891 decoded = encoded - 512;
14892 } else {
14893 decoded = encoded - 768;
14896 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14899 static void gen_addius5(DisasContext *ctx)
14901 int imm = SIMM(ctx->opcode, 1, 4);
14902 int rd = (ctx->opcode >> 5) & 0x1f;
14904 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14907 static void gen_andi16(DisasContext *ctx)
14909 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14910 31, 32, 63, 64, 255, 32768, 65535 };
14911 int rd = mmreg(uMIPS_RD(ctx->opcode));
14912 int rs = mmreg(uMIPS_RS(ctx->opcode));
14913 int encoded = ZIMM(ctx->opcode, 0, 4);
14915 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14918 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14919 int base, int16_t offset)
14921 TCGv t0, t1;
14922 TCGv_i32 t2;
14924 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14925 generate_exception_end(ctx, EXCP_RI);
14926 return;
14929 t0 = tcg_temp_new();
14931 gen_base_offset_addr(ctx, t0, base, offset);
14933 t1 = tcg_const_tl(reglist);
14934 t2 = tcg_const_i32(ctx->mem_idx);
14936 save_cpu_state(ctx, 1);
14937 switch (opc) {
14938 case LWM32:
14939 gen_helper_lwm(cpu_env, t0, t1, t2);
14940 break;
14941 case SWM32:
14942 gen_helper_swm(cpu_env, t0, t1, t2);
14943 break;
14944 #ifdef TARGET_MIPS64
14945 case LDM:
14946 gen_helper_ldm(cpu_env, t0, t1, t2);
14947 break;
14948 case SDM:
14949 gen_helper_sdm(cpu_env, t0, t1, t2);
14950 break;
14951 #endif
14953 tcg_temp_free(t0);
14954 tcg_temp_free(t1);
14955 tcg_temp_free_i32(t2);
14959 static void gen_pool16c_insn(DisasContext *ctx)
14961 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14962 int rs = mmreg(ctx->opcode & 0x7);
14964 switch (((ctx->opcode) >> 4) & 0x3f) {
14965 case NOT16 + 0:
14966 case NOT16 + 1:
14967 case NOT16 + 2:
14968 case NOT16 + 3:
14969 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14970 break;
14971 case XOR16 + 0:
14972 case XOR16 + 1:
14973 case XOR16 + 2:
14974 case XOR16 + 3:
14975 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14976 break;
14977 case AND16 + 0:
14978 case AND16 + 1:
14979 case AND16 + 2:
14980 case AND16 + 3:
14981 gen_logic(ctx, OPC_AND, rd, rd, rs);
14982 break;
14983 case OR16 + 0:
14984 case OR16 + 1:
14985 case OR16 + 2:
14986 case OR16 + 3:
14987 gen_logic(ctx, OPC_OR, rd, rd, rs);
14988 break;
14989 case LWM16 + 0:
14990 case LWM16 + 1:
14991 case LWM16 + 2:
14992 case LWM16 + 3:
14994 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14995 int offset = ZIMM(ctx->opcode, 0, 4);
14997 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14998 29, offset << 2);
15000 break;
15001 case SWM16 + 0:
15002 case SWM16 + 1:
15003 case SWM16 + 2:
15004 case SWM16 + 3:
15006 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15007 int offset = ZIMM(ctx->opcode, 0, 4);
15009 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15010 29, offset << 2);
15012 break;
15013 case JR16 + 0:
15014 case JR16 + 1:
15016 int reg = ctx->opcode & 0x1f;
15018 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15020 break;
15021 case JRC16 + 0:
15022 case JRC16 + 1:
15024 int reg = ctx->opcode & 0x1f;
15025 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15026 /* Let normal delay slot handling in our caller take us
15027 to the branch target. */
15029 break;
15030 case JALR16 + 0:
15031 case JALR16 + 1:
15032 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15033 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15034 break;
15035 case JALR16S + 0:
15036 case JALR16S + 1:
15037 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15038 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15039 break;
15040 case MFHI16 + 0:
15041 case MFHI16 + 1:
15042 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15043 break;
15044 case MFLO16 + 0:
15045 case MFLO16 + 1:
15046 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15047 break;
15048 case BREAK16:
15049 generate_exception_end(ctx, EXCP_BREAK);
15050 break;
15051 case SDBBP16:
15052 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15053 gen_helper_do_semihosting(cpu_env);
15054 } else {
15055 /* XXX: not clear which exception should be raised
15056 * when in debug mode...
15058 check_insn(ctx, ISA_MIPS32);
15059 generate_exception_end(ctx, EXCP_DBp);
15061 break;
15062 case JRADDIUSP + 0:
15063 case JRADDIUSP + 1:
15065 int imm = ZIMM(ctx->opcode, 0, 5);
15066 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15067 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15068 /* Let normal delay slot handling in our caller take us
15069 to the branch target. */
15071 break;
15072 default:
15073 generate_exception_end(ctx, EXCP_RI);
15074 break;
15078 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15079 int enc_rs)
15081 int rd, rs, re, rt;
15082 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15083 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15084 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15085 rd = rd_enc[enc_dest];
15086 re = re_enc[enc_dest];
15087 rs = rs_rt_enc[enc_rs];
15088 rt = rs_rt_enc[enc_rt];
15089 if (rs) {
15090 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15091 } else {
15092 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15094 if (rt) {
15095 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15096 } else {
15097 tcg_gen_movi_tl(cpu_gpr[re], 0);
15101 static void gen_pool16c_r6_insn(DisasContext *ctx)
15103 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15104 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15106 switch (ctx->opcode & 0xf) {
15107 case R6_NOT16:
15108 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15109 break;
15110 case R6_AND16:
15111 gen_logic(ctx, OPC_AND, rt, rt, rs);
15112 break;
15113 case R6_LWM16:
15115 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15116 int offset = extract32(ctx->opcode, 4, 4);
15117 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15119 break;
15120 case R6_JRC16: /* JRCADDIUSP */
15121 if ((ctx->opcode >> 4) & 1) {
15122 /* JRCADDIUSP */
15123 int imm = extract32(ctx->opcode, 5, 5);
15124 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15125 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15126 } else {
15127 /* JRC16 */
15128 rs = extract32(ctx->opcode, 5, 5);
15129 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15131 break;
15132 case MOVEP:
15133 case MOVEP_05:
15134 case MOVEP_06:
15135 case MOVEP_07:
15136 case MOVEP_0C:
15137 case MOVEP_0D:
15138 case MOVEP_0E:
15139 case MOVEP_0F:
15141 int enc_dest = uMIPS_RD(ctx->opcode);
15142 int enc_rt = uMIPS_RS2(ctx->opcode);
15143 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15144 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15146 break;
15147 case R6_XOR16:
15148 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15149 break;
15150 case R6_OR16:
15151 gen_logic(ctx, OPC_OR, rt, rt, rs);
15152 break;
15153 case R6_SWM16:
15155 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15156 int offset = extract32(ctx->opcode, 4, 4);
15157 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15159 break;
15160 case JALRC16: /* BREAK16, SDBBP16 */
15161 switch (ctx->opcode & 0x3f) {
15162 case JALRC16:
15163 case JALRC16 + 0x20:
15164 /* JALRC16 */
15165 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15166 31, 0, 0);
15167 break;
15168 case R6_BREAK16:
15169 /* BREAK16 */
15170 generate_exception(ctx, EXCP_BREAK);
15171 break;
15172 case R6_SDBBP16:
15173 /* SDBBP16 */
15174 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15175 gen_helper_do_semihosting(cpu_env);
15176 } else {
15177 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15178 generate_exception(ctx, EXCP_RI);
15179 } else {
15180 generate_exception(ctx, EXCP_DBp);
15183 break;
15185 break;
15186 default:
15187 generate_exception(ctx, EXCP_RI);
15188 break;
15192 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
15194 TCGv t0 = tcg_temp_new();
15195 TCGv t1 = tcg_temp_new();
15197 gen_load_gpr(t0, base);
15199 if (index != 0) {
15200 gen_load_gpr(t1, index);
15201 tcg_gen_shli_tl(t1, t1, 2);
15202 gen_op_addr_add(ctx, t0, t1, t0);
15205 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15206 gen_store_gpr(t1, rd);
15208 tcg_temp_free(t0);
15209 tcg_temp_free(t1);
15212 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
15213 int base, int16_t offset)
15215 TCGv t0, t1;
15217 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15218 generate_exception_end(ctx, EXCP_RI);
15219 return;
15222 t0 = tcg_temp_new();
15223 t1 = tcg_temp_new();
15225 gen_base_offset_addr(ctx, t0, base, offset);
15227 switch (opc) {
15228 case LWP:
15229 if (rd == base) {
15230 generate_exception_end(ctx, EXCP_RI);
15231 return;
15233 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15234 gen_store_gpr(t1, rd);
15235 tcg_gen_movi_tl(t1, 4);
15236 gen_op_addr_add(ctx, t0, t0, t1);
15237 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15238 gen_store_gpr(t1, rd+1);
15239 break;
15240 case SWP:
15241 gen_load_gpr(t1, rd);
15242 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15243 tcg_gen_movi_tl(t1, 4);
15244 gen_op_addr_add(ctx, t0, t0, t1);
15245 gen_load_gpr(t1, rd+1);
15246 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15247 break;
15248 #ifdef TARGET_MIPS64
15249 case LDP:
15250 if (rd == base) {
15251 generate_exception_end(ctx, EXCP_RI);
15252 return;
15254 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15255 gen_store_gpr(t1, rd);
15256 tcg_gen_movi_tl(t1, 8);
15257 gen_op_addr_add(ctx, t0, t0, t1);
15258 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15259 gen_store_gpr(t1, rd+1);
15260 break;
15261 case SDP:
15262 gen_load_gpr(t1, rd);
15263 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15264 tcg_gen_movi_tl(t1, 8);
15265 gen_op_addr_add(ctx, t0, t0, t1);
15266 gen_load_gpr(t1, rd+1);
15267 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15268 break;
15269 #endif
15271 tcg_temp_free(t0);
15272 tcg_temp_free(t1);
15275 static void gen_sync(int stype)
15277 TCGBar tcg_mo = TCG_BAR_SC;
15279 switch (stype) {
15280 case 0x4: /* SYNC_WMB */
15281 tcg_mo |= TCG_MO_ST_ST;
15282 break;
15283 case 0x10: /* SYNC_MB */
15284 tcg_mo |= TCG_MO_ALL;
15285 break;
15286 case 0x11: /* SYNC_ACQUIRE */
15287 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15288 break;
15289 case 0x12: /* SYNC_RELEASE */
15290 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15291 break;
15292 case 0x13: /* SYNC_RMB */
15293 tcg_mo |= TCG_MO_LD_LD;
15294 break;
15295 default:
15296 tcg_mo |= TCG_MO_ALL;
15297 break;
15300 tcg_gen_mb(tcg_mo);
15303 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15305 int extension = (ctx->opcode >> 6) & 0x3f;
15306 int minor = (ctx->opcode >> 12) & 0xf;
15307 uint32_t mips32_op;
15309 switch (extension) {
15310 case TEQ:
15311 mips32_op = OPC_TEQ;
15312 goto do_trap;
15313 case TGE:
15314 mips32_op = OPC_TGE;
15315 goto do_trap;
15316 case TGEU:
15317 mips32_op = OPC_TGEU;
15318 goto do_trap;
15319 case TLT:
15320 mips32_op = OPC_TLT;
15321 goto do_trap;
15322 case TLTU:
15323 mips32_op = OPC_TLTU;
15324 goto do_trap;
15325 case TNE:
15326 mips32_op = OPC_TNE;
15327 do_trap:
15328 gen_trap(ctx, mips32_op, rs, rt, -1);
15329 break;
15330 #ifndef CONFIG_USER_ONLY
15331 case MFC0:
15332 case MFC0 + 32:
15333 check_cp0_enabled(ctx);
15334 if (rt == 0) {
15335 /* Treat as NOP. */
15336 break;
15338 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15339 break;
15340 case MTC0:
15341 case MTC0 + 32:
15342 check_cp0_enabled(ctx);
15344 TCGv t0 = tcg_temp_new();
15346 gen_load_gpr(t0, rt);
15347 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15348 tcg_temp_free(t0);
15350 break;
15351 #endif
15352 case 0x2a:
15353 switch (minor & 3) {
15354 case MADD_ACC:
15355 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15356 break;
15357 case MADDU_ACC:
15358 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15359 break;
15360 case MSUB_ACC:
15361 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15362 break;
15363 case MSUBU_ACC:
15364 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15365 break;
15366 default:
15367 goto pool32axf_invalid;
15369 break;
15370 case 0x32:
15371 switch (minor & 3) {
15372 case MULT_ACC:
15373 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15374 break;
15375 case MULTU_ACC:
15376 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15377 break;
15378 default:
15379 goto pool32axf_invalid;
15381 break;
15382 case 0x2c:
15383 switch (minor) {
15384 case BITSWAP:
15385 check_insn(ctx, ISA_MIPS32R6);
15386 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15387 break;
15388 case SEB:
15389 gen_bshfl(ctx, OPC_SEB, rs, rt);
15390 break;
15391 case SEH:
15392 gen_bshfl(ctx, OPC_SEH, rs, rt);
15393 break;
15394 case CLO:
15395 mips32_op = OPC_CLO;
15396 goto do_cl;
15397 case CLZ:
15398 mips32_op = OPC_CLZ;
15399 do_cl:
15400 check_insn(ctx, ISA_MIPS32);
15401 gen_cl(ctx, mips32_op, rt, rs);
15402 break;
15403 case RDHWR:
15404 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15405 gen_rdhwr(ctx, rt, rs, 0);
15406 break;
15407 case WSBH:
15408 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15409 break;
15410 case MULT:
15411 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15412 mips32_op = OPC_MULT;
15413 goto do_mul;
15414 case MULTU:
15415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15416 mips32_op = OPC_MULTU;
15417 goto do_mul;
15418 case DIV:
15419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15420 mips32_op = OPC_DIV;
15421 goto do_div;
15422 case DIVU:
15423 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15424 mips32_op = OPC_DIVU;
15425 goto do_div;
15426 do_div:
15427 check_insn(ctx, ISA_MIPS32);
15428 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15429 break;
15430 case MADD:
15431 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15432 mips32_op = OPC_MADD;
15433 goto do_mul;
15434 case MADDU:
15435 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15436 mips32_op = OPC_MADDU;
15437 goto do_mul;
15438 case MSUB:
15439 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15440 mips32_op = OPC_MSUB;
15441 goto do_mul;
15442 case MSUBU:
15443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15444 mips32_op = OPC_MSUBU;
15445 do_mul:
15446 check_insn(ctx, ISA_MIPS32);
15447 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15448 break;
15449 default:
15450 goto pool32axf_invalid;
15452 break;
15453 case 0x34:
15454 switch (minor) {
15455 case MFC2:
15456 case MTC2:
15457 case MFHC2:
15458 case MTHC2:
15459 case CFC2:
15460 case CTC2:
15461 generate_exception_err(ctx, EXCP_CpU, 2);
15462 break;
15463 default:
15464 goto pool32axf_invalid;
15466 break;
15467 case 0x3c:
15468 switch (minor) {
15469 case JALR: /* JALRC */
15470 case JALR_HB: /* JALRC_HB */
15471 if (ctx->insn_flags & ISA_MIPS32R6) {
15472 /* JALRC, JALRC_HB */
15473 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15474 } else {
15475 /* JALR, JALR_HB */
15476 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15477 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15479 break;
15480 case JALRS:
15481 case JALRS_HB:
15482 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15483 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15484 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15485 break;
15486 default:
15487 goto pool32axf_invalid;
15489 break;
15490 case 0x05:
15491 switch (minor) {
15492 case RDPGPR:
15493 check_cp0_enabled(ctx);
15494 check_insn(ctx, ISA_MIPS32R2);
15495 gen_load_srsgpr(rs, rt);
15496 break;
15497 case WRPGPR:
15498 check_cp0_enabled(ctx);
15499 check_insn(ctx, ISA_MIPS32R2);
15500 gen_store_srsgpr(rs, rt);
15501 break;
15502 default:
15503 goto pool32axf_invalid;
15505 break;
15506 #ifndef CONFIG_USER_ONLY
15507 case 0x0d:
15508 switch (minor) {
15509 case TLBP:
15510 mips32_op = OPC_TLBP;
15511 goto do_cp0;
15512 case TLBR:
15513 mips32_op = OPC_TLBR;
15514 goto do_cp0;
15515 case TLBWI:
15516 mips32_op = OPC_TLBWI;
15517 goto do_cp0;
15518 case TLBWR:
15519 mips32_op = OPC_TLBWR;
15520 goto do_cp0;
15521 case TLBINV:
15522 mips32_op = OPC_TLBINV;
15523 goto do_cp0;
15524 case TLBINVF:
15525 mips32_op = OPC_TLBINVF;
15526 goto do_cp0;
15527 case WAIT:
15528 mips32_op = OPC_WAIT;
15529 goto do_cp0;
15530 case DERET:
15531 mips32_op = OPC_DERET;
15532 goto do_cp0;
15533 case ERET:
15534 mips32_op = OPC_ERET;
15535 do_cp0:
15536 gen_cp0(env, ctx, mips32_op, rt, rs);
15537 break;
15538 default:
15539 goto pool32axf_invalid;
15541 break;
15542 case 0x1d:
15543 switch (minor) {
15544 case DI:
15545 check_cp0_enabled(ctx);
15547 TCGv t0 = tcg_temp_new();
15549 save_cpu_state(ctx, 1);
15550 gen_helper_di(t0, cpu_env);
15551 gen_store_gpr(t0, rs);
15552 /* Stop translation as we may have switched the execution mode */
15553 ctx->base.is_jmp = DISAS_STOP;
15554 tcg_temp_free(t0);
15556 break;
15557 case EI:
15558 check_cp0_enabled(ctx);
15560 TCGv t0 = tcg_temp_new();
15562 save_cpu_state(ctx, 1);
15563 gen_helper_ei(t0, cpu_env);
15564 gen_store_gpr(t0, rs);
15565 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15566 of translated code to check for pending interrupts. */
15567 gen_save_pc(ctx->base.pc_next + 4);
15568 ctx->base.is_jmp = DISAS_EXIT;
15569 tcg_temp_free(t0);
15571 break;
15572 default:
15573 goto pool32axf_invalid;
15575 break;
15576 #endif
15577 case 0x2d:
15578 switch (minor) {
15579 case SYNC:
15580 gen_sync(extract32(ctx->opcode, 16, 5));
15581 break;
15582 case SYSCALL:
15583 generate_exception_end(ctx, EXCP_SYSCALL);
15584 break;
15585 case SDBBP:
15586 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15587 gen_helper_do_semihosting(cpu_env);
15588 } else {
15589 check_insn(ctx, ISA_MIPS32);
15590 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15591 generate_exception_end(ctx, EXCP_RI);
15592 } else {
15593 generate_exception_end(ctx, EXCP_DBp);
15596 break;
15597 default:
15598 goto pool32axf_invalid;
15600 break;
15601 case 0x01:
15602 switch (minor & 3) {
15603 case MFHI_ACC:
15604 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15605 break;
15606 case MFLO_ACC:
15607 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15608 break;
15609 case MTHI_ACC:
15610 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15611 break;
15612 case MTLO_ACC:
15613 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15614 break;
15615 default:
15616 goto pool32axf_invalid;
15618 break;
15619 case 0x35:
15620 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15621 switch (minor) {
15622 case MFHI32:
15623 gen_HILO(ctx, OPC_MFHI, 0, rs);
15624 break;
15625 case MFLO32:
15626 gen_HILO(ctx, OPC_MFLO, 0, rs);
15627 break;
15628 case MTHI32:
15629 gen_HILO(ctx, OPC_MTHI, 0, rs);
15630 break;
15631 case MTLO32:
15632 gen_HILO(ctx, OPC_MTLO, 0, rs);
15633 break;
15634 default:
15635 goto pool32axf_invalid;
15637 break;
15638 default:
15639 pool32axf_invalid:
15640 MIPS_INVAL("pool32axf");
15641 generate_exception_end(ctx, EXCP_RI);
15642 break;
15646 /* Values for microMIPS fmt field. Variable-width, depending on which
15647 formats the instruction supports. */
15649 enum {
15650 FMT_SD_S = 0,
15651 FMT_SD_D = 1,
15653 FMT_SDPS_S = 0,
15654 FMT_SDPS_D = 1,
15655 FMT_SDPS_PS = 2,
15657 FMT_SWL_S = 0,
15658 FMT_SWL_W = 1,
15659 FMT_SWL_L = 2,
15661 FMT_DWL_D = 0,
15662 FMT_DWL_W = 1,
15663 FMT_DWL_L = 2
15666 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15668 int extension = (ctx->opcode >> 6) & 0x3ff;
15669 uint32_t mips32_op;
15671 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15672 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15673 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15675 switch (extension) {
15676 case FLOAT_1BIT_FMT(CFC1, 0):
15677 mips32_op = OPC_CFC1;
15678 goto do_cp1;
15679 case FLOAT_1BIT_FMT(CTC1, 0):
15680 mips32_op = OPC_CTC1;
15681 goto do_cp1;
15682 case FLOAT_1BIT_FMT(MFC1, 0):
15683 mips32_op = OPC_MFC1;
15684 goto do_cp1;
15685 case FLOAT_1BIT_FMT(MTC1, 0):
15686 mips32_op = OPC_MTC1;
15687 goto do_cp1;
15688 case FLOAT_1BIT_FMT(MFHC1, 0):
15689 mips32_op = OPC_MFHC1;
15690 goto do_cp1;
15691 case FLOAT_1BIT_FMT(MTHC1, 0):
15692 mips32_op = OPC_MTHC1;
15693 do_cp1:
15694 gen_cp1(ctx, mips32_op, rt, rs);
15695 break;
15697 /* Reciprocal square root */
15698 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15699 mips32_op = OPC_RSQRT_S;
15700 goto do_unaryfp;
15701 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15702 mips32_op = OPC_RSQRT_D;
15703 goto do_unaryfp;
15705 /* Square root */
15706 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15707 mips32_op = OPC_SQRT_S;
15708 goto do_unaryfp;
15709 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15710 mips32_op = OPC_SQRT_D;
15711 goto do_unaryfp;
15713 /* Reciprocal */
15714 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15715 mips32_op = OPC_RECIP_S;
15716 goto do_unaryfp;
15717 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15718 mips32_op = OPC_RECIP_D;
15719 goto do_unaryfp;
15721 /* Floor */
15722 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15723 mips32_op = OPC_FLOOR_L_S;
15724 goto do_unaryfp;
15725 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15726 mips32_op = OPC_FLOOR_L_D;
15727 goto do_unaryfp;
15728 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15729 mips32_op = OPC_FLOOR_W_S;
15730 goto do_unaryfp;
15731 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15732 mips32_op = OPC_FLOOR_W_D;
15733 goto do_unaryfp;
15735 /* Ceiling */
15736 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15737 mips32_op = OPC_CEIL_L_S;
15738 goto do_unaryfp;
15739 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15740 mips32_op = OPC_CEIL_L_D;
15741 goto do_unaryfp;
15742 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15743 mips32_op = OPC_CEIL_W_S;
15744 goto do_unaryfp;
15745 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15746 mips32_op = OPC_CEIL_W_D;
15747 goto do_unaryfp;
15749 /* Truncation */
15750 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15751 mips32_op = OPC_TRUNC_L_S;
15752 goto do_unaryfp;
15753 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15754 mips32_op = OPC_TRUNC_L_D;
15755 goto do_unaryfp;
15756 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15757 mips32_op = OPC_TRUNC_W_S;
15758 goto do_unaryfp;
15759 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15760 mips32_op = OPC_TRUNC_W_D;
15761 goto do_unaryfp;
15763 /* Round */
15764 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15765 mips32_op = OPC_ROUND_L_S;
15766 goto do_unaryfp;
15767 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15768 mips32_op = OPC_ROUND_L_D;
15769 goto do_unaryfp;
15770 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15771 mips32_op = OPC_ROUND_W_S;
15772 goto do_unaryfp;
15773 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15774 mips32_op = OPC_ROUND_W_D;
15775 goto do_unaryfp;
15777 /* Integer to floating-point conversion */
15778 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15779 mips32_op = OPC_CVT_L_S;
15780 goto do_unaryfp;
15781 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15782 mips32_op = OPC_CVT_L_D;
15783 goto do_unaryfp;
15784 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15785 mips32_op = OPC_CVT_W_S;
15786 goto do_unaryfp;
15787 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15788 mips32_op = OPC_CVT_W_D;
15789 goto do_unaryfp;
15791 /* Paired-foo conversions */
15792 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15793 mips32_op = OPC_CVT_S_PL;
15794 goto do_unaryfp;
15795 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15796 mips32_op = OPC_CVT_S_PU;
15797 goto do_unaryfp;
15798 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15799 mips32_op = OPC_CVT_PW_PS;
15800 goto do_unaryfp;
15801 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15802 mips32_op = OPC_CVT_PS_PW;
15803 goto do_unaryfp;
15805 /* Floating-point moves */
15806 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15807 mips32_op = OPC_MOV_S;
15808 goto do_unaryfp;
15809 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15810 mips32_op = OPC_MOV_D;
15811 goto do_unaryfp;
15812 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15813 mips32_op = OPC_MOV_PS;
15814 goto do_unaryfp;
15816 /* Absolute value */
15817 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15818 mips32_op = OPC_ABS_S;
15819 goto do_unaryfp;
15820 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15821 mips32_op = OPC_ABS_D;
15822 goto do_unaryfp;
15823 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15824 mips32_op = OPC_ABS_PS;
15825 goto do_unaryfp;
15827 /* Negation */
15828 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15829 mips32_op = OPC_NEG_S;
15830 goto do_unaryfp;
15831 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15832 mips32_op = OPC_NEG_D;
15833 goto do_unaryfp;
15834 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15835 mips32_op = OPC_NEG_PS;
15836 goto do_unaryfp;
15838 /* Reciprocal square root step */
15839 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15840 mips32_op = OPC_RSQRT1_S;
15841 goto do_unaryfp;
15842 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15843 mips32_op = OPC_RSQRT1_D;
15844 goto do_unaryfp;
15845 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15846 mips32_op = OPC_RSQRT1_PS;
15847 goto do_unaryfp;
15849 /* Reciprocal step */
15850 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15851 mips32_op = OPC_RECIP1_S;
15852 goto do_unaryfp;
15853 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15854 mips32_op = OPC_RECIP1_S;
15855 goto do_unaryfp;
15856 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15857 mips32_op = OPC_RECIP1_PS;
15858 goto do_unaryfp;
15860 /* Conversions from double */
15861 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15862 mips32_op = OPC_CVT_D_S;
15863 goto do_unaryfp;
15864 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15865 mips32_op = OPC_CVT_D_W;
15866 goto do_unaryfp;
15867 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15868 mips32_op = OPC_CVT_D_L;
15869 goto do_unaryfp;
15871 /* Conversions from single */
15872 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15873 mips32_op = OPC_CVT_S_D;
15874 goto do_unaryfp;
15875 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15876 mips32_op = OPC_CVT_S_W;
15877 goto do_unaryfp;
15878 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15879 mips32_op = OPC_CVT_S_L;
15880 do_unaryfp:
15881 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15882 break;
15884 /* Conditional moves on floating-point codes */
15885 case COND_FLOAT_MOV(MOVT, 0):
15886 case COND_FLOAT_MOV(MOVT, 1):
15887 case COND_FLOAT_MOV(MOVT, 2):
15888 case COND_FLOAT_MOV(MOVT, 3):
15889 case COND_FLOAT_MOV(MOVT, 4):
15890 case COND_FLOAT_MOV(MOVT, 5):
15891 case COND_FLOAT_MOV(MOVT, 6):
15892 case COND_FLOAT_MOV(MOVT, 7):
15893 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15894 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15895 break;
15896 case COND_FLOAT_MOV(MOVF, 0):
15897 case COND_FLOAT_MOV(MOVF, 1):
15898 case COND_FLOAT_MOV(MOVF, 2):
15899 case COND_FLOAT_MOV(MOVF, 3):
15900 case COND_FLOAT_MOV(MOVF, 4):
15901 case COND_FLOAT_MOV(MOVF, 5):
15902 case COND_FLOAT_MOV(MOVF, 6):
15903 case COND_FLOAT_MOV(MOVF, 7):
15904 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15905 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15906 break;
15907 default:
15908 MIPS_INVAL("pool32fxf");
15909 generate_exception_end(ctx, EXCP_RI);
15910 break;
15914 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15916 int32_t offset;
15917 uint16_t insn;
15918 int rt, rs, rd, rr;
15919 int16_t imm;
15920 uint32_t op, minor, minor2, mips32_op;
15921 uint32_t cond, fmt, cc;
15923 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15924 ctx->opcode = (ctx->opcode << 16) | insn;
15926 rt = (ctx->opcode >> 21) & 0x1f;
15927 rs = (ctx->opcode >> 16) & 0x1f;
15928 rd = (ctx->opcode >> 11) & 0x1f;
15929 rr = (ctx->opcode >> 6) & 0x1f;
15930 imm = (int16_t) ctx->opcode;
15932 op = (ctx->opcode >> 26) & 0x3f;
15933 switch (op) {
15934 case POOL32A:
15935 minor = ctx->opcode & 0x3f;
15936 switch (minor) {
15937 case 0x00:
15938 minor = (ctx->opcode >> 6) & 0xf;
15939 switch (minor) {
15940 case SLL32:
15941 mips32_op = OPC_SLL;
15942 goto do_shifti;
15943 case SRA:
15944 mips32_op = OPC_SRA;
15945 goto do_shifti;
15946 case SRL32:
15947 mips32_op = OPC_SRL;
15948 goto do_shifti;
15949 case ROTR:
15950 mips32_op = OPC_ROTR;
15951 do_shifti:
15952 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15953 break;
15954 case SELEQZ:
15955 check_insn(ctx, ISA_MIPS32R6);
15956 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15957 break;
15958 case SELNEZ:
15959 check_insn(ctx, ISA_MIPS32R6);
15960 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15961 break;
15962 case R6_RDHWR:
15963 check_insn(ctx, ISA_MIPS32R6);
15964 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15965 break;
15966 default:
15967 goto pool32a_invalid;
15969 break;
15970 case 0x10:
15971 minor = (ctx->opcode >> 6) & 0xf;
15972 switch (minor) {
15973 /* Arithmetic */
15974 case ADD:
15975 mips32_op = OPC_ADD;
15976 goto do_arith;
15977 case ADDU32:
15978 mips32_op = OPC_ADDU;
15979 goto do_arith;
15980 case SUB:
15981 mips32_op = OPC_SUB;
15982 goto do_arith;
15983 case SUBU32:
15984 mips32_op = OPC_SUBU;
15985 goto do_arith;
15986 case MUL:
15987 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15988 mips32_op = OPC_MUL;
15989 do_arith:
15990 gen_arith(ctx, mips32_op, rd, rs, rt);
15991 break;
15992 /* Shifts */
15993 case SLLV:
15994 mips32_op = OPC_SLLV;
15995 goto do_shift;
15996 case SRLV:
15997 mips32_op = OPC_SRLV;
15998 goto do_shift;
15999 case SRAV:
16000 mips32_op = OPC_SRAV;
16001 goto do_shift;
16002 case ROTRV:
16003 mips32_op = OPC_ROTRV;
16004 do_shift:
16005 gen_shift(ctx, mips32_op, rd, rs, rt);
16006 break;
16007 /* Logical operations */
16008 case AND:
16009 mips32_op = OPC_AND;
16010 goto do_logic;
16011 case OR32:
16012 mips32_op = OPC_OR;
16013 goto do_logic;
16014 case NOR:
16015 mips32_op = OPC_NOR;
16016 goto do_logic;
16017 case XOR32:
16018 mips32_op = OPC_XOR;
16019 do_logic:
16020 gen_logic(ctx, mips32_op, rd, rs, rt);
16021 break;
16022 /* Set less than */
16023 case SLT:
16024 mips32_op = OPC_SLT;
16025 goto do_slt;
16026 case SLTU:
16027 mips32_op = OPC_SLTU;
16028 do_slt:
16029 gen_slt(ctx, mips32_op, rd, rs, rt);
16030 break;
16031 default:
16032 goto pool32a_invalid;
16034 break;
16035 case 0x18:
16036 minor = (ctx->opcode >> 6) & 0xf;
16037 switch (minor) {
16038 /* Conditional moves */
16039 case MOVN: /* MUL */
16040 if (ctx->insn_flags & ISA_MIPS32R6) {
16041 /* MUL */
16042 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16043 } else {
16044 /* MOVN */
16045 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16047 break;
16048 case MOVZ: /* MUH */
16049 if (ctx->insn_flags & ISA_MIPS32R6) {
16050 /* MUH */
16051 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16052 } else {
16053 /* MOVZ */
16054 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16056 break;
16057 case MULU:
16058 check_insn(ctx, ISA_MIPS32R6);
16059 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16060 break;
16061 case MUHU:
16062 check_insn(ctx, ISA_MIPS32R6);
16063 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16064 break;
16065 case LWXS: /* DIV */
16066 if (ctx->insn_flags & ISA_MIPS32R6) {
16067 /* DIV */
16068 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16069 } else {
16070 /* LWXS */
16071 gen_ldxs(ctx, rs, rt, rd);
16073 break;
16074 case MOD:
16075 check_insn(ctx, ISA_MIPS32R6);
16076 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16077 break;
16078 case R6_DIVU:
16079 check_insn(ctx, ISA_MIPS32R6);
16080 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16081 break;
16082 case MODU:
16083 check_insn(ctx, ISA_MIPS32R6);
16084 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16085 break;
16086 default:
16087 goto pool32a_invalid;
16089 break;
16090 case INS:
16091 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16092 return;
16093 case LSA:
16094 check_insn(ctx, ISA_MIPS32R6);
16095 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16096 extract32(ctx->opcode, 9, 2));
16097 break;
16098 case ALIGN:
16099 check_insn(ctx, ISA_MIPS32R6);
16100 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16101 break;
16102 case EXT:
16103 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16104 return;
16105 case POOL32AXF:
16106 gen_pool32axf(env, ctx, rt, rs);
16107 break;
16108 case BREAK32:
16109 generate_exception_end(ctx, EXCP_BREAK);
16110 break;
16111 case SIGRIE:
16112 check_insn(ctx, ISA_MIPS32R6);
16113 generate_exception_end(ctx, EXCP_RI);
16114 break;
16115 default:
16116 pool32a_invalid:
16117 MIPS_INVAL("pool32a");
16118 generate_exception_end(ctx, EXCP_RI);
16119 break;
16121 break;
16122 case POOL32B:
16123 minor = (ctx->opcode >> 12) & 0xf;
16124 switch (minor) {
16125 case CACHE:
16126 check_cp0_enabled(ctx);
16127 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16128 gen_cache_operation(ctx, rt, rs, imm);
16130 break;
16131 case LWC2:
16132 case SWC2:
16133 /* COP2: Not implemented. */
16134 generate_exception_err(ctx, EXCP_CpU, 2);
16135 break;
16136 #ifdef TARGET_MIPS64
16137 case LDP:
16138 case SDP:
16139 check_insn(ctx, ISA_MIPS3);
16140 check_mips_64(ctx);
16141 #endif
16142 /* fall through */
16143 case LWP:
16144 case SWP:
16145 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16146 break;
16147 #ifdef TARGET_MIPS64
16148 case LDM:
16149 case SDM:
16150 check_insn(ctx, ISA_MIPS3);
16151 check_mips_64(ctx);
16152 #endif
16153 /* fall through */
16154 case LWM32:
16155 case SWM32:
16156 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16157 break;
16158 default:
16159 MIPS_INVAL("pool32b");
16160 generate_exception_end(ctx, EXCP_RI);
16161 break;
16163 break;
16164 case POOL32F:
16165 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16166 minor = ctx->opcode & 0x3f;
16167 check_cp1_enabled(ctx);
16168 switch (minor) {
16169 case ALNV_PS:
16170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16171 mips32_op = OPC_ALNV_PS;
16172 goto do_madd;
16173 case MADD_S:
16174 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16175 mips32_op = OPC_MADD_S;
16176 goto do_madd;
16177 case MADD_D:
16178 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16179 mips32_op = OPC_MADD_D;
16180 goto do_madd;
16181 case MADD_PS:
16182 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16183 mips32_op = OPC_MADD_PS;
16184 goto do_madd;
16185 case MSUB_S:
16186 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16187 mips32_op = OPC_MSUB_S;
16188 goto do_madd;
16189 case MSUB_D:
16190 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16191 mips32_op = OPC_MSUB_D;
16192 goto do_madd;
16193 case MSUB_PS:
16194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16195 mips32_op = OPC_MSUB_PS;
16196 goto do_madd;
16197 case NMADD_S:
16198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16199 mips32_op = OPC_NMADD_S;
16200 goto do_madd;
16201 case NMADD_D:
16202 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16203 mips32_op = OPC_NMADD_D;
16204 goto do_madd;
16205 case NMADD_PS:
16206 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16207 mips32_op = OPC_NMADD_PS;
16208 goto do_madd;
16209 case NMSUB_S:
16210 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16211 mips32_op = OPC_NMSUB_S;
16212 goto do_madd;
16213 case NMSUB_D:
16214 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16215 mips32_op = OPC_NMSUB_D;
16216 goto do_madd;
16217 case NMSUB_PS:
16218 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16219 mips32_op = OPC_NMSUB_PS;
16220 do_madd:
16221 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16222 break;
16223 case CABS_COND_FMT:
16224 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16225 cond = (ctx->opcode >> 6) & 0xf;
16226 cc = (ctx->opcode >> 13) & 0x7;
16227 fmt = (ctx->opcode >> 10) & 0x3;
16228 switch (fmt) {
16229 case 0x0:
16230 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16231 break;
16232 case 0x1:
16233 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16234 break;
16235 case 0x2:
16236 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16237 break;
16238 default:
16239 goto pool32f_invalid;
16241 break;
16242 case C_COND_FMT:
16243 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16244 cond = (ctx->opcode >> 6) & 0xf;
16245 cc = (ctx->opcode >> 13) & 0x7;
16246 fmt = (ctx->opcode >> 10) & 0x3;
16247 switch (fmt) {
16248 case 0x0:
16249 gen_cmp_s(ctx, cond, rt, rs, cc);
16250 break;
16251 case 0x1:
16252 gen_cmp_d(ctx, cond, rt, rs, cc);
16253 break;
16254 case 0x2:
16255 gen_cmp_ps(ctx, cond, rt, rs, cc);
16256 break;
16257 default:
16258 goto pool32f_invalid;
16260 break;
16261 case CMP_CONDN_S:
16262 check_insn(ctx, ISA_MIPS32R6);
16263 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16264 break;
16265 case CMP_CONDN_D:
16266 check_insn(ctx, ISA_MIPS32R6);
16267 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16268 break;
16269 case POOL32FXF:
16270 gen_pool32fxf(ctx, rt, rs);
16271 break;
16272 case 0x00:
16273 /* PLL foo */
16274 switch ((ctx->opcode >> 6) & 0x7) {
16275 case PLL_PS:
16276 mips32_op = OPC_PLL_PS;
16277 goto do_ps;
16278 case PLU_PS:
16279 mips32_op = OPC_PLU_PS;
16280 goto do_ps;
16281 case PUL_PS:
16282 mips32_op = OPC_PUL_PS;
16283 goto do_ps;
16284 case PUU_PS:
16285 mips32_op = OPC_PUU_PS;
16286 goto do_ps;
16287 case CVT_PS_S:
16288 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16289 mips32_op = OPC_CVT_PS_S;
16290 do_ps:
16291 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16292 break;
16293 default:
16294 goto pool32f_invalid;
16296 break;
16297 case MIN_FMT:
16298 check_insn(ctx, ISA_MIPS32R6);
16299 switch ((ctx->opcode >> 9) & 0x3) {
16300 case FMT_SDPS_S:
16301 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16302 break;
16303 case FMT_SDPS_D:
16304 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16305 break;
16306 default:
16307 goto pool32f_invalid;
16309 break;
16310 case 0x08:
16311 /* [LS][WDU]XC1 */
16312 switch ((ctx->opcode >> 6) & 0x7) {
16313 case LWXC1:
16314 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16315 mips32_op = OPC_LWXC1;
16316 goto do_ldst_cp1;
16317 case SWXC1:
16318 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16319 mips32_op = OPC_SWXC1;
16320 goto do_ldst_cp1;
16321 case LDXC1:
16322 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16323 mips32_op = OPC_LDXC1;
16324 goto do_ldst_cp1;
16325 case SDXC1:
16326 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16327 mips32_op = OPC_SDXC1;
16328 goto do_ldst_cp1;
16329 case LUXC1:
16330 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16331 mips32_op = OPC_LUXC1;
16332 goto do_ldst_cp1;
16333 case SUXC1:
16334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16335 mips32_op = OPC_SUXC1;
16336 do_ldst_cp1:
16337 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16338 break;
16339 default:
16340 goto pool32f_invalid;
16342 break;
16343 case MAX_FMT:
16344 check_insn(ctx, ISA_MIPS32R6);
16345 switch ((ctx->opcode >> 9) & 0x3) {
16346 case FMT_SDPS_S:
16347 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16348 break;
16349 case FMT_SDPS_D:
16350 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16351 break;
16352 default:
16353 goto pool32f_invalid;
16355 break;
16356 case 0x18:
16357 /* 3D insns */
16358 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16359 fmt = (ctx->opcode >> 9) & 0x3;
16360 switch ((ctx->opcode >> 6) & 0x7) {
16361 case RSQRT2_FMT:
16362 switch (fmt) {
16363 case FMT_SDPS_S:
16364 mips32_op = OPC_RSQRT2_S;
16365 goto do_3d;
16366 case FMT_SDPS_D:
16367 mips32_op = OPC_RSQRT2_D;
16368 goto do_3d;
16369 case FMT_SDPS_PS:
16370 mips32_op = OPC_RSQRT2_PS;
16371 goto do_3d;
16372 default:
16373 goto pool32f_invalid;
16375 break;
16376 case RECIP2_FMT:
16377 switch (fmt) {
16378 case FMT_SDPS_S:
16379 mips32_op = OPC_RECIP2_S;
16380 goto do_3d;
16381 case FMT_SDPS_D:
16382 mips32_op = OPC_RECIP2_D;
16383 goto do_3d;
16384 case FMT_SDPS_PS:
16385 mips32_op = OPC_RECIP2_PS;
16386 goto do_3d;
16387 default:
16388 goto pool32f_invalid;
16390 break;
16391 case ADDR_PS:
16392 mips32_op = OPC_ADDR_PS;
16393 goto do_3d;
16394 case MULR_PS:
16395 mips32_op = OPC_MULR_PS;
16396 do_3d:
16397 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16398 break;
16399 default:
16400 goto pool32f_invalid;
16402 break;
16403 case 0x20:
16404 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16405 cc = (ctx->opcode >> 13) & 0x7;
16406 fmt = (ctx->opcode >> 9) & 0x3;
16407 switch ((ctx->opcode >> 6) & 0x7) {
16408 case MOVF_FMT: /* RINT_FMT */
16409 if (ctx->insn_flags & ISA_MIPS32R6) {
16410 /* RINT_FMT */
16411 switch (fmt) {
16412 case FMT_SDPS_S:
16413 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16414 break;
16415 case FMT_SDPS_D:
16416 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16417 break;
16418 default:
16419 goto pool32f_invalid;
16421 } else {
16422 /* MOVF_FMT */
16423 switch (fmt) {
16424 case FMT_SDPS_S:
16425 gen_movcf_s(ctx, rs, rt, cc, 0);
16426 break;
16427 case FMT_SDPS_D:
16428 gen_movcf_d(ctx, rs, rt, cc, 0);
16429 break;
16430 case FMT_SDPS_PS:
16431 check_ps(ctx);
16432 gen_movcf_ps(ctx, rs, rt, cc, 0);
16433 break;
16434 default:
16435 goto pool32f_invalid;
16438 break;
16439 case MOVT_FMT: /* CLASS_FMT */
16440 if (ctx->insn_flags & ISA_MIPS32R6) {
16441 /* CLASS_FMT */
16442 switch (fmt) {
16443 case FMT_SDPS_S:
16444 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16445 break;
16446 case FMT_SDPS_D:
16447 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16448 break;
16449 default:
16450 goto pool32f_invalid;
16452 } else {
16453 /* MOVT_FMT */
16454 switch (fmt) {
16455 case FMT_SDPS_S:
16456 gen_movcf_s(ctx, rs, rt, cc, 1);
16457 break;
16458 case FMT_SDPS_D:
16459 gen_movcf_d(ctx, rs, rt, cc, 1);
16460 break;
16461 case FMT_SDPS_PS:
16462 check_ps(ctx);
16463 gen_movcf_ps(ctx, rs, rt, cc, 1);
16464 break;
16465 default:
16466 goto pool32f_invalid;
16469 break;
16470 case PREFX:
16471 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16472 break;
16473 default:
16474 goto pool32f_invalid;
16476 break;
16477 #define FINSN_3ARG_SDPS(prfx) \
16478 switch ((ctx->opcode >> 8) & 0x3) { \
16479 case FMT_SDPS_S: \
16480 mips32_op = OPC_##prfx##_S; \
16481 goto do_fpop; \
16482 case FMT_SDPS_D: \
16483 mips32_op = OPC_##prfx##_D; \
16484 goto do_fpop; \
16485 case FMT_SDPS_PS: \
16486 check_ps(ctx); \
16487 mips32_op = OPC_##prfx##_PS; \
16488 goto do_fpop; \
16489 default: \
16490 goto pool32f_invalid; \
16492 case MINA_FMT:
16493 check_insn(ctx, ISA_MIPS32R6);
16494 switch ((ctx->opcode >> 9) & 0x3) {
16495 case FMT_SDPS_S:
16496 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16497 break;
16498 case FMT_SDPS_D:
16499 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16500 break;
16501 default:
16502 goto pool32f_invalid;
16504 break;
16505 case MAXA_FMT:
16506 check_insn(ctx, ISA_MIPS32R6);
16507 switch ((ctx->opcode >> 9) & 0x3) {
16508 case FMT_SDPS_S:
16509 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16510 break;
16511 case FMT_SDPS_D:
16512 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16513 break;
16514 default:
16515 goto pool32f_invalid;
16517 break;
16518 case 0x30:
16519 /* regular FP ops */
16520 switch ((ctx->opcode >> 6) & 0x3) {
16521 case ADD_FMT:
16522 FINSN_3ARG_SDPS(ADD);
16523 break;
16524 case SUB_FMT:
16525 FINSN_3ARG_SDPS(SUB);
16526 break;
16527 case MUL_FMT:
16528 FINSN_3ARG_SDPS(MUL);
16529 break;
16530 case DIV_FMT:
16531 fmt = (ctx->opcode >> 8) & 0x3;
16532 if (fmt == 1) {
16533 mips32_op = OPC_DIV_D;
16534 } else if (fmt == 0) {
16535 mips32_op = OPC_DIV_S;
16536 } else {
16537 goto pool32f_invalid;
16539 goto do_fpop;
16540 default:
16541 goto pool32f_invalid;
16543 break;
16544 case 0x38:
16545 /* cmovs */
16546 switch ((ctx->opcode >> 6) & 0x7) {
16547 case MOVN_FMT: /* SELEQZ_FMT */
16548 if (ctx->insn_flags & ISA_MIPS32R6) {
16549 /* SELEQZ_FMT */
16550 switch ((ctx->opcode >> 9) & 0x3) {
16551 case FMT_SDPS_S:
16552 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16553 break;
16554 case FMT_SDPS_D:
16555 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16556 break;
16557 default:
16558 goto pool32f_invalid;
16560 } else {
16561 /* MOVN_FMT */
16562 FINSN_3ARG_SDPS(MOVN);
16564 break;
16565 case MOVN_FMT_04:
16566 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16567 FINSN_3ARG_SDPS(MOVN);
16568 break;
16569 case MOVZ_FMT: /* SELNEZ_FMT */
16570 if (ctx->insn_flags & ISA_MIPS32R6) {
16571 /* SELNEZ_FMT */
16572 switch ((ctx->opcode >> 9) & 0x3) {
16573 case FMT_SDPS_S:
16574 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16575 break;
16576 case FMT_SDPS_D:
16577 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16578 break;
16579 default:
16580 goto pool32f_invalid;
16582 } else {
16583 /* MOVZ_FMT */
16584 FINSN_3ARG_SDPS(MOVZ);
16586 break;
16587 case MOVZ_FMT_05:
16588 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16589 FINSN_3ARG_SDPS(MOVZ);
16590 break;
16591 case SEL_FMT:
16592 check_insn(ctx, ISA_MIPS32R6);
16593 switch ((ctx->opcode >> 9) & 0x3) {
16594 case FMT_SDPS_S:
16595 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16596 break;
16597 case FMT_SDPS_D:
16598 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16599 break;
16600 default:
16601 goto pool32f_invalid;
16603 break;
16604 case MADDF_FMT:
16605 check_insn(ctx, ISA_MIPS32R6);
16606 switch ((ctx->opcode >> 9) & 0x3) {
16607 case FMT_SDPS_S:
16608 mips32_op = OPC_MADDF_S;
16609 goto do_fpop;
16610 case FMT_SDPS_D:
16611 mips32_op = OPC_MADDF_D;
16612 goto do_fpop;
16613 default:
16614 goto pool32f_invalid;
16616 break;
16617 case MSUBF_FMT:
16618 check_insn(ctx, ISA_MIPS32R6);
16619 switch ((ctx->opcode >> 9) & 0x3) {
16620 case FMT_SDPS_S:
16621 mips32_op = OPC_MSUBF_S;
16622 goto do_fpop;
16623 case FMT_SDPS_D:
16624 mips32_op = OPC_MSUBF_D;
16625 goto do_fpop;
16626 default:
16627 goto pool32f_invalid;
16629 break;
16630 default:
16631 goto pool32f_invalid;
16633 break;
16634 do_fpop:
16635 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16636 break;
16637 default:
16638 pool32f_invalid:
16639 MIPS_INVAL("pool32f");
16640 generate_exception_end(ctx, EXCP_RI);
16641 break;
16643 } else {
16644 generate_exception_err(ctx, EXCP_CpU, 1);
16646 break;
16647 case POOL32I:
16648 minor = (ctx->opcode >> 21) & 0x1f;
16649 switch (minor) {
16650 case BLTZ:
16651 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16652 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16653 break;
16654 case BLTZAL:
16655 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16656 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16657 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16658 break;
16659 case BLTZALS:
16660 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16661 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16662 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16663 break;
16664 case BGEZ:
16665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16666 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16667 break;
16668 case BGEZAL:
16669 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16670 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16671 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16672 break;
16673 case BGEZALS:
16674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16675 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16676 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16677 break;
16678 case BLEZ:
16679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16680 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16681 break;
16682 case BGTZ:
16683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16684 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16685 break;
16687 /* Traps */
16688 case TLTI: /* BC1EQZC */
16689 if (ctx->insn_flags & ISA_MIPS32R6) {
16690 /* BC1EQZC */
16691 check_cp1_enabled(ctx);
16692 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16693 } else {
16694 /* TLTI */
16695 mips32_op = OPC_TLTI;
16696 goto do_trapi;
16698 break;
16699 case TGEI: /* BC1NEZC */
16700 if (ctx->insn_flags & ISA_MIPS32R6) {
16701 /* BC1NEZC */
16702 check_cp1_enabled(ctx);
16703 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16704 } else {
16705 /* TGEI */
16706 mips32_op = OPC_TGEI;
16707 goto do_trapi;
16709 break;
16710 case TLTIU:
16711 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16712 mips32_op = OPC_TLTIU;
16713 goto do_trapi;
16714 case TGEIU:
16715 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16716 mips32_op = OPC_TGEIU;
16717 goto do_trapi;
16718 case TNEI: /* SYNCI */
16719 if (ctx->insn_flags & ISA_MIPS32R6) {
16720 /* SYNCI */
16721 /* Break the TB to be able to sync copied instructions
16722 immediately */
16723 ctx->base.is_jmp = DISAS_STOP;
16724 } else {
16725 /* TNEI */
16726 mips32_op = OPC_TNEI;
16727 goto do_trapi;
16729 break;
16730 case TEQI:
16731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16732 mips32_op = OPC_TEQI;
16733 do_trapi:
16734 gen_trap(ctx, mips32_op, rs, -1, imm);
16735 break;
16737 case BNEZC:
16738 case BEQZC:
16739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16740 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16741 4, rs, 0, imm << 1, 0);
16742 /* Compact branches don't have a delay slot, so just let
16743 the normal delay slot handling take us to the branch
16744 target. */
16745 break;
16746 case LUI:
16747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16748 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16749 break;
16750 case SYNCI:
16751 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16752 /* Break the TB to be able to sync copied instructions
16753 immediately */
16754 ctx->base.is_jmp = DISAS_STOP;
16755 break;
16756 case BC2F:
16757 case BC2T:
16758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16759 /* COP2: Not implemented. */
16760 generate_exception_err(ctx, EXCP_CpU, 2);
16761 break;
16762 case BC1F:
16763 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16764 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16765 goto do_cp1branch;
16766 case BC1T:
16767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16768 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16769 goto do_cp1branch;
16770 case BC1ANY4F:
16771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16772 mips32_op = OPC_BC1FANY4;
16773 goto do_cp1mips3d;
16774 case BC1ANY4T:
16775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16776 mips32_op = OPC_BC1TANY4;
16777 do_cp1mips3d:
16778 check_cop1x(ctx);
16779 check_insn(ctx, ASE_MIPS3D);
16780 /* Fall through */
16781 do_cp1branch:
16782 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16783 check_cp1_enabled(ctx);
16784 gen_compute_branch1(ctx, mips32_op,
16785 (ctx->opcode >> 18) & 0x7, imm << 1);
16786 } else {
16787 generate_exception_err(ctx, EXCP_CpU, 1);
16789 break;
16790 case BPOSGE64:
16791 case BPOSGE32:
16792 /* MIPS DSP: not implemented */
16793 /* Fall through */
16794 default:
16795 MIPS_INVAL("pool32i");
16796 generate_exception_end(ctx, EXCP_RI);
16797 break;
16799 break;
16800 case POOL32C:
16801 minor = (ctx->opcode >> 12) & 0xf;
16802 offset = sextract32(ctx->opcode, 0,
16803 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16804 switch (minor) {
16805 case LWL:
16806 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16807 mips32_op = OPC_LWL;
16808 goto do_ld_lr;
16809 case SWL:
16810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16811 mips32_op = OPC_SWL;
16812 goto do_st_lr;
16813 case LWR:
16814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16815 mips32_op = OPC_LWR;
16816 goto do_ld_lr;
16817 case SWR:
16818 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16819 mips32_op = OPC_SWR;
16820 goto do_st_lr;
16821 #if defined(TARGET_MIPS64)
16822 case LDL:
16823 check_insn(ctx, ISA_MIPS3);
16824 check_mips_64(ctx);
16825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16826 mips32_op = OPC_LDL;
16827 goto do_ld_lr;
16828 case SDL:
16829 check_insn(ctx, ISA_MIPS3);
16830 check_mips_64(ctx);
16831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16832 mips32_op = OPC_SDL;
16833 goto do_st_lr;
16834 case LDR:
16835 check_insn(ctx, ISA_MIPS3);
16836 check_mips_64(ctx);
16837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16838 mips32_op = OPC_LDR;
16839 goto do_ld_lr;
16840 case SDR:
16841 check_insn(ctx, ISA_MIPS3);
16842 check_mips_64(ctx);
16843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16844 mips32_op = OPC_SDR;
16845 goto do_st_lr;
16846 case LWU:
16847 check_insn(ctx, ISA_MIPS3);
16848 check_mips_64(ctx);
16849 mips32_op = OPC_LWU;
16850 goto do_ld_lr;
16851 case LLD:
16852 check_insn(ctx, ISA_MIPS3);
16853 check_mips_64(ctx);
16854 mips32_op = OPC_LLD;
16855 goto do_ld_lr;
16856 #endif
16857 case LL:
16858 mips32_op = OPC_LL;
16859 goto do_ld_lr;
16860 do_ld_lr:
16861 gen_ld(ctx, mips32_op, rt, rs, offset);
16862 break;
16863 do_st_lr:
16864 gen_st(ctx, mips32_op, rt, rs, offset);
16865 break;
16866 case SC:
16867 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16868 break;
16869 #if defined(TARGET_MIPS64)
16870 case SCD:
16871 check_insn(ctx, ISA_MIPS3);
16872 check_mips_64(ctx);
16873 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16874 break;
16875 #endif
16876 case LD_EVA:
16877 if (!ctx->eva) {
16878 MIPS_INVAL("pool32c ld-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 LBUE:
16888 mips32_op = OPC_LBUE;
16889 goto do_ld_lr;
16890 case LHUE:
16891 mips32_op = OPC_LHUE;
16892 goto do_ld_lr;
16893 case LWLE:
16894 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16895 mips32_op = OPC_LWLE;
16896 goto do_ld_lr;
16897 case LWRE:
16898 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16899 mips32_op = OPC_LWRE;
16900 goto do_ld_lr;
16901 case LBE:
16902 mips32_op = OPC_LBE;
16903 goto do_ld_lr;
16904 case LHE:
16905 mips32_op = OPC_LHE;
16906 goto do_ld_lr;
16907 case LLE:
16908 mips32_op = OPC_LLE;
16909 goto do_ld_lr;
16910 case LWE:
16911 mips32_op = OPC_LWE;
16912 goto do_ld_lr;
16914 break;
16915 case ST_EVA:
16916 if (!ctx->eva) {
16917 MIPS_INVAL("pool32c st-eva");
16918 generate_exception_end(ctx, EXCP_RI);
16919 break;
16921 check_cp0_enabled(ctx);
16923 minor2 = (ctx->opcode >> 9) & 0x7;
16924 offset = sextract32(ctx->opcode, 0, 9);
16925 switch (minor2) {
16926 case SWLE:
16927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16928 mips32_op = OPC_SWLE;
16929 goto do_st_lr;
16930 case SWRE:
16931 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16932 mips32_op = OPC_SWRE;
16933 goto do_st_lr;
16934 case PREFE:
16935 /* Treat as no-op */
16936 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16937 /* hint codes 24-31 are reserved and signal RI */
16938 generate_exception(ctx, EXCP_RI);
16940 break;
16941 case CACHEE:
16942 /* Treat as no-op */
16943 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16944 gen_cache_operation(ctx, rt, rs, offset);
16946 break;
16947 case SBE:
16948 mips32_op = OPC_SBE;
16949 goto do_st_lr;
16950 case SHE:
16951 mips32_op = OPC_SHE;
16952 goto do_st_lr;
16953 case SCE:
16954 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16955 break;
16956 case SWE:
16957 mips32_op = OPC_SWE;
16958 goto do_st_lr;
16960 break;
16961 case PREF:
16962 /* Treat as no-op */
16963 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16964 /* hint codes 24-31 are reserved and signal RI */
16965 generate_exception(ctx, EXCP_RI);
16967 break;
16968 default:
16969 MIPS_INVAL("pool32c");
16970 generate_exception_end(ctx, EXCP_RI);
16971 break;
16973 break;
16974 case ADDI32: /* AUI, LUI */
16975 if (ctx->insn_flags & ISA_MIPS32R6) {
16976 /* AUI, LUI */
16977 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16978 } else {
16979 /* ADDI32 */
16980 mips32_op = OPC_ADDI;
16981 goto do_addi;
16983 break;
16984 case ADDIU32:
16985 mips32_op = OPC_ADDIU;
16986 do_addi:
16987 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16988 break;
16990 /* Logical operations */
16991 case ORI32:
16992 mips32_op = OPC_ORI;
16993 goto do_logici;
16994 case XORI32:
16995 mips32_op = OPC_XORI;
16996 goto do_logici;
16997 case ANDI32:
16998 mips32_op = OPC_ANDI;
16999 do_logici:
17000 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17001 break;
17003 /* Set less than immediate */
17004 case SLTI32:
17005 mips32_op = OPC_SLTI;
17006 goto do_slti;
17007 case SLTIU32:
17008 mips32_op = OPC_SLTIU;
17009 do_slti:
17010 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17011 break;
17012 case JALX32:
17013 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17014 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17015 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17016 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17017 break;
17018 case JALS32: /* BOVC, BEQC, BEQZALC */
17019 if (ctx->insn_flags & ISA_MIPS32R6) {
17020 if (rs >= rt) {
17021 /* BOVC */
17022 mips32_op = OPC_BOVC;
17023 } else if (rs < rt && rs == 0) {
17024 /* BEQZALC */
17025 mips32_op = OPC_BEQZALC;
17026 } else {
17027 /* BEQC */
17028 mips32_op = OPC_BEQC;
17030 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17031 } else {
17032 /* JALS32 */
17033 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17034 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17035 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17037 break;
17038 case BEQ32: /* BC */
17039 if (ctx->insn_flags & ISA_MIPS32R6) {
17040 /* BC */
17041 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17042 sextract32(ctx->opcode << 1, 0, 27));
17043 } else {
17044 /* BEQ32 */
17045 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17047 break;
17048 case BNE32: /* BALC */
17049 if (ctx->insn_flags & ISA_MIPS32R6) {
17050 /* BALC */
17051 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17052 sextract32(ctx->opcode << 1, 0, 27));
17053 } else {
17054 /* BNE32 */
17055 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17057 break;
17058 case J32: /* BGTZC, BLTZC, BLTC */
17059 if (ctx->insn_flags & ISA_MIPS32R6) {
17060 if (rs == 0 && rt != 0) {
17061 /* BGTZC */
17062 mips32_op = OPC_BGTZC;
17063 } else if (rs != 0 && rt != 0 && rs == rt) {
17064 /* BLTZC */
17065 mips32_op = OPC_BLTZC;
17066 } else {
17067 /* BLTC */
17068 mips32_op = OPC_BLTC;
17070 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17071 } else {
17072 /* J32 */
17073 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17074 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17076 break;
17077 case JAL32: /* BLEZC, BGEZC, BGEC */
17078 if (ctx->insn_flags & ISA_MIPS32R6) {
17079 if (rs == 0 && rt != 0) {
17080 /* BLEZC */
17081 mips32_op = OPC_BLEZC;
17082 } else if (rs != 0 && rt != 0 && rs == rt) {
17083 /* BGEZC */
17084 mips32_op = OPC_BGEZC;
17085 } else {
17086 /* BGEC */
17087 mips32_op = OPC_BGEC;
17089 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17090 } else {
17091 /* JAL32 */
17092 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17093 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17094 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17096 break;
17097 /* Floating point (COP1) */
17098 case LWC132:
17099 mips32_op = OPC_LWC1;
17100 goto do_cop1;
17101 case LDC132:
17102 mips32_op = OPC_LDC1;
17103 goto do_cop1;
17104 case SWC132:
17105 mips32_op = OPC_SWC1;
17106 goto do_cop1;
17107 case SDC132:
17108 mips32_op = OPC_SDC1;
17109 do_cop1:
17110 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17111 break;
17112 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17113 if (ctx->insn_flags & ISA_MIPS32R6) {
17114 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17115 switch ((ctx->opcode >> 16) & 0x1f) {
17116 case ADDIUPC_00:
17117 case ADDIUPC_01:
17118 case ADDIUPC_02:
17119 case ADDIUPC_03:
17120 case ADDIUPC_04:
17121 case ADDIUPC_05:
17122 case ADDIUPC_06:
17123 case ADDIUPC_07:
17124 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17125 break;
17126 case AUIPC:
17127 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17128 break;
17129 case ALUIPC:
17130 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17131 break;
17132 case LWPC_08:
17133 case LWPC_09:
17134 case LWPC_0A:
17135 case LWPC_0B:
17136 case LWPC_0C:
17137 case LWPC_0D:
17138 case LWPC_0E:
17139 case LWPC_0F:
17140 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17141 break;
17142 default:
17143 generate_exception(ctx, EXCP_RI);
17144 break;
17146 } else {
17147 /* ADDIUPC */
17148 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17149 offset = SIMM(ctx->opcode, 0, 23) << 2;
17151 gen_addiupc(ctx, reg, offset, 0, 0);
17153 break;
17154 case BNVC: /* BNEC, BNEZALC */
17155 check_insn(ctx, ISA_MIPS32R6);
17156 if (rs >= rt) {
17157 /* BNVC */
17158 mips32_op = OPC_BNVC;
17159 } else if (rs < rt && rs == 0) {
17160 /* BNEZALC */
17161 mips32_op = OPC_BNEZALC;
17162 } else {
17163 /* BNEC */
17164 mips32_op = OPC_BNEC;
17166 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17167 break;
17168 case R6_BNEZC: /* JIALC */
17169 check_insn(ctx, ISA_MIPS32R6);
17170 if (rt != 0) {
17171 /* BNEZC */
17172 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17173 sextract32(ctx->opcode << 1, 0, 22));
17174 } else {
17175 /* JIALC */
17176 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17178 break;
17179 case R6_BEQZC: /* JIC */
17180 check_insn(ctx, ISA_MIPS32R6);
17181 if (rt != 0) {
17182 /* BEQZC */
17183 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17184 sextract32(ctx->opcode << 1, 0, 22));
17185 } else {
17186 /* JIC */
17187 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17189 break;
17190 case BLEZALC: /* BGEZALC, BGEUC */
17191 check_insn(ctx, ISA_MIPS32R6);
17192 if (rs == 0 && rt != 0) {
17193 /* BLEZALC */
17194 mips32_op = OPC_BLEZALC;
17195 } else if (rs != 0 && rt != 0 && rs == rt) {
17196 /* BGEZALC */
17197 mips32_op = OPC_BGEZALC;
17198 } else {
17199 /* BGEUC */
17200 mips32_op = OPC_BGEUC;
17202 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17203 break;
17204 case BGTZALC: /* BLTZALC, BLTUC */
17205 check_insn(ctx, ISA_MIPS32R6);
17206 if (rs == 0 && rt != 0) {
17207 /* BGTZALC */
17208 mips32_op = OPC_BGTZALC;
17209 } else if (rs != 0 && rt != 0 && rs == rt) {
17210 /* BLTZALC */
17211 mips32_op = OPC_BLTZALC;
17212 } else {
17213 /* BLTUC */
17214 mips32_op = OPC_BLTUC;
17216 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17217 break;
17218 /* Loads and stores */
17219 case LB32:
17220 mips32_op = OPC_LB;
17221 goto do_ld;
17222 case LBU32:
17223 mips32_op = OPC_LBU;
17224 goto do_ld;
17225 case LH32:
17226 mips32_op = OPC_LH;
17227 goto do_ld;
17228 case LHU32:
17229 mips32_op = OPC_LHU;
17230 goto do_ld;
17231 case LW32:
17232 mips32_op = OPC_LW;
17233 goto do_ld;
17234 #ifdef TARGET_MIPS64
17235 case LD32:
17236 check_insn(ctx, ISA_MIPS3);
17237 check_mips_64(ctx);
17238 mips32_op = OPC_LD;
17239 goto do_ld;
17240 case SD32:
17241 check_insn(ctx, ISA_MIPS3);
17242 check_mips_64(ctx);
17243 mips32_op = OPC_SD;
17244 goto do_st;
17245 #endif
17246 case SB32:
17247 mips32_op = OPC_SB;
17248 goto do_st;
17249 case SH32:
17250 mips32_op = OPC_SH;
17251 goto do_st;
17252 case SW32:
17253 mips32_op = OPC_SW;
17254 goto do_st;
17255 do_ld:
17256 gen_ld(ctx, mips32_op, rt, rs, imm);
17257 break;
17258 do_st:
17259 gen_st(ctx, mips32_op, rt, rs, imm);
17260 break;
17261 default:
17262 generate_exception_end(ctx, EXCP_RI);
17263 break;
17267 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
17269 uint32_t op;
17271 /* make sure instructions are on a halfword boundary */
17272 if (ctx->base.pc_next & 0x1) {
17273 env->CP0_BadVAddr = ctx->base.pc_next;
17274 generate_exception_end(ctx, EXCP_AdEL);
17275 return 2;
17278 op = (ctx->opcode >> 10) & 0x3f;
17279 /* Enforce properly-sized instructions in a delay slot */
17280 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17281 switch (op & 0x7) { /* MSB-3..MSB-5 */
17282 case 0:
17283 /* POOL32A, POOL32B, POOL32I, POOL32C */
17284 case 4:
17285 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17286 case 5:
17287 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17288 case 6:
17289 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17290 case 7:
17291 /* LB32, LH32, LWC132, LDC132, LW32 */
17292 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17293 generate_exception_end(ctx, EXCP_RI);
17294 return 2;
17296 break;
17297 case 1:
17298 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17299 case 2:
17300 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17301 case 3:
17302 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17303 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17304 generate_exception_end(ctx, EXCP_RI);
17305 return 2;
17307 break;
17311 switch (op) {
17312 case POOL16A:
17314 int rd = mmreg(uMIPS_RD(ctx->opcode));
17315 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17316 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17317 uint32_t opc = 0;
17319 switch (ctx->opcode & 0x1) {
17320 case ADDU16:
17321 opc = OPC_ADDU;
17322 break;
17323 case SUBU16:
17324 opc = OPC_SUBU;
17325 break;
17327 if (ctx->insn_flags & ISA_MIPS32R6) {
17328 /* In the Release 6 the register number location in
17329 * the instruction encoding has changed.
17331 gen_arith(ctx, opc, rs1, rd, rs2);
17332 } else {
17333 gen_arith(ctx, opc, rd, rs1, rs2);
17336 break;
17337 case POOL16B:
17339 int rd = mmreg(uMIPS_RD(ctx->opcode));
17340 int rs = mmreg(uMIPS_RS(ctx->opcode));
17341 int amount = (ctx->opcode >> 1) & 0x7;
17342 uint32_t opc = 0;
17343 amount = amount == 0 ? 8 : amount;
17345 switch (ctx->opcode & 0x1) {
17346 case SLL16:
17347 opc = OPC_SLL;
17348 break;
17349 case SRL16:
17350 opc = OPC_SRL;
17351 break;
17354 gen_shift_imm(ctx, opc, rd, rs, amount);
17356 break;
17357 case POOL16C:
17358 if (ctx->insn_flags & ISA_MIPS32R6) {
17359 gen_pool16c_r6_insn(ctx);
17360 } else {
17361 gen_pool16c_insn(ctx);
17363 break;
17364 case LWGP16:
17366 int rd = mmreg(uMIPS_RD(ctx->opcode));
17367 int rb = 28; /* GP */
17368 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17370 gen_ld(ctx, OPC_LW, rd, rb, offset);
17372 break;
17373 case POOL16F:
17374 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17375 if (ctx->opcode & 1) {
17376 generate_exception_end(ctx, EXCP_RI);
17377 } else {
17378 /* MOVEP */
17379 int enc_dest = uMIPS_RD(ctx->opcode);
17380 int enc_rt = uMIPS_RS2(ctx->opcode);
17381 int enc_rs = uMIPS_RS1(ctx->opcode);
17382 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17384 break;
17385 case LBU16:
17387 int rd = mmreg(uMIPS_RD(ctx->opcode));
17388 int rb = mmreg(uMIPS_RS(ctx->opcode));
17389 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17390 offset = (offset == 0xf ? -1 : offset);
17392 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17394 break;
17395 case LHU16:
17397 int rd = mmreg(uMIPS_RD(ctx->opcode));
17398 int rb = mmreg(uMIPS_RS(ctx->opcode));
17399 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17401 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17403 break;
17404 case LWSP16:
17406 int rd = (ctx->opcode >> 5) & 0x1f;
17407 int rb = 29; /* SP */
17408 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17410 gen_ld(ctx, OPC_LW, rd, rb, offset);
17412 break;
17413 case LW16:
17415 int rd = mmreg(uMIPS_RD(ctx->opcode));
17416 int rb = mmreg(uMIPS_RS(ctx->opcode));
17417 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17419 gen_ld(ctx, OPC_LW, rd, rb, offset);
17421 break;
17422 case SB16:
17424 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17425 int rb = mmreg(uMIPS_RS(ctx->opcode));
17426 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17428 gen_st(ctx, OPC_SB, rd, rb, offset);
17430 break;
17431 case SH16:
17433 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17434 int rb = mmreg(uMIPS_RS(ctx->opcode));
17435 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17437 gen_st(ctx, OPC_SH, rd, rb, offset);
17439 break;
17440 case SWSP16:
17442 int rd = (ctx->opcode >> 5) & 0x1f;
17443 int rb = 29; /* SP */
17444 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17446 gen_st(ctx, OPC_SW, rd, rb, offset);
17448 break;
17449 case SW16:
17451 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17452 int rb = mmreg(uMIPS_RS(ctx->opcode));
17453 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17455 gen_st(ctx, OPC_SW, rd, rb, offset);
17457 break;
17458 case MOVE16:
17460 int rd = uMIPS_RD5(ctx->opcode);
17461 int rs = uMIPS_RS5(ctx->opcode);
17463 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17465 break;
17466 case ANDI16:
17467 gen_andi16(ctx);
17468 break;
17469 case POOL16D:
17470 switch (ctx->opcode & 0x1) {
17471 case ADDIUS5:
17472 gen_addius5(ctx);
17473 break;
17474 case ADDIUSP:
17475 gen_addiusp(ctx);
17476 break;
17478 break;
17479 case POOL16E:
17480 switch (ctx->opcode & 0x1) {
17481 case ADDIUR2:
17482 gen_addiur2(ctx);
17483 break;
17484 case ADDIUR1SP:
17485 gen_addiur1sp(ctx);
17486 break;
17488 break;
17489 case B16: /* BC16 */
17490 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17491 sextract32(ctx->opcode, 0, 10) << 1,
17492 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17493 break;
17494 case BNEZ16: /* BNEZC16 */
17495 case BEQZ16: /* BEQZC16 */
17496 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17497 mmreg(uMIPS_RD(ctx->opcode)),
17498 0, sextract32(ctx->opcode, 0, 7) << 1,
17499 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17501 break;
17502 case LI16:
17504 int reg = mmreg(uMIPS_RD(ctx->opcode));
17505 int imm = ZIMM(ctx->opcode, 0, 7);
17507 imm = (imm == 0x7f ? -1 : imm);
17508 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17510 break;
17511 case RES_29:
17512 case RES_31:
17513 case RES_39:
17514 generate_exception_end(ctx, EXCP_RI);
17515 break;
17516 default:
17517 decode_micromips32_opc(env, ctx);
17518 return 4;
17521 return 2;
17526 * nanoMIPS opcodes
17530 /* MAJOR, P16, and P32 pools opcodes */
17531 enum {
17532 NM_P_ADDIU = 0x00,
17533 NM_ADDIUPC = 0x01,
17534 NM_MOVE_BALC = 0x02,
17535 NM_P16_MV = 0x04,
17536 NM_LW16 = 0x05,
17537 NM_BC16 = 0x06,
17538 NM_P16_SR = 0x07,
17540 NM_POOL32A = 0x08,
17541 NM_P_BAL = 0x0a,
17542 NM_P16_SHIFT = 0x0c,
17543 NM_LWSP16 = 0x0d,
17544 NM_BALC16 = 0x0e,
17545 NM_P16_4X4 = 0x0f,
17547 NM_P_GP_W = 0x10,
17548 NM_P_GP_BH = 0x11,
17549 NM_P_J = 0x12,
17550 NM_P16C = 0x14,
17551 NM_LWGP16 = 0x15,
17552 NM_P16_LB = 0x17,
17554 NM_P48I = 0x18,
17555 NM_P16_A1 = 0x1c,
17556 NM_LW4X4 = 0x1d,
17557 NM_P16_LH = 0x1f,
17559 NM_P_U12 = 0x20,
17560 NM_P_LS_U12 = 0x21,
17561 NM_P_BR1 = 0x22,
17562 NM_P16_A2 = 0x24,
17563 NM_SW16 = 0x25,
17564 NM_BEQZC16 = 0x26,
17566 NM_POOL32F = 0x28,
17567 NM_P_LS_S9 = 0x29,
17568 NM_P_BR2 = 0x2a,
17570 NM_P16_ADDU = 0x2c,
17571 NM_SWSP16 = 0x2d,
17572 NM_BNEZC16 = 0x2e,
17573 NM_MOVEP = 0x2f,
17575 NM_POOL32S = 0x30,
17576 NM_P_BRI = 0x32,
17577 NM_LI16 = 0x34,
17578 NM_SWGP16 = 0x35,
17579 NM_P16_BR = 0x36,
17581 NM_P_LUI = 0x38,
17582 NM_ANDI16 = 0x3c,
17583 NM_SW4X4 = 0x3d,
17584 NM_MOVEPREV = 0x3f,
17587 /* POOL32A instruction pool */
17588 enum {
17589 NM_POOL32A0 = 0x00,
17590 NM_SPECIAL2 = 0x01,
17591 NM_COP2_1 = 0x02,
17592 NM_UDI = 0x03,
17593 NM_POOL32A5 = 0x05,
17594 NM_POOL32A7 = 0x07,
17597 /* P.GP.W instruction pool */
17598 enum {
17599 NM_ADDIUGP_W = 0x00,
17600 NM_LWGP = 0x02,
17601 NM_SWGP = 0x03,
17604 /* P48I instruction pool */
17605 enum {
17606 NM_LI48 = 0x00,
17607 NM_ADDIU48 = 0x01,
17608 NM_ADDIUGP48 = 0x02,
17609 NM_ADDIUPC48 = 0x03,
17610 NM_LWPC48 = 0x0b,
17611 NM_SWPC48 = 0x0f,
17614 /* P.U12 instruction pool */
17615 enum {
17616 NM_ORI = 0x00,
17617 NM_XORI = 0x01,
17618 NM_ANDI = 0x02,
17619 NM_P_SR = 0x03,
17620 NM_SLTI = 0x04,
17621 NM_SLTIU = 0x05,
17622 NM_SEQI = 0x06,
17623 NM_ADDIUNEG = 0x08,
17624 NM_P_SHIFT = 0x0c,
17625 NM_P_ROTX = 0x0d,
17626 NM_P_INS = 0x0e,
17627 NM_P_EXT = 0x0f,
17630 /* POOL32F instruction pool */
17631 enum {
17632 NM_POOL32F_0 = 0x00,
17633 NM_POOL32F_3 = 0x03,
17634 NM_POOL32F_5 = 0x05,
17637 /* POOL32S instruction pool */
17638 enum {
17639 NM_POOL32S_0 = 0x00,
17640 NM_POOL32S_4 = 0x04,
17643 /* P.LUI instruction pool */
17644 enum {
17645 NM_LUI = 0x00,
17646 NM_ALUIPC = 0x01,
17649 /* P.GP.BH instruction pool */
17650 enum {
17651 NM_LBGP = 0x00,
17652 NM_SBGP = 0x01,
17653 NM_LBUGP = 0x02,
17654 NM_ADDIUGP_B = 0x03,
17655 NM_P_GP_LH = 0x04,
17656 NM_P_GP_SH = 0x05,
17657 NM_P_GP_CP1 = 0x06,
17660 /* P.LS.U12 instruction pool */
17661 enum {
17662 NM_LB = 0x00,
17663 NM_SB = 0x01,
17664 NM_LBU = 0x02,
17665 NM_P_PREFU12 = 0x03,
17666 NM_LH = 0x04,
17667 NM_SH = 0x05,
17668 NM_LHU = 0x06,
17669 NM_LWU = 0x07,
17670 NM_LW = 0x08,
17671 NM_SW = 0x09,
17672 NM_LWC1 = 0x0a,
17673 NM_SWC1 = 0x0b,
17674 NM_LDC1 = 0x0e,
17675 NM_SDC1 = 0x0f,
17678 /* P.LS.S9 instruction pool */
17679 enum {
17680 NM_P_LS_S0 = 0x00,
17681 NM_P_LS_S1 = 0x01,
17682 NM_P_LS_E0 = 0x02,
17683 NM_P_LS_WM = 0x04,
17684 NM_P_LS_UAWM = 0x05,
17687 /* P.BAL instruction pool */
17688 enum {
17689 NM_BC = 0x00,
17690 NM_BALC = 0x01,
17693 /* P.J instruction pool */
17694 enum {
17695 NM_JALRC = 0x00,
17696 NM_JALRC_HB = 0x01,
17697 NM_P_BALRSC = 0x08,
17700 /* P.BR1 instruction pool */
17701 enum {
17702 NM_BEQC = 0x00,
17703 NM_P_BR3A = 0x01,
17704 NM_BGEC = 0x02,
17705 NM_BGEUC = 0x03,
17708 /* P.BR2 instruction pool */
17709 enum {
17710 NM_BNEC = 0x00,
17711 NM_BLTC = 0x02,
17712 NM_BLTUC = 0x03,
17715 /* P.BRI instruction pool */
17716 enum {
17717 NM_BEQIC = 0x00,
17718 NM_BBEQZC = 0x01,
17719 NM_BGEIC = 0x02,
17720 NM_BGEIUC = 0x03,
17721 NM_BNEIC = 0x04,
17722 NM_BBNEZC = 0x05,
17723 NM_BLTIC = 0x06,
17724 NM_BLTIUC = 0x07,
17727 /* P16.SHIFT instruction pool */
17728 enum {
17729 NM_SLL16 = 0x00,
17730 NM_SRL16 = 0x01,
17733 /* POOL16C instruction pool */
17734 enum {
17735 NM_POOL16C_0 = 0x00,
17736 NM_LWXS16 = 0x01,
17739 /* P16.A1 instruction pool */
17740 enum {
17741 NM_ADDIUR1SP = 0x01,
17744 /* P16.A2 instruction pool */
17745 enum {
17746 NM_ADDIUR2 = 0x00,
17747 NM_P_ADDIURS5 = 0x01,
17750 /* P16.ADDU instruction pool */
17751 enum {
17752 NM_ADDU16 = 0x00,
17753 NM_SUBU16 = 0x01,
17756 /* P16.SR instruction pool */
17757 enum {
17758 NM_SAVE16 = 0x00,
17759 NM_RESTORE_JRC16 = 0x01,
17762 /* P16.4X4 instruction pool */
17763 enum {
17764 NM_ADDU4X4 = 0x00,
17765 NM_MUL4X4 = 0x01,
17768 /* P16.LB instruction pool */
17769 enum {
17770 NM_LB16 = 0x00,
17771 NM_SB16 = 0x01,
17772 NM_LBU16 = 0x02,
17775 /* P16.LH instruction pool */
17776 enum {
17777 NM_LH16 = 0x00,
17778 NM_SH16 = 0x01,
17779 NM_LHU16 = 0x02,
17782 /* P.RI instruction pool */
17783 enum {
17784 NM_SIGRIE = 0x00,
17785 NM_P_SYSCALL = 0x01,
17786 NM_BREAK = 0x02,
17787 NM_SDBBP = 0x03,
17790 /* POOL32A0 instruction pool */
17791 enum {
17792 NM_P_TRAP = 0x00,
17793 NM_SEB = 0x01,
17794 NM_SLLV = 0x02,
17795 NM_MUL = 0x03,
17796 NM_MFC0 = 0x06,
17797 NM_MFHC0 = 0x07,
17798 NM_SEH = 0x09,
17799 NM_SRLV = 0x0a,
17800 NM_MUH = 0x0b,
17801 NM_MTC0 = 0x0e,
17802 NM_MTHC0 = 0x0f,
17803 NM_SRAV = 0x12,
17804 NM_MULU = 0x13,
17805 NM_ROTRV = 0x1a,
17806 NM_MUHU = 0x1b,
17807 NM_ADD = 0x22,
17808 NM_DIV = 0x23,
17809 NM_ADDU = 0x2a,
17810 NM_MOD = 0x2b,
17811 NM_SUB = 0x32,
17812 NM_DIVU = 0x33,
17813 NM_RDHWR = 0x38,
17814 NM_SUBU = 0x3a,
17815 NM_MODU = 0x3b,
17816 NM_P_CMOVE = 0x42,
17817 NM_FORK = 0x45,
17818 NM_MFTR = 0x46,
17819 NM_MFHTR = 0x47,
17820 NM_AND = 0x4a,
17821 NM_YIELD = 0x4d,
17822 NM_MTTR = 0x4e,
17823 NM_MTHTR = 0x4f,
17824 NM_OR = 0x52,
17825 NM_D_E_MT_VPE = 0x56,
17826 NM_NOR = 0x5a,
17827 NM_XOR = 0x62,
17828 NM_SLT = 0x6a,
17829 NM_P_SLTU = 0x72,
17830 NM_SOV = 0x7a,
17833 /* CRC32 instruction pool */
17834 enum {
17835 NM_CRC32B = 0x00,
17836 NM_CRC32H = 0x01,
17837 NM_CRC32W = 0x02,
17838 NM_CRC32CB = 0x04,
17839 NM_CRC32CH = 0x05,
17840 NM_CRC32CW = 0x06,
17843 /* POOL32A5 instruction pool */
17844 enum {
17845 NM_CMP_EQ_PH = 0x00,
17846 NM_CMP_LT_PH = 0x08,
17847 NM_CMP_LE_PH = 0x10,
17848 NM_CMPGU_EQ_QB = 0x18,
17849 NM_CMPGU_LT_QB = 0x20,
17850 NM_CMPGU_LE_QB = 0x28,
17851 NM_CMPGDU_EQ_QB = 0x30,
17852 NM_CMPGDU_LT_QB = 0x38,
17853 NM_CMPGDU_LE_QB = 0x40,
17854 NM_CMPU_EQ_QB = 0x48,
17855 NM_CMPU_LT_QB = 0x50,
17856 NM_CMPU_LE_QB = 0x58,
17857 NM_ADDQ_S_W = 0x60,
17858 NM_SUBQ_S_W = 0x68,
17859 NM_ADDSC = 0x70,
17860 NM_ADDWC = 0x78,
17862 NM_ADDQ_S_PH = 0x01,
17863 NM_ADDQH_R_PH = 0x09,
17864 NM_ADDQH_R_W = 0x11,
17865 NM_ADDU_S_QB = 0x19,
17866 NM_ADDU_S_PH = 0x21,
17867 NM_ADDUH_R_QB = 0x29,
17868 NM_SHRAV_R_PH = 0x31,
17869 NM_SHRAV_R_QB = 0x39,
17870 NM_SUBQ_S_PH = 0x41,
17871 NM_SUBQH_R_PH = 0x49,
17872 NM_SUBQH_R_W = 0x51,
17873 NM_SUBU_S_QB = 0x59,
17874 NM_SUBU_S_PH = 0x61,
17875 NM_SUBUH_R_QB = 0x69,
17876 NM_SHLLV_S_PH = 0x71,
17877 NM_PRECR_SRA_R_PH_W = 0x79,
17879 NM_MULEU_S_PH_QBL = 0x12,
17880 NM_MULEU_S_PH_QBR = 0x1a,
17881 NM_MULQ_RS_PH = 0x22,
17882 NM_MULQ_S_PH = 0x2a,
17883 NM_MULQ_RS_W = 0x32,
17884 NM_MULQ_S_W = 0x3a,
17885 NM_APPEND = 0x42,
17886 NM_MODSUB = 0x52,
17887 NM_SHRAV_R_W = 0x5a,
17888 NM_SHRLV_PH = 0x62,
17889 NM_SHRLV_QB = 0x6a,
17890 NM_SHLLV_QB = 0x72,
17891 NM_SHLLV_S_W = 0x7a,
17893 NM_SHILO = 0x03,
17895 NM_MULEQ_S_W_PHL = 0x04,
17896 NM_MULEQ_S_W_PHR = 0x0c,
17898 NM_MUL_S_PH = 0x05,
17899 NM_PRECR_QB_PH = 0x0d,
17900 NM_PRECRQ_QB_PH = 0x15,
17901 NM_PRECRQ_PH_W = 0x1d,
17902 NM_PRECRQ_RS_PH_W = 0x25,
17903 NM_PRECRQU_S_QB_PH = 0x2d,
17904 NM_PACKRL_PH = 0x35,
17905 NM_PICK_QB = 0x3d,
17906 NM_PICK_PH = 0x45,
17908 NM_SHRA_R_W = 0x5e,
17909 NM_SHRA_R_PH = 0x66,
17910 NM_SHLL_S_PH = 0x76,
17911 NM_SHLL_S_W = 0x7e,
17913 NM_REPL_PH = 0x07
17916 /* POOL32A7 instruction pool */
17917 enum {
17918 NM_P_LSX = 0x00,
17919 NM_LSA = 0x01,
17920 NM_EXTW = 0x03,
17921 NM_POOL32AXF = 0x07,
17924 /* P.SR instruction pool */
17925 enum {
17926 NM_PP_SR = 0x00,
17927 NM_P_SR_F = 0x01,
17930 /* P.SHIFT instruction pool */
17931 enum {
17932 NM_P_SLL = 0x00,
17933 NM_SRL = 0x02,
17934 NM_SRA = 0x04,
17935 NM_ROTR = 0x06,
17938 /* P.ROTX instruction pool */
17939 enum {
17940 NM_ROTX = 0x00,
17943 /* P.INS instruction pool */
17944 enum {
17945 NM_INS = 0x00,
17948 /* P.EXT instruction pool */
17949 enum {
17950 NM_EXT = 0x00,
17953 /* POOL32F_0 (fmt) instruction pool */
17954 enum {
17955 NM_RINT_S = 0x04,
17956 NM_RINT_D = 0x44,
17957 NM_ADD_S = 0x06,
17958 NM_SELEQZ_S = 0x07,
17959 NM_SELEQZ_D = 0x47,
17960 NM_CLASS_S = 0x0c,
17961 NM_CLASS_D = 0x4c,
17962 NM_SUB_S = 0x0e,
17963 NM_SELNEZ_S = 0x0f,
17964 NM_SELNEZ_D = 0x4f,
17965 NM_MUL_S = 0x16,
17966 NM_SEL_S = 0x17,
17967 NM_SEL_D = 0x57,
17968 NM_DIV_S = 0x1e,
17969 NM_ADD_D = 0x26,
17970 NM_SUB_D = 0x2e,
17971 NM_MUL_D = 0x36,
17972 NM_MADDF_S = 0x37,
17973 NM_MADDF_D = 0x77,
17974 NM_DIV_D = 0x3e,
17975 NM_MSUBF_S = 0x3f,
17976 NM_MSUBF_D = 0x7f,
17979 /* POOL32F_3 instruction pool */
17980 enum {
17981 NM_MIN_FMT = 0x00,
17982 NM_MAX_FMT = 0x01,
17983 NM_MINA_FMT = 0x04,
17984 NM_MAXA_FMT = 0x05,
17985 NM_POOL32FXF = 0x07,
17988 /* POOL32F_5 instruction pool */
17989 enum {
17990 NM_CMP_CONDN_S = 0x00,
17991 NM_CMP_CONDN_D = 0x02,
17994 /* P.GP.LH instruction pool */
17995 enum {
17996 NM_LHGP = 0x00,
17997 NM_LHUGP = 0x01,
18000 /* P.GP.SH instruction pool */
18001 enum {
18002 NM_SHGP = 0x00,
18005 /* P.GP.CP1 instruction pool */
18006 enum {
18007 NM_LWC1GP = 0x00,
18008 NM_SWC1GP = 0x01,
18009 NM_LDC1GP = 0x02,
18010 NM_SDC1GP = 0x03,
18013 /* P.LS.S0 instruction pool */
18014 enum {
18015 NM_LBS9 = 0x00,
18016 NM_LHS9 = 0x04,
18017 NM_LWS9 = 0x08,
18018 NM_LDS9 = 0x0c,
18020 NM_SBS9 = 0x01,
18021 NM_SHS9 = 0x05,
18022 NM_SWS9 = 0x09,
18023 NM_SDS9 = 0x0d,
18025 NM_LBUS9 = 0x02,
18026 NM_LHUS9 = 0x06,
18027 NM_LWC1S9 = 0x0a,
18028 NM_LDC1S9 = 0x0e,
18030 NM_P_PREFS9 = 0x03,
18031 NM_LWUS9 = 0x07,
18032 NM_SWC1S9 = 0x0b,
18033 NM_SDC1S9 = 0x0f,
18036 /* P.LS.S1 instruction pool */
18037 enum {
18038 NM_ASET_ACLR = 0x02,
18039 NM_UALH = 0x04,
18040 NM_UASH = 0x05,
18041 NM_CACHE = 0x07,
18042 NM_P_LL = 0x0a,
18043 NM_P_SC = 0x0b,
18046 /* P.LS.E0 instruction pool */
18047 enum {
18048 NM_LBE = 0x00,
18049 NM_SBE = 0x01,
18050 NM_LBUE = 0x02,
18051 NM_P_PREFE = 0x03,
18052 NM_LHE = 0x04,
18053 NM_SHE = 0x05,
18054 NM_LHUE = 0x06,
18055 NM_CACHEE = 0x07,
18056 NM_LWE = 0x08,
18057 NM_SWE = 0x09,
18058 NM_P_LLE = 0x0a,
18059 NM_P_SCE = 0x0b,
18062 /* P.PREFE instruction pool */
18063 enum {
18064 NM_SYNCIE = 0x00,
18065 NM_PREFE = 0x01,
18068 /* P.LLE instruction pool */
18069 enum {
18070 NM_LLE = 0x00,
18071 NM_LLWPE = 0x01,
18074 /* P.SCE instruction pool */
18075 enum {
18076 NM_SCE = 0x00,
18077 NM_SCWPE = 0x01,
18080 /* P.LS.WM instruction pool */
18081 enum {
18082 NM_LWM = 0x00,
18083 NM_SWM = 0x01,
18086 /* P.LS.UAWM instruction pool */
18087 enum {
18088 NM_UALWM = 0x00,
18089 NM_UASWM = 0x01,
18092 /* P.BR3A instruction pool */
18093 enum {
18094 NM_BC1EQZC = 0x00,
18095 NM_BC1NEZC = 0x01,
18096 NM_BC2EQZC = 0x02,
18097 NM_BC2NEZC = 0x03,
18098 NM_BPOSGE32C = 0x04,
18101 /* P16.RI instruction pool */
18102 enum {
18103 NM_P16_SYSCALL = 0x01,
18104 NM_BREAK16 = 0x02,
18105 NM_SDBBP16 = 0x03,
18108 /* POOL16C_0 instruction pool */
18109 enum {
18110 NM_POOL16C_00 = 0x00,
18113 /* P16.JRC instruction pool */
18114 enum {
18115 NM_JRC = 0x00,
18116 NM_JALRC16 = 0x01,
18119 /* P.SYSCALL instruction pool */
18120 enum {
18121 NM_SYSCALL = 0x00,
18122 NM_HYPCALL = 0x01,
18125 /* P.TRAP instruction pool */
18126 enum {
18127 NM_TEQ = 0x00,
18128 NM_TNE = 0x01,
18131 /* P.CMOVE instruction pool */
18132 enum {
18133 NM_MOVZ = 0x00,
18134 NM_MOVN = 0x01,
18137 /* POOL32Axf instruction pool */
18138 enum {
18139 NM_POOL32AXF_1 = 0x01,
18140 NM_POOL32AXF_2 = 0x02,
18141 NM_POOL32AXF_4 = 0x04,
18142 NM_POOL32AXF_5 = 0x05,
18143 NM_POOL32AXF_7 = 0x07,
18146 /* POOL32Axf_1 instruction pool */
18147 enum {
18148 NM_POOL32AXF_1_0 = 0x00,
18149 NM_POOL32AXF_1_1 = 0x01,
18150 NM_POOL32AXF_1_3 = 0x03,
18151 NM_POOL32AXF_1_4 = 0x04,
18152 NM_POOL32AXF_1_5 = 0x05,
18153 NM_POOL32AXF_1_7 = 0x07,
18156 /* POOL32Axf_2 instruction pool */
18157 enum {
18158 NM_POOL32AXF_2_0_7 = 0x00,
18159 NM_POOL32AXF_2_8_15 = 0x01,
18160 NM_POOL32AXF_2_16_23 = 0x02,
18161 NM_POOL32AXF_2_24_31 = 0x03,
18164 /* POOL32Axf_7 instruction pool */
18165 enum {
18166 NM_SHRA_R_QB = 0x0,
18167 NM_SHRL_PH = 0x1,
18168 NM_REPL_QB = 0x2,
18171 /* POOL32Axf_1_0 instruction pool */
18172 enum {
18173 NM_MFHI = 0x0,
18174 NM_MFLO = 0x1,
18175 NM_MTHI = 0x2,
18176 NM_MTLO = 0x3,
18179 /* POOL32Axf_1_1 instruction pool */
18180 enum {
18181 NM_MTHLIP = 0x0,
18182 NM_SHILOV = 0x1,
18185 /* POOL32Axf_1_3 instruction pool */
18186 enum {
18187 NM_RDDSP = 0x0,
18188 NM_WRDSP = 0x1,
18189 NM_EXTP = 0x2,
18190 NM_EXTPDP = 0x3,
18193 /* POOL32Axf_1_4 instruction pool */
18194 enum {
18195 NM_SHLL_QB = 0x0,
18196 NM_SHRL_QB = 0x1,
18199 /* POOL32Axf_1_5 instruction pool */
18200 enum {
18201 NM_MAQ_S_W_PHR = 0x0,
18202 NM_MAQ_S_W_PHL = 0x1,
18203 NM_MAQ_SA_W_PHR = 0x2,
18204 NM_MAQ_SA_W_PHL = 0x3,
18207 /* POOL32Axf_1_7 instruction pool */
18208 enum {
18209 NM_EXTR_W = 0x0,
18210 NM_EXTR_R_W = 0x1,
18211 NM_EXTR_RS_W = 0x2,
18212 NM_EXTR_S_H = 0x3,
18215 /* POOL32Axf_2_0_7 instruction pool */
18216 enum {
18217 NM_DPA_W_PH = 0x0,
18218 NM_DPAQ_S_W_PH = 0x1,
18219 NM_DPS_W_PH = 0x2,
18220 NM_DPSQ_S_W_PH = 0x3,
18221 NM_BALIGN = 0x4,
18222 NM_MADD = 0x5,
18223 NM_MULT = 0x6,
18224 NM_EXTRV_W = 0x7,
18227 /* POOL32Axf_2_8_15 instruction pool */
18228 enum {
18229 NM_DPAX_W_PH = 0x0,
18230 NM_DPAQ_SA_L_W = 0x1,
18231 NM_DPSX_W_PH = 0x2,
18232 NM_DPSQ_SA_L_W = 0x3,
18233 NM_MADDU = 0x5,
18234 NM_MULTU = 0x6,
18235 NM_EXTRV_R_W = 0x7,
18238 /* POOL32Axf_2_16_23 instruction pool */
18239 enum {
18240 NM_DPAU_H_QBL = 0x0,
18241 NM_DPAQX_S_W_PH = 0x1,
18242 NM_DPSU_H_QBL = 0x2,
18243 NM_DPSQX_S_W_PH = 0x3,
18244 NM_EXTPV = 0x4,
18245 NM_MSUB = 0x5,
18246 NM_MULSA_W_PH = 0x6,
18247 NM_EXTRV_RS_W = 0x7,
18250 /* POOL32Axf_2_24_31 instruction pool */
18251 enum {
18252 NM_DPAU_H_QBR = 0x0,
18253 NM_DPAQX_SA_W_PH = 0x1,
18254 NM_DPSU_H_QBR = 0x2,
18255 NM_DPSQX_SA_W_PH = 0x3,
18256 NM_EXTPDPV = 0x4,
18257 NM_MSUBU = 0x5,
18258 NM_MULSAQ_S_W_PH = 0x6,
18259 NM_EXTRV_S_H = 0x7,
18262 /* POOL32Axf_{4, 5} instruction pool */
18263 enum {
18264 NM_CLO = 0x25,
18265 NM_CLZ = 0x2d,
18267 NM_TLBP = 0x01,
18268 NM_TLBR = 0x09,
18269 NM_TLBWI = 0x11,
18270 NM_TLBWR = 0x19,
18271 NM_TLBINV = 0x03,
18272 NM_TLBINVF = 0x0b,
18273 NM_DI = 0x23,
18274 NM_EI = 0x2b,
18275 NM_RDPGPR = 0x70,
18276 NM_WRPGPR = 0x78,
18277 NM_WAIT = 0x61,
18278 NM_DERET = 0x71,
18279 NM_ERETX = 0x79,
18281 /* nanoMIPS DSP instructions */
18282 NM_ABSQ_S_QB = 0x00,
18283 NM_ABSQ_S_PH = 0x08,
18284 NM_ABSQ_S_W = 0x10,
18285 NM_PRECEQ_W_PHL = 0x28,
18286 NM_PRECEQ_W_PHR = 0x30,
18287 NM_PRECEQU_PH_QBL = 0x38,
18288 NM_PRECEQU_PH_QBR = 0x48,
18289 NM_PRECEU_PH_QBL = 0x58,
18290 NM_PRECEU_PH_QBR = 0x68,
18291 NM_PRECEQU_PH_QBLA = 0x39,
18292 NM_PRECEQU_PH_QBRA = 0x49,
18293 NM_PRECEU_PH_QBLA = 0x59,
18294 NM_PRECEU_PH_QBRA = 0x69,
18295 NM_REPLV_PH = 0x01,
18296 NM_REPLV_QB = 0x09,
18297 NM_BITREV = 0x18,
18298 NM_INSV = 0x20,
18299 NM_RADDU_W_QB = 0x78,
18301 NM_BITSWAP = 0x05,
18302 NM_WSBH = 0x3d,
18305 /* PP.SR instruction pool */
18306 enum {
18307 NM_SAVE = 0x00,
18308 NM_RESTORE = 0x02,
18309 NM_RESTORE_JRC = 0x03,
18312 /* P.SR.F instruction pool */
18313 enum {
18314 NM_SAVEF = 0x00,
18315 NM_RESTOREF = 0x01,
18318 /* P16.SYSCALL instruction pool */
18319 enum {
18320 NM_SYSCALL16 = 0x00,
18321 NM_HYPCALL16 = 0x01,
18324 /* POOL16C_00 instruction pool */
18325 enum {
18326 NM_NOT16 = 0x00,
18327 NM_XOR16 = 0x01,
18328 NM_AND16 = 0x02,
18329 NM_OR16 = 0x03,
18332 /* PP.LSX and PP.LSXS instruction pool */
18333 enum {
18334 NM_LBX = 0x00,
18335 NM_LHX = 0x04,
18336 NM_LWX = 0x08,
18337 NM_LDX = 0x0c,
18339 NM_SBX = 0x01,
18340 NM_SHX = 0x05,
18341 NM_SWX = 0x09,
18342 NM_SDX = 0x0d,
18344 NM_LBUX = 0x02,
18345 NM_LHUX = 0x06,
18346 NM_LWC1X = 0x0a,
18347 NM_LDC1X = 0x0e,
18349 NM_LWUX = 0x07,
18350 NM_SWC1X = 0x0b,
18351 NM_SDC1X = 0x0f,
18353 NM_LHXS = 0x04,
18354 NM_LWXS = 0x08,
18355 NM_LDXS = 0x0c,
18357 NM_SHXS = 0x05,
18358 NM_SWXS = 0x09,
18359 NM_SDXS = 0x0d,
18361 NM_LHUXS = 0x06,
18362 NM_LWC1XS = 0x0a,
18363 NM_LDC1XS = 0x0e,
18365 NM_LWUXS = 0x07,
18366 NM_SWC1XS = 0x0b,
18367 NM_SDC1XS = 0x0f,
18370 /* ERETx instruction pool */
18371 enum {
18372 NM_ERET = 0x00,
18373 NM_ERETNC = 0x01,
18376 /* POOL32FxF_{0, 1} insturction pool */
18377 enum {
18378 NM_CFC1 = 0x40,
18379 NM_CTC1 = 0x60,
18380 NM_MFC1 = 0x80,
18381 NM_MTC1 = 0xa0,
18382 NM_MFHC1 = 0xc0,
18383 NM_MTHC1 = 0xe0,
18385 NM_CVT_S_PL = 0x84,
18386 NM_CVT_S_PU = 0xa4,
18388 NM_CVT_L_S = 0x004,
18389 NM_CVT_L_D = 0x104,
18390 NM_CVT_W_S = 0x024,
18391 NM_CVT_W_D = 0x124,
18393 NM_RSQRT_S = 0x008,
18394 NM_RSQRT_D = 0x108,
18396 NM_SQRT_S = 0x028,
18397 NM_SQRT_D = 0x128,
18399 NM_RECIP_S = 0x048,
18400 NM_RECIP_D = 0x148,
18402 NM_FLOOR_L_S = 0x00c,
18403 NM_FLOOR_L_D = 0x10c,
18405 NM_FLOOR_W_S = 0x02c,
18406 NM_FLOOR_W_D = 0x12c,
18408 NM_CEIL_L_S = 0x04c,
18409 NM_CEIL_L_D = 0x14c,
18410 NM_CEIL_W_S = 0x06c,
18411 NM_CEIL_W_D = 0x16c,
18412 NM_TRUNC_L_S = 0x08c,
18413 NM_TRUNC_L_D = 0x18c,
18414 NM_TRUNC_W_S = 0x0ac,
18415 NM_TRUNC_W_D = 0x1ac,
18416 NM_ROUND_L_S = 0x0cc,
18417 NM_ROUND_L_D = 0x1cc,
18418 NM_ROUND_W_S = 0x0ec,
18419 NM_ROUND_W_D = 0x1ec,
18421 NM_MOV_S = 0x01,
18422 NM_MOV_D = 0x81,
18423 NM_ABS_S = 0x0d,
18424 NM_ABS_D = 0x8d,
18425 NM_NEG_S = 0x2d,
18426 NM_NEG_D = 0xad,
18427 NM_CVT_D_S = 0x04d,
18428 NM_CVT_D_W = 0x0cd,
18429 NM_CVT_D_L = 0x14d,
18430 NM_CVT_S_D = 0x06d,
18431 NM_CVT_S_W = 0x0ed,
18432 NM_CVT_S_L = 0x16d,
18435 /* P.LL instruction pool */
18436 enum {
18437 NM_LL = 0x00,
18438 NM_LLWP = 0x01,
18441 /* P.SC instruction pool */
18442 enum {
18443 NM_SC = 0x00,
18444 NM_SCWP = 0x01,
18447 /* P.DVP instruction pool */
18448 enum {
18449 NM_DVP = 0x00,
18450 NM_EVP = 0x01,
18456 * nanoMIPS decoding engine
18461 /* extraction utilities */
18463 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18464 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18465 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18466 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18467 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18468 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18470 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18471 static inline int decode_gpr_gpr3(int r)
18473 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18475 return map[r & 0x7];
18478 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18479 static inline int decode_gpr_gpr3_src_store(int r)
18481 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18483 return map[r & 0x7];
18486 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18487 static inline int decode_gpr_gpr4(int r)
18489 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18490 16, 17, 18, 19, 20, 21, 22, 23 };
18492 return map[r & 0xf];
18495 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18496 static inline int decode_gpr_gpr4_zero(int r)
18498 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18499 16, 17, 18, 19, 20, 21, 22, 23 };
18501 return map[r & 0xf];
18505 /* extraction utilities */
18507 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18508 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18509 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18510 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18511 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18512 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18515 static void gen_adjust_sp(DisasContext *ctx, int u)
18517 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18520 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18521 uint8_t gp, uint16_t u)
18523 int counter = 0;
18524 TCGv va = tcg_temp_new();
18525 TCGv t0 = tcg_temp_new();
18527 while (counter != count) {
18528 bool use_gp = gp && (counter == count - 1);
18529 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18530 int this_offset = -((counter + 1) << 2);
18531 gen_base_offset_addr(ctx, va, 29, this_offset);
18532 gen_load_gpr(t0, this_rt);
18533 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18534 (MO_TEUL | ctx->default_tcg_memop_mask));
18535 counter++;
18538 /* adjust stack pointer */
18539 gen_adjust_sp(ctx, -u);
18541 tcg_temp_free(t0);
18542 tcg_temp_free(va);
18545 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18546 uint8_t gp, uint16_t u)
18548 int counter = 0;
18549 TCGv va = tcg_temp_new();
18550 TCGv t0 = tcg_temp_new();
18552 while (counter != count) {
18553 bool use_gp = gp && (counter == count - 1);
18554 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18555 int this_offset = u - ((counter + 1) << 2);
18556 gen_base_offset_addr(ctx, va, 29, this_offset);
18557 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18558 ctx->default_tcg_memop_mask);
18559 tcg_gen_ext32s_tl(t0, t0);
18560 gen_store_gpr(t0, this_rt);
18561 counter++;
18564 /* adjust stack pointer */
18565 gen_adjust_sp(ctx, u);
18567 tcg_temp_free(t0);
18568 tcg_temp_free(va);
18571 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18573 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18574 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18576 switch (extract32(ctx->opcode, 2, 2)) {
18577 case NM_NOT16:
18578 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18579 break;
18580 case NM_AND16:
18581 gen_logic(ctx, OPC_AND, rt, rt, rs);
18582 break;
18583 case NM_XOR16:
18584 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18585 break;
18586 case NM_OR16:
18587 gen_logic(ctx, OPC_OR, rt, rt, rs);
18588 break;
18592 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18594 int rt = extract32(ctx->opcode, 21, 5);
18595 int rs = extract32(ctx->opcode, 16, 5);
18596 int rd = extract32(ctx->opcode, 11, 5);
18598 switch (extract32(ctx->opcode, 3, 7)) {
18599 case NM_P_TRAP:
18600 switch (extract32(ctx->opcode, 10, 1)) {
18601 case NM_TEQ:
18602 check_nms(ctx);
18603 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18604 break;
18605 case NM_TNE:
18606 check_nms(ctx);
18607 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18608 break;
18610 break;
18611 case NM_RDHWR:
18612 check_nms(ctx);
18613 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18614 break;
18615 case NM_SEB:
18616 check_nms(ctx);
18617 gen_bshfl(ctx, OPC_SEB, rs, rt);
18618 break;
18619 case NM_SEH:
18620 gen_bshfl(ctx, OPC_SEH, rs, rt);
18621 break;
18622 case NM_SLLV:
18623 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18624 break;
18625 case NM_SRLV:
18626 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18627 break;
18628 case NM_SRAV:
18629 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18630 break;
18631 case NM_ROTRV:
18632 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18633 break;
18634 case NM_ADD:
18635 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18636 break;
18637 case NM_ADDU:
18638 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18639 break;
18640 case NM_SUB:
18641 check_nms(ctx);
18642 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18643 break;
18644 case NM_SUBU:
18645 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18646 break;
18647 case NM_P_CMOVE:
18648 switch (extract32(ctx->opcode, 10, 1)) {
18649 case NM_MOVZ:
18650 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18651 break;
18652 case NM_MOVN:
18653 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18654 break;
18656 break;
18657 case NM_AND:
18658 gen_logic(ctx, OPC_AND, rd, rs, rt);
18659 break;
18660 case NM_OR:
18661 gen_logic(ctx, OPC_OR, rd, rs, rt);
18662 break;
18663 case NM_NOR:
18664 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18665 break;
18666 case NM_XOR:
18667 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18668 break;
18669 case NM_SLT:
18670 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18671 break;
18672 case NM_P_SLTU:
18673 if (rd == 0) {
18674 /* P_DVP */
18675 #ifndef CONFIG_USER_ONLY
18676 TCGv t0 = tcg_temp_new();
18677 switch (extract32(ctx->opcode, 10, 1)) {
18678 case NM_DVP:
18679 if (ctx->vp) {
18680 check_cp0_enabled(ctx);
18681 gen_helper_dvp(t0, cpu_env);
18682 gen_store_gpr(t0, rt);
18684 break;
18685 case NM_EVP:
18686 if (ctx->vp) {
18687 check_cp0_enabled(ctx);
18688 gen_helper_evp(t0, cpu_env);
18689 gen_store_gpr(t0, rt);
18691 break;
18693 tcg_temp_free(t0);
18694 #endif
18695 } else {
18696 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18698 break;
18699 case NM_SOV:
18701 TCGv t0 = tcg_temp_new();
18702 TCGv t1 = tcg_temp_new();
18703 TCGv t2 = tcg_temp_new();
18705 gen_load_gpr(t1, rs);
18706 gen_load_gpr(t2, rt);
18707 tcg_gen_add_tl(t0, t1, t2);
18708 tcg_gen_ext32s_tl(t0, t0);
18709 tcg_gen_xor_tl(t1, t1, t2);
18710 tcg_gen_xor_tl(t2, t0, t2);
18711 tcg_gen_andc_tl(t1, t2, t1);
18713 /* operands of same sign, result different sign */
18714 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18715 gen_store_gpr(t0, rd);
18717 tcg_temp_free(t0);
18718 tcg_temp_free(t1);
18719 tcg_temp_free(t2);
18721 break;
18722 case NM_MUL:
18723 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18724 break;
18725 case NM_MUH:
18726 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18727 break;
18728 case NM_MULU:
18729 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18730 break;
18731 case NM_MUHU:
18732 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18733 break;
18734 case NM_DIV:
18735 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18736 break;
18737 case NM_MOD:
18738 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18739 break;
18740 case NM_DIVU:
18741 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18742 break;
18743 case NM_MODU:
18744 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18745 break;
18746 #ifndef CONFIG_USER_ONLY
18747 case NM_MFC0:
18748 check_cp0_enabled(ctx);
18749 if (rt == 0) {
18750 /* Treat as NOP. */
18751 break;
18753 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18754 break;
18755 case NM_MTC0:
18756 check_cp0_enabled(ctx);
18758 TCGv t0 = tcg_temp_new();
18760 gen_load_gpr(t0, rt);
18761 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18762 tcg_temp_free(t0);
18764 break;
18765 case NM_D_E_MT_VPE:
18767 uint8_t sc = extract32(ctx->opcode, 10, 1);
18768 TCGv t0 = tcg_temp_new();
18770 switch (sc) {
18771 case 0:
18772 if (rs == 1) {
18773 /* DMT */
18774 check_cp0_mt(ctx);
18775 gen_helper_dmt(t0);
18776 gen_store_gpr(t0, rt);
18777 } else if (rs == 0) {
18778 /* DVPE */
18779 check_cp0_mt(ctx);
18780 gen_helper_dvpe(t0, cpu_env);
18781 gen_store_gpr(t0, rt);
18782 } else {
18783 generate_exception_end(ctx, EXCP_RI);
18785 break;
18786 case 1:
18787 if (rs == 1) {
18788 /* EMT */
18789 check_cp0_mt(ctx);
18790 gen_helper_emt(t0);
18791 gen_store_gpr(t0, rt);
18792 } else if (rs == 0) {
18793 /* EVPE */
18794 check_cp0_mt(ctx);
18795 gen_helper_evpe(t0, cpu_env);
18796 gen_store_gpr(t0, rt);
18797 } else {
18798 generate_exception_end(ctx, EXCP_RI);
18800 break;
18803 tcg_temp_free(t0);
18805 break;
18806 case NM_FORK:
18807 check_mt(ctx);
18809 TCGv t0 = tcg_temp_new();
18810 TCGv t1 = tcg_temp_new();
18812 gen_load_gpr(t0, rt);
18813 gen_load_gpr(t1, rs);
18814 gen_helper_fork(t0, t1);
18815 tcg_temp_free(t0);
18816 tcg_temp_free(t1);
18818 break;
18819 case NM_MFTR:
18820 case NM_MFHTR:
18821 check_cp0_enabled(ctx);
18822 if (rd == 0) {
18823 /* Treat as NOP. */
18824 return;
18826 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18827 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18828 break;
18829 case NM_MTTR:
18830 case NM_MTHTR:
18831 check_cp0_enabled(ctx);
18832 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18833 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18834 break;
18835 case NM_YIELD:
18836 check_mt(ctx);
18838 TCGv t0 = tcg_temp_new();
18840 gen_load_gpr(t0, rs);
18841 gen_helper_yield(t0, cpu_env, t0);
18842 gen_store_gpr(t0, rt);
18843 tcg_temp_free(t0);
18845 break;
18846 #endif
18847 default:
18848 generate_exception_end(ctx, EXCP_RI);
18849 break;
18853 /* dsp */
18854 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18855 int ret, int v1, int v2)
18857 TCGv_i32 t0;
18858 TCGv v0_t;
18859 TCGv v1_t;
18861 t0 = tcg_temp_new_i32();
18863 v0_t = tcg_temp_new();
18864 v1_t = tcg_temp_new();
18866 tcg_gen_movi_i32(t0, v2 >> 3);
18868 gen_load_gpr(v0_t, ret);
18869 gen_load_gpr(v1_t, v1);
18871 switch (opc) {
18872 case NM_MAQ_S_W_PHR:
18873 check_dsp(ctx);
18874 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18875 break;
18876 case NM_MAQ_S_W_PHL:
18877 check_dsp(ctx);
18878 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18879 break;
18880 case NM_MAQ_SA_W_PHR:
18881 check_dsp(ctx);
18882 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18883 break;
18884 case NM_MAQ_SA_W_PHL:
18885 check_dsp(ctx);
18886 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18887 break;
18888 default:
18889 generate_exception_end(ctx, EXCP_RI);
18890 break;
18893 tcg_temp_free_i32(t0);
18895 tcg_temp_free(v0_t);
18896 tcg_temp_free(v1_t);
18900 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18901 int ret, int v1, int v2)
18903 int16_t imm;
18904 TCGv t0 = tcg_temp_new();
18905 TCGv t1 = tcg_temp_new();
18906 TCGv v0_t = tcg_temp_new();
18908 gen_load_gpr(v0_t, v1);
18910 switch (opc) {
18911 case NM_POOL32AXF_1_0:
18912 check_dsp(ctx);
18913 switch (extract32(ctx->opcode, 12, 2)) {
18914 case NM_MFHI:
18915 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18916 break;
18917 case NM_MFLO:
18918 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18919 break;
18920 case NM_MTHI:
18921 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18922 break;
18923 case NM_MTLO:
18924 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18925 break;
18927 break;
18928 case NM_POOL32AXF_1_1:
18929 check_dsp(ctx);
18930 switch (extract32(ctx->opcode, 12, 2)) {
18931 case NM_MTHLIP:
18932 tcg_gen_movi_tl(t0, v2);
18933 gen_helper_mthlip(t0, v0_t, cpu_env);
18934 break;
18935 case NM_SHILOV:
18936 tcg_gen_movi_tl(t0, v2 >> 3);
18937 gen_helper_shilo(t0, v0_t, cpu_env);
18938 break;
18939 default:
18940 generate_exception_end(ctx, EXCP_RI);
18941 break;
18943 break;
18944 case NM_POOL32AXF_1_3:
18945 check_dsp(ctx);
18946 imm = extract32(ctx->opcode, 14, 7);
18947 switch (extract32(ctx->opcode, 12, 2)) {
18948 case NM_RDDSP:
18949 tcg_gen_movi_tl(t0, imm);
18950 gen_helper_rddsp(t0, t0, cpu_env);
18951 gen_store_gpr(t0, ret);
18952 break;
18953 case NM_WRDSP:
18954 gen_load_gpr(t0, ret);
18955 tcg_gen_movi_tl(t1, imm);
18956 gen_helper_wrdsp(t0, t1, cpu_env);
18957 break;
18958 case NM_EXTP:
18959 tcg_gen_movi_tl(t0, v2 >> 3);
18960 tcg_gen_movi_tl(t1, v1);
18961 gen_helper_extp(t0, t0, t1, cpu_env);
18962 gen_store_gpr(t0, ret);
18963 break;
18964 case NM_EXTPDP:
18965 tcg_gen_movi_tl(t0, v2 >> 3);
18966 tcg_gen_movi_tl(t1, v1);
18967 gen_helper_extpdp(t0, t0, t1, cpu_env);
18968 gen_store_gpr(t0, ret);
18969 break;
18971 break;
18972 case NM_POOL32AXF_1_4:
18973 check_dsp(ctx);
18974 tcg_gen_movi_tl(t0, v2 >> 2);
18975 switch (extract32(ctx->opcode, 12, 1)) {
18976 case NM_SHLL_QB:
18977 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18978 gen_store_gpr(t0, ret);
18979 break;
18980 case NM_SHRL_QB:
18981 gen_helper_shrl_qb(t0, t0, v0_t);
18982 gen_store_gpr(t0, ret);
18983 break;
18985 break;
18986 case NM_POOL32AXF_1_5:
18987 opc = extract32(ctx->opcode, 12, 2);
18988 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18989 break;
18990 case NM_POOL32AXF_1_7:
18991 check_dsp(ctx);
18992 tcg_gen_movi_tl(t0, v2 >> 3);
18993 tcg_gen_movi_tl(t1, v1);
18994 switch (extract32(ctx->opcode, 12, 2)) {
18995 case NM_EXTR_W:
18996 gen_helper_extr_w(t0, t0, t1, cpu_env);
18997 gen_store_gpr(t0, ret);
18998 break;
18999 case NM_EXTR_R_W:
19000 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19001 gen_store_gpr(t0, ret);
19002 break;
19003 case NM_EXTR_RS_W:
19004 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19005 gen_store_gpr(t0, ret);
19006 break;
19007 case NM_EXTR_S_H:
19008 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19009 gen_store_gpr(t0, ret);
19010 break;
19012 break;
19013 default:
19014 generate_exception_end(ctx, EXCP_RI);
19015 break;
19018 tcg_temp_free(t0);
19019 tcg_temp_free(t1);
19020 tcg_temp_free(v0_t);
19023 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19024 TCGv v0, TCGv v1, int rd)
19026 TCGv_i32 t0;
19028 t0 = tcg_temp_new_i32();
19030 tcg_gen_movi_i32(t0, rd >> 3);
19032 switch (opc) {
19033 case NM_POOL32AXF_2_0_7:
19034 switch (extract32(ctx->opcode, 9, 3)) {
19035 case NM_DPA_W_PH:
19036 check_dsp_r2(ctx);
19037 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19038 break;
19039 case NM_DPAQ_S_W_PH:
19040 check_dsp(ctx);
19041 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19042 break;
19043 case NM_DPS_W_PH:
19044 check_dsp_r2(ctx);
19045 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19046 break;
19047 case NM_DPSQ_S_W_PH:
19048 check_dsp(ctx);
19049 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19050 break;
19051 default:
19052 generate_exception_end(ctx, EXCP_RI);
19053 break;
19055 break;
19056 case NM_POOL32AXF_2_8_15:
19057 switch (extract32(ctx->opcode, 9, 3)) {
19058 case NM_DPAX_W_PH:
19059 check_dsp_r2(ctx);
19060 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19061 break;
19062 case NM_DPAQ_SA_L_W:
19063 check_dsp(ctx);
19064 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19065 break;
19066 case NM_DPSX_W_PH:
19067 check_dsp_r2(ctx);
19068 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19069 break;
19070 case NM_DPSQ_SA_L_W:
19071 check_dsp(ctx);
19072 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19073 break;
19074 default:
19075 generate_exception_end(ctx, EXCP_RI);
19076 break;
19078 break;
19079 case NM_POOL32AXF_2_16_23:
19080 switch (extract32(ctx->opcode, 9, 3)) {
19081 case NM_DPAU_H_QBL:
19082 check_dsp(ctx);
19083 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19084 break;
19085 case NM_DPAQX_S_W_PH:
19086 check_dsp_r2(ctx);
19087 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19088 break;
19089 case NM_DPSU_H_QBL:
19090 check_dsp(ctx);
19091 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19092 break;
19093 case NM_DPSQX_S_W_PH:
19094 check_dsp_r2(ctx);
19095 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19096 break;
19097 case NM_MULSA_W_PH:
19098 check_dsp_r2(ctx);
19099 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19100 break;
19101 default:
19102 generate_exception_end(ctx, EXCP_RI);
19103 break;
19105 break;
19106 case NM_POOL32AXF_2_24_31:
19107 switch (extract32(ctx->opcode, 9, 3)) {
19108 case NM_DPAU_H_QBR:
19109 check_dsp(ctx);
19110 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19111 break;
19112 case NM_DPAQX_SA_W_PH:
19113 check_dsp_r2(ctx);
19114 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19115 break;
19116 case NM_DPSU_H_QBR:
19117 check_dsp(ctx);
19118 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19119 break;
19120 case NM_DPSQX_SA_W_PH:
19121 check_dsp_r2(ctx);
19122 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19123 break;
19124 case NM_MULSAQ_S_W_PH:
19125 check_dsp(ctx);
19126 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19127 break;
19128 default:
19129 generate_exception_end(ctx, EXCP_RI);
19130 break;
19132 break;
19133 default:
19134 generate_exception_end(ctx, EXCP_RI);
19135 break;
19138 tcg_temp_free_i32(t0);
19141 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19142 int rt, int rs, int rd)
19144 int ret = rt;
19145 TCGv t0 = tcg_temp_new();
19146 TCGv t1 = tcg_temp_new();
19147 TCGv v0_t = tcg_temp_new();
19148 TCGv v1_t = tcg_temp_new();
19150 gen_load_gpr(v0_t, rt);
19151 gen_load_gpr(v1_t, rs);
19153 switch (opc) {
19154 case NM_POOL32AXF_2_0_7:
19155 switch (extract32(ctx->opcode, 9, 3)) {
19156 case NM_DPA_W_PH:
19157 case NM_DPAQ_S_W_PH:
19158 case NM_DPS_W_PH:
19159 case NM_DPSQ_S_W_PH:
19160 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19161 break;
19162 case NM_BALIGN:
19163 check_dsp_r2(ctx);
19164 if (rt != 0) {
19165 gen_load_gpr(t0, rs);
19166 rd &= 3;
19167 if (rd != 0 && rd != 2) {
19168 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19169 tcg_gen_ext32u_tl(t0, t0);
19170 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19171 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19173 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19175 break;
19176 case NM_MADD:
19177 check_dsp(ctx);
19179 int acc = extract32(ctx->opcode, 14, 2);
19180 TCGv_i64 t2 = tcg_temp_new_i64();
19181 TCGv_i64 t3 = tcg_temp_new_i64();
19183 gen_load_gpr(t0, rt);
19184 gen_load_gpr(t1, rs);
19185 tcg_gen_ext_tl_i64(t2, t0);
19186 tcg_gen_ext_tl_i64(t3, t1);
19187 tcg_gen_mul_i64(t2, t2, t3);
19188 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19189 tcg_gen_add_i64(t2, t2, t3);
19190 tcg_temp_free_i64(t3);
19191 gen_move_low32(cpu_LO[acc], t2);
19192 gen_move_high32(cpu_HI[acc], t2);
19193 tcg_temp_free_i64(t2);
19195 break;
19196 case NM_MULT:
19197 check_dsp(ctx);
19199 int acc = extract32(ctx->opcode, 14, 2);
19200 TCGv_i32 t2 = tcg_temp_new_i32();
19201 TCGv_i32 t3 = tcg_temp_new_i32();
19203 gen_load_gpr(t0, rs);
19204 gen_load_gpr(t1, rt);
19205 tcg_gen_trunc_tl_i32(t2, t0);
19206 tcg_gen_trunc_tl_i32(t3, t1);
19207 tcg_gen_muls2_i32(t2, t3, t2, t3);
19208 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19209 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19210 tcg_temp_free_i32(t2);
19211 tcg_temp_free_i32(t3);
19213 break;
19214 case NM_EXTRV_W:
19215 check_dsp(ctx);
19216 gen_load_gpr(v1_t, rs);
19217 tcg_gen_movi_tl(t0, rd >> 3);
19218 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19219 gen_store_gpr(t0, ret);
19220 break;
19222 break;
19223 case NM_POOL32AXF_2_8_15:
19224 switch (extract32(ctx->opcode, 9, 3)) {
19225 case NM_DPAX_W_PH:
19226 case NM_DPAQ_SA_L_W:
19227 case NM_DPSX_W_PH:
19228 case NM_DPSQ_SA_L_W:
19229 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19230 break;
19231 case NM_MADDU:
19232 check_dsp(ctx);
19234 int acc = extract32(ctx->opcode, 14, 2);
19235 TCGv_i64 t2 = tcg_temp_new_i64();
19236 TCGv_i64 t3 = tcg_temp_new_i64();
19238 gen_load_gpr(t0, rs);
19239 gen_load_gpr(t1, rt);
19240 tcg_gen_ext32u_tl(t0, t0);
19241 tcg_gen_ext32u_tl(t1, t1);
19242 tcg_gen_extu_tl_i64(t2, t0);
19243 tcg_gen_extu_tl_i64(t3, t1);
19244 tcg_gen_mul_i64(t2, t2, t3);
19245 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19246 tcg_gen_add_i64(t2, t2, t3);
19247 tcg_temp_free_i64(t3);
19248 gen_move_low32(cpu_LO[acc], t2);
19249 gen_move_high32(cpu_HI[acc], t2);
19250 tcg_temp_free_i64(t2);
19252 break;
19253 case NM_MULTU:
19254 check_dsp(ctx);
19256 int acc = extract32(ctx->opcode, 14, 2);
19257 TCGv_i32 t2 = tcg_temp_new_i32();
19258 TCGv_i32 t3 = tcg_temp_new_i32();
19260 gen_load_gpr(t0, rs);
19261 gen_load_gpr(t1, rt);
19262 tcg_gen_trunc_tl_i32(t2, t0);
19263 tcg_gen_trunc_tl_i32(t3, t1);
19264 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19265 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19266 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19267 tcg_temp_free_i32(t2);
19268 tcg_temp_free_i32(t3);
19270 break;
19271 case NM_EXTRV_R_W:
19272 check_dsp(ctx);
19273 tcg_gen_movi_tl(t0, rd >> 3);
19274 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19275 gen_store_gpr(t0, ret);
19276 break;
19277 default:
19278 generate_exception_end(ctx, EXCP_RI);
19279 break;
19281 break;
19282 case NM_POOL32AXF_2_16_23:
19283 switch (extract32(ctx->opcode, 9, 3)) {
19284 case NM_DPAU_H_QBL:
19285 case NM_DPAQX_S_W_PH:
19286 case NM_DPSU_H_QBL:
19287 case NM_DPSQX_S_W_PH:
19288 case NM_MULSA_W_PH:
19289 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19290 break;
19291 case NM_EXTPV:
19292 check_dsp(ctx);
19293 tcg_gen_movi_tl(t0, rd >> 3);
19294 gen_helper_extp(t0, t0, v1_t, cpu_env);
19295 gen_store_gpr(t0, ret);
19296 break;
19297 case NM_MSUB:
19298 check_dsp(ctx);
19300 int acc = extract32(ctx->opcode, 14, 2);
19301 TCGv_i64 t2 = tcg_temp_new_i64();
19302 TCGv_i64 t3 = tcg_temp_new_i64();
19304 gen_load_gpr(t0, rs);
19305 gen_load_gpr(t1, rt);
19306 tcg_gen_ext_tl_i64(t2, t0);
19307 tcg_gen_ext_tl_i64(t3, t1);
19308 tcg_gen_mul_i64(t2, t2, t3);
19309 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19310 tcg_gen_sub_i64(t2, t3, t2);
19311 tcg_temp_free_i64(t3);
19312 gen_move_low32(cpu_LO[acc], t2);
19313 gen_move_high32(cpu_HI[acc], t2);
19314 tcg_temp_free_i64(t2);
19316 break;
19317 case NM_EXTRV_RS_W:
19318 check_dsp(ctx);
19319 tcg_gen_movi_tl(t0, rd >> 3);
19320 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19321 gen_store_gpr(t0, ret);
19322 break;
19324 break;
19325 case NM_POOL32AXF_2_24_31:
19326 switch (extract32(ctx->opcode, 9, 3)) {
19327 case NM_DPAU_H_QBR:
19328 case NM_DPAQX_SA_W_PH:
19329 case NM_DPSU_H_QBR:
19330 case NM_DPSQX_SA_W_PH:
19331 case NM_MULSAQ_S_W_PH:
19332 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19333 break;
19334 case NM_EXTPDPV:
19335 check_dsp(ctx);
19336 tcg_gen_movi_tl(t0, rd >> 3);
19337 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19338 gen_store_gpr(t0, ret);
19339 break;
19340 case NM_MSUBU:
19341 check_dsp(ctx);
19343 int acc = extract32(ctx->opcode, 14, 2);
19344 TCGv_i64 t2 = tcg_temp_new_i64();
19345 TCGv_i64 t3 = tcg_temp_new_i64();
19347 gen_load_gpr(t0, rs);
19348 gen_load_gpr(t1, rt);
19349 tcg_gen_ext32u_tl(t0, t0);
19350 tcg_gen_ext32u_tl(t1, t1);
19351 tcg_gen_extu_tl_i64(t2, t0);
19352 tcg_gen_extu_tl_i64(t3, t1);
19353 tcg_gen_mul_i64(t2, t2, t3);
19354 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19355 tcg_gen_sub_i64(t2, t3, t2);
19356 tcg_temp_free_i64(t3);
19357 gen_move_low32(cpu_LO[acc], t2);
19358 gen_move_high32(cpu_HI[acc], t2);
19359 tcg_temp_free_i64(t2);
19361 break;
19362 case NM_EXTRV_S_H:
19363 check_dsp(ctx);
19364 tcg_gen_movi_tl(t0, rd >> 3);
19365 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19366 gen_store_gpr(t0, ret);
19367 break;
19369 break;
19370 default:
19371 generate_exception_end(ctx, EXCP_RI);
19372 break;
19375 tcg_temp_free(t0);
19376 tcg_temp_free(t1);
19378 tcg_temp_free(v0_t);
19379 tcg_temp_free(v1_t);
19382 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19383 int rt, int rs)
19385 int ret = rt;
19386 TCGv t0 = tcg_temp_new();
19387 TCGv v0_t = tcg_temp_new();
19389 gen_load_gpr(v0_t, rs);
19391 switch (opc) {
19392 case NM_ABSQ_S_QB:
19393 check_dsp_r2(ctx);
19394 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19395 gen_store_gpr(v0_t, ret);
19396 break;
19397 case NM_ABSQ_S_PH:
19398 check_dsp(ctx);
19399 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19400 gen_store_gpr(v0_t, ret);
19401 break;
19402 case NM_ABSQ_S_W:
19403 check_dsp(ctx);
19404 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19405 gen_store_gpr(v0_t, ret);
19406 break;
19407 case NM_PRECEQ_W_PHL:
19408 check_dsp(ctx);
19409 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19410 tcg_gen_ext32s_tl(v0_t, v0_t);
19411 gen_store_gpr(v0_t, ret);
19412 break;
19413 case NM_PRECEQ_W_PHR:
19414 check_dsp(ctx);
19415 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19416 tcg_gen_shli_tl(v0_t, v0_t, 16);
19417 tcg_gen_ext32s_tl(v0_t, v0_t);
19418 gen_store_gpr(v0_t, ret);
19419 break;
19420 case NM_PRECEQU_PH_QBL:
19421 check_dsp(ctx);
19422 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19423 gen_store_gpr(v0_t, ret);
19424 break;
19425 case NM_PRECEQU_PH_QBR:
19426 check_dsp(ctx);
19427 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19428 gen_store_gpr(v0_t, ret);
19429 break;
19430 case NM_PRECEQU_PH_QBLA:
19431 check_dsp(ctx);
19432 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19433 gen_store_gpr(v0_t, ret);
19434 break;
19435 case NM_PRECEQU_PH_QBRA:
19436 check_dsp(ctx);
19437 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19438 gen_store_gpr(v0_t, ret);
19439 break;
19440 case NM_PRECEU_PH_QBL:
19441 check_dsp(ctx);
19442 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19443 gen_store_gpr(v0_t, ret);
19444 break;
19445 case NM_PRECEU_PH_QBR:
19446 check_dsp(ctx);
19447 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19448 gen_store_gpr(v0_t, ret);
19449 break;
19450 case NM_PRECEU_PH_QBLA:
19451 check_dsp(ctx);
19452 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19453 gen_store_gpr(v0_t, ret);
19454 break;
19455 case NM_PRECEU_PH_QBRA:
19456 check_dsp(ctx);
19457 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19458 gen_store_gpr(v0_t, ret);
19459 break;
19460 case NM_REPLV_PH:
19461 check_dsp(ctx);
19462 tcg_gen_ext16u_tl(v0_t, v0_t);
19463 tcg_gen_shli_tl(t0, v0_t, 16);
19464 tcg_gen_or_tl(v0_t, v0_t, t0);
19465 tcg_gen_ext32s_tl(v0_t, v0_t);
19466 gen_store_gpr(v0_t, ret);
19467 break;
19468 case NM_REPLV_QB:
19469 check_dsp(ctx);
19470 tcg_gen_ext8u_tl(v0_t, v0_t);
19471 tcg_gen_shli_tl(t0, v0_t, 8);
19472 tcg_gen_or_tl(v0_t, v0_t, t0);
19473 tcg_gen_shli_tl(t0, v0_t, 16);
19474 tcg_gen_or_tl(v0_t, v0_t, t0);
19475 tcg_gen_ext32s_tl(v0_t, v0_t);
19476 gen_store_gpr(v0_t, ret);
19477 break;
19478 case NM_BITREV:
19479 check_dsp(ctx);
19480 gen_helper_bitrev(v0_t, v0_t);
19481 gen_store_gpr(v0_t, ret);
19482 break;
19483 case NM_INSV:
19484 check_dsp(ctx);
19486 TCGv tv0 = tcg_temp_new();
19488 gen_load_gpr(tv0, rt);
19489 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19490 gen_store_gpr(v0_t, ret);
19491 tcg_temp_free(tv0);
19493 break;
19494 case NM_RADDU_W_QB:
19495 check_dsp(ctx);
19496 gen_helper_raddu_w_qb(v0_t, v0_t);
19497 gen_store_gpr(v0_t, ret);
19498 break;
19499 case NM_BITSWAP:
19500 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19501 break;
19502 case NM_CLO:
19503 check_nms(ctx);
19504 gen_cl(ctx, OPC_CLO, ret, rs);
19505 break;
19506 case NM_CLZ:
19507 check_nms(ctx);
19508 gen_cl(ctx, OPC_CLZ, ret, rs);
19509 break;
19510 case NM_WSBH:
19511 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19512 break;
19513 default:
19514 generate_exception_end(ctx, EXCP_RI);
19515 break;
19518 tcg_temp_free(v0_t);
19519 tcg_temp_free(t0);
19522 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19523 int rt, int rs, int rd)
19525 TCGv t0 = tcg_temp_new();
19526 TCGv rs_t = tcg_temp_new();
19528 gen_load_gpr(rs_t, rs);
19530 switch (opc) {
19531 case NM_SHRA_R_QB:
19532 check_dsp_r2(ctx);
19533 tcg_gen_movi_tl(t0, rd >> 2);
19534 switch (extract32(ctx->opcode, 12, 1)) {
19535 case 0:
19536 /* NM_SHRA_QB */
19537 gen_helper_shra_qb(t0, t0, rs_t);
19538 gen_store_gpr(t0, rt);
19539 break;
19540 case 1:
19541 /* NM_SHRA_R_QB */
19542 gen_helper_shra_r_qb(t0, t0, rs_t);
19543 gen_store_gpr(t0, rt);
19544 break;
19546 break;
19547 case NM_SHRL_PH:
19548 check_dsp_r2(ctx);
19549 tcg_gen_movi_tl(t0, rd >> 1);
19550 gen_helper_shrl_ph(t0, t0, rs_t);
19551 gen_store_gpr(t0, rt);
19552 break;
19553 case NM_REPL_QB:
19554 check_dsp(ctx);
19556 int16_t imm;
19557 target_long result;
19558 imm = extract32(ctx->opcode, 13, 8);
19559 result = (uint32_t)imm << 24 |
19560 (uint32_t)imm << 16 |
19561 (uint32_t)imm << 8 |
19562 (uint32_t)imm;
19563 result = (int32_t)result;
19564 tcg_gen_movi_tl(t0, result);
19565 gen_store_gpr(t0, rt);
19567 break;
19568 default:
19569 generate_exception_end(ctx, EXCP_RI);
19570 break;
19572 tcg_temp_free(t0);
19573 tcg_temp_free(rs_t);
19577 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19579 int rt = extract32(ctx->opcode, 21, 5);
19580 int rs = extract32(ctx->opcode, 16, 5);
19581 int rd = extract32(ctx->opcode, 11, 5);
19583 switch (extract32(ctx->opcode, 6, 3)) {
19584 case NM_POOL32AXF_1:
19586 int32_t op1 = extract32(ctx->opcode, 9, 3);
19587 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19589 break;
19590 case NM_POOL32AXF_2:
19592 int32_t op1 = extract32(ctx->opcode, 12, 2);
19593 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19595 break;
19596 case NM_POOL32AXF_4:
19598 int32_t op1 = extract32(ctx->opcode, 9, 7);
19599 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19601 break;
19602 case NM_POOL32AXF_5:
19603 switch (extract32(ctx->opcode, 9, 7)) {
19604 #ifndef CONFIG_USER_ONLY
19605 case NM_TLBP:
19606 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19607 break;
19608 case NM_TLBR:
19609 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19610 break;
19611 case NM_TLBWI:
19612 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19613 break;
19614 case NM_TLBWR:
19615 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19616 break;
19617 case NM_TLBINV:
19618 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19619 break;
19620 case NM_TLBINVF:
19621 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19622 break;
19623 case NM_DI:
19624 check_cp0_enabled(ctx);
19626 TCGv t0 = tcg_temp_new();
19628 save_cpu_state(ctx, 1);
19629 gen_helper_di(t0, cpu_env);
19630 gen_store_gpr(t0, rt);
19631 /* Stop translation as we may have switched the execution mode */
19632 ctx->base.is_jmp = DISAS_STOP;
19633 tcg_temp_free(t0);
19635 break;
19636 case NM_EI:
19637 check_cp0_enabled(ctx);
19639 TCGv t0 = tcg_temp_new();
19641 save_cpu_state(ctx, 1);
19642 gen_helper_ei(t0, cpu_env);
19643 gen_store_gpr(t0, rt);
19644 /* Stop translation as we may have switched the execution mode */
19645 ctx->base.is_jmp = DISAS_STOP;
19646 tcg_temp_free(t0);
19648 break;
19649 case NM_RDPGPR:
19650 gen_load_srsgpr(rs, rt);
19651 break;
19652 case NM_WRPGPR:
19653 gen_store_srsgpr(rs, rt);
19654 break;
19655 case NM_WAIT:
19656 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19657 break;
19658 case NM_DERET:
19659 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19660 break;
19661 case NM_ERETX:
19662 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19663 break;
19664 #endif
19665 default:
19666 generate_exception_end(ctx, EXCP_RI);
19667 break;
19669 break;
19670 case NM_POOL32AXF_7:
19672 int32_t op1 = extract32(ctx->opcode, 9, 3);
19673 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19675 break;
19676 default:
19677 generate_exception_end(ctx, EXCP_RI);
19678 break;
19682 /* Immediate Value Compact Branches */
19683 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19684 int rt, int32_t imm, int32_t offset)
19686 TCGCond cond;
19687 int bcond_compute = 0;
19688 TCGv t0 = tcg_temp_new();
19689 TCGv t1 = tcg_temp_new();
19691 gen_load_gpr(t0, rt);
19692 tcg_gen_movi_tl(t1, imm);
19693 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19695 /* Load needed operands and calculate btarget */
19696 switch (opc) {
19697 case NM_BEQIC:
19698 if (rt == 0 && imm == 0) {
19699 /* Unconditional branch */
19700 } else if (rt == 0 && imm != 0) {
19701 /* Treat as NOP */
19702 goto out;
19703 } else {
19704 bcond_compute = 1;
19705 cond = TCG_COND_EQ;
19707 break;
19708 case NM_BBEQZC:
19709 case NM_BBNEZC:
19710 check_nms(ctx);
19711 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19712 generate_exception_end(ctx, EXCP_RI);
19713 goto out;
19714 } else if (rt == 0 && opc == NM_BBEQZC) {
19715 /* Unconditional branch */
19716 } else if (rt == 0 && opc == NM_BBNEZC) {
19717 /* Treat as NOP */
19718 goto out;
19719 } else {
19720 tcg_gen_shri_tl(t0, t0, imm);
19721 tcg_gen_andi_tl(t0, t0, 1);
19722 tcg_gen_movi_tl(t1, 0);
19723 bcond_compute = 1;
19724 if (opc == NM_BBEQZC) {
19725 cond = TCG_COND_EQ;
19726 } else {
19727 cond = TCG_COND_NE;
19730 break;
19731 case NM_BNEIC:
19732 if (rt == 0 && imm == 0) {
19733 /* Treat as NOP */
19734 goto out;
19735 } else if (rt == 0 && imm != 0) {
19736 /* Unconditional branch */
19737 } else {
19738 bcond_compute = 1;
19739 cond = TCG_COND_NE;
19741 break;
19742 case NM_BGEIC:
19743 if (rt == 0 && imm == 0) {
19744 /* Unconditional branch */
19745 } else {
19746 bcond_compute = 1;
19747 cond = TCG_COND_GE;
19749 break;
19750 case NM_BLTIC:
19751 bcond_compute = 1;
19752 cond = TCG_COND_LT;
19753 break;
19754 case NM_BGEIUC:
19755 if (rt == 0 && imm == 0) {
19756 /* Unconditional branch */
19757 } else {
19758 bcond_compute = 1;
19759 cond = TCG_COND_GEU;
19761 break;
19762 case NM_BLTIUC:
19763 bcond_compute = 1;
19764 cond = TCG_COND_LTU;
19765 break;
19766 default:
19767 MIPS_INVAL("Immediate Value Compact branch");
19768 generate_exception_end(ctx, EXCP_RI);
19769 goto out;
19772 if (bcond_compute == 0) {
19773 /* Uncoditional compact branch */
19774 gen_goto_tb(ctx, 0, ctx->btarget);
19775 } else {
19776 /* Conditional compact branch */
19777 TCGLabel *fs = gen_new_label();
19779 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19781 gen_goto_tb(ctx, 1, ctx->btarget);
19782 gen_set_label(fs);
19784 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19787 out:
19788 tcg_temp_free(t0);
19789 tcg_temp_free(t1);
19792 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19793 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19794 int rt)
19796 TCGv t0 = tcg_temp_new();
19797 TCGv t1 = tcg_temp_new();
19799 /* load rs */
19800 gen_load_gpr(t0, rs);
19802 /* link */
19803 if (rt != 0) {
19804 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19807 /* calculate btarget */
19808 tcg_gen_shli_tl(t0, t0, 1);
19809 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19810 gen_op_addr_add(ctx, btarget, t1, t0);
19812 /* unconditional branch to register */
19813 tcg_gen_mov_tl(cpu_PC, btarget);
19814 tcg_gen_lookup_and_goto_ptr();
19816 tcg_temp_free(t0);
19817 tcg_temp_free(t1);
19820 /* nanoMIPS Branches */
19821 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19822 int rs, int rt, int32_t offset)
19824 int bcond_compute = 0;
19825 TCGv t0 = tcg_temp_new();
19826 TCGv t1 = tcg_temp_new();
19828 /* Load needed operands and calculate btarget */
19829 switch (opc) {
19830 /* compact branch */
19831 case OPC_BGEC:
19832 case OPC_BLTC:
19833 gen_load_gpr(t0, rs);
19834 gen_load_gpr(t1, rt);
19835 bcond_compute = 1;
19836 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19837 break;
19838 case OPC_BGEUC:
19839 case OPC_BLTUC:
19840 if (rs == 0 || rs == rt) {
19841 /* OPC_BLEZALC, OPC_BGEZALC */
19842 /* OPC_BGTZALC, OPC_BLTZALC */
19843 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19845 gen_load_gpr(t0, rs);
19846 gen_load_gpr(t1, rt);
19847 bcond_compute = 1;
19848 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19849 break;
19850 case OPC_BC:
19851 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19852 break;
19853 case OPC_BEQZC:
19854 if (rs != 0) {
19855 /* OPC_BEQZC, OPC_BNEZC */
19856 gen_load_gpr(t0, rs);
19857 bcond_compute = 1;
19858 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19859 } else {
19860 /* OPC_JIC, OPC_JIALC */
19861 TCGv tbase = tcg_temp_new();
19862 TCGv toffset = tcg_temp_new();
19864 gen_load_gpr(tbase, rt);
19865 tcg_gen_movi_tl(toffset, offset);
19866 gen_op_addr_add(ctx, btarget, tbase, toffset);
19867 tcg_temp_free(tbase);
19868 tcg_temp_free(toffset);
19870 break;
19871 default:
19872 MIPS_INVAL("Compact branch/jump");
19873 generate_exception_end(ctx, EXCP_RI);
19874 goto out;
19877 if (bcond_compute == 0) {
19878 /* Uncoditional compact branch */
19879 switch (opc) {
19880 case OPC_BC:
19881 gen_goto_tb(ctx, 0, ctx->btarget);
19882 break;
19883 default:
19884 MIPS_INVAL("Compact branch/jump");
19885 generate_exception_end(ctx, EXCP_RI);
19886 goto out;
19888 } else {
19889 /* Conditional compact branch */
19890 TCGLabel *fs = gen_new_label();
19892 switch (opc) {
19893 case OPC_BGEUC:
19894 if (rs == 0 && rt != 0) {
19895 /* OPC_BLEZALC */
19896 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19897 } else if (rs != 0 && rt != 0 && rs == rt) {
19898 /* OPC_BGEZALC */
19899 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19900 } else {
19901 /* OPC_BGEUC */
19902 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19904 break;
19905 case OPC_BLTUC:
19906 if (rs == 0 && rt != 0) {
19907 /* OPC_BGTZALC */
19908 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19909 } else if (rs != 0 && rt != 0 && rs == rt) {
19910 /* OPC_BLTZALC */
19911 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19912 } else {
19913 /* OPC_BLTUC */
19914 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19916 break;
19917 case OPC_BGEC:
19918 if (rs == 0 && rt != 0) {
19919 /* OPC_BLEZC */
19920 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19921 } else if (rs != 0 && rt != 0 && rs == rt) {
19922 /* OPC_BGEZC */
19923 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19924 } else {
19925 /* OPC_BGEC */
19926 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19928 break;
19929 case OPC_BLTC:
19930 if (rs == 0 && rt != 0) {
19931 /* OPC_BGTZC */
19932 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19933 } else if (rs != 0 && rt != 0 && rs == rt) {
19934 /* OPC_BLTZC */
19935 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19936 } else {
19937 /* OPC_BLTC */
19938 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19940 break;
19941 case OPC_BEQZC:
19942 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19943 break;
19944 default:
19945 MIPS_INVAL("Compact conditional branch/jump");
19946 generate_exception_end(ctx, EXCP_RI);
19947 goto out;
19950 /* Generating branch here as compact branches don't have delay slot */
19951 gen_goto_tb(ctx, 1, ctx->btarget);
19952 gen_set_label(fs);
19954 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19957 out:
19958 tcg_temp_free(t0);
19959 tcg_temp_free(t1);
19963 /* nanoMIPS CP1 Branches */
19964 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19965 int32_t ft, int32_t offset)
19967 target_ulong btarget;
19968 TCGv_i64 t0 = tcg_temp_new_i64();
19970 gen_load_fpr64(ctx, t0, ft);
19971 tcg_gen_andi_i64(t0, t0, 1);
19973 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19975 switch (op) {
19976 case NM_BC1EQZC:
19977 tcg_gen_xori_i64(t0, t0, 1);
19978 ctx->hflags |= MIPS_HFLAG_BC;
19979 break;
19980 case NM_BC1NEZC:
19981 /* t0 already set */
19982 ctx->hflags |= MIPS_HFLAG_BC;
19983 break;
19984 default:
19985 MIPS_INVAL("cp1 cond branch");
19986 generate_exception_end(ctx, EXCP_RI);
19987 goto out;
19990 tcg_gen_trunc_i64_tl(bcond, t0);
19992 ctx->btarget = btarget;
19994 out:
19995 tcg_temp_free_i64(t0);
19999 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20001 TCGv t0, t1;
20002 t0 = tcg_temp_new();
20003 t1 = tcg_temp_new();
20005 gen_load_gpr(t0, rs);
20006 gen_load_gpr(t1, rt);
20008 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20009 /* PP.LSXS instructions require shifting */
20010 switch (extract32(ctx->opcode, 7, 4)) {
20011 case NM_SHXS:
20012 check_nms(ctx);
20013 case NM_LHXS:
20014 case NM_LHUXS:
20015 tcg_gen_shli_tl(t0, t0, 1);
20016 break;
20017 case NM_SWXS:
20018 check_nms(ctx);
20019 case NM_LWXS:
20020 case NM_LWC1XS:
20021 case NM_SWC1XS:
20022 tcg_gen_shli_tl(t0, t0, 2);
20023 break;
20024 case NM_LDC1XS:
20025 case NM_SDC1XS:
20026 tcg_gen_shli_tl(t0, t0, 3);
20027 break;
20030 gen_op_addr_add(ctx, t0, t0, t1);
20032 switch (extract32(ctx->opcode, 7, 4)) {
20033 case NM_LBX:
20034 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20035 MO_SB);
20036 gen_store_gpr(t0, rd);
20037 break;
20038 case NM_LHX:
20039 /*case NM_LHXS:*/
20040 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20041 MO_TESW);
20042 gen_store_gpr(t0, rd);
20043 break;
20044 case NM_LWX:
20045 /*case NM_LWXS:*/
20046 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20047 MO_TESL);
20048 gen_store_gpr(t0, rd);
20049 break;
20050 case NM_LBUX:
20051 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20052 MO_UB);
20053 gen_store_gpr(t0, rd);
20054 break;
20055 case NM_LHUX:
20056 /*case NM_LHUXS:*/
20057 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20058 MO_TEUW);
20059 gen_store_gpr(t0, rd);
20060 break;
20061 case NM_SBX:
20062 check_nms(ctx);
20063 gen_load_gpr(t1, rd);
20064 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20065 MO_8);
20066 break;
20067 case NM_SHX:
20068 /*case NM_SHXS:*/
20069 check_nms(ctx);
20070 gen_load_gpr(t1, rd);
20071 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20072 MO_TEUW);
20073 break;
20074 case NM_SWX:
20075 /*case NM_SWXS:*/
20076 check_nms(ctx);
20077 gen_load_gpr(t1, rd);
20078 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20079 MO_TEUL);
20080 break;
20081 case NM_LWC1X:
20082 /*case NM_LWC1XS:*/
20083 case NM_LDC1X:
20084 /*case NM_LDC1XS:*/
20085 case NM_SWC1X:
20086 /*case NM_SWC1XS:*/
20087 case NM_SDC1X:
20088 /*case NM_SDC1XS:*/
20089 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20090 check_cp1_enabled(ctx);
20091 switch (extract32(ctx->opcode, 7, 4)) {
20092 case NM_LWC1X:
20093 /*case NM_LWC1XS:*/
20094 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20095 break;
20096 case NM_LDC1X:
20097 /*case NM_LDC1XS:*/
20098 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20099 break;
20100 case NM_SWC1X:
20101 /*case NM_SWC1XS:*/
20102 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20103 break;
20104 case NM_SDC1X:
20105 /*case NM_SDC1XS:*/
20106 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20107 break;
20109 } else {
20110 generate_exception_err(ctx, EXCP_CpU, 1);
20112 break;
20113 default:
20114 generate_exception_end(ctx, EXCP_RI);
20115 break;
20118 tcg_temp_free(t0);
20119 tcg_temp_free(t1);
20122 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20124 int rt, rs, rd;
20126 rt = extract32(ctx->opcode, 21, 5);
20127 rs = extract32(ctx->opcode, 16, 5);
20128 rd = extract32(ctx->opcode, 11, 5);
20130 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20131 generate_exception_end(ctx, EXCP_RI);
20132 return;
20134 check_cp1_enabled(ctx);
20135 switch (extract32(ctx->opcode, 0, 3)) {
20136 case NM_POOL32F_0:
20137 switch (extract32(ctx->opcode, 3, 7)) {
20138 case NM_RINT_S:
20139 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20140 break;
20141 case NM_RINT_D:
20142 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20143 break;
20144 case NM_CLASS_S:
20145 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20146 break;
20147 case NM_CLASS_D:
20148 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20149 break;
20150 case NM_ADD_S:
20151 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20152 break;
20153 case NM_ADD_D:
20154 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20155 break;
20156 case NM_SUB_S:
20157 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20158 break;
20159 case NM_SUB_D:
20160 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20161 break;
20162 case NM_MUL_S:
20163 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20164 break;
20165 case NM_MUL_D:
20166 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20167 break;
20168 case NM_DIV_S:
20169 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20170 break;
20171 case NM_DIV_D:
20172 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20173 break;
20174 case NM_SELEQZ_S:
20175 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20176 break;
20177 case NM_SELEQZ_D:
20178 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20179 break;
20180 case NM_SELNEZ_S:
20181 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20182 break;
20183 case NM_SELNEZ_D:
20184 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20185 break;
20186 case NM_SEL_S:
20187 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20188 break;
20189 case NM_SEL_D:
20190 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20191 break;
20192 case NM_MADDF_S:
20193 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20194 break;
20195 case NM_MADDF_D:
20196 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20197 break;
20198 case NM_MSUBF_S:
20199 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20200 break;
20201 case NM_MSUBF_D:
20202 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20203 break;
20204 default:
20205 generate_exception_end(ctx, EXCP_RI);
20206 break;
20208 break;
20209 case NM_POOL32F_3:
20210 switch (extract32(ctx->opcode, 3, 3)) {
20211 case NM_MIN_FMT:
20212 switch (extract32(ctx->opcode, 9, 1)) {
20213 case FMT_SDPS_S:
20214 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20215 break;
20216 case FMT_SDPS_D:
20217 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20218 break;
20220 break;
20221 case NM_MAX_FMT:
20222 switch (extract32(ctx->opcode, 9, 1)) {
20223 case FMT_SDPS_S:
20224 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20225 break;
20226 case FMT_SDPS_D:
20227 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20228 break;
20230 break;
20231 case NM_MINA_FMT:
20232 switch (extract32(ctx->opcode, 9, 1)) {
20233 case FMT_SDPS_S:
20234 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20235 break;
20236 case FMT_SDPS_D:
20237 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20238 break;
20240 break;
20241 case NM_MAXA_FMT:
20242 switch (extract32(ctx->opcode, 9, 1)) {
20243 case FMT_SDPS_S:
20244 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20245 break;
20246 case FMT_SDPS_D:
20247 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20248 break;
20250 break;
20251 case NM_POOL32FXF:
20252 switch (extract32(ctx->opcode, 6, 8)) {
20253 case NM_CFC1:
20254 gen_cp1(ctx, OPC_CFC1, rt, rs);
20255 break;
20256 case NM_CTC1:
20257 gen_cp1(ctx, OPC_CTC1, rt, rs);
20258 break;
20259 case NM_MFC1:
20260 gen_cp1(ctx, OPC_MFC1, rt, rs);
20261 break;
20262 case NM_MTC1:
20263 gen_cp1(ctx, OPC_MTC1, rt, rs);
20264 break;
20265 case NM_MFHC1:
20266 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20267 break;
20268 case NM_MTHC1:
20269 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20270 break;
20271 case NM_CVT_S_PL:
20272 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20273 break;
20274 case NM_CVT_S_PU:
20275 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20276 break;
20277 default:
20278 switch (extract32(ctx->opcode, 6, 9)) {
20279 case NM_CVT_L_S:
20280 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20281 break;
20282 case NM_CVT_L_D:
20283 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20284 break;
20285 case NM_CVT_W_S:
20286 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20287 break;
20288 case NM_CVT_W_D:
20289 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20290 break;
20291 case NM_RSQRT_S:
20292 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20293 break;
20294 case NM_RSQRT_D:
20295 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20296 break;
20297 case NM_SQRT_S:
20298 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20299 break;
20300 case NM_SQRT_D:
20301 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20302 break;
20303 case NM_RECIP_S:
20304 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20305 break;
20306 case NM_RECIP_D:
20307 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20308 break;
20309 case NM_FLOOR_L_S:
20310 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20311 break;
20312 case NM_FLOOR_L_D:
20313 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20314 break;
20315 case NM_FLOOR_W_S:
20316 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20317 break;
20318 case NM_FLOOR_W_D:
20319 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20320 break;
20321 case NM_CEIL_L_S:
20322 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20323 break;
20324 case NM_CEIL_L_D:
20325 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20326 break;
20327 case NM_CEIL_W_S:
20328 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20329 break;
20330 case NM_CEIL_W_D:
20331 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20332 break;
20333 case NM_TRUNC_L_S:
20334 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20335 break;
20336 case NM_TRUNC_L_D:
20337 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20338 break;
20339 case NM_TRUNC_W_S:
20340 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20341 break;
20342 case NM_TRUNC_W_D:
20343 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20344 break;
20345 case NM_ROUND_L_S:
20346 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20347 break;
20348 case NM_ROUND_L_D:
20349 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20350 break;
20351 case NM_ROUND_W_S:
20352 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20353 break;
20354 case NM_ROUND_W_D:
20355 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20356 break;
20357 case NM_MOV_S:
20358 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20359 break;
20360 case NM_MOV_D:
20361 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20362 break;
20363 case NM_ABS_S:
20364 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20365 break;
20366 case NM_ABS_D:
20367 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20368 break;
20369 case NM_NEG_S:
20370 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20371 break;
20372 case NM_NEG_D:
20373 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20374 break;
20375 case NM_CVT_D_S:
20376 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20377 break;
20378 case NM_CVT_D_W:
20379 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20380 break;
20381 case NM_CVT_D_L:
20382 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20383 break;
20384 case NM_CVT_S_D:
20385 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20386 break;
20387 case NM_CVT_S_W:
20388 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20389 break;
20390 case NM_CVT_S_L:
20391 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20392 break;
20393 default:
20394 generate_exception_end(ctx, EXCP_RI);
20395 break;
20397 break;
20399 break;
20401 break;
20402 case NM_POOL32F_5:
20403 switch (extract32(ctx->opcode, 3, 3)) {
20404 case NM_CMP_CONDN_S:
20405 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20406 break;
20407 case NM_CMP_CONDN_D:
20408 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20409 break;
20410 default:
20411 generate_exception_end(ctx, EXCP_RI);
20412 break;
20414 break;
20415 default:
20416 generate_exception_end(ctx, EXCP_RI);
20417 break;
20421 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20422 int rd, int rs, int rt)
20424 int ret = rd;
20425 TCGv t0 = tcg_temp_new();
20426 TCGv v1_t = tcg_temp_new();
20427 TCGv v2_t = tcg_temp_new();
20429 gen_load_gpr(v1_t, rs);
20430 gen_load_gpr(v2_t, rt);
20432 switch (opc) {
20433 case NM_CMP_EQ_PH:
20434 check_dsp(ctx);
20435 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20436 break;
20437 case NM_CMP_LT_PH:
20438 check_dsp(ctx);
20439 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20440 break;
20441 case NM_CMP_LE_PH:
20442 check_dsp(ctx);
20443 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20444 break;
20445 case NM_CMPU_EQ_QB:
20446 check_dsp(ctx);
20447 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20448 break;
20449 case NM_CMPU_LT_QB:
20450 check_dsp(ctx);
20451 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20452 break;
20453 case NM_CMPU_LE_QB:
20454 check_dsp(ctx);
20455 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20456 break;
20457 case NM_CMPGU_EQ_QB:
20458 check_dsp(ctx);
20459 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20460 gen_store_gpr(v1_t, ret);
20461 break;
20462 case NM_CMPGU_LT_QB:
20463 check_dsp(ctx);
20464 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20465 gen_store_gpr(v1_t, ret);
20466 break;
20467 case NM_CMPGU_LE_QB:
20468 check_dsp(ctx);
20469 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20470 gen_store_gpr(v1_t, ret);
20471 break;
20472 case NM_CMPGDU_EQ_QB:
20473 check_dsp_r2(ctx);
20474 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20475 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20476 gen_store_gpr(v1_t, ret);
20477 break;
20478 case NM_CMPGDU_LT_QB:
20479 check_dsp_r2(ctx);
20480 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20481 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20482 gen_store_gpr(v1_t, ret);
20483 break;
20484 case NM_CMPGDU_LE_QB:
20485 check_dsp_r2(ctx);
20486 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20487 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20488 gen_store_gpr(v1_t, ret);
20489 break;
20490 case NM_PACKRL_PH:
20491 check_dsp(ctx);
20492 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20493 gen_store_gpr(v1_t, ret);
20494 break;
20495 case NM_PICK_QB:
20496 check_dsp(ctx);
20497 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20498 gen_store_gpr(v1_t, ret);
20499 break;
20500 case NM_PICK_PH:
20501 check_dsp(ctx);
20502 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20503 gen_store_gpr(v1_t, ret);
20504 break;
20505 case NM_ADDQ_S_W:
20506 check_dsp(ctx);
20507 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20508 gen_store_gpr(v1_t, ret);
20509 break;
20510 case NM_SUBQ_S_W:
20511 check_dsp(ctx);
20512 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20513 gen_store_gpr(v1_t, ret);
20514 break;
20515 case NM_ADDSC:
20516 check_dsp(ctx);
20517 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20518 gen_store_gpr(v1_t, ret);
20519 break;
20520 case NM_ADDWC:
20521 check_dsp(ctx);
20522 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20523 gen_store_gpr(v1_t, ret);
20524 break;
20525 case NM_ADDQ_S_PH:
20526 check_dsp(ctx);
20527 switch (extract32(ctx->opcode, 10, 1)) {
20528 case 0:
20529 /* ADDQ_PH */
20530 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20531 gen_store_gpr(v1_t, ret);
20532 break;
20533 case 1:
20534 /* ADDQ_S_PH */
20535 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20536 gen_store_gpr(v1_t, ret);
20537 break;
20539 break;
20540 case NM_ADDQH_R_PH:
20541 check_dsp_r2(ctx);
20542 switch (extract32(ctx->opcode, 10, 1)) {
20543 case 0:
20544 /* ADDQH_PH */
20545 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20546 gen_store_gpr(v1_t, ret);
20547 break;
20548 case 1:
20549 /* ADDQH_R_PH */
20550 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20551 gen_store_gpr(v1_t, ret);
20552 break;
20554 break;
20555 case NM_ADDQH_R_W:
20556 check_dsp_r2(ctx);
20557 switch (extract32(ctx->opcode, 10, 1)) {
20558 case 0:
20559 /* ADDQH_W */
20560 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20561 gen_store_gpr(v1_t, ret);
20562 break;
20563 case 1:
20564 /* ADDQH_R_W */
20565 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20566 gen_store_gpr(v1_t, ret);
20567 break;
20569 break;
20570 case NM_ADDU_S_QB:
20571 check_dsp(ctx);
20572 switch (extract32(ctx->opcode, 10, 1)) {
20573 case 0:
20574 /* ADDU_QB */
20575 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20576 gen_store_gpr(v1_t, ret);
20577 break;
20578 case 1:
20579 /* ADDU_S_QB */
20580 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20581 gen_store_gpr(v1_t, ret);
20582 break;
20584 break;
20585 case NM_ADDU_S_PH:
20586 check_dsp_r2(ctx);
20587 switch (extract32(ctx->opcode, 10, 1)) {
20588 case 0:
20589 /* ADDU_PH */
20590 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20591 gen_store_gpr(v1_t, ret);
20592 break;
20593 case 1:
20594 /* ADDU_S_PH */
20595 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20596 gen_store_gpr(v1_t, ret);
20597 break;
20599 break;
20600 case NM_ADDUH_R_QB:
20601 check_dsp_r2(ctx);
20602 switch (extract32(ctx->opcode, 10, 1)) {
20603 case 0:
20604 /* ADDUH_QB */
20605 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20606 gen_store_gpr(v1_t, ret);
20607 break;
20608 case 1:
20609 /* ADDUH_R_QB */
20610 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20611 gen_store_gpr(v1_t, ret);
20612 break;
20614 break;
20615 case NM_SHRAV_R_PH:
20616 check_dsp(ctx);
20617 switch (extract32(ctx->opcode, 10, 1)) {
20618 case 0:
20619 /* SHRAV_PH */
20620 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20621 gen_store_gpr(v1_t, ret);
20622 break;
20623 case 1:
20624 /* SHRAV_R_PH */
20625 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20626 gen_store_gpr(v1_t, ret);
20627 break;
20629 break;
20630 case NM_SHRAV_R_QB:
20631 check_dsp_r2(ctx);
20632 switch (extract32(ctx->opcode, 10, 1)) {
20633 case 0:
20634 /* SHRAV_QB */
20635 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20636 gen_store_gpr(v1_t, ret);
20637 break;
20638 case 1:
20639 /* SHRAV_R_QB */
20640 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20641 gen_store_gpr(v1_t, ret);
20642 break;
20644 break;
20645 case NM_SUBQ_S_PH:
20646 check_dsp(ctx);
20647 switch (extract32(ctx->opcode, 10, 1)) {
20648 case 0:
20649 /* SUBQ_PH */
20650 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20651 gen_store_gpr(v1_t, ret);
20652 break;
20653 case 1:
20654 /* SUBQ_S_PH */
20655 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20656 gen_store_gpr(v1_t, ret);
20657 break;
20659 break;
20660 case NM_SUBQH_R_PH:
20661 check_dsp_r2(ctx);
20662 switch (extract32(ctx->opcode, 10, 1)) {
20663 case 0:
20664 /* SUBQH_PH */
20665 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20666 gen_store_gpr(v1_t, ret);
20667 break;
20668 case 1:
20669 /* SUBQH_R_PH */
20670 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20671 gen_store_gpr(v1_t, ret);
20672 break;
20674 break;
20675 case NM_SUBQH_R_W:
20676 check_dsp_r2(ctx);
20677 switch (extract32(ctx->opcode, 10, 1)) {
20678 case 0:
20679 /* SUBQH_W */
20680 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20681 gen_store_gpr(v1_t, ret);
20682 break;
20683 case 1:
20684 /* SUBQH_R_W */
20685 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20686 gen_store_gpr(v1_t, ret);
20687 break;
20689 break;
20690 case NM_SUBU_S_QB:
20691 check_dsp(ctx);
20692 switch (extract32(ctx->opcode, 10, 1)) {
20693 case 0:
20694 /* SUBU_QB */
20695 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20696 gen_store_gpr(v1_t, ret);
20697 break;
20698 case 1:
20699 /* SUBU_S_QB */
20700 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20701 gen_store_gpr(v1_t, ret);
20702 break;
20704 break;
20705 case NM_SUBU_S_PH:
20706 check_dsp_r2(ctx);
20707 switch (extract32(ctx->opcode, 10, 1)) {
20708 case 0:
20709 /* SUBU_PH */
20710 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20711 gen_store_gpr(v1_t, ret);
20712 break;
20713 case 1:
20714 /* SUBU_S_PH */
20715 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20716 gen_store_gpr(v1_t, ret);
20717 break;
20719 break;
20720 case NM_SUBUH_R_QB:
20721 check_dsp_r2(ctx);
20722 switch (extract32(ctx->opcode, 10, 1)) {
20723 case 0:
20724 /* SUBUH_QB */
20725 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20726 gen_store_gpr(v1_t, ret);
20727 break;
20728 case 1:
20729 /* SUBUH_R_QB */
20730 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20731 gen_store_gpr(v1_t, ret);
20732 break;
20734 break;
20735 case NM_SHLLV_S_PH:
20736 check_dsp(ctx);
20737 switch (extract32(ctx->opcode, 10, 1)) {
20738 case 0:
20739 /* SHLLV_PH */
20740 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20741 gen_store_gpr(v1_t, ret);
20742 break;
20743 case 1:
20744 /* SHLLV_S_PH */
20745 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20746 gen_store_gpr(v1_t, ret);
20747 break;
20749 break;
20750 case NM_PRECR_SRA_R_PH_W:
20751 check_dsp_r2(ctx);
20752 switch (extract32(ctx->opcode, 10, 1)) {
20753 case 0:
20754 /* PRECR_SRA_PH_W */
20756 TCGv_i32 sa_t = tcg_const_i32(rd);
20757 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20758 cpu_gpr[rt]);
20759 gen_store_gpr(v1_t, rt);
20760 tcg_temp_free_i32(sa_t);
20762 break;
20763 case 1:
20764 /* PRECR_SRA_R_PH_W */
20766 TCGv_i32 sa_t = tcg_const_i32(rd);
20767 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20768 cpu_gpr[rt]);
20769 gen_store_gpr(v1_t, rt);
20770 tcg_temp_free_i32(sa_t);
20772 break;
20774 break;
20775 case NM_MULEU_S_PH_QBL:
20776 check_dsp(ctx);
20777 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20778 gen_store_gpr(v1_t, ret);
20779 break;
20780 case NM_MULEU_S_PH_QBR:
20781 check_dsp(ctx);
20782 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20783 gen_store_gpr(v1_t, ret);
20784 break;
20785 case NM_MULQ_RS_PH:
20786 check_dsp(ctx);
20787 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20788 gen_store_gpr(v1_t, ret);
20789 break;
20790 case NM_MULQ_S_PH:
20791 check_dsp_r2(ctx);
20792 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20793 gen_store_gpr(v1_t, ret);
20794 break;
20795 case NM_MULQ_RS_W:
20796 check_dsp_r2(ctx);
20797 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20798 gen_store_gpr(v1_t, ret);
20799 break;
20800 case NM_MULQ_S_W:
20801 check_dsp_r2(ctx);
20802 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20803 gen_store_gpr(v1_t, ret);
20804 break;
20805 case NM_APPEND:
20806 check_dsp_r2(ctx);
20807 gen_load_gpr(t0, rs);
20808 if (rd != 0) {
20809 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20811 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20812 break;
20813 case NM_MODSUB:
20814 check_dsp(ctx);
20815 gen_helper_modsub(v1_t, v1_t, v2_t);
20816 gen_store_gpr(v1_t, ret);
20817 break;
20818 case NM_SHRAV_R_W:
20819 check_dsp(ctx);
20820 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20821 gen_store_gpr(v1_t, ret);
20822 break;
20823 case NM_SHRLV_PH:
20824 check_dsp_r2(ctx);
20825 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20826 gen_store_gpr(v1_t, ret);
20827 break;
20828 case NM_SHRLV_QB:
20829 check_dsp(ctx);
20830 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20831 gen_store_gpr(v1_t, ret);
20832 break;
20833 case NM_SHLLV_QB:
20834 check_dsp(ctx);
20835 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20836 gen_store_gpr(v1_t, ret);
20837 break;
20838 case NM_SHLLV_S_W:
20839 check_dsp(ctx);
20840 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20841 gen_store_gpr(v1_t, ret);
20842 break;
20843 case NM_SHILO:
20844 check_dsp(ctx);
20846 TCGv tv0 = tcg_temp_new();
20847 TCGv tv1 = tcg_temp_new();
20848 int16_t imm = extract32(ctx->opcode, 16, 7);
20850 tcg_gen_movi_tl(tv0, rd >> 3);
20851 tcg_gen_movi_tl(tv1, imm);
20852 gen_helper_shilo(tv0, tv1, cpu_env);
20854 break;
20855 case NM_MULEQ_S_W_PHL:
20856 check_dsp(ctx);
20857 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20858 gen_store_gpr(v1_t, ret);
20859 break;
20860 case NM_MULEQ_S_W_PHR:
20861 check_dsp(ctx);
20862 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20863 gen_store_gpr(v1_t, ret);
20864 break;
20865 case NM_MUL_S_PH:
20866 check_dsp_r2(ctx);
20867 switch (extract32(ctx->opcode, 10, 1)) {
20868 case 0:
20869 /* MUL_PH */
20870 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20871 gen_store_gpr(v1_t, ret);
20872 break;
20873 case 1:
20874 /* MUL_S_PH */
20875 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20876 gen_store_gpr(v1_t, ret);
20877 break;
20879 break;
20880 case NM_PRECR_QB_PH:
20881 check_dsp_r2(ctx);
20882 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20883 gen_store_gpr(v1_t, ret);
20884 break;
20885 case NM_PRECRQ_QB_PH:
20886 check_dsp(ctx);
20887 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20888 gen_store_gpr(v1_t, ret);
20889 break;
20890 case NM_PRECRQ_PH_W:
20891 check_dsp(ctx);
20892 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20893 gen_store_gpr(v1_t, ret);
20894 break;
20895 case NM_PRECRQ_RS_PH_W:
20896 check_dsp(ctx);
20897 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20898 gen_store_gpr(v1_t, ret);
20899 break;
20900 case NM_PRECRQU_S_QB_PH:
20901 check_dsp(ctx);
20902 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20903 gen_store_gpr(v1_t, ret);
20904 break;
20905 case NM_SHRA_R_W:
20906 check_dsp(ctx);
20907 tcg_gen_movi_tl(t0, rd);
20908 gen_helper_shra_r_w(v1_t, t0, v1_t);
20909 gen_store_gpr(v1_t, rt);
20910 break;
20911 case NM_SHRA_R_PH:
20912 check_dsp(ctx);
20913 tcg_gen_movi_tl(t0, rd >> 1);
20914 switch (extract32(ctx->opcode, 10, 1)) {
20915 case 0:
20916 /* SHRA_PH */
20917 gen_helper_shra_ph(v1_t, t0, v1_t);
20918 gen_store_gpr(v1_t, rt);
20919 break;
20920 case 1:
20921 /* SHRA_R_PH */
20922 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20923 gen_store_gpr(v1_t, rt);
20924 break;
20926 break;
20927 case NM_SHLL_S_PH:
20928 check_dsp(ctx);
20929 tcg_gen_movi_tl(t0, rd >> 1);
20930 switch (extract32(ctx->opcode, 10, 2)) {
20931 case 0:
20932 /* SHLL_PH */
20933 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20934 gen_store_gpr(v1_t, rt);
20935 break;
20936 case 2:
20937 /* SHLL_S_PH */
20938 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20939 gen_store_gpr(v1_t, rt);
20940 break;
20941 default:
20942 generate_exception_end(ctx, EXCP_RI);
20943 break;
20945 break;
20946 case NM_SHLL_S_W:
20947 check_dsp(ctx);
20948 tcg_gen_movi_tl(t0, rd);
20949 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20950 gen_store_gpr(v1_t, rt);
20951 break;
20952 case NM_REPL_PH:
20953 check_dsp(ctx);
20955 int16_t imm;
20956 imm = sextract32(ctx->opcode, 11, 11);
20957 imm = (int16_t)(imm << 6) >> 6;
20958 if (rt != 0) {
20959 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20962 break;
20963 default:
20964 generate_exception_end(ctx, EXCP_RI);
20965 break;
20969 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20971 uint16_t insn;
20972 uint32_t op;
20973 int rt, rs, rd;
20974 int offset;
20975 int imm;
20977 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20978 ctx->opcode = (ctx->opcode << 16) | insn;
20980 rt = extract32(ctx->opcode, 21, 5);
20981 rs = extract32(ctx->opcode, 16, 5);
20982 rd = extract32(ctx->opcode, 11, 5);
20984 op = extract32(ctx->opcode, 26, 6);
20985 switch (op) {
20986 case NM_P_ADDIU:
20987 if (rt == 0) {
20988 /* P.RI */
20989 switch (extract32(ctx->opcode, 19, 2)) {
20990 case NM_SIGRIE:
20991 default:
20992 generate_exception_end(ctx, EXCP_RI);
20993 break;
20994 case NM_P_SYSCALL:
20995 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20996 generate_exception_end(ctx, EXCP_SYSCALL);
20997 } else {
20998 generate_exception_end(ctx, EXCP_RI);
21000 break;
21001 case NM_BREAK:
21002 generate_exception_end(ctx, EXCP_BREAK);
21003 break;
21004 case NM_SDBBP:
21005 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21006 gen_helper_do_semihosting(cpu_env);
21007 } else {
21008 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21009 generate_exception_end(ctx, EXCP_RI);
21010 } else {
21011 generate_exception_end(ctx, EXCP_DBp);
21014 break;
21016 } else {
21017 /* NM_ADDIU */
21018 imm = extract32(ctx->opcode, 0, 16);
21019 if (rs != 0) {
21020 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21021 } else {
21022 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21024 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21026 break;
21027 case NM_ADDIUPC:
21028 if (rt != 0) {
21029 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21030 extract32(ctx->opcode, 1, 20) << 1;
21031 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21032 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21034 break;
21035 case NM_POOL32A:
21036 switch (ctx->opcode & 0x07) {
21037 case NM_POOL32A0:
21038 gen_pool32a0_nanomips_insn(env, ctx);
21039 break;
21040 case NM_POOL32A5:
21042 int32_t op1 = extract32(ctx->opcode, 3, 7);
21043 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21045 break;
21046 case NM_POOL32A7:
21047 switch (extract32(ctx->opcode, 3, 3)) {
21048 case NM_P_LSX:
21049 gen_p_lsx(ctx, rd, rs, rt);
21050 break;
21051 case NM_LSA:
21052 /* In nanoMIPS, the shift field directly encodes the shift
21053 * amount, meaning that the supported shift values are in
21054 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
21055 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21056 extract32(ctx->opcode, 9, 2) - 1);
21057 break;
21058 case NM_EXTW:
21059 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21060 break;
21061 case NM_POOL32AXF:
21062 gen_pool32axf_nanomips_insn(env, ctx);
21063 break;
21064 default:
21065 generate_exception_end(ctx, EXCP_RI);
21066 break;
21068 break;
21069 default:
21070 generate_exception_end(ctx, EXCP_RI);
21071 break;
21073 break;
21074 case NM_P_GP_W:
21075 switch (ctx->opcode & 0x03) {
21076 case NM_ADDIUGP_W:
21077 if (rt != 0) {
21078 offset = extract32(ctx->opcode, 0, 21);
21079 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21081 break;
21082 case NM_LWGP:
21083 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21084 break;
21085 case NM_SWGP:
21086 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21087 break;
21088 default:
21089 generate_exception_end(ctx, EXCP_RI);
21090 break;
21092 break;
21093 case NM_P48I:
21095 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21096 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21097 switch (extract32(ctx->opcode, 16, 5)) {
21098 case NM_LI48:
21099 check_nms(ctx);
21100 if (rt != 0) {
21101 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21103 break;
21104 case NM_ADDIU48:
21105 check_nms(ctx);
21106 if (rt != 0) {
21107 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21108 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21110 break;
21111 case NM_ADDIUGP48:
21112 check_nms(ctx);
21113 if (rt != 0) {
21114 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21116 break;
21117 case NM_ADDIUPC48:
21118 check_nms(ctx);
21119 if (rt != 0) {
21120 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21121 addr_off);
21123 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21125 break;
21126 case NM_LWPC48:
21127 check_nms(ctx);
21128 if (rt != 0) {
21129 TCGv t0;
21130 t0 = tcg_temp_new();
21132 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21133 addr_off);
21135 tcg_gen_movi_tl(t0, addr);
21136 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21137 tcg_temp_free(t0);
21139 break;
21140 case NM_SWPC48:
21141 check_nms(ctx);
21143 TCGv t0, t1;
21144 t0 = tcg_temp_new();
21145 t1 = tcg_temp_new();
21147 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21148 addr_off);
21150 tcg_gen_movi_tl(t0, addr);
21151 gen_load_gpr(t1, rt);
21153 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21155 tcg_temp_free(t0);
21156 tcg_temp_free(t1);
21158 break;
21159 default:
21160 generate_exception_end(ctx, EXCP_RI);
21161 break;
21163 return 6;
21165 case NM_P_U12:
21166 switch (extract32(ctx->opcode, 12, 4)) {
21167 case NM_ORI:
21168 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21169 break;
21170 case NM_XORI:
21171 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21172 break;
21173 case NM_ANDI:
21174 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21175 break;
21176 case NM_P_SR:
21177 switch (extract32(ctx->opcode, 20, 1)) {
21178 case NM_PP_SR:
21179 switch (ctx->opcode & 3) {
21180 case NM_SAVE:
21181 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21182 extract32(ctx->opcode, 2, 1),
21183 extract32(ctx->opcode, 3, 9) << 3);
21184 break;
21185 case NM_RESTORE:
21186 case NM_RESTORE_JRC:
21187 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21188 extract32(ctx->opcode, 2, 1),
21189 extract32(ctx->opcode, 3, 9) << 3);
21190 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21191 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21193 break;
21194 default:
21195 generate_exception_end(ctx, EXCP_RI);
21196 break;
21198 break;
21199 case NM_P_SR_F:
21200 generate_exception_end(ctx, EXCP_RI);
21201 break;
21203 break;
21204 case NM_SLTI:
21205 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21206 break;
21207 case NM_SLTIU:
21208 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21209 break;
21210 case NM_SEQI:
21212 TCGv t0 = tcg_temp_new();
21214 imm = extract32(ctx->opcode, 0, 12);
21215 gen_load_gpr(t0, rs);
21216 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21217 gen_store_gpr(t0, rt);
21219 tcg_temp_free(t0);
21221 break;
21222 case NM_ADDIUNEG:
21223 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21224 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21225 break;
21226 case NM_P_SHIFT:
21228 int shift = extract32(ctx->opcode, 0, 5);
21229 switch (extract32(ctx->opcode, 5, 4)) {
21230 case NM_P_SLL:
21231 if (rt == 0 && shift == 0) {
21232 /* NOP */
21233 } else if (rt == 0 && shift == 3) {
21234 /* EHB - treat as NOP */
21235 } else if (rt == 0 && shift == 5) {
21236 /* PAUSE - treat as NOP */
21237 } else if (rt == 0 && shift == 6) {
21238 /* SYNC */
21239 gen_sync(extract32(ctx->opcode, 16, 5));
21240 } else {
21241 /* SLL */
21242 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21243 extract32(ctx->opcode, 0, 5));
21245 break;
21246 case NM_SRL:
21247 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21248 extract32(ctx->opcode, 0, 5));
21249 break;
21250 case NM_SRA:
21251 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21252 extract32(ctx->opcode, 0, 5));
21253 break;
21254 case NM_ROTR:
21255 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21256 extract32(ctx->opcode, 0, 5));
21257 break;
21260 break;
21261 case NM_P_ROTX:
21262 check_nms(ctx);
21263 if (rt != 0) {
21264 TCGv t0 = tcg_temp_new();
21265 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21266 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21267 << 1);
21268 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21270 gen_load_gpr(t0, rs);
21271 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21272 tcg_temp_free(t0);
21274 tcg_temp_free_i32(shift);
21275 tcg_temp_free_i32(shiftx);
21276 tcg_temp_free_i32(stripe);
21278 break;
21279 case NM_P_INS:
21280 switch (((ctx->opcode >> 10) & 2) |
21281 (extract32(ctx->opcode, 5, 1))) {
21282 case NM_INS:
21283 check_nms(ctx);
21284 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21285 extract32(ctx->opcode, 6, 5));
21286 break;
21287 default:
21288 generate_exception_end(ctx, EXCP_RI);
21289 break;
21291 break;
21292 case NM_P_EXT:
21293 switch (((ctx->opcode >> 10) & 2) |
21294 (extract32(ctx->opcode, 5, 1))) {
21295 case NM_EXT:
21296 check_nms(ctx);
21297 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21298 extract32(ctx->opcode, 6, 5));
21299 break;
21300 default:
21301 generate_exception_end(ctx, EXCP_RI);
21302 break;
21304 break;
21305 default:
21306 generate_exception_end(ctx, EXCP_RI);
21307 break;
21309 break;
21310 case NM_POOL32F:
21311 gen_pool32f_nanomips_insn(ctx);
21312 break;
21313 case NM_POOL32S:
21314 break;
21315 case NM_P_LUI:
21316 switch (extract32(ctx->opcode, 1, 1)) {
21317 case NM_LUI:
21318 if (rt != 0) {
21319 tcg_gen_movi_tl(cpu_gpr[rt],
21320 sextract32(ctx->opcode, 0, 1) << 31 |
21321 extract32(ctx->opcode, 2, 10) << 21 |
21322 extract32(ctx->opcode, 12, 9) << 12);
21324 break;
21325 case NM_ALUIPC:
21326 if (rt != 0) {
21327 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21328 extract32(ctx->opcode, 2, 10) << 21 |
21329 extract32(ctx->opcode, 12, 9) << 12;
21330 target_long addr;
21331 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21332 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21334 break;
21336 break;
21337 case NM_P_GP_BH:
21339 uint32_t u = extract32(ctx->opcode, 0, 18);
21341 switch (extract32(ctx->opcode, 18, 3)) {
21342 case NM_LBGP:
21343 gen_ld(ctx, OPC_LB, rt, 28, u);
21344 break;
21345 case NM_SBGP:
21346 gen_st(ctx, OPC_SB, rt, 28, u);
21347 break;
21348 case NM_LBUGP:
21349 gen_ld(ctx, OPC_LBU, rt, 28, u);
21350 break;
21351 case NM_ADDIUGP_B:
21352 if (rt != 0) {
21353 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21355 break;
21356 case NM_P_GP_LH:
21357 u &= ~1;
21358 switch (ctx->opcode & 1) {
21359 case NM_LHGP:
21360 gen_ld(ctx, OPC_LH, rt, 28, u);
21361 break;
21362 case NM_LHUGP:
21363 gen_ld(ctx, OPC_LHU, rt, 28, u);
21364 break;
21366 break;
21367 case NM_P_GP_SH:
21368 u &= ~1;
21369 switch (ctx->opcode & 1) {
21370 case NM_SHGP:
21371 gen_st(ctx, OPC_SH, rt, 28, u);
21372 break;
21373 default:
21374 generate_exception_end(ctx, EXCP_RI);
21375 break;
21377 break;
21378 case NM_P_GP_CP1:
21379 u &= ~0x3;
21380 switch (ctx->opcode & 0x3) {
21381 case NM_LWC1GP:
21382 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21383 break;
21384 case NM_LDC1GP:
21385 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21386 break;
21387 case NM_SWC1GP:
21388 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21389 break;
21390 case NM_SDC1GP:
21391 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21392 break;
21394 break;
21395 default:
21396 generate_exception_end(ctx, EXCP_RI);
21397 break;
21400 break;
21401 case NM_P_LS_U12:
21403 uint32_t u = extract32(ctx->opcode, 0, 12);
21405 switch (extract32(ctx->opcode, 12, 4)) {
21406 case NM_P_PREFU12:
21407 if (rt == 31) {
21408 /* SYNCI */
21409 /* Break the TB to be able to sync copied instructions
21410 immediately */
21411 ctx->base.is_jmp = DISAS_STOP;
21412 } else {
21413 /* PREF */
21414 /* Treat as NOP. */
21416 break;
21417 case NM_LB:
21418 gen_ld(ctx, OPC_LB, rt, rs, u);
21419 break;
21420 case NM_LH:
21421 gen_ld(ctx, OPC_LH, rt, rs, u);
21422 break;
21423 case NM_LW:
21424 gen_ld(ctx, OPC_LW, rt, rs, u);
21425 break;
21426 case NM_LBU:
21427 gen_ld(ctx, OPC_LBU, rt, rs, u);
21428 break;
21429 case NM_LHU:
21430 gen_ld(ctx, OPC_LHU, rt, rs, u);
21431 break;
21432 case NM_SB:
21433 gen_st(ctx, OPC_SB, rt, rs, u);
21434 break;
21435 case NM_SH:
21436 gen_st(ctx, OPC_SH, rt, rs, u);
21437 break;
21438 case NM_SW:
21439 gen_st(ctx, OPC_SW, rt, rs, u);
21440 break;
21441 case NM_LWC1:
21442 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21443 break;
21444 case NM_LDC1:
21445 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21446 break;
21447 case NM_SWC1:
21448 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21449 break;
21450 case NM_SDC1:
21451 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21452 break;
21453 default:
21454 generate_exception_end(ctx, EXCP_RI);
21455 break;
21458 break;
21459 case NM_P_LS_S9:
21461 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21462 extract32(ctx->opcode, 0, 8);
21464 switch (extract32(ctx->opcode, 8, 3)) {
21465 case NM_P_LS_S0:
21466 switch (extract32(ctx->opcode, 11, 4)) {
21467 case NM_LBS9:
21468 gen_ld(ctx, OPC_LB, rt, rs, s);
21469 break;
21470 case NM_LHS9:
21471 gen_ld(ctx, OPC_LH, rt, rs, s);
21472 break;
21473 case NM_LWS9:
21474 gen_ld(ctx, OPC_LW, rt, rs, s);
21475 break;
21476 case NM_LBUS9:
21477 gen_ld(ctx, OPC_LBU, rt, rs, s);
21478 break;
21479 case NM_LHUS9:
21480 gen_ld(ctx, OPC_LHU, rt, rs, s);
21481 break;
21482 case NM_SBS9:
21483 gen_st(ctx, OPC_SB, rt, rs, s);
21484 break;
21485 case NM_SHS9:
21486 gen_st(ctx, OPC_SH, rt, rs, s);
21487 break;
21488 case NM_SWS9:
21489 gen_st(ctx, OPC_SW, rt, rs, s);
21490 break;
21491 case NM_LWC1S9:
21492 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21493 break;
21494 case NM_LDC1S9:
21495 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21496 break;
21497 case NM_SWC1S9:
21498 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21499 break;
21500 case NM_SDC1S9:
21501 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21502 break;
21503 case NM_P_PREFS9:
21504 if (rt == 31) {
21505 /* SYNCI */
21506 /* Break the TB to be able to sync copied instructions
21507 immediately */
21508 ctx->base.is_jmp = DISAS_STOP;
21509 } else {
21510 /* PREF */
21511 /* Treat as NOP. */
21513 break;
21514 default:
21515 generate_exception_end(ctx, EXCP_RI);
21516 break;
21518 break;
21519 case NM_P_LS_S1:
21520 switch (extract32(ctx->opcode, 11, 4)) {
21521 case NM_UALH:
21522 case NM_UASH:
21523 check_nms(ctx);
21525 TCGv t0 = tcg_temp_new();
21526 TCGv t1 = tcg_temp_new();
21528 gen_base_offset_addr(ctx, t0, rs, s);
21530 switch (extract32(ctx->opcode, 11, 4)) {
21531 case NM_UALH:
21532 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21533 MO_UNALN);
21534 gen_store_gpr(t0, rt);
21535 break;
21536 case NM_UASH:
21537 gen_load_gpr(t1, rt);
21538 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21539 MO_UNALN);
21540 break;
21542 tcg_temp_free(t0);
21543 tcg_temp_free(t1);
21545 break;
21546 case NM_P_LL:
21547 switch (ctx->opcode & 0x03) {
21548 case NM_LL:
21549 gen_ld(ctx, OPC_LL, rt, rs, s);
21550 break;
21551 case NM_LLWP:
21552 check_xnp(ctx);
21553 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21554 break;
21556 break;
21557 case NM_P_SC:
21558 switch (ctx->opcode & 0x03) {
21559 case NM_SC:
21560 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21561 break;
21562 case NM_SCWP:
21563 check_xnp(ctx);
21564 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21565 break;
21567 break;
21568 case NM_CACHE:
21569 check_cp0_enabled(ctx);
21570 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21571 gen_cache_operation(ctx, rt, rs, s);
21573 break;
21575 break;
21576 case NM_P_LS_E0:
21577 switch (extract32(ctx->opcode, 11, 4)) {
21578 case NM_LBE:
21579 check_eva(ctx);
21580 check_cp0_enabled(ctx);
21581 gen_ld(ctx, OPC_LBE, rt, rs, s);
21582 break;
21583 case NM_SBE:
21584 check_eva(ctx);
21585 check_cp0_enabled(ctx);
21586 gen_st(ctx, OPC_SBE, rt, rs, s);
21587 break;
21588 case NM_LBUE:
21589 check_eva(ctx);
21590 check_cp0_enabled(ctx);
21591 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21592 break;
21593 case NM_P_PREFE:
21594 if (rt == 31) {
21595 /* case NM_SYNCIE */
21596 check_eva(ctx);
21597 check_cp0_enabled(ctx);
21598 /* Break the TB to be able to sync copied instructions
21599 immediately */
21600 ctx->base.is_jmp = DISAS_STOP;
21601 } else {
21602 /* case NM_PREFE */
21603 check_eva(ctx);
21604 check_cp0_enabled(ctx);
21605 /* Treat as NOP. */
21607 break;
21608 case NM_LHE:
21609 check_eva(ctx);
21610 check_cp0_enabled(ctx);
21611 gen_ld(ctx, OPC_LHE, rt, rs, s);
21612 break;
21613 case NM_SHE:
21614 check_eva(ctx);
21615 check_cp0_enabled(ctx);
21616 gen_st(ctx, OPC_SHE, rt, rs, s);
21617 break;
21618 case NM_LHUE:
21619 check_eva(ctx);
21620 check_cp0_enabled(ctx);
21621 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21622 break;
21623 case NM_CACHEE:
21624 check_nms_dl_il_sl_tl_l2c(ctx);
21625 gen_cache_operation(ctx, rt, rs, s);
21626 break;
21627 case NM_LWE:
21628 check_eva(ctx);
21629 check_cp0_enabled(ctx);
21630 gen_ld(ctx, OPC_LWE, rt, rs, s);
21631 break;
21632 case NM_SWE:
21633 check_eva(ctx);
21634 check_cp0_enabled(ctx);
21635 gen_st(ctx, OPC_SWE, rt, rs, s);
21636 break;
21637 case NM_P_LLE:
21638 switch (extract32(ctx->opcode, 2, 2)) {
21639 case NM_LLE:
21640 check_xnp(ctx);
21641 check_eva(ctx);
21642 check_cp0_enabled(ctx);
21643 gen_ld(ctx, OPC_LLE, rt, rs, s);
21644 break;
21645 case NM_LLWPE:
21646 check_xnp(ctx);
21647 check_eva(ctx);
21648 check_cp0_enabled(ctx);
21649 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21650 break;
21651 default:
21652 generate_exception_end(ctx, EXCP_RI);
21653 break;
21655 break;
21656 case NM_P_SCE:
21657 switch (extract32(ctx->opcode, 2, 2)) {
21658 case NM_SCE:
21659 check_xnp(ctx);
21660 check_eva(ctx);
21661 check_cp0_enabled(ctx);
21662 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21663 break;
21664 case NM_SCWPE:
21665 check_xnp(ctx);
21666 check_eva(ctx);
21667 check_cp0_enabled(ctx);
21668 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21669 break;
21670 default:
21671 generate_exception_end(ctx, EXCP_RI);
21672 break;
21674 break;
21676 break;
21677 case NM_P_LS_WM:
21678 case NM_P_LS_UAWM:
21679 check_nms(ctx);
21681 int count = extract32(ctx->opcode, 12, 3);
21682 int counter = 0;
21684 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21685 extract32(ctx->opcode, 0, 8);
21686 TCGv va = tcg_temp_new();
21687 TCGv t1 = tcg_temp_new();
21688 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21689 NM_P_LS_UAWM ? MO_UNALN : 0;
21691 count = (count == 0) ? 8 : count;
21692 while (counter != count) {
21693 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21694 int this_offset = offset + (counter << 2);
21696 gen_base_offset_addr(ctx, va, rs, this_offset);
21698 switch (extract32(ctx->opcode, 11, 1)) {
21699 case NM_LWM:
21700 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21701 memop | MO_TESL);
21702 gen_store_gpr(t1, this_rt);
21703 if ((this_rt == rs) &&
21704 (counter != (count - 1))) {
21705 /* UNPREDICTABLE */
21707 break;
21708 case NM_SWM:
21709 this_rt = (rt == 0) ? 0 : this_rt;
21710 gen_load_gpr(t1, this_rt);
21711 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21712 memop | MO_TEUL);
21713 break;
21715 counter++;
21717 tcg_temp_free(va);
21718 tcg_temp_free(t1);
21720 break;
21721 default:
21722 generate_exception_end(ctx, EXCP_RI);
21723 break;
21726 break;
21727 case NM_MOVE_BALC:
21728 check_nms(ctx);
21730 TCGv t0 = tcg_temp_new();
21731 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21732 extract32(ctx->opcode, 1, 20) << 1;
21733 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21734 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21735 extract32(ctx->opcode, 21, 3));
21736 gen_load_gpr(t0, rt);
21737 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21738 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21739 tcg_temp_free(t0);
21741 break;
21742 case NM_P_BAL:
21744 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21745 extract32(ctx->opcode, 1, 24) << 1;
21747 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21748 /* BC */
21749 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21750 } else {
21751 /* BALC */
21752 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21755 break;
21756 case NM_P_J:
21757 switch (extract32(ctx->opcode, 12, 4)) {
21758 case NM_JALRC:
21759 case NM_JALRC_HB:
21760 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21761 break;
21762 case NM_P_BALRSC:
21763 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21764 break;
21765 default:
21766 generate_exception_end(ctx, EXCP_RI);
21767 break;
21769 break;
21770 case NM_P_BR1:
21772 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21773 extract32(ctx->opcode, 1, 13) << 1;
21774 switch (extract32(ctx->opcode, 14, 2)) {
21775 case NM_BEQC:
21776 check_nms(ctx);
21777 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21778 break;
21779 case NM_P_BR3A:
21780 s = sextract32(ctx->opcode, 0, 1) << 14 |
21781 extract32(ctx->opcode, 1, 13) << 1;
21782 check_cp1_enabled(ctx);
21783 switch (extract32(ctx->opcode, 16, 5)) {
21784 case NM_BC1EQZC:
21785 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21786 break;
21787 case NM_BC1NEZC:
21788 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21789 break;
21790 case NM_BPOSGE32C:
21791 check_dsp_r3(ctx);
21793 int32_t imm = extract32(ctx->opcode, 1, 13) |
21794 extract32(ctx->opcode, 0, 1) << 13;
21796 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21797 imm);
21799 break;
21800 default:
21801 generate_exception_end(ctx, EXCP_RI);
21802 break;
21804 break;
21805 case NM_BGEC:
21806 if (rs == rt) {
21807 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21808 } else {
21809 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21811 break;
21812 case NM_BGEUC:
21813 if (rs == rt || rt == 0) {
21814 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21815 } else if (rs == 0) {
21816 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21817 } else {
21818 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21820 break;
21823 break;
21824 case NM_P_BR2:
21826 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21827 extract32(ctx->opcode, 1, 13) << 1;
21828 switch (extract32(ctx->opcode, 14, 2)) {
21829 case NM_BNEC:
21830 check_nms(ctx);
21831 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21832 break;
21833 case NM_BLTC:
21834 if (rs != 0 && rt != 0 && rs == rt) {
21835 /* NOP */
21836 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21837 } else {
21838 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21840 break;
21841 case NM_BLTUC:
21842 if (rs == 0 || rs == rt) {
21843 /* NOP */
21844 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21845 } else {
21846 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21848 break;
21849 default:
21850 generate_exception_end(ctx, EXCP_RI);
21851 break;
21854 break;
21855 case NM_P_BRI:
21857 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21858 extract32(ctx->opcode, 1, 10) << 1;
21859 uint32_t u = extract32(ctx->opcode, 11, 7);
21861 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21862 rt, u, s);
21864 break;
21865 default:
21866 generate_exception_end(ctx, EXCP_RI);
21867 break;
21869 return 4;
21872 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21874 uint32_t op;
21875 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21876 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21877 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21878 int offset;
21879 int imm;
21881 /* make sure instructions are on a halfword boundary */
21882 if (ctx->base.pc_next & 0x1) {
21883 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21884 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21885 tcg_temp_free(tmp);
21886 generate_exception_end(ctx, EXCP_AdEL);
21887 return 2;
21890 op = extract32(ctx->opcode, 10, 6);
21891 switch (op) {
21892 case NM_P16_MV:
21893 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21894 if (rt != 0) {
21895 /* MOVE */
21896 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21897 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21898 } else {
21899 /* P16.RI */
21900 switch (extract32(ctx->opcode, 3, 2)) {
21901 case NM_P16_SYSCALL:
21902 if (extract32(ctx->opcode, 2, 1) == 0) {
21903 generate_exception_end(ctx, EXCP_SYSCALL);
21904 } else {
21905 generate_exception_end(ctx, EXCP_RI);
21907 break;
21908 case NM_BREAK16:
21909 generate_exception_end(ctx, EXCP_BREAK);
21910 break;
21911 case NM_SDBBP16:
21912 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21913 gen_helper_do_semihosting(cpu_env);
21914 } else {
21915 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21916 generate_exception_end(ctx, EXCP_RI);
21917 } else {
21918 generate_exception_end(ctx, EXCP_DBp);
21921 break;
21922 default:
21923 generate_exception_end(ctx, EXCP_RI);
21924 break;
21927 break;
21928 case NM_P16_SHIFT:
21930 int shift = extract32(ctx->opcode, 0, 3);
21931 uint32_t opc = 0;
21932 shift = (shift == 0) ? 8 : shift;
21934 switch (extract32(ctx->opcode, 3, 1)) {
21935 case NM_SLL16:
21936 opc = OPC_SLL;
21937 break;
21938 case NM_SRL16:
21939 opc = OPC_SRL;
21940 break;
21942 gen_shift_imm(ctx, opc, rt, rs, shift);
21944 break;
21945 case NM_P16C:
21946 switch (ctx->opcode & 1) {
21947 case NM_POOL16C_0:
21948 gen_pool16c_nanomips_insn(ctx);
21949 break;
21950 case NM_LWXS16:
21951 gen_ldxs(ctx, rt, rs, rd);
21952 break;
21954 break;
21955 case NM_P16_A1:
21956 switch (extract32(ctx->opcode, 6, 1)) {
21957 case NM_ADDIUR1SP:
21958 imm = extract32(ctx->opcode, 0, 6) << 2;
21959 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21960 break;
21961 default:
21962 generate_exception_end(ctx, EXCP_RI);
21963 break;
21965 break;
21966 case NM_P16_A2:
21967 switch (extract32(ctx->opcode, 3, 1)) {
21968 case NM_ADDIUR2:
21969 imm = extract32(ctx->opcode, 0, 3) << 2;
21970 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21971 break;
21972 case NM_P_ADDIURS5:
21973 rt = extract32(ctx->opcode, 5, 5);
21974 if (rt != 0) {
21975 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21976 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21977 (extract32(ctx->opcode, 0, 3));
21978 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21980 break;
21982 break;
21983 case NM_P16_ADDU:
21984 switch (ctx->opcode & 0x1) {
21985 case NM_ADDU16:
21986 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21987 break;
21988 case NM_SUBU16:
21989 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21990 break;
21992 break;
21993 case NM_P16_4X4:
21994 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21995 extract32(ctx->opcode, 5, 3);
21996 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21997 extract32(ctx->opcode, 0, 3);
21998 rt = decode_gpr_gpr4(rt);
21999 rs = decode_gpr_gpr4(rs);
22000 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22001 (extract32(ctx->opcode, 3, 1))) {
22002 case NM_ADDU4X4:
22003 check_nms(ctx);
22004 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22005 break;
22006 case NM_MUL4X4:
22007 check_nms(ctx);
22008 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22009 break;
22010 default:
22011 generate_exception_end(ctx, EXCP_RI);
22012 break;
22014 break;
22015 case NM_LI16:
22017 int imm = extract32(ctx->opcode, 0, 7);
22018 imm = (imm == 0x7f ? -1 : imm);
22019 if (rt != 0) {
22020 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22023 break;
22024 case NM_ANDI16:
22026 uint32_t u = extract32(ctx->opcode, 0, 4);
22027 u = (u == 12) ? 0xff :
22028 (u == 13) ? 0xffff : u;
22029 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22031 break;
22032 case NM_P16_LB:
22033 offset = extract32(ctx->opcode, 0, 2);
22034 switch (extract32(ctx->opcode, 2, 2)) {
22035 case NM_LB16:
22036 gen_ld(ctx, OPC_LB, rt, rs, offset);
22037 break;
22038 case NM_SB16:
22039 rt = decode_gpr_gpr3_src_store(
22040 NANOMIPS_EXTRACT_RD(ctx->opcode));
22041 gen_st(ctx, OPC_SB, rt, rs, offset);
22042 break;
22043 case NM_LBU16:
22044 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22045 break;
22046 default:
22047 generate_exception_end(ctx, EXCP_RI);
22048 break;
22050 break;
22051 case NM_P16_LH:
22052 offset = extract32(ctx->opcode, 1, 2) << 1;
22053 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22054 case NM_LH16:
22055 gen_ld(ctx, OPC_LH, rt, rs, offset);
22056 break;
22057 case NM_SH16:
22058 rt = decode_gpr_gpr3_src_store(
22059 NANOMIPS_EXTRACT_RD(ctx->opcode));
22060 gen_st(ctx, OPC_SH, rt, rs, offset);
22061 break;
22062 case NM_LHU16:
22063 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22064 break;
22065 default:
22066 generate_exception_end(ctx, EXCP_RI);
22067 break;
22069 break;
22070 case NM_LW16:
22071 offset = extract32(ctx->opcode, 0, 4) << 2;
22072 gen_ld(ctx, OPC_LW, rt, rs, offset);
22073 break;
22074 case NM_LWSP16:
22075 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22076 offset = extract32(ctx->opcode, 0, 5) << 2;
22077 gen_ld(ctx, OPC_LW, rt, 29, offset);
22078 break;
22079 case NM_LW4X4:
22080 check_nms(ctx);
22081 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22082 extract32(ctx->opcode, 5, 3);
22083 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22084 extract32(ctx->opcode, 0, 3);
22085 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22086 (extract32(ctx->opcode, 8, 1) << 2);
22087 rt = decode_gpr_gpr4(rt);
22088 rs = decode_gpr_gpr4(rs);
22089 gen_ld(ctx, OPC_LW, rt, rs, offset);
22090 break;
22091 case NM_SW4X4:
22092 check_nms(ctx);
22093 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22094 extract32(ctx->opcode, 5, 3);
22095 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22096 extract32(ctx->opcode, 0, 3);
22097 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22098 (extract32(ctx->opcode, 8, 1) << 2);
22099 rt = decode_gpr_gpr4_zero(rt);
22100 rs = decode_gpr_gpr4(rs);
22101 gen_st(ctx, OPC_SW, rt, rs, offset);
22102 break;
22103 case NM_LWGP16:
22104 offset = extract32(ctx->opcode, 0, 7) << 2;
22105 gen_ld(ctx, OPC_LW, rt, 28, offset);
22106 break;
22107 case NM_SWSP16:
22108 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22109 offset = extract32(ctx->opcode, 0, 5) << 2;
22110 gen_st(ctx, OPC_SW, rt, 29, offset);
22111 break;
22112 case NM_SW16:
22113 rt = decode_gpr_gpr3_src_store(
22114 NANOMIPS_EXTRACT_RD(ctx->opcode));
22115 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
22116 offset = extract32(ctx->opcode, 0, 4) << 2;
22117 gen_st(ctx, OPC_SW, rt, rs, offset);
22118 break;
22119 case NM_SWGP16:
22120 rt = decode_gpr_gpr3_src_store(
22121 NANOMIPS_EXTRACT_RD(ctx->opcode));
22122 offset = extract32(ctx->opcode, 0, 7) << 2;
22123 gen_st(ctx, OPC_SW, rt, 28, offset);
22124 break;
22125 case NM_BC16:
22126 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22127 (sextract32(ctx->opcode, 0, 1) << 10) |
22128 (extract32(ctx->opcode, 1, 9) << 1));
22129 break;
22130 case NM_BALC16:
22131 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22132 (sextract32(ctx->opcode, 0, 1) << 10) |
22133 (extract32(ctx->opcode, 1, 9) << 1));
22134 break;
22135 case NM_BEQZC16:
22136 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22137 (sextract32(ctx->opcode, 0, 1) << 7) |
22138 (extract32(ctx->opcode, 1, 6) << 1));
22139 break;
22140 case NM_BNEZC16:
22141 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22142 (sextract32(ctx->opcode, 0, 1) << 7) |
22143 (extract32(ctx->opcode, 1, 6) << 1));
22144 break;
22145 case NM_P16_BR:
22146 switch (ctx->opcode & 0xf) {
22147 case 0:
22148 /* P16.JRC */
22149 switch (extract32(ctx->opcode, 4, 1)) {
22150 case NM_JRC:
22151 gen_compute_branch_nm(ctx, OPC_JR, 2,
22152 extract32(ctx->opcode, 5, 5), 0, 0);
22153 break;
22154 case NM_JALRC16:
22155 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22156 extract32(ctx->opcode, 5, 5), 31, 0);
22157 break;
22159 break;
22160 default:
22162 /* P16.BRI */
22163 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22164 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22165 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22166 extract32(ctx->opcode, 0, 4) << 1);
22168 break;
22170 break;
22171 case NM_P16_SR:
22173 int count = extract32(ctx->opcode, 0, 4);
22174 int u = extract32(ctx->opcode, 4, 4) << 4;
22176 rt = 30 + extract32(ctx->opcode, 9, 1);
22177 switch (extract32(ctx->opcode, 8, 1)) {
22178 case NM_SAVE16:
22179 gen_save(ctx, rt, count, 0, u);
22180 break;
22181 case NM_RESTORE_JRC16:
22182 gen_restore(ctx, rt, count, 0, u);
22183 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22184 break;
22187 break;
22188 case NM_MOVEP:
22189 case NM_MOVEPREV:
22190 check_nms(ctx);
22192 static const int gpr2reg1[] = {4, 5, 6, 7};
22193 static const int gpr2reg2[] = {5, 6, 7, 8};
22194 int re;
22195 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22196 extract32(ctx->opcode, 8, 1);
22197 int r1 = gpr2reg1[rd2];
22198 int r2 = gpr2reg2[rd2];
22199 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22200 extract32(ctx->opcode, 0, 3);
22201 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22202 extract32(ctx->opcode, 5, 3);
22203 TCGv t0 = tcg_temp_new();
22204 TCGv t1 = tcg_temp_new();
22205 if (op == NM_MOVEP) {
22206 rd = r1;
22207 re = r2;
22208 rs = decode_gpr_gpr4_zero(r3);
22209 rt = decode_gpr_gpr4_zero(r4);
22210 } else {
22211 rd = decode_gpr_gpr4(r3);
22212 re = decode_gpr_gpr4(r4);
22213 rs = r1;
22214 rt = r2;
22216 gen_load_gpr(t0, rs);
22217 gen_load_gpr(t1, rt);
22218 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22219 tcg_gen_mov_tl(cpu_gpr[re], t1);
22220 tcg_temp_free(t0);
22221 tcg_temp_free(t1);
22223 break;
22224 default:
22225 return decode_nanomips_32_48_opc(env, ctx);
22228 return 2;
22232 /* SmartMIPS extension to MIPS32 */
22234 #if defined(TARGET_MIPS64)
22236 /* MDMX extension to MIPS64 */
22238 #endif
22240 /* MIPSDSP functions. */
22241 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22242 int rd, int base, int offset)
22244 TCGv t0;
22246 check_dsp(ctx);
22247 t0 = tcg_temp_new();
22249 if (base == 0) {
22250 gen_load_gpr(t0, offset);
22251 } else if (offset == 0) {
22252 gen_load_gpr(t0, base);
22253 } else {
22254 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22257 switch (opc) {
22258 case OPC_LBUX:
22259 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22260 gen_store_gpr(t0, rd);
22261 break;
22262 case OPC_LHX:
22263 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22264 gen_store_gpr(t0, rd);
22265 break;
22266 case OPC_LWX:
22267 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22268 gen_store_gpr(t0, rd);
22269 break;
22270 #if defined(TARGET_MIPS64)
22271 case OPC_LDX:
22272 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22273 gen_store_gpr(t0, rd);
22274 break;
22275 #endif
22277 tcg_temp_free(t0);
22280 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22281 int ret, int v1, int v2)
22283 TCGv v1_t;
22284 TCGv v2_t;
22286 if (ret == 0) {
22287 /* Treat as NOP. */
22288 return;
22291 v1_t = tcg_temp_new();
22292 v2_t = tcg_temp_new();
22294 gen_load_gpr(v1_t, v1);
22295 gen_load_gpr(v2_t, v2);
22297 switch (op1) {
22298 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22299 case OPC_MULT_G_2E:
22300 check_dsp_r2(ctx);
22301 switch (op2) {
22302 case OPC_ADDUH_QB:
22303 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22304 break;
22305 case OPC_ADDUH_R_QB:
22306 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22307 break;
22308 case OPC_ADDQH_PH:
22309 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22310 break;
22311 case OPC_ADDQH_R_PH:
22312 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22313 break;
22314 case OPC_ADDQH_W:
22315 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22316 break;
22317 case OPC_ADDQH_R_W:
22318 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22319 break;
22320 case OPC_SUBUH_QB:
22321 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22322 break;
22323 case OPC_SUBUH_R_QB:
22324 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22325 break;
22326 case OPC_SUBQH_PH:
22327 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22328 break;
22329 case OPC_SUBQH_R_PH:
22330 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22331 break;
22332 case OPC_SUBQH_W:
22333 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22334 break;
22335 case OPC_SUBQH_R_W:
22336 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22337 break;
22339 break;
22340 case OPC_ABSQ_S_PH_DSP:
22341 switch (op2) {
22342 case OPC_ABSQ_S_QB:
22343 check_dsp_r2(ctx);
22344 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22345 break;
22346 case OPC_ABSQ_S_PH:
22347 check_dsp(ctx);
22348 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22349 break;
22350 case OPC_ABSQ_S_W:
22351 check_dsp(ctx);
22352 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22353 break;
22354 case OPC_PRECEQ_W_PHL:
22355 check_dsp(ctx);
22356 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22357 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22358 break;
22359 case OPC_PRECEQ_W_PHR:
22360 check_dsp(ctx);
22361 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22362 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22363 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22364 break;
22365 case OPC_PRECEQU_PH_QBL:
22366 check_dsp(ctx);
22367 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22368 break;
22369 case OPC_PRECEQU_PH_QBR:
22370 check_dsp(ctx);
22371 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22372 break;
22373 case OPC_PRECEQU_PH_QBLA:
22374 check_dsp(ctx);
22375 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22376 break;
22377 case OPC_PRECEQU_PH_QBRA:
22378 check_dsp(ctx);
22379 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22380 break;
22381 case OPC_PRECEU_PH_QBL:
22382 check_dsp(ctx);
22383 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22384 break;
22385 case OPC_PRECEU_PH_QBR:
22386 check_dsp(ctx);
22387 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22388 break;
22389 case OPC_PRECEU_PH_QBLA:
22390 check_dsp(ctx);
22391 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22392 break;
22393 case OPC_PRECEU_PH_QBRA:
22394 check_dsp(ctx);
22395 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22396 break;
22398 break;
22399 case OPC_ADDU_QB_DSP:
22400 switch (op2) {
22401 case OPC_ADDQ_PH:
22402 check_dsp(ctx);
22403 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22404 break;
22405 case OPC_ADDQ_S_PH:
22406 check_dsp(ctx);
22407 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22408 break;
22409 case OPC_ADDQ_S_W:
22410 check_dsp(ctx);
22411 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22412 break;
22413 case OPC_ADDU_QB:
22414 check_dsp(ctx);
22415 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22416 break;
22417 case OPC_ADDU_S_QB:
22418 check_dsp(ctx);
22419 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22420 break;
22421 case OPC_ADDU_PH:
22422 check_dsp_r2(ctx);
22423 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22424 break;
22425 case OPC_ADDU_S_PH:
22426 check_dsp_r2(ctx);
22427 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22428 break;
22429 case OPC_SUBQ_PH:
22430 check_dsp(ctx);
22431 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22432 break;
22433 case OPC_SUBQ_S_PH:
22434 check_dsp(ctx);
22435 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22436 break;
22437 case OPC_SUBQ_S_W:
22438 check_dsp(ctx);
22439 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22440 break;
22441 case OPC_SUBU_QB:
22442 check_dsp(ctx);
22443 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22444 break;
22445 case OPC_SUBU_S_QB:
22446 check_dsp(ctx);
22447 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22448 break;
22449 case OPC_SUBU_PH:
22450 check_dsp_r2(ctx);
22451 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22452 break;
22453 case OPC_SUBU_S_PH:
22454 check_dsp_r2(ctx);
22455 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22456 break;
22457 case OPC_ADDSC:
22458 check_dsp(ctx);
22459 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22460 break;
22461 case OPC_ADDWC:
22462 check_dsp(ctx);
22463 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22464 break;
22465 case OPC_MODSUB:
22466 check_dsp(ctx);
22467 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22468 break;
22469 case OPC_RADDU_W_QB:
22470 check_dsp(ctx);
22471 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22472 break;
22474 break;
22475 case OPC_CMPU_EQ_QB_DSP:
22476 switch (op2) {
22477 case OPC_PRECR_QB_PH:
22478 check_dsp_r2(ctx);
22479 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22480 break;
22481 case OPC_PRECRQ_QB_PH:
22482 check_dsp(ctx);
22483 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22484 break;
22485 case OPC_PRECR_SRA_PH_W:
22486 check_dsp_r2(ctx);
22488 TCGv_i32 sa_t = tcg_const_i32(v2);
22489 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22490 cpu_gpr[ret]);
22491 tcg_temp_free_i32(sa_t);
22492 break;
22494 case OPC_PRECR_SRA_R_PH_W:
22495 check_dsp_r2(ctx);
22497 TCGv_i32 sa_t = tcg_const_i32(v2);
22498 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22499 cpu_gpr[ret]);
22500 tcg_temp_free_i32(sa_t);
22501 break;
22503 case OPC_PRECRQ_PH_W:
22504 check_dsp(ctx);
22505 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22506 break;
22507 case OPC_PRECRQ_RS_PH_W:
22508 check_dsp(ctx);
22509 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22510 break;
22511 case OPC_PRECRQU_S_QB_PH:
22512 check_dsp(ctx);
22513 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22514 break;
22516 break;
22517 #ifdef TARGET_MIPS64
22518 case OPC_ABSQ_S_QH_DSP:
22519 switch (op2) {
22520 case OPC_PRECEQ_L_PWL:
22521 check_dsp(ctx);
22522 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22523 break;
22524 case OPC_PRECEQ_L_PWR:
22525 check_dsp(ctx);
22526 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22527 break;
22528 case OPC_PRECEQ_PW_QHL:
22529 check_dsp(ctx);
22530 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22531 break;
22532 case OPC_PRECEQ_PW_QHR:
22533 check_dsp(ctx);
22534 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22535 break;
22536 case OPC_PRECEQ_PW_QHLA:
22537 check_dsp(ctx);
22538 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22539 break;
22540 case OPC_PRECEQ_PW_QHRA:
22541 check_dsp(ctx);
22542 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22543 break;
22544 case OPC_PRECEQU_QH_OBL:
22545 check_dsp(ctx);
22546 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22547 break;
22548 case OPC_PRECEQU_QH_OBR:
22549 check_dsp(ctx);
22550 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22551 break;
22552 case OPC_PRECEQU_QH_OBLA:
22553 check_dsp(ctx);
22554 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22555 break;
22556 case OPC_PRECEQU_QH_OBRA:
22557 check_dsp(ctx);
22558 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22559 break;
22560 case OPC_PRECEU_QH_OBL:
22561 check_dsp(ctx);
22562 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22563 break;
22564 case OPC_PRECEU_QH_OBR:
22565 check_dsp(ctx);
22566 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22567 break;
22568 case OPC_PRECEU_QH_OBLA:
22569 check_dsp(ctx);
22570 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22571 break;
22572 case OPC_PRECEU_QH_OBRA:
22573 check_dsp(ctx);
22574 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22575 break;
22576 case OPC_ABSQ_S_OB:
22577 check_dsp_r2(ctx);
22578 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22579 break;
22580 case OPC_ABSQ_S_PW:
22581 check_dsp(ctx);
22582 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22583 break;
22584 case OPC_ABSQ_S_QH:
22585 check_dsp(ctx);
22586 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22587 break;
22589 break;
22590 case OPC_ADDU_OB_DSP:
22591 switch (op2) {
22592 case OPC_RADDU_L_OB:
22593 check_dsp(ctx);
22594 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22595 break;
22596 case OPC_SUBQ_PW:
22597 check_dsp(ctx);
22598 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22599 break;
22600 case OPC_SUBQ_S_PW:
22601 check_dsp(ctx);
22602 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22603 break;
22604 case OPC_SUBQ_QH:
22605 check_dsp(ctx);
22606 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22607 break;
22608 case OPC_SUBQ_S_QH:
22609 check_dsp(ctx);
22610 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22611 break;
22612 case OPC_SUBU_OB:
22613 check_dsp(ctx);
22614 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22615 break;
22616 case OPC_SUBU_S_OB:
22617 check_dsp(ctx);
22618 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22619 break;
22620 case OPC_SUBU_QH:
22621 check_dsp_r2(ctx);
22622 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22623 break;
22624 case OPC_SUBU_S_QH:
22625 check_dsp_r2(ctx);
22626 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22627 break;
22628 case OPC_SUBUH_OB:
22629 check_dsp_r2(ctx);
22630 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22631 break;
22632 case OPC_SUBUH_R_OB:
22633 check_dsp_r2(ctx);
22634 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22635 break;
22636 case OPC_ADDQ_PW:
22637 check_dsp(ctx);
22638 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22639 break;
22640 case OPC_ADDQ_S_PW:
22641 check_dsp(ctx);
22642 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22643 break;
22644 case OPC_ADDQ_QH:
22645 check_dsp(ctx);
22646 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22647 break;
22648 case OPC_ADDQ_S_QH:
22649 check_dsp(ctx);
22650 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22651 break;
22652 case OPC_ADDU_OB:
22653 check_dsp(ctx);
22654 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22655 break;
22656 case OPC_ADDU_S_OB:
22657 check_dsp(ctx);
22658 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22659 break;
22660 case OPC_ADDU_QH:
22661 check_dsp_r2(ctx);
22662 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22663 break;
22664 case OPC_ADDU_S_QH:
22665 check_dsp_r2(ctx);
22666 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22667 break;
22668 case OPC_ADDUH_OB:
22669 check_dsp_r2(ctx);
22670 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22671 break;
22672 case OPC_ADDUH_R_OB:
22673 check_dsp_r2(ctx);
22674 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22675 break;
22677 break;
22678 case OPC_CMPU_EQ_OB_DSP:
22679 switch (op2) {
22680 case OPC_PRECR_OB_QH:
22681 check_dsp_r2(ctx);
22682 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22683 break;
22684 case OPC_PRECR_SRA_QH_PW:
22685 check_dsp_r2(ctx);
22687 TCGv_i32 ret_t = tcg_const_i32(ret);
22688 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22689 tcg_temp_free_i32(ret_t);
22690 break;
22692 case OPC_PRECR_SRA_R_QH_PW:
22693 check_dsp_r2(ctx);
22695 TCGv_i32 sa_v = tcg_const_i32(ret);
22696 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22697 tcg_temp_free_i32(sa_v);
22698 break;
22700 case OPC_PRECRQ_OB_QH:
22701 check_dsp(ctx);
22702 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22703 break;
22704 case OPC_PRECRQ_PW_L:
22705 check_dsp(ctx);
22706 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22707 break;
22708 case OPC_PRECRQ_QH_PW:
22709 check_dsp(ctx);
22710 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22711 break;
22712 case OPC_PRECRQ_RS_QH_PW:
22713 check_dsp(ctx);
22714 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22715 break;
22716 case OPC_PRECRQU_S_OB_QH:
22717 check_dsp(ctx);
22718 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22719 break;
22721 break;
22722 #endif
22725 tcg_temp_free(v1_t);
22726 tcg_temp_free(v2_t);
22729 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22730 int ret, int v1, int v2)
22732 uint32_t op2;
22733 TCGv t0;
22734 TCGv v1_t;
22735 TCGv v2_t;
22737 if (ret == 0) {
22738 /* Treat as NOP. */
22739 return;
22742 t0 = tcg_temp_new();
22743 v1_t = tcg_temp_new();
22744 v2_t = tcg_temp_new();
22746 tcg_gen_movi_tl(t0, v1);
22747 gen_load_gpr(v1_t, v1);
22748 gen_load_gpr(v2_t, v2);
22750 switch (opc) {
22751 case OPC_SHLL_QB_DSP:
22753 op2 = MASK_SHLL_QB(ctx->opcode);
22754 switch (op2) {
22755 case OPC_SHLL_QB:
22756 check_dsp(ctx);
22757 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22758 break;
22759 case OPC_SHLLV_QB:
22760 check_dsp(ctx);
22761 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22762 break;
22763 case OPC_SHLL_PH:
22764 check_dsp(ctx);
22765 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22766 break;
22767 case OPC_SHLLV_PH:
22768 check_dsp(ctx);
22769 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22770 break;
22771 case OPC_SHLL_S_PH:
22772 check_dsp(ctx);
22773 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22774 break;
22775 case OPC_SHLLV_S_PH:
22776 check_dsp(ctx);
22777 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22778 break;
22779 case OPC_SHLL_S_W:
22780 check_dsp(ctx);
22781 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22782 break;
22783 case OPC_SHLLV_S_W:
22784 check_dsp(ctx);
22785 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22786 break;
22787 case OPC_SHRL_QB:
22788 check_dsp(ctx);
22789 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22790 break;
22791 case OPC_SHRLV_QB:
22792 check_dsp(ctx);
22793 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22794 break;
22795 case OPC_SHRL_PH:
22796 check_dsp_r2(ctx);
22797 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22798 break;
22799 case OPC_SHRLV_PH:
22800 check_dsp_r2(ctx);
22801 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22802 break;
22803 case OPC_SHRA_QB:
22804 check_dsp_r2(ctx);
22805 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22806 break;
22807 case OPC_SHRA_R_QB:
22808 check_dsp_r2(ctx);
22809 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22810 break;
22811 case OPC_SHRAV_QB:
22812 check_dsp_r2(ctx);
22813 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22814 break;
22815 case OPC_SHRAV_R_QB:
22816 check_dsp_r2(ctx);
22817 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22818 break;
22819 case OPC_SHRA_PH:
22820 check_dsp(ctx);
22821 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22822 break;
22823 case OPC_SHRA_R_PH:
22824 check_dsp(ctx);
22825 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22826 break;
22827 case OPC_SHRAV_PH:
22828 check_dsp(ctx);
22829 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22830 break;
22831 case OPC_SHRAV_R_PH:
22832 check_dsp(ctx);
22833 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22834 break;
22835 case OPC_SHRA_R_W:
22836 check_dsp(ctx);
22837 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22838 break;
22839 case OPC_SHRAV_R_W:
22840 check_dsp(ctx);
22841 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22842 break;
22843 default: /* Invalid */
22844 MIPS_INVAL("MASK SHLL.QB");
22845 generate_exception_end(ctx, EXCP_RI);
22846 break;
22848 break;
22850 #ifdef TARGET_MIPS64
22851 case OPC_SHLL_OB_DSP:
22852 op2 = MASK_SHLL_OB(ctx->opcode);
22853 switch (op2) {
22854 case OPC_SHLL_PW:
22855 check_dsp(ctx);
22856 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22857 break;
22858 case OPC_SHLLV_PW:
22859 check_dsp(ctx);
22860 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22861 break;
22862 case OPC_SHLL_S_PW:
22863 check_dsp(ctx);
22864 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22865 break;
22866 case OPC_SHLLV_S_PW:
22867 check_dsp(ctx);
22868 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22869 break;
22870 case OPC_SHLL_OB:
22871 check_dsp(ctx);
22872 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22873 break;
22874 case OPC_SHLLV_OB:
22875 check_dsp(ctx);
22876 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22877 break;
22878 case OPC_SHLL_QH:
22879 check_dsp(ctx);
22880 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22881 break;
22882 case OPC_SHLLV_QH:
22883 check_dsp(ctx);
22884 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22885 break;
22886 case OPC_SHLL_S_QH:
22887 check_dsp(ctx);
22888 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22889 break;
22890 case OPC_SHLLV_S_QH:
22891 check_dsp(ctx);
22892 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22893 break;
22894 case OPC_SHRA_OB:
22895 check_dsp_r2(ctx);
22896 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22897 break;
22898 case OPC_SHRAV_OB:
22899 check_dsp_r2(ctx);
22900 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22901 break;
22902 case OPC_SHRA_R_OB:
22903 check_dsp_r2(ctx);
22904 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22905 break;
22906 case OPC_SHRAV_R_OB:
22907 check_dsp_r2(ctx);
22908 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22909 break;
22910 case OPC_SHRA_PW:
22911 check_dsp(ctx);
22912 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22913 break;
22914 case OPC_SHRAV_PW:
22915 check_dsp(ctx);
22916 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22917 break;
22918 case OPC_SHRA_R_PW:
22919 check_dsp(ctx);
22920 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22921 break;
22922 case OPC_SHRAV_R_PW:
22923 check_dsp(ctx);
22924 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22925 break;
22926 case OPC_SHRA_QH:
22927 check_dsp(ctx);
22928 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22929 break;
22930 case OPC_SHRAV_QH:
22931 check_dsp(ctx);
22932 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22933 break;
22934 case OPC_SHRA_R_QH:
22935 check_dsp(ctx);
22936 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22937 break;
22938 case OPC_SHRAV_R_QH:
22939 check_dsp(ctx);
22940 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22941 break;
22942 case OPC_SHRL_OB:
22943 check_dsp(ctx);
22944 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22945 break;
22946 case OPC_SHRLV_OB:
22947 check_dsp(ctx);
22948 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22949 break;
22950 case OPC_SHRL_QH:
22951 check_dsp_r2(ctx);
22952 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22953 break;
22954 case OPC_SHRLV_QH:
22955 check_dsp_r2(ctx);
22956 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22957 break;
22958 default: /* Invalid */
22959 MIPS_INVAL("MASK SHLL.OB");
22960 generate_exception_end(ctx, EXCP_RI);
22961 break;
22963 break;
22964 #endif
22967 tcg_temp_free(t0);
22968 tcg_temp_free(v1_t);
22969 tcg_temp_free(v2_t);
22972 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22973 int ret, int v1, int v2, int check_ret)
22975 TCGv_i32 t0;
22976 TCGv v1_t;
22977 TCGv v2_t;
22979 if ((ret == 0) && (check_ret == 1)) {
22980 /* Treat as NOP. */
22981 return;
22984 t0 = tcg_temp_new_i32();
22985 v1_t = tcg_temp_new();
22986 v2_t = tcg_temp_new();
22988 tcg_gen_movi_i32(t0, ret);
22989 gen_load_gpr(v1_t, v1);
22990 gen_load_gpr(v2_t, v2);
22992 switch (op1) {
22993 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22994 * the same mask and op1. */
22995 case OPC_MULT_G_2E:
22996 check_dsp_r2(ctx);
22997 switch (op2) {
22998 case OPC_MUL_PH:
22999 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23000 break;
23001 case OPC_MUL_S_PH:
23002 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23003 break;
23004 case OPC_MULQ_S_W:
23005 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23006 break;
23007 case OPC_MULQ_RS_W:
23008 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23009 break;
23011 break;
23012 case OPC_DPA_W_PH_DSP:
23013 switch (op2) {
23014 case OPC_DPAU_H_QBL:
23015 check_dsp(ctx);
23016 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23017 break;
23018 case OPC_DPAU_H_QBR:
23019 check_dsp(ctx);
23020 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23021 break;
23022 case OPC_DPSU_H_QBL:
23023 check_dsp(ctx);
23024 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23025 break;
23026 case OPC_DPSU_H_QBR:
23027 check_dsp(ctx);
23028 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23029 break;
23030 case OPC_DPA_W_PH:
23031 check_dsp_r2(ctx);
23032 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23033 break;
23034 case OPC_DPAX_W_PH:
23035 check_dsp_r2(ctx);
23036 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23037 break;
23038 case OPC_DPAQ_S_W_PH:
23039 check_dsp(ctx);
23040 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23041 break;
23042 case OPC_DPAQX_S_W_PH:
23043 check_dsp_r2(ctx);
23044 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23045 break;
23046 case OPC_DPAQX_SA_W_PH:
23047 check_dsp_r2(ctx);
23048 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23049 break;
23050 case OPC_DPS_W_PH:
23051 check_dsp_r2(ctx);
23052 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23053 break;
23054 case OPC_DPSX_W_PH:
23055 check_dsp_r2(ctx);
23056 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23057 break;
23058 case OPC_DPSQ_S_W_PH:
23059 check_dsp(ctx);
23060 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23061 break;
23062 case OPC_DPSQX_S_W_PH:
23063 check_dsp_r2(ctx);
23064 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23065 break;
23066 case OPC_DPSQX_SA_W_PH:
23067 check_dsp_r2(ctx);
23068 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23069 break;
23070 case OPC_MULSAQ_S_W_PH:
23071 check_dsp(ctx);
23072 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23073 break;
23074 case OPC_DPAQ_SA_L_W:
23075 check_dsp(ctx);
23076 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23077 break;
23078 case OPC_DPSQ_SA_L_W:
23079 check_dsp(ctx);
23080 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23081 break;
23082 case OPC_MAQ_S_W_PHL:
23083 check_dsp(ctx);
23084 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23085 break;
23086 case OPC_MAQ_S_W_PHR:
23087 check_dsp(ctx);
23088 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23089 break;
23090 case OPC_MAQ_SA_W_PHL:
23091 check_dsp(ctx);
23092 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23093 break;
23094 case OPC_MAQ_SA_W_PHR:
23095 check_dsp(ctx);
23096 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23097 break;
23098 case OPC_MULSA_W_PH:
23099 check_dsp_r2(ctx);
23100 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23101 break;
23103 break;
23104 #ifdef TARGET_MIPS64
23105 case OPC_DPAQ_W_QH_DSP:
23107 int ac = ret & 0x03;
23108 tcg_gen_movi_i32(t0, ac);
23110 switch (op2) {
23111 case OPC_DMADD:
23112 check_dsp(ctx);
23113 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23114 break;
23115 case OPC_DMADDU:
23116 check_dsp(ctx);
23117 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23118 break;
23119 case OPC_DMSUB:
23120 check_dsp(ctx);
23121 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23122 break;
23123 case OPC_DMSUBU:
23124 check_dsp(ctx);
23125 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23126 break;
23127 case OPC_DPA_W_QH:
23128 check_dsp_r2(ctx);
23129 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23130 break;
23131 case OPC_DPAQ_S_W_QH:
23132 check_dsp(ctx);
23133 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23134 break;
23135 case OPC_DPAQ_SA_L_PW:
23136 check_dsp(ctx);
23137 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23138 break;
23139 case OPC_DPAU_H_OBL:
23140 check_dsp(ctx);
23141 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23142 break;
23143 case OPC_DPAU_H_OBR:
23144 check_dsp(ctx);
23145 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23146 break;
23147 case OPC_DPS_W_QH:
23148 check_dsp_r2(ctx);
23149 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23150 break;
23151 case OPC_DPSQ_S_W_QH:
23152 check_dsp(ctx);
23153 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23154 break;
23155 case OPC_DPSQ_SA_L_PW:
23156 check_dsp(ctx);
23157 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23158 break;
23159 case OPC_DPSU_H_OBL:
23160 check_dsp(ctx);
23161 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23162 break;
23163 case OPC_DPSU_H_OBR:
23164 check_dsp(ctx);
23165 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23166 break;
23167 case OPC_MAQ_S_L_PWL:
23168 check_dsp(ctx);
23169 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23170 break;
23171 case OPC_MAQ_S_L_PWR:
23172 check_dsp(ctx);
23173 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23174 break;
23175 case OPC_MAQ_S_W_QHLL:
23176 check_dsp(ctx);
23177 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23178 break;
23179 case OPC_MAQ_SA_W_QHLL:
23180 check_dsp(ctx);
23181 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23182 break;
23183 case OPC_MAQ_S_W_QHLR:
23184 check_dsp(ctx);
23185 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23186 break;
23187 case OPC_MAQ_SA_W_QHLR:
23188 check_dsp(ctx);
23189 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23190 break;
23191 case OPC_MAQ_S_W_QHRL:
23192 check_dsp(ctx);
23193 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23194 break;
23195 case OPC_MAQ_SA_W_QHRL:
23196 check_dsp(ctx);
23197 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23198 break;
23199 case OPC_MAQ_S_W_QHRR:
23200 check_dsp(ctx);
23201 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23202 break;
23203 case OPC_MAQ_SA_W_QHRR:
23204 check_dsp(ctx);
23205 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23206 break;
23207 case OPC_MULSAQ_S_L_PW:
23208 check_dsp(ctx);
23209 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23210 break;
23211 case OPC_MULSAQ_S_W_QH:
23212 check_dsp(ctx);
23213 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23214 break;
23217 break;
23218 #endif
23219 case OPC_ADDU_QB_DSP:
23220 switch (op2) {
23221 case OPC_MULEU_S_PH_QBL:
23222 check_dsp(ctx);
23223 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23224 break;
23225 case OPC_MULEU_S_PH_QBR:
23226 check_dsp(ctx);
23227 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23228 break;
23229 case OPC_MULQ_RS_PH:
23230 check_dsp(ctx);
23231 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23232 break;
23233 case OPC_MULEQ_S_W_PHL:
23234 check_dsp(ctx);
23235 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23236 break;
23237 case OPC_MULEQ_S_W_PHR:
23238 check_dsp(ctx);
23239 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23240 break;
23241 case OPC_MULQ_S_PH:
23242 check_dsp_r2(ctx);
23243 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23244 break;
23246 break;
23247 #ifdef TARGET_MIPS64
23248 case OPC_ADDU_OB_DSP:
23249 switch (op2) {
23250 case OPC_MULEQ_S_PW_QHL:
23251 check_dsp(ctx);
23252 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23253 break;
23254 case OPC_MULEQ_S_PW_QHR:
23255 check_dsp(ctx);
23256 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23257 break;
23258 case OPC_MULEU_S_QH_OBL:
23259 check_dsp(ctx);
23260 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23261 break;
23262 case OPC_MULEU_S_QH_OBR:
23263 check_dsp(ctx);
23264 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23265 break;
23266 case OPC_MULQ_RS_QH:
23267 check_dsp(ctx);
23268 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23269 break;
23271 break;
23272 #endif
23275 tcg_temp_free_i32(t0);
23276 tcg_temp_free(v1_t);
23277 tcg_temp_free(v2_t);
23280 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23281 int ret, int val)
23283 int16_t imm;
23284 TCGv t0;
23285 TCGv val_t;
23287 if (ret == 0) {
23288 /* Treat as NOP. */
23289 return;
23292 t0 = tcg_temp_new();
23293 val_t = tcg_temp_new();
23294 gen_load_gpr(val_t, val);
23296 switch (op1) {
23297 case OPC_ABSQ_S_PH_DSP:
23298 switch (op2) {
23299 case OPC_BITREV:
23300 check_dsp(ctx);
23301 gen_helper_bitrev(cpu_gpr[ret], val_t);
23302 break;
23303 case OPC_REPL_QB:
23304 check_dsp(ctx);
23306 target_long result;
23307 imm = (ctx->opcode >> 16) & 0xFF;
23308 result = (uint32_t)imm << 24 |
23309 (uint32_t)imm << 16 |
23310 (uint32_t)imm << 8 |
23311 (uint32_t)imm;
23312 result = (int32_t)result;
23313 tcg_gen_movi_tl(cpu_gpr[ret], result);
23315 break;
23316 case OPC_REPLV_QB:
23317 check_dsp(ctx);
23318 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23319 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23320 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23321 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23322 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23323 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23324 break;
23325 case OPC_REPL_PH:
23326 check_dsp(ctx);
23328 imm = (ctx->opcode >> 16) & 0x03FF;
23329 imm = (int16_t)(imm << 6) >> 6;
23330 tcg_gen_movi_tl(cpu_gpr[ret], \
23331 (target_long)((int32_t)imm << 16 | \
23332 (uint16_t)imm));
23334 break;
23335 case OPC_REPLV_PH:
23336 check_dsp(ctx);
23337 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23338 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23339 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23340 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23341 break;
23343 break;
23344 #ifdef TARGET_MIPS64
23345 case OPC_ABSQ_S_QH_DSP:
23346 switch (op2) {
23347 case OPC_REPL_OB:
23348 check_dsp(ctx);
23350 target_long temp;
23352 imm = (ctx->opcode >> 16) & 0xFF;
23353 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23354 temp = (temp << 16) | temp;
23355 temp = (temp << 32) | temp;
23356 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23357 break;
23359 case OPC_REPL_PW:
23360 check_dsp(ctx);
23362 target_long temp;
23364 imm = (ctx->opcode >> 16) & 0x03FF;
23365 imm = (int16_t)(imm << 6) >> 6;
23366 temp = ((target_long)imm << 32) \
23367 | ((target_long)imm & 0xFFFFFFFF);
23368 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23369 break;
23371 case OPC_REPL_QH:
23372 check_dsp(ctx);
23374 target_long temp;
23376 imm = (ctx->opcode >> 16) & 0x03FF;
23377 imm = (int16_t)(imm << 6) >> 6;
23379 temp = ((uint64_t)(uint16_t)imm << 48) |
23380 ((uint64_t)(uint16_t)imm << 32) |
23381 ((uint64_t)(uint16_t)imm << 16) |
23382 (uint64_t)(uint16_t)imm;
23383 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23384 break;
23386 case OPC_REPLV_OB:
23387 check_dsp(ctx);
23388 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23389 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23390 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23391 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23392 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23393 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23394 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23395 break;
23396 case OPC_REPLV_PW:
23397 check_dsp(ctx);
23398 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23399 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23400 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23401 break;
23402 case OPC_REPLV_QH:
23403 check_dsp(ctx);
23404 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23405 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23406 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23407 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23408 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23409 break;
23411 break;
23412 #endif
23414 tcg_temp_free(t0);
23415 tcg_temp_free(val_t);
23418 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23419 uint32_t op1, uint32_t op2,
23420 int ret, int v1, int v2, int check_ret)
23422 TCGv t1;
23423 TCGv v1_t;
23424 TCGv v2_t;
23426 if ((ret == 0) && (check_ret == 1)) {
23427 /* Treat as NOP. */
23428 return;
23431 t1 = tcg_temp_new();
23432 v1_t = tcg_temp_new();
23433 v2_t = tcg_temp_new();
23435 gen_load_gpr(v1_t, v1);
23436 gen_load_gpr(v2_t, v2);
23438 switch (op1) {
23439 case OPC_CMPU_EQ_QB_DSP:
23440 switch (op2) {
23441 case OPC_CMPU_EQ_QB:
23442 check_dsp(ctx);
23443 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23444 break;
23445 case OPC_CMPU_LT_QB:
23446 check_dsp(ctx);
23447 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23448 break;
23449 case OPC_CMPU_LE_QB:
23450 check_dsp(ctx);
23451 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23452 break;
23453 case OPC_CMPGU_EQ_QB:
23454 check_dsp(ctx);
23455 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23456 break;
23457 case OPC_CMPGU_LT_QB:
23458 check_dsp(ctx);
23459 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23460 break;
23461 case OPC_CMPGU_LE_QB:
23462 check_dsp(ctx);
23463 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23464 break;
23465 case OPC_CMPGDU_EQ_QB:
23466 check_dsp_r2(ctx);
23467 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23468 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23469 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23470 tcg_gen_shli_tl(t1, t1, 24);
23471 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23472 break;
23473 case OPC_CMPGDU_LT_QB:
23474 check_dsp_r2(ctx);
23475 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23476 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23477 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23478 tcg_gen_shli_tl(t1, t1, 24);
23479 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23480 break;
23481 case OPC_CMPGDU_LE_QB:
23482 check_dsp_r2(ctx);
23483 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23484 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23485 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23486 tcg_gen_shli_tl(t1, t1, 24);
23487 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23488 break;
23489 case OPC_CMP_EQ_PH:
23490 check_dsp(ctx);
23491 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23492 break;
23493 case OPC_CMP_LT_PH:
23494 check_dsp(ctx);
23495 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23496 break;
23497 case OPC_CMP_LE_PH:
23498 check_dsp(ctx);
23499 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23500 break;
23501 case OPC_PICK_QB:
23502 check_dsp(ctx);
23503 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23504 break;
23505 case OPC_PICK_PH:
23506 check_dsp(ctx);
23507 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23508 break;
23509 case OPC_PACKRL_PH:
23510 check_dsp(ctx);
23511 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23512 break;
23514 break;
23515 #ifdef TARGET_MIPS64
23516 case OPC_CMPU_EQ_OB_DSP:
23517 switch (op2) {
23518 case OPC_CMP_EQ_PW:
23519 check_dsp(ctx);
23520 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23521 break;
23522 case OPC_CMP_LT_PW:
23523 check_dsp(ctx);
23524 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23525 break;
23526 case OPC_CMP_LE_PW:
23527 check_dsp(ctx);
23528 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23529 break;
23530 case OPC_CMP_EQ_QH:
23531 check_dsp(ctx);
23532 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23533 break;
23534 case OPC_CMP_LT_QH:
23535 check_dsp(ctx);
23536 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23537 break;
23538 case OPC_CMP_LE_QH:
23539 check_dsp(ctx);
23540 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23541 break;
23542 case OPC_CMPGDU_EQ_OB:
23543 check_dsp_r2(ctx);
23544 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23545 break;
23546 case OPC_CMPGDU_LT_OB:
23547 check_dsp_r2(ctx);
23548 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23549 break;
23550 case OPC_CMPGDU_LE_OB:
23551 check_dsp_r2(ctx);
23552 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23553 break;
23554 case OPC_CMPGU_EQ_OB:
23555 check_dsp(ctx);
23556 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23557 break;
23558 case OPC_CMPGU_LT_OB:
23559 check_dsp(ctx);
23560 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23561 break;
23562 case OPC_CMPGU_LE_OB:
23563 check_dsp(ctx);
23564 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23565 break;
23566 case OPC_CMPU_EQ_OB:
23567 check_dsp(ctx);
23568 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23569 break;
23570 case OPC_CMPU_LT_OB:
23571 check_dsp(ctx);
23572 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23573 break;
23574 case OPC_CMPU_LE_OB:
23575 check_dsp(ctx);
23576 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23577 break;
23578 case OPC_PACKRL_PW:
23579 check_dsp(ctx);
23580 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23581 break;
23582 case OPC_PICK_OB:
23583 check_dsp(ctx);
23584 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23585 break;
23586 case OPC_PICK_PW:
23587 check_dsp(ctx);
23588 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23589 break;
23590 case OPC_PICK_QH:
23591 check_dsp(ctx);
23592 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23593 break;
23595 break;
23596 #endif
23599 tcg_temp_free(t1);
23600 tcg_temp_free(v1_t);
23601 tcg_temp_free(v2_t);
23604 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23605 uint32_t op1, int rt, int rs, int sa)
23607 TCGv t0;
23609 check_dsp_r2(ctx);
23611 if (rt == 0) {
23612 /* Treat as NOP. */
23613 return;
23616 t0 = tcg_temp_new();
23617 gen_load_gpr(t0, rs);
23619 switch (op1) {
23620 case OPC_APPEND_DSP:
23621 switch (MASK_APPEND(ctx->opcode)) {
23622 case OPC_APPEND:
23623 if (sa != 0) {
23624 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23626 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23627 break;
23628 case OPC_PREPEND:
23629 if (sa != 0) {
23630 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23631 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23632 tcg_gen_shli_tl(t0, t0, 32 - sa);
23633 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23635 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23636 break;
23637 case OPC_BALIGN:
23638 sa &= 3;
23639 if (sa != 0 && sa != 2) {
23640 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23641 tcg_gen_ext32u_tl(t0, t0);
23642 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23643 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23645 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23646 break;
23647 default: /* Invalid */
23648 MIPS_INVAL("MASK APPEND");
23649 generate_exception_end(ctx, EXCP_RI);
23650 break;
23652 break;
23653 #ifdef TARGET_MIPS64
23654 case OPC_DAPPEND_DSP:
23655 switch (MASK_DAPPEND(ctx->opcode)) {
23656 case OPC_DAPPEND:
23657 if (sa != 0) {
23658 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23660 break;
23661 case OPC_PREPENDD:
23662 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23663 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23664 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23665 break;
23666 case OPC_PREPENDW:
23667 if (sa != 0) {
23668 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23669 tcg_gen_shli_tl(t0, t0, 64 - sa);
23670 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23672 break;
23673 case OPC_DBALIGN:
23674 sa &= 7;
23675 if (sa != 0 && sa != 2 && sa != 4) {
23676 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23677 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23678 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23680 break;
23681 default: /* Invalid */
23682 MIPS_INVAL("MASK DAPPEND");
23683 generate_exception_end(ctx, EXCP_RI);
23684 break;
23686 break;
23687 #endif
23689 tcg_temp_free(t0);
23692 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23693 int ret, int v1, int v2, int check_ret)
23696 TCGv t0;
23697 TCGv t1;
23698 TCGv v1_t;
23699 TCGv v2_t;
23700 int16_t imm;
23702 if ((ret == 0) && (check_ret == 1)) {
23703 /* Treat as NOP. */
23704 return;
23707 t0 = tcg_temp_new();
23708 t1 = tcg_temp_new();
23709 v1_t = tcg_temp_new();
23710 v2_t = tcg_temp_new();
23712 gen_load_gpr(v1_t, v1);
23713 gen_load_gpr(v2_t, v2);
23715 switch (op1) {
23716 case OPC_EXTR_W_DSP:
23717 check_dsp(ctx);
23718 switch (op2) {
23719 case OPC_EXTR_W:
23720 tcg_gen_movi_tl(t0, v2);
23721 tcg_gen_movi_tl(t1, v1);
23722 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23723 break;
23724 case OPC_EXTR_R_W:
23725 tcg_gen_movi_tl(t0, v2);
23726 tcg_gen_movi_tl(t1, v1);
23727 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23728 break;
23729 case OPC_EXTR_RS_W:
23730 tcg_gen_movi_tl(t0, v2);
23731 tcg_gen_movi_tl(t1, v1);
23732 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23733 break;
23734 case OPC_EXTR_S_H:
23735 tcg_gen_movi_tl(t0, v2);
23736 tcg_gen_movi_tl(t1, v1);
23737 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23738 break;
23739 case OPC_EXTRV_S_H:
23740 tcg_gen_movi_tl(t0, v2);
23741 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23742 break;
23743 case OPC_EXTRV_W:
23744 tcg_gen_movi_tl(t0, v2);
23745 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23746 break;
23747 case OPC_EXTRV_R_W:
23748 tcg_gen_movi_tl(t0, v2);
23749 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23750 break;
23751 case OPC_EXTRV_RS_W:
23752 tcg_gen_movi_tl(t0, v2);
23753 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23754 break;
23755 case OPC_EXTP:
23756 tcg_gen_movi_tl(t0, v2);
23757 tcg_gen_movi_tl(t1, v1);
23758 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23759 break;
23760 case OPC_EXTPV:
23761 tcg_gen_movi_tl(t0, v2);
23762 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23763 break;
23764 case OPC_EXTPDP:
23765 tcg_gen_movi_tl(t0, v2);
23766 tcg_gen_movi_tl(t1, v1);
23767 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23768 break;
23769 case OPC_EXTPDPV:
23770 tcg_gen_movi_tl(t0, v2);
23771 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23772 break;
23773 case OPC_SHILO:
23774 imm = (ctx->opcode >> 20) & 0x3F;
23775 tcg_gen_movi_tl(t0, ret);
23776 tcg_gen_movi_tl(t1, imm);
23777 gen_helper_shilo(t0, t1, cpu_env);
23778 break;
23779 case OPC_SHILOV:
23780 tcg_gen_movi_tl(t0, ret);
23781 gen_helper_shilo(t0, v1_t, cpu_env);
23782 break;
23783 case OPC_MTHLIP:
23784 tcg_gen_movi_tl(t0, ret);
23785 gen_helper_mthlip(t0, v1_t, cpu_env);
23786 break;
23787 case OPC_WRDSP:
23788 imm = (ctx->opcode >> 11) & 0x3FF;
23789 tcg_gen_movi_tl(t0, imm);
23790 gen_helper_wrdsp(v1_t, t0, cpu_env);
23791 break;
23792 case OPC_RDDSP:
23793 imm = (ctx->opcode >> 16) & 0x03FF;
23794 tcg_gen_movi_tl(t0, imm);
23795 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23796 break;
23798 break;
23799 #ifdef TARGET_MIPS64
23800 case OPC_DEXTR_W_DSP:
23801 check_dsp(ctx);
23802 switch (op2) {
23803 case OPC_DMTHLIP:
23804 tcg_gen_movi_tl(t0, ret);
23805 gen_helper_dmthlip(v1_t, t0, cpu_env);
23806 break;
23807 case OPC_DSHILO:
23809 int shift = (ctx->opcode >> 19) & 0x7F;
23810 int ac = (ctx->opcode >> 11) & 0x03;
23811 tcg_gen_movi_tl(t0, shift);
23812 tcg_gen_movi_tl(t1, ac);
23813 gen_helper_dshilo(t0, t1, cpu_env);
23814 break;
23816 case OPC_DSHILOV:
23818 int ac = (ctx->opcode >> 11) & 0x03;
23819 tcg_gen_movi_tl(t0, ac);
23820 gen_helper_dshilo(v1_t, t0, cpu_env);
23821 break;
23823 case OPC_DEXTP:
23824 tcg_gen_movi_tl(t0, v2);
23825 tcg_gen_movi_tl(t1, v1);
23827 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23828 break;
23829 case OPC_DEXTPV:
23830 tcg_gen_movi_tl(t0, v2);
23831 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23832 break;
23833 case OPC_DEXTPDP:
23834 tcg_gen_movi_tl(t0, v2);
23835 tcg_gen_movi_tl(t1, v1);
23836 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23837 break;
23838 case OPC_DEXTPDPV:
23839 tcg_gen_movi_tl(t0, v2);
23840 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23841 break;
23842 case OPC_DEXTR_L:
23843 tcg_gen_movi_tl(t0, v2);
23844 tcg_gen_movi_tl(t1, v1);
23845 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23846 break;
23847 case OPC_DEXTR_R_L:
23848 tcg_gen_movi_tl(t0, v2);
23849 tcg_gen_movi_tl(t1, v1);
23850 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23851 break;
23852 case OPC_DEXTR_RS_L:
23853 tcg_gen_movi_tl(t0, v2);
23854 tcg_gen_movi_tl(t1, v1);
23855 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23856 break;
23857 case OPC_DEXTR_W:
23858 tcg_gen_movi_tl(t0, v2);
23859 tcg_gen_movi_tl(t1, v1);
23860 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23861 break;
23862 case OPC_DEXTR_R_W:
23863 tcg_gen_movi_tl(t0, v2);
23864 tcg_gen_movi_tl(t1, v1);
23865 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23866 break;
23867 case OPC_DEXTR_RS_W:
23868 tcg_gen_movi_tl(t0, v2);
23869 tcg_gen_movi_tl(t1, v1);
23870 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23871 break;
23872 case OPC_DEXTR_S_H:
23873 tcg_gen_movi_tl(t0, v2);
23874 tcg_gen_movi_tl(t1, v1);
23875 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23876 break;
23877 case OPC_DEXTRV_S_H:
23878 tcg_gen_movi_tl(t0, v2);
23879 tcg_gen_movi_tl(t1, v1);
23880 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23881 break;
23882 case OPC_DEXTRV_L:
23883 tcg_gen_movi_tl(t0, v2);
23884 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23885 break;
23886 case OPC_DEXTRV_R_L:
23887 tcg_gen_movi_tl(t0, v2);
23888 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23889 break;
23890 case OPC_DEXTRV_RS_L:
23891 tcg_gen_movi_tl(t0, v2);
23892 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23893 break;
23894 case OPC_DEXTRV_W:
23895 tcg_gen_movi_tl(t0, v2);
23896 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23897 break;
23898 case OPC_DEXTRV_R_W:
23899 tcg_gen_movi_tl(t0, v2);
23900 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23901 break;
23902 case OPC_DEXTRV_RS_W:
23903 tcg_gen_movi_tl(t0, v2);
23904 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23905 break;
23907 break;
23908 #endif
23911 tcg_temp_free(t0);
23912 tcg_temp_free(t1);
23913 tcg_temp_free(v1_t);
23914 tcg_temp_free(v2_t);
23917 /* End MIPSDSP functions. */
23919 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23921 int rs, rt, rd, sa;
23922 uint32_t op1, op2;
23924 rs = (ctx->opcode >> 21) & 0x1f;
23925 rt = (ctx->opcode >> 16) & 0x1f;
23926 rd = (ctx->opcode >> 11) & 0x1f;
23927 sa = (ctx->opcode >> 6) & 0x1f;
23929 op1 = MASK_SPECIAL(ctx->opcode);
23930 switch (op1) {
23931 case OPC_LSA:
23932 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23933 break;
23934 case OPC_MULT:
23935 case OPC_MULTU:
23936 case OPC_DIV:
23937 case OPC_DIVU:
23938 op2 = MASK_R6_MULDIV(ctx->opcode);
23939 switch (op2) {
23940 case R6_OPC_MUL:
23941 case R6_OPC_MUH:
23942 case R6_OPC_MULU:
23943 case R6_OPC_MUHU:
23944 case R6_OPC_DIV:
23945 case R6_OPC_MOD:
23946 case R6_OPC_DIVU:
23947 case R6_OPC_MODU:
23948 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23949 break;
23950 default:
23951 MIPS_INVAL("special_r6 muldiv");
23952 generate_exception_end(ctx, EXCP_RI);
23953 break;
23955 break;
23956 case OPC_SELEQZ:
23957 case OPC_SELNEZ:
23958 gen_cond_move(ctx, op1, rd, rs, rt);
23959 break;
23960 case R6_OPC_CLO:
23961 case R6_OPC_CLZ:
23962 if (rt == 0 && sa == 1) {
23963 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23964 We need additionally to check other fields */
23965 gen_cl(ctx, op1, rd, rs);
23966 } else {
23967 generate_exception_end(ctx, EXCP_RI);
23969 break;
23970 case R6_OPC_SDBBP:
23971 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23972 gen_helper_do_semihosting(cpu_env);
23973 } else {
23974 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23975 generate_exception_end(ctx, EXCP_RI);
23976 } else {
23977 generate_exception_end(ctx, EXCP_DBp);
23980 break;
23981 #if defined(TARGET_MIPS64)
23982 case OPC_DLSA:
23983 check_mips_64(ctx);
23984 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23985 break;
23986 case R6_OPC_DCLO:
23987 case R6_OPC_DCLZ:
23988 if (rt == 0 && sa == 1) {
23989 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23990 We need additionally to check other fields */
23991 check_mips_64(ctx);
23992 gen_cl(ctx, op1, rd, rs);
23993 } else {
23994 generate_exception_end(ctx, EXCP_RI);
23996 break;
23997 case OPC_DMULT:
23998 case OPC_DMULTU:
23999 case OPC_DDIV:
24000 case OPC_DDIVU:
24002 op2 = MASK_R6_MULDIV(ctx->opcode);
24003 switch (op2) {
24004 case R6_OPC_DMUL:
24005 case R6_OPC_DMUH:
24006 case R6_OPC_DMULU:
24007 case R6_OPC_DMUHU:
24008 case R6_OPC_DDIV:
24009 case R6_OPC_DMOD:
24010 case R6_OPC_DDIVU:
24011 case R6_OPC_DMODU:
24012 check_mips_64(ctx);
24013 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24014 break;
24015 default:
24016 MIPS_INVAL("special_r6 muldiv");
24017 generate_exception_end(ctx, EXCP_RI);
24018 break;
24020 break;
24021 #endif
24022 default: /* Invalid */
24023 MIPS_INVAL("special_r6");
24024 generate_exception_end(ctx, EXCP_RI);
24025 break;
24029 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24031 int rs = extract32(ctx->opcode, 21, 5);
24032 int rt = extract32(ctx->opcode, 16, 5);
24033 int rd = extract32(ctx->opcode, 11, 5);
24034 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24036 switch (op1) {
24037 case OPC_MOVN: /* Conditional move */
24038 case OPC_MOVZ:
24039 gen_cond_move(ctx, op1, rd, rs, rt);
24040 break;
24041 case OPC_MFHI: /* Move from HI/LO */
24042 case OPC_MFLO:
24043 gen_HILO(ctx, op1, 0, rd);
24044 break;
24045 case OPC_MTHI:
24046 case OPC_MTLO: /* Move to HI/LO */
24047 gen_HILO(ctx, op1, 0, rs);
24048 break;
24049 case OPC_MULT:
24050 case OPC_MULTU:
24051 gen_mul_txx9(ctx, op1, rd, rs, rt);
24052 break;
24053 case OPC_DIV:
24054 case OPC_DIVU:
24055 gen_muldiv(ctx, op1, 0, rs, rt);
24056 break;
24057 #if defined(TARGET_MIPS64)
24058 case OPC_DMULT:
24059 case OPC_DMULTU:
24060 case OPC_DDIV:
24061 case OPC_DDIVU:
24062 check_insn_opc_user_only(ctx, INSN_R5900);
24063 gen_muldiv(ctx, op1, 0, rs, rt);
24064 break;
24065 #endif
24066 case OPC_JR:
24067 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24068 break;
24069 default: /* Invalid */
24070 MIPS_INVAL("special_tx79");
24071 generate_exception_end(ctx, EXCP_RI);
24072 break;
24076 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24078 int rs, rt, rd, sa;
24079 uint32_t op1;
24081 rs = (ctx->opcode >> 21) & 0x1f;
24082 rt = (ctx->opcode >> 16) & 0x1f;
24083 rd = (ctx->opcode >> 11) & 0x1f;
24084 sa = (ctx->opcode >> 6) & 0x1f;
24086 op1 = MASK_SPECIAL(ctx->opcode);
24087 switch (op1) {
24088 case OPC_MOVN: /* Conditional move */
24089 case OPC_MOVZ:
24090 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24091 INSN_LOONGSON2E | INSN_LOONGSON2F);
24092 gen_cond_move(ctx, op1, rd, rs, rt);
24093 break;
24094 case OPC_MFHI: /* Move from HI/LO */
24095 case OPC_MFLO:
24096 gen_HILO(ctx, op1, rs & 3, rd);
24097 break;
24098 case OPC_MTHI:
24099 case OPC_MTLO: /* Move to HI/LO */
24100 gen_HILO(ctx, op1, rd & 3, rs);
24101 break;
24102 case OPC_MOVCI:
24103 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24104 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24105 check_cp1_enabled(ctx);
24106 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24107 (ctx->opcode >> 16) & 1);
24108 } else {
24109 generate_exception_err(ctx, EXCP_CpU, 1);
24111 break;
24112 case OPC_MULT:
24113 case OPC_MULTU:
24114 if (sa) {
24115 check_insn(ctx, INSN_VR54XX);
24116 op1 = MASK_MUL_VR54XX(ctx->opcode);
24117 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24118 } else {
24119 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24121 break;
24122 case OPC_DIV:
24123 case OPC_DIVU:
24124 gen_muldiv(ctx, op1, 0, rs, rt);
24125 break;
24126 #if defined(TARGET_MIPS64)
24127 case OPC_DMULT:
24128 case OPC_DMULTU:
24129 case OPC_DDIV:
24130 case OPC_DDIVU:
24131 check_insn(ctx, ISA_MIPS3);
24132 check_mips_64(ctx);
24133 gen_muldiv(ctx, op1, 0, rs, rt);
24134 break;
24135 #endif
24136 case OPC_JR:
24137 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24138 break;
24139 case OPC_SPIM:
24140 #ifdef MIPS_STRICT_STANDARD
24141 MIPS_INVAL("SPIM");
24142 generate_exception_end(ctx, EXCP_RI);
24143 #else
24144 /* Implemented as RI exception for now. */
24145 MIPS_INVAL("spim (unofficial)");
24146 generate_exception_end(ctx, EXCP_RI);
24147 #endif
24148 break;
24149 default: /* Invalid */
24150 MIPS_INVAL("special_legacy");
24151 generate_exception_end(ctx, EXCP_RI);
24152 break;
24156 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24158 int rs, rt, rd, sa;
24159 uint32_t op1;
24161 rs = (ctx->opcode >> 21) & 0x1f;
24162 rt = (ctx->opcode >> 16) & 0x1f;
24163 rd = (ctx->opcode >> 11) & 0x1f;
24164 sa = (ctx->opcode >> 6) & 0x1f;
24166 op1 = MASK_SPECIAL(ctx->opcode);
24167 switch (op1) {
24168 case OPC_SLL: /* Shift with immediate */
24169 if (sa == 5 && rd == 0 &&
24170 rs == 0 && rt == 0) { /* PAUSE */
24171 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24172 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24173 generate_exception_end(ctx, EXCP_RI);
24174 break;
24177 /* Fallthrough */
24178 case OPC_SRA:
24179 gen_shift_imm(ctx, op1, rd, rt, sa);
24180 break;
24181 case OPC_SRL:
24182 switch ((ctx->opcode >> 21) & 0x1f) {
24183 case 1:
24184 /* rotr is decoded as srl on non-R2 CPUs */
24185 if (ctx->insn_flags & ISA_MIPS32R2) {
24186 op1 = OPC_ROTR;
24188 /* Fallthrough */
24189 case 0:
24190 gen_shift_imm(ctx, op1, rd, rt, sa);
24191 break;
24192 default:
24193 generate_exception_end(ctx, EXCP_RI);
24194 break;
24196 break;
24197 case OPC_ADD:
24198 case OPC_ADDU:
24199 case OPC_SUB:
24200 case OPC_SUBU:
24201 gen_arith(ctx, op1, rd, rs, rt);
24202 break;
24203 case OPC_SLLV: /* Shifts */
24204 case OPC_SRAV:
24205 gen_shift(ctx, op1, rd, rs, rt);
24206 break;
24207 case OPC_SRLV:
24208 switch ((ctx->opcode >> 6) & 0x1f) {
24209 case 1:
24210 /* rotrv is decoded as srlv on non-R2 CPUs */
24211 if (ctx->insn_flags & ISA_MIPS32R2) {
24212 op1 = OPC_ROTRV;
24214 /* Fallthrough */
24215 case 0:
24216 gen_shift(ctx, op1, rd, rs, rt);
24217 break;
24218 default:
24219 generate_exception_end(ctx, EXCP_RI);
24220 break;
24222 break;
24223 case OPC_SLT: /* Set on less than */
24224 case OPC_SLTU:
24225 gen_slt(ctx, op1, rd, rs, rt);
24226 break;
24227 case OPC_AND: /* Logic*/
24228 case OPC_OR:
24229 case OPC_NOR:
24230 case OPC_XOR:
24231 gen_logic(ctx, op1, rd, rs, rt);
24232 break;
24233 case OPC_JALR:
24234 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24235 break;
24236 case OPC_TGE: /* Traps */
24237 case OPC_TGEU:
24238 case OPC_TLT:
24239 case OPC_TLTU:
24240 case OPC_TEQ:
24241 case OPC_TNE:
24242 check_insn(ctx, ISA_MIPS2);
24243 gen_trap(ctx, op1, rs, rt, -1);
24244 break;
24245 case OPC_LSA: /* OPC_PMON */
24246 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24247 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24248 decode_opc_special_r6(env, ctx);
24249 } else {
24250 /* Pmon entry point, also R4010 selsl */
24251 #ifdef MIPS_STRICT_STANDARD
24252 MIPS_INVAL("PMON / selsl");
24253 generate_exception_end(ctx, EXCP_RI);
24254 #else
24255 gen_helper_0e0i(pmon, sa);
24256 #endif
24258 break;
24259 case OPC_SYSCALL:
24260 generate_exception_end(ctx, EXCP_SYSCALL);
24261 break;
24262 case OPC_BREAK:
24263 generate_exception_end(ctx, EXCP_BREAK);
24264 break;
24265 case OPC_SYNC:
24266 check_insn(ctx, ISA_MIPS2);
24267 gen_sync(extract32(ctx->opcode, 6, 5));
24268 break;
24270 #if defined(TARGET_MIPS64)
24271 /* MIPS64 specific opcodes */
24272 case OPC_DSLL:
24273 case OPC_DSRA:
24274 case OPC_DSLL32:
24275 case OPC_DSRA32:
24276 check_insn(ctx, ISA_MIPS3);
24277 check_mips_64(ctx);
24278 gen_shift_imm(ctx, op1, rd, rt, sa);
24279 break;
24280 case OPC_DSRL:
24281 switch ((ctx->opcode >> 21) & 0x1f) {
24282 case 1:
24283 /* drotr is decoded as dsrl on non-R2 CPUs */
24284 if (ctx->insn_flags & ISA_MIPS32R2) {
24285 op1 = OPC_DROTR;
24287 /* Fallthrough */
24288 case 0:
24289 check_insn(ctx, ISA_MIPS3);
24290 check_mips_64(ctx);
24291 gen_shift_imm(ctx, op1, rd, rt, sa);
24292 break;
24293 default:
24294 generate_exception_end(ctx, EXCP_RI);
24295 break;
24297 break;
24298 case OPC_DSRL32:
24299 switch ((ctx->opcode >> 21) & 0x1f) {
24300 case 1:
24301 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24302 if (ctx->insn_flags & ISA_MIPS32R2) {
24303 op1 = OPC_DROTR32;
24305 /* Fallthrough */
24306 case 0:
24307 check_insn(ctx, ISA_MIPS3);
24308 check_mips_64(ctx);
24309 gen_shift_imm(ctx, op1, rd, rt, sa);
24310 break;
24311 default:
24312 generate_exception_end(ctx, EXCP_RI);
24313 break;
24315 break;
24316 case OPC_DADD:
24317 case OPC_DADDU:
24318 case OPC_DSUB:
24319 case OPC_DSUBU:
24320 check_insn(ctx, ISA_MIPS3);
24321 check_mips_64(ctx);
24322 gen_arith(ctx, op1, rd, rs, rt);
24323 break;
24324 case OPC_DSLLV:
24325 case OPC_DSRAV:
24326 check_insn(ctx, ISA_MIPS3);
24327 check_mips_64(ctx);
24328 gen_shift(ctx, op1, rd, rs, rt);
24329 break;
24330 case OPC_DSRLV:
24331 switch ((ctx->opcode >> 6) & 0x1f) {
24332 case 1:
24333 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24334 if (ctx->insn_flags & ISA_MIPS32R2) {
24335 op1 = OPC_DROTRV;
24337 /* Fallthrough */
24338 case 0:
24339 check_insn(ctx, ISA_MIPS3);
24340 check_mips_64(ctx);
24341 gen_shift(ctx, op1, rd, rs, rt);
24342 break;
24343 default:
24344 generate_exception_end(ctx, EXCP_RI);
24345 break;
24347 break;
24348 case OPC_DLSA:
24349 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24350 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24351 decode_opc_special_r6(env, ctx);
24353 break;
24354 #endif
24355 default:
24356 if (ctx->insn_flags & ISA_MIPS32R6) {
24357 decode_opc_special_r6(env, ctx);
24358 } else if (ctx->insn_flags & INSN_R5900) {
24359 decode_opc_special_tx79(env, ctx);
24360 } else {
24361 decode_opc_special_legacy(env, ctx);
24367 #if !defined(TARGET_MIPS64)
24369 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24370 #define MXU_APTN1_A 0
24371 #define MXU_APTN1_S 1
24373 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24374 #define MXU_APTN2_AA 0
24375 #define MXU_APTN2_AS 1
24376 #define MXU_APTN2_SA 2
24377 #define MXU_APTN2_SS 3
24379 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24380 #define MXU_EPTN2_AA 0
24381 #define MXU_EPTN2_AS 1
24382 #define MXU_EPTN2_SA 2
24383 #define MXU_EPTN2_SS 3
24385 /* MXU operand getting pattern 'optn2' */
24386 #define MXU_OPTN2_PTN0 0
24387 #define MXU_OPTN2_PTN1 1
24388 #define MXU_OPTN2_PTN2 2
24389 #define MXU_OPTN2_PTN3 3
24390 /* alternative naming scheme for 'optn2' */
24391 #define MXU_OPTN2_WW 0
24392 #define MXU_OPTN2_LW 1
24393 #define MXU_OPTN2_HW 2
24394 #define MXU_OPTN2_XW 3
24396 /* MXU operand getting pattern 'optn3' */
24397 #define MXU_OPTN3_PTN0 0
24398 #define MXU_OPTN3_PTN1 1
24399 #define MXU_OPTN3_PTN2 2
24400 #define MXU_OPTN3_PTN3 3
24401 #define MXU_OPTN3_PTN4 4
24402 #define MXU_OPTN3_PTN5 5
24403 #define MXU_OPTN3_PTN6 6
24404 #define MXU_OPTN3_PTN7 7
24408 * S32I2M XRa, rb - Register move from GRF to XRF
24410 static void gen_mxu_s32i2m(DisasContext *ctx)
24412 TCGv t0;
24413 uint32_t XRa, Rb;
24415 t0 = tcg_temp_new();
24417 XRa = extract32(ctx->opcode, 6, 5);
24418 Rb = extract32(ctx->opcode, 16, 5);
24420 gen_load_gpr(t0, Rb);
24421 if (XRa <= 15) {
24422 gen_store_mxu_gpr(t0, XRa);
24423 } else if (XRa == 16) {
24424 gen_store_mxu_cr(t0);
24427 tcg_temp_free(t0);
24431 * S32M2I XRa, rb - Register move from XRF to GRF
24433 static void gen_mxu_s32m2i(DisasContext *ctx)
24435 TCGv t0;
24436 uint32_t XRa, Rb;
24438 t0 = tcg_temp_new();
24440 XRa = extract32(ctx->opcode, 6, 5);
24441 Rb = extract32(ctx->opcode, 16, 5);
24443 if (XRa <= 15) {
24444 gen_load_mxu_gpr(t0, XRa);
24445 } else if (XRa == 16) {
24446 gen_load_mxu_cr(t0);
24449 gen_store_gpr(t0, Rb);
24451 tcg_temp_free(t0);
24455 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24457 static void gen_mxu_s8ldd(DisasContext *ctx)
24459 TCGv t0, t1;
24460 uint32_t XRa, Rb, s8, optn3;
24462 t0 = tcg_temp_new();
24463 t1 = tcg_temp_new();
24465 XRa = extract32(ctx->opcode, 6, 4);
24466 s8 = extract32(ctx->opcode, 10, 8);
24467 optn3 = extract32(ctx->opcode, 18, 3);
24468 Rb = extract32(ctx->opcode, 21, 5);
24470 gen_load_gpr(t0, Rb);
24471 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24473 switch (optn3) {
24474 /* XRa[7:0] = tmp8 */
24475 case MXU_OPTN3_PTN0:
24476 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24477 gen_load_mxu_gpr(t0, XRa);
24478 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24479 break;
24480 /* XRa[15:8] = tmp8 */
24481 case MXU_OPTN3_PTN1:
24482 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24483 gen_load_mxu_gpr(t0, XRa);
24484 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24485 break;
24486 /* XRa[23:16] = tmp8 */
24487 case MXU_OPTN3_PTN2:
24488 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24489 gen_load_mxu_gpr(t0, XRa);
24490 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24491 break;
24492 /* XRa[31:24] = tmp8 */
24493 case MXU_OPTN3_PTN3:
24494 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24495 gen_load_mxu_gpr(t0, XRa);
24496 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24497 break;
24498 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24499 case MXU_OPTN3_PTN4:
24500 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24501 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24502 break;
24503 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24504 case MXU_OPTN3_PTN5:
24505 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24506 tcg_gen_shli_tl(t1, t1, 8);
24507 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24508 break;
24509 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24510 case MXU_OPTN3_PTN6:
24511 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24512 tcg_gen_mov_tl(t0, t1);
24513 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24514 tcg_gen_shli_tl(t1, t1, 16);
24515 tcg_gen_or_tl(t0, t0, t1);
24516 break;
24517 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24518 case MXU_OPTN3_PTN7:
24519 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24520 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24521 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24522 break;
24525 gen_store_mxu_gpr(t0, XRa);
24527 tcg_temp_free(t0);
24528 tcg_temp_free(t1);
24532 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24534 static void gen_mxu_d16mul(DisasContext *ctx)
24536 TCGv t0, t1, t2, t3;
24537 uint32_t XRa, XRb, XRc, XRd, optn2;
24539 t0 = tcg_temp_new();
24540 t1 = tcg_temp_new();
24541 t2 = tcg_temp_new();
24542 t3 = tcg_temp_new();
24544 XRa = extract32(ctx->opcode, 6, 4);
24545 XRb = extract32(ctx->opcode, 10, 4);
24546 XRc = extract32(ctx->opcode, 14, 4);
24547 XRd = extract32(ctx->opcode, 18, 4);
24548 optn2 = extract32(ctx->opcode, 22, 2);
24550 gen_load_mxu_gpr(t1, XRb);
24551 tcg_gen_sextract_tl(t0, t1, 0, 16);
24552 tcg_gen_sextract_tl(t1, t1, 16, 16);
24553 gen_load_mxu_gpr(t3, XRc);
24554 tcg_gen_sextract_tl(t2, t3, 0, 16);
24555 tcg_gen_sextract_tl(t3, t3, 16, 16);
24557 switch (optn2) {
24558 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24559 tcg_gen_mul_tl(t3, t1, t3);
24560 tcg_gen_mul_tl(t2, t0, t2);
24561 break;
24562 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24563 tcg_gen_mul_tl(t3, t0, t3);
24564 tcg_gen_mul_tl(t2, t0, t2);
24565 break;
24566 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24567 tcg_gen_mul_tl(t3, t1, t3);
24568 tcg_gen_mul_tl(t2, t1, t2);
24569 break;
24570 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24571 tcg_gen_mul_tl(t3, t0, t3);
24572 tcg_gen_mul_tl(t2, t1, t2);
24573 break;
24575 gen_store_mxu_gpr(t3, XRa);
24576 gen_store_mxu_gpr(t2, XRd);
24578 tcg_temp_free(t0);
24579 tcg_temp_free(t1);
24580 tcg_temp_free(t2);
24581 tcg_temp_free(t3);
24585 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24586 * and accumulate
24588 static void gen_mxu_d16mac(DisasContext *ctx)
24590 TCGv t0, t1, t2, t3;
24591 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24593 t0 = tcg_temp_new();
24594 t1 = tcg_temp_new();
24595 t2 = tcg_temp_new();
24596 t3 = tcg_temp_new();
24598 XRa = extract32(ctx->opcode, 6, 4);
24599 XRb = extract32(ctx->opcode, 10, 4);
24600 XRc = extract32(ctx->opcode, 14, 4);
24601 XRd = extract32(ctx->opcode, 18, 4);
24602 optn2 = extract32(ctx->opcode, 22, 2);
24603 aptn2 = extract32(ctx->opcode, 24, 2);
24605 gen_load_mxu_gpr(t1, XRb);
24606 tcg_gen_sextract_tl(t0, t1, 0, 16);
24607 tcg_gen_sextract_tl(t1, t1, 16, 16);
24609 gen_load_mxu_gpr(t3, XRc);
24610 tcg_gen_sextract_tl(t2, t3, 0, 16);
24611 tcg_gen_sextract_tl(t3, t3, 16, 16);
24613 switch (optn2) {
24614 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24615 tcg_gen_mul_tl(t3, t1, t3);
24616 tcg_gen_mul_tl(t2, t0, t2);
24617 break;
24618 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24619 tcg_gen_mul_tl(t3, t0, t3);
24620 tcg_gen_mul_tl(t2, t0, t2);
24621 break;
24622 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24623 tcg_gen_mul_tl(t3, t1, t3);
24624 tcg_gen_mul_tl(t2, t1, t2);
24625 break;
24626 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24627 tcg_gen_mul_tl(t3, t0, t3);
24628 tcg_gen_mul_tl(t2, t1, t2);
24629 break;
24631 gen_load_mxu_gpr(t0, XRa);
24632 gen_load_mxu_gpr(t1, XRd);
24634 switch (aptn2) {
24635 case MXU_APTN2_AA:
24636 tcg_gen_add_tl(t3, t0, t3);
24637 tcg_gen_add_tl(t2, t1, t2);
24638 break;
24639 case MXU_APTN2_AS:
24640 tcg_gen_add_tl(t3, t0, t3);
24641 tcg_gen_sub_tl(t2, t1, t2);
24642 break;
24643 case MXU_APTN2_SA:
24644 tcg_gen_sub_tl(t3, t0, t3);
24645 tcg_gen_add_tl(t2, t1, t2);
24646 break;
24647 case MXU_APTN2_SS:
24648 tcg_gen_sub_tl(t3, t0, t3);
24649 tcg_gen_sub_tl(t2, t1, t2);
24650 break;
24652 gen_store_mxu_gpr(t3, XRa);
24653 gen_store_mxu_gpr(t2, XRd);
24655 tcg_temp_free(t0);
24656 tcg_temp_free(t1);
24657 tcg_temp_free(t2);
24658 tcg_temp_free(t3);
24662 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24663 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24665 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24667 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24668 uint32_t XRa, XRb, XRc, XRd, sel;
24670 t0 = tcg_temp_new();
24671 t1 = tcg_temp_new();
24672 t2 = tcg_temp_new();
24673 t3 = tcg_temp_new();
24674 t4 = tcg_temp_new();
24675 t5 = tcg_temp_new();
24676 t6 = tcg_temp_new();
24677 t7 = tcg_temp_new();
24679 XRa = extract32(ctx->opcode, 6, 4);
24680 XRb = extract32(ctx->opcode, 10, 4);
24681 XRc = extract32(ctx->opcode, 14, 4);
24682 XRd = extract32(ctx->opcode, 18, 4);
24683 sel = extract32(ctx->opcode, 22, 2);
24685 gen_load_mxu_gpr(t3, XRb);
24686 gen_load_mxu_gpr(t7, XRc);
24688 if (sel == 0x2) {
24689 /* Q8MULSU */
24690 tcg_gen_ext8s_tl(t0, t3);
24691 tcg_gen_shri_tl(t3, t3, 8);
24692 tcg_gen_ext8s_tl(t1, t3);
24693 tcg_gen_shri_tl(t3, t3, 8);
24694 tcg_gen_ext8s_tl(t2, t3);
24695 tcg_gen_shri_tl(t3, t3, 8);
24696 tcg_gen_ext8s_tl(t3, t3);
24697 } else {
24698 /* Q8MUL */
24699 tcg_gen_ext8u_tl(t0, t3);
24700 tcg_gen_shri_tl(t3, t3, 8);
24701 tcg_gen_ext8u_tl(t1, t3);
24702 tcg_gen_shri_tl(t3, t3, 8);
24703 tcg_gen_ext8u_tl(t2, t3);
24704 tcg_gen_shri_tl(t3, t3, 8);
24705 tcg_gen_ext8u_tl(t3, t3);
24708 tcg_gen_ext8u_tl(t4, t7);
24709 tcg_gen_shri_tl(t7, t7, 8);
24710 tcg_gen_ext8u_tl(t5, t7);
24711 tcg_gen_shri_tl(t7, t7, 8);
24712 tcg_gen_ext8u_tl(t6, t7);
24713 tcg_gen_shri_tl(t7, t7, 8);
24714 tcg_gen_ext8u_tl(t7, t7);
24716 tcg_gen_mul_tl(t0, t0, t4);
24717 tcg_gen_mul_tl(t1, t1, t5);
24718 tcg_gen_mul_tl(t2, t2, t6);
24719 tcg_gen_mul_tl(t3, t3, t7);
24721 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24722 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24723 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24724 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24726 tcg_gen_shli_tl(t1, t1, 16);
24727 tcg_gen_shli_tl(t3, t3, 16);
24729 tcg_gen_or_tl(t0, t0, t1);
24730 tcg_gen_or_tl(t1, t2, t3);
24732 gen_store_mxu_gpr(t0, XRd);
24733 gen_store_mxu_gpr(t1, XRa);
24735 tcg_temp_free(t0);
24736 tcg_temp_free(t1);
24737 tcg_temp_free(t2);
24738 tcg_temp_free(t3);
24739 tcg_temp_free(t4);
24740 tcg_temp_free(t5);
24741 tcg_temp_free(t6);
24742 tcg_temp_free(t7);
24746 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24747 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24749 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24751 TCGv t0, t1;
24752 uint32_t XRa, Rb, s12, sel;
24754 t0 = tcg_temp_new();
24755 t1 = tcg_temp_new();
24757 XRa = extract32(ctx->opcode, 6, 4);
24758 s12 = extract32(ctx->opcode, 10, 10);
24759 sel = extract32(ctx->opcode, 20, 1);
24760 Rb = extract32(ctx->opcode, 21, 5);
24762 gen_load_gpr(t0, Rb);
24764 tcg_gen_movi_tl(t1, s12);
24765 tcg_gen_shli_tl(t1, t1, 2);
24766 if (s12 & 0x200) {
24767 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24769 tcg_gen_add_tl(t1, t0, t1);
24770 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24772 if (sel == 1) {
24773 /* S32LDDR */
24774 tcg_gen_bswap32_tl(t1, t1);
24776 gen_store_mxu_gpr(t1, XRa);
24778 tcg_temp_free(t0);
24779 tcg_temp_free(t1);
24784 * MXU instruction category: logic
24785 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24787 * S32NOR S32AND S32OR S32XOR
24791 * S32NOR XRa, XRb, XRc
24792 * Update XRa with the result of logical bitwise 'nor' operation
24793 * applied to the content of XRb and XRc.
24795 * 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
24796 * +-----------+---------+-----+-------+-------+-------+-----------+
24797 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24798 * +-----------+---------+-----+-------+-------+-------+-----------+
24800 static void gen_mxu_S32NOR(DisasContext *ctx)
24802 uint32_t pad, XRc, XRb, XRa;
24804 pad = extract32(ctx->opcode, 21, 5);
24805 XRc = extract32(ctx->opcode, 14, 4);
24806 XRb = extract32(ctx->opcode, 10, 4);
24807 XRa = extract32(ctx->opcode, 6, 4);
24809 if (unlikely(pad != 0)) {
24810 /* opcode padding incorrect -> do nothing */
24811 } else if (unlikely(XRa == 0)) {
24812 /* destination is zero register -> do nothing */
24813 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24814 /* both operands zero registers -> just set destination to all 1s */
24815 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
24816 } else if (unlikely(XRb == 0)) {
24817 /* XRb zero register -> just set destination to the negation of XRc */
24818 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24819 } else if (unlikely(XRc == 0)) {
24820 /* XRa zero register -> just set destination to the negation of XRb */
24821 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24822 } else if (unlikely(XRb == XRc)) {
24823 /* both operands same -> just set destination to the negation of XRb */
24824 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24825 } else {
24826 /* the most general case */
24827 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24832 * S32AND XRa, XRb, XRc
24833 * Update XRa with the result of logical bitwise 'and' operation
24834 * applied to the content of XRb and XRc.
24836 * 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
24837 * +-----------+---------+-----+-------+-------+-------+-----------+
24838 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24839 * +-----------+---------+-----+-------+-------+-------+-----------+
24841 static void gen_mxu_S32AND(DisasContext *ctx)
24843 uint32_t pad, XRc, XRb, XRa;
24845 pad = extract32(ctx->opcode, 21, 5);
24846 XRc = extract32(ctx->opcode, 14, 4);
24847 XRb = extract32(ctx->opcode, 10, 4);
24848 XRa = extract32(ctx->opcode, 6, 4);
24850 if (unlikely(pad != 0)) {
24851 /* opcode padding incorrect -> do nothing */
24852 } else if (unlikely(XRa == 0)) {
24853 /* destination is zero register -> do nothing */
24854 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24855 /* one of operands zero register -> just set destination to all 0s */
24856 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24857 } else if (unlikely(XRb == XRc)) {
24858 /* both operands same -> just set destination to one of them */
24859 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24860 } else {
24861 /* the most general case */
24862 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24867 * S32OR XRa, XRb, XRc
24868 * Update XRa with the result of logical bitwise 'or' operation
24869 * applied to the content of XRb and XRc.
24871 * 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
24872 * +-----------+---------+-----+-------+-------+-------+-----------+
24873 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24874 * +-----------+---------+-----+-------+-------+-------+-----------+
24876 static void gen_mxu_S32OR(DisasContext *ctx)
24878 uint32_t pad, XRc, XRb, XRa;
24880 pad = extract32(ctx->opcode, 21, 5);
24881 XRc = extract32(ctx->opcode, 14, 4);
24882 XRb = extract32(ctx->opcode, 10, 4);
24883 XRa = extract32(ctx->opcode, 6, 4);
24885 if (unlikely(pad != 0)) {
24886 /* opcode padding incorrect -> do nothing */
24887 } else if (unlikely(XRa == 0)) {
24888 /* destination is zero register -> do nothing */
24889 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24890 /* both operands zero registers -> just set destination to all 0s */
24891 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24892 } else if (unlikely(XRb == 0)) {
24893 /* XRb zero register -> just set destination to the content of XRc */
24894 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24895 } else if (unlikely(XRc == 0)) {
24896 /* XRc zero register -> just set destination to the content of XRb */
24897 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24898 } else if (unlikely(XRb == XRc)) {
24899 /* both operands same -> just set destination to one of them */
24900 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24901 } else {
24902 /* the most general case */
24903 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24908 * S32XOR XRa, XRb, XRc
24909 * Update XRa with the result of logical bitwise 'xor' operation
24910 * applied to the content of XRb and XRc.
24912 * 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
24913 * +-----------+---------+-----+-------+-------+-------+-----------+
24914 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24915 * +-----------+---------+-----+-------+-------+-------+-----------+
24917 static void gen_mxu_S32XOR(DisasContext *ctx)
24919 uint32_t pad, XRc, XRb, XRa;
24921 pad = extract32(ctx->opcode, 21, 5);
24922 XRc = extract32(ctx->opcode, 14, 4);
24923 XRb = extract32(ctx->opcode, 10, 4);
24924 XRa = extract32(ctx->opcode, 6, 4);
24926 if (unlikely(pad != 0)) {
24927 /* opcode padding incorrect -> do nothing */
24928 } else if (unlikely(XRa == 0)) {
24929 /* destination is zero register -> do nothing */
24930 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24931 /* both operands zero registers -> just set destination to all 0s */
24932 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24933 } else if (unlikely(XRb == 0)) {
24934 /* XRb zero register -> just set destination to the content of XRc */
24935 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24936 } else if (unlikely(XRc == 0)) {
24937 /* XRc zero register -> just set destination to the content of XRb */
24938 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24939 } else if (unlikely(XRb == XRc)) {
24940 /* both operands same -> just set destination to all 0s */
24941 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24942 } else {
24943 /* the most general case */
24944 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24950 * MXU instruction category max/min
24951 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24953 * S32MAX D16MAX Q8MAX
24954 * S32MIN D16MIN Q8MIN
24958 * S32MAX XRa, XRb, XRc
24959 * Update XRa with the maximum of signed 32-bit integers contained
24960 * in XRb and XRc.
24962 * S32MIN XRa, XRb, XRc
24963 * Update XRa with the minimum of signed 32-bit integers contained
24964 * in XRb and XRc.
24966 * 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
24967 * +-----------+---------+-----+-------+-------+-------+-----------+
24968 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
24969 * +-----------+---------+-----+-------+-------+-------+-----------+
24971 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
24973 uint32_t pad, opc, XRc, XRb, XRa;
24975 pad = extract32(ctx->opcode, 21, 5);
24976 opc = extract32(ctx->opcode, 18, 3);
24977 XRc = extract32(ctx->opcode, 14, 4);
24978 XRb = extract32(ctx->opcode, 10, 4);
24979 XRa = extract32(ctx->opcode, 6, 4);
24981 if (unlikely(pad != 0)) {
24982 /* opcode padding incorrect -> do nothing */
24983 } else if (unlikely(XRa == 0)) {
24984 /* destination is zero register -> do nothing */
24985 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24986 /* both operands zero registers -> just set destination to zero */
24987 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24988 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24989 /* exactly one operand is zero register - find which one is not...*/
24990 uint32_t XRx = XRb ? XRb : XRc;
24991 /* ...and do max/min operation with one operand 0 */
24992 if (opc == OPC_MXU_S32MAX) {
24993 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24994 } else {
24995 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24997 } else if (unlikely(XRb == XRc)) {
24998 /* both operands same -> just set destination to one of them */
24999 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25000 } else {
25001 /* the most general case */
25002 if (opc == OPC_MXU_S32MAX) {
25003 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25004 mxu_gpr[XRc - 1]);
25005 } else {
25006 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25007 mxu_gpr[XRc - 1]);
25013 * D16MAX
25014 * Update XRa with the 16-bit-wise maximums of signed integers
25015 * contained in XRb and XRc.
25017 * D16MIN
25018 * Update XRa with the 16-bit-wise minimums of signed integers
25019 * contained in XRb and XRc.
25021 * 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
25022 * +-----------+---------+-----+-------+-------+-------+-----------+
25023 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25024 * +-----------+---------+-----+-------+-------+-------+-----------+
25026 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25028 uint32_t pad, opc, XRc, XRb, XRa;
25030 pad = extract32(ctx->opcode, 21, 5);
25031 opc = extract32(ctx->opcode, 18, 3);
25032 XRc = extract32(ctx->opcode, 14, 4);
25033 XRb = extract32(ctx->opcode, 10, 4);
25034 XRa = extract32(ctx->opcode, 6, 4);
25036 if (unlikely(pad != 0)) {
25037 /* opcode padding incorrect -> do nothing */
25038 } else if (unlikely(XRc == 0)) {
25039 /* destination is zero register -> do nothing */
25040 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25041 /* both operands zero registers -> just set destination to zero */
25042 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25043 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25044 /* exactly one operand is zero register - find which one is not...*/
25045 uint32_t XRx = XRb ? XRb : XRc;
25046 /* ...and do half-word-wise max/min with one operand 0 */
25047 TCGv_i32 t0 = tcg_temp_new();
25048 TCGv_i32 t1 = tcg_const_i32(0);
25050 /* the left half-word first */
25051 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25052 if (opc == OPC_MXU_D16MAX) {
25053 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25054 } else {
25055 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25058 /* the right half-word */
25059 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25060 /* move half-words to the leftmost position */
25061 tcg_gen_shli_i32(t0, t0, 16);
25062 /* t0 will be max/min of t0 and t1 */
25063 if (opc == OPC_MXU_D16MAX) {
25064 tcg_gen_smax_i32(t0, t0, t1);
25065 } else {
25066 tcg_gen_smin_i32(t0, t0, t1);
25068 /* return resulting half-words to its original position */
25069 tcg_gen_shri_i32(t0, t0, 16);
25070 /* finaly update the destination */
25071 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25073 tcg_temp_free(t1);
25074 tcg_temp_free(t0);
25075 } else if (unlikely(XRb == XRc)) {
25076 /* both operands same -> just set destination to one of them */
25077 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25078 } else {
25079 /* the most general case */
25080 TCGv_i32 t0 = tcg_temp_new();
25081 TCGv_i32 t1 = tcg_temp_new();
25083 /* the left half-word first */
25084 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25085 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25086 if (opc == OPC_MXU_D16MAX) {
25087 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25088 } else {
25089 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25092 /* the right half-word */
25093 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25094 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25095 /* move half-words to the leftmost position */
25096 tcg_gen_shli_i32(t0, t0, 16);
25097 tcg_gen_shli_i32(t1, t1, 16);
25098 /* t0 will be max/min of t0 and t1 */
25099 if (opc == OPC_MXU_D16MAX) {
25100 tcg_gen_smax_i32(t0, t0, t1);
25101 } else {
25102 tcg_gen_smin_i32(t0, t0, t1);
25104 /* return resulting half-words to its original position */
25105 tcg_gen_shri_i32(t0, t0, 16);
25106 /* finaly update the destination */
25107 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25109 tcg_temp_free(t1);
25110 tcg_temp_free(t0);
25115 * Q8MAX
25116 * Update XRa with the 8-bit-wise maximums of signed integers
25117 * contained in XRb and XRc.
25119 * Q8MIN
25120 * Update XRa with the 8-bit-wise minimums of signed integers
25121 * contained in XRb and XRc.
25123 * 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
25124 * +-----------+---------+-----+-------+-------+-------+-----------+
25125 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25126 * +-----------+---------+-----+-------+-------+-------+-----------+
25128 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25130 uint32_t pad, opc, XRc, XRb, XRa;
25132 pad = extract32(ctx->opcode, 21, 5);
25133 opc = extract32(ctx->opcode, 18, 3);
25134 XRc = extract32(ctx->opcode, 14, 4);
25135 XRb = extract32(ctx->opcode, 10, 4);
25136 XRa = extract32(ctx->opcode, 6, 4);
25138 if (unlikely(pad != 0)) {
25139 /* opcode padding incorrect -> do nothing */
25140 } else if (unlikely(XRa == 0)) {
25141 /* destination is zero register -> do nothing */
25142 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25143 /* both operands zero registers -> just set destination to zero */
25144 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25145 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25146 /* exactly one operand is zero register - make it be the first...*/
25147 uint32_t XRx = XRb ? XRb : XRc;
25148 /* ...and do byte-wise max/min with one operand 0 */
25149 TCGv_i32 t0 = tcg_temp_new();
25150 TCGv_i32 t1 = tcg_const_i32(0);
25151 int32_t i;
25153 /* the leftmost byte (byte 3) first */
25154 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25155 if (opc == OPC_MXU_Q8MAX) {
25156 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25157 } else {
25158 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25161 /* bytes 2, 1, 0 */
25162 for (i = 2; i >= 0; i--) {
25163 /* extract the byte */
25164 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25165 /* move the byte to the leftmost position */
25166 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25167 /* t0 will be max/min of t0 and t1 */
25168 if (opc == OPC_MXU_Q8MAX) {
25169 tcg_gen_smax_i32(t0, t0, t1);
25170 } else {
25171 tcg_gen_smin_i32(t0, t0, t1);
25173 /* return resulting byte to its original position */
25174 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25175 /* finaly update the destination */
25176 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25179 tcg_temp_free(t1);
25180 tcg_temp_free(t0);
25181 } else if (unlikely(XRb == XRc)) {
25182 /* both operands same -> just set destination to one of them */
25183 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25184 } else {
25185 /* the most general case */
25186 TCGv_i32 t0 = tcg_temp_new();
25187 TCGv_i32 t1 = tcg_temp_new();
25188 int32_t i;
25190 /* the leftmost bytes (bytes 3) first */
25191 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25192 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25193 if (opc == OPC_MXU_Q8MAX) {
25194 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25195 } else {
25196 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25199 /* bytes 2, 1, 0 */
25200 for (i = 2; i >= 0; i--) {
25201 /* extract corresponding bytes */
25202 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25203 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25204 /* move the bytes to the leftmost position */
25205 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25206 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25207 /* t0 will be max/min of t0 and t1 */
25208 if (opc == OPC_MXU_Q8MAX) {
25209 tcg_gen_smax_i32(t0, t0, t1);
25210 } else {
25211 tcg_gen_smin_i32(t0, t0, t1);
25213 /* return resulting byte to its original position */
25214 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25215 /* finaly update the destination */
25216 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25219 tcg_temp_free(t1);
25220 tcg_temp_free(t0);
25226 * MXU instruction category: align
25227 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25229 * S32ALN S32ALNI
25233 * S32ALNI XRc, XRb, XRa, optn3
25234 * Arrange bytes from XRb and XRc according to one of five sets of
25235 * rules determined by optn3, and place the result in XRa.
25237 * 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
25238 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25239 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25240 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25243 static void gen_mxu_S32ALNI(DisasContext *ctx)
25245 uint32_t optn3, pad, XRc, XRb, XRa;
25247 optn3 = extract32(ctx->opcode, 23, 3);
25248 pad = extract32(ctx->opcode, 21, 2);
25249 XRc = extract32(ctx->opcode, 14, 4);
25250 XRb = extract32(ctx->opcode, 10, 4);
25251 XRa = extract32(ctx->opcode, 6, 4);
25253 if (unlikely(pad != 0)) {
25254 /* opcode padding incorrect -> do nothing */
25255 } else if (unlikely(XRa == 0)) {
25256 /* destination is zero register -> do nothing */
25257 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25258 /* both operands zero registers -> just set destination to all 0s */
25259 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25260 } else if (unlikely(XRb == 0)) {
25261 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25262 switch (optn3) {
25263 case MXU_OPTN3_PTN0:
25264 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25265 break;
25266 case MXU_OPTN3_PTN1:
25267 case MXU_OPTN3_PTN2:
25268 case MXU_OPTN3_PTN3:
25269 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25270 8 * (4 - optn3));
25271 break;
25272 case MXU_OPTN3_PTN4:
25273 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25274 break;
25276 } else if (unlikely(XRc == 0)) {
25277 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25278 switch (optn3) {
25279 case MXU_OPTN3_PTN0:
25280 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25281 break;
25282 case MXU_OPTN3_PTN1:
25283 case MXU_OPTN3_PTN2:
25284 case MXU_OPTN3_PTN3:
25285 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25286 break;
25287 case MXU_OPTN3_PTN4:
25288 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25289 break;
25291 } else if (unlikely(XRb == XRc)) {
25292 /* both operands same -> just rotation or moving from any of them */
25293 switch (optn3) {
25294 case MXU_OPTN3_PTN0:
25295 case MXU_OPTN3_PTN4:
25296 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25297 break;
25298 case MXU_OPTN3_PTN1:
25299 case MXU_OPTN3_PTN2:
25300 case MXU_OPTN3_PTN3:
25301 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25302 break;
25304 } else {
25305 /* the most general case */
25306 switch (optn3) {
25307 case MXU_OPTN3_PTN0:
25309 /* */
25310 /* XRb XRc */
25311 /* +---------------+ */
25312 /* | A B C D | E F G H */
25313 /* +-------+-------+ */
25314 /* | */
25315 /* XRa */
25316 /* */
25318 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25320 break;
25321 case MXU_OPTN3_PTN1:
25323 /* */
25324 /* XRb XRc */
25325 /* +-------------------+ */
25326 /* A | B C D E | F G H */
25327 /* +---------+---------+ */
25328 /* | */
25329 /* XRa */
25330 /* */
25332 TCGv_i32 t0 = tcg_temp_new();
25333 TCGv_i32 t1 = tcg_temp_new();
25335 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25336 tcg_gen_shli_i32(t0, t0, 8);
25338 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25339 tcg_gen_shri_i32(t1, t1, 24);
25341 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25343 tcg_temp_free(t1);
25344 tcg_temp_free(t0);
25346 break;
25347 case MXU_OPTN3_PTN2:
25349 /* */
25350 /* XRb XRc */
25351 /* +-------------------+ */
25352 /* A B | C D E F | G H */
25353 /* +---------+---------+ */
25354 /* | */
25355 /* XRa */
25356 /* */
25358 TCGv_i32 t0 = tcg_temp_new();
25359 TCGv_i32 t1 = tcg_temp_new();
25361 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25362 tcg_gen_shli_i32(t0, t0, 16);
25364 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25365 tcg_gen_shri_i32(t1, t1, 16);
25367 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25369 tcg_temp_free(t1);
25370 tcg_temp_free(t0);
25372 break;
25373 case MXU_OPTN3_PTN3:
25375 /* */
25376 /* XRb XRc */
25377 /* +-------------------+ */
25378 /* A B C | D E F G | H */
25379 /* +---------+---------+ */
25380 /* | */
25381 /* XRa */
25382 /* */
25384 TCGv_i32 t0 = tcg_temp_new();
25385 TCGv_i32 t1 = tcg_temp_new();
25387 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25388 tcg_gen_shli_i32(t0, t0, 24);
25390 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25391 tcg_gen_shri_i32(t1, t1, 8);
25393 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25395 tcg_temp_free(t1);
25396 tcg_temp_free(t0);
25398 break;
25399 case MXU_OPTN3_PTN4:
25401 /* */
25402 /* XRb XRc */
25403 /* +---------------+ */
25404 /* A B C D | E F G H | */
25405 /* +-------+-------+ */
25406 /* | */
25407 /* XRa */
25408 /* */
25410 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25412 break;
25419 * Decoding engine for MXU
25420 * =======================
25425 * Decode MXU pool00
25427 * 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
25428 * +-----------+---------+-----+-------+-------+-------+-----------+
25429 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25430 * +-----------+---------+-----+-------+-------+-------+-----------+
25433 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25435 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25437 switch (opcode) {
25438 case OPC_MXU_S32MAX:
25439 case OPC_MXU_S32MIN:
25440 gen_mxu_S32MAX_S32MIN(ctx);
25441 break;
25442 case OPC_MXU_D16MAX:
25443 case OPC_MXU_D16MIN:
25444 gen_mxu_D16MAX_D16MIN(ctx);
25445 break;
25446 case OPC_MXU_Q8MAX:
25447 case OPC_MXU_Q8MIN:
25448 gen_mxu_Q8MAX_Q8MIN(ctx);
25449 break;
25450 case OPC_MXU_Q8SLT:
25451 /* TODO: Implement emulation of Q8SLT instruction. */
25452 MIPS_INVAL("OPC_MXU_Q8SLT");
25453 generate_exception_end(ctx, EXCP_RI);
25454 break;
25455 case OPC_MXU_Q8SLTU:
25456 /* TODO: Implement emulation of Q8SLTU instruction. */
25457 MIPS_INVAL("OPC_MXU_Q8SLTU");
25458 generate_exception_end(ctx, EXCP_RI);
25459 break;
25460 default:
25461 MIPS_INVAL("decode_opc_mxu");
25462 generate_exception_end(ctx, EXCP_RI);
25463 break;
25469 * Decode MXU pool01
25471 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25472 * 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
25473 * +-----------+---------+-----+-------+-------+-------+-----------+
25474 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25475 * +-----------+---------+-----+-------+-------+-------+-----------+
25477 * Q8ADD:
25478 * 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
25479 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25480 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25481 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25484 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25486 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25488 switch (opcode) {
25489 case OPC_MXU_S32SLT:
25490 /* TODO: Implement emulation of S32SLT instruction. */
25491 MIPS_INVAL("OPC_MXU_S32SLT");
25492 generate_exception_end(ctx, EXCP_RI);
25493 break;
25494 case OPC_MXU_D16SLT:
25495 /* TODO: Implement emulation of D16SLT instruction. */
25496 MIPS_INVAL("OPC_MXU_D16SLT");
25497 generate_exception_end(ctx, EXCP_RI);
25498 break;
25499 case OPC_MXU_D16AVG:
25500 /* TODO: Implement emulation of D16AVG instruction. */
25501 MIPS_INVAL("OPC_MXU_D16AVG");
25502 generate_exception_end(ctx, EXCP_RI);
25503 break;
25504 case OPC_MXU_D16AVGR:
25505 /* TODO: Implement emulation of D16AVGR instruction. */
25506 MIPS_INVAL("OPC_MXU_D16AVGR");
25507 generate_exception_end(ctx, EXCP_RI);
25508 break;
25509 case OPC_MXU_Q8AVG:
25510 /* TODO: Implement emulation of Q8AVG instruction. */
25511 MIPS_INVAL("OPC_MXU_Q8AVG");
25512 generate_exception_end(ctx, EXCP_RI);
25513 break;
25514 case OPC_MXU_Q8AVGR:
25515 /* TODO: Implement emulation of Q8AVGR instruction. */
25516 MIPS_INVAL("OPC_MXU_Q8AVGR");
25517 generate_exception_end(ctx, EXCP_RI);
25518 break;
25519 case OPC_MXU_Q8ADD:
25520 /* TODO: Implement emulation of Q8ADD instruction. */
25521 MIPS_INVAL("OPC_MXU_Q8ADD");
25522 generate_exception_end(ctx, EXCP_RI);
25523 break;
25524 default:
25525 MIPS_INVAL("decode_opc_mxu");
25526 generate_exception_end(ctx, EXCP_RI);
25527 break;
25533 * Decode MXU pool02
25535 * 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
25536 * +-----------+---------+-----+-------+-------+-------+-----------+
25537 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25538 * +-----------+---------+-----+-------+-------+-------+-----------+
25541 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25543 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25545 switch (opcode) {
25546 case OPC_MXU_S32CPS:
25547 /* TODO: Implement emulation of S32CPS instruction. */
25548 MIPS_INVAL("OPC_MXU_S32CPS");
25549 generate_exception_end(ctx, EXCP_RI);
25550 break;
25551 case OPC_MXU_D16CPS:
25552 /* TODO: Implement emulation of D16CPS instruction. */
25553 MIPS_INVAL("OPC_MXU_D16CPS");
25554 generate_exception_end(ctx, EXCP_RI);
25555 break;
25556 case OPC_MXU_Q8ABD:
25557 /* TODO: Implement emulation of Q8ABD instruction. */
25558 MIPS_INVAL("OPC_MXU_Q8ABD");
25559 generate_exception_end(ctx, EXCP_RI);
25560 break;
25561 case OPC_MXU_Q16SAT:
25562 /* TODO: Implement emulation of Q16SAT instruction. */
25563 MIPS_INVAL("OPC_MXU_Q16SAT");
25564 generate_exception_end(ctx, EXCP_RI);
25565 break;
25566 default:
25567 MIPS_INVAL("decode_opc_mxu");
25568 generate_exception_end(ctx, EXCP_RI);
25569 break;
25575 * Decode MXU pool03
25577 * D16MULF:
25578 * 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
25579 * +-----------+---+---+-------+-------+-------+-------+-----------+
25580 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25581 * +-----------+---+---+-------+-------+-------+-------+-----------+
25583 * D16MULE:
25584 * 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
25585 * +-----------+---+---+-------+-------+-------+-------+-----------+
25586 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25587 * +-----------+---+---+-------+-------+-------+-------+-----------+
25590 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25592 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25594 switch (opcode) {
25595 case OPC_MXU_D16MULF:
25596 /* TODO: Implement emulation of D16MULF instruction. */
25597 MIPS_INVAL("OPC_MXU_D16MULF");
25598 generate_exception_end(ctx, EXCP_RI);
25599 break;
25600 case OPC_MXU_D16MULE:
25601 /* TODO: Implement emulation of D16MULE instruction. */
25602 MIPS_INVAL("OPC_MXU_D16MULE");
25603 generate_exception_end(ctx, EXCP_RI);
25604 break;
25605 default:
25606 MIPS_INVAL("decode_opc_mxu");
25607 generate_exception_end(ctx, EXCP_RI);
25608 break;
25614 * Decode MXU pool04
25616 * 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
25617 * +-----------+---------+-+-------------------+-------+-----------+
25618 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25619 * +-----------+---------+-+-------------------+-------+-----------+
25622 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25624 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25626 switch (opcode) {
25627 case OPC_MXU_S32LDD:
25628 case OPC_MXU_S32LDDR:
25629 gen_mxu_s32ldd_s32lddr(ctx);
25630 break;
25631 default:
25632 MIPS_INVAL("decode_opc_mxu");
25633 generate_exception_end(ctx, EXCP_RI);
25634 break;
25640 * Decode MXU pool05
25642 * 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
25643 * +-----------+---------+-+-------------------+-------+-----------+
25644 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25645 * +-----------+---------+-+-------------------+-------+-----------+
25648 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25650 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25652 switch (opcode) {
25653 case OPC_MXU_S32STD:
25654 /* TODO: Implement emulation of S32STD instruction. */
25655 MIPS_INVAL("OPC_MXU_S32STD");
25656 generate_exception_end(ctx, EXCP_RI);
25657 break;
25658 case OPC_MXU_S32STDR:
25659 /* TODO: Implement emulation of S32STDR instruction. */
25660 MIPS_INVAL("OPC_MXU_S32STDR");
25661 generate_exception_end(ctx, EXCP_RI);
25662 break;
25663 default:
25664 MIPS_INVAL("decode_opc_mxu");
25665 generate_exception_end(ctx, EXCP_RI);
25666 break;
25672 * Decode MXU pool06
25674 * 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
25675 * +-----------+---------+---------+---+-------+-------+-----------+
25676 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25677 * +-----------+---------+---------+---+-------+-------+-----------+
25680 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25682 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25684 switch (opcode) {
25685 case OPC_MXU_S32LDDV:
25686 /* TODO: Implement emulation of S32LDDV instruction. */
25687 MIPS_INVAL("OPC_MXU_S32LDDV");
25688 generate_exception_end(ctx, EXCP_RI);
25689 break;
25690 case OPC_MXU_S32LDDVR:
25691 /* TODO: Implement emulation of S32LDDVR instruction. */
25692 MIPS_INVAL("OPC_MXU_S32LDDVR");
25693 generate_exception_end(ctx, EXCP_RI);
25694 break;
25695 default:
25696 MIPS_INVAL("decode_opc_mxu");
25697 generate_exception_end(ctx, EXCP_RI);
25698 break;
25704 * Decode MXU pool07
25706 * 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
25707 * +-----------+---------+---------+---+-------+-------+-----------+
25708 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
25709 * +-----------+---------+---------+---+-------+-------+-----------+
25712 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
25714 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25716 switch (opcode) {
25717 case OPC_MXU_S32STDV:
25718 /* TODO: Implement emulation of S32TDV instruction. */
25719 MIPS_INVAL("OPC_MXU_S32TDV");
25720 generate_exception_end(ctx, EXCP_RI);
25721 break;
25722 case OPC_MXU_S32STDVR:
25723 /* TODO: Implement emulation of S32TDVR instruction. */
25724 MIPS_INVAL("OPC_MXU_S32TDVR");
25725 generate_exception_end(ctx, EXCP_RI);
25726 break;
25727 default:
25728 MIPS_INVAL("decode_opc_mxu");
25729 generate_exception_end(ctx, EXCP_RI);
25730 break;
25736 * Decode MXU pool08
25738 * 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
25739 * +-----------+---------+-+-------------------+-------+-----------+
25740 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
25741 * +-----------+---------+-+-------------------+-------+-----------+
25744 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
25746 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25748 switch (opcode) {
25749 case OPC_MXU_S32LDI:
25750 /* TODO: Implement emulation of S32LDI instruction. */
25751 MIPS_INVAL("OPC_MXU_S32LDI");
25752 generate_exception_end(ctx, EXCP_RI);
25753 break;
25754 case OPC_MXU_S32LDIR:
25755 /* TODO: Implement emulation of S32LDIR instruction. */
25756 MIPS_INVAL("OPC_MXU_S32LDIR");
25757 generate_exception_end(ctx, EXCP_RI);
25758 break;
25759 default:
25760 MIPS_INVAL("decode_opc_mxu");
25761 generate_exception_end(ctx, EXCP_RI);
25762 break;
25768 * Decode MXU pool09
25770 * 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
25771 * +-----------+---------+-+-------------------+-------+-----------+
25772 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
25773 * +-----------+---------+-+-------------------+-------+-----------+
25776 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
25778 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25780 switch (opcode) {
25781 case OPC_MXU_S32SDI:
25782 /* TODO: Implement emulation of S32SDI instruction. */
25783 MIPS_INVAL("OPC_MXU_S32SDI");
25784 generate_exception_end(ctx, EXCP_RI);
25785 break;
25786 case OPC_MXU_S32SDIR:
25787 /* TODO: Implement emulation of S32SDIR instruction. */
25788 MIPS_INVAL("OPC_MXU_S32SDIR");
25789 generate_exception_end(ctx, EXCP_RI);
25790 break;
25791 default:
25792 MIPS_INVAL("decode_opc_mxu");
25793 generate_exception_end(ctx, EXCP_RI);
25794 break;
25800 * Decode MXU pool10
25802 * 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
25803 * +-----------+---------+---------+---+-------+-------+-----------+
25804 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
25805 * +-----------+---------+---------+---+-------+-------+-----------+
25808 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
25810 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25812 switch (opcode) {
25813 case OPC_MXU_S32LDIV:
25814 /* TODO: Implement emulation of S32LDIV instruction. */
25815 MIPS_INVAL("OPC_MXU_S32LDIV");
25816 generate_exception_end(ctx, EXCP_RI);
25817 break;
25818 case OPC_MXU_S32LDIVR:
25819 /* TODO: Implement emulation of S32LDIVR instruction. */
25820 MIPS_INVAL("OPC_MXU_S32LDIVR");
25821 generate_exception_end(ctx, EXCP_RI);
25822 break;
25823 default:
25824 MIPS_INVAL("decode_opc_mxu");
25825 generate_exception_end(ctx, EXCP_RI);
25826 break;
25832 * Decode MXU pool11
25834 * 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
25835 * +-----------+---------+---------+---+-------+-------+-----------+
25836 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
25837 * +-----------+---------+---------+---+-------+-------+-----------+
25840 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
25842 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25844 switch (opcode) {
25845 case OPC_MXU_S32SDIV:
25846 /* TODO: Implement emulation of S32SDIV instruction. */
25847 MIPS_INVAL("OPC_MXU_S32SDIV");
25848 generate_exception_end(ctx, EXCP_RI);
25849 break;
25850 case OPC_MXU_S32SDIVR:
25851 /* TODO: Implement emulation of S32SDIVR instruction. */
25852 MIPS_INVAL("OPC_MXU_S32SDIVR");
25853 generate_exception_end(ctx, EXCP_RI);
25854 break;
25855 default:
25856 MIPS_INVAL("decode_opc_mxu");
25857 generate_exception_end(ctx, EXCP_RI);
25858 break;
25864 * Decode MXU pool12
25866 * 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
25867 * +-----------+---+---+-------+-------+-------+-------+-----------+
25868 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
25869 * +-----------+---+---+-------+-------+-------+-------+-----------+
25872 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
25874 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25876 switch (opcode) {
25877 case OPC_MXU_D32ACC:
25878 /* TODO: Implement emulation of D32ACC instruction. */
25879 MIPS_INVAL("OPC_MXU_D32ACC");
25880 generate_exception_end(ctx, EXCP_RI);
25881 break;
25882 case OPC_MXU_D32ACCM:
25883 /* TODO: Implement emulation of D32ACCM instruction. */
25884 MIPS_INVAL("OPC_MXU_D32ACCM");
25885 generate_exception_end(ctx, EXCP_RI);
25886 break;
25887 case OPC_MXU_D32ASUM:
25888 /* TODO: Implement emulation of D32ASUM instruction. */
25889 MIPS_INVAL("OPC_MXU_D32ASUM");
25890 generate_exception_end(ctx, EXCP_RI);
25891 break;
25892 default:
25893 MIPS_INVAL("decode_opc_mxu");
25894 generate_exception_end(ctx, EXCP_RI);
25895 break;
25901 * Decode MXU pool13
25903 * 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
25904 * +-----------+---+---+-------+-------+-------+-------+-----------+
25905 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
25906 * +-----------+---+---+-------+-------+-------+-------+-----------+
25909 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
25911 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25913 switch (opcode) {
25914 case OPC_MXU_Q16ACC:
25915 /* TODO: Implement emulation of Q16ACC instruction. */
25916 MIPS_INVAL("OPC_MXU_Q16ACC");
25917 generate_exception_end(ctx, EXCP_RI);
25918 break;
25919 case OPC_MXU_Q16ACCM:
25920 /* TODO: Implement emulation of Q16ACCM instruction. */
25921 MIPS_INVAL("OPC_MXU_Q16ACCM");
25922 generate_exception_end(ctx, EXCP_RI);
25923 break;
25924 case OPC_MXU_Q16ASUM:
25925 /* TODO: Implement emulation of Q16ASUM instruction. */
25926 MIPS_INVAL("OPC_MXU_Q16ASUM");
25927 generate_exception_end(ctx, EXCP_RI);
25928 break;
25929 default:
25930 MIPS_INVAL("decode_opc_mxu");
25931 generate_exception_end(ctx, EXCP_RI);
25932 break;
25938 * Decode MXU pool14
25940 * Q8ADDE, Q8ACCE:
25941 * 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
25942 * +-----------+---+---+-------+-------+-------+-------+-----------+
25943 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
25944 * +-----------+---+---+-------+-------+-------+-------+-----------+
25946 * D8SUM, D8SUMC:
25947 * 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
25948 * +-----------+---+---+-------+-------+-------+-------+-----------+
25949 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
25950 * +-----------+---+---+-------+-------+-------+-------+-----------+
25953 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
25955 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25957 switch (opcode) {
25958 case OPC_MXU_Q8ADDE:
25959 /* TODO: Implement emulation of Q8ADDE instruction. */
25960 MIPS_INVAL("OPC_MXU_Q8ADDE");
25961 generate_exception_end(ctx, EXCP_RI);
25962 break;
25963 case OPC_MXU_D8SUM:
25964 /* TODO: Implement emulation of D8SUM instruction. */
25965 MIPS_INVAL("OPC_MXU_D8SUM");
25966 generate_exception_end(ctx, EXCP_RI);
25967 break;
25968 case OPC_MXU_D8SUMC:
25969 /* TODO: Implement emulation of D8SUMC instruction. */
25970 MIPS_INVAL("OPC_MXU_D8SUMC");
25971 generate_exception_end(ctx, EXCP_RI);
25972 break;
25973 default:
25974 MIPS_INVAL("decode_opc_mxu");
25975 generate_exception_end(ctx, EXCP_RI);
25976 break;
25982 * Decode MXU pool15
25984 * S32MUL, S32MULU, S32EXTRV:
25985 * 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
25986 * +-----------+---------+---------+---+-------+-------+-----------+
25987 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
25988 * +-----------+---------+---------+---+-------+-------+-----------+
25990 * S32EXTR:
25991 * 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
25992 * +-----------+---------+---------+---+-------+-------+-----------+
25993 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
25994 * +-----------+---------+---------+---+-------+-------+-----------+
25997 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
25999 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26001 switch (opcode) {
26002 case OPC_MXU_S32MUL:
26003 /* TODO: Implement emulation of S32MUL instruction. */
26004 MIPS_INVAL("OPC_MXU_S32MUL");
26005 generate_exception_end(ctx, EXCP_RI);
26006 break;
26007 case OPC_MXU_S32MULU:
26008 /* TODO: Implement emulation of S32MULU instruction. */
26009 MIPS_INVAL("OPC_MXU_S32MULU");
26010 generate_exception_end(ctx, EXCP_RI);
26011 break;
26012 case OPC_MXU_S32EXTR:
26013 /* TODO: Implement emulation of S32EXTR instruction. */
26014 MIPS_INVAL("OPC_MXU_S32EXTR");
26015 generate_exception_end(ctx, EXCP_RI);
26016 break;
26017 case OPC_MXU_S32EXTRV:
26018 /* TODO: Implement emulation of S32EXTRV instruction. */
26019 MIPS_INVAL("OPC_MXU_S32EXTRV");
26020 generate_exception_end(ctx, EXCP_RI);
26021 break;
26022 default:
26023 MIPS_INVAL("decode_opc_mxu");
26024 generate_exception_end(ctx, EXCP_RI);
26025 break;
26031 * Decode MXU pool16
26033 * D32SARW:
26034 * 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
26035 * +-----------+---------+-----+-------+-------+-------+-----------+
26036 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26037 * +-----------+---------+-----+-------+-------+-------+-----------+
26039 * S32ALN:
26040 * 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
26041 * +-----------+---------+-----+-------+-------+-------+-----------+
26042 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26043 * +-----------+---------+-----+-------+-------+-------+-----------+
26045 * S32ALNI:
26046 * 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
26047 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26048 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26049 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26051 * S32LUI:
26052 * 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
26053 * +-----------+-----+---+-----+-------+---------------+-----------+
26054 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26055 * +-----------+-----+---+-----+-------+---------------+-----------+
26057 * S32NOR, S32AND, S32OR, S32XOR:
26058 * 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
26059 * +-----------+---------+-----+-------+-------+-------+-----------+
26060 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26061 * +-----------+---------+-----+-------+-------+-------+-----------+
26064 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26066 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26068 switch (opcode) {
26069 case OPC_MXU_D32SARW:
26070 /* TODO: Implement emulation of D32SARW instruction. */
26071 MIPS_INVAL("OPC_MXU_D32SARW");
26072 generate_exception_end(ctx, EXCP_RI);
26073 break;
26074 case OPC_MXU_S32ALN:
26075 /* TODO: Implement emulation of S32ALN instruction. */
26076 MIPS_INVAL("OPC_MXU_S32ALN");
26077 generate_exception_end(ctx, EXCP_RI);
26078 break;
26079 case OPC_MXU_S32ALNI:
26080 gen_mxu_S32ALNI(ctx);
26081 break;
26082 case OPC_MXU_S32LUI:
26083 /* TODO: Implement emulation of S32LUI instruction. */
26084 MIPS_INVAL("OPC_MXU_S32LUI");
26085 generate_exception_end(ctx, EXCP_RI);
26086 break;
26087 case OPC_MXU_S32NOR:
26088 gen_mxu_S32NOR(ctx);
26089 break;
26090 case OPC_MXU_S32AND:
26091 gen_mxu_S32AND(ctx);
26092 break;
26093 case OPC_MXU_S32OR:
26094 gen_mxu_S32OR(ctx);
26095 break;
26096 case OPC_MXU_S32XOR:
26097 gen_mxu_S32XOR(ctx);
26098 break;
26099 default:
26100 MIPS_INVAL("decode_opc_mxu");
26101 generate_exception_end(ctx, EXCP_RI);
26102 break;
26108 * Decode MXU pool17
26110 * 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
26111 * +-----------+---------+---------+---+---------+-----+-----------+
26112 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26113 * +-----------+---------+---------+---+---------+-----+-----------+
26116 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26118 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26120 switch (opcode) {
26121 case OPC_MXU_LXW:
26122 /* TODO: Implement emulation of LXW instruction. */
26123 MIPS_INVAL("OPC_MXU_LXW");
26124 generate_exception_end(ctx, EXCP_RI);
26125 break;
26126 case OPC_MXU_LXH:
26127 /* TODO: Implement emulation of LXH instruction. */
26128 MIPS_INVAL("OPC_MXU_LXH");
26129 generate_exception_end(ctx, EXCP_RI);
26130 break;
26131 case OPC_MXU_LXHU:
26132 /* TODO: Implement emulation of LXHU instruction. */
26133 MIPS_INVAL("OPC_MXU_LXHU");
26134 generate_exception_end(ctx, EXCP_RI);
26135 break;
26136 case OPC_MXU_LXB:
26137 /* TODO: Implement emulation of LXB instruction. */
26138 MIPS_INVAL("OPC_MXU_LXB");
26139 generate_exception_end(ctx, EXCP_RI);
26140 break;
26141 case OPC_MXU_LXBU:
26142 /* TODO: Implement emulation of LXBU instruction. */
26143 MIPS_INVAL("OPC_MXU_LXBU");
26144 generate_exception_end(ctx, EXCP_RI);
26145 break;
26146 default:
26147 MIPS_INVAL("decode_opc_mxu");
26148 generate_exception_end(ctx, EXCP_RI);
26149 break;
26154 * Decode MXU pool18
26156 * 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
26157 * +-----------+---------+-----+-------+-------+-------+-----------+
26158 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26159 * +-----------+---------+-----+-------+-------+-------+-----------+
26162 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26164 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26166 switch (opcode) {
26167 case OPC_MXU_D32SLLV:
26168 /* TODO: Implement emulation of D32SLLV instruction. */
26169 MIPS_INVAL("OPC_MXU_D32SLLV");
26170 generate_exception_end(ctx, EXCP_RI);
26171 break;
26172 case OPC_MXU_D32SLRV:
26173 /* TODO: Implement emulation of D32SLRV instruction. */
26174 MIPS_INVAL("OPC_MXU_D32SLRV");
26175 generate_exception_end(ctx, EXCP_RI);
26176 break;
26177 case OPC_MXU_D32SARV:
26178 /* TODO: Implement emulation of D32SARV instruction. */
26179 MIPS_INVAL("OPC_MXU_D32SARV");
26180 generate_exception_end(ctx, EXCP_RI);
26181 break;
26182 case OPC_MXU_Q16SLLV:
26183 /* TODO: Implement emulation of Q16SLLV instruction. */
26184 MIPS_INVAL("OPC_MXU_Q16SLLV");
26185 generate_exception_end(ctx, EXCP_RI);
26186 break;
26187 case OPC_MXU_Q16SLRV:
26188 /* TODO: Implement emulation of Q16SLRV instruction. */
26189 MIPS_INVAL("OPC_MXU_Q16SLRV");
26190 generate_exception_end(ctx, EXCP_RI);
26191 break;
26192 case OPC_MXU_Q16SARV:
26193 /* TODO: Implement emulation of Q16SARV instruction. */
26194 MIPS_INVAL("OPC_MXU_Q16SARV");
26195 generate_exception_end(ctx, EXCP_RI);
26196 break;
26197 default:
26198 MIPS_INVAL("decode_opc_mxu");
26199 generate_exception_end(ctx, EXCP_RI);
26200 break;
26206 * Decode MXU pool19
26208 * 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
26209 * +-----------+---+---+-------+-------+-------+-------+-----------+
26210 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26211 * +-----------+---+---+-------+-------+-------+-------+-----------+
26214 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26216 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26218 switch (opcode) {
26219 case OPC_MXU_Q8MUL:
26220 case OPC_MXU_Q8MULSU:
26221 gen_mxu_q8mul_q8mulsu(ctx);
26222 break;
26223 default:
26224 MIPS_INVAL("decode_opc_mxu");
26225 generate_exception_end(ctx, EXCP_RI);
26226 break;
26232 * Decode MXU pool20
26234 * 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
26235 * +-----------+---------+-----+-------+-------+-------+-----------+
26236 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26237 * +-----------+---------+-----+-------+-------+-------+-----------+
26240 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26242 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26244 switch (opcode) {
26245 case OPC_MXU_Q8MOVZ:
26246 /* TODO: Implement emulation of Q8MOVZ instruction. */
26247 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26248 generate_exception_end(ctx, EXCP_RI);
26249 break;
26250 case OPC_MXU_Q8MOVN:
26251 /* TODO: Implement emulation of Q8MOVN instruction. */
26252 MIPS_INVAL("OPC_MXU_Q8MOVN");
26253 generate_exception_end(ctx, EXCP_RI);
26254 break;
26255 case OPC_MXU_D16MOVZ:
26256 /* TODO: Implement emulation of D16MOVZ instruction. */
26257 MIPS_INVAL("OPC_MXU_D16MOVZ");
26258 generate_exception_end(ctx, EXCP_RI);
26259 break;
26260 case OPC_MXU_D16MOVN:
26261 /* TODO: Implement emulation of D16MOVN instruction. */
26262 MIPS_INVAL("OPC_MXU_D16MOVN");
26263 generate_exception_end(ctx, EXCP_RI);
26264 break;
26265 case OPC_MXU_S32MOVZ:
26266 /* TODO: Implement emulation of S32MOVZ instruction. */
26267 MIPS_INVAL("OPC_MXU_S32MOVZ");
26268 generate_exception_end(ctx, EXCP_RI);
26269 break;
26270 case OPC_MXU_S32MOVN:
26271 /* TODO: Implement emulation of S32MOVN instruction. */
26272 MIPS_INVAL("OPC_MXU_S32MOVN");
26273 generate_exception_end(ctx, EXCP_RI);
26274 break;
26275 default:
26276 MIPS_INVAL("decode_opc_mxu");
26277 generate_exception_end(ctx, EXCP_RI);
26278 break;
26284 * Decode MXU pool21
26286 * 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
26287 * +-----------+---+---+-------+-------+-------+-------+-----------+
26288 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26289 * +-----------+---+---+-------+-------+-------+-------+-----------+
26292 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26294 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26296 switch (opcode) {
26297 case OPC_MXU_Q8MAC:
26298 /* TODO: Implement emulation of Q8MAC instruction. */
26299 MIPS_INVAL("OPC_MXU_Q8MAC");
26300 generate_exception_end(ctx, EXCP_RI);
26301 break;
26302 case OPC_MXU_Q8MACSU:
26303 /* TODO: Implement emulation of Q8MACSU instruction. */
26304 MIPS_INVAL("OPC_MXU_Q8MACSU");
26305 generate_exception_end(ctx, EXCP_RI);
26306 break;
26307 default:
26308 MIPS_INVAL("decode_opc_mxu");
26309 generate_exception_end(ctx, EXCP_RI);
26310 break;
26316 * Main MXU decoding function
26318 * 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
26319 * +-----------+---------------------------------------+-----------+
26320 * | SPECIAL2 | |x x x x x x|
26321 * +-----------+---------------------------------------+-----------+
26324 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26327 * TODO: Investigate necessity of including handling of
26328 * CLZ, CLO, SDBB in this function, as they belong to
26329 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26331 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26333 if (opcode == OPC__MXU_MUL) {
26334 uint32_t rs, rt, rd, op1;
26336 rs = extract32(ctx->opcode, 21, 5);
26337 rt = extract32(ctx->opcode, 16, 5);
26338 rd = extract32(ctx->opcode, 11, 5);
26339 op1 = MASK_SPECIAL2(ctx->opcode);
26341 gen_arith(ctx, op1, rd, rs, rt);
26343 return;
26346 if (opcode == OPC_MXU_S32M2I) {
26347 gen_mxu_s32m2i(ctx);
26348 return;
26351 if (opcode == OPC_MXU_S32I2M) {
26352 gen_mxu_s32i2m(ctx);
26353 return;
26357 TCGv t_mxu_cr = tcg_temp_new();
26358 TCGLabel *l_exit = gen_new_label();
26360 gen_load_mxu_cr(t_mxu_cr);
26361 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26362 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26364 switch (opcode) {
26365 case OPC_MXU_S32MADD:
26366 /* TODO: Implement emulation of S32MADD instruction. */
26367 MIPS_INVAL("OPC_MXU_S32MADD");
26368 generate_exception_end(ctx, EXCP_RI);
26369 break;
26370 case OPC_MXU_S32MADDU:
26371 /* TODO: Implement emulation of S32MADDU instruction. */
26372 MIPS_INVAL("OPC_MXU_S32MADDU");
26373 generate_exception_end(ctx, EXCP_RI);
26374 break;
26375 case OPC_MXU__POOL00:
26376 decode_opc_mxu__pool00(env, ctx);
26377 break;
26378 case OPC_MXU_S32MSUB:
26379 /* TODO: Implement emulation of S32MSUB instruction. */
26380 MIPS_INVAL("OPC_MXU_S32MSUB");
26381 generate_exception_end(ctx, EXCP_RI);
26382 break;
26383 case OPC_MXU_S32MSUBU:
26384 /* TODO: Implement emulation of S32MSUBU instruction. */
26385 MIPS_INVAL("OPC_MXU_S32MSUBU");
26386 generate_exception_end(ctx, EXCP_RI);
26387 break;
26388 case OPC_MXU__POOL01:
26389 decode_opc_mxu__pool01(env, ctx);
26390 break;
26391 case OPC_MXU__POOL02:
26392 decode_opc_mxu__pool02(env, ctx);
26393 break;
26394 case OPC_MXU_D16MUL:
26395 gen_mxu_d16mul(ctx);
26396 break;
26397 case OPC_MXU__POOL03:
26398 decode_opc_mxu__pool03(env, ctx);
26399 break;
26400 case OPC_MXU_D16MAC:
26401 gen_mxu_d16mac(ctx);
26402 break;
26403 case OPC_MXU_D16MACF:
26404 /* TODO: Implement emulation of D16MACF instruction. */
26405 MIPS_INVAL("OPC_MXU_D16MACF");
26406 generate_exception_end(ctx, EXCP_RI);
26407 break;
26408 case OPC_MXU_D16MADL:
26409 /* TODO: Implement emulation of D16MADL instruction. */
26410 MIPS_INVAL("OPC_MXU_D16MADL");
26411 generate_exception_end(ctx, EXCP_RI);
26412 break;
26413 case OPC_MXU_S16MAD:
26414 /* TODO: Implement emulation of S16MAD instruction. */
26415 MIPS_INVAL("OPC_MXU_S16MAD");
26416 generate_exception_end(ctx, EXCP_RI);
26417 break;
26418 case OPC_MXU_Q16ADD:
26419 /* TODO: Implement emulation of Q16ADD instruction. */
26420 MIPS_INVAL("OPC_MXU_Q16ADD");
26421 generate_exception_end(ctx, EXCP_RI);
26422 break;
26423 case OPC_MXU_D16MACE:
26424 /* TODO: Implement emulation of D16MACE instruction. */
26425 MIPS_INVAL("OPC_MXU_D16MACE");
26426 generate_exception_end(ctx, EXCP_RI);
26427 break;
26428 case OPC_MXU__POOL04:
26429 decode_opc_mxu__pool04(env, ctx);
26430 break;
26431 case OPC_MXU__POOL05:
26432 decode_opc_mxu__pool05(env, ctx);
26433 break;
26434 case OPC_MXU__POOL06:
26435 decode_opc_mxu__pool06(env, ctx);
26436 break;
26437 case OPC_MXU__POOL07:
26438 decode_opc_mxu__pool07(env, ctx);
26439 break;
26440 case OPC_MXU__POOL08:
26441 decode_opc_mxu__pool08(env, ctx);
26442 break;
26443 case OPC_MXU__POOL09:
26444 decode_opc_mxu__pool09(env, ctx);
26445 break;
26446 case OPC_MXU__POOL10:
26447 decode_opc_mxu__pool10(env, ctx);
26448 break;
26449 case OPC_MXU__POOL11:
26450 decode_opc_mxu__pool11(env, ctx);
26451 break;
26452 case OPC_MXU_D32ADD:
26453 /* TODO: Implement emulation of D32ADD instruction. */
26454 MIPS_INVAL("OPC_MXU_D32ADD");
26455 generate_exception_end(ctx, EXCP_RI);
26456 break;
26457 case OPC_MXU__POOL12:
26458 decode_opc_mxu__pool12(env, ctx);
26459 break;
26460 case OPC_MXU__POOL13:
26461 decode_opc_mxu__pool13(env, ctx);
26462 break;
26463 case OPC_MXU__POOL14:
26464 decode_opc_mxu__pool14(env, ctx);
26465 break;
26466 case OPC_MXU_Q8ACCE:
26467 /* TODO: Implement emulation of Q8ACCE instruction. */
26468 MIPS_INVAL("OPC_MXU_Q8ACCE");
26469 generate_exception_end(ctx, EXCP_RI);
26470 break;
26471 case OPC_MXU_S8LDD:
26472 gen_mxu_s8ldd(ctx);
26473 break;
26474 case OPC_MXU_S8STD:
26475 /* TODO: Implement emulation of S8STD instruction. */
26476 MIPS_INVAL("OPC_MXU_S8STD");
26477 generate_exception_end(ctx, EXCP_RI);
26478 break;
26479 case OPC_MXU_S8LDI:
26480 /* TODO: Implement emulation of S8LDI instruction. */
26481 MIPS_INVAL("OPC_MXU_S8LDI");
26482 generate_exception_end(ctx, EXCP_RI);
26483 break;
26484 case OPC_MXU_S8SDI:
26485 /* TODO: Implement emulation of S8SDI instruction. */
26486 MIPS_INVAL("OPC_MXU_S8SDI");
26487 generate_exception_end(ctx, EXCP_RI);
26488 break;
26489 case OPC_MXU__POOL15:
26490 decode_opc_mxu__pool15(env, ctx);
26491 break;
26492 case OPC_MXU__POOL16:
26493 decode_opc_mxu__pool16(env, ctx);
26494 break;
26495 case OPC_MXU__POOL17:
26496 decode_opc_mxu__pool17(env, ctx);
26497 break;
26498 case OPC_MXU_S16LDD:
26499 /* TODO: Implement emulation of S16LDD instruction. */
26500 MIPS_INVAL("OPC_MXU_S16LDD");
26501 generate_exception_end(ctx, EXCP_RI);
26502 break;
26503 case OPC_MXU_S16STD:
26504 /* TODO: Implement emulation of S16STD instruction. */
26505 MIPS_INVAL("OPC_MXU_S16STD");
26506 generate_exception_end(ctx, EXCP_RI);
26507 break;
26508 case OPC_MXU_S16LDI:
26509 /* TODO: Implement emulation of S16LDI instruction. */
26510 MIPS_INVAL("OPC_MXU_S16LDI");
26511 generate_exception_end(ctx, EXCP_RI);
26512 break;
26513 case OPC_MXU_S16SDI:
26514 /* TODO: Implement emulation of S16SDI instruction. */
26515 MIPS_INVAL("OPC_MXU_S16SDI");
26516 generate_exception_end(ctx, EXCP_RI);
26517 break;
26518 case OPC_MXU_D32SLL:
26519 /* TODO: Implement emulation of D32SLL instruction. */
26520 MIPS_INVAL("OPC_MXU_D32SLL");
26521 generate_exception_end(ctx, EXCP_RI);
26522 break;
26523 case OPC_MXU_D32SLR:
26524 /* TODO: Implement emulation of D32SLR instruction. */
26525 MIPS_INVAL("OPC_MXU_D32SLR");
26526 generate_exception_end(ctx, EXCP_RI);
26527 break;
26528 case OPC_MXU_D32SARL:
26529 /* TODO: Implement emulation of D32SARL instruction. */
26530 MIPS_INVAL("OPC_MXU_D32SARL");
26531 generate_exception_end(ctx, EXCP_RI);
26532 break;
26533 case OPC_MXU_D32SAR:
26534 /* TODO: Implement emulation of D32SAR instruction. */
26535 MIPS_INVAL("OPC_MXU_D32SAR");
26536 generate_exception_end(ctx, EXCP_RI);
26537 break;
26538 case OPC_MXU_Q16SLL:
26539 /* TODO: Implement emulation of Q16SLL instruction. */
26540 MIPS_INVAL("OPC_MXU_Q16SLL");
26541 generate_exception_end(ctx, EXCP_RI);
26542 break;
26543 case OPC_MXU_Q16SLR:
26544 /* TODO: Implement emulation of Q16SLR instruction. */
26545 MIPS_INVAL("OPC_MXU_Q16SLR");
26546 generate_exception_end(ctx, EXCP_RI);
26547 break;
26548 case OPC_MXU__POOL18:
26549 decode_opc_mxu__pool18(env, ctx);
26550 break;
26551 case OPC_MXU_Q16SAR:
26552 /* TODO: Implement emulation of Q16SAR instruction. */
26553 MIPS_INVAL("OPC_MXU_Q16SAR");
26554 generate_exception_end(ctx, EXCP_RI);
26555 break;
26556 case OPC_MXU__POOL19:
26557 decode_opc_mxu__pool19(env, ctx);
26558 break;
26559 case OPC_MXU__POOL20:
26560 decode_opc_mxu__pool20(env, ctx);
26561 break;
26562 case OPC_MXU__POOL21:
26563 decode_opc_mxu__pool21(env, ctx);
26564 break;
26565 case OPC_MXU_Q16SCOP:
26566 /* TODO: Implement emulation of Q16SCOP instruction. */
26567 MIPS_INVAL("OPC_MXU_Q16SCOP");
26568 generate_exception_end(ctx, EXCP_RI);
26569 break;
26570 case OPC_MXU_Q8MADL:
26571 /* TODO: Implement emulation of Q8MADL instruction. */
26572 MIPS_INVAL("OPC_MXU_Q8MADL");
26573 generate_exception_end(ctx, EXCP_RI);
26574 break;
26575 case OPC_MXU_S32SFL:
26576 /* TODO: Implement emulation of S32SFL instruction. */
26577 MIPS_INVAL("OPC_MXU_S32SFL");
26578 generate_exception_end(ctx, EXCP_RI);
26579 break;
26580 case OPC_MXU_Q8SAD:
26581 /* TODO: Implement emulation of Q8SAD instruction. */
26582 MIPS_INVAL("OPC_MXU_Q8SAD");
26583 generate_exception_end(ctx, EXCP_RI);
26584 break;
26585 default:
26586 MIPS_INVAL("decode_opc_mxu");
26587 generate_exception_end(ctx, EXCP_RI);
26590 gen_set_label(l_exit);
26591 tcg_temp_free(t_mxu_cr);
26595 #endif /* !defined(TARGET_MIPS64) */
26598 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26600 int rs, rt, rd;
26601 uint32_t op1;
26603 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26605 rs = (ctx->opcode >> 21) & 0x1f;
26606 rt = (ctx->opcode >> 16) & 0x1f;
26607 rd = (ctx->opcode >> 11) & 0x1f;
26609 op1 = MASK_SPECIAL2(ctx->opcode);
26610 switch (op1) {
26611 case OPC_MADD: /* Multiply and add/sub */
26612 case OPC_MADDU:
26613 case OPC_MSUB:
26614 case OPC_MSUBU:
26615 check_insn(ctx, ISA_MIPS32);
26616 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26617 break;
26618 case OPC_MUL:
26619 gen_arith(ctx, op1, rd, rs, rt);
26620 break;
26621 case OPC_DIV_G_2F:
26622 case OPC_DIVU_G_2F:
26623 case OPC_MULT_G_2F:
26624 case OPC_MULTU_G_2F:
26625 case OPC_MOD_G_2F:
26626 case OPC_MODU_G_2F:
26627 check_insn(ctx, INSN_LOONGSON2F);
26628 gen_loongson_integer(ctx, op1, rd, rs, rt);
26629 break;
26630 case OPC_CLO:
26631 case OPC_CLZ:
26632 check_insn(ctx, ISA_MIPS32);
26633 gen_cl(ctx, op1, rd, rs);
26634 break;
26635 case OPC_SDBBP:
26636 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26637 gen_helper_do_semihosting(cpu_env);
26638 } else {
26639 /* XXX: not clear which exception should be raised
26640 * when in debug mode...
26642 check_insn(ctx, ISA_MIPS32);
26643 generate_exception_end(ctx, EXCP_DBp);
26645 break;
26646 #if defined(TARGET_MIPS64)
26647 case OPC_DCLO:
26648 case OPC_DCLZ:
26649 check_insn(ctx, ISA_MIPS64);
26650 check_mips_64(ctx);
26651 gen_cl(ctx, op1, rd, rs);
26652 break;
26653 case OPC_DMULT_G_2F:
26654 case OPC_DMULTU_G_2F:
26655 case OPC_DDIV_G_2F:
26656 case OPC_DDIVU_G_2F:
26657 case OPC_DMOD_G_2F:
26658 case OPC_DMODU_G_2F:
26659 check_insn(ctx, INSN_LOONGSON2F);
26660 gen_loongson_integer(ctx, op1, rd, rs, rt);
26661 break;
26662 #endif
26663 default: /* Invalid */
26664 MIPS_INVAL("special2_legacy");
26665 generate_exception_end(ctx, EXCP_RI);
26666 break;
26670 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26672 int rs, rt, rd, sa;
26673 uint32_t op1, op2;
26674 int16_t imm;
26676 rs = (ctx->opcode >> 21) & 0x1f;
26677 rt = (ctx->opcode >> 16) & 0x1f;
26678 rd = (ctx->opcode >> 11) & 0x1f;
26679 sa = (ctx->opcode >> 6) & 0x1f;
26680 imm = (int16_t)ctx->opcode >> 7;
26682 op1 = MASK_SPECIAL3(ctx->opcode);
26683 switch (op1) {
26684 case R6_OPC_PREF:
26685 if (rt >= 24) {
26686 /* hint codes 24-31 are reserved and signal RI */
26687 generate_exception_end(ctx, EXCP_RI);
26689 /* Treat as NOP. */
26690 break;
26691 case R6_OPC_CACHE:
26692 check_cp0_enabled(ctx);
26693 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26694 gen_cache_operation(ctx, rt, rs, imm);
26696 break;
26697 case R6_OPC_SC:
26698 gen_st_cond(ctx, op1, rt, rs, imm);
26699 break;
26700 case R6_OPC_LL:
26701 gen_ld(ctx, op1, rt, rs, imm);
26702 break;
26703 case OPC_BSHFL:
26705 if (rd == 0) {
26706 /* Treat as NOP. */
26707 break;
26709 op2 = MASK_BSHFL(ctx->opcode);
26710 switch (op2) {
26711 case OPC_ALIGN:
26712 case OPC_ALIGN_1:
26713 case OPC_ALIGN_2:
26714 case OPC_ALIGN_3:
26715 gen_align(ctx, 32, rd, rs, rt, sa & 3);
26716 break;
26717 case OPC_BITSWAP:
26718 gen_bitswap(ctx, op2, rd, rt);
26719 break;
26722 break;
26723 #if defined(TARGET_MIPS64)
26724 case R6_OPC_SCD:
26725 gen_st_cond(ctx, op1, rt, rs, imm);
26726 break;
26727 case R6_OPC_LLD:
26728 gen_ld(ctx, op1, rt, rs, imm);
26729 break;
26730 case OPC_DBSHFL:
26731 check_mips_64(ctx);
26733 if (rd == 0) {
26734 /* Treat as NOP. */
26735 break;
26737 op2 = MASK_DBSHFL(ctx->opcode);
26738 switch (op2) {
26739 case OPC_DALIGN:
26740 case OPC_DALIGN_1:
26741 case OPC_DALIGN_2:
26742 case OPC_DALIGN_3:
26743 case OPC_DALIGN_4:
26744 case OPC_DALIGN_5:
26745 case OPC_DALIGN_6:
26746 case OPC_DALIGN_7:
26747 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26748 break;
26749 case OPC_DBITSWAP:
26750 gen_bitswap(ctx, op2, rd, rt);
26751 break;
26755 break;
26756 #endif
26757 default: /* Invalid */
26758 MIPS_INVAL("special3_r6");
26759 generate_exception_end(ctx, EXCP_RI);
26760 break;
26764 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26766 int rs, rt, rd;
26767 uint32_t op1, op2;
26769 rs = (ctx->opcode >> 21) & 0x1f;
26770 rt = (ctx->opcode >> 16) & 0x1f;
26771 rd = (ctx->opcode >> 11) & 0x1f;
26773 op1 = MASK_SPECIAL3(ctx->opcode);
26774 switch (op1) {
26775 case OPC_DIV_G_2E:
26776 case OPC_DIVU_G_2E:
26777 case OPC_MOD_G_2E:
26778 case OPC_MODU_G_2E:
26779 case OPC_MULT_G_2E:
26780 case OPC_MULTU_G_2E:
26781 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26782 * the same mask and op1. */
26783 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26784 op2 = MASK_ADDUH_QB(ctx->opcode);
26785 switch (op2) {
26786 case OPC_ADDUH_QB:
26787 case OPC_ADDUH_R_QB:
26788 case OPC_ADDQH_PH:
26789 case OPC_ADDQH_R_PH:
26790 case OPC_ADDQH_W:
26791 case OPC_ADDQH_R_W:
26792 case OPC_SUBUH_QB:
26793 case OPC_SUBUH_R_QB:
26794 case OPC_SUBQH_PH:
26795 case OPC_SUBQH_R_PH:
26796 case OPC_SUBQH_W:
26797 case OPC_SUBQH_R_W:
26798 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26799 break;
26800 case OPC_MUL_PH:
26801 case OPC_MUL_S_PH:
26802 case OPC_MULQ_S_W:
26803 case OPC_MULQ_RS_W:
26804 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26805 break;
26806 default:
26807 MIPS_INVAL("MASK ADDUH.QB");
26808 generate_exception_end(ctx, EXCP_RI);
26809 break;
26811 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26812 gen_loongson_integer(ctx, op1, rd, rs, rt);
26813 } else {
26814 generate_exception_end(ctx, EXCP_RI);
26816 break;
26817 case OPC_LX_DSP:
26818 op2 = MASK_LX(ctx->opcode);
26819 switch (op2) {
26820 #if defined(TARGET_MIPS64)
26821 case OPC_LDX:
26822 #endif
26823 case OPC_LBUX:
26824 case OPC_LHX:
26825 case OPC_LWX:
26826 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26827 break;
26828 default: /* Invalid */
26829 MIPS_INVAL("MASK LX");
26830 generate_exception_end(ctx, EXCP_RI);
26831 break;
26833 break;
26834 case OPC_ABSQ_S_PH_DSP:
26835 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26836 switch (op2) {
26837 case OPC_ABSQ_S_QB:
26838 case OPC_ABSQ_S_PH:
26839 case OPC_ABSQ_S_W:
26840 case OPC_PRECEQ_W_PHL:
26841 case OPC_PRECEQ_W_PHR:
26842 case OPC_PRECEQU_PH_QBL:
26843 case OPC_PRECEQU_PH_QBR:
26844 case OPC_PRECEQU_PH_QBLA:
26845 case OPC_PRECEQU_PH_QBRA:
26846 case OPC_PRECEU_PH_QBL:
26847 case OPC_PRECEU_PH_QBR:
26848 case OPC_PRECEU_PH_QBLA:
26849 case OPC_PRECEU_PH_QBRA:
26850 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26851 break;
26852 case OPC_BITREV:
26853 case OPC_REPL_QB:
26854 case OPC_REPLV_QB:
26855 case OPC_REPL_PH:
26856 case OPC_REPLV_PH:
26857 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26858 break;
26859 default:
26860 MIPS_INVAL("MASK ABSQ_S.PH");
26861 generate_exception_end(ctx, EXCP_RI);
26862 break;
26864 break;
26865 case OPC_ADDU_QB_DSP:
26866 op2 = MASK_ADDU_QB(ctx->opcode);
26867 switch (op2) {
26868 case OPC_ADDQ_PH:
26869 case OPC_ADDQ_S_PH:
26870 case OPC_ADDQ_S_W:
26871 case OPC_ADDU_QB:
26872 case OPC_ADDU_S_QB:
26873 case OPC_ADDU_PH:
26874 case OPC_ADDU_S_PH:
26875 case OPC_SUBQ_PH:
26876 case OPC_SUBQ_S_PH:
26877 case OPC_SUBQ_S_W:
26878 case OPC_SUBU_QB:
26879 case OPC_SUBU_S_QB:
26880 case OPC_SUBU_PH:
26881 case OPC_SUBU_S_PH:
26882 case OPC_ADDSC:
26883 case OPC_ADDWC:
26884 case OPC_MODSUB:
26885 case OPC_RADDU_W_QB:
26886 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26887 break;
26888 case OPC_MULEU_S_PH_QBL:
26889 case OPC_MULEU_S_PH_QBR:
26890 case OPC_MULQ_RS_PH:
26891 case OPC_MULEQ_S_W_PHL:
26892 case OPC_MULEQ_S_W_PHR:
26893 case OPC_MULQ_S_PH:
26894 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26895 break;
26896 default: /* Invalid */
26897 MIPS_INVAL("MASK ADDU.QB");
26898 generate_exception_end(ctx, EXCP_RI);
26899 break;
26902 break;
26903 case OPC_CMPU_EQ_QB_DSP:
26904 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26905 switch (op2) {
26906 case OPC_PRECR_SRA_PH_W:
26907 case OPC_PRECR_SRA_R_PH_W:
26908 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26909 break;
26910 case OPC_PRECR_QB_PH:
26911 case OPC_PRECRQ_QB_PH:
26912 case OPC_PRECRQ_PH_W:
26913 case OPC_PRECRQ_RS_PH_W:
26914 case OPC_PRECRQU_S_QB_PH:
26915 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26916 break;
26917 case OPC_CMPU_EQ_QB:
26918 case OPC_CMPU_LT_QB:
26919 case OPC_CMPU_LE_QB:
26920 case OPC_CMP_EQ_PH:
26921 case OPC_CMP_LT_PH:
26922 case OPC_CMP_LE_PH:
26923 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26924 break;
26925 case OPC_CMPGU_EQ_QB:
26926 case OPC_CMPGU_LT_QB:
26927 case OPC_CMPGU_LE_QB:
26928 case OPC_CMPGDU_EQ_QB:
26929 case OPC_CMPGDU_LT_QB:
26930 case OPC_CMPGDU_LE_QB:
26931 case OPC_PICK_QB:
26932 case OPC_PICK_PH:
26933 case OPC_PACKRL_PH:
26934 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26935 break;
26936 default: /* Invalid */
26937 MIPS_INVAL("MASK CMPU.EQ.QB");
26938 generate_exception_end(ctx, EXCP_RI);
26939 break;
26941 break;
26942 case OPC_SHLL_QB_DSP:
26943 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26944 break;
26945 case OPC_DPA_W_PH_DSP:
26946 op2 = MASK_DPA_W_PH(ctx->opcode);
26947 switch (op2) {
26948 case OPC_DPAU_H_QBL:
26949 case OPC_DPAU_H_QBR:
26950 case OPC_DPSU_H_QBL:
26951 case OPC_DPSU_H_QBR:
26952 case OPC_DPA_W_PH:
26953 case OPC_DPAX_W_PH:
26954 case OPC_DPAQ_S_W_PH:
26955 case OPC_DPAQX_S_W_PH:
26956 case OPC_DPAQX_SA_W_PH:
26957 case OPC_DPS_W_PH:
26958 case OPC_DPSX_W_PH:
26959 case OPC_DPSQ_S_W_PH:
26960 case OPC_DPSQX_S_W_PH:
26961 case OPC_DPSQX_SA_W_PH:
26962 case OPC_MULSAQ_S_W_PH:
26963 case OPC_DPAQ_SA_L_W:
26964 case OPC_DPSQ_SA_L_W:
26965 case OPC_MAQ_S_W_PHL:
26966 case OPC_MAQ_S_W_PHR:
26967 case OPC_MAQ_SA_W_PHL:
26968 case OPC_MAQ_SA_W_PHR:
26969 case OPC_MULSA_W_PH:
26970 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26971 break;
26972 default: /* Invalid */
26973 MIPS_INVAL("MASK DPAW.PH");
26974 generate_exception_end(ctx, EXCP_RI);
26975 break;
26977 break;
26978 case OPC_INSV_DSP:
26979 op2 = MASK_INSV(ctx->opcode);
26980 switch (op2) {
26981 case OPC_INSV:
26982 check_dsp(ctx);
26984 TCGv t0, t1;
26986 if (rt == 0) {
26987 break;
26990 t0 = tcg_temp_new();
26991 t1 = tcg_temp_new();
26993 gen_load_gpr(t0, rt);
26994 gen_load_gpr(t1, rs);
26996 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
26998 tcg_temp_free(t0);
26999 tcg_temp_free(t1);
27000 break;
27002 default: /* Invalid */
27003 MIPS_INVAL("MASK INSV");
27004 generate_exception_end(ctx, EXCP_RI);
27005 break;
27007 break;
27008 case OPC_APPEND_DSP:
27009 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27010 break;
27011 case OPC_EXTR_W_DSP:
27012 op2 = MASK_EXTR_W(ctx->opcode);
27013 switch (op2) {
27014 case OPC_EXTR_W:
27015 case OPC_EXTR_R_W:
27016 case OPC_EXTR_RS_W:
27017 case OPC_EXTR_S_H:
27018 case OPC_EXTRV_S_H:
27019 case OPC_EXTRV_W:
27020 case OPC_EXTRV_R_W:
27021 case OPC_EXTRV_RS_W:
27022 case OPC_EXTP:
27023 case OPC_EXTPV:
27024 case OPC_EXTPDP:
27025 case OPC_EXTPDPV:
27026 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27027 break;
27028 case OPC_RDDSP:
27029 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27030 break;
27031 case OPC_SHILO:
27032 case OPC_SHILOV:
27033 case OPC_MTHLIP:
27034 case OPC_WRDSP:
27035 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27036 break;
27037 default: /* Invalid */
27038 MIPS_INVAL("MASK EXTR.W");
27039 generate_exception_end(ctx, EXCP_RI);
27040 break;
27042 break;
27043 #if defined(TARGET_MIPS64)
27044 case OPC_DDIV_G_2E:
27045 case OPC_DDIVU_G_2E:
27046 case OPC_DMULT_G_2E:
27047 case OPC_DMULTU_G_2E:
27048 case OPC_DMOD_G_2E:
27049 case OPC_DMODU_G_2E:
27050 check_insn(ctx, INSN_LOONGSON2E);
27051 gen_loongson_integer(ctx, op1, rd, rs, rt);
27052 break;
27053 case OPC_ABSQ_S_QH_DSP:
27054 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27055 switch (op2) {
27056 case OPC_PRECEQ_L_PWL:
27057 case OPC_PRECEQ_L_PWR:
27058 case OPC_PRECEQ_PW_QHL:
27059 case OPC_PRECEQ_PW_QHR:
27060 case OPC_PRECEQ_PW_QHLA:
27061 case OPC_PRECEQ_PW_QHRA:
27062 case OPC_PRECEQU_QH_OBL:
27063 case OPC_PRECEQU_QH_OBR:
27064 case OPC_PRECEQU_QH_OBLA:
27065 case OPC_PRECEQU_QH_OBRA:
27066 case OPC_PRECEU_QH_OBL:
27067 case OPC_PRECEU_QH_OBR:
27068 case OPC_PRECEU_QH_OBLA:
27069 case OPC_PRECEU_QH_OBRA:
27070 case OPC_ABSQ_S_OB:
27071 case OPC_ABSQ_S_PW:
27072 case OPC_ABSQ_S_QH:
27073 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27074 break;
27075 case OPC_REPL_OB:
27076 case OPC_REPL_PW:
27077 case OPC_REPL_QH:
27078 case OPC_REPLV_OB:
27079 case OPC_REPLV_PW:
27080 case OPC_REPLV_QH:
27081 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27082 break;
27083 default: /* Invalid */
27084 MIPS_INVAL("MASK ABSQ_S.QH");
27085 generate_exception_end(ctx, EXCP_RI);
27086 break;
27088 break;
27089 case OPC_ADDU_OB_DSP:
27090 op2 = MASK_ADDU_OB(ctx->opcode);
27091 switch (op2) {
27092 case OPC_RADDU_L_OB:
27093 case OPC_SUBQ_PW:
27094 case OPC_SUBQ_S_PW:
27095 case OPC_SUBQ_QH:
27096 case OPC_SUBQ_S_QH:
27097 case OPC_SUBU_OB:
27098 case OPC_SUBU_S_OB:
27099 case OPC_SUBU_QH:
27100 case OPC_SUBU_S_QH:
27101 case OPC_SUBUH_OB:
27102 case OPC_SUBUH_R_OB:
27103 case OPC_ADDQ_PW:
27104 case OPC_ADDQ_S_PW:
27105 case OPC_ADDQ_QH:
27106 case OPC_ADDQ_S_QH:
27107 case OPC_ADDU_OB:
27108 case OPC_ADDU_S_OB:
27109 case OPC_ADDU_QH:
27110 case OPC_ADDU_S_QH:
27111 case OPC_ADDUH_OB:
27112 case OPC_ADDUH_R_OB:
27113 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27114 break;
27115 case OPC_MULEQ_S_PW_QHL:
27116 case OPC_MULEQ_S_PW_QHR:
27117 case OPC_MULEU_S_QH_OBL:
27118 case OPC_MULEU_S_QH_OBR:
27119 case OPC_MULQ_RS_QH:
27120 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27121 break;
27122 default: /* Invalid */
27123 MIPS_INVAL("MASK ADDU.OB");
27124 generate_exception_end(ctx, EXCP_RI);
27125 break;
27127 break;
27128 case OPC_CMPU_EQ_OB_DSP:
27129 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27130 switch (op2) {
27131 case OPC_PRECR_SRA_QH_PW:
27132 case OPC_PRECR_SRA_R_QH_PW:
27133 /* Return value is rt. */
27134 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27135 break;
27136 case OPC_PRECR_OB_QH:
27137 case OPC_PRECRQ_OB_QH:
27138 case OPC_PRECRQ_PW_L:
27139 case OPC_PRECRQ_QH_PW:
27140 case OPC_PRECRQ_RS_QH_PW:
27141 case OPC_PRECRQU_S_OB_QH:
27142 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27143 break;
27144 case OPC_CMPU_EQ_OB:
27145 case OPC_CMPU_LT_OB:
27146 case OPC_CMPU_LE_OB:
27147 case OPC_CMP_EQ_QH:
27148 case OPC_CMP_LT_QH:
27149 case OPC_CMP_LE_QH:
27150 case OPC_CMP_EQ_PW:
27151 case OPC_CMP_LT_PW:
27152 case OPC_CMP_LE_PW:
27153 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27154 break;
27155 case OPC_CMPGDU_EQ_OB:
27156 case OPC_CMPGDU_LT_OB:
27157 case OPC_CMPGDU_LE_OB:
27158 case OPC_CMPGU_EQ_OB:
27159 case OPC_CMPGU_LT_OB:
27160 case OPC_CMPGU_LE_OB:
27161 case OPC_PACKRL_PW:
27162 case OPC_PICK_OB:
27163 case OPC_PICK_PW:
27164 case OPC_PICK_QH:
27165 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27166 break;
27167 default: /* Invalid */
27168 MIPS_INVAL("MASK CMPU_EQ.OB");
27169 generate_exception_end(ctx, EXCP_RI);
27170 break;
27172 break;
27173 case OPC_DAPPEND_DSP:
27174 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27175 break;
27176 case OPC_DEXTR_W_DSP:
27177 op2 = MASK_DEXTR_W(ctx->opcode);
27178 switch (op2) {
27179 case OPC_DEXTP:
27180 case OPC_DEXTPDP:
27181 case OPC_DEXTPDPV:
27182 case OPC_DEXTPV:
27183 case OPC_DEXTR_L:
27184 case OPC_DEXTR_R_L:
27185 case OPC_DEXTR_RS_L:
27186 case OPC_DEXTR_W:
27187 case OPC_DEXTR_R_W:
27188 case OPC_DEXTR_RS_W:
27189 case OPC_DEXTR_S_H:
27190 case OPC_DEXTRV_L:
27191 case OPC_DEXTRV_R_L:
27192 case OPC_DEXTRV_RS_L:
27193 case OPC_DEXTRV_S_H:
27194 case OPC_DEXTRV_W:
27195 case OPC_DEXTRV_R_W:
27196 case OPC_DEXTRV_RS_W:
27197 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27198 break;
27199 case OPC_DMTHLIP:
27200 case OPC_DSHILO:
27201 case OPC_DSHILOV:
27202 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27203 break;
27204 default: /* Invalid */
27205 MIPS_INVAL("MASK EXTR.W");
27206 generate_exception_end(ctx, EXCP_RI);
27207 break;
27209 break;
27210 case OPC_DPAQ_W_QH_DSP:
27211 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27212 switch (op2) {
27213 case OPC_DPAU_H_OBL:
27214 case OPC_DPAU_H_OBR:
27215 case OPC_DPSU_H_OBL:
27216 case OPC_DPSU_H_OBR:
27217 case OPC_DPA_W_QH:
27218 case OPC_DPAQ_S_W_QH:
27219 case OPC_DPS_W_QH:
27220 case OPC_DPSQ_S_W_QH:
27221 case OPC_MULSAQ_S_W_QH:
27222 case OPC_DPAQ_SA_L_PW:
27223 case OPC_DPSQ_SA_L_PW:
27224 case OPC_MULSAQ_S_L_PW:
27225 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27226 break;
27227 case OPC_MAQ_S_W_QHLL:
27228 case OPC_MAQ_S_W_QHLR:
27229 case OPC_MAQ_S_W_QHRL:
27230 case OPC_MAQ_S_W_QHRR:
27231 case OPC_MAQ_SA_W_QHLL:
27232 case OPC_MAQ_SA_W_QHLR:
27233 case OPC_MAQ_SA_W_QHRL:
27234 case OPC_MAQ_SA_W_QHRR:
27235 case OPC_MAQ_S_L_PWL:
27236 case OPC_MAQ_S_L_PWR:
27237 case OPC_DMADD:
27238 case OPC_DMADDU:
27239 case OPC_DMSUB:
27240 case OPC_DMSUBU:
27241 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27242 break;
27243 default: /* Invalid */
27244 MIPS_INVAL("MASK DPAQ.W.QH");
27245 generate_exception_end(ctx, EXCP_RI);
27246 break;
27248 break;
27249 case OPC_DINSV_DSP:
27250 op2 = MASK_INSV(ctx->opcode);
27251 switch (op2) {
27252 case OPC_DINSV:
27254 TCGv t0, t1;
27256 if (rt == 0) {
27257 break;
27259 check_dsp(ctx);
27261 t0 = tcg_temp_new();
27262 t1 = tcg_temp_new();
27264 gen_load_gpr(t0, rt);
27265 gen_load_gpr(t1, rs);
27267 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27269 tcg_temp_free(t0);
27270 tcg_temp_free(t1);
27271 break;
27273 default: /* Invalid */
27274 MIPS_INVAL("MASK DINSV");
27275 generate_exception_end(ctx, EXCP_RI);
27276 break;
27278 break;
27279 case OPC_SHLL_OB_DSP:
27280 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27281 break;
27282 #endif
27283 default: /* Invalid */
27284 MIPS_INVAL("special3_legacy");
27285 generate_exception_end(ctx, EXCP_RI);
27286 break;
27290 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27292 uint32_t opc = MASK_MMI0(ctx->opcode);
27294 switch (opc) {
27295 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27296 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27297 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27298 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27299 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27300 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27301 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27302 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27303 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27304 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27305 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27306 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27307 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27308 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27309 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27310 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27311 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27312 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27313 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27314 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27315 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27316 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27317 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27318 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27319 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27320 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27321 break;
27322 default:
27323 MIPS_INVAL("TX79 MMI class MMI0");
27324 generate_exception_end(ctx, EXCP_RI);
27325 break;
27329 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27331 uint32_t opc = MASK_MMI1(ctx->opcode);
27333 switch (opc) {
27334 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27335 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27336 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27337 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27338 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27339 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27340 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27341 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27342 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27343 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27344 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27345 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27346 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27347 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27348 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27349 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27350 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27351 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27352 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27353 break;
27354 default:
27355 MIPS_INVAL("TX79 MMI class MMI1");
27356 generate_exception_end(ctx, EXCP_RI);
27357 break;
27361 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27363 uint32_t opc = MASK_MMI2(ctx->opcode);
27365 switch (opc) {
27366 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27367 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27368 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27369 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27370 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27371 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27372 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27373 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27374 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27375 case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */
27376 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27377 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27378 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27379 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27380 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27381 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27382 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27383 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27384 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27385 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27386 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27387 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27388 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27389 break;
27390 default:
27391 MIPS_INVAL("TX79 MMI class MMI2");
27392 generate_exception_end(ctx, EXCP_RI);
27393 break;
27397 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27399 uint32_t opc = MASK_MMI3(ctx->opcode);
27401 switch (opc) {
27402 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27403 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27404 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27405 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27406 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27407 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27408 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27409 case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */
27410 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27411 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27412 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27413 case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */
27414 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27415 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27416 break;
27417 default:
27418 MIPS_INVAL("TX79 MMI class MMI3");
27419 generate_exception_end(ctx, EXCP_RI);
27420 break;
27424 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27426 uint32_t opc = MASK_MMI(ctx->opcode);
27427 int rs = extract32(ctx->opcode, 21, 5);
27428 int rt = extract32(ctx->opcode, 16, 5);
27429 int rd = extract32(ctx->opcode, 11, 5);
27431 switch (opc) {
27432 case MMI_OPC_CLASS_MMI0:
27433 decode_mmi0(env, ctx);
27434 break;
27435 case MMI_OPC_CLASS_MMI1:
27436 decode_mmi1(env, ctx);
27437 break;
27438 case MMI_OPC_CLASS_MMI2:
27439 decode_mmi2(env, ctx);
27440 break;
27441 case MMI_OPC_CLASS_MMI3:
27442 decode_mmi3(env, ctx);
27443 break;
27444 case MMI_OPC_MULT1:
27445 case MMI_OPC_MULTU1:
27446 case MMI_OPC_MADD:
27447 case MMI_OPC_MADDU:
27448 case MMI_OPC_MADD1:
27449 case MMI_OPC_MADDU1:
27450 gen_mul_txx9(ctx, opc, rd, rs, rt);
27451 break;
27452 case MMI_OPC_DIV1:
27453 case MMI_OPC_DIVU1:
27454 gen_div1_tx79(ctx, opc, rs, rt);
27455 break;
27456 case MMI_OPC_MTLO1:
27457 case MMI_OPC_MTHI1:
27458 gen_HILO1_tx79(ctx, opc, rs);
27459 break;
27460 case MMI_OPC_MFLO1:
27461 case MMI_OPC_MFHI1:
27462 gen_HILO1_tx79(ctx, opc, rd);
27463 break;
27464 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27465 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27466 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27467 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27468 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27469 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27470 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27471 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27472 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27473 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27474 break;
27475 default:
27476 MIPS_INVAL("TX79 MMI class");
27477 generate_exception_end(ctx, EXCP_RI);
27478 break;
27482 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27484 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27487 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27489 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27493 * The TX79-specific instruction Store Quadword
27495 * +--------+-------+-------+------------------------+
27496 * | 011111 | base | rt | offset | SQ
27497 * +--------+-------+-------+------------------------+
27498 * 6 5 5 16
27500 * has the same opcode as the Read Hardware Register instruction
27502 * +--------+-------+-------+-------+-------+--------+
27503 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27504 * +--------+-------+-------+-------+-------+--------+
27505 * 6 5 5 5 5 6
27507 * that is required, trapped and emulated by the Linux kernel. However, all
27508 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27509 * offset is odd. Therefore all valid SQ instructions can execute normally.
27510 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27511 * between SQ and RDHWR, as the Linux kernel does.
27513 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27515 int base = extract32(ctx->opcode, 21, 5);
27516 int rt = extract32(ctx->opcode, 16, 5);
27517 int offset = extract32(ctx->opcode, 0, 16);
27519 #ifdef CONFIG_USER_ONLY
27520 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27521 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27523 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27524 int rd = extract32(ctx->opcode, 11, 5);
27526 gen_rdhwr(ctx, rt, rd, 0);
27527 return;
27529 #endif
27531 gen_mmi_sq(ctx, base, rt, offset);
27534 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27536 int rs, rt, rd, sa;
27537 uint32_t op1, op2;
27538 int16_t imm;
27540 rs = (ctx->opcode >> 21) & 0x1f;
27541 rt = (ctx->opcode >> 16) & 0x1f;
27542 rd = (ctx->opcode >> 11) & 0x1f;
27543 sa = (ctx->opcode >> 6) & 0x1f;
27544 imm = sextract32(ctx->opcode, 7, 9);
27546 op1 = MASK_SPECIAL3(ctx->opcode);
27549 * EVA loads and stores overlap Loongson 2E instructions decoded by
27550 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27551 * EVA is absent.
27553 if (ctx->eva) {
27554 switch (op1) {
27555 case OPC_LWLE:
27556 case OPC_LWRE:
27557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27558 /* fall through */
27559 case OPC_LBUE:
27560 case OPC_LHUE:
27561 case OPC_LBE:
27562 case OPC_LHE:
27563 case OPC_LLE:
27564 case OPC_LWE:
27565 check_cp0_enabled(ctx);
27566 gen_ld(ctx, op1, rt, rs, imm);
27567 return;
27568 case OPC_SWLE:
27569 case OPC_SWRE:
27570 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27571 /* fall through */
27572 case OPC_SBE:
27573 case OPC_SHE:
27574 case OPC_SWE:
27575 check_cp0_enabled(ctx);
27576 gen_st(ctx, op1, rt, rs, imm);
27577 return;
27578 case OPC_SCE:
27579 check_cp0_enabled(ctx);
27580 gen_st_cond(ctx, op1, rt, rs, imm);
27581 return;
27582 case OPC_CACHEE:
27583 check_cp0_enabled(ctx);
27584 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27585 gen_cache_operation(ctx, rt, rs, imm);
27587 /* Treat as NOP. */
27588 return;
27589 case OPC_PREFE:
27590 check_cp0_enabled(ctx);
27591 /* Treat as NOP. */
27592 return;
27596 switch (op1) {
27597 case OPC_EXT:
27598 case OPC_INS:
27599 check_insn(ctx, ISA_MIPS32R2);
27600 gen_bitops(ctx, op1, rt, rs, sa, rd);
27601 break;
27602 case OPC_BSHFL:
27603 op2 = MASK_BSHFL(ctx->opcode);
27604 switch (op2) {
27605 case OPC_ALIGN:
27606 case OPC_ALIGN_1:
27607 case OPC_ALIGN_2:
27608 case OPC_ALIGN_3:
27609 case OPC_BITSWAP:
27610 check_insn(ctx, ISA_MIPS32R6);
27611 decode_opc_special3_r6(env, ctx);
27612 break;
27613 default:
27614 check_insn(ctx, ISA_MIPS32R2);
27615 gen_bshfl(ctx, op2, rt, rd);
27616 break;
27618 break;
27619 #if defined(TARGET_MIPS64)
27620 case OPC_DEXTM:
27621 case OPC_DEXTU:
27622 case OPC_DEXT:
27623 case OPC_DINSM:
27624 case OPC_DINSU:
27625 case OPC_DINS:
27626 check_insn(ctx, ISA_MIPS64R2);
27627 check_mips_64(ctx);
27628 gen_bitops(ctx, op1, rt, rs, sa, rd);
27629 break;
27630 case OPC_DBSHFL:
27631 op2 = MASK_DBSHFL(ctx->opcode);
27632 switch (op2) {
27633 case OPC_DALIGN:
27634 case OPC_DALIGN_1:
27635 case OPC_DALIGN_2:
27636 case OPC_DALIGN_3:
27637 case OPC_DALIGN_4:
27638 case OPC_DALIGN_5:
27639 case OPC_DALIGN_6:
27640 case OPC_DALIGN_7:
27641 case OPC_DBITSWAP:
27642 check_insn(ctx, ISA_MIPS32R6);
27643 decode_opc_special3_r6(env, ctx);
27644 break;
27645 default:
27646 check_insn(ctx, ISA_MIPS64R2);
27647 check_mips_64(ctx);
27648 op2 = MASK_DBSHFL(ctx->opcode);
27649 gen_bshfl(ctx, op2, rt, rd);
27650 break;
27652 break;
27653 #endif
27654 case OPC_RDHWR:
27655 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27656 break;
27657 case OPC_FORK:
27658 check_mt(ctx);
27660 TCGv t0 = tcg_temp_new();
27661 TCGv t1 = tcg_temp_new();
27663 gen_load_gpr(t0, rt);
27664 gen_load_gpr(t1, rs);
27665 gen_helper_fork(t0, t1);
27666 tcg_temp_free(t0);
27667 tcg_temp_free(t1);
27669 break;
27670 case OPC_YIELD:
27671 check_mt(ctx);
27673 TCGv t0 = tcg_temp_new();
27675 gen_load_gpr(t0, rs);
27676 gen_helper_yield(t0, cpu_env, t0);
27677 gen_store_gpr(t0, rd);
27678 tcg_temp_free(t0);
27680 break;
27681 default:
27682 if (ctx->insn_flags & ISA_MIPS32R6) {
27683 decode_opc_special3_r6(env, ctx);
27684 } else {
27685 decode_opc_special3_legacy(env, ctx);
27690 /* MIPS SIMD Architecture (MSA) */
27691 static inline int check_msa_access(DisasContext *ctx)
27693 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
27694 !(ctx->hflags & MIPS_HFLAG_F64))) {
27695 generate_exception_end(ctx, EXCP_RI);
27696 return 0;
27699 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
27700 if (ctx->insn_flags & ASE_MSA) {
27701 generate_exception_end(ctx, EXCP_MSADIS);
27702 return 0;
27703 } else {
27704 generate_exception_end(ctx, EXCP_RI);
27705 return 0;
27708 return 1;
27711 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
27713 /* generates tcg ops to check if any element is 0 */
27714 /* Note this function only works with MSA_WRLEN = 128 */
27715 uint64_t eval_zero_or_big = 0;
27716 uint64_t eval_big = 0;
27717 TCGv_i64 t0 = tcg_temp_new_i64();
27718 TCGv_i64 t1 = tcg_temp_new_i64();
27719 switch (df) {
27720 case DF_BYTE:
27721 eval_zero_or_big = 0x0101010101010101ULL;
27722 eval_big = 0x8080808080808080ULL;
27723 break;
27724 case DF_HALF:
27725 eval_zero_or_big = 0x0001000100010001ULL;
27726 eval_big = 0x8000800080008000ULL;
27727 break;
27728 case DF_WORD:
27729 eval_zero_or_big = 0x0000000100000001ULL;
27730 eval_big = 0x8000000080000000ULL;
27731 break;
27732 case DF_DOUBLE:
27733 eval_zero_or_big = 0x0000000000000001ULL;
27734 eval_big = 0x8000000000000000ULL;
27735 break;
27737 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
27738 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
27739 tcg_gen_andi_i64(t0, t0, eval_big);
27740 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
27741 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
27742 tcg_gen_andi_i64(t1, t1, eval_big);
27743 tcg_gen_or_i64(t0, t0, t1);
27744 /* if all bits are zero then all elements are not zero */
27745 /* if some bit is non-zero then some element is zero */
27746 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
27747 tcg_gen_trunc_i64_tl(tresult, t0);
27748 tcg_temp_free_i64(t0);
27749 tcg_temp_free_i64(t1);
27752 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
27754 uint8_t df = (ctx->opcode >> 21) & 0x3;
27755 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27756 int64_t s16 = (int16_t)ctx->opcode;
27758 check_msa_access(ctx);
27760 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27761 generate_exception_end(ctx, EXCP_RI);
27762 return;
27764 switch (op1) {
27765 case OPC_BZ_V:
27766 case OPC_BNZ_V:
27768 TCGv_i64 t0 = tcg_temp_new_i64();
27769 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
27770 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
27771 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
27772 tcg_gen_trunc_i64_tl(bcond, t0);
27773 tcg_temp_free_i64(t0);
27775 break;
27776 case OPC_BZ_B:
27777 case OPC_BZ_H:
27778 case OPC_BZ_W:
27779 case OPC_BZ_D:
27780 gen_check_zero_element(bcond, df, wt);
27781 break;
27782 case OPC_BNZ_B:
27783 case OPC_BNZ_H:
27784 case OPC_BNZ_W:
27785 case OPC_BNZ_D:
27786 gen_check_zero_element(bcond, df, wt);
27787 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
27788 break;
27791 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
27793 ctx->hflags |= MIPS_HFLAG_BC;
27794 ctx->hflags |= MIPS_HFLAG_BDS32;
27797 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
27799 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
27800 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
27801 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27802 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27804 TCGv_i32 twd = tcg_const_i32(wd);
27805 TCGv_i32 tws = tcg_const_i32(ws);
27806 TCGv_i32 ti8 = tcg_const_i32(i8);
27808 switch (MASK_MSA_I8(ctx->opcode)) {
27809 case OPC_ANDI_B:
27810 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
27811 break;
27812 case OPC_ORI_B:
27813 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
27814 break;
27815 case OPC_NORI_B:
27816 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
27817 break;
27818 case OPC_XORI_B:
27819 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
27820 break;
27821 case OPC_BMNZI_B:
27822 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
27823 break;
27824 case OPC_BMZI_B:
27825 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
27826 break;
27827 case OPC_BSELI_B:
27828 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
27829 break;
27830 case OPC_SHF_B:
27831 case OPC_SHF_H:
27832 case OPC_SHF_W:
27834 uint8_t df = (ctx->opcode >> 24) & 0x3;
27835 if (df == DF_DOUBLE) {
27836 generate_exception_end(ctx, EXCP_RI);
27837 } else {
27838 TCGv_i32 tdf = tcg_const_i32(df);
27839 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
27840 tcg_temp_free_i32(tdf);
27843 break;
27844 default:
27845 MIPS_INVAL("MSA instruction");
27846 generate_exception_end(ctx, EXCP_RI);
27847 break;
27850 tcg_temp_free_i32(twd);
27851 tcg_temp_free_i32(tws);
27852 tcg_temp_free_i32(ti8);
27855 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
27857 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27858 uint8_t df = (ctx->opcode >> 21) & 0x3;
27859 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
27860 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
27861 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27862 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27864 TCGv_i32 tdf = tcg_const_i32(df);
27865 TCGv_i32 twd = tcg_const_i32(wd);
27866 TCGv_i32 tws = tcg_const_i32(ws);
27867 TCGv_i32 timm = tcg_temp_new_i32();
27868 tcg_gen_movi_i32(timm, u5);
27870 switch (MASK_MSA_I5(ctx->opcode)) {
27871 case OPC_ADDVI_df:
27872 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
27873 break;
27874 case OPC_SUBVI_df:
27875 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
27876 break;
27877 case OPC_MAXI_S_df:
27878 tcg_gen_movi_i32(timm, s5);
27879 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
27880 break;
27881 case OPC_MAXI_U_df:
27882 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
27883 break;
27884 case OPC_MINI_S_df:
27885 tcg_gen_movi_i32(timm, s5);
27886 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
27887 break;
27888 case OPC_MINI_U_df:
27889 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
27890 break;
27891 case OPC_CEQI_df:
27892 tcg_gen_movi_i32(timm, s5);
27893 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
27894 break;
27895 case OPC_CLTI_S_df:
27896 tcg_gen_movi_i32(timm, s5);
27897 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
27898 break;
27899 case OPC_CLTI_U_df:
27900 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
27901 break;
27902 case OPC_CLEI_S_df:
27903 tcg_gen_movi_i32(timm, s5);
27904 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
27905 break;
27906 case OPC_CLEI_U_df:
27907 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
27908 break;
27909 case OPC_LDI_df:
27911 int32_t s10 = sextract32(ctx->opcode, 11, 10);
27912 tcg_gen_movi_i32(timm, s10);
27913 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
27915 break;
27916 default:
27917 MIPS_INVAL("MSA instruction");
27918 generate_exception_end(ctx, EXCP_RI);
27919 break;
27922 tcg_temp_free_i32(tdf);
27923 tcg_temp_free_i32(twd);
27924 tcg_temp_free_i32(tws);
27925 tcg_temp_free_i32(timm);
27928 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
27930 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27931 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
27932 uint32_t df = 0, m = 0;
27933 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27934 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27936 TCGv_i32 tdf;
27937 TCGv_i32 tm;
27938 TCGv_i32 twd;
27939 TCGv_i32 tws;
27941 if ((dfm & 0x40) == 0x00) {
27942 m = dfm & 0x3f;
27943 df = DF_DOUBLE;
27944 } else if ((dfm & 0x60) == 0x40) {
27945 m = dfm & 0x1f;
27946 df = DF_WORD;
27947 } else if ((dfm & 0x70) == 0x60) {
27948 m = dfm & 0x0f;
27949 df = DF_HALF;
27950 } else if ((dfm & 0x78) == 0x70) {
27951 m = dfm & 0x7;
27952 df = DF_BYTE;
27953 } else {
27954 generate_exception_end(ctx, EXCP_RI);
27955 return;
27958 tdf = tcg_const_i32(df);
27959 tm = tcg_const_i32(m);
27960 twd = tcg_const_i32(wd);
27961 tws = tcg_const_i32(ws);
27963 switch (MASK_MSA_BIT(ctx->opcode)) {
27964 case OPC_SLLI_df:
27965 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
27966 break;
27967 case OPC_SRAI_df:
27968 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
27969 break;
27970 case OPC_SRLI_df:
27971 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
27972 break;
27973 case OPC_BCLRI_df:
27974 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
27975 break;
27976 case OPC_BSETI_df:
27977 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
27978 break;
27979 case OPC_BNEGI_df:
27980 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
27981 break;
27982 case OPC_BINSLI_df:
27983 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
27984 break;
27985 case OPC_BINSRI_df:
27986 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
27987 break;
27988 case OPC_SAT_S_df:
27989 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
27990 break;
27991 case OPC_SAT_U_df:
27992 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
27993 break;
27994 case OPC_SRARI_df:
27995 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
27996 break;
27997 case OPC_SRLRI_df:
27998 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
27999 break;
28000 default:
28001 MIPS_INVAL("MSA instruction");
28002 generate_exception_end(ctx, EXCP_RI);
28003 break;
28006 tcg_temp_free_i32(tdf);
28007 tcg_temp_free_i32(tm);
28008 tcg_temp_free_i32(twd);
28009 tcg_temp_free_i32(tws);
28012 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28014 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28015 uint8_t df = (ctx->opcode >> 21) & 0x3;
28016 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28017 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28018 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28020 TCGv_i32 tdf = tcg_const_i32(df);
28021 TCGv_i32 twd = tcg_const_i32(wd);
28022 TCGv_i32 tws = tcg_const_i32(ws);
28023 TCGv_i32 twt = tcg_const_i32(wt);
28025 switch (MASK_MSA_3R(ctx->opcode)) {
28026 case OPC_SLL_df:
28027 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28028 break;
28029 case OPC_ADDV_df:
28030 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28031 break;
28032 case OPC_CEQ_df:
28033 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28034 break;
28035 case OPC_ADD_A_df:
28036 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28037 break;
28038 case OPC_SUBS_S_df:
28039 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28040 break;
28041 case OPC_MULV_df:
28042 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28043 break;
28044 case OPC_SLD_df:
28045 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28046 break;
28047 case OPC_VSHF_df:
28048 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28049 break;
28050 case OPC_SRA_df:
28051 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28052 break;
28053 case OPC_SUBV_df:
28054 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28055 break;
28056 case OPC_ADDS_A_df:
28057 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28058 break;
28059 case OPC_SUBS_U_df:
28060 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28061 break;
28062 case OPC_MADDV_df:
28063 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28064 break;
28065 case OPC_SPLAT_df:
28066 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28067 break;
28068 case OPC_SRAR_df:
28069 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28070 break;
28071 case OPC_SRL_df:
28072 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28073 break;
28074 case OPC_MAX_S_df:
28075 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28076 break;
28077 case OPC_CLT_S_df:
28078 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28079 break;
28080 case OPC_ADDS_S_df:
28081 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28082 break;
28083 case OPC_SUBSUS_U_df:
28084 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28085 break;
28086 case OPC_MSUBV_df:
28087 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28088 break;
28089 case OPC_PCKEV_df:
28090 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28091 break;
28092 case OPC_SRLR_df:
28093 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28094 break;
28095 case OPC_BCLR_df:
28096 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28097 break;
28098 case OPC_MAX_U_df:
28099 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28100 break;
28101 case OPC_CLT_U_df:
28102 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28103 break;
28104 case OPC_ADDS_U_df:
28105 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28106 break;
28107 case OPC_SUBSUU_S_df:
28108 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28109 break;
28110 case OPC_PCKOD_df:
28111 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28112 break;
28113 case OPC_BSET_df:
28114 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28115 break;
28116 case OPC_MIN_S_df:
28117 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28118 break;
28119 case OPC_CLE_S_df:
28120 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28121 break;
28122 case OPC_AVE_S_df:
28123 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28124 break;
28125 case OPC_ASUB_S_df:
28126 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28127 break;
28128 case OPC_DIV_S_df:
28129 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28130 break;
28131 case OPC_ILVL_df:
28132 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28133 break;
28134 case OPC_BNEG_df:
28135 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28136 break;
28137 case OPC_MIN_U_df:
28138 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28139 break;
28140 case OPC_CLE_U_df:
28141 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28142 break;
28143 case OPC_AVE_U_df:
28144 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28145 break;
28146 case OPC_ASUB_U_df:
28147 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28148 break;
28149 case OPC_DIV_U_df:
28150 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28151 break;
28152 case OPC_ILVR_df:
28153 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28154 break;
28155 case OPC_BINSL_df:
28156 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28157 break;
28158 case OPC_MAX_A_df:
28159 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28160 break;
28161 case OPC_AVER_S_df:
28162 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28163 break;
28164 case OPC_MOD_S_df:
28165 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28166 break;
28167 case OPC_ILVEV_df:
28168 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28169 break;
28170 case OPC_BINSR_df:
28171 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28172 break;
28173 case OPC_MIN_A_df:
28174 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28175 break;
28176 case OPC_AVER_U_df:
28177 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28178 break;
28179 case OPC_MOD_U_df:
28180 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28181 break;
28182 case OPC_ILVOD_df:
28183 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28184 break;
28186 case OPC_DOTP_S_df:
28187 case OPC_DOTP_U_df:
28188 case OPC_DPADD_S_df:
28189 case OPC_DPADD_U_df:
28190 case OPC_DPSUB_S_df:
28191 case OPC_HADD_S_df:
28192 case OPC_DPSUB_U_df:
28193 case OPC_HADD_U_df:
28194 case OPC_HSUB_S_df:
28195 case OPC_HSUB_U_df:
28196 if (df == DF_BYTE) {
28197 generate_exception_end(ctx, EXCP_RI);
28198 break;
28200 switch (MASK_MSA_3R(ctx->opcode)) {
28201 case OPC_DOTP_S_df:
28202 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28203 break;
28204 case OPC_DOTP_U_df:
28205 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28206 break;
28207 case OPC_DPADD_S_df:
28208 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28209 break;
28210 case OPC_DPADD_U_df:
28211 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28212 break;
28213 case OPC_DPSUB_S_df:
28214 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28215 break;
28216 case OPC_HADD_S_df:
28217 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28218 break;
28219 case OPC_DPSUB_U_df:
28220 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28221 break;
28222 case OPC_HADD_U_df:
28223 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28224 break;
28225 case OPC_HSUB_S_df:
28226 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28227 break;
28228 case OPC_HSUB_U_df:
28229 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28230 break;
28232 break;
28233 default:
28234 MIPS_INVAL("MSA instruction");
28235 generate_exception_end(ctx, EXCP_RI);
28236 break;
28238 tcg_temp_free_i32(twd);
28239 tcg_temp_free_i32(tws);
28240 tcg_temp_free_i32(twt);
28241 tcg_temp_free_i32(tdf);
28244 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28246 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28247 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28248 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28249 TCGv telm = tcg_temp_new();
28250 TCGv_i32 tsr = tcg_const_i32(source);
28251 TCGv_i32 tdt = tcg_const_i32(dest);
28253 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28254 case OPC_CTCMSA:
28255 gen_load_gpr(telm, source);
28256 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28257 break;
28258 case OPC_CFCMSA:
28259 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28260 gen_store_gpr(telm, dest);
28261 break;
28262 case OPC_MOVE_V:
28263 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28264 break;
28265 default:
28266 MIPS_INVAL("MSA instruction");
28267 generate_exception_end(ctx, EXCP_RI);
28268 break;
28271 tcg_temp_free(telm);
28272 tcg_temp_free_i32(tdt);
28273 tcg_temp_free_i32(tsr);
28276 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28277 uint32_t n)
28279 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28280 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28281 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28283 TCGv_i32 tws = tcg_const_i32(ws);
28284 TCGv_i32 twd = tcg_const_i32(wd);
28285 TCGv_i32 tn = tcg_const_i32(n);
28286 TCGv_i32 tdf = tcg_const_i32(df);
28288 switch (MASK_MSA_ELM(ctx->opcode)) {
28289 case OPC_SLDI_df:
28290 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28291 break;
28292 case OPC_SPLATI_df:
28293 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28294 break;
28295 case OPC_INSVE_df:
28296 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28297 break;
28298 case OPC_COPY_S_df:
28299 case OPC_COPY_U_df:
28300 case OPC_INSERT_df:
28301 #if !defined(TARGET_MIPS64)
28302 /* Double format valid only for MIPS64 */
28303 if (df == DF_DOUBLE) {
28304 generate_exception_end(ctx, EXCP_RI);
28305 break;
28307 #endif
28308 switch (MASK_MSA_ELM(ctx->opcode)) {
28309 case OPC_COPY_S_df:
28310 if (likely(wd != 0)) {
28311 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
28313 break;
28314 case OPC_COPY_U_df:
28315 if (likely(wd != 0)) {
28316 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
28318 break;
28319 case OPC_INSERT_df:
28320 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
28321 break;
28323 break;
28324 default:
28325 MIPS_INVAL("MSA instruction");
28326 generate_exception_end(ctx, EXCP_RI);
28328 tcg_temp_free_i32(twd);
28329 tcg_temp_free_i32(tws);
28330 tcg_temp_free_i32(tn);
28331 tcg_temp_free_i32(tdf);
28334 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28336 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28337 uint32_t df = 0, n = 0;
28339 if ((dfn & 0x30) == 0x00) {
28340 n = dfn & 0x0f;
28341 df = DF_BYTE;
28342 } else if ((dfn & 0x38) == 0x20) {
28343 n = dfn & 0x07;
28344 df = DF_HALF;
28345 } else if ((dfn & 0x3c) == 0x30) {
28346 n = dfn & 0x03;
28347 df = DF_WORD;
28348 } else if ((dfn & 0x3e) == 0x38) {
28349 n = dfn & 0x01;
28350 df = DF_DOUBLE;
28351 } else if (dfn == 0x3E) {
28352 /* CTCMSA, CFCMSA, MOVE.V */
28353 gen_msa_elm_3e(env, ctx);
28354 return;
28355 } else {
28356 generate_exception_end(ctx, EXCP_RI);
28357 return;
28360 gen_msa_elm_df(env, ctx, df, n);
28363 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28365 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28366 uint8_t df = (ctx->opcode >> 21) & 0x1;
28367 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28368 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28369 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28371 TCGv_i32 twd = tcg_const_i32(wd);
28372 TCGv_i32 tws = tcg_const_i32(ws);
28373 TCGv_i32 twt = tcg_const_i32(wt);
28374 TCGv_i32 tdf = tcg_temp_new_i32();
28376 /* adjust df value for floating-point instruction */
28377 tcg_gen_movi_i32(tdf, df + 2);
28379 switch (MASK_MSA_3RF(ctx->opcode)) {
28380 case OPC_FCAF_df:
28381 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28382 break;
28383 case OPC_FADD_df:
28384 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28385 break;
28386 case OPC_FCUN_df:
28387 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28388 break;
28389 case OPC_FSUB_df:
28390 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28391 break;
28392 case OPC_FCOR_df:
28393 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28394 break;
28395 case OPC_FCEQ_df:
28396 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28397 break;
28398 case OPC_FMUL_df:
28399 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28400 break;
28401 case OPC_FCUNE_df:
28402 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28403 break;
28404 case OPC_FCUEQ_df:
28405 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28406 break;
28407 case OPC_FDIV_df:
28408 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28409 break;
28410 case OPC_FCNE_df:
28411 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28412 break;
28413 case OPC_FCLT_df:
28414 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28415 break;
28416 case OPC_FMADD_df:
28417 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28418 break;
28419 case OPC_MUL_Q_df:
28420 tcg_gen_movi_i32(tdf, df + 1);
28421 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28422 break;
28423 case OPC_FCULT_df:
28424 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28425 break;
28426 case OPC_FMSUB_df:
28427 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28428 break;
28429 case OPC_MADD_Q_df:
28430 tcg_gen_movi_i32(tdf, df + 1);
28431 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28432 break;
28433 case OPC_FCLE_df:
28434 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28435 break;
28436 case OPC_MSUB_Q_df:
28437 tcg_gen_movi_i32(tdf, df + 1);
28438 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28439 break;
28440 case OPC_FCULE_df:
28441 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28442 break;
28443 case OPC_FEXP2_df:
28444 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28445 break;
28446 case OPC_FSAF_df:
28447 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28448 break;
28449 case OPC_FEXDO_df:
28450 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28451 break;
28452 case OPC_FSUN_df:
28453 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28454 break;
28455 case OPC_FSOR_df:
28456 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28457 break;
28458 case OPC_FSEQ_df:
28459 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28460 break;
28461 case OPC_FTQ_df:
28462 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28463 break;
28464 case OPC_FSUNE_df:
28465 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28466 break;
28467 case OPC_FSUEQ_df:
28468 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28469 break;
28470 case OPC_FSNE_df:
28471 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28472 break;
28473 case OPC_FSLT_df:
28474 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28475 break;
28476 case OPC_FMIN_df:
28477 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28478 break;
28479 case OPC_MULR_Q_df:
28480 tcg_gen_movi_i32(tdf, df + 1);
28481 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28482 break;
28483 case OPC_FSULT_df:
28484 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28485 break;
28486 case OPC_FMIN_A_df:
28487 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28488 break;
28489 case OPC_MADDR_Q_df:
28490 tcg_gen_movi_i32(tdf, df + 1);
28491 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28492 break;
28493 case OPC_FSLE_df:
28494 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28495 break;
28496 case OPC_FMAX_df:
28497 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28498 break;
28499 case OPC_MSUBR_Q_df:
28500 tcg_gen_movi_i32(tdf, df + 1);
28501 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28502 break;
28503 case OPC_FSULE_df:
28504 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28505 break;
28506 case OPC_FMAX_A_df:
28507 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28508 break;
28509 default:
28510 MIPS_INVAL("MSA instruction");
28511 generate_exception_end(ctx, EXCP_RI);
28512 break;
28515 tcg_temp_free_i32(twd);
28516 tcg_temp_free_i32(tws);
28517 tcg_temp_free_i32(twt);
28518 tcg_temp_free_i32(tdf);
28521 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28523 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28524 (op & (0x7 << 18)))
28525 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28526 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28527 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28528 uint8_t df = (ctx->opcode >> 16) & 0x3;
28529 TCGv_i32 twd = tcg_const_i32(wd);
28530 TCGv_i32 tws = tcg_const_i32(ws);
28531 TCGv_i32 twt = tcg_const_i32(wt);
28532 TCGv_i32 tdf = tcg_const_i32(df);
28534 switch (MASK_MSA_2R(ctx->opcode)) {
28535 case OPC_FILL_df:
28536 #if !defined(TARGET_MIPS64)
28537 /* Double format valid only for MIPS64 */
28538 if (df == DF_DOUBLE) {
28539 generate_exception_end(ctx, EXCP_RI);
28540 break;
28542 #endif
28543 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28544 break;
28545 case OPC_PCNT_df:
28546 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28547 break;
28548 case OPC_NLOC_df:
28549 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28550 break;
28551 case OPC_NLZC_df:
28552 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28553 break;
28554 default:
28555 MIPS_INVAL("MSA instruction");
28556 generate_exception_end(ctx, EXCP_RI);
28557 break;
28560 tcg_temp_free_i32(twd);
28561 tcg_temp_free_i32(tws);
28562 tcg_temp_free_i32(twt);
28563 tcg_temp_free_i32(tdf);
28566 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28568 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28569 (op & (0xf << 17)))
28570 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28571 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28572 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28573 uint8_t df = (ctx->opcode >> 16) & 0x1;
28574 TCGv_i32 twd = tcg_const_i32(wd);
28575 TCGv_i32 tws = tcg_const_i32(ws);
28576 TCGv_i32 twt = tcg_const_i32(wt);
28577 /* adjust df value for floating-point instruction */
28578 TCGv_i32 tdf = tcg_const_i32(df + 2);
28580 switch (MASK_MSA_2RF(ctx->opcode)) {
28581 case OPC_FCLASS_df:
28582 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28583 break;
28584 case OPC_FTRUNC_S_df:
28585 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28586 break;
28587 case OPC_FTRUNC_U_df:
28588 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28589 break;
28590 case OPC_FSQRT_df:
28591 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28592 break;
28593 case OPC_FRSQRT_df:
28594 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28595 break;
28596 case OPC_FRCP_df:
28597 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28598 break;
28599 case OPC_FRINT_df:
28600 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28601 break;
28602 case OPC_FLOG2_df:
28603 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28604 break;
28605 case OPC_FEXUPL_df:
28606 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28607 break;
28608 case OPC_FEXUPR_df:
28609 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28610 break;
28611 case OPC_FFQL_df:
28612 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28613 break;
28614 case OPC_FFQR_df:
28615 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28616 break;
28617 case OPC_FTINT_S_df:
28618 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28619 break;
28620 case OPC_FTINT_U_df:
28621 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
28622 break;
28623 case OPC_FFINT_S_df:
28624 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
28625 break;
28626 case OPC_FFINT_U_df:
28627 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
28628 break;
28631 tcg_temp_free_i32(twd);
28632 tcg_temp_free_i32(tws);
28633 tcg_temp_free_i32(twt);
28634 tcg_temp_free_i32(tdf);
28637 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
28639 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
28640 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28641 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28642 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28643 TCGv_i32 twd = tcg_const_i32(wd);
28644 TCGv_i32 tws = tcg_const_i32(ws);
28645 TCGv_i32 twt = tcg_const_i32(wt);
28647 switch (MASK_MSA_VEC(ctx->opcode)) {
28648 case OPC_AND_V:
28649 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
28650 break;
28651 case OPC_OR_V:
28652 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
28653 break;
28654 case OPC_NOR_V:
28655 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
28656 break;
28657 case OPC_XOR_V:
28658 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
28659 break;
28660 case OPC_BMNZ_V:
28661 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
28662 break;
28663 case OPC_BMZ_V:
28664 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
28665 break;
28666 case OPC_BSEL_V:
28667 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
28668 break;
28669 default:
28670 MIPS_INVAL("MSA instruction");
28671 generate_exception_end(ctx, EXCP_RI);
28672 break;
28675 tcg_temp_free_i32(twd);
28676 tcg_temp_free_i32(tws);
28677 tcg_temp_free_i32(twt);
28680 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
28682 switch (MASK_MSA_VEC(ctx->opcode)) {
28683 case OPC_AND_V:
28684 case OPC_OR_V:
28685 case OPC_NOR_V:
28686 case OPC_XOR_V:
28687 case OPC_BMNZ_V:
28688 case OPC_BMZ_V:
28689 case OPC_BSEL_V:
28690 gen_msa_vec_v(env, ctx);
28691 break;
28692 case OPC_MSA_2R:
28693 gen_msa_2r(env, ctx);
28694 break;
28695 case OPC_MSA_2RF:
28696 gen_msa_2rf(env, ctx);
28697 break;
28698 default:
28699 MIPS_INVAL("MSA instruction");
28700 generate_exception_end(ctx, EXCP_RI);
28701 break;
28705 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
28707 uint32_t opcode = ctx->opcode;
28708 check_insn(ctx, ASE_MSA);
28709 check_msa_access(ctx);
28711 switch (MASK_MSA_MINOR(opcode)) {
28712 case OPC_MSA_I8_00:
28713 case OPC_MSA_I8_01:
28714 case OPC_MSA_I8_02:
28715 gen_msa_i8(env, ctx);
28716 break;
28717 case OPC_MSA_I5_06:
28718 case OPC_MSA_I5_07:
28719 gen_msa_i5(env, ctx);
28720 break;
28721 case OPC_MSA_BIT_09:
28722 case OPC_MSA_BIT_0A:
28723 gen_msa_bit(env, ctx);
28724 break;
28725 case OPC_MSA_3R_0D:
28726 case OPC_MSA_3R_0E:
28727 case OPC_MSA_3R_0F:
28728 case OPC_MSA_3R_10:
28729 case OPC_MSA_3R_11:
28730 case OPC_MSA_3R_12:
28731 case OPC_MSA_3R_13:
28732 case OPC_MSA_3R_14:
28733 case OPC_MSA_3R_15:
28734 gen_msa_3r(env, ctx);
28735 break;
28736 case OPC_MSA_ELM:
28737 gen_msa_elm(env, ctx);
28738 break;
28739 case OPC_MSA_3RF_1A:
28740 case OPC_MSA_3RF_1B:
28741 case OPC_MSA_3RF_1C:
28742 gen_msa_3rf(env, ctx);
28743 break;
28744 case OPC_MSA_VEC:
28745 gen_msa_vec(env, ctx);
28746 break;
28747 case OPC_LD_B:
28748 case OPC_LD_H:
28749 case OPC_LD_W:
28750 case OPC_LD_D:
28751 case OPC_ST_B:
28752 case OPC_ST_H:
28753 case OPC_ST_W:
28754 case OPC_ST_D:
28756 int32_t s10 = sextract32(ctx->opcode, 16, 10);
28757 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
28758 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28759 uint8_t df = (ctx->opcode >> 0) & 0x3;
28761 TCGv_i32 twd = tcg_const_i32(wd);
28762 TCGv taddr = tcg_temp_new();
28763 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
28765 switch (MASK_MSA_MINOR(opcode)) {
28766 case OPC_LD_B:
28767 gen_helper_msa_ld_b(cpu_env, twd, taddr);
28768 break;
28769 case OPC_LD_H:
28770 gen_helper_msa_ld_h(cpu_env, twd, taddr);
28771 break;
28772 case OPC_LD_W:
28773 gen_helper_msa_ld_w(cpu_env, twd, taddr);
28774 break;
28775 case OPC_LD_D:
28776 gen_helper_msa_ld_d(cpu_env, twd, taddr);
28777 break;
28778 case OPC_ST_B:
28779 gen_helper_msa_st_b(cpu_env, twd, taddr);
28780 break;
28781 case OPC_ST_H:
28782 gen_helper_msa_st_h(cpu_env, twd, taddr);
28783 break;
28784 case OPC_ST_W:
28785 gen_helper_msa_st_w(cpu_env, twd, taddr);
28786 break;
28787 case OPC_ST_D:
28788 gen_helper_msa_st_d(cpu_env, twd, taddr);
28789 break;
28792 tcg_temp_free_i32(twd);
28793 tcg_temp_free(taddr);
28795 break;
28796 default:
28797 MIPS_INVAL("MSA instruction");
28798 generate_exception_end(ctx, EXCP_RI);
28799 break;
28804 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
28806 int32_t offset;
28807 int rs, rt, rd, sa;
28808 uint32_t op, op1;
28809 int16_t imm;
28811 /* make sure instructions are on a word boundary */
28812 if (ctx->base.pc_next & 0x3) {
28813 env->CP0_BadVAddr = ctx->base.pc_next;
28814 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
28815 return;
28818 /* Handle blikely not taken case */
28819 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
28820 TCGLabel *l1 = gen_new_label();
28822 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28823 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
28824 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
28825 gen_set_label(l1);
28828 op = MASK_OP_MAJOR(ctx->opcode);
28829 rs = (ctx->opcode >> 21) & 0x1f;
28830 rt = (ctx->opcode >> 16) & 0x1f;
28831 rd = (ctx->opcode >> 11) & 0x1f;
28832 sa = (ctx->opcode >> 6) & 0x1f;
28833 imm = (int16_t)ctx->opcode;
28834 switch (op) {
28835 case OPC_SPECIAL:
28836 decode_opc_special(env, ctx);
28837 break;
28838 case OPC_SPECIAL2:
28839 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
28840 decode_mmi(env, ctx);
28841 #if !defined(TARGET_MIPS64)
28842 } else if (ctx->insn_flags & ASE_MXU) {
28843 decode_opc_mxu(env, ctx);
28844 #endif
28845 } else {
28846 decode_opc_special2_legacy(env, ctx);
28848 break;
28849 case OPC_SPECIAL3:
28850 if (ctx->insn_flags & INSN_R5900) {
28851 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
28852 } else {
28853 decode_opc_special3(env, ctx);
28855 break;
28856 case OPC_REGIMM:
28857 op1 = MASK_REGIMM(ctx->opcode);
28858 switch (op1) {
28859 case OPC_BLTZL: /* REGIMM branches */
28860 case OPC_BGEZL:
28861 case OPC_BLTZALL:
28862 case OPC_BGEZALL:
28863 check_insn(ctx, ISA_MIPS2);
28864 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28865 /* Fallthrough */
28866 case OPC_BLTZ:
28867 case OPC_BGEZ:
28868 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28869 break;
28870 case OPC_BLTZAL:
28871 case OPC_BGEZAL:
28872 if (ctx->insn_flags & ISA_MIPS32R6) {
28873 if (rs == 0) {
28874 /* OPC_NAL, OPC_BAL */
28875 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
28876 } else {
28877 generate_exception_end(ctx, EXCP_RI);
28879 } else {
28880 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28882 break;
28883 case OPC_TGEI: /* REGIMM traps */
28884 case OPC_TGEIU:
28885 case OPC_TLTI:
28886 case OPC_TLTIU:
28887 case OPC_TEQI:
28889 case OPC_TNEI:
28890 check_insn(ctx, ISA_MIPS2);
28891 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28892 gen_trap(ctx, op1, rs, -1, imm);
28893 break;
28894 case OPC_SIGRIE:
28895 check_insn(ctx, ISA_MIPS32R6);
28896 generate_exception_end(ctx, EXCP_RI);
28897 break;
28898 case OPC_SYNCI:
28899 check_insn(ctx, ISA_MIPS32R2);
28900 /* Break the TB to be able to sync copied instructions
28901 immediately */
28902 ctx->base.is_jmp = DISAS_STOP;
28903 break;
28904 case OPC_BPOSGE32: /* MIPS DSP branch */
28905 #if defined(TARGET_MIPS64)
28906 case OPC_BPOSGE64:
28907 #endif
28908 check_dsp(ctx);
28909 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
28910 break;
28911 #if defined(TARGET_MIPS64)
28912 case OPC_DAHI:
28913 check_insn(ctx, ISA_MIPS32R6);
28914 check_mips_64(ctx);
28915 if (rs != 0) {
28916 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28918 break;
28919 case OPC_DATI:
28920 check_insn(ctx, ISA_MIPS32R6);
28921 check_mips_64(ctx);
28922 if (rs != 0) {
28923 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28925 break;
28926 #endif
28927 default: /* Invalid */
28928 MIPS_INVAL("regimm");
28929 generate_exception_end(ctx, EXCP_RI);
28930 break;
28932 break;
28933 case OPC_CP0:
28934 check_cp0_enabled(ctx);
28935 op1 = MASK_CP0(ctx->opcode);
28936 switch (op1) {
28937 case OPC_MFC0:
28938 case OPC_MTC0:
28939 case OPC_MFTR:
28940 case OPC_MTTR:
28941 case OPC_MFHC0:
28942 case OPC_MTHC0:
28943 #if defined(TARGET_MIPS64)
28944 case OPC_DMFC0:
28945 case OPC_DMTC0:
28946 #endif
28947 #ifndef CONFIG_USER_ONLY
28948 gen_cp0(env, ctx, op1, rt, rd);
28949 #endif /* !CONFIG_USER_ONLY */
28950 break;
28951 case OPC_C0:
28952 case OPC_C0_1:
28953 case OPC_C0_2:
28954 case OPC_C0_3:
28955 case OPC_C0_4:
28956 case OPC_C0_5:
28957 case OPC_C0_6:
28958 case OPC_C0_7:
28959 case OPC_C0_8:
28960 case OPC_C0_9:
28961 case OPC_C0_A:
28962 case OPC_C0_B:
28963 case OPC_C0_C:
28964 case OPC_C0_D:
28965 case OPC_C0_E:
28966 case OPC_C0_F:
28967 #ifndef CONFIG_USER_ONLY
28968 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
28969 #endif /* !CONFIG_USER_ONLY */
28970 break;
28971 case OPC_MFMC0:
28972 #ifndef CONFIG_USER_ONLY
28974 uint32_t op2;
28975 TCGv t0 = tcg_temp_new();
28977 op2 = MASK_MFMC0(ctx->opcode);
28978 switch (op2) {
28979 case OPC_DMT:
28980 check_cp0_mt(ctx);
28981 gen_helper_dmt(t0);
28982 gen_store_gpr(t0, rt);
28983 break;
28984 case OPC_EMT:
28985 check_cp0_mt(ctx);
28986 gen_helper_emt(t0);
28987 gen_store_gpr(t0, rt);
28988 break;
28989 case OPC_DVPE:
28990 check_cp0_mt(ctx);
28991 gen_helper_dvpe(t0, cpu_env);
28992 gen_store_gpr(t0, rt);
28993 break;
28994 case OPC_EVPE:
28995 check_cp0_mt(ctx);
28996 gen_helper_evpe(t0, cpu_env);
28997 gen_store_gpr(t0, rt);
28998 break;
28999 case OPC_DVP:
29000 check_insn(ctx, ISA_MIPS32R6);
29001 if (ctx->vp) {
29002 gen_helper_dvp(t0, cpu_env);
29003 gen_store_gpr(t0, rt);
29005 break;
29006 case OPC_EVP:
29007 check_insn(ctx, ISA_MIPS32R6);
29008 if (ctx->vp) {
29009 gen_helper_evp(t0, cpu_env);
29010 gen_store_gpr(t0, rt);
29012 break;
29013 case OPC_DI:
29014 check_insn(ctx, ISA_MIPS32R2);
29015 save_cpu_state(ctx, 1);
29016 gen_helper_di(t0, cpu_env);
29017 gen_store_gpr(t0, rt);
29018 /* Stop translation as we may have switched
29019 the execution mode. */
29020 ctx->base.is_jmp = DISAS_STOP;
29021 break;
29022 case OPC_EI:
29023 check_insn(ctx, ISA_MIPS32R2);
29024 save_cpu_state(ctx, 1);
29025 gen_helper_ei(t0, cpu_env);
29026 gen_store_gpr(t0, rt);
29027 /* DISAS_STOP isn't sufficient, we need to ensure we break
29028 out of translated code to check for pending interrupts */
29029 gen_save_pc(ctx->base.pc_next + 4);
29030 ctx->base.is_jmp = DISAS_EXIT;
29031 break;
29032 default: /* Invalid */
29033 MIPS_INVAL("mfmc0");
29034 generate_exception_end(ctx, EXCP_RI);
29035 break;
29037 tcg_temp_free(t0);
29039 #endif /* !CONFIG_USER_ONLY */
29040 break;
29041 case OPC_RDPGPR:
29042 check_insn(ctx, ISA_MIPS32R2);
29043 gen_load_srsgpr(rt, rd);
29044 break;
29045 case OPC_WRPGPR:
29046 check_insn(ctx, ISA_MIPS32R2);
29047 gen_store_srsgpr(rt, rd);
29048 break;
29049 default:
29050 MIPS_INVAL("cp0");
29051 generate_exception_end(ctx, EXCP_RI);
29052 break;
29054 break;
29055 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29056 if (ctx->insn_flags & ISA_MIPS32R6) {
29057 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29058 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29059 } else {
29060 /* OPC_ADDI */
29061 /* Arithmetic with immediate opcode */
29062 gen_arith_imm(ctx, op, rt, rs, imm);
29064 break;
29065 case OPC_ADDIU:
29066 gen_arith_imm(ctx, op, rt, rs, imm);
29067 break;
29068 case OPC_SLTI: /* Set on less than with immediate opcode */
29069 case OPC_SLTIU:
29070 gen_slt_imm(ctx, op, rt, rs, imm);
29071 break;
29072 case OPC_ANDI: /* Arithmetic with immediate opcode */
29073 case OPC_LUI: /* OPC_AUI */
29074 case OPC_ORI:
29075 case OPC_XORI:
29076 gen_logic_imm(ctx, op, rt, rs, imm);
29077 break;
29078 case OPC_J: /* Jump */
29079 case OPC_JAL:
29080 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29081 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29082 break;
29083 /* Branch */
29084 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29085 if (ctx->insn_flags & ISA_MIPS32R6) {
29086 if (rt == 0) {
29087 generate_exception_end(ctx, EXCP_RI);
29088 break;
29090 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29091 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29092 } else {
29093 /* OPC_BLEZL */
29094 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29096 break;
29097 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29098 if (ctx->insn_flags & ISA_MIPS32R6) {
29099 if (rt == 0) {
29100 generate_exception_end(ctx, EXCP_RI);
29101 break;
29103 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29104 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29105 } else {
29106 /* OPC_BGTZL */
29107 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29109 break;
29110 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29111 if (rt == 0) {
29112 /* OPC_BLEZ */
29113 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29114 } else {
29115 check_insn(ctx, ISA_MIPS32R6);
29116 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29117 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29119 break;
29120 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29121 if (rt == 0) {
29122 /* OPC_BGTZ */
29123 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29124 } else {
29125 check_insn(ctx, ISA_MIPS32R6);
29126 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29127 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29129 break;
29130 case OPC_BEQL:
29131 case OPC_BNEL:
29132 check_insn(ctx, ISA_MIPS2);
29133 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29134 /* Fallthrough */
29135 case OPC_BEQ:
29136 case OPC_BNE:
29137 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29138 break;
29139 case OPC_LL: /* Load and stores */
29140 check_insn(ctx, ISA_MIPS2);
29141 if (ctx->insn_flags & INSN_R5900) {
29142 check_insn_opc_user_only(ctx, INSN_R5900);
29144 /* Fallthrough */
29145 case OPC_LWL:
29146 case OPC_LWR:
29147 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29148 /* Fallthrough */
29149 case OPC_LB:
29150 case OPC_LH:
29151 case OPC_LW:
29152 case OPC_LWPC:
29153 case OPC_LBU:
29154 case OPC_LHU:
29155 gen_ld(ctx, op, rt, rs, imm);
29156 break;
29157 case OPC_SWL:
29158 case OPC_SWR:
29159 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29160 /* fall through */
29161 case OPC_SB:
29162 case OPC_SH:
29163 case OPC_SW:
29164 gen_st(ctx, op, rt, rs, imm);
29165 break;
29166 case OPC_SC:
29167 check_insn(ctx, ISA_MIPS2);
29168 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29169 if (ctx->insn_flags & INSN_R5900) {
29170 check_insn_opc_user_only(ctx, INSN_R5900);
29172 gen_st_cond(ctx, op, rt, rs, imm);
29173 break;
29174 case OPC_CACHE:
29175 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29176 check_cp0_enabled(ctx);
29177 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29178 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29179 gen_cache_operation(ctx, rt, rs, imm);
29181 /* Treat as NOP. */
29182 break;
29183 case OPC_PREF:
29184 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29185 if (ctx->insn_flags & INSN_R5900) {
29186 /* Treat as NOP. */
29187 } else {
29188 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29189 /* Treat as NOP. */
29191 break;
29193 /* Floating point (COP1). */
29194 case OPC_LWC1:
29195 case OPC_LDC1:
29196 case OPC_SWC1:
29197 case OPC_SDC1:
29198 gen_cop1_ldst(ctx, op, rt, rs, imm);
29199 break;
29201 case OPC_CP1:
29202 op1 = MASK_CP1(ctx->opcode);
29204 switch (op1) {
29205 case OPC_MFHC1:
29206 case OPC_MTHC1:
29207 check_cp1_enabled(ctx);
29208 check_insn(ctx, ISA_MIPS32R2);
29209 /* fall through */
29210 case OPC_MFC1:
29211 case OPC_CFC1:
29212 case OPC_MTC1:
29213 case OPC_CTC1:
29214 check_cp1_enabled(ctx);
29215 gen_cp1(ctx, op1, rt, rd);
29216 break;
29217 #if defined(TARGET_MIPS64)
29218 case OPC_DMFC1:
29219 case OPC_DMTC1:
29220 check_cp1_enabled(ctx);
29221 check_insn(ctx, ISA_MIPS3);
29222 check_mips_64(ctx);
29223 gen_cp1(ctx, op1, rt, rd);
29224 break;
29225 #endif
29226 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29227 check_cp1_enabled(ctx);
29228 if (ctx->insn_flags & ISA_MIPS32R6) {
29229 /* OPC_BC1EQZ */
29230 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29231 rt, imm << 2, 4);
29232 } else {
29233 /* OPC_BC1ANY2 */
29234 check_cop1x(ctx);
29235 check_insn(ctx, ASE_MIPS3D);
29236 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29237 (rt >> 2) & 0x7, imm << 2);
29239 break;
29240 case OPC_BC1NEZ:
29241 check_cp1_enabled(ctx);
29242 check_insn(ctx, ISA_MIPS32R6);
29243 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29244 rt, imm << 2, 4);
29245 break;
29246 case OPC_BC1ANY4:
29247 check_cp1_enabled(ctx);
29248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29249 check_cop1x(ctx);
29250 check_insn(ctx, ASE_MIPS3D);
29251 /* fall through */
29252 case OPC_BC1:
29253 check_cp1_enabled(ctx);
29254 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29255 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29256 (rt >> 2) & 0x7, imm << 2);
29257 break;
29258 case OPC_PS_FMT:
29259 check_ps(ctx);
29260 /* fall through */
29261 case OPC_S_FMT:
29262 case OPC_D_FMT:
29263 check_cp1_enabled(ctx);
29264 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29265 (imm >> 8) & 0x7);
29266 break;
29267 case OPC_W_FMT:
29268 case OPC_L_FMT:
29270 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29271 check_cp1_enabled(ctx);
29272 if (ctx->insn_flags & ISA_MIPS32R6) {
29273 switch (r6_op) {
29274 case R6_OPC_CMP_AF_S:
29275 case R6_OPC_CMP_UN_S:
29276 case R6_OPC_CMP_EQ_S:
29277 case R6_OPC_CMP_UEQ_S:
29278 case R6_OPC_CMP_LT_S:
29279 case R6_OPC_CMP_ULT_S:
29280 case R6_OPC_CMP_LE_S:
29281 case R6_OPC_CMP_ULE_S:
29282 case R6_OPC_CMP_SAF_S:
29283 case R6_OPC_CMP_SUN_S:
29284 case R6_OPC_CMP_SEQ_S:
29285 case R6_OPC_CMP_SEUQ_S:
29286 case R6_OPC_CMP_SLT_S:
29287 case R6_OPC_CMP_SULT_S:
29288 case R6_OPC_CMP_SLE_S:
29289 case R6_OPC_CMP_SULE_S:
29290 case R6_OPC_CMP_OR_S:
29291 case R6_OPC_CMP_UNE_S:
29292 case R6_OPC_CMP_NE_S:
29293 case R6_OPC_CMP_SOR_S:
29294 case R6_OPC_CMP_SUNE_S:
29295 case R6_OPC_CMP_SNE_S:
29296 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29297 break;
29298 case R6_OPC_CMP_AF_D:
29299 case R6_OPC_CMP_UN_D:
29300 case R6_OPC_CMP_EQ_D:
29301 case R6_OPC_CMP_UEQ_D:
29302 case R6_OPC_CMP_LT_D:
29303 case R6_OPC_CMP_ULT_D:
29304 case R6_OPC_CMP_LE_D:
29305 case R6_OPC_CMP_ULE_D:
29306 case R6_OPC_CMP_SAF_D:
29307 case R6_OPC_CMP_SUN_D:
29308 case R6_OPC_CMP_SEQ_D:
29309 case R6_OPC_CMP_SEUQ_D:
29310 case R6_OPC_CMP_SLT_D:
29311 case R6_OPC_CMP_SULT_D:
29312 case R6_OPC_CMP_SLE_D:
29313 case R6_OPC_CMP_SULE_D:
29314 case R6_OPC_CMP_OR_D:
29315 case R6_OPC_CMP_UNE_D:
29316 case R6_OPC_CMP_NE_D:
29317 case R6_OPC_CMP_SOR_D:
29318 case R6_OPC_CMP_SUNE_D:
29319 case R6_OPC_CMP_SNE_D:
29320 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29321 break;
29322 default:
29323 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29324 rt, rd, sa, (imm >> 8) & 0x7);
29326 break;
29328 } else {
29329 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29330 (imm >> 8) & 0x7);
29332 break;
29334 case OPC_BZ_V:
29335 case OPC_BNZ_V:
29336 case OPC_BZ_B:
29337 case OPC_BZ_H:
29338 case OPC_BZ_W:
29339 case OPC_BZ_D:
29340 case OPC_BNZ_B:
29341 case OPC_BNZ_H:
29342 case OPC_BNZ_W:
29343 case OPC_BNZ_D:
29344 check_insn(ctx, ASE_MSA);
29345 gen_msa_branch(env, ctx, op1);
29346 break;
29347 default:
29348 MIPS_INVAL("cp1");
29349 generate_exception_end(ctx, EXCP_RI);
29350 break;
29352 break;
29354 /* Compact branches [R6] and COP2 [non-R6] */
29355 case OPC_BC: /* OPC_LWC2 */
29356 case OPC_BALC: /* OPC_SWC2 */
29357 if (ctx->insn_flags & ISA_MIPS32R6) {
29358 /* OPC_BC, OPC_BALC */
29359 gen_compute_compact_branch(ctx, op, 0, 0,
29360 sextract32(ctx->opcode << 2, 0, 28));
29361 } else {
29362 /* OPC_LWC2, OPC_SWC2 */
29363 /* COP2: Not implemented. */
29364 generate_exception_err(ctx, EXCP_CpU, 2);
29366 break;
29367 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29368 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29369 if (ctx->insn_flags & ISA_MIPS32R6) {
29370 if (rs != 0) {
29371 /* OPC_BEQZC, OPC_BNEZC */
29372 gen_compute_compact_branch(ctx, op, rs, 0,
29373 sextract32(ctx->opcode << 2, 0, 23));
29374 } else {
29375 /* OPC_JIC, OPC_JIALC */
29376 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29378 } else {
29379 /* OPC_LWC2, OPC_SWC2 */
29380 /* COP2: Not implemented. */
29381 generate_exception_err(ctx, EXCP_CpU, 2);
29383 break;
29384 case OPC_CP2:
29385 check_insn(ctx, INSN_LOONGSON2F);
29386 /* Note that these instructions use different fields. */
29387 gen_loongson_multimedia(ctx, sa, rd, rt);
29388 break;
29390 case OPC_CP3:
29391 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29392 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29393 check_cp1_enabled(ctx);
29394 op1 = MASK_CP3(ctx->opcode);
29395 switch (op1) {
29396 case OPC_LUXC1:
29397 case OPC_SUXC1:
29398 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29399 /* Fallthrough */
29400 case OPC_LWXC1:
29401 case OPC_LDXC1:
29402 case OPC_SWXC1:
29403 case OPC_SDXC1:
29404 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29405 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29406 break;
29407 case OPC_PREFX:
29408 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29409 /* Treat as NOP. */
29410 break;
29411 case OPC_ALNV_PS:
29412 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29413 /* Fallthrough */
29414 case OPC_MADD_S:
29415 case OPC_MADD_D:
29416 case OPC_MADD_PS:
29417 case OPC_MSUB_S:
29418 case OPC_MSUB_D:
29419 case OPC_MSUB_PS:
29420 case OPC_NMADD_S:
29421 case OPC_NMADD_D:
29422 case OPC_NMADD_PS:
29423 case OPC_NMSUB_S:
29424 case OPC_NMSUB_D:
29425 case OPC_NMSUB_PS:
29426 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29427 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29428 break;
29429 default:
29430 MIPS_INVAL("cp3");
29431 generate_exception_end(ctx, EXCP_RI);
29432 break;
29434 } else {
29435 generate_exception_err(ctx, EXCP_CpU, 1);
29437 break;
29439 #if defined(TARGET_MIPS64)
29440 /* MIPS64 opcodes */
29441 case OPC_LLD:
29442 if (ctx->insn_flags & INSN_R5900) {
29443 check_insn_opc_user_only(ctx, INSN_R5900);
29445 /* fall through */
29446 case OPC_LDL:
29447 case OPC_LDR:
29448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29449 /* fall through */
29450 case OPC_LWU:
29451 case OPC_LD:
29452 check_insn(ctx, ISA_MIPS3);
29453 check_mips_64(ctx);
29454 gen_ld(ctx, op, rt, rs, imm);
29455 break;
29456 case OPC_SDL:
29457 case OPC_SDR:
29458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29459 /* fall through */
29460 case OPC_SD:
29461 check_insn(ctx, ISA_MIPS3);
29462 check_mips_64(ctx);
29463 gen_st(ctx, op, rt, rs, imm);
29464 break;
29465 case OPC_SCD:
29466 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29467 check_insn(ctx, ISA_MIPS3);
29468 if (ctx->insn_flags & INSN_R5900) {
29469 check_insn_opc_user_only(ctx, INSN_R5900);
29471 check_mips_64(ctx);
29472 gen_st_cond(ctx, op, rt, rs, imm);
29473 break;
29474 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29475 if (ctx->insn_flags & ISA_MIPS32R6) {
29476 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29477 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29478 } else {
29479 /* OPC_DADDI */
29480 check_insn(ctx, ISA_MIPS3);
29481 check_mips_64(ctx);
29482 gen_arith_imm(ctx, op, rt, rs, imm);
29484 break;
29485 case OPC_DADDIU:
29486 check_insn(ctx, ISA_MIPS3);
29487 check_mips_64(ctx);
29488 gen_arith_imm(ctx, op, rt, rs, imm);
29489 break;
29490 #else
29491 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29492 if (ctx->insn_flags & ISA_MIPS32R6) {
29493 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29494 } else {
29495 MIPS_INVAL("major opcode");
29496 generate_exception_end(ctx, EXCP_RI);
29498 break;
29499 #endif
29500 case OPC_DAUI: /* OPC_JALX */
29501 if (ctx->insn_flags & ISA_MIPS32R6) {
29502 #if defined(TARGET_MIPS64)
29503 /* OPC_DAUI */
29504 check_mips_64(ctx);
29505 if (rs == 0) {
29506 generate_exception(ctx, EXCP_RI);
29507 } else if (rt != 0) {
29508 TCGv t0 = tcg_temp_new();
29509 gen_load_gpr(t0, rs);
29510 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29511 tcg_temp_free(t0);
29513 #else
29514 generate_exception_end(ctx, EXCP_RI);
29515 MIPS_INVAL("major opcode");
29516 #endif
29517 } else {
29518 /* OPC_JALX */
29519 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29520 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29521 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29523 break;
29524 case OPC_MSA: /* OPC_MDMX */
29525 if (ctx->insn_flags & INSN_R5900) {
29526 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29527 } else {
29528 /* MDMX: Not implemented. */
29529 gen_msa(env, ctx);
29531 break;
29532 case OPC_PCREL:
29533 check_insn(ctx, ISA_MIPS32R6);
29534 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29535 break;
29536 default: /* Invalid */
29537 MIPS_INVAL("major opcode");
29538 generate_exception_end(ctx, EXCP_RI);
29539 break;
29543 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29545 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29546 CPUMIPSState *env = cs->env_ptr;
29548 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29549 ctx->saved_pc = -1;
29550 ctx->insn_flags = env->insn_flags;
29551 ctx->CP0_Config1 = env->CP0_Config1;
29552 ctx->CP0_Config2 = env->CP0_Config2;
29553 ctx->CP0_Config3 = env->CP0_Config3;
29554 ctx->CP0_Config5 = env->CP0_Config5;
29555 ctx->btarget = 0;
29556 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29557 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29558 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29559 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29560 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29561 ctx->PAMask = env->PAMask;
29562 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29563 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29564 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29565 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29566 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29567 /* Restore delay slot state from the tb context. */
29568 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29569 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29570 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29571 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29572 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29573 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29574 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29575 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29576 restore_cpu_state(env, ctx);
29577 #ifdef CONFIG_USER_ONLY
29578 ctx->mem_idx = MIPS_HFLAG_UM;
29579 #else
29580 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29581 #endif
29582 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29583 MO_UNALN : MO_ALIGN;
29585 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29586 ctx->hflags);
29589 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29593 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29595 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29597 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29598 ctx->btarget);
29601 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29602 const CPUBreakpoint *bp)
29604 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29606 save_cpu_state(ctx, 1);
29607 ctx->base.is_jmp = DISAS_NORETURN;
29608 gen_helper_raise_exception_debug(cpu_env);
29609 /* The address covered by the breakpoint must be included in
29610 [tb->pc, tb->pc + tb->size) in order to for it to be
29611 properly cleared -- thus we increment the PC here so that
29612 the logic setting tb->size below does the right thing. */
29613 ctx->base.pc_next += 4;
29614 return true;
29617 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29619 CPUMIPSState *env = cs->env_ptr;
29620 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29621 int insn_bytes;
29622 int is_slot;
29624 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29625 if (ctx->insn_flags & ISA_NANOMIPS32) {
29626 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29627 insn_bytes = decode_nanomips_opc(env, ctx);
29628 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29629 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
29630 insn_bytes = 4;
29631 decode_opc(env, ctx);
29632 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29633 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29634 insn_bytes = decode_micromips_opc(env, ctx);
29635 } else if (ctx->insn_flags & ASE_MIPS16) {
29636 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29637 insn_bytes = decode_mips16_opc(env, ctx);
29638 } else {
29639 generate_exception_end(ctx, EXCP_RI);
29640 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29641 return;
29644 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29645 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29646 MIPS_HFLAG_FBNSLOT))) {
29647 /* force to generate branch as there is neither delay nor
29648 forbidden slot */
29649 is_slot = 1;
29651 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29652 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29653 /* Force to generate branch as microMIPS R6 doesn't restrict
29654 branches in the forbidden slot. */
29655 is_slot = 1;
29658 if (is_slot) {
29659 gen_branch(ctx, insn_bytes);
29661 ctx->base.pc_next += insn_bytes;
29663 if (ctx->base.is_jmp != DISAS_NEXT) {
29664 return;
29666 /* Execute a branch and its delay slot as a single instruction.
29667 This is what GDB expects and is consistent with what the
29668 hardware does (e.g. if a delay slot instruction faults, the
29669 reported PC is the PC of the branch). */
29670 if (ctx->base.singlestep_enabled &&
29671 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29672 ctx->base.is_jmp = DISAS_TOO_MANY;
29674 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29675 ctx->base.is_jmp = DISAS_TOO_MANY;
29679 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29681 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29683 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29684 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29685 gen_helper_raise_exception_debug(cpu_env);
29686 } else {
29687 switch (ctx->base.is_jmp) {
29688 case DISAS_STOP:
29689 gen_save_pc(ctx->base.pc_next);
29690 tcg_gen_lookup_and_goto_ptr();
29691 break;
29692 case DISAS_NEXT:
29693 case DISAS_TOO_MANY:
29694 save_cpu_state(ctx, 0);
29695 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29696 break;
29697 case DISAS_EXIT:
29698 tcg_gen_exit_tb(NULL, 0);
29699 break;
29700 case DISAS_NORETURN:
29701 break;
29702 default:
29703 g_assert_not_reached();
29708 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29710 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29711 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29714 static const TranslatorOps mips_tr_ops = {
29715 .init_disas_context = mips_tr_init_disas_context,
29716 .tb_start = mips_tr_tb_start,
29717 .insn_start = mips_tr_insn_start,
29718 .breakpoint_check = mips_tr_breakpoint_check,
29719 .translate_insn = mips_tr_translate_insn,
29720 .tb_stop = mips_tr_tb_stop,
29721 .disas_log = mips_tr_disas_log,
29724 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
29726 DisasContext ctx;
29728 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
29731 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
29732 int flags)
29734 int i;
29735 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
29737 #define printfpr(fp) \
29738 do { \
29739 if (is_fpu64) \
29740 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29741 " fd:%13g fs:%13g psu: %13g\n", \
29742 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29743 (double)(fp)->fd, \
29744 (double)(fp)->fs[FP_ENDIAN_IDX], \
29745 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29746 else { \
29747 fpr_t tmp; \
29748 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29749 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29750 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29751 " fd:%13g fs:%13g psu:%13g\n", \
29752 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29753 (double)tmp.fd, \
29754 (double)tmp.fs[FP_ENDIAN_IDX], \
29755 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29757 } while(0)
29760 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29761 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
29762 get_float_exception_flags(&env->active_fpu.fp_status));
29763 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29764 fpu_fprintf(f, "%3s: ", fregnames[i]);
29765 printfpr(&env->active_fpu.fpr[i]);
29768 #undef printfpr
29771 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
29772 int flags)
29774 MIPSCPU *cpu = MIPS_CPU(cs);
29775 CPUMIPSState *env = &cpu->env;
29776 int i;
29778 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29779 " LO=0x" TARGET_FMT_lx " ds %04x "
29780 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
29781 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29782 env->hflags, env->btarget, env->bcond);
29783 for (i = 0; i < 32; i++) {
29784 if ((i & 3) == 0)
29785 cpu_fprintf(f, "GPR%02d:", i);
29786 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
29787 if ((i & 3) == 3)
29788 cpu_fprintf(f, "\n");
29791 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
29792 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
29793 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
29794 PRIx64 "\n",
29795 env->CP0_Config0, env->CP0_Config1, env->lladdr);
29796 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
29797 env->CP0_Config2, env->CP0_Config3);
29798 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
29799 env->CP0_Config4, env->CP0_Config5);
29800 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
29801 fpu_dump_state(env, f, cpu_fprintf, flags);
29805 void mips_tcg_init(void)
29807 int i;
29809 cpu_gpr[0] = NULL;
29810 for (i = 1; i < 32; i++)
29811 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
29812 offsetof(CPUMIPSState, active_tc.gpr[i]),
29813 regnames[i]);
29815 for (i = 0; i < 32; i++) {
29816 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
29817 msa_wr_d[i * 2] =
29818 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
29819 /* The scalar floating-point unit (FPU) registers are mapped on
29820 * the MSA vector registers. */
29821 fpu_f64[i] = msa_wr_d[i * 2];
29822 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
29823 msa_wr_d[i * 2 + 1] =
29824 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
29827 cpu_PC = tcg_global_mem_new(cpu_env,
29828 offsetof(CPUMIPSState, active_tc.PC), "PC");
29829 for (i = 0; i < MIPS_DSP_ACC; i++) {
29830 cpu_HI[i] = tcg_global_mem_new(cpu_env,
29831 offsetof(CPUMIPSState, active_tc.HI[i]),
29832 regnames_HI[i]);
29833 cpu_LO[i] = tcg_global_mem_new(cpu_env,
29834 offsetof(CPUMIPSState, active_tc.LO[i]),
29835 regnames_LO[i]);
29837 cpu_dspctrl = tcg_global_mem_new(cpu_env,
29838 offsetof(CPUMIPSState, active_tc.DSPControl),
29839 "DSPControl");
29840 bcond = tcg_global_mem_new(cpu_env,
29841 offsetof(CPUMIPSState, bcond), "bcond");
29842 btarget = tcg_global_mem_new(cpu_env,
29843 offsetof(CPUMIPSState, btarget), "btarget");
29844 hflags = tcg_global_mem_new_i32(cpu_env,
29845 offsetof(CPUMIPSState, hflags), "hflags");
29847 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
29848 offsetof(CPUMIPSState, active_fpu.fcr0),
29849 "fcr0");
29850 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
29851 offsetof(CPUMIPSState, active_fpu.fcr31),
29852 "fcr31");
29854 #if defined(TARGET_MIPS64)
29855 cpu_mmr[0] = NULL;
29856 for (i = 1; i < 32; i++) {
29857 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
29858 offsetof(CPUMIPSState,
29859 active_tc.mmr[i]),
29860 regnames[i]);
29862 #endif
29864 #if !defined(TARGET_MIPS64)
29865 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29866 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29867 offsetof(CPUMIPSState,
29868 active_tc.mxu_gpr[i]),
29869 mxuregnames[i]);
29872 mxu_CR = tcg_global_mem_new(cpu_env,
29873 offsetof(CPUMIPSState, active_tc.mxu_cr),
29874 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
29875 #endif
29878 #include "translate_init.inc.c"
29880 void cpu_mips_realize_env(CPUMIPSState *env)
29882 env->exception_base = (int32_t)0xBFC00000;
29884 #ifndef CONFIG_USER_ONLY
29885 mmu_init(env, env->cpu_model);
29886 #endif
29887 fpu_init(env, env->cpu_model);
29888 mvp_init(env, env->cpu_model);
29891 bool cpu_supports_cps_smp(const char *cpu_type)
29893 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29894 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
29897 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
29899 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29900 return (mcc->cpu_def->insn_flags & isa) != 0;
29903 void cpu_set_exception_base(int vp_index, target_ulong address)
29905 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
29906 vp->env.exception_base = address;
29909 void cpu_state_reset(CPUMIPSState *env)
29911 MIPSCPU *cpu = mips_env_get_cpu(env);
29912 CPUState *cs = CPU(cpu);
29914 /* Reset registers to their default values */
29915 env->CP0_PRid = env->cpu_model->CP0_PRid;
29916 env->CP0_Config0 = env->cpu_model->CP0_Config0;
29917 #ifdef TARGET_WORDS_BIGENDIAN
29918 env->CP0_Config0 |= (1 << CP0C0_BE);
29919 #endif
29920 env->CP0_Config1 = env->cpu_model->CP0_Config1;
29921 env->CP0_Config2 = env->cpu_model->CP0_Config2;
29922 env->CP0_Config3 = env->cpu_model->CP0_Config3;
29923 env->CP0_Config4 = env->cpu_model->CP0_Config4;
29924 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
29925 env->CP0_Config5 = env->cpu_model->CP0_Config5;
29926 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
29927 env->CP0_Config6 = env->cpu_model->CP0_Config6;
29928 env->CP0_Config7 = env->cpu_model->CP0_Config7;
29929 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
29930 << env->cpu_model->CP0_LLAddr_shift;
29931 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
29932 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
29933 env->CCRes = env->cpu_model->CCRes;
29934 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
29935 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
29936 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
29937 env->current_tc = 0;
29938 env->SEGBITS = env->cpu_model->SEGBITS;
29939 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
29940 #if defined(TARGET_MIPS64)
29941 if (env->cpu_model->insn_flags & ISA_MIPS3) {
29942 env->SEGMask |= 3ULL << 62;
29944 #endif
29945 env->PABITS = env->cpu_model->PABITS;
29946 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
29947 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
29948 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
29949 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
29950 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
29951 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
29952 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
29953 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
29954 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
29955 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
29956 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
29957 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
29958 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
29959 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
29960 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
29961 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
29962 env->msair = env->cpu_model->MSAIR;
29963 env->insn_flags = env->cpu_model->insn_flags;
29965 #if defined(CONFIG_USER_ONLY)
29966 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
29967 # ifdef TARGET_MIPS64
29968 /* Enable 64-bit register mode. */
29969 env->CP0_Status |= (1 << CP0St_PX);
29970 # endif
29971 # ifdef TARGET_ABI_MIPSN64
29972 /* Enable 64-bit address mode. */
29973 env->CP0_Status |= (1 << CP0St_UX);
29974 # endif
29975 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
29976 hardware registers. */
29977 env->CP0_HWREna |= 0x0000000F;
29978 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
29979 env->CP0_Status |= (1 << CP0St_CU1);
29981 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
29982 env->CP0_Status |= (1 << CP0St_MX);
29984 # if defined(TARGET_MIPS64)
29985 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
29986 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
29987 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
29988 env->CP0_Status |= (1 << CP0St_FR);
29990 # endif
29991 #else
29992 if (env->hflags & MIPS_HFLAG_BMASK) {
29993 /* If the exception was raised from a delay slot,
29994 come back to the jump. */
29995 env->CP0_ErrorEPC = (env->active_tc.PC
29996 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
29997 } else {
29998 env->CP0_ErrorEPC = env->active_tc.PC;
30000 env->active_tc.PC = env->exception_base;
30001 env->CP0_Random = env->tlb->nb_tlb - 1;
30002 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30003 env->CP0_Wired = 0;
30004 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30005 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30006 if (mips_um_ksegs_enabled()) {
30007 env->CP0_EBase |= 0x40000000;
30008 } else {
30009 env->CP0_EBase |= (int32_t)0x80000000;
30011 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30012 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30014 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30015 0x3ff : 0xff;
30016 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30017 /* vectored interrupts not implemented, timer on int 7,
30018 no performance counters. */
30019 env->CP0_IntCtl = 0xe0000000;
30021 int i;
30023 for (i = 0; i < 7; i++) {
30024 env->CP0_WatchLo[i] = 0;
30025 env->CP0_WatchHi[i] = 0x80000000;
30027 env->CP0_WatchLo[7] = 0;
30028 env->CP0_WatchHi[7] = 0;
30030 /* Count register increments in debug mode, EJTAG version 1 */
30031 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30033 cpu_mips_store_count(env, 1);
30035 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30036 int i;
30038 /* Only TC0 on VPE 0 starts as active. */
30039 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30040 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30041 env->tcs[i].CP0_TCHalt = 1;
30043 env->active_tc.CP0_TCHalt = 1;
30044 cs->halted = 1;
30046 if (cs->cpu_index == 0) {
30047 /* VPE0 starts up enabled. */
30048 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30049 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30051 /* TC0 starts up unhalted. */
30052 cs->halted = 0;
30053 env->active_tc.CP0_TCHalt = 0;
30054 env->tcs[0].CP0_TCHalt = 0;
30055 /* With thread 0 active. */
30056 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30057 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30062 * Configure default legacy segmentation control. We use this regardless of
30063 * whether segmentation control is presented to the guest.
30065 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30066 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30067 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30068 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30069 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30070 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30071 (2 << CP0SC_C);
30072 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30073 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30074 (3 << CP0SC_C)) << 16;
30075 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30076 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30077 (1 << CP0SC_EU) | (2 << CP0SC_C);
30078 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30079 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30080 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30081 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30082 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30083 #endif
30084 if ((env->insn_flags & ISA_MIPS32R6) &&
30085 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30086 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30087 env->CP0_Status |= (1 << CP0St_FR);
30090 if (env->insn_flags & ISA_MIPS32R6) {
30091 /* PTW = 1 */
30092 env->CP0_PWSize = 0x40;
30093 /* GDI = 12 */
30094 /* UDI = 12 */
30095 /* MDI = 12 */
30096 /* PRI = 12 */
30097 /* PTEI = 2 */
30098 env->CP0_PWField = 0x0C30C302;
30099 } else {
30100 /* GDI = 0 */
30101 /* UDI = 0 */
30102 /* MDI = 0 */
30103 /* PRI = 0 */
30104 /* PTEI = 2 */
30105 env->CP0_PWField = 0x02;
30108 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30109 /* microMIPS on reset when Config3.ISA is 3 */
30110 env->hflags |= MIPS_HFLAG_M16;
30113 /* MSA */
30114 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30115 msa_reset(env);
30118 compute_hflags(env);
30119 restore_fp_status(env);
30120 restore_pamask(env);
30121 cs->exception_index = EXCP_NONE;
30123 if (semihosting_get_argc()) {
30124 /* UHI interface can be used to obtain argc and argv */
30125 env->active_tc.gpr[4] = -1;
30129 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30130 target_ulong *data)
30132 env->active_tc.PC = data[0];
30133 env->hflags &= ~MIPS_HFLAG_BMASK;
30134 env->hflags |= data[1];
30135 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30136 case MIPS_HFLAG_BR:
30137 break;
30138 case MIPS_HFLAG_BC:
30139 case MIPS_HFLAG_BL:
30140 case MIPS_HFLAG_B:
30141 env->btarget = data[2];
30142 break;