chardev: split up qmp_chardev_open_socket connection code
[qemu/ar7.git] / target / mips / translate.c
blobe9b5d1d8601362d919fa25e7a298aa446ec9ec07
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, bool eva)
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 eva ? MIPS_HFLAG_UM : 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_RT3(op) ((op >> 7) & 0x7)
18464 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18465 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18466 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18467 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18469 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18470 static inline int decode_gpr_gpr3(int r)
18472 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18474 return map[r & 0x7];
18477 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18478 static inline int decode_gpr_gpr3_src_store(int r)
18480 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18482 return map[r & 0x7];
18485 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18486 static inline int decode_gpr_gpr4(int r)
18488 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18489 16, 17, 18, 19, 20, 21, 22, 23 };
18491 return map[r & 0xf];
18494 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18495 static inline int decode_gpr_gpr4_zero(int r)
18497 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18498 16, 17, 18, 19, 20, 21, 22, 23 };
18500 return map[r & 0xf];
18504 static void gen_adjust_sp(DisasContext *ctx, int u)
18506 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18509 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18510 uint8_t gp, uint16_t u)
18512 int counter = 0;
18513 TCGv va = tcg_temp_new();
18514 TCGv t0 = tcg_temp_new();
18516 while (counter != count) {
18517 bool use_gp = gp && (counter == count - 1);
18518 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18519 int this_offset = -((counter + 1) << 2);
18520 gen_base_offset_addr(ctx, va, 29, this_offset);
18521 gen_load_gpr(t0, this_rt);
18522 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18523 (MO_TEUL | ctx->default_tcg_memop_mask));
18524 counter++;
18527 /* adjust stack pointer */
18528 gen_adjust_sp(ctx, -u);
18530 tcg_temp_free(t0);
18531 tcg_temp_free(va);
18534 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18535 uint8_t gp, uint16_t u)
18537 int counter = 0;
18538 TCGv va = tcg_temp_new();
18539 TCGv t0 = tcg_temp_new();
18541 while (counter != count) {
18542 bool use_gp = gp && (counter == count - 1);
18543 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18544 int this_offset = u - ((counter + 1) << 2);
18545 gen_base_offset_addr(ctx, va, 29, this_offset);
18546 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18547 ctx->default_tcg_memop_mask);
18548 tcg_gen_ext32s_tl(t0, t0);
18549 gen_store_gpr(t0, this_rt);
18550 counter++;
18553 /* adjust stack pointer */
18554 gen_adjust_sp(ctx, u);
18556 tcg_temp_free(t0);
18557 tcg_temp_free(va);
18560 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18562 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18563 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18565 switch (extract32(ctx->opcode, 2, 2)) {
18566 case NM_NOT16:
18567 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18568 break;
18569 case NM_AND16:
18570 gen_logic(ctx, OPC_AND, rt, rt, rs);
18571 break;
18572 case NM_XOR16:
18573 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18574 break;
18575 case NM_OR16:
18576 gen_logic(ctx, OPC_OR, rt, rt, rs);
18577 break;
18581 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18583 int rt = extract32(ctx->opcode, 21, 5);
18584 int rs = extract32(ctx->opcode, 16, 5);
18585 int rd = extract32(ctx->opcode, 11, 5);
18587 switch (extract32(ctx->opcode, 3, 7)) {
18588 case NM_P_TRAP:
18589 switch (extract32(ctx->opcode, 10, 1)) {
18590 case NM_TEQ:
18591 check_nms(ctx);
18592 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18593 break;
18594 case NM_TNE:
18595 check_nms(ctx);
18596 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18597 break;
18599 break;
18600 case NM_RDHWR:
18601 check_nms(ctx);
18602 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18603 break;
18604 case NM_SEB:
18605 check_nms(ctx);
18606 gen_bshfl(ctx, OPC_SEB, rs, rt);
18607 break;
18608 case NM_SEH:
18609 gen_bshfl(ctx, OPC_SEH, rs, rt);
18610 break;
18611 case NM_SLLV:
18612 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18613 break;
18614 case NM_SRLV:
18615 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18616 break;
18617 case NM_SRAV:
18618 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18619 break;
18620 case NM_ROTRV:
18621 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18622 break;
18623 case NM_ADD:
18624 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18625 break;
18626 case NM_ADDU:
18627 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18628 break;
18629 case NM_SUB:
18630 check_nms(ctx);
18631 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18632 break;
18633 case NM_SUBU:
18634 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18635 break;
18636 case NM_P_CMOVE:
18637 switch (extract32(ctx->opcode, 10, 1)) {
18638 case NM_MOVZ:
18639 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18640 break;
18641 case NM_MOVN:
18642 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18643 break;
18645 break;
18646 case NM_AND:
18647 gen_logic(ctx, OPC_AND, rd, rs, rt);
18648 break;
18649 case NM_OR:
18650 gen_logic(ctx, OPC_OR, rd, rs, rt);
18651 break;
18652 case NM_NOR:
18653 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18654 break;
18655 case NM_XOR:
18656 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18657 break;
18658 case NM_SLT:
18659 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18660 break;
18661 case NM_P_SLTU:
18662 if (rd == 0) {
18663 /* P_DVP */
18664 #ifndef CONFIG_USER_ONLY
18665 TCGv t0 = tcg_temp_new();
18666 switch (extract32(ctx->opcode, 10, 1)) {
18667 case NM_DVP:
18668 if (ctx->vp) {
18669 check_cp0_enabled(ctx);
18670 gen_helper_dvp(t0, cpu_env);
18671 gen_store_gpr(t0, rt);
18673 break;
18674 case NM_EVP:
18675 if (ctx->vp) {
18676 check_cp0_enabled(ctx);
18677 gen_helper_evp(t0, cpu_env);
18678 gen_store_gpr(t0, rt);
18680 break;
18682 tcg_temp_free(t0);
18683 #endif
18684 } else {
18685 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18687 break;
18688 case NM_SOV:
18690 TCGv t0 = tcg_temp_new();
18691 TCGv t1 = tcg_temp_new();
18692 TCGv t2 = tcg_temp_new();
18694 gen_load_gpr(t1, rs);
18695 gen_load_gpr(t2, rt);
18696 tcg_gen_add_tl(t0, t1, t2);
18697 tcg_gen_ext32s_tl(t0, t0);
18698 tcg_gen_xor_tl(t1, t1, t2);
18699 tcg_gen_xor_tl(t2, t0, t2);
18700 tcg_gen_andc_tl(t1, t2, t1);
18702 /* operands of same sign, result different sign */
18703 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18704 gen_store_gpr(t0, rd);
18706 tcg_temp_free(t0);
18707 tcg_temp_free(t1);
18708 tcg_temp_free(t2);
18710 break;
18711 case NM_MUL:
18712 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18713 break;
18714 case NM_MUH:
18715 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18716 break;
18717 case NM_MULU:
18718 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18719 break;
18720 case NM_MUHU:
18721 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18722 break;
18723 case NM_DIV:
18724 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18725 break;
18726 case NM_MOD:
18727 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18728 break;
18729 case NM_DIVU:
18730 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18731 break;
18732 case NM_MODU:
18733 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18734 break;
18735 #ifndef CONFIG_USER_ONLY
18736 case NM_MFC0:
18737 check_cp0_enabled(ctx);
18738 if (rt == 0) {
18739 /* Treat as NOP. */
18740 break;
18742 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18743 break;
18744 case NM_MTC0:
18745 check_cp0_enabled(ctx);
18747 TCGv t0 = tcg_temp_new();
18749 gen_load_gpr(t0, rt);
18750 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18751 tcg_temp_free(t0);
18753 break;
18754 case NM_D_E_MT_VPE:
18756 uint8_t sc = extract32(ctx->opcode, 10, 1);
18757 TCGv t0 = tcg_temp_new();
18759 switch (sc) {
18760 case 0:
18761 if (rs == 1) {
18762 /* DMT */
18763 check_cp0_mt(ctx);
18764 gen_helper_dmt(t0);
18765 gen_store_gpr(t0, rt);
18766 } else if (rs == 0) {
18767 /* DVPE */
18768 check_cp0_mt(ctx);
18769 gen_helper_dvpe(t0, cpu_env);
18770 gen_store_gpr(t0, rt);
18771 } else {
18772 generate_exception_end(ctx, EXCP_RI);
18774 break;
18775 case 1:
18776 if (rs == 1) {
18777 /* EMT */
18778 check_cp0_mt(ctx);
18779 gen_helper_emt(t0);
18780 gen_store_gpr(t0, rt);
18781 } else if (rs == 0) {
18782 /* EVPE */
18783 check_cp0_mt(ctx);
18784 gen_helper_evpe(t0, cpu_env);
18785 gen_store_gpr(t0, rt);
18786 } else {
18787 generate_exception_end(ctx, EXCP_RI);
18789 break;
18792 tcg_temp_free(t0);
18794 break;
18795 case NM_FORK:
18796 check_mt(ctx);
18798 TCGv t0 = tcg_temp_new();
18799 TCGv t1 = tcg_temp_new();
18801 gen_load_gpr(t0, rt);
18802 gen_load_gpr(t1, rs);
18803 gen_helper_fork(t0, t1);
18804 tcg_temp_free(t0);
18805 tcg_temp_free(t1);
18807 break;
18808 case NM_MFTR:
18809 case NM_MFHTR:
18810 check_cp0_enabled(ctx);
18811 if (rd == 0) {
18812 /* Treat as NOP. */
18813 return;
18815 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18816 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18817 break;
18818 case NM_MTTR:
18819 case NM_MTHTR:
18820 check_cp0_enabled(ctx);
18821 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18822 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18823 break;
18824 case NM_YIELD:
18825 check_mt(ctx);
18827 TCGv t0 = tcg_temp_new();
18829 gen_load_gpr(t0, rs);
18830 gen_helper_yield(t0, cpu_env, t0);
18831 gen_store_gpr(t0, rt);
18832 tcg_temp_free(t0);
18834 break;
18835 #endif
18836 default:
18837 generate_exception_end(ctx, EXCP_RI);
18838 break;
18842 /* dsp */
18843 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18844 int ret, int v1, int v2)
18846 TCGv_i32 t0;
18847 TCGv v0_t;
18848 TCGv v1_t;
18850 t0 = tcg_temp_new_i32();
18852 v0_t = tcg_temp_new();
18853 v1_t = tcg_temp_new();
18855 tcg_gen_movi_i32(t0, v2 >> 3);
18857 gen_load_gpr(v0_t, ret);
18858 gen_load_gpr(v1_t, v1);
18860 switch (opc) {
18861 case NM_MAQ_S_W_PHR:
18862 check_dsp(ctx);
18863 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18864 break;
18865 case NM_MAQ_S_W_PHL:
18866 check_dsp(ctx);
18867 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18868 break;
18869 case NM_MAQ_SA_W_PHR:
18870 check_dsp(ctx);
18871 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18872 break;
18873 case NM_MAQ_SA_W_PHL:
18874 check_dsp(ctx);
18875 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18876 break;
18877 default:
18878 generate_exception_end(ctx, EXCP_RI);
18879 break;
18882 tcg_temp_free_i32(t0);
18884 tcg_temp_free(v0_t);
18885 tcg_temp_free(v1_t);
18889 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18890 int ret, int v1, int v2)
18892 int16_t imm;
18893 TCGv t0 = tcg_temp_new();
18894 TCGv t1 = tcg_temp_new();
18895 TCGv v0_t = tcg_temp_new();
18897 gen_load_gpr(v0_t, v1);
18899 switch (opc) {
18900 case NM_POOL32AXF_1_0:
18901 check_dsp(ctx);
18902 switch (extract32(ctx->opcode, 12, 2)) {
18903 case NM_MFHI:
18904 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18905 break;
18906 case NM_MFLO:
18907 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18908 break;
18909 case NM_MTHI:
18910 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18911 break;
18912 case NM_MTLO:
18913 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18914 break;
18916 break;
18917 case NM_POOL32AXF_1_1:
18918 check_dsp(ctx);
18919 switch (extract32(ctx->opcode, 12, 2)) {
18920 case NM_MTHLIP:
18921 tcg_gen_movi_tl(t0, v2);
18922 gen_helper_mthlip(t0, v0_t, cpu_env);
18923 break;
18924 case NM_SHILOV:
18925 tcg_gen_movi_tl(t0, v2 >> 3);
18926 gen_helper_shilo(t0, v0_t, cpu_env);
18927 break;
18928 default:
18929 generate_exception_end(ctx, EXCP_RI);
18930 break;
18932 break;
18933 case NM_POOL32AXF_1_3:
18934 check_dsp(ctx);
18935 imm = extract32(ctx->opcode, 14, 7);
18936 switch (extract32(ctx->opcode, 12, 2)) {
18937 case NM_RDDSP:
18938 tcg_gen_movi_tl(t0, imm);
18939 gen_helper_rddsp(t0, t0, cpu_env);
18940 gen_store_gpr(t0, ret);
18941 break;
18942 case NM_WRDSP:
18943 gen_load_gpr(t0, ret);
18944 tcg_gen_movi_tl(t1, imm);
18945 gen_helper_wrdsp(t0, t1, cpu_env);
18946 break;
18947 case NM_EXTP:
18948 tcg_gen_movi_tl(t0, v2 >> 3);
18949 tcg_gen_movi_tl(t1, v1);
18950 gen_helper_extp(t0, t0, t1, cpu_env);
18951 gen_store_gpr(t0, ret);
18952 break;
18953 case NM_EXTPDP:
18954 tcg_gen_movi_tl(t0, v2 >> 3);
18955 tcg_gen_movi_tl(t1, v1);
18956 gen_helper_extpdp(t0, t0, t1, cpu_env);
18957 gen_store_gpr(t0, ret);
18958 break;
18960 break;
18961 case NM_POOL32AXF_1_4:
18962 check_dsp(ctx);
18963 tcg_gen_movi_tl(t0, v2 >> 2);
18964 switch (extract32(ctx->opcode, 12, 1)) {
18965 case NM_SHLL_QB:
18966 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18967 gen_store_gpr(t0, ret);
18968 break;
18969 case NM_SHRL_QB:
18970 gen_helper_shrl_qb(t0, t0, v0_t);
18971 gen_store_gpr(t0, ret);
18972 break;
18974 break;
18975 case NM_POOL32AXF_1_5:
18976 opc = extract32(ctx->opcode, 12, 2);
18977 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18978 break;
18979 case NM_POOL32AXF_1_7:
18980 check_dsp(ctx);
18981 tcg_gen_movi_tl(t0, v2 >> 3);
18982 tcg_gen_movi_tl(t1, v1);
18983 switch (extract32(ctx->opcode, 12, 2)) {
18984 case NM_EXTR_W:
18985 gen_helper_extr_w(t0, t0, t1, cpu_env);
18986 gen_store_gpr(t0, ret);
18987 break;
18988 case NM_EXTR_R_W:
18989 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18990 gen_store_gpr(t0, ret);
18991 break;
18992 case NM_EXTR_RS_W:
18993 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18994 gen_store_gpr(t0, ret);
18995 break;
18996 case NM_EXTR_S_H:
18997 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18998 gen_store_gpr(t0, ret);
18999 break;
19001 break;
19002 default:
19003 generate_exception_end(ctx, EXCP_RI);
19004 break;
19007 tcg_temp_free(t0);
19008 tcg_temp_free(t1);
19009 tcg_temp_free(v0_t);
19012 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19013 TCGv v0, TCGv v1, int rd)
19015 TCGv_i32 t0;
19017 t0 = tcg_temp_new_i32();
19019 tcg_gen_movi_i32(t0, rd >> 3);
19021 switch (opc) {
19022 case NM_POOL32AXF_2_0_7:
19023 switch (extract32(ctx->opcode, 9, 3)) {
19024 case NM_DPA_W_PH:
19025 check_dsp_r2(ctx);
19026 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19027 break;
19028 case NM_DPAQ_S_W_PH:
19029 check_dsp(ctx);
19030 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19031 break;
19032 case NM_DPS_W_PH:
19033 check_dsp_r2(ctx);
19034 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19035 break;
19036 case NM_DPSQ_S_W_PH:
19037 check_dsp(ctx);
19038 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19039 break;
19040 default:
19041 generate_exception_end(ctx, EXCP_RI);
19042 break;
19044 break;
19045 case NM_POOL32AXF_2_8_15:
19046 switch (extract32(ctx->opcode, 9, 3)) {
19047 case NM_DPAX_W_PH:
19048 check_dsp_r2(ctx);
19049 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19050 break;
19051 case NM_DPAQ_SA_L_W:
19052 check_dsp(ctx);
19053 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19054 break;
19055 case NM_DPSX_W_PH:
19056 check_dsp_r2(ctx);
19057 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19058 break;
19059 case NM_DPSQ_SA_L_W:
19060 check_dsp(ctx);
19061 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19062 break;
19063 default:
19064 generate_exception_end(ctx, EXCP_RI);
19065 break;
19067 break;
19068 case NM_POOL32AXF_2_16_23:
19069 switch (extract32(ctx->opcode, 9, 3)) {
19070 case NM_DPAU_H_QBL:
19071 check_dsp(ctx);
19072 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19073 break;
19074 case NM_DPAQX_S_W_PH:
19075 check_dsp_r2(ctx);
19076 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19077 break;
19078 case NM_DPSU_H_QBL:
19079 check_dsp(ctx);
19080 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19081 break;
19082 case NM_DPSQX_S_W_PH:
19083 check_dsp_r2(ctx);
19084 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19085 break;
19086 case NM_MULSA_W_PH:
19087 check_dsp_r2(ctx);
19088 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19089 break;
19090 default:
19091 generate_exception_end(ctx, EXCP_RI);
19092 break;
19094 break;
19095 case NM_POOL32AXF_2_24_31:
19096 switch (extract32(ctx->opcode, 9, 3)) {
19097 case NM_DPAU_H_QBR:
19098 check_dsp(ctx);
19099 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19100 break;
19101 case NM_DPAQX_SA_W_PH:
19102 check_dsp_r2(ctx);
19103 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19104 break;
19105 case NM_DPSU_H_QBR:
19106 check_dsp(ctx);
19107 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19108 break;
19109 case NM_DPSQX_SA_W_PH:
19110 check_dsp_r2(ctx);
19111 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19112 break;
19113 case NM_MULSAQ_S_W_PH:
19114 check_dsp(ctx);
19115 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19116 break;
19117 default:
19118 generate_exception_end(ctx, EXCP_RI);
19119 break;
19121 break;
19122 default:
19123 generate_exception_end(ctx, EXCP_RI);
19124 break;
19127 tcg_temp_free_i32(t0);
19130 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19131 int rt, int rs, int rd)
19133 int ret = rt;
19134 TCGv t0 = tcg_temp_new();
19135 TCGv t1 = tcg_temp_new();
19136 TCGv v0_t = tcg_temp_new();
19137 TCGv v1_t = tcg_temp_new();
19139 gen_load_gpr(v0_t, rt);
19140 gen_load_gpr(v1_t, rs);
19142 switch (opc) {
19143 case NM_POOL32AXF_2_0_7:
19144 switch (extract32(ctx->opcode, 9, 3)) {
19145 case NM_DPA_W_PH:
19146 case NM_DPAQ_S_W_PH:
19147 case NM_DPS_W_PH:
19148 case NM_DPSQ_S_W_PH:
19149 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19150 break;
19151 case NM_BALIGN:
19152 check_dsp_r2(ctx);
19153 if (rt != 0) {
19154 gen_load_gpr(t0, rs);
19155 rd &= 3;
19156 if (rd != 0 && rd != 2) {
19157 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19158 tcg_gen_ext32u_tl(t0, t0);
19159 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19160 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19162 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19164 break;
19165 case NM_MADD:
19166 check_dsp(ctx);
19168 int acc = extract32(ctx->opcode, 14, 2);
19169 TCGv_i64 t2 = tcg_temp_new_i64();
19170 TCGv_i64 t3 = tcg_temp_new_i64();
19172 gen_load_gpr(t0, rt);
19173 gen_load_gpr(t1, rs);
19174 tcg_gen_ext_tl_i64(t2, t0);
19175 tcg_gen_ext_tl_i64(t3, t1);
19176 tcg_gen_mul_i64(t2, t2, t3);
19177 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19178 tcg_gen_add_i64(t2, t2, t3);
19179 tcg_temp_free_i64(t3);
19180 gen_move_low32(cpu_LO[acc], t2);
19181 gen_move_high32(cpu_HI[acc], t2);
19182 tcg_temp_free_i64(t2);
19184 break;
19185 case NM_MULT:
19186 check_dsp(ctx);
19188 int acc = extract32(ctx->opcode, 14, 2);
19189 TCGv_i32 t2 = tcg_temp_new_i32();
19190 TCGv_i32 t3 = tcg_temp_new_i32();
19192 gen_load_gpr(t0, rs);
19193 gen_load_gpr(t1, rt);
19194 tcg_gen_trunc_tl_i32(t2, t0);
19195 tcg_gen_trunc_tl_i32(t3, t1);
19196 tcg_gen_muls2_i32(t2, t3, t2, t3);
19197 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19198 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19199 tcg_temp_free_i32(t2);
19200 tcg_temp_free_i32(t3);
19202 break;
19203 case NM_EXTRV_W:
19204 check_dsp(ctx);
19205 gen_load_gpr(v1_t, rs);
19206 tcg_gen_movi_tl(t0, rd >> 3);
19207 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19208 gen_store_gpr(t0, ret);
19209 break;
19211 break;
19212 case NM_POOL32AXF_2_8_15:
19213 switch (extract32(ctx->opcode, 9, 3)) {
19214 case NM_DPAX_W_PH:
19215 case NM_DPAQ_SA_L_W:
19216 case NM_DPSX_W_PH:
19217 case NM_DPSQ_SA_L_W:
19218 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19219 break;
19220 case NM_MADDU:
19221 check_dsp(ctx);
19223 int acc = extract32(ctx->opcode, 14, 2);
19224 TCGv_i64 t2 = tcg_temp_new_i64();
19225 TCGv_i64 t3 = tcg_temp_new_i64();
19227 gen_load_gpr(t0, rs);
19228 gen_load_gpr(t1, rt);
19229 tcg_gen_ext32u_tl(t0, t0);
19230 tcg_gen_ext32u_tl(t1, t1);
19231 tcg_gen_extu_tl_i64(t2, t0);
19232 tcg_gen_extu_tl_i64(t3, t1);
19233 tcg_gen_mul_i64(t2, t2, t3);
19234 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19235 tcg_gen_add_i64(t2, t2, t3);
19236 tcg_temp_free_i64(t3);
19237 gen_move_low32(cpu_LO[acc], t2);
19238 gen_move_high32(cpu_HI[acc], t2);
19239 tcg_temp_free_i64(t2);
19241 break;
19242 case NM_MULTU:
19243 check_dsp(ctx);
19245 int acc = extract32(ctx->opcode, 14, 2);
19246 TCGv_i32 t2 = tcg_temp_new_i32();
19247 TCGv_i32 t3 = tcg_temp_new_i32();
19249 gen_load_gpr(t0, rs);
19250 gen_load_gpr(t1, rt);
19251 tcg_gen_trunc_tl_i32(t2, t0);
19252 tcg_gen_trunc_tl_i32(t3, t1);
19253 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19254 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19255 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19256 tcg_temp_free_i32(t2);
19257 tcg_temp_free_i32(t3);
19259 break;
19260 case NM_EXTRV_R_W:
19261 check_dsp(ctx);
19262 tcg_gen_movi_tl(t0, rd >> 3);
19263 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19264 gen_store_gpr(t0, ret);
19265 break;
19266 default:
19267 generate_exception_end(ctx, EXCP_RI);
19268 break;
19270 break;
19271 case NM_POOL32AXF_2_16_23:
19272 switch (extract32(ctx->opcode, 9, 3)) {
19273 case NM_DPAU_H_QBL:
19274 case NM_DPAQX_S_W_PH:
19275 case NM_DPSU_H_QBL:
19276 case NM_DPSQX_S_W_PH:
19277 case NM_MULSA_W_PH:
19278 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19279 break;
19280 case NM_EXTPV:
19281 check_dsp(ctx);
19282 tcg_gen_movi_tl(t0, rd >> 3);
19283 gen_helper_extp(t0, t0, v1_t, cpu_env);
19284 gen_store_gpr(t0, ret);
19285 break;
19286 case NM_MSUB:
19287 check_dsp(ctx);
19289 int acc = extract32(ctx->opcode, 14, 2);
19290 TCGv_i64 t2 = tcg_temp_new_i64();
19291 TCGv_i64 t3 = tcg_temp_new_i64();
19293 gen_load_gpr(t0, rs);
19294 gen_load_gpr(t1, rt);
19295 tcg_gen_ext_tl_i64(t2, t0);
19296 tcg_gen_ext_tl_i64(t3, t1);
19297 tcg_gen_mul_i64(t2, t2, t3);
19298 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19299 tcg_gen_sub_i64(t2, t3, t2);
19300 tcg_temp_free_i64(t3);
19301 gen_move_low32(cpu_LO[acc], t2);
19302 gen_move_high32(cpu_HI[acc], t2);
19303 tcg_temp_free_i64(t2);
19305 break;
19306 case NM_EXTRV_RS_W:
19307 check_dsp(ctx);
19308 tcg_gen_movi_tl(t0, rd >> 3);
19309 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19310 gen_store_gpr(t0, ret);
19311 break;
19313 break;
19314 case NM_POOL32AXF_2_24_31:
19315 switch (extract32(ctx->opcode, 9, 3)) {
19316 case NM_DPAU_H_QBR:
19317 case NM_DPAQX_SA_W_PH:
19318 case NM_DPSU_H_QBR:
19319 case NM_DPSQX_SA_W_PH:
19320 case NM_MULSAQ_S_W_PH:
19321 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19322 break;
19323 case NM_EXTPDPV:
19324 check_dsp(ctx);
19325 tcg_gen_movi_tl(t0, rd >> 3);
19326 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19327 gen_store_gpr(t0, ret);
19328 break;
19329 case NM_MSUBU:
19330 check_dsp(ctx);
19332 int acc = extract32(ctx->opcode, 14, 2);
19333 TCGv_i64 t2 = tcg_temp_new_i64();
19334 TCGv_i64 t3 = tcg_temp_new_i64();
19336 gen_load_gpr(t0, rs);
19337 gen_load_gpr(t1, rt);
19338 tcg_gen_ext32u_tl(t0, t0);
19339 tcg_gen_ext32u_tl(t1, t1);
19340 tcg_gen_extu_tl_i64(t2, t0);
19341 tcg_gen_extu_tl_i64(t3, t1);
19342 tcg_gen_mul_i64(t2, t2, t3);
19343 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19344 tcg_gen_sub_i64(t2, t3, t2);
19345 tcg_temp_free_i64(t3);
19346 gen_move_low32(cpu_LO[acc], t2);
19347 gen_move_high32(cpu_HI[acc], t2);
19348 tcg_temp_free_i64(t2);
19350 break;
19351 case NM_EXTRV_S_H:
19352 check_dsp(ctx);
19353 tcg_gen_movi_tl(t0, rd >> 3);
19354 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19355 gen_store_gpr(t0, ret);
19356 break;
19358 break;
19359 default:
19360 generate_exception_end(ctx, EXCP_RI);
19361 break;
19364 tcg_temp_free(t0);
19365 tcg_temp_free(t1);
19367 tcg_temp_free(v0_t);
19368 tcg_temp_free(v1_t);
19371 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19372 int rt, int rs)
19374 int ret = rt;
19375 TCGv t0 = tcg_temp_new();
19376 TCGv v0_t = tcg_temp_new();
19378 gen_load_gpr(v0_t, rs);
19380 switch (opc) {
19381 case NM_ABSQ_S_QB:
19382 check_dsp_r2(ctx);
19383 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19384 gen_store_gpr(v0_t, ret);
19385 break;
19386 case NM_ABSQ_S_PH:
19387 check_dsp(ctx);
19388 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19389 gen_store_gpr(v0_t, ret);
19390 break;
19391 case NM_ABSQ_S_W:
19392 check_dsp(ctx);
19393 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19394 gen_store_gpr(v0_t, ret);
19395 break;
19396 case NM_PRECEQ_W_PHL:
19397 check_dsp(ctx);
19398 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19399 tcg_gen_ext32s_tl(v0_t, v0_t);
19400 gen_store_gpr(v0_t, ret);
19401 break;
19402 case NM_PRECEQ_W_PHR:
19403 check_dsp(ctx);
19404 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19405 tcg_gen_shli_tl(v0_t, v0_t, 16);
19406 tcg_gen_ext32s_tl(v0_t, v0_t);
19407 gen_store_gpr(v0_t, ret);
19408 break;
19409 case NM_PRECEQU_PH_QBL:
19410 check_dsp(ctx);
19411 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19412 gen_store_gpr(v0_t, ret);
19413 break;
19414 case NM_PRECEQU_PH_QBR:
19415 check_dsp(ctx);
19416 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19417 gen_store_gpr(v0_t, ret);
19418 break;
19419 case NM_PRECEQU_PH_QBLA:
19420 check_dsp(ctx);
19421 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19422 gen_store_gpr(v0_t, ret);
19423 break;
19424 case NM_PRECEQU_PH_QBRA:
19425 check_dsp(ctx);
19426 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19427 gen_store_gpr(v0_t, ret);
19428 break;
19429 case NM_PRECEU_PH_QBL:
19430 check_dsp(ctx);
19431 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19432 gen_store_gpr(v0_t, ret);
19433 break;
19434 case NM_PRECEU_PH_QBR:
19435 check_dsp(ctx);
19436 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19437 gen_store_gpr(v0_t, ret);
19438 break;
19439 case NM_PRECEU_PH_QBLA:
19440 check_dsp(ctx);
19441 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19442 gen_store_gpr(v0_t, ret);
19443 break;
19444 case NM_PRECEU_PH_QBRA:
19445 check_dsp(ctx);
19446 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19447 gen_store_gpr(v0_t, ret);
19448 break;
19449 case NM_REPLV_PH:
19450 check_dsp(ctx);
19451 tcg_gen_ext16u_tl(v0_t, v0_t);
19452 tcg_gen_shli_tl(t0, v0_t, 16);
19453 tcg_gen_or_tl(v0_t, v0_t, t0);
19454 tcg_gen_ext32s_tl(v0_t, v0_t);
19455 gen_store_gpr(v0_t, ret);
19456 break;
19457 case NM_REPLV_QB:
19458 check_dsp(ctx);
19459 tcg_gen_ext8u_tl(v0_t, v0_t);
19460 tcg_gen_shli_tl(t0, v0_t, 8);
19461 tcg_gen_or_tl(v0_t, v0_t, t0);
19462 tcg_gen_shli_tl(t0, v0_t, 16);
19463 tcg_gen_or_tl(v0_t, v0_t, t0);
19464 tcg_gen_ext32s_tl(v0_t, v0_t);
19465 gen_store_gpr(v0_t, ret);
19466 break;
19467 case NM_BITREV:
19468 check_dsp(ctx);
19469 gen_helper_bitrev(v0_t, v0_t);
19470 gen_store_gpr(v0_t, ret);
19471 break;
19472 case NM_INSV:
19473 check_dsp(ctx);
19475 TCGv tv0 = tcg_temp_new();
19477 gen_load_gpr(tv0, rt);
19478 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19479 gen_store_gpr(v0_t, ret);
19480 tcg_temp_free(tv0);
19482 break;
19483 case NM_RADDU_W_QB:
19484 check_dsp(ctx);
19485 gen_helper_raddu_w_qb(v0_t, v0_t);
19486 gen_store_gpr(v0_t, ret);
19487 break;
19488 case NM_BITSWAP:
19489 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19490 break;
19491 case NM_CLO:
19492 check_nms(ctx);
19493 gen_cl(ctx, OPC_CLO, ret, rs);
19494 break;
19495 case NM_CLZ:
19496 check_nms(ctx);
19497 gen_cl(ctx, OPC_CLZ, ret, rs);
19498 break;
19499 case NM_WSBH:
19500 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19501 break;
19502 default:
19503 generate_exception_end(ctx, EXCP_RI);
19504 break;
19507 tcg_temp_free(v0_t);
19508 tcg_temp_free(t0);
19511 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19512 int rt, int rs, int rd)
19514 TCGv t0 = tcg_temp_new();
19515 TCGv rs_t = tcg_temp_new();
19517 gen_load_gpr(rs_t, rs);
19519 switch (opc) {
19520 case NM_SHRA_R_QB:
19521 check_dsp_r2(ctx);
19522 tcg_gen_movi_tl(t0, rd >> 2);
19523 switch (extract32(ctx->opcode, 12, 1)) {
19524 case 0:
19525 /* NM_SHRA_QB */
19526 gen_helper_shra_qb(t0, t0, rs_t);
19527 gen_store_gpr(t0, rt);
19528 break;
19529 case 1:
19530 /* NM_SHRA_R_QB */
19531 gen_helper_shra_r_qb(t0, t0, rs_t);
19532 gen_store_gpr(t0, rt);
19533 break;
19535 break;
19536 case NM_SHRL_PH:
19537 check_dsp_r2(ctx);
19538 tcg_gen_movi_tl(t0, rd >> 1);
19539 gen_helper_shrl_ph(t0, t0, rs_t);
19540 gen_store_gpr(t0, rt);
19541 break;
19542 case NM_REPL_QB:
19543 check_dsp(ctx);
19545 int16_t imm;
19546 target_long result;
19547 imm = extract32(ctx->opcode, 13, 8);
19548 result = (uint32_t)imm << 24 |
19549 (uint32_t)imm << 16 |
19550 (uint32_t)imm << 8 |
19551 (uint32_t)imm;
19552 result = (int32_t)result;
19553 tcg_gen_movi_tl(t0, result);
19554 gen_store_gpr(t0, rt);
19556 break;
19557 default:
19558 generate_exception_end(ctx, EXCP_RI);
19559 break;
19561 tcg_temp_free(t0);
19562 tcg_temp_free(rs_t);
19566 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19568 int rt = extract32(ctx->opcode, 21, 5);
19569 int rs = extract32(ctx->opcode, 16, 5);
19570 int rd = extract32(ctx->opcode, 11, 5);
19572 switch (extract32(ctx->opcode, 6, 3)) {
19573 case NM_POOL32AXF_1:
19575 int32_t op1 = extract32(ctx->opcode, 9, 3);
19576 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19578 break;
19579 case NM_POOL32AXF_2:
19581 int32_t op1 = extract32(ctx->opcode, 12, 2);
19582 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19584 break;
19585 case NM_POOL32AXF_4:
19587 int32_t op1 = extract32(ctx->opcode, 9, 7);
19588 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19590 break;
19591 case NM_POOL32AXF_5:
19592 switch (extract32(ctx->opcode, 9, 7)) {
19593 #ifndef CONFIG_USER_ONLY
19594 case NM_TLBP:
19595 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19596 break;
19597 case NM_TLBR:
19598 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19599 break;
19600 case NM_TLBWI:
19601 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19602 break;
19603 case NM_TLBWR:
19604 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19605 break;
19606 case NM_TLBINV:
19607 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19608 break;
19609 case NM_TLBINVF:
19610 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19611 break;
19612 case NM_DI:
19613 check_cp0_enabled(ctx);
19615 TCGv t0 = tcg_temp_new();
19617 save_cpu_state(ctx, 1);
19618 gen_helper_di(t0, cpu_env);
19619 gen_store_gpr(t0, rt);
19620 /* Stop translation as we may have switched the execution mode */
19621 ctx->base.is_jmp = DISAS_STOP;
19622 tcg_temp_free(t0);
19624 break;
19625 case NM_EI:
19626 check_cp0_enabled(ctx);
19628 TCGv t0 = tcg_temp_new();
19630 save_cpu_state(ctx, 1);
19631 gen_helper_ei(t0, cpu_env);
19632 gen_store_gpr(t0, rt);
19633 /* Stop translation as we may have switched the execution mode */
19634 ctx->base.is_jmp = DISAS_STOP;
19635 tcg_temp_free(t0);
19637 break;
19638 case NM_RDPGPR:
19639 gen_load_srsgpr(rs, rt);
19640 break;
19641 case NM_WRPGPR:
19642 gen_store_srsgpr(rs, rt);
19643 break;
19644 case NM_WAIT:
19645 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19646 break;
19647 case NM_DERET:
19648 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19649 break;
19650 case NM_ERETX:
19651 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19652 break;
19653 #endif
19654 default:
19655 generate_exception_end(ctx, EXCP_RI);
19656 break;
19658 break;
19659 case NM_POOL32AXF_7:
19661 int32_t op1 = extract32(ctx->opcode, 9, 3);
19662 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19664 break;
19665 default:
19666 generate_exception_end(ctx, EXCP_RI);
19667 break;
19671 /* Immediate Value Compact Branches */
19672 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19673 int rt, int32_t imm, int32_t offset)
19675 TCGCond cond;
19676 int bcond_compute = 0;
19677 TCGv t0 = tcg_temp_new();
19678 TCGv t1 = tcg_temp_new();
19680 gen_load_gpr(t0, rt);
19681 tcg_gen_movi_tl(t1, imm);
19682 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19684 /* Load needed operands and calculate btarget */
19685 switch (opc) {
19686 case NM_BEQIC:
19687 if (rt == 0 && imm == 0) {
19688 /* Unconditional branch */
19689 } else if (rt == 0 && imm != 0) {
19690 /* Treat as NOP */
19691 goto out;
19692 } else {
19693 bcond_compute = 1;
19694 cond = TCG_COND_EQ;
19696 break;
19697 case NM_BBEQZC:
19698 case NM_BBNEZC:
19699 check_nms(ctx);
19700 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19701 generate_exception_end(ctx, EXCP_RI);
19702 goto out;
19703 } else if (rt == 0 && opc == NM_BBEQZC) {
19704 /* Unconditional branch */
19705 } else if (rt == 0 && opc == NM_BBNEZC) {
19706 /* Treat as NOP */
19707 goto out;
19708 } else {
19709 tcg_gen_shri_tl(t0, t0, imm);
19710 tcg_gen_andi_tl(t0, t0, 1);
19711 tcg_gen_movi_tl(t1, 0);
19712 bcond_compute = 1;
19713 if (opc == NM_BBEQZC) {
19714 cond = TCG_COND_EQ;
19715 } else {
19716 cond = TCG_COND_NE;
19719 break;
19720 case NM_BNEIC:
19721 if (rt == 0 && imm == 0) {
19722 /* Treat as NOP */
19723 goto out;
19724 } else if (rt == 0 && imm != 0) {
19725 /* Unconditional branch */
19726 } else {
19727 bcond_compute = 1;
19728 cond = TCG_COND_NE;
19730 break;
19731 case NM_BGEIC:
19732 if (rt == 0 && imm == 0) {
19733 /* Unconditional branch */
19734 } else {
19735 bcond_compute = 1;
19736 cond = TCG_COND_GE;
19738 break;
19739 case NM_BLTIC:
19740 bcond_compute = 1;
19741 cond = TCG_COND_LT;
19742 break;
19743 case NM_BGEIUC:
19744 if (rt == 0 && imm == 0) {
19745 /* Unconditional branch */
19746 } else {
19747 bcond_compute = 1;
19748 cond = TCG_COND_GEU;
19750 break;
19751 case NM_BLTIUC:
19752 bcond_compute = 1;
19753 cond = TCG_COND_LTU;
19754 break;
19755 default:
19756 MIPS_INVAL("Immediate Value Compact branch");
19757 generate_exception_end(ctx, EXCP_RI);
19758 goto out;
19761 /* branch completion */
19762 clear_branch_hflags(ctx);
19763 ctx->base.is_jmp = DISAS_NORETURN;
19765 if (bcond_compute == 0) {
19766 /* Uncoditional compact branch */
19767 gen_goto_tb(ctx, 0, ctx->btarget);
19768 } else {
19769 /* Conditional compact branch */
19770 TCGLabel *fs = gen_new_label();
19772 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19774 gen_goto_tb(ctx, 1, ctx->btarget);
19775 gen_set_label(fs);
19777 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19780 out:
19781 tcg_temp_free(t0);
19782 tcg_temp_free(t1);
19785 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19786 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19787 int rt)
19789 TCGv t0 = tcg_temp_new();
19790 TCGv t1 = tcg_temp_new();
19792 /* load rs */
19793 gen_load_gpr(t0, rs);
19795 /* link */
19796 if (rt != 0) {
19797 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19800 /* calculate btarget */
19801 tcg_gen_shli_tl(t0, t0, 1);
19802 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19803 gen_op_addr_add(ctx, btarget, t1, t0);
19805 /* branch completion */
19806 clear_branch_hflags(ctx);
19807 ctx->base.is_jmp = DISAS_NORETURN;
19809 /* unconditional branch to register */
19810 tcg_gen_mov_tl(cpu_PC, btarget);
19811 tcg_gen_lookup_and_goto_ptr();
19813 tcg_temp_free(t0);
19814 tcg_temp_free(t1);
19817 /* nanoMIPS Branches */
19818 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19819 int rs, int rt, int32_t offset)
19821 int bcond_compute = 0;
19822 TCGv t0 = tcg_temp_new();
19823 TCGv t1 = tcg_temp_new();
19825 /* Load needed operands and calculate btarget */
19826 switch (opc) {
19827 /* compact branch */
19828 case OPC_BGEC:
19829 case OPC_BLTC:
19830 gen_load_gpr(t0, rs);
19831 gen_load_gpr(t1, rt);
19832 bcond_compute = 1;
19833 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19834 break;
19835 case OPC_BGEUC:
19836 case OPC_BLTUC:
19837 if (rs == 0 || rs == rt) {
19838 /* OPC_BLEZALC, OPC_BGEZALC */
19839 /* OPC_BGTZALC, OPC_BLTZALC */
19840 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19842 gen_load_gpr(t0, rs);
19843 gen_load_gpr(t1, rt);
19844 bcond_compute = 1;
19845 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19846 break;
19847 case OPC_BC:
19848 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19849 break;
19850 case OPC_BEQZC:
19851 if (rs != 0) {
19852 /* OPC_BEQZC, OPC_BNEZC */
19853 gen_load_gpr(t0, rs);
19854 bcond_compute = 1;
19855 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19856 } else {
19857 /* OPC_JIC, OPC_JIALC */
19858 TCGv tbase = tcg_temp_new();
19859 TCGv toffset = tcg_temp_new();
19861 gen_load_gpr(tbase, rt);
19862 tcg_gen_movi_tl(toffset, offset);
19863 gen_op_addr_add(ctx, btarget, tbase, toffset);
19864 tcg_temp_free(tbase);
19865 tcg_temp_free(toffset);
19867 break;
19868 default:
19869 MIPS_INVAL("Compact branch/jump");
19870 generate_exception_end(ctx, EXCP_RI);
19871 goto out;
19874 if (bcond_compute == 0) {
19875 /* Uncoditional compact branch */
19876 switch (opc) {
19877 case OPC_BC:
19878 gen_goto_tb(ctx, 0, ctx->btarget);
19879 break;
19880 default:
19881 MIPS_INVAL("Compact branch/jump");
19882 generate_exception_end(ctx, EXCP_RI);
19883 goto out;
19885 } else {
19886 /* Conditional compact branch */
19887 TCGLabel *fs = gen_new_label();
19889 switch (opc) {
19890 case OPC_BGEUC:
19891 if (rs == 0 && rt != 0) {
19892 /* OPC_BLEZALC */
19893 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19894 } else if (rs != 0 && rt != 0 && rs == rt) {
19895 /* OPC_BGEZALC */
19896 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19897 } else {
19898 /* OPC_BGEUC */
19899 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19901 break;
19902 case OPC_BLTUC:
19903 if (rs == 0 && rt != 0) {
19904 /* OPC_BGTZALC */
19905 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19906 } else if (rs != 0 && rt != 0 && rs == rt) {
19907 /* OPC_BLTZALC */
19908 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19909 } else {
19910 /* OPC_BLTUC */
19911 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19913 break;
19914 case OPC_BGEC:
19915 if (rs == 0 && rt != 0) {
19916 /* OPC_BLEZC */
19917 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19918 } else if (rs != 0 && rt != 0 && rs == rt) {
19919 /* OPC_BGEZC */
19920 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19921 } else {
19922 /* OPC_BGEC */
19923 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19925 break;
19926 case OPC_BLTC:
19927 if (rs == 0 && rt != 0) {
19928 /* OPC_BGTZC */
19929 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19930 } else if (rs != 0 && rt != 0 && rs == rt) {
19931 /* OPC_BLTZC */
19932 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19933 } else {
19934 /* OPC_BLTC */
19935 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19937 break;
19938 case OPC_BEQZC:
19939 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19940 break;
19941 default:
19942 MIPS_INVAL("Compact conditional branch/jump");
19943 generate_exception_end(ctx, EXCP_RI);
19944 goto out;
19947 /* branch completion */
19948 clear_branch_hflags(ctx);
19949 ctx->base.is_jmp = DISAS_NORETURN;
19951 /* Generating branch here as compact branches don't have delay slot */
19952 gen_goto_tb(ctx, 1, ctx->btarget);
19953 gen_set_label(fs);
19955 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19958 out:
19959 tcg_temp_free(t0);
19960 tcg_temp_free(t1);
19964 /* nanoMIPS CP1 Branches */
19965 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19966 int32_t ft, int32_t offset)
19968 target_ulong btarget;
19969 TCGv_i64 t0 = tcg_temp_new_i64();
19971 gen_load_fpr64(ctx, t0, ft);
19972 tcg_gen_andi_i64(t0, t0, 1);
19974 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19976 switch (op) {
19977 case NM_BC1EQZC:
19978 tcg_gen_xori_i64(t0, t0, 1);
19979 ctx->hflags |= MIPS_HFLAG_BC;
19980 break;
19981 case NM_BC1NEZC:
19982 /* t0 already set */
19983 ctx->hflags |= MIPS_HFLAG_BC;
19984 break;
19985 default:
19986 MIPS_INVAL("cp1 cond branch");
19987 generate_exception_end(ctx, EXCP_RI);
19988 goto out;
19991 tcg_gen_trunc_i64_tl(bcond, t0);
19993 ctx->btarget = btarget;
19995 out:
19996 tcg_temp_free_i64(t0);
20000 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20002 TCGv t0, t1;
20003 t0 = tcg_temp_new();
20004 t1 = tcg_temp_new();
20006 gen_load_gpr(t0, rs);
20007 gen_load_gpr(t1, rt);
20009 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20010 /* PP.LSXS instructions require shifting */
20011 switch (extract32(ctx->opcode, 7, 4)) {
20012 case NM_SHXS:
20013 check_nms(ctx);
20014 case NM_LHXS:
20015 case NM_LHUXS:
20016 tcg_gen_shli_tl(t0, t0, 1);
20017 break;
20018 case NM_SWXS:
20019 check_nms(ctx);
20020 case NM_LWXS:
20021 case NM_LWC1XS:
20022 case NM_SWC1XS:
20023 tcg_gen_shli_tl(t0, t0, 2);
20024 break;
20025 case NM_LDC1XS:
20026 case NM_SDC1XS:
20027 tcg_gen_shli_tl(t0, t0, 3);
20028 break;
20031 gen_op_addr_add(ctx, t0, t0, t1);
20033 switch (extract32(ctx->opcode, 7, 4)) {
20034 case NM_LBX:
20035 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20036 MO_SB);
20037 gen_store_gpr(t0, rd);
20038 break;
20039 case NM_LHX:
20040 /*case NM_LHXS:*/
20041 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20042 MO_TESW);
20043 gen_store_gpr(t0, rd);
20044 break;
20045 case NM_LWX:
20046 /*case NM_LWXS:*/
20047 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20048 MO_TESL);
20049 gen_store_gpr(t0, rd);
20050 break;
20051 case NM_LBUX:
20052 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20053 MO_UB);
20054 gen_store_gpr(t0, rd);
20055 break;
20056 case NM_LHUX:
20057 /*case NM_LHUXS:*/
20058 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20059 MO_TEUW);
20060 gen_store_gpr(t0, rd);
20061 break;
20062 case NM_SBX:
20063 check_nms(ctx);
20064 gen_load_gpr(t1, rd);
20065 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20066 MO_8);
20067 break;
20068 case NM_SHX:
20069 /*case NM_SHXS:*/
20070 check_nms(ctx);
20071 gen_load_gpr(t1, rd);
20072 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20073 MO_TEUW);
20074 break;
20075 case NM_SWX:
20076 /*case NM_SWXS:*/
20077 check_nms(ctx);
20078 gen_load_gpr(t1, rd);
20079 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20080 MO_TEUL);
20081 break;
20082 case NM_LWC1X:
20083 /*case NM_LWC1XS:*/
20084 case NM_LDC1X:
20085 /*case NM_LDC1XS:*/
20086 case NM_SWC1X:
20087 /*case NM_SWC1XS:*/
20088 case NM_SDC1X:
20089 /*case NM_SDC1XS:*/
20090 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20091 check_cp1_enabled(ctx);
20092 switch (extract32(ctx->opcode, 7, 4)) {
20093 case NM_LWC1X:
20094 /*case NM_LWC1XS:*/
20095 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20096 break;
20097 case NM_LDC1X:
20098 /*case NM_LDC1XS:*/
20099 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20100 break;
20101 case NM_SWC1X:
20102 /*case NM_SWC1XS:*/
20103 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20104 break;
20105 case NM_SDC1X:
20106 /*case NM_SDC1XS:*/
20107 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20108 break;
20110 } else {
20111 generate_exception_err(ctx, EXCP_CpU, 1);
20113 break;
20114 default:
20115 generate_exception_end(ctx, EXCP_RI);
20116 break;
20119 tcg_temp_free(t0);
20120 tcg_temp_free(t1);
20123 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20125 int rt, rs, rd;
20127 rt = extract32(ctx->opcode, 21, 5);
20128 rs = extract32(ctx->opcode, 16, 5);
20129 rd = extract32(ctx->opcode, 11, 5);
20131 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20132 generate_exception_end(ctx, EXCP_RI);
20133 return;
20135 check_cp1_enabled(ctx);
20136 switch (extract32(ctx->opcode, 0, 3)) {
20137 case NM_POOL32F_0:
20138 switch (extract32(ctx->opcode, 3, 7)) {
20139 case NM_RINT_S:
20140 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20141 break;
20142 case NM_RINT_D:
20143 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20144 break;
20145 case NM_CLASS_S:
20146 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20147 break;
20148 case NM_CLASS_D:
20149 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20150 break;
20151 case NM_ADD_S:
20152 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20153 break;
20154 case NM_ADD_D:
20155 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20156 break;
20157 case NM_SUB_S:
20158 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20159 break;
20160 case NM_SUB_D:
20161 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20162 break;
20163 case NM_MUL_S:
20164 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20165 break;
20166 case NM_MUL_D:
20167 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20168 break;
20169 case NM_DIV_S:
20170 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20171 break;
20172 case NM_DIV_D:
20173 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20174 break;
20175 case NM_SELEQZ_S:
20176 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20177 break;
20178 case NM_SELEQZ_D:
20179 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20180 break;
20181 case NM_SELNEZ_S:
20182 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20183 break;
20184 case NM_SELNEZ_D:
20185 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20186 break;
20187 case NM_SEL_S:
20188 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20189 break;
20190 case NM_SEL_D:
20191 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20192 break;
20193 case NM_MADDF_S:
20194 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20195 break;
20196 case NM_MADDF_D:
20197 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20198 break;
20199 case NM_MSUBF_S:
20200 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20201 break;
20202 case NM_MSUBF_D:
20203 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20204 break;
20205 default:
20206 generate_exception_end(ctx, EXCP_RI);
20207 break;
20209 break;
20210 case NM_POOL32F_3:
20211 switch (extract32(ctx->opcode, 3, 3)) {
20212 case NM_MIN_FMT:
20213 switch (extract32(ctx->opcode, 9, 1)) {
20214 case FMT_SDPS_S:
20215 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20216 break;
20217 case FMT_SDPS_D:
20218 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20219 break;
20221 break;
20222 case NM_MAX_FMT:
20223 switch (extract32(ctx->opcode, 9, 1)) {
20224 case FMT_SDPS_S:
20225 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20226 break;
20227 case FMT_SDPS_D:
20228 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20229 break;
20231 break;
20232 case NM_MINA_FMT:
20233 switch (extract32(ctx->opcode, 9, 1)) {
20234 case FMT_SDPS_S:
20235 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20236 break;
20237 case FMT_SDPS_D:
20238 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20239 break;
20241 break;
20242 case NM_MAXA_FMT:
20243 switch (extract32(ctx->opcode, 9, 1)) {
20244 case FMT_SDPS_S:
20245 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20246 break;
20247 case FMT_SDPS_D:
20248 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20249 break;
20251 break;
20252 case NM_POOL32FXF:
20253 switch (extract32(ctx->opcode, 6, 8)) {
20254 case NM_CFC1:
20255 gen_cp1(ctx, OPC_CFC1, rt, rs);
20256 break;
20257 case NM_CTC1:
20258 gen_cp1(ctx, OPC_CTC1, rt, rs);
20259 break;
20260 case NM_MFC1:
20261 gen_cp1(ctx, OPC_MFC1, rt, rs);
20262 break;
20263 case NM_MTC1:
20264 gen_cp1(ctx, OPC_MTC1, rt, rs);
20265 break;
20266 case NM_MFHC1:
20267 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20268 break;
20269 case NM_MTHC1:
20270 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20271 break;
20272 case NM_CVT_S_PL:
20273 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20274 break;
20275 case NM_CVT_S_PU:
20276 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20277 break;
20278 default:
20279 switch (extract32(ctx->opcode, 6, 9)) {
20280 case NM_CVT_L_S:
20281 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20282 break;
20283 case NM_CVT_L_D:
20284 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20285 break;
20286 case NM_CVT_W_S:
20287 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20288 break;
20289 case NM_CVT_W_D:
20290 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20291 break;
20292 case NM_RSQRT_S:
20293 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20294 break;
20295 case NM_RSQRT_D:
20296 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20297 break;
20298 case NM_SQRT_S:
20299 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20300 break;
20301 case NM_SQRT_D:
20302 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20303 break;
20304 case NM_RECIP_S:
20305 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20306 break;
20307 case NM_RECIP_D:
20308 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20309 break;
20310 case NM_FLOOR_L_S:
20311 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20312 break;
20313 case NM_FLOOR_L_D:
20314 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20315 break;
20316 case NM_FLOOR_W_S:
20317 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20318 break;
20319 case NM_FLOOR_W_D:
20320 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20321 break;
20322 case NM_CEIL_L_S:
20323 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20324 break;
20325 case NM_CEIL_L_D:
20326 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20327 break;
20328 case NM_CEIL_W_S:
20329 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20330 break;
20331 case NM_CEIL_W_D:
20332 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20333 break;
20334 case NM_TRUNC_L_S:
20335 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20336 break;
20337 case NM_TRUNC_L_D:
20338 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20339 break;
20340 case NM_TRUNC_W_S:
20341 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20342 break;
20343 case NM_TRUNC_W_D:
20344 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20345 break;
20346 case NM_ROUND_L_S:
20347 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20348 break;
20349 case NM_ROUND_L_D:
20350 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20351 break;
20352 case NM_ROUND_W_S:
20353 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20354 break;
20355 case NM_ROUND_W_D:
20356 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20357 break;
20358 case NM_MOV_S:
20359 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20360 break;
20361 case NM_MOV_D:
20362 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20363 break;
20364 case NM_ABS_S:
20365 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20366 break;
20367 case NM_ABS_D:
20368 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20369 break;
20370 case NM_NEG_S:
20371 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20372 break;
20373 case NM_NEG_D:
20374 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20375 break;
20376 case NM_CVT_D_S:
20377 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20378 break;
20379 case NM_CVT_D_W:
20380 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20381 break;
20382 case NM_CVT_D_L:
20383 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20384 break;
20385 case NM_CVT_S_D:
20386 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20387 break;
20388 case NM_CVT_S_W:
20389 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20390 break;
20391 case NM_CVT_S_L:
20392 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20393 break;
20394 default:
20395 generate_exception_end(ctx, EXCP_RI);
20396 break;
20398 break;
20400 break;
20402 break;
20403 case NM_POOL32F_5:
20404 switch (extract32(ctx->opcode, 3, 3)) {
20405 case NM_CMP_CONDN_S:
20406 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20407 break;
20408 case NM_CMP_CONDN_D:
20409 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20410 break;
20411 default:
20412 generate_exception_end(ctx, EXCP_RI);
20413 break;
20415 break;
20416 default:
20417 generate_exception_end(ctx, EXCP_RI);
20418 break;
20422 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20423 int rd, int rs, int rt)
20425 int ret = rd;
20426 TCGv t0 = tcg_temp_new();
20427 TCGv v1_t = tcg_temp_new();
20428 TCGv v2_t = tcg_temp_new();
20430 gen_load_gpr(v1_t, rs);
20431 gen_load_gpr(v2_t, rt);
20433 switch (opc) {
20434 case NM_CMP_EQ_PH:
20435 check_dsp(ctx);
20436 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20437 break;
20438 case NM_CMP_LT_PH:
20439 check_dsp(ctx);
20440 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20441 break;
20442 case NM_CMP_LE_PH:
20443 check_dsp(ctx);
20444 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20445 break;
20446 case NM_CMPU_EQ_QB:
20447 check_dsp(ctx);
20448 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20449 break;
20450 case NM_CMPU_LT_QB:
20451 check_dsp(ctx);
20452 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20453 break;
20454 case NM_CMPU_LE_QB:
20455 check_dsp(ctx);
20456 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20457 break;
20458 case NM_CMPGU_EQ_QB:
20459 check_dsp(ctx);
20460 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20461 gen_store_gpr(v1_t, ret);
20462 break;
20463 case NM_CMPGU_LT_QB:
20464 check_dsp(ctx);
20465 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20466 gen_store_gpr(v1_t, ret);
20467 break;
20468 case NM_CMPGU_LE_QB:
20469 check_dsp(ctx);
20470 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20471 gen_store_gpr(v1_t, ret);
20472 break;
20473 case NM_CMPGDU_EQ_QB:
20474 check_dsp_r2(ctx);
20475 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20476 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20477 gen_store_gpr(v1_t, ret);
20478 break;
20479 case NM_CMPGDU_LT_QB:
20480 check_dsp_r2(ctx);
20481 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20482 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20483 gen_store_gpr(v1_t, ret);
20484 break;
20485 case NM_CMPGDU_LE_QB:
20486 check_dsp_r2(ctx);
20487 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20488 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20489 gen_store_gpr(v1_t, ret);
20490 break;
20491 case NM_PACKRL_PH:
20492 check_dsp(ctx);
20493 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20494 gen_store_gpr(v1_t, ret);
20495 break;
20496 case NM_PICK_QB:
20497 check_dsp(ctx);
20498 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20499 gen_store_gpr(v1_t, ret);
20500 break;
20501 case NM_PICK_PH:
20502 check_dsp(ctx);
20503 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20504 gen_store_gpr(v1_t, ret);
20505 break;
20506 case NM_ADDQ_S_W:
20507 check_dsp(ctx);
20508 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20509 gen_store_gpr(v1_t, ret);
20510 break;
20511 case NM_SUBQ_S_W:
20512 check_dsp(ctx);
20513 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20514 gen_store_gpr(v1_t, ret);
20515 break;
20516 case NM_ADDSC:
20517 check_dsp(ctx);
20518 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20519 gen_store_gpr(v1_t, ret);
20520 break;
20521 case NM_ADDWC:
20522 check_dsp(ctx);
20523 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20524 gen_store_gpr(v1_t, ret);
20525 break;
20526 case NM_ADDQ_S_PH:
20527 check_dsp(ctx);
20528 switch (extract32(ctx->opcode, 10, 1)) {
20529 case 0:
20530 /* ADDQ_PH */
20531 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20532 gen_store_gpr(v1_t, ret);
20533 break;
20534 case 1:
20535 /* ADDQ_S_PH */
20536 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20537 gen_store_gpr(v1_t, ret);
20538 break;
20540 break;
20541 case NM_ADDQH_R_PH:
20542 check_dsp_r2(ctx);
20543 switch (extract32(ctx->opcode, 10, 1)) {
20544 case 0:
20545 /* ADDQH_PH */
20546 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20547 gen_store_gpr(v1_t, ret);
20548 break;
20549 case 1:
20550 /* ADDQH_R_PH */
20551 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20552 gen_store_gpr(v1_t, ret);
20553 break;
20555 break;
20556 case NM_ADDQH_R_W:
20557 check_dsp_r2(ctx);
20558 switch (extract32(ctx->opcode, 10, 1)) {
20559 case 0:
20560 /* ADDQH_W */
20561 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20562 gen_store_gpr(v1_t, ret);
20563 break;
20564 case 1:
20565 /* ADDQH_R_W */
20566 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20567 gen_store_gpr(v1_t, ret);
20568 break;
20570 break;
20571 case NM_ADDU_S_QB:
20572 check_dsp(ctx);
20573 switch (extract32(ctx->opcode, 10, 1)) {
20574 case 0:
20575 /* ADDU_QB */
20576 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20577 gen_store_gpr(v1_t, ret);
20578 break;
20579 case 1:
20580 /* ADDU_S_QB */
20581 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20582 gen_store_gpr(v1_t, ret);
20583 break;
20585 break;
20586 case NM_ADDU_S_PH:
20587 check_dsp_r2(ctx);
20588 switch (extract32(ctx->opcode, 10, 1)) {
20589 case 0:
20590 /* ADDU_PH */
20591 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20592 gen_store_gpr(v1_t, ret);
20593 break;
20594 case 1:
20595 /* ADDU_S_PH */
20596 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20597 gen_store_gpr(v1_t, ret);
20598 break;
20600 break;
20601 case NM_ADDUH_R_QB:
20602 check_dsp_r2(ctx);
20603 switch (extract32(ctx->opcode, 10, 1)) {
20604 case 0:
20605 /* ADDUH_QB */
20606 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20607 gen_store_gpr(v1_t, ret);
20608 break;
20609 case 1:
20610 /* ADDUH_R_QB */
20611 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20612 gen_store_gpr(v1_t, ret);
20613 break;
20615 break;
20616 case NM_SHRAV_R_PH:
20617 check_dsp(ctx);
20618 switch (extract32(ctx->opcode, 10, 1)) {
20619 case 0:
20620 /* SHRAV_PH */
20621 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20622 gen_store_gpr(v1_t, ret);
20623 break;
20624 case 1:
20625 /* SHRAV_R_PH */
20626 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20627 gen_store_gpr(v1_t, ret);
20628 break;
20630 break;
20631 case NM_SHRAV_R_QB:
20632 check_dsp_r2(ctx);
20633 switch (extract32(ctx->opcode, 10, 1)) {
20634 case 0:
20635 /* SHRAV_QB */
20636 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20637 gen_store_gpr(v1_t, ret);
20638 break;
20639 case 1:
20640 /* SHRAV_R_QB */
20641 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20642 gen_store_gpr(v1_t, ret);
20643 break;
20645 break;
20646 case NM_SUBQ_S_PH:
20647 check_dsp(ctx);
20648 switch (extract32(ctx->opcode, 10, 1)) {
20649 case 0:
20650 /* SUBQ_PH */
20651 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20652 gen_store_gpr(v1_t, ret);
20653 break;
20654 case 1:
20655 /* SUBQ_S_PH */
20656 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20657 gen_store_gpr(v1_t, ret);
20658 break;
20660 break;
20661 case NM_SUBQH_R_PH:
20662 check_dsp_r2(ctx);
20663 switch (extract32(ctx->opcode, 10, 1)) {
20664 case 0:
20665 /* SUBQH_PH */
20666 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20667 gen_store_gpr(v1_t, ret);
20668 break;
20669 case 1:
20670 /* SUBQH_R_PH */
20671 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20672 gen_store_gpr(v1_t, ret);
20673 break;
20675 break;
20676 case NM_SUBQH_R_W:
20677 check_dsp_r2(ctx);
20678 switch (extract32(ctx->opcode, 10, 1)) {
20679 case 0:
20680 /* SUBQH_W */
20681 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20682 gen_store_gpr(v1_t, ret);
20683 break;
20684 case 1:
20685 /* SUBQH_R_W */
20686 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20687 gen_store_gpr(v1_t, ret);
20688 break;
20690 break;
20691 case NM_SUBU_S_QB:
20692 check_dsp(ctx);
20693 switch (extract32(ctx->opcode, 10, 1)) {
20694 case 0:
20695 /* SUBU_QB */
20696 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20697 gen_store_gpr(v1_t, ret);
20698 break;
20699 case 1:
20700 /* SUBU_S_QB */
20701 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20702 gen_store_gpr(v1_t, ret);
20703 break;
20705 break;
20706 case NM_SUBU_S_PH:
20707 check_dsp_r2(ctx);
20708 switch (extract32(ctx->opcode, 10, 1)) {
20709 case 0:
20710 /* SUBU_PH */
20711 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20712 gen_store_gpr(v1_t, ret);
20713 break;
20714 case 1:
20715 /* SUBU_S_PH */
20716 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20717 gen_store_gpr(v1_t, ret);
20718 break;
20720 break;
20721 case NM_SUBUH_R_QB:
20722 check_dsp_r2(ctx);
20723 switch (extract32(ctx->opcode, 10, 1)) {
20724 case 0:
20725 /* SUBUH_QB */
20726 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20727 gen_store_gpr(v1_t, ret);
20728 break;
20729 case 1:
20730 /* SUBUH_R_QB */
20731 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20732 gen_store_gpr(v1_t, ret);
20733 break;
20735 break;
20736 case NM_SHLLV_S_PH:
20737 check_dsp(ctx);
20738 switch (extract32(ctx->opcode, 10, 1)) {
20739 case 0:
20740 /* SHLLV_PH */
20741 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20742 gen_store_gpr(v1_t, ret);
20743 break;
20744 case 1:
20745 /* SHLLV_S_PH */
20746 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20747 gen_store_gpr(v1_t, ret);
20748 break;
20750 break;
20751 case NM_PRECR_SRA_R_PH_W:
20752 check_dsp_r2(ctx);
20753 switch (extract32(ctx->opcode, 10, 1)) {
20754 case 0:
20755 /* PRECR_SRA_PH_W */
20757 TCGv_i32 sa_t = tcg_const_i32(rd);
20758 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20759 cpu_gpr[rt]);
20760 gen_store_gpr(v1_t, rt);
20761 tcg_temp_free_i32(sa_t);
20763 break;
20764 case 1:
20765 /* PRECR_SRA_R_PH_W */
20767 TCGv_i32 sa_t = tcg_const_i32(rd);
20768 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20769 cpu_gpr[rt]);
20770 gen_store_gpr(v1_t, rt);
20771 tcg_temp_free_i32(sa_t);
20773 break;
20775 break;
20776 case NM_MULEU_S_PH_QBL:
20777 check_dsp(ctx);
20778 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20779 gen_store_gpr(v1_t, ret);
20780 break;
20781 case NM_MULEU_S_PH_QBR:
20782 check_dsp(ctx);
20783 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20784 gen_store_gpr(v1_t, ret);
20785 break;
20786 case NM_MULQ_RS_PH:
20787 check_dsp(ctx);
20788 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20789 gen_store_gpr(v1_t, ret);
20790 break;
20791 case NM_MULQ_S_PH:
20792 check_dsp_r2(ctx);
20793 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20794 gen_store_gpr(v1_t, ret);
20795 break;
20796 case NM_MULQ_RS_W:
20797 check_dsp_r2(ctx);
20798 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20799 gen_store_gpr(v1_t, ret);
20800 break;
20801 case NM_MULQ_S_W:
20802 check_dsp_r2(ctx);
20803 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20804 gen_store_gpr(v1_t, ret);
20805 break;
20806 case NM_APPEND:
20807 check_dsp_r2(ctx);
20808 gen_load_gpr(t0, rs);
20809 if (rd != 0) {
20810 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20812 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20813 break;
20814 case NM_MODSUB:
20815 check_dsp(ctx);
20816 gen_helper_modsub(v1_t, v1_t, v2_t);
20817 gen_store_gpr(v1_t, ret);
20818 break;
20819 case NM_SHRAV_R_W:
20820 check_dsp(ctx);
20821 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20822 gen_store_gpr(v1_t, ret);
20823 break;
20824 case NM_SHRLV_PH:
20825 check_dsp_r2(ctx);
20826 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20827 gen_store_gpr(v1_t, ret);
20828 break;
20829 case NM_SHRLV_QB:
20830 check_dsp(ctx);
20831 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20832 gen_store_gpr(v1_t, ret);
20833 break;
20834 case NM_SHLLV_QB:
20835 check_dsp(ctx);
20836 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20837 gen_store_gpr(v1_t, ret);
20838 break;
20839 case NM_SHLLV_S_W:
20840 check_dsp(ctx);
20841 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20842 gen_store_gpr(v1_t, ret);
20843 break;
20844 case NM_SHILO:
20845 check_dsp(ctx);
20847 TCGv tv0 = tcg_temp_new();
20848 TCGv tv1 = tcg_temp_new();
20849 int16_t imm = extract32(ctx->opcode, 16, 7);
20851 tcg_gen_movi_tl(tv0, rd >> 3);
20852 tcg_gen_movi_tl(tv1, imm);
20853 gen_helper_shilo(tv0, tv1, cpu_env);
20855 break;
20856 case NM_MULEQ_S_W_PHL:
20857 check_dsp(ctx);
20858 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20859 gen_store_gpr(v1_t, ret);
20860 break;
20861 case NM_MULEQ_S_W_PHR:
20862 check_dsp(ctx);
20863 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20864 gen_store_gpr(v1_t, ret);
20865 break;
20866 case NM_MUL_S_PH:
20867 check_dsp_r2(ctx);
20868 switch (extract32(ctx->opcode, 10, 1)) {
20869 case 0:
20870 /* MUL_PH */
20871 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20872 gen_store_gpr(v1_t, ret);
20873 break;
20874 case 1:
20875 /* MUL_S_PH */
20876 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20877 gen_store_gpr(v1_t, ret);
20878 break;
20880 break;
20881 case NM_PRECR_QB_PH:
20882 check_dsp_r2(ctx);
20883 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20884 gen_store_gpr(v1_t, ret);
20885 break;
20886 case NM_PRECRQ_QB_PH:
20887 check_dsp(ctx);
20888 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20889 gen_store_gpr(v1_t, ret);
20890 break;
20891 case NM_PRECRQ_PH_W:
20892 check_dsp(ctx);
20893 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20894 gen_store_gpr(v1_t, ret);
20895 break;
20896 case NM_PRECRQ_RS_PH_W:
20897 check_dsp(ctx);
20898 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20899 gen_store_gpr(v1_t, ret);
20900 break;
20901 case NM_PRECRQU_S_QB_PH:
20902 check_dsp(ctx);
20903 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20904 gen_store_gpr(v1_t, ret);
20905 break;
20906 case NM_SHRA_R_W:
20907 check_dsp(ctx);
20908 tcg_gen_movi_tl(t0, rd);
20909 gen_helper_shra_r_w(v1_t, t0, v1_t);
20910 gen_store_gpr(v1_t, rt);
20911 break;
20912 case NM_SHRA_R_PH:
20913 check_dsp(ctx);
20914 tcg_gen_movi_tl(t0, rd >> 1);
20915 switch (extract32(ctx->opcode, 10, 1)) {
20916 case 0:
20917 /* SHRA_PH */
20918 gen_helper_shra_ph(v1_t, t0, v1_t);
20919 gen_store_gpr(v1_t, rt);
20920 break;
20921 case 1:
20922 /* SHRA_R_PH */
20923 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20924 gen_store_gpr(v1_t, rt);
20925 break;
20927 break;
20928 case NM_SHLL_S_PH:
20929 check_dsp(ctx);
20930 tcg_gen_movi_tl(t0, rd >> 1);
20931 switch (extract32(ctx->opcode, 10, 2)) {
20932 case 0:
20933 /* SHLL_PH */
20934 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20935 gen_store_gpr(v1_t, rt);
20936 break;
20937 case 2:
20938 /* SHLL_S_PH */
20939 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20940 gen_store_gpr(v1_t, rt);
20941 break;
20942 default:
20943 generate_exception_end(ctx, EXCP_RI);
20944 break;
20946 break;
20947 case NM_SHLL_S_W:
20948 check_dsp(ctx);
20949 tcg_gen_movi_tl(t0, rd);
20950 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20951 gen_store_gpr(v1_t, rt);
20952 break;
20953 case NM_REPL_PH:
20954 check_dsp(ctx);
20956 int16_t imm;
20957 imm = sextract32(ctx->opcode, 11, 11);
20958 imm = (int16_t)(imm << 6) >> 6;
20959 if (rt != 0) {
20960 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20963 break;
20964 default:
20965 generate_exception_end(ctx, EXCP_RI);
20966 break;
20970 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20972 uint16_t insn;
20973 uint32_t op;
20974 int rt, rs, rd;
20975 int offset;
20976 int imm;
20978 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20979 ctx->opcode = (ctx->opcode << 16) | insn;
20981 rt = extract32(ctx->opcode, 21, 5);
20982 rs = extract32(ctx->opcode, 16, 5);
20983 rd = extract32(ctx->opcode, 11, 5);
20985 op = extract32(ctx->opcode, 26, 6);
20986 switch (op) {
20987 case NM_P_ADDIU:
20988 if (rt == 0) {
20989 /* P.RI */
20990 switch (extract32(ctx->opcode, 19, 2)) {
20991 case NM_SIGRIE:
20992 default:
20993 generate_exception_end(ctx, EXCP_RI);
20994 break;
20995 case NM_P_SYSCALL:
20996 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20997 generate_exception_end(ctx, EXCP_SYSCALL);
20998 } else {
20999 generate_exception_end(ctx, EXCP_RI);
21001 break;
21002 case NM_BREAK:
21003 generate_exception_end(ctx, EXCP_BREAK);
21004 break;
21005 case NM_SDBBP:
21006 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21007 gen_helper_do_semihosting(cpu_env);
21008 } else {
21009 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21010 generate_exception_end(ctx, EXCP_RI);
21011 } else {
21012 generate_exception_end(ctx, EXCP_DBp);
21015 break;
21017 } else {
21018 /* NM_ADDIU */
21019 imm = extract32(ctx->opcode, 0, 16);
21020 if (rs != 0) {
21021 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21022 } else {
21023 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21025 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21027 break;
21028 case NM_ADDIUPC:
21029 if (rt != 0) {
21030 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21031 extract32(ctx->opcode, 1, 20) << 1;
21032 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21033 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21035 break;
21036 case NM_POOL32A:
21037 switch (ctx->opcode & 0x07) {
21038 case NM_POOL32A0:
21039 gen_pool32a0_nanomips_insn(env, ctx);
21040 break;
21041 case NM_POOL32A5:
21043 int32_t op1 = extract32(ctx->opcode, 3, 7);
21044 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21046 break;
21047 case NM_POOL32A7:
21048 switch (extract32(ctx->opcode, 3, 3)) {
21049 case NM_P_LSX:
21050 gen_p_lsx(ctx, rd, rs, rt);
21051 break;
21052 case NM_LSA:
21053 /* In nanoMIPS, the shift field directly encodes the shift
21054 * amount, meaning that the supported shift values are in
21055 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
21056 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21057 extract32(ctx->opcode, 9, 2) - 1);
21058 break;
21059 case NM_EXTW:
21060 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21061 break;
21062 case NM_POOL32AXF:
21063 gen_pool32axf_nanomips_insn(env, ctx);
21064 break;
21065 default:
21066 generate_exception_end(ctx, EXCP_RI);
21067 break;
21069 break;
21070 default:
21071 generate_exception_end(ctx, EXCP_RI);
21072 break;
21074 break;
21075 case NM_P_GP_W:
21076 switch (ctx->opcode & 0x03) {
21077 case NM_ADDIUGP_W:
21078 if (rt != 0) {
21079 offset = extract32(ctx->opcode, 0, 21);
21080 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21082 break;
21083 case NM_LWGP:
21084 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21085 break;
21086 case NM_SWGP:
21087 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21088 break;
21089 default:
21090 generate_exception_end(ctx, EXCP_RI);
21091 break;
21093 break;
21094 case NM_P48I:
21096 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21097 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21098 switch (extract32(ctx->opcode, 16, 5)) {
21099 case NM_LI48:
21100 check_nms(ctx);
21101 if (rt != 0) {
21102 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21104 break;
21105 case NM_ADDIU48:
21106 check_nms(ctx);
21107 if (rt != 0) {
21108 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21109 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21111 break;
21112 case NM_ADDIUGP48:
21113 check_nms(ctx);
21114 if (rt != 0) {
21115 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21117 break;
21118 case NM_ADDIUPC48:
21119 check_nms(ctx);
21120 if (rt != 0) {
21121 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21122 addr_off);
21124 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21126 break;
21127 case NM_LWPC48:
21128 check_nms(ctx);
21129 if (rt != 0) {
21130 TCGv t0;
21131 t0 = tcg_temp_new();
21133 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21134 addr_off);
21136 tcg_gen_movi_tl(t0, addr);
21137 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21138 tcg_temp_free(t0);
21140 break;
21141 case NM_SWPC48:
21142 check_nms(ctx);
21144 TCGv t0, t1;
21145 t0 = tcg_temp_new();
21146 t1 = tcg_temp_new();
21148 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21149 addr_off);
21151 tcg_gen_movi_tl(t0, addr);
21152 gen_load_gpr(t1, rt);
21154 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21156 tcg_temp_free(t0);
21157 tcg_temp_free(t1);
21159 break;
21160 default:
21161 generate_exception_end(ctx, EXCP_RI);
21162 break;
21164 return 6;
21166 case NM_P_U12:
21167 switch (extract32(ctx->opcode, 12, 4)) {
21168 case NM_ORI:
21169 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21170 break;
21171 case NM_XORI:
21172 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21173 break;
21174 case NM_ANDI:
21175 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21176 break;
21177 case NM_P_SR:
21178 switch (extract32(ctx->opcode, 20, 1)) {
21179 case NM_PP_SR:
21180 switch (ctx->opcode & 3) {
21181 case NM_SAVE:
21182 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21183 extract32(ctx->opcode, 2, 1),
21184 extract32(ctx->opcode, 3, 9) << 3);
21185 break;
21186 case NM_RESTORE:
21187 case NM_RESTORE_JRC:
21188 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21189 extract32(ctx->opcode, 2, 1),
21190 extract32(ctx->opcode, 3, 9) << 3);
21191 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21192 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21194 break;
21195 default:
21196 generate_exception_end(ctx, EXCP_RI);
21197 break;
21199 break;
21200 case NM_P_SR_F:
21201 generate_exception_end(ctx, EXCP_RI);
21202 break;
21204 break;
21205 case NM_SLTI:
21206 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21207 break;
21208 case NM_SLTIU:
21209 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21210 break;
21211 case NM_SEQI:
21213 TCGv t0 = tcg_temp_new();
21215 imm = extract32(ctx->opcode, 0, 12);
21216 gen_load_gpr(t0, rs);
21217 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21218 gen_store_gpr(t0, rt);
21220 tcg_temp_free(t0);
21222 break;
21223 case NM_ADDIUNEG:
21224 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21225 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21226 break;
21227 case NM_P_SHIFT:
21229 int shift = extract32(ctx->opcode, 0, 5);
21230 switch (extract32(ctx->opcode, 5, 4)) {
21231 case NM_P_SLL:
21232 if (rt == 0 && shift == 0) {
21233 /* NOP */
21234 } else if (rt == 0 && shift == 3) {
21235 /* EHB - treat as NOP */
21236 } else if (rt == 0 && shift == 5) {
21237 /* PAUSE - treat as NOP */
21238 } else if (rt == 0 && shift == 6) {
21239 /* SYNC */
21240 gen_sync(extract32(ctx->opcode, 16, 5));
21241 } else {
21242 /* SLL */
21243 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21244 extract32(ctx->opcode, 0, 5));
21246 break;
21247 case NM_SRL:
21248 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21249 extract32(ctx->opcode, 0, 5));
21250 break;
21251 case NM_SRA:
21252 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21253 extract32(ctx->opcode, 0, 5));
21254 break;
21255 case NM_ROTR:
21256 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21257 extract32(ctx->opcode, 0, 5));
21258 break;
21261 break;
21262 case NM_P_ROTX:
21263 check_nms(ctx);
21264 if (rt != 0) {
21265 TCGv t0 = tcg_temp_new();
21266 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21267 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21268 << 1);
21269 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21271 gen_load_gpr(t0, rs);
21272 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21273 tcg_temp_free(t0);
21275 tcg_temp_free_i32(shift);
21276 tcg_temp_free_i32(shiftx);
21277 tcg_temp_free_i32(stripe);
21279 break;
21280 case NM_P_INS:
21281 switch (((ctx->opcode >> 10) & 2) |
21282 (extract32(ctx->opcode, 5, 1))) {
21283 case NM_INS:
21284 check_nms(ctx);
21285 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21286 extract32(ctx->opcode, 6, 5));
21287 break;
21288 default:
21289 generate_exception_end(ctx, EXCP_RI);
21290 break;
21292 break;
21293 case NM_P_EXT:
21294 switch (((ctx->opcode >> 10) & 2) |
21295 (extract32(ctx->opcode, 5, 1))) {
21296 case NM_EXT:
21297 check_nms(ctx);
21298 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21299 extract32(ctx->opcode, 6, 5));
21300 break;
21301 default:
21302 generate_exception_end(ctx, EXCP_RI);
21303 break;
21305 break;
21306 default:
21307 generate_exception_end(ctx, EXCP_RI);
21308 break;
21310 break;
21311 case NM_POOL32F:
21312 gen_pool32f_nanomips_insn(ctx);
21313 break;
21314 case NM_POOL32S:
21315 break;
21316 case NM_P_LUI:
21317 switch (extract32(ctx->opcode, 1, 1)) {
21318 case NM_LUI:
21319 if (rt != 0) {
21320 tcg_gen_movi_tl(cpu_gpr[rt],
21321 sextract32(ctx->opcode, 0, 1) << 31 |
21322 extract32(ctx->opcode, 2, 10) << 21 |
21323 extract32(ctx->opcode, 12, 9) << 12);
21325 break;
21326 case NM_ALUIPC:
21327 if (rt != 0) {
21328 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21329 extract32(ctx->opcode, 2, 10) << 21 |
21330 extract32(ctx->opcode, 12, 9) << 12;
21331 target_long addr;
21332 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21333 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21335 break;
21337 break;
21338 case NM_P_GP_BH:
21340 uint32_t u = extract32(ctx->opcode, 0, 18);
21342 switch (extract32(ctx->opcode, 18, 3)) {
21343 case NM_LBGP:
21344 gen_ld(ctx, OPC_LB, rt, 28, u);
21345 break;
21346 case NM_SBGP:
21347 gen_st(ctx, OPC_SB, rt, 28, u);
21348 break;
21349 case NM_LBUGP:
21350 gen_ld(ctx, OPC_LBU, rt, 28, u);
21351 break;
21352 case NM_ADDIUGP_B:
21353 if (rt != 0) {
21354 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21356 break;
21357 case NM_P_GP_LH:
21358 u &= ~1;
21359 switch (ctx->opcode & 1) {
21360 case NM_LHGP:
21361 gen_ld(ctx, OPC_LH, rt, 28, u);
21362 break;
21363 case NM_LHUGP:
21364 gen_ld(ctx, OPC_LHU, rt, 28, u);
21365 break;
21367 break;
21368 case NM_P_GP_SH:
21369 u &= ~1;
21370 switch (ctx->opcode & 1) {
21371 case NM_SHGP:
21372 gen_st(ctx, OPC_SH, rt, 28, u);
21373 break;
21374 default:
21375 generate_exception_end(ctx, EXCP_RI);
21376 break;
21378 break;
21379 case NM_P_GP_CP1:
21380 u &= ~0x3;
21381 switch (ctx->opcode & 0x3) {
21382 case NM_LWC1GP:
21383 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21384 break;
21385 case NM_LDC1GP:
21386 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21387 break;
21388 case NM_SWC1GP:
21389 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21390 break;
21391 case NM_SDC1GP:
21392 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21393 break;
21395 break;
21396 default:
21397 generate_exception_end(ctx, EXCP_RI);
21398 break;
21401 break;
21402 case NM_P_LS_U12:
21404 uint32_t u = extract32(ctx->opcode, 0, 12);
21406 switch (extract32(ctx->opcode, 12, 4)) {
21407 case NM_P_PREFU12:
21408 if (rt == 31) {
21409 /* SYNCI */
21410 /* Break the TB to be able to sync copied instructions
21411 immediately */
21412 ctx->base.is_jmp = DISAS_STOP;
21413 } else {
21414 /* PREF */
21415 /* Treat as NOP. */
21417 break;
21418 case NM_LB:
21419 gen_ld(ctx, OPC_LB, rt, rs, u);
21420 break;
21421 case NM_LH:
21422 gen_ld(ctx, OPC_LH, rt, rs, u);
21423 break;
21424 case NM_LW:
21425 gen_ld(ctx, OPC_LW, rt, rs, u);
21426 break;
21427 case NM_LBU:
21428 gen_ld(ctx, OPC_LBU, rt, rs, u);
21429 break;
21430 case NM_LHU:
21431 gen_ld(ctx, OPC_LHU, rt, rs, u);
21432 break;
21433 case NM_SB:
21434 gen_st(ctx, OPC_SB, rt, rs, u);
21435 break;
21436 case NM_SH:
21437 gen_st(ctx, OPC_SH, rt, rs, u);
21438 break;
21439 case NM_SW:
21440 gen_st(ctx, OPC_SW, rt, rs, u);
21441 break;
21442 case NM_LWC1:
21443 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21444 break;
21445 case NM_LDC1:
21446 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21447 break;
21448 case NM_SWC1:
21449 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21450 break;
21451 case NM_SDC1:
21452 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21453 break;
21454 default:
21455 generate_exception_end(ctx, EXCP_RI);
21456 break;
21459 break;
21460 case NM_P_LS_S9:
21462 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21463 extract32(ctx->opcode, 0, 8);
21465 switch (extract32(ctx->opcode, 8, 3)) {
21466 case NM_P_LS_S0:
21467 switch (extract32(ctx->opcode, 11, 4)) {
21468 case NM_LBS9:
21469 gen_ld(ctx, OPC_LB, rt, rs, s);
21470 break;
21471 case NM_LHS9:
21472 gen_ld(ctx, OPC_LH, rt, rs, s);
21473 break;
21474 case NM_LWS9:
21475 gen_ld(ctx, OPC_LW, rt, rs, s);
21476 break;
21477 case NM_LBUS9:
21478 gen_ld(ctx, OPC_LBU, rt, rs, s);
21479 break;
21480 case NM_LHUS9:
21481 gen_ld(ctx, OPC_LHU, rt, rs, s);
21482 break;
21483 case NM_SBS9:
21484 gen_st(ctx, OPC_SB, rt, rs, s);
21485 break;
21486 case NM_SHS9:
21487 gen_st(ctx, OPC_SH, rt, rs, s);
21488 break;
21489 case NM_SWS9:
21490 gen_st(ctx, OPC_SW, rt, rs, s);
21491 break;
21492 case NM_LWC1S9:
21493 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21494 break;
21495 case NM_LDC1S9:
21496 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21497 break;
21498 case NM_SWC1S9:
21499 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21500 break;
21501 case NM_SDC1S9:
21502 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21503 break;
21504 case NM_P_PREFS9:
21505 if (rt == 31) {
21506 /* SYNCI */
21507 /* Break the TB to be able to sync copied instructions
21508 immediately */
21509 ctx->base.is_jmp = DISAS_STOP;
21510 } else {
21511 /* PREF */
21512 /* Treat as NOP. */
21514 break;
21515 default:
21516 generate_exception_end(ctx, EXCP_RI);
21517 break;
21519 break;
21520 case NM_P_LS_S1:
21521 switch (extract32(ctx->opcode, 11, 4)) {
21522 case NM_UALH:
21523 case NM_UASH:
21524 check_nms(ctx);
21526 TCGv t0 = tcg_temp_new();
21527 TCGv t1 = tcg_temp_new();
21529 gen_base_offset_addr(ctx, t0, rs, s);
21531 switch (extract32(ctx->opcode, 11, 4)) {
21532 case NM_UALH:
21533 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21534 MO_UNALN);
21535 gen_store_gpr(t0, rt);
21536 break;
21537 case NM_UASH:
21538 gen_load_gpr(t1, rt);
21539 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21540 MO_UNALN);
21541 break;
21543 tcg_temp_free(t0);
21544 tcg_temp_free(t1);
21546 break;
21547 case NM_P_LL:
21548 switch (ctx->opcode & 0x03) {
21549 case NM_LL:
21550 gen_ld(ctx, OPC_LL, rt, rs, s);
21551 break;
21552 case NM_LLWP:
21553 check_xnp(ctx);
21554 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21555 break;
21557 break;
21558 case NM_P_SC:
21559 switch (ctx->opcode & 0x03) {
21560 case NM_SC:
21561 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21562 break;
21563 case NM_SCWP:
21564 check_xnp(ctx);
21565 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21566 false);
21567 break;
21569 break;
21570 case NM_CACHE:
21571 check_cp0_enabled(ctx);
21572 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21573 gen_cache_operation(ctx, rt, rs, s);
21575 break;
21577 break;
21578 case NM_P_LS_E0:
21579 switch (extract32(ctx->opcode, 11, 4)) {
21580 case NM_LBE:
21581 check_eva(ctx);
21582 check_cp0_enabled(ctx);
21583 gen_ld(ctx, OPC_LBE, rt, rs, s);
21584 break;
21585 case NM_SBE:
21586 check_eva(ctx);
21587 check_cp0_enabled(ctx);
21588 gen_st(ctx, OPC_SBE, rt, rs, s);
21589 break;
21590 case NM_LBUE:
21591 check_eva(ctx);
21592 check_cp0_enabled(ctx);
21593 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21594 break;
21595 case NM_P_PREFE:
21596 if (rt == 31) {
21597 /* case NM_SYNCIE */
21598 check_eva(ctx);
21599 check_cp0_enabled(ctx);
21600 /* Break the TB to be able to sync copied instructions
21601 immediately */
21602 ctx->base.is_jmp = DISAS_STOP;
21603 } else {
21604 /* case NM_PREFE */
21605 check_eva(ctx);
21606 check_cp0_enabled(ctx);
21607 /* Treat as NOP. */
21609 break;
21610 case NM_LHE:
21611 check_eva(ctx);
21612 check_cp0_enabled(ctx);
21613 gen_ld(ctx, OPC_LHE, rt, rs, s);
21614 break;
21615 case NM_SHE:
21616 check_eva(ctx);
21617 check_cp0_enabled(ctx);
21618 gen_st(ctx, OPC_SHE, rt, rs, s);
21619 break;
21620 case NM_LHUE:
21621 check_eva(ctx);
21622 check_cp0_enabled(ctx);
21623 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21624 break;
21625 case NM_CACHEE:
21626 check_nms_dl_il_sl_tl_l2c(ctx);
21627 gen_cache_operation(ctx, rt, rs, s);
21628 break;
21629 case NM_LWE:
21630 check_eva(ctx);
21631 check_cp0_enabled(ctx);
21632 gen_ld(ctx, OPC_LWE, rt, rs, s);
21633 break;
21634 case NM_SWE:
21635 check_eva(ctx);
21636 check_cp0_enabled(ctx);
21637 gen_st(ctx, OPC_SWE, rt, rs, s);
21638 break;
21639 case NM_P_LLE:
21640 switch (extract32(ctx->opcode, 2, 2)) {
21641 case NM_LLE:
21642 check_xnp(ctx);
21643 check_eva(ctx);
21644 check_cp0_enabled(ctx);
21645 gen_ld(ctx, OPC_LLE, rt, rs, s);
21646 break;
21647 case NM_LLWPE:
21648 check_xnp(ctx);
21649 check_eva(ctx);
21650 check_cp0_enabled(ctx);
21651 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21652 break;
21653 default:
21654 generate_exception_end(ctx, EXCP_RI);
21655 break;
21657 break;
21658 case NM_P_SCE:
21659 switch (extract32(ctx->opcode, 2, 2)) {
21660 case NM_SCE:
21661 check_xnp(ctx);
21662 check_eva(ctx);
21663 check_cp0_enabled(ctx);
21664 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21665 break;
21666 case NM_SCWPE:
21667 check_xnp(ctx);
21668 check_eva(ctx);
21669 check_cp0_enabled(ctx);
21670 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21671 true);
21672 break;
21673 default:
21674 generate_exception_end(ctx, EXCP_RI);
21675 break;
21677 break;
21679 break;
21680 case NM_P_LS_WM:
21681 case NM_P_LS_UAWM:
21682 check_nms(ctx);
21684 int count = extract32(ctx->opcode, 12, 3);
21685 int counter = 0;
21687 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21688 extract32(ctx->opcode, 0, 8);
21689 TCGv va = tcg_temp_new();
21690 TCGv t1 = tcg_temp_new();
21691 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21692 NM_P_LS_UAWM ? MO_UNALN : 0;
21694 count = (count == 0) ? 8 : count;
21695 while (counter != count) {
21696 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21697 int this_offset = offset + (counter << 2);
21699 gen_base_offset_addr(ctx, va, rs, this_offset);
21701 switch (extract32(ctx->opcode, 11, 1)) {
21702 case NM_LWM:
21703 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21704 memop | MO_TESL);
21705 gen_store_gpr(t1, this_rt);
21706 if ((this_rt == rs) &&
21707 (counter != (count - 1))) {
21708 /* UNPREDICTABLE */
21710 break;
21711 case NM_SWM:
21712 this_rt = (rt == 0) ? 0 : this_rt;
21713 gen_load_gpr(t1, this_rt);
21714 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21715 memop | MO_TEUL);
21716 break;
21718 counter++;
21720 tcg_temp_free(va);
21721 tcg_temp_free(t1);
21723 break;
21724 default:
21725 generate_exception_end(ctx, EXCP_RI);
21726 break;
21729 break;
21730 case NM_MOVE_BALC:
21731 check_nms(ctx);
21733 TCGv t0 = tcg_temp_new();
21734 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21735 extract32(ctx->opcode, 1, 20) << 1;
21736 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21737 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21738 extract32(ctx->opcode, 21, 3));
21739 gen_load_gpr(t0, rt);
21740 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21741 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21742 tcg_temp_free(t0);
21744 break;
21745 case NM_P_BAL:
21747 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21748 extract32(ctx->opcode, 1, 24) << 1;
21750 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21751 /* BC */
21752 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21753 } else {
21754 /* BALC */
21755 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21758 break;
21759 case NM_P_J:
21760 switch (extract32(ctx->opcode, 12, 4)) {
21761 case NM_JALRC:
21762 case NM_JALRC_HB:
21763 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21764 break;
21765 case NM_P_BALRSC:
21766 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21767 break;
21768 default:
21769 generate_exception_end(ctx, EXCP_RI);
21770 break;
21772 break;
21773 case NM_P_BR1:
21775 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21776 extract32(ctx->opcode, 1, 13) << 1;
21777 switch (extract32(ctx->opcode, 14, 2)) {
21778 case NM_BEQC:
21779 check_nms(ctx);
21780 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21781 break;
21782 case NM_P_BR3A:
21783 s = sextract32(ctx->opcode, 0, 1) << 14 |
21784 extract32(ctx->opcode, 1, 13) << 1;
21785 check_cp1_enabled(ctx);
21786 switch (extract32(ctx->opcode, 16, 5)) {
21787 case NM_BC1EQZC:
21788 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21789 break;
21790 case NM_BC1NEZC:
21791 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21792 break;
21793 case NM_BPOSGE32C:
21794 check_dsp_r3(ctx);
21796 int32_t imm = extract32(ctx->opcode, 1, 13) |
21797 extract32(ctx->opcode, 0, 1) << 13;
21799 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21800 imm);
21802 break;
21803 default:
21804 generate_exception_end(ctx, EXCP_RI);
21805 break;
21807 break;
21808 case NM_BGEC:
21809 if (rs == rt) {
21810 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21811 } else {
21812 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21814 break;
21815 case NM_BGEUC:
21816 if (rs == rt || rt == 0) {
21817 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21818 } else if (rs == 0) {
21819 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21820 } else {
21821 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21823 break;
21826 break;
21827 case NM_P_BR2:
21829 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21830 extract32(ctx->opcode, 1, 13) << 1;
21831 switch (extract32(ctx->opcode, 14, 2)) {
21832 case NM_BNEC:
21833 check_nms(ctx);
21834 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21835 break;
21836 case NM_BLTC:
21837 if (rs != 0 && rt != 0 && rs == rt) {
21838 /* NOP */
21839 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21840 } else {
21841 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21843 break;
21844 case NM_BLTUC:
21845 if (rs == 0 || rs == rt) {
21846 /* NOP */
21847 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21848 } else {
21849 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21851 break;
21852 default:
21853 generate_exception_end(ctx, EXCP_RI);
21854 break;
21857 break;
21858 case NM_P_BRI:
21860 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21861 extract32(ctx->opcode, 1, 10) << 1;
21862 uint32_t u = extract32(ctx->opcode, 11, 7);
21864 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21865 rt, u, s);
21867 break;
21868 default:
21869 generate_exception_end(ctx, EXCP_RI);
21870 break;
21872 return 4;
21875 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21877 uint32_t op;
21878 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21879 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21880 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21881 int offset;
21882 int imm;
21884 /* make sure instructions are on a halfword boundary */
21885 if (ctx->base.pc_next & 0x1) {
21886 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21887 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21888 tcg_temp_free(tmp);
21889 generate_exception_end(ctx, EXCP_AdEL);
21890 return 2;
21893 op = extract32(ctx->opcode, 10, 6);
21894 switch (op) {
21895 case NM_P16_MV:
21896 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21897 if (rt != 0) {
21898 /* MOVE */
21899 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21900 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21901 } else {
21902 /* P16.RI */
21903 switch (extract32(ctx->opcode, 3, 2)) {
21904 case NM_P16_SYSCALL:
21905 if (extract32(ctx->opcode, 2, 1) == 0) {
21906 generate_exception_end(ctx, EXCP_SYSCALL);
21907 } else {
21908 generate_exception_end(ctx, EXCP_RI);
21910 break;
21911 case NM_BREAK16:
21912 generate_exception_end(ctx, EXCP_BREAK);
21913 break;
21914 case NM_SDBBP16:
21915 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21916 gen_helper_do_semihosting(cpu_env);
21917 } else {
21918 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21919 generate_exception_end(ctx, EXCP_RI);
21920 } else {
21921 generate_exception_end(ctx, EXCP_DBp);
21924 break;
21925 default:
21926 generate_exception_end(ctx, EXCP_RI);
21927 break;
21930 break;
21931 case NM_P16_SHIFT:
21933 int shift = extract32(ctx->opcode, 0, 3);
21934 uint32_t opc = 0;
21935 shift = (shift == 0) ? 8 : shift;
21937 switch (extract32(ctx->opcode, 3, 1)) {
21938 case NM_SLL16:
21939 opc = OPC_SLL;
21940 break;
21941 case NM_SRL16:
21942 opc = OPC_SRL;
21943 break;
21945 gen_shift_imm(ctx, opc, rt, rs, shift);
21947 break;
21948 case NM_P16C:
21949 switch (ctx->opcode & 1) {
21950 case NM_POOL16C_0:
21951 gen_pool16c_nanomips_insn(ctx);
21952 break;
21953 case NM_LWXS16:
21954 gen_ldxs(ctx, rt, rs, rd);
21955 break;
21957 break;
21958 case NM_P16_A1:
21959 switch (extract32(ctx->opcode, 6, 1)) {
21960 case NM_ADDIUR1SP:
21961 imm = extract32(ctx->opcode, 0, 6) << 2;
21962 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21963 break;
21964 default:
21965 generate_exception_end(ctx, EXCP_RI);
21966 break;
21968 break;
21969 case NM_P16_A2:
21970 switch (extract32(ctx->opcode, 3, 1)) {
21971 case NM_ADDIUR2:
21972 imm = extract32(ctx->opcode, 0, 3) << 2;
21973 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21974 break;
21975 case NM_P_ADDIURS5:
21976 rt = extract32(ctx->opcode, 5, 5);
21977 if (rt != 0) {
21978 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21979 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21980 (extract32(ctx->opcode, 0, 3));
21981 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21983 break;
21985 break;
21986 case NM_P16_ADDU:
21987 switch (ctx->opcode & 0x1) {
21988 case NM_ADDU16:
21989 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21990 break;
21991 case NM_SUBU16:
21992 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21993 break;
21995 break;
21996 case NM_P16_4X4:
21997 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21998 extract32(ctx->opcode, 5, 3);
21999 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22000 extract32(ctx->opcode, 0, 3);
22001 rt = decode_gpr_gpr4(rt);
22002 rs = decode_gpr_gpr4(rs);
22003 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22004 (extract32(ctx->opcode, 3, 1))) {
22005 case NM_ADDU4X4:
22006 check_nms(ctx);
22007 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22008 break;
22009 case NM_MUL4X4:
22010 check_nms(ctx);
22011 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22012 break;
22013 default:
22014 generate_exception_end(ctx, EXCP_RI);
22015 break;
22017 break;
22018 case NM_LI16:
22020 int imm = extract32(ctx->opcode, 0, 7);
22021 imm = (imm == 0x7f ? -1 : imm);
22022 if (rt != 0) {
22023 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22026 break;
22027 case NM_ANDI16:
22029 uint32_t u = extract32(ctx->opcode, 0, 4);
22030 u = (u == 12) ? 0xff :
22031 (u == 13) ? 0xffff : u;
22032 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22034 break;
22035 case NM_P16_LB:
22036 offset = extract32(ctx->opcode, 0, 2);
22037 switch (extract32(ctx->opcode, 2, 2)) {
22038 case NM_LB16:
22039 gen_ld(ctx, OPC_LB, rt, rs, offset);
22040 break;
22041 case NM_SB16:
22042 rt = decode_gpr_gpr3_src_store(
22043 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22044 gen_st(ctx, OPC_SB, rt, rs, offset);
22045 break;
22046 case NM_LBU16:
22047 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22048 break;
22049 default:
22050 generate_exception_end(ctx, EXCP_RI);
22051 break;
22053 break;
22054 case NM_P16_LH:
22055 offset = extract32(ctx->opcode, 1, 2) << 1;
22056 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22057 case NM_LH16:
22058 gen_ld(ctx, OPC_LH, rt, rs, offset);
22059 break;
22060 case NM_SH16:
22061 rt = decode_gpr_gpr3_src_store(
22062 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22063 gen_st(ctx, OPC_SH, rt, rs, offset);
22064 break;
22065 case NM_LHU16:
22066 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22067 break;
22068 default:
22069 generate_exception_end(ctx, EXCP_RI);
22070 break;
22072 break;
22073 case NM_LW16:
22074 offset = extract32(ctx->opcode, 0, 4) << 2;
22075 gen_ld(ctx, OPC_LW, rt, rs, offset);
22076 break;
22077 case NM_LWSP16:
22078 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22079 offset = extract32(ctx->opcode, 0, 5) << 2;
22080 gen_ld(ctx, OPC_LW, rt, 29, offset);
22081 break;
22082 case NM_LW4X4:
22083 check_nms(ctx);
22084 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22085 extract32(ctx->opcode, 5, 3);
22086 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22087 extract32(ctx->opcode, 0, 3);
22088 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22089 (extract32(ctx->opcode, 8, 1) << 2);
22090 rt = decode_gpr_gpr4(rt);
22091 rs = decode_gpr_gpr4(rs);
22092 gen_ld(ctx, OPC_LW, rt, rs, offset);
22093 break;
22094 case NM_SW4X4:
22095 check_nms(ctx);
22096 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22097 extract32(ctx->opcode, 5, 3);
22098 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22099 extract32(ctx->opcode, 0, 3);
22100 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22101 (extract32(ctx->opcode, 8, 1) << 2);
22102 rt = decode_gpr_gpr4_zero(rt);
22103 rs = decode_gpr_gpr4(rs);
22104 gen_st(ctx, OPC_SW, rt, rs, offset);
22105 break;
22106 case NM_LWGP16:
22107 offset = extract32(ctx->opcode, 0, 7) << 2;
22108 gen_ld(ctx, OPC_LW, rt, 28, offset);
22109 break;
22110 case NM_SWSP16:
22111 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22112 offset = extract32(ctx->opcode, 0, 5) << 2;
22113 gen_st(ctx, OPC_SW, rt, 29, offset);
22114 break;
22115 case NM_SW16:
22116 rt = decode_gpr_gpr3_src_store(
22117 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22118 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22119 offset = extract32(ctx->opcode, 0, 4) << 2;
22120 gen_st(ctx, OPC_SW, rt, rs, offset);
22121 break;
22122 case NM_SWGP16:
22123 rt = decode_gpr_gpr3_src_store(
22124 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22125 offset = extract32(ctx->opcode, 0, 7) << 2;
22126 gen_st(ctx, OPC_SW, rt, 28, offset);
22127 break;
22128 case NM_BC16:
22129 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22130 (sextract32(ctx->opcode, 0, 1) << 10) |
22131 (extract32(ctx->opcode, 1, 9) << 1));
22132 break;
22133 case NM_BALC16:
22134 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22135 (sextract32(ctx->opcode, 0, 1) << 10) |
22136 (extract32(ctx->opcode, 1, 9) << 1));
22137 break;
22138 case NM_BEQZC16:
22139 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22140 (sextract32(ctx->opcode, 0, 1) << 7) |
22141 (extract32(ctx->opcode, 1, 6) << 1));
22142 break;
22143 case NM_BNEZC16:
22144 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22145 (sextract32(ctx->opcode, 0, 1) << 7) |
22146 (extract32(ctx->opcode, 1, 6) << 1));
22147 break;
22148 case NM_P16_BR:
22149 switch (ctx->opcode & 0xf) {
22150 case 0:
22151 /* P16.JRC */
22152 switch (extract32(ctx->opcode, 4, 1)) {
22153 case NM_JRC:
22154 gen_compute_branch_nm(ctx, OPC_JR, 2,
22155 extract32(ctx->opcode, 5, 5), 0, 0);
22156 break;
22157 case NM_JALRC16:
22158 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22159 extract32(ctx->opcode, 5, 5), 31, 0);
22160 break;
22162 break;
22163 default:
22165 /* P16.BRI */
22166 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22167 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22168 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22169 extract32(ctx->opcode, 0, 4) << 1);
22171 break;
22173 break;
22174 case NM_P16_SR:
22176 int count = extract32(ctx->opcode, 0, 4);
22177 int u = extract32(ctx->opcode, 4, 4) << 4;
22179 rt = 30 + extract32(ctx->opcode, 9, 1);
22180 switch (extract32(ctx->opcode, 8, 1)) {
22181 case NM_SAVE16:
22182 gen_save(ctx, rt, count, 0, u);
22183 break;
22184 case NM_RESTORE_JRC16:
22185 gen_restore(ctx, rt, count, 0, u);
22186 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22187 break;
22190 break;
22191 case NM_MOVEP:
22192 case NM_MOVEPREV:
22193 check_nms(ctx);
22195 static const int gpr2reg1[] = {4, 5, 6, 7};
22196 static const int gpr2reg2[] = {5, 6, 7, 8};
22197 int re;
22198 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22199 extract32(ctx->opcode, 8, 1);
22200 int r1 = gpr2reg1[rd2];
22201 int r2 = gpr2reg2[rd2];
22202 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22203 extract32(ctx->opcode, 0, 3);
22204 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22205 extract32(ctx->opcode, 5, 3);
22206 TCGv t0 = tcg_temp_new();
22207 TCGv t1 = tcg_temp_new();
22208 if (op == NM_MOVEP) {
22209 rd = r1;
22210 re = r2;
22211 rs = decode_gpr_gpr4_zero(r3);
22212 rt = decode_gpr_gpr4_zero(r4);
22213 } else {
22214 rd = decode_gpr_gpr4(r3);
22215 re = decode_gpr_gpr4(r4);
22216 rs = r1;
22217 rt = r2;
22219 gen_load_gpr(t0, rs);
22220 gen_load_gpr(t1, rt);
22221 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22222 tcg_gen_mov_tl(cpu_gpr[re], t1);
22223 tcg_temp_free(t0);
22224 tcg_temp_free(t1);
22226 break;
22227 default:
22228 return decode_nanomips_32_48_opc(env, ctx);
22231 return 2;
22235 /* SmartMIPS extension to MIPS32 */
22237 #if defined(TARGET_MIPS64)
22239 /* MDMX extension to MIPS64 */
22241 #endif
22243 /* MIPSDSP functions. */
22244 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22245 int rd, int base, int offset)
22247 TCGv t0;
22249 check_dsp(ctx);
22250 t0 = tcg_temp_new();
22252 if (base == 0) {
22253 gen_load_gpr(t0, offset);
22254 } else if (offset == 0) {
22255 gen_load_gpr(t0, base);
22256 } else {
22257 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22260 switch (opc) {
22261 case OPC_LBUX:
22262 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22263 gen_store_gpr(t0, rd);
22264 break;
22265 case OPC_LHX:
22266 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22267 gen_store_gpr(t0, rd);
22268 break;
22269 case OPC_LWX:
22270 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22271 gen_store_gpr(t0, rd);
22272 break;
22273 #if defined(TARGET_MIPS64)
22274 case OPC_LDX:
22275 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22276 gen_store_gpr(t0, rd);
22277 break;
22278 #endif
22280 tcg_temp_free(t0);
22283 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22284 int ret, int v1, int v2)
22286 TCGv v1_t;
22287 TCGv v2_t;
22289 if (ret == 0) {
22290 /* Treat as NOP. */
22291 return;
22294 v1_t = tcg_temp_new();
22295 v2_t = tcg_temp_new();
22297 gen_load_gpr(v1_t, v1);
22298 gen_load_gpr(v2_t, v2);
22300 switch (op1) {
22301 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22302 case OPC_MULT_G_2E:
22303 check_dsp_r2(ctx);
22304 switch (op2) {
22305 case OPC_ADDUH_QB:
22306 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22307 break;
22308 case OPC_ADDUH_R_QB:
22309 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22310 break;
22311 case OPC_ADDQH_PH:
22312 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22313 break;
22314 case OPC_ADDQH_R_PH:
22315 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22316 break;
22317 case OPC_ADDQH_W:
22318 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22319 break;
22320 case OPC_ADDQH_R_W:
22321 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22322 break;
22323 case OPC_SUBUH_QB:
22324 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22325 break;
22326 case OPC_SUBUH_R_QB:
22327 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22328 break;
22329 case OPC_SUBQH_PH:
22330 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22331 break;
22332 case OPC_SUBQH_R_PH:
22333 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22334 break;
22335 case OPC_SUBQH_W:
22336 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22337 break;
22338 case OPC_SUBQH_R_W:
22339 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22340 break;
22342 break;
22343 case OPC_ABSQ_S_PH_DSP:
22344 switch (op2) {
22345 case OPC_ABSQ_S_QB:
22346 check_dsp_r2(ctx);
22347 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22348 break;
22349 case OPC_ABSQ_S_PH:
22350 check_dsp(ctx);
22351 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22352 break;
22353 case OPC_ABSQ_S_W:
22354 check_dsp(ctx);
22355 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22356 break;
22357 case OPC_PRECEQ_W_PHL:
22358 check_dsp(ctx);
22359 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22360 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22361 break;
22362 case OPC_PRECEQ_W_PHR:
22363 check_dsp(ctx);
22364 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22365 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22366 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22367 break;
22368 case OPC_PRECEQU_PH_QBL:
22369 check_dsp(ctx);
22370 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22371 break;
22372 case OPC_PRECEQU_PH_QBR:
22373 check_dsp(ctx);
22374 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22375 break;
22376 case OPC_PRECEQU_PH_QBLA:
22377 check_dsp(ctx);
22378 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22379 break;
22380 case OPC_PRECEQU_PH_QBRA:
22381 check_dsp(ctx);
22382 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22383 break;
22384 case OPC_PRECEU_PH_QBL:
22385 check_dsp(ctx);
22386 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22387 break;
22388 case OPC_PRECEU_PH_QBR:
22389 check_dsp(ctx);
22390 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22391 break;
22392 case OPC_PRECEU_PH_QBLA:
22393 check_dsp(ctx);
22394 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22395 break;
22396 case OPC_PRECEU_PH_QBRA:
22397 check_dsp(ctx);
22398 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22399 break;
22401 break;
22402 case OPC_ADDU_QB_DSP:
22403 switch (op2) {
22404 case OPC_ADDQ_PH:
22405 check_dsp(ctx);
22406 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22407 break;
22408 case OPC_ADDQ_S_PH:
22409 check_dsp(ctx);
22410 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22411 break;
22412 case OPC_ADDQ_S_W:
22413 check_dsp(ctx);
22414 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22415 break;
22416 case OPC_ADDU_QB:
22417 check_dsp(ctx);
22418 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22419 break;
22420 case OPC_ADDU_S_QB:
22421 check_dsp(ctx);
22422 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22423 break;
22424 case OPC_ADDU_PH:
22425 check_dsp_r2(ctx);
22426 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22427 break;
22428 case OPC_ADDU_S_PH:
22429 check_dsp_r2(ctx);
22430 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22431 break;
22432 case OPC_SUBQ_PH:
22433 check_dsp(ctx);
22434 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22435 break;
22436 case OPC_SUBQ_S_PH:
22437 check_dsp(ctx);
22438 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22439 break;
22440 case OPC_SUBQ_S_W:
22441 check_dsp(ctx);
22442 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22443 break;
22444 case OPC_SUBU_QB:
22445 check_dsp(ctx);
22446 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22447 break;
22448 case OPC_SUBU_S_QB:
22449 check_dsp(ctx);
22450 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22451 break;
22452 case OPC_SUBU_PH:
22453 check_dsp_r2(ctx);
22454 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22455 break;
22456 case OPC_SUBU_S_PH:
22457 check_dsp_r2(ctx);
22458 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22459 break;
22460 case OPC_ADDSC:
22461 check_dsp(ctx);
22462 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22463 break;
22464 case OPC_ADDWC:
22465 check_dsp(ctx);
22466 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22467 break;
22468 case OPC_MODSUB:
22469 check_dsp(ctx);
22470 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22471 break;
22472 case OPC_RADDU_W_QB:
22473 check_dsp(ctx);
22474 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22475 break;
22477 break;
22478 case OPC_CMPU_EQ_QB_DSP:
22479 switch (op2) {
22480 case OPC_PRECR_QB_PH:
22481 check_dsp_r2(ctx);
22482 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22483 break;
22484 case OPC_PRECRQ_QB_PH:
22485 check_dsp(ctx);
22486 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22487 break;
22488 case OPC_PRECR_SRA_PH_W:
22489 check_dsp_r2(ctx);
22491 TCGv_i32 sa_t = tcg_const_i32(v2);
22492 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22493 cpu_gpr[ret]);
22494 tcg_temp_free_i32(sa_t);
22495 break;
22497 case OPC_PRECR_SRA_R_PH_W:
22498 check_dsp_r2(ctx);
22500 TCGv_i32 sa_t = tcg_const_i32(v2);
22501 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22502 cpu_gpr[ret]);
22503 tcg_temp_free_i32(sa_t);
22504 break;
22506 case OPC_PRECRQ_PH_W:
22507 check_dsp(ctx);
22508 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22509 break;
22510 case OPC_PRECRQ_RS_PH_W:
22511 check_dsp(ctx);
22512 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22513 break;
22514 case OPC_PRECRQU_S_QB_PH:
22515 check_dsp(ctx);
22516 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22517 break;
22519 break;
22520 #ifdef TARGET_MIPS64
22521 case OPC_ABSQ_S_QH_DSP:
22522 switch (op2) {
22523 case OPC_PRECEQ_L_PWL:
22524 check_dsp(ctx);
22525 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22526 break;
22527 case OPC_PRECEQ_L_PWR:
22528 check_dsp(ctx);
22529 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22530 break;
22531 case OPC_PRECEQ_PW_QHL:
22532 check_dsp(ctx);
22533 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22534 break;
22535 case OPC_PRECEQ_PW_QHR:
22536 check_dsp(ctx);
22537 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22538 break;
22539 case OPC_PRECEQ_PW_QHLA:
22540 check_dsp(ctx);
22541 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22542 break;
22543 case OPC_PRECEQ_PW_QHRA:
22544 check_dsp(ctx);
22545 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22546 break;
22547 case OPC_PRECEQU_QH_OBL:
22548 check_dsp(ctx);
22549 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22550 break;
22551 case OPC_PRECEQU_QH_OBR:
22552 check_dsp(ctx);
22553 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22554 break;
22555 case OPC_PRECEQU_QH_OBLA:
22556 check_dsp(ctx);
22557 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22558 break;
22559 case OPC_PRECEQU_QH_OBRA:
22560 check_dsp(ctx);
22561 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22562 break;
22563 case OPC_PRECEU_QH_OBL:
22564 check_dsp(ctx);
22565 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22566 break;
22567 case OPC_PRECEU_QH_OBR:
22568 check_dsp(ctx);
22569 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22570 break;
22571 case OPC_PRECEU_QH_OBLA:
22572 check_dsp(ctx);
22573 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22574 break;
22575 case OPC_PRECEU_QH_OBRA:
22576 check_dsp(ctx);
22577 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22578 break;
22579 case OPC_ABSQ_S_OB:
22580 check_dsp_r2(ctx);
22581 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22582 break;
22583 case OPC_ABSQ_S_PW:
22584 check_dsp(ctx);
22585 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22586 break;
22587 case OPC_ABSQ_S_QH:
22588 check_dsp(ctx);
22589 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22590 break;
22592 break;
22593 case OPC_ADDU_OB_DSP:
22594 switch (op2) {
22595 case OPC_RADDU_L_OB:
22596 check_dsp(ctx);
22597 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22598 break;
22599 case OPC_SUBQ_PW:
22600 check_dsp(ctx);
22601 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22602 break;
22603 case OPC_SUBQ_S_PW:
22604 check_dsp(ctx);
22605 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22606 break;
22607 case OPC_SUBQ_QH:
22608 check_dsp(ctx);
22609 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22610 break;
22611 case OPC_SUBQ_S_QH:
22612 check_dsp(ctx);
22613 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22614 break;
22615 case OPC_SUBU_OB:
22616 check_dsp(ctx);
22617 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22618 break;
22619 case OPC_SUBU_S_OB:
22620 check_dsp(ctx);
22621 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22622 break;
22623 case OPC_SUBU_QH:
22624 check_dsp_r2(ctx);
22625 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22626 break;
22627 case OPC_SUBU_S_QH:
22628 check_dsp_r2(ctx);
22629 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22630 break;
22631 case OPC_SUBUH_OB:
22632 check_dsp_r2(ctx);
22633 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22634 break;
22635 case OPC_SUBUH_R_OB:
22636 check_dsp_r2(ctx);
22637 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22638 break;
22639 case OPC_ADDQ_PW:
22640 check_dsp(ctx);
22641 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22642 break;
22643 case OPC_ADDQ_S_PW:
22644 check_dsp(ctx);
22645 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22646 break;
22647 case OPC_ADDQ_QH:
22648 check_dsp(ctx);
22649 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22650 break;
22651 case OPC_ADDQ_S_QH:
22652 check_dsp(ctx);
22653 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22654 break;
22655 case OPC_ADDU_OB:
22656 check_dsp(ctx);
22657 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22658 break;
22659 case OPC_ADDU_S_OB:
22660 check_dsp(ctx);
22661 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22662 break;
22663 case OPC_ADDU_QH:
22664 check_dsp_r2(ctx);
22665 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22666 break;
22667 case OPC_ADDU_S_QH:
22668 check_dsp_r2(ctx);
22669 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22670 break;
22671 case OPC_ADDUH_OB:
22672 check_dsp_r2(ctx);
22673 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22674 break;
22675 case OPC_ADDUH_R_OB:
22676 check_dsp_r2(ctx);
22677 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22678 break;
22680 break;
22681 case OPC_CMPU_EQ_OB_DSP:
22682 switch (op2) {
22683 case OPC_PRECR_OB_QH:
22684 check_dsp_r2(ctx);
22685 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22686 break;
22687 case OPC_PRECR_SRA_QH_PW:
22688 check_dsp_r2(ctx);
22690 TCGv_i32 ret_t = tcg_const_i32(ret);
22691 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22692 tcg_temp_free_i32(ret_t);
22693 break;
22695 case OPC_PRECR_SRA_R_QH_PW:
22696 check_dsp_r2(ctx);
22698 TCGv_i32 sa_v = tcg_const_i32(ret);
22699 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22700 tcg_temp_free_i32(sa_v);
22701 break;
22703 case OPC_PRECRQ_OB_QH:
22704 check_dsp(ctx);
22705 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22706 break;
22707 case OPC_PRECRQ_PW_L:
22708 check_dsp(ctx);
22709 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22710 break;
22711 case OPC_PRECRQ_QH_PW:
22712 check_dsp(ctx);
22713 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22714 break;
22715 case OPC_PRECRQ_RS_QH_PW:
22716 check_dsp(ctx);
22717 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22718 break;
22719 case OPC_PRECRQU_S_OB_QH:
22720 check_dsp(ctx);
22721 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22722 break;
22724 break;
22725 #endif
22728 tcg_temp_free(v1_t);
22729 tcg_temp_free(v2_t);
22732 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22733 int ret, int v1, int v2)
22735 uint32_t op2;
22736 TCGv t0;
22737 TCGv v1_t;
22738 TCGv v2_t;
22740 if (ret == 0) {
22741 /* Treat as NOP. */
22742 return;
22745 t0 = tcg_temp_new();
22746 v1_t = tcg_temp_new();
22747 v2_t = tcg_temp_new();
22749 tcg_gen_movi_tl(t0, v1);
22750 gen_load_gpr(v1_t, v1);
22751 gen_load_gpr(v2_t, v2);
22753 switch (opc) {
22754 case OPC_SHLL_QB_DSP:
22756 op2 = MASK_SHLL_QB(ctx->opcode);
22757 switch (op2) {
22758 case OPC_SHLL_QB:
22759 check_dsp(ctx);
22760 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22761 break;
22762 case OPC_SHLLV_QB:
22763 check_dsp(ctx);
22764 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_SHLL_PH:
22767 check_dsp(ctx);
22768 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22769 break;
22770 case OPC_SHLLV_PH:
22771 check_dsp(ctx);
22772 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_SHLL_S_PH:
22775 check_dsp(ctx);
22776 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22777 break;
22778 case OPC_SHLLV_S_PH:
22779 check_dsp(ctx);
22780 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_SHLL_S_W:
22783 check_dsp(ctx);
22784 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22785 break;
22786 case OPC_SHLLV_S_W:
22787 check_dsp(ctx);
22788 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_SHRL_QB:
22791 check_dsp(ctx);
22792 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22793 break;
22794 case OPC_SHRLV_QB:
22795 check_dsp(ctx);
22796 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22797 break;
22798 case OPC_SHRL_PH:
22799 check_dsp_r2(ctx);
22800 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22801 break;
22802 case OPC_SHRLV_PH:
22803 check_dsp_r2(ctx);
22804 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22805 break;
22806 case OPC_SHRA_QB:
22807 check_dsp_r2(ctx);
22808 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22809 break;
22810 case OPC_SHRA_R_QB:
22811 check_dsp_r2(ctx);
22812 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22813 break;
22814 case OPC_SHRAV_QB:
22815 check_dsp_r2(ctx);
22816 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22817 break;
22818 case OPC_SHRAV_R_QB:
22819 check_dsp_r2(ctx);
22820 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22821 break;
22822 case OPC_SHRA_PH:
22823 check_dsp(ctx);
22824 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22825 break;
22826 case OPC_SHRA_R_PH:
22827 check_dsp(ctx);
22828 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22829 break;
22830 case OPC_SHRAV_PH:
22831 check_dsp(ctx);
22832 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22833 break;
22834 case OPC_SHRAV_R_PH:
22835 check_dsp(ctx);
22836 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22837 break;
22838 case OPC_SHRA_R_W:
22839 check_dsp(ctx);
22840 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22841 break;
22842 case OPC_SHRAV_R_W:
22843 check_dsp(ctx);
22844 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22845 break;
22846 default: /* Invalid */
22847 MIPS_INVAL("MASK SHLL.QB");
22848 generate_exception_end(ctx, EXCP_RI);
22849 break;
22851 break;
22853 #ifdef TARGET_MIPS64
22854 case OPC_SHLL_OB_DSP:
22855 op2 = MASK_SHLL_OB(ctx->opcode);
22856 switch (op2) {
22857 case OPC_SHLL_PW:
22858 check_dsp(ctx);
22859 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22860 break;
22861 case OPC_SHLLV_PW:
22862 check_dsp(ctx);
22863 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22864 break;
22865 case OPC_SHLL_S_PW:
22866 check_dsp(ctx);
22867 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22868 break;
22869 case OPC_SHLLV_S_PW:
22870 check_dsp(ctx);
22871 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22872 break;
22873 case OPC_SHLL_OB:
22874 check_dsp(ctx);
22875 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22876 break;
22877 case OPC_SHLLV_OB:
22878 check_dsp(ctx);
22879 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22880 break;
22881 case OPC_SHLL_QH:
22882 check_dsp(ctx);
22883 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22884 break;
22885 case OPC_SHLLV_QH:
22886 check_dsp(ctx);
22887 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22888 break;
22889 case OPC_SHLL_S_QH:
22890 check_dsp(ctx);
22891 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22892 break;
22893 case OPC_SHLLV_S_QH:
22894 check_dsp(ctx);
22895 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22896 break;
22897 case OPC_SHRA_OB:
22898 check_dsp_r2(ctx);
22899 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22900 break;
22901 case OPC_SHRAV_OB:
22902 check_dsp_r2(ctx);
22903 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22904 break;
22905 case OPC_SHRA_R_OB:
22906 check_dsp_r2(ctx);
22907 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22908 break;
22909 case OPC_SHRAV_R_OB:
22910 check_dsp_r2(ctx);
22911 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22912 break;
22913 case OPC_SHRA_PW:
22914 check_dsp(ctx);
22915 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22916 break;
22917 case OPC_SHRAV_PW:
22918 check_dsp(ctx);
22919 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22920 break;
22921 case OPC_SHRA_R_PW:
22922 check_dsp(ctx);
22923 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22924 break;
22925 case OPC_SHRAV_R_PW:
22926 check_dsp(ctx);
22927 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22928 break;
22929 case OPC_SHRA_QH:
22930 check_dsp(ctx);
22931 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22932 break;
22933 case OPC_SHRAV_QH:
22934 check_dsp(ctx);
22935 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22936 break;
22937 case OPC_SHRA_R_QH:
22938 check_dsp(ctx);
22939 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22940 break;
22941 case OPC_SHRAV_R_QH:
22942 check_dsp(ctx);
22943 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22944 break;
22945 case OPC_SHRL_OB:
22946 check_dsp(ctx);
22947 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22948 break;
22949 case OPC_SHRLV_OB:
22950 check_dsp(ctx);
22951 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22952 break;
22953 case OPC_SHRL_QH:
22954 check_dsp_r2(ctx);
22955 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22956 break;
22957 case OPC_SHRLV_QH:
22958 check_dsp_r2(ctx);
22959 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22960 break;
22961 default: /* Invalid */
22962 MIPS_INVAL("MASK SHLL.OB");
22963 generate_exception_end(ctx, EXCP_RI);
22964 break;
22966 break;
22967 #endif
22970 tcg_temp_free(t0);
22971 tcg_temp_free(v1_t);
22972 tcg_temp_free(v2_t);
22975 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22976 int ret, int v1, int v2, int check_ret)
22978 TCGv_i32 t0;
22979 TCGv v1_t;
22980 TCGv v2_t;
22982 if ((ret == 0) && (check_ret == 1)) {
22983 /* Treat as NOP. */
22984 return;
22987 t0 = tcg_temp_new_i32();
22988 v1_t = tcg_temp_new();
22989 v2_t = tcg_temp_new();
22991 tcg_gen_movi_i32(t0, ret);
22992 gen_load_gpr(v1_t, v1);
22993 gen_load_gpr(v2_t, v2);
22995 switch (op1) {
22996 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22997 * the same mask and op1. */
22998 case OPC_MULT_G_2E:
22999 check_dsp_r2(ctx);
23000 switch (op2) {
23001 case OPC_MUL_PH:
23002 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23003 break;
23004 case OPC_MUL_S_PH:
23005 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23006 break;
23007 case OPC_MULQ_S_W:
23008 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23009 break;
23010 case OPC_MULQ_RS_W:
23011 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23012 break;
23014 break;
23015 case OPC_DPA_W_PH_DSP:
23016 switch (op2) {
23017 case OPC_DPAU_H_QBL:
23018 check_dsp(ctx);
23019 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23020 break;
23021 case OPC_DPAU_H_QBR:
23022 check_dsp(ctx);
23023 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23024 break;
23025 case OPC_DPSU_H_QBL:
23026 check_dsp(ctx);
23027 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23028 break;
23029 case OPC_DPSU_H_QBR:
23030 check_dsp(ctx);
23031 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23032 break;
23033 case OPC_DPA_W_PH:
23034 check_dsp_r2(ctx);
23035 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_DPAX_W_PH:
23038 check_dsp_r2(ctx);
23039 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23040 break;
23041 case OPC_DPAQ_S_W_PH:
23042 check_dsp(ctx);
23043 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23044 break;
23045 case OPC_DPAQX_S_W_PH:
23046 check_dsp_r2(ctx);
23047 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23048 break;
23049 case OPC_DPAQX_SA_W_PH:
23050 check_dsp_r2(ctx);
23051 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23052 break;
23053 case OPC_DPS_W_PH:
23054 check_dsp_r2(ctx);
23055 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23056 break;
23057 case OPC_DPSX_W_PH:
23058 check_dsp_r2(ctx);
23059 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23060 break;
23061 case OPC_DPSQ_S_W_PH:
23062 check_dsp(ctx);
23063 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23064 break;
23065 case OPC_DPSQX_S_W_PH:
23066 check_dsp_r2(ctx);
23067 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23068 break;
23069 case OPC_DPSQX_SA_W_PH:
23070 check_dsp_r2(ctx);
23071 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23072 break;
23073 case OPC_MULSAQ_S_W_PH:
23074 check_dsp(ctx);
23075 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23076 break;
23077 case OPC_DPAQ_SA_L_W:
23078 check_dsp(ctx);
23079 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23080 break;
23081 case OPC_DPSQ_SA_L_W:
23082 check_dsp(ctx);
23083 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23084 break;
23085 case OPC_MAQ_S_W_PHL:
23086 check_dsp(ctx);
23087 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23088 break;
23089 case OPC_MAQ_S_W_PHR:
23090 check_dsp(ctx);
23091 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23092 break;
23093 case OPC_MAQ_SA_W_PHL:
23094 check_dsp(ctx);
23095 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23096 break;
23097 case OPC_MAQ_SA_W_PHR:
23098 check_dsp(ctx);
23099 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23100 break;
23101 case OPC_MULSA_W_PH:
23102 check_dsp_r2(ctx);
23103 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23104 break;
23106 break;
23107 #ifdef TARGET_MIPS64
23108 case OPC_DPAQ_W_QH_DSP:
23110 int ac = ret & 0x03;
23111 tcg_gen_movi_i32(t0, ac);
23113 switch (op2) {
23114 case OPC_DMADD:
23115 check_dsp(ctx);
23116 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23117 break;
23118 case OPC_DMADDU:
23119 check_dsp(ctx);
23120 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23121 break;
23122 case OPC_DMSUB:
23123 check_dsp(ctx);
23124 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23125 break;
23126 case OPC_DMSUBU:
23127 check_dsp(ctx);
23128 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23129 break;
23130 case OPC_DPA_W_QH:
23131 check_dsp_r2(ctx);
23132 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23133 break;
23134 case OPC_DPAQ_S_W_QH:
23135 check_dsp(ctx);
23136 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23137 break;
23138 case OPC_DPAQ_SA_L_PW:
23139 check_dsp(ctx);
23140 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23141 break;
23142 case OPC_DPAU_H_OBL:
23143 check_dsp(ctx);
23144 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23145 break;
23146 case OPC_DPAU_H_OBR:
23147 check_dsp(ctx);
23148 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23149 break;
23150 case OPC_DPS_W_QH:
23151 check_dsp_r2(ctx);
23152 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23153 break;
23154 case OPC_DPSQ_S_W_QH:
23155 check_dsp(ctx);
23156 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23157 break;
23158 case OPC_DPSQ_SA_L_PW:
23159 check_dsp(ctx);
23160 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23161 break;
23162 case OPC_DPSU_H_OBL:
23163 check_dsp(ctx);
23164 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23165 break;
23166 case OPC_DPSU_H_OBR:
23167 check_dsp(ctx);
23168 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23169 break;
23170 case OPC_MAQ_S_L_PWL:
23171 check_dsp(ctx);
23172 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23173 break;
23174 case OPC_MAQ_S_L_PWR:
23175 check_dsp(ctx);
23176 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23177 break;
23178 case OPC_MAQ_S_W_QHLL:
23179 check_dsp(ctx);
23180 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23181 break;
23182 case OPC_MAQ_SA_W_QHLL:
23183 check_dsp(ctx);
23184 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23185 break;
23186 case OPC_MAQ_S_W_QHLR:
23187 check_dsp(ctx);
23188 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23189 break;
23190 case OPC_MAQ_SA_W_QHLR:
23191 check_dsp(ctx);
23192 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23193 break;
23194 case OPC_MAQ_S_W_QHRL:
23195 check_dsp(ctx);
23196 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23197 break;
23198 case OPC_MAQ_SA_W_QHRL:
23199 check_dsp(ctx);
23200 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23201 break;
23202 case OPC_MAQ_S_W_QHRR:
23203 check_dsp(ctx);
23204 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23205 break;
23206 case OPC_MAQ_SA_W_QHRR:
23207 check_dsp(ctx);
23208 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23209 break;
23210 case OPC_MULSAQ_S_L_PW:
23211 check_dsp(ctx);
23212 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23213 break;
23214 case OPC_MULSAQ_S_W_QH:
23215 check_dsp(ctx);
23216 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23217 break;
23220 break;
23221 #endif
23222 case OPC_ADDU_QB_DSP:
23223 switch (op2) {
23224 case OPC_MULEU_S_PH_QBL:
23225 check_dsp(ctx);
23226 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23227 break;
23228 case OPC_MULEU_S_PH_QBR:
23229 check_dsp(ctx);
23230 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23231 break;
23232 case OPC_MULQ_RS_PH:
23233 check_dsp(ctx);
23234 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23235 break;
23236 case OPC_MULEQ_S_W_PHL:
23237 check_dsp(ctx);
23238 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23239 break;
23240 case OPC_MULEQ_S_W_PHR:
23241 check_dsp(ctx);
23242 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23243 break;
23244 case OPC_MULQ_S_PH:
23245 check_dsp_r2(ctx);
23246 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23247 break;
23249 break;
23250 #ifdef TARGET_MIPS64
23251 case OPC_ADDU_OB_DSP:
23252 switch (op2) {
23253 case OPC_MULEQ_S_PW_QHL:
23254 check_dsp(ctx);
23255 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23256 break;
23257 case OPC_MULEQ_S_PW_QHR:
23258 check_dsp(ctx);
23259 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_MULEU_S_QH_OBL:
23262 check_dsp(ctx);
23263 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23264 break;
23265 case OPC_MULEU_S_QH_OBR:
23266 check_dsp(ctx);
23267 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23268 break;
23269 case OPC_MULQ_RS_QH:
23270 check_dsp(ctx);
23271 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23272 break;
23274 break;
23275 #endif
23278 tcg_temp_free_i32(t0);
23279 tcg_temp_free(v1_t);
23280 tcg_temp_free(v2_t);
23283 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23284 int ret, int val)
23286 int16_t imm;
23287 TCGv t0;
23288 TCGv val_t;
23290 if (ret == 0) {
23291 /* Treat as NOP. */
23292 return;
23295 t0 = tcg_temp_new();
23296 val_t = tcg_temp_new();
23297 gen_load_gpr(val_t, val);
23299 switch (op1) {
23300 case OPC_ABSQ_S_PH_DSP:
23301 switch (op2) {
23302 case OPC_BITREV:
23303 check_dsp(ctx);
23304 gen_helper_bitrev(cpu_gpr[ret], val_t);
23305 break;
23306 case OPC_REPL_QB:
23307 check_dsp(ctx);
23309 target_long result;
23310 imm = (ctx->opcode >> 16) & 0xFF;
23311 result = (uint32_t)imm << 24 |
23312 (uint32_t)imm << 16 |
23313 (uint32_t)imm << 8 |
23314 (uint32_t)imm;
23315 result = (int32_t)result;
23316 tcg_gen_movi_tl(cpu_gpr[ret], result);
23318 break;
23319 case OPC_REPLV_QB:
23320 check_dsp(ctx);
23321 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23322 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23323 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23324 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23325 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23326 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23327 break;
23328 case OPC_REPL_PH:
23329 check_dsp(ctx);
23331 imm = (ctx->opcode >> 16) & 0x03FF;
23332 imm = (int16_t)(imm << 6) >> 6;
23333 tcg_gen_movi_tl(cpu_gpr[ret], \
23334 (target_long)((int32_t)imm << 16 | \
23335 (uint16_t)imm));
23337 break;
23338 case OPC_REPLV_PH:
23339 check_dsp(ctx);
23340 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23341 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23342 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23343 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23344 break;
23346 break;
23347 #ifdef TARGET_MIPS64
23348 case OPC_ABSQ_S_QH_DSP:
23349 switch (op2) {
23350 case OPC_REPL_OB:
23351 check_dsp(ctx);
23353 target_long temp;
23355 imm = (ctx->opcode >> 16) & 0xFF;
23356 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23357 temp = (temp << 16) | temp;
23358 temp = (temp << 32) | temp;
23359 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23360 break;
23362 case OPC_REPL_PW:
23363 check_dsp(ctx);
23365 target_long temp;
23367 imm = (ctx->opcode >> 16) & 0x03FF;
23368 imm = (int16_t)(imm << 6) >> 6;
23369 temp = ((target_long)imm << 32) \
23370 | ((target_long)imm & 0xFFFFFFFF);
23371 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23372 break;
23374 case OPC_REPL_QH:
23375 check_dsp(ctx);
23377 target_long temp;
23379 imm = (ctx->opcode >> 16) & 0x03FF;
23380 imm = (int16_t)(imm << 6) >> 6;
23382 temp = ((uint64_t)(uint16_t)imm << 48) |
23383 ((uint64_t)(uint16_t)imm << 32) |
23384 ((uint64_t)(uint16_t)imm << 16) |
23385 (uint64_t)(uint16_t)imm;
23386 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23387 break;
23389 case OPC_REPLV_OB:
23390 check_dsp(ctx);
23391 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23392 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23393 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23394 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23395 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23396 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23397 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23398 break;
23399 case OPC_REPLV_PW:
23400 check_dsp(ctx);
23401 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23402 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23403 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23404 break;
23405 case OPC_REPLV_QH:
23406 check_dsp(ctx);
23407 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23408 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23409 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23410 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23411 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23412 break;
23414 break;
23415 #endif
23417 tcg_temp_free(t0);
23418 tcg_temp_free(val_t);
23421 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23422 uint32_t op1, uint32_t op2,
23423 int ret, int v1, int v2, int check_ret)
23425 TCGv t1;
23426 TCGv v1_t;
23427 TCGv v2_t;
23429 if ((ret == 0) && (check_ret == 1)) {
23430 /* Treat as NOP. */
23431 return;
23434 t1 = tcg_temp_new();
23435 v1_t = tcg_temp_new();
23436 v2_t = tcg_temp_new();
23438 gen_load_gpr(v1_t, v1);
23439 gen_load_gpr(v2_t, v2);
23441 switch (op1) {
23442 case OPC_CMPU_EQ_QB_DSP:
23443 switch (op2) {
23444 case OPC_CMPU_EQ_QB:
23445 check_dsp(ctx);
23446 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23447 break;
23448 case OPC_CMPU_LT_QB:
23449 check_dsp(ctx);
23450 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23451 break;
23452 case OPC_CMPU_LE_QB:
23453 check_dsp(ctx);
23454 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23455 break;
23456 case OPC_CMPGU_EQ_QB:
23457 check_dsp(ctx);
23458 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23459 break;
23460 case OPC_CMPGU_LT_QB:
23461 check_dsp(ctx);
23462 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23463 break;
23464 case OPC_CMPGU_LE_QB:
23465 check_dsp(ctx);
23466 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23467 break;
23468 case OPC_CMPGDU_EQ_QB:
23469 check_dsp_r2(ctx);
23470 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23471 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23472 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23473 tcg_gen_shli_tl(t1, t1, 24);
23474 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23475 break;
23476 case OPC_CMPGDU_LT_QB:
23477 check_dsp_r2(ctx);
23478 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23479 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23480 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23481 tcg_gen_shli_tl(t1, t1, 24);
23482 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23483 break;
23484 case OPC_CMPGDU_LE_QB:
23485 check_dsp_r2(ctx);
23486 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23487 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23488 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23489 tcg_gen_shli_tl(t1, t1, 24);
23490 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23491 break;
23492 case OPC_CMP_EQ_PH:
23493 check_dsp(ctx);
23494 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23495 break;
23496 case OPC_CMP_LT_PH:
23497 check_dsp(ctx);
23498 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23499 break;
23500 case OPC_CMP_LE_PH:
23501 check_dsp(ctx);
23502 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23503 break;
23504 case OPC_PICK_QB:
23505 check_dsp(ctx);
23506 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23507 break;
23508 case OPC_PICK_PH:
23509 check_dsp(ctx);
23510 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23511 break;
23512 case OPC_PACKRL_PH:
23513 check_dsp(ctx);
23514 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23515 break;
23517 break;
23518 #ifdef TARGET_MIPS64
23519 case OPC_CMPU_EQ_OB_DSP:
23520 switch (op2) {
23521 case OPC_CMP_EQ_PW:
23522 check_dsp(ctx);
23523 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23524 break;
23525 case OPC_CMP_LT_PW:
23526 check_dsp(ctx);
23527 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23528 break;
23529 case OPC_CMP_LE_PW:
23530 check_dsp(ctx);
23531 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23532 break;
23533 case OPC_CMP_EQ_QH:
23534 check_dsp(ctx);
23535 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23536 break;
23537 case OPC_CMP_LT_QH:
23538 check_dsp(ctx);
23539 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23540 break;
23541 case OPC_CMP_LE_QH:
23542 check_dsp(ctx);
23543 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23544 break;
23545 case OPC_CMPGDU_EQ_OB:
23546 check_dsp_r2(ctx);
23547 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23548 break;
23549 case OPC_CMPGDU_LT_OB:
23550 check_dsp_r2(ctx);
23551 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23552 break;
23553 case OPC_CMPGDU_LE_OB:
23554 check_dsp_r2(ctx);
23555 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23556 break;
23557 case OPC_CMPGU_EQ_OB:
23558 check_dsp(ctx);
23559 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23560 break;
23561 case OPC_CMPGU_LT_OB:
23562 check_dsp(ctx);
23563 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23564 break;
23565 case OPC_CMPGU_LE_OB:
23566 check_dsp(ctx);
23567 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23568 break;
23569 case OPC_CMPU_EQ_OB:
23570 check_dsp(ctx);
23571 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23572 break;
23573 case OPC_CMPU_LT_OB:
23574 check_dsp(ctx);
23575 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23576 break;
23577 case OPC_CMPU_LE_OB:
23578 check_dsp(ctx);
23579 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23580 break;
23581 case OPC_PACKRL_PW:
23582 check_dsp(ctx);
23583 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23584 break;
23585 case OPC_PICK_OB:
23586 check_dsp(ctx);
23587 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23588 break;
23589 case OPC_PICK_PW:
23590 check_dsp(ctx);
23591 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23592 break;
23593 case OPC_PICK_QH:
23594 check_dsp(ctx);
23595 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23596 break;
23598 break;
23599 #endif
23602 tcg_temp_free(t1);
23603 tcg_temp_free(v1_t);
23604 tcg_temp_free(v2_t);
23607 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23608 uint32_t op1, int rt, int rs, int sa)
23610 TCGv t0;
23612 check_dsp_r2(ctx);
23614 if (rt == 0) {
23615 /* Treat as NOP. */
23616 return;
23619 t0 = tcg_temp_new();
23620 gen_load_gpr(t0, rs);
23622 switch (op1) {
23623 case OPC_APPEND_DSP:
23624 switch (MASK_APPEND(ctx->opcode)) {
23625 case OPC_APPEND:
23626 if (sa != 0) {
23627 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23629 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23630 break;
23631 case OPC_PREPEND:
23632 if (sa != 0) {
23633 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23634 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23635 tcg_gen_shli_tl(t0, t0, 32 - sa);
23636 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23638 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23639 break;
23640 case OPC_BALIGN:
23641 sa &= 3;
23642 if (sa != 0 && sa != 2) {
23643 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23644 tcg_gen_ext32u_tl(t0, t0);
23645 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23646 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23648 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23649 break;
23650 default: /* Invalid */
23651 MIPS_INVAL("MASK APPEND");
23652 generate_exception_end(ctx, EXCP_RI);
23653 break;
23655 break;
23656 #ifdef TARGET_MIPS64
23657 case OPC_DAPPEND_DSP:
23658 switch (MASK_DAPPEND(ctx->opcode)) {
23659 case OPC_DAPPEND:
23660 if (sa != 0) {
23661 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23663 break;
23664 case OPC_PREPENDD:
23665 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23666 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23667 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23668 break;
23669 case OPC_PREPENDW:
23670 if (sa != 0) {
23671 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23672 tcg_gen_shli_tl(t0, t0, 64 - sa);
23673 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23675 break;
23676 case OPC_DBALIGN:
23677 sa &= 7;
23678 if (sa != 0 && sa != 2 && sa != 4) {
23679 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23680 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23681 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23683 break;
23684 default: /* Invalid */
23685 MIPS_INVAL("MASK DAPPEND");
23686 generate_exception_end(ctx, EXCP_RI);
23687 break;
23689 break;
23690 #endif
23692 tcg_temp_free(t0);
23695 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23696 int ret, int v1, int v2, int check_ret)
23699 TCGv t0;
23700 TCGv t1;
23701 TCGv v1_t;
23702 TCGv v2_t;
23703 int16_t imm;
23705 if ((ret == 0) && (check_ret == 1)) {
23706 /* Treat as NOP. */
23707 return;
23710 t0 = tcg_temp_new();
23711 t1 = tcg_temp_new();
23712 v1_t = tcg_temp_new();
23713 v2_t = tcg_temp_new();
23715 gen_load_gpr(v1_t, v1);
23716 gen_load_gpr(v2_t, v2);
23718 switch (op1) {
23719 case OPC_EXTR_W_DSP:
23720 check_dsp(ctx);
23721 switch (op2) {
23722 case OPC_EXTR_W:
23723 tcg_gen_movi_tl(t0, v2);
23724 tcg_gen_movi_tl(t1, v1);
23725 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23726 break;
23727 case OPC_EXTR_R_W:
23728 tcg_gen_movi_tl(t0, v2);
23729 tcg_gen_movi_tl(t1, v1);
23730 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23731 break;
23732 case OPC_EXTR_RS_W:
23733 tcg_gen_movi_tl(t0, v2);
23734 tcg_gen_movi_tl(t1, v1);
23735 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23736 break;
23737 case OPC_EXTR_S_H:
23738 tcg_gen_movi_tl(t0, v2);
23739 tcg_gen_movi_tl(t1, v1);
23740 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23741 break;
23742 case OPC_EXTRV_S_H:
23743 tcg_gen_movi_tl(t0, v2);
23744 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23745 break;
23746 case OPC_EXTRV_W:
23747 tcg_gen_movi_tl(t0, v2);
23748 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23749 break;
23750 case OPC_EXTRV_R_W:
23751 tcg_gen_movi_tl(t0, v2);
23752 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23753 break;
23754 case OPC_EXTRV_RS_W:
23755 tcg_gen_movi_tl(t0, v2);
23756 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23757 break;
23758 case OPC_EXTP:
23759 tcg_gen_movi_tl(t0, v2);
23760 tcg_gen_movi_tl(t1, v1);
23761 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23762 break;
23763 case OPC_EXTPV:
23764 tcg_gen_movi_tl(t0, v2);
23765 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23766 break;
23767 case OPC_EXTPDP:
23768 tcg_gen_movi_tl(t0, v2);
23769 tcg_gen_movi_tl(t1, v1);
23770 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23771 break;
23772 case OPC_EXTPDPV:
23773 tcg_gen_movi_tl(t0, v2);
23774 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23775 break;
23776 case OPC_SHILO:
23777 imm = (ctx->opcode >> 20) & 0x3F;
23778 tcg_gen_movi_tl(t0, ret);
23779 tcg_gen_movi_tl(t1, imm);
23780 gen_helper_shilo(t0, t1, cpu_env);
23781 break;
23782 case OPC_SHILOV:
23783 tcg_gen_movi_tl(t0, ret);
23784 gen_helper_shilo(t0, v1_t, cpu_env);
23785 break;
23786 case OPC_MTHLIP:
23787 tcg_gen_movi_tl(t0, ret);
23788 gen_helper_mthlip(t0, v1_t, cpu_env);
23789 break;
23790 case OPC_WRDSP:
23791 imm = (ctx->opcode >> 11) & 0x3FF;
23792 tcg_gen_movi_tl(t0, imm);
23793 gen_helper_wrdsp(v1_t, t0, cpu_env);
23794 break;
23795 case OPC_RDDSP:
23796 imm = (ctx->opcode >> 16) & 0x03FF;
23797 tcg_gen_movi_tl(t0, imm);
23798 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23799 break;
23801 break;
23802 #ifdef TARGET_MIPS64
23803 case OPC_DEXTR_W_DSP:
23804 check_dsp(ctx);
23805 switch (op2) {
23806 case OPC_DMTHLIP:
23807 tcg_gen_movi_tl(t0, ret);
23808 gen_helper_dmthlip(v1_t, t0, cpu_env);
23809 break;
23810 case OPC_DSHILO:
23812 int shift = (ctx->opcode >> 19) & 0x7F;
23813 int ac = (ctx->opcode >> 11) & 0x03;
23814 tcg_gen_movi_tl(t0, shift);
23815 tcg_gen_movi_tl(t1, ac);
23816 gen_helper_dshilo(t0, t1, cpu_env);
23817 break;
23819 case OPC_DSHILOV:
23821 int ac = (ctx->opcode >> 11) & 0x03;
23822 tcg_gen_movi_tl(t0, ac);
23823 gen_helper_dshilo(v1_t, t0, cpu_env);
23824 break;
23826 case OPC_DEXTP:
23827 tcg_gen_movi_tl(t0, v2);
23828 tcg_gen_movi_tl(t1, v1);
23830 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23831 break;
23832 case OPC_DEXTPV:
23833 tcg_gen_movi_tl(t0, v2);
23834 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23835 break;
23836 case OPC_DEXTPDP:
23837 tcg_gen_movi_tl(t0, v2);
23838 tcg_gen_movi_tl(t1, v1);
23839 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23840 break;
23841 case OPC_DEXTPDPV:
23842 tcg_gen_movi_tl(t0, v2);
23843 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23844 break;
23845 case OPC_DEXTR_L:
23846 tcg_gen_movi_tl(t0, v2);
23847 tcg_gen_movi_tl(t1, v1);
23848 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23849 break;
23850 case OPC_DEXTR_R_L:
23851 tcg_gen_movi_tl(t0, v2);
23852 tcg_gen_movi_tl(t1, v1);
23853 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23854 break;
23855 case OPC_DEXTR_RS_L:
23856 tcg_gen_movi_tl(t0, v2);
23857 tcg_gen_movi_tl(t1, v1);
23858 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23859 break;
23860 case OPC_DEXTR_W:
23861 tcg_gen_movi_tl(t0, v2);
23862 tcg_gen_movi_tl(t1, v1);
23863 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23864 break;
23865 case OPC_DEXTR_R_W:
23866 tcg_gen_movi_tl(t0, v2);
23867 tcg_gen_movi_tl(t1, v1);
23868 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23869 break;
23870 case OPC_DEXTR_RS_W:
23871 tcg_gen_movi_tl(t0, v2);
23872 tcg_gen_movi_tl(t1, v1);
23873 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23874 break;
23875 case OPC_DEXTR_S_H:
23876 tcg_gen_movi_tl(t0, v2);
23877 tcg_gen_movi_tl(t1, v1);
23878 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23879 break;
23880 case OPC_DEXTRV_S_H:
23881 tcg_gen_movi_tl(t0, v2);
23882 tcg_gen_movi_tl(t1, v1);
23883 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23884 break;
23885 case OPC_DEXTRV_L:
23886 tcg_gen_movi_tl(t0, v2);
23887 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23888 break;
23889 case OPC_DEXTRV_R_L:
23890 tcg_gen_movi_tl(t0, v2);
23891 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23892 break;
23893 case OPC_DEXTRV_RS_L:
23894 tcg_gen_movi_tl(t0, v2);
23895 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23896 break;
23897 case OPC_DEXTRV_W:
23898 tcg_gen_movi_tl(t0, v2);
23899 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23900 break;
23901 case OPC_DEXTRV_R_W:
23902 tcg_gen_movi_tl(t0, v2);
23903 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23904 break;
23905 case OPC_DEXTRV_RS_W:
23906 tcg_gen_movi_tl(t0, v2);
23907 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23908 break;
23910 break;
23911 #endif
23914 tcg_temp_free(t0);
23915 tcg_temp_free(t1);
23916 tcg_temp_free(v1_t);
23917 tcg_temp_free(v2_t);
23920 /* End MIPSDSP functions. */
23922 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23924 int rs, rt, rd, sa;
23925 uint32_t op1, op2;
23927 rs = (ctx->opcode >> 21) & 0x1f;
23928 rt = (ctx->opcode >> 16) & 0x1f;
23929 rd = (ctx->opcode >> 11) & 0x1f;
23930 sa = (ctx->opcode >> 6) & 0x1f;
23932 op1 = MASK_SPECIAL(ctx->opcode);
23933 switch (op1) {
23934 case OPC_LSA:
23935 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23936 break;
23937 case OPC_MULT:
23938 case OPC_MULTU:
23939 case OPC_DIV:
23940 case OPC_DIVU:
23941 op2 = MASK_R6_MULDIV(ctx->opcode);
23942 switch (op2) {
23943 case R6_OPC_MUL:
23944 case R6_OPC_MUH:
23945 case R6_OPC_MULU:
23946 case R6_OPC_MUHU:
23947 case R6_OPC_DIV:
23948 case R6_OPC_MOD:
23949 case R6_OPC_DIVU:
23950 case R6_OPC_MODU:
23951 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23952 break;
23953 default:
23954 MIPS_INVAL("special_r6 muldiv");
23955 generate_exception_end(ctx, EXCP_RI);
23956 break;
23958 break;
23959 case OPC_SELEQZ:
23960 case OPC_SELNEZ:
23961 gen_cond_move(ctx, op1, rd, rs, rt);
23962 break;
23963 case R6_OPC_CLO:
23964 case R6_OPC_CLZ:
23965 if (rt == 0 && sa == 1) {
23966 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23967 We need additionally to check other fields */
23968 gen_cl(ctx, op1, rd, rs);
23969 } else {
23970 generate_exception_end(ctx, EXCP_RI);
23972 break;
23973 case R6_OPC_SDBBP:
23974 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23975 gen_helper_do_semihosting(cpu_env);
23976 } else {
23977 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23978 generate_exception_end(ctx, EXCP_RI);
23979 } else {
23980 generate_exception_end(ctx, EXCP_DBp);
23983 break;
23984 #if defined(TARGET_MIPS64)
23985 case OPC_DLSA:
23986 check_mips_64(ctx);
23987 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23988 break;
23989 case R6_OPC_DCLO:
23990 case R6_OPC_DCLZ:
23991 if (rt == 0 && sa == 1) {
23992 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23993 We need additionally to check other fields */
23994 check_mips_64(ctx);
23995 gen_cl(ctx, op1, rd, rs);
23996 } else {
23997 generate_exception_end(ctx, EXCP_RI);
23999 break;
24000 case OPC_DMULT:
24001 case OPC_DMULTU:
24002 case OPC_DDIV:
24003 case OPC_DDIVU:
24005 op2 = MASK_R6_MULDIV(ctx->opcode);
24006 switch (op2) {
24007 case R6_OPC_DMUL:
24008 case R6_OPC_DMUH:
24009 case R6_OPC_DMULU:
24010 case R6_OPC_DMUHU:
24011 case R6_OPC_DDIV:
24012 case R6_OPC_DMOD:
24013 case R6_OPC_DDIVU:
24014 case R6_OPC_DMODU:
24015 check_mips_64(ctx);
24016 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24017 break;
24018 default:
24019 MIPS_INVAL("special_r6 muldiv");
24020 generate_exception_end(ctx, EXCP_RI);
24021 break;
24023 break;
24024 #endif
24025 default: /* Invalid */
24026 MIPS_INVAL("special_r6");
24027 generate_exception_end(ctx, EXCP_RI);
24028 break;
24032 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24034 int rs = extract32(ctx->opcode, 21, 5);
24035 int rt = extract32(ctx->opcode, 16, 5);
24036 int rd = extract32(ctx->opcode, 11, 5);
24037 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24039 switch (op1) {
24040 case OPC_MOVN: /* Conditional move */
24041 case OPC_MOVZ:
24042 gen_cond_move(ctx, op1, rd, rs, rt);
24043 break;
24044 case OPC_MFHI: /* Move from HI/LO */
24045 case OPC_MFLO:
24046 gen_HILO(ctx, op1, 0, rd);
24047 break;
24048 case OPC_MTHI:
24049 case OPC_MTLO: /* Move to HI/LO */
24050 gen_HILO(ctx, op1, 0, rs);
24051 break;
24052 case OPC_MULT:
24053 case OPC_MULTU:
24054 gen_mul_txx9(ctx, op1, rd, rs, rt);
24055 break;
24056 case OPC_DIV:
24057 case OPC_DIVU:
24058 gen_muldiv(ctx, op1, 0, rs, rt);
24059 break;
24060 #if defined(TARGET_MIPS64)
24061 case OPC_DMULT:
24062 case OPC_DMULTU:
24063 case OPC_DDIV:
24064 case OPC_DDIVU:
24065 check_insn_opc_user_only(ctx, INSN_R5900);
24066 gen_muldiv(ctx, op1, 0, rs, rt);
24067 break;
24068 #endif
24069 case OPC_JR:
24070 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24071 break;
24072 default: /* Invalid */
24073 MIPS_INVAL("special_tx79");
24074 generate_exception_end(ctx, EXCP_RI);
24075 break;
24079 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24081 int rs, rt, rd, sa;
24082 uint32_t op1;
24084 rs = (ctx->opcode >> 21) & 0x1f;
24085 rt = (ctx->opcode >> 16) & 0x1f;
24086 rd = (ctx->opcode >> 11) & 0x1f;
24087 sa = (ctx->opcode >> 6) & 0x1f;
24089 op1 = MASK_SPECIAL(ctx->opcode);
24090 switch (op1) {
24091 case OPC_MOVN: /* Conditional move */
24092 case OPC_MOVZ:
24093 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24094 INSN_LOONGSON2E | INSN_LOONGSON2F);
24095 gen_cond_move(ctx, op1, rd, rs, rt);
24096 break;
24097 case OPC_MFHI: /* Move from HI/LO */
24098 case OPC_MFLO:
24099 gen_HILO(ctx, op1, rs & 3, rd);
24100 break;
24101 case OPC_MTHI:
24102 case OPC_MTLO: /* Move to HI/LO */
24103 gen_HILO(ctx, op1, rd & 3, rs);
24104 break;
24105 case OPC_MOVCI:
24106 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24107 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24108 check_cp1_enabled(ctx);
24109 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24110 (ctx->opcode >> 16) & 1);
24111 } else {
24112 generate_exception_err(ctx, EXCP_CpU, 1);
24114 break;
24115 case OPC_MULT:
24116 case OPC_MULTU:
24117 if (sa) {
24118 check_insn(ctx, INSN_VR54XX);
24119 op1 = MASK_MUL_VR54XX(ctx->opcode);
24120 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24121 } else {
24122 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24124 break;
24125 case OPC_DIV:
24126 case OPC_DIVU:
24127 gen_muldiv(ctx, op1, 0, rs, rt);
24128 break;
24129 #if defined(TARGET_MIPS64)
24130 case OPC_DMULT:
24131 case OPC_DMULTU:
24132 case OPC_DDIV:
24133 case OPC_DDIVU:
24134 check_insn(ctx, ISA_MIPS3);
24135 check_mips_64(ctx);
24136 gen_muldiv(ctx, op1, 0, rs, rt);
24137 break;
24138 #endif
24139 case OPC_JR:
24140 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24141 break;
24142 case OPC_SPIM:
24143 #ifdef MIPS_STRICT_STANDARD
24144 MIPS_INVAL("SPIM");
24145 generate_exception_end(ctx, EXCP_RI);
24146 #else
24147 /* Implemented as RI exception for now. */
24148 MIPS_INVAL("spim (unofficial)");
24149 generate_exception_end(ctx, EXCP_RI);
24150 #endif
24151 break;
24152 default: /* Invalid */
24153 MIPS_INVAL("special_legacy");
24154 generate_exception_end(ctx, EXCP_RI);
24155 break;
24159 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24161 int rs, rt, rd, sa;
24162 uint32_t op1;
24164 rs = (ctx->opcode >> 21) & 0x1f;
24165 rt = (ctx->opcode >> 16) & 0x1f;
24166 rd = (ctx->opcode >> 11) & 0x1f;
24167 sa = (ctx->opcode >> 6) & 0x1f;
24169 op1 = MASK_SPECIAL(ctx->opcode);
24170 switch (op1) {
24171 case OPC_SLL: /* Shift with immediate */
24172 if (sa == 5 && rd == 0 &&
24173 rs == 0 && rt == 0) { /* PAUSE */
24174 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24175 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24176 generate_exception_end(ctx, EXCP_RI);
24177 break;
24180 /* Fallthrough */
24181 case OPC_SRA:
24182 gen_shift_imm(ctx, op1, rd, rt, sa);
24183 break;
24184 case OPC_SRL:
24185 switch ((ctx->opcode >> 21) & 0x1f) {
24186 case 1:
24187 /* rotr is decoded as srl on non-R2 CPUs */
24188 if (ctx->insn_flags & ISA_MIPS32R2) {
24189 op1 = OPC_ROTR;
24191 /* Fallthrough */
24192 case 0:
24193 gen_shift_imm(ctx, op1, rd, rt, sa);
24194 break;
24195 default:
24196 generate_exception_end(ctx, EXCP_RI);
24197 break;
24199 break;
24200 case OPC_ADD:
24201 case OPC_ADDU:
24202 case OPC_SUB:
24203 case OPC_SUBU:
24204 gen_arith(ctx, op1, rd, rs, rt);
24205 break;
24206 case OPC_SLLV: /* Shifts */
24207 case OPC_SRAV:
24208 gen_shift(ctx, op1, rd, rs, rt);
24209 break;
24210 case OPC_SRLV:
24211 switch ((ctx->opcode >> 6) & 0x1f) {
24212 case 1:
24213 /* rotrv is decoded as srlv on non-R2 CPUs */
24214 if (ctx->insn_flags & ISA_MIPS32R2) {
24215 op1 = OPC_ROTRV;
24217 /* Fallthrough */
24218 case 0:
24219 gen_shift(ctx, op1, rd, rs, rt);
24220 break;
24221 default:
24222 generate_exception_end(ctx, EXCP_RI);
24223 break;
24225 break;
24226 case OPC_SLT: /* Set on less than */
24227 case OPC_SLTU:
24228 gen_slt(ctx, op1, rd, rs, rt);
24229 break;
24230 case OPC_AND: /* Logic*/
24231 case OPC_OR:
24232 case OPC_NOR:
24233 case OPC_XOR:
24234 gen_logic(ctx, op1, rd, rs, rt);
24235 break;
24236 case OPC_JALR:
24237 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24238 break;
24239 case OPC_TGE: /* Traps */
24240 case OPC_TGEU:
24241 case OPC_TLT:
24242 case OPC_TLTU:
24243 case OPC_TEQ:
24244 case OPC_TNE:
24245 check_insn(ctx, ISA_MIPS2);
24246 gen_trap(ctx, op1, rs, rt, -1);
24247 break;
24248 case OPC_LSA: /* OPC_PMON */
24249 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24250 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24251 decode_opc_special_r6(env, ctx);
24252 } else {
24253 /* Pmon entry point, also R4010 selsl */
24254 #ifdef MIPS_STRICT_STANDARD
24255 MIPS_INVAL("PMON / selsl");
24256 generate_exception_end(ctx, EXCP_RI);
24257 #else
24258 gen_helper_0e0i(pmon, sa);
24259 #endif
24261 break;
24262 case OPC_SYSCALL:
24263 generate_exception_end(ctx, EXCP_SYSCALL);
24264 break;
24265 case OPC_BREAK:
24266 generate_exception_end(ctx, EXCP_BREAK);
24267 break;
24268 case OPC_SYNC:
24269 check_insn(ctx, ISA_MIPS2);
24270 gen_sync(extract32(ctx->opcode, 6, 5));
24271 break;
24273 #if defined(TARGET_MIPS64)
24274 /* MIPS64 specific opcodes */
24275 case OPC_DSLL:
24276 case OPC_DSRA:
24277 case OPC_DSLL32:
24278 case OPC_DSRA32:
24279 check_insn(ctx, ISA_MIPS3);
24280 check_mips_64(ctx);
24281 gen_shift_imm(ctx, op1, rd, rt, sa);
24282 break;
24283 case OPC_DSRL:
24284 switch ((ctx->opcode >> 21) & 0x1f) {
24285 case 1:
24286 /* drotr is decoded as dsrl on non-R2 CPUs */
24287 if (ctx->insn_flags & ISA_MIPS32R2) {
24288 op1 = OPC_DROTR;
24290 /* Fallthrough */
24291 case 0:
24292 check_insn(ctx, ISA_MIPS3);
24293 check_mips_64(ctx);
24294 gen_shift_imm(ctx, op1, rd, rt, sa);
24295 break;
24296 default:
24297 generate_exception_end(ctx, EXCP_RI);
24298 break;
24300 break;
24301 case OPC_DSRL32:
24302 switch ((ctx->opcode >> 21) & 0x1f) {
24303 case 1:
24304 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24305 if (ctx->insn_flags & ISA_MIPS32R2) {
24306 op1 = OPC_DROTR32;
24308 /* Fallthrough */
24309 case 0:
24310 check_insn(ctx, ISA_MIPS3);
24311 check_mips_64(ctx);
24312 gen_shift_imm(ctx, op1, rd, rt, sa);
24313 break;
24314 default:
24315 generate_exception_end(ctx, EXCP_RI);
24316 break;
24318 break;
24319 case OPC_DADD:
24320 case OPC_DADDU:
24321 case OPC_DSUB:
24322 case OPC_DSUBU:
24323 check_insn(ctx, ISA_MIPS3);
24324 check_mips_64(ctx);
24325 gen_arith(ctx, op1, rd, rs, rt);
24326 break;
24327 case OPC_DSLLV:
24328 case OPC_DSRAV:
24329 check_insn(ctx, ISA_MIPS3);
24330 check_mips_64(ctx);
24331 gen_shift(ctx, op1, rd, rs, rt);
24332 break;
24333 case OPC_DSRLV:
24334 switch ((ctx->opcode >> 6) & 0x1f) {
24335 case 1:
24336 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24337 if (ctx->insn_flags & ISA_MIPS32R2) {
24338 op1 = OPC_DROTRV;
24340 /* Fallthrough */
24341 case 0:
24342 check_insn(ctx, ISA_MIPS3);
24343 check_mips_64(ctx);
24344 gen_shift(ctx, op1, rd, rs, rt);
24345 break;
24346 default:
24347 generate_exception_end(ctx, EXCP_RI);
24348 break;
24350 break;
24351 case OPC_DLSA:
24352 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24353 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24354 decode_opc_special_r6(env, ctx);
24356 break;
24357 #endif
24358 default:
24359 if (ctx->insn_flags & ISA_MIPS32R6) {
24360 decode_opc_special_r6(env, ctx);
24361 } else if (ctx->insn_flags & INSN_R5900) {
24362 decode_opc_special_tx79(env, ctx);
24363 } else {
24364 decode_opc_special_legacy(env, ctx);
24370 #if !defined(TARGET_MIPS64)
24372 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24373 #define MXU_APTN1_A 0
24374 #define MXU_APTN1_S 1
24376 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24377 #define MXU_APTN2_AA 0
24378 #define MXU_APTN2_AS 1
24379 #define MXU_APTN2_SA 2
24380 #define MXU_APTN2_SS 3
24382 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24383 #define MXU_EPTN2_AA 0
24384 #define MXU_EPTN2_AS 1
24385 #define MXU_EPTN2_SA 2
24386 #define MXU_EPTN2_SS 3
24388 /* MXU operand getting pattern 'optn2' */
24389 #define MXU_OPTN2_PTN0 0
24390 #define MXU_OPTN2_PTN1 1
24391 #define MXU_OPTN2_PTN2 2
24392 #define MXU_OPTN2_PTN3 3
24393 /* alternative naming scheme for 'optn2' */
24394 #define MXU_OPTN2_WW 0
24395 #define MXU_OPTN2_LW 1
24396 #define MXU_OPTN2_HW 2
24397 #define MXU_OPTN2_XW 3
24399 /* MXU operand getting pattern 'optn3' */
24400 #define MXU_OPTN3_PTN0 0
24401 #define MXU_OPTN3_PTN1 1
24402 #define MXU_OPTN3_PTN2 2
24403 #define MXU_OPTN3_PTN3 3
24404 #define MXU_OPTN3_PTN4 4
24405 #define MXU_OPTN3_PTN5 5
24406 #define MXU_OPTN3_PTN6 6
24407 #define MXU_OPTN3_PTN7 7
24411 * S32I2M XRa, rb - Register move from GRF to XRF
24413 static void gen_mxu_s32i2m(DisasContext *ctx)
24415 TCGv t0;
24416 uint32_t XRa, Rb;
24418 t0 = tcg_temp_new();
24420 XRa = extract32(ctx->opcode, 6, 5);
24421 Rb = extract32(ctx->opcode, 16, 5);
24423 gen_load_gpr(t0, Rb);
24424 if (XRa <= 15) {
24425 gen_store_mxu_gpr(t0, XRa);
24426 } else if (XRa == 16) {
24427 gen_store_mxu_cr(t0);
24430 tcg_temp_free(t0);
24434 * S32M2I XRa, rb - Register move from XRF to GRF
24436 static void gen_mxu_s32m2i(DisasContext *ctx)
24438 TCGv t0;
24439 uint32_t XRa, Rb;
24441 t0 = tcg_temp_new();
24443 XRa = extract32(ctx->opcode, 6, 5);
24444 Rb = extract32(ctx->opcode, 16, 5);
24446 if (XRa <= 15) {
24447 gen_load_mxu_gpr(t0, XRa);
24448 } else if (XRa == 16) {
24449 gen_load_mxu_cr(t0);
24452 gen_store_gpr(t0, Rb);
24454 tcg_temp_free(t0);
24458 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24460 static void gen_mxu_s8ldd(DisasContext *ctx)
24462 TCGv t0, t1;
24463 uint32_t XRa, Rb, s8, optn3;
24465 t0 = tcg_temp_new();
24466 t1 = tcg_temp_new();
24468 XRa = extract32(ctx->opcode, 6, 4);
24469 s8 = extract32(ctx->opcode, 10, 8);
24470 optn3 = extract32(ctx->opcode, 18, 3);
24471 Rb = extract32(ctx->opcode, 21, 5);
24473 gen_load_gpr(t0, Rb);
24474 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24476 switch (optn3) {
24477 /* XRa[7:0] = tmp8 */
24478 case MXU_OPTN3_PTN0:
24479 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24480 gen_load_mxu_gpr(t0, XRa);
24481 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24482 break;
24483 /* XRa[15:8] = tmp8 */
24484 case MXU_OPTN3_PTN1:
24485 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24486 gen_load_mxu_gpr(t0, XRa);
24487 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24488 break;
24489 /* XRa[23:16] = tmp8 */
24490 case MXU_OPTN3_PTN2:
24491 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24492 gen_load_mxu_gpr(t0, XRa);
24493 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24494 break;
24495 /* XRa[31:24] = tmp8 */
24496 case MXU_OPTN3_PTN3:
24497 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24498 gen_load_mxu_gpr(t0, XRa);
24499 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24500 break;
24501 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24502 case MXU_OPTN3_PTN4:
24503 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24504 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24505 break;
24506 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24507 case MXU_OPTN3_PTN5:
24508 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24509 tcg_gen_shli_tl(t1, t1, 8);
24510 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24511 break;
24512 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24513 case MXU_OPTN3_PTN6:
24514 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24515 tcg_gen_mov_tl(t0, t1);
24516 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24517 tcg_gen_shli_tl(t1, t1, 16);
24518 tcg_gen_or_tl(t0, t0, t1);
24519 break;
24520 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24521 case MXU_OPTN3_PTN7:
24522 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24523 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24524 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24525 break;
24528 gen_store_mxu_gpr(t0, XRa);
24530 tcg_temp_free(t0);
24531 tcg_temp_free(t1);
24535 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24537 static void gen_mxu_d16mul(DisasContext *ctx)
24539 TCGv t0, t1, t2, t3;
24540 uint32_t XRa, XRb, XRc, XRd, optn2;
24542 t0 = tcg_temp_new();
24543 t1 = tcg_temp_new();
24544 t2 = tcg_temp_new();
24545 t3 = tcg_temp_new();
24547 XRa = extract32(ctx->opcode, 6, 4);
24548 XRb = extract32(ctx->opcode, 10, 4);
24549 XRc = extract32(ctx->opcode, 14, 4);
24550 XRd = extract32(ctx->opcode, 18, 4);
24551 optn2 = extract32(ctx->opcode, 22, 2);
24553 gen_load_mxu_gpr(t1, XRb);
24554 tcg_gen_sextract_tl(t0, t1, 0, 16);
24555 tcg_gen_sextract_tl(t1, t1, 16, 16);
24556 gen_load_mxu_gpr(t3, XRc);
24557 tcg_gen_sextract_tl(t2, t3, 0, 16);
24558 tcg_gen_sextract_tl(t3, t3, 16, 16);
24560 switch (optn2) {
24561 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24562 tcg_gen_mul_tl(t3, t1, t3);
24563 tcg_gen_mul_tl(t2, t0, t2);
24564 break;
24565 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24566 tcg_gen_mul_tl(t3, t0, t3);
24567 tcg_gen_mul_tl(t2, t0, t2);
24568 break;
24569 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24570 tcg_gen_mul_tl(t3, t1, t3);
24571 tcg_gen_mul_tl(t2, t1, t2);
24572 break;
24573 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24574 tcg_gen_mul_tl(t3, t0, t3);
24575 tcg_gen_mul_tl(t2, t1, t2);
24576 break;
24578 gen_store_mxu_gpr(t3, XRa);
24579 gen_store_mxu_gpr(t2, XRd);
24581 tcg_temp_free(t0);
24582 tcg_temp_free(t1);
24583 tcg_temp_free(t2);
24584 tcg_temp_free(t3);
24588 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24589 * and accumulate
24591 static void gen_mxu_d16mac(DisasContext *ctx)
24593 TCGv t0, t1, t2, t3;
24594 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24596 t0 = tcg_temp_new();
24597 t1 = tcg_temp_new();
24598 t2 = tcg_temp_new();
24599 t3 = tcg_temp_new();
24601 XRa = extract32(ctx->opcode, 6, 4);
24602 XRb = extract32(ctx->opcode, 10, 4);
24603 XRc = extract32(ctx->opcode, 14, 4);
24604 XRd = extract32(ctx->opcode, 18, 4);
24605 optn2 = extract32(ctx->opcode, 22, 2);
24606 aptn2 = extract32(ctx->opcode, 24, 2);
24608 gen_load_mxu_gpr(t1, XRb);
24609 tcg_gen_sextract_tl(t0, t1, 0, 16);
24610 tcg_gen_sextract_tl(t1, t1, 16, 16);
24612 gen_load_mxu_gpr(t3, XRc);
24613 tcg_gen_sextract_tl(t2, t3, 0, 16);
24614 tcg_gen_sextract_tl(t3, t3, 16, 16);
24616 switch (optn2) {
24617 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24618 tcg_gen_mul_tl(t3, t1, t3);
24619 tcg_gen_mul_tl(t2, t0, t2);
24620 break;
24621 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24622 tcg_gen_mul_tl(t3, t0, t3);
24623 tcg_gen_mul_tl(t2, t0, t2);
24624 break;
24625 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24626 tcg_gen_mul_tl(t3, t1, t3);
24627 tcg_gen_mul_tl(t2, t1, t2);
24628 break;
24629 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24630 tcg_gen_mul_tl(t3, t0, t3);
24631 tcg_gen_mul_tl(t2, t1, t2);
24632 break;
24634 gen_load_mxu_gpr(t0, XRa);
24635 gen_load_mxu_gpr(t1, XRd);
24637 switch (aptn2) {
24638 case MXU_APTN2_AA:
24639 tcg_gen_add_tl(t3, t0, t3);
24640 tcg_gen_add_tl(t2, t1, t2);
24641 break;
24642 case MXU_APTN2_AS:
24643 tcg_gen_add_tl(t3, t0, t3);
24644 tcg_gen_sub_tl(t2, t1, t2);
24645 break;
24646 case MXU_APTN2_SA:
24647 tcg_gen_sub_tl(t3, t0, t3);
24648 tcg_gen_add_tl(t2, t1, t2);
24649 break;
24650 case MXU_APTN2_SS:
24651 tcg_gen_sub_tl(t3, t0, t3);
24652 tcg_gen_sub_tl(t2, t1, t2);
24653 break;
24655 gen_store_mxu_gpr(t3, XRa);
24656 gen_store_mxu_gpr(t2, XRd);
24658 tcg_temp_free(t0);
24659 tcg_temp_free(t1);
24660 tcg_temp_free(t2);
24661 tcg_temp_free(t3);
24665 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24666 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24668 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24670 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24671 uint32_t XRa, XRb, XRc, XRd, sel;
24673 t0 = tcg_temp_new();
24674 t1 = tcg_temp_new();
24675 t2 = tcg_temp_new();
24676 t3 = tcg_temp_new();
24677 t4 = tcg_temp_new();
24678 t5 = tcg_temp_new();
24679 t6 = tcg_temp_new();
24680 t7 = tcg_temp_new();
24682 XRa = extract32(ctx->opcode, 6, 4);
24683 XRb = extract32(ctx->opcode, 10, 4);
24684 XRc = extract32(ctx->opcode, 14, 4);
24685 XRd = extract32(ctx->opcode, 18, 4);
24686 sel = extract32(ctx->opcode, 22, 2);
24688 gen_load_mxu_gpr(t3, XRb);
24689 gen_load_mxu_gpr(t7, XRc);
24691 if (sel == 0x2) {
24692 /* Q8MULSU */
24693 tcg_gen_ext8s_tl(t0, t3);
24694 tcg_gen_shri_tl(t3, t3, 8);
24695 tcg_gen_ext8s_tl(t1, t3);
24696 tcg_gen_shri_tl(t3, t3, 8);
24697 tcg_gen_ext8s_tl(t2, t3);
24698 tcg_gen_shri_tl(t3, t3, 8);
24699 tcg_gen_ext8s_tl(t3, t3);
24700 } else {
24701 /* Q8MUL */
24702 tcg_gen_ext8u_tl(t0, t3);
24703 tcg_gen_shri_tl(t3, t3, 8);
24704 tcg_gen_ext8u_tl(t1, t3);
24705 tcg_gen_shri_tl(t3, t3, 8);
24706 tcg_gen_ext8u_tl(t2, t3);
24707 tcg_gen_shri_tl(t3, t3, 8);
24708 tcg_gen_ext8u_tl(t3, t3);
24711 tcg_gen_ext8u_tl(t4, t7);
24712 tcg_gen_shri_tl(t7, t7, 8);
24713 tcg_gen_ext8u_tl(t5, t7);
24714 tcg_gen_shri_tl(t7, t7, 8);
24715 tcg_gen_ext8u_tl(t6, t7);
24716 tcg_gen_shri_tl(t7, t7, 8);
24717 tcg_gen_ext8u_tl(t7, t7);
24719 tcg_gen_mul_tl(t0, t0, t4);
24720 tcg_gen_mul_tl(t1, t1, t5);
24721 tcg_gen_mul_tl(t2, t2, t6);
24722 tcg_gen_mul_tl(t3, t3, t7);
24724 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24725 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24726 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24727 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24729 tcg_gen_shli_tl(t1, t1, 16);
24730 tcg_gen_shli_tl(t3, t3, 16);
24732 tcg_gen_or_tl(t0, t0, t1);
24733 tcg_gen_or_tl(t1, t2, t3);
24735 gen_store_mxu_gpr(t0, XRd);
24736 gen_store_mxu_gpr(t1, XRa);
24738 tcg_temp_free(t0);
24739 tcg_temp_free(t1);
24740 tcg_temp_free(t2);
24741 tcg_temp_free(t3);
24742 tcg_temp_free(t4);
24743 tcg_temp_free(t5);
24744 tcg_temp_free(t6);
24745 tcg_temp_free(t7);
24749 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24750 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24752 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24754 TCGv t0, t1;
24755 uint32_t XRa, Rb, s12, sel;
24757 t0 = tcg_temp_new();
24758 t1 = tcg_temp_new();
24760 XRa = extract32(ctx->opcode, 6, 4);
24761 s12 = extract32(ctx->opcode, 10, 10);
24762 sel = extract32(ctx->opcode, 20, 1);
24763 Rb = extract32(ctx->opcode, 21, 5);
24765 gen_load_gpr(t0, Rb);
24767 tcg_gen_movi_tl(t1, s12);
24768 tcg_gen_shli_tl(t1, t1, 2);
24769 if (s12 & 0x200) {
24770 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24772 tcg_gen_add_tl(t1, t0, t1);
24773 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24775 if (sel == 1) {
24776 /* S32LDDR */
24777 tcg_gen_bswap32_tl(t1, t1);
24779 gen_store_mxu_gpr(t1, XRa);
24781 tcg_temp_free(t0);
24782 tcg_temp_free(t1);
24787 * MXU instruction category: logic
24788 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24790 * S32NOR S32AND S32OR S32XOR
24794 * S32NOR XRa, XRb, XRc
24795 * Update XRa with the result of logical bitwise 'nor' operation
24796 * applied to the content of XRb and XRc.
24798 * 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
24799 * +-----------+---------+-----+-------+-------+-------+-----------+
24800 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24801 * +-----------+---------+-----+-------+-------+-------+-----------+
24803 static void gen_mxu_S32NOR(DisasContext *ctx)
24805 uint32_t pad, XRc, XRb, XRa;
24807 pad = extract32(ctx->opcode, 21, 5);
24808 XRc = extract32(ctx->opcode, 14, 4);
24809 XRb = extract32(ctx->opcode, 10, 4);
24810 XRa = extract32(ctx->opcode, 6, 4);
24812 if (unlikely(pad != 0)) {
24813 /* opcode padding incorrect -> do nothing */
24814 } else if (unlikely(XRa == 0)) {
24815 /* destination is zero register -> do nothing */
24816 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24817 /* both operands zero registers -> just set destination to all 1s */
24818 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
24819 } else if (unlikely(XRb == 0)) {
24820 /* XRb zero register -> just set destination to the negation of XRc */
24821 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24822 } else if (unlikely(XRc == 0)) {
24823 /* XRa zero register -> just set destination to the negation of XRb */
24824 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24825 } else if (unlikely(XRb == XRc)) {
24826 /* both operands same -> just set destination to the negation of XRb */
24827 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24828 } else {
24829 /* the most general case */
24830 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24835 * S32AND XRa, XRb, XRc
24836 * Update XRa with the result of logical bitwise 'and' operation
24837 * applied to the content of XRb and XRc.
24839 * 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
24840 * +-----------+---------+-----+-------+-------+-------+-----------+
24841 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24842 * +-----------+---------+-----+-------+-------+-------+-----------+
24844 static void gen_mxu_S32AND(DisasContext *ctx)
24846 uint32_t pad, XRc, XRb, XRa;
24848 pad = extract32(ctx->opcode, 21, 5);
24849 XRc = extract32(ctx->opcode, 14, 4);
24850 XRb = extract32(ctx->opcode, 10, 4);
24851 XRa = extract32(ctx->opcode, 6, 4);
24853 if (unlikely(pad != 0)) {
24854 /* opcode padding incorrect -> do nothing */
24855 } else if (unlikely(XRa == 0)) {
24856 /* destination is zero register -> do nothing */
24857 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24858 /* one of operands zero register -> just set destination to all 0s */
24859 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24860 } else if (unlikely(XRb == XRc)) {
24861 /* both operands same -> just set destination to one of them */
24862 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24863 } else {
24864 /* the most general case */
24865 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24870 * S32OR XRa, XRb, XRc
24871 * Update XRa with the result of logical bitwise 'or' operation
24872 * applied to the content of XRb and XRc.
24874 * 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
24875 * +-----------+---------+-----+-------+-------+-------+-----------+
24876 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24877 * +-----------+---------+-----+-------+-------+-------+-----------+
24879 static void gen_mxu_S32OR(DisasContext *ctx)
24881 uint32_t pad, XRc, XRb, XRa;
24883 pad = extract32(ctx->opcode, 21, 5);
24884 XRc = extract32(ctx->opcode, 14, 4);
24885 XRb = extract32(ctx->opcode, 10, 4);
24886 XRa = extract32(ctx->opcode, 6, 4);
24888 if (unlikely(pad != 0)) {
24889 /* opcode padding incorrect -> do nothing */
24890 } else if (unlikely(XRa == 0)) {
24891 /* destination is zero register -> do nothing */
24892 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24893 /* both operands zero registers -> just set destination to all 0s */
24894 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24895 } else if (unlikely(XRb == 0)) {
24896 /* XRb zero register -> just set destination to the content of XRc */
24897 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24898 } else if (unlikely(XRc == 0)) {
24899 /* XRc zero register -> just set destination to the content of XRb */
24900 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24901 } else if (unlikely(XRb == XRc)) {
24902 /* both operands same -> just set destination to one of them */
24903 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24904 } else {
24905 /* the most general case */
24906 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24911 * S32XOR XRa, XRb, XRc
24912 * Update XRa with the result of logical bitwise 'xor' operation
24913 * applied to the content of XRb and XRc.
24915 * 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
24916 * +-----------+---------+-----+-------+-------+-------+-----------+
24917 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24918 * +-----------+---------+-----+-------+-------+-------+-----------+
24920 static void gen_mxu_S32XOR(DisasContext *ctx)
24922 uint32_t pad, XRc, XRb, XRa;
24924 pad = extract32(ctx->opcode, 21, 5);
24925 XRc = extract32(ctx->opcode, 14, 4);
24926 XRb = extract32(ctx->opcode, 10, 4);
24927 XRa = extract32(ctx->opcode, 6, 4);
24929 if (unlikely(pad != 0)) {
24930 /* opcode padding incorrect -> do nothing */
24931 } else if (unlikely(XRa == 0)) {
24932 /* destination is zero register -> do nothing */
24933 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24934 /* both operands zero registers -> just set destination to all 0s */
24935 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24936 } else if (unlikely(XRb == 0)) {
24937 /* XRb zero register -> just set destination to the content of XRc */
24938 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24939 } else if (unlikely(XRc == 0)) {
24940 /* XRc zero register -> just set destination to the content of XRb */
24941 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24942 } else if (unlikely(XRb == XRc)) {
24943 /* both operands same -> just set destination to all 0s */
24944 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24945 } else {
24946 /* the most general case */
24947 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24953 * MXU instruction category max/min
24954 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24956 * S32MAX D16MAX Q8MAX
24957 * S32MIN D16MIN Q8MIN
24961 * S32MAX XRa, XRb, XRc
24962 * Update XRa with the maximum of signed 32-bit integers contained
24963 * in XRb and XRc.
24965 * S32MIN XRa, XRb, XRc
24966 * Update XRa with the minimum of signed 32-bit integers contained
24967 * in XRb and XRc.
24969 * 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
24970 * +-----------+---------+-----+-------+-------+-------+-----------+
24971 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
24972 * +-----------+---------+-----+-------+-------+-------+-----------+
24974 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
24976 uint32_t pad, opc, XRc, XRb, XRa;
24978 pad = extract32(ctx->opcode, 21, 5);
24979 opc = extract32(ctx->opcode, 18, 3);
24980 XRc = extract32(ctx->opcode, 14, 4);
24981 XRb = extract32(ctx->opcode, 10, 4);
24982 XRa = extract32(ctx->opcode, 6, 4);
24984 if (unlikely(pad != 0)) {
24985 /* opcode padding incorrect -> do nothing */
24986 } else if (unlikely(XRa == 0)) {
24987 /* destination is zero register -> do nothing */
24988 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24989 /* both operands zero registers -> just set destination to zero */
24990 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24991 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24992 /* exactly one operand is zero register - find which one is not...*/
24993 uint32_t XRx = XRb ? XRb : XRc;
24994 /* ...and do max/min operation with one operand 0 */
24995 if (opc == OPC_MXU_S32MAX) {
24996 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24997 } else {
24998 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25000 } else if (unlikely(XRb == XRc)) {
25001 /* both operands same -> just set destination to one of them */
25002 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25003 } else {
25004 /* the most general case */
25005 if (opc == OPC_MXU_S32MAX) {
25006 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25007 mxu_gpr[XRc - 1]);
25008 } else {
25009 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25010 mxu_gpr[XRc - 1]);
25016 * D16MAX
25017 * Update XRa with the 16-bit-wise maximums of signed integers
25018 * contained in XRb and XRc.
25020 * D16MIN
25021 * Update XRa with the 16-bit-wise minimums of signed integers
25022 * contained in XRb and XRc.
25024 * 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
25025 * +-----------+---------+-----+-------+-------+-------+-----------+
25026 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25027 * +-----------+---------+-----+-------+-------+-------+-----------+
25029 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25031 uint32_t pad, opc, XRc, XRb, XRa;
25033 pad = extract32(ctx->opcode, 21, 5);
25034 opc = extract32(ctx->opcode, 18, 3);
25035 XRc = extract32(ctx->opcode, 14, 4);
25036 XRb = extract32(ctx->opcode, 10, 4);
25037 XRa = extract32(ctx->opcode, 6, 4);
25039 if (unlikely(pad != 0)) {
25040 /* opcode padding incorrect -> do nothing */
25041 } else if (unlikely(XRc == 0)) {
25042 /* destination is zero register -> do nothing */
25043 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25044 /* both operands zero registers -> just set destination to zero */
25045 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25046 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25047 /* exactly one operand is zero register - find which one is not...*/
25048 uint32_t XRx = XRb ? XRb : XRc;
25049 /* ...and do half-word-wise max/min with one operand 0 */
25050 TCGv_i32 t0 = tcg_temp_new();
25051 TCGv_i32 t1 = tcg_const_i32(0);
25053 /* the left half-word first */
25054 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25055 if (opc == OPC_MXU_D16MAX) {
25056 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25057 } else {
25058 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25061 /* the right half-word */
25062 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25063 /* move half-words to the leftmost position */
25064 tcg_gen_shli_i32(t0, t0, 16);
25065 /* t0 will be max/min of t0 and t1 */
25066 if (opc == OPC_MXU_D16MAX) {
25067 tcg_gen_smax_i32(t0, t0, t1);
25068 } else {
25069 tcg_gen_smin_i32(t0, t0, t1);
25071 /* return resulting half-words to its original position */
25072 tcg_gen_shri_i32(t0, t0, 16);
25073 /* finaly update the destination */
25074 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25076 tcg_temp_free(t1);
25077 tcg_temp_free(t0);
25078 } else if (unlikely(XRb == XRc)) {
25079 /* both operands same -> just set destination to one of them */
25080 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25081 } else {
25082 /* the most general case */
25083 TCGv_i32 t0 = tcg_temp_new();
25084 TCGv_i32 t1 = tcg_temp_new();
25086 /* the left half-word first */
25087 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25088 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25089 if (opc == OPC_MXU_D16MAX) {
25090 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25091 } else {
25092 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25095 /* the right half-word */
25096 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25097 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25098 /* move half-words to the leftmost position */
25099 tcg_gen_shli_i32(t0, t0, 16);
25100 tcg_gen_shli_i32(t1, t1, 16);
25101 /* t0 will be max/min of t0 and t1 */
25102 if (opc == OPC_MXU_D16MAX) {
25103 tcg_gen_smax_i32(t0, t0, t1);
25104 } else {
25105 tcg_gen_smin_i32(t0, t0, t1);
25107 /* return resulting half-words to its original position */
25108 tcg_gen_shri_i32(t0, t0, 16);
25109 /* finaly update the destination */
25110 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25112 tcg_temp_free(t1);
25113 tcg_temp_free(t0);
25118 * Q8MAX
25119 * Update XRa with the 8-bit-wise maximums of signed integers
25120 * contained in XRb and XRc.
25122 * Q8MIN
25123 * Update XRa with the 8-bit-wise minimums of signed integers
25124 * contained in XRb and XRc.
25126 * 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
25127 * +-----------+---------+-----+-------+-------+-------+-----------+
25128 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25129 * +-----------+---------+-----+-------+-------+-------+-----------+
25131 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25133 uint32_t pad, opc, XRc, XRb, XRa;
25135 pad = extract32(ctx->opcode, 21, 5);
25136 opc = extract32(ctx->opcode, 18, 3);
25137 XRc = extract32(ctx->opcode, 14, 4);
25138 XRb = extract32(ctx->opcode, 10, 4);
25139 XRa = extract32(ctx->opcode, 6, 4);
25141 if (unlikely(pad != 0)) {
25142 /* opcode padding incorrect -> do nothing */
25143 } else if (unlikely(XRa == 0)) {
25144 /* destination is zero register -> do nothing */
25145 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25146 /* both operands zero registers -> just set destination to zero */
25147 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25148 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25149 /* exactly one operand is zero register - make it be the first...*/
25150 uint32_t XRx = XRb ? XRb : XRc;
25151 /* ...and do byte-wise max/min with one operand 0 */
25152 TCGv_i32 t0 = tcg_temp_new();
25153 TCGv_i32 t1 = tcg_const_i32(0);
25154 int32_t i;
25156 /* the leftmost byte (byte 3) first */
25157 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25158 if (opc == OPC_MXU_Q8MAX) {
25159 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25160 } else {
25161 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25164 /* bytes 2, 1, 0 */
25165 for (i = 2; i >= 0; i--) {
25166 /* extract the byte */
25167 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25168 /* move the byte to the leftmost position */
25169 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25170 /* t0 will be max/min of t0 and t1 */
25171 if (opc == OPC_MXU_Q8MAX) {
25172 tcg_gen_smax_i32(t0, t0, t1);
25173 } else {
25174 tcg_gen_smin_i32(t0, t0, t1);
25176 /* return resulting byte to its original position */
25177 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25178 /* finaly update the destination */
25179 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25182 tcg_temp_free(t1);
25183 tcg_temp_free(t0);
25184 } else if (unlikely(XRb == XRc)) {
25185 /* both operands same -> just set destination to one of them */
25186 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25187 } else {
25188 /* the most general case */
25189 TCGv_i32 t0 = tcg_temp_new();
25190 TCGv_i32 t1 = tcg_temp_new();
25191 int32_t i;
25193 /* the leftmost bytes (bytes 3) first */
25194 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25195 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25196 if (opc == OPC_MXU_Q8MAX) {
25197 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25198 } else {
25199 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25202 /* bytes 2, 1, 0 */
25203 for (i = 2; i >= 0; i--) {
25204 /* extract corresponding bytes */
25205 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25206 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25207 /* move the bytes to the leftmost position */
25208 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25209 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25210 /* t0 will be max/min of t0 and t1 */
25211 if (opc == OPC_MXU_Q8MAX) {
25212 tcg_gen_smax_i32(t0, t0, t1);
25213 } else {
25214 tcg_gen_smin_i32(t0, t0, t1);
25216 /* return resulting byte to its original position */
25217 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25218 /* finaly update the destination */
25219 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25222 tcg_temp_free(t1);
25223 tcg_temp_free(t0);
25229 * MXU instruction category: align
25230 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25232 * S32ALN S32ALNI
25236 * S32ALNI XRc, XRb, XRa, optn3
25237 * Arrange bytes from XRb and XRc according to one of five sets of
25238 * rules determined by optn3, and place the result in XRa.
25240 * 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
25241 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25242 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25243 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25246 static void gen_mxu_S32ALNI(DisasContext *ctx)
25248 uint32_t optn3, pad, XRc, XRb, XRa;
25250 optn3 = extract32(ctx->opcode, 23, 3);
25251 pad = extract32(ctx->opcode, 21, 2);
25252 XRc = extract32(ctx->opcode, 14, 4);
25253 XRb = extract32(ctx->opcode, 10, 4);
25254 XRa = extract32(ctx->opcode, 6, 4);
25256 if (unlikely(pad != 0)) {
25257 /* opcode padding incorrect -> do nothing */
25258 } else if (unlikely(XRa == 0)) {
25259 /* destination is zero register -> do nothing */
25260 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25261 /* both operands zero registers -> just set destination to all 0s */
25262 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25263 } else if (unlikely(XRb == 0)) {
25264 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25265 switch (optn3) {
25266 case MXU_OPTN3_PTN0:
25267 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25268 break;
25269 case MXU_OPTN3_PTN1:
25270 case MXU_OPTN3_PTN2:
25271 case MXU_OPTN3_PTN3:
25272 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25273 8 * (4 - optn3));
25274 break;
25275 case MXU_OPTN3_PTN4:
25276 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25277 break;
25279 } else if (unlikely(XRc == 0)) {
25280 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25281 switch (optn3) {
25282 case MXU_OPTN3_PTN0:
25283 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25284 break;
25285 case MXU_OPTN3_PTN1:
25286 case MXU_OPTN3_PTN2:
25287 case MXU_OPTN3_PTN3:
25288 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25289 break;
25290 case MXU_OPTN3_PTN4:
25291 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25292 break;
25294 } else if (unlikely(XRb == XRc)) {
25295 /* both operands same -> just rotation or moving from any of them */
25296 switch (optn3) {
25297 case MXU_OPTN3_PTN0:
25298 case MXU_OPTN3_PTN4:
25299 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25300 break;
25301 case MXU_OPTN3_PTN1:
25302 case MXU_OPTN3_PTN2:
25303 case MXU_OPTN3_PTN3:
25304 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25305 break;
25307 } else {
25308 /* the most general case */
25309 switch (optn3) {
25310 case MXU_OPTN3_PTN0:
25312 /* */
25313 /* XRb XRc */
25314 /* +---------------+ */
25315 /* | A B C D | E F G H */
25316 /* +-------+-------+ */
25317 /* | */
25318 /* XRa */
25319 /* */
25321 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25323 break;
25324 case MXU_OPTN3_PTN1:
25326 /* */
25327 /* XRb XRc */
25328 /* +-------------------+ */
25329 /* A | B C D E | F G H */
25330 /* +---------+---------+ */
25331 /* | */
25332 /* XRa */
25333 /* */
25335 TCGv_i32 t0 = tcg_temp_new();
25336 TCGv_i32 t1 = tcg_temp_new();
25338 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25339 tcg_gen_shli_i32(t0, t0, 8);
25341 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25342 tcg_gen_shri_i32(t1, t1, 24);
25344 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25346 tcg_temp_free(t1);
25347 tcg_temp_free(t0);
25349 break;
25350 case MXU_OPTN3_PTN2:
25352 /* */
25353 /* XRb XRc */
25354 /* +-------------------+ */
25355 /* A B | C D E F | G H */
25356 /* +---------+---------+ */
25357 /* | */
25358 /* XRa */
25359 /* */
25361 TCGv_i32 t0 = tcg_temp_new();
25362 TCGv_i32 t1 = tcg_temp_new();
25364 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25365 tcg_gen_shli_i32(t0, t0, 16);
25367 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25368 tcg_gen_shri_i32(t1, t1, 16);
25370 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25372 tcg_temp_free(t1);
25373 tcg_temp_free(t0);
25375 break;
25376 case MXU_OPTN3_PTN3:
25378 /* */
25379 /* XRb XRc */
25380 /* +-------------------+ */
25381 /* A B C | D E F G | H */
25382 /* +---------+---------+ */
25383 /* | */
25384 /* XRa */
25385 /* */
25387 TCGv_i32 t0 = tcg_temp_new();
25388 TCGv_i32 t1 = tcg_temp_new();
25390 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25391 tcg_gen_shli_i32(t0, t0, 24);
25393 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25394 tcg_gen_shri_i32(t1, t1, 8);
25396 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25398 tcg_temp_free(t1);
25399 tcg_temp_free(t0);
25401 break;
25402 case MXU_OPTN3_PTN4:
25404 /* */
25405 /* XRb XRc */
25406 /* +---------------+ */
25407 /* A B C D | E F G H | */
25408 /* +-------+-------+ */
25409 /* | */
25410 /* XRa */
25411 /* */
25413 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25415 break;
25422 * Decoding engine for MXU
25423 * =======================
25428 * Decode MXU pool00
25430 * 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
25431 * +-----------+---------+-----+-------+-------+-------+-----------+
25432 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25433 * +-----------+---------+-----+-------+-------+-------+-----------+
25436 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25438 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25440 switch (opcode) {
25441 case OPC_MXU_S32MAX:
25442 case OPC_MXU_S32MIN:
25443 gen_mxu_S32MAX_S32MIN(ctx);
25444 break;
25445 case OPC_MXU_D16MAX:
25446 case OPC_MXU_D16MIN:
25447 gen_mxu_D16MAX_D16MIN(ctx);
25448 break;
25449 case OPC_MXU_Q8MAX:
25450 case OPC_MXU_Q8MIN:
25451 gen_mxu_Q8MAX_Q8MIN(ctx);
25452 break;
25453 case OPC_MXU_Q8SLT:
25454 /* TODO: Implement emulation of Q8SLT instruction. */
25455 MIPS_INVAL("OPC_MXU_Q8SLT");
25456 generate_exception_end(ctx, EXCP_RI);
25457 break;
25458 case OPC_MXU_Q8SLTU:
25459 /* TODO: Implement emulation of Q8SLTU instruction. */
25460 MIPS_INVAL("OPC_MXU_Q8SLTU");
25461 generate_exception_end(ctx, EXCP_RI);
25462 break;
25463 default:
25464 MIPS_INVAL("decode_opc_mxu");
25465 generate_exception_end(ctx, EXCP_RI);
25466 break;
25472 * Decode MXU pool01
25474 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25475 * 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
25476 * +-----------+---------+-----+-------+-------+-------+-----------+
25477 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25478 * +-----------+---------+-----+-------+-------+-------+-----------+
25480 * Q8ADD:
25481 * 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
25482 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25483 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25484 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25487 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25489 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25491 switch (opcode) {
25492 case OPC_MXU_S32SLT:
25493 /* TODO: Implement emulation of S32SLT instruction. */
25494 MIPS_INVAL("OPC_MXU_S32SLT");
25495 generate_exception_end(ctx, EXCP_RI);
25496 break;
25497 case OPC_MXU_D16SLT:
25498 /* TODO: Implement emulation of D16SLT instruction. */
25499 MIPS_INVAL("OPC_MXU_D16SLT");
25500 generate_exception_end(ctx, EXCP_RI);
25501 break;
25502 case OPC_MXU_D16AVG:
25503 /* TODO: Implement emulation of D16AVG instruction. */
25504 MIPS_INVAL("OPC_MXU_D16AVG");
25505 generate_exception_end(ctx, EXCP_RI);
25506 break;
25507 case OPC_MXU_D16AVGR:
25508 /* TODO: Implement emulation of D16AVGR instruction. */
25509 MIPS_INVAL("OPC_MXU_D16AVGR");
25510 generate_exception_end(ctx, EXCP_RI);
25511 break;
25512 case OPC_MXU_Q8AVG:
25513 /* TODO: Implement emulation of Q8AVG instruction. */
25514 MIPS_INVAL("OPC_MXU_Q8AVG");
25515 generate_exception_end(ctx, EXCP_RI);
25516 break;
25517 case OPC_MXU_Q8AVGR:
25518 /* TODO: Implement emulation of Q8AVGR instruction. */
25519 MIPS_INVAL("OPC_MXU_Q8AVGR");
25520 generate_exception_end(ctx, EXCP_RI);
25521 break;
25522 case OPC_MXU_Q8ADD:
25523 /* TODO: Implement emulation of Q8ADD instruction. */
25524 MIPS_INVAL("OPC_MXU_Q8ADD");
25525 generate_exception_end(ctx, EXCP_RI);
25526 break;
25527 default:
25528 MIPS_INVAL("decode_opc_mxu");
25529 generate_exception_end(ctx, EXCP_RI);
25530 break;
25536 * Decode MXU pool02
25538 * 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
25539 * +-----------+---------+-----+-------+-------+-------+-----------+
25540 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25541 * +-----------+---------+-----+-------+-------+-------+-----------+
25544 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25546 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25548 switch (opcode) {
25549 case OPC_MXU_S32CPS:
25550 /* TODO: Implement emulation of S32CPS instruction. */
25551 MIPS_INVAL("OPC_MXU_S32CPS");
25552 generate_exception_end(ctx, EXCP_RI);
25553 break;
25554 case OPC_MXU_D16CPS:
25555 /* TODO: Implement emulation of D16CPS instruction. */
25556 MIPS_INVAL("OPC_MXU_D16CPS");
25557 generate_exception_end(ctx, EXCP_RI);
25558 break;
25559 case OPC_MXU_Q8ABD:
25560 /* TODO: Implement emulation of Q8ABD instruction. */
25561 MIPS_INVAL("OPC_MXU_Q8ABD");
25562 generate_exception_end(ctx, EXCP_RI);
25563 break;
25564 case OPC_MXU_Q16SAT:
25565 /* TODO: Implement emulation of Q16SAT instruction. */
25566 MIPS_INVAL("OPC_MXU_Q16SAT");
25567 generate_exception_end(ctx, EXCP_RI);
25568 break;
25569 default:
25570 MIPS_INVAL("decode_opc_mxu");
25571 generate_exception_end(ctx, EXCP_RI);
25572 break;
25578 * Decode MXU pool03
25580 * D16MULF:
25581 * 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
25582 * +-----------+---+---+-------+-------+-------+-------+-----------+
25583 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25584 * +-----------+---+---+-------+-------+-------+-------+-----------+
25586 * D16MULE:
25587 * 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
25588 * +-----------+---+---+-------+-------+-------+-------+-----------+
25589 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25590 * +-----------+---+---+-------+-------+-------+-------+-----------+
25593 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25595 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25597 switch (opcode) {
25598 case OPC_MXU_D16MULF:
25599 /* TODO: Implement emulation of D16MULF instruction. */
25600 MIPS_INVAL("OPC_MXU_D16MULF");
25601 generate_exception_end(ctx, EXCP_RI);
25602 break;
25603 case OPC_MXU_D16MULE:
25604 /* TODO: Implement emulation of D16MULE instruction. */
25605 MIPS_INVAL("OPC_MXU_D16MULE");
25606 generate_exception_end(ctx, EXCP_RI);
25607 break;
25608 default:
25609 MIPS_INVAL("decode_opc_mxu");
25610 generate_exception_end(ctx, EXCP_RI);
25611 break;
25617 * Decode MXU pool04
25619 * 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
25620 * +-----------+---------+-+-------------------+-------+-----------+
25621 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25622 * +-----------+---------+-+-------------------+-------+-----------+
25625 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25627 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25629 switch (opcode) {
25630 case OPC_MXU_S32LDD:
25631 case OPC_MXU_S32LDDR:
25632 gen_mxu_s32ldd_s32lddr(ctx);
25633 break;
25634 default:
25635 MIPS_INVAL("decode_opc_mxu");
25636 generate_exception_end(ctx, EXCP_RI);
25637 break;
25643 * Decode MXU pool05
25645 * 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
25646 * +-----------+---------+-+-------------------+-------+-----------+
25647 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25648 * +-----------+---------+-+-------------------+-------+-----------+
25651 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25653 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25655 switch (opcode) {
25656 case OPC_MXU_S32STD:
25657 /* TODO: Implement emulation of S32STD instruction. */
25658 MIPS_INVAL("OPC_MXU_S32STD");
25659 generate_exception_end(ctx, EXCP_RI);
25660 break;
25661 case OPC_MXU_S32STDR:
25662 /* TODO: Implement emulation of S32STDR instruction. */
25663 MIPS_INVAL("OPC_MXU_S32STDR");
25664 generate_exception_end(ctx, EXCP_RI);
25665 break;
25666 default:
25667 MIPS_INVAL("decode_opc_mxu");
25668 generate_exception_end(ctx, EXCP_RI);
25669 break;
25675 * Decode MXU pool06
25677 * 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
25678 * +-----------+---------+---------+---+-------+-------+-----------+
25679 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25680 * +-----------+---------+---------+---+-------+-------+-----------+
25683 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25685 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25687 switch (opcode) {
25688 case OPC_MXU_S32LDDV:
25689 /* TODO: Implement emulation of S32LDDV instruction. */
25690 MIPS_INVAL("OPC_MXU_S32LDDV");
25691 generate_exception_end(ctx, EXCP_RI);
25692 break;
25693 case OPC_MXU_S32LDDVR:
25694 /* TODO: Implement emulation of S32LDDVR instruction. */
25695 MIPS_INVAL("OPC_MXU_S32LDDVR");
25696 generate_exception_end(ctx, EXCP_RI);
25697 break;
25698 default:
25699 MIPS_INVAL("decode_opc_mxu");
25700 generate_exception_end(ctx, EXCP_RI);
25701 break;
25707 * Decode MXU pool07
25709 * 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
25710 * +-----------+---------+---------+---+-------+-------+-----------+
25711 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
25712 * +-----------+---------+---------+---+-------+-------+-----------+
25715 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
25717 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25719 switch (opcode) {
25720 case OPC_MXU_S32STDV:
25721 /* TODO: Implement emulation of S32TDV instruction. */
25722 MIPS_INVAL("OPC_MXU_S32TDV");
25723 generate_exception_end(ctx, EXCP_RI);
25724 break;
25725 case OPC_MXU_S32STDVR:
25726 /* TODO: Implement emulation of S32TDVR instruction. */
25727 MIPS_INVAL("OPC_MXU_S32TDVR");
25728 generate_exception_end(ctx, EXCP_RI);
25729 break;
25730 default:
25731 MIPS_INVAL("decode_opc_mxu");
25732 generate_exception_end(ctx, EXCP_RI);
25733 break;
25739 * Decode MXU pool08
25741 * 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
25742 * +-----------+---------+-+-------------------+-------+-----------+
25743 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
25744 * +-----------+---------+-+-------------------+-------+-----------+
25747 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
25749 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25751 switch (opcode) {
25752 case OPC_MXU_S32LDI:
25753 /* TODO: Implement emulation of S32LDI instruction. */
25754 MIPS_INVAL("OPC_MXU_S32LDI");
25755 generate_exception_end(ctx, EXCP_RI);
25756 break;
25757 case OPC_MXU_S32LDIR:
25758 /* TODO: Implement emulation of S32LDIR instruction. */
25759 MIPS_INVAL("OPC_MXU_S32LDIR");
25760 generate_exception_end(ctx, EXCP_RI);
25761 break;
25762 default:
25763 MIPS_INVAL("decode_opc_mxu");
25764 generate_exception_end(ctx, EXCP_RI);
25765 break;
25771 * Decode MXU pool09
25773 * 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
25774 * +-----------+---------+-+-------------------+-------+-----------+
25775 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
25776 * +-----------+---------+-+-------------------+-------+-----------+
25779 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
25781 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25783 switch (opcode) {
25784 case OPC_MXU_S32SDI:
25785 /* TODO: Implement emulation of S32SDI instruction. */
25786 MIPS_INVAL("OPC_MXU_S32SDI");
25787 generate_exception_end(ctx, EXCP_RI);
25788 break;
25789 case OPC_MXU_S32SDIR:
25790 /* TODO: Implement emulation of S32SDIR instruction. */
25791 MIPS_INVAL("OPC_MXU_S32SDIR");
25792 generate_exception_end(ctx, EXCP_RI);
25793 break;
25794 default:
25795 MIPS_INVAL("decode_opc_mxu");
25796 generate_exception_end(ctx, EXCP_RI);
25797 break;
25803 * Decode MXU pool10
25805 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25806 * +-----------+---------+---------+---+-------+-------+-----------+
25807 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
25808 * +-----------+---------+---------+---+-------+-------+-----------+
25811 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
25813 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25815 switch (opcode) {
25816 case OPC_MXU_S32LDIV:
25817 /* TODO: Implement emulation of S32LDIV instruction. */
25818 MIPS_INVAL("OPC_MXU_S32LDIV");
25819 generate_exception_end(ctx, EXCP_RI);
25820 break;
25821 case OPC_MXU_S32LDIVR:
25822 /* TODO: Implement emulation of S32LDIVR instruction. */
25823 MIPS_INVAL("OPC_MXU_S32LDIVR");
25824 generate_exception_end(ctx, EXCP_RI);
25825 break;
25826 default:
25827 MIPS_INVAL("decode_opc_mxu");
25828 generate_exception_end(ctx, EXCP_RI);
25829 break;
25835 * Decode MXU pool11
25837 * 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
25838 * +-----------+---------+---------+---+-------+-------+-----------+
25839 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
25840 * +-----------+---------+---------+---+-------+-------+-----------+
25843 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
25845 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25847 switch (opcode) {
25848 case OPC_MXU_S32SDIV:
25849 /* TODO: Implement emulation of S32SDIV instruction. */
25850 MIPS_INVAL("OPC_MXU_S32SDIV");
25851 generate_exception_end(ctx, EXCP_RI);
25852 break;
25853 case OPC_MXU_S32SDIVR:
25854 /* TODO: Implement emulation of S32SDIVR instruction. */
25855 MIPS_INVAL("OPC_MXU_S32SDIVR");
25856 generate_exception_end(ctx, EXCP_RI);
25857 break;
25858 default:
25859 MIPS_INVAL("decode_opc_mxu");
25860 generate_exception_end(ctx, EXCP_RI);
25861 break;
25867 * Decode MXU pool12
25869 * 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
25870 * +-----------+---+---+-------+-------+-------+-------+-----------+
25871 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
25872 * +-----------+---+---+-------+-------+-------+-------+-----------+
25875 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
25877 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25879 switch (opcode) {
25880 case OPC_MXU_D32ACC:
25881 /* TODO: Implement emulation of D32ACC instruction. */
25882 MIPS_INVAL("OPC_MXU_D32ACC");
25883 generate_exception_end(ctx, EXCP_RI);
25884 break;
25885 case OPC_MXU_D32ACCM:
25886 /* TODO: Implement emulation of D32ACCM instruction. */
25887 MIPS_INVAL("OPC_MXU_D32ACCM");
25888 generate_exception_end(ctx, EXCP_RI);
25889 break;
25890 case OPC_MXU_D32ASUM:
25891 /* TODO: Implement emulation of D32ASUM instruction. */
25892 MIPS_INVAL("OPC_MXU_D32ASUM");
25893 generate_exception_end(ctx, EXCP_RI);
25894 break;
25895 default:
25896 MIPS_INVAL("decode_opc_mxu");
25897 generate_exception_end(ctx, EXCP_RI);
25898 break;
25904 * Decode MXU pool13
25906 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25907 * +-----------+---+---+-------+-------+-------+-------+-----------+
25908 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
25909 * +-----------+---+---+-------+-------+-------+-------+-----------+
25912 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
25914 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25916 switch (opcode) {
25917 case OPC_MXU_Q16ACC:
25918 /* TODO: Implement emulation of Q16ACC instruction. */
25919 MIPS_INVAL("OPC_MXU_Q16ACC");
25920 generate_exception_end(ctx, EXCP_RI);
25921 break;
25922 case OPC_MXU_Q16ACCM:
25923 /* TODO: Implement emulation of Q16ACCM instruction. */
25924 MIPS_INVAL("OPC_MXU_Q16ACCM");
25925 generate_exception_end(ctx, EXCP_RI);
25926 break;
25927 case OPC_MXU_Q16ASUM:
25928 /* TODO: Implement emulation of Q16ASUM instruction. */
25929 MIPS_INVAL("OPC_MXU_Q16ASUM");
25930 generate_exception_end(ctx, EXCP_RI);
25931 break;
25932 default:
25933 MIPS_INVAL("decode_opc_mxu");
25934 generate_exception_end(ctx, EXCP_RI);
25935 break;
25941 * Decode MXU pool14
25943 * Q8ADDE, Q8ACCE:
25944 * 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
25945 * +-----------+---+---+-------+-------+-------+-------+-----------+
25946 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
25947 * +-----------+---+---+-------+-------+-------+-------+-----------+
25949 * D8SUM, D8SUMC:
25950 * 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
25951 * +-----------+---+---+-------+-------+-------+-------+-----------+
25952 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
25953 * +-----------+---+---+-------+-------+-------+-------+-----------+
25956 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
25958 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25960 switch (opcode) {
25961 case OPC_MXU_Q8ADDE:
25962 /* TODO: Implement emulation of Q8ADDE instruction. */
25963 MIPS_INVAL("OPC_MXU_Q8ADDE");
25964 generate_exception_end(ctx, EXCP_RI);
25965 break;
25966 case OPC_MXU_D8SUM:
25967 /* TODO: Implement emulation of D8SUM instruction. */
25968 MIPS_INVAL("OPC_MXU_D8SUM");
25969 generate_exception_end(ctx, EXCP_RI);
25970 break;
25971 case OPC_MXU_D8SUMC:
25972 /* TODO: Implement emulation of D8SUMC instruction. */
25973 MIPS_INVAL("OPC_MXU_D8SUMC");
25974 generate_exception_end(ctx, EXCP_RI);
25975 break;
25976 default:
25977 MIPS_INVAL("decode_opc_mxu");
25978 generate_exception_end(ctx, EXCP_RI);
25979 break;
25985 * Decode MXU pool15
25987 * S32MUL, S32MULU, S32EXTRV:
25988 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25989 * +-----------+---------+---------+---+-------+-------+-----------+
25990 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
25991 * +-----------+---------+---------+---+-------+-------+-----------+
25993 * S32EXTR:
25994 * 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
25995 * +-----------+---------+---------+---+-------+-------+-----------+
25996 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
25997 * +-----------+---------+---------+---+-------+-------+-----------+
26000 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26002 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26004 switch (opcode) {
26005 case OPC_MXU_S32MUL:
26006 /* TODO: Implement emulation of S32MUL instruction. */
26007 MIPS_INVAL("OPC_MXU_S32MUL");
26008 generate_exception_end(ctx, EXCP_RI);
26009 break;
26010 case OPC_MXU_S32MULU:
26011 /* TODO: Implement emulation of S32MULU instruction. */
26012 MIPS_INVAL("OPC_MXU_S32MULU");
26013 generate_exception_end(ctx, EXCP_RI);
26014 break;
26015 case OPC_MXU_S32EXTR:
26016 /* TODO: Implement emulation of S32EXTR instruction. */
26017 MIPS_INVAL("OPC_MXU_S32EXTR");
26018 generate_exception_end(ctx, EXCP_RI);
26019 break;
26020 case OPC_MXU_S32EXTRV:
26021 /* TODO: Implement emulation of S32EXTRV instruction. */
26022 MIPS_INVAL("OPC_MXU_S32EXTRV");
26023 generate_exception_end(ctx, EXCP_RI);
26024 break;
26025 default:
26026 MIPS_INVAL("decode_opc_mxu");
26027 generate_exception_end(ctx, EXCP_RI);
26028 break;
26034 * Decode MXU pool16
26036 * D32SARW:
26037 * 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
26038 * +-----------+---------+-----+-------+-------+-------+-----------+
26039 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26040 * +-----------+---------+-----+-------+-------+-------+-----------+
26042 * S32ALN:
26043 * 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
26044 * +-----------+---------+-----+-------+-------+-------+-----------+
26045 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26046 * +-----------+---------+-----+-------+-------+-------+-----------+
26048 * S32ALNI:
26049 * 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
26050 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26051 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26052 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26054 * S32LUI:
26055 * 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
26056 * +-----------+-----+---+-----+-------+---------------+-----------+
26057 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26058 * +-----------+-----+---+-----+-------+---------------+-----------+
26060 * S32NOR, S32AND, S32OR, S32XOR:
26061 * 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
26062 * +-----------+---------+-----+-------+-------+-------+-----------+
26063 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26064 * +-----------+---------+-----+-------+-------+-------+-----------+
26067 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26069 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26071 switch (opcode) {
26072 case OPC_MXU_D32SARW:
26073 /* TODO: Implement emulation of D32SARW instruction. */
26074 MIPS_INVAL("OPC_MXU_D32SARW");
26075 generate_exception_end(ctx, EXCP_RI);
26076 break;
26077 case OPC_MXU_S32ALN:
26078 /* TODO: Implement emulation of S32ALN instruction. */
26079 MIPS_INVAL("OPC_MXU_S32ALN");
26080 generate_exception_end(ctx, EXCP_RI);
26081 break;
26082 case OPC_MXU_S32ALNI:
26083 gen_mxu_S32ALNI(ctx);
26084 break;
26085 case OPC_MXU_S32LUI:
26086 /* TODO: Implement emulation of S32LUI instruction. */
26087 MIPS_INVAL("OPC_MXU_S32LUI");
26088 generate_exception_end(ctx, EXCP_RI);
26089 break;
26090 case OPC_MXU_S32NOR:
26091 gen_mxu_S32NOR(ctx);
26092 break;
26093 case OPC_MXU_S32AND:
26094 gen_mxu_S32AND(ctx);
26095 break;
26096 case OPC_MXU_S32OR:
26097 gen_mxu_S32OR(ctx);
26098 break;
26099 case OPC_MXU_S32XOR:
26100 gen_mxu_S32XOR(ctx);
26101 break;
26102 default:
26103 MIPS_INVAL("decode_opc_mxu");
26104 generate_exception_end(ctx, EXCP_RI);
26105 break;
26111 * Decode MXU pool17
26113 * 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
26114 * +-----------+---------+---------+---+---------+-----+-----------+
26115 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26116 * +-----------+---------+---------+---+---------+-----+-----------+
26119 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26121 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26123 switch (opcode) {
26124 case OPC_MXU_LXW:
26125 /* TODO: Implement emulation of LXW instruction. */
26126 MIPS_INVAL("OPC_MXU_LXW");
26127 generate_exception_end(ctx, EXCP_RI);
26128 break;
26129 case OPC_MXU_LXH:
26130 /* TODO: Implement emulation of LXH instruction. */
26131 MIPS_INVAL("OPC_MXU_LXH");
26132 generate_exception_end(ctx, EXCP_RI);
26133 break;
26134 case OPC_MXU_LXHU:
26135 /* TODO: Implement emulation of LXHU instruction. */
26136 MIPS_INVAL("OPC_MXU_LXHU");
26137 generate_exception_end(ctx, EXCP_RI);
26138 break;
26139 case OPC_MXU_LXB:
26140 /* TODO: Implement emulation of LXB instruction. */
26141 MIPS_INVAL("OPC_MXU_LXB");
26142 generate_exception_end(ctx, EXCP_RI);
26143 break;
26144 case OPC_MXU_LXBU:
26145 /* TODO: Implement emulation of LXBU instruction. */
26146 MIPS_INVAL("OPC_MXU_LXBU");
26147 generate_exception_end(ctx, EXCP_RI);
26148 break;
26149 default:
26150 MIPS_INVAL("decode_opc_mxu");
26151 generate_exception_end(ctx, EXCP_RI);
26152 break;
26157 * Decode MXU pool18
26159 * 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
26160 * +-----------+---------+-----+-------+-------+-------+-----------+
26161 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26162 * +-----------+---------+-----+-------+-------+-------+-----------+
26165 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26167 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26169 switch (opcode) {
26170 case OPC_MXU_D32SLLV:
26171 /* TODO: Implement emulation of D32SLLV instruction. */
26172 MIPS_INVAL("OPC_MXU_D32SLLV");
26173 generate_exception_end(ctx, EXCP_RI);
26174 break;
26175 case OPC_MXU_D32SLRV:
26176 /* TODO: Implement emulation of D32SLRV instruction. */
26177 MIPS_INVAL("OPC_MXU_D32SLRV");
26178 generate_exception_end(ctx, EXCP_RI);
26179 break;
26180 case OPC_MXU_D32SARV:
26181 /* TODO: Implement emulation of D32SARV instruction. */
26182 MIPS_INVAL("OPC_MXU_D32SARV");
26183 generate_exception_end(ctx, EXCP_RI);
26184 break;
26185 case OPC_MXU_Q16SLLV:
26186 /* TODO: Implement emulation of Q16SLLV instruction. */
26187 MIPS_INVAL("OPC_MXU_Q16SLLV");
26188 generate_exception_end(ctx, EXCP_RI);
26189 break;
26190 case OPC_MXU_Q16SLRV:
26191 /* TODO: Implement emulation of Q16SLRV instruction. */
26192 MIPS_INVAL("OPC_MXU_Q16SLRV");
26193 generate_exception_end(ctx, EXCP_RI);
26194 break;
26195 case OPC_MXU_Q16SARV:
26196 /* TODO: Implement emulation of Q16SARV instruction. */
26197 MIPS_INVAL("OPC_MXU_Q16SARV");
26198 generate_exception_end(ctx, EXCP_RI);
26199 break;
26200 default:
26201 MIPS_INVAL("decode_opc_mxu");
26202 generate_exception_end(ctx, EXCP_RI);
26203 break;
26209 * Decode MXU pool19
26211 * 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
26212 * +-----------+---+---+-------+-------+-------+-------+-----------+
26213 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26214 * +-----------+---+---+-------+-------+-------+-------+-----------+
26217 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26219 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26221 switch (opcode) {
26222 case OPC_MXU_Q8MUL:
26223 case OPC_MXU_Q8MULSU:
26224 gen_mxu_q8mul_q8mulsu(ctx);
26225 break;
26226 default:
26227 MIPS_INVAL("decode_opc_mxu");
26228 generate_exception_end(ctx, EXCP_RI);
26229 break;
26235 * Decode MXU pool20
26237 * 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
26238 * +-----------+---------+-----+-------+-------+-------+-----------+
26239 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26240 * +-----------+---------+-----+-------+-------+-------+-----------+
26243 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26245 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26247 switch (opcode) {
26248 case OPC_MXU_Q8MOVZ:
26249 /* TODO: Implement emulation of Q8MOVZ instruction. */
26250 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26251 generate_exception_end(ctx, EXCP_RI);
26252 break;
26253 case OPC_MXU_Q8MOVN:
26254 /* TODO: Implement emulation of Q8MOVN instruction. */
26255 MIPS_INVAL("OPC_MXU_Q8MOVN");
26256 generate_exception_end(ctx, EXCP_RI);
26257 break;
26258 case OPC_MXU_D16MOVZ:
26259 /* TODO: Implement emulation of D16MOVZ instruction. */
26260 MIPS_INVAL("OPC_MXU_D16MOVZ");
26261 generate_exception_end(ctx, EXCP_RI);
26262 break;
26263 case OPC_MXU_D16MOVN:
26264 /* TODO: Implement emulation of D16MOVN instruction. */
26265 MIPS_INVAL("OPC_MXU_D16MOVN");
26266 generate_exception_end(ctx, EXCP_RI);
26267 break;
26268 case OPC_MXU_S32MOVZ:
26269 /* TODO: Implement emulation of S32MOVZ instruction. */
26270 MIPS_INVAL("OPC_MXU_S32MOVZ");
26271 generate_exception_end(ctx, EXCP_RI);
26272 break;
26273 case OPC_MXU_S32MOVN:
26274 /* TODO: Implement emulation of S32MOVN instruction. */
26275 MIPS_INVAL("OPC_MXU_S32MOVN");
26276 generate_exception_end(ctx, EXCP_RI);
26277 break;
26278 default:
26279 MIPS_INVAL("decode_opc_mxu");
26280 generate_exception_end(ctx, EXCP_RI);
26281 break;
26287 * Decode MXU pool21
26289 * 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
26290 * +-----------+---+---+-------+-------+-------+-------+-----------+
26291 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26292 * +-----------+---+---+-------+-------+-------+-------+-----------+
26295 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26297 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26299 switch (opcode) {
26300 case OPC_MXU_Q8MAC:
26301 /* TODO: Implement emulation of Q8MAC instruction. */
26302 MIPS_INVAL("OPC_MXU_Q8MAC");
26303 generate_exception_end(ctx, EXCP_RI);
26304 break;
26305 case OPC_MXU_Q8MACSU:
26306 /* TODO: Implement emulation of Q8MACSU instruction. */
26307 MIPS_INVAL("OPC_MXU_Q8MACSU");
26308 generate_exception_end(ctx, EXCP_RI);
26309 break;
26310 default:
26311 MIPS_INVAL("decode_opc_mxu");
26312 generate_exception_end(ctx, EXCP_RI);
26313 break;
26319 * Main MXU decoding function
26321 * 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
26322 * +-----------+---------------------------------------+-----------+
26323 * | SPECIAL2 | |x x x x x x|
26324 * +-----------+---------------------------------------+-----------+
26327 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26330 * TODO: Investigate necessity of including handling of
26331 * CLZ, CLO, SDBB in this function, as they belong to
26332 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26334 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26336 if (opcode == OPC__MXU_MUL) {
26337 uint32_t rs, rt, rd, op1;
26339 rs = extract32(ctx->opcode, 21, 5);
26340 rt = extract32(ctx->opcode, 16, 5);
26341 rd = extract32(ctx->opcode, 11, 5);
26342 op1 = MASK_SPECIAL2(ctx->opcode);
26344 gen_arith(ctx, op1, rd, rs, rt);
26346 return;
26349 if (opcode == OPC_MXU_S32M2I) {
26350 gen_mxu_s32m2i(ctx);
26351 return;
26354 if (opcode == OPC_MXU_S32I2M) {
26355 gen_mxu_s32i2m(ctx);
26356 return;
26360 TCGv t_mxu_cr = tcg_temp_new();
26361 TCGLabel *l_exit = gen_new_label();
26363 gen_load_mxu_cr(t_mxu_cr);
26364 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26365 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26367 switch (opcode) {
26368 case OPC_MXU_S32MADD:
26369 /* TODO: Implement emulation of S32MADD instruction. */
26370 MIPS_INVAL("OPC_MXU_S32MADD");
26371 generate_exception_end(ctx, EXCP_RI);
26372 break;
26373 case OPC_MXU_S32MADDU:
26374 /* TODO: Implement emulation of S32MADDU instruction. */
26375 MIPS_INVAL("OPC_MXU_S32MADDU");
26376 generate_exception_end(ctx, EXCP_RI);
26377 break;
26378 case OPC_MXU__POOL00:
26379 decode_opc_mxu__pool00(env, ctx);
26380 break;
26381 case OPC_MXU_S32MSUB:
26382 /* TODO: Implement emulation of S32MSUB instruction. */
26383 MIPS_INVAL("OPC_MXU_S32MSUB");
26384 generate_exception_end(ctx, EXCP_RI);
26385 break;
26386 case OPC_MXU_S32MSUBU:
26387 /* TODO: Implement emulation of S32MSUBU instruction. */
26388 MIPS_INVAL("OPC_MXU_S32MSUBU");
26389 generate_exception_end(ctx, EXCP_RI);
26390 break;
26391 case OPC_MXU__POOL01:
26392 decode_opc_mxu__pool01(env, ctx);
26393 break;
26394 case OPC_MXU__POOL02:
26395 decode_opc_mxu__pool02(env, ctx);
26396 break;
26397 case OPC_MXU_D16MUL:
26398 gen_mxu_d16mul(ctx);
26399 break;
26400 case OPC_MXU__POOL03:
26401 decode_opc_mxu__pool03(env, ctx);
26402 break;
26403 case OPC_MXU_D16MAC:
26404 gen_mxu_d16mac(ctx);
26405 break;
26406 case OPC_MXU_D16MACF:
26407 /* TODO: Implement emulation of D16MACF instruction. */
26408 MIPS_INVAL("OPC_MXU_D16MACF");
26409 generate_exception_end(ctx, EXCP_RI);
26410 break;
26411 case OPC_MXU_D16MADL:
26412 /* TODO: Implement emulation of D16MADL instruction. */
26413 MIPS_INVAL("OPC_MXU_D16MADL");
26414 generate_exception_end(ctx, EXCP_RI);
26415 break;
26416 case OPC_MXU_S16MAD:
26417 /* TODO: Implement emulation of S16MAD instruction. */
26418 MIPS_INVAL("OPC_MXU_S16MAD");
26419 generate_exception_end(ctx, EXCP_RI);
26420 break;
26421 case OPC_MXU_Q16ADD:
26422 /* TODO: Implement emulation of Q16ADD instruction. */
26423 MIPS_INVAL("OPC_MXU_Q16ADD");
26424 generate_exception_end(ctx, EXCP_RI);
26425 break;
26426 case OPC_MXU_D16MACE:
26427 /* TODO: Implement emulation of D16MACE instruction. */
26428 MIPS_INVAL("OPC_MXU_D16MACE");
26429 generate_exception_end(ctx, EXCP_RI);
26430 break;
26431 case OPC_MXU__POOL04:
26432 decode_opc_mxu__pool04(env, ctx);
26433 break;
26434 case OPC_MXU__POOL05:
26435 decode_opc_mxu__pool05(env, ctx);
26436 break;
26437 case OPC_MXU__POOL06:
26438 decode_opc_mxu__pool06(env, ctx);
26439 break;
26440 case OPC_MXU__POOL07:
26441 decode_opc_mxu__pool07(env, ctx);
26442 break;
26443 case OPC_MXU__POOL08:
26444 decode_opc_mxu__pool08(env, ctx);
26445 break;
26446 case OPC_MXU__POOL09:
26447 decode_opc_mxu__pool09(env, ctx);
26448 break;
26449 case OPC_MXU__POOL10:
26450 decode_opc_mxu__pool10(env, ctx);
26451 break;
26452 case OPC_MXU__POOL11:
26453 decode_opc_mxu__pool11(env, ctx);
26454 break;
26455 case OPC_MXU_D32ADD:
26456 /* TODO: Implement emulation of D32ADD instruction. */
26457 MIPS_INVAL("OPC_MXU_D32ADD");
26458 generate_exception_end(ctx, EXCP_RI);
26459 break;
26460 case OPC_MXU__POOL12:
26461 decode_opc_mxu__pool12(env, ctx);
26462 break;
26463 case OPC_MXU__POOL13:
26464 decode_opc_mxu__pool13(env, ctx);
26465 break;
26466 case OPC_MXU__POOL14:
26467 decode_opc_mxu__pool14(env, ctx);
26468 break;
26469 case OPC_MXU_Q8ACCE:
26470 /* TODO: Implement emulation of Q8ACCE instruction. */
26471 MIPS_INVAL("OPC_MXU_Q8ACCE");
26472 generate_exception_end(ctx, EXCP_RI);
26473 break;
26474 case OPC_MXU_S8LDD:
26475 gen_mxu_s8ldd(ctx);
26476 break;
26477 case OPC_MXU_S8STD:
26478 /* TODO: Implement emulation of S8STD instruction. */
26479 MIPS_INVAL("OPC_MXU_S8STD");
26480 generate_exception_end(ctx, EXCP_RI);
26481 break;
26482 case OPC_MXU_S8LDI:
26483 /* TODO: Implement emulation of S8LDI instruction. */
26484 MIPS_INVAL("OPC_MXU_S8LDI");
26485 generate_exception_end(ctx, EXCP_RI);
26486 break;
26487 case OPC_MXU_S8SDI:
26488 /* TODO: Implement emulation of S8SDI instruction. */
26489 MIPS_INVAL("OPC_MXU_S8SDI");
26490 generate_exception_end(ctx, EXCP_RI);
26491 break;
26492 case OPC_MXU__POOL15:
26493 decode_opc_mxu__pool15(env, ctx);
26494 break;
26495 case OPC_MXU__POOL16:
26496 decode_opc_mxu__pool16(env, ctx);
26497 break;
26498 case OPC_MXU__POOL17:
26499 decode_opc_mxu__pool17(env, ctx);
26500 break;
26501 case OPC_MXU_S16LDD:
26502 /* TODO: Implement emulation of S16LDD instruction. */
26503 MIPS_INVAL("OPC_MXU_S16LDD");
26504 generate_exception_end(ctx, EXCP_RI);
26505 break;
26506 case OPC_MXU_S16STD:
26507 /* TODO: Implement emulation of S16STD instruction. */
26508 MIPS_INVAL("OPC_MXU_S16STD");
26509 generate_exception_end(ctx, EXCP_RI);
26510 break;
26511 case OPC_MXU_S16LDI:
26512 /* TODO: Implement emulation of S16LDI instruction. */
26513 MIPS_INVAL("OPC_MXU_S16LDI");
26514 generate_exception_end(ctx, EXCP_RI);
26515 break;
26516 case OPC_MXU_S16SDI:
26517 /* TODO: Implement emulation of S16SDI instruction. */
26518 MIPS_INVAL("OPC_MXU_S16SDI");
26519 generate_exception_end(ctx, EXCP_RI);
26520 break;
26521 case OPC_MXU_D32SLL:
26522 /* TODO: Implement emulation of D32SLL instruction. */
26523 MIPS_INVAL("OPC_MXU_D32SLL");
26524 generate_exception_end(ctx, EXCP_RI);
26525 break;
26526 case OPC_MXU_D32SLR:
26527 /* TODO: Implement emulation of D32SLR instruction. */
26528 MIPS_INVAL("OPC_MXU_D32SLR");
26529 generate_exception_end(ctx, EXCP_RI);
26530 break;
26531 case OPC_MXU_D32SARL:
26532 /* TODO: Implement emulation of D32SARL instruction. */
26533 MIPS_INVAL("OPC_MXU_D32SARL");
26534 generate_exception_end(ctx, EXCP_RI);
26535 break;
26536 case OPC_MXU_D32SAR:
26537 /* TODO: Implement emulation of D32SAR instruction. */
26538 MIPS_INVAL("OPC_MXU_D32SAR");
26539 generate_exception_end(ctx, EXCP_RI);
26540 break;
26541 case OPC_MXU_Q16SLL:
26542 /* TODO: Implement emulation of Q16SLL instruction. */
26543 MIPS_INVAL("OPC_MXU_Q16SLL");
26544 generate_exception_end(ctx, EXCP_RI);
26545 break;
26546 case OPC_MXU_Q16SLR:
26547 /* TODO: Implement emulation of Q16SLR instruction. */
26548 MIPS_INVAL("OPC_MXU_Q16SLR");
26549 generate_exception_end(ctx, EXCP_RI);
26550 break;
26551 case OPC_MXU__POOL18:
26552 decode_opc_mxu__pool18(env, ctx);
26553 break;
26554 case OPC_MXU_Q16SAR:
26555 /* TODO: Implement emulation of Q16SAR instruction. */
26556 MIPS_INVAL("OPC_MXU_Q16SAR");
26557 generate_exception_end(ctx, EXCP_RI);
26558 break;
26559 case OPC_MXU__POOL19:
26560 decode_opc_mxu__pool19(env, ctx);
26561 break;
26562 case OPC_MXU__POOL20:
26563 decode_opc_mxu__pool20(env, ctx);
26564 break;
26565 case OPC_MXU__POOL21:
26566 decode_opc_mxu__pool21(env, ctx);
26567 break;
26568 case OPC_MXU_Q16SCOP:
26569 /* TODO: Implement emulation of Q16SCOP instruction. */
26570 MIPS_INVAL("OPC_MXU_Q16SCOP");
26571 generate_exception_end(ctx, EXCP_RI);
26572 break;
26573 case OPC_MXU_Q8MADL:
26574 /* TODO: Implement emulation of Q8MADL instruction. */
26575 MIPS_INVAL("OPC_MXU_Q8MADL");
26576 generate_exception_end(ctx, EXCP_RI);
26577 break;
26578 case OPC_MXU_S32SFL:
26579 /* TODO: Implement emulation of S32SFL instruction. */
26580 MIPS_INVAL("OPC_MXU_S32SFL");
26581 generate_exception_end(ctx, EXCP_RI);
26582 break;
26583 case OPC_MXU_Q8SAD:
26584 /* TODO: Implement emulation of Q8SAD instruction. */
26585 MIPS_INVAL("OPC_MXU_Q8SAD");
26586 generate_exception_end(ctx, EXCP_RI);
26587 break;
26588 default:
26589 MIPS_INVAL("decode_opc_mxu");
26590 generate_exception_end(ctx, EXCP_RI);
26593 gen_set_label(l_exit);
26594 tcg_temp_free(t_mxu_cr);
26598 #endif /* !defined(TARGET_MIPS64) */
26601 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26603 int rs, rt, rd;
26604 uint32_t op1;
26606 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26608 rs = (ctx->opcode >> 21) & 0x1f;
26609 rt = (ctx->opcode >> 16) & 0x1f;
26610 rd = (ctx->opcode >> 11) & 0x1f;
26612 op1 = MASK_SPECIAL2(ctx->opcode);
26613 switch (op1) {
26614 case OPC_MADD: /* Multiply and add/sub */
26615 case OPC_MADDU:
26616 case OPC_MSUB:
26617 case OPC_MSUBU:
26618 check_insn(ctx, ISA_MIPS32);
26619 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26620 break;
26621 case OPC_MUL:
26622 gen_arith(ctx, op1, rd, rs, rt);
26623 break;
26624 case OPC_DIV_G_2F:
26625 case OPC_DIVU_G_2F:
26626 case OPC_MULT_G_2F:
26627 case OPC_MULTU_G_2F:
26628 case OPC_MOD_G_2F:
26629 case OPC_MODU_G_2F:
26630 check_insn(ctx, INSN_LOONGSON2F);
26631 gen_loongson_integer(ctx, op1, rd, rs, rt);
26632 break;
26633 case OPC_CLO:
26634 case OPC_CLZ:
26635 check_insn(ctx, ISA_MIPS32);
26636 gen_cl(ctx, op1, rd, rs);
26637 break;
26638 case OPC_SDBBP:
26639 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26640 gen_helper_do_semihosting(cpu_env);
26641 } else {
26642 /* XXX: not clear which exception should be raised
26643 * when in debug mode...
26645 check_insn(ctx, ISA_MIPS32);
26646 generate_exception_end(ctx, EXCP_DBp);
26648 break;
26649 #if defined(TARGET_MIPS64)
26650 case OPC_DCLO:
26651 case OPC_DCLZ:
26652 check_insn(ctx, ISA_MIPS64);
26653 check_mips_64(ctx);
26654 gen_cl(ctx, op1, rd, rs);
26655 break;
26656 case OPC_DMULT_G_2F:
26657 case OPC_DMULTU_G_2F:
26658 case OPC_DDIV_G_2F:
26659 case OPC_DDIVU_G_2F:
26660 case OPC_DMOD_G_2F:
26661 case OPC_DMODU_G_2F:
26662 check_insn(ctx, INSN_LOONGSON2F);
26663 gen_loongson_integer(ctx, op1, rd, rs, rt);
26664 break;
26665 #endif
26666 default: /* Invalid */
26667 MIPS_INVAL("special2_legacy");
26668 generate_exception_end(ctx, EXCP_RI);
26669 break;
26673 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26675 int rs, rt, rd, sa;
26676 uint32_t op1, op2;
26677 int16_t imm;
26679 rs = (ctx->opcode >> 21) & 0x1f;
26680 rt = (ctx->opcode >> 16) & 0x1f;
26681 rd = (ctx->opcode >> 11) & 0x1f;
26682 sa = (ctx->opcode >> 6) & 0x1f;
26683 imm = (int16_t)ctx->opcode >> 7;
26685 op1 = MASK_SPECIAL3(ctx->opcode);
26686 switch (op1) {
26687 case R6_OPC_PREF:
26688 if (rt >= 24) {
26689 /* hint codes 24-31 are reserved and signal RI */
26690 generate_exception_end(ctx, EXCP_RI);
26692 /* Treat as NOP. */
26693 break;
26694 case R6_OPC_CACHE:
26695 check_cp0_enabled(ctx);
26696 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26697 gen_cache_operation(ctx, rt, rs, imm);
26699 break;
26700 case R6_OPC_SC:
26701 gen_st_cond(ctx, op1, rt, rs, imm);
26702 break;
26703 case R6_OPC_LL:
26704 gen_ld(ctx, op1, rt, rs, imm);
26705 break;
26706 case OPC_BSHFL:
26708 if (rd == 0) {
26709 /* Treat as NOP. */
26710 break;
26712 op2 = MASK_BSHFL(ctx->opcode);
26713 switch (op2) {
26714 case OPC_ALIGN:
26715 case OPC_ALIGN_1:
26716 case OPC_ALIGN_2:
26717 case OPC_ALIGN_3:
26718 gen_align(ctx, 32, rd, rs, rt, sa & 3);
26719 break;
26720 case OPC_BITSWAP:
26721 gen_bitswap(ctx, op2, rd, rt);
26722 break;
26725 break;
26726 #if defined(TARGET_MIPS64)
26727 case R6_OPC_SCD:
26728 gen_st_cond(ctx, op1, rt, rs, imm);
26729 break;
26730 case R6_OPC_LLD:
26731 gen_ld(ctx, op1, rt, rs, imm);
26732 break;
26733 case OPC_DBSHFL:
26734 check_mips_64(ctx);
26736 if (rd == 0) {
26737 /* Treat as NOP. */
26738 break;
26740 op2 = MASK_DBSHFL(ctx->opcode);
26741 switch (op2) {
26742 case OPC_DALIGN:
26743 case OPC_DALIGN_1:
26744 case OPC_DALIGN_2:
26745 case OPC_DALIGN_3:
26746 case OPC_DALIGN_4:
26747 case OPC_DALIGN_5:
26748 case OPC_DALIGN_6:
26749 case OPC_DALIGN_7:
26750 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26751 break;
26752 case OPC_DBITSWAP:
26753 gen_bitswap(ctx, op2, rd, rt);
26754 break;
26758 break;
26759 #endif
26760 default: /* Invalid */
26761 MIPS_INVAL("special3_r6");
26762 generate_exception_end(ctx, EXCP_RI);
26763 break;
26767 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26769 int rs, rt, rd;
26770 uint32_t op1, op2;
26772 rs = (ctx->opcode >> 21) & 0x1f;
26773 rt = (ctx->opcode >> 16) & 0x1f;
26774 rd = (ctx->opcode >> 11) & 0x1f;
26776 op1 = MASK_SPECIAL3(ctx->opcode);
26777 switch (op1) {
26778 case OPC_DIV_G_2E:
26779 case OPC_DIVU_G_2E:
26780 case OPC_MOD_G_2E:
26781 case OPC_MODU_G_2E:
26782 case OPC_MULT_G_2E:
26783 case OPC_MULTU_G_2E:
26784 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26785 * the same mask and op1. */
26786 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26787 op2 = MASK_ADDUH_QB(ctx->opcode);
26788 switch (op2) {
26789 case OPC_ADDUH_QB:
26790 case OPC_ADDUH_R_QB:
26791 case OPC_ADDQH_PH:
26792 case OPC_ADDQH_R_PH:
26793 case OPC_ADDQH_W:
26794 case OPC_ADDQH_R_W:
26795 case OPC_SUBUH_QB:
26796 case OPC_SUBUH_R_QB:
26797 case OPC_SUBQH_PH:
26798 case OPC_SUBQH_R_PH:
26799 case OPC_SUBQH_W:
26800 case OPC_SUBQH_R_W:
26801 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26802 break;
26803 case OPC_MUL_PH:
26804 case OPC_MUL_S_PH:
26805 case OPC_MULQ_S_W:
26806 case OPC_MULQ_RS_W:
26807 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26808 break;
26809 default:
26810 MIPS_INVAL("MASK ADDUH.QB");
26811 generate_exception_end(ctx, EXCP_RI);
26812 break;
26814 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26815 gen_loongson_integer(ctx, op1, rd, rs, rt);
26816 } else {
26817 generate_exception_end(ctx, EXCP_RI);
26819 break;
26820 case OPC_LX_DSP:
26821 op2 = MASK_LX(ctx->opcode);
26822 switch (op2) {
26823 #if defined(TARGET_MIPS64)
26824 case OPC_LDX:
26825 #endif
26826 case OPC_LBUX:
26827 case OPC_LHX:
26828 case OPC_LWX:
26829 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26830 break;
26831 default: /* Invalid */
26832 MIPS_INVAL("MASK LX");
26833 generate_exception_end(ctx, EXCP_RI);
26834 break;
26836 break;
26837 case OPC_ABSQ_S_PH_DSP:
26838 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26839 switch (op2) {
26840 case OPC_ABSQ_S_QB:
26841 case OPC_ABSQ_S_PH:
26842 case OPC_ABSQ_S_W:
26843 case OPC_PRECEQ_W_PHL:
26844 case OPC_PRECEQ_W_PHR:
26845 case OPC_PRECEQU_PH_QBL:
26846 case OPC_PRECEQU_PH_QBR:
26847 case OPC_PRECEQU_PH_QBLA:
26848 case OPC_PRECEQU_PH_QBRA:
26849 case OPC_PRECEU_PH_QBL:
26850 case OPC_PRECEU_PH_QBR:
26851 case OPC_PRECEU_PH_QBLA:
26852 case OPC_PRECEU_PH_QBRA:
26853 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26854 break;
26855 case OPC_BITREV:
26856 case OPC_REPL_QB:
26857 case OPC_REPLV_QB:
26858 case OPC_REPL_PH:
26859 case OPC_REPLV_PH:
26860 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26861 break;
26862 default:
26863 MIPS_INVAL("MASK ABSQ_S.PH");
26864 generate_exception_end(ctx, EXCP_RI);
26865 break;
26867 break;
26868 case OPC_ADDU_QB_DSP:
26869 op2 = MASK_ADDU_QB(ctx->opcode);
26870 switch (op2) {
26871 case OPC_ADDQ_PH:
26872 case OPC_ADDQ_S_PH:
26873 case OPC_ADDQ_S_W:
26874 case OPC_ADDU_QB:
26875 case OPC_ADDU_S_QB:
26876 case OPC_ADDU_PH:
26877 case OPC_ADDU_S_PH:
26878 case OPC_SUBQ_PH:
26879 case OPC_SUBQ_S_PH:
26880 case OPC_SUBQ_S_W:
26881 case OPC_SUBU_QB:
26882 case OPC_SUBU_S_QB:
26883 case OPC_SUBU_PH:
26884 case OPC_SUBU_S_PH:
26885 case OPC_ADDSC:
26886 case OPC_ADDWC:
26887 case OPC_MODSUB:
26888 case OPC_RADDU_W_QB:
26889 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26890 break;
26891 case OPC_MULEU_S_PH_QBL:
26892 case OPC_MULEU_S_PH_QBR:
26893 case OPC_MULQ_RS_PH:
26894 case OPC_MULEQ_S_W_PHL:
26895 case OPC_MULEQ_S_W_PHR:
26896 case OPC_MULQ_S_PH:
26897 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26898 break;
26899 default: /* Invalid */
26900 MIPS_INVAL("MASK ADDU.QB");
26901 generate_exception_end(ctx, EXCP_RI);
26902 break;
26905 break;
26906 case OPC_CMPU_EQ_QB_DSP:
26907 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26908 switch (op2) {
26909 case OPC_PRECR_SRA_PH_W:
26910 case OPC_PRECR_SRA_R_PH_W:
26911 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26912 break;
26913 case OPC_PRECR_QB_PH:
26914 case OPC_PRECRQ_QB_PH:
26915 case OPC_PRECRQ_PH_W:
26916 case OPC_PRECRQ_RS_PH_W:
26917 case OPC_PRECRQU_S_QB_PH:
26918 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26919 break;
26920 case OPC_CMPU_EQ_QB:
26921 case OPC_CMPU_LT_QB:
26922 case OPC_CMPU_LE_QB:
26923 case OPC_CMP_EQ_PH:
26924 case OPC_CMP_LT_PH:
26925 case OPC_CMP_LE_PH:
26926 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26927 break;
26928 case OPC_CMPGU_EQ_QB:
26929 case OPC_CMPGU_LT_QB:
26930 case OPC_CMPGU_LE_QB:
26931 case OPC_CMPGDU_EQ_QB:
26932 case OPC_CMPGDU_LT_QB:
26933 case OPC_CMPGDU_LE_QB:
26934 case OPC_PICK_QB:
26935 case OPC_PICK_PH:
26936 case OPC_PACKRL_PH:
26937 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26938 break;
26939 default: /* Invalid */
26940 MIPS_INVAL("MASK CMPU.EQ.QB");
26941 generate_exception_end(ctx, EXCP_RI);
26942 break;
26944 break;
26945 case OPC_SHLL_QB_DSP:
26946 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26947 break;
26948 case OPC_DPA_W_PH_DSP:
26949 op2 = MASK_DPA_W_PH(ctx->opcode);
26950 switch (op2) {
26951 case OPC_DPAU_H_QBL:
26952 case OPC_DPAU_H_QBR:
26953 case OPC_DPSU_H_QBL:
26954 case OPC_DPSU_H_QBR:
26955 case OPC_DPA_W_PH:
26956 case OPC_DPAX_W_PH:
26957 case OPC_DPAQ_S_W_PH:
26958 case OPC_DPAQX_S_W_PH:
26959 case OPC_DPAQX_SA_W_PH:
26960 case OPC_DPS_W_PH:
26961 case OPC_DPSX_W_PH:
26962 case OPC_DPSQ_S_W_PH:
26963 case OPC_DPSQX_S_W_PH:
26964 case OPC_DPSQX_SA_W_PH:
26965 case OPC_MULSAQ_S_W_PH:
26966 case OPC_DPAQ_SA_L_W:
26967 case OPC_DPSQ_SA_L_W:
26968 case OPC_MAQ_S_W_PHL:
26969 case OPC_MAQ_S_W_PHR:
26970 case OPC_MAQ_SA_W_PHL:
26971 case OPC_MAQ_SA_W_PHR:
26972 case OPC_MULSA_W_PH:
26973 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26974 break;
26975 default: /* Invalid */
26976 MIPS_INVAL("MASK DPAW.PH");
26977 generate_exception_end(ctx, EXCP_RI);
26978 break;
26980 break;
26981 case OPC_INSV_DSP:
26982 op2 = MASK_INSV(ctx->opcode);
26983 switch (op2) {
26984 case OPC_INSV:
26985 check_dsp(ctx);
26987 TCGv t0, t1;
26989 if (rt == 0) {
26990 break;
26993 t0 = tcg_temp_new();
26994 t1 = tcg_temp_new();
26996 gen_load_gpr(t0, rt);
26997 gen_load_gpr(t1, rs);
26999 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27001 tcg_temp_free(t0);
27002 tcg_temp_free(t1);
27003 break;
27005 default: /* Invalid */
27006 MIPS_INVAL("MASK INSV");
27007 generate_exception_end(ctx, EXCP_RI);
27008 break;
27010 break;
27011 case OPC_APPEND_DSP:
27012 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27013 break;
27014 case OPC_EXTR_W_DSP:
27015 op2 = MASK_EXTR_W(ctx->opcode);
27016 switch (op2) {
27017 case OPC_EXTR_W:
27018 case OPC_EXTR_R_W:
27019 case OPC_EXTR_RS_W:
27020 case OPC_EXTR_S_H:
27021 case OPC_EXTRV_S_H:
27022 case OPC_EXTRV_W:
27023 case OPC_EXTRV_R_W:
27024 case OPC_EXTRV_RS_W:
27025 case OPC_EXTP:
27026 case OPC_EXTPV:
27027 case OPC_EXTPDP:
27028 case OPC_EXTPDPV:
27029 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27030 break;
27031 case OPC_RDDSP:
27032 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27033 break;
27034 case OPC_SHILO:
27035 case OPC_SHILOV:
27036 case OPC_MTHLIP:
27037 case OPC_WRDSP:
27038 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27039 break;
27040 default: /* Invalid */
27041 MIPS_INVAL("MASK EXTR.W");
27042 generate_exception_end(ctx, EXCP_RI);
27043 break;
27045 break;
27046 #if defined(TARGET_MIPS64)
27047 case OPC_DDIV_G_2E:
27048 case OPC_DDIVU_G_2E:
27049 case OPC_DMULT_G_2E:
27050 case OPC_DMULTU_G_2E:
27051 case OPC_DMOD_G_2E:
27052 case OPC_DMODU_G_2E:
27053 check_insn(ctx, INSN_LOONGSON2E);
27054 gen_loongson_integer(ctx, op1, rd, rs, rt);
27055 break;
27056 case OPC_ABSQ_S_QH_DSP:
27057 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27058 switch (op2) {
27059 case OPC_PRECEQ_L_PWL:
27060 case OPC_PRECEQ_L_PWR:
27061 case OPC_PRECEQ_PW_QHL:
27062 case OPC_PRECEQ_PW_QHR:
27063 case OPC_PRECEQ_PW_QHLA:
27064 case OPC_PRECEQ_PW_QHRA:
27065 case OPC_PRECEQU_QH_OBL:
27066 case OPC_PRECEQU_QH_OBR:
27067 case OPC_PRECEQU_QH_OBLA:
27068 case OPC_PRECEQU_QH_OBRA:
27069 case OPC_PRECEU_QH_OBL:
27070 case OPC_PRECEU_QH_OBR:
27071 case OPC_PRECEU_QH_OBLA:
27072 case OPC_PRECEU_QH_OBRA:
27073 case OPC_ABSQ_S_OB:
27074 case OPC_ABSQ_S_PW:
27075 case OPC_ABSQ_S_QH:
27076 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27077 break;
27078 case OPC_REPL_OB:
27079 case OPC_REPL_PW:
27080 case OPC_REPL_QH:
27081 case OPC_REPLV_OB:
27082 case OPC_REPLV_PW:
27083 case OPC_REPLV_QH:
27084 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27085 break;
27086 default: /* Invalid */
27087 MIPS_INVAL("MASK ABSQ_S.QH");
27088 generate_exception_end(ctx, EXCP_RI);
27089 break;
27091 break;
27092 case OPC_ADDU_OB_DSP:
27093 op2 = MASK_ADDU_OB(ctx->opcode);
27094 switch (op2) {
27095 case OPC_RADDU_L_OB:
27096 case OPC_SUBQ_PW:
27097 case OPC_SUBQ_S_PW:
27098 case OPC_SUBQ_QH:
27099 case OPC_SUBQ_S_QH:
27100 case OPC_SUBU_OB:
27101 case OPC_SUBU_S_OB:
27102 case OPC_SUBU_QH:
27103 case OPC_SUBU_S_QH:
27104 case OPC_SUBUH_OB:
27105 case OPC_SUBUH_R_OB:
27106 case OPC_ADDQ_PW:
27107 case OPC_ADDQ_S_PW:
27108 case OPC_ADDQ_QH:
27109 case OPC_ADDQ_S_QH:
27110 case OPC_ADDU_OB:
27111 case OPC_ADDU_S_OB:
27112 case OPC_ADDU_QH:
27113 case OPC_ADDU_S_QH:
27114 case OPC_ADDUH_OB:
27115 case OPC_ADDUH_R_OB:
27116 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27117 break;
27118 case OPC_MULEQ_S_PW_QHL:
27119 case OPC_MULEQ_S_PW_QHR:
27120 case OPC_MULEU_S_QH_OBL:
27121 case OPC_MULEU_S_QH_OBR:
27122 case OPC_MULQ_RS_QH:
27123 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27124 break;
27125 default: /* Invalid */
27126 MIPS_INVAL("MASK ADDU.OB");
27127 generate_exception_end(ctx, EXCP_RI);
27128 break;
27130 break;
27131 case OPC_CMPU_EQ_OB_DSP:
27132 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27133 switch (op2) {
27134 case OPC_PRECR_SRA_QH_PW:
27135 case OPC_PRECR_SRA_R_QH_PW:
27136 /* Return value is rt. */
27137 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27138 break;
27139 case OPC_PRECR_OB_QH:
27140 case OPC_PRECRQ_OB_QH:
27141 case OPC_PRECRQ_PW_L:
27142 case OPC_PRECRQ_QH_PW:
27143 case OPC_PRECRQ_RS_QH_PW:
27144 case OPC_PRECRQU_S_OB_QH:
27145 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27146 break;
27147 case OPC_CMPU_EQ_OB:
27148 case OPC_CMPU_LT_OB:
27149 case OPC_CMPU_LE_OB:
27150 case OPC_CMP_EQ_QH:
27151 case OPC_CMP_LT_QH:
27152 case OPC_CMP_LE_QH:
27153 case OPC_CMP_EQ_PW:
27154 case OPC_CMP_LT_PW:
27155 case OPC_CMP_LE_PW:
27156 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27157 break;
27158 case OPC_CMPGDU_EQ_OB:
27159 case OPC_CMPGDU_LT_OB:
27160 case OPC_CMPGDU_LE_OB:
27161 case OPC_CMPGU_EQ_OB:
27162 case OPC_CMPGU_LT_OB:
27163 case OPC_CMPGU_LE_OB:
27164 case OPC_PACKRL_PW:
27165 case OPC_PICK_OB:
27166 case OPC_PICK_PW:
27167 case OPC_PICK_QH:
27168 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27169 break;
27170 default: /* Invalid */
27171 MIPS_INVAL("MASK CMPU_EQ.OB");
27172 generate_exception_end(ctx, EXCP_RI);
27173 break;
27175 break;
27176 case OPC_DAPPEND_DSP:
27177 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27178 break;
27179 case OPC_DEXTR_W_DSP:
27180 op2 = MASK_DEXTR_W(ctx->opcode);
27181 switch (op2) {
27182 case OPC_DEXTP:
27183 case OPC_DEXTPDP:
27184 case OPC_DEXTPDPV:
27185 case OPC_DEXTPV:
27186 case OPC_DEXTR_L:
27187 case OPC_DEXTR_R_L:
27188 case OPC_DEXTR_RS_L:
27189 case OPC_DEXTR_W:
27190 case OPC_DEXTR_R_W:
27191 case OPC_DEXTR_RS_W:
27192 case OPC_DEXTR_S_H:
27193 case OPC_DEXTRV_L:
27194 case OPC_DEXTRV_R_L:
27195 case OPC_DEXTRV_RS_L:
27196 case OPC_DEXTRV_S_H:
27197 case OPC_DEXTRV_W:
27198 case OPC_DEXTRV_R_W:
27199 case OPC_DEXTRV_RS_W:
27200 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27201 break;
27202 case OPC_DMTHLIP:
27203 case OPC_DSHILO:
27204 case OPC_DSHILOV:
27205 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27206 break;
27207 default: /* Invalid */
27208 MIPS_INVAL("MASK EXTR.W");
27209 generate_exception_end(ctx, EXCP_RI);
27210 break;
27212 break;
27213 case OPC_DPAQ_W_QH_DSP:
27214 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27215 switch (op2) {
27216 case OPC_DPAU_H_OBL:
27217 case OPC_DPAU_H_OBR:
27218 case OPC_DPSU_H_OBL:
27219 case OPC_DPSU_H_OBR:
27220 case OPC_DPA_W_QH:
27221 case OPC_DPAQ_S_W_QH:
27222 case OPC_DPS_W_QH:
27223 case OPC_DPSQ_S_W_QH:
27224 case OPC_MULSAQ_S_W_QH:
27225 case OPC_DPAQ_SA_L_PW:
27226 case OPC_DPSQ_SA_L_PW:
27227 case OPC_MULSAQ_S_L_PW:
27228 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27229 break;
27230 case OPC_MAQ_S_W_QHLL:
27231 case OPC_MAQ_S_W_QHLR:
27232 case OPC_MAQ_S_W_QHRL:
27233 case OPC_MAQ_S_W_QHRR:
27234 case OPC_MAQ_SA_W_QHLL:
27235 case OPC_MAQ_SA_W_QHLR:
27236 case OPC_MAQ_SA_W_QHRL:
27237 case OPC_MAQ_SA_W_QHRR:
27238 case OPC_MAQ_S_L_PWL:
27239 case OPC_MAQ_S_L_PWR:
27240 case OPC_DMADD:
27241 case OPC_DMADDU:
27242 case OPC_DMSUB:
27243 case OPC_DMSUBU:
27244 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27245 break;
27246 default: /* Invalid */
27247 MIPS_INVAL("MASK DPAQ.W.QH");
27248 generate_exception_end(ctx, EXCP_RI);
27249 break;
27251 break;
27252 case OPC_DINSV_DSP:
27253 op2 = MASK_INSV(ctx->opcode);
27254 switch (op2) {
27255 case OPC_DINSV:
27257 TCGv t0, t1;
27259 if (rt == 0) {
27260 break;
27262 check_dsp(ctx);
27264 t0 = tcg_temp_new();
27265 t1 = tcg_temp_new();
27267 gen_load_gpr(t0, rt);
27268 gen_load_gpr(t1, rs);
27270 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27272 tcg_temp_free(t0);
27273 tcg_temp_free(t1);
27274 break;
27276 default: /* Invalid */
27277 MIPS_INVAL("MASK DINSV");
27278 generate_exception_end(ctx, EXCP_RI);
27279 break;
27281 break;
27282 case OPC_SHLL_OB_DSP:
27283 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27284 break;
27285 #endif
27286 default: /* Invalid */
27287 MIPS_INVAL("special3_legacy");
27288 generate_exception_end(ctx, EXCP_RI);
27289 break;
27293 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27295 uint32_t opc = MASK_MMI0(ctx->opcode);
27297 switch (opc) {
27298 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27299 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27300 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27301 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27302 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27303 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27304 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27305 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27306 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27307 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27308 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27309 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27310 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27311 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27312 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27313 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27314 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27315 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27316 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27317 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27318 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27319 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27320 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27321 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27322 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27323 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27324 break;
27325 default:
27326 MIPS_INVAL("TX79 MMI class MMI0");
27327 generate_exception_end(ctx, EXCP_RI);
27328 break;
27332 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27334 uint32_t opc = MASK_MMI1(ctx->opcode);
27336 switch (opc) {
27337 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27338 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27339 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27340 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27341 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27342 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27343 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27344 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27345 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27346 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27347 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27348 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27349 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27350 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27351 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27352 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27353 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27354 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27355 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27356 break;
27357 default:
27358 MIPS_INVAL("TX79 MMI class MMI1");
27359 generate_exception_end(ctx, EXCP_RI);
27360 break;
27364 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27366 uint32_t opc = MASK_MMI2(ctx->opcode);
27368 switch (opc) {
27369 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27370 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27371 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27372 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27373 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27374 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27375 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27376 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27377 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27378 case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */
27379 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27380 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27381 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27382 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27383 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27384 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27385 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27386 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27387 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27388 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27389 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27390 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27391 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27392 break;
27393 default:
27394 MIPS_INVAL("TX79 MMI class MMI2");
27395 generate_exception_end(ctx, EXCP_RI);
27396 break;
27400 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27402 uint32_t opc = MASK_MMI3(ctx->opcode);
27404 switch (opc) {
27405 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27406 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27407 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27408 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27409 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27410 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27411 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27412 case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */
27413 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27414 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27415 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27416 case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */
27417 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27418 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27419 break;
27420 default:
27421 MIPS_INVAL("TX79 MMI class MMI3");
27422 generate_exception_end(ctx, EXCP_RI);
27423 break;
27427 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27429 uint32_t opc = MASK_MMI(ctx->opcode);
27430 int rs = extract32(ctx->opcode, 21, 5);
27431 int rt = extract32(ctx->opcode, 16, 5);
27432 int rd = extract32(ctx->opcode, 11, 5);
27434 switch (opc) {
27435 case MMI_OPC_CLASS_MMI0:
27436 decode_mmi0(env, ctx);
27437 break;
27438 case MMI_OPC_CLASS_MMI1:
27439 decode_mmi1(env, ctx);
27440 break;
27441 case MMI_OPC_CLASS_MMI2:
27442 decode_mmi2(env, ctx);
27443 break;
27444 case MMI_OPC_CLASS_MMI3:
27445 decode_mmi3(env, ctx);
27446 break;
27447 case MMI_OPC_MULT1:
27448 case MMI_OPC_MULTU1:
27449 case MMI_OPC_MADD:
27450 case MMI_OPC_MADDU:
27451 case MMI_OPC_MADD1:
27452 case MMI_OPC_MADDU1:
27453 gen_mul_txx9(ctx, opc, rd, rs, rt);
27454 break;
27455 case MMI_OPC_DIV1:
27456 case MMI_OPC_DIVU1:
27457 gen_div1_tx79(ctx, opc, rs, rt);
27458 break;
27459 case MMI_OPC_MTLO1:
27460 case MMI_OPC_MTHI1:
27461 gen_HILO1_tx79(ctx, opc, rs);
27462 break;
27463 case MMI_OPC_MFLO1:
27464 case MMI_OPC_MFHI1:
27465 gen_HILO1_tx79(ctx, opc, rd);
27466 break;
27467 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27468 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27469 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27470 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27471 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27472 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27473 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27474 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27475 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27476 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27477 break;
27478 default:
27479 MIPS_INVAL("TX79 MMI class");
27480 generate_exception_end(ctx, EXCP_RI);
27481 break;
27485 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27487 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27490 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27492 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27496 * The TX79-specific instruction Store Quadword
27498 * +--------+-------+-------+------------------------+
27499 * | 011111 | base | rt | offset | SQ
27500 * +--------+-------+-------+------------------------+
27501 * 6 5 5 16
27503 * has the same opcode as the Read Hardware Register instruction
27505 * +--------+-------+-------+-------+-------+--------+
27506 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27507 * +--------+-------+-------+-------+-------+--------+
27508 * 6 5 5 5 5 6
27510 * that is required, trapped and emulated by the Linux kernel. However, all
27511 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27512 * offset is odd. Therefore all valid SQ instructions can execute normally.
27513 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27514 * between SQ and RDHWR, as the Linux kernel does.
27516 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27518 int base = extract32(ctx->opcode, 21, 5);
27519 int rt = extract32(ctx->opcode, 16, 5);
27520 int offset = extract32(ctx->opcode, 0, 16);
27522 #ifdef CONFIG_USER_ONLY
27523 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27524 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27526 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27527 int rd = extract32(ctx->opcode, 11, 5);
27529 gen_rdhwr(ctx, rt, rd, 0);
27530 return;
27532 #endif
27534 gen_mmi_sq(ctx, base, rt, offset);
27537 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27539 int rs, rt, rd, sa;
27540 uint32_t op1, op2;
27541 int16_t imm;
27543 rs = (ctx->opcode >> 21) & 0x1f;
27544 rt = (ctx->opcode >> 16) & 0x1f;
27545 rd = (ctx->opcode >> 11) & 0x1f;
27546 sa = (ctx->opcode >> 6) & 0x1f;
27547 imm = sextract32(ctx->opcode, 7, 9);
27549 op1 = MASK_SPECIAL3(ctx->opcode);
27552 * EVA loads and stores overlap Loongson 2E instructions decoded by
27553 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27554 * EVA is absent.
27556 if (ctx->eva) {
27557 switch (op1) {
27558 case OPC_LWLE:
27559 case OPC_LWRE:
27560 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27561 /* fall through */
27562 case OPC_LBUE:
27563 case OPC_LHUE:
27564 case OPC_LBE:
27565 case OPC_LHE:
27566 case OPC_LLE:
27567 case OPC_LWE:
27568 check_cp0_enabled(ctx);
27569 gen_ld(ctx, op1, rt, rs, imm);
27570 return;
27571 case OPC_SWLE:
27572 case OPC_SWRE:
27573 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27574 /* fall through */
27575 case OPC_SBE:
27576 case OPC_SHE:
27577 case OPC_SWE:
27578 check_cp0_enabled(ctx);
27579 gen_st(ctx, op1, rt, rs, imm);
27580 return;
27581 case OPC_SCE:
27582 check_cp0_enabled(ctx);
27583 gen_st_cond(ctx, op1, rt, rs, imm);
27584 return;
27585 case OPC_CACHEE:
27586 check_cp0_enabled(ctx);
27587 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27588 gen_cache_operation(ctx, rt, rs, imm);
27590 /* Treat as NOP. */
27591 return;
27592 case OPC_PREFE:
27593 check_cp0_enabled(ctx);
27594 /* Treat as NOP. */
27595 return;
27599 switch (op1) {
27600 case OPC_EXT:
27601 case OPC_INS:
27602 check_insn(ctx, ISA_MIPS32R2);
27603 gen_bitops(ctx, op1, rt, rs, sa, rd);
27604 break;
27605 case OPC_BSHFL:
27606 op2 = MASK_BSHFL(ctx->opcode);
27607 switch (op2) {
27608 case OPC_ALIGN:
27609 case OPC_ALIGN_1:
27610 case OPC_ALIGN_2:
27611 case OPC_ALIGN_3:
27612 case OPC_BITSWAP:
27613 check_insn(ctx, ISA_MIPS32R6);
27614 decode_opc_special3_r6(env, ctx);
27615 break;
27616 default:
27617 check_insn(ctx, ISA_MIPS32R2);
27618 gen_bshfl(ctx, op2, rt, rd);
27619 break;
27621 break;
27622 #if defined(TARGET_MIPS64)
27623 case OPC_DEXTM:
27624 case OPC_DEXTU:
27625 case OPC_DEXT:
27626 case OPC_DINSM:
27627 case OPC_DINSU:
27628 case OPC_DINS:
27629 check_insn(ctx, ISA_MIPS64R2);
27630 check_mips_64(ctx);
27631 gen_bitops(ctx, op1, rt, rs, sa, rd);
27632 break;
27633 case OPC_DBSHFL:
27634 op2 = MASK_DBSHFL(ctx->opcode);
27635 switch (op2) {
27636 case OPC_DALIGN:
27637 case OPC_DALIGN_1:
27638 case OPC_DALIGN_2:
27639 case OPC_DALIGN_3:
27640 case OPC_DALIGN_4:
27641 case OPC_DALIGN_5:
27642 case OPC_DALIGN_6:
27643 case OPC_DALIGN_7:
27644 case OPC_DBITSWAP:
27645 check_insn(ctx, ISA_MIPS32R6);
27646 decode_opc_special3_r6(env, ctx);
27647 break;
27648 default:
27649 check_insn(ctx, ISA_MIPS64R2);
27650 check_mips_64(ctx);
27651 op2 = MASK_DBSHFL(ctx->opcode);
27652 gen_bshfl(ctx, op2, rt, rd);
27653 break;
27655 break;
27656 #endif
27657 case OPC_RDHWR:
27658 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27659 break;
27660 case OPC_FORK:
27661 check_mt(ctx);
27663 TCGv t0 = tcg_temp_new();
27664 TCGv t1 = tcg_temp_new();
27666 gen_load_gpr(t0, rt);
27667 gen_load_gpr(t1, rs);
27668 gen_helper_fork(t0, t1);
27669 tcg_temp_free(t0);
27670 tcg_temp_free(t1);
27672 break;
27673 case OPC_YIELD:
27674 check_mt(ctx);
27676 TCGv t0 = tcg_temp_new();
27678 gen_load_gpr(t0, rs);
27679 gen_helper_yield(t0, cpu_env, t0);
27680 gen_store_gpr(t0, rd);
27681 tcg_temp_free(t0);
27683 break;
27684 default:
27685 if (ctx->insn_flags & ISA_MIPS32R6) {
27686 decode_opc_special3_r6(env, ctx);
27687 } else {
27688 decode_opc_special3_legacy(env, ctx);
27693 /* MIPS SIMD Architecture (MSA) */
27694 static inline int check_msa_access(DisasContext *ctx)
27696 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
27697 !(ctx->hflags & MIPS_HFLAG_F64))) {
27698 generate_exception_end(ctx, EXCP_RI);
27699 return 0;
27702 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
27703 if (ctx->insn_flags & ASE_MSA) {
27704 generate_exception_end(ctx, EXCP_MSADIS);
27705 return 0;
27706 } else {
27707 generate_exception_end(ctx, EXCP_RI);
27708 return 0;
27711 return 1;
27714 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
27716 /* generates tcg ops to check if any element is 0 */
27717 /* Note this function only works with MSA_WRLEN = 128 */
27718 uint64_t eval_zero_or_big = 0;
27719 uint64_t eval_big = 0;
27720 TCGv_i64 t0 = tcg_temp_new_i64();
27721 TCGv_i64 t1 = tcg_temp_new_i64();
27722 switch (df) {
27723 case DF_BYTE:
27724 eval_zero_or_big = 0x0101010101010101ULL;
27725 eval_big = 0x8080808080808080ULL;
27726 break;
27727 case DF_HALF:
27728 eval_zero_or_big = 0x0001000100010001ULL;
27729 eval_big = 0x8000800080008000ULL;
27730 break;
27731 case DF_WORD:
27732 eval_zero_or_big = 0x0000000100000001ULL;
27733 eval_big = 0x8000000080000000ULL;
27734 break;
27735 case DF_DOUBLE:
27736 eval_zero_or_big = 0x0000000000000001ULL;
27737 eval_big = 0x8000000000000000ULL;
27738 break;
27740 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
27741 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
27742 tcg_gen_andi_i64(t0, t0, eval_big);
27743 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
27744 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
27745 tcg_gen_andi_i64(t1, t1, eval_big);
27746 tcg_gen_or_i64(t0, t0, t1);
27747 /* if all bits are zero then all elements are not zero */
27748 /* if some bit is non-zero then some element is zero */
27749 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
27750 tcg_gen_trunc_i64_tl(tresult, t0);
27751 tcg_temp_free_i64(t0);
27752 tcg_temp_free_i64(t1);
27755 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
27757 uint8_t df = (ctx->opcode >> 21) & 0x3;
27758 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27759 int64_t s16 = (int16_t)ctx->opcode;
27761 check_msa_access(ctx);
27763 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27764 generate_exception_end(ctx, EXCP_RI);
27765 return;
27767 switch (op1) {
27768 case OPC_BZ_V:
27769 case OPC_BNZ_V:
27771 TCGv_i64 t0 = tcg_temp_new_i64();
27772 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
27773 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
27774 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
27775 tcg_gen_trunc_i64_tl(bcond, t0);
27776 tcg_temp_free_i64(t0);
27778 break;
27779 case OPC_BZ_B:
27780 case OPC_BZ_H:
27781 case OPC_BZ_W:
27782 case OPC_BZ_D:
27783 gen_check_zero_element(bcond, df, wt);
27784 break;
27785 case OPC_BNZ_B:
27786 case OPC_BNZ_H:
27787 case OPC_BNZ_W:
27788 case OPC_BNZ_D:
27789 gen_check_zero_element(bcond, df, wt);
27790 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
27791 break;
27794 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
27796 ctx->hflags |= MIPS_HFLAG_BC;
27797 ctx->hflags |= MIPS_HFLAG_BDS32;
27800 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
27802 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
27803 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
27804 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27805 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27807 TCGv_i32 twd = tcg_const_i32(wd);
27808 TCGv_i32 tws = tcg_const_i32(ws);
27809 TCGv_i32 ti8 = tcg_const_i32(i8);
27811 switch (MASK_MSA_I8(ctx->opcode)) {
27812 case OPC_ANDI_B:
27813 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
27814 break;
27815 case OPC_ORI_B:
27816 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
27817 break;
27818 case OPC_NORI_B:
27819 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
27820 break;
27821 case OPC_XORI_B:
27822 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
27823 break;
27824 case OPC_BMNZI_B:
27825 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
27826 break;
27827 case OPC_BMZI_B:
27828 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
27829 break;
27830 case OPC_BSELI_B:
27831 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
27832 break;
27833 case OPC_SHF_B:
27834 case OPC_SHF_H:
27835 case OPC_SHF_W:
27837 uint8_t df = (ctx->opcode >> 24) & 0x3;
27838 if (df == DF_DOUBLE) {
27839 generate_exception_end(ctx, EXCP_RI);
27840 } else {
27841 TCGv_i32 tdf = tcg_const_i32(df);
27842 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
27843 tcg_temp_free_i32(tdf);
27846 break;
27847 default:
27848 MIPS_INVAL("MSA instruction");
27849 generate_exception_end(ctx, EXCP_RI);
27850 break;
27853 tcg_temp_free_i32(twd);
27854 tcg_temp_free_i32(tws);
27855 tcg_temp_free_i32(ti8);
27858 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
27860 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27861 uint8_t df = (ctx->opcode >> 21) & 0x3;
27862 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
27863 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
27864 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27865 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27867 TCGv_i32 tdf = tcg_const_i32(df);
27868 TCGv_i32 twd = tcg_const_i32(wd);
27869 TCGv_i32 tws = tcg_const_i32(ws);
27870 TCGv_i32 timm = tcg_temp_new_i32();
27871 tcg_gen_movi_i32(timm, u5);
27873 switch (MASK_MSA_I5(ctx->opcode)) {
27874 case OPC_ADDVI_df:
27875 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
27876 break;
27877 case OPC_SUBVI_df:
27878 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
27879 break;
27880 case OPC_MAXI_S_df:
27881 tcg_gen_movi_i32(timm, s5);
27882 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
27883 break;
27884 case OPC_MAXI_U_df:
27885 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
27886 break;
27887 case OPC_MINI_S_df:
27888 tcg_gen_movi_i32(timm, s5);
27889 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
27890 break;
27891 case OPC_MINI_U_df:
27892 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
27893 break;
27894 case OPC_CEQI_df:
27895 tcg_gen_movi_i32(timm, s5);
27896 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
27897 break;
27898 case OPC_CLTI_S_df:
27899 tcg_gen_movi_i32(timm, s5);
27900 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
27901 break;
27902 case OPC_CLTI_U_df:
27903 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
27904 break;
27905 case OPC_CLEI_S_df:
27906 tcg_gen_movi_i32(timm, s5);
27907 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
27908 break;
27909 case OPC_CLEI_U_df:
27910 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
27911 break;
27912 case OPC_LDI_df:
27914 int32_t s10 = sextract32(ctx->opcode, 11, 10);
27915 tcg_gen_movi_i32(timm, s10);
27916 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
27918 break;
27919 default:
27920 MIPS_INVAL("MSA instruction");
27921 generate_exception_end(ctx, EXCP_RI);
27922 break;
27925 tcg_temp_free_i32(tdf);
27926 tcg_temp_free_i32(twd);
27927 tcg_temp_free_i32(tws);
27928 tcg_temp_free_i32(timm);
27931 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
27933 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27934 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
27935 uint32_t df = 0, m = 0;
27936 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27937 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27939 TCGv_i32 tdf;
27940 TCGv_i32 tm;
27941 TCGv_i32 twd;
27942 TCGv_i32 tws;
27944 if ((dfm & 0x40) == 0x00) {
27945 m = dfm & 0x3f;
27946 df = DF_DOUBLE;
27947 } else if ((dfm & 0x60) == 0x40) {
27948 m = dfm & 0x1f;
27949 df = DF_WORD;
27950 } else if ((dfm & 0x70) == 0x60) {
27951 m = dfm & 0x0f;
27952 df = DF_HALF;
27953 } else if ((dfm & 0x78) == 0x70) {
27954 m = dfm & 0x7;
27955 df = DF_BYTE;
27956 } else {
27957 generate_exception_end(ctx, EXCP_RI);
27958 return;
27961 tdf = tcg_const_i32(df);
27962 tm = tcg_const_i32(m);
27963 twd = tcg_const_i32(wd);
27964 tws = tcg_const_i32(ws);
27966 switch (MASK_MSA_BIT(ctx->opcode)) {
27967 case OPC_SLLI_df:
27968 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
27969 break;
27970 case OPC_SRAI_df:
27971 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
27972 break;
27973 case OPC_SRLI_df:
27974 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
27975 break;
27976 case OPC_BCLRI_df:
27977 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
27978 break;
27979 case OPC_BSETI_df:
27980 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
27981 break;
27982 case OPC_BNEGI_df:
27983 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
27984 break;
27985 case OPC_BINSLI_df:
27986 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
27987 break;
27988 case OPC_BINSRI_df:
27989 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
27990 break;
27991 case OPC_SAT_S_df:
27992 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
27993 break;
27994 case OPC_SAT_U_df:
27995 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
27996 break;
27997 case OPC_SRARI_df:
27998 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
27999 break;
28000 case OPC_SRLRI_df:
28001 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28002 break;
28003 default:
28004 MIPS_INVAL("MSA instruction");
28005 generate_exception_end(ctx, EXCP_RI);
28006 break;
28009 tcg_temp_free_i32(tdf);
28010 tcg_temp_free_i32(tm);
28011 tcg_temp_free_i32(twd);
28012 tcg_temp_free_i32(tws);
28015 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28017 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28018 uint8_t df = (ctx->opcode >> 21) & 0x3;
28019 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28020 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28021 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28023 TCGv_i32 tdf = tcg_const_i32(df);
28024 TCGv_i32 twd = tcg_const_i32(wd);
28025 TCGv_i32 tws = tcg_const_i32(ws);
28026 TCGv_i32 twt = tcg_const_i32(wt);
28028 switch (MASK_MSA_3R(ctx->opcode)) {
28029 case OPC_SLL_df:
28030 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28031 break;
28032 case OPC_ADDV_df:
28033 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28034 break;
28035 case OPC_CEQ_df:
28036 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28037 break;
28038 case OPC_ADD_A_df:
28039 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28040 break;
28041 case OPC_SUBS_S_df:
28042 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28043 break;
28044 case OPC_MULV_df:
28045 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28046 break;
28047 case OPC_SLD_df:
28048 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28049 break;
28050 case OPC_VSHF_df:
28051 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28052 break;
28053 case OPC_SRA_df:
28054 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28055 break;
28056 case OPC_SUBV_df:
28057 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28058 break;
28059 case OPC_ADDS_A_df:
28060 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28061 break;
28062 case OPC_SUBS_U_df:
28063 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28064 break;
28065 case OPC_MADDV_df:
28066 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28067 break;
28068 case OPC_SPLAT_df:
28069 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28070 break;
28071 case OPC_SRAR_df:
28072 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28073 break;
28074 case OPC_SRL_df:
28075 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28076 break;
28077 case OPC_MAX_S_df:
28078 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28079 break;
28080 case OPC_CLT_S_df:
28081 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28082 break;
28083 case OPC_ADDS_S_df:
28084 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28085 break;
28086 case OPC_SUBSUS_U_df:
28087 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28088 break;
28089 case OPC_MSUBV_df:
28090 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28091 break;
28092 case OPC_PCKEV_df:
28093 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28094 break;
28095 case OPC_SRLR_df:
28096 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28097 break;
28098 case OPC_BCLR_df:
28099 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28100 break;
28101 case OPC_MAX_U_df:
28102 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28103 break;
28104 case OPC_CLT_U_df:
28105 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28106 break;
28107 case OPC_ADDS_U_df:
28108 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28109 break;
28110 case OPC_SUBSUU_S_df:
28111 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28112 break;
28113 case OPC_PCKOD_df:
28114 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28115 break;
28116 case OPC_BSET_df:
28117 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28118 break;
28119 case OPC_MIN_S_df:
28120 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28121 break;
28122 case OPC_CLE_S_df:
28123 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28124 break;
28125 case OPC_AVE_S_df:
28126 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28127 break;
28128 case OPC_ASUB_S_df:
28129 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28130 break;
28131 case OPC_DIV_S_df:
28132 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28133 break;
28134 case OPC_ILVL_df:
28135 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28136 break;
28137 case OPC_BNEG_df:
28138 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28139 break;
28140 case OPC_MIN_U_df:
28141 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28142 break;
28143 case OPC_CLE_U_df:
28144 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28145 break;
28146 case OPC_AVE_U_df:
28147 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28148 break;
28149 case OPC_ASUB_U_df:
28150 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28151 break;
28152 case OPC_DIV_U_df:
28153 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28154 break;
28155 case OPC_ILVR_df:
28156 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28157 break;
28158 case OPC_BINSL_df:
28159 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28160 break;
28161 case OPC_MAX_A_df:
28162 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28163 break;
28164 case OPC_AVER_S_df:
28165 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28166 break;
28167 case OPC_MOD_S_df:
28168 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28169 break;
28170 case OPC_ILVEV_df:
28171 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28172 break;
28173 case OPC_BINSR_df:
28174 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28175 break;
28176 case OPC_MIN_A_df:
28177 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28178 break;
28179 case OPC_AVER_U_df:
28180 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28181 break;
28182 case OPC_MOD_U_df:
28183 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28184 break;
28185 case OPC_ILVOD_df:
28186 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28187 break;
28189 case OPC_DOTP_S_df:
28190 case OPC_DOTP_U_df:
28191 case OPC_DPADD_S_df:
28192 case OPC_DPADD_U_df:
28193 case OPC_DPSUB_S_df:
28194 case OPC_HADD_S_df:
28195 case OPC_DPSUB_U_df:
28196 case OPC_HADD_U_df:
28197 case OPC_HSUB_S_df:
28198 case OPC_HSUB_U_df:
28199 if (df == DF_BYTE) {
28200 generate_exception_end(ctx, EXCP_RI);
28201 break;
28203 switch (MASK_MSA_3R(ctx->opcode)) {
28204 case OPC_DOTP_S_df:
28205 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28206 break;
28207 case OPC_DOTP_U_df:
28208 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28209 break;
28210 case OPC_DPADD_S_df:
28211 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28212 break;
28213 case OPC_DPADD_U_df:
28214 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28215 break;
28216 case OPC_DPSUB_S_df:
28217 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28218 break;
28219 case OPC_HADD_S_df:
28220 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28221 break;
28222 case OPC_DPSUB_U_df:
28223 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28224 break;
28225 case OPC_HADD_U_df:
28226 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28227 break;
28228 case OPC_HSUB_S_df:
28229 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28230 break;
28231 case OPC_HSUB_U_df:
28232 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28233 break;
28235 break;
28236 default:
28237 MIPS_INVAL("MSA instruction");
28238 generate_exception_end(ctx, EXCP_RI);
28239 break;
28241 tcg_temp_free_i32(twd);
28242 tcg_temp_free_i32(tws);
28243 tcg_temp_free_i32(twt);
28244 tcg_temp_free_i32(tdf);
28247 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28249 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28250 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28251 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28252 TCGv telm = tcg_temp_new();
28253 TCGv_i32 tsr = tcg_const_i32(source);
28254 TCGv_i32 tdt = tcg_const_i32(dest);
28256 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28257 case OPC_CTCMSA:
28258 gen_load_gpr(telm, source);
28259 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28260 break;
28261 case OPC_CFCMSA:
28262 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28263 gen_store_gpr(telm, dest);
28264 break;
28265 case OPC_MOVE_V:
28266 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28267 break;
28268 default:
28269 MIPS_INVAL("MSA instruction");
28270 generate_exception_end(ctx, EXCP_RI);
28271 break;
28274 tcg_temp_free(telm);
28275 tcg_temp_free_i32(tdt);
28276 tcg_temp_free_i32(tsr);
28279 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28280 uint32_t n)
28282 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28283 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28284 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28286 TCGv_i32 tws = tcg_const_i32(ws);
28287 TCGv_i32 twd = tcg_const_i32(wd);
28288 TCGv_i32 tn = tcg_const_i32(n);
28289 TCGv_i32 tdf = tcg_const_i32(df);
28291 switch (MASK_MSA_ELM(ctx->opcode)) {
28292 case OPC_SLDI_df:
28293 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28294 break;
28295 case OPC_SPLATI_df:
28296 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28297 break;
28298 case OPC_INSVE_df:
28299 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28300 break;
28301 case OPC_COPY_S_df:
28302 case OPC_COPY_U_df:
28303 case OPC_INSERT_df:
28304 #if !defined(TARGET_MIPS64)
28305 /* Double format valid only for MIPS64 */
28306 if (df == DF_DOUBLE) {
28307 generate_exception_end(ctx, EXCP_RI);
28308 break;
28310 #endif
28311 switch (MASK_MSA_ELM(ctx->opcode)) {
28312 case OPC_COPY_S_df:
28313 if (likely(wd != 0)) {
28314 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
28316 break;
28317 case OPC_COPY_U_df:
28318 if (likely(wd != 0)) {
28319 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
28321 break;
28322 case OPC_INSERT_df:
28323 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
28324 break;
28326 break;
28327 default:
28328 MIPS_INVAL("MSA instruction");
28329 generate_exception_end(ctx, EXCP_RI);
28331 tcg_temp_free_i32(twd);
28332 tcg_temp_free_i32(tws);
28333 tcg_temp_free_i32(tn);
28334 tcg_temp_free_i32(tdf);
28337 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28339 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28340 uint32_t df = 0, n = 0;
28342 if ((dfn & 0x30) == 0x00) {
28343 n = dfn & 0x0f;
28344 df = DF_BYTE;
28345 } else if ((dfn & 0x38) == 0x20) {
28346 n = dfn & 0x07;
28347 df = DF_HALF;
28348 } else if ((dfn & 0x3c) == 0x30) {
28349 n = dfn & 0x03;
28350 df = DF_WORD;
28351 } else if ((dfn & 0x3e) == 0x38) {
28352 n = dfn & 0x01;
28353 df = DF_DOUBLE;
28354 } else if (dfn == 0x3E) {
28355 /* CTCMSA, CFCMSA, MOVE.V */
28356 gen_msa_elm_3e(env, ctx);
28357 return;
28358 } else {
28359 generate_exception_end(ctx, EXCP_RI);
28360 return;
28363 gen_msa_elm_df(env, ctx, df, n);
28366 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28368 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28369 uint8_t df = (ctx->opcode >> 21) & 0x1;
28370 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28371 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28372 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28374 TCGv_i32 twd = tcg_const_i32(wd);
28375 TCGv_i32 tws = tcg_const_i32(ws);
28376 TCGv_i32 twt = tcg_const_i32(wt);
28377 TCGv_i32 tdf = tcg_temp_new_i32();
28379 /* adjust df value for floating-point instruction */
28380 tcg_gen_movi_i32(tdf, df + 2);
28382 switch (MASK_MSA_3RF(ctx->opcode)) {
28383 case OPC_FCAF_df:
28384 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28385 break;
28386 case OPC_FADD_df:
28387 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28388 break;
28389 case OPC_FCUN_df:
28390 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28391 break;
28392 case OPC_FSUB_df:
28393 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28394 break;
28395 case OPC_FCOR_df:
28396 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28397 break;
28398 case OPC_FCEQ_df:
28399 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28400 break;
28401 case OPC_FMUL_df:
28402 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28403 break;
28404 case OPC_FCUNE_df:
28405 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28406 break;
28407 case OPC_FCUEQ_df:
28408 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28409 break;
28410 case OPC_FDIV_df:
28411 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28412 break;
28413 case OPC_FCNE_df:
28414 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28415 break;
28416 case OPC_FCLT_df:
28417 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28418 break;
28419 case OPC_FMADD_df:
28420 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28421 break;
28422 case OPC_MUL_Q_df:
28423 tcg_gen_movi_i32(tdf, df + 1);
28424 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28425 break;
28426 case OPC_FCULT_df:
28427 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28428 break;
28429 case OPC_FMSUB_df:
28430 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28431 break;
28432 case OPC_MADD_Q_df:
28433 tcg_gen_movi_i32(tdf, df + 1);
28434 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28435 break;
28436 case OPC_FCLE_df:
28437 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28438 break;
28439 case OPC_MSUB_Q_df:
28440 tcg_gen_movi_i32(tdf, df + 1);
28441 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28442 break;
28443 case OPC_FCULE_df:
28444 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28445 break;
28446 case OPC_FEXP2_df:
28447 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28448 break;
28449 case OPC_FSAF_df:
28450 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28451 break;
28452 case OPC_FEXDO_df:
28453 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28454 break;
28455 case OPC_FSUN_df:
28456 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28457 break;
28458 case OPC_FSOR_df:
28459 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28460 break;
28461 case OPC_FSEQ_df:
28462 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28463 break;
28464 case OPC_FTQ_df:
28465 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28466 break;
28467 case OPC_FSUNE_df:
28468 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28469 break;
28470 case OPC_FSUEQ_df:
28471 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28472 break;
28473 case OPC_FSNE_df:
28474 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28475 break;
28476 case OPC_FSLT_df:
28477 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28478 break;
28479 case OPC_FMIN_df:
28480 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28481 break;
28482 case OPC_MULR_Q_df:
28483 tcg_gen_movi_i32(tdf, df + 1);
28484 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28485 break;
28486 case OPC_FSULT_df:
28487 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28488 break;
28489 case OPC_FMIN_A_df:
28490 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28491 break;
28492 case OPC_MADDR_Q_df:
28493 tcg_gen_movi_i32(tdf, df + 1);
28494 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28495 break;
28496 case OPC_FSLE_df:
28497 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28498 break;
28499 case OPC_FMAX_df:
28500 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28501 break;
28502 case OPC_MSUBR_Q_df:
28503 tcg_gen_movi_i32(tdf, df + 1);
28504 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28505 break;
28506 case OPC_FSULE_df:
28507 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28508 break;
28509 case OPC_FMAX_A_df:
28510 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28511 break;
28512 default:
28513 MIPS_INVAL("MSA instruction");
28514 generate_exception_end(ctx, EXCP_RI);
28515 break;
28518 tcg_temp_free_i32(twd);
28519 tcg_temp_free_i32(tws);
28520 tcg_temp_free_i32(twt);
28521 tcg_temp_free_i32(tdf);
28524 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28526 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28527 (op & (0x7 << 18)))
28528 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28529 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28530 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28531 uint8_t df = (ctx->opcode >> 16) & 0x3;
28532 TCGv_i32 twd = tcg_const_i32(wd);
28533 TCGv_i32 tws = tcg_const_i32(ws);
28534 TCGv_i32 twt = tcg_const_i32(wt);
28535 TCGv_i32 tdf = tcg_const_i32(df);
28537 switch (MASK_MSA_2R(ctx->opcode)) {
28538 case OPC_FILL_df:
28539 #if !defined(TARGET_MIPS64)
28540 /* Double format valid only for MIPS64 */
28541 if (df == DF_DOUBLE) {
28542 generate_exception_end(ctx, EXCP_RI);
28543 break;
28545 #endif
28546 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28547 break;
28548 case OPC_PCNT_df:
28549 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28550 break;
28551 case OPC_NLOC_df:
28552 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28553 break;
28554 case OPC_NLZC_df:
28555 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28556 break;
28557 default:
28558 MIPS_INVAL("MSA instruction");
28559 generate_exception_end(ctx, EXCP_RI);
28560 break;
28563 tcg_temp_free_i32(twd);
28564 tcg_temp_free_i32(tws);
28565 tcg_temp_free_i32(twt);
28566 tcg_temp_free_i32(tdf);
28569 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28571 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28572 (op & (0xf << 17)))
28573 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28574 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28575 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28576 uint8_t df = (ctx->opcode >> 16) & 0x1;
28577 TCGv_i32 twd = tcg_const_i32(wd);
28578 TCGv_i32 tws = tcg_const_i32(ws);
28579 TCGv_i32 twt = tcg_const_i32(wt);
28580 /* adjust df value for floating-point instruction */
28581 TCGv_i32 tdf = tcg_const_i32(df + 2);
28583 switch (MASK_MSA_2RF(ctx->opcode)) {
28584 case OPC_FCLASS_df:
28585 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28586 break;
28587 case OPC_FTRUNC_S_df:
28588 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28589 break;
28590 case OPC_FTRUNC_U_df:
28591 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28592 break;
28593 case OPC_FSQRT_df:
28594 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28595 break;
28596 case OPC_FRSQRT_df:
28597 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28598 break;
28599 case OPC_FRCP_df:
28600 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28601 break;
28602 case OPC_FRINT_df:
28603 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28604 break;
28605 case OPC_FLOG2_df:
28606 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28607 break;
28608 case OPC_FEXUPL_df:
28609 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28610 break;
28611 case OPC_FEXUPR_df:
28612 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28613 break;
28614 case OPC_FFQL_df:
28615 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28616 break;
28617 case OPC_FFQR_df:
28618 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28619 break;
28620 case OPC_FTINT_S_df:
28621 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28622 break;
28623 case OPC_FTINT_U_df:
28624 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
28625 break;
28626 case OPC_FFINT_S_df:
28627 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
28628 break;
28629 case OPC_FFINT_U_df:
28630 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
28631 break;
28634 tcg_temp_free_i32(twd);
28635 tcg_temp_free_i32(tws);
28636 tcg_temp_free_i32(twt);
28637 tcg_temp_free_i32(tdf);
28640 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
28642 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
28643 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28644 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28645 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28646 TCGv_i32 twd = tcg_const_i32(wd);
28647 TCGv_i32 tws = tcg_const_i32(ws);
28648 TCGv_i32 twt = tcg_const_i32(wt);
28650 switch (MASK_MSA_VEC(ctx->opcode)) {
28651 case OPC_AND_V:
28652 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
28653 break;
28654 case OPC_OR_V:
28655 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
28656 break;
28657 case OPC_NOR_V:
28658 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
28659 break;
28660 case OPC_XOR_V:
28661 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
28662 break;
28663 case OPC_BMNZ_V:
28664 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
28665 break;
28666 case OPC_BMZ_V:
28667 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
28668 break;
28669 case OPC_BSEL_V:
28670 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
28671 break;
28672 default:
28673 MIPS_INVAL("MSA instruction");
28674 generate_exception_end(ctx, EXCP_RI);
28675 break;
28678 tcg_temp_free_i32(twd);
28679 tcg_temp_free_i32(tws);
28680 tcg_temp_free_i32(twt);
28683 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
28685 switch (MASK_MSA_VEC(ctx->opcode)) {
28686 case OPC_AND_V:
28687 case OPC_OR_V:
28688 case OPC_NOR_V:
28689 case OPC_XOR_V:
28690 case OPC_BMNZ_V:
28691 case OPC_BMZ_V:
28692 case OPC_BSEL_V:
28693 gen_msa_vec_v(env, ctx);
28694 break;
28695 case OPC_MSA_2R:
28696 gen_msa_2r(env, ctx);
28697 break;
28698 case OPC_MSA_2RF:
28699 gen_msa_2rf(env, ctx);
28700 break;
28701 default:
28702 MIPS_INVAL("MSA instruction");
28703 generate_exception_end(ctx, EXCP_RI);
28704 break;
28708 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
28710 uint32_t opcode = ctx->opcode;
28711 check_insn(ctx, ASE_MSA);
28712 check_msa_access(ctx);
28714 switch (MASK_MSA_MINOR(opcode)) {
28715 case OPC_MSA_I8_00:
28716 case OPC_MSA_I8_01:
28717 case OPC_MSA_I8_02:
28718 gen_msa_i8(env, ctx);
28719 break;
28720 case OPC_MSA_I5_06:
28721 case OPC_MSA_I5_07:
28722 gen_msa_i5(env, ctx);
28723 break;
28724 case OPC_MSA_BIT_09:
28725 case OPC_MSA_BIT_0A:
28726 gen_msa_bit(env, ctx);
28727 break;
28728 case OPC_MSA_3R_0D:
28729 case OPC_MSA_3R_0E:
28730 case OPC_MSA_3R_0F:
28731 case OPC_MSA_3R_10:
28732 case OPC_MSA_3R_11:
28733 case OPC_MSA_3R_12:
28734 case OPC_MSA_3R_13:
28735 case OPC_MSA_3R_14:
28736 case OPC_MSA_3R_15:
28737 gen_msa_3r(env, ctx);
28738 break;
28739 case OPC_MSA_ELM:
28740 gen_msa_elm(env, ctx);
28741 break;
28742 case OPC_MSA_3RF_1A:
28743 case OPC_MSA_3RF_1B:
28744 case OPC_MSA_3RF_1C:
28745 gen_msa_3rf(env, ctx);
28746 break;
28747 case OPC_MSA_VEC:
28748 gen_msa_vec(env, ctx);
28749 break;
28750 case OPC_LD_B:
28751 case OPC_LD_H:
28752 case OPC_LD_W:
28753 case OPC_LD_D:
28754 case OPC_ST_B:
28755 case OPC_ST_H:
28756 case OPC_ST_W:
28757 case OPC_ST_D:
28759 int32_t s10 = sextract32(ctx->opcode, 16, 10);
28760 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
28761 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28762 uint8_t df = (ctx->opcode >> 0) & 0x3;
28764 TCGv_i32 twd = tcg_const_i32(wd);
28765 TCGv taddr = tcg_temp_new();
28766 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
28768 switch (MASK_MSA_MINOR(opcode)) {
28769 case OPC_LD_B:
28770 gen_helper_msa_ld_b(cpu_env, twd, taddr);
28771 break;
28772 case OPC_LD_H:
28773 gen_helper_msa_ld_h(cpu_env, twd, taddr);
28774 break;
28775 case OPC_LD_W:
28776 gen_helper_msa_ld_w(cpu_env, twd, taddr);
28777 break;
28778 case OPC_LD_D:
28779 gen_helper_msa_ld_d(cpu_env, twd, taddr);
28780 break;
28781 case OPC_ST_B:
28782 gen_helper_msa_st_b(cpu_env, twd, taddr);
28783 break;
28784 case OPC_ST_H:
28785 gen_helper_msa_st_h(cpu_env, twd, taddr);
28786 break;
28787 case OPC_ST_W:
28788 gen_helper_msa_st_w(cpu_env, twd, taddr);
28789 break;
28790 case OPC_ST_D:
28791 gen_helper_msa_st_d(cpu_env, twd, taddr);
28792 break;
28795 tcg_temp_free_i32(twd);
28796 tcg_temp_free(taddr);
28798 break;
28799 default:
28800 MIPS_INVAL("MSA instruction");
28801 generate_exception_end(ctx, EXCP_RI);
28802 break;
28807 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
28809 int32_t offset;
28810 int rs, rt, rd, sa;
28811 uint32_t op, op1;
28812 int16_t imm;
28814 /* make sure instructions are on a word boundary */
28815 if (ctx->base.pc_next & 0x3) {
28816 env->CP0_BadVAddr = ctx->base.pc_next;
28817 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
28818 return;
28821 /* Handle blikely not taken case */
28822 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
28823 TCGLabel *l1 = gen_new_label();
28825 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28826 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
28827 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
28828 gen_set_label(l1);
28831 op = MASK_OP_MAJOR(ctx->opcode);
28832 rs = (ctx->opcode >> 21) & 0x1f;
28833 rt = (ctx->opcode >> 16) & 0x1f;
28834 rd = (ctx->opcode >> 11) & 0x1f;
28835 sa = (ctx->opcode >> 6) & 0x1f;
28836 imm = (int16_t)ctx->opcode;
28837 switch (op) {
28838 case OPC_SPECIAL:
28839 decode_opc_special(env, ctx);
28840 break;
28841 case OPC_SPECIAL2:
28842 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
28843 decode_mmi(env, ctx);
28844 #if !defined(TARGET_MIPS64)
28845 } else if (ctx->insn_flags & ASE_MXU) {
28846 decode_opc_mxu(env, ctx);
28847 #endif
28848 } else {
28849 decode_opc_special2_legacy(env, ctx);
28851 break;
28852 case OPC_SPECIAL3:
28853 if (ctx->insn_flags & INSN_R5900) {
28854 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
28855 } else {
28856 decode_opc_special3(env, ctx);
28858 break;
28859 case OPC_REGIMM:
28860 op1 = MASK_REGIMM(ctx->opcode);
28861 switch (op1) {
28862 case OPC_BLTZL: /* REGIMM branches */
28863 case OPC_BGEZL:
28864 case OPC_BLTZALL:
28865 case OPC_BGEZALL:
28866 check_insn(ctx, ISA_MIPS2);
28867 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28868 /* Fallthrough */
28869 case OPC_BLTZ:
28870 case OPC_BGEZ:
28871 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28872 break;
28873 case OPC_BLTZAL:
28874 case OPC_BGEZAL:
28875 if (ctx->insn_flags & ISA_MIPS32R6) {
28876 if (rs == 0) {
28877 /* OPC_NAL, OPC_BAL */
28878 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
28879 } else {
28880 generate_exception_end(ctx, EXCP_RI);
28882 } else {
28883 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28885 break;
28886 case OPC_TGEI: /* REGIMM traps */
28887 case OPC_TGEIU:
28888 case OPC_TLTI:
28889 case OPC_TLTIU:
28890 case OPC_TEQI:
28892 case OPC_TNEI:
28893 check_insn(ctx, ISA_MIPS2);
28894 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28895 gen_trap(ctx, op1, rs, -1, imm);
28896 break;
28897 case OPC_SIGRIE:
28898 check_insn(ctx, ISA_MIPS32R6);
28899 generate_exception_end(ctx, EXCP_RI);
28900 break;
28901 case OPC_SYNCI:
28902 check_insn(ctx, ISA_MIPS32R2);
28903 /* Break the TB to be able to sync copied instructions
28904 immediately */
28905 ctx->base.is_jmp = DISAS_STOP;
28906 break;
28907 case OPC_BPOSGE32: /* MIPS DSP branch */
28908 #if defined(TARGET_MIPS64)
28909 case OPC_BPOSGE64:
28910 #endif
28911 check_dsp(ctx);
28912 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
28913 break;
28914 #if defined(TARGET_MIPS64)
28915 case OPC_DAHI:
28916 check_insn(ctx, ISA_MIPS32R6);
28917 check_mips_64(ctx);
28918 if (rs != 0) {
28919 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28921 break;
28922 case OPC_DATI:
28923 check_insn(ctx, ISA_MIPS32R6);
28924 check_mips_64(ctx);
28925 if (rs != 0) {
28926 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28928 break;
28929 #endif
28930 default: /* Invalid */
28931 MIPS_INVAL("regimm");
28932 generate_exception_end(ctx, EXCP_RI);
28933 break;
28935 break;
28936 case OPC_CP0:
28937 check_cp0_enabled(ctx);
28938 op1 = MASK_CP0(ctx->opcode);
28939 switch (op1) {
28940 case OPC_MFC0:
28941 case OPC_MTC0:
28942 case OPC_MFTR:
28943 case OPC_MTTR:
28944 case OPC_MFHC0:
28945 case OPC_MTHC0:
28946 #if defined(TARGET_MIPS64)
28947 case OPC_DMFC0:
28948 case OPC_DMTC0:
28949 #endif
28950 #ifndef CONFIG_USER_ONLY
28951 gen_cp0(env, ctx, op1, rt, rd);
28952 #endif /* !CONFIG_USER_ONLY */
28953 break;
28954 case OPC_C0:
28955 case OPC_C0_1:
28956 case OPC_C0_2:
28957 case OPC_C0_3:
28958 case OPC_C0_4:
28959 case OPC_C0_5:
28960 case OPC_C0_6:
28961 case OPC_C0_7:
28962 case OPC_C0_8:
28963 case OPC_C0_9:
28964 case OPC_C0_A:
28965 case OPC_C0_B:
28966 case OPC_C0_C:
28967 case OPC_C0_D:
28968 case OPC_C0_E:
28969 case OPC_C0_F:
28970 #ifndef CONFIG_USER_ONLY
28971 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
28972 #endif /* !CONFIG_USER_ONLY */
28973 break;
28974 case OPC_MFMC0:
28975 #ifndef CONFIG_USER_ONLY
28977 uint32_t op2;
28978 TCGv t0 = tcg_temp_new();
28980 op2 = MASK_MFMC0(ctx->opcode);
28981 switch (op2) {
28982 case OPC_DMT:
28983 check_cp0_mt(ctx);
28984 gen_helper_dmt(t0);
28985 gen_store_gpr(t0, rt);
28986 break;
28987 case OPC_EMT:
28988 check_cp0_mt(ctx);
28989 gen_helper_emt(t0);
28990 gen_store_gpr(t0, rt);
28991 break;
28992 case OPC_DVPE:
28993 check_cp0_mt(ctx);
28994 gen_helper_dvpe(t0, cpu_env);
28995 gen_store_gpr(t0, rt);
28996 break;
28997 case OPC_EVPE:
28998 check_cp0_mt(ctx);
28999 gen_helper_evpe(t0, cpu_env);
29000 gen_store_gpr(t0, rt);
29001 break;
29002 case OPC_DVP:
29003 check_insn(ctx, ISA_MIPS32R6);
29004 if (ctx->vp) {
29005 gen_helper_dvp(t0, cpu_env);
29006 gen_store_gpr(t0, rt);
29008 break;
29009 case OPC_EVP:
29010 check_insn(ctx, ISA_MIPS32R6);
29011 if (ctx->vp) {
29012 gen_helper_evp(t0, cpu_env);
29013 gen_store_gpr(t0, rt);
29015 break;
29016 case OPC_DI:
29017 check_insn(ctx, ISA_MIPS32R2);
29018 save_cpu_state(ctx, 1);
29019 gen_helper_di(t0, cpu_env);
29020 gen_store_gpr(t0, rt);
29021 /* Stop translation as we may have switched
29022 the execution mode. */
29023 ctx->base.is_jmp = DISAS_STOP;
29024 break;
29025 case OPC_EI:
29026 check_insn(ctx, ISA_MIPS32R2);
29027 save_cpu_state(ctx, 1);
29028 gen_helper_ei(t0, cpu_env);
29029 gen_store_gpr(t0, rt);
29030 /* DISAS_STOP isn't sufficient, we need to ensure we break
29031 out of translated code to check for pending interrupts */
29032 gen_save_pc(ctx->base.pc_next + 4);
29033 ctx->base.is_jmp = DISAS_EXIT;
29034 break;
29035 default: /* Invalid */
29036 MIPS_INVAL("mfmc0");
29037 generate_exception_end(ctx, EXCP_RI);
29038 break;
29040 tcg_temp_free(t0);
29042 #endif /* !CONFIG_USER_ONLY */
29043 break;
29044 case OPC_RDPGPR:
29045 check_insn(ctx, ISA_MIPS32R2);
29046 gen_load_srsgpr(rt, rd);
29047 break;
29048 case OPC_WRPGPR:
29049 check_insn(ctx, ISA_MIPS32R2);
29050 gen_store_srsgpr(rt, rd);
29051 break;
29052 default:
29053 MIPS_INVAL("cp0");
29054 generate_exception_end(ctx, EXCP_RI);
29055 break;
29057 break;
29058 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29059 if (ctx->insn_flags & ISA_MIPS32R6) {
29060 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29061 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29062 } else {
29063 /* OPC_ADDI */
29064 /* Arithmetic with immediate opcode */
29065 gen_arith_imm(ctx, op, rt, rs, imm);
29067 break;
29068 case OPC_ADDIU:
29069 gen_arith_imm(ctx, op, rt, rs, imm);
29070 break;
29071 case OPC_SLTI: /* Set on less than with immediate opcode */
29072 case OPC_SLTIU:
29073 gen_slt_imm(ctx, op, rt, rs, imm);
29074 break;
29075 case OPC_ANDI: /* Arithmetic with immediate opcode */
29076 case OPC_LUI: /* OPC_AUI */
29077 case OPC_ORI:
29078 case OPC_XORI:
29079 gen_logic_imm(ctx, op, rt, rs, imm);
29080 break;
29081 case OPC_J: /* Jump */
29082 case OPC_JAL:
29083 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29084 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29085 break;
29086 /* Branch */
29087 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29088 if (ctx->insn_flags & ISA_MIPS32R6) {
29089 if (rt == 0) {
29090 generate_exception_end(ctx, EXCP_RI);
29091 break;
29093 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29094 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29095 } else {
29096 /* OPC_BLEZL */
29097 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29099 break;
29100 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29101 if (ctx->insn_flags & ISA_MIPS32R6) {
29102 if (rt == 0) {
29103 generate_exception_end(ctx, EXCP_RI);
29104 break;
29106 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29107 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29108 } else {
29109 /* OPC_BGTZL */
29110 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29112 break;
29113 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29114 if (rt == 0) {
29115 /* OPC_BLEZ */
29116 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29117 } else {
29118 check_insn(ctx, ISA_MIPS32R6);
29119 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29120 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29122 break;
29123 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29124 if (rt == 0) {
29125 /* OPC_BGTZ */
29126 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29127 } else {
29128 check_insn(ctx, ISA_MIPS32R6);
29129 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29130 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29132 break;
29133 case OPC_BEQL:
29134 case OPC_BNEL:
29135 check_insn(ctx, ISA_MIPS2);
29136 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29137 /* Fallthrough */
29138 case OPC_BEQ:
29139 case OPC_BNE:
29140 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29141 break;
29142 case OPC_LL: /* Load and stores */
29143 check_insn(ctx, ISA_MIPS2);
29144 if (ctx->insn_flags & INSN_R5900) {
29145 check_insn_opc_user_only(ctx, INSN_R5900);
29147 /* Fallthrough */
29148 case OPC_LWL:
29149 case OPC_LWR:
29150 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29151 /* Fallthrough */
29152 case OPC_LB:
29153 case OPC_LH:
29154 case OPC_LW:
29155 case OPC_LWPC:
29156 case OPC_LBU:
29157 case OPC_LHU:
29158 gen_ld(ctx, op, rt, rs, imm);
29159 break;
29160 case OPC_SWL:
29161 case OPC_SWR:
29162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29163 /* fall through */
29164 case OPC_SB:
29165 case OPC_SH:
29166 case OPC_SW:
29167 gen_st(ctx, op, rt, rs, imm);
29168 break;
29169 case OPC_SC:
29170 check_insn(ctx, ISA_MIPS2);
29171 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29172 if (ctx->insn_flags & INSN_R5900) {
29173 check_insn_opc_user_only(ctx, INSN_R5900);
29175 gen_st_cond(ctx, op, rt, rs, imm);
29176 break;
29177 case OPC_CACHE:
29178 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29179 check_cp0_enabled(ctx);
29180 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29181 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29182 gen_cache_operation(ctx, rt, rs, imm);
29184 /* Treat as NOP. */
29185 break;
29186 case OPC_PREF:
29187 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29188 if (ctx->insn_flags & INSN_R5900) {
29189 /* Treat as NOP. */
29190 } else {
29191 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29192 /* Treat as NOP. */
29194 break;
29196 /* Floating point (COP1). */
29197 case OPC_LWC1:
29198 case OPC_LDC1:
29199 case OPC_SWC1:
29200 case OPC_SDC1:
29201 gen_cop1_ldst(ctx, op, rt, rs, imm);
29202 break;
29204 case OPC_CP1:
29205 op1 = MASK_CP1(ctx->opcode);
29207 switch (op1) {
29208 case OPC_MFHC1:
29209 case OPC_MTHC1:
29210 check_cp1_enabled(ctx);
29211 check_insn(ctx, ISA_MIPS32R2);
29212 /* fall through */
29213 case OPC_MFC1:
29214 case OPC_CFC1:
29215 case OPC_MTC1:
29216 case OPC_CTC1:
29217 check_cp1_enabled(ctx);
29218 gen_cp1(ctx, op1, rt, rd);
29219 break;
29220 #if defined(TARGET_MIPS64)
29221 case OPC_DMFC1:
29222 case OPC_DMTC1:
29223 check_cp1_enabled(ctx);
29224 check_insn(ctx, ISA_MIPS3);
29225 check_mips_64(ctx);
29226 gen_cp1(ctx, op1, rt, rd);
29227 break;
29228 #endif
29229 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29230 check_cp1_enabled(ctx);
29231 if (ctx->insn_flags & ISA_MIPS32R6) {
29232 /* OPC_BC1EQZ */
29233 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29234 rt, imm << 2, 4);
29235 } else {
29236 /* OPC_BC1ANY2 */
29237 check_cop1x(ctx);
29238 check_insn(ctx, ASE_MIPS3D);
29239 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29240 (rt >> 2) & 0x7, imm << 2);
29242 break;
29243 case OPC_BC1NEZ:
29244 check_cp1_enabled(ctx);
29245 check_insn(ctx, ISA_MIPS32R6);
29246 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29247 rt, imm << 2, 4);
29248 break;
29249 case OPC_BC1ANY4:
29250 check_cp1_enabled(ctx);
29251 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29252 check_cop1x(ctx);
29253 check_insn(ctx, ASE_MIPS3D);
29254 /* fall through */
29255 case OPC_BC1:
29256 check_cp1_enabled(ctx);
29257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29258 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29259 (rt >> 2) & 0x7, imm << 2);
29260 break;
29261 case OPC_PS_FMT:
29262 check_ps(ctx);
29263 /* fall through */
29264 case OPC_S_FMT:
29265 case OPC_D_FMT:
29266 check_cp1_enabled(ctx);
29267 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29268 (imm >> 8) & 0x7);
29269 break;
29270 case OPC_W_FMT:
29271 case OPC_L_FMT:
29273 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29274 check_cp1_enabled(ctx);
29275 if (ctx->insn_flags & ISA_MIPS32R6) {
29276 switch (r6_op) {
29277 case R6_OPC_CMP_AF_S:
29278 case R6_OPC_CMP_UN_S:
29279 case R6_OPC_CMP_EQ_S:
29280 case R6_OPC_CMP_UEQ_S:
29281 case R6_OPC_CMP_LT_S:
29282 case R6_OPC_CMP_ULT_S:
29283 case R6_OPC_CMP_LE_S:
29284 case R6_OPC_CMP_ULE_S:
29285 case R6_OPC_CMP_SAF_S:
29286 case R6_OPC_CMP_SUN_S:
29287 case R6_OPC_CMP_SEQ_S:
29288 case R6_OPC_CMP_SEUQ_S:
29289 case R6_OPC_CMP_SLT_S:
29290 case R6_OPC_CMP_SULT_S:
29291 case R6_OPC_CMP_SLE_S:
29292 case R6_OPC_CMP_SULE_S:
29293 case R6_OPC_CMP_OR_S:
29294 case R6_OPC_CMP_UNE_S:
29295 case R6_OPC_CMP_NE_S:
29296 case R6_OPC_CMP_SOR_S:
29297 case R6_OPC_CMP_SUNE_S:
29298 case R6_OPC_CMP_SNE_S:
29299 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29300 break;
29301 case R6_OPC_CMP_AF_D:
29302 case R6_OPC_CMP_UN_D:
29303 case R6_OPC_CMP_EQ_D:
29304 case R6_OPC_CMP_UEQ_D:
29305 case R6_OPC_CMP_LT_D:
29306 case R6_OPC_CMP_ULT_D:
29307 case R6_OPC_CMP_LE_D:
29308 case R6_OPC_CMP_ULE_D:
29309 case R6_OPC_CMP_SAF_D:
29310 case R6_OPC_CMP_SUN_D:
29311 case R6_OPC_CMP_SEQ_D:
29312 case R6_OPC_CMP_SEUQ_D:
29313 case R6_OPC_CMP_SLT_D:
29314 case R6_OPC_CMP_SULT_D:
29315 case R6_OPC_CMP_SLE_D:
29316 case R6_OPC_CMP_SULE_D:
29317 case R6_OPC_CMP_OR_D:
29318 case R6_OPC_CMP_UNE_D:
29319 case R6_OPC_CMP_NE_D:
29320 case R6_OPC_CMP_SOR_D:
29321 case R6_OPC_CMP_SUNE_D:
29322 case R6_OPC_CMP_SNE_D:
29323 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29324 break;
29325 default:
29326 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29327 rt, rd, sa, (imm >> 8) & 0x7);
29329 break;
29331 } else {
29332 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29333 (imm >> 8) & 0x7);
29335 break;
29337 case OPC_BZ_V:
29338 case OPC_BNZ_V:
29339 case OPC_BZ_B:
29340 case OPC_BZ_H:
29341 case OPC_BZ_W:
29342 case OPC_BZ_D:
29343 case OPC_BNZ_B:
29344 case OPC_BNZ_H:
29345 case OPC_BNZ_W:
29346 case OPC_BNZ_D:
29347 check_insn(ctx, ASE_MSA);
29348 gen_msa_branch(env, ctx, op1);
29349 break;
29350 default:
29351 MIPS_INVAL("cp1");
29352 generate_exception_end(ctx, EXCP_RI);
29353 break;
29355 break;
29357 /* Compact branches [R6] and COP2 [non-R6] */
29358 case OPC_BC: /* OPC_LWC2 */
29359 case OPC_BALC: /* OPC_SWC2 */
29360 if (ctx->insn_flags & ISA_MIPS32R6) {
29361 /* OPC_BC, OPC_BALC */
29362 gen_compute_compact_branch(ctx, op, 0, 0,
29363 sextract32(ctx->opcode << 2, 0, 28));
29364 } else {
29365 /* OPC_LWC2, OPC_SWC2 */
29366 /* COP2: Not implemented. */
29367 generate_exception_err(ctx, EXCP_CpU, 2);
29369 break;
29370 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29371 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29372 if (ctx->insn_flags & ISA_MIPS32R6) {
29373 if (rs != 0) {
29374 /* OPC_BEQZC, OPC_BNEZC */
29375 gen_compute_compact_branch(ctx, op, rs, 0,
29376 sextract32(ctx->opcode << 2, 0, 23));
29377 } else {
29378 /* OPC_JIC, OPC_JIALC */
29379 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29381 } else {
29382 /* OPC_LWC2, OPC_SWC2 */
29383 /* COP2: Not implemented. */
29384 generate_exception_err(ctx, EXCP_CpU, 2);
29386 break;
29387 case OPC_CP2:
29388 check_insn(ctx, INSN_LOONGSON2F);
29389 /* Note that these instructions use different fields. */
29390 gen_loongson_multimedia(ctx, sa, rd, rt);
29391 break;
29393 case OPC_CP3:
29394 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29395 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29396 check_cp1_enabled(ctx);
29397 op1 = MASK_CP3(ctx->opcode);
29398 switch (op1) {
29399 case OPC_LUXC1:
29400 case OPC_SUXC1:
29401 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29402 /* Fallthrough */
29403 case OPC_LWXC1:
29404 case OPC_LDXC1:
29405 case OPC_SWXC1:
29406 case OPC_SDXC1:
29407 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29408 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29409 break;
29410 case OPC_PREFX:
29411 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29412 /* Treat as NOP. */
29413 break;
29414 case OPC_ALNV_PS:
29415 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29416 /* Fallthrough */
29417 case OPC_MADD_S:
29418 case OPC_MADD_D:
29419 case OPC_MADD_PS:
29420 case OPC_MSUB_S:
29421 case OPC_MSUB_D:
29422 case OPC_MSUB_PS:
29423 case OPC_NMADD_S:
29424 case OPC_NMADD_D:
29425 case OPC_NMADD_PS:
29426 case OPC_NMSUB_S:
29427 case OPC_NMSUB_D:
29428 case OPC_NMSUB_PS:
29429 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29430 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29431 break;
29432 default:
29433 MIPS_INVAL("cp3");
29434 generate_exception_end(ctx, EXCP_RI);
29435 break;
29437 } else {
29438 generate_exception_err(ctx, EXCP_CpU, 1);
29440 break;
29442 #if defined(TARGET_MIPS64)
29443 /* MIPS64 opcodes */
29444 case OPC_LLD:
29445 if (ctx->insn_flags & INSN_R5900) {
29446 check_insn_opc_user_only(ctx, INSN_R5900);
29448 /* fall through */
29449 case OPC_LDL:
29450 case OPC_LDR:
29451 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29452 /* fall through */
29453 case OPC_LWU:
29454 case OPC_LD:
29455 check_insn(ctx, ISA_MIPS3);
29456 check_mips_64(ctx);
29457 gen_ld(ctx, op, rt, rs, imm);
29458 break;
29459 case OPC_SDL:
29460 case OPC_SDR:
29461 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29462 /* fall through */
29463 case OPC_SD:
29464 check_insn(ctx, ISA_MIPS3);
29465 check_mips_64(ctx);
29466 gen_st(ctx, op, rt, rs, imm);
29467 break;
29468 case OPC_SCD:
29469 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29470 check_insn(ctx, ISA_MIPS3);
29471 if (ctx->insn_flags & INSN_R5900) {
29472 check_insn_opc_user_only(ctx, INSN_R5900);
29474 check_mips_64(ctx);
29475 gen_st_cond(ctx, op, rt, rs, imm);
29476 break;
29477 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29478 if (ctx->insn_flags & ISA_MIPS32R6) {
29479 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29480 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29481 } else {
29482 /* OPC_DADDI */
29483 check_insn(ctx, ISA_MIPS3);
29484 check_mips_64(ctx);
29485 gen_arith_imm(ctx, op, rt, rs, imm);
29487 break;
29488 case OPC_DADDIU:
29489 check_insn(ctx, ISA_MIPS3);
29490 check_mips_64(ctx);
29491 gen_arith_imm(ctx, op, rt, rs, imm);
29492 break;
29493 #else
29494 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29495 if (ctx->insn_flags & ISA_MIPS32R6) {
29496 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29497 } else {
29498 MIPS_INVAL("major opcode");
29499 generate_exception_end(ctx, EXCP_RI);
29501 break;
29502 #endif
29503 case OPC_DAUI: /* OPC_JALX */
29504 if (ctx->insn_flags & ISA_MIPS32R6) {
29505 #if defined(TARGET_MIPS64)
29506 /* OPC_DAUI */
29507 check_mips_64(ctx);
29508 if (rs == 0) {
29509 generate_exception(ctx, EXCP_RI);
29510 } else if (rt != 0) {
29511 TCGv t0 = tcg_temp_new();
29512 gen_load_gpr(t0, rs);
29513 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29514 tcg_temp_free(t0);
29516 #else
29517 generate_exception_end(ctx, EXCP_RI);
29518 MIPS_INVAL("major opcode");
29519 #endif
29520 } else {
29521 /* OPC_JALX */
29522 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29523 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29524 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29526 break;
29527 case OPC_MSA: /* OPC_MDMX */
29528 if (ctx->insn_flags & INSN_R5900) {
29529 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29530 } else {
29531 /* MDMX: Not implemented. */
29532 gen_msa(env, ctx);
29534 break;
29535 case OPC_PCREL:
29536 check_insn(ctx, ISA_MIPS32R6);
29537 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29538 break;
29539 default: /* Invalid */
29540 MIPS_INVAL("major opcode");
29541 generate_exception_end(ctx, EXCP_RI);
29542 break;
29546 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29548 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29549 CPUMIPSState *env = cs->env_ptr;
29551 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29552 ctx->saved_pc = -1;
29553 ctx->insn_flags = env->insn_flags;
29554 ctx->CP0_Config1 = env->CP0_Config1;
29555 ctx->CP0_Config2 = env->CP0_Config2;
29556 ctx->CP0_Config3 = env->CP0_Config3;
29557 ctx->CP0_Config5 = env->CP0_Config5;
29558 ctx->btarget = 0;
29559 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29560 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29561 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29562 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29563 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29564 ctx->PAMask = env->PAMask;
29565 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29566 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29567 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29568 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29569 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29570 /* Restore delay slot state from the tb context. */
29571 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29572 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29573 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29574 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29575 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29576 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29577 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29578 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29579 restore_cpu_state(env, ctx);
29580 #ifdef CONFIG_USER_ONLY
29581 ctx->mem_idx = MIPS_HFLAG_UM;
29582 #else
29583 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29584 #endif
29585 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29586 MO_UNALN : MO_ALIGN;
29588 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29589 ctx->hflags);
29592 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29596 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29598 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29600 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29601 ctx->btarget);
29604 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29605 const CPUBreakpoint *bp)
29607 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29609 save_cpu_state(ctx, 1);
29610 ctx->base.is_jmp = DISAS_NORETURN;
29611 gen_helper_raise_exception_debug(cpu_env);
29612 /* The address covered by the breakpoint must be included in
29613 [tb->pc, tb->pc + tb->size) in order to for it to be
29614 properly cleared -- thus we increment the PC here so that
29615 the logic setting tb->size below does the right thing. */
29616 ctx->base.pc_next += 4;
29617 return true;
29620 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29622 CPUMIPSState *env = cs->env_ptr;
29623 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29624 int insn_bytes;
29625 int is_slot;
29627 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29628 if (ctx->insn_flags & ISA_NANOMIPS32) {
29629 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29630 insn_bytes = decode_nanomips_opc(env, ctx);
29631 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29632 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
29633 insn_bytes = 4;
29634 decode_opc(env, ctx);
29635 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29636 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29637 insn_bytes = decode_micromips_opc(env, ctx);
29638 } else if (ctx->insn_flags & ASE_MIPS16) {
29639 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29640 insn_bytes = decode_mips16_opc(env, ctx);
29641 } else {
29642 generate_exception_end(ctx, EXCP_RI);
29643 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29644 return;
29647 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29648 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29649 MIPS_HFLAG_FBNSLOT))) {
29650 /* force to generate branch as there is neither delay nor
29651 forbidden slot */
29652 is_slot = 1;
29654 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29655 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29656 /* Force to generate branch as microMIPS R6 doesn't restrict
29657 branches in the forbidden slot. */
29658 is_slot = 1;
29661 if (is_slot) {
29662 gen_branch(ctx, insn_bytes);
29664 ctx->base.pc_next += insn_bytes;
29666 if (ctx->base.is_jmp != DISAS_NEXT) {
29667 return;
29669 /* Execute a branch and its delay slot as a single instruction.
29670 This is what GDB expects and is consistent with what the
29671 hardware does (e.g. if a delay slot instruction faults, the
29672 reported PC is the PC of the branch). */
29673 if (ctx->base.singlestep_enabled &&
29674 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29675 ctx->base.is_jmp = DISAS_TOO_MANY;
29677 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29678 ctx->base.is_jmp = DISAS_TOO_MANY;
29682 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29684 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29686 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29687 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29688 gen_helper_raise_exception_debug(cpu_env);
29689 } else {
29690 switch (ctx->base.is_jmp) {
29691 case DISAS_STOP:
29692 gen_save_pc(ctx->base.pc_next);
29693 tcg_gen_lookup_and_goto_ptr();
29694 break;
29695 case DISAS_NEXT:
29696 case DISAS_TOO_MANY:
29697 save_cpu_state(ctx, 0);
29698 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29699 break;
29700 case DISAS_EXIT:
29701 tcg_gen_exit_tb(NULL, 0);
29702 break;
29703 case DISAS_NORETURN:
29704 break;
29705 default:
29706 g_assert_not_reached();
29711 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29713 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29714 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29717 static const TranslatorOps mips_tr_ops = {
29718 .init_disas_context = mips_tr_init_disas_context,
29719 .tb_start = mips_tr_tb_start,
29720 .insn_start = mips_tr_insn_start,
29721 .breakpoint_check = mips_tr_breakpoint_check,
29722 .translate_insn = mips_tr_translate_insn,
29723 .tb_stop = mips_tr_tb_stop,
29724 .disas_log = mips_tr_disas_log,
29727 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
29729 DisasContext ctx;
29731 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
29734 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
29735 int flags)
29737 int i;
29738 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
29740 #define printfpr(fp) \
29741 do { \
29742 if (is_fpu64) \
29743 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29744 " fd:%13g fs:%13g psu: %13g\n", \
29745 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29746 (double)(fp)->fd, \
29747 (double)(fp)->fs[FP_ENDIAN_IDX], \
29748 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29749 else { \
29750 fpr_t tmp; \
29751 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29752 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29753 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29754 " fd:%13g fs:%13g psu:%13g\n", \
29755 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29756 (double)tmp.fd, \
29757 (double)tmp.fs[FP_ENDIAN_IDX], \
29758 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29760 } while(0)
29763 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29764 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
29765 get_float_exception_flags(&env->active_fpu.fp_status));
29766 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29767 fpu_fprintf(f, "%3s: ", fregnames[i]);
29768 printfpr(&env->active_fpu.fpr[i]);
29771 #undef printfpr
29774 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
29775 int flags)
29777 MIPSCPU *cpu = MIPS_CPU(cs);
29778 CPUMIPSState *env = &cpu->env;
29779 int i;
29781 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29782 " LO=0x" TARGET_FMT_lx " ds %04x "
29783 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
29784 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29785 env->hflags, env->btarget, env->bcond);
29786 for (i = 0; i < 32; i++) {
29787 if ((i & 3) == 0)
29788 cpu_fprintf(f, "GPR%02d:", i);
29789 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
29790 if ((i & 3) == 3)
29791 cpu_fprintf(f, "\n");
29794 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
29795 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
29796 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
29797 PRIx64 "\n",
29798 env->CP0_Config0, env->CP0_Config1, env->lladdr);
29799 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
29800 env->CP0_Config2, env->CP0_Config3);
29801 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
29802 env->CP0_Config4, env->CP0_Config5);
29803 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
29804 fpu_dump_state(env, f, cpu_fprintf, flags);
29808 void mips_tcg_init(void)
29810 int i;
29812 cpu_gpr[0] = NULL;
29813 for (i = 1; i < 32; i++)
29814 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
29815 offsetof(CPUMIPSState, active_tc.gpr[i]),
29816 regnames[i]);
29818 for (i = 0; i < 32; i++) {
29819 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
29820 msa_wr_d[i * 2] =
29821 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
29822 /* The scalar floating-point unit (FPU) registers are mapped on
29823 * the MSA vector registers. */
29824 fpu_f64[i] = msa_wr_d[i * 2];
29825 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
29826 msa_wr_d[i * 2 + 1] =
29827 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
29830 cpu_PC = tcg_global_mem_new(cpu_env,
29831 offsetof(CPUMIPSState, active_tc.PC), "PC");
29832 for (i = 0; i < MIPS_DSP_ACC; i++) {
29833 cpu_HI[i] = tcg_global_mem_new(cpu_env,
29834 offsetof(CPUMIPSState, active_tc.HI[i]),
29835 regnames_HI[i]);
29836 cpu_LO[i] = tcg_global_mem_new(cpu_env,
29837 offsetof(CPUMIPSState, active_tc.LO[i]),
29838 regnames_LO[i]);
29840 cpu_dspctrl = tcg_global_mem_new(cpu_env,
29841 offsetof(CPUMIPSState, active_tc.DSPControl),
29842 "DSPControl");
29843 bcond = tcg_global_mem_new(cpu_env,
29844 offsetof(CPUMIPSState, bcond), "bcond");
29845 btarget = tcg_global_mem_new(cpu_env,
29846 offsetof(CPUMIPSState, btarget), "btarget");
29847 hflags = tcg_global_mem_new_i32(cpu_env,
29848 offsetof(CPUMIPSState, hflags), "hflags");
29850 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
29851 offsetof(CPUMIPSState, active_fpu.fcr0),
29852 "fcr0");
29853 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
29854 offsetof(CPUMIPSState, active_fpu.fcr31),
29855 "fcr31");
29857 #if defined(TARGET_MIPS64)
29858 cpu_mmr[0] = NULL;
29859 for (i = 1; i < 32; i++) {
29860 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
29861 offsetof(CPUMIPSState,
29862 active_tc.mmr[i]),
29863 regnames[i]);
29865 #endif
29867 #if !defined(TARGET_MIPS64)
29868 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29869 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29870 offsetof(CPUMIPSState,
29871 active_tc.mxu_gpr[i]),
29872 mxuregnames[i]);
29875 mxu_CR = tcg_global_mem_new(cpu_env,
29876 offsetof(CPUMIPSState, active_tc.mxu_cr),
29877 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
29878 #endif
29881 #include "translate_init.inc.c"
29883 void cpu_mips_realize_env(CPUMIPSState *env)
29885 env->exception_base = (int32_t)0xBFC00000;
29887 #ifndef CONFIG_USER_ONLY
29888 mmu_init(env, env->cpu_model);
29889 #endif
29890 fpu_init(env, env->cpu_model);
29891 mvp_init(env, env->cpu_model);
29894 bool cpu_supports_cps_smp(const char *cpu_type)
29896 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29897 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
29900 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
29902 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29903 return (mcc->cpu_def->insn_flags & isa) != 0;
29906 void cpu_set_exception_base(int vp_index, target_ulong address)
29908 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
29909 vp->env.exception_base = address;
29912 void cpu_state_reset(CPUMIPSState *env)
29914 MIPSCPU *cpu = mips_env_get_cpu(env);
29915 CPUState *cs = CPU(cpu);
29917 /* Reset registers to their default values */
29918 env->CP0_PRid = env->cpu_model->CP0_PRid;
29919 env->CP0_Config0 = env->cpu_model->CP0_Config0;
29920 #ifdef TARGET_WORDS_BIGENDIAN
29921 env->CP0_Config0 |= (1 << CP0C0_BE);
29922 #endif
29923 env->CP0_Config1 = env->cpu_model->CP0_Config1;
29924 env->CP0_Config2 = env->cpu_model->CP0_Config2;
29925 env->CP0_Config3 = env->cpu_model->CP0_Config3;
29926 env->CP0_Config4 = env->cpu_model->CP0_Config4;
29927 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
29928 env->CP0_Config5 = env->cpu_model->CP0_Config5;
29929 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
29930 env->CP0_Config6 = env->cpu_model->CP0_Config6;
29931 env->CP0_Config7 = env->cpu_model->CP0_Config7;
29932 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
29933 << env->cpu_model->CP0_LLAddr_shift;
29934 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
29935 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
29936 env->CCRes = env->cpu_model->CCRes;
29937 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
29938 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
29939 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
29940 env->current_tc = 0;
29941 env->SEGBITS = env->cpu_model->SEGBITS;
29942 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
29943 #if defined(TARGET_MIPS64)
29944 if (env->cpu_model->insn_flags & ISA_MIPS3) {
29945 env->SEGMask |= 3ULL << 62;
29947 #endif
29948 env->PABITS = env->cpu_model->PABITS;
29949 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
29950 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
29951 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
29952 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
29953 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
29954 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
29955 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
29956 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
29957 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
29958 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
29959 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
29960 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
29961 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
29962 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
29963 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
29964 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
29965 env->msair = env->cpu_model->MSAIR;
29966 env->insn_flags = env->cpu_model->insn_flags;
29968 #if defined(CONFIG_USER_ONLY)
29969 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
29970 # ifdef TARGET_MIPS64
29971 /* Enable 64-bit register mode. */
29972 env->CP0_Status |= (1 << CP0St_PX);
29973 # endif
29974 # ifdef TARGET_ABI_MIPSN64
29975 /* Enable 64-bit address mode. */
29976 env->CP0_Status |= (1 << CP0St_UX);
29977 # endif
29978 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
29979 hardware registers. */
29980 env->CP0_HWREna |= 0x0000000F;
29981 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
29982 env->CP0_Status |= (1 << CP0St_CU1);
29984 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
29985 env->CP0_Status |= (1 << CP0St_MX);
29987 # if defined(TARGET_MIPS64)
29988 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
29989 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
29990 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
29991 env->CP0_Status |= (1 << CP0St_FR);
29993 # endif
29994 #else
29995 if (env->hflags & MIPS_HFLAG_BMASK) {
29996 /* If the exception was raised from a delay slot,
29997 come back to the jump. */
29998 env->CP0_ErrorEPC = (env->active_tc.PC
29999 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
30000 } else {
30001 env->CP0_ErrorEPC = env->active_tc.PC;
30003 env->active_tc.PC = env->exception_base;
30004 env->CP0_Random = env->tlb->nb_tlb - 1;
30005 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30006 env->CP0_Wired = 0;
30007 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30008 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30009 if (mips_um_ksegs_enabled()) {
30010 env->CP0_EBase |= 0x40000000;
30011 } else {
30012 env->CP0_EBase |= (int32_t)0x80000000;
30014 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30015 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30017 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30018 0x3ff : 0xff;
30019 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30020 /* vectored interrupts not implemented, timer on int 7,
30021 no performance counters. */
30022 env->CP0_IntCtl = 0xe0000000;
30024 int i;
30026 for (i = 0; i < 7; i++) {
30027 env->CP0_WatchLo[i] = 0;
30028 env->CP0_WatchHi[i] = 0x80000000;
30030 env->CP0_WatchLo[7] = 0;
30031 env->CP0_WatchHi[7] = 0;
30033 /* Count register increments in debug mode, EJTAG version 1 */
30034 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30036 cpu_mips_store_count(env, 1);
30038 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30039 int i;
30041 /* Only TC0 on VPE 0 starts as active. */
30042 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30043 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30044 env->tcs[i].CP0_TCHalt = 1;
30046 env->active_tc.CP0_TCHalt = 1;
30047 cs->halted = 1;
30049 if (cs->cpu_index == 0) {
30050 /* VPE0 starts up enabled. */
30051 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30052 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30054 /* TC0 starts up unhalted. */
30055 cs->halted = 0;
30056 env->active_tc.CP0_TCHalt = 0;
30057 env->tcs[0].CP0_TCHalt = 0;
30058 /* With thread 0 active. */
30059 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30060 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30065 * Configure default legacy segmentation control. We use this regardless of
30066 * whether segmentation control is presented to the guest.
30068 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30069 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30070 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30071 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30072 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30073 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30074 (2 << CP0SC_C);
30075 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30076 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30077 (3 << CP0SC_C)) << 16;
30078 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30079 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30080 (1 << CP0SC_EU) | (2 << CP0SC_C);
30081 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30082 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30083 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30084 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30085 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30086 #endif
30087 if ((env->insn_flags & ISA_MIPS32R6) &&
30088 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30089 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30090 env->CP0_Status |= (1 << CP0St_FR);
30093 if (env->insn_flags & ISA_MIPS32R6) {
30094 /* PTW = 1 */
30095 env->CP0_PWSize = 0x40;
30096 /* GDI = 12 */
30097 /* UDI = 12 */
30098 /* MDI = 12 */
30099 /* PRI = 12 */
30100 /* PTEI = 2 */
30101 env->CP0_PWField = 0x0C30C302;
30102 } else {
30103 /* GDI = 0 */
30104 /* UDI = 0 */
30105 /* MDI = 0 */
30106 /* PRI = 0 */
30107 /* PTEI = 2 */
30108 env->CP0_PWField = 0x02;
30111 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30112 /* microMIPS on reset when Config3.ISA is 3 */
30113 env->hflags |= MIPS_HFLAG_M16;
30116 /* MSA */
30117 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30118 msa_reset(env);
30121 compute_hflags(env);
30122 restore_fp_status(env);
30123 restore_pamask(env);
30124 cs->exception_index = EXCP_NONE;
30126 if (semihosting_get_argc()) {
30127 /* UHI interface can be used to obtain argc and argv */
30128 env->active_tc.gpr[4] = -1;
30132 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30133 target_ulong *data)
30135 env->active_tc.PC = data[0];
30136 env->hflags &= ~MIPS_HFLAG_BMASK;
30137 env->hflags |= data[1];
30138 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30139 case MIPS_HFLAG_BR:
30140 break;
30141 case MIPS_HFLAG_BC:
30142 case MIPS_HFLAG_BL:
30143 case MIPS_HFLAG_B:
30144 env->btarget = data[2];
30145 break;