target/mips: Define R5900 MMI class, and LQ and SQ opcode constants
[qemu/ar7.git] / target / mips / translate.c
blobe205c3eaef77337c4bfc6eccc541fd29be9c4101
1 /*
2 * MIPS32 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 */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
471 /* DBSHFL opcodes */
472 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
474 enum {
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
482 /* MIPS DSP REGIMM opcodes */
483 enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
488 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489 /* MIPS DSP Load */
490 enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
497 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
527 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603 enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663 enum {
664 /* MIPS DSP Append Sub-class */
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693 enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722 enum {
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754 enum {
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787 enum {
788 /* DSP Append Sub-class */
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822 enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828 enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859 enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 /* Coprocessor 0 (rs field) */
890 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
892 enum {
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 /* MFMC0 opcodes */
923 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
925 enum {
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 /* Coprocessor 0 (with rs == C0) */
937 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
939 enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
952 /* Coprocessor 1 (rs field) */
953 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
955 /* Values for the fmt field in FP instructions */
956 enum {
957 /* 0 - 15 are reserved */
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
965 /* 23 - 31 are reserved */
968 enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1001 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1004 enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1011 enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1016 enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1021 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1023 enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1037 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1039 enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1134 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1136 enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
1152 OPC_NMADD_D = 0x31 | OPC_CP3,
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1159 /* MSA Opcodes */
1160 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161 enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1195 enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1394 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1395 * ============================================
1397 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1398 * instructions set. It is designed to fit the needs of signal, graphical and
1399 * video processing applications. MXU instruction set is used in Xburst family
1400 * of microprocessors by Ingenic.
1402 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1403 * the control register.
1405 * The notation used in MXU assembler mnemonics:
1407 * XRa, XRb, XRc, XRd - MXU registers
1408 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1409 * s12 - a subfield of an instruction code
1410 * strd2 - a subfield of an instruction code
1411 * eptn2 - a subfield of an instruction code
1412 * eptn3 - a subfield of an instruction code
1413 * optn2 - a subfield of an instruction code
1414 * optn3 - a subfield of an instruction code
1415 * sft4 - a subfield of an instruction code
1417 * Load/Store instructions Multiplication instructions
1418 * ----------------------- ---------------------------
1420 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1421 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1422 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1423 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1424 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1425 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1426 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1427 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1428 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1429 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1430 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1431 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1432 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1433 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1434 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1435 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1436 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1437 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1438 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1439 * S16SDI XRa, Rb, s10, eptn2
1440 * S8LDD XRa, Rb, s8, eptn3
1441 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1442 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1443 * S8SDI XRa, Rb, s8, eptn3
1444 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1445 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1446 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1447 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1448 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1449 * S32CPS XRa, XRb, XRc
1450 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1451 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1452 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1453 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1454 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1455 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1456 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1457 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1458 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1459 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1460 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1461 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1462 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1463 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1464 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1465 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1466 * Q8SLT XRa, XRb, XRc
1467 * Q8SLTU XRa, XRb, XRc
1468 * Q8MOVZ XRa, XRb, XRc Shift instructions
1469 * Q8MOVN XRa, XRb, XRc ------------------
1471 * D32SLL XRa, XRb, XRc, XRd, sft4
1472 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1473 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1474 * D32SARL XRa, XRb, XRc, sft4
1475 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1476 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1477 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1478 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1479 * Q16SLL XRa, XRb, XRc, XRd, sft4
1480 * Q16SLR XRa, XRb, XRc, XRd, sft4
1481 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1482 * ------------------------- Q16SLLV XRa, XRb, Rb
1483 * Q16SLRV XRa, XRb, Rb
1484 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1485 * S32ALN XRa, XRb, XRc, Rb
1486 * S32ALNI XRa, XRb, XRc, s3
1487 * S32LUI XRa, s8, optn3 Move instructions
1488 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1489 * S32EXTRV XRa, XRb, Rs, Rt
1490 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1491 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1494 * bits
1495 * 05..00
1497 * ┌─ 000000 ─ OPC_MXU_S32MADD
1498 * ├─ 000001 ─ OPC_MXU_S32MADDU
1499 * ├─ 000010 ─ <not assigned>
1500 * │ 20..18
1501 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1502 * │ ├─ 001 ─ OPC_MXU_S32MIN
1503 * │ ├─ 010 ─ OPC_MXU_D16MAX
1504 * │ ├─ 011 ─ OPC_MXU_D16MIN
1505 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1506 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1507 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1508 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1509 * ├─ 000100 ─ OPC_MXU_S32MSUB
1510 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1511 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1512 * │ ├─ 001 ─ OPC_MXU_D16SLT
1513 * │ ├─ 010 ─ OPC_MXU_D16AVG
1514 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1515 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1516 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1517 * │ └─ 111 ─ OPC_MXU_Q8ADD
1518 * │
1519 * │ 20..18
1520 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1521 * │ ├─ 010 ─ OPC_MXU_D16CPS
1522 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1523 * │ └─ 110 ─ OPC_MXU_Q16SAT
1524 * ├─ 001000 ─ OPC_MXU_D16MUL
1525 * │ 25..24
1526 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1527 * │ └─ 01 ─ OPC_MXU_D16MULE
1528 * ├─ 001010 ─ OPC_MXU_D16MAC
1529 * ├─ 001011 ─ OPC_MXU_D16MACF
1530 * ├─ 001100 ─ OPC_MXU_D16MADL
1531 * │ 25..24
1532 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1533 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1534 * ├─ 001110 ─ OPC_MXU_Q16ADD
1535 * ├─ 001111 ─ OPC_MXU_D16MACE
1536 * │ 23
1537 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1538 * │ └─ 1 ─ OPC_MXU_S32LDDR
1539 * │
1540 * │ 23
1541 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1542 * │ └─ 1 ─ OPC_MXU_S32STDR
1543 * │
1544 * │ 13..10
1545 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1546 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1547 * │
1548 * │ 13..10
1549 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1550 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1551 * │
1552 * │ 23
1553 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1554 * │ └─ 1 ─ OPC_MXU_S32LDIR
1555 * │
1556 * │ 23
1557 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1558 * │ └─ 1 ─ OPC_MXU_S32SDIR
1559 * │
1560 * │ 13..10
1561 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1562 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1563 * │
1564 * │ 13..10
1565 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1566 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1567 * ├─ 011000 ─ OPC_MXU_D32ADD
1568 * │ 23..22
1569 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1570 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1571 * │ └─ 10 ─ OPC_MXU_D32ASUM
1572 * ├─ 011010 ─ <not assigned>
1573 * │ 23..22
1574 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1575 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1576 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1577 * │
1578 * │ 23..22
1579 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1580 * │ ├─ 01 ─ OPC_MXU_D8SUM
1581 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1582 * ├─ 011110 ─ <not assigned>
1583 * ├─ 011111 ─ <not assigned>
1584 * ├─ 100000 ─ <not assigned>
1585 * ├─ 100001 ─ <not assigned>
1586 * ├─ 100010 ─ OPC_MXU_S8LDD
1587 * ├─ 100011 ─ OPC_MXU_S8STD
1588 * ├─ 100100 ─ OPC_MXU_S8LDI
1589 * ├─ 100101 ─ OPC_MXU_S8SDI
1590 * │ 15..14
1591 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1592 * │ ├─ 00 ─ OPC_MXU_S32MULU
1593 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1594 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1595 * │
1596 * │ 20..18
1597 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1598 * │ ├─ 001 ─ OPC_MXU_S32ALN
1599 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1600 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1601 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1602 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1603 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1604 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1605 * ├─ 101000 ─ <not assigned>
1606 * ├─ 101001 ─ <not assigned>
1607 * ├─ 101010 ─ <not assigned>
1608 * ├─ 101011 ─ <not assigned>
1609 * ├─ 101100 ─ <not assigned>
1610 * ├─ 101101 ─ <not assigned>
1611 * ├─ 101110 ─ OPC_MXU_S32M2I
1612 * ├─ 101111 ─ OPC_MXU_S32I2M
1613 * ├─ 110000 ─ OPC_MXU_D32SLL
1614 * ├─ 110001 ─ OPC_MXU_D32SLR
1615 * ├─ 110010 ─ OPC_MXU_D32SARL
1616 * ├─ 110011 ─ OPC_MXU_D32SAR
1617 * ├─ 110100 ─ OPC_MXU_Q16SLL
1618 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1619 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1620 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1621 * │ ├─ 010 ─ OPC_MXU_D32SARV
1622 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1623 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1624 * │ └─ 101 ─ OPC_MXU_Q16SARV
1625 * ├─ 110111 ─ OPC_MXU_Q16SAR
1626 * │ 23..22
1627 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1628 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1629 * │
1630 * │ 20..18
1631 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1632 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1633 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1634 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1635 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1636 * │ └─ 101 ─ OPC_MXU_S32MOV
1637 * │
1638 * │ 23..22
1639 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1640 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1641 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1642 * ├─ 111100 ─ OPC_MXU_Q8MADL
1643 * ├─ 111101 ─ OPC_MXU_S32SFL
1644 * ├─ 111110 ─ OPC_MXU_Q8SAD
1645 * └─ 111111 ─ <not assigned>
1648 * Compiled after:
1650 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1651 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1654 enum {
1655 OPC_MXU_S32MADD = 0x00,
1656 OPC_MXU_S32MADDU = 0x01,
1657 /* not assigned 0x02 */
1658 OPC_MXU__POOL00 = 0x03,
1659 OPC_MXU_S32MSUB = 0x04,
1660 OPC_MXU_S32MSUBU = 0x05,
1661 OPC_MXU__POOL01 = 0x06,
1662 OPC_MXU__POOL02 = 0x07,
1663 OPC_MXU_D16MUL = 0x08,
1664 OPC_MXU__POOL03 = 0x09,
1665 OPC_MXU_D16MAC = 0x0A,
1666 OPC_MXU_D16MACF = 0x0B,
1667 OPC_MXU_D16MADL = 0x0C,
1668 OPC_MXU__POOL04 = 0x0D,
1669 OPC_MXU_Q16ADD = 0x0E,
1670 OPC_MXU_D16MACE = 0x0F,
1671 OPC_MXU__POOL05 = 0x10,
1672 OPC_MXU__POOL06 = 0x11,
1673 OPC_MXU__POOL07 = 0x12,
1674 OPC_MXU__POOL08 = 0x13,
1675 OPC_MXU__POOL09 = 0x14,
1676 OPC_MXU__POOL10 = 0x15,
1677 OPC_MXU__POOL11 = 0x16,
1678 OPC_MXU__POOL12 = 0x17,
1679 OPC_MXU_D32ADD = 0x18,
1680 OPC_MXU__POOL13 = 0x19,
1681 /* not assigned 0x1A */
1682 OPC_MXU__POOL14 = 0x1B,
1683 OPC_MXU__POOL15 = 0x1C,
1684 OPC_MXU_Q8ACCE = 0x1D,
1685 /* not assigned 0x1E */
1686 /* not assigned 0x1F */
1687 /* not assigned 0x20 */
1688 /* not assigned 0x21 */
1689 OPC_MXU_S8LDD = 0x22,
1690 OPC_MXU_S8STD = 0x23,
1691 OPC_MXU_S8LDI = 0x24,
1692 OPC_MXU_S8SDI = 0x25,
1693 OPC_MXU__POOL16 = 0x26,
1694 OPC_MXU__POOL17 = 0x27,
1695 OPC_MXU_LXB = 0x28,
1696 /* not assigned 0x29 */
1697 OPC_MXU_S16LDD = 0x2A,
1698 OPC_MXU_S16STD = 0x2B,
1699 OPC_MXU_S16LDI = 0x2C,
1700 OPC_MXU_S16SDI = 0x2D,
1701 OPC_MXU_S32M2I = 0x2E,
1702 OPC_MXU_S32I2M = 0x2F,
1703 OPC_MXU_D32SLL = 0x30,
1704 OPC_MXU_D32SLR = 0x31,
1705 OPC_MXU_D32SARL = 0x32,
1706 OPC_MXU_D32SAR = 0x33,
1707 OPC_MXU_Q16SLL = 0x34,
1708 OPC_MXU_Q16SLR = 0x35,
1709 OPC_MXU__POOL18 = 0x36,
1710 OPC_MXU_Q16SAR = 0x37,
1711 OPC_MXU__POOL19 = 0x38,
1712 OPC_MXU__POOL20 = 0x39,
1713 OPC_MXU__POOL21 = 0x3A,
1714 OPC_MXU_Q16SCOP = 0x3B,
1715 OPC_MXU_Q8MADL = 0x3C,
1716 OPC_MXU_S32SFL = 0x3D,
1717 OPC_MXU_Q8SAD = 0x3E,
1718 /* not assigned 0x3F */
1723 * MXU pool 00
1725 enum {
1726 OPC_MXU_S32MAX = 0x00,
1727 OPC_MXU_S32MIN = 0x01,
1728 OPC_MXU_D16MAX = 0x02,
1729 OPC_MXU_D16MIN = 0x03,
1730 OPC_MXU_Q8MAX = 0x04,
1731 OPC_MXU_Q8MIN = 0x05,
1732 OPC_MXU_Q8SLT = 0x06,
1733 OPC_MXU_Q8SLTU = 0x07,
1737 * MXU pool 01
1739 enum {
1740 OPC_MXU_S32SLT = 0x00,
1741 OPC_MXU_D16SLT = 0x01,
1742 OPC_MXU_D16AVG = 0x02,
1743 OPC_MXU_D16AVGR = 0x03,
1744 OPC_MXU_Q8AVG = 0x04,
1745 OPC_MXU_Q8AVGR = 0x05,
1746 OPC_MXU_Q8ADD = 0x07,
1750 * MXU pool 02
1752 enum {
1753 OPC_MXU_S32CPS = 0x00,
1754 OPC_MXU_D16CPS = 0x02,
1755 OPC_MXU_Q8ABD = 0x04,
1756 OPC_MXU_Q16SAT = 0x06,
1760 * MXU pool 03
1762 enum {
1763 OPC_MXU_D16MULF = 0x00,
1764 OPC_MXU_D16MULE = 0x01,
1768 * MXU pool 04
1770 enum {
1771 OPC_MXU_S16MAD = 0x00,
1772 OPC_MXU_S16MAD_1 = 0x01,
1776 * MXU pool 05
1778 enum {
1779 OPC_MXU_S32LDD = 0x00,
1780 OPC_MXU_S32LDDR = 0x01,
1784 * MXU pool 06
1786 enum {
1787 OPC_MXU_S32STD = 0x00,
1788 OPC_MXU_S32STDR = 0x01,
1792 * MXU pool 07
1794 enum {
1795 OPC_MXU_S32LDDV = 0x00,
1796 OPC_MXU_S32LDDVR = 0x01,
1800 * MXU pool 08
1802 enum {
1803 OPC_MXU_S32STDV = 0x00,
1804 OPC_MXU_S32STDVR = 0x01,
1808 * MXU pool 09
1810 enum {
1811 OPC_MXU_S32LDI = 0x00,
1812 OPC_MXU_S32LDIR = 0x01,
1816 * MXU pool 10
1818 enum {
1819 OPC_MXU_S32SDI = 0x00,
1820 OPC_MXU_S32SDIR = 0x01,
1824 * MXU pool 11
1826 enum {
1827 OPC_MXU_S32LDIV = 0x00,
1828 OPC_MXU_S32LDIVR = 0x01,
1832 * MXU pool 12
1834 enum {
1835 OPC_MXU_S32SDIV = 0x00,
1836 OPC_MXU_S32SDIVR = 0x01,
1840 * MXU pool 13
1842 enum {
1843 OPC_MXU_D32ACC = 0x00,
1844 OPC_MXU_D32ACCM = 0x01,
1845 OPC_MXU_D32ASUM = 0x02,
1849 * MXU pool 14
1851 enum {
1852 OPC_MXU_Q16ACC = 0x00,
1853 OPC_MXU_Q16ACCM = 0x01,
1854 OPC_MXU_Q16ASUM = 0x02,
1858 * MXU pool 15
1860 enum {
1861 OPC_MXU_Q8ADDE = 0x00,
1862 OPC_MXU_D8SUM = 0x01,
1863 OPC_MXU_D8SUMC = 0x02,
1867 * MXU pool 16
1869 enum {
1870 OPC_MXU_S32MUL = 0x00,
1871 OPC_MXU_S32MULU = 0x01,
1872 OPC_MXU_S32EXTR = 0x02,
1873 OPC_MXU_S32EXTRV = 0x03,
1877 * MXU pool 17
1879 enum {
1880 OPC_MXU_D32SARW = 0x00,
1881 OPC_MXU_S32ALN = 0x01,
1882 OPC_MXU_S32ALNI = 0x02,
1883 OPC_MXU_S32NOR = 0x03,
1884 OPC_MXU_S32AND = 0x04,
1885 OPC_MXU_S32OR = 0x05,
1886 OPC_MXU_S32XOR = 0x06,
1887 OPC_MXU_S32LUI = 0x07,
1891 * MXU pool 18
1893 enum {
1894 OPC_MXU_D32SLLV = 0x00,
1895 OPC_MXU_D32SLRV = 0x01,
1896 OPC_MXU_D32SARV = 0x03,
1897 OPC_MXU_Q16SLLV = 0x04,
1898 OPC_MXU_Q16SLRV = 0x05,
1899 OPC_MXU_Q16SARV = 0x07,
1903 * MXU pool 19
1905 enum {
1906 OPC_MXU_Q8MUL = 0x00,
1907 OPC_MXU_Q8MULSU = 0x01,
1911 * MXU pool 20
1913 enum {
1914 OPC_MXU_Q8MOVZ = 0x00,
1915 OPC_MXU_Q8MOVN = 0x01,
1916 OPC_MXU_D16MOVZ = 0x02,
1917 OPC_MXU_D16MOVN = 0x03,
1918 OPC_MXU_S32MOVZ = 0x04,
1919 OPC_MXU_S32MOVN = 0x05,
1923 * MXU pool 21
1925 enum {
1926 OPC_MXU_Q8MAC = 0x00,
1927 OPC_MXU_Q8MACSU = 0x01,
1931 * Overview of the TX79-specific instruction set
1932 * =============================================
1934 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1935 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1936 * instructions and certain multimedia instructions (MMIs). These MMIs
1937 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1938 * or sixteen 8-bit paths.
1940 * Reference:
1942 * The Toshiba TX System RISC TX79 Core Architecture manual,
1943 * https://wiki.qemu.org/File:C790.pdf
1945 * Three-Operand Multiply and Multiply-Add (4 instructions)
1946 * --------------------------------------------------------
1947 * MADD [rd,] rs, rt Multiply/Add
1948 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1949 * MULT [rd,] rs, rt Multiply (3-operand)
1950 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1952 * Multiply Instructions for Pipeline 1 (10 instructions)
1953 * ------------------------------------------------------
1954 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1955 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1956 * DIV1 rs, rt Divide Pipeline 1
1957 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1958 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1959 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1960 * MFHI1 rd Move From HI1 Register
1961 * MFLO1 rd Move From LO1 Register
1962 * MTHI1 rs Move To HI1 Register
1963 * MTLO1 rs Move To LO1 Register
1965 * Arithmetic (19 instructions)
1966 * ----------------------------
1967 * PADDB rd, rs, rt Parallel Add Byte
1968 * PSUBB rd, rs, rt Parallel Subtract Byte
1969 * PADDH rd, rs, rt Parallel Add Halfword
1970 * PSUBH rd, rs, rt Parallel Subtract Halfword
1971 * PADDW rd, rs, rt Parallel Add Word
1972 * PSUBW rd, rs, rt Parallel Subtract Word
1973 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1974 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1975 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1976 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1977 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1978 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1979 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1980 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1981 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1982 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1983 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1984 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1985 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1987 * Min/Max (4 instructions)
1988 * ------------------------
1989 * PMAXH rd, rs, rt Parallel Maximum Halfword
1990 * PMINH rd, rs, rt Parallel Minimum Halfword
1991 * PMAXW rd, rs, rt Parallel Maximum Word
1992 * PMINW rd, rs, rt Parallel Minimum Word
1994 * Absolute (2 instructions)
1995 * -------------------------
1996 * PABSH rd, rt Parallel Absolute Halfword
1997 * PABSW rd, rt Parallel Absolute Word
1999 * Logical (4 instructions)
2000 * ------------------------
2001 * PAND rd, rs, rt Parallel AND
2002 * POR rd, rs, rt Parallel OR
2003 * PXOR rd, rs, rt Parallel XOR
2004 * PNOR rd, rs, rt Parallel NOR
2006 * Shift (9 instructions)
2007 * ----------------------
2008 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2009 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2010 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2011 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2012 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2013 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2014 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2015 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2016 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2018 * Compare (6 instructions)
2019 * ------------------------
2020 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2021 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2022 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2023 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2024 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2025 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2027 * LZC (1 instruction)
2028 * -------------------
2029 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2031 * Quadword Load and Store (2 instructions)
2032 * ----------------------------------------
2033 * LQ rt, offset(base) Load Quadword
2034 * SQ rt, offset(base) Store Quadword
2036 * Multiply and Divide (19 instructions)
2037 * -------------------------------------
2038 * PMULTW rd, rs, rt Parallel Multiply Word
2039 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2040 * PDIVW rs, rt Parallel Divide Word
2041 * PDIVUW rs, rt Parallel Divide Unsigned Word
2042 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2043 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2044 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2045 * PMULTH rd, rs, rt Parallel Multiply Halfword
2046 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2047 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2048 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2049 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2050 * PDIVBW rs, rt Parallel Divide Broadcast Word
2051 * PMFHI rd Parallel Move From HI Register
2052 * PMFLO rd Parallel Move From LO Register
2053 * PMTHI rs Parallel Move To HI Register
2054 * PMTLO rs Parallel Move To LO Register
2055 * PMFHL rd Parallel Move From HI/LO Register
2056 * PMTHL rs Parallel Move To HI/LO Register
2058 * Pack/Extend (11 instructions)
2059 * -----------------------------
2060 * PPAC5 rd, rt Parallel Pack to 5 bits
2061 * PPACB rd, rs, rt Parallel Pack to Byte
2062 * PPACH rd, rs, rt Parallel Pack to Halfword
2063 * PPACW rd, rs, rt Parallel Pack to Word
2064 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2065 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2066 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2067 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2068 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2069 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2070 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2072 * Others (16 instructions)
2073 * ------------------------
2074 * PCPYH rd, rt Parallel Copy Halfword
2075 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2076 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2077 * PREVH rd, rt Parallel Reverse Halfword
2078 * PINTH rd, rs, rt Parallel Interleave Halfword
2079 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2080 * PEXEH rd, rt Parallel Exchange Even Halfword
2081 * PEXCH rd, rt Parallel Exchange Center Halfword
2082 * PEXEW rd, rt Parallel Exchange Even Word
2083 * PEXCW rd, rt Parallel Exchange Center Word
2084 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2085 * MFSA rd Move from Shift Amount Register
2086 * MTSA rs Move to Shift Amount Register
2087 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2088 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2089 * PROT3W rd, rt Parallel Rotate 3 Words
2091 * The TX79-specific Multimedia Instruction encodings
2092 * ==================================================
2094 * TX79 Multimedia Instruction encoding table keys:
2096 * * This code is reserved for future use. An attempt to execute it
2097 * causes a Reserved Instruction exception.
2098 * % This code indicates an instruction class. The instruction word
2099 * must be further decoded by examining additional tables that show
2100 * the values for other instruction fields.
2101 * # This code is reserved for the unsupported instructions DMULT,
2102 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2103 * to execute it causes a Reserved Instruction exception.
2105 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2107 * 31 26 0
2108 * +--------+----------------------------------------+
2109 * | opcode | |
2110 * +--------+----------------------------------------+
2112 * opcode bits 28..26
2113 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2114 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2115 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2116 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2117 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2118 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2119 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2120 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2121 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2122 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2123 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2126 enum {
2127 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2128 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2129 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2132 /* global register indices */
2133 static TCGv cpu_gpr[32], cpu_PC;
2134 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2135 static TCGv cpu_dspctrl, btarget, bcond;
2136 static TCGv_i32 hflags;
2137 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2138 static TCGv_i64 fpu_f64[32];
2139 static TCGv_i64 msa_wr_d[64];
2141 #include "exec/gen-icount.h"
2143 #define gen_helper_0e0i(name, arg) do { \
2144 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2145 gen_helper_##name(cpu_env, helper_tmp); \
2146 tcg_temp_free_i32(helper_tmp); \
2147 } while(0)
2149 #define gen_helper_0e1i(name, arg1, arg2) do { \
2150 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2151 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2152 tcg_temp_free_i32(helper_tmp); \
2153 } while(0)
2155 #define gen_helper_1e0i(name, ret, arg1) do { \
2156 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2157 gen_helper_##name(ret, cpu_env, helper_tmp); \
2158 tcg_temp_free_i32(helper_tmp); \
2159 } while(0)
2161 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2162 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2163 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2164 tcg_temp_free_i32(helper_tmp); \
2165 } while(0)
2167 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2168 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2169 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2170 tcg_temp_free_i32(helper_tmp); \
2171 } while(0)
2173 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2174 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2175 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2176 tcg_temp_free_i32(helper_tmp); \
2177 } while(0)
2179 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2180 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2181 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2182 tcg_temp_free_i32(helper_tmp); \
2183 } while(0)
2185 typedef struct DisasContext {
2186 DisasContextBase base;
2187 target_ulong saved_pc;
2188 target_ulong page_start;
2189 uint32_t opcode;
2190 uint64_t insn_flags;
2191 int32_t CP0_Config1;
2192 int32_t CP0_Config2;
2193 int32_t CP0_Config3;
2194 int32_t CP0_Config5;
2195 /* Routine used to access memory */
2196 int mem_idx;
2197 TCGMemOp default_tcg_memop_mask;
2198 uint32_t hflags, saved_hflags;
2199 target_ulong btarget;
2200 bool ulri;
2201 int kscrexist;
2202 bool rxi;
2203 int ie;
2204 bool bi;
2205 bool bp;
2206 uint64_t PAMask;
2207 bool mvh;
2208 bool eva;
2209 bool sc;
2210 int CP0_LLAddr_shift;
2211 bool ps;
2212 bool vp;
2213 bool cmgcr;
2214 bool mrp;
2215 bool nan2008;
2216 bool abs2008;
2217 } DisasContext;
2219 #define DISAS_STOP DISAS_TARGET_0
2220 #define DISAS_EXIT DISAS_TARGET_1
2222 static const char * const regnames[] = {
2223 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2224 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2225 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2226 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2229 static const char * const regnames_HI[] = {
2230 "HI0", "HI1", "HI2", "HI3",
2233 static const char * const regnames_LO[] = {
2234 "LO0", "LO1", "LO2", "LO3",
2237 static const char * const fregnames[] = {
2238 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2239 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2240 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2241 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2244 static const char * const msaregnames[] = {
2245 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2246 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2247 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2248 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2249 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2250 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2251 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2252 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2253 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2254 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2255 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2256 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2257 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2258 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2259 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2260 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2263 #define LOG_DISAS(...) \
2264 do { \
2265 if (MIPS_DEBUG_DISAS) { \
2266 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2268 } while (0)
2270 #define MIPS_INVAL(op) \
2271 do { \
2272 if (MIPS_DEBUG_DISAS) { \
2273 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2274 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2275 ctx->base.pc_next, ctx->opcode, op, \
2276 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2277 ((ctx->opcode >> 16) & 0x1F)); \
2279 } while (0)
2281 /* General purpose registers moves. */
2282 static inline void gen_load_gpr (TCGv t, int reg)
2284 if (reg == 0)
2285 tcg_gen_movi_tl(t, 0);
2286 else
2287 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2290 static inline void gen_store_gpr (TCGv t, int reg)
2292 if (reg != 0)
2293 tcg_gen_mov_tl(cpu_gpr[reg], t);
2296 /* Moves to/from shadow registers. */
2297 static inline void gen_load_srsgpr (int from, int to)
2299 TCGv t0 = tcg_temp_new();
2301 if (from == 0)
2302 tcg_gen_movi_tl(t0, 0);
2303 else {
2304 TCGv_i32 t2 = tcg_temp_new_i32();
2305 TCGv_ptr addr = tcg_temp_new_ptr();
2307 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2308 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2309 tcg_gen_andi_i32(t2, t2, 0xf);
2310 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2311 tcg_gen_ext_i32_ptr(addr, t2);
2312 tcg_gen_add_ptr(addr, cpu_env, addr);
2314 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2315 tcg_temp_free_ptr(addr);
2316 tcg_temp_free_i32(t2);
2318 gen_store_gpr(t0, to);
2319 tcg_temp_free(t0);
2322 static inline void gen_store_srsgpr (int from, int to)
2324 if (to != 0) {
2325 TCGv t0 = tcg_temp_new();
2326 TCGv_i32 t2 = tcg_temp_new_i32();
2327 TCGv_ptr addr = tcg_temp_new_ptr();
2329 gen_load_gpr(t0, from);
2330 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2331 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2332 tcg_gen_andi_i32(t2, t2, 0xf);
2333 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2334 tcg_gen_ext_i32_ptr(addr, t2);
2335 tcg_gen_add_ptr(addr, cpu_env, addr);
2337 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2338 tcg_temp_free_ptr(addr);
2339 tcg_temp_free_i32(t2);
2340 tcg_temp_free(t0);
2344 /* Tests */
2345 static inline void gen_save_pc(target_ulong pc)
2347 tcg_gen_movi_tl(cpu_PC, pc);
2350 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2352 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2353 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2354 gen_save_pc(ctx->base.pc_next);
2355 ctx->saved_pc = ctx->base.pc_next;
2357 if (ctx->hflags != ctx->saved_hflags) {
2358 tcg_gen_movi_i32(hflags, ctx->hflags);
2359 ctx->saved_hflags = ctx->hflags;
2360 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2361 case MIPS_HFLAG_BR:
2362 break;
2363 case MIPS_HFLAG_BC:
2364 case MIPS_HFLAG_BL:
2365 case MIPS_HFLAG_B:
2366 tcg_gen_movi_tl(btarget, ctx->btarget);
2367 break;
2372 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2374 ctx->saved_hflags = ctx->hflags;
2375 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2376 case MIPS_HFLAG_BR:
2377 break;
2378 case MIPS_HFLAG_BC:
2379 case MIPS_HFLAG_BL:
2380 case MIPS_HFLAG_B:
2381 ctx->btarget = env->btarget;
2382 break;
2386 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2388 TCGv_i32 texcp = tcg_const_i32(excp);
2389 TCGv_i32 terr = tcg_const_i32(err);
2390 save_cpu_state(ctx, 1);
2391 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2392 tcg_temp_free_i32(terr);
2393 tcg_temp_free_i32(texcp);
2394 ctx->base.is_jmp = DISAS_NORETURN;
2397 static inline void generate_exception(DisasContext *ctx, int excp)
2399 gen_helper_0e0i(raise_exception, excp);
2402 static inline void generate_exception_end(DisasContext *ctx, int excp)
2404 generate_exception_err(ctx, excp, 0);
2407 /* Floating point register moves. */
2408 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2410 if (ctx->hflags & MIPS_HFLAG_FRE) {
2411 generate_exception(ctx, EXCP_RI);
2413 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2416 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2418 TCGv_i64 t64;
2419 if (ctx->hflags & MIPS_HFLAG_FRE) {
2420 generate_exception(ctx, EXCP_RI);
2422 t64 = tcg_temp_new_i64();
2423 tcg_gen_extu_i32_i64(t64, t);
2424 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2425 tcg_temp_free_i64(t64);
2428 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2430 if (ctx->hflags & MIPS_HFLAG_F64) {
2431 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2432 } else {
2433 gen_load_fpr32(ctx, t, reg | 1);
2437 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2439 if (ctx->hflags & MIPS_HFLAG_F64) {
2440 TCGv_i64 t64 = tcg_temp_new_i64();
2441 tcg_gen_extu_i32_i64(t64, t);
2442 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2443 tcg_temp_free_i64(t64);
2444 } else {
2445 gen_store_fpr32(ctx, t, reg | 1);
2449 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2451 if (ctx->hflags & MIPS_HFLAG_F64) {
2452 tcg_gen_mov_i64(t, fpu_f64[reg]);
2453 } else {
2454 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2458 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2460 if (ctx->hflags & MIPS_HFLAG_F64) {
2461 tcg_gen_mov_i64(fpu_f64[reg], t);
2462 } else {
2463 TCGv_i64 t0;
2464 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2465 t0 = tcg_temp_new_i64();
2466 tcg_gen_shri_i64(t0, t, 32);
2467 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2468 tcg_temp_free_i64(t0);
2472 static inline int get_fp_bit (int cc)
2474 if (cc)
2475 return 24 + cc;
2476 else
2477 return 23;
2480 /* Addresses computation */
2481 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2483 tcg_gen_add_tl(ret, arg0, arg1);
2485 #if defined(TARGET_MIPS64)
2486 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2487 tcg_gen_ext32s_i64(ret, ret);
2489 #endif
2492 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2493 target_long ofs)
2495 tcg_gen_addi_tl(ret, base, ofs);
2497 #if defined(TARGET_MIPS64)
2498 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2499 tcg_gen_ext32s_i64(ret, ret);
2501 #endif
2504 /* Addresses computation (translation time) */
2505 static target_long addr_add(DisasContext *ctx, target_long base,
2506 target_long offset)
2508 target_long sum = base + offset;
2510 #if defined(TARGET_MIPS64)
2511 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2512 sum = (int32_t)sum;
2514 #endif
2515 return sum;
2518 /* Sign-extract the low 32-bits to a target_long. */
2519 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2521 #if defined(TARGET_MIPS64)
2522 tcg_gen_ext32s_i64(ret, arg);
2523 #else
2524 tcg_gen_extrl_i64_i32(ret, arg);
2525 #endif
2528 /* Sign-extract the high 32-bits to a target_long. */
2529 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2531 #if defined(TARGET_MIPS64)
2532 tcg_gen_sari_i64(ret, arg, 32);
2533 #else
2534 tcg_gen_extrh_i64_i32(ret, arg);
2535 #endif
2538 static inline void check_cp0_enabled(DisasContext *ctx)
2540 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2541 generate_exception_err(ctx, EXCP_CpU, 0);
2544 static inline void check_cp1_enabled(DisasContext *ctx)
2546 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2547 generate_exception_err(ctx, EXCP_CpU, 1);
2550 /* Verify that the processor is running with COP1X instructions enabled.
2551 This is associated with the nabla symbol in the MIPS32 and MIPS64
2552 opcode tables. */
2554 static inline void check_cop1x(DisasContext *ctx)
2556 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2557 generate_exception_end(ctx, EXCP_RI);
2560 /* Verify that the processor is running with 64-bit floating-point
2561 operations enabled. */
2563 static inline void check_cp1_64bitmode(DisasContext *ctx)
2565 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2566 generate_exception_end(ctx, EXCP_RI);
2570 * Verify if floating point register is valid; an operation is not defined
2571 * if bit 0 of any register specification is set and the FR bit in the
2572 * Status register equals zero, since the register numbers specify an
2573 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2574 * in the Status register equals one, both even and odd register numbers
2575 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2577 * Multiple 64 bit wide registers can be checked by calling
2578 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2580 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2582 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2583 generate_exception_end(ctx, EXCP_RI);
2586 /* Verify that the processor is running with DSP instructions enabled.
2587 This is enabled by CP0 Status register MX(24) bit.
2590 static inline void check_dsp(DisasContext *ctx)
2592 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2593 if (ctx->insn_flags & ASE_DSP) {
2594 generate_exception_end(ctx, EXCP_DSPDIS);
2595 } else {
2596 generate_exception_end(ctx, EXCP_RI);
2601 static inline void check_dsp_r2(DisasContext *ctx)
2603 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2604 if (ctx->insn_flags & ASE_DSP) {
2605 generate_exception_end(ctx, EXCP_DSPDIS);
2606 } else {
2607 generate_exception_end(ctx, EXCP_RI);
2612 static inline void check_dsp_r3(DisasContext *ctx)
2614 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2615 if (ctx->insn_flags & ASE_DSP) {
2616 generate_exception_end(ctx, EXCP_DSPDIS);
2617 } else {
2618 generate_exception_end(ctx, EXCP_RI);
2623 /* This code generates a "reserved instruction" exception if the
2624 CPU does not support the instruction set corresponding to flags. */
2625 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2627 if (unlikely(!(ctx->insn_flags & flags))) {
2628 generate_exception_end(ctx, EXCP_RI);
2632 /* This code generates a "reserved instruction" exception if the
2633 CPU has corresponding flag set which indicates that the instruction
2634 has been removed. */
2635 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2637 if (unlikely(ctx->insn_flags & flags)) {
2638 generate_exception_end(ctx, EXCP_RI);
2642 /* This code generates a "reserved instruction" exception if the
2643 CPU does not support 64-bit paired-single (PS) floating point data type */
2644 static inline void check_ps(DisasContext *ctx)
2646 if (unlikely(!ctx->ps)) {
2647 generate_exception(ctx, EXCP_RI);
2649 check_cp1_64bitmode(ctx);
2652 #ifdef TARGET_MIPS64
2653 /* This code generates a "reserved instruction" exception if 64-bit
2654 instructions are not enabled. */
2655 static inline void check_mips_64(DisasContext *ctx)
2657 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2658 generate_exception_end(ctx, EXCP_RI);
2660 #endif
2662 #ifndef CONFIG_USER_ONLY
2663 static inline void check_mvh(DisasContext *ctx)
2665 if (unlikely(!ctx->mvh)) {
2666 generate_exception(ctx, EXCP_RI);
2669 #endif
2672 * This code generates a "reserved instruction" exception if the
2673 * Config5 XNP bit is set.
2675 static inline void check_xnp(DisasContext *ctx)
2677 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2678 generate_exception_end(ctx, EXCP_RI);
2682 #ifndef CONFIG_USER_ONLY
2684 * This code generates a "reserved instruction" exception if the
2685 * Config3 PW bit is NOT set.
2687 static inline void check_pw(DisasContext *ctx)
2689 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2690 generate_exception_end(ctx, EXCP_RI);
2693 #endif
2696 * This code generates a "reserved instruction" exception if the
2697 * Config3 MT bit is NOT set.
2699 static inline void check_mt(DisasContext *ctx)
2701 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2702 generate_exception_end(ctx, EXCP_RI);
2706 #ifndef CONFIG_USER_ONLY
2708 * This code generates a "coprocessor unusable" exception if CP0 is not
2709 * available, and, if that is not the case, generates a "reserved instruction"
2710 * exception if the Config5 MT bit is NOT set. This is needed for availability
2711 * control of some of MT ASE instructions.
2713 static inline void check_cp0_mt(DisasContext *ctx)
2715 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2716 generate_exception_err(ctx, EXCP_CpU, 0);
2717 } else {
2718 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2719 generate_exception_err(ctx, EXCP_RI, 0);
2723 #endif
2726 * This code generates a "reserved instruction" exception if the
2727 * Config5 NMS bit is set.
2729 static inline void check_nms(DisasContext *ctx)
2731 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2732 generate_exception_end(ctx, EXCP_RI);
2737 /* Define small wrappers for gen_load_fpr* so that we have a uniform
2738 calling interface for 32 and 64-bit FPRs. No sense in changing
2739 all callers for gen_load_fpr32 when we need the CTX parameter for
2740 this one use. */
2741 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2742 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2743 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2744 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2745 int ft, int fs, int cc) \
2747 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
2748 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
2749 switch (ifmt) { \
2750 case FMT_PS: \
2751 check_ps(ctx); \
2752 break; \
2753 case FMT_D: \
2754 if (abs) { \
2755 check_cop1x(ctx); \
2757 check_cp1_registers(ctx, fs | ft); \
2758 break; \
2759 case FMT_S: \
2760 if (abs) { \
2761 check_cop1x(ctx); \
2763 break; \
2765 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2766 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
2767 switch (n) { \
2768 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
2769 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
2770 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
2771 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
2772 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
2773 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
2774 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
2775 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2776 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2777 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2778 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2779 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2780 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2781 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2782 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2783 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
2784 default: abort(); \
2786 tcg_temp_free_i##bits (fp0); \
2787 tcg_temp_free_i##bits (fp1); \
2790 FOP_CONDS(, 0, d, FMT_D, 64)
2791 FOP_CONDS(abs, 1, d, FMT_D, 64)
2792 FOP_CONDS(, 0, s, FMT_S, 32)
2793 FOP_CONDS(abs, 1, s, FMT_S, 32)
2794 FOP_CONDS(, 0, ps, FMT_PS, 64)
2795 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2796 #undef FOP_CONDS
2798 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2799 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2800 int ft, int fs, int fd) \
2802 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2803 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2804 if (ifmt == FMT_D) { \
2805 check_cp1_registers(ctx, fs | ft | fd); \
2807 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2808 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2809 switch (n) { \
2810 case 0: \
2811 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2812 break; \
2813 case 1: \
2814 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2815 break; \
2816 case 2: \
2817 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2818 break; \
2819 case 3: \
2820 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2821 break; \
2822 case 4: \
2823 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2824 break; \
2825 case 5: \
2826 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2827 break; \
2828 case 6: \
2829 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2830 break; \
2831 case 7: \
2832 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2833 break; \
2834 case 8: \
2835 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2836 break; \
2837 case 9: \
2838 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2839 break; \
2840 case 10: \
2841 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2842 break; \
2843 case 11: \
2844 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2845 break; \
2846 case 12: \
2847 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2848 break; \
2849 case 13: \
2850 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2851 break; \
2852 case 14: \
2853 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2854 break; \
2855 case 15: \
2856 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2857 break; \
2858 case 17: \
2859 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2860 break; \
2861 case 18: \
2862 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2863 break; \
2864 case 19: \
2865 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2866 break; \
2867 case 25: \
2868 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2869 break; \
2870 case 26: \
2871 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2872 break; \
2873 case 27: \
2874 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2875 break; \
2876 default: \
2877 abort(); \
2879 STORE; \
2880 tcg_temp_free_i ## bits (fp0); \
2881 tcg_temp_free_i ## bits (fp1); \
2884 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2885 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2886 #undef FOP_CONDNS
2887 #undef gen_ldcmp_fpr32
2888 #undef gen_ldcmp_fpr64
2890 /* load/store instructions. */
2891 #ifdef CONFIG_USER_ONLY
2892 #define OP_LD_ATOMIC(insn,fname) \
2893 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2894 DisasContext *ctx) \
2896 TCGv t0 = tcg_temp_new(); \
2897 tcg_gen_mov_tl(t0, arg1); \
2898 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2899 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2900 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2901 tcg_temp_free(t0); \
2903 #else
2904 #define OP_LD_ATOMIC(insn,fname) \
2905 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2906 DisasContext *ctx) \
2908 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2910 #endif
2911 OP_LD_ATOMIC(ll,ld32s);
2912 #if defined(TARGET_MIPS64)
2913 OP_LD_ATOMIC(lld,ld64);
2914 #endif
2915 #undef OP_LD_ATOMIC
2917 #ifdef CONFIG_USER_ONLY
2918 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2919 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2920 DisasContext *ctx) \
2922 TCGv t0 = tcg_temp_new(); \
2923 TCGLabel *l1 = gen_new_label(); \
2924 TCGLabel *l2 = gen_new_label(); \
2926 tcg_gen_andi_tl(t0, arg2, almask); \
2927 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2928 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2929 generate_exception(ctx, EXCP_AdES); \
2930 gen_set_label(l1); \
2931 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2932 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2933 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2934 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2935 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2936 generate_exception_end(ctx, EXCP_SC); \
2937 gen_set_label(l2); \
2938 tcg_gen_movi_tl(t0, 0); \
2939 gen_store_gpr(t0, rt); \
2940 tcg_temp_free(t0); \
2942 #else
2943 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2944 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2945 DisasContext *ctx) \
2947 TCGv t0 = tcg_temp_new(); \
2948 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
2949 gen_store_gpr(t0, rt); \
2950 tcg_temp_free(t0); \
2952 #endif
2953 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2954 #if defined(TARGET_MIPS64)
2955 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2956 #endif
2957 #undef OP_ST_ATOMIC
2959 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2960 int base, int offset)
2962 if (base == 0) {
2963 tcg_gen_movi_tl(addr, offset);
2964 } else if (offset == 0) {
2965 gen_load_gpr(addr, base);
2966 } else {
2967 tcg_gen_movi_tl(addr, offset);
2968 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2972 static target_ulong pc_relative_pc (DisasContext *ctx)
2974 target_ulong pc = ctx->base.pc_next;
2976 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2977 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2979 pc -= branch_bytes;
2982 pc &= ~(target_ulong)3;
2983 return pc;
2986 /* Load */
2987 static void gen_ld(DisasContext *ctx, uint32_t opc,
2988 int rt, int base, int offset)
2990 TCGv t0, t1, t2;
2991 int mem_idx = ctx->mem_idx;
2993 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2994 /* Loongson CPU uses a load to zero register for prefetch.
2995 We emulate it as a NOP. On other CPU we must perform the
2996 actual memory access. */
2997 return;
3000 t0 = tcg_temp_new();
3001 gen_base_offset_addr(ctx, t0, base, offset);
3003 switch (opc) {
3004 #if defined(TARGET_MIPS64)
3005 case OPC_LWU:
3006 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3007 ctx->default_tcg_memop_mask);
3008 gen_store_gpr(t0, rt);
3009 break;
3010 case OPC_LD:
3011 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3012 ctx->default_tcg_memop_mask);
3013 gen_store_gpr(t0, rt);
3014 break;
3015 case OPC_LLD:
3016 case R6_OPC_LLD:
3017 op_ld_lld(t0, t0, mem_idx, ctx);
3018 gen_store_gpr(t0, rt);
3019 break;
3020 case OPC_LDL:
3021 t1 = tcg_temp_new();
3022 /* Do a byte access to possibly trigger a page
3023 fault with the unaligned address. */
3024 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3025 tcg_gen_andi_tl(t1, t0, 7);
3026 #ifndef TARGET_WORDS_BIGENDIAN
3027 tcg_gen_xori_tl(t1, t1, 7);
3028 #endif
3029 tcg_gen_shli_tl(t1, t1, 3);
3030 tcg_gen_andi_tl(t0, t0, ~7);
3031 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3032 tcg_gen_shl_tl(t0, t0, t1);
3033 t2 = tcg_const_tl(-1);
3034 tcg_gen_shl_tl(t2, t2, t1);
3035 gen_load_gpr(t1, rt);
3036 tcg_gen_andc_tl(t1, t1, t2);
3037 tcg_temp_free(t2);
3038 tcg_gen_or_tl(t0, t0, t1);
3039 tcg_temp_free(t1);
3040 gen_store_gpr(t0, rt);
3041 break;
3042 case OPC_LDR:
3043 t1 = tcg_temp_new();
3044 /* Do a byte access to possibly trigger a page
3045 fault with the unaligned address. */
3046 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3047 tcg_gen_andi_tl(t1, t0, 7);
3048 #ifdef TARGET_WORDS_BIGENDIAN
3049 tcg_gen_xori_tl(t1, t1, 7);
3050 #endif
3051 tcg_gen_shli_tl(t1, t1, 3);
3052 tcg_gen_andi_tl(t0, t0, ~7);
3053 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3054 tcg_gen_shr_tl(t0, t0, t1);
3055 tcg_gen_xori_tl(t1, t1, 63);
3056 t2 = tcg_const_tl(0xfffffffffffffffeull);
3057 tcg_gen_shl_tl(t2, t2, t1);
3058 gen_load_gpr(t1, rt);
3059 tcg_gen_and_tl(t1, t1, t2);
3060 tcg_temp_free(t2);
3061 tcg_gen_or_tl(t0, t0, t1);
3062 tcg_temp_free(t1);
3063 gen_store_gpr(t0, rt);
3064 break;
3065 case OPC_LDPC:
3066 t1 = tcg_const_tl(pc_relative_pc(ctx));
3067 gen_op_addr_add(ctx, t0, t0, t1);
3068 tcg_temp_free(t1);
3069 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3070 gen_store_gpr(t0, rt);
3071 break;
3072 #endif
3073 case OPC_LWPC:
3074 t1 = tcg_const_tl(pc_relative_pc(ctx));
3075 gen_op_addr_add(ctx, t0, t0, t1);
3076 tcg_temp_free(t1);
3077 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3078 gen_store_gpr(t0, rt);
3079 break;
3080 case OPC_LWE:
3081 mem_idx = MIPS_HFLAG_UM;
3082 /* fall through */
3083 case OPC_LW:
3084 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3085 ctx->default_tcg_memop_mask);
3086 gen_store_gpr(t0, rt);
3087 break;
3088 case OPC_LHE:
3089 mem_idx = MIPS_HFLAG_UM;
3090 /* fall through */
3091 case OPC_LH:
3092 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3093 ctx->default_tcg_memop_mask);
3094 gen_store_gpr(t0, rt);
3095 break;
3096 case OPC_LHUE:
3097 mem_idx = MIPS_HFLAG_UM;
3098 /* fall through */
3099 case OPC_LHU:
3100 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3101 ctx->default_tcg_memop_mask);
3102 gen_store_gpr(t0, rt);
3103 break;
3104 case OPC_LBE:
3105 mem_idx = MIPS_HFLAG_UM;
3106 /* fall through */
3107 case OPC_LB:
3108 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3109 gen_store_gpr(t0, rt);
3110 break;
3111 case OPC_LBUE:
3112 mem_idx = MIPS_HFLAG_UM;
3113 /* fall through */
3114 case OPC_LBU:
3115 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3116 gen_store_gpr(t0, rt);
3117 break;
3118 case OPC_LWLE:
3119 mem_idx = MIPS_HFLAG_UM;
3120 /* fall through */
3121 case OPC_LWL:
3122 t1 = tcg_temp_new();
3123 /* Do a byte access to possibly trigger a page
3124 fault with the unaligned address. */
3125 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3126 tcg_gen_andi_tl(t1, t0, 3);
3127 #ifndef TARGET_WORDS_BIGENDIAN
3128 tcg_gen_xori_tl(t1, t1, 3);
3129 #endif
3130 tcg_gen_shli_tl(t1, t1, 3);
3131 tcg_gen_andi_tl(t0, t0, ~3);
3132 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3133 tcg_gen_shl_tl(t0, t0, t1);
3134 t2 = tcg_const_tl(-1);
3135 tcg_gen_shl_tl(t2, t2, t1);
3136 gen_load_gpr(t1, rt);
3137 tcg_gen_andc_tl(t1, t1, t2);
3138 tcg_temp_free(t2);
3139 tcg_gen_or_tl(t0, t0, t1);
3140 tcg_temp_free(t1);
3141 tcg_gen_ext32s_tl(t0, t0);
3142 gen_store_gpr(t0, rt);
3143 break;
3144 case OPC_LWRE:
3145 mem_idx = MIPS_HFLAG_UM;
3146 /* fall through */
3147 case OPC_LWR:
3148 t1 = tcg_temp_new();
3149 /* Do a byte access to possibly trigger a page
3150 fault with the unaligned address. */
3151 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3152 tcg_gen_andi_tl(t1, t0, 3);
3153 #ifdef TARGET_WORDS_BIGENDIAN
3154 tcg_gen_xori_tl(t1, t1, 3);
3155 #endif
3156 tcg_gen_shli_tl(t1, t1, 3);
3157 tcg_gen_andi_tl(t0, t0, ~3);
3158 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3159 tcg_gen_shr_tl(t0, t0, t1);
3160 tcg_gen_xori_tl(t1, t1, 31);
3161 t2 = tcg_const_tl(0xfffffffeull);
3162 tcg_gen_shl_tl(t2, t2, t1);
3163 gen_load_gpr(t1, rt);
3164 tcg_gen_and_tl(t1, t1, t2);
3165 tcg_temp_free(t2);
3166 tcg_gen_or_tl(t0, t0, t1);
3167 tcg_temp_free(t1);
3168 tcg_gen_ext32s_tl(t0, t0);
3169 gen_store_gpr(t0, rt);
3170 break;
3171 case OPC_LLE:
3172 mem_idx = MIPS_HFLAG_UM;
3173 /* fall through */
3174 case OPC_LL:
3175 case R6_OPC_LL:
3176 op_ld_ll(t0, t0, mem_idx, ctx);
3177 gen_store_gpr(t0, rt);
3178 break;
3180 tcg_temp_free(t0);
3183 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3184 uint32_t reg1, uint32_t reg2)
3186 TCGv taddr = tcg_temp_new();
3187 TCGv_i64 tval = tcg_temp_new_i64();
3188 TCGv tmp1 = tcg_temp_new();
3189 TCGv tmp2 = tcg_temp_new();
3191 gen_base_offset_addr(ctx, taddr, base, offset);
3192 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3193 #ifdef TARGET_WORDS_BIGENDIAN
3194 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3195 #else
3196 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3197 #endif
3198 gen_store_gpr(tmp1, reg1);
3199 tcg_temp_free(tmp1);
3200 gen_store_gpr(tmp2, reg2);
3201 tcg_temp_free(tmp2);
3202 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3203 tcg_temp_free_i64(tval);
3204 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3205 tcg_temp_free(taddr);
3208 /* Store */
3209 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3210 int base, int offset)
3212 TCGv t0 = tcg_temp_new();
3213 TCGv t1 = tcg_temp_new();
3214 int mem_idx = ctx->mem_idx;
3216 gen_base_offset_addr(ctx, t0, base, offset);
3217 gen_load_gpr(t1, rt);
3218 switch (opc) {
3219 #if defined(TARGET_MIPS64)
3220 case OPC_SD:
3221 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3222 ctx->default_tcg_memop_mask);
3223 break;
3224 case OPC_SDL:
3225 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3226 break;
3227 case OPC_SDR:
3228 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3229 break;
3230 #endif
3231 case OPC_SWE:
3232 mem_idx = MIPS_HFLAG_UM;
3233 /* fall through */
3234 case OPC_SW:
3235 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3236 ctx->default_tcg_memop_mask);
3237 break;
3238 case OPC_SHE:
3239 mem_idx = MIPS_HFLAG_UM;
3240 /* fall through */
3241 case OPC_SH:
3242 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3243 ctx->default_tcg_memop_mask);
3244 break;
3245 case OPC_SBE:
3246 mem_idx = MIPS_HFLAG_UM;
3247 /* fall through */
3248 case OPC_SB:
3249 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3250 break;
3251 case OPC_SWLE:
3252 mem_idx = MIPS_HFLAG_UM;
3253 /* fall through */
3254 case OPC_SWL:
3255 gen_helper_0e2i(swl, t1, t0, mem_idx);
3256 break;
3257 case OPC_SWRE:
3258 mem_idx = MIPS_HFLAG_UM;
3259 /* fall through */
3260 case OPC_SWR:
3261 gen_helper_0e2i(swr, t1, t0, mem_idx);
3262 break;
3264 tcg_temp_free(t0);
3265 tcg_temp_free(t1);
3269 /* Store conditional */
3270 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3271 int base, int16_t offset)
3273 TCGv t0, t1;
3274 int mem_idx = ctx->mem_idx;
3276 #ifdef CONFIG_USER_ONLY
3277 t0 = tcg_temp_local_new();
3278 t1 = tcg_temp_local_new();
3279 #else
3280 t0 = tcg_temp_new();
3281 t1 = tcg_temp_new();
3282 #endif
3283 gen_base_offset_addr(ctx, t0, base, offset);
3284 gen_load_gpr(t1, rt);
3285 switch (opc) {
3286 #if defined(TARGET_MIPS64)
3287 case OPC_SCD:
3288 case R6_OPC_SCD:
3289 op_st_scd(t1, t0, rt, mem_idx, ctx);
3290 break;
3291 #endif
3292 case OPC_SCE:
3293 mem_idx = MIPS_HFLAG_UM;
3294 /* fall through */
3295 case OPC_SC:
3296 case R6_OPC_SC:
3297 op_st_sc(t1, t0, rt, mem_idx, ctx);
3298 break;
3300 tcg_temp_free(t1);
3301 tcg_temp_free(t0);
3304 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3305 uint32_t reg1, uint32_t reg2)
3307 TCGv taddr = tcg_temp_local_new();
3308 TCGv lladdr = tcg_temp_local_new();
3309 TCGv_i64 tval = tcg_temp_new_i64();
3310 TCGv_i64 llval = tcg_temp_new_i64();
3311 TCGv_i64 val = tcg_temp_new_i64();
3312 TCGv tmp1 = tcg_temp_new();
3313 TCGv tmp2 = tcg_temp_new();
3314 TCGLabel *lab_fail = gen_new_label();
3315 TCGLabel *lab_done = gen_new_label();
3317 gen_base_offset_addr(ctx, taddr, base, offset);
3319 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3320 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3322 gen_load_gpr(tmp1, reg1);
3323 gen_load_gpr(tmp2, reg2);
3325 #ifdef TARGET_WORDS_BIGENDIAN
3326 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3327 #else
3328 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3329 #endif
3331 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3332 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3333 ctx->mem_idx, MO_64);
3334 if (reg1 != 0) {
3335 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3337 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3339 gen_set_label(lab_fail);
3341 if (reg1 != 0) {
3342 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3344 gen_set_label(lab_done);
3345 tcg_gen_movi_tl(lladdr, -1);
3346 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3349 /* Load and store */
3350 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3351 TCGv t0)
3353 /* Don't do NOP if destination is zero: we must perform the actual
3354 memory access. */
3355 switch (opc) {
3356 case OPC_LWC1:
3358 TCGv_i32 fp0 = tcg_temp_new_i32();
3359 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3360 ctx->default_tcg_memop_mask);
3361 gen_store_fpr32(ctx, fp0, ft);
3362 tcg_temp_free_i32(fp0);
3364 break;
3365 case OPC_SWC1:
3367 TCGv_i32 fp0 = tcg_temp_new_i32();
3368 gen_load_fpr32(ctx, fp0, ft);
3369 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3370 ctx->default_tcg_memop_mask);
3371 tcg_temp_free_i32(fp0);
3373 break;
3374 case OPC_LDC1:
3376 TCGv_i64 fp0 = tcg_temp_new_i64();
3377 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3378 ctx->default_tcg_memop_mask);
3379 gen_store_fpr64(ctx, fp0, ft);
3380 tcg_temp_free_i64(fp0);
3382 break;
3383 case OPC_SDC1:
3385 TCGv_i64 fp0 = tcg_temp_new_i64();
3386 gen_load_fpr64(ctx, fp0, ft);
3387 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3388 ctx->default_tcg_memop_mask);
3389 tcg_temp_free_i64(fp0);
3391 break;
3392 default:
3393 MIPS_INVAL("flt_ldst");
3394 generate_exception_end(ctx, EXCP_RI);
3395 break;
3399 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3400 int rs, int16_t imm)
3402 TCGv t0 = tcg_temp_new();
3404 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3405 check_cp1_enabled(ctx);
3406 switch (op) {
3407 case OPC_LDC1:
3408 case OPC_SDC1:
3409 check_insn(ctx, ISA_MIPS2);
3410 /* Fallthrough */
3411 default:
3412 gen_base_offset_addr(ctx, t0, rs, imm);
3413 gen_flt_ldst(ctx, op, rt, t0);
3415 } else {
3416 generate_exception_err(ctx, EXCP_CpU, 1);
3418 tcg_temp_free(t0);
3421 /* Arithmetic with immediate operand */
3422 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3423 int rt, int rs, int imm)
3425 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3427 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3428 /* If no destination, treat it as a NOP.
3429 For addi, we must generate the overflow exception when needed. */
3430 return;
3432 switch (opc) {
3433 case OPC_ADDI:
3435 TCGv t0 = tcg_temp_local_new();
3436 TCGv t1 = tcg_temp_new();
3437 TCGv t2 = tcg_temp_new();
3438 TCGLabel *l1 = gen_new_label();
3440 gen_load_gpr(t1, rs);
3441 tcg_gen_addi_tl(t0, t1, uimm);
3442 tcg_gen_ext32s_tl(t0, t0);
3444 tcg_gen_xori_tl(t1, t1, ~uimm);
3445 tcg_gen_xori_tl(t2, t0, uimm);
3446 tcg_gen_and_tl(t1, t1, t2);
3447 tcg_temp_free(t2);
3448 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3449 tcg_temp_free(t1);
3450 /* operands of same sign, result different sign */
3451 generate_exception(ctx, EXCP_OVERFLOW);
3452 gen_set_label(l1);
3453 tcg_gen_ext32s_tl(t0, t0);
3454 gen_store_gpr(t0, rt);
3455 tcg_temp_free(t0);
3457 break;
3458 case OPC_ADDIU:
3459 if (rs != 0) {
3460 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3461 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3462 } else {
3463 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3465 break;
3466 #if defined(TARGET_MIPS64)
3467 case OPC_DADDI:
3469 TCGv t0 = tcg_temp_local_new();
3470 TCGv t1 = tcg_temp_new();
3471 TCGv t2 = tcg_temp_new();
3472 TCGLabel *l1 = gen_new_label();
3474 gen_load_gpr(t1, rs);
3475 tcg_gen_addi_tl(t0, t1, uimm);
3477 tcg_gen_xori_tl(t1, t1, ~uimm);
3478 tcg_gen_xori_tl(t2, t0, uimm);
3479 tcg_gen_and_tl(t1, t1, t2);
3480 tcg_temp_free(t2);
3481 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3482 tcg_temp_free(t1);
3483 /* operands of same sign, result different sign */
3484 generate_exception(ctx, EXCP_OVERFLOW);
3485 gen_set_label(l1);
3486 gen_store_gpr(t0, rt);
3487 tcg_temp_free(t0);
3489 break;
3490 case OPC_DADDIU:
3491 if (rs != 0) {
3492 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3493 } else {
3494 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3496 break;
3497 #endif
3501 /* Logic with immediate operand */
3502 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3503 int rt, int rs, int16_t imm)
3505 target_ulong uimm;
3507 if (rt == 0) {
3508 /* If no destination, treat it as a NOP. */
3509 return;
3511 uimm = (uint16_t)imm;
3512 switch (opc) {
3513 case OPC_ANDI:
3514 if (likely(rs != 0))
3515 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3516 else
3517 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3518 break;
3519 case OPC_ORI:
3520 if (rs != 0)
3521 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3522 else
3523 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3524 break;
3525 case OPC_XORI:
3526 if (likely(rs != 0))
3527 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3528 else
3529 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3530 break;
3531 case OPC_LUI:
3532 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3533 /* OPC_AUI */
3534 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3535 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3536 } else {
3537 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3539 break;
3541 default:
3542 break;
3546 /* Set on less than with immediate operand */
3547 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3548 int rt, int rs, int16_t imm)
3550 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3551 TCGv t0;
3553 if (rt == 0) {
3554 /* If no destination, treat it as a NOP. */
3555 return;
3557 t0 = tcg_temp_new();
3558 gen_load_gpr(t0, rs);
3559 switch (opc) {
3560 case OPC_SLTI:
3561 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3562 break;
3563 case OPC_SLTIU:
3564 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3565 break;
3567 tcg_temp_free(t0);
3570 /* Shifts with immediate operand */
3571 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3572 int rt, int rs, int16_t imm)
3574 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3575 TCGv t0;
3577 if (rt == 0) {
3578 /* If no destination, treat it as a NOP. */
3579 return;
3582 t0 = tcg_temp_new();
3583 gen_load_gpr(t0, rs);
3584 switch (opc) {
3585 case OPC_SLL:
3586 tcg_gen_shli_tl(t0, t0, uimm);
3587 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3588 break;
3589 case OPC_SRA:
3590 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3591 break;
3592 case OPC_SRL:
3593 if (uimm != 0) {
3594 tcg_gen_ext32u_tl(t0, t0);
3595 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3596 } else {
3597 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3599 break;
3600 case OPC_ROTR:
3601 if (uimm != 0) {
3602 TCGv_i32 t1 = tcg_temp_new_i32();
3604 tcg_gen_trunc_tl_i32(t1, t0);
3605 tcg_gen_rotri_i32(t1, t1, uimm);
3606 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3607 tcg_temp_free_i32(t1);
3608 } else {
3609 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3611 break;
3612 #if defined(TARGET_MIPS64)
3613 case OPC_DSLL:
3614 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3615 break;
3616 case OPC_DSRA:
3617 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3618 break;
3619 case OPC_DSRL:
3620 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3621 break;
3622 case OPC_DROTR:
3623 if (uimm != 0) {
3624 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3625 } else {
3626 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3628 break;
3629 case OPC_DSLL32:
3630 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3631 break;
3632 case OPC_DSRA32:
3633 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3634 break;
3635 case OPC_DSRL32:
3636 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3637 break;
3638 case OPC_DROTR32:
3639 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3640 break;
3641 #endif
3643 tcg_temp_free(t0);
3646 /* Arithmetic */
3647 static void gen_arith(DisasContext *ctx, uint32_t opc,
3648 int rd, int rs, int rt)
3650 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3651 && opc != OPC_DADD && opc != OPC_DSUB) {
3652 /* If no destination, treat it as a NOP.
3653 For add & sub, we must generate the overflow exception when needed. */
3654 return;
3657 switch (opc) {
3658 case OPC_ADD:
3660 TCGv t0 = tcg_temp_local_new();
3661 TCGv t1 = tcg_temp_new();
3662 TCGv t2 = tcg_temp_new();
3663 TCGLabel *l1 = gen_new_label();
3665 gen_load_gpr(t1, rs);
3666 gen_load_gpr(t2, rt);
3667 tcg_gen_add_tl(t0, t1, t2);
3668 tcg_gen_ext32s_tl(t0, t0);
3669 tcg_gen_xor_tl(t1, t1, t2);
3670 tcg_gen_xor_tl(t2, t0, t2);
3671 tcg_gen_andc_tl(t1, t2, t1);
3672 tcg_temp_free(t2);
3673 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3674 tcg_temp_free(t1);
3675 /* operands of same sign, result different sign */
3676 generate_exception(ctx, EXCP_OVERFLOW);
3677 gen_set_label(l1);
3678 gen_store_gpr(t0, rd);
3679 tcg_temp_free(t0);
3681 break;
3682 case OPC_ADDU:
3683 if (rs != 0 && rt != 0) {
3684 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3685 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3686 } else if (rs == 0 && rt != 0) {
3687 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3688 } else if (rs != 0 && rt == 0) {
3689 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3690 } else {
3691 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3693 break;
3694 case OPC_SUB:
3696 TCGv t0 = tcg_temp_local_new();
3697 TCGv t1 = tcg_temp_new();
3698 TCGv t2 = tcg_temp_new();
3699 TCGLabel *l1 = gen_new_label();
3701 gen_load_gpr(t1, rs);
3702 gen_load_gpr(t2, rt);
3703 tcg_gen_sub_tl(t0, t1, t2);
3704 tcg_gen_ext32s_tl(t0, t0);
3705 tcg_gen_xor_tl(t2, t1, t2);
3706 tcg_gen_xor_tl(t1, t0, t1);
3707 tcg_gen_and_tl(t1, t1, t2);
3708 tcg_temp_free(t2);
3709 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3710 tcg_temp_free(t1);
3711 /* operands of different sign, first operand and result different sign */
3712 generate_exception(ctx, EXCP_OVERFLOW);
3713 gen_set_label(l1);
3714 gen_store_gpr(t0, rd);
3715 tcg_temp_free(t0);
3717 break;
3718 case OPC_SUBU:
3719 if (rs != 0 && rt != 0) {
3720 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3721 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3722 } else if (rs == 0 && rt != 0) {
3723 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3724 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3725 } else if (rs != 0 && rt == 0) {
3726 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3727 } else {
3728 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3730 break;
3731 #if defined(TARGET_MIPS64)
3732 case OPC_DADD:
3734 TCGv t0 = tcg_temp_local_new();
3735 TCGv t1 = tcg_temp_new();
3736 TCGv t2 = tcg_temp_new();
3737 TCGLabel *l1 = gen_new_label();
3739 gen_load_gpr(t1, rs);
3740 gen_load_gpr(t2, rt);
3741 tcg_gen_add_tl(t0, t1, t2);
3742 tcg_gen_xor_tl(t1, t1, t2);
3743 tcg_gen_xor_tl(t2, t0, t2);
3744 tcg_gen_andc_tl(t1, t2, t1);
3745 tcg_temp_free(t2);
3746 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3747 tcg_temp_free(t1);
3748 /* operands of same sign, result different sign */
3749 generate_exception(ctx, EXCP_OVERFLOW);
3750 gen_set_label(l1);
3751 gen_store_gpr(t0, rd);
3752 tcg_temp_free(t0);
3754 break;
3755 case OPC_DADDU:
3756 if (rs != 0 && rt != 0) {
3757 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3758 } else if (rs == 0 && rt != 0) {
3759 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3760 } else if (rs != 0 && rt == 0) {
3761 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3762 } else {
3763 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3765 break;
3766 case OPC_DSUB:
3768 TCGv t0 = tcg_temp_local_new();
3769 TCGv t1 = tcg_temp_new();
3770 TCGv t2 = tcg_temp_new();
3771 TCGLabel *l1 = gen_new_label();
3773 gen_load_gpr(t1, rs);
3774 gen_load_gpr(t2, rt);
3775 tcg_gen_sub_tl(t0, t1, t2);
3776 tcg_gen_xor_tl(t2, t1, t2);
3777 tcg_gen_xor_tl(t1, t0, t1);
3778 tcg_gen_and_tl(t1, t1, t2);
3779 tcg_temp_free(t2);
3780 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3781 tcg_temp_free(t1);
3782 /* operands of different sign, first operand and result different sign */
3783 generate_exception(ctx, EXCP_OVERFLOW);
3784 gen_set_label(l1);
3785 gen_store_gpr(t0, rd);
3786 tcg_temp_free(t0);
3788 break;
3789 case OPC_DSUBU:
3790 if (rs != 0 && rt != 0) {
3791 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3792 } else if (rs == 0 && rt != 0) {
3793 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3794 } else if (rs != 0 && rt == 0) {
3795 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3796 } else {
3797 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3799 break;
3800 #endif
3801 case OPC_MUL:
3802 if (likely(rs != 0 && rt != 0)) {
3803 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3804 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3805 } else {
3806 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3808 break;
3812 /* Conditional move */
3813 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3814 int rd, int rs, int rt)
3816 TCGv t0, t1, t2;
3818 if (rd == 0) {
3819 /* If no destination, treat it as a NOP. */
3820 return;
3823 t0 = tcg_temp_new();
3824 gen_load_gpr(t0, rt);
3825 t1 = tcg_const_tl(0);
3826 t2 = tcg_temp_new();
3827 gen_load_gpr(t2, rs);
3828 switch (opc) {
3829 case OPC_MOVN:
3830 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3831 break;
3832 case OPC_MOVZ:
3833 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3834 break;
3835 case OPC_SELNEZ:
3836 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3837 break;
3838 case OPC_SELEQZ:
3839 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3840 break;
3842 tcg_temp_free(t2);
3843 tcg_temp_free(t1);
3844 tcg_temp_free(t0);
3847 /* Logic */
3848 static void gen_logic(DisasContext *ctx, uint32_t opc,
3849 int rd, int rs, int rt)
3851 if (rd == 0) {
3852 /* If no destination, treat it as a NOP. */
3853 return;
3856 switch (opc) {
3857 case OPC_AND:
3858 if (likely(rs != 0 && rt != 0)) {
3859 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3860 } else {
3861 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3863 break;
3864 case OPC_NOR:
3865 if (rs != 0 && rt != 0) {
3866 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3867 } else if (rs == 0 && rt != 0) {
3868 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3869 } else if (rs != 0 && rt == 0) {
3870 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3871 } else {
3872 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3874 break;
3875 case OPC_OR:
3876 if (likely(rs != 0 && rt != 0)) {
3877 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3878 } else if (rs == 0 && rt != 0) {
3879 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3880 } else if (rs != 0 && rt == 0) {
3881 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3882 } else {
3883 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3885 break;
3886 case OPC_XOR:
3887 if (likely(rs != 0 && rt != 0)) {
3888 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3889 } else if (rs == 0 && rt != 0) {
3890 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3891 } else if (rs != 0 && rt == 0) {
3892 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3893 } else {
3894 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3896 break;
3900 /* Set on lower than */
3901 static void gen_slt(DisasContext *ctx, uint32_t opc,
3902 int rd, int rs, int rt)
3904 TCGv t0, t1;
3906 if (rd == 0) {
3907 /* If no destination, treat it as a NOP. */
3908 return;
3911 t0 = tcg_temp_new();
3912 t1 = tcg_temp_new();
3913 gen_load_gpr(t0, rs);
3914 gen_load_gpr(t1, rt);
3915 switch (opc) {
3916 case OPC_SLT:
3917 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3918 break;
3919 case OPC_SLTU:
3920 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3921 break;
3923 tcg_temp_free(t0);
3924 tcg_temp_free(t1);
3927 /* Shifts */
3928 static void gen_shift(DisasContext *ctx, uint32_t opc,
3929 int rd, int rs, int rt)
3931 TCGv t0, t1;
3933 if (rd == 0) {
3934 /* If no destination, treat it as a NOP.
3935 For add & sub, we must generate the overflow exception when needed. */
3936 return;
3939 t0 = tcg_temp_new();
3940 t1 = tcg_temp_new();
3941 gen_load_gpr(t0, rs);
3942 gen_load_gpr(t1, rt);
3943 switch (opc) {
3944 case OPC_SLLV:
3945 tcg_gen_andi_tl(t0, t0, 0x1f);
3946 tcg_gen_shl_tl(t0, t1, t0);
3947 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3948 break;
3949 case OPC_SRAV:
3950 tcg_gen_andi_tl(t0, t0, 0x1f);
3951 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3952 break;
3953 case OPC_SRLV:
3954 tcg_gen_ext32u_tl(t1, t1);
3955 tcg_gen_andi_tl(t0, t0, 0x1f);
3956 tcg_gen_shr_tl(t0, t1, t0);
3957 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3958 break;
3959 case OPC_ROTRV:
3961 TCGv_i32 t2 = tcg_temp_new_i32();
3962 TCGv_i32 t3 = tcg_temp_new_i32();
3964 tcg_gen_trunc_tl_i32(t2, t0);
3965 tcg_gen_trunc_tl_i32(t3, t1);
3966 tcg_gen_andi_i32(t2, t2, 0x1f);
3967 tcg_gen_rotr_i32(t2, t3, t2);
3968 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3969 tcg_temp_free_i32(t2);
3970 tcg_temp_free_i32(t3);
3972 break;
3973 #if defined(TARGET_MIPS64)
3974 case OPC_DSLLV:
3975 tcg_gen_andi_tl(t0, t0, 0x3f);
3976 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3977 break;
3978 case OPC_DSRAV:
3979 tcg_gen_andi_tl(t0, t0, 0x3f);
3980 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3981 break;
3982 case OPC_DSRLV:
3983 tcg_gen_andi_tl(t0, t0, 0x3f);
3984 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3985 break;
3986 case OPC_DROTRV:
3987 tcg_gen_andi_tl(t0, t0, 0x3f);
3988 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3989 break;
3990 #endif
3992 tcg_temp_free(t0);
3993 tcg_temp_free(t1);
3996 /* Arithmetic on HI/LO registers */
3997 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3999 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4000 /* Treat as NOP. */
4001 return;
4004 if (acc != 0) {
4005 check_dsp(ctx);
4008 switch (opc) {
4009 case OPC_MFHI:
4010 #if defined(TARGET_MIPS64)
4011 if (acc != 0) {
4012 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4013 } else
4014 #endif
4016 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4018 break;
4019 case OPC_MFLO:
4020 #if defined(TARGET_MIPS64)
4021 if (acc != 0) {
4022 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4023 } else
4024 #endif
4026 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4028 break;
4029 case OPC_MTHI:
4030 if (reg != 0) {
4031 #if defined(TARGET_MIPS64)
4032 if (acc != 0) {
4033 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4034 } else
4035 #endif
4037 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4039 } else {
4040 tcg_gen_movi_tl(cpu_HI[acc], 0);
4042 break;
4043 case OPC_MTLO:
4044 if (reg != 0) {
4045 #if defined(TARGET_MIPS64)
4046 if (acc != 0) {
4047 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4048 } else
4049 #endif
4051 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4053 } else {
4054 tcg_gen_movi_tl(cpu_LO[acc], 0);
4056 break;
4060 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4061 TCGMemOp memop)
4063 TCGv t0 = tcg_const_tl(addr);
4064 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4065 gen_store_gpr(t0, reg);
4066 tcg_temp_free(t0);
4069 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4070 int rs)
4072 target_long offset;
4073 target_long addr;
4075 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4076 case OPC_ADDIUPC:
4077 if (rs != 0) {
4078 offset = sextract32(ctx->opcode << 2, 0, 21);
4079 addr = addr_add(ctx, pc, offset);
4080 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4082 break;
4083 case R6_OPC_LWPC:
4084 offset = sextract32(ctx->opcode << 2, 0, 21);
4085 addr = addr_add(ctx, pc, offset);
4086 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4087 break;
4088 #if defined(TARGET_MIPS64)
4089 case OPC_LWUPC:
4090 check_mips_64(ctx);
4091 offset = sextract32(ctx->opcode << 2, 0, 21);
4092 addr = addr_add(ctx, pc, offset);
4093 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4094 break;
4095 #endif
4096 default:
4097 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4098 case OPC_AUIPC:
4099 if (rs != 0) {
4100 offset = sextract32(ctx->opcode, 0, 16) << 16;
4101 addr = addr_add(ctx, pc, offset);
4102 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4104 break;
4105 case OPC_ALUIPC:
4106 if (rs != 0) {
4107 offset = sextract32(ctx->opcode, 0, 16) << 16;
4108 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4109 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4111 break;
4112 #if defined(TARGET_MIPS64)
4113 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4114 case R6_OPC_LDPC + (1 << 16):
4115 case R6_OPC_LDPC + (2 << 16):
4116 case R6_OPC_LDPC + (3 << 16):
4117 check_mips_64(ctx);
4118 offset = sextract32(ctx->opcode << 3, 0, 21);
4119 addr = addr_add(ctx, (pc & ~0x7), offset);
4120 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4121 break;
4122 #endif
4123 default:
4124 MIPS_INVAL("OPC_PCREL");
4125 generate_exception_end(ctx, EXCP_RI);
4126 break;
4128 break;
4132 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4134 TCGv t0, t1;
4136 if (rd == 0) {
4137 /* Treat as NOP. */
4138 return;
4141 t0 = tcg_temp_new();
4142 t1 = tcg_temp_new();
4144 gen_load_gpr(t0, rs);
4145 gen_load_gpr(t1, rt);
4147 switch (opc) {
4148 case R6_OPC_DIV:
4150 TCGv t2 = tcg_temp_new();
4151 TCGv t3 = tcg_temp_new();
4152 tcg_gen_ext32s_tl(t0, t0);
4153 tcg_gen_ext32s_tl(t1, t1);
4154 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4155 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4156 tcg_gen_and_tl(t2, t2, t3);
4157 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4158 tcg_gen_or_tl(t2, t2, t3);
4159 tcg_gen_movi_tl(t3, 0);
4160 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4161 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4162 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4163 tcg_temp_free(t3);
4164 tcg_temp_free(t2);
4166 break;
4167 case R6_OPC_MOD:
4169 TCGv t2 = tcg_temp_new();
4170 TCGv t3 = tcg_temp_new();
4171 tcg_gen_ext32s_tl(t0, t0);
4172 tcg_gen_ext32s_tl(t1, t1);
4173 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4174 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4175 tcg_gen_and_tl(t2, t2, t3);
4176 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4177 tcg_gen_or_tl(t2, t2, t3);
4178 tcg_gen_movi_tl(t3, 0);
4179 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4180 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4181 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4182 tcg_temp_free(t3);
4183 tcg_temp_free(t2);
4185 break;
4186 case R6_OPC_DIVU:
4188 TCGv t2 = tcg_const_tl(0);
4189 TCGv t3 = tcg_const_tl(1);
4190 tcg_gen_ext32u_tl(t0, t0);
4191 tcg_gen_ext32u_tl(t1, t1);
4192 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4193 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4194 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4195 tcg_temp_free(t3);
4196 tcg_temp_free(t2);
4198 break;
4199 case R6_OPC_MODU:
4201 TCGv t2 = tcg_const_tl(0);
4202 TCGv t3 = tcg_const_tl(1);
4203 tcg_gen_ext32u_tl(t0, t0);
4204 tcg_gen_ext32u_tl(t1, t1);
4205 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4206 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4207 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4208 tcg_temp_free(t3);
4209 tcg_temp_free(t2);
4211 break;
4212 case R6_OPC_MUL:
4214 TCGv_i32 t2 = tcg_temp_new_i32();
4215 TCGv_i32 t3 = tcg_temp_new_i32();
4216 tcg_gen_trunc_tl_i32(t2, t0);
4217 tcg_gen_trunc_tl_i32(t3, t1);
4218 tcg_gen_mul_i32(t2, t2, t3);
4219 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4220 tcg_temp_free_i32(t2);
4221 tcg_temp_free_i32(t3);
4223 break;
4224 case R6_OPC_MUH:
4226 TCGv_i32 t2 = tcg_temp_new_i32();
4227 TCGv_i32 t3 = tcg_temp_new_i32();
4228 tcg_gen_trunc_tl_i32(t2, t0);
4229 tcg_gen_trunc_tl_i32(t3, t1);
4230 tcg_gen_muls2_i32(t2, t3, t2, t3);
4231 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4232 tcg_temp_free_i32(t2);
4233 tcg_temp_free_i32(t3);
4235 break;
4236 case R6_OPC_MULU:
4238 TCGv_i32 t2 = tcg_temp_new_i32();
4239 TCGv_i32 t3 = tcg_temp_new_i32();
4240 tcg_gen_trunc_tl_i32(t2, t0);
4241 tcg_gen_trunc_tl_i32(t3, t1);
4242 tcg_gen_mul_i32(t2, t2, t3);
4243 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4244 tcg_temp_free_i32(t2);
4245 tcg_temp_free_i32(t3);
4247 break;
4248 case R6_OPC_MUHU:
4250 TCGv_i32 t2 = tcg_temp_new_i32();
4251 TCGv_i32 t3 = tcg_temp_new_i32();
4252 tcg_gen_trunc_tl_i32(t2, t0);
4253 tcg_gen_trunc_tl_i32(t3, t1);
4254 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4255 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4256 tcg_temp_free_i32(t2);
4257 tcg_temp_free_i32(t3);
4259 break;
4260 #if defined(TARGET_MIPS64)
4261 case R6_OPC_DDIV:
4263 TCGv t2 = tcg_temp_new();
4264 TCGv t3 = tcg_temp_new();
4265 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4266 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4267 tcg_gen_and_tl(t2, t2, t3);
4268 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4269 tcg_gen_or_tl(t2, t2, t3);
4270 tcg_gen_movi_tl(t3, 0);
4271 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4272 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4273 tcg_temp_free(t3);
4274 tcg_temp_free(t2);
4276 break;
4277 case R6_OPC_DMOD:
4279 TCGv t2 = tcg_temp_new();
4280 TCGv t3 = tcg_temp_new();
4281 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4282 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4283 tcg_gen_and_tl(t2, t2, t3);
4284 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4285 tcg_gen_or_tl(t2, t2, t3);
4286 tcg_gen_movi_tl(t3, 0);
4287 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4288 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4289 tcg_temp_free(t3);
4290 tcg_temp_free(t2);
4292 break;
4293 case R6_OPC_DDIVU:
4295 TCGv t2 = tcg_const_tl(0);
4296 TCGv t3 = tcg_const_tl(1);
4297 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4298 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4299 tcg_temp_free(t3);
4300 tcg_temp_free(t2);
4302 break;
4303 case R6_OPC_DMODU:
4305 TCGv t2 = tcg_const_tl(0);
4306 TCGv t3 = tcg_const_tl(1);
4307 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4308 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4309 tcg_temp_free(t3);
4310 tcg_temp_free(t2);
4312 break;
4313 case R6_OPC_DMUL:
4314 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4315 break;
4316 case R6_OPC_DMUH:
4318 TCGv t2 = tcg_temp_new();
4319 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4320 tcg_temp_free(t2);
4322 break;
4323 case R6_OPC_DMULU:
4324 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4325 break;
4326 case R6_OPC_DMUHU:
4328 TCGv t2 = tcg_temp_new();
4329 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4330 tcg_temp_free(t2);
4332 break;
4333 #endif
4334 default:
4335 MIPS_INVAL("r6 mul/div");
4336 generate_exception_end(ctx, EXCP_RI);
4337 goto out;
4339 out:
4340 tcg_temp_free(t0);
4341 tcg_temp_free(t1);
4344 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4345 int acc, int rs, int rt)
4347 TCGv t0, t1;
4349 t0 = tcg_temp_new();
4350 t1 = tcg_temp_new();
4352 gen_load_gpr(t0, rs);
4353 gen_load_gpr(t1, rt);
4355 if (acc != 0) {
4356 check_dsp(ctx);
4359 switch (opc) {
4360 case OPC_DIV:
4362 TCGv t2 = tcg_temp_new();
4363 TCGv t3 = tcg_temp_new();
4364 tcg_gen_ext32s_tl(t0, t0);
4365 tcg_gen_ext32s_tl(t1, t1);
4366 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4367 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4368 tcg_gen_and_tl(t2, t2, t3);
4369 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4370 tcg_gen_or_tl(t2, t2, t3);
4371 tcg_gen_movi_tl(t3, 0);
4372 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4373 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4374 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4375 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4376 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4377 tcg_temp_free(t3);
4378 tcg_temp_free(t2);
4380 break;
4381 case OPC_DIVU:
4383 TCGv t2 = tcg_const_tl(0);
4384 TCGv t3 = tcg_const_tl(1);
4385 tcg_gen_ext32u_tl(t0, t0);
4386 tcg_gen_ext32u_tl(t1, t1);
4387 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4388 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4389 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4390 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4391 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4392 tcg_temp_free(t3);
4393 tcg_temp_free(t2);
4395 break;
4396 case OPC_MULT:
4398 TCGv_i32 t2 = tcg_temp_new_i32();
4399 TCGv_i32 t3 = tcg_temp_new_i32();
4400 tcg_gen_trunc_tl_i32(t2, t0);
4401 tcg_gen_trunc_tl_i32(t3, t1);
4402 tcg_gen_muls2_i32(t2, t3, t2, t3);
4403 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4404 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4405 tcg_temp_free_i32(t2);
4406 tcg_temp_free_i32(t3);
4408 break;
4409 case OPC_MULTU:
4411 TCGv_i32 t2 = tcg_temp_new_i32();
4412 TCGv_i32 t3 = tcg_temp_new_i32();
4413 tcg_gen_trunc_tl_i32(t2, t0);
4414 tcg_gen_trunc_tl_i32(t3, t1);
4415 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4416 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4417 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4418 tcg_temp_free_i32(t2);
4419 tcg_temp_free_i32(t3);
4421 break;
4422 #if defined(TARGET_MIPS64)
4423 case OPC_DDIV:
4425 TCGv t2 = tcg_temp_new();
4426 TCGv t3 = tcg_temp_new();
4427 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4428 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4429 tcg_gen_and_tl(t2, t2, t3);
4430 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4431 tcg_gen_or_tl(t2, t2, t3);
4432 tcg_gen_movi_tl(t3, 0);
4433 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4434 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4435 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4436 tcg_temp_free(t3);
4437 tcg_temp_free(t2);
4439 break;
4440 case OPC_DDIVU:
4442 TCGv t2 = tcg_const_tl(0);
4443 TCGv t3 = tcg_const_tl(1);
4444 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4445 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4446 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4447 tcg_temp_free(t3);
4448 tcg_temp_free(t2);
4450 break;
4451 case OPC_DMULT:
4452 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4453 break;
4454 case OPC_DMULTU:
4455 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4456 break;
4457 #endif
4458 case OPC_MADD:
4460 TCGv_i64 t2 = tcg_temp_new_i64();
4461 TCGv_i64 t3 = tcg_temp_new_i64();
4463 tcg_gen_ext_tl_i64(t2, t0);
4464 tcg_gen_ext_tl_i64(t3, t1);
4465 tcg_gen_mul_i64(t2, t2, t3);
4466 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4467 tcg_gen_add_i64(t2, t2, t3);
4468 tcg_temp_free_i64(t3);
4469 gen_move_low32(cpu_LO[acc], t2);
4470 gen_move_high32(cpu_HI[acc], t2);
4471 tcg_temp_free_i64(t2);
4473 break;
4474 case OPC_MADDU:
4476 TCGv_i64 t2 = tcg_temp_new_i64();
4477 TCGv_i64 t3 = tcg_temp_new_i64();
4479 tcg_gen_ext32u_tl(t0, t0);
4480 tcg_gen_ext32u_tl(t1, t1);
4481 tcg_gen_extu_tl_i64(t2, t0);
4482 tcg_gen_extu_tl_i64(t3, t1);
4483 tcg_gen_mul_i64(t2, t2, t3);
4484 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4485 tcg_gen_add_i64(t2, t2, t3);
4486 tcg_temp_free_i64(t3);
4487 gen_move_low32(cpu_LO[acc], t2);
4488 gen_move_high32(cpu_HI[acc], t2);
4489 tcg_temp_free_i64(t2);
4491 break;
4492 case OPC_MSUB:
4494 TCGv_i64 t2 = tcg_temp_new_i64();
4495 TCGv_i64 t3 = tcg_temp_new_i64();
4497 tcg_gen_ext_tl_i64(t2, t0);
4498 tcg_gen_ext_tl_i64(t3, t1);
4499 tcg_gen_mul_i64(t2, t2, t3);
4500 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4501 tcg_gen_sub_i64(t2, t3, t2);
4502 tcg_temp_free_i64(t3);
4503 gen_move_low32(cpu_LO[acc], t2);
4504 gen_move_high32(cpu_HI[acc], t2);
4505 tcg_temp_free_i64(t2);
4507 break;
4508 case OPC_MSUBU:
4510 TCGv_i64 t2 = tcg_temp_new_i64();
4511 TCGv_i64 t3 = tcg_temp_new_i64();
4513 tcg_gen_ext32u_tl(t0, t0);
4514 tcg_gen_ext32u_tl(t1, t1);
4515 tcg_gen_extu_tl_i64(t2, t0);
4516 tcg_gen_extu_tl_i64(t3, t1);
4517 tcg_gen_mul_i64(t2, t2, t3);
4518 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4519 tcg_gen_sub_i64(t2, t3, t2);
4520 tcg_temp_free_i64(t3);
4521 gen_move_low32(cpu_LO[acc], t2);
4522 gen_move_high32(cpu_HI[acc], t2);
4523 tcg_temp_free_i64(t2);
4525 break;
4526 default:
4527 MIPS_INVAL("mul/div");
4528 generate_exception_end(ctx, EXCP_RI);
4529 goto out;
4531 out:
4532 tcg_temp_free(t0);
4533 tcg_temp_free(t1);
4536 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4537 int rd, int rs, int rt)
4539 TCGv t0 = tcg_temp_new();
4540 TCGv t1 = tcg_temp_new();
4542 gen_load_gpr(t0, rs);
4543 gen_load_gpr(t1, rt);
4545 switch (opc) {
4546 case OPC_VR54XX_MULS:
4547 gen_helper_muls(t0, cpu_env, t0, t1);
4548 break;
4549 case OPC_VR54XX_MULSU:
4550 gen_helper_mulsu(t0, cpu_env, t0, t1);
4551 break;
4552 case OPC_VR54XX_MACC:
4553 gen_helper_macc(t0, cpu_env, t0, t1);
4554 break;
4555 case OPC_VR54XX_MACCU:
4556 gen_helper_maccu(t0, cpu_env, t0, t1);
4557 break;
4558 case OPC_VR54XX_MSAC:
4559 gen_helper_msac(t0, cpu_env, t0, t1);
4560 break;
4561 case OPC_VR54XX_MSACU:
4562 gen_helper_msacu(t0, cpu_env, t0, t1);
4563 break;
4564 case OPC_VR54XX_MULHI:
4565 gen_helper_mulhi(t0, cpu_env, t0, t1);
4566 break;
4567 case OPC_VR54XX_MULHIU:
4568 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4569 break;
4570 case OPC_VR54XX_MULSHI:
4571 gen_helper_mulshi(t0, cpu_env, t0, t1);
4572 break;
4573 case OPC_VR54XX_MULSHIU:
4574 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4575 break;
4576 case OPC_VR54XX_MACCHI:
4577 gen_helper_macchi(t0, cpu_env, t0, t1);
4578 break;
4579 case OPC_VR54XX_MACCHIU:
4580 gen_helper_macchiu(t0, cpu_env, t0, t1);
4581 break;
4582 case OPC_VR54XX_MSACHI:
4583 gen_helper_msachi(t0, cpu_env, t0, t1);
4584 break;
4585 case OPC_VR54XX_MSACHIU:
4586 gen_helper_msachiu(t0, cpu_env, t0, t1);
4587 break;
4588 default:
4589 MIPS_INVAL("mul vr54xx");
4590 generate_exception_end(ctx, EXCP_RI);
4591 goto out;
4593 gen_store_gpr(t0, rd);
4595 out:
4596 tcg_temp_free(t0);
4597 tcg_temp_free(t1);
4600 static void gen_cl (DisasContext *ctx, uint32_t opc,
4601 int rd, int rs)
4603 TCGv t0;
4605 if (rd == 0) {
4606 /* Treat as NOP. */
4607 return;
4609 t0 = cpu_gpr[rd];
4610 gen_load_gpr(t0, rs);
4612 switch (opc) {
4613 case OPC_CLO:
4614 case R6_OPC_CLO:
4615 #if defined(TARGET_MIPS64)
4616 case OPC_DCLO:
4617 case R6_OPC_DCLO:
4618 #endif
4619 tcg_gen_not_tl(t0, t0);
4620 break;
4623 switch (opc) {
4624 case OPC_CLO:
4625 case R6_OPC_CLO:
4626 case OPC_CLZ:
4627 case R6_OPC_CLZ:
4628 tcg_gen_ext32u_tl(t0, t0);
4629 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4630 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4631 break;
4632 #if defined(TARGET_MIPS64)
4633 case OPC_DCLO:
4634 case R6_OPC_DCLO:
4635 case OPC_DCLZ:
4636 case R6_OPC_DCLZ:
4637 tcg_gen_clzi_i64(t0, t0, 64);
4638 break;
4639 #endif
4643 /* Godson integer instructions */
4644 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4645 int rd, int rs, int rt)
4647 TCGv t0, t1;
4649 if (rd == 0) {
4650 /* Treat as NOP. */
4651 return;
4654 switch (opc) {
4655 case OPC_MULT_G_2E:
4656 case OPC_MULT_G_2F:
4657 case OPC_MULTU_G_2E:
4658 case OPC_MULTU_G_2F:
4659 #if defined(TARGET_MIPS64)
4660 case OPC_DMULT_G_2E:
4661 case OPC_DMULT_G_2F:
4662 case OPC_DMULTU_G_2E:
4663 case OPC_DMULTU_G_2F:
4664 #endif
4665 t0 = tcg_temp_new();
4666 t1 = tcg_temp_new();
4667 break;
4668 default:
4669 t0 = tcg_temp_local_new();
4670 t1 = tcg_temp_local_new();
4671 break;
4674 gen_load_gpr(t0, rs);
4675 gen_load_gpr(t1, rt);
4677 switch (opc) {
4678 case OPC_MULT_G_2E:
4679 case OPC_MULT_G_2F:
4680 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4681 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4682 break;
4683 case OPC_MULTU_G_2E:
4684 case OPC_MULTU_G_2F:
4685 tcg_gen_ext32u_tl(t0, t0);
4686 tcg_gen_ext32u_tl(t1, t1);
4687 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4688 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4689 break;
4690 case OPC_DIV_G_2E:
4691 case OPC_DIV_G_2F:
4693 TCGLabel *l1 = gen_new_label();
4694 TCGLabel *l2 = gen_new_label();
4695 TCGLabel *l3 = gen_new_label();
4696 tcg_gen_ext32s_tl(t0, t0);
4697 tcg_gen_ext32s_tl(t1, t1);
4698 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4699 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4700 tcg_gen_br(l3);
4701 gen_set_label(l1);
4702 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4703 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4704 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4705 tcg_gen_br(l3);
4706 gen_set_label(l2);
4707 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4708 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4709 gen_set_label(l3);
4711 break;
4712 case OPC_DIVU_G_2E:
4713 case OPC_DIVU_G_2F:
4715 TCGLabel *l1 = gen_new_label();
4716 TCGLabel *l2 = gen_new_label();
4717 tcg_gen_ext32u_tl(t0, t0);
4718 tcg_gen_ext32u_tl(t1, t1);
4719 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4720 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4721 tcg_gen_br(l2);
4722 gen_set_label(l1);
4723 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4724 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4725 gen_set_label(l2);
4727 break;
4728 case OPC_MOD_G_2E:
4729 case OPC_MOD_G_2F:
4731 TCGLabel *l1 = gen_new_label();
4732 TCGLabel *l2 = gen_new_label();
4733 TCGLabel *l3 = gen_new_label();
4734 tcg_gen_ext32u_tl(t0, t0);
4735 tcg_gen_ext32u_tl(t1, t1);
4736 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4737 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4738 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4739 gen_set_label(l1);
4740 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4741 tcg_gen_br(l3);
4742 gen_set_label(l2);
4743 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4744 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4745 gen_set_label(l3);
4747 break;
4748 case OPC_MODU_G_2E:
4749 case OPC_MODU_G_2F:
4751 TCGLabel *l1 = gen_new_label();
4752 TCGLabel *l2 = gen_new_label();
4753 tcg_gen_ext32u_tl(t0, t0);
4754 tcg_gen_ext32u_tl(t1, t1);
4755 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4756 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4757 tcg_gen_br(l2);
4758 gen_set_label(l1);
4759 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4760 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4761 gen_set_label(l2);
4763 break;
4764 #if defined(TARGET_MIPS64)
4765 case OPC_DMULT_G_2E:
4766 case OPC_DMULT_G_2F:
4767 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4768 break;
4769 case OPC_DMULTU_G_2E:
4770 case OPC_DMULTU_G_2F:
4771 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4772 break;
4773 case OPC_DDIV_G_2E:
4774 case OPC_DDIV_G_2F:
4776 TCGLabel *l1 = gen_new_label();
4777 TCGLabel *l2 = gen_new_label();
4778 TCGLabel *l3 = gen_new_label();
4779 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4780 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4781 tcg_gen_br(l3);
4782 gen_set_label(l1);
4783 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4784 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4785 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4786 tcg_gen_br(l3);
4787 gen_set_label(l2);
4788 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4789 gen_set_label(l3);
4791 break;
4792 case OPC_DDIVU_G_2E:
4793 case OPC_DDIVU_G_2F:
4795 TCGLabel *l1 = gen_new_label();
4796 TCGLabel *l2 = gen_new_label();
4797 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4798 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4799 tcg_gen_br(l2);
4800 gen_set_label(l1);
4801 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4802 gen_set_label(l2);
4804 break;
4805 case OPC_DMOD_G_2E:
4806 case OPC_DMOD_G_2F:
4808 TCGLabel *l1 = gen_new_label();
4809 TCGLabel *l2 = gen_new_label();
4810 TCGLabel *l3 = gen_new_label();
4811 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4812 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4813 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4814 gen_set_label(l1);
4815 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4816 tcg_gen_br(l3);
4817 gen_set_label(l2);
4818 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4819 gen_set_label(l3);
4821 break;
4822 case OPC_DMODU_G_2E:
4823 case OPC_DMODU_G_2F:
4825 TCGLabel *l1 = gen_new_label();
4826 TCGLabel *l2 = gen_new_label();
4827 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4828 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4829 tcg_gen_br(l2);
4830 gen_set_label(l1);
4831 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4832 gen_set_label(l2);
4834 break;
4835 #endif
4838 tcg_temp_free(t0);
4839 tcg_temp_free(t1);
4842 /* Loongson multimedia instructions */
4843 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4845 uint32_t opc, shift_max;
4846 TCGv_i64 t0, t1;
4848 opc = MASK_LMI(ctx->opcode);
4849 switch (opc) {
4850 case OPC_ADD_CP2:
4851 case OPC_SUB_CP2:
4852 case OPC_DADD_CP2:
4853 case OPC_DSUB_CP2:
4854 t0 = tcg_temp_local_new_i64();
4855 t1 = tcg_temp_local_new_i64();
4856 break;
4857 default:
4858 t0 = tcg_temp_new_i64();
4859 t1 = tcg_temp_new_i64();
4860 break;
4863 check_cp1_enabled(ctx);
4864 gen_load_fpr64(ctx, t0, rs);
4865 gen_load_fpr64(ctx, t1, rt);
4867 #define LMI_HELPER(UP, LO) \
4868 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
4869 #define LMI_HELPER_1(UP, LO) \
4870 case OPC_##UP: gen_helper_##LO(t0, t0); break
4871 #define LMI_DIRECT(UP, LO, OP) \
4872 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
4874 switch (opc) {
4875 LMI_HELPER(PADDSH, paddsh);
4876 LMI_HELPER(PADDUSH, paddush);
4877 LMI_HELPER(PADDH, paddh);
4878 LMI_HELPER(PADDW, paddw);
4879 LMI_HELPER(PADDSB, paddsb);
4880 LMI_HELPER(PADDUSB, paddusb);
4881 LMI_HELPER(PADDB, paddb);
4883 LMI_HELPER(PSUBSH, psubsh);
4884 LMI_HELPER(PSUBUSH, psubush);
4885 LMI_HELPER(PSUBH, psubh);
4886 LMI_HELPER(PSUBW, psubw);
4887 LMI_HELPER(PSUBSB, psubsb);
4888 LMI_HELPER(PSUBUSB, psubusb);
4889 LMI_HELPER(PSUBB, psubb);
4891 LMI_HELPER(PSHUFH, pshufh);
4892 LMI_HELPER(PACKSSWH, packsswh);
4893 LMI_HELPER(PACKSSHB, packsshb);
4894 LMI_HELPER(PACKUSHB, packushb);
4896 LMI_HELPER(PUNPCKLHW, punpcklhw);
4897 LMI_HELPER(PUNPCKHHW, punpckhhw);
4898 LMI_HELPER(PUNPCKLBH, punpcklbh);
4899 LMI_HELPER(PUNPCKHBH, punpckhbh);
4900 LMI_HELPER(PUNPCKLWD, punpcklwd);
4901 LMI_HELPER(PUNPCKHWD, punpckhwd);
4903 LMI_HELPER(PAVGH, pavgh);
4904 LMI_HELPER(PAVGB, pavgb);
4905 LMI_HELPER(PMAXSH, pmaxsh);
4906 LMI_HELPER(PMINSH, pminsh);
4907 LMI_HELPER(PMAXUB, pmaxub);
4908 LMI_HELPER(PMINUB, pminub);
4910 LMI_HELPER(PCMPEQW, pcmpeqw);
4911 LMI_HELPER(PCMPGTW, pcmpgtw);
4912 LMI_HELPER(PCMPEQH, pcmpeqh);
4913 LMI_HELPER(PCMPGTH, pcmpgth);
4914 LMI_HELPER(PCMPEQB, pcmpeqb);
4915 LMI_HELPER(PCMPGTB, pcmpgtb);
4917 LMI_HELPER(PSLLW, psllw);
4918 LMI_HELPER(PSLLH, psllh);
4919 LMI_HELPER(PSRLW, psrlw);
4920 LMI_HELPER(PSRLH, psrlh);
4921 LMI_HELPER(PSRAW, psraw);
4922 LMI_HELPER(PSRAH, psrah);
4924 LMI_HELPER(PMULLH, pmullh);
4925 LMI_HELPER(PMULHH, pmulhh);
4926 LMI_HELPER(PMULHUH, pmulhuh);
4927 LMI_HELPER(PMADDHW, pmaddhw);
4929 LMI_HELPER(PASUBUB, pasubub);
4930 LMI_HELPER_1(BIADD, biadd);
4931 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4933 LMI_DIRECT(PADDD, paddd, add);
4934 LMI_DIRECT(PSUBD, psubd, sub);
4935 LMI_DIRECT(XOR_CP2, xor, xor);
4936 LMI_DIRECT(NOR_CP2, nor, nor);
4937 LMI_DIRECT(AND_CP2, and, and);
4938 LMI_DIRECT(OR_CP2, or, or);
4940 case OPC_PANDN:
4941 tcg_gen_andc_i64(t0, t1, t0);
4942 break;
4944 case OPC_PINSRH_0:
4945 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4946 break;
4947 case OPC_PINSRH_1:
4948 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4949 break;
4950 case OPC_PINSRH_2:
4951 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4952 break;
4953 case OPC_PINSRH_3:
4954 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4955 break;
4957 case OPC_PEXTRH:
4958 tcg_gen_andi_i64(t1, t1, 3);
4959 tcg_gen_shli_i64(t1, t1, 4);
4960 tcg_gen_shr_i64(t0, t0, t1);
4961 tcg_gen_ext16u_i64(t0, t0);
4962 break;
4964 case OPC_ADDU_CP2:
4965 tcg_gen_add_i64(t0, t0, t1);
4966 tcg_gen_ext32s_i64(t0, t0);
4967 break;
4968 case OPC_SUBU_CP2:
4969 tcg_gen_sub_i64(t0, t0, t1);
4970 tcg_gen_ext32s_i64(t0, t0);
4971 break;
4973 case OPC_SLL_CP2:
4974 shift_max = 32;
4975 goto do_shift;
4976 case OPC_SRL_CP2:
4977 shift_max = 32;
4978 goto do_shift;
4979 case OPC_SRA_CP2:
4980 shift_max = 32;
4981 goto do_shift;
4982 case OPC_DSLL_CP2:
4983 shift_max = 64;
4984 goto do_shift;
4985 case OPC_DSRL_CP2:
4986 shift_max = 64;
4987 goto do_shift;
4988 case OPC_DSRA_CP2:
4989 shift_max = 64;
4990 goto do_shift;
4991 do_shift:
4992 /* Make sure shift count isn't TCG undefined behaviour. */
4993 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4995 switch (opc) {
4996 case OPC_SLL_CP2:
4997 case OPC_DSLL_CP2:
4998 tcg_gen_shl_i64(t0, t0, t1);
4999 break;
5000 case OPC_SRA_CP2:
5001 case OPC_DSRA_CP2:
5002 /* Since SRA is UndefinedResult without sign-extended inputs,
5003 we can treat SRA and DSRA the same. */
5004 tcg_gen_sar_i64(t0, t0, t1);
5005 break;
5006 case OPC_SRL_CP2:
5007 /* We want to shift in zeros for SRL; zero-extend first. */
5008 tcg_gen_ext32u_i64(t0, t0);
5009 /* FALLTHRU */
5010 case OPC_DSRL_CP2:
5011 tcg_gen_shr_i64(t0, t0, t1);
5012 break;
5015 if (shift_max == 32) {
5016 tcg_gen_ext32s_i64(t0, t0);
5019 /* Shifts larger than MAX produce zero. */
5020 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5021 tcg_gen_neg_i64(t1, t1);
5022 tcg_gen_and_i64(t0, t0, t1);
5023 break;
5025 case OPC_ADD_CP2:
5026 case OPC_DADD_CP2:
5028 TCGv_i64 t2 = tcg_temp_new_i64();
5029 TCGLabel *lab = gen_new_label();
5031 tcg_gen_mov_i64(t2, t0);
5032 tcg_gen_add_i64(t0, t1, t2);
5033 if (opc == OPC_ADD_CP2) {
5034 tcg_gen_ext32s_i64(t0, t0);
5036 tcg_gen_xor_i64(t1, t1, t2);
5037 tcg_gen_xor_i64(t2, t2, t0);
5038 tcg_gen_andc_i64(t1, t2, t1);
5039 tcg_temp_free_i64(t2);
5040 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5041 generate_exception(ctx, EXCP_OVERFLOW);
5042 gen_set_label(lab);
5043 break;
5046 case OPC_SUB_CP2:
5047 case OPC_DSUB_CP2:
5049 TCGv_i64 t2 = tcg_temp_new_i64();
5050 TCGLabel *lab = gen_new_label();
5052 tcg_gen_mov_i64(t2, t0);
5053 tcg_gen_sub_i64(t0, t1, t2);
5054 if (opc == OPC_SUB_CP2) {
5055 tcg_gen_ext32s_i64(t0, t0);
5057 tcg_gen_xor_i64(t1, t1, t2);
5058 tcg_gen_xor_i64(t2, t2, t0);
5059 tcg_gen_and_i64(t1, t1, t2);
5060 tcg_temp_free_i64(t2);
5061 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5062 generate_exception(ctx, EXCP_OVERFLOW);
5063 gen_set_label(lab);
5064 break;
5067 case OPC_PMULUW:
5068 tcg_gen_ext32u_i64(t0, t0);
5069 tcg_gen_ext32u_i64(t1, t1);
5070 tcg_gen_mul_i64(t0, t0, t1);
5071 break;
5073 case OPC_SEQU_CP2:
5074 case OPC_SEQ_CP2:
5075 case OPC_SLTU_CP2:
5076 case OPC_SLT_CP2:
5077 case OPC_SLEU_CP2:
5078 case OPC_SLE_CP2:
5079 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5080 FD field is the CC field? */
5081 default:
5082 MIPS_INVAL("loongson_cp2");
5083 generate_exception_end(ctx, EXCP_RI);
5084 return;
5087 #undef LMI_HELPER
5088 #undef LMI_DIRECT
5090 gen_store_fpr64(ctx, t0, rd);
5092 tcg_temp_free_i64(t0);
5093 tcg_temp_free_i64(t1);
5096 /* Traps */
5097 static void gen_trap (DisasContext *ctx, uint32_t opc,
5098 int rs, int rt, int16_t imm)
5100 int cond;
5101 TCGv t0 = tcg_temp_new();
5102 TCGv t1 = tcg_temp_new();
5104 cond = 0;
5105 /* Load needed operands */
5106 switch (opc) {
5107 case OPC_TEQ:
5108 case OPC_TGE:
5109 case OPC_TGEU:
5110 case OPC_TLT:
5111 case OPC_TLTU:
5112 case OPC_TNE:
5113 /* Compare two registers */
5114 if (rs != rt) {
5115 gen_load_gpr(t0, rs);
5116 gen_load_gpr(t1, rt);
5117 cond = 1;
5119 break;
5120 case OPC_TEQI:
5121 case OPC_TGEI:
5122 case OPC_TGEIU:
5123 case OPC_TLTI:
5124 case OPC_TLTIU:
5125 case OPC_TNEI:
5126 /* Compare register to immediate */
5127 if (rs != 0 || imm != 0) {
5128 gen_load_gpr(t0, rs);
5129 tcg_gen_movi_tl(t1, (int32_t)imm);
5130 cond = 1;
5132 break;
5134 if (cond == 0) {
5135 switch (opc) {
5136 case OPC_TEQ: /* rs == rs */
5137 case OPC_TEQI: /* r0 == 0 */
5138 case OPC_TGE: /* rs >= rs */
5139 case OPC_TGEI: /* r0 >= 0 */
5140 case OPC_TGEU: /* rs >= rs unsigned */
5141 case OPC_TGEIU: /* r0 >= 0 unsigned */
5142 /* Always trap */
5143 generate_exception_end(ctx, EXCP_TRAP);
5144 break;
5145 case OPC_TLT: /* rs < rs */
5146 case OPC_TLTI: /* r0 < 0 */
5147 case OPC_TLTU: /* rs < rs unsigned */
5148 case OPC_TLTIU: /* r0 < 0 unsigned */
5149 case OPC_TNE: /* rs != rs */
5150 case OPC_TNEI: /* r0 != 0 */
5151 /* Never trap: treat as NOP. */
5152 break;
5154 } else {
5155 TCGLabel *l1 = gen_new_label();
5157 switch (opc) {
5158 case OPC_TEQ:
5159 case OPC_TEQI:
5160 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5161 break;
5162 case OPC_TGE:
5163 case OPC_TGEI:
5164 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5165 break;
5166 case OPC_TGEU:
5167 case OPC_TGEIU:
5168 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5169 break;
5170 case OPC_TLT:
5171 case OPC_TLTI:
5172 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5173 break;
5174 case OPC_TLTU:
5175 case OPC_TLTIU:
5176 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5177 break;
5178 case OPC_TNE:
5179 case OPC_TNEI:
5180 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5181 break;
5183 generate_exception(ctx, EXCP_TRAP);
5184 gen_set_label(l1);
5186 tcg_temp_free(t0);
5187 tcg_temp_free(t1);
5190 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5192 if (unlikely(ctx->base.singlestep_enabled)) {
5193 return false;
5196 #ifndef CONFIG_USER_ONLY
5197 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5198 #else
5199 return true;
5200 #endif
5203 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5205 if (use_goto_tb(ctx, dest)) {
5206 tcg_gen_goto_tb(n);
5207 gen_save_pc(dest);
5208 tcg_gen_exit_tb(ctx->base.tb, n);
5209 } else {
5210 gen_save_pc(dest);
5211 if (ctx->base.singlestep_enabled) {
5212 save_cpu_state(ctx, 0);
5213 gen_helper_raise_exception_debug(cpu_env);
5215 tcg_gen_lookup_and_goto_ptr();
5219 /* Branches (before delay slot) */
5220 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5221 int insn_bytes,
5222 int rs, int rt, int32_t offset,
5223 int delayslot_size)
5225 target_ulong btgt = -1;
5226 int blink = 0;
5227 int bcond_compute = 0;
5228 TCGv t0 = tcg_temp_new();
5229 TCGv t1 = tcg_temp_new();
5231 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5232 #ifdef MIPS_DEBUG_DISAS
5233 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5234 TARGET_FMT_lx "\n", ctx->base.pc_next);
5235 #endif
5236 generate_exception_end(ctx, EXCP_RI);
5237 goto out;
5240 /* Load needed operands */
5241 switch (opc) {
5242 case OPC_BEQ:
5243 case OPC_BEQL:
5244 case OPC_BNE:
5245 case OPC_BNEL:
5246 /* Compare two registers */
5247 if (rs != rt) {
5248 gen_load_gpr(t0, rs);
5249 gen_load_gpr(t1, rt);
5250 bcond_compute = 1;
5252 btgt = ctx->base.pc_next + insn_bytes + offset;
5253 break;
5254 case OPC_BGEZ:
5255 case OPC_BGEZAL:
5256 case OPC_BGEZALL:
5257 case OPC_BGEZL:
5258 case OPC_BGTZ:
5259 case OPC_BGTZL:
5260 case OPC_BLEZ:
5261 case OPC_BLEZL:
5262 case OPC_BLTZ:
5263 case OPC_BLTZAL:
5264 case OPC_BLTZALL:
5265 case OPC_BLTZL:
5266 /* Compare to zero */
5267 if (rs != 0) {
5268 gen_load_gpr(t0, rs);
5269 bcond_compute = 1;
5271 btgt = ctx->base.pc_next + insn_bytes + offset;
5272 break;
5273 case OPC_BPOSGE32:
5274 #if defined(TARGET_MIPS64)
5275 case OPC_BPOSGE64:
5276 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5277 #else
5278 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5279 #endif
5280 bcond_compute = 1;
5281 btgt = ctx->base.pc_next + insn_bytes + offset;
5282 break;
5283 case OPC_J:
5284 case OPC_JAL:
5285 case OPC_JALX:
5286 /* Jump to immediate */
5287 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5288 (uint32_t)offset;
5289 break;
5290 case OPC_JR:
5291 case OPC_JALR:
5292 /* Jump to register */
5293 if (offset != 0 && offset != 16) {
5294 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5295 others are reserved. */
5296 MIPS_INVAL("jump hint");
5297 generate_exception_end(ctx, EXCP_RI);
5298 goto out;
5300 gen_load_gpr(btarget, rs);
5301 break;
5302 default:
5303 MIPS_INVAL("branch/jump");
5304 generate_exception_end(ctx, EXCP_RI);
5305 goto out;
5307 if (bcond_compute == 0) {
5308 /* No condition to be computed */
5309 switch (opc) {
5310 case OPC_BEQ: /* rx == rx */
5311 case OPC_BEQL: /* rx == rx likely */
5312 case OPC_BGEZ: /* 0 >= 0 */
5313 case OPC_BGEZL: /* 0 >= 0 likely */
5314 case OPC_BLEZ: /* 0 <= 0 */
5315 case OPC_BLEZL: /* 0 <= 0 likely */
5316 /* Always take */
5317 ctx->hflags |= MIPS_HFLAG_B;
5318 break;
5319 case OPC_BGEZAL: /* 0 >= 0 */
5320 case OPC_BGEZALL: /* 0 >= 0 likely */
5321 /* Always take and link */
5322 blink = 31;
5323 ctx->hflags |= MIPS_HFLAG_B;
5324 break;
5325 case OPC_BNE: /* rx != rx */
5326 case OPC_BGTZ: /* 0 > 0 */
5327 case OPC_BLTZ: /* 0 < 0 */
5328 /* Treat as NOP. */
5329 goto out;
5330 case OPC_BLTZAL: /* 0 < 0 */
5331 /* Handle as an unconditional branch to get correct delay
5332 slot checking. */
5333 blink = 31;
5334 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5335 ctx->hflags |= MIPS_HFLAG_B;
5336 break;
5337 case OPC_BLTZALL: /* 0 < 0 likely */
5338 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5339 /* Skip the instruction in the delay slot */
5340 ctx->base.pc_next += 4;
5341 goto out;
5342 case OPC_BNEL: /* rx != rx likely */
5343 case OPC_BGTZL: /* 0 > 0 likely */
5344 case OPC_BLTZL: /* 0 < 0 likely */
5345 /* Skip the instruction in the delay slot */
5346 ctx->base.pc_next += 4;
5347 goto out;
5348 case OPC_J:
5349 ctx->hflags |= MIPS_HFLAG_B;
5350 break;
5351 case OPC_JALX:
5352 ctx->hflags |= MIPS_HFLAG_BX;
5353 /* Fallthrough */
5354 case OPC_JAL:
5355 blink = 31;
5356 ctx->hflags |= MIPS_HFLAG_B;
5357 break;
5358 case OPC_JR:
5359 ctx->hflags |= MIPS_HFLAG_BR;
5360 break;
5361 case OPC_JALR:
5362 blink = rt;
5363 ctx->hflags |= MIPS_HFLAG_BR;
5364 break;
5365 default:
5366 MIPS_INVAL("branch/jump");
5367 generate_exception_end(ctx, EXCP_RI);
5368 goto out;
5370 } else {
5371 switch (opc) {
5372 case OPC_BEQ:
5373 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5374 goto not_likely;
5375 case OPC_BEQL:
5376 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5377 goto likely;
5378 case OPC_BNE:
5379 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5380 goto not_likely;
5381 case OPC_BNEL:
5382 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5383 goto likely;
5384 case OPC_BGEZ:
5385 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5386 goto not_likely;
5387 case OPC_BGEZL:
5388 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5389 goto likely;
5390 case OPC_BGEZAL:
5391 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5392 blink = 31;
5393 goto not_likely;
5394 case OPC_BGEZALL:
5395 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5396 blink = 31;
5397 goto likely;
5398 case OPC_BGTZ:
5399 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5400 goto not_likely;
5401 case OPC_BGTZL:
5402 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5403 goto likely;
5404 case OPC_BLEZ:
5405 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5406 goto not_likely;
5407 case OPC_BLEZL:
5408 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5409 goto likely;
5410 case OPC_BLTZ:
5411 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5412 goto not_likely;
5413 case OPC_BLTZL:
5414 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5415 goto likely;
5416 case OPC_BPOSGE32:
5417 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5418 goto not_likely;
5419 #if defined(TARGET_MIPS64)
5420 case OPC_BPOSGE64:
5421 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5422 goto not_likely;
5423 #endif
5424 case OPC_BLTZAL:
5425 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5426 blink = 31;
5427 not_likely:
5428 ctx->hflags |= MIPS_HFLAG_BC;
5429 break;
5430 case OPC_BLTZALL:
5431 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5432 blink = 31;
5433 likely:
5434 ctx->hflags |= MIPS_HFLAG_BL;
5435 break;
5436 default:
5437 MIPS_INVAL("conditional branch/jump");
5438 generate_exception_end(ctx, EXCP_RI);
5439 goto out;
5443 ctx->btarget = btgt;
5445 switch (delayslot_size) {
5446 case 2:
5447 ctx->hflags |= MIPS_HFLAG_BDS16;
5448 break;
5449 case 4:
5450 ctx->hflags |= MIPS_HFLAG_BDS32;
5451 break;
5454 if (blink > 0) {
5455 int post_delay = insn_bytes + delayslot_size;
5456 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5458 tcg_gen_movi_tl(cpu_gpr[blink],
5459 ctx->base.pc_next + post_delay + lowbit);
5462 out:
5463 if (insn_bytes == 2)
5464 ctx->hflags |= MIPS_HFLAG_B16;
5465 tcg_temp_free(t0);
5466 tcg_temp_free(t1);
5470 /* nanoMIPS Branches */
5471 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5472 int insn_bytes,
5473 int rs, int rt, int32_t offset)
5475 target_ulong btgt = -1;
5476 int bcond_compute = 0;
5477 TCGv t0 = tcg_temp_new();
5478 TCGv t1 = tcg_temp_new();
5480 /* Load needed operands */
5481 switch (opc) {
5482 case OPC_BEQ:
5483 case OPC_BNE:
5484 /* Compare two registers */
5485 if (rs != rt) {
5486 gen_load_gpr(t0, rs);
5487 gen_load_gpr(t1, rt);
5488 bcond_compute = 1;
5490 btgt = ctx->base.pc_next + insn_bytes + offset;
5491 break;
5492 case OPC_BGEZAL:
5493 /* Compare to zero */
5494 if (rs != 0) {
5495 gen_load_gpr(t0, rs);
5496 bcond_compute = 1;
5498 btgt = ctx->base.pc_next + insn_bytes + offset;
5499 break;
5500 case OPC_BPOSGE32:
5501 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5502 bcond_compute = 1;
5503 btgt = ctx->base.pc_next + insn_bytes + offset;
5504 break;
5505 case OPC_JR:
5506 case OPC_JALR:
5507 /* Jump to register */
5508 if (offset != 0 && offset != 16) {
5509 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5510 others are reserved. */
5511 MIPS_INVAL("jump hint");
5512 generate_exception_end(ctx, EXCP_RI);
5513 goto out;
5515 gen_load_gpr(btarget, rs);
5516 break;
5517 default:
5518 MIPS_INVAL("branch/jump");
5519 generate_exception_end(ctx, EXCP_RI);
5520 goto out;
5522 if (bcond_compute == 0) {
5523 /* No condition to be computed */
5524 switch (opc) {
5525 case OPC_BEQ: /* rx == rx */
5526 /* Always take */
5527 ctx->hflags |= MIPS_HFLAG_B;
5528 break;
5529 case OPC_BGEZAL: /* 0 >= 0 */
5530 /* Always take and link */
5531 tcg_gen_movi_tl(cpu_gpr[31],
5532 ctx->base.pc_next + insn_bytes);
5533 ctx->hflags |= MIPS_HFLAG_B;
5534 break;
5535 case OPC_BNE: /* rx != rx */
5536 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5537 /* Skip the instruction in the delay slot */
5538 ctx->base.pc_next += 4;
5539 goto out;
5540 case OPC_JR:
5541 ctx->hflags |= MIPS_HFLAG_BR;
5542 break;
5543 case OPC_JALR:
5544 if (rt > 0) {
5545 tcg_gen_movi_tl(cpu_gpr[rt],
5546 ctx->base.pc_next + insn_bytes);
5548 ctx->hflags |= MIPS_HFLAG_BR;
5549 break;
5550 default:
5551 MIPS_INVAL("branch/jump");
5552 generate_exception_end(ctx, EXCP_RI);
5553 goto out;
5555 } else {
5556 switch (opc) {
5557 case OPC_BEQ:
5558 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5559 goto not_likely;
5560 case OPC_BNE:
5561 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5562 goto not_likely;
5563 case OPC_BGEZAL:
5564 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5565 tcg_gen_movi_tl(cpu_gpr[31],
5566 ctx->base.pc_next + insn_bytes);
5567 goto not_likely;
5568 case OPC_BPOSGE32:
5569 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5570 not_likely:
5571 ctx->hflags |= MIPS_HFLAG_BC;
5572 break;
5573 default:
5574 MIPS_INVAL("conditional branch/jump");
5575 generate_exception_end(ctx, EXCP_RI);
5576 goto out;
5580 ctx->btarget = btgt;
5582 out:
5583 if (insn_bytes == 2) {
5584 ctx->hflags |= MIPS_HFLAG_B16;
5586 tcg_temp_free(t0);
5587 tcg_temp_free(t1);
5591 /* special3 bitfield operations */
5592 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5593 int rs, int lsb, int msb)
5595 TCGv t0 = tcg_temp_new();
5596 TCGv t1 = tcg_temp_new();
5598 gen_load_gpr(t1, rs);
5599 switch (opc) {
5600 case OPC_EXT:
5601 if (lsb + msb > 31) {
5602 goto fail;
5604 if (msb != 31) {
5605 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5606 } else {
5607 /* The two checks together imply that lsb == 0,
5608 so this is a simple sign-extension. */
5609 tcg_gen_ext32s_tl(t0, t1);
5611 break;
5612 #if defined(TARGET_MIPS64)
5613 case OPC_DEXTU:
5614 lsb += 32;
5615 goto do_dext;
5616 case OPC_DEXTM:
5617 msb += 32;
5618 goto do_dext;
5619 case OPC_DEXT:
5620 do_dext:
5621 if (lsb + msb > 63) {
5622 goto fail;
5624 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5625 break;
5626 #endif
5627 case OPC_INS:
5628 if (lsb > msb) {
5629 goto fail;
5631 gen_load_gpr(t0, rt);
5632 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5633 tcg_gen_ext32s_tl(t0, t0);
5634 break;
5635 #if defined(TARGET_MIPS64)
5636 case OPC_DINSU:
5637 lsb += 32;
5638 /* FALLTHRU */
5639 case OPC_DINSM:
5640 msb += 32;
5641 /* FALLTHRU */
5642 case OPC_DINS:
5643 if (lsb > msb) {
5644 goto fail;
5646 gen_load_gpr(t0, rt);
5647 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5648 break;
5649 #endif
5650 default:
5651 fail:
5652 MIPS_INVAL("bitops");
5653 generate_exception_end(ctx, EXCP_RI);
5654 tcg_temp_free(t0);
5655 tcg_temp_free(t1);
5656 return;
5658 gen_store_gpr(t0, rt);
5659 tcg_temp_free(t0);
5660 tcg_temp_free(t1);
5663 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5665 TCGv t0;
5667 if (rd == 0) {
5668 /* If no destination, treat it as a NOP. */
5669 return;
5672 t0 = tcg_temp_new();
5673 gen_load_gpr(t0, rt);
5674 switch (op2) {
5675 case OPC_WSBH:
5677 TCGv t1 = tcg_temp_new();
5678 TCGv t2 = tcg_const_tl(0x00FF00FF);
5680 tcg_gen_shri_tl(t1, t0, 8);
5681 tcg_gen_and_tl(t1, t1, t2);
5682 tcg_gen_and_tl(t0, t0, t2);
5683 tcg_gen_shli_tl(t0, t0, 8);
5684 tcg_gen_or_tl(t0, t0, t1);
5685 tcg_temp_free(t2);
5686 tcg_temp_free(t1);
5687 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5689 break;
5690 case OPC_SEB:
5691 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5692 break;
5693 case OPC_SEH:
5694 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5695 break;
5696 #if defined(TARGET_MIPS64)
5697 case OPC_DSBH:
5699 TCGv t1 = tcg_temp_new();
5700 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5702 tcg_gen_shri_tl(t1, t0, 8);
5703 tcg_gen_and_tl(t1, t1, t2);
5704 tcg_gen_and_tl(t0, t0, t2);
5705 tcg_gen_shli_tl(t0, t0, 8);
5706 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5707 tcg_temp_free(t2);
5708 tcg_temp_free(t1);
5710 break;
5711 case OPC_DSHD:
5713 TCGv t1 = tcg_temp_new();
5714 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5716 tcg_gen_shri_tl(t1, t0, 16);
5717 tcg_gen_and_tl(t1, t1, t2);
5718 tcg_gen_and_tl(t0, t0, t2);
5719 tcg_gen_shli_tl(t0, t0, 16);
5720 tcg_gen_or_tl(t0, t0, t1);
5721 tcg_gen_shri_tl(t1, t0, 32);
5722 tcg_gen_shli_tl(t0, t0, 32);
5723 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5724 tcg_temp_free(t2);
5725 tcg_temp_free(t1);
5727 break;
5728 #endif
5729 default:
5730 MIPS_INVAL("bsfhl");
5731 generate_exception_end(ctx, EXCP_RI);
5732 tcg_temp_free(t0);
5733 return;
5735 tcg_temp_free(t0);
5738 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
5739 int imm2)
5741 TCGv t0;
5742 TCGv t1;
5743 if (rd == 0) {
5744 /* Treat as NOP. */
5745 return;
5747 t0 = tcg_temp_new();
5748 t1 = tcg_temp_new();
5749 gen_load_gpr(t0, rs);
5750 gen_load_gpr(t1, rt);
5751 tcg_gen_shli_tl(t0, t0, imm2 + 1);
5752 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
5753 if (opc == OPC_LSA) {
5754 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5757 tcg_temp_free(t1);
5758 tcg_temp_free(t0);
5760 return;
5763 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5764 int rt, int bits)
5766 TCGv t0;
5767 if (rd == 0) {
5768 /* Treat as NOP. */
5769 return;
5771 t0 = tcg_temp_new();
5772 if (bits == 0 || bits == wordsz) {
5773 if (bits == 0) {
5774 gen_load_gpr(t0, rt);
5775 } else {
5776 gen_load_gpr(t0, rs);
5778 switch (wordsz) {
5779 case 32:
5780 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5781 break;
5782 #if defined(TARGET_MIPS64)
5783 case 64:
5784 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5785 break;
5786 #endif
5788 } else {
5789 TCGv t1 = tcg_temp_new();
5790 gen_load_gpr(t0, rt);
5791 gen_load_gpr(t1, rs);
5792 switch (wordsz) {
5793 case 32:
5795 TCGv_i64 t2 = tcg_temp_new_i64();
5796 tcg_gen_concat_tl_i64(t2, t1, t0);
5797 tcg_gen_shri_i64(t2, t2, 32 - bits);
5798 gen_move_low32(cpu_gpr[rd], t2);
5799 tcg_temp_free_i64(t2);
5801 break;
5802 #if defined(TARGET_MIPS64)
5803 case 64:
5804 tcg_gen_shli_tl(t0, t0, bits);
5805 tcg_gen_shri_tl(t1, t1, 64 - bits);
5806 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5807 break;
5808 #endif
5810 tcg_temp_free(t1);
5813 tcg_temp_free(t0);
5816 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5817 int bp)
5819 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5822 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5823 int shift)
5825 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5828 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5830 TCGv t0;
5831 if (rd == 0) {
5832 /* Treat as NOP. */
5833 return;
5835 t0 = tcg_temp_new();
5836 gen_load_gpr(t0, rt);
5837 switch (opc) {
5838 case OPC_BITSWAP:
5839 gen_helper_bitswap(cpu_gpr[rd], t0);
5840 break;
5841 #if defined(TARGET_MIPS64)
5842 case OPC_DBITSWAP:
5843 gen_helper_dbitswap(cpu_gpr[rd], t0);
5844 break;
5845 #endif
5847 tcg_temp_free(t0);
5850 #ifndef CONFIG_USER_ONLY
5851 /* CP0 (MMU and control) */
5852 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5854 TCGv_i64 t0 = tcg_temp_new_i64();
5855 TCGv_i64 t1 = tcg_temp_new_i64();
5857 tcg_gen_ext_tl_i64(t0, arg);
5858 tcg_gen_ld_i64(t1, cpu_env, off);
5859 #if defined(TARGET_MIPS64)
5860 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5861 #else
5862 tcg_gen_concat32_i64(t1, t1, t0);
5863 #endif
5864 tcg_gen_st_i64(t1, cpu_env, off);
5865 tcg_temp_free_i64(t1);
5866 tcg_temp_free_i64(t0);
5869 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5871 TCGv_i64 t0 = tcg_temp_new_i64();
5872 TCGv_i64 t1 = tcg_temp_new_i64();
5874 tcg_gen_ext_tl_i64(t0, arg);
5875 tcg_gen_ld_i64(t1, cpu_env, off);
5876 tcg_gen_concat32_i64(t1, t1, t0);
5877 tcg_gen_st_i64(t1, cpu_env, off);
5878 tcg_temp_free_i64(t1);
5879 tcg_temp_free_i64(t0);
5882 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5884 TCGv_i64 t0 = tcg_temp_new_i64();
5886 tcg_gen_ld_i64(t0, cpu_env, off);
5887 #if defined(TARGET_MIPS64)
5888 tcg_gen_shri_i64(t0, t0, 30);
5889 #else
5890 tcg_gen_shri_i64(t0, t0, 32);
5891 #endif
5892 gen_move_low32(arg, t0);
5893 tcg_temp_free_i64(t0);
5896 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5898 TCGv_i64 t0 = tcg_temp_new_i64();
5900 tcg_gen_ld_i64(t0, cpu_env, off);
5901 tcg_gen_shri_i64(t0, t0, 32 + shift);
5902 gen_move_low32(arg, t0);
5903 tcg_temp_free_i64(t0);
5906 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5908 TCGv_i32 t0 = tcg_temp_new_i32();
5910 tcg_gen_ld_i32(t0, cpu_env, off);
5911 tcg_gen_ext_i32_tl(arg, t0);
5912 tcg_temp_free_i32(t0);
5915 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5917 tcg_gen_ld_tl(arg, cpu_env, off);
5918 tcg_gen_ext32s_tl(arg, arg);
5921 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5923 TCGv_i32 t0 = tcg_temp_new_i32();
5925 tcg_gen_trunc_tl_i32(t0, arg);
5926 tcg_gen_st_i32(t0, cpu_env, off);
5927 tcg_temp_free_i32(t0);
5930 #define CP0_CHECK(c) \
5931 do { \
5932 if (!(c)) { \
5933 goto cp0_unimplemented; \
5935 } while (0)
5937 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5939 const char *rn = "invalid";
5941 switch (reg) {
5942 case 2:
5943 switch (sel) {
5944 case 0:
5945 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5946 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5947 rn = "EntryLo0";
5948 break;
5949 default:
5950 goto cp0_unimplemented;
5952 break;
5953 case 3:
5954 switch (sel) {
5955 case 0:
5956 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5957 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5958 rn = "EntryLo1";
5959 break;
5960 default:
5961 goto cp0_unimplemented;
5963 break;
5964 case 17:
5965 switch (sel) {
5966 case 0:
5967 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5968 ctx->CP0_LLAddr_shift);
5969 rn = "LLAddr";
5970 break;
5971 case 1:
5972 CP0_CHECK(ctx->mrp);
5973 gen_helper_mfhc0_maar(arg, cpu_env);
5974 rn = "MAAR";
5975 break;
5976 default:
5977 goto cp0_unimplemented;
5979 break;
5980 case 28:
5981 switch (sel) {
5982 case 0:
5983 case 2:
5984 case 4:
5985 case 6:
5986 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5987 rn = "TagLo";
5988 break;
5989 default:
5990 goto cp0_unimplemented;
5992 break;
5993 default:
5994 goto cp0_unimplemented;
5996 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5997 return;
5999 cp0_unimplemented:
6000 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6001 tcg_gen_movi_tl(arg, 0);
6004 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6006 const char *rn = "invalid";
6007 uint64_t mask = ctx->PAMask >> 36;
6009 switch (reg) {
6010 case 2:
6011 switch (sel) {
6012 case 0:
6013 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6014 tcg_gen_andi_tl(arg, arg, mask);
6015 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6016 rn = "EntryLo0";
6017 break;
6018 default:
6019 goto cp0_unimplemented;
6021 break;
6022 case 3:
6023 switch (sel) {
6024 case 0:
6025 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6026 tcg_gen_andi_tl(arg, arg, mask);
6027 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6028 rn = "EntryLo1";
6029 break;
6030 default:
6031 goto cp0_unimplemented;
6033 break;
6034 case 17:
6035 switch (sel) {
6036 case 0:
6037 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6038 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6039 relevant for modern MIPS cores supporting MTHC0, therefore
6040 treating MTHC0 to LLAddr as NOP. */
6041 rn = "LLAddr";
6042 break;
6043 case 1:
6044 CP0_CHECK(ctx->mrp);
6045 gen_helper_mthc0_maar(cpu_env, arg);
6046 rn = "MAAR";
6047 break;
6048 default:
6049 goto cp0_unimplemented;
6051 break;
6052 case 28:
6053 switch (sel) {
6054 case 0:
6055 case 2:
6056 case 4:
6057 case 6:
6058 tcg_gen_andi_tl(arg, arg, mask);
6059 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6060 rn = "TagLo";
6061 break;
6062 default:
6063 goto cp0_unimplemented;
6065 break;
6066 default:
6067 goto cp0_unimplemented;
6069 trace_mips_translate_c0("mthc0", rn, reg, sel);
6071 cp0_unimplemented:
6072 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6075 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6077 if (ctx->insn_flags & ISA_MIPS32R6) {
6078 tcg_gen_movi_tl(arg, 0);
6079 } else {
6080 tcg_gen_movi_tl(arg, ~0);
6084 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6086 const char *rn = "invalid";
6088 if (sel != 0)
6089 check_insn(ctx, ISA_MIPS32);
6091 switch (reg) {
6092 case 0:
6093 switch (sel) {
6094 case 0:
6095 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6096 rn = "Index";
6097 break;
6098 case 1:
6099 CP0_CHECK(ctx->insn_flags & ASE_MT);
6100 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6101 rn = "MVPControl";
6102 break;
6103 case 2:
6104 CP0_CHECK(ctx->insn_flags & ASE_MT);
6105 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6106 rn = "MVPConf0";
6107 break;
6108 case 3:
6109 CP0_CHECK(ctx->insn_flags & ASE_MT);
6110 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6111 rn = "MVPConf1";
6112 break;
6113 case 4:
6114 CP0_CHECK(ctx->vp);
6115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6116 rn = "VPControl";
6117 break;
6118 default:
6119 goto cp0_unimplemented;
6121 break;
6122 case 1:
6123 switch (sel) {
6124 case 0:
6125 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6126 gen_helper_mfc0_random(arg, cpu_env);
6127 rn = "Random";
6128 break;
6129 case 1:
6130 CP0_CHECK(ctx->insn_flags & ASE_MT);
6131 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6132 rn = "VPEControl";
6133 break;
6134 case 2:
6135 CP0_CHECK(ctx->insn_flags & ASE_MT);
6136 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6137 rn = "VPEConf0";
6138 break;
6139 case 3:
6140 CP0_CHECK(ctx->insn_flags & ASE_MT);
6141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6142 rn = "VPEConf1";
6143 break;
6144 case 4:
6145 CP0_CHECK(ctx->insn_flags & ASE_MT);
6146 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6147 rn = "YQMask";
6148 break;
6149 case 5:
6150 CP0_CHECK(ctx->insn_flags & ASE_MT);
6151 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6152 rn = "VPESchedule";
6153 break;
6154 case 6:
6155 CP0_CHECK(ctx->insn_flags & ASE_MT);
6156 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6157 rn = "VPEScheFBack";
6158 break;
6159 case 7:
6160 CP0_CHECK(ctx->insn_flags & ASE_MT);
6161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6162 rn = "VPEOpt";
6163 break;
6164 default:
6165 goto cp0_unimplemented;
6167 break;
6168 case 2:
6169 switch (sel) {
6170 case 0:
6172 TCGv_i64 tmp = tcg_temp_new_i64();
6173 tcg_gen_ld_i64(tmp, cpu_env,
6174 offsetof(CPUMIPSState, CP0_EntryLo0));
6175 #if defined(TARGET_MIPS64)
6176 if (ctx->rxi) {
6177 /* Move RI/XI fields to bits 31:30 */
6178 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6179 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6181 #endif
6182 gen_move_low32(arg, tmp);
6183 tcg_temp_free_i64(tmp);
6185 rn = "EntryLo0";
6186 break;
6187 case 1:
6188 CP0_CHECK(ctx->insn_flags & ASE_MT);
6189 gen_helper_mfc0_tcstatus(arg, cpu_env);
6190 rn = "TCStatus";
6191 break;
6192 case 2:
6193 CP0_CHECK(ctx->insn_flags & ASE_MT);
6194 gen_helper_mfc0_tcbind(arg, cpu_env);
6195 rn = "TCBind";
6196 break;
6197 case 3:
6198 CP0_CHECK(ctx->insn_flags & ASE_MT);
6199 gen_helper_mfc0_tcrestart(arg, cpu_env);
6200 rn = "TCRestart";
6201 break;
6202 case 4:
6203 CP0_CHECK(ctx->insn_flags & ASE_MT);
6204 gen_helper_mfc0_tchalt(arg, cpu_env);
6205 rn = "TCHalt";
6206 break;
6207 case 5:
6208 CP0_CHECK(ctx->insn_flags & ASE_MT);
6209 gen_helper_mfc0_tccontext(arg, cpu_env);
6210 rn = "TCContext";
6211 break;
6212 case 6:
6213 CP0_CHECK(ctx->insn_flags & ASE_MT);
6214 gen_helper_mfc0_tcschedule(arg, cpu_env);
6215 rn = "TCSchedule";
6216 break;
6217 case 7:
6218 CP0_CHECK(ctx->insn_flags & ASE_MT);
6219 gen_helper_mfc0_tcschefback(arg, cpu_env);
6220 rn = "TCScheFBack";
6221 break;
6222 default:
6223 goto cp0_unimplemented;
6225 break;
6226 case 3:
6227 switch (sel) {
6228 case 0:
6230 TCGv_i64 tmp = tcg_temp_new_i64();
6231 tcg_gen_ld_i64(tmp, cpu_env,
6232 offsetof(CPUMIPSState, CP0_EntryLo1));
6233 #if defined(TARGET_MIPS64)
6234 if (ctx->rxi) {
6235 /* Move RI/XI fields to bits 31:30 */
6236 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6237 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6239 #endif
6240 gen_move_low32(arg, tmp);
6241 tcg_temp_free_i64(tmp);
6243 rn = "EntryLo1";
6244 break;
6245 case 1:
6246 CP0_CHECK(ctx->vp);
6247 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6248 rn = "GlobalNumber";
6249 break;
6250 default:
6251 goto cp0_unimplemented;
6253 break;
6254 case 4:
6255 switch (sel) {
6256 case 0:
6257 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6258 tcg_gen_ext32s_tl(arg, arg);
6259 rn = "Context";
6260 break;
6261 case 1:
6262 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6263 rn = "ContextConfig";
6264 goto cp0_unimplemented;
6265 case 2:
6266 CP0_CHECK(ctx->ulri);
6267 tcg_gen_ld_tl(arg, cpu_env,
6268 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6269 tcg_gen_ext32s_tl(arg, arg);
6270 rn = "UserLocal";
6271 break;
6272 default:
6273 goto cp0_unimplemented;
6275 break;
6276 case 5:
6277 switch (sel) {
6278 case 0:
6279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6280 rn = "PageMask";
6281 break;
6282 case 1:
6283 check_insn(ctx, ISA_MIPS32R2);
6284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6285 rn = "PageGrain";
6286 break;
6287 case 2:
6288 CP0_CHECK(ctx->sc);
6289 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6290 tcg_gen_ext32s_tl(arg, arg);
6291 rn = "SegCtl0";
6292 break;
6293 case 3:
6294 CP0_CHECK(ctx->sc);
6295 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6296 tcg_gen_ext32s_tl(arg, arg);
6297 rn = "SegCtl1";
6298 break;
6299 case 4:
6300 CP0_CHECK(ctx->sc);
6301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6302 tcg_gen_ext32s_tl(arg, arg);
6303 rn = "SegCtl2";
6304 break;
6305 case 5:
6306 check_pw(ctx);
6307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6308 rn = "PWBase";
6309 break;
6310 case 6:
6311 check_pw(ctx);
6312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6313 rn = "PWField";
6314 break;
6315 case 7:
6316 check_pw(ctx);
6317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6318 rn = "PWSize";
6319 break;
6320 default:
6321 goto cp0_unimplemented;
6323 break;
6324 case 6:
6325 switch (sel) {
6326 case 0:
6327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6328 rn = "Wired";
6329 break;
6330 case 1:
6331 check_insn(ctx, ISA_MIPS32R2);
6332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6333 rn = "SRSConf0";
6334 break;
6335 case 2:
6336 check_insn(ctx, ISA_MIPS32R2);
6337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6338 rn = "SRSConf1";
6339 break;
6340 case 3:
6341 check_insn(ctx, ISA_MIPS32R2);
6342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6343 rn = "SRSConf2";
6344 break;
6345 case 4:
6346 check_insn(ctx, ISA_MIPS32R2);
6347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6348 rn = "SRSConf3";
6349 break;
6350 case 5:
6351 check_insn(ctx, ISA_MIPS32R2);
6352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6353 rn = "SRSConf4";
6354 break;
6355 case 6:
6356 check_pw(ctx);
6357 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6358 rn = "PWCtl";
6359 break;
6360 default:
6361 goto cp0_unimplemented;
6363 break;
6364 case 7:
6365 switch (sel) {
6366 case 0:
6367 check_insn(ctx, ISA_MIPS32R2);
6368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6369 rn = "HWREna";
6370 break;
6371 default:
6372 goto cp0_unimplemented;
6374 break;
6375 case 8:
6376 switch (sel) {
6377 case 0:
6378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6379 tcg_gen_ext32s_tl(arg, arg);
6380 rn = "BadVAddr";
6381 break;
6382 case 1:
6383 CP0_CHECK(ctx->bi);
6384 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6385 rn = "BadInstr";
6386 break;
6387 case 2:
6388 CP0_CHECK(ctx->bp);
6389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6390 rn = "BadInstrP";
6391 break;
6392 case 3:
6393 CP0_CHECK(ctx->bi);
6394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6395 tcg_gen_andi_tl(arg, arg, ~0xffff);
6396 rn = "BadInstrX";
6397 break;
6398 default:
6399 goto cp0_unimplemented;
6401 break;
6402 case 9:
6403 switch (sel) {
6404 case 0:
6405 /* Mark as an IO operation because we read the time. */
6406 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6407 gen_io_start();
6409 gen_helper_mfc0_count(arg, cpu_env);
6410 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6411 gen_io_end();
6413 /* Break the TB to be able to take timer interrupts immediately
6414 after reading count. DISAS_STOP isn't sufficient, we need to
6415 ensure we break completely out of translated code. */
6416 gen_save_pc(ctx->base.pc_next + 4);
6417 ctx->base.is_jmp = DISAS_EXIT;
6418 rn = "Count";
6419 break;
6420 /* 6,7 are implementation dependent */
6421 default:
6422 goto cp0_unimplemented;
6424 break;
6425 case 10:
6426 switch (sel) {
6427 case 0:
6428 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6429 tcg_gen_ext32s_tl(arg, arg);
6430 rn = "EntryHi";
6431 break;
6432 default:
6433 goto cp0_unimplemented;
6435 break;
6436 case 11:
6437 switch (sel) {
6438 case 0:
6439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6440 rn = "Compare";
6441 break;
6442 /* 6,7 are implementation dependent */
6443 default:
6444 goto cp0_unimplemented;
6446 break;
6447 case 12:
6448 switch (sel) {
6449 case 0:
6450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6451 rn = "Status";
6452 break;
6453 case 1:
6454 check_insn(ctx, ISA_MIPS32R2);
6455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6456 rn = "IntCtl";
6457 break;
6458 case 2:
6459 check_insn(ctx, ISA_MIPS32R2);
6460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6461 rn = "SRSCtl";
6462 break;
6463 case 3:
6464 check_insn(ctx, ISA_MIPS32R2);
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6466 rn = "SRSMap";
6467 break;
6468 default:
6469 goto cp0_unimplemented;
6471 break;
6472 case 13:
6473 switch (sel) {
6474 case 0:
6475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6476 rn = "Cause";
6477 break;
6478 default:
6479 goto cp0_unimplemented;
6481 break;
6482 case 14:
6483 switch (sel) {
6484 case 0:
6485 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6486 tcg_gen_ext32s_tl(arg, arg);
6487 rn = "EPC";
6488 break;
6489 default:
6490 goto cp0_unimplemented;
6492 break;
6493 case 15:
6494 switch (sel) {
6495 case 0:
6496 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6497 rn = "PRid";
6498 break;
6499 case 1:
6500 check_insn(ctx, ISA_MIPS32R2);
6501 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6502 tcg_gen_ext32s_tl(arg, arg);
6503 rn = "EBase";
6504 break;
6505 case 3:
6506 check_insn(ctx, ISA_MIPS32R2);
6507 CP0_CHECK(ctx->cmgcr);
6508 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6509 tcg_gen_ext32s_tl(arg, arg);
6510 rn = "CMGCRBase";
6511 break;
6512 default:
6513 goto cp0_unimplemented;
6515 break;
6516 case 16:
6517 switch (sel) {
6518 case 0:
6519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6520 rn = "Config";
6521 break;
6522 case 1:
6523 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6524 rn = "Config1";
6525 break;
6526 case 2:
6527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6528 rn = "Config2";
6529 break;
6530 case 3:
6531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6532 rn = "Config3";
6533 break;
6534 case 4:
6535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6536 rn = "Config4";
6537 break;
6538 case 5:
6539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6540 rn = "Config5";
6541 break;
6542 /* 6,7 are implementation dependent */
6543 case 6:
6544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6545 rn = "Config6";
6546 break;
6547 case 7:
6548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6549 rn = "Config7";
6550 break;
6551 default:
6552 goto cp0_unimplemented;
6554 break;
6555 case 17:
6556 switch (sel) {
6557 case 0:
6558 gen_helper_mfc0_lladdr(arg, cpu_env);
6559 rn = "LLAddr";
6560 break;
6561 case 1:
6562 CP0_CHECK(ctx->mrp);
6563 gen_helper_mfc0_maar(arg, cpu_env);
6564 rn = "MAAR";
6565 break;
6566 case 2:
6567 CP0_CHECK(ctx->mrp);
6568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6569 rn = "MAARI";
6570 break;
6571 default:
6572 goto cp0_unimplemented;
6574 break;
6575 case 18:
6576 switch (sel) {
6577 case 0:
6578 case 1:
6579 case 2:
6580 case 3:
6581 case 4:
6582 case 5:
6583 case 6:
6584 case 7:
6585 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6586 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6587 rn = "WatchLo";
6588 break;
6589 default:
6590 goto cp0_unimplemented;
6592 break;
6593 case 19:
6594 switch (sel) {
6595 case 0:
6596 case 1:
6597 case 2:
6598 case 3:
6599 case 4:
6600 case 5:
6601 case 6:
6602 case 7:
6603 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6604 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6605 rn = "WatchHi";
6606 break;
6607 default:
6608 goto cp0_unimplemented;
6610 break;
6611 case 20:
6612 switch (sel) {
6613 case 0:
6614 #if defined(TARGET_MIPS64)
6615 check_insn(ctx, ISA_MIPS3);
6616 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6617 tcg_gen_ext32s_tl(arg, arg);
6618 rn = "XContext";
6619 break;
6620 #endif
6621 default:
6622 goto cp0_unimplemented;
6624 break;
6625 case 21:
6626 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6627 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6628 switch (sel) {
6629 case 0:
6630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6631 rn = "Framemask";
6632 break;
6633 default:
6634 goto cp0_unimplemented;
6636 break;
6637 case 22:
6638 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6639 rn = "'Diagnostic"; /* implementation dependent */
6640 break;
6641 case 23:
6642 switch (sel) {
6643 case 0:
6644 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6645 rn = "Debug";
6646 break;
6647 case 1:
6648 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6649 rn = "TraceControl";
6650 goto cp0_unimplemented;
6651 case 2:
6652 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6653 rn = "TraceControl2";
6654 goto cp0_unimplemented;
6655 case 3:
6656 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
6657 rn = "UserTraceData";
6658 goto cp0_unimplemented;
6659 case 4:
6660 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
6661 rn = "TraceBPC";
6662 goto cp0_unimplemented;
6663 default:
6664 goto cp0_unimplemented;
6666 break;
6667 case 24:
6668 switch (sel) {
6669 case 0:
6670 /* EJTAG support */
6671 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6672 tcg_gen_ext32s_tl(arg, arg);
6673 rn = "DEPC";
6674 break;
6675 default:
6676 goto cp0_unimplemented;
6678 break;
6679 case 25:
6680 switch (sel) {
6681 case 0:
6682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6683 rn = "Performance0";
6684 break;
6685 case 1:
6686 // gen_helper_mfc0_performance1(arg);
6687 rn = "Performance1";
6688 goto cp0_unimplemented;
6689 case 2:
6690 // gen_helper_mfc0_performance2(arg);
6691 rn = "Performance2";
6692 goto cp0_unimplemented;
6693 case 3:
6694 // gen_helper_mfc0_performance3(arg);
6695 rn = "Performance3";
6696 goto cp0_unimplemented;
6697 case 4:
6698 // gen_helper_mfc0_performance4(arg);
6699 rn = "Performance4";
6700 goto cp0_unimplemented;
6701 case 5:
6702 // gen_helper_mfc0_performance5(arg);
6703 rn = "Performance5";
6704 goto cp0_unimplemented;
6705 case 6:
6706 // gen_helper_mfc0_performance6(arg);
6707 rn = "Performance6";
6708 goto cp0_unimplemented;
6709 case 7:
6710 // gen_helper_mfc0_performance7(arg);
6711 rn = "Performance7";
6712 goto cp0_unimplemented;
6713 default:
6714 goto cp0_unimplemented;
6716 break;
6717 case 26:
6718 switch (sel) {
6719 case 0:
6720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6721 rn = "ErrCtl";
6722 break;
6723 default:
6724 goto cp0_unimplemented;
6726 break;
6727 case 27:
6728 switch (sel) {
6729 case 0:
6730 case 1:
6731 case 2:
6732 case 3:
6733 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6734 rn = "CacheErr";
6735 break;
6736 default:
6737 goto cp0_unimplemented;
6739 break;
6740 case 28:
6741 switch (sel) {
6742 case 0:
6743 case 2:
6744 case 4:
6745 case 6:
6747 TCGv_i64 tmp = tcg_temp_new_i64();
6748 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6749 gen_move_low32(arg, tmp);
6750 tcg_temp_free_i64(tmp);
6752 rn = "TagLo";
6753 break;
6754 case 1:
6755 case 3:
6756 case 5:
6757 case 7:
6758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6759 rn = "DataLo";
6760 break;
6761 default:
6762 goto cp0_unimplemented;
6764 break;
6765 case 29:
6766 switch (sel) {
6767 case 0:
6768 case 2:
6769 case 4:
6770 case 6:
6771 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6772 rn = "TagHi";
6773 break;
6774 case 1:
6775 case 3:
6776 case 5:
6777 case 7:
6778 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6779 rn = "DataHi";
6780 break;
6781 default:
6782 goto cp0_unimplemented;
6784 break;
6785 case 30:
6786 switch (sel) {
6787 case 0:
6788 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6789 tcg_gen_ext32s_tl(arg, arg);
6790 rn = "ErrorEPC";
6791 break;
6792 default:
6793 goto cp0_unimplemented;
6795 break;
6796 case 31:
6797 switch (sel) {
6798 case 0:
6799 /* EJTAG support */
6800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6801 rn = "DESAVE";
6802 break;
6803 case 2:
6804 case 3:
6805 case 4:
6806 case 5:
6807 case 6:
6808 case 7:
6809 CP0_CHECK(ctx->kscrexist & (1 << sel));
6810 tcg_gen_ld_tl(arg, cpu_env,
6811 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6812 tcg_gen_ext32s_tl(arg, arg);
6813 rn = "KScratch";
6814 break;
6815 default:
6816 goto cp0_unimplemented;
6818 break;
6819 default:
6820 goto cp0_unimplemented;
6822 trace_mips_translate_c0("mfc0", rn, reg, sel);
6823 return;
6825 cp0_unimplemented:
6826 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6827 gen_mfc0_unimplemented(ctx, arg);
6830 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6832 const char *rn = "invalid";
6834 if (sel != 0)
6835 check_insn(ctx, ISA_MIPS32);
6837 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6838 gen_io_start();
6841 switch (reg) {
6842 case 0:
6843 switch (sel) {
6844 case 0:
6845 gen_helper_mtc0_index(cpu_env, arg);
6846 rn = "Index";
6847 break;
6848 case 1:
6849 CP0_CHECK(ctx->insn_flags & ASE_MT);
6850 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6851 rn = "MVPControl";
6852 break;
6853 case 2:
6854 CP0_CHECK(ctx->insn_flags & ASE_MT);
6855 /* ignored */
6856 rn = "MVPConf0";
6857 break;
6858 case 3:
6859 CP0_CHECK(ctx->insn_flags & ASE_MT);
6860 /* ignored */
6861 rn = "MVPConf1";
6862 break;
6863 case 4:
6864 CP0_CHECK(ctx->vp);
6865 /* ignored */
6866 rn = "VPControl";
6867 break;
6868 default:
6869 goto cp0_unimplemented;
6871 break;
6872 case 1:
6873 switch (sel) {
6874 case 0:
6875 /* ignored */
6876 rn = "Random";
6877 break;
6878 case 1:
6879 CP0_CHECK(ctx->insn_flags & ASE_MT);
6880 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6881 rn = "VPEControl";
6882 break;
6883 case 2:
6884 CP0_CHECK(ctx->insn_flags & ASE_MT);
6885 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6886 rn = "VPEConf0";
6887 break;
6888 case 3:
6889 CP0_CHECK(ctx->insn_flags & ASE_MT);
6890 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6891 rn = "VPEConf1";
6892 break;
6893 case 4:
6894 CP0_CHECK(ctx->insn_flags & ASE_MT);
6895 gen_helper_mtc0_yqmask(cpu_env, arg);
6896 rn = "YQMask";
6897 break;
6898 case 5:
6899 CP0_CHECK(ctx->insn_flags & ASE_MT);
6900 tcg_gen_st_tl(arg, cpu_env,
6901 offsetof(CPUMIPSState, CP0_VPESchedule));
6902 rn = "VPESchedule";
6903 break;
6904 case 6:
6905 CP0_CHECK(ctx->insn_flags & ASE_MT);
6906 tcg_gen_st_tl(arg, cpu_env,
6907 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6908 rn = "VPEScheFBack";
6909 break;
6910 case 7:
6911 CP0_CHECK(ctx->insn_flags & ASE_MT);
6912 gen_helper_mtc0_vpeopt(cpu_env, arg);
6913 rn = "VPEOpt";
6914 break;
6915 default:
6916 goto cp0_unimplemented;
6918 break;
6919 case 2:
6920 switch (sel) {
6921 case 0:
6922 gen_helper_mtc0_entrylo0(cpu_env, arg);
6923 rn = "EntryLo0";
6924 break;
6925 case 1:
6926 CP0_CHECK(ctx->insn_flags & ASE_MT);
6927 gen_helper_mtc0_tcstatus(cpu_env, arg);
6928 rn = "TCStatus";
6929 break;
6930 case 2:
6931 CP0_CHECK(ctx->insn_flags & ASE_MT);
6932 gen_helper_mtc0_tcbind(cpu_env, arg);
6933 rn = "TCBind";
6934 break;
6935 case 3:
6936 CP0_CHECK(ctx->insn_flags & ASE_MT);
6937 gen_helper_mtc0_tcrestart(cpu_env, arg);
6938 rn = "TCRestart";
6939 break;
6940 case 4:
6941 CP0_CHECK(ctx->insn_flags & ASE_MT);
6942 gen_helper_mtc0_tchalt(cpu_env, arg);
6943 rn = "TCHalt";
6944 break;
6945 case 5:
6946 CP0_CHECK(ctx->insn_flags & ASE_MT);
6947 gen_helper_mtc0_tccontext(cpu_env, arg);
6948 rn = "TCContext";
6949 break;
6950 case 6:
6951 CP0_CHECK(ctx->insn_flags & ASE_MT);
6952 gen_helper_mtc0_tcschedule(cpu_env, arg);
6953 rn = "TCSchedule";
6954 break;
6955 case 7:
6956 CP0_CHECK(ctx->insn_flags & ASE_MT);
6957 gen_helper_mtc0_tcschefback(cpu_env, arg);
6958 rn = "TCScheFBack";
6959 break;
6960 default:
6961 goto cp0_unimplemented;
6963 break;
6964 case 3:
6965 switch (sel) {
6966 case 0:
6967 gen_helper_mtc0_entrylo1(cpu_env, arg);
6968 rn = "EntryLo1";
6969 break;
6970 case 1:
6971 CP0_CHECK(ctx->vp);
6972 /* ignored */
6973 rn = "GlobalNumber";
6974 break;
6975 default:
6976 goto cp0_unimplemented;
6978 break;
6979 case 4:
6980 switch (sel) {
6981 case 0:
6982 gen_helper_mtc0_context(cpu_env, arg);
6983 rn = "Context";
6984 break;
6985 case 1:
6986 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6987 rn = "ContextConfig";
6988 goto cp0_unimplemented;
6989 case 2:
6990 CP0_CHECK(ctx->ulri);
6991 tcg_gen_st_tl(arg, cpu_env,
6992 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6993 rn = "UserLocal";
6994 break;
6995 default:
6996 goto cp0_unimplemented;
6998 break;
6999 case 5:
7000 switch (sel) {
7001 case 0:
7002 gen_helper_mtc0_pagemask(cpu_env, arg);
7003 rn = "PageMask";
7004 break;
7005 case 1:
7006 check_insn(ctx, ISA_MIPS32R2);
7007 gen_helper_mtc0_pagegrain(cpu_env, arg);
7008 rn = "PageGrain";
7009 ctx->base.is_jmp = DISAS_STOP;
7010 break;
7011 case 2:
7012 CP0_CHECK(ctx->sc);
7013 gen_helper_mtc0_segctl0(cpu_env, arg);
7014 rn = "SegCtl0";
7015 break;
7016 case 3:
7017 CP0_CHECK(ctx->sc);
7018 gen_helper_mtc0_segctl1(cpu_env, arg);
7019 rn = "SegCtl1";
7020 break;
7021 case 4:
7022 CP0_CHECK(ctx->sc);
7023 gen_helper_mtc0_segctl2(cpu_env, arg);
7024 rn = "SegCtl2";
7025 break;
7026 case 5:
7027 check_pw(ctx);
7028 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7029 rn = "PWBase";
7030 break;
7031 case 6:
7032 check_pw(ctx);
7033 gen_helper_mtc0_pwfield(cpu_env, arg);
7034 rn = "PWField";
7035 break;
7036 case 7:
7037 check_pw(ctx);
7038 gen_helper_mtc0_pwsize(cpu_env, arg);
7039 rn = "PWSize";
7040 break;
7041 default:
7042 goto cp0_unimplemented;
7044 break;
7045 case 6:
7046 switch (sel) {
7047 case 0:
7048 gen_helper_mtc0_wired(cpu_env, arg);
7049 rn = "Wired";
7050 break;
7051 case 1:
7052 check_insn(ctx, ISA_MIPS32R2);
7053 gen_helper_mtc0_srsconf0(cpu_env, arg);
7054 rn = "SRSConf0";
7055 break;
7056 case 2:
7057 check_insn(ctx, ISA_MIPS32R2);
7058 gen_helper_mtc0_srsconf1(cpu_env, arg);
7059 rn = "SRSConf1";
7060 break;
7061 case 3:
7062 check_insn(ctx, ISA_MIPS32R2);
7063 gen_helper_mtc0_srsconf2(cpu_env, arg);
7064 rn = "SRSConf2";
7065 break;
7066 case 4:
7067 check_insn(ctx, ISA_MIPS32R2);
7068 gen_helper_mtc0_srsconf3(cpu_env, arg);
7069 rn = "SRSConf3";
7070 break;
7071 case 5:
7072 check_insn(ctx, ISA_MIPS32R2);
7073 gen_helper_mtc0_srsconf4(cpu_env, arg);
7074 rn = "SRSConf4";
7075 break;
7076 case 6:
7077 check_pw(ctx);
7078 gen_helper_mtc0_pwctl(cpu_env, arg);
7079 rn = "PWCtl";
7080 break;
7081 default:
7082 goto cp0_unimplemented;
7084 break;
7085 case 7:
7086 switch (sel) {
7087 case 0:
7088 check_insn(ctx, ISA_MIPS32R2);
7089 gen_helper_mtc0_hwrena(cpu_env, arg);
7090 ctx->base.is_jmp = DISAS_STOP;
7091 rn = "HWREna";
7092 break;
7093 default:
7094 goto cp0_unimplemented;
7096 break;
7097 case 8:
7098 switch (sel) {
7099 case 0:
7100 /* ignored */
7101 rn = "BadVAddr";
7102 break;
7103 case 1:
7104 /* ignored */
7105 rn = "BadInstr";
7106 break;
7107 case 2:
7108 /* ignored */
7109 rn = "BadInstrP";
7110 break;
7111 case 3:
7112 /* ignored */
7113 rn = "BadInstrX";
7114 break;
7115 default:
7116 goto cp0_unimplemented;
7118 break;
7119 case 9:
7120 switch (sel) {
7121 case 0:
7122 gen_helper_mtc0_count(cpu_env, arg);
7123 rn = "Count";
7124 break;
7125 /* 6,7 are implementation dependent */
7126 default:
7127 goto cp0_unimplemented;
7129 break;
7130 case 10:
7131 switch (sel) {
7132 case 0:
7133 gen_helper_mtc0_entryhi(cpu_env, arg);
7134 rn = "EntryHi";
7135 break;
7136 default:
7137 goto cp0_unimplemented;
7139 break;
7140 case 11:
7141 switch (sel) {
7142 case 0:
7143 gen_helper_mtc0_compare(cpu_env, arg);
7144 rn = "Compare";
7145 break;
7146 /* 6,7 are implementation dependent */
7147 default:
7148 goto cp0_unimplemented;
7150 break;
7151 case 12:
7152 switch (sel) {
7153 case 0:
7154 save_cpu_state(ctx, 1);
7155 gen_helper_mtc0_status(cpu_env, arg);
7156 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7157 gen_save_pc(ctx->base.pc_next + 4);
7158 ctx->base.is_jmp = DISAS_EXIT;
7159 rn = "Status";
7160 break;
7161 case 1:
7162 check_insn(ctx, ISA_MIPS32R2);
7163 gen_helper_mtc0_intctl(cpu_env, arg);
7164 /* Stop translation as we may have switched the execution mode */
7165 ctx->base.is_jmp = DISAS_STOP;
7166 rn = "IntCtl";
7167 break;
7168 case 2:
7169 check_insn(ctx, ISA_MIPS32R2);
7170 gen_helper_mtc0_srsctl(cpu_env, arg);
7171 /* Stop translation as we may have switched the execution mode */
7172 ctx->base.is_jmp = DISAS_STOP;
7173 rn = "SRSCtl";
7174 break;
7175 case 3:
7176 check_insn(ctx, ISA_MIPS32R2);
7177 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7178 /* Stop translation as we may have switched the execution mode */
7179 ctx->base.is_jmp = DISAS_STOP;
7180 rn = "SRSMap";
7181 break;
7182 default:
7183 goto cp0_unimplemented;
7185 break;
7186 case 13:
7187 switch (sel) {
7188 case 0:
7189 save_cpu_state(ctx, 1);
7190 gen_helper_mtc0_cause(cpu_env, arg);
7191 /* Stop translation as we may have triggered an interrupt.
7192 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7193 * translated code to check for pending interrupts. */
7194 gen_save_pc(ctx->base.pc_next + 4);
7195 ctx->base.is_jmp = DISAS_EXIT;
7196 rn = "Cause";
7197 break;
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 case 14:
7203 switch (sel) {
7204 case 0:
7205 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7206 rn = "EPC";
7207 break;
7208 default:
7209 goto cp0_unimplemented;
7211 break;
7212 case 15:
7213 switch (sel) {
7214 case 0:
7215 /* ignored */
7216 rn = "PRid";
7217 break;
7218 case 1:
7219 check_insn(ctx, ISA_MIPS32R2);
7220 gen_helper_mtc0_ebase(cpu_env, arg);
7221 rn = "EBase";
7222 break;
7223 default:
7224 goto cp0_unimplemented;
7226 break;
7227 case 16:
7228 switch (sel) {
7229 case 0:
7230 gen_helper_mtc0_config0(cpu_env, arg);
7231 rn = "Config";
7232 /* Stop translation as we may have switched the execution mode */
7233 ctx->base.is_jmp = DISAS_STOP;
7234 break;
7235 case 1:
7236 /* ignored, read only */
7237 rn = "Config1";
7238 break;
7239 case 2:
7240 gen_helper_mtc0_config2(cpu_env, arg);
7241 rn = "Config2";
7242 /* Stop translation as we may have switched the execution mode */
7243 ctx->base.is_jmp = DISAS_STOP;
7244 break;
7245 case 3:
7246 gen_helper_mtc0_config3(cpu_env, arg);
7247 rn = "Config3";
7248 /* Stop translation as we may have switched the execution mode */
7249 ctx->base.is_jmp = DISAS_STOP;
7250 break;
7251 case 4:
7252 gen_helper_mtc0_config4(cpu_env, arg);
7253 rn = "Config4";
7254 ctx->base.is_jmp = DISAS_STOP;
7255 break;
7256 case 5:
7257 gen_helper_mtc0_config5(cpu_env, arg);
7258 rn = "Config5";
7259 /* Stop translation as we may have switched the execution mode */
7260 ctx->base.is_jmp = DISAS_STOP;
7261 break;
7262 /* 6,7 are implementation dependent */
7263 case 6:
7264 /* ignored */
7265 rn = "Config6";
7266 break;
7267 case 7:
7268 /* ignored */
7269 rn = "Config7";
7270 break;
7271 default:
7272 rn = "Invalid config selector";
7273 goto cp0_unimplemented;
7275 break;
7276 case 17:
7277 switch (sel) {
7278 case 0:
7279 gen_helper_mtc0_lladdr(cpu_env, arg);
7280 rn = "LLAddr";
7281 break;
7282 case 1:
7283 CP0_CHECK(ctx->mrp);
7284 gen_helper_mtc0_maar(cpu_env, arg);
7285 rn = "MAAR";
7286 break;
7287 case 2:
7288 CP0_CHECK(ctx->mrp);
7289 gen_helper_mtc0_maari(cpu_env, arg);
7290 rn = "MAARI";
7291 break;
7292 default:
7293 goto cp0_unimplemented;
7295 break;
7296 case 18:
7297 switch (sel) {
7298 case 0:
7299 case 1:
7300 case 2:
7301 case 3:
7302 case 4:
7303 case 5:
7304 case 6:
7305 case 7:
7306 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7307 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7308 rn = "WatchLo";
7309 break;
7310 default:
7311 goto cp0_unimplemented;
7313 break;
7314 case 19:
7315 switch (sel) {
7316 case 0:
7317 case 1:
7318 case 2:
7319 case 3:
7320 case 4:
7321 case 5:
7322 case 6:
7323 case 7:
7324 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7325 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7326 rn = "WatchHi";
7327 break;
7328 default:
7329 goto cp0_unimplemented;
7331 break;
7332 case 20:
7333 switch (sel) {
7334 case 0:
7335 #if defined(TARGET_MIPS64)
7336 check_insn(ctx, ISA_MIPS3);
7337 gen_helper_mtc0_xcontext(cpu_env, arg);
7338 rn = "XContext";
7339 break;
7340 #endif
7341 default:
7342 goto cp0_unimplemented;
7344 break;
7345 case 21:
7346 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7347 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7348 switch (sel) {
7349 case 0:
7350 gen_helper_mtc0_framemask(cpu_env, arg);
7351 rn = "Framemask";
7352 break;
7353 default:
7354 goto cp0_unimplemented;
7356 break;
7357 case 22:
7358 /* ignored */
7359 rn = "Diagnostic"; /* implementation dependent */
7360 break;
7361 case 23:
7362 switch (sel) {
7363 case 0:
7364 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7365 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7366 gen_save_pc(ctx->base.pc_next + 4);
7367 ctx->base.is_jmp = DISAS_EXIT;
7368 rn = "Debug";
7369 break;
7370 case 1:
7371 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7372 rn = "TraceControl";
7373 /* Stop translation as we may have switched the execution mode */
7374 ctx->base.is_jmp = DISAS_STOP;
7375 goto cp0_unimplemented;
7376 case 2:
7377 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7378 rn = "TraceControl2";
7379 /* Stop translation as we may have switched the execution mode */
7380 ctx->base.is_jmp = DISAS_STOP;
7381 goto cp0_unimplemented;
7382 case 3:
7383 /* Stop translation as we may have switched the execution mode */
7384 ctx->base.is_jmp = DISAS_STOP;
7385 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7386 rn = "UserTraceData";
7387 /* Stop translation as we may have switched the execution mode */
7388 ctx->base.is_jmp = DISAS_STOP;
7389 goto cp0_unimplemented;
7390 case 4:
7391 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7392 /* Stop translation as we may have switched the execution mode */
7393 ctx->base.is_jmp = DISAS_STOP;
7394 rn = "TraceBPC";
7395 goto cp0_unimplemented;
7396 default:
7397 goto cp0_unimplemented;
7399 break;
7400 case 24:
7401 switch (sel) {
7402 case 0:
7403 /* EJTAG support */
7404 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7405 rn = "DEPC";
7406 break;
7407 default:
7408 goto cp0_unimplemented;
7410 break;
7411 case 25:
7412 switch (sel) {
7413 case 0:
7414 gen_helper_mtc0_performance0(cpu_env, arg);
7415 rn = "Performance0";
7416 break;
7417 case 1:
7418 // gen_helper_mtc0_performance1(arg);
7419 rn = "Performance1";
7420 goto cp0_unimplemented;
7421 case 2:
7422 // gen_helper_mtc0_performance2(arg);
7423 rn = "Performance2";
7424 goto cp0_unimplemented;
7425 case 3:
7426 // gen_helper_mtc0_performance3(arg);
7427 rn = "Performance3";
7428 goto cp0_unimplemented;
7429 case 4:
7430 // gen_helper_mtc0_performance4(arg);
7431 rn = "Performance4";
7432 goto cp0_unimplemented;
7433 case 5:
7434 // gen_helper_mtc0_performance5(arg);
7435 rn = "Performance5";
7436 goto cp0_unimplemented;
7437 case 6:
7438 // gen_helper_mtc0_performance6(arg);
7439 rn = "Performance6";
7440 goto cp0_unimplemented;
7441 case 7:
7442 // gen_helper_mtc0_performance7(arg);
7443 rn = "Performance7";
7444 goto cp0_unimplemented;
7445 default:
7446 goto cp0_unimplemented;
7448 break;
7449 case 26:
7450 switch (sel) {
7451 case 0:
7452 gen_helper_mtc0_errctl(cpu_env, arg);
7453 ctx->base.is_jmp = DISAS_STOP;
7454 rn = "ErrCtl";
7455 break;
7456 default:
7457 goto cp0_unimplemented;
7459 break;
7460 case 27:
7461 switch (sel) {
7462 case 0:
7463 case 1:
7464 case 2:
7465 case 3:
7466 /* ignored */
7467 rn = "CacheErr";
7468 break;
7469 default:
7470 goto cp0_unimplemented;
7472 break;
7473 case 28:
7474 switch (sel) {
7475 case 0:
7476 case 2:
7477 case 4:
7478 case 6:
7479 gen_helper_mtc0_taglo(cpu_env, arg);
7480 rn = "TagLo";
7481 break;
7482 case 1:
7483 case 3:
7484 case 5:
7485 case 7:
7486 gen_helper_mtc0_datalo(cpu_env, arg);
7487 rn = "DataLo";
7488 break;
7489 default:
7490 goto cp0_unimplemented;
7492 break;
7493 case 29:
7494 switch (sel) {
7495 case 0:
7496 case 2:
7497 case 4:
7498 case 6:
7499 gen_helper_mtc0_taghi(cpu_env, arg);
7500 rn = "TagHi";
7501 break;
7502 case 1:
7503 case 3:
7504 case 5:
7505 case 7:
7506 gen_helper_mtc0_datahi(cpu_env, arg);
7507 rn = "DataHi";
7508 break;
7509 default:
7510 rn = "invalid sel";
7511 goto cp0_unimplemented;
7513 break;
7514 case 30:
7515 switch (sel) {
7516 case 0:
7517 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7518 rn = "ErrorEPC";
7519 break;
7520 default:
7521 goto cp0_unimplemented;
7523 break;
7524 case 31:
7525 switch (sel) {
7526 case 0:
7527 /* EJTAG support */
7528 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7529 rn = "DESAVE";
7530 break;
7531 case 2:
7532 case 3:
7533 case 4:
7534 case 5:
7535 case 6:
7536 case 7:
7537 CP0_CHECK(ctx->kscrexist & (1 << sel));
7538 tcg_gen_st_tl(arg, cpu_env,
7539 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7540 rn = "KScratch";
7541 break;
7542 default:
7543 goto cp0_unimplemented;
7545 break;
7546 default:
7547 goto cp0_unimplemented;
7549 trace_mips_translate_c0("mtc0", rn, reg, sel);
7551 /* For simplicity assume that all writes can cause interrupts. */
7552 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7553 gen_io_end();
7554 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7555 * translated code to check for pending interrupts. */
7556 gen_save_pc(ctx->base.pc_next + 4);
7557 ctx->base.is_jmp = DISAS_EXIT;
7559 return;
7561 cp0_unimplemented:
7562 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7565 #if defined(TARGET_MIPS64)
7566 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7568 const char *rn = "invalid";
7570 if (sel != 0)
7571 check_insn(ctx, ISA_MIPS64);
7573 switch (reg) {
7574 case 0:
7575 switch (sel) {
7576 case 0:
7577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7578 rn = "Index";
7579 break;
7580 case 1:
7581 CP0_CHECK(ctx->insn_flags & ASE_MT);
7582 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7583 rn = "MVPControl";
7584 break;
7585 case 2:
7586 CP0_CHECK(ctx->insn_flags & ASE_MT);
7587 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7588 rn = "MVPConf0";
7589 break;
7590 case 3:
7591 CP0_CHECK(ctx->insn_flags & ASE_MT);
7592 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7593 rn = "MVPConf1";
7594 break;
7595 case 4:
7596 CP0_CHECK(ctx->vp);
7597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7598 rn = "VPControl";
7599 break;
7600 default:
7601 goto cp0_unimplemented;
7603 break;
7604 case 1:
7605 switch (sel) {
7606 case 0:
7607 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7608 gen_helper_mfc0_random(arg, cpu_env);
7609 rn = "Random";
7610 break;
7611 case 1:
7612 CP0_CHECK(ctx->insn_flags & ASE_MT);
7613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7614 rn = "VPEControl";
7615 break;
7616 case 2:
7617 CP0_CHECK(ctx->insn_flags & ASE_MT);
7618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7619 rn = "VPEConf0";
7620 break;
7621 case 3:
7622 CP0_CHECK(ctx->insn_flags & ASE_MT);
7623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7624 rn = "VPEConf1";
7625 break;
7626 case 4:
7627 CP0_CHECK(ctx->insn_flags & ASE_MT);
7628 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7629 rn = "YQMask";
7630 break;
7631 case 5:
7632 CP0_CHECK(ctx->insn_flags & ASE_MT);
7633 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7634 rn = "VPESchedule";
7635 break;
7636 case 6:
7637 CP0_CHECK(ctx->insn_flags & ASE_MT);
7638 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7639 rn = "VPEScheFBack";
7640 break;
7641 case 7:
7642 CP0_CHECK(ctx->insn_flags & ASE_MT);
7643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7644 rn = "VPEOpt";
7645 break;
7646 default:
7647 goto cp0_unimplemented;
7649 break;
7650 case 2:
7651 switch (sel) {
7652 case 0:
7653 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7654 rn = "EntryLo0";
7655 break;
7656 case 1:
7657 CP0_CHECK(ctx->insn_flags & ASE_MT);
7658 gen_helper_mfc0_tcstatus(arg, cpu_env);
7659 rn = "TCStatus";
7660 break;
7661 case 2:
7662 CP0_CHECK(ctx->insn_flags & ASE_MT);
7663 gen_helper_mfc0_tcbind(arg, cpu_env);
7664 rn = "TCBind";
7665 break;
7666 case 3:
7667 CP0_CHECK(ctx->insn_flags & ASE_MT);
7668 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7669 rn = "TCRestart";
7670 break;
7671 case 4:
7672 CP0_CHECK(ctx->insn_flags & ASE_MT);
7673 gen_helper_dmfc0_tchalt(arg, cpu_env);
7674 rn = "TCHalt";
7675 break;
7676 case 5:
7677 CP0_CHECK(ctx->insn_flags & ASE_MT);
7678 gen_helper_dmfc0_tccontext(arg, cpu_env);
7679 rn = "TCContext";
7680 break;
7681 case 6:
7682 CP0_CHECK(ctx->insn_flags & ASE_MT);
7683 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7684 rn = "TCSchedule";
7685 break;
7686 case 7:
7687 CP0_CHECK(ctx->insn_flags & ASE_MT);
7688 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7689 rn = "TCScheFBack";
7690 break;
7691 default:
7692 goto cp0_unimplemented;
7694 break;
7695 case 3:
7696 switch (sel) {
7697 case 0:
7698 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7699 rn = "EntryLo1";
7700 break;
7701 case 1:
7702 CP0_CHECK(ctx->vp);
7703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7704 rn = "GlobalNumber";
7705 break;
7706 default:
7707 goto cp0_unimplemented;
7709 break;
7710 case 4:
7711 switch (sel) {
7712 case 0:
7713 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7714 rn = "Context";
7715 break;
7716 case 1:
7717 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
7718 rn = "ContextConfig";
7719 goto cp0_unimplemented;
7720 case 2:
7721 CP0_CHECK(ctx->ulri);
7722 tcg_gen_ld_tl(arg, cpu_env,
7723 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7724 rn = "UserLocal";
7725 break;
7726 default:
7727 goto cp0_unimplemented;
7729 break;
7730 case 5:
7731 switch (sel) {
7732 case 0:
7733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7734 rn = "PageMask";
7735 break;
7736 case 1:
7737 check_insn(ctx, ISA_MIPS32R2);
7738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7739 rn = "PageGrain";
7740 break;
7741 case 2:
7742 CP0_CHECK(ctx->sc);
7743 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7744 rn = "SegCtl0";
7745 break;
7746 case 3:
7747 CP0_CHECK(ctx->sc);
7748 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7749 rn = "SegCtl1";
7750 break;
7751 case 4:
7752 CP0_CHECK(ctx->sc);
7753 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7754 rn = "SegCtl2";
7755 break;
7756 case 5:
7757 check_pw(ctx);
7758 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7759 rn = "PWBase";
7760 break;
7761 case 6:
7762 check_pw(ctx);
7763 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7764 rn = "PWField";
7765 break;
7766 case 7:
7767 check_pw(ctx);
7768 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7769 rn = "PWSize";
7770 break;
7771 default:
7772 goto cp0_unimplemented;
7774 break;
7775 case 6:
7776 switch (sel) {
7777 case 0:
7778 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7779 rn = "Wired";
7780 break;
7781 case 1:
7782 check_insn(ctx, ISA_MIPS32R2);
7783 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7784 rn = "SRSConf0";
7785 break;
7786 case 2:
7787 check_insn(ctx, ISA_MIPS32R2);
7788 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7789 rn = "SRSConf1";
7790 break;
7791 case 3:
7792 check_insn(ctx, ISA_MIPS32R2);
7793 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7794 rn = "SRSConf2";
7795 break;
7796 case 4:
7797 check_insn(ctx, ISA_MIPS32R2);
7798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7799 rn = "SRSConf3";
7800 break;
7801 case 5:
7802 check_insn(ctx, ISA_MIPS32R2);
7803 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7804 rn = "SRSConf4";
7805 break;
7806 case 6:
7807 check_pw(ctx);
7808 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7809 rn = "PWCtl";
7810 break;
7811 default:
7812 goto cp0_unimplemented;
7814 break;
7815 case 7:
7816 switch (sel) {
7817 case 0:
7818 check_insn(ctx, ISA_MIPS32R2);
7819 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7820 rn = "HWREna";
7821 break;
7822 default:
7823 goto cp0_unimplemented;
7825 break;
7826 case 8:
7827 switch (sel) {
7828 case 0:
7829 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7830 rn = "BadVAddr";
7831 break;
7832 case 1:
7833 CP0_CHECK(ctx->bi);
7834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7835 rn = "BadInstr";
7836 break;
7837 case 2:
7838 CP0_CHECK(ctx->bp);
7839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7840 rn = "BadInstrP";
7841 break;
7842 case 3:
7843 CP0_CHECK(ctx->bi);
7844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7845 tcg_gen_andi_tl(arg, arg, ~0xffff);
7846 rn = "BadInstrX";
7847 break;
7848 default:
7849 goto cp0_unimplemented;
7851 break;
7852 case 9:
7853 switch (sel) {
7854 case 0:
7855 /* Mark as an IO operation because we read the time. */
7856 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7857 gen_io_start();
7859 gen_helper_mfc0_count(arg, cpu_env);
7860 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7861 gen_io_end();
7863 /* Break the TB to be able to take timer interrupts immediately
7864 after reading count. DISAS_STOP isn't sufficient, we need to
7865 ensure we break completely out of translated code. */
7866 gen_save_pc(ctx->base.pc_next + 4);
7867 ctx->base.is_jmp = DISAS_EXIT;
7868 rn = "Count";
7869 break;
7870 /* 6,7 are implementation dependent */
7871 default:
7872 goto cp0_unimplemented;
7874 break;
7875 case 10:
7876 switch (sel) {
7877 case 0:
7878 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7879 rn = "EntryHi";
7880 break;
7881 default:
7882 goto cp0_unimplemented;
7884 break;
7885 case 11:
7886 switch (sel) {
7887 case 0:
7888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7889 rn = "Compare";
7890 break;
7891 /* 6,7 are implementation dependent */
7892 default:
7893 goto cp0_unimplemented;
7895 break;
7896 case 12:
7897 switch (sel) {
7898 case 0:
7899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7900 rn = "Status";
7901 break;
7902 case 1:
7903 check_insn(ctx, ISA_MIPS32R2);
7904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7905 rn = "IntCtl";
7906 break;
7907 case 2:
7908 check_insn(ctx, ISA_MIPS32R2);
7909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7910 rn = "SRSCtl";
7911 break;
7912 case 3:
7913 check_insn(ctx, ISA_MIPS32R2);
7914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7915 rn = "SRSMap";
7916 break;
7917 default:
7918 goto cp0_unimplemented;
7920 break;
7921 case 13:
7922 switch (sel) {
7923 case 0:
7924 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7925 rn = "Cause";
7926 break;
7927 default:
7928 goto cp0_unimplemented;
7930 break;
7931 case 14:
7932 switch (sel) {
7933 case 0:
7934 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7935 rn = "EPC";
7936 break;
7937 default:
7938 goto cp0_unimplemented;
7940 break;
7941 case 15:
7942 switch (sel) {
7943 case 0:
7944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7945 rn = "PRid";
7946 break;
7947 case 1:
7948 check_insn(ctx, ISA_MIPS32R2);
7949 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7950 rn = "EBase";
7951 break;
7952 case 3:
7953 check_insn(ctx, ISA_MIPS32R2);
7954 CP0_CHECK(ctx->cmgcr);
7955 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7956 rn = "CMGCRBase";
7957 break;
7958 default:
7959 goto cp0_unimplemented;
7961 break;
7962 case 16:
7963 switch (sel) {
7964 case 0:
7965 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7966 rn = "Config";
7967 break;
7968 case 1:
7969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7970 rn = "Config1";
7971 break;
7972 case 2:
7973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7974 rn = "Config2";
7975 break;
7976 case 3:
7977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7978 rn = "Config3";
7979 break;
7980 case 4:
7981 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7982 rn = "Config4";
7983 break;
7984 case 5:
7985 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7986 rn = "Config5";
7987 break;
7988 /* 6,7 are implementation dependent */
7989 case 6:
7990 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7991 rn = "Config6";
7992 break;
7993 case 7:
7994 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7995 rn = "Config7";
7996 break;
7997 default:
7998 goto cp0_unimplemented;
8000 break;
8001 case 17:
8002 switch (sel) {
8003 case 0:
8004 gen_helper_dmfc0_lladdr(arg, cpu_env);
8005 rn = "LLAddr";
8006 break;
8007 case 1:
8008 CP0_CHECK(ctx->mrp);
8009 gen_helper_dmfc0_maar(arg, cpu_env);
8010 rn = "MAAR";
8011 break;
8012 case 2:
8013 CP0_CHECK(ctx->mrp);
8014 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8015 rn = "MAARI";
8016 break;
8017 default:
8018 goto cp0_unimplemented;
8020 break;
8021 case 18:
8022 switch (sel) {
8023 case 0:
8024 case 1:
8025 case 2:
8026 case 3:
8027 case 4:
8028 case 5:
8029 case 6:
8030 case 7:
8031 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8032 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8033 rn = "WatchLo";
8034 break;
8035 default:
8036 goto cp0_unimplemented;
8038 break;
8039 case 19:
8040 switch (sel) {
8041 case 0:
8042 case 1:
8043 case 2:
8044 case 3:
8045 case 4:
8046 case 5:
8047 case 6:
8048 case 7:
8049 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8050 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8051 rn = "WatchHi";
8052 break;
8053 default:
8054 goto cp0_unimplemented;
8056 break;
8057 case 20:
8058 switch (sel) {
8059 case 0:
8060 check_insn(ctx, ISA_MIPS3);
8061 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8062 rn = "XContext";
8063 break;
8064 default:
8065 goto cp0_unimplemented;
8067 break;
8068 case 21:
8069 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8070 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8071 switch (sel) {
8072 case 0:
8073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8074 rn = "Framemask";
8075 break;
8076 default:
8077 goto cp0_unimplemented;
8079 break;
8080 case 22:
8081 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8082 rn = "'Diagnostic"; /* implementation dependent */
8083 break;
8084 case 23:
8085 switch (sel) {
8086 case 0:
8087 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8088 rn = "Debug";
8089 break;
8090 case 1:
8091 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8092 rn = "TraceControl";
8093 goto cp0_unimplemented;
8094 case 2:
8095 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8096 rn = "TraceControl2";
8097 goto cp0_unimplemented;
8098 case 3:
8099 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8100 rn = "UserTraceData";
8101 goto cp0_unimplemented;
8102 case 4:
8103 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8104 rn = "TraceBPC";
8105 goto cp0_unimplemented;
8106 default:
8107 goto cp0_unimplemented;
8109 break;
8110 case 24:
8111 switch (sel) {
8112 case 0:
8113 /* EJTAG support */
8114 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8115 rn = "DEPC";
8116 break;
8117 default:
8118 goto cp0_unimplemented;
8120 break;
8121 case 25:
8122 switch (sel) {
8123 case 0:
8124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8125 rn = "Performance0";
8126 break;
8127 case 1:
8128 // gen_helper_dmfc0_performance1(arg);
8129 rn = "Performance1";
8130 goto cp0_unimplemented;
8131 case 2:
8132 // gen_helper_dmfc0_performance2(arg);
8133 rn = "Performance2";
8134 goto cp0_unimplemented;
8135 case 3:
8136 // gen_helper_dmfc0_performance3(arg);
8137 rn = "Performance3";
8138 goto cp0_unimplemented;
8139 case 4:
8140 // gen_helper_dmfc0_performance4(arg);
8141 rn = "Performance4";
8142 goto cp0_unimplemented;
8143 case 5:
8144 // gen_helper_dmfc0_performance5(arg);
8145 rn = "Performance5";
8146 goto cp0_unimplemented;
8147 case 6:
8148 // gen_helper_dmfc0_performance6(arg);
8149 rn = "Performance6";
8150 goto cp0_unimplemented;
8151 case 7:
8152 // gen_helper_dmfc0_performance7(arg);
8153 rn = "Performance7";
8154 goto cp0_unimplemented;
8155 default:
8156 goto cp0_unimplemented;
8158 break;
8159 case 26:
8160 switch (sel) {
8161 case 0:
8162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8163 rn = "ErrCtl";
8164 break;
8165 default:
8166 goto cp0_unimplemented;
8168 break;
8169 case 27:
8170 switch (sel) {
8171 /* ignored */
8172 case 0:
8173 case 1:
8174 case 2:
8175 case 3:
8176 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8177 rn = "CacheErr";
8178 break;
8179 default:
8180 goto cp0_unimplemented;
8182 break;
8183 case 28:
8184 switch (sel) {
8185 case 0:
8186 case 2:
8187 case 4:
8188 case 6:
8189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8190 rn = "TagLo";
8191 break;
8192 case 1:
8193 case 3:
8194 case 5:
8195 case 7:
8196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8197 rn = "DataLo";
8198 break;
8199 default:
8200 goto cp0_unimplemented;
8202 break;
8203 case 29:
8204 switch (sel) {
8205 case 0:
8206 case 2:
8207 case 4:
8208 case 6:
8209 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8210 rn = "TagHi";
8211 break;
8212 case 1:
8213 case 3:
8214 case 5:
8215 case 7:
8216 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8217 rn = "DataHi";
8218 break;
8219 default:
8220 goto cp0_unimplemented;
8222 break;
8223 case 30:
8224 switch (sel) {
8225 case 0:
8226 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8227 rn = "ErrorEPC";
8228 break;
8229 default:
8230 goto cp0_unimplemented;
8232 break;
8233 case 31:
8234 switch (sel) {
8235 case 0:
8236 /* EJTAG support */
8237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8238 rn = "DESAVE";
8239 break;
8240 case 2:
8241 case 3:
8242 case 4:
8243 case 5:
8244 case 6:
8245 case 7:
8246 CP0_CHECK(ctx->kscrexist & (1 << sel));
8247 tcg_gen_ld_tl(arg, cpu_env,
8248 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8249 rn = "KScratch";
8250 break;
8251 default:
8252 goto cp0_unimplemented;
8254 break;
8255 default:
8256 goto cp0_unimplemented;
8258 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8259 return;
8261 cp0_unimplemented:
8262 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8263 gen_mfc0_unimplemented(ctx, arg);
8266 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8268 const char *rn = "invalid";
8270 if (sel != 0)
8271 check_insn(ctx, ISA_MIPS64);
8273 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8274 gen_io_start();
8277 switch (reg) {
8278 case 0:
8279 switch (sel) {
8280 case 0:
8281 gen_helper_mtc0_index(cpu_env, arg);
8282 rn = "Index";
8283 break;
8284 case 1:
8285 CP0_CHECK(ctx->insn_flags & ASE_MT);
8286 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8287 rn = "MVPControl";
8288 break;
8289 case 2:
8290 CP0_CHECK(ctx->insn_flags & ASE_MT);
8291 /* ignored */
8292 rn = "MVPConf0";
8293 break;
8294 case 3:
8295 CP0_CHECK(ctx->insn_flags & ASE_MT);
8296 /* ignored */
8297 rn = "MVPConf1";
8298 break;
8299 case 4:
8300 CP0_CHECK(ctx->vp);
8301 /* ignored */
8302 rn = "VPControl";
8303 break;
8304 default:
8305 goto cp0_unimplemented;
8307 break;
8308 case 1:
8309 switch (sel) {
8310 case 0:
8311 /* ignored */
8312 rn = "Random";
8313 break;
8314 case 1:
8315 CP0_CHECK(ctx->insn_flags & ASE_MT);
8316 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8317 rn = "VPEControl";
8318 break;
8319 case 2:
8320 CP0_CHECK(ctx->insn_flags & ASE_MT);
8321 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8322 rn = "VPEConf0";
8323 break;
8324 case 3:
8325 CP0_CHECK(ctx->insn_flags & ASE_MT);
8326 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8327 rn = "VPEConf1";
8328 break;
8329 case 4:
8330 CP0_CHECK(ctx->insn_flags & ASE_MT);
8331 gen_helper_mtc0_yqmask(cpu_env, arg);
8332 rn = "YQMask";
8333 break;
8334 case 5:
8335 CP0_CHECK(ctx->insn_flags & ASE_MT);
8336 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8337 rn = "VPESchedule";
8338 break;
8339 case 6:
8340 CP0_CHECK(ctx->insn_flags & ASE_MT);
8341 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8342 rn = "VPEScheFBack";
8343 break;
8344 case 7:
8345 CP0_CHECK(ctx->insn_flags & ASE_MT);
8346 gen_helper_mtc0_vpeopt(cpu_env, arg);
8347 rn = "VPEOpt";
8348 break;
8349 default:
8350 goto cp0_unimplemented;
8352 break;
8353 case 2:
8354 switch (sel) {
8355 case 0:
8356 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8357 rn = "EntryLo0";
8358 break;
8359 case 1:
8360 CP0_CHECK(ctx->insn_flags & ASE_MT);
8361 gen_helper_mtc0_tcstatus(cpu_env, arg);
8362 rn = "TCStatus";
8363 break;
8364 case 2:
8365 CP0_CHECK(ctx->insn_flags & ASE_MT);
8366 gen_helper_mtc0_tcbind(cpu_env, arg);
8367 rn = "TCBind";
8368 break;
8369 case 3:
8370 CP0_CHECK(ctx->insn_flags & ASE_MT);
8371 gen_helper_mtc0_tcrestart(cpu_env, arg);
8372 rn = "TCRestart";
8373 break;
8374 case 4:
8375 CP0_CHECK(ctx->insn_flags & ASE_MT);
8376 gen_helper_mtc0_tchalt(cpu_env, arg);
8377 rn = "TCHalt";
8378 break;
8379 case 5:
8380 CP0_CHECK(ctx->insn_flags & ASE_MT);
8381 gen_helper_mtc0_tccontext(cpu_env, arg);
8382 rn = "TCContext";
8383 break;
8384 case 6:
8385 CP0_CHECK(ctx->insn_flags & ASE_MT);
8386 gen_helper_mtc0_tcschedule(cpu_env, arg);
8387 rn = "TCSchedule";
8388 break;
8389 case 7:
8390 CP0_CHECK(ctx->insn_flags & ASE_MT);
8391 gen_helper_mtc0_tcschefback(cpu_env, arg);
8392 rn = "TCScheFBack";
8393 break;
8394 default:
8395 goto cp0_unimplemented;
8397 break;
8398 case 3:
8399 switch (sel) {
8400 case 0:
8401 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8402 rn = "EntryLo1";
8403 break;
8404 case 1:
8405 CP0_CHECK(ctx->vp);
8406 /* ignored */
8407 rn = "GlobalNumber";
8408 break;
8409 default:
8410 goto cp0_unimplemented;
8412 break;
8413 case 4:
8414 switch (sel) {
8415 case 0:
8416 gen_helper_mtc0_context(cpu_env, arg);
8417 rn = "Context";
8418 break;
8419 case 1:
8420 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8421 rn = "ContextConfig";
8422 goto cp0_unimplemented;
8423 case 2:
8424 CP0_CHECK(ctx->ulri);
8425 tcg_gen_st_tl(arg, cpu_env,
8426 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8427 rn = "UserLocal";
8428 break;
8429 default:
8430 goto cp0_unimplemented;
8432 break;
8433 case 5:
8434 switch (sel) {
8435 case 0:
8436 gen_helper_mtc0_pagemask(cpu_env, arg);
8437 rn = "PageMask";
8438 break;
8439 case 1:
8440 check_insn(ctx, ISA_MIPS32R2);
8441 gen_helper_mtc0_pagegrain(cpu_env, arg);
8442 rn = "PageGrain";
8443 break;
8444 case 2:
8445 CP0_CHECK(ctx->sc);
8446 gen_helper_mtc0_segctl0(cpu_env, arg);
8447 rn = "SegCtl0";
8448 break;
8449 case 3:
8450 CP0_CHECK(ctx->sc);
8451 gen_helper_mtc0_segctl1(cpu_env, arg);
8452 rn = "SegCtl1";
8453 break;
8454 case 4:
8455 CP0_CHECK(ctx->sc);
8456 gen_helper_mtc0_segctl2(cpu_env, arg);
8457 rn = "SegCtl2";
8458 break;
8459 case 5:
8460 check_pw(ctx);
8461 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8462 rn = "PWBase";
8463 break;
8464 case 6:
8465 check_pw(ctx);
8466 gen_helper_mtc0_pwfield(cpu_env, arg);
8467 rn = "PWField";
8468 break;
8469 case 7:
8470 check_pw(ctx);
8471 gen_helper_mtc0_pwsize(cpu_env, arg);
8472 rn = "PWSize";
8473 break;
8474 default:
8475 goto cp0_unimplemented;
8477 break;
8478 case 6:
8479 switch (sel) {
8480 case 0:
8481 gen_helper_mtc0_wired(cpu_env, arg);
8482 rn = "Wired";
8483 break;
8484 case 1:
8485 check_insn(ctx, ISA_MIPS32R2);
8486 gen_helper_mtc0_srsconf0(cpu_env, arg);
8487 rn = "SRSConf0";
8488 break;
8489 case 2:
8490 check_insn(ctx, ISA_MIPS32R2);
8491 gen_helper_mtc0_srsconf1(cpu_env, arg);
8492 rn = "SRSConf1";
8493 break;
8494 case 3:
8495 check_insn(ctx, ISA_MIPS32R2);
8496 gen_helper_mtc0_srsconf2(cpu_env, arg);
8497 rn = "SRSConf2";
8498 break;
8499 case 4:
8500 check_insn(ctx, ISA_MIPS32R2);
8501 gen_helper_mtc0_srsconf3(cpu_env, arg);
8502 rn = "SRSConf3";
8503 break;
8504 case 5:
8505 check_insn(ctx, ISA_MIPS32R2);
8506 gen_helper_mtc0_srsconf4(cpu_env, arg);
8507 rn = "SRSConf4";
8508 break;
8509 case 6:
8510 check_pw(ctx);
8511 gen_helper_mtc0_pwctl(cpu_env, arg);
8512 rn = "PWCtl";
8513 break;
8514 default:
8515 goto cp0_unimplemented;
8517 break;
8518 case 7:
8519 switch (sel) {
8520 case 0:
8521 check_insn(ctx, ISA_MIPS32R2);
8522 gen_helper_mtc0_hwrena(cpu_env, arg);
8523 ctx->base.is_jmp = DISAS_STOP;
8524 rn = "HWREna";
8525 break;
8526 default:
8527 goto cp0_unimplemented;
8529 break;
8530 case 8:
8531 switch (sel) {
8532 case 0:
8533 /* ignored */
8534 rn = "BadVAddr";
8535 break;
8536 case 1:
8537 /* ignored */
8538 rn = "BadInstr";
8539 break;
8540 case 2:
8541 /* ignored */
8542 rn = "BadInstrP";
8543 break;
8544 case 3:
8545 /* ignored */
8546 rn = "BadInstrX";
8547 break;
8548 default:
8549 goto cp0_unimplemented;
8551 break;
8552 case 9:
8553 switch (sel) {
8554 case 0:
8555 gen_helper_mtc0_count(cpu_env, arg);
8556 rn = "Count";
8557 break;
8558 /* 6,7 are implementation dependent */
8559 default:
8560 goto cp0_unimplemented;
8562 /* Stop translation as we may have switched the execution mode */
8563 ctx->base.is_jmp = DISAS_STOP;
8564 break;
8565 case 10:
8566 switch (sel) {
8567 case 0:
8568 gen_helper_mtc0_entryhi(cpu_env, arg);
8569 rn = "EntryHi";
8570 break;
8571 default:
8572 goto cp0_unimplemented;
8574 break;
8575 case 11:
8576 switch (sel) {
8577 case 0:
8578 gen_helper_mtc0_compare(cpu_env, arg);
8579 rn = "Compare";
8580 break;
8581 /* 6,7 are implementation dependent */
8582 default:
8583 goto cp0_unimplemented;
8585 /* Stop translation as we may have switched the execution mode */
8586 ctx->base.is_jmp = DISAS_STOP;
8587 break;
8588 case 12:
8589 switch (sel) {
8590 case 0:
8591 save_cpu_state(ctx, 1);
8592 gen_helper_mtc0_status(cpu_env, arg);
8593 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8594 gen_save_pc(ctx->base.pc_next + 4);
8595 ctx->base.is_jmp = DISAS_EXIT;
8596 rn = "Status";
8597 break;
8598 case 1:
8599 check_insn(ctx, ISA_MIPS32R2);
8600 gen_helper_mtc0_intctl(cpu_env, arg);
8601 /* Stop translation as we may have switched the execution mode */
8602 ctx->base.is_jmp = DISAS_STOP;
8603 rn = "IntCtl";
8604 break;
8605 case 2:
8606 check_insn(ctx, ISA_MIPS32R2);
8607 gen_helper_mtc0_srsctl(cpu_env, arg);
8608 /* Stop translation as we may have switched the execution mode */
8609 ctx->base.is_jmp = DISAS_STOP;
8610 rn = "SRSCtl";
8611 break;
8612 case 3:
8613 check_insn(ctx, ISA_MIPS32R2);
8614 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8615 /* Stop translation as we may have switched the execution mode */
8616 ctx->base.is_jmp = DISAS_STOP;
8617 rn = "SRSMap";
8618 break;
8619 default:
8620 goto cp0_unimplemented;
8622 break;
8623 case 13:
8624 switch (sel) {
8625 case 0:
8626 save_cpu_state(ctx, 1);
8627 gen_helper_mtc0_cause(cpu_env, arg);
8628 /* Stop translation as we may have triggered an interrupt.
8629 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8630 * translated code to check for pending interrupts. */
8631 gen_save_pc(ctx->base.pc_next + 4);
8632 ctx->base.is_jmp = DISAS_EXIT;
8633 rn = "Cause";
8634 break;
8635 default:
8636 goto cp0_unimplemented;
8638 break;
8639 case 14:
8640 switch (sel) {
8641 case 0:
8642 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8643 rn = "EPC";
8644 break;
8645 default:
8646 goto cp0_unimplemented;
8648 break;
8649 case 15:
8650 switch (sel) {
8651 case 0:
8652 /* ignored */
8653 rn = "PRid";
8654 break;
8655 case 1:
8656 check_insn(ctx, ISA_MIPS32R2);
8657 gen_helper_mtc0_ebase(cpu_env, arg);
8658 rn = "EBase";
8659 break;
8660 default:
8661 goto cp0_unimplemented;
8663 break;
8664 case 16:
8665 switch (sel) {
8666 case 0:
8667 gen_helper_mtc0_config0(cpu_env, arg);
8668 rn = "Config";
8669 /* Stop translation as we may have switched the execution mode */
8670 ctx->base.is_jmp = DISAS_STOP;
8671 break;
8672 case 1:
8673 /* ignored, read only */
8674 rn = "Config1";
8675 break;
8676 case 2:
8677 gen_helper_mtc0_config2(cpu_env, arg);
8678 rn = "Config2";
8679 /* Stop translation as we may have switched the execution mode */
8680 ctx->base.is_jmp = DISAS_STOP;
8681 break;
8682 case 3:
8683 gen_helper_mtc0_config3(cpu_env, arg);
8684 rn = "Config3";
8685 /* Stop translation as we may have switched the execution mode */
8686 ctx->base.is_jmp = DISAS_STOP;
8687 break;
8688 case 4:
8689 /* currently ignored */
8690 rn = "Config4";
8691 break;
8692 case 5:
8693 gen_helper_mtc0_config5(cpu_env, arg);
8694 rn = "Config5";
8695 /* Stop translation as we may have switched the execution mode */
8696 ctx->base.is_jmp = DISAS_STOP;
8697 break;
8698 /* 6,7 are implementation dependent */
8699 default:
8700 rn = "Invalid config selector";
8701 goto cp0_unimplemented;
8703 break;
8704 case 17:
8705 switch (sel) {
8706 case 0:
8707 gen_helper_mtc0_lladdr(cpu_env, arg);
8708 rn = "LLAddr";
8709 break;
8710 case 1:
8711 CP0_CHECK(ctx->mrp);
8712 gen_helper_mtc0_maar(cpu_env, arg);
8713 rn = "MAAR";
8714 break;
8715 case 2:
8716 CP0_CHECK(ctx->mrp);
8717 gen_helper_mtc0_maari(cpu_env, arg);
8718 rn = "MAARI";
8719 break;
8720 default:
8721 goto cp0_unimplemented;
8723 break;
8724 case 18:
8725 switch (sel) {
8726 case 0:
8727 case 1:
8728 case 2:
8729 case 3:
8730 case 4:
8731 case 5:
8732 case 6:
8733 case 7:
8734 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8735 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8736 rn = "WatchLo";
8737 break;
8738 default:
8739 goto cp0_unimplemented;
8741 break;
8742 case 19:
8743 switch (sel) {
8744 case 0:
8745 case 1:
8746 case 2:
8747 case 3:
8748 case 4:
8749 case 5:
8750 case 6:
8751 case 7:
8752 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8753 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8754 rn = "WatchHi";
8755 break;
8756 default:
8757 goto cp0_unimplemented;
8759 break;
8760 case 20:
8761 switch (sel) {
8762 case 0:
8763 check_insn(ctx, ISA_MIPS3);
8764 gen_helper_mtc0_xcontext(cpu_env, arg);
8765 rn = "XContext";
8766 break;
8767 default:
8768 goto cp0_unimplemented;
8770 break;
8771 case 21:
8772 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8773 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8774 switch (sel) {
8775 case 0:
8776 gen_helper_mtc0_framemask(cpu_env, arg);
8777 rn = "Framemask";
8778 break;
8779 default:
8780 goto cp0_unimplemented;
8782 break;
8783 case 22:
8784 /* ignored */
8785 rn = "Diagnostic"; /* implementation dependent */
8786 break;
8787 case 23:
8788 switch (sel) {
8789 case 0:
8790 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8791 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8792 gen_save_pc(ctx->base.pc_next + 4);
8793 ctx->base.is_jmp = DISAS_EXIT;
8794 rn = "Debug";
8795 break;
8796 case 1:
8797 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8798 /* Stop translation as we may have switched the execution mode */
8799 ctx->base.is_jmp = DISAS_STOP;
8800 rn = "TraceControl";
8801 goto cp0_unimplemented;
8802 case 2:
8803 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8804 /* Stop translation as we may have switched the execution mode */
8805 ctx->base.is_jmp = DISAS_STOP;
8806 rn = "TraceControl2";
8807 goto cp0_unimplemented;
8808 case 3:
8809 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8810 /* Stop translation as we may have switched the execution mode */
8811 ctx->base.is_jmp = DISAS_STOP;
8812 rn = "UserTraceData";
8813 goto cp0_unimplemented;
8814 case 4:
8815 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8816 /* Stop translation as we may have switched the execution mode */
8817 ctx->base.is_jmp = DISAS_STOP;
8818 rn = "TraceBPC";
8819 goto cp0_unimplemented;
8820 default:
8821 goto cp0_unimplemented;
8823 break;
8824 case 24:
8825 switch (sel) {
8826 case 0:
8827 /* EJTAG support */
8828 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8829 rn = "DEPC";
8830 break;
8831 default:
8832 goto cp0_unimplemented;
8834 break;
8835 case 25:
8836 switch (sel) {
8837 case 0:
8838 gen_helper_mtc0_performance0(cpu_env, arg);
8839 rn = "Performance0";
8840 break;
8841 case 1:
8842 // gen_helper_mtc0_performance1(cpu_env, arg);
8843 rn = "Performance1";
8844 goto cp0_unimplemented;
8845 case 2:
8846 // gen_helper_mtc0_performance2(cpu_env, arg);
8847 rn = "Performance2";
8848 goto cp0_unimplemented;
8849 case 3:
8850 // gen_helper_mtc0_performance3(cpu_env, arg);
8851 rn = "Performance3";
8852 goto cp0_unimplemented;
8853 case 4:
8854 // gen_helper_mtc0_performance4(cpu_env, arg);
8855 rn = "Performance4";
8856 goto cp0_unimplemented;
8857 case 5:
8858 // gen_helper_mtc0_performance5(cpu_env, arg);
8859 rn = "Performance5";
8860 goto cp0_unimplemented;
8861 case 6:
8862 // gen_helper_mtc0_performance6(cpu_env, arg);
8863 rn = "Performance6";
8864 goto cp0_unimplemented;
8865 case 7:
8866 // gen_helper_mtc0_performance7(cpu_env, arg);
8867 rn = "Performance7";
8868 goto cp0_unimplemented;
8869 default:
8870 goto cp0_unimplemented;
8872 break;
8873 case 26:
8874 switch (sel) {
8875 case 0:
8876 gen_helper_mtc0_errctl(cpu_env, arg);
8877 ctx->base.is_jmp = DISAS_STOP;
8878 rn = "ErrCtl";
8879 break;
8880 default:
8881 goto cp0_unimplemented;
8883 break;
8884 case 27:
8885 switch (sel) {
8886 case 0:
8887 case 1:
8888 case 2:
8889 case 3:
8890 /* ignored */
8891 rn = "CacheErr";
8892 break;
8893 default:
8894 goto cp0_unimplemented;
8896 break;
8897 case 28:
8898 switch (sel) {
8899 case 0:
8900 case 2:
8901 case 4:
8902 case 6:
8903 gen_helper_mtc0_taglo(cpu_env, arg);
8904 rn = "TagLo";
8905 break;
8906 case 1:
8907 case 3:
8908 case 5:
8909 case 7:
8910 gen_helper_mtc0_datalo(cpu_env, arg);
8911 rn = "DataLo";
8912 break;
8913 default:
8914 goto cp0_unimplemented;
8916 break;
8917 case 29:
8918 switch (sel) {
8919 case 0:
8920 case 2:
8921 case 4:
8922 case 6:
8923 gen_helper_mtc0_taghi(cpu_env, arg);
8924 rn = "TagHi";
8925 break;
8926 case 1:
8927 case 3:
8928 case 5:
8929 case 7:
8930 gen_helper_mtc0_datahi(cpu_env, arg);
8931 rn = "DataHi";
8932 break;
8933 default:
8934 rn = "invalid sel";
8935 goto cp0_unimplemented;
8937 break;
8938 case 30:
8939 switch (sel) {
8940 case 0:
8941 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8942 rn = "ErrorEPC";
8943 break;
8944 default:
8945 goto cp0_unimplemented;
8947 break;
8948 case 31:
8949 switch (sel) {
8950 case 0:
8951 /* EJTAG support */
8952 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8953 rn = "DESAVE";
8954 break;
8955 case 2:
8956 case 3:
8957 case 4:
8958 case 5:
8959 case 6:
8960 case 7:
8961 CP0_CHECK(ctx->kscrexist & (1 << sel));
8962 tcg_gen_st_tl(arg, cpu_env,
8963 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8964 rn = "KScratch";
8965 break;
8966 default:
8967 goto cp0_unimplemented;
8969 break;
8970 default:
8971 goto cp0_unimplemented;
8973 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8975 /* For simplicity assume that all writes can cause interrupts. */
8976 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8977 gen_io_end();
8978 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8979 * translated code to check for pending interrupts. */
8980 gen_save_pc(ctx->base.pc_next + 4);
8981 ctx->base.is_jmp = DISAS_EXIT;
8983 return;
8985 cp0_unimplemented:
8986 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8988 #endif /* TARGET_MIPS64 */
8990 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8991 int u, int sel, int h)
8993 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8994 TCGv t0 = tcg_temp_local_new();
8996 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8997 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8998 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8999 tcg_gen_movi_tl(t0, -1);
9000 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9001 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9002 tcg_gen_movi_tl(t0, -1);
9003 else if (u == 0) {
9004 switch (rt) {
9005 case 1:
9006 switch (sel) {
9007 case 1:
9008 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9009 break;
9010 case 2:
9011 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9012 break;
9013 default:
9014 goto die;
9015 break;
9017 break;
9018 case 2:
9019 switch (sel) {
9020 case 1:
9021 gen_helper_mftc0_tcstatus(t0, cpu_env);
9022 break;
9023 case 2:
9024 gen_helper_mftc0_tcbind(t0, cpu_env);
9025 break;
9026 case 3:
9027 gen_helper_mftc0_tcrestart(t0, cpu_env);
9028 break;
9029 case 4:
9030 gen_helper_mftc0_tchalt(t0, cpu_env);
9031 break;
9032 case 5:
9033 gen_helper_mftc0_tccontext(t0, cpu_env);
9034 break;
9035 case 6:
9036 gen_helper_mftc0_tcschedule(t0, cpu_env);
9037 break;
9038 case 7:
9039 gen_helper_mftc0_tcschefback(t0, cpu_env);
9040 break;
9041 default:
9042 gen_mfc0(ctx, t0, rt, sel);
9043 break;
9045 break;
9046 case 10:
9047 switch (sel) {
9048 case 0:
9049 gen_helper_mftc0_entryhi(t0, cpu_env);
9050 break;
9051 default:
9052 gen_mfc0(ctx, t0, rt, sel);
9053 break;
9055 case 12:
9056 switch (sel) {
9057 case 0:
9058 gen_helper_mftc0_status(t0, cpu_env);
9059 break;
9060 default:
9061 gen_mfc0(ctx, t0, rt, sel);
9062 break;
9064 case 13:
9065 switch (sel) {
9066 case 0:
9067 gen_helper_mftc0_cause(t0, cpu_env);
9068 break;
9069 default:
9070 goto die;
9071 break;
9073 break;
9074 case 14:
9075 switch (sel) {
9076 case 0:
9077 gen_helper_mftc0_epc(t0, cpu_env);
9078 break;
9079 default:
9080 goto die;
9081 break;
9083 break;
9084 case 15:
9085 switch (sel) {
9086 case 1:
9087 gen_helper_mftc0_ebase(t0, cpu_env);
9088 break;
9089 default:
9090 goto die;
9091 break;
9093 break;
9094 case 16:
9095 switch (sel) {
9096 case 0:
9097 case 1:
9098 case 2:
9099 case 3:
9100 case 4:
9101 case 5:
9102 case 6:
9103 case 7:
9104 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9105 break;
9106 default:
9107 goto die;
9108 break;
9110 break;
9111 case 23:
9112 switch (sel) {
9113 case 0:
9114 gen_helper_mftc0_debug(t0, cpu_env);
9115 break;
9116 default:
9117 gen_mfc0(ctx, t0, rt, sel);
9118 break;
9120 break;
9121 default:
9122 gen_mfc0(ctx, t0, rt, sel);
9124 } else switch (sel) {
9125 /* GPR registers. */
9126 case 0:
9127 gen_helper_1e0i(mftgpr, t0, rt);
9128 break;
9129 /* Auxiliary CPU registers */
9130 case 1:
9131 switch (rt) {
9132 case 0:
9133 gen_helper_1e0i(mftlo, t0, 0);
9134 break;
9135 case 1:
9136 gen_helper_1e0i(mfthi, t0, 0);
9137 break;
9138 case 2:
9139 gen_helper_1e0i(mftacx, t0, 0);
9140 break;
9141 case 4:
9142 gen_helper_1e0i(mftlo, t0, 1);
9143 break;
9144 case 5:
9145 gen_helper_1e0i(mfthi, t0, 1);
9146 break;
9147 case 6:
9148 gen_helper_1e0i(mftacx, t0, 1);
9149 break;
9150 case 8:
9151 gen_helper_1e0i(mftlo, t0, 2);
9152 break;
9153 case 9:
9154 gen_helper_1e0i(mfthi, t0, 2);
9155 break;
9156 case 10:
9157 gen_helper_1e0i(mftacx, t0, 2);
9158 break;
9159 case 12:
9160 gen_helper_1e0i(mftlo, t0, 3);
9161 break;
9162 case 13:
9163 gen_helper_1e0i(mfthi, t0, 3);
9164 break;
9165 case 14:
9166 gen_helper_1e0i(mftacx, t0, 3);
9167 break;
9168 case 16:
9169 gen_helper_mftdsp(t0, cpu_env);
9170 break;
9171 default:
9172 goto die;
9174 break;
9175 /* Floating point (COP1). */
9176 case 2:
9177 /* XXX: For now we support only a single FPU context. */
9178 if (h == 0) {
9179 TCGv_i32 fp0 = tcg_temp_new_i32();
9181 gen_load_fpr32(ctx, fp0, rt);
9182 tcg_gen_ext_i32_tl(t0, fp0);
9183 tcg_temp_free_i32(fp0);
9184 } else {
9185 TCGv_i32 fp0 = tcg_temp_new_i32();
9187 gen_load_fpr32h(ctx, fp0, rt);
9188 tcg_gen_ext_i32_tl(t0, fp0);
9189 tcg_temp_free_i32(fp0);
9191 break;
9192 case 3:
9193 /* XXX: For now we support only a single FPU context. */
9194 gen_helper_1e0i(cfc1, t0, rt);
9195 break;
9196 /* COP2: Not implemented. */
9197 case 4:
9198 case 5:
9199 /* fall through */
9200 default:
9201 goto die;
9203 trace_mips_translate_tr("mftr", rt, u, sel, h);
9204 gen_store_gpr(t0, rd);
9205 tcg_temp_free(t0);
9206 return;
9208 die:
9209 tcg_temp_free(t0);
9210 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9211 generate_exception_end(ctx, EXCP_RI);
9214 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9215 int u, int sel, int h)
9217 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9218 TCGv t0 = tcg_temp_local_new();
9220 gen_load_gpr(t0, rt);
9221 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9222 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9223 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9224 /* NOP */ ;
9225 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9226 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9227 /* NOP */ ;
9228 else if (u == 0) {
9229 switch (rd) {
9230 case 1:
9231 switch (sel) {
9232 case 1:
9233 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9234 break;
9235 case 2:
9236 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9237 break;
9238 default:
9239 goto die;
9240 break;
9242 break;
9243 case 2:
9244 switch (sel) {
9245 case 1:
9246 gen_helper_mttc0_tcstatus(cpu_env, t0);
9247 break;
9248 case 2:
9249 gen_helper_mttc0_tcbind(cpu_env, t0);
9250 break;
9251 case 3:
9252 gen_helper_mttc0_tcrestart(cpu_env, t0);
9253 break;
9254 case 4:
9255 gen_helper_mttc0_tchalt(cpu_env, t0);
9256 break;
9257 case 5:
9258 gen_helper_mttc0_tccontext(cpu_env, t0);
9259 break;
9260 case 6:
9261 gen_helper_mttc0_tcschedule(cpu_env, t0);
9262 break;
9263 case 7:
9264 gen_helper_mttc0_tcschefback(cpu_env, t0);
9265 break;
9266 default:
9267 gen_mtc0(ctx, t0, rd, sel);
9268 break;
9270 break;
9271 case 10:
9272 switch (sel) {
9273 case 0:
9274 gen_helper_mttc0_entryhi(cpu_env, t0);
9275 break;
9276 default:
9277 gen_mtc0(ctx, t0, rd, sel);
9278 break;
9280 case 12:
9281 switch (sel) {
9282 case 0:
9283 gen_helper_mttc0_status(cpu_env, t0);
9284 break;
9285 default:
9286 gen_mtc0(ctx, t0, rd, sel);
9287 break;
9289 case 13:
9290 switch (sel) {
9291 case 0:
9292 gen_helper_mttc0_cause(cpu_env, t0);
9293 break;
9294 default:
9295 goto die;
9296 break;
9298 break;
9299 case 15:
9300 switch (sel) {
9301 case 1:
9302 gen_helper_mttc0_ebase(cpu_env, t0);
9303 break;
9304 default:
9305 goto die;
9306 break;
9308 break;
9309 case 23:
9310 switch (sel) {
9311 case 0:
9312 gen_helper_mttc0_debug(cpu_env, t0);
9313 break;
9314 default:
9315 gen_mtc0(ctx, t0, rd, sel);
9316 break;
9318 break;
9319 default:
9320 gen_mtc0(ctx, t0, rd, sel);
9322 } else switch (sel) {
9323 /* GPR registers. */
9324 case 0:
9325 gen_helper_0e1i(mttgpr, t0, rd);
9326 break;
9327 /* Auxiliary CPU registers */
9328 case 1:
9329 switch (rd) {
9330 case 0:
9331 gen_helper_0e1i(mttlo, t0, 0);
9332 break;
9333 case 1:
9334 gen_helper_0e1i(mtthi, t0, 0);
9335 break;
9336 case 2:
9337 gen_helper_0e1i(mttacx, t0, 0);
9338 break;
9339 case 4:
9340 gen_helper_0e1i(mttlo, t0, 1);
9341 break;
9342 case 5:
9343 gen_helper_0e1i(mtthi, t0, 1);
9344 break;
9345 case 6:
9346 gen_helper_0e1i(mttacx, t0, 1);
9347 break;
9348 case 8:
9349 gen_helper_0e1i(mttlo, t0, 2);
9350 break;
9351 case 9:
9352 gen_helper_0e1i(mtthi, t0, 2);
9353 break;
9354 case 10:
9355 gen_helper_0e1i(mttacx, t0, 2);
9356 break;
9357 case 12:
9358 gen_helper_0e1i(mttlo, t0, 3);
9359 break;
9360 case 13:
9361 gen_helper_0e1i(mtthi, t0, 3);
9362 break;
9363 case 14:
9364 gen_helper_0e1i(mttacx, t0, 3);
9365 break;
9366 case 16:
9367 gen_helper_mttdsp(cpu_env, t0);
9368 break;
9369 default:
9370 goto die;
9372 break;
9373 /* Floating point (COP1). */
9374 case 2:
9375 /* XXX: For now we support only a single FPU context. */
9376 if (h == 0) {
9377 TCGv_i32 fp0 = tcg_temp_new_i32();
9379 tcg_gen_trunc_tl_i32(fp0, t0);
9380 gen_store_fpr32(ctx, fp0, rd);
9381 tcg_temp_free_i32(fp0);
9382 } else {
9383 TCGv_i32 fp0 = tcg_temp_new_i32();
9385 tcg_gen_trunc_tl_i32(fp0, t0);
9386 gen_store_fpr32h(ctx, fp0, rd);
9387 tcg_temp_free_i32(fp0);
9389 break;
9390 case 3:
9391 /* XXX: For now we support only a single FPU context. */
9393 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9395 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9396 tcg_temp_free_i32(fs_tmp);
9398 /* Stop translation as we may have changed hflags */
9399 ctx->base.is_jmp = DISAS_STOP;
9400 break;
9401 /* COP2: Not implemented. */
9402 case 4:
9403 case 5:
9404 /* fall through */
9405 default:
9406 goto die;
9408 trace_mips_translate_tr("mttr", rd, u, sel, h);
9409 tcg_temp_free(t0);
9410 return;
9412 die:
9413 tcg_temp_free(t0);
9414 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9415 generate_exception_end(ctx, EXCP_RI);
9418 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9420 const char *opn = "ldst";
9422 check_cp0_enabled(ctx);
9423 switch (opc) {
9424 case OPC_MFC0:
9425 if (rt == 0) {
9426 /* Treat as NOP. */
9427 return;
9429 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9430 opn = "mfc0";
9431 break;
9432 case OPC_MTC0:
9434 TCGv t0 = tcg_temp_new();
9436 gen_load_gpr(t0, rt);
9437 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9438 tcg_temp_free(t0);
9440 opn = "mtc0";
9441 break;
9442 #if defined(TARGET_MIPS64)
9443 case OPC_DMFC0:
9444 check_insn(ctx, ISA_MIPS3);
9445 if (rt == 0) {
9446 /* Treat as NOP. */
9447 return;
9449 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9450 opn = "dmfc0";
9451 break;
9452 case OPC_DMTC0:
9453 check_insn(ctx, ISA_MIPS3);
9455 TCGv t0 = tcg_temp_new();
9457 gen_load_gpr(t0, rt);
9458 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9459 tcg_temp_free(t0);
9461 opn = "dmtc0";
9462 break;
9463 #endif
9464 case OPC_MFHC0:
9465 check_mvh(ctx);
9466 if (rt == 0) {
9467 /* Treat as NOP. */
9468 return;
9470 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9471 opn = "mfhc0";
9472 break;
9473 case OPC_MTHC0:
9474 check_mvh(ctx);
9476 TCGv t0 = tcg_temp_new();
9477 gen_load_gpr(t0, rt);
9478 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9479 tcg_temp_free(t0);
9481 opn = "mthc0";
9482 break;
9483 case OPC_MFTR:
9484 check_cp0_enabled(ctx);
9485 if (rd == 0) {
9486 /* Treat as NOP. */
9487 return;
9489 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9490 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9491 opn = "mftr";
9492 break;
9493 case OPC_MTTR:
9494 check_cp0_enabled(ctx);
9495 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9496 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9497 opn = "mttr";
9498 break;
9499 case OPC_TLBWI:
9500 opn = "tlbwi";
9501 if (!env->tlb->helper_tlbwi)
9502 goto die;
9503 gen_helper_tlbwi(cpu_env);
9504 break;
9505 case OPC_TLBINV:
9506 opn = "tlbinv";
9507 if (ctx->ie >= 2) {
9508 if (!env->tlb->helper_tlbinv) {
9509 goto die;
9511 gen_helper_tlbinv(cpu_env);
9512 } /* treat as nop if TLBINV not supported */
9513 break;
9514 case OPC_TLBINVF:
9515 opn = "tlbinvf";
9516 if (ctx->ie >= 2) {
9517 if (!env->tlb->helper_tlbinvf) {
9518 goto die;
9520 gen_helper_tlbinvf(cpu_env);
9521 } /* treat as nop if TLBINV not supported */
9522 break;
9523 case OPC_TLBWR:
9524 opn = "tlbwr";
9525 if (!env->tlb->helper_tlbwr)
9526 goto die;
9527 gen_helper_tlbwr(cpu_env);
9528 break;
9529 case OPC_TLBP:
9530 opn = "tlbp";
9531 if (!env->tlb->helper_tlbp)
9532 goto die;
9533 gen_helper_tlbp(cpu_env);
9534 break;
9535 case OPC_TLBR:
9536 opn = "tlbr";
9537 if (!env->tlb->helper_tlbr)
9538 goto die;
9539 gen_helper_tlbr(cpu_env);
9540 break;
9541 case OPC_ERET: /* OPC_ERETNC */
9542 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9543 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9544 goto die;
9545 } else {
9546 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9547 if (ctx->opcode & (1 << bit_shift)) {
9548 /* OPC_ERETNC */
9549 opn = "eretnc";
9550 check_insn(ctx, ISA_MIPS32R5);
9551 gen_helper_eretnc(cpu_env);
9552 } else {
9553 /* OPC_ERET */
9554 opn = "eret";
9555 check_insn(ctx, ISA_MIPS2);
9556 gen_helper_eret(cpu_env);
9558 ctx->base.is_jmp = DISAS_EXIT;
9560 break;
9561 case OPC_DERET:
9562 opn = "deret";
9563 check_insn(ctx, ISA_MIPS32);
9564 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9565 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9566 goto die;
9568 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9569 MIPS_INVAL(opn);
9570 generate_exception_end(ctx, EXCP_RI);
9571 } else {
9572 gen_helper_deret(cpu_env);
9573 ctx->base.is_jmp = DISAS_EXIT;
9575 break;
9576 case OPC_WAIT:
9577 opn = "wait";
9578 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9579 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9580 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9581 goto die;
9583 /* If we get an exception, we want to restart at next instruction */
9584 ctx->base.pc_next += 4;
9585 save_cpu_state(ctx, 1);
9586 ctx->base.pc_next -= 4;
9587 gen_helper_wait(cpu_env);
9588 ctx->base.is_jmp = DISAS_NORETURN;
9589 break;
9590 default:
9591 die:
9592 MIPS_INVAL(opn);
9593 generate_exception_end(ctx, EXCP_RI);
9594 return;
9596 (void)opn; /* avoid a compiler warning */
9598 #endif /* !CONFIG_USER_ONLY */
9600 /* CP1 Branches (before delay slot) */
9601 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9602 int32_t cc, int32_t offset)
9604 target_ulong btarget;
9605 TCGv_i32 t0 = tcg_temp_new_i32();
9607 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9608 generate_exception_end(ctx, EXCP_RI);
9609 goto out;
9612 if (cc != 0)
9613 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9615 btarget = ctx->base.pc_next + 4 + offset;
9617 switch (op) {
9618 case OPC_BC1F:
9619 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9620 tcg_gen_not_i32(t0, t0);
9621 tcg_gen_andi_i32(t0, t0, 1);
9622 tcg_gen_extu_i32_tl(bcond, t0);
9623 goto not_likely;
9624 case OPC_BC1FL:
9625 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9626 tcg_gen_not_i32(t0, t0);
9627 tcg_gen_andi_i32(t0, t0, 1);
9628 tcg_gen_extu_i32_tl(bcond, t0);
9629 goto likely;
9630 case OPC_BC1T:
9631 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9632 tcg_gen_andi_i32(t0, t0, 1);
9633 tcg_gen_extu_i32_tl(bcond, t0);
9634 goto not_likely;
9635 case OPC_BC1TL:
9636 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9637 tcg_gen_andi_i32(t0, t0, 1);
9638 tcg_gen_extu_i32_tl(bcond, t0);
9639 likely:
9640 ctx->hflags |= MIPS_HFLAG_BL;
9641 break;
9642 case OPC_BC1FANY2:
9644 TCGv_i32 t1 = tcg_temp_new_i32();
9645 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9646 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9647 tcg_gen_nand_i32(t0, t0, t1);
9648 tcg_temp_free_i32(t1);
9649 tcg_gen_andi_i32(t0, t0, 1);
9650 tcg_gen_extu_i32_tl(bcond, t0);
9652 goto not_likely;
9653 case OPC_BC1TANY2:
9655 TCGv_i32 t1 = tcg_temp_new_i32();
9656 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9657 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9658 tcg_gen_or_i32(t0, t0, t1);
9659 tcg_temp_free_i32(t1);
9660 tcg_gen_andi_i32(t0, t0, 1);
9661 tcg_gen_extu_i32_tl(bcond, t0);
9663 goto not_likely;
9664 case OPC_BC1FANY4:
9666 TCGv_i32 t1 = tcg_temp_new_i32();
9667 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9668 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9669 tcg_gen_and_i32(t0, t0, t1);
9670 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9671 tcg_gen_and_i32(t0, t0, t1);
9672 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9673 tcg_gen_nand_i32(t0, t0, t1);
9674 tcg_temp_free_i32(t1);
9675 tcg_gen_andi_i32(t0, t0, 1);
9676 tcg_gen_extu_i32_tl(bcond, t0);
9678 goto not_likely;
9679 case OPC_BC1TANY4:
9681 TCGv_i32 t1 = tcg_temp_new_i32();
9682 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9683 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9684 tcg_gen_or_i32(t0, t0, t1);
9685 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9686 tcg_gen_or_i32(t0, t0, t1);
9687 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9688 tcg_gen_or_i32(t0, t0, t1);
9689 tcg_temp_free_i32(t1);
9690 tcg_gen_andi_i32(t0, t0, 1);
9691 tcg_gen_extu_i32_tl(bcond, t0);
9693 not_likely:
9694 ctx->hflags |= MIPS_HFLAG_BC;
9695 break;
9696 default:
9697 MIPS_INVAL("cp1 cond branch");
9698 generate_exception_end(ctx, EXCP_RI);
9699 goto out;
9701 ctx->btarget = btarget;
9702 ctx->hflags |= MIPS_HFLAG_BDS32;
9703 out:
9704 tcg_temp_free_i32(t0);
9707 /* R6 CP1 Branches */
9708 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9709 int32_t ft, int32_t offset,
9710 int delayslot_size)
9712 target_ulong btarget;
9713 TCGv_i64 t0 = tcg_temp_new_i64();
9715 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9716 #ifdef MIPS_DEBUG_DISAS
9717 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9718 "\n", ctx->base.pc_next);
9719 #endif
9720 generate_exception_end(ctx, EXCP_RI);
9721 goto out;
9724 gen_load_fpr64(ctx, t0, ft);
9725 tcg_gen_andi_i64(t0, t0, 1);
9727 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9729 switch (op) {
9730 case OPC_BC1EQZ:
9731 tcg_gen_xori_i64(t0, t0, 1);
9732 ctx->hflags |= MIPS_HFLAG_BC;
9733 break;
9734 case OPC_BC1NEZ:
9735 /* t0 already set */
9736 ctx->hflags |= MIPS_HFLAG_BC;
9737 break;
9738 default:
9739 MIPS_INVAL("cp1 cond branch");
9740 generate_exception_end(ctx, EXCP_RI);
9741 goto out;
9744 tcg_gen_trunc_i64_tl(bcond, t0);
9746 ctx->btarget = btarget;
9748 switch (delayslot_size) {
9749 case 2:
9750 ctx->hflags |= MIPS_HFLAG_BDS16;
9751 break;
9752 case 4:
9753 ctx->hflags |= MIPS_HFLAG_BDS32;
9754 break;
9757 out:
9758 tcg_temp_free_i64(t0);
9761 /* Coprocessor 1 (FPU) */
9763 #define FOP(func, fmt) (((fmt) << 21) | (func))
9765 enum fopcode {
9766 OPC_ADD_S = FOP(0, FMT_S),
9767 OPC_SUB_S = FOP(1, FMT_S),
9768 OPC_MUL_S = FOP(2, FMT_S),
9769 OPC_DIV_S = FOP(3, FMT_S),
9770 OPC_SQRT_S = FOP(4, FMT_S),
9771 OPC_ABS_S = FOP(5, FMT_S),
9772 OPC_MOV_S = FOP(6, FMT_S),
9773 OPC_NEG_S = FOP(7, FMT_S),
9774 OPC_ROUND_L_S = FOP(8, FMT_S),
9775 OPC_TRUNC_L_S = FOP(9, FMT_S),
9776 OPC_CEIL_L_S = FOP(10, FMT_S),
9777 OPC_FLOOR_L_S = FOP(11, FMT_S),
9778 OPC_ROUND_W_S = FOP(12, FMT_S),
9779 OPC_TRUNC_W_S = FOP(13, FMT_S),
9780 OPC_CEIL_W_S = FOP(14, FMT_S),
9781 OPC_FLOOR_W_S = FOP(15, FMT_S),
9782 OPC_SEL_S = FOP(16, FMT_S),
9783 OPC_MOVCF_S = FOP(17, FMT_S),
9784 OPC_MOVZ_S = FOP(18, FMT_S),
9785 OPC_MOVN_S = FOP(19, FMT_S),
9786 OPC_SELEQZ_S = FOP(20, FMT_S),
9787 OPC_RECIP_S = FOP(21, FMT_S),
9788 OPC_RSQRT_S = FOP(22, FMT_S),
9789 OPC_SELNEZ_S = FOP(23, FMT_S),
9790 OPC_MADDF_S = FOP(24, FMT_S),
9791 OPC_MSUBF_S = FOP(25, FMT_S),
9792 OPC_RINT_S = FOP(26, FMT_S),
9793 OPC_CLASS_S = FOP(27, FMT_S),
9794 OPC_MIN_S = FOP(28, FMT_S),
9795 OPC_RECIP2_S = FOP(28, FMT_S),
9796 OPC_MINA_S = FOP(29, FMT_S),
9797 OPC_RECIP1_S = FOP(29, FMT_S),
9798 OPC_MAX_S = FOP(30, FMT_S),
9799 OPC_RSQRT1_S = FOP(30, FMT_S),
9800 OPC_MAXA_S = FOP(31, FMT_S),
9801 OPC_RSQRT2_S = FOP(31, FMT_S),
9802 OPC_CVT_D_S = FOP(33, FMT_S),
9803 OPC_CVT_W_S = FOP(36, FMT_S),
9804 OPC_CVT_L_S = FOP(37, FMT_S),
9805 OPC_CVT_PS_S = FOP(38, FMT_S),
9806 OPC_CMP_F_S = FOP (48, FMT_S),
9807 OPC_CMP_UN_S = FOP (49, FMT_S),
9808 OPC_CMP_EQ_S = FOP (50, FMT_S),
9809 OPC_CMP_UEQ_S = FOP (51, FMT_S),
9810 OPC_CMP_OLT_S = FOP (52, FMT_S),
9811 OPC_CMP_ULT_S = FOP (53, FMT_S),
9812 OPC_CMP_OLE_S = FOP (54, FMT_S),
9813 OPC_CMP_ULE_S = FOP (55, FMT_S),
9814 OPC_CMP_SF_S = FOP (56, FMT_S),
9815 OPC_CMP_NGLE_S = FOP (57, FMT_S),
9816 OPC_CMP_SEQ_S = FOP (58, FMT_S),
9817 OPC_CMP_NGL_S = FOP (59, FMT_S),
9818 OPC_CMP_LT_S = FOP (60, FMT_S),
9819 OPC_CMP_NGE_S = FOP (61, FMT_S),
9820 OPC_CMP_LE_S = FOP (62, FMT_S),
9821 OPC_CMP_NGT_S = FOP (63, FMT_S),
9823 OPC_ADD_D = FOP(0, FMT_D),
9824 OPC_SUB_D = FOP(1, FMT_D),
9825 OPC_MUL_D = FOP(2, FMT_D),
9826 OPC_DIV_D = FOP(3, FMT_D),
9827 OPC_SQRT_D = FOP(4, FMT_D),
9828 OPC_ABS_D = FOP(5, FMT_D),
9829 OPC_MOV_D = FOP(6, FMT_D),
9830 OPC_NEG_D = FOP(7, FMT_D),
9831 OPC_ROUND_L_D = FOP(8, FMT_D),
9832 OPC_TRUNC_L_D = FOP(9, FMT_D),
9833 OPC_CEIL_L_D = FOP(10, FMT_D),
9834 OPC_FLOOR_L_D = FOP(11, FMT_D),
9835 OPC_ROUND_W_D = FOP(12, FMT_D),
9836 OPC_TRUNC_W_D = FOP(13, FMT_D),
9837 OPC_CEIL_W_D = FOP(14, FMT_D),
9838 OPC_FLOOR_W_D = FOP(15, FMT_D),
9839 OPC_SEL_D = FOP(16, FMT_D),
9840 OPC_MOVCF_D = FOP(17, FMT_D),
9841 OPC_MOVZ_D = FOP(18, FMT_D),
9842 OPC_MOVN_D = FOP(19, FMT_D),
9843 OPC_SELEQZ_D = FOP(20, FMT_D),
9844 OPC_RECIP_D = FOP(21, FMT_D),
9845 OPC_RSQRT_D = FOP(22, FMT_D),
9846 OPC_SELNEZ_D = FOP(23, FMT_D),
9847 OPC_MADDF_D = FOP(24, FMT_D),
9848 OPC_MSUBF_D = FOP(25, FMT_D),
9849 OPC_RINT_D = FOP(26, FMT_D),
9850 OPC_CLASS_D = FOP(27, FMT_D),
9851 OPC_MIN_D = FOP(28, FMT_D),
9852 OPC_RECIP2_D = FOP(28, FMT_D),
9853 OPC_MINA_D = FOP(29, FMT_D),
9854 OPC_RECIP1_D = FOP(29, FMT_D),
9855 OPC_MAX_D = FOP(30, FMT_D),
9856 OPC_RSQRT1_D = FOP(30, FMT_D),
9857 OPC_MAXA_D = FOP(31, FMT_D),
9858 OPC_RSQRT2_D = FOP(31, FMT_D),
9859 OPC_CVT_S_D = FOP(32, FMT_D),
9860 OPC_CVT_W_D = FOP(36, FMT_D),
9861 OPC_CVT_L_D = FOP(37, FMT_D),
9862 OPC_CMP_F_D = FOP (48, FMT_D),
9863 OPC_CMP_UN_D = FOP (49, FMT_D),
9864 OPC_CMP_EQ_D = FOP (50, FMT_D),
9865 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9866 OPC_CMP_OLT_D = FOP (52, FMT_D),
9867 OPC_CMP_ULT_D = FOP (53, FMT_D),
9868 OPC_CMP_OLE_D = FOP (54, FMT_D),
9869 OPC_CMP_ULE_D = FOP (55, FMT_D),
9870 OPC_CMP_SF_D = FOP (56, FMT_D),
9871 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9872 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9873 OPC_CMP_NGL_D = FOP (59, FMT_D),
9874 OPC_CMP_LT_D = FOP (60, FMT_D),
9875 OPC_CMP_NGE_D = FOP (61, FMT_D),
9876 OPC_CMP_LE_D = FOP (62, FMT_D),
9877 OPC_CMP_NGT_D = FOP (63, FMT_D),
9879 OPC_CVT_S_W = FOP(32, FMT_W),
9880 OPC_CVT_D_W = FOP(33, FMT_W),
9881 OPC_CVT_S_L = FOP(32, FMT_L),
9882 OPC_CVT_D_L = FOP(33, FMT_L),
9883 OPC_CVT_PS_PW = FOP(38, FMT_W),
9885 OPC_ADD_PS = FOP(0, FMT_PS),
9886 OPC_SUB_PS = FOP(1, FMT_PS),
9887 OPC_MUL_PS = FOP(2, FMT_PS),
9888 OPC_DIV_PS = FOP(3, FMT_PS),
9889 OPC_ABS_PS = FOP(5, FMT_PS),
9890 OPC_MOV_PS = FOP(6, FMT_PS),
9891 OPC_NEG_PS = FOP(7, FMT_PS),
9892 OPC_MOVCF_PS = FOP(17, FMT_PS),
9893 OPC_MOVZ_PS = FOP(18, FMT_PS),
9894 OPC_MOVN_PS = FOP(19, FMT_PS),
9895 OPC_ADDR_PS = FOP(24, FMT_PS),
9896 OPC_MULR_PS = FOP(26, FMT_PS),
9897 OPC_RECIP2_PS = FOP(28, FMT_PS),
9898 OPC_RECIP1_PS = FOP(29, FMT_PS),
9899 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9900 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9902 OPC_CVT_S_PU = FOP(32, FMT_PS),
9903 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9904 OPC_CVT_S_PL = FOP(40, FMT_PS),
9905 OPC_PLL_PS = FOP(44, FMT_PS),
9906 OPC_PLU_PS = FOP(45, FMT_PS),
9907 OPC_PUL_PS = FOP(46, FMT_PS),
9908 OPC_PUU_PS = FOP(47, FMT_PS),
9909 OPC_CMP_F_PS = FOP (48, FMT_PS),
9910 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9911 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9912 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9913 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9914 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9915 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9916 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9917 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9918 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9919 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9920 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9921 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9922 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9923 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9924 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9927 enum r6_f_cmp_op {
9928 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9929 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9930 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9931 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9932 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9933 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9934 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9935 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9936 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9937 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9938 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9939 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9940 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9941 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9942 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9943 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9944 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9945 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9946 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9947 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9948 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9949 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9951 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9952 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9953 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9954 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9955 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9956 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9957 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9958 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9959 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9960 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9961 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9962 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9963 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9964 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9965 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9966 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9967 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9968 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9969 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9970 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9971 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9972 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9974 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
9976 TCGv t0 = tcg_temp_new();
9978 switch (opc) {
9979 case OPC_MFC1:
9981 TCGv_i32 fp0 = tcg_temp_new_i32();
9983 gen_load_fpr32(ctx, fp0, fs);
9984 tcg_gen_ext_i32_tl(t0, fp0);
9985 tcg_temp_free_i32(fp0);
9987 gen_store_gpr(t0, rt);
9988 break;
9989 case OPC_MTC1:
9990 gen_load_gpr(t0, rt);
9992 TCGv_i32 fp0 = tcg_temp_new_i32();
9994 tcg_gen_trunc_tl_i32(fp0, t0);
9995 gen_store_fpr32(ctx, fp0, fs);
9996 tcg_temp_free_i32(fp0);
9998 break;
9999 case OPC_CFC1:
10000 gen_helper_1e0i(cfc1, t0, fs);
10001 gen_store_gpr(t0, rt);
10002 break;
10003 case OPC_CTC1:
10004 gen_load_gpr(t0, rt);
10005 save_cpu_state(ctx, 0);
10007 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10009 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10010 tcg_temp_free_i32(fs_tmp);
10012 /* Stop translation as we may have changed hflags */
10013 ctx->base.is_jmp = DISAS_STOP;
10014 break;
10015 #if defined(TARGET_MIPS64)
10016 case OPC_DMFC1:
10017 gen_load_fpr64(ctx, t0, fs);
10018 gen_store_gpr(t0, rt);
10019 break;
10020 case OPC_DMTC1:
10021 gen_load_gpr(t0, rt);
10022 gen_store_fpr64(ctx, t0, fs);
10023 break;
10024 #endif
10025 case OPC_MFHC1:
10027 TCGv_i32 fp0 = tcg_temp_new_i32();
10029 gen_load_fpr32h(ctx, fp0, fs);
10030 tcg_gen_ext_i32_tl(t0, fp0);
10031 tcg_temp_free_i32(fp0);
10033 gen_store_gpr(t0, rt);
10034 break;
10035 case OPC_MTHC1:
10036 gen_load_gpr(t0, rt);
10038 TCGv_i32 fp0 = tcg_temp_new_i32();
10040 tcg_gen_trunc_tl_i32(fp0, t0);
10041 gen_store_fpr32h(ctx, fp0, fs);
10042 tcg_temp_free_i32(fp0);
10044 break;
10045 default:
10046 MIPS_INVAL("cp1 move");
10047 generate_exception_end(ctx, EXCP_RI);
10048 goto out;
10051 out:
10052 tcg_temp_free(t0);
10055 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10057 TCGLabel *l1;
10058 TCGCond cond;
10059 TCGv_i32 t0;
10061 if (rd == 0) {
10062 /* Treat as NOP. */
10063 return;
10066 if (tf)
10067 cond = TCG_COND_EQ;
10068 else
10069 cond = TCG_COND_NE;
10071 l1 = gen_new_label();
10072 t0 = tcg_temp_new_i32();
10073 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10074 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10075 tcg_temp_free_i32(t0);
10076 if (rs == 0) {
10077 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10078 } else {
10079 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10081 gen_set_label(l1);
10084 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10085 int tf)
10087 int cond;
10088 TCGv_i32 t0 = tcg_temp_new_i32();
10089 TCGLabel *l1 = gen_new_label();
10091 if (tf)
10092 cond = TCG_COND_EQ;
10093 else
10094 cond = TCG_COND_NE;
10096 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10097 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10098 gen_load_fpr32(ctx, t0, fs);
10099 gen_store_fpr32(ctx, t0, fd);
10100 gen_set_label(l1);
10101 tcg_temp_free_i32(t0);
10104 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10106 int cond;
10107 TCGv_i32 t0 = tcg_temp_new_i32();
10108 TCGv_i64 fp0;
10109 TCGLabel *l1 = gen_new_label();
10111 if (tf)
10112 cond = TCG_COND_EQ;
10113 else
10114 cond = TCG_COND_NE;
10116 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10117 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10118 tcg_temp_free_i32(t0);
10119 fp0 = tcg_temp_new_i64();
10120 gen_load_fpr64(ctx, fp0, fs);
10121 gen_store_fpr64(ctx, fp0, fd);
10122 tcg_temp_free_i64(fp0);
10123 gen_set_label(l1);
10126 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10127 int cc, int tf)
10129 int cond;
10130 TCGv_i32 t0 = tcg_temp_new_i32();
10131 TCGLabel *l1 = gen_new_label();
10132 TCGLabel *l2 = gen_new_label();
10134 if (tf)
10135 cond = TCG_COND_EQ;
10136 else
10137 cond = TCG_COND_NE;
10139 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10140 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10141 gen_load_fpr32(ctx, t0, fs);
10142 gen_store_fpr32(ctx, t0, fd);
10143 gen_set_label(l1);
10145 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10146 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10147 gen_load_fpr32h(ctx, t0, fs);
10148 gen_store_fpr32h(ctx, t0, fd);
10149 tcg_temp_free_i32(t0);
10150 gen_set_label(l2);
10153 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10154 int fs)
10156 TCGv_i32 t1 = tcg_const_i32(0);
10157 TCGv_i32 fp0 = tcg_temp_new_i32();
10158 TCGv_i32 fp1 = tcg_temp_new_i32();
10159 TCGv_i32 fp2 = tcg_temp_new_i32();
10160 gen_load_fpr32(ctx, fp0, fd);
10161 gen_load_fpr32(ctx, fp1, ft);
10162 gen_load_fpr32(ctx, fp2, fs);
10164 switch (op1) {
10165 case OPC_SEL_S:
10166 tcg_gen_andi_i32(fp0, fp0, 1);
10167 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10168 break;
10169 case OPC_SELEQZ_S:
10170 tcg_gen_andi_i32(fp1, fp1, 1);
10171 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10172 break;
10173 case OPC_SELNEZ_S:
10174 tcg_gen_andi_i32(fp1, fp1, 1);
10175 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10176 break;
10177 default:
10178 MIPS_INVAL("gen_sel_s");
10179 generate_exception_end(ctx, EXCP_RI);
10180 break;
10183 gen_store_fpr32(ctx, fp0, fd);
10184 tcg_temp_free_i32(fp2);
10185 tcg_temp_free_i32(fp1);
10186 tcg_temp_free_i32(fp0);
10187 tcg_temp_free_i32(t1);
10190 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10191 int fs)
10193 TCGv_i64 t1 = tcg_const_i64(0);
10194 TCGv_i64 fp0 = tcg_temp_new_i64();
10195 TCGv_i64 fp1 = tcg_temp_new_i64();
10196 TCGv_i64 fp2 = tcg_temp_new_i64();
10197 gen_load_fpr64(ctx, fp0, fd);
10198 gen_load_fpr64(ctx, fp1, ft);
10199 gen_load_fpr64(ctx, fp2, fs);
10201 switch (op1) {
10202 case OPC_SEL_D:
10203 tcg_gen_andi_i64(fp0, fp0, 1);
10204 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10205 break;
10206 case OPC_SELEQZ_D:
10207 tcg_gen_andi_i64(fp1, fp1, 1);
10208 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10209 break;
10210 case OPC_SELNEZ_D:
10211 tcg_gen_andi_i64(fp1, fp1, 1);
10212 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10213 break;
10214 default:
10215 MIPS_INVAL("gen_sel_d");
10216 generate_exception_end(ctx, EXCP_RI);
10217 break;
10220 gen_store_fpr64(ctx, fp0, fd);
10221 tcg_temp_free_i64(fp2);
10222 tcg_temp_free_i64(fp1);
10223 tcg_temp_free_i64(fp0);
10224 tcg_temp_free_i64(t1);
10227 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10228 int ft, int fs, int fd, int cc)
10230 uint32_t func = ctx->opcode & 0x3f;
10231 switch (op1) {
10232 case OPC_ADD_S:
10234 TCGv_i32 fp0 = tcg_temp_new_i32();
10235 TCGv_i32 fp1 = tcg_temp_new_i32();
10237 gen_load_fpr32(ctx, fp0, fs);
10238 gen_load_fpr32(ctx, fp1, ft);
10239 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10240 tcg_temp_free_i32(fp1);
10241 gen_store_fpr32(ctx, fp0, fd);
10242 tcg_temp_free_i32(fp0);
10244 break;
10245 case OPC_SUB_S:
10247 TCGv_i32 fp0 = tcg_temp_new_i32();
10248 TCGv_i32 fp1 = tcg_temp_new_i32();
10250 gen_load_fpr32(ctx, fp0, fs);
10251 gen_load_fpr32(ctx, fp1, ft);
10252 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10253 tcg_temp_free_i32(fp1);
10254 gen_store_fpr32(ctx, fp0, fd);
10255 tcg_temp_free_i32(fp0);
10257 break;
10258 case OPC_MUL_S:
10260 TCGv_i32 fp0 = tcg_temp_new_i32();
10261 TCGv_i32 fp1 = tcg_temp_new_i32();
10263 gen_load_fpr32(ctx, fp0, fs);
10264 gen_load_fpr32(ctx, fp1, ft);
10265 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10266 tcg_temp_free_i32(fp1);
10267 gen_store_fpr32(ctx, fp0, fd);
10268 tcg_temp_free_i32(fp0);
10270 break;
10271 case OPC_DIV_S:
10273 TCGv_i32 fp0 = tcg_temp_new_i32();
10274 TCGv_i32 fp1 = tcg_temp_new_i32();
10276 gen_load_fpr32(ctx, fp0, fs);
10277 gen_load_fpr32(ctx, fp1, ft);
10278 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10279 tcg_temp_free_i32(fp1);
10280 gen_store_fpr32(ctx, fp0, fd);
10281 tcg_temp_free_i32(fp0);
10283 break;
10284 case OPC_SQRT_S:
10286 TCGv_i32 fp0 = tcg_temp_new_i32();
10288 gen_load_fpr32(ctx, fp0, fs);
10289 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10290 gen_store_fpr32(ctx, fp0, fd);
10291 tcg_temp_free_i32(fp0);
10293 break;
10294 case OPC_ABS_S:
10296 TCGv_i32 fp0 = tcg_temp_new_i32();
10298 gen_load_fpr32(ctx, fp0, fs);
10299 if (ctx->abs2008) {
10300 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10301 } else {
10302 gen_helper_float_abs_s(fp0, fp0);
10304 gen_store_fpr32(ctx, fp0, fd);
10305 tcg_temp_free_i32(fp0);
10307 break;
10308 case OPC_MOV_S:
10310 TCGv_i32 fp0 = tcg_temp_new_i32();
10312 gen_load_fpr32(ctx, fp0, fs);
10313 gen_store_fpr32(ctx, fp0, fd);
10314 tcg_temp_free_i32(fp0);
10316 break;
10317 case OPC_NEG_S:
10319 TCGv_i32 fp0 = tcg_temp_new_i32();
10321 gen_load_fpr32(ctx, fp0, fs);
10322 if (ctx->abs2008) {
10323 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10324 } else {
10325 gen_helper_float_chs_s(fp0, fp0);
10327 gen_store_fpr32(ctx, fp0, fd);
10328 tcg_temp_free_i32(fp0);
10330 break;
10331 case OPC_ROUND_L_S:
10332 check_cp1_64bitmode(ctx);
10334 TCGv_i32 fp32 = tcg_temp_new_i32();
10335 TCGv_i64 fp64 = tcg_temp_new_i64();
10337 gen_load_fpr32(ctx, fp32, fs);
10338 if (ctx->nan2008) {
10339 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10340 } else {
10341 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10343 tcg_temp_free_i32(fp32);
10344 gen_store_fpr64(ctx, fp64, fd);
10345 tcg_temp_free_i64(fp64);
10347 break;
10348 case OPC_TRUNC_L_S:
10349 check_cp1_64bitmode(ctx);
10351 TCGv_i32 fp32 = tcg_temp_new_i32();
10352 TCGv_i64 fp64 = tcg_temp_new_i64();
10354 gen_load_fpr32(ctx, fp32, fs);
10355 if (ctx->nan2008) {
10356 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10357 } else {
10358 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10360 tcg_temp_free_i32(fp32);
10361 gen_store_fpr64(ctx, fp64, fd);
10362 tcg_temp_free_i64(fp64);
10364 break;
10365 case OPC_CEIL_L_S:
10366 check_cp1_64bitmode(ctx);
10368 TCGv_i32 fp32 = tcg_temp_new_i32();
10369 TCGv_i64 fp64 = tcg_temp_new_i64();
10371 gen_load_fpr32(ctx, fp32, fs);
10372 if (ctx->nan2008) {
10373 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10374 } else {
10375 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10377 tcg_temp_free_i32(fp32);
10378 gen_store_fpr64(ctx, fp64, fd);
10379 tcg_temp_free_i64(fp64);
10381 break;
10382 case OPC_FLOOR_L_S:
10383 check_cp1_64bitmode(ctx);
10385 TCGv_i32 fp32 = tcg_temp_new_i32();
10386 TCGv_i64 fp64 = tcg_temp_new_i64();
10388 gen_load_fpr32(ctx, fp32, fs);
10389 if (ctx->nan2008) {
10390 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10391 } else {
10392 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10394 tcg_temp_free_i32(fp32);
10395 gen_store_fpr64(ctx, fp64, fd);
10396 tcg_temp_free_i64(fp64);
10398 break;
10399 case OPC_ROUND_W_S:
10401 TCGv_i32 fp0 = tcg_temp_new_i32();
10403 gen_load_fpr32(ctx, fp0, fs);
10404 if (ctx->nan2008) {
10405 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10406 } else {
10407 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10409 gen_store_fpr32(ctx, fp0, fd);
10410 tcg_temp_free_i32(fp0);
10412 break;
10413 case OPC_TRUNC_W_S:
10415 TCGv_i32 fp0 = tcg_temp_new_i32();
10417 gen_load_fpr32(ctx, fp0, fs);
10418 if (ctx->nan2008) {
10419 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10420 } else {
10421 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10423 gen_store_fpr32(ctx, fp0, fd);
10424 tcg_temp_free_i32(fp0);
10426 break;
10427 case OPC_CEIL_W_S:
10429 TCGv_i32 fp0 = tcg_temp_new_i32();
10431 gen_load_fpr32(ctx, fp0, fs);
10432 if (ctx->nan2008) {
10433 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10434 } else {
10435 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10437 gen_store_fpr32(ctx, fp0, fd);
10438 tcg_temp_free_i32(fp0);
10440 break;
10441 case OPC_FLOOR_W_S:
10443 TCGv_i32 fp0 = tcg_temp_new_i32();
10445 gen_load_fpr32(ctx, fp0, fs);
10446 if (ctx->nan2008) {
10447 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10448 } else {
10449 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10451 gen_store_fpr32(ctx, fp0, fd);
10452 tcg_temp_free_i32(fp0);
10454 break;
10455 case OPC_SEL_S:
10456 check_insn(ctx, ISA_MIPS32R6);
10457 gen_sel_s(ctx, op1, fd, ft, fs);
10458 break;
10459 case OPC_SELEQZ_S:
10460 check_insn(ctx, ISA_MIPS32R6);
10461 gen_sel_s(ctx, op1, fd, ft, fs);
10462 break;
10463 case OPC_SELNEZ_S:
10464 check_insn(ctx, ISA_MIPS32R6);
10465 gen_sel_s(ctx, op1, fd, ft, fs);
10466 break;
10467 case OPC_MOVCF_S:
10468 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10469 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10470 break;
10471 case OPC_MOVZ_S:
10472 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10474 TCGLabel *l1 = gen_new_label();
10475 TCGv_i32 fp0;
10477 if (ft != 0) {
10478 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10480 fp0 = tcg_temp_new_i32();
10481 gen_load_fpr32(ctx, fp0, fs);
10482 gen_store_fpr32(ctx, fp0, fd);
10483 tcg_temp_free_i32(fp0);
10484 gen_set_label(l1);
10486 break;
10487 case OPC_MOVN_S:
10488 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10490 TCGLabel *l1 = gen_new_label();
10491 TCGv_i32 fp0;
10493 if (ft != 0) {
10494 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10495 fp0 = tcg_temp_new_i32();
10496 gen_load_fpr32(ctx, fp0, fs);
10497 gen_store_fpr32(ctx, fp0, fd);
10498 tcg_temp_free_i32(fp0);
10499 gen_set_label(l1);
10502 break;
10503 case OPC_RECIP_S:
10505 TCGv_i32 fp0 = tcg_temp_new_i32();
10507 gen_load_fpr32(ctx, fp0, fs);
10508 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10509 gen_store_fpr32(ctx, fp0, fd);
10510 tcg_temp_free_i32(fp0);
10512 break;
10513 case OPC_RSQRT_S:
10515 TCGv_i32 fp0 = tcg_temp_new_i32();
10517 gen_load_fpr32(ctx, fp0, fs);
10518 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10519 gen_store_fpr32(ctx, fp0, fd);
10520 tcg_temp_free_i32(fp0);
10522 break;
10523 case OPC_MADDF_S:
10524 check_insn(ctx, ISA_MIPS32R6);
10526 TCGv_i32 fp0 = tcg_temp_new_i32();
10527 TCGv_i32 fp1 = tcg_temp_new_i32();
10528 TCGv_i32 fp2 = tcg_temp_new_i32();
10529 gen_load_fpr32(ctx, fp0, fs);
10530 gen_load_fpr32(ctx, fp1, ft);
10531 gen_load_fpr32(ctx, fp2, fd);
10532 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10533 gen_store_fpr32(ctx, fp2, fd);
10534 tcg_temp_free_i32(fp2);
10535 tcg_temp_free_i32(fp1);
10536 tcg_temp_free_i32(fp0);
10538 break;
10539 case OPC_MSUBF_S:
10540 check_insn(ctx, ISA_MIPS32R6);
10542 TCGv_i32 fp0 = tcg_temp_new_i32();
10543 TCGv_i32 fp1 = tcg_temp_new_i32();
10544 TCGv_i32 fp2 = tcg_temp_new_i32();
10545 gen_load_fpr32(ctx, fp0, fs);
10546 gen_load_fpr32(ctx, fp1, ft);
10547 gen_load_fpr32(ctx, fp2, fd);
10548 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10549 gen_store_fpr32(ctx, fp2, fd);
10550 tcg_temp_free_i32(fp2);
10551 tcg_temp_free_i32(fp1);
10552 tcg_temp_free_i32(fp0);
10554 break;
10555 case OPC_RINT_S:
10556 check_insn(ctx, ISA_MIPS32R6);
10558 TCGv_i32 fp0 = tcg_temp_new_i32();
10559 gen_load_fpr32(ctx, fp0, fs);
10560 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10561 gen_store_fpr32(ctx, fp0, fd);
10562 tcg_temp_free_i32(fp0);
10564 break;
10565 case OPC_CLASS_S:
10566 check_insn(ctx, ISA_MIPS32R6);
10568 TCGv_i32 fp0 = tcg_temp_new_i32();
10569 gen_load_fpr32(ctx, fp0, fs);
10570 gen_helper_float_class_s(fp0, cpu_env, fp0);
10571 gen_store_fpr32(ctx, fp0, fd);
10572 tcg_temp_free_i32(fp0);
10574 break;
10575 case OPC_MIN_S: /* OPC_RECIP2_S */
10576 if (ctx->insn_flags & ISA_MIPS32R6) {
10577 /* OPC_MIN_S */
10578 TCGv_i32 fp0 = tcg_temp_new_i32();
10579 TCGv_i32 fp1 = tcg_temp_new_i32();
10580 TCGv_i32 fp2 = tcg_temp_new_i32();
10581 gen_load_fpr32(ctx, fp0, fs);
10582 gen_load_fpr32(ctx, fp1, ft);
10583 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10584 gen_store_fpr32(ctx, fp2, fd);
10585 tcg_temp_free_i32(fp2);
10586 tcg_temp_free_i32(fp1);
10587 tcg_temp_free_i32(fp0);
10588 } else {
10589 /* OPC_RECIP2_S */
10590 check_cp1_64bitmode(ctx);
10592 TCGv_i32 fp0 = tcg_temp_new_i32();
10593 TCGv_i32 fp1 = tcg_temp_new_i32();
10595 gen_load_fpr32(ctx, fp0, fs);
10596 gen_load_fpr32(ctx, fp1, ft);
10597 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10598 tcg_temp_free_i32(fp1);
10599 gen_store_fpr32(ctx, fp0, fd);
10600 tcg_temp_free_i32(fp0);
10603 break;
10604 case OPC_MINA_S: /* OPC_RECIP1_S */
10605 if (ctx->insn_flags & ISA_MIPS32R6) {
10606 /* OPC_MINA_S */
10607 TCGv_i32 fp0 = tcg_temp_new_i32();
10608 TCGv_i32 fp1 = tcg_temp_new_i32();
10609 TCGv_i32 fp2 = tcg_temp_new_i32();
10610 gen_load_fpr32(ctx, fp0, fs);
10611 gen_load_fpr32(ctx, fp1, ft);
10612 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10613 gen_store_fpr32(ctx, fp2, fd);
10614 tcg_temp_free_i32(fp2);
10615 tcg_temp_free_i32(fp1);
10616 tcg_temp_free_i32(fp0);
10617 } else {
10618 /* OPC_RECIP1_S */
10619 check_cp1_64bitmode(ctx);
10621 TCGv_i32 fp0 = tcg_temp_new_i32();
10623 gen_load_fpr32(ctx, fp0, fs);
10624 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10625 gen_store_fpr32(ctx, fp0, fd);
10626 tcg_temp_free_i32(fp0);
10629 break;
10630 case OPC_MAX_S: /* OPC_RSQRT1_S */
10631 if (ctx->insn_flags & ISA_MIPS32R6) {
10632 /* OPC_MAX_S */
10633 TCGv_i32 fp0 = tcg_temp_new_i32();
10634 TCGv_i32 fp1 = tcg_temp_new_i32();
10635 gen_load_fpr32(ctx, fp0, fs);
10636 gen_load_fpr32(ctx, fp1, ft);
10637 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10638 gen_store_fpr32(ctx, fp1, fd);
10639 tcg_temp_free_i32(fp1);
10640 tcg_temp_free_i32(fp0);
10641 } else {
10642 /* OPC_RSQRT1_S */
10643 check_cp1_64bitmode(ctx);
10645 TCGv_i32 fp0 = tcg_temp_new_i32();
10647 gen_load_fpr32(ctx, fp0, fs);
10648 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10649 gen_store_fpr32(ctx, fp0, fd);
10650 tcg_temp_free_i32(fp0);
10653 break;
10654 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10655 if (ctx->insn_flags & ISA_MIPS32R6) {
10656 /* OPC_MAXA_S */
10657 TCGv_i32 fp0 = tcg_temp_new_i32();
10658 TCGv_i32 fp1 = tcg_temp_new_i32();
10659 gen_load_fpr32(ctx, fp0, fs);
10660 gen_load_fpr32(ctx, fp1, ft);
10661 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10662 gen_store_fpr32(ctx, fp1, fd);
10663 tcg_temp_free_i32(fp1);
10664 tcg_temp_free_i32(fp0);
10665 } else {
10666 /* OPC_RSQRT2_S */
10667 check_cp1_64bitmode(ctx);
10669 TCGv_i32 fp0 = tcg_temp_new_i32();
10670 TCGv_i32 fp1 = tcg_temp_new_i32();
10672 gen_load_fpr32(ctx, fp0, fs);
10673 gen_load_fpr32(ctx, fp1, ft);
10674 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10675 tcg_temp_free_i32(fp1);
10676 gen_store_fpr32(ctx, fp0, fd);
10677 tcg_temp_free_i32(fp0);
10680 break;
10681 case OPC_CVT_D_S:
10682 check_cp1_registers(ctx, fd);
10684 TCGv_i32 fp32 = tcg_temp_new_i32();
10685 TCGv_i64 fp64 = tcg_temp_new_i64();
10687 gen_load_fpr32(ctx, fp32, fs);
10688 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10689 tcg_temp_free_i32(fp32);
10690 gen_store_fpr64(ctx, fp64, fd);
10691 tcg_temp_free_i64(fp64);
10693 break;
10694 case OPC_CVT_W_S:
10696 TCGv_i32 fp0 = tcg_temp_new_i32();
10698 gen_load_fpr32(ctx, fp0, fs);
10699 if (ctx->nan2008) {
10700 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10701 } else {
10702 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10704 gen_store_fpr32(ctx, fp0, fd);
10705 tcg_temp_free_i32(fp0);
10707 break;
10708 case OPC_CVT_L_S:
10709 check_cp1_64bitmode(ctx);
10711 TCGv_i32 fp32 = tcg_temp_new_i32();
10712 TCGv_i64 fp64 = tcg_temp_new_i64();
10714 gen_load_fpr32(ctx, fp32, fs);
10715 if (ctx->nan2008) {
10716 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10717 } else {
10718 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10720 tcg_temp_free_i32(fp32);
10721 gen_store_fpr64(ctx, fp64, fd);
10722 tcg_temp_free_i64(fp64);
10724 break;
10725 case OPC_CVT_PS_S:
10726 check_ps(ctx);
10728 TCGv_i64 fp64 = tcg_temp_new_i64();
10729 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10730 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10732 gen_load_fpr32(ctx, fp32_0, fs);
10733 gen_load_fpr32(ctx, fp32_1, ft);
10734 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10735 tcg_temp_free_i32(fp32_1);
10736 tcg_temp_free_i32(fp32_0);
10737 gen_store_fpr64(ctx, fp64, fd);
10738 tcg_temp_free_i64(fp64);
10740 break;
10741 case OPC_CMP_F_S:
10742 case OPC_CMP_UN_S:
10743 case OPC_CMP_EQ_S:
10744 case OPC_CMP_UEQ_S:
10745 case OPC_CMP_OLT_S:
10746 case OPC_CMP_ULT_S:
10747 case OPC_CMP_OLE_S:
10748 case OPC_CMP_ULE_S:
10749 case OPC_CMP_SF_S:
10750 case OPC_CMP_NGLE_S:
10751 case OPC_CMP_SEQ_S:
10752 case OPC_CMP_NGL_S:
10753 case OPC_CMP_LT_S:
10754 case OPC_CMP_NGE_S:
10755 case OPC_CMP_LE_S:
10756 case OPC_CMP_NGT_S:
10757 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10758 if (ctx->opcode & (1 << 6)) {
10759 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
10760 } else {
10761 gen_cmp_s(ctx, func-48, ft, fs, cc);
10763 break;
10764 case OPC_ADD_D:
10765 check_cp1_registers(ctx, fs | ft | fd);
10767 TCGv_i64 fp0 = tcg_temp_new_i64();
10768 TCGv_i64 fp1 = tcg_temp_new_i64();
10770 gen_load_fpr64(ctx, fp0, fs);
10771 gen_load_fpr64(ctx, fp1, ft);
10772 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10773 tcg_temp_free_i64(fp1);
10774 gen_store_fpr64(ctx, fp0, fd);
10775 tcg_temp_free_i64(fp0);
10777 break;
10778 case OPC_SUB_D:
10779 check_cp1_registers(ctx, fs | ft | fd);
10781 TCGv_i64 fp0 = tcg_temp_new_i64();
10782 TCGv_i64 fp1 = tcg_temp_new_i64();
10784 gen_load_fpr64(ctx, fp0, fs);
10785 gen_load_fpr64(ctx, fp1, ft);
10786 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10787 tcg_temp_free_i64(fp1);
10788 gen_store_fpr64(ctx, fp0, fd);
10789 tcg_temp_free_i64(fp0);
10791 break;
10792 case OPC_MUL_D:
10793 check_cp1_registers(ctx, fs | ft | fd);
10795 TCGv_i64 fp0 = tcg_temp_new_i64();
10796 TCGv_i64 fp1 = tcg_temp_new_i64();
10798 gen_load_fpr64(ctx, fp0, fs);
10799 gen_load_fpr64(ctx, fp1, ft);
10800 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10801 tcg_temp_free_i64(fp1);
10802 gen_store_fpr64(ctx, fp0, fd);
10803 tcg_temp_free_i64(fp0);
10805 break;
10806 case OPC_DIV_D:
10807 check_cp1_registers(ctx, fs | ft | fd);
10809 TCGv_i64 fp0 = tcg_temp_new_i64();
10810 TCGv_i64 fp1 = tcg_temp_new_i64();
10812 gen_load_fpr64(ctx, fp0, fs);
10813 gen_load_fpr64(ctx, fp1, ft);
10814 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10815 tcg_temp_free_i64(fp1);
10816 gen_store_fpr64(ctx, fp0, fd);
10817 tcg_temp_free_i64(fp0);
10819 break;
10820 case OPC_SQRT_D:
10821 check_cp1_registers(ctx, fs | fd);
10823 TCGv_i64 fp0 = tcg_temp_new_i64();
10825 gen_load_fpr64(ctx, fp0, fs);
10826 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10827 gen_store_fpr64(ctx, fp0, fd);
10828 tcg_temp_free_i64(fp0);
10830 break;
10831 case OPC_ABS_D:
10832 check_cp1_registers(ctx, fs | fd);
10834 TCGv_i64 fp0 = tcg_temp_new_i64();
10836 gen_load_fpr64(ctx, fp0, fs);
10837 if (ctx->abs2008) {
10838 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10839 } else {
10840 gen_helper_float_abs_d(fp0, fp0);
10842 gen_store_fpr64(ctx, fp0, fd);
10843 tcg_temp_free_i64(fp0);
10845 break;
10846 case OPC_MOV_D:
10847 check_cp1_registers(ctx, fs | fd);
10849 TCGv_i64 fp0 = tcg_temp_new_i64();
10851 gen_load_fpr64(ctx, fp0, fs);
10852 gen_store_fpr64(ctx, fp0, fd);
10853 tcg_temp_free_i64(fp0);
10855 break;
10856 case OPC_NEG_D:
10857 check_cp1_registers(ctx, fs | fd);
10859 TCGv_i64 fp0 = tcg_temp_new_i64();
10861 gen_load_fpr64(ctx, fp0, fs);
10862 if (ctx->abs2008) {
10863 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10864 } else {
10865 gen_helper_float_chs_d(fp0, fp0);
10867 gen_store_fpr64(ctx, fp0, fd);
10868 tcg_temp_free_i64(fp0);
10870 break;
10871 case OPC_ROUND_L_D:
10872 check_cp1_64bitmode(ctx);
10874 TCGv_i64 fp0 = tcg_temp_new_i64();
10876 gen_load_fpr64(ctx, fp0, fs);
10877 if (ctx->nan2008) {
10878 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10879 } else {
10880 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10882 gen_store_fpr64(ctx, fp0, fd);
10883 tcg_temp_free_i64(fp0);
10885 break;
10886 case OPC_TRUNC_L_D:
10887 check_cp1_64bitmode(ctx);
10889 TCGv_i64 fp0 = tcg_temp_new_i64();
10891 gen_load_fpr64(ctx, fp0, fs);
10892 if (ctx->nan2008) {
10893 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10894 } else {
10895 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10897 gen_store_fpr64(ctx, fp0, fd);
10898 tcg_temp_free_i64(fp0);
10900 break;
10901 case OPC_CEIL_L_D:
10902 check_cp1_64bitmode(ctx);
10904 TCGv_i64 fp0 = tcg_temp_new_i64();
10906 gen_load_fpr64(ctx, fp0, fs);
10907 if (ctx->nan2008) {
10908 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10909 } else {
10910 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10912 gen_store_fpr64(ctx, fp0, fd);
10913 tcg_temp_free_i64(fp0);
10915 break;
10916 case OPC_FLOOR_L_D:
10917 check_cp1_64bitmode(ctx);
10919 TCGv_i64 fp0 = tcg_temp_new_i64();
10921 gen_load_fpr64(ctx, fp0, fs);
10922 if (ctx->nan2008) {
10923 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10924 } else {
10925 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10927 gen_store_fpr64(ctx, fp0, fd);
10928 tcg_temp_free_i64(fp0);
10930 break;
10931 case OPC_ROUND_W_D:
10932 check_cp1_registers(ctx, fs);
10934 TCGv_i32 fp32 = tcg_temp_new_i32();
10935 TCGv_i64 fp64 = tcg_temp_new_i64();
10937 gen_load_fpr64(ctx, fp64, fs);
10938 if (ctx->nan2008) {
10939 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10940 } else {
10941 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10943 tcg_temp_free_i64(fp64);
10944 gen_store_fpr32(ctx, fp32, fd);
10945 tcg_temp_free_i32(fp32);
10947 break;
10948 case OPC_TRUNC_W_D:
10949 check_cp1_registers(ctx, fs);
10951 TCGv_i32 fp32 = tcg_temp_new_i32();
10952 TCGv_i64 fp64 = tcg_temp_new_i64();
10954 gen_load_fpr64(ctx, fp64, fs);
10955 if (ctx->nan2008) {
10956 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10957 } else {
10958 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10960 tcg_temp_free_i64(fp64);
10961 gen_store_fpr32(ctx, fp32, fd);
10962 tcg_temp_free_i32(fp32);
10964 break;
10965 case OPC_CEIL_W_D:
10966 check_cp1_registers(ctx, fs);
10968 TCGv_i32 fp32 = tcg_temp_new_i32();
10969 TCGv_i64 fp64 = tcg_temp_new_i64();
10971 gen_load_fpr64(ctx, fp64, fs);
10972 if (ctx->nan2008) {
10973 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10974 } else {
10975 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10977 tcg_temp_free_i64(fp64);
10978 gen_store_fpr32(ctx, fp32, fd);
10979 tcg_temp_free_i32(fp32);
10981 break;
10982 case OPC_FLOOR_W_D:
10983 check_cp1_registers(ctx, fs);
10985 TCGv_i32 fp32 = tcg_temp_new_i32();
10986 TCGv_i64 fp64 = tcg_temp_new_i64();
10988 gen_load_fpr64(ctx, fp64, fs);
10989 if (ctx->nan2008) {
10990 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10991 } else {
10992 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10994 tcg_temp_free_i64(fp64);
10995 gen_store_fpr32(ctx, fp32, fd);
10996 tcg_temp_free_i32(fp32);
10998 break;
10999 case OPC_SEL_D:
11000 check_insn(ctx, ISA_MIPS32R6);
11001 gen_sel_d(ctx, op1, fd, ft, fs);
11002 break;
11003 case OPC_SELEQZ_D:
11004 check_insn(ctx, ISA_MIPS32R6);
11005 gen_sel_d(ctx, op1, fd, ft, fs);
11006 break;
11007 case OPC_SELNEZ_D:
11008 check_insn(ctx, ISA_MIPS32R6);
11009 gen_sel_d(ctx, op1, fd, ft, fs);
11010 break;
11011 case OPC_MOVCF_D:
11012 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11013 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11014 break;
11015 case OPC_MOVZ_D:
11016 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11018 TCGLabel *l1 = gen_new_label();
11019 TCGv_i64 fp0;
11021 if (ft != 0) {
11022 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11024 fp0 = tcg_temp_new_i64();
11025 gen_load_fpr64(ctx, fp0, fs);
11026 gen_store_fpr64(ctx, fp0, fd);
11027 tcg_temp_free_i64(fp0);
11028 gen_set_label(l1);
11030 break;
11031 case OPC_MOVN_D:
11032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11034 TCGLabel *l1 = gen_new_label();
11035 TCGv_i64 fp0;
11037 if (ft != 0) {
11038 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11039 fp0 = tcg_temp_new_i64();
11040 gen_load_fpr64(ctx, fp0, fs);
11041 gen_store_fpr64(ctx, fp0, fd);
11042 tcg_temp_free_i64(fp0);
11043 gen_set_label(l1);
11046 break;
11047 case OPC_RECIP_D:
11048 check_cp1_registers(ctx, fs | fd);
11050 TCGv_i64 fp0 = tcg_temp_new_i64();
11052 gen_load_fpr64(ctx, fp0, fs);
11053 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11054 gen_store_fpr64(ctx, fp0, fd);
11055 tcg_temp_free_i64(fp0);
11057 break;
11058 case OPC_RSQRT_D:
11059 check_cp1_registers(ctx, fs | fd);
11061 TCGv_i64 fp0 = tcg_temp_new_i64();
11063 gen_load_fpr64(ctx, fp0, fs);
11064 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11065 gen_store_fpr64(ctx, fp0, fd);
11066 tcg_temp_free_i64(fp0);
11068 break;
11069 case OPC_MADDF_D:
11070 check_insn(ctx, ISA_MIPS32R6);
11072 TCGv_i64 fp0 = tcg_temp_new_i64();
11073 TCGv_i64 fp1 = tcg_temp_new_i64();
11074 TCGv_i64 fp2 = tcg_temp_new_i64();
11075 gen_load_fpr64(ctx, fp0, fs);
11076 gen_load_fpr64(ctx, fp1, ft);
11077 gen_load_fpr64(ctx, fp2, fd);
11078 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11079 gen_store_fpr64(ctx, fp2, fd);
11080 tcg_temp_free_i64(fp2);
11081 tcg_temp_free_i64(fp1);
11082 tcg_temp_free_i64(fp0);
11084 break;
11085 case OPC_MSUBF_D:
11086 check_insn(ctx, ISA_MIPS32R6);
11088 TCGv_i64 fp0 = tcg_temp_new_i64();
11089 TCGv_i64 fp1 = tcg_temp_new_i64();
11090 TCGv_i64 fp2 = tcg_temp_new_i64();
11091 gen_load_fpr64(ctx, fp0, fs);
11092 gen_load_fpr64(ctx, fp1, ft);
11093 gen_load_fpr64(ctx, fp2, fd);
11094 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11095 gen_store_fpr64(ctx, fp2, fd);
11096 tcg_temp_free_i64(fp2);
11097 tcg_temp_free_i64(fp1);
11098 tcg_temp_free_i64(fp0);
11100 break;
11101 case OPC_RINT_D:
11102 check_insn(ctx, ISA_MIPS32R6);
11104 TCGv_i64 fp0 = tcg_temp_new_i64();
11105 gen_load_fpr64(ctx, fp0, fs);
11106 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11107 gen_store_fpr64(ctx, fp0, fd);
11108 tcg_temp_free_i64(fp0);
11110 break;
11111 case OPC_CLASS_D:
11112 check_insn(ctx, ISA_MIPS32R6);
11114 TCGv_i64 fp0 = tcg_temp_new_i64();
11115 gen_load_fpr64(ctx, fp0, fs);
11116 gen_helper_float_class_d(fp0, cpu_env, fp0);
11117 gen_store_fpr64(ctx, fp0, fd);
11118 tcg_temp_free_i64(fp0);
11120 break;
11121 case OPC_MIN_D: /* OPC_RECIP2_D */
11122 if (ctx->insn_flags & ISA_MIPS32R6) {
11123 /* OPC_MIN_D */
11124 TCGv_i64 fp0 = tcg_temp_new_i64();
11125 TCGv_i64 fp1 = tcg_temp_new_i64();
11126 gen_load_fpr64(ctx, fp0, fs);
11127 gen_load_fpr64(ctx, fp1, ft);
11128 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11129 gen_store_fpr64(ctx, fp1, fd);
11130 tcg_temp_free_i64(fp1);
11131 tcg_temp_free_i64(fp0);
11132 } else {
11133 /* OPC_RECIP2_D */
11134 check_cp1_64bitmode(ctx);
11136 TCGv_i64 fp0 = tcg_temp_new_i64();
11137 TCGv_i64 fp1 = tcg_temp_new_i64();
11139 gen_load_fpr64(ctx, fp0, fs);
11140 gen_load_fpr64(ctx, fp1, ft);
11141 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11142 tcg_temp_free_i64(fp1);
11143 gen_store_fpr64(ctx, fp0, fd);
11144 tcg_temp_free_i64(fp0);
11147 break;
11148 case OPC_MINA_D: /* OPC_RECIP1_D */
11149 if (ctx->insn_flags & ISA_MIPS32R6) {
11150 /* OPC_MINA_D */
11151 TCGv_i64 fp0 = tcg_temp_new_i64();
11152 TCGv_i64 fp1 = tcg_temp_new_i64();
11153 gen_load_fpr64(ctx, fp0, fs);
11154 gen_load_fpr64(ctx, fp1, ft);
11155 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11156 gen_store_fpr64(ctx, fp1, fd);
11157 tcg_temp_free_i64(fp1);
11158 tcg_temp_free_i64(fp0);
11159 } else {
11160 /* OPC_RECIP1_D */
11161 check_cp1_64bitmode(ctx);
11163 TCGv_i64 fp0 = tcg_temp_new_i64();
11165 gen_load_fpr64(ctx, fp0, fs);
11166 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11167 gen_store_fpr64(ctx, fp0, fd);
11168 tcg_temp_free_i64(fp0);
11171 break;
11172 case OPC_MAX_D: /* OPC_RSQRT1_D */
11173 if (ctx->insn_flags & ISA_MIPS32R6) {
11174 /* OPC_MAX_D */
11175 TCGv_i64 fp0 = tcg_temp_new_i64();
11176 TCGv_i64 fp1 = tcg_temp_new_i64();
11177 gen_load_fpr64(ctx, fp0, fs);
11178 gen_load_fpr64(ctx, fp1, ft);
11179 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11180 gen_store_fpr64(ctx, fp1, fd);
11181 tcg_temp_free_i64(fp1);
11182 tcg_temp_free_i64(fp0);
11183 } else {
11184 /* OPC_RSQRT1_D */
11185 check_cp1_64bitmode(ctx);
11187 TCGv_i64 fp0 = tcg_temp_new_i64();
11189 gen_load_fpr64(ctx, fp0, fs);
11190 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11191 gen_store_fpr64(ctx, fp0, fd);
11192 tcg_temp_free_i64(fp0);
11195 break;
11196 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11197 if (ctx->insn_flags & ISA_MIPS32R6) {
11198 /* OPC_MAXA_D */
11199 TCGv_i64 fp0 = tcg_temp_new_i64();
11200 TCGv_i64 fp1 = tcg_temp_new_i64();
11201 gen_load_fpr64(ctx, fp0, fs);
11202 gen_load_fpr64(ctx, fp1, ft);
11203 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11204 gen_store_fpr64(ctx, fp1, fd);
11205 tcg_temp_free_i64(fp1);
11206 tcg_temp_free_i64(fp0);
11207 } else {
11208 /* OPC_RSQRT2_D */
11209 check_cp1_64bitmode(ctx);
11211 TCGv_i64 fp0 = tcg_temp_new_i64();
11212 TCGv_i64 fp1 = tcg_temp_new_i64();
11214 gen_load_fpr64(ctx, fp0, fs);
11215 gen_load_fpr64(ctx, fp1, ft);
11216 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11217 tcg_temp_free_i64(fp1);
11218 gen_store_fpr64(ctx, fp0, fd);
11219 tcg_temp_free_i64(fp0);
11222 break;
11223 case OPC_CMP_F_D:
11224 case OPC_CMP_UN_D:
11225 case OPC_CMP_EQ_D:
11226 case OPC_CMP_UEQ_D:
11227 case OPC_CMP_OLT_D:
11228 case OPC_CMP_ULT_D:
11229 case OPC_CMP_OLE_D:
11230 case OPC_CMP_ULE_D:
11231 case OPC_CMP_SF_D:
11232 case OPC_CMP_NGLE_D:
11233 case OPC_CMP_SEQ_D:
11234 case OPC_CMP_NGL_D:
11235 case OPC_CMP_LT_D:
11236 case OPC_CMP_NGE_D:
11237 case OPC_CMP_LE_D:
11238 case OPC_CMP_NGT_D:
11239 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11240 if (ctx->opcode & (1 << 6)) {
11241 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11242 } else {
11243 gen_cmp_d(ctx, func-48, ft, fs, cc);
11245 break;
11246 case OPC_CVT_S_D:
11247 check_cp1_registers(ctx, fs);
11249 TCGv_i32 fp32 = tcg_temp_new_i32();
11250 TCGv_i64 fp64 = tcg_temp_new_i64();
11252 gen_load_fpr64(ctx, fp64, fs);
11253 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11254 tcg_temp_free_i64(fp64);
11255 gen_store_fpr32(ctx, fp32, fd);
11256 tcg_temp_free_i32(fp32);
11258 break;
11259 case OPC_CVT_W_D:
11260 check_cp1_registers(ctx, fs);
11262 TCGv_i32 fp32 = tcg_temp_new_i32();
11263 TCGv_i64 fp64 = tcg_temp_new_i64();
11265 gen_load_fpr64(ctx, fp64, fs);
11266 if (ctx->nan2008) {
11267 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11268 } else {
11269 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11271 tcg_temp_free_i64(fp64);
11272 gen_store_fpr32(ctx, fp32, fd);
11273 tcg_temp_free_i32(fp32);
11275 break;
11276 case OPC_CVT_L_D:
11277 check_cp1_64bitmode(ctx);
11279 TCGv_i64 fp0 = tcg_temp_new_i64();
11281 gen_load_fpr64(ctx, fp0, fs);
11282 if (ctx->nan2008) {
11283 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11284 } else {
11285 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11287 gen_store_fpr64(ctx, fp0, fd);
11288 tcg_temp_free_i64(fp0);
11290 break;
11291 case OPC_CVT_S_W:
11293 TCGv_i32 fp0 = tcg_temp_new_i32();
11295 gen_load_fpr32(ctx, fp0, fs);
11296 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11297 gen_store_fpr32(ctx, fp0, fd);
11298 tcg_temp_free_i32(fp0);
11300 break;
11301 case OPC_CVT_D_W:
11302 check_cp1_registers(ctx, fd);
11304 TCGv_i32 fp32 = tcg_temp_new_i32();
11305 TCGv_i64 fp64 = tcg_temp_new_i64();
11307 gen_load_fpr32(ctx, fp32, fs);
11308 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11309 tcg_temp_free_i32(fp32);
11310 gen_store_fpr64(ctx, fp64, fd);
11311 tcg_temp_free_i64(fp64);
11313 break;
11314 case OPC_CVT_S_L:
11315 check_cp1_64bitmode(ctx);
11317 TCGv_i32 fp32 = tcg_temp_new_i32();
11318 TCGv_i64 fp64 = tcg_temp_new_i64();
11320 gen_load_fpr64(ctx, fp64, fs);
11321 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11322 tcg_temp_free_i64(fp64);
11323 gen_store_fpr32(ctx, fp32, fd);
11324 tcg_temp_free_i32(fp32);
11326 break;
11327 case OPC_CVT_D_L:
11328 check_cp1_64bitmode(ctx);
11330 TCGv_i64 fp0 = tcg_temp_new_i64();
11332 gen_load_fpr64(ctx, fp0, fs);
11333 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11334 gen_store_fpr64(ctx, fp0, fd);
11335 tcg_temp_free_i64(fp0);
11337 break;
11338 case OPC_CVT_PS_PW:
11339 check_ps(ctx);
11341 TCGv_i64 fp0 = tcg_temp_new_i64();
11343 gen_load_fpr64(ctx, fp0, fs);
11344 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11345 gen_store_fpr64(ctx, fp0, fd);
11346 tcg_temp_free_i64(fp0);
11348 break;
11349 case OPC_ADD_PS:
11350 check_ps(ctx);
11352 TCGv_i64 fp0 = tcg_temp_new_i64();
11353 TCGv_i64 fp1 = tcg_temp_new_i64();
11355 gen_load_fpr64(ctx, fp0, fs);
11356 gen_load_fpr64(ctx, fp1, ft);
11357 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11358 tcg_temp_free_i64(fp1);
11359 gen_store_fpr64(ctx, fp0, fd);
11360 tcg_temp_free_i64(fp0);
11362 break;
11363 case OPC_SUB_PS:
11364 check_ps(ctx);
11366 TCGv_i64 fp0 = tcg_temp_new_i64();
11367 TCGv_i64 fp1 = tcg_temp_new_i64();
11369 gen_load_fpr64(ctx, fp0, fs);
11370 gen_load_fpr64(ctx, fp1, ft);
11371 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11372 tcg_temp_free_i64(fp1);
11373 gen_store_fpr64(ctx, fp0, fd);
11374 tcg_temp_free_i64(fp0);
11376 break;
11377 case OPC_MUL_PS:
11378 check_ps(ctx);
11380 TCGv_i64 fp0 = tcg_temp_new_i64();
11381 TCGv_i64 fp1 = tcg_temp_new_i64();
11383 gen_load_fpr64(ctx, fp0, fs);
11384 gen_load_fpr64(ctx, fp1, ft);
11385 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11386 tcg_temp_free_i64(fp1);
11387 gen_store_fpr64(ctx, fp0, fd);
11388 tcg_temp_free_i64(fp0);
11390 break;
11391 case OPC_ABS_PS:
11392 check_ps(ctx);
11394 TCGv_i64 fp0 = tcg_temp_new_i64();
11396 gen_load_fpr64(ctx, fp0, fs);
11397 gen_helper_float_abs_ps(fp0, fp0);
11398 gen_store_fpr64(ctx, fp0, fd);
11399 tcg_temp_free_i64(fp0);
11401 break;
11402 case OPC_MOV_PS:
11403 check_ps(ctx);
11405 TCGv_i64 fp0 = tcg_temp_new_i64();
11407 gen_load_fpr64(ctx, fp0, fs);
11408 gen_store_fpr64(ctx, fp0, fd);
11409 tcg_temp_free_i64(fp0);
11411 break;
11412 case OPC_NEG_PS:
11413 check_ps(ctx);
11415 TCGv_i64 fp0 = tcg_temp_new_i64();
11417 gen_load_fpr64(ctx, fp0, fs);
11418 gen_helper_float_chs_ps(fp0, fp0);
11419 gen_store_fpr64(ctx, fp0, fd);
11420 tcg_temp_free_i64(fp0);
11422 break;
11423 case OPC_MOVCF_PS:
11424 check_ps(ctx);
11425 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11426 break;
11427 case OPC_MOVZ_PS:
11428 check_ps(ctx);
11430 TCGLabel *l1 = gen_new_label();
11431 TCGv_i64 fp0;
11433 if (ft != 0)
11434 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11435 fp0 = tcg_temp_new_i64();
11436 gen_load_fpr64(ctx, fp0, fs);
11437 gen_store_fpr64(ctx, fp0, fd);
11438 tcg_temp_free_i64(fp0);
11439 gen_set_label(l1);
11441 break;
11442 case OPC_MOVN_PS:
11443 check_ps(ctx);
11445 TCGLabel *l1 = gen_new_label();
11446 TCGv_i64 fp0;
11448 if (ft != 0) {
11449 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11450 fp0 = tcg_temp_new_i64();
11451 gen_load_fpr64(ctx, fp0, fs);
11452 gen_store_fpr64(ctx, fp0, fd);
11453 tcg_temp_free_i64(fp0);
11454 gen_set_label(l1);
11457 break;
11458 case OPC_ADDR_PS:
11459 check_ps(ctx);
11461 TCGv_i64 fp0 = tcg_temp_new_i64();
11462 TCGv_i64 fp1 = tcg_temp_new_i64();
11464 gen_load_fpr64(ctx, fp0, ft);
11465 gen_load_fpr64(ctx, fp1, fs);
11466 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11467 tcg_temp_free_i64(fp1);
11468 gen_store_fpr64(ctx, fp0, fd);
11469 tcg_temp_free_i64(fp0);
11471 break;
11472 case OPC_MULR_PS:
11473 check_ps(ctx);
11475 TCGv_i64 fp0 = tcg_temp_new_i64();
11476 TCGv_i64 fp1 = tcg_temp_new_i64();
11478 gen_load_fpr64(ctx, fp0, ft);
11479 gen_load_fpr64(ctx, fp1, fs);
11480 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11481 tcg_temp_free_i64(fp1);
11482 gen_store_fpr64(ctx, fp0, fd);
11483 tcg_temp_free_i64(fp0);
11485 break;
11486 case OPC_RECIP2_PS:
11487 check_ps(ctx);
11489 TCGv_i64 fp0 = tcg_temp_new_i64();
11490 TCGv_i64 fp1 = tcg_temp_new_i64();
11492 gen_load_fpr64(ctx, fp0, fs);
11493 gen_load_fpr64(ctx, fp1, ft);
11494 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11495 tcg_temp_free_i64(fp1);
11496 gen_store_fpr64(ctx, fp0, fd);
11497 tcg_temp_free_i64(fp0);
11499 break;
11500 case OPC_RECIP1_PS:
11501 check_ps(ctx);
11503 TCGv_i64 fp0 = tcg_temp_new_i64();
11505 gen_load_fpr64(ctx, fp0, fs);
11506 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11507 gen_store_fpr64(ctx, fp0, fd);
11508 tcg_temp_free_i64(fp0);
11510 break;
11511 case OPC_RSQRT1_PS:
11512 check_ps(ctx);
11514 TCGv_i64 fp0 = tcg_temp_new_i64();
11516 gen_load_fpr64(ctx, fp0, fs);
11517 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11518 gen_store_fpr64(ctx, fp0, fd);
11519 tcg_temp_free_i64(fp0);
11521 break;
11522 case OPC_RSQRT2_PS:
11523 check_ps(ctx);
11525 TCGv_i64 fp0 = tcg_temp_new_i64();
11526 TCGv_i64 fp1 = tcg_temp_new_i64();
11528 gen_load_fpr64(ctx, fp0, fs);
11529 gen_load_fpr64(ctx, fp1, ft);
11530 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11531 tcg_temp_free_i64(fp1);
11532 gen_store_fpr64(ctx, fp0, fd);
11533 tcg_temp_free_i64(fp0);
11535 break;
11536 case OPC_CVT_S_PU:
11537 check_cp1_64bitmode(ctx);
11539 TCGv_i32 fp0 = tcg_temp_new_i32();
11541 gen_load_fpr32h(ctx, fp0, fs);
11542 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11543 gen_store_fpr32(ctx, fp0, fd);
11544 tcg_temp_free_i32(fp0);
11546 break;
11547 case OPC_CVT_PW_PS:
11548 check_ps(ctx);
11550 TCGv_i64 fp0 = tcg_temp_new_i64();
11552 gen_load_fpr64(ctx, fp0, fs);
11553 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11554 gen_store_fpr64(ctx, fp0, fd);
11555 tcg_temp_free_i64(fp0);
11557 break;
11558 case OPC_CVT_S_PL:
11559 check_cp1_64bitmode(ctx);
11561 TCGv_i32 fp0 = tcg_temp_new_i32();
11563 gen_load_fpr32(ctx, fp0, fs);
11564 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11565 gen_store_fpr32(ctx, fp0, fd);
11566 tcg_temp_free_i32(fp0);
11568 break;
11569 case OPC_PLL_PS:
11570 check_ps(ctx);
11572 TCGv_i32 fp0 = tcg_temp_new_i32();
11573 TCGv_i32 fp1 = tcg_temp_new_i32();
11575 gen_load_fpr32(ctx, fp0, fs);
11576 gen_load_fpr32(ctx, fp1, ft);
11577 gen_store_fpr32h(ctx, fp0, fd);
11578 gen_store_fpr32(ctx, fp1, fd);
11579 tcg_temp_free_i32(fp0);
11580 tcg_temp_free_i32(fp1);
11582 break;
11583 case OPC_PLU_PS:
11584 check_ps(ctx);
11586 TCGv_i32 fp0 = tcg_temp_new_i32();
11587 TCGv_i32 fp1 = tcg_temp_new_i32();
11589 gen_load_fpr32(ctx, fp0, fs);
11590 gen_load_fpr32h(ctx, fp1, ft);
11591 gen_store_fpr32(ctx, fp1, fd);
11592 gen_store_fpr32h(ctx, fp0, fd);
11593 tcg_temp_free_i32(fp0);
11594 tcg_temp_free_i32(fp1);
11596 break;
11597 case OPC_PUL_PS:
11598 check_ps(ctx);
11600 TCGv_i32 fp0 = tcg_temp_new_i32();
11601 TCGv_i32 fp1 = tcg_temp_new_i32();
11603 gen_load_fpr32h(ctx, fp0, fs);
11604 gen_load_fpr32(ctx, fp1, ft);
11605 gen_store_fpr32(ctx, fp1, fd);
11606 gen_store_fpr32h(ctx, fp0, fd);
11607 tcg_temp_free_i32(fp0);
11608 tcg_temp_free_i32(fp1);
11610 break;
11611 case OPC_PUU_PS:
11612 check_ps(ctx);
11614 TCGv_i32 fp0 = tcg_temp_new_i32();
11615 TCGv_i32 fp1 = tcg_temp_new_i32();
11617 gen_load_fpr32h(ctx, fp0, fs);
11618 gen_load_fpr32h(ctx, fp1, ft);
11619 gen_store_fpr32(ctx, fp1, fd);
11620 gen_store_fpr32h(ctx, fp0, fd);
11621 tcg_temp_free_i32(fp0);
11622 tcg_temp_free_i32(fp1);
11624 break;
11625 case OPC_CMP_F_PS:
11626 case OPC_CMP_UN_PS:
11627 case OPC_CMP_EQ_PS:
11628 case OPC_CMP_UEQ_PS:
11629 case OPC_CMP_OLT_PS:
11630 case OPC_CMP_ULT_PS:
11631 case OPC_CMP_OLE_PS:
11632 case OPC_CMP_ULE_PS:
11633 case OPC_CMP_SF_PS:
11634 case OPC_CMP_NGLE_PS:
11635 case OPC_CMP_SEQ_PS:
11636 case OPC_CMP_NGL_PS:
11637 case OPC_CMP_LT_PS:
11638 case OPC_CMP_NGE_PS:
11639 case OPC_CMP_LE_PS:
11640 case OPC_CMP_NGT_PS:
11641 if (ctx->opcode & (1 << 6)) {
11642 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11643 } else {
11644 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11646 break;
11647 default:
11648 MIPS_INVAL("farith");
11649 generate_exception_end(ctx, EXCP_RI);
11650 return;
11654 /* Coprocessor 3 (FPU) */
11655 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11656 int fd, int fs, int base, int index)
11658 TCGv t0 = tcg_temp_new();
11660 if (base == 0) {
11661 gen_load_gpr(t0, index);
11662 } else if (index == 0) {
11663 gen_load_gpr(t0, base);
11664 } else {
11665 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11667 /* Don't do NOP if destination is zero: we must perform the actual
11668 memory access. */
11669 switch (opc) {
11670 case OPC_LWXC1:
11671 check_cop1x(ctx);
11673 TCGv_i32 fp0 = tcg_temp_new_i32();
11675 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11676 tcg_gen_trunc_tl_i32(fp0, t0);
11677 gen_store_fpr32(ctx, fp0, fd);
11678 tcg_temp_free_i32(fp0);
11680 break;
11681 case OPC_LDXC1:
11682 check_cop1x(ctx);
11683 check_cp1_registers(ctx, fd);
11685 TCGv_i64 fp0 = tcg_temp_new_i64();
11686 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11687 gen_store_fpr64(ctx, fp0, fd);
11688 tcg_temp_free_i64(fp0);
11690 break;
11691 case OPC_LUXC1:
11692 check_cp1_64bitmode(ctx);
11693 tcg_gen_andi_tl(t0, t0, ~0x7);
11695 TCGv_i64 fp0 = tcg_temp_new_i64();
11697 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11698 gen_store_fpr64(ctx, fp0, fd);
11699 tcg_temp_free_i64(fp0);
11701 break;
11702 case OPC_SWXC1:
11703 check_cop1x(ctx);
11705 TCGv_i32 fp0 = tcg_temp_new_i32();
11706 gen_load_fpr32(ctx, fp0, fs);
11707 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11708 tcg_temp_free_i32(fp0);
11710 break;
11711 case OPC_SDXC1:
11712 check_cop1x(ctx);
11713 check_cp1_registers(ctx, fs);
11715 TCGv_i64 fp0 = tcg_temp_new_i64();
11716 gen_load_fpr64(ctx, fp0, fs);
11717 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11718 tcg_temp_free_i64(fp0);
11720 break;
11721 case OPC_SUXC1:
11722 check_cp1_64bitmode(ctx);
11723 tcg_gen_andi_tl(t0, t0, ~0x7);
11725 TCGv_i64 fp0 = tcg_temp_new_i64();
11726 gen_load_fpr64(ctx, fp0, fs);
11727 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11728 tcg_temp_free_i64(fp0);
11730 break;
11732 tcg_temp_free(t0);
11735 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
11736 int fd, int fr, int fs, int ft)
11738 switch (opc) {
11739 case OPC_ALNV_PS:
11740 check_ps(ctx);
11742 TCGv t0 = tcg_temp_local_new();
11743 TCGv_i32 fp = tcg_temp_new_i32();
11744 TCGv_i32 fph = tcg_temp_new_i32();
11745 TCGLabel *l1 = gen_new_label();
11746 TCGLabel *l2 = gen_new_label();
11748 gen_load_gpr(t0, fr);
11749 tcg_gen_andi_tl(t0, t0, 0x7);
11751 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11752 gen_load_fpr32(ctx, fp, fs);
11753 gen_load_fpr32h(ctx, fph, fs);
11754 gen_store_fpr32(ctx, fp, fd);
11755 gen_store_fpr32h(ctx, fph, fd);
11756 tcg_gen_br(l2);
11757 gen_set_label(l1);
11758 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11759 tcg_temp_free(t0);
11760 #ifdef TARGET_WORDS_BIGENDIAN
11761 gen_load_fpr32(ctx, fp, fs);
11762 gen_load_fpr32h(ctx, fph, ft);
11763 gen_store_fpr32h(ctx, fp, fd);
11764 gen_store_fpr32(ctx, fph, fd);
11765 #else
11766 gen_load_fpr32h(ctx, fph, fs);
11767 gen_load_fpr32(ctx, fp, ft);
11768 gen_store_fpr32(ctx, fph, fd);
11769 gen_store_fpr32h(ctx, fp, fd);
11770 #endif
11771 gen_set_label(l2);
11772 tcg_temp_free_i32(fp);
11773 tcg_temp_free_i32(fph);
11775 break;
11776 case OPC_MADD_S:
11777 check_cop1x(ctx);
11779 TCGv_i32 fp0 = tcg_temp_new_i32();
11780 TCGv_i32 fp1 = tcg_temp_new_i32();
11781 TCGv_i32 fp2 = tcg_temp_new_i32();
11783 gen_load_fpr32(ctx, fp0, fs);
11784 gen_load_fpr32(ctx, fp1, ft);
11785 gen_load_fpr32(ctx, fp2, fr);
11786 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11787 tcg_temp_free_i32(fp0);
11788 tcg_temp_free_i32(fp1);
11789 gen_store_fpr32(ctx, fp2, fd);
11790 tcg_temp_free_i32(fp2);
11792 break;
11793 case OPC_MADD_D:
11794 check_cop1x(ctx);
11795 check_cp1_registers(ctx, fd | fs | ft | fr);
11797 TCGv_i64 fp0 = tcg_temp_new_i64();
11798 TCGv_i64 fp1 = tcg_temp_new_i64();
11799 TCGv_i64 fp2 = tcg_temp_new_i64();
11801 gen_load_fpr64(ctx, fp0, fs);
11802 gen_load_fpr64(ctx, fp1, ft);
11803 gen_load_fpr64(ctx, fp2, fr);
11804 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11805 tcg_temp_free_i64(fp0);
11806 tcg_temp_free_i64(fp1);
11807 gen_store_fpr64(ctx, fp2, fd);
11808 tcg_temp_free_i64(fp2);
11810 break;
11811 case OPC_MADD_PS:
11812 check_ps(ctx);
11814 TCGv_i64 fp0 = tcg_temp_new_i64();
11815 TCGv_i64 fp1 = tcg_temp_new_i64();
11816 TCGv_i64 fp2 = tcg_temp_new_i64();
11818 gen_load_fpr64(ctx, fp0, fs);
11819 gen_load_fpr64(ctx, fp1, ft);
11820 gen_load_fpr64(ctx, fp2, fr);
11821 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11822 tcg_temp_free_i64(fp0);
11823 tcg_temp_free_i64(fp1);
11824 gen_store_fpr64(ctx, fp2, fd);
11825 tcg_temp_free_i64(fp2);
11827 break;
11828 case OPC_MSUB_S:
11829 check_cop1x(ctx);
11831 TCGv_i32 fp0 = tcg_temp_new_i32();
11832 TCGv_i32 fp1 = tcg_temp_new_i32();
11833 TCGv_i32 fp2 = tcg_temp_new_i32();
11835 gen_load_fpr32(ctx, fp0, fs);
11836 gen_load_fpr32(ctx, fp1, ft);
11837 gen_load_fpr32(ctx, fp2, fr);
11838 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11839 tcg_temp_free_i32(fp0);
11840 tcg_temp_free_i32(fp1);
11841 gen_store_fpr32(ctx, fp2, fd);
11842 tcg_temp_free_i32(fp2);
11844 break;
11845 case OPC_MSUB_D:
11846 check_cop1x(ctx);
11847 check_cp1_registers(ctx, fd | fs | ft | fr);
11849 TCGv_i64 fp0 = tcg_temp_new_i64();
11850 TCGv_i64 fp1 = tcg_temp_new_i64();
11851 TCGv_i64 fp2 = tcg_temp_new_i64();
11853 gen_load_fpr64(ctx, fp0, fs);
11854 gen_load_fpr64(ctx, fp1, ft);
11855 gen_load_fpr64(ctx, fp2, fr);
11856 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11857 tcg_temp_free_i64(fp0);
11858 tcg_temp_free_i64(fp1);
11859 gen_store_fpr64(ctx, fp2, fd);
11860 tcg_temp_free_i64(fp2);
11862 break;
11863 case OPC_MSUB_PS:
11864 check_ps(ctx);
11866 TCGv_i64 fp0 = tcg_temp_new_i64();
11867 TCGv_i64 fp1 = tcg_temp_new_i64();
11868 TCGv_i64 fp2 = tcg_temp_new_i64();
11870 gen_load_fpr64(ctx, fp0, fs);
11871 gen_load_fpr64(ctx, fp1, ft);
11872 gen_load_fpr64(ctx, fp2, fr);
11873 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11874 tcg_temp_free_i64(fp0);
11875 tcg_temp_free_i64(fp1);
11876 gen_store_fpr64(ctx, fp2, fd);
11877 tcg_temp_free_i64(fp2);
11879 break;
11880 case OPC_NMADD_S:
11881 check_cop1x(ctx);
11883 TCGv_i32 fp0 = tcg_temp_new_i32();
11884 TCGv_i32 fp1 = tcg_temp_new_i32();
11885 TCGv_i32 fp2 = tcg_temp_new_i32();
11887 gen_load_fpr32(ctx, fp0, fs);
11888 gen_load_fpr32(ctx, fp1, ft);
11889 gen_load_fpr32(ctx, fp2, fr);
11890 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11891 tcg_temp_free_i32(fp0);
11892 tcg_temp_free_i32(fp1);
11893 gen_store_fpr32(ctx, fp2, fd);
11894 tcg_temp_free_i32(fp2);
11896 break;
11897 case OPC_NMADD_D:
11898 check_cop1x(ctx);
11899 check_cp1_registers(ctx, fd | fs | ft | fr);
11901 TCGv_i64 fp0 = tcg_temp_new_i64();
11902 TCGv_i64 fp1 = tcg_temp_new_i64();
11903 TCGv_i64 fp2 = tcg_temp_new_i64();
11905 gen_load_fpr64(ctx, fp0, fs);
11906 gen_load_fpr64(ctx, fp1, ft);
11907 gen_load_fpr64(ctx, fp2, fr);
11908 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11909 tcg_temp_free_i64(fp0);
11910 tcg_temp_free_i64(fp1);
11911 gen_store_fpr64(ctx, fp2, fd);
11912 tcg_temp_free_i64(fp2);
11914 break;
11915 case OPC_NMADD_PS:
11916 check_ps(ctx);
11918 TCGv_i64 fp0 = tcg_temp_new_i64();
11919 TCGv_i64 fp1 = tcg_temp_new_i64();
11920 TCGv_i64 fp2 = tcg_temp_new_i64();
11922 gen_load_fpr64(ctx, fp0, fs);
11923 gen_load_fpr64(ctx, fp1, ft);
11924 gen_load_fpr64(ctx, fp2, fr);
11925 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11926 tcg_temp_free_i64(fp0);
11927 tcg_temp_free_i64(fp1);
11928 gen_store_fpr64(ctx, fp2, fd);
11929 tcg_temp_free_i64(fp2);
11931 break;
11932 case OPC_NMSUB_S:
11933 check_cop1x(ctx);
11935 TCGv_i32 fp0 = tcg_temp_new_i32();
11936 TCGv_i32 fp1 = tcg_temp_new_i32();
11937 TCGv_i32 fp2 = tcg_temp_new_i32();
11939 gen_load_fpr32(ctx, fp0, fs);
11940 gen_load_fpr32(ctx, fp1, ft);
11941 gen_load_fpr32(ctx, fp2, fr);
11942 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11943 tcg_temp_free_i32(fp0);
11944 tcg_temp_free_i32(fp1);
11945 gen_store_fpr32(ctx, fp2, fd);
11946 tcg_temp_free_i32(fp2);
11948 break;
11949 case OPC_NMSUB_D:
11950 check_cop1x(ctx);
11951 check_cp1_registers(ctx, fd | fs | ft | fr);
11953 TCGv_i64 fp0 = tcg_temp_new_i64();
11954 TCGv_i64 fp1 = tcg_temp_new_i64();
11955 TCGv_i64 fp2 = tcg_temp_new_i64();
11957 gen_load_fpr64(ctx, fp0, fs);
11958 gen_load_fpr64(ctx, fp1, ft);
11959 gen_load_fpr64(ctx, fp2, fr);
11960 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11961 tcg_temp_free_i64(fp0);
11962 tcg_temp_free_i64(fp1);
11963 gen_store_fpr64(ctx, fp2, fd);
11964 tcg_temp_free_i64(fp2);
11966 break;
11967 case OPC_NMSUB_PS:
11968 check_ps(ctx);
11970 TCGv_i64 fp0 = tcg_temp_new_i64();
11971 TCGv_i64 fp1 = tcg_temp_new_i64();
11972 TCGv_i64 fp2 = tcg_temp_new_i64();
11974 gen_load_fpr64(ctx, fp0, fs);
11975 gen_load_fpr64(ctx, fp1, ft);
11976 gen_load_fpr64(ctx, fp2, fr);
11977 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11978 tcg_temp_free_i64(fp0);
11979 tcg_temp_free_i64(fp1);
11980 gen_store_fpr64(ctx, fp2, fd);
11981 tcg_temp_free_i64(fp2);
11983 break;
11984 default:
11985 MIPS_INVAL("flt3_arith");
11986 generate_exception_end(ctx, EXCP_RI);
11987 return;
11991 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11993 TCGv t0;
11995 #if !defined(CONFIG_USER_ONLY)
11996 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11997 Therefore only check the ISA in system mode. */
11998 check_insn(ctx, ISA_MIPS32R2);
11999 #endif
12000 t0 = tcg_temp_new();
12002 switch (rd) {
12003 case 0:
12004 gen_helper_rdhwr_cpunum(t0, cpu_env);
12005 gen_store_gpr(t0, rt);
12006 break;
12007 case 1:
12008 gen_helper_rdhwr_synci_step(t0, cpu_env);
12009 gen_store_gpr(t0, rt);
12010 break;
12011 case 2:
12012 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12013 gen_io_start();
12015 gen_helper_rdhwr_cc(t0, cpu_env);
12016 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12017 gen_io_end();
12019 gen_store_gpr(t0, rt);
12020 /* Break the TB to be able to take timer interrupts immediately
12021 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12022 we break completely out of translated code. */
12023 gen_save_pc(ctx->base.pc_next + 4);
12024 ctx->base.is_jmp = DISAS_EXIT;
12025 break;
12026 case 3:
12027 gen_helper_rdhwr_ccres(t0, cpu_env);
12028 gen_store_gpr(t0, rt);
12029 break;
12030 case 4:
12031 check_insn(ctx, ISA_MIPS32R6);
12032 if (sel != 0) {
12033 /* Performance counter registers are not implemented other than
12034 * control register 0.
12036 generate_exception(ctx, EXCP_RI);
12038 gen_helper_rdhwr_performance(t0, cpu_env);
12039 gen_store_gpr(t0, rt);
12040 break;
12041 case 5:
12042 check_insn(ctx, ISA_MIPS32R6);
12043 gen_helper_rdhwr_xnp(t0, cpu_env);
12044 gen_store_gpr(t0, rt);
12045 break;
12046 case 29:
12047 #if defined(CONFIG_USER_ONLY)
12048 tcg_gen_ld_tl(t0, cpu_env,
12049 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12050 gen_store_gpr(t0, rt);
12051 break;
12052 #else
12053 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12054 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12055 tcg_gen_ld_tl(t0, cpu_env,
12056 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12057 gen_store_gpr(t0, rt);
12058 } else {
12059 generate_exception_end(ctx, EXCP_RI);
12061 break;
12062 #endif
12063 default: /* Invalid */
12064 MIPS_INVAL("rdhwr");
12065 generate_exception_end(ctx, EXCP_RI);
12066 break;
12068 tcg_temp_free(t0);
12071 static inline void clear_branch_hflags(DisasContext *ctx)
12073 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12074 if (ctx->base.is_jmp == DISAS_NEXT) {
12075 save_cpu_state(ctx, 0);
12076 } else {
12077 /* it is not safe to save ctx->hflags as hflags may be changed
12078 in execution time by the instruction in delay / forbidden slot. */
12079 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12083 static void gen_branch(DisasContext *ctx, int insn_bytes)
12085 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12086 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12087 /* Branches completion */
12088 clear_branch_hflags(ctx);
12089 ctx->base.is_jmp = DISAS_NORETURN;
12090 /* FIXME: Need to clear can_do_io. */
12091 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12092 case MIPS_HFLAG_FBNSLOT:
12093 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12094 break;
12095 case MIPS_HFLAG_B:
12096 /* unconditional branch */
12097 if (proc_hflags & MIPS_HFLAG_BX) {
12098 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12100 gen_goto_tb(ctx, 0, ctx->btarget);
12101 break;
12102 case MIPS_HFLAG_BL:
12103 /* blikely taken case */
12104 gen_goto_tb(ctx, 0, ctx->btarget);
12105 break;
12106 case MIPS_HFLAG_BC:
12107 /* Conditional branch */
12109 TCGLabel *l1 = gen_new_label();
12111 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12112 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12113 gen_set_label(l1);
12114 gen_goto_tb(ctx, 0, ctx->btarget);
12116 break;
12117 case MIPS_HFLAG_BR:
12118 /* unconditional branch to register */
12119 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12120 TCGv t0 = tcg_temp_new();
12121 TCGv_i32 t1 = tcg_temp_new_i32();
12123 tcg_gen_andi_tl(t0, btarget, 0x1);
12124 tcg_gen_trunc_tl_i32(t1, t0);
12125 tcg_temp_free(t0);
12126 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12127 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12128 tcg_gen_or_i32(hflags, hflags, t1);
12129 tcg_temp_free_i32(t1);
12131 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12132 } else {
12133 tcg_gen_mov_tl(cpu_PC, btarget);
12135 if (ctx->base.singlestep_enabled) {
12136 save_cpu_state(ctx, 0);
12137 gen_helper_raise_exception_debug(cpu_env);
12139 tcg_gen_lookup_and_goto_ptr();
12140 break;
12141 default:
12142 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12143 abort();
12148 /* Compact Branches */
12149 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12150 int rs, int rt, int32_t offset)
12152 int bcond_compute = 0;
12153 TCGv t0 = tcg_temp_new();
12154 TCGv t1 = tcg_temp_new();
12155 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12157 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12158 #ifdef MIPS_DEBUG_DISAS
12159 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12160 "\n", ctx->base.pc_next);
12161 #endif
12162 generate_exception_end(ctx, EXCP_RI);
12163 goto out;
12166 /* Load needed operands and calculate btarget */
12167 switch (opc) {
12168 /* compact branch */
12169 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12170 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12171 gen_load_gpr(t0, rs);
12172 gen_load_gpr(t1, rt);
12173 bcond_compute = 1;
12174 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12175 if (rs <= rt && rs == 0) {
12176 /* OPC_BEQZALC, OPC_BNEZALC */
12177 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12179 break;
12180 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12181 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12182 gen_load_gpr(t0, rs);
12183 gen_load_gpr(t1, rt);
12184 bcond_compute = 1;
12185 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12186 break;
12187 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12188 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12189 if (rs == 0 || rs == rt) {
12190 /* OPC_BLEZALC, OPC_BGEZALC */
12191 /* OPC_BGTZALC, OPC_BLTZALC */
12192 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12194 gen_load_gpr(t0, rs);
12195 gen_load_gpr(t1, rt);
12196 bcond_compute = 1;
12197 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12198 break;
12199 case OPC_BC:
12200 case OPC_BALC:
12201 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12202 break;
12203 case OPC_BEQZC:
12204 case OPC_BNEZC:
12205 if (rs != 0) {
12206 /* OPC_BEQZC, OPC_BNEZC */
12207 gen_load_gpr(t0, rs);
12208 bcond_compute = 1;
12209 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12210 } else {
12211 /* OPC_JIC, OPC_JIALC */
12212 TCGv tbase = tcg_temp_new();
12213 TCGv toffset = tcg_temp_new();
12215 gen_load_gpr(tbase, rt);
12216 tcg_gen_movi_tl(toffset, offset);
12217 gen_op_addr_add(ctx, btarget, tbase, toffset);
12218 tcg_temp_free(tbase);
12219 tcg_temp_free(toffset);
12221 break;
12222 default:
12223 MIPS_INVAL("Compact branch/jump");
12224 generate_exception_end(ctx, EXCP_RI);
12225 goto out;
12228 if (bcond_compute == 0) {
12229 /* Uncoditional compact branch */
12230 switch (opc) {
12231 case OPC_JIALC:
12232 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12233 /* Fallthrough */
12234 case OPC_JIC:
12235 ctx->hflags |= MIPS_HFLAG_BR;
12236 break;
12237 case OPC_BALC:
12238 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12239 /* Fallthrough */
12240 case OPC_BC:
12241 ctx->hflags |= MIPS_HFLAG_B;
12242 break;
12243 default:
12244 MIPS_INVAL("Compact branch/jump");
12245 generate_exception_end(ctx, EXCP_RI);
12246 goto out;
12249 /* Generating branch here as compact branches don't have delay slot */
12250 gen_branch(ctx, 4);
12251 } else {
12252 /* Conditional compact branch */
12253 TCGLabel *fs = gen_new_label();
12254 save_cpu_state(ctx, 0);
12256 switch (opc) {
12257 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12258 if (rs == 0 && rt != 0) {
12259 /* OPC_BLEZALC */
12260 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12261 } else if (rs != 0 && rt != 0 && rs == rt) {
12262 /* OPC_BGEZALC */
12263 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12264 } else {
12265 /* OPC_BGEUC */
12266 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12268 break;
12269 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12270 if (rs == 0 && rt != 0) {
12271 /* OPC_BGTZALC */
12272 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12273 } else if (rs != 0 && rt != 0 && rs == rt) {
12274 /* OPC_BLTZALC */
12275 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12276 } else {
12277 /* OPC_BLTUC */
12278 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12280 break;
12281 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12282 if (rs == 0 && rt != 0) {
12283 /* OPC_BLEZC */
12284 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12285 } else if (rs != 0 && rt != 0 && rs == rt) {
12286 /* OPC_BGEZC */
12287 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12288 } else {
12289 /* OPC_BGEC */
12290 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12292 break;
12293 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12294 if (rs == 0 && rt != 0) {
12295 /* OPC_BGTZC */
12296 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12297 } else if (rs != 0 && rt != 0 && rs == rt) {
12298 /* OPC_BLTZC */
12299 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12300 } else {
12301 /* OPC_BLTC */
12302 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12304 break;
12305 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12306 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12307 if (rs >= rt) {
12308 /* OPC_BOVC, OPC_BNVC */
12309 TCGv t2 = tcg_temp_new();
12310 TCGv t3 = tcg_temp_new();
12311 TCGv t4 = tcg_temp_new();
12312 TCGv input_overflow = tcg_temp_new();
12314 gen_load_gpr(t0, rs);
12315 gen_load_gpr(t1, rt);
12316 tcg_gen_ext32s_tl(t2, t0);
12317 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12318 tcg_gen_ext32s_tl(t3, t1);
12319 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12320 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12322 tcg_gen_add_tl(t4, t2, t3);
12323 tcg_gen_ext32s_tl(t4, t4);
12324 tcg_gen_xor_tl(t2, t2, t3);
12325 tcg_gen_xor_tl(t3, t4, t3);
12326 tcg_gen_andc_tl(t2, t3, t2);
12327 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12328 tcg_gen_or_tl(t4, t4, input_overflow);
12329 if (opc == OPC_BOVC) {
12330 /* OPC_BOVC */
12331 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12332 } else {
12333 /* OPC_BNVC */
12334 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12336 tcg_temp_free(input_overflow);
12337 tcg_temp_free(t4);
12338 tcg_temp_free(t3);
12339 tcg_temp_free(t2);
12340 } else if (rs < rt && rs == 0) {
12341 /* OPC_BEQZALC, OPC_BNEZALC */
12342 if (opc == OPC_BEQZALC) {
12343 /* OPC_BEQZALC */
12344 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12345 } else {
12346 /* OPC_BNEZALC */
12347 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12349 } else {
12350 /* OPC_BEQC, OPC_BNEC */
12351 if (opc == OPC_BEQC) {
12352 /* OPC_BEQC */
12353 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12354 } else {
12355 /* OPC_BNEC */
12356 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12359 break;
12360 case OPC_BEQZC:
12361 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12362 break;
12363 case OPC_BNEZC:
12364 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12365 break;
12366 default:
12367 MIPS_INVAL("Compact conditional branch/jump");
12368 generate_exception_end(ctx, EXCP_RI);
12369 goto out;
12372 /* Generating branch here as compact branches don't have delay slot */
12373 gen_goto_tb(ctx, 1, ctx->btarget);
12374 gen_set_label(fs);
12376 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12379 out:
12380 tcg_temp_free(t0);
12381 tcg_temp_free(t1);
12384 /* ISA extensions (ASEs) */
12385 /* MIPS16 extension to MIPS32 */
12387 /* MIPS16 major opcodes */
12388 enum {
12389 M16_OPC_ADDIUSP = 0x00,
12390 M16_OPC_ADDIUPC = 0x01,
12391 M16_OPC_B = 0x02,
12392 M16_OPC_JAL = 0x03,
12393 M16_OPC_BEQZ = 0x04,
12394 M16_OPC_BNEQZ = 0x05,
12395 M16_OPC_SHIFT = 0x06,
12396 M16_OPC_LD = 0x07,
12397 M16_OPC_RRIA = 0x08,
12398 M16_OPC_ADDIU8 = 0x09,
12399 M16_OPC_SLTI = 0x0a,
12400 M16_OPC_SLTIU = 0x0b,
12401 M16_OPC_I8 = 0x0c,
12402 M16_OPC_LI = 0x0d,
12403 M16_OPC_CMPI = 0x0e,
12404 M16_OPC_SD = 0x0f,
12405 M16_OPC_LB = 0x10,
12406 M16_OPC_LH = 0x11,
12407 M16_OPC_LWSP = 0x12,
12408 M16_OPC_LW = 0x13,
12409 M16_OPC_LBU = 0x14,
12410 M16_OPC_LHU = 0x15,
12411 M16_OPC_LWPC = 0x16,
12412 M16_OPC_LWU = 0x17,
12413 M16_OPC_SB = 0x18,
12414 M16_OPC_SH = 0x19,
12415 M16_OPC_SWSP = 0x1a,
12416 M16_OPC_SW = 0x1b,
12417 M16_OPC_RRR = 0x1c,
12418 M16_OPC_RR = 0x1d,
12419 M16_OPC_EXTEND = 0x1e,
12420 M16_OPC_I64 = 0x1f
12423 /* I8 funct field */
12424 enum {
12425 I8_BTEQZ = 0x0,
12426 I8_BTNEZ = 0x1,
12427 I8_SWRASP = 0x2,
12428 I8_ADJSP = 0x3,
12429 I8_SVRS = 0x4,
12430 I8_MOV32R = 0x5,
12431 I8_MOVR32 = 0x7
12434 /* RRR f field */
12435 enum {
12436 RRR_DADDU = 0x0,
12437 RRR_ADDU = 0x1,
12438 RRR_DSUBU = 0x2,
12439 RRR_SUBU = 0x3
12442 /* RR funct field */
12443 enum {
12444 RR_JR = 0x00,
12445 RR_SDBBP = 0x01,
12446 RR_SLT = 0x02,
12447 RR_SLTU = 0x03,
12448 RR_SLLV = 0x04,
12449 RR_BREAK = 0x05,
12450 RR_SRLV = 0x06,
12451 RR_SRAV = 0x07,
12452 RR_DSRL = 0x08,
12453 RR_CMP = 0x0a,
12454 RR_NEG = 0x0b,
12455 RR_AND = 0x0c,
12456 RR_OR = 0x0d,
12457 RR_XOR = 0x0e,
12458 RR_NOT = 0x0f,
12459 RR_MFHI = 0x10,
12460 RR_CNVT = 0x11,
12461 RR_MFLO = 0x12,
12462 RR_DSRA = 0x13,
12463 RR_DSLLV = 0x14,
12464 RR_DSRLV = 0x16,
12465 RR_DSRAV = 0x17,
12466 RR_MULT = 0x18,
12467 RR_MULTU = 0x19,
12468 RR_DIV = 0x1a,
12469 RR_DIVU = 0x1b,
12470 RR_DMULT = 0x1c,
12471 RR_DMULTU = 0x1d,
12472 RR_DDIV = 0x1e,
12473 RR_DDIVU = 0x1f
12476 /* I64 funct field */
12477 enum {
12478 I64_LDSP = 0x0,
12479 I64_SDSP = 0x1,
12480 I64_SDRASP = 0x2,
12481 I64_DADJSP = 0x3,
12482 I64_LDPC = 0x4,
12483 I64_DADDIU5 = 0x5,
12484 I64_DADDIUPC = 0x6,
12485 I64_DADDIUSP = 0x7
12488 /* RR ry field for CNVT */
12489 enum {
12490 RR_RY_CNVT_ZEB = 0x0,
12491 RR_RY_CNVT_ZEH = 0x1,
12492 RR_RY_CNVT_ZEW = 0x2,
12493 RR_RY_CNVT_SEB = 0x4,
12494 RR_RY_CNVT_SEH = 0x5,
12495 RR_RY_CNVT_SEW = 0x6,
12498 static int xlat (int r)
12500 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12502 return map[r];
12505 static void gen_mips16_save (DisasContext *ctx,
12506 int xsregs, int aregs,
12507 int do_ra, int do_s0, int do_s1,
12508 int framesize)
12510 TCGv t0 = tcg_temp_new();
12511 TCGv t1 = tcg_temp_new();
12512 TCGv t2 = tcg_temp_new();
12513 int args, astatic;
12515 switch (aregs) {
12516 case 0:
12517 case 1:
12518 case 2:
12519 case 3:
12520 case 11:
12521 args = 0;
12522 break;
12523 case 4:
12524 case 5:
12525 case 6:
12526 case 7:
12527 args = 1;
12528 break;
12529 case 8:
12530 case 9:
12531 case 10:
12532 args = 2;
12533 break;
12534 case 12:
12535 case 13:
12536 args = 3;
12537 break;
12538 case 14:
12539 args = 4;
12540 break;
12541 default:
12542 generate_exception_end(ctx, EXCP_RI);
12543 return;
12546 switch (args) {
12547 case 4:
12548 gen_base_offset_addr(ctx, t0, 29, 12);
12549 gen_load_gpr(t1, 7);
12550 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12551 /* Fall through */
12552 case 3:
12553 gen_base_offset_addr(ctx, t0, 29, 8);
12554 gen_load_gpr(t1, 6);
12555 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12556 /* Fall through */
12557 case 2:
12558 gen_base_offset_addr(ctx, t0, 29, 4);
12559 gen_load_gpr(t1, 5);
12560 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12561 /* Fall through */
12562 case 1:
12563 gen_base_offset_addr(ctx, t0, 29, 0);
12564 gen_load_gpr(t1, 4);
12565 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12568 gen_load_gpr(t0, 29);
12570 #define DECR_AND_STORE(reg) do { \
12571 tcg_gen_movi_tl(t2, -4); \
12572 gen_op_addr_add(ctx, t0, t0, t2); \
12573 gen_load_gpr(t1, reg); \
12574 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12575 } while (0)
12577 if (do_ra) {
12578 DECR_AND_STORE(31);
12581 switch (xsregs) {
12582 case 7:
12583 DECR_AND_STORE(30);
12584 /* Fall through */
12585 case 6:
12586 DECR_AND_STORE(23);
12587 /* Fall through */
12588 case 5:
12589 DECR_AND_STORE(22);
12590 /* Fall through */
12591 case 4:
12592 DECR_AND_STORE(21);
12593 /* Fall through */
12594 case 3:
12595 DECR_AND_STORE(20);
12596 /* Fall through */
12597 case 2:
12598 DECR_AND_STORE(19);
12599 /* Fall through */
12600 case 1:
12601 DECR_AND_STORE(18);
12604 if (do_s1) {
12605 DECR_AND_STORE(17);
12607 if (do_s0) {
12608 DECR_AND_STORE(16);
12611 switch (aregs) {
12612 case 0:
12613 case 4:
12614 case 8:
12615 case 12:
12616 case 14:
12617 astatic = 0;
12618 break;
12619 case 1:
12620 case 5:
12621 case 9:
12622 case 13:
12623 astatic = 1;
12624 break;
12625 case 2:
12626 case 6:
12627 case 10:
12628 astatic = 2;
12629 break;
12630 case 3:
12631 case 7:
12632 astatic = 3;
12633 break;
12634 case 11:
12635 astatic = 4;
12636 break;
12637 default:
12638 generate_exception_end(ctx, EXCP_RI);
12639 return;
12642 if (astatic > 0) {
12643 DECR_AND_STORE(7);
12644 if (astatic > 1) {
12645 DECR_AND_STORE(6);
12646 if (astatic > 2) {
12647 DECR_AND_STORE(5);
12648 if (astatic > 3) {
12649 DECR_AND_STORE(4);
12654 #undef DECR_AND_STORE
12656 tcg_gen_movi_tl(t2, -framesize);
12657 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12658 tcg_temp_free(t0);
12659 tcg_temp_free(t1);
12660 tcg_temp_free(t2);
12663 static void gen_mips16_restore (DisasContext *ctx,
12664 int xsregs, int aregs,
12665 int do_ra, int do_s0, int do_s1,
12666 int framesize)
12668 int astatic;
12669 TCGv t0 = tcg_temp_new();
12670 TCGv t1 = tcg_temp_new();
12671 TCGv t2 = tcg_temp_new();
12673 tcg_gen_movi_tl(t2, framesize);
12674 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12676 #define DECR_AND_LOAD(reg) do { \
12677 tcg_gen_movi_tl(t2, -4); \
12678 gen_op_addr_add(ctx, t0, t0, t2); \
12679 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12680 gen_store_gpr(t1, reg); \
12681 } while (0)
12683 if (do_ra) {
12684 DECR_AND_LOAD(31);
12687 switch (xsregs) {
12688 case 7:
12689 DECR_AND_LOAD(30);
12690 /* Fall through */
12691 case 6:
12692 DECR_AND_LOAD(23);
12693 /* Fall through */
12694 case 5:
12695 DECR_AND_LOAD(22);
12696 /* Fall through */
12697 case 4:
12698 DECR_AND_LOAD(21);
12699 /* Fall through */
12700 case 3:
12701 DECR_AND_LOAD(20);
12702 /* Fall through */
12703 case 2:
12704 DECR_AND_LOAD(19);
12705 /* Fall through */
12706 case 1:
12707 DECR_AND_LOAD(18);
12710 if (do_s1) {
12711 DECR_AND_LOAD(17);
12713 if (do_s0) {
12714 DECR_AND_LOAD(16);
12717 switch (aregs) {
12718 case 0:
12719 case 4:
12720 case 8:
12721 case 12:
12722 case 14:
12723 astatic = 0;
12724 break;
12725 case 1:
12726 case 5:
12727 case 9:
12728 case 13:
12729 astatic = 1;
12730 break;
12731 case 2:
12732 case 6:
12733 case 10:
12734 astatic = 2;
12735 break;
12736 case 3:
12737 case 7:
12738 astatic = 3;
12739 break;
12740 case 11:
12741 astatic = 4;
12742 break;
12743 default:
12744 generate_exception_end(ctx, EXCP_RI);
12745 return;
12748 if (astatic > 0) {
12749 DECR_AND_LOAD(7);
12750 if (astatic > 1) {
12751 DECR_AND_LOAD(6);
12752 if (astatic > 2) {
12753 DECR_AND_LOAD(5);
12754 if (astatic > 3) {
12755 DECR_AND_LOAD(4);
12760 #undef DECR_AND_LOAD
12762 tcg_gen_movi_tl(t2, framesize);
12763 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12764 tcg_temp_free(t0);
12765 tcg_temp_free(t1);
12766 tcg_temp_free(t2);
12769 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
12770 int is_64_bit, int extended)
12772 TCGv t0;
12774 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12775 generate_exception_end(ctx, EXCP_RI);
12776 return;
12779 t0 = tcg_temp_new();
12781 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12782 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12783 if (!is_64_bit) {
12784 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12787 tcg_temp_free(t0);
12790 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12791 int16_t offset)
12793 TCGv_i32 t0 = tcg_const_i32(op);
12794 TCGv t1 = tcg_temp_new();
12795 gen_base_offset_addr(ctx, t1, base, offset);
12796 gen_helper_cache(cpu_env, t1, t0);
12799 #if defined(TARGET_MIPS64)
12800 static void decode_i64_mips16 (DisasContext *ctx,
12801 int ry, int funct, int16_t offset,
12802 int extended)
12804 switch (funct) {
12805 case I64_LDSP:
12806 check_insn(ctx, ISA_MIPS3);
12807 check_mips_64(ctx);
12808 offset = extended ? offset : offset << 3;
12809 gen_ld(ctx, OPC_LD, ry, 29, offset);
12810 break;
12811 case I64_SDSP:
12812 check_insn(ctx, ISA_MIPS3);
12813 check_mips_64(ctx);
12814 offset = extended ? offset : offset << 3;
12815 gen_st(ctx, OPC_SD, ry, 29, offset);
12816 break;
12817 case I64_SDRASP:
12818 check_insn(ctx, ISA_MIPS3);
12819 check_mips_64(ctx);
12820 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12821 gen_st(ctx, OPC_SD, 31, 29, offset);
12822 break;
12823 case I64_DADJSP:
12824 check_insn(ctx, ISA_MIPS3);
12825 check_mips_64(ctx);
12826 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12827 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12828 break;
12829 case I64_LDPC:
12830 check_insn(ctx, ISA_MIPS3);
12831 check_mips_64(ctx);
12832 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12833 generate_exception_end(ctx, EXCP_RI);
12834 } else {
12835 offset = extended ? offset : offset << 3;
12836 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12838 break;
12839 case I64_DADDIU5:
12840 check_insn(ctx, ISA_MIPS3);
12841 check_mips_64(ctx);
12842 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12843 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12844 break;
12845 case I64_DADDIUPC:
12846 check_insn(ctx, ISA_MIPS3);
12847 check_mips_64(ctx);
12848 offset = extended ? offset : offset << 2;
12849 gen_addiupc(ctx, ry, offset, 1, extended);
12850 break;
12851 case I64_DADDIUSP:
12852 check_insn(ctx, ISA_MIPS3);
12853 check_mips_64(ctx);
12854 offset = extended ? offset : offset << 2;
12855 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12856 break;
12859 #endif
12861 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12863 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
12864 int op, rx, ry, funct, sa;
12865 int16_t imm, offset;
12867 ctx->opcode = (ctx->opcode << 16) | extend;
12868 op = (ctx->opcode >> 11) & 0x1f;
12869 sa = (ctx->opcode >> 22) & 0x1f;
12870 funct = (ctx->opcode >> 8) & 0x7;
12871 rx = xlat((ctx->opcode >> 8) & 0x7);
12872 ry = xlat((ctx->opcode >> 5) & 0x7);
12873 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12874 | ((ctx->opcode >> 21) & 0x3f) << 5
12875 | (ctx->opcode & 0x1f));
12877 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12878 counterparts. */
12879 switch (op) {
12880 case M16_OPC_ADDIUSP:
12881 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12882 break;
12883 case M16_OPC_ADDIUPC:
12884 gen_addiupc(ctx, rx, imm, 0, 1);
12885 break;
12886 case M16_OPC_B:
12887 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12888 /* No delay slot, so just process as a normal instruction */
12889 break;
12890 case M16_OPC_BEQZ:
12891 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12892 /* No delay slot, so just process as a normal instruction */
12893 break;
12894 case M16_OPC_BNEQZ:
12895 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12896 /* No delay slot, so just process as a normal instruction */
12897 break;
12898 case M16_OPC_SHIFT:
12899 switch (ctx->opcode & 0x3) {
12900 case 0x0:
12901 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12902 break;
12903 case 0x1:
12904 #if defined(TARGET_MIPS64)
12905 check_mips_64(ctx);
12906 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12907 #else
12908 generate_exception_end(ctx, EXCP_RI);
12909 #endif
12910 break;
12911 case 0x2:
12912 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12913 break;
12914 case 0x3:
12915 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12916 break;
12918 break;
12919 #if defined(TARGET_MIPS64)
12920 case M16_OPC_LD:
12921 check_insn(ctx, ISA_MIPS3);
12922 check_mips_64(ctx);
12923 gen_ld(ctx, OPC_LD, ry, rx, offset);
12924 break;
12925 #endif
12926 case M16_OPC_RRIA:
12927 imm = ctx->opcode & 0xf;
12928 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12929 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12930 imm = (int16_t) (imm << 1) >> 1;
12931 if ((ctx->opcode >> 4) & 0x1) {
12932 #if defined(TARGET_MIPS64)
12933 check_mips_64(ctx);
12934 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12935 #else
12936 generate_exception_end(ctx, EXCP_RI);
12937 #endif
12938 } else {
12939 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12941 break;
12942 case M16_OPC_ADDIU8:
12943 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12944 break;
12945 case M16_OPC_SLTI:
12946 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12947 break;
12948 case M16_OPC_SLTIU:
12949 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12950 break;
12951 case M16_OPC_I8:
12952 switch (funct) {
12953 case I8_BTEQZ:
12954 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12955 break;
12956 case I8_BTNEZ:
12957 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12958 break;
12959 case I8_SWRASP:
12960 gen_st(ctx, OPC_SW, 31, 29, imm);
12961 break;
12962 case I8_ADJSP:
12963 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12964 break;
12965 case I8_SVRS:
12966 check_insn(ctx, ISA_MIPS32);
12968 int xsregs = (ctx->opcode >> 24) & 0x7;
12969 int aregs = (ctx->opcode >> 16) & 0xf;
12970 int do_ra = (ctx->opcode >> 6) & 0x1;
12971 int do_s0 = (ctx->opcode >> 5) & 0x1;
12972 int do_s1 = (ctx->opcode >> 4) & 0x1;
12973 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12974 | (ctx->opcode & 0xf)) << 3;
12976 if (ctx->opcode & (1 << 7)) {
12977 gen_mips16_save(ctx, xsregs, aregs,
12978 do_ra, do_s0, do_s1,
12979 framesize);
12980 } else {
12981 gen_mips16_restore(ctx, xsregs, aregs,
12982 do_ra, do_s0, do_s1,
12983 framesize);
12986 break;
12987 default:
12988 generate_exception_end(ctx, EXCP_RI);
12989 break;
12991 break;
12992 case M16_OPC_LI:
12993 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12994 break;
12995 case M16_OPC_CMPI:
12996 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12997 break;
12998 #if defined(TARGET_MIPS64)
12999 case M16_OPC_SD:
13000 check_insn(ctx, ISA_MIPS3);
13001 check_mips_64(ctx);
13002 gen_st(ctx, OPC_SD, ry, rx, offset);
13003 break;
13004 #endif
13005 case M16_OPC_LB:
13006 gen_ld(ctx, OPC_LB, ry, rx, offset);
13007 break;
13008 case M16_OPC_LH:
13009 gen_ld(ctx, OPC_LH, ry, rx, offset);
13010 break;
13011 case M16_OPC_LWSP:
13012 gen_ld(ctx, OPC_LW, rx, 29, offset);
13013 break;
13014 case M16_OPC_LW:
13015 gen_ld(ctx, OPC_LW, ry, rx, offset);
13016 break;
13017 case M16_OPC_LBU:
13018 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13019 break;
13020 case M16_OPC_LHU:
13021 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13022 break;
13023 case M16_OPC_LWPC:
13024 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13025 break;
13026 #if defined(TARGET_MIPS64)
13027 case M16_OPC_LWU:
13028 check_insn(ctx, ISA_MIPS3);
13029 check_mips_64(ctx);
13030 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13031 break;
13032 #endif
13033 case M16_OPC_SB:
13034 gen_st(ctx, OPC_SB, ry, rx, offset);
13035 break;
13036 case M16_OPC_SH:
13037 gen_st(ctx, OPC_SH, ry, rx, offset);
13038 break;
13039 case M16_OPC_SWSP:
13040 gen_st(ctx, OPC_SW, rx, 29, offset);
13041 break;
13042 case M16_OPC_SW:
13043 gen_st(ctx, OPC_SW, ry, rx, offset);
13044 break;
13045 #if defined(TARGET_MIPS64)
13046 case M16_OPC_I64:
13047 decode_i64_mips16(ctx, ry, funct, offset, 1);
13048 break;
13049 #endif
13050 default:
13051 generate_exception_end(ctx, EXCP_RI);
13052 break;
13055 return 4;
13058 static inline bool is_uhi(int sdbbp_code)
13060 #ifdef CONFIG_USER_ONLY
13061 return false;
13062 #else
13063 return semihosting_enabled() && sdbbp_code == 1;
13064 #endif
13067 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13069 int rx, ry;
13070 int sa;
13071 int op, cnvt_op, op1, offset;
13072 int funct;
13073 int n_bytes;
13075 op = (ctx->opcode >> 11) & 0x1f;
13076 sa = (ctx->opcode >> 2) & 0x7;
13077 sa = sa == 0 ? 8 : sa;
13078 rx = xlat((ctx->opcode >> 8) & 0x7);
13079 cnvt_op = (ctx->opcode >> 5) & 0x7;
13080 ry = xlat((ctx->opcode >> 5) & 0x7);
13081 op1 = offset = ctx->opcode & 0x1f;
13083 n_bytes = 2;
13085 switch (op) {
13086 case M16_OPC_ADDIUSP:
13088 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13090 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13092 break;
13093 case M16_OPC_ADDIUPC:
13094 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13095 break;
13096 case M16_OPC_B:
13097 offset = (ctx->opcode & 0x7ff) << 1;
13098 offset = (int16_t)(offset << 4) >> 4;
13099 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13100 /* No delay slot, so just process as a normal instruction */
13101 break;
13102 case M16_OPC_JAL:
13103 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13104 offset = (((ctx->opcode & 0x1f) << 21)
13105 | ((ctx->opcode >> 5) & 0x1f) << 16
13106 | offset) << 2;
13107 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13108 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13109 n_bytes = 4;
13110 break;
13111 case M16_OPC_BEQZ:
13112 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13113 ((int8_t)ctx->opcode) << 1, 0);
13114 /* No delay slot, so just process as a normal instruction */
13115 break;
13116 case M16_OPC_BNEQZ:
13117 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13118 ((int8_t)ctx->opcode) << 1, 0);
13119 /* No delay slot, so just process as a normal instruction */
13120 break;
13121 case M16_OPC_SHIFT:
13122 switch (ctx->opcode & 0x3) {
13123 case 0x0:
13124 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13125 break;
13126 case 0x1:
13127 #if defined(TARGET_MIPS64)
13128 check_insn(ctx, ISA_MIPS3);
13129 check_mips_64(ctx);
13130 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13131 #else
13132 generate_exception_end(ctx, EXCP_RI);
13133 #endif
13134 break;
13135 case 0x2:
13136 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13137 break;
13138 case 0x3:
13139 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13140 break;
13142 break;
13143 #if defined(TARGET_MIPS64)
13144 case M16_OPC_LD:
13145 check_insn(ctx, ISA_MIPS3);
13146 check_mips_64(ctx);
13147 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13148 break;
13149 #endif
13150 case M16_OPC_RRIA:
13152 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13154 if ((ctx->opcode >> 4) & 1) {
13155 #if defined(TARGET_MIPS64)
13156 check_insn(ctx, ISA_MIPS3);
13157 check_mips_64(ctx);
13158 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13159 #else
13160 generate_exception_end(ctx, EXCP_RI);
13161 #endif
13162 } else {
13163 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13166 break;
13167 case M16_OPC_ADDIU8:
13169 int16_t imm = (int8_t) ctx->opcode;
13171 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13173 break;
13174 case M16_OPC_SLTI:
13176 int16_t imm = (uint8_t) ctx->opcode;
13177 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13179 break;
13180 case M16_OPC_SLTIU:
13182 int16_t imm = (uint8_t) ctx->opcode;
13183 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13185 break;
13186 case M16_OPC_I8:
13188 int reg32;
13190 funct = (ctx->opcode >> 8) & 0x7;
13191 switch (funct) {
13192 case I8_BTEQZ:
13193 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13194 ((int8_t)ctx->opcode) << 1, 0);
13195 break;
13196 case I8_BTNEZ:
13197 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13198 ((int8_t)ctx->opcode) << 1, 0);
13199 break;
13200 case I8_SWRASP:
13201 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13202 break;
13203 case I8_ADJSP:
13204 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13205 ((int8_t)ctx->opcode) << 3);
13206 break;
13207 case I8_SVRS:
13208 check_insn(ctx, ISA_MIPS32);
13210 int do_ra = ctx->opcode & (1 << 6);
13211 int do_s0 = ctx->opcode & (1 << 5);
13212 int do_s1 = ctx->opcode & (1 << 4);
13213 int framesize = ctx->opcode & 0xf;
13215 if (framesize == 0) {
13216 framesize = 128;
13217 } else {
13218 framesize = framesize << 3;
13221 if (ctx->opcode & (1 << 7)) {
13222 gen_mips16_save(ctx, 0, 0,
13223 do_ra, do_s0, do_s1, framesize);
13224 } else {
13225 gen_mips16_restore(ctx, 0, 0,
13226 do_ra, do_s0, do_s1, framesize);
13229 break;
13230 case I8_MOV32R:
13232 int rz = xlat(ctx->opcode & 0x7);
13234 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13235 ((ctx->opcode >> 5) & 0x7);
13236 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13238 break;
13239 case I8_MOVR32:
13240 reg32 = ctx->opcode & 0x1f;
13241 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13242 break;
13243 default:
13244 generate_exception_end(ctx, EXCP_RI);
13245 break;
13248 break;
13249 case M16_OPC_LI:
13251 int16_t imm = (uint8_t) ctx->opcode;
13253 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13255 break;
13256 case M16_OPC_CMPI:
13258 int16_t imm = (uint8_t) ctx->opcode;
13259 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13261 break;
13262 #if defined(TARGET_MIPS64)
13263 case M16_OPC_SD:
13264 check_insn(ctx, ISA_MIPS3);
13265 check_mips_64(ctx);
13266 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13267 break;
13268 #endif
13269 case M16_OPC_LB:
13270 gen_ld(ctx, OPC_LB, ry, rx, offset);
13271 break;
13272 case M16_OPC_LH:
13273 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13274 break;
13275 case M16_OPC_LWSP:
13276 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13277 break;
13278 case M16_OPC_LW:
13279 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13280 break;
13281 case M16_OPC_LBU:
13282 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13283 break;
13284 case M16_OPC_LHU:
13285 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13286 break;
13287 case M16_OPC_LWPC:
13288 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13289 break;
13290 #if defined (TARGET_MIPS64)
13291 case M16_OPC_LWU:
13292 check_insn(ctx, ISA_MIPS3);
13293 check_mips_64(ctx);
13294 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13295 break;
13296 #endif
13297 case M16_OPC_SB:
13298 gen_st(ctx, OPC_SB, ry, rx, offset);
13299 break;
13300 case M16_OPC_SH:
13301 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13302 break;
13303 case M16_OPC_SWSP:
13304 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13305 break;
13306 case M16_OPC_SW:
13307 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13308 break;
13309 case M16_OPC_RRR:
13311 int rz = xlat((ctx->opcode >> 2) & 0x7);
13312 int mips32_op;
13314 switch (ctx->opcode & 0x3) {
13315 case RRR_ADDU:
13316 mips32_op = OPC_ADDU;
13317 break;
13318 case RRR_SUBU:
13319 mips32_op = OPC_SUBU;
13320 break;
13321 #if defined(TARGET_MIPS64)
13322 case RRR_DADDU:
13323 mips32_op = OPC_DADDU;
13324 check_insn(ctx, ISA_MIPS3);
13325 check_mips_64(ctx);
13326 break;
13327 case RRR_DSUBU:
13328 mips32_op = OPC_DSUBU;
13329 check_insn(ctx, ISA_MIPS3);
13330 check_mips_64(ctx);
13331 break;
13332 #endif
13333 default:
13334 generate_exception_end(ctx, EXCP_RI);
13335 goto done;
13338 gen_arith(ctx, mips32_op, rz, rx, ry);
13339 done:
13342 break;
13343 case M16_OPC_RR:
13344 switch (op1) {
13345 case RR_JR:
13347 int nd = (ctx->opcode >> 7) & 0x1;
13348 int link = (ctx->opcode >> 6) & 0x1;
13349 int ra = (ctx->opcode >> 5) & 0x1;
13351 if (nd) {
13352 check_insn(ctx, ISA_MIPS32);
13355 if (link) {
13356 op = OPC_JALR;
13357 } else {
13358 op = OPC_JR;
13361 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13362 (nd ? 0 : 2));
13364 break;
13365 case RR_SDBBP:
13366 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13367 gen_helper_do_semihosting(cpu_env);
13368 } else {
13369 /* XXX: not clear which exception should be raised
13370 * when in debug mode...
13372 check_insn(ctx, ISA_MIPS32);
13373 generate_exception_end(ctx, EXCP_DBp);
13375 break;
13376 case RR_SLT:
13377 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13378 break;
13379 case RR_SLTU:
13380 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13381 break;
13382 case RR_BREAK:
13383 generate_exception_end(ctx, EXCP_BREAK);
13384 break;
13385 case RR_SLLV:
13386 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13387 break;
13388 case RR_SRLV:
13389 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13390 break;
13391 case RR_SRAV:
13392 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13393 break;
13394 #if defined (TARGET_MIPS64)
13395 case RR_DSRL:
13396 check_insn(ctx, ISA_MIPS3);
13397 check_mips_64(ctx);
13398 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13399 break;
13400 #endif
13401 case RR_CMP:
13402 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13403 break;
13404 case RR_NEG:
13405 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13406 break;
13407 case RR_AND:
13408 gen_logic(ctx, OPC_AND, rx, rx, ry);
13409 break;
13410 case RR_OR:
13411 gen_logic(ctx, OPC_OR, rx, rx, ry);
13412 break;
13413 case RR_XOR:
13414 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13415 break;
13416 case RR_NOT:
13417 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13418 break;
13419 case RR_MFHI:
13420 gen_HILO(ctx, OPC_MFHI, 0, rx);
13421 break;
13422 case RR_CNVT:
13423 check_insn(ctx, ISA_MIPS32);
13424 switch (cnvt_op) {
13425 case RR_RY_CNVT_ZEB:
13426 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13427 break;
13428 case RR_RY_CNVT_ZEH:
13429 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13430 break;
13431 case RR_RY_CNVT_SEB:
13432 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13433 break;
13434 case RR_RY_CNVT_SEH:
13435 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13436 break;
13437 #if defined (TARGET_MIPS64)
13438 case RR_RY_CNVT_ZEW:
13439 check_insn(ctx, ISA_MIPS64);
13440 check_mips_64(ctx);
13441 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13442 break;
13443 case RR_RY_CNVT_SEW:
13444 check_insn(ctx, ISA_MIPS64);
13445 check_mips_64(ctx);
13446 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13447 break;
13448 #endif
13449 default:
13450 generate_exception_end(ctx, EXCP_RI);
13451 break;
13453 break;
13454 case RR_MFLO:
13455 gen_HILO(ctx, OPC_MFLO, 0, rx);
13456 break;
13457 #if defined (TARGET_MIPS64)
13458 case RR_DSRA:
13459 check_insn(ctx, ISA_MIPS3);
13460 check_mips_64(ctx);
13461 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13462 break;
13463 case RR_DSLLV:
13464 check_insn(ctx, ISA_MIPS3);
13465 check_mips_64(ctx);
13466 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13467 break;
13468 case RR_DSRLV:
13469 check_insn(ctx, ISA_MIPS3);
13470 check_mips_64(ctx);
13471 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13472 break;
13473 case RR_DSRAV:
13474 check_insn(ctx, ISA_MIPS3);
13475 check_mips_64(ctx);
13476 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13477 break;
13478 #endif
13479 case RR_MULT:
13480 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13481 break;
13482 case RR_MULTU:
13483 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13484 break;
13485 case RR_DIV:
13486 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13487 break;
13488 case RR_DIVU:
13489 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13490 break;
13491 #if defined (TARGET_MIPS64)
13492 case RR_DMULT:
13493 check_insn(ctx, ISA_MIPS3);
13494 check_mips_64(ctx);
13495 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13496 break;
13497 case RR_DMULTU:
13498 check_insn(ctx, ISA_MIPS3);
13499 check_mips_64(ctx);
13500 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13501 break;
13502 case RR_DDIV:
13503 check_insn(ctx, ISA_MIPS3);
13504 check_mips_64(ctx);
13505 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13506 break;
13507 case RR_DDIVU:
13508 check_insn(ctx, ISA_MIPS3);
13509 check_mips_64(ctx);
13510 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13511 break;
13512 #endif
13513 default:
13514 generate_exception_end(ctx, EXCP_RI);
13515 break;
13517 break;
13518 case M16_OPC_EXTEND:
13519 decode_extended_mips16_opc(env, ctx);
13520 n_bytes = 4;
13521 break;
13522 #if defined(TARGET_MIPS64)
13523 case M16_OPC_I64:
13524 funct = (ctx->opcode >> 8) & 0x7;
13525 decode_i64_mips16(ctx, ry, funct, offset, 0);
13526 break;
13527 #endif
13528 default:
13529 generate_exception_end(ctx, EXCP_RI);
13530 break;
13533 return n_bytes;
13536 /* microMIPS extension to MIPS32/MIPS64 */
13539 * microMIPS32/microMIPS64 major opcodes
13541 * 1. MIPS Architecture for Programmers Volume II-B:
13542 * The microMIPS32 Instruction Set (Revision 3.05)
13544 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13546 * 2. MIPS Architecture For Programmers Volume II-A:
13547 * The MIPS64 Instruction Set (Revision 3.51)
13550 enum {
13551 POOL32A = 0x00,
13552 POOL16A = 0x01,
13553 LBU16 = 0x02,
13554 MOVE16 = 0x03,
13555 ADDI32 = 0x04,
13556 R6_LUI = 0x04,
13557 AUI = 0x04,
13558 LBU32 = 0x05,
13559 SB32 = 0x06,
13560 LB32 = 0x07,
13562 POOL32B = 0x08,
13563 POOL16B = 0x09,
13564 LHU16 = 0x0a,
13565 ANDI16 = 0x0b,
13566 ADDIU32 = 0x0c,
13567 LHU32 = 0x0d,
13568 SH32 = 0x0e,
13569 LH32 = 0x0f,
13571 POOL32I = 0x10,
13572 POOL16C = 0x11,
13573 LWSP16 = 0x12,
13574 POOL16D = 0x13,
13575 ORI32 = 0x14,
13576 POOL32F = 0x15,
13577 POOL32S = 0x16, /* MIPS64 */
13578 DADDIU32 = 0x17, /* MIPS64 */
13580 POOL32C = 0x18,
13581 LWGP16 = 0x19,
13582 LW16 = 0x1a,
13583 POOL16E = 0x1b,
13584 XORI32 = 0x1c,
13585 JALS32 = 0x1d,
13586 BOVC = 0x1d,
13587 BEQC = 0x1d,
13588 BEQZALC = 0x1d,
13589 ADDIUPC = 0x1e,
13590 PCREL = 0x1e,
13591 BNVC = 0x1f,
13592 BNEC = 0x1f,
13593 BNEZALC = 0x1f,
13595 R6_BEQZC = 0x20,
13596 JIC = 0x20,
13597 POOL16F = 0x21,
13598 SB16 = 0x22,
13599 BEQZ16 = 0x23,
13600 BEQZC16 = 0x23,
13601 SLTI32 = 0x24,
13602 BEQ32 = 0x25,
13603 BC = 0x25,
13604 SWC132 = 0x26,
13605 LWC132 = 0x27,
13607 /* 0x29 is reserved */
13608 RES_29 = 0x29,
13609 R6_BNEZC = 0x28,
13610 JIALC = 0x28,
13611 SH16 = 0x2a,
13612 BNEZ16 = 0x2b,
13613 BNEZC16 = 0x2b,
13614 SLTIU32 = 0x2c,
13615 BNE32 = 0x2d,
13616 BALC = 0x2d,
13617 SDC132 = 0x2e,
13618 LDC132 = 0x2f,
13620 /* 0x31 is reserved */
13621 RES_31 = 0x31,
13622 BLEZALC = 0x30,
13623 BGEZALC = 0x30,
13624 BGEUC = 0x30,
13625 SWSP16 = 0x32,
13626 B16 = 0x33,
13627 BC16 = 0x33,
13628 ANDI32 = 0x34,
13629 J32 = 0x35,
13630 BGTZC = 0x35,
13631 BLTZC = 0x35,
13632 BLTC = 0x35,
13633 SD32 = 0x36, /* MIPS64 */
13634 LD32 = 0x37, /* MIPS64 */
13636 /* 0x39 is reserved */
13637 RES_39 = 0x39,
13638 BGTZALC = 0x38,
13639 BLTZALC = 0x38,
13640 BLTUC = 0x38,
13641 SW16 = 0x3a,
13642 LI16 = 0x3b,
13643 JALX32 = 0x3c,
13644 JAL32 = 0x3d,
13645 BLEZC = 0x3d,
13646 BGEZC = 0x3d,
13647 BGEC = 0x3d,
13648 SW32 = 0x3e,
13649 LW32 = 0x3f
13652 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13653 enum {
13654 ADDIUPC_00 = 0x00,
13655 ADDIUPC_01 = 0x01,
13656 ADDIUPC_02 = 0x02,
13657 ADDIUPC_03 = 0x03,
13658 ADDIUPC_04 = 0x04,
13659 ADDIUPC_05 = 0x05,
13660 ADDIUPC_06 = 0x06,
13661 ADDIUPC_07 = 0x07,
13662 AUIPC = 0x1e,
13663 ALUIPC = 0x1f,
13664 LWPC_08 = 0x08,
13665 LWPC_09 = 0x09,
13666 LWPC_0A = 0x0A,
13667 LWPC_0B = 0x0B,
13668 LWPC_0C = 0x0C,
13669 LWPC_0D = 0x0D,
13670 LWPC_0E = 0x0E,
13671 LWPC_0F = 0x0F,
13674 /* POOL32A encoding of minor opcode field */
13676 enum {
13677 /* These opcodes are distinguished only by bits 9..6; those bits are
13678 * what are recorded below. */
13679 SLL32 = 0x0,
13680 SRL32 = 0x1,
13681 SRA = 0x2,
13682 ROTR = 0x3,
13683 SELEQZ = 0x5,
13684 SELNEZ = 0x6,
13685 R6_RDHWR = 0x7,
13687 SLLV = 0x0,
13688 SRLV = 0x1,
13689 SRAV = 0x2,
13690 ROTRV = 0x3,
13691 ADD = 0x4,
13692 ADDU32 = 0x5,
13693 SUB = 0x6,
13694 SUBU32 = 0x7,
13695 MUL = 0x8,
13696 AND = 0x9,
13697 OR32 = 0xa,
13698 NOR = 0xb,
13699 XOR32 = 0xc,
13700 SLT = 0xd,
13701 SLTU = 0xe,
13703 MOVN = 0x0,
13704 R6_MUL = 0x0,
13705 MOVZ = 0x1,
13706 MUH = 0x1,
13707 MULU = 0x2,
13708 MUHU = 0x3,
13709 LWXS = 0x4,
13710 R6_DIV = 0x4,
13711 MOD = 0x5,
13712 R6_DIVU = 0x6,
13713 MODU = 0x7,
13715 /* The following can be distinguished by their lower 6 bits. */
13716 BREAK32 = 0x07,
13717 INS = 0x0c,
13718 LSA = 0x0f,
13719 ALIGN = 0x1f,
13720 EXT = 0x2c,
13721 POOL32AXF = 0x3c,
13722 SIGRIE = 0x3f
13725 /* POOL32AXF encoding of minor opcode field extension */
13728 * 1. MIPS Architecture for Programmers Volume II-B:
13729 * The microMIPS32 Instruction Set (Revision 3.05)
13731 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13733 * 2. MIPS Architecture for Programmers VolumeIV-e:
13734 * The MIPS DSP Application-Specific Extension
13735 * to the microMIPS32 Architecture (Revision 2.34)
13737 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13740 enum {
13741 /* bits 11..6 */
13742 TEQ = 0x00,
13743 TGE = 0x08,
13744 TGEU = 0x10,
13745 TLT = 0x20,
13746 TLTU = 0x28,
13747 TNE = 0x30,
13749 MFC0 = 0x03,
13750 MTC0 = 0x0b,
13752 /* begin of microMIPS32 DSP */
13754 /* bits 13..12 for 0x01 */
13755 MFHI_ACC = 0x0,
13756 MFLO_ACC = 0x1,
13757 MTHI_ACC = 0x2,
13758 MTLO_ACC = 0x3,
13760 /* bits 13..12 for 0x2a */
13761 MADD_ACC = 0x0,
13762 MADDU_ACC = 0x1,
13763 MSUB_ACC = 0x2,
13764 MSUBU_ACC = 0x3,
13766 /* bits 13..12 for 0x32 */
13767 MULT_ACC = 0x0,
13768 MULTU_ACC = 0x1,
13770 /* end of microMIPS32 DSP */
13772 /* bits 15..12 for 0x2c */
13773 BITSWAP = 0x0,
13774 SEB = 0x2,
13775 SEH = 0x3,
13776 CLO = 0x4,
13777 CLZ = 0x5,
13778 RDHWR = 0x6,
13779 WSBH = 0x7,
13780 MULT = 0x8,
13781 MULTU = 0x9,
13782 DIV = 0xa,
13783 DIVU = 0xb,
13784 MADD = 0xc,
13785 MADDU = 0xd,
13786 MSUB = 0xe,
13787 MSUBU = 0xf,
13789 /* bits 15..12 for 0x34 */
13790 MFC2 = 0x4,
13791 MTC2 = 0x5,
13792 MFHC2 = 0x8,
13793 MTHC2 = 0x9,
13794 CFC2 = 0xc,
13795 CTC2 = 0xd,
13797 /* bits 15..12 for 0x3c */
13798 JALR = 0x0,
13799 JR = 0x0, /* alias */
13800 JALRC = 0x0,
13801 JRC = 0x0,
13802 JALR_HB = 0x1,
13803 JALRC_HB = 0x1,
13804 JALRS = 0x4,
13805 JALRS_HB = 0x5,
13807 /* bits 15..12 for 0x05 */
13808 RDPGPR = 0xe,
13809 WRPGPR = 0xf,
13811 /* bits 15..12 for 0x0d */
13812 TLBP = 0x0,
13813 TLBR = 0x1,
13814 TLBWI = 0x2,
13815 TLBWR = 0x3,
13816 TLBINV = 0x4,
13817 TLBINVF = 0x5,
13818 WAIT = 0x9,
13819 IRET = 0xd,
13820 DERET = 0xe,
13821 ERET = 0xf,
13823 /* bits 15..12 for 0x15 */
13824 DMT = 0x0,
13825 DVPE = 0x1,
13826 EMT = 0x2,
13827 EVPE = 0x3,
13829 /* bits 15..12 for 0x1d */
13830 DI = 0x4,
13831 EI = 0x5,
13833 /* bits 15..12 for 0x2d */
13834 SYNC = 0x6,
13835 SYSCALL = 0x8,
13836 SDBBP = 0xd,
13838 /* bits 15..12 for 0x35 */
13839 MFHI32 = 0x0,
13840 MFLO32 = 0x1,
13841 MTHI32 = 0x2,
13842 MTLO32 = 0x3,
13845 /* POOL32B encoding of minor opcode field (bits 15..12) */
13847 enum {
13848 LWC2 = 0x0,
13849 LWP = 0x1,
13850 LDP = 0x4,
13851 LWM32 = 0x5,
13852 CACHE = 0x6,
13853 LDM = 0x7,
13854 SWC2 = 0x8,
13855 SWP = 0x9,
13856 SDP = 0xc,
13857 SWM32 = 0xd,
13858 SDM = 0xf
13861 /* POOL32C encoding of minor opcode field (bits 15..12) */
13863 enum {
13864 LWL = 0x0,
13865 SWL = 0x8,
13866 LWR = 0x1,
13867 SWR = 0x9,
13868 PREF = 0x2,
13869 ST_EVA = 0xa,
13870 LL = 0x3,
13871 SC = 0xb,
13872 LDL = 0x4,
13873 SDL = 0xc,
13874 LDR = 0x5,
13875 SDR = 0xd,
13876 LD_EVA = 0x6,
13877 LWU = 0xe,
13878 LLD = 0x7,
13879 SCD = 0xf
13882 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13884 enum {
13885 LBUE = 0x0,
13886 LHUE = 0x1,
13887 LWLE = 0x2,
13888 LWRE = 0x3,
13889 LBE = 0x4,
13890 LHE = 0x5,
13891 LLE = 0x6,
13892 LWE = 0x7,
13895 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13897 enum {
13898 SWLE = 0x0,
13899 SWRE = 0x1,
13900 PREFE = 0x2,
13901 CACHEE = 0x3,
13902 SBE = 0x4,
13903 SHE = 0x5,
13904 SCE = 0x6,
13905 SWE = 0x7,
13908 /* POOL32F encoding of minor opcode field (bits 5..0) */
13910 enum {
13911 /* These are the bit 7..6 values */
13912 ADD_FMT = 0x0,
13914 SUB_FMT = 0x1,
13916 MUL_FMT = 0x2,
13918 DIV_FMT = 0x3,
13920 /* These are the bit 8..6 values */
13921 MOVN_FMT = 0x0,
13922 RSQRT2_FMT = 0x0,
13923 MOVF_FMT = 0x0,
13924 RINT_FMT = 0x0,
13925 SELNEZ_FMT = 0x0,
13927 MOVZ_FMT = 0x1,
13928 LWXC1 = 0x1,
13929 MOVT_FMT = 0x1,
13930 CLASS_FMT = 0x1,
13931 SELEQZ_FMT = 0x1,
13933 PLL_PS = 0x2,
13934 SWXC1 = 0x2,
13935 SEL_FMT = 0x2,
13937 PLU_PS = 0x3,
13938 LDXC1 = 0x3,
13940 MOVN_FMT_04 = 0x4,
13941 PUL_PS = 0x4,
13942 SDXC1 = 0x4,
13943 RECIP2_FMT = 0x4,
13945 MOVZ_FMT_05 = 0x05,
13946 PUU_PS = 0x5,
13947 LUXC1 = 0x5,
13949 CVT_PS_S = 0x6,
13950 SUXC1 = 0x6,
13951 ADDR_PS = 0x6,
13952 PREFX = 0x6,
13953 MADDF_FMT = 0x6,
13955 MULR_PS = 0x7,
13956 MSUBF_FMT = 0x7,
13958 MADD_S = 0x01,
13959 MADD_D = 0x09,
13960 MADD_PS = 0x11,
13961 ALNV_PS = 0x19,
13962 MSUB_S = 0x21,
13963 MSUB_D = 0x29,
13964 MSUB_PS = 0x31,
13966 NMADD_S = 0x02,
13967 NMADD_D = 0x0a,
13968 NMADD_PS = 0x12,
13969 NMSUB_S = 0x22,
13970 NMSUB_D = 0x2a,
13971 NMSUB_PS = 0x32,
13973 MIN_FMT = 0x3,
13974 MAX_FMT = 0xb,
13975 MINA_FMT = 0x23,
13976 MAXA_FMT = 0x2b,
13977 POOL32FXF = 0x3b,
13979 CABS_COND_FMT = 0x1c, /* MIPS3D */
13980 C_COND_FMT = 0x3c,
13982 CMP_CONDN_S = 0x5,
13983 CMP_CONDN_D = 0x15
13986 /* POOL32Fxf encoding of minor opcode extension field */
13988 enum {
13989 CVT_L = 0x04,
13990 RSQRT_FMT = 0x08,
13991 FLOOR_L = 0x0c,
13992 CVT_PW_PS = 0x1c,
13993 CVT_W = 0x24,
13994 SQRT_FMT = 0x28,
13995 FLOOR_W = 0x2c,
13996 CVT_PS_PW = 0x3c,
13997 CFC1 = 0x40,
13998 RECIP_FMT = 0x48,
13999 CEIL_L = 0x4c,
14000 CTC1 = 0x60,
14001 CEIL_W = 0x6c,
14002 MFC1 = 0x80,
14003 CVT_S_PL = 0x84,
14004 TRUNC_L = 0x8c,
14005 MTC1 = 0xa0,
14006 CVT_S_PU = 0xa4,
14007 TRUNC_W = 0xac,
14008 MFHC1 = 0xc0,
14009 ROUND_L = 0xcc,
14010 MTHC1 = 0xe0,
14011 ROUND_W = 0xec,
14013 MOV_FMT = 0x01,
14014 MOVF = 0x05,
14015 ABS_FMT = 0x0d,
14016 RSQRT1_FMT = 0x1d,
14017 MOVT = 0x25,
14018 NEG_FMT = 0x2d,
14019 CVT_D = 0x4d,
14020 RECIP1_FMT = 0x5d,
14021 CVT_S = 0x6d
14024 /* POOL32I encoding of minor opcode field (bits 25..21) */
14026 enum {
14027 BLTZ = 0x00,
14028 BLTZAL = 0x01,
14029 BGEZ = 0x02,
14030 BGEZAL = 0x03,
14031 BLEZ = 0x04,
14032 BNEZC = 0x05,
14033 BGTZ = 0x06,
14034 BEQZC = 0x07,
14035 TLTI = 0x08,
14036 BC1EQZC = 0x08,
14037 TGEI = 0x09,
14038 BC1NEZC = 0x09,
14039 TLTIU = 0x0a,
14040 BC2EQZC = 0x0a,
14041 TGEIU = 0x0b,
14042 BC2NEZC = 0x0a,
14043 TNEI = 0x0c,
14044 R6_SYNCI = 0x0c,
14045 LUI = 0x0d,
14046 TEQI = 0x0e,
14047 SYNCI = 0x10,
14048 BLTZALS = 0x11,
14049 BGEZALS = 0x13,
14050 BC2F = 0x14,
14051 BC2T = 0x15,
14052 BPOSGE64 = 0x1a,
14053 BPOSGE32 = 0x1b,
14054 /* These overlap and are distinguished by bit16 of the instruction */
14055 BC1F = 0x1c,
14056 BC1T = 0x1d,
14057 BC1ANY2F = 0x1c,
14058 BC1ANY2T = 0x1d,
14059 BC1ANY4F = 0x1e,
14060 BC1ANY4T = 0x1f
14063 /* POOL16A encoding of minor opcode field */
14065 enum {
14066 ADDU16 = 0x0,
14067 SUBU16 = 0x1
14070 /* POOL16B encoding of minor opcode field */
14072 enum {
14073 SLL16 = 0x0,
14074 SRL16 = 0x1
14077 /* POOL16C encoding of minor opcode field */
14079 enum {
14080 NOT16 = 0x00,
14081 XOR16 = 0x04,
14082 AND16 = 0x08,
14083 OR16 = 0x0c,
14084 LWM16 = 0x10,
14085 SWM16 = 0x14,
14086 JR16 = 0x18,
14087 JRC16 = 0x1a,
14088 JALR16 = 0x1c,
14089 JALR16S = 0x1e,
14090 MFHI16 = 0x20,
14091 MFLO16 = 0x24,
14092 BREAK16 = 0x28,
14093 SDBBP16 = 0x2c,
14094 JRADDIUSP = 0x30
14097 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14099 enum {
14100 R6_NOT16 = 0x00,
14101 R6_AND16 = 0x01,
14102 R6_LWM16 = 0x02,
14103 R6_JRC16 = 0x03,
14104 MOVEP = 0x04,
14105 MOVEP_05 = 0x05,
14106 MOVEP_06 = 0x06,
14107 MOVEP_07 = 0x07,
14108 R6_XOR16 = 0x08,
14109 R6_OR16 = 0x09,
14110 R6_SWM16 = 0x0a,
14111 JALRC16 = 0x0b,
14112 MOVEP_0C = 0x0c,
14113 MOVEP_0D = 0x0d,
14114 MOVEP_0E = 0x0e,
14115 MOVEP_0F = 0x0f,
14116 JRCADDIUSP = 0x13,
14117 R6_BREAK16 = 0x1b,
14118 R6_SDBBP16 = 0x3b
14121 /* POOL16D encoding of minor opcode field */
14123 enum {
14124 ADDIUS5 = 0x0,
14125 ADDIUSP = 0x1
14128 /* POOL16E encoding of minor opcode field */
14130 enum {
14131 ADDIUR2 = 0x0,
14132 ADDIUR1SP = 0x1
14135 static int mmreg (int r)
14137 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14139 return map[r];
14142 /* Used for 16-bit store instructions. */
14143 static int mmreg2 (int r)
14145 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14147 return map[r];
14150 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14151 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14152 #define uMIPS_RS2(op) uMIPS_RS(op)
14153 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14154 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14155 #define uMIPS_RS5(op) (op & 0x1f)
14157 /* Signed immediate */
14158 #define SIMM(op, start, width) \
14159 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14160 << (32-width)) \
14161 >> (32-width))
14162 /* Zero-extended immediate */
14163 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14165 static void gen_addiur1sp(DisasContext *ctx)
14167 int rd = mmreg(uMIPS_RD(ctx->opcode));
14169 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14172 static void gen_addiur2(DisasContext *ctx)
14174 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14175 int rd = mmreg(uMIPS_RD(ctx->opcode));
14176 int rs = mmreg(uMIPS_RS(ctx->opcode));
14178 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14181 static void gen_addiusp(DisasContext *ctx)
14183 int encoded = ZIMM(ctx->opcode, 1, 9);
14184 int decoded;
14186 if (encoded <= 1) {
14187 decoded = 256 + encoded;
14188 } else if (encoded <= 255) {
14189 decoded = encoded;
14190 } else if (encoded <= 509) {
14191 decoded = encoded - 512;
14192 } else {
14193 decoded = encoded - 768;
14196 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14199 static void gen_addius5(DisasContext *ctx)
14201 int imm = SIMM(ctx->opcode, 1, 4);
14202 int rd = (ctx->opcode >> 5) & 0x1f;
14204 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14207 static void gen_andi16(DisasContext *ctx)
14209 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14210 31, 32, 63, 64, 255, 32768, 65535 };
14211 int rd = mmreg(uMIPS_RD(ctx->opcode));
14212 int rs = mmreg(uMIPS_RS(ctx->opcode));
14213 int encoded = ZIMM(ctx->opcode, 0, 4);
14215 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14218 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14219 int base, int16_t offset)
14221 TCGv t0, t1;
14222 TCGv_i32 t2;
14224 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14225 generate_exception_end(ctx, EXCP_RI);
14226 return;
14229 t0 = tcg_temp_new();
14231 gen_base_offset_addr(ctx, t0, base, offset);
14233 t1 = tcg_const_tl(reglist);
14234 t2 = tcg_const_i32(ctx->mem_idx);
14236 save_cpu_state(ctx, 1);
14237 switch (opc) {
14238 case LWM32:
14239 gen_helper_lwm(cpu_env, t0, t1, t2);
14240 break;
14241 case SWM32:
14242 gen_helper_swm(cpu_env, t0, t1, t2);
14243 break;
14244 #ifdef TARGET_MIPS64
14245 case LDM:
14246 gen_helper_ldm(cpu_env, t0, t1, t2);
14247 break;
14248 case SDM:
14249 gen_helper_sdm(cpu_env, t0, t1, t2);
14250 break;
14251 #endif
14253 tcg_temp_free(t0);
14254 tcg_temp_free(t1);
14255 tcg_temp_free_i32(t2);
14259 static void gen_pool16c_insn(DisasContext *ctx)
14261 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14262 int rs = mmreg(ctx->opcode & 0x7);
14264 switch (((ctx->opcode) >> 4) & 0x3f) {
14265 case NOT16 + 0:
14266 case NOT16 + 1:
14267 case NOT16 + 2:
14268 case NOT16 + 3:
14269 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14270 break;
14271 case XOR16 + 0:
14272 case XOR16 + 1:
14273 case XOR16 + 2:
14274 case XOR16 + 3:
14275 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14276 break;
14277 case AND16 + 0:
14278 case AND16 + 1:
14279 case AND16 + 2:
14280 case AND16 + 3:
14281 gen_logic(ctx, OPC_AND, rd, rd, rs);
14282 break;
14283 case OR16 + 0:
14284 case OR16 + 1:
14285 case OR16 + 2:
14286 case OR16 + 3:
14287 gen_logic(ctx, OPC_OR, rd, rd, rs);
14288 break;
14289 case LWM16 + 0:
14290 case LWM16 + 1:
14291 case LWM16 + 2:
14292 case LWM16 + 3:
14294 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14295 int offset = ZIMM(ctx->opcode, 0, 4);
14297 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14298 29, offset << 2);
14300 break;
14301 case SWM16 + 0:
14302 case SWM16 + 1:
14303 case SWM16 + 2:
14304 case SWM16 + 3:
14306 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14307 int offset = ZIMM(ctx->opcode, 0, 4);
14309 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14310 29, offset << 2);
14312 break;
14313 case JR16 + 0:
14314 case JR16 + 1:
14316 int reg = ctx->opcode & 0x1f;
14318 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14320 break;
14321 case JRC16 + 0:
14322 case JRC16 + 1:
14324 int reg = ctx->opcode & 0x1f;
14325 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14326 /* Let normal delay slot handling in our caller take us
14327 to the branch target. */
14329 break;
14330 case JALR16 + 0:
14331 case JALR16 + 1:
14332 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14333 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14334 break;
14335 case JALR16S + 0:
14336 case JALR16S + 1:
14337 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14338 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14339 break;
14340 case MFHI16 + 0:
14341 case MFHI16 + 1:
14342 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14343 break;
14344 case MFLO16 + 0:
14345 case MFLO16 + 1:
14346 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14347 break;
14348 case BREAK16:
14349 generate_exception_end(ctx, EXCP_BREAK);
14350 break;
14351 case SDBBP16:
14352 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14353 gen_helper_do_semihosting(cpu_env);
14354 } else {
14355 /* XXX: not clear which exception should be raised
14356 * when in debug mode...
14358 check_insn(ctx, ISA_MIPS32);
14359 generate_exception_end(ctx, EXCP_DBp);
14361 break;
14362 case JRADDIUSP + 0:
14363 case JRADDIUSP + 1:
14365 int imm = ZIMM(ctx->opcode, 0, 5);
14366 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14367 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14368 /* Let normal delay slot handling in our caller take us
14369 to the branch target. */
14371 break;
14372 default:
14373 generate_exception_end(ctx, EXCP_RI);
14374 break;
14378 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14379 int enc_rs)
14381 int rd, rs, re, rt;
14382 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14383 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14384 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14385 rd = rd_enc[enc_dest];
14386 re = re_enc[enc_dest];
14387 rs = rs_rt_enc[enc_rs];
14388 rt = rs_rt_enc[enc_rt];
14389 if (rs) {
14390 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14391 } else {
14392 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14394 if (rt) {
14395 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14396 } else {
14397 tcg_gen_movi_tl(cpu_gpr[re], 0);
14401 static void gen_pool16c_r6_insn(DisasContext *ctx)
14403 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14404 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14406 switch (ctx->opcode & 0xf) {
14407 case R6_NOT16:
14408 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14409 break;
14410 case R6_AND16:
14411 gen_logic(ctx, OPC_AND, rt, rt, rs);
14412 break;
14413 case R6_LWM16:
14415 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14416 int offset = extract32(ctx->opcode, 4, 4);
14417 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14419 break;
14420 case R6_JRC16: /* JRCADDIUSP */
14421 if ((ctx->opcode >> 4) & 1) {
14422 /* JRCADDIUSP */
14423 int imm = extract32(ctx->opcode, 5, 5);
14424 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14425 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14426 } else {
14427 /* JRC16 */
14428 rs = extract32(ctx->opcode, 5, 5);
14429 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14431 break;
14432 case MOVEP:
14433 case MOVEP_05:
14434 case MOVEP_06:
14435 case MOVEP_07:
14436 case MOVEP_0C:
14437 case MOVEP_0D:
14438 case MOVEP_0E:
14439 case MOVEP_0F:
14441 int enc_dest = uMIPS_RD(ctx->opcode);
14442 int enc_rt = uMIPS_RS2(ctx->opcode);
14443 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14444 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14446 break;
14447 case R6_XOR16:
14448 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14449 break;
14450 case R6_OR16:
14451 gen_logic(ctx, OPC_OR, rt, rt, rs);
14452 break;
14453 case R6_SWM16:
14455 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14456 int offset = extract32(ctx->opcode, 4, 4);
14457 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14459 break;
14460 case JALRC16: /* BREAK16, SDBBP16 */
14461 switch (ctx->opcode & 0x3f) {
14462 case JALRC16:
14463 case JALRC16 + 0x20:
14464 /* JALRC16 */
14465 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14466 31, 0, 0);
14467 break;
14468 case R6_BREAK16:
14469 /* BREAK16 */
14470 generate_exception(ctx, EXCP_BREAK);
14471 break;
14472 case R6_SDBBP16:
14473 /* SDBBP16 */
14474 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14475 gen_helper_do_semihosting(cpu_env);
14476 } else {
14477 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14478 generate_exception(ctx, EXCP_RI);
14479 } else {
14480 generate_exception(ctx, EXCP_DBp);
14483 break;
14485 break;
14486 default:
14487 generate_exception(ctx, EXCP_RI);
14488 break;
14492 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14494 TCGv t0 = tcg_temp_new();
14495 TCGv t1 = tcg_temp_new();
14497 gen_load_gpr(t0, base);
14499 if (index != 0) {
14500 gen_load_gpr(t1, index);
14501 tcg_gen_shli_tl(t1, t1, 2);
14502 gen_op_addr_add(ctx, t0, t1, t0);
14505 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14506 gen_store_gpr(t1, rd);
14508 tcg_temp_free(t0);
14509 tcg_temp_free(t1);
14512 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14513 int base, int16_t offset)
14515 TCGv t0, t1;
14517 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14518 generate_exception_end(ctx, EXCP_RI);
14519 return;
14522 t0 = tcg_temp_new();
14523 t1 = tcg_temp_new();
14525 gen_base_offset_addr(ctx, t0, base, offset);
14527 switch (opc) {
14528 case LWP:
14529 if (rd == base) {
14530 generate_exception_end(ctx, EXCP_RI);
14531 return;
14533 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14534 gen_store_gpr(t1, rd);
14535 tcg_gen_movi_tl(t1, 4);
14536 gen_op_addr_add(ctx, t0, t0, t1);
14537 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14538 gen_store_gpr(t1, rd+1);
14539 break;
14540 case SWP:
14541 gen_load_gpr(t1, rd);
14542 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14543 tcg_gen_movi_tl(t1, 4);
14544 gen_op_addr_add(ctx, t0, t0, t1);
14545 gen_load_gpr(t1, rd+1);
14546 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14547 break;
14548 #ifdef TARGET_MIPS64
14549 case LDP:
14550 if (rd == base) {
14551 generate_exception_end(ctx, EXCP_RI);
14552 return;
14554 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14555 gen_store_gpr(t1, rd);
14556 tcg_gen_movi_tl(t1, 8);
14557 gen_op_addr_add(ctx, t0, t0, t1);
14558 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14559 gen_store_gpr(t1, rd+1);
14560 break;
14561 case SDP:
14562 gen_load_gpr(t1, rd);
14563 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14564 tcg_gen_movi_tl(t1, 8);
14565 gen_op_addr_add(ctx, t0, t0, t1);
14566 gen_load_gpr(t1, rd+1);
14567 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14568 break;
14569 #endif
14571 tcg_temp_free(t0);
14572 tcg_temp_free(t1);
14575 static void gen_sync(int stype)
14577 TCGBar tcg_mo = TCG_BAR_SC;
14579 switch (stype) {
14580 case 0x4: /* SYNC_WMB */
14581 tcg_mo |= TCG_MO_ST_ST;
14582 break;
14583 case 0x10: /* SYNC_MB */
14584 tcg_mo |= TCG_MO_ALL;
14585 break;
14586 case 0x11: /* SYNC_ACQUIRE */
14587 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14588 break;
14589 case 0x12: /* SYNC_RELEASE */
14590 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14591 break;
14592 case 0x13: /* SYNC_RMB */
14593 tcg_mo |= TCG_MO_LD_LD;
14594 break;
14595 default:
14596 tcg_mo |= TCG_MO_ALL;
14597 break;
14600 tcg_gen_mb(tcg_mo);
14603 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14605 int extension = (ctx->opcode >> 6) & 0x3f;
14606 int minor = (ctx->opcode >> 12) & 0xf;
14607 uint32_t mips32_op;
14609 switch (extension) {
14610 case TEQ:
14611 mips32_op = OPC_TEQ;
14612 goto do_trap;
14613 case TGE:
14614 mips32_op = OPC_TGE;
14615 goto do_trap;
14616 case TGEU:
14617 mips32_op = OPC_TGEU;
14618 goto do_trap;
14619 case TLT:
14620 mips32_op = OPC_TLT;
14621 goto do_trap;
14622 case TLTU:
14623 mips32_op = OPC_TLTU;
14624 goto do_trap;
14625 case TNE:
14626 mips32_op = OPC_TNE;
14627 do_trap:
14628 gen_trap(ctx, mips32_op, rs, rt, -1);
14629 break;
14630 #ifndef CONFIG_USER_ONLY
14631 case MFC0:
14632 case MFC0 + 32:
14633 check_cp0_enabled(ctx);
14634 if (rt == 0) {
14635 /* Treat as NOP. */
14636 break;
14638 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14639 break;
14640 case MTC0:
14641 case MTC0 + 32:
14642 check_cp0_enabled(ctx);
14644 TCGv t0 = tcg_temp_new();
14646 gen_load_gpr(t0, rt);
14647 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14648 tcg_temp_free(t0);
14650 break;
14651 #endif
14652 case 0x2a:
14653 switch (minor & 3) {
14654 case MADD_ACC:
14655 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14656 break;
14657 case MADDU_ACC:
14658 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14659 break;
14660 case MSUB_ACC:
14661 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14662 break;
14663 case MSUBU_ACC:
14664 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14665 break;
14666 default:
14667 goto pool32axf_invalid;
14669 break;
14670 case 0x32:
14671 switch (minor & 3) {
14672 case MULT_ACC:
14673 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14674 break;
14675 case MULTU_ACC:
14676 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14677 break;
14678 default:
14679 goto pool32axf_invalid;
14681 break;
14682 case 0x2c:
14683 switch (minor) {
14684 case BITSWAP:
14685 check_insn(ctx, ISA_MIPS32R6);
14686 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14687 break;
14688 case SEB:
14689 gen_bshfl(ctx, OPC_SEB, rs, rt);
14690 break;
14691 case SEH:
14692 gen_bshfl(ctx, OPC_SEH, rs, rt);
14693 break;
14694 case CLO:
14695 mips32_op = OPC_CLO;
14696 goto do_cl;
14697 case CLZ:
14698 mips32_op = OPC_CLZ;
14699 do_cl:
14700 check_insn(ctx, ISA_MIPS32);
14701 gen_cl(ctx, mips32_op, rt, rs);
14702 break;
14703 case RDHWR:
14704 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14705 gen_rdhwr(ctx, rt, rs, 0);
14706 break;
14707 case WSBH:
14708 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14709 break;
14710 case MULT:
14711 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14712 mips32_op = OPC_MULT;
14713 goto do_mul;
14714 case MULTU:
14715 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14716 mips32_op = OPC_MULTU;
14717 goto do_mul;
14718 case DIV:
14719 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14720 mips32_op = OPC_DIV;
14721 goto do_div;
14722 case DIVU:
14723 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14724 mips32_op = OPC_DIVU;
14725 goto do_div;
14726 do_div:
14727 check_insn(ctx, ISA_MIPS32);
14728 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14729 break;
14730 case MADD:
14731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14732 mips32_op = OPC_MADD;
14733 goto do_mul;
14734 case MADDU:
14735 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14736 mips32_op = OPC_MADDU;
14737 goto do_mul;
14738 case MSUB:
14739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14740 mips32_op = OPC_MSUB;
14741 goto do_mul;
14742 case MSUBU:
14743 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14744 mips32_op = OPC_MSUBU;
14745 do_mul:
14746 check_insn(ctx, ISA_MIPS32);
14747 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14748 break;
14749 default:
14750 goto pool32axf_invalid;
14752 break;
14753 case 0x34:
14754 switch (minor) {
14755 case MFC2:
14756 case MTC2:
14757 case MFHC2:
14758 case MTHC2:
14759 case CFC2:
14760 case CTC2:
14761 generate_exception_err(ctx, EXCP_CpU, 2);
14762 break;
14763 default:
14764 goto pool32axf_invalid;
14766 break;
14767 case 0x3c:
14768 switch (minor) {
14769 case JALR: /* JALRC */
14770 case JALR_HB: /* JALRC_HB */
14771 if (ctx->insn_flags & ISA_MIPS32R6) {
14772 /* JALRC, JALRC_HB */
14773 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14774 } else {
14775 /* JALR, JALR_HB */
14776 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14777 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14779 break;
14780 case JALRS:
14781 case JALRS_HB:
14782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14783 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14784 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14785 break;
14786 default:
14787 goto pool32axf_invalid;
14789 break;
14790 case 0x05:
14791 switch (minor) {
14792 case RDPGPR:
14793 check_cp0_enabled(ctx);
14794 check_insn(ctx, ISA_MIPS32R2);
14795 gen_load_srsgpr(rs, rt);
14796 break;
14797 case WRPGPR:
14798 check_cp0_enabled(ctx);
14799 check_insn(ctx, ISA_MIPS32R2);
14800 gen_store_srsgpr(rs, rt);
14801 break;
14802 default:
14803 goto pool32axf_invalid;
14805 break;
14806 #ifndef CONFIG_USER_ONLY
14807 case 0x0d:
14808 switch (minor) {
14809 case TLBP:
14810 mips32_op = OPC_TLBP;
14811 goto do_cp0;
14812 case TLBR:
14813 mips32_op = OPC_TLBR;
14814 goto do_cp0;
14815 case TLBWI:
14816 mips32_op = OPC_TLBWI;
14817 goto do_cp0;
14818 case TLBWR:
14819 mips32_op = OPC_TLBWR;
14820 goto do_cp0;
14821 case TLBINV:
14822 mips32_op = OPC_TLBINV;
14823 goto do_cp0;
14824 case TLBINVF:
14825 mips32_op = OPC_TLBINVF;
14826 goto do_cp0;
14827 case WAIT:
14828 mips32_op = OPC_WAIT;
14829 goto do_cp0;
14830 case DERET:
14831 mips32_op = OPC_DERET;
14832 goto do_cp0;
14833 case ERET:
14834 mips32_op = OPC_ERET;
14835 do_cp0:
14836 gen_cp0(env, ctx, mips32_op, rt, rs);
14837 break;
14838 default:
14839 goto pool32axf_invalid;
14841 break;
14842 case 0x1d:
14843 switch (minor) {
14844 case DI:
14845 check_cp0_enabled(ctx);
14847 TCGv t0 = tcg_temp_new();
14849 save_cpu_state(ctx, 1);
14850 gen_helper_di(t0, cpu_env);
14851 gen_store_gpr(t0, rs);
14852 /* Stop translation as we may have switched the execution mode */
14853 ctx->base.is_jmp = DISAS_STOP;
14854 tcg_temp_free(t0);
14856 break;
14857 case EI:
14858 check_cp0_enabled(ctx);
14860 TCGv t0 = tcg_temp_new();
14862 save_cpu_state(ctx, 1);
14863 gen_helper_ei(t0, cpu_env);
14864 gen_store_gpr(t0, rs);
14865 /* DISAS_STOP isn't sufficient, we need to ensure we break out
14866 of translated code to check for pending interrupts. */
14867 gen_save_pc(ctx->base.pc_next + 4);
14868 ctx->base.is_jmp = DISAS_EXIT;
14869 tcg_temp_free(t0);
14871 break;
14872 default:
14873 goto pool32axf_invalid;
14875 break;
14876 #endif
14877 case 0x2d:
14878 switch (minor) {
14879 case SYNC:
14880 gen_sync(extract32(ctx->opcode, 16, 5));
14881 break;
14882 case SYSCALL:
14883 generate_exception_end(ctx, EXCP_SYSCALL);
14884 break;
14885 case SDBBP:
14886 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14887 gen_helper_do_semihosting(cpu_env);
14888 } else {
14889 check_insn(ctx, ISA_MIPS32);
14890 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14891 generate_exception_end(ctx, EXCP_RI);
14892 } else {
14893 generate_exception_end(ctx, EXCP_DBp);
14896 break;
14897 default:
14898 goto pool32axf_invalid;
14900 break;
14901 case 0x01:
14902 switch (minor & 3) {
14903 case MFHI_ACC:
14904 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14905 break;
14906 case MFLO_ACC:
14907 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14908 break;
14909 case MTHI_ACC:
14910 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14911 break;
14912 case MTLO_ACC:
14913 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14914 break;
14915 default:
14916 goto pool32axf_invalid;
14918 break;
14919 case 0x35:
14920 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14921 switch (minor) {
14922 case MFHI32:
14923 gen_HILO(ctx, OPC_MFHI, 0, rs);
14924 break;
14925 case MFLO32:
14926 gen_HILO(ctx, OPC_MFLO, 0, rs);
14927 break;
14928 case MTHI32:
14929 gen_HILO(ctx, OPC_MTHI, 0, rs);
14930 break;
14931 case MTLO32:
14932 gen_HILO(ctx, OPC_MTLO, 0, rs);
14933 break;
14934 default:
14935 goto pool32axf_invalid;
14937 break;
14938 default:
14939 pool32axf_invalid:
14940 MIPS_INVAL("pool32axf");
14941 generate_exception_end(ctx, EXCP_RI);
14942 break;
14946 /* Values for microMIPS fmt field. Variable-width, depending on which
14947 formats the instruction supports. */
14949 enum {
14950 FMT_SD_S = 0,
14951 FMT_SD_D = 1,
14953 FMT_SDPS_S = 0,
14954 FMT_SDPS_D = 1,
14955 FMT_SDPS_PS = 2,
14957 FMT_SWL_S = 0,
14958 FMT_SWL_W = 1,
14959 FMT_SWL_L = 2,
14961 FMT_DWL_D = 0,
14962 FMT_DWL_W = 1,
14963 FMT_DWL_L = 2
14966 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14968 int extension = (ctx->opcode >> 6) & 0x3ff;
14969 uint32_t mips32_op;
14971 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14972 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14973 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14975 switch (extension) {
14976 case FLOAT_1BIT_FMT(CFC1, 0):
14977 mips32_op = OPC_CFC1;
14978 goto do_cp1;
14979 case FLOAT_1BIT_FMT(CTC1, 0):
14980 mips32_op = OPC_CTC1;
14981 goto do_cp1;
14982 case FLOAT_1BIT_FMT(MFC1, 0):
14983 mips32_op = OPC_MFC1;
14984 goto do_cp1;
14985 case FLOAT_1BIT_FMT(MTC1, 0):
14986 mips32_op = OPC_MTC1;
14987 goto do_cp1;
14988 case FLOAT_1BIT_FMT(MFHC1, 0):
14989 mips32_op = OPC_MFHC1;
14990 goto do_cp1;
14991 case FLOAT_1BIT_FMT(MTHC1, 0):
14992 mips32_op = OPC_MTHC1;
14993 do_cp1:
14994 gen_cp1(ctx, mips32_op, rt, rs);
14995 break;
14997 /* Reciprocal square root */
14998 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14999 mips32_op = OPC_RSQRT_S;
15000 goto do_unaryfp;
15001 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15002 mips32_op = OPC_RSQRT_D;
15003 goto do_unaryfp;
15005 /* Square root */
15006 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15007 mips32_op = OPC_SQRT_S;
15008 goto do_unaryfp;
15009 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15010 mips32_op = OPC_SQRT_D;
15011 goto do_unaryfp;
15013 /* Reciprocal */
15014 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15015 mips32_op = OPC_RECIP_S;
15016 goto do_unaryfp;
15017 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15018 mips32_op = OPC_RECIP_D;
15019 goto do_unaryfp;
15021 /* Floor */
15022 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15023 mips32_op = OPC_FLOOR_L_S;
15024 goto do_unaryfp;
15025 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15026 mips32_op = OPC_FLOOR_L_D;
15027 goto do_unaryfp;
15028 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15029 mips32_op = OPC_FLOOR_W_S;
15030 goto do_unaryfp;
15031 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15032 mips32_op = OPC_FLOOR_W_D;
15033 goto do_unaryfp;
15035 /* Ceiling */
15036 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15037 mips32_op = OPC_CEIL_L_S;
15038 goto do_unaryfp;
15039 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15040 mips32_op = OPC_CEIL_L_D;
15041 goto do_unaryfp;
15042 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15043 mips32_op = OPC_CEIL_W_S;
15044 goto do_unaryfp;
15045 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15046 mips32_op = OPC_CEIL_W_D;
15047 goto do_unaryfp;
15049 /* Truncation */
15050 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15051 mips32_op = OPC_TRUNC_L_S;
15052 goto do_unaryfp;
15053 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15054 mips32_op = OPC_TRUNC_L_D;
15055 goto do_unaryfp;
15056 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15057 mips32_op = OPC_TRUNC_W_S;
15058 goto do_unaryfp;
15059 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15060 mips32_op = OPC_TRUNC_W_D;
15061 goto do_unaryfp;
15063 /* Round */
15064 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15065 mips32_op = OPC_ROUND_L_S;
15066 goto do_unaryfp;
15067 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15068 mips32_op = OPC_ROUND_L_D;
15069 goto do_unaryfp;
15070 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15071 mips32_op = OPC_ROUND_W_S;
15072 goto do_unaryfp;
15073 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15074 mips32_op = OPC_ROUND_W_D;
15075 goto do_unaryfp;
15077 /* Integer to floating-point conversion */
15078 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15079 mips32_op = OPC_CVT_L_S;
15080 goto do_unaryfp;
15081 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15082 mips32_op = OPC_CVT_L_D;
15083 goto do_unaryfp;
15084 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15085 mips32_op = OPC_CVT_W_S;
15086 goto do_unaryfp;
15087 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15088 mips32_op = OPC_CVT_W_D;
15089 goto do_unaryfp;
15091 /* Paired-foo conversions */
15092 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15093 mips32_op = OPC_CVT_S_PL;
15094 goto do_unaryfp;
15095 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15096 mips32_op = OPC_CVT_S_PU;
15097 goto do_unaryfp;
15098 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15099 mips32_op = OPC_CVT_PW_PS;
15100 goto do_unaryfp;
15101 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15102 mips32_op = OPC_CVT_PS_PW;
15103 goto do_unaryfp;
15105 /* Floating-point moves */
15106 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15107 mips32_op = OPC_MOV_S;
15108 goto do_unaryfp;
15109 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15110 mips32_op = OPC_MOV_D;
15111 goto do_unaryfp;
15112 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15113 mips32_op = OPC_MOV_PS;
15114 goto do_unaryfp;
15116 /* Absolute value */
15117 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15118 mips32_op = OPC_ABS_S;
15119 goto do_unaryfp;
15120 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15121 mips32_op = OPC_ABS_D;
15122 goto do_unaryfp;
15123 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15124 mips32_op = OPC_ABS_PS;
15125 goto do_unaryfp;
15127 /* Negation */
15128 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15129 mips32_op = OPC_NEG_S;
15130 goto do_unaryfp;
15131 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15132 mips32_op = OPC_NEG_D;
15133 goto do_unaryfp;
15134 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15135 mips32_op = OPC_NEG_PS;
15136 goto do_unaryfp;
15138 /* Reciprocal square root step */
15139 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15140 mips32_op = OPC_RSQRT1_S;
15141 goto do_unaryfp;
15142 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15143 mips32_op = OPC_RSQRT1_D;
15144 goto do_unaryfp;
15145 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15146 mips32_op = OPC_RSQRT1_PS;
15147 goto do_unaryfp;
15149 /* Reciprocal step */
15150 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15151 mips32_op = OPC_RECIP1_S;
15152 goto do_unaryfp;
15153 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15154 mips32_op = OPC_RECIP1_S;
15155 goto do_unaryfp;
15156 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15157 mips32_op = OPC_RECIP1_PS;
15158 goto do_unaryfp;
15160 /* Conversions from double */
15161 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15162 mips32_op = OPC_CVT_D_S;
15163 goto do_unaryfp;
15164 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15165 mips32_op = OPC_CVT_D_W;
15166 goto do_unaryfp;
15167 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15168 mips32_op = OPC_CVT_D_L;
15169 goto do_unaryfp;
15171 /* Conversions from single */
15172 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15173 mips32_op = OPC_CVT_S_D;
15174 goto do_unaryfp;
15175 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15176 mips32_op = OPC_CVT_S_W;
15177 goto do_unaryfp;
15178 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15179 mips32_op = OPC_CVT_S_L;
15180 do_unaryfp:
15181 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15182 break;
15184 /* Conditional moves on floating-point codes */
15185 case COND_FLOAT_MOV(MOVT, 0):
15186 case COND_FLOAT_MOV(MOVT, 1):
15187 case COND_FLOAT_MOV(MOVT, 2):
15188 case COND_FLOAT_MOV(MOVT, 3):
15189 case COND_FLOAT_MOV(MOVT, 4):
15190 case COND_FLOAT_MOV(MOVT, 5):
15191 case COND_FLOAT_MOV(MOVT, 6):
15192 case COND_FLOAT_MOV(MOVT, 7):
15193 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15194 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15195 break;
15196 case COND_FLOAT_MOV(MOVF, 0):
15197 case COND_FLOAT_MOV(MOVF, 1):
15198 case COND_FLOAT_MOV(MOVF, 2):
15199 case COND_FLOAT_MOV(MOVF, 3):
15200 case COND_FLOAT_MOV(MOVF, 4):
15201 case COND_FLOAT_MOV(MOVF, 5):
15202 case COND_FLOAT_MOV(MOVF, 6):
15203 case COND_FLOAT_MOV(MOVF, 7):
15204 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15205 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15206 break;
15207 default:
15208 MIPS_INVAL("pool32fxf");
15209 generate_exception_end(ctx, EXCP_RI);
15210 break;
15214 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15216 int32_t offset;
15217 uint16_t insn;
15218 int rt, rs, rd, rr;
15219 int16_t imm;
15220 uint32_t op, minor, minor2, mips32_op;
15221 uint32_t cond, fmt, cc;
15223 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15224 ctx->opcode = (ctx->opcode << 16) | insn;
15226 rt = (ctx->opcode >> 21) & 0x1f;
15227 rs = (ctx->opcode >> 16) & 0x1f;
15228 rd = (ctx->opcode >> 11) & 0x1f;
15229 rr = (ctx->opcode >> 6) & 0x1f;
15230 imm = (int16_t) ctx->opcode;
15232 op = (ctx->opcode >> 26) & 0x3f;
15233 switch (op) {
15234 case POOL32A:
15235 minor = ctx->opcode & 0x3f;
15236 switch (minor) {
15237 case 0x00:
15238 minor = (ctx->opcode >> 6) & 0xf;
15239 switch (minor) {
15240 case SLL32:
15241 mips32_op = OPC_SLL;
15242 goto do_shifti;
15243 case SRA:
15244 mips32_op = OPC_SRA;
15245 goto do_shifti;
15246 case SRL32:
15247 mips32_op = OPC_SRL;
15248 goto do_shifti;
15249 case ROTR:
15250 mips32_op = OPC_ROTR;
15251 do_shifti:
15252 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15253 break;
15254 case SELEQZ:
15255 check_insn(ctx, ISA_MIPS32R6);
15256 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15257 break;
15258 case SELNEZ:
15259 check_insn(ctx, ISA_MIPS32R6);
15260 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15261 break;
15262 case R6_RDHWR:
15263 check_insn(ctx, ISA_MIPS32R6);
15264 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15265 break;
15266 default:
15267 goto pool32a_invalid;
15269 break;
15270 case 0x10:
15271 minor = (ctx->opcode >> 6) & 0xf;
15272 switch (minor) {
15273 /* Arithmetic */
15274 case ADD:
15275 mips32_op = OPC_ADD;
15276 goto do_arith;
15277 case ADDU32:
15278 mips32_op = OPC_ADDU;
15279 goto do_arith;
15280 case SUB:
15281 mips32_op = OPC_SUB;
15282 goto do_arith;
15283 case SUBU32:
15284 mips32_op = OPC_SUBU;
15285 goto do_arith;
15286 case MUL:
15287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15288 mips32_op = OPC_MUL;
15289 do_arith:
15290 gen_arith(ctx, mips32_op, rd, rs, rt);
15291 break;
15292 /* Shifts */
15293 case SLLV:
15294 mips32_op = OPC_SLLV;
15295 goto do_shift;
15296 case SRLV:
15297 mips32_op = OPC_SRLV;
15298 goto do_shift;
15299 case SRAV:
15300 mips32_op = OPC_SRAV;
15301 goto do_shift;
15302 case ROTRV:
15303 mips32_op = OPC_ROTRV;
15304 do_shift:
15305 gen_shift(ctx, mips32_op, rd, rs, rt);
15306 break;
15307 /* Logical operations */
15308 case AND:
15309 mips32_op = OPC_AND;
15310 goto do_logic;
15311 case OR32:
15312 mips32_op = OPC_OR;
15313 goto do_logic;
15314 case NOR:
15315 mips32_op = OPC_NOR;
15316 goto do_logic;
15317 case XOR32:
15318 mips32_op = OPC_XOR;
15319 do_logic:
15320 gen_logic(ctx, mips32_op, rd, rs, rt);
15321 break;
15322 /* Set less than */
15323 case SLT:
15324 mips32_op = OPC_SLT;
15325 goto do_slt;
15326 case SLTU:
15327 mips32_op = OPC_SLTU;
15328 do_slt:
15329 gen_slt(ctx, mips32_op, rd, rs, rt);
15330 break;
15331 default:
15332 goto pool32a_invalid;
15334 break;
15335 case 0x18:
15336 minor = (ctx->opcode >> 6) & 0xf;
15337 switch (minor) {
15338 /* Conditional moves */
15339 case MOVN: /* MUL */
15340 if (ctx->insn_flags & ISA_MIPS32R6) {
15341 /* MUL */
15342 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15343 } else {
15344 /* MOVN */
15345 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15347 break;
15348 case MOVZ: /* MUH */
15349 if (ctx->insn_flags & ISA_MIPS32R6) {
15350 /* MUH */
15351 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15352 } else {
15353 /* MOVZ */
15354 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15356 break;
15357 case MULU:
15358 check_insn(ctx, ISA_MIPS32R6);
15359 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15360 break;
15361 case MUHU:
15362 check_insn(ctx, ISA_MIPS32R6);
15363 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15364 break;
15365 case LWXS: /* DIV */
15366 if (ctx->insn_flags & ISA_MIPS32R6) {
15367 /* DIV */
15368 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15369 } else {
15370 /* LWXS */
15371 gen_ldxs(ctx, rs, rt, rd);
15373 break;
15374 case MOD:
15375 check_insn(ctx, ISA_MIPS32R6);
15376 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15377 break;
15378 case R6_DIVU:
15379 check_insn(ctx, ISA_MIPS32R6);
15380 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15381 break;
15382 case MODU:
15383 check_insn(ctx, ISA_MIPS32R6);
15384 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15385 break;
15386 default:
15387 goto pool32a_invalid;
15389 break;
15390 case INS:
15391 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15392 return;
15393 case LSA:
15394 check_insn(ctx, ISA_MIPS32R6);
15395 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15396 extract32(ctx->opcode, 9, 2));
15397 break;
15398 case ALIGN:
15399 check_insn(ctx, ISA_MIPS32R6);
15400 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15401 break;
15402 case EXT:
15403 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15404 return;
15405 case POOL32AXF:
15406 gen_pool32axf(env, ctx, rt, rs);
15407 break;
15408 case BREAK32:
15409 generate_exception_end(ctx, EXCP_BREAK);
15410 break;
15411 case SIGRIE:
15412 check_insn(ctx, ISA_MIPS32R6);
15413 generate_exception_end(ctx, EXCP_RI);
15414 break;
15415 default:
15416 pool32a_invalid:
15417 MIPS_INVAL("pool32a");
15418 generate_exception_end(ctx, EXCP_RI);
15419 break;
15421 break;
15422 case POOL32B:
15423 minor = (ctx->opcode >> 12) & 0xf;
15424 switch (minor) {
15425 case CACHE:
15426 check_cp0_enabled(ctx);
15427 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15428 gen_cache_operation(ctx, rt, rs, imm);
15430 break;
15431 case LWC2:
15432 case SWC2:
15433 /* COP2: Not implemented. */
15434 generate_exception_err(ctx, EXCP_CpU, 2);
15435 break;
15436 #ifdef TARGET_MIPS64
15437 case LDP:
15438 case SDP:
15439 check_insn(ctx, ISA_MIPS3);
15440 check_mips_64(ctx);
15441 #endif
15442 /* fall through */
15443 case LWP:
15444 case SWP:
15445 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15446 break;
15447 #ifdef TARGET_MIPS64
15448 case LDM:
15449 case SDM:
15450 check_insn(ctx, ISA_MIPS3);
15451 check_mips_64(ctx);
15452 #endif
15453 /* fall through */
15454 case LWM32:
15455 case SWM32:
15456 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15457 break;
15458 default:
15459 MIPS_INVAL("pool32b");
15460 generate_exception_end(ctx, EXCP_RI);
15461 break;
15463 break;
15464 case POOL32F:
15465 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15466 minor = ctx->opcode & 0x3f;
15467 check_cp1_enabled(ctx);
15468 switch (minor) {
15469 case ALNV_PS:
15470 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15471 mips32_op = OPC_ALNV_PS;
15472 goto do_madd;
15473 case MADD_S:
15474 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15475 mips32_op = OPC_MADD_S;
15476 goto do_madd;
15477 case MADD_D:
15478 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15479 mips32_op = OPC_MADD_D;
15480 goto do_madd;
15481 case MADD_PS:
15482 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15483 mips32_op = OPC_MADD_PS;
15484 goto do_madd;
15485 case MSUB_S:
15486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15487 mips32_op = OPC_MSUB_S;
15488 goto do_madd;
15489 case MSUB_D:
15490 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15491 mips32_op = OPC_MSUB_D;
15492 goto do_madd;
15493 case MSUB_PS:
15494 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15495 mips32_op = OPC_MSUB_PS;
15496 goto do_madd;
15497 case NMADD_S:
15498 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15499 mips32_op = OPC_NMADD_S;
15500 goto do_madd;
15501 case NMADD_D:
15502 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15503 mips32_op = OPC_NMADD_D;
15504 goto do_madd;
15505 case NMADD_PS:
15506 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15507 mips32_op = OPC_NMADD_PS;
15508 goto do_madd;
15509 case NMSUB_S:
15510 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15511 mips32_op = OPC_NMSUB_S;
15512 goto do_madd;
15513 case NMSUB_D:
15514 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15515 mips32_op = OPC_NMSUB_D;
15516 goto do_madd;
15517 case NMSUB_PS:
15518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15519 mips32_op = OPC_NMSUB_PS;
15520 do_madd:
15521 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15522 break;
15523 case CABS_COND_FMT:
15524 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15525 cond = (ctx->opcode >> 6) & 0xf;
15526 cc = (ctx->opcode >> 13) & 0x7;
15527 fmt = (ctx->opcode >> 10) & 0x3;
15528 switch (fmt) {
15529 case 0x0:
15530 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15531 break;
15532 case 0x1:
15533 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15534 break;
15535 case 0x2:
15536 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15537 break;
15538 default:
15539 goto pool32f_invalid;
15541 break;
15542 case C_COND_FMT:
15543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15544 cond = (ctx->opcode >> 6) & 0xf;
15545 cc = (ctx->opcode >> 13) & 0x7;
15546 fmt = (ctx->opcode >> 10) & 0x3;
15547 switch (fmt) {
15548 case 0x0:
15549 gen_cmp_s(ctx, cond, rt, rs, cc);
15550 break;
15551 case 0x1:
15552 gen_cmp_d(ctx, cond, rt, rs, cc);
15553 break;
15554 case 0x2:
15555 gen_cmp_ps(ctx, cond, rt, rs, cc);
15556 break;
15557 default:
15558 goto pool32f_invalid;
15560 break;
15561 case CMP_CONDN_S:
15562 check_insn(ctx, ISA_MIPS32R6);
15563 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15564 break;
15565 case CMP_CONDN_D:
15566 check_insn(ctx, ISA_MIPS32R6);
15567 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15568 break;
15569 case POOL32FXF:
15570 gen_pool32fxf(ctx, rt, rs);
15571 break;
15572 case 0x00:
15573 /* PLL foo */
15574 switch ((ctx->opcode >> 6) & 0x7) {
15575 case PLL_PS:
15576 mips32_op = OPC_PLL_PS;
15577 goto do_ps;
15578 case PLU_PS:
15579 mips32_op = OPC_PLU_PS;
15580 goto do_ps;
15581 case PUL_PS:
15582 mips32_op = OPC_PUL_PS;
15583 goto do_ps;
15584 case PUU_PS:
15585 mips32_op = OPC_PUU_PS;
15586 goto do_ps;
15587 case CVT_PS_S:
15588 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15589 mips32_op = OPC_CVT_PS_S;
15590 do_ps:
15591 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15592 break;
15593 default:
15594 goto pool32f_invalid;
15596 break;
15597 case MIN_FMT:
15598 check_insn(ctx, ISA_MIPS32R6);
15599 switch ((ctx->opcode >> 9) & 0x3) {
15600 case FMT_SDPS_S:
15601 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15602 break;
15603 case FMT_SDPS_D:
15604 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15605 break;
15606 default:
15607 goto pool32f_invalid;
15609 break;
15610 case 0x08:
15611 /* [LS][WDU]XC1 */
15612 switch ((ctx->opcode >> 6) & 0x7) {
15613 case LWXC1:
15614 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15615 mips32_op = OPC_LWXC1;
15616 goto do_ldst_cp1;
15617 case SWXC1:
15618 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15619 mips32_op = OPC_SWXC1;
15620 goto do_ldst_cp1;
15621 case LDXC1:
15622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15623 mips32_op = OPC_LDXC1;
15624 goto do_ldst_cp1;
15625 case SDXC1:
15626 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15627 mips32_op = OPC_SDXC1;
15628 goto do_ldst_cp1;
15629 case LUXC1:
15630 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15631 mips32_op = OPC_LUXC1;
15632 goto do_ldst_cp1;
15633 case SUXC1:
15634 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15635 mips32_op = OPC_SUXC1;
15636 do_ldst_cp1:
15637 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15638 break;
15639 default:
15640 goto pool32f_invalid;
15642 break;
15643 case MAX_FMT:
15644 check_insn(ctx, ISA_MIPS32R6);
15645 switch ((ctx->opcode >> 9) & 0x3) {
15646 case FMT_SDPS_S:
15647 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15648 break;
15649 case FMT_SDPS_D:
15650 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15651 break;
15652 default:
15653 goto pool32f_invalid;
15655 break;
15656 case 0x18:
15657 /* 3D insns */
15658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15659 fmt = (ctx->opcode >> 9) & 0x3;
15660 switch ((ctx->opcode >> 6) & 0x7) {
15661 case RSQRT2_FMT:
15662 switch (fmt) {
15663 case FMT_SDPS_S:
15664 mips32_op = OPC_RSQRT2_S;
15665 goto do_3d;
15666 case FMT_SDPS_D:
15667 mips32_op = OPC_RSQRT2_D;
15668 goto do_3d;
15669 case FMT_SDPS_PS:
15670 mips32_op = OPC_RSQRT2_PS;
15671 goto do_3d;
15672 default:
15673 goto pool32f_invalid;
15675 break;
15676 case RECIP2_FMT:
15677 switch (fmt) {
15678 case FMT_SDPS_S:
15679 mips32_op = OPC_RECIP2_S;
15680 goto do_3d;
15681 case FMT_SDPS_D:
15682 mips32_op = OPC_RECIP2_D;
15683 goto do_3d;
15684 case FMT_SDPS_PS:
15685 mips32_op = OPC_RECIP2_PS;
15686 goto do_3d;
15687 default:
15688 goto pool32f_invalid;
15690 break;
15691 case ADDR_PS:
15692 mips32_op = OPC_ADDR_PS;
15693 goto do_3d;
15694 case MULR_PS:
15695 mips32_op = OPC_MULR_PS;
15696 do_3d:
15697 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15698 break;
15699 default:
15700 goto pool32f_invalid;
15702 break;
15703 case 0x20:
15704 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15705 cc = (ctx->opcode >> 13) & 0x7;
15706 fmt = (ctx->opcode >> 9) & 0x3;
15707 switch ((ctx->opcode >> 6) & 0x7) {
15708 case MOVF_FMT: /* RINT_FMT */
15709 if (ctx->insn_flags & ISA_MIPS32R6) {
15710 /* RINT_FMT */
15711 switch (fmt) {
15712 case FMT_SDPS_S:
15713 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15714 break;
15715 case FMT_SDPS_D:
15716 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15717 break;
15718 default:
15719 goto pool32f_invalid;
15721 } else {
15722 /* MOVF_FMT */
15723 switch (fmt) {
15724 case FMT_SDPS_S:
15725 gen_movcf_s(ctx, rs, rt, cc, 0);
15726 break;
15727 case FMT_SDPS_D:
15728 gen_movcf_d(ctx, rs, rt, cc, 0);
15729 break;
15730 case FMT_SDPS_PS:
15731 check_ps(ctx);
15732 gen_movcf_ps(ctx, rs, rt, cc, 0);
15733 break;
15734 default:
15735 goto pool32f_invalid;
15738 break;
15739 case MOVT_FMT: /* CLASS_FMT */
15740 if (ctx->insn_flags & ISA_MIPS32R6) {
15741 /* CLASS_FMT */
15742 switch (fmt) {
15743 case FMT_SDPS_S:
15744 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15745 break;
15746 case FMT_SDPS_D:
15747 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15748 break;
15749 default:
15750 goto pool32f_invalid;
15752 } else {
15753 /* MOVT_FMT */
15754 switch (fmt) {
15755 case FMT_SDPS_S:
15756 gen_movcf_s(ctx, rs, rt, cc, 1);
15757 break;
15758 case FMT_SDPS_D:
15759 gen_movcf_d(ctx, rs, rt, cc, 1);
15760 break;
15761 case FMT_SDPS_PS:
15762 check_ps(ctx);
15763 gen_movcf_ps(ctx, rs, rt, cc, 1);
15764 break;
15765 default:
15766 goto pool32f_invalid;
15769 break;
15770 case PREFX:
15771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15772 break;
15773 default:
15774 goto pool32f_invalid;
15776 break;
15777 #define FINSN_3ARG_SDPS(prfx) \
15778 switch ((ctx->opcode >> 8) & 0x3) { \
15779 case FMT_SDPS_S: \
15780 mips32_op = OPC_##prfx##_S; \
15781 goto do_fpop; \
15782 case FMT_SDPS_D: \
15783 mips32_op = OPC_##prfx##_D; \
15784 goto do_fpop; \
15785 case FMT_SDPS_PS: \
15786 check_ps(ctx); \
15787 mips32_op = OPC_##prfx##_PS; \
15788 goto do_fpop; \
15789 default: \
15790 goto pool32f_invalid; \
15792 case MINA_FMT:
15793 check_insn(ctx, ISA_MIPS32R6);
15794 switch ((ctx->opcode >> 9) & 0x3) {
15795 case FMT_SDPS_S:
15796 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15797 break;
15798 case FMT_SDPS_D:
15799 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15800 break;
15801 default:
15802 goto pool32f_invalid;
15804 break;
15805 case MAXA_FMT:
15806 check_insn(ctx, ISA_MIPS32R6);
15807 switch ((ctx->opcode >> 9) & 0x3) {
15808 case FMT_SDPS_S:
15809 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15810 break;
15811 case FMT_SDPS_D:
15812 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15813 break;
15814 default:
15815 goto pool32f_invalid;
15817 break;
15818 case 0x30:
15819 /* regular FP ops */
15820 switch ((ctx->opcode >> 6) & 0x3) {
15821 case ADD_FMT:
15822 FINSN_3ARG_SDPS(ADD);
15823 break;
15824 case SUB_FMT:
15825 FINSN_3ARG_SDPS(SUB);
15826 break;
15827 case MUL_FMT:
15828 FINSN_3ARG_SDPS(MUL);
15829 break;
15830 case DIV_FMT:
15831 fmt = (ctx->opcode >> 8) & 0x3;
15832 if (fmt == 1) {
15833 mips32_op = OPC_DIV_D;
15834 } else if (fmt == 0) {
15835 mips32_op = OPC_DIV_S;
15836 } else {
15837 goto pool32f_invalid;
15839 goto do_fpop;
15840 default:
15841 goto pool32f_invalid;
15843 break;
15844 case 0x38:
15845 /* cmovs */
15846 switch ((ctx->opcode >> 6) & 0x7) {
15847 case MOVN_FMT: /* SELEQZ_FMT */
15848 if (ctx->insn_flags & ISA_MIPS32R6) {
15849 /* SELEQZ_FMT */
15850 switch ((ctx->opcode >> 9) & 0x3) {
15851 case FMT_SDPS_S:
15852 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15853 break;
15854 case FMT_SDPS_D:
15855 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15856 break;
15857 default:
15858 goto pool32f_invalid;
15860 } else {
15861 /* MOVN_FMT */
15862 FINSN_3ARG_SDPS(MOVN);
15864 break;
15865 case MOVN_FMT_04:
15866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15867 FINSN_3ARG_SDPS(MOVN);
15868 break;
15869 case MOVZ_FMT: /* SELNEZ_FMT */
15870 if (ctx->insn_flags & ISA_MIPS32R6) {
15871 /* SELNEZ_FMT */
15872 switch ((ctx->opcode >> 9) & 0x3) {
15873 case FMT_SDPS_S:
15874 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15875 break;
15876 case FMT_SDPS_D:
15877 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15878 break;
15879 default:
15880 goto pool32f_invalid;
15882 } else {
15883 /* MOVZ_FMT */
15884 FINSN_3ARG_SDPS(MOVZ);
15886 break;
15887 case MOVZ_FMT_05:
15888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15889 FINSN_3ARG_SDPS(MOVZ);
15890 break;
15891 case SEL_FMT:
15892 check_insn(ctx, ISA_MIPS32R6);
15893 switch ((ctx->opcode >> 9) & 0x3) {
15894 case FMT_SDPS_S:
15895 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15896 break;
15897 case FMT_SDPS_D:
15898 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15899 break;
15900 default:
15901 goto pool32f_invalid;
15903 break;
15904 case MADDF_FMT:
15905 check_insn(ctx, ISA_MIPS32R6);
15906 switch ((ctx->opcode >> 9) & 0x3) {
15907 case FMT_SDPS_S:
15908 mips32_op = OPC_MADDF_S;
15909 goto do_fpop;
15910 case FMT_SDPS_D:
15911 mips32_op = OPC_MADDF_D;
15912 goto do_fpop;
15913 default:
15914 goto pool32f_invalid;
15916 break;
15917 case MSUBF_FMT:
15918 check_insn(ctx, ISA_MIPS32R6);
15919 switch ((ctx->opcode >> 9) & 0x3) {
15920 case FMT_SDPS_S:
15921 mips32_op = OPC_MSUBF_S;
15922 goto do_fpop;
15923 case FMT_SDPS_D:
15924 mips32_op = OPC_MSUBF_D;
15925 goto do_fpop;
15926 default:
15927 goto pool32f_invalid;
15929 break;
15930 default:
15931 goto pool32f_invalid;
15933 break;
15934 do_fpop:
15935 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15936 break;
15937 default:
15938 pool32f_invalid:
15939 MIPS_INVAL("pool32f");
15940 generate_exception_end(ctx, EXCP_RI);
15941 break;
15943 } else {
15944 generate_exception_err(ctx, EXCP_CpU, 1);
15946 break;
15947 case POOL32I:
15948 minor = (ctx->opcode >> 21) & 0x1f;
15949 switch (minor) {
15950 case BLTZ:
15951 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15952 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15953 break;
15954 case BLTZAL:
15955 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15956 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15957 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15958 break;
15959 case BLTZALS:
15960 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15961 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15962 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15963 break;
15964 case BGEZ:
15965 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15966 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15967 break;
15968 case BGEZAL:
15969 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15970 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15971 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15972 break;
15973 case BGEZALS:
15974 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15975 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15976 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15977 break;
15978 case BLEZ:
15979 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15980 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15981 break;
15982 case BGTZ:
15983 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15984 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
15985 break;
15987 /* Traps */
15988 case TLTI: /* BC1EQZC */
15989 if (ctx->insn_flags & ISA_MIPS32R6) {
15990 /* BC1EQZC */
15991 check_cp1_enabled(ctx);
15992 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15993 } else {
15994 /* TLTI */
15995 mips32_op = OPC_TLTI;
15996 goto do_trapi;
15998 break;
15999 case TGEI: /* BC1NEZC */
16000 if (ctx->insn_flags & ISA_MIPS32R6) {
16001 /* BC1NEZC */
16002 check_cp1_enabled(ctx);
16003 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16004 } else {
16005 /* TGEI */
16006 mips32_op = OPC_TGEI;
16007 goto do_trapi;
16009 break;
16010 case TLTIU:
16011 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16012 mips32_op = OPC_TLTIU;
16013 goto do_trapi;
16014 case TGEIU:
16015 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16016 mips32_op = OPC_TGEIU;
16017 goto do_trapi;
16018 case TNEI: /* SYNCI */
16019 if (ctx->insn_flags & ISA_MIPS32R6) {
16020 /* SYNCI */
16021 /* Break the TB to be able to sync copied instructions
16022 immediately */
16023 ctx->base.is_jmp = DISAS_STOP;
16024 } else {
16025 /* TNEI */
16026 mips32_op = OPC_TNEI;
16027 goto do_trapi;
16029 break;
16030 case TEQI:
16031 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16032 mips32_op = OPC_TEQI;
16033 do_trapi:
16034 gen_trap(ctx, mips32_op, rs, -1, imm);
16035 break;
16037 case BNEZC:
16038 case BEQZC:
16039 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16040 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16041 4, rs, 0, imm << 1, 0);
16042 /* Compact branches don't have a delay slot, so just let
16043 the normal delay slot handling take us to the branch
16044 target. */
16045 break;
16046 case LUI:
16047 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16048 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16049 break;
16050 case SYNCI:
16051 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16052 /* Break the TB to be able to sync copied instructions
16053 immediately */
16054 ctx->base.is_jmp = DISAS_STOP;
16055 break;
16056 case BC2F:
16057 case BC2T:
16058 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16059 /* COP2: Not implemented. */
16060 generate_exception_err(ctx, EXCP_CpU, 2);
16061 break;
16062 case BC1F:
16063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16064 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16065 goto do_cp1branch;
16066 case BC1T:
16067 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16068 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16069 goto do_cp1branch;
16070 case BC1ANY4F:
16071 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16072 mips32_op = OPC_BC1FANY4;
16073 goto do_cp1mips3d;
16074 case BC1ANY4T:
16075 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16076 mips32_op = OPC_BC1TANY4;
16077 do_cp1mips3d:
16078 check_cop1x(ctx);
16079 check_insn(ctx, ASE_MIPS3D);
16080 /* Fall through */
16081 do_cp1branch:
16082 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16083 check_cp1_enabled(ctx);
16084 gen_compute_branch1(ctx, mips32_op,
16085 (ctx->opcode >> 18) & 0x7, imm << 1);
16086 } else {
16087 generate_exception_err(ctx, EXCP_CpU, 1);
16089 break;
16090 case BPOSGE64:
16091 case BPOSGE32:
16092 /* MIPS DSP: not implemented */
16093 /* Fall through */
16094 default:
16095 MIPS_INVAL("pool32i");
16096 generate_exception_end(ctx, EXCP_RI);
16097 break;
16099 break;
16100 case POOL32C:
16101 minor = (ctx->opcode >> 12) & 0xf;
16102 offset = sextract32(ctx->opcode, 0,
16103 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16104 switch (minor) {
16105 case LWL:
16106 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16107 mips32_op = OPC_LWL;
16108 goto do_ld_lr;
16109 case SWL:
16110 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16111 mips32_op = OPC_SWL;
16112 goto do_st_lr;
16113 case LWR:
16114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16115 mips32_op = OPC_LWR;
16116 goto do_ld_lr;
16117 case SWR:
16118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16119 mips32_op = OPC_SWR;
16120 goto do_st_lr;
16121 #if defined(TARGET_MIPS64)
16122 case LDL:
16123 check_insn(ctx, ISA_MIPS3);
16124 check_mips_64(ctx);
16125 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16126 mips32_op = OPC_LDL;
16127 goto do_ld_lr;
16128 case SDL:
16129 check_insn(ctx, ISA_MIPS3);
16130 check_mips_64(ctx);
16131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16132 mips32_op = OPC_SDL;
16133 goto do_st_lr;
16134 case LDR:
16135 check_insn(ctx, ISA_MIPS3);
16136 check_mips_64(ctx);
16137 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16138 mips32_op = OPC_LDR;
16139 goto do_ld_lr;
16140 case SDR:
16141 check_insn(ctx, ISA_MIPS3);
16142 check_mips_64(ctx);
16143 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16144 mips32_op = OPC_SDR;
16145 goto do_st_lr;
16146 case LWU:
16147 check_insn(ctx, ISA_MIPS3);
16148 check_mips_64(ctx);
16149 mips32_op = OPC_LWU;
16150 goto do_ld_lr;
16151 case LLD:
16152 check_insn(ctx, ISA_MIPS3);
16153 check_mips_64(ctx);
16154 mips32_op = OPC_LLD;
16155 goto do_ld_lr;
16156 #endif
16157 case LL:
16158 mips32_op = OPC_LL;
16159 goto do_ld_lr;
16160 do_ld_lr:
16161 gen_ld(ctx, mips32_op, rt, rs, offset);
16162 break;
16163 do_st_lr:
16164 gen_st(ctx, mips32_op, rt, rs, offset);
16165 break;
16166 case SC:
16167 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16168 break;
16169 #if defined(TARGET_MIPS64)
16170 case SCD:
16171 check_insn(ctx, ISA_MIPS3);
16172 check_mips_64(ctx);
16173 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16174 break;
16175 #endif
16176 case LD_EVA:
16177 if (!ctx->eva) {
16178 MIPS_INVAL("pool32c ld-eva");
16179 generate_exception_end(ctx, EXCP_RI);
16180 break;
16182 check_cp0_enabled(ctx);
16184 minor2 = (ctx->opcode >> 9) & 0x7;
16185 offset = sextract32(ctx->opcode, 0, 9);
16186 switch (minor2) {
16187 case LBUE:
16188 mips32_op = OPC_LBUE;
16189 goto do_ld_lr;
16190 case LHUE:
16191 mips32_op = OPC_LHUE;
16192 goto do_ld_lr;
16193 case LWLE:
16194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16195 mips32_op = OPC_LWLE;
16196 goto do_ld_lr;
16197 case LWRE:
16198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16199 mips32_op = OPC_LWRE;
16200 goto do_ld_lr;
16201 case LBE:
16202 mips32_op = OPC_LBE;
16203 goto do_ld_lr;
16204 case LHE:
16205 mips32_op = OPC_LHE;
16206 goto do_ld_lr;
16207 case LLE:
16208 mips32_op = OPC_LLE;
16209 goto do_ld_lr;
16210 case LWE:
16211 mips32_op = OPC_LWE;
16212 goto do_ld_lr;
16214 break;
16215 case ST_EVA:
16216 if (!ctx->eva) {
16217 MIPS_INVAL("pool32c st-eva");
16218 generate_exception_end(ctx, EXCP_RI);
16219 break;
16221 check_cp0_enabled(ctx);
16223 minor2 = (ctx->opcode >> 9) & 0x7;
16224 offset = sextract32(ctx->opcode, 0, 9);
16225 switch (minor2) {
16226 case SWLE:
16227 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16228 mips32_op = OPC_SWLE;
16229 goto do_st_lr;
16230 case SWRE:
16231 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16232 mips32_op = OPC_SWRE;
16233 goto do_st_lr;
16234 case PREFE:
16235 /* Treat as no-op */
16236 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16237 /* hint codes 24-31 are reserved and signal RI */
16238 generate_exception(ctx, EXCP_RI);
16240 break;
16241 case CACHEE:
16242 /* Treat as no-op */
16243 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16244 gen_cache_operation(ctx, rt, rs, offset);
16246 break;
16247 case SBE:
16248 mips32_op = OPC_SBE;
16249 goto do_st_lr;
16250 case SHE:
16251 mips32_op = OPC_SHE;
16252 goto do_st_lr;
16253 case SCE:
16254 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16255 break;
16256 case SWE:
16257 mips32_op = OPC_SWE;
16258 goto do_st_lr;
16260 break;
16261 case PREF:
16262 /* Treat as no-op */
16263 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16264 /* hint codes 24-31 are reserved and signal RI */
16265 generate_exception(ctx, EXCP_RI);
16267 break;
16268 default:
16269 MIPS_INVAL("pool32c");
16270 generate_exception_end(ctx, EXCP_RI);
16271 break;
16273 break;
16274 case ADDI32: /* AUI, LUI */
16275 if (ctx->insn_flags & ISA_MIPS32R6) {
16276 /* AUI, LUI */
16277 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16278 } else {
16279 /* ADDI32 */
16280 mips32_op = OPC_ADDI;
16281 goto do_addi;
16283 break;
16284 case ADDIU32:
16285 mips32_op = OPC_ADDIU;
16286 do_addi:
16287 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16288 break;
16290 /* Logical operations */
16291 case ORI32:
16292 mips32_op = OPC_ORI;
16293 goto do_logici;
16294 case XORI32:
16295 mips32_op = OPC_XORI;
16296 goto do_logici;
16297 case ANDI32:
16298 mips32_op = OPC_ANDI;
16299 do_logici:
16300 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16301 break;
16303 /* Set less than immediate */
16304 case SLTI32:
16305 mips32_op = OPC_SLTI;
16306 goto do_slti;
16307 case SLTIU32:
16308 mips32_op = OPC_SLTIU;
16309 do_slti:
16310 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16311 break;
16312 case JALX32:
16313 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16314 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16315 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16316 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16317 break;
16318 case JALS32: /* BOVC, BEQC, BEQZALC */
16319 if (ctx->insn_flags & ISA_MIPS32R6) {
16320 if (rs >= rt) {
16321 /* BOVC */
16322 mips32_op = OPC_BOVC;
16323 } else if (rs < rt && rs == 0) {
16324 /* BEQZALC */
16325 mips32_op = OPC_BEQZALC;
16326 } else {
16327 /* BEQC */
16328 mips32_op = OPC_BEQC;
16330 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16331 } else {
16332 /* JALS32 */
16333 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16334 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16335 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16337 break;
16338 case BEQ32: /* BC */
16339 if (ctx->insn_flags & ISA_MIPS32R6) {
16340 /* BC */
16341 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16342 sextract32(ctx->opcode << 1, 0, 27));
16343 } else {
16344 /* BEQ32 */
16345 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16347 break;
16348 case BNE32: /* BALC */
16349 if (ctx->insn_flags & ISA_MIPS32R6) {
16350 /* BALC */
16351 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16352 sextract32(ctx->opcode << 1, 0, 27));
16353 } else {
16354 /* BNE32 */
16355 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16357 break;
16358 case J32: /* BGTZC, BLTZC, BLTC */
16359 if (ctx->insn_flags & ISA_MIPS32R6) {
16360 if (rs == 0 && rt != 0) {
16361 /* BGTZC */
16362 mips32_op = OPC_BGTZC;
16363 } else if (rs != 0 && rt != 0 && rs == rt) {
16364 /* BLTZC */
16365 mips32_op = OPC_BLTZC;
16366 } else {
16367 /* BLTC */
16368 mips32_op = OPC_BLTC;
16370 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16371 } else {
16372 /* J32 */
16373 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16374 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16376 break;
16377 case JAL32: /* BLEZC, BGEZC, BGEC */
16378 if (ctx->insn_flags & ISA_MIPS32R6) {
16379 if (rs == 0 && rt != 0) {
16380 /* BLEZC */
16381 mips32_op = OPC_BLEZC;
16382 } else if (rs != 0 && rt != 0 && rs == rt) {
16383 /* BGEZC */
16384 mips32_op = OPC_BGEZC;
16385 } else {
16386 /* BGEC */
16387 mips32_op = OPC_BGEC;
16389 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16390 } else {
16391 /* JAL32 */
16392 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16393 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16394 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16396 break;
16397 /* Floating point (COP1) */
16398 case LWC132:
16399 mips32_op = OPC_LWC1;
16400 goto do_cop1;
16401 case LDC132:
16402 mips32_op = OPC_LDC1;
16403 goto do_cop1;
16404 case SWC132:
16405 mips32_op = OPC_SWC1;
16406 goto do_cop1;
16407 case SDC132:
16408 mips32_op = OPC_SDC1;
16409 do_cop1:
16410 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16411 break;
16412 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16413 if (ctx->insn_flags & ISA_MIPS32R6) {
16414 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16415 switch ((ctx->opcode >> 16) & 0x1f) {
16416 case ADDIUPC_00:
16417 case ADDIUPC_01:
16418 case ADDIUPC_02:
16419 case ADDIUPC_03:
16420 case ADDIUPC_04:
16421 case ADDIUPC_05:
16422 case ADDIUPC_06:
16423 case ADDIUPC_07:
16424 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16425 break;
16426 case AUIPC:
16427 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16428 break;
16429 case ALUIPC:
16430 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16431 break;
16432 case LWPC_08:
16433 case LWPC_09:
16434 case LWPC_0A:
16435 case LWPC_0B:
16436 case LWPC_0C:
16437 case LWPC_0D:
16438 case LWPC_0E:
16439 case LWPC_0F:
16440 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16441 break;
16442 default:
16443 generate_exception(ctx, EXCP_RI);
16444 break;
16446 } else {
16447 /* ADDIUPC */
16448 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16449 offset = SIMM(ctx->opcode, 0, 23) << 2;
16451 gen_addiupc(ctx, reg, offset, 0, 0);
16453 break;
16454 case BNVC: /* BNEC, BNEZALC */
16455 check_insn(ctx, ISA_MIPS32R6);
16456 if (rs >= rt) {
16457 /* BNVC */
16458 mips32_op = OPC_BNVC;
16459 } else if (rs < rt && rs == 0) {
16460 /* BNEZALC */
16461 mips32_op = OPC_BNEZALC;
16462 } else {
16463 /* BNEC */
16464 mips32_op = OPC_BNEC;
16466 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16467 break;
16468 case R6_BNEZC: /* JIALC */
16469 check_insn(ctx, ISA_MIPS32R6);
16470 if (rt != 0) {
16471 /* BNEZC */
16472 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16473 sextract32(ctx->opcode << 1, 0, 22));
16474 } else {
16475 /* JIALC */
16476 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16478 break;
16479 case R6_BEQZC: /* JIC */
16480 check_insn(ctx, ISA_MIPS32R6);
16481 if (rt != 0) {
16482 /* BEQZC */
16483 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16484 sextract32(ctx->opcode << 1, 0, 22));
16485 } else {
16486 /* JIC */
16487 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16489 break;
16490 case BLEZALC: /* BGEZALC, BGEUC */
16491 check_insn(ctx, ISA_MIPS32R6);
16492 if (rs == 0 && rt != 0) {
16493 /* BLEZALC */
16494 mips32_op = OPC_BLEZALC;
16495 } else if (rs != 0 && rt != 0 && rs == rt) {
16496 /* BGEZALC */
16497 mips32_op = OPC_BGEZALC;
16498 } else {
16499 /* BGEUC */
16500 mips32_op = OPC_BGEUC;
16502 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16503 break;
16504 case BGTZALC: /* BLTZALC, BLTUC */
16505 check_insn(ctx, ISA_MIPS32R6);
16506 if (rs == 0 && rt != 0) {
16507 /* BGTZALC */
16508 mips32_op = OPC_BGTZALC;
16509 } else if (rs != 0 && rt != 0 && rs == rt) {
16510 /* BLTZALC */
16511 mips32_op = OPC_BLTZALC;
16512 } else {
16513 /* BLTUC */
16514 mips32_op = OPC_BLTUC;
16516 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16517 break;
16518 /* Loads and stores */
16519 case LB32:
16520 mips32_op = OPC_LB;
16521 goto do_ld;
16522 case LBU32:
16523 mips32_op = OPC_LBU;
16524 goto do_ld;
16525 case LH32:
16526 mips32_op = OPC_LH;
16527 goto do_ld;
16528 case LHU32:
16529 mips32_op = OPC_LHU;
16530 goto do_ld;
16531 case LW32:
16532 mips32_op = OPC_LW;
16533 goto do_ld;
16534 #ifdef TARGET_MIPS64
16535 case LD32:
16536 check_insn(ctx, ISA_MIPS3);
16537 check_mips_64(ctx);
16538 mips32_op = OPC_LD;
16539 goto do_ld;
16540 case SD32:
16541 check_insn(ctx, ISA_MIPS3);
16542 check_mips_64(ctx);
16543 mips32_op = OPC_SD;
16544 goto do_st;
16545 #endif
16546 case SB32:
16547 mips32_op = OPC_SB;
16548 goto do_st;
16549 case SH32:
16550 mips32_op = OPC_SH;
16551 goto do_st;
16552 case SW32:
16553 mips32_op = OPC_SW;
16554 goto do_st;
16555 do_ld:
16556 gen_ld(ctx, mips32_op, rt, rs, imm);
16557 break;
16558 do_st:
16559 gen_st(ctx, mips32_op, rt, rs, imm);
16560 break;
16561 default:
16562 generate_exception_end(ctx, EXCP_RI);
16563 break;
16567 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16569 uint32_t op;
16571 /* make sure instructions are on a halfword boundary */
16572 if (ctx->base.pc_next & 0x1) {
16573 env->CP0_BadVAddr = ctx->base.pc_next;
16574 generate_exception_end(ctx, EXCP_AdEL);
16575 return 2;
16578 op = (ctx->opcode >> 10) & 0x3f;
16579 /* Enforce properly-sized instructions in a delay slot */
16580 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16581 switch (op & 0x7) { /* MSB-3..MSB-5 */
16582 case 0:
16583 /* POOL32A, POOL32B, POOL32I, POOL32C */
16584 case 4:
16585 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16586 case 5:
16587 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16588 case 6:
16589 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16590 case 7:
16591 /* LB32, LH32, LWC132, LDC132, LW32 */
16592 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16593 generate_exception_end(ctx, EXCP_RI);
16594 return 2;
16596 break;
16597 case 1:
16598 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16599 case 2:
16600 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16601 case 3:
16602 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16603 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16604 generate_exception_end(ctx, EXCP_RI);
16605 return 2;
16607 break;
16611 switch (op) {
16612 case POOL16A:
16614 int rd = mmreg(uMIPS_RD(ctx->opcode));
16615 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16616 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16617 uint32_t opc = 0;
16619 switch (ctx->opcode & 0x1) {
16620 case ADDU16:
16621 opc = OPC_ADDU;
16622 break;
16623 case SUBU16:
16624 opc = OPC_SUBU;
16625 break;
16627 if (ctx->insn_flags & ISA_MIPS32R6) {
16628 /* In the Release 6 the register number location in
16629 * the instruction encoding has changed.
16631 gen_arith(ctx, opc, rs1, rd, rs2);
16632 } else {
16633 gen_arith(ctx, opc, rd, rs1, rs2);
16636 break;
16637 case POOL16B:
16639 int rd = mmreg(uMIPS_RD(ctx->opcode));
16640 int rs = mmreg(uMIPS_RS(ctx->opcode));
16641 int amount = (ctx->opcode >> 1) & 0x7;
16642 uint32_t opc = 0;
16643 amount = amount == 0 ? 8 : amount;
16645 switch (ctx->opcode & 0x1) {
16646 case SLL16:
16647 opc = OPC_SLL;
16648 break;
16649 case SRL16:
16650 opc = OPC_SRL;
16651 break;
16654 gen_shift_imm(ctx, opc, rd, rs, amount);
16656 break;
16657 case POOL16C:
16658 if (ctx->insn_flags & ISA_MIPS32R6) {
16659 gen_pool16c_r6_insn(ctx);
16660 } else {
16661 gen_pool16c_insn(ctx);
16663 break;
16664 case LWGP16:
16666 int rd = mmreg(uMIPS_RD(ctx->opcode));
16667 int rb = 28; /* GP */
16668 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16670 gen_ld(ctx, OPC_LW, rd, rb, offset);
16672 break;
16673 case POOL16F:
16674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16675 if (ctx->opcode & 1) {
16676 generate_exception_end(ctx, EXCP_RI);
16677 } else {
16678 /* MOVEP */
16679 int enc_dest = uMIPS_RD(ctx->opcode);
16680 int enc_rt = uMIPS_RS2(ctx->opcode);
16681 int enc_rs = uMIPS_RS1(ctx->opcode);
16682 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16684 break;
16685 case LBU16:
16687 int rd = mmreg(uMIPS_RD(ctx->opcode));
16688 int rb = mmreg(uMIPS_RS(ctx->opcode));
16689 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16690 offset = (offset == 0xf ? -1 : offset);
16692 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16694 break;
16695 case LHU16:
16697 int rd = mmreg(uMIPS_RD(ctx->opcode));
16698 int rb = mmreg(uMIPS_RS(ctx->opcode));
16699 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16701 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16703 break;
16704 case LWSP16:
16706 int rd = (ctx->opcode >> 5) & 0x1f;
16707 int rb = 29; /* SP */
16708 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16710 gen_ld(ctx, OPC_LW, rd, rb, offset);
16712 break;
16713 case LW16:
16715 int rd = mmreg(uMIPS_RD(ctx->opcode));
16716 int rb = mmreg(uMIPS_RS(ctx->opcode));
16717 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16719 gen_ld(ctx, OPC_LW, rd, rb, offset);
16721 break;
16722 case SB16:
16724 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16725 int rb = mmreg(uMIPS_RS(ctx->opcode));
16726 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16728 gen_st(ctx, OPC_SB, rd, rb, offset);
16730 break;
16731 case SH16:
16733 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16734 int rb = mmreg(uMIPS_RS(ctx->opcode));
16735 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16737 gen_st(ctx, OPC_SH, rd, rb, offset);
16739 break;
16740 case SWSP16:
16742 int rd = (ctx->opcode >> 5) & 0x1f;
16743 int rb = 29; /* SP */
16744 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16746 gen_st(ctx, OPC_SW, rd, rb, offset);
16748 break;
16749 case SW16:
16751 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16752 int rb = mmreg(uMIPS_RS(ctx->opcode));
16753 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16755 gen_st(ctx, OPC_SW, rd, rb, offset);
16757 break;
16758 case MOVE16:
16760 int rd = uMIPS_RD5(ctx->opcode);
16761 int rs = uMIPS_RS5(ctx->opcode);
16763 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16765 break;
16766 case ANDI16:
16767 gen_andi16(ctx);
16768 break;
16769 case POOL16D:
16770 switch (ctx->opcode & 0x1) {
16771 case ADDIUS5:
16772 gen_addius5(ctx);
16773 break;
16774 case ADDIUSP:
16775 gen_addiusp(ctx);
16776 break;
16778 break;
16779 case POOL16E:
16780 switch (ctx->opcode & 0x1) {
16781 case ADDIUR2:
16782 gen_addiur2(ctx);
16783 break;
16784 case ADDIUR1SP:
16785 gen_addiur1sp(ctx);
16786 break;
16788 break;
16789 case B16: /* BC16 */
16790 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16791 sextract32(ctx->opcode, 0, 10) << 1,
16792 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16793 break;
16794 case BNEZ16: /* BNEZC16 */
16795 case BEQZ16: /* BEQZC16 */
16796 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16797 mmreg(uMIPS_RD(ctx->opcode)),
16798 0, sextract32(ctx->opcode, 0, 7) << 1,
16799 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16801 break;
16802 case LI16:
16804 int reg = mmreg(uMIPS_RD(ctx->opcode));
16805 int imm = ZIMM(ctx->opcode, 0, 7);
16807 imm = (imm == 0x7f ? -1 : imm);
16808 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16810 break;
16811 case RES_29:
16812 case RES_31:
16813 case RES_39:
16814 generate_exception_end(ctx, EXCP_RI);
16815 break;
16816 default:
16817 decode_micromips32_opc(env, ctx);
16818 return 4;
16821 return 2;
16826 * nanoMIPS opcodes
16830 /* MAJOR, P16, and P32 pools opcodes */
16831 enum {
16832 NM_P_ADDIU = 0x00,
16833 NM_ADDIUPC = 0x01,
16834 NM_MOVE_BALC = 0x02,
16835 NM_P16_MV = 0x04,
16836 NM_LW16 = 0x05,
16837 NM_BC16 = 0x06,
16838 NM_P16_SR = 0x07,
16840 NM_POOL32A = 0x08,
16841 NM_P_BAL = 0x0a,
16842 NM_P16_SHIFT = 0x0c,
16843 NM_LWSP16 = 0x0d,
16844 NM_BALC16 = 0x0e,
16845 NM_P16_4X4 = 0x0f,
16847 NM_P_GP_W = 0x10,
16848 NM_P_GP_BH = 0x11,
16849 NM_P_J = 0x12,
16850 NM_P16C = 0x14,
16851 NM_LWGP16 = 0x15,
16852 NM_P16_LB = 0x17,
16854 NM_P48I = 0x18,
16855 NM_P16_A1 = 0x1c,
16856 NM_LW4X4 = 0x1d,
16857 NM_P16_LH = 0x1f,
16859 NM_P_U12 = 0x20,
16860 NM_P_LS_U12 = 0x21,
16861 NM_P_BR1 = 0x22,
16862 NM_P16_A2 = 0x24,
16863 NM_SW16 = 0x25,
16864 NM_BEQZC16 = 0x26,
16866 NM_POOL32F = 0x28,
16867 NM_P_LS_S9 = 0x29,
16868 NM_P_BR2 = 0x2a,
16870 NM_P16_ADDU = 0x2c,
16871 NM_SWSP16 = 0x2d,
16872 NM_BNEZC16 = 0x2e,
16873 NM_MOVEP = 0x2f,
16875 NM_POOL32S = 0x30,
16876 NM_P_BRI = 0x32,
16877 NM_LI16 = 0x34,
16878 NM_SWGP16 = 0x35,
16879 NM_P16_BR = 0x36,
16881 NM_P_LUI = 0x38,
16882 NM_ANDI16 = 0x3c,
16883 NM_SW4X4 = 0x3d,
16884 NM_MOVEPREV = 0x3f,
16887 /* POOL32A instruction pool */
16888 enum {
16889 NM_POOL32A0 = 0x00,
16890 NM_SPECIAL2 = 0x01,
16891 NM_COP2_1 = 0x02,
16892 NM_UDI = 0x03,
16893 NM_POOL32A5 = 0x05,
16894 NM_POOL32A7 = 0x07,
16897 /* P.GP.W instruction pool */
16898 enum {
16899 NM_ADDIUGP_W = 0x00,
16900 NM_LWGP = 0x02,
16901 NM_SWGP = 0x03,
16904 /* P48I instruction pool */
16905 enum {
16906 NM_LI48 = 0x00,
16907 NM_ADDIU48 = 0x01,
16908 NM_ADDIUGP48 = 0x02,
16909 NM_ADDIUPC48 = 0x03,
16910 NM_LWPC48 = 0x0b,
16911 NM_SWPC48 = 0x0f,
16914 /* P.U12 instruction pool */
16915 enum {
16916 NM_ORI = 0x00,
16917 NM_XORI = 0x01,
16918 NM_ANDI = 0x02,
16919 NM_P_SR = 0x03,
16920 NM_SLTI = 0x04,
16921 NM_SLTIU = 0x05,
16922 NM_SEQI = 0x06,
16923 NM_ADDIUNEG = 0x08,
16924 NM_P_SHIFT = 0x0c,
16925 NM_P_ROTX = 0x0d,
16926 NM_P_INS = 0x0e,
16927 NM_P_EXT = 0x0f,
16930 /* POOL32F instruction pool */
16931 enum {
16932 NM_POOL32F_0 = 0x00,
16933 NM_POOL32F_3 = 0x03,
16934 NM_POOL32F_5 = 0x05,
16937 /* POOL32S instruction pool */
16938 enum {
16939 NM_POOL32S_0 = 0x00,
16940 NM_POOL32S_4 = 0x04,
16943 /* P.LUI instruction pool */
16944 enum {
16945 NM_LUI = 0x00,
16946 NM_ALUIPC = 0x01,
16949 /* P.GP.BH instruction pool */
16950 enum {
16951 NM_LBGP = 0x00,
16952 NM_SBGP = 0x01,
16953 NM_LBUGP = 0x02,
16954 NM_ADDIUGP_B = 0x03,
16955 NM_P_GP_LH = 0x04,
16956 NM_P_GP_SH = 0x05,
16957 NM_P_GP_CP1 = 0x06,
16960 /* P.LS.U12 instruction pool */
16961 enum {
16962 NM_LB = 0x00,
16963 NM_SB = 0x01,
16964 NM_LBU = 0x02,
16965 NM_P_PREFU12 = 0x03,
16966 NM_LH = 0x04,
16967 NM_SH = 0x05,
16968 NM_LHU = 0x06,
16969 NM_LWU = 0x07,
16970 NM_LW = 0x08,
16971 NM_SW = 0x09,
16972 NM_LWC1 = 0x0a,
16973 NM_SWC1 = 0x0b,
16974 NM_LDC1 = 0x0e,
16975 NM_SDC1 = 0x0f,
16978 /* P.LS.S9 instruction pool */
16979 enum {
16980 NM_P_LS_S0 = 0x00,
16981 NM_P_LS_S1 = 0x01,
16982 NM_P_LS_E0 = 0x02,
16983 NM_P_LS_WM = 0x04,
16984 NM_P_LS_UAWM = 0x05,
16987 /* P.BAL instruction pool */
16988 enum {
16989 NM_BC = 0x00,
16990 NM_BALC = 0x01,
16993 /* P.J instruction pool */
16994 enum {
16995 NM_JALRC = 0x00,
16996 NM_JALRC_HB = 0x01,
16997 NM_P_BALRSC = 0x08,
17000 /* P.BR1 instruction pool */
17001 enum {
17002 NM_BEQC = 0x00,
17003 NM_P_BR3A = 0x01,
17004 NM_BGEC = 0x02,
17005 NM_BGEUC = 0x03,
17008 /* P.BR2 instruction pool */
17009 enum {
17010 NM_BNEC = 0x00,
17011 NM_BLTC = 0x02,
17012 NM_BLTUC = 0x03,
17015 /* P.BRI instruction pool */
17016 enum {
17017 NM_BEQIC = 0x00,
17018 NM_BBEQZC = 0x01,
17019 NM_BGEIC = 0x02,
17020 NM_BGEIUC = 0x03,
17021 NM_BNEIC = 0x04,
17022 NM_BBNEZC = 0x05,
17023 NM_BLTIC = 0x06,
17024 NM_BLTIUC = 0x07,
17027 /* P16.SHIFT instruction pool */
17028 enum {
17029 NM_SLL16 = 0x00,
17030 NM_SRL16 = 0x01,
17033 /* POOL16C instruction pool */
17034 enum {
17035 NM_POOL16C_0 = 0x00,
17036 NM_LWXS16 = 0x01,
17039 /* P16.A1 instruction pool */
17040 enum {
17041 NM_ADDIUR1SP = 0x01,
17044 /* P16.A2 instruction pool */
17045 enum {
17046 NM_ADDIUR2 = 0x00,
17047 NM_P_ADDIURS5 = 0x01,
17050 /* P16.ADDU instruction pool */
17051 enum {
17052 NM_ADDU16 = 0x00,
17053 NM_SUBU16 = 0x01,
17056 /* P16.SR instruction pool */
17057 enum {
17058 NM_SAVE16 = 0x00,
17059 NM_RESTORE_JRC16 = 0x01,
17062 /* P16.4X4 instruction pool */
17063 enum {
17064 NM_ADDU4X4 = 0x00,
17065 NM_MUL4X4 = 0x01,
17068 /* P16.LB instruction pool */
17069 enum {
17070 NM_LB16 = 0x00,
17071 NM_SB16 = 0x01,
17072 NM_LBU16 = 0x02,
17075 /* P16.LH instruction pool */
17076 enum {
17077 NM_LH16 = 0x00,
17078 NM_SH16 = 0x01,
17079 NM_LHU16 = 0x02,
17082 /* P.RI instruction pool */
17083 enum {
17084 NM_SIGRIE = 0x00,
17085 NM_P_SYSCALL = 0x01,
17086 NM_BREAK = 0x02,
17087 NM_SDBBP = 0x03,
17090 /* POOL32A0 instruction pool */
17091 enum {
17092 NM_P_TRAP = 0x00,
17093 NM_SEB = 0x01,
17094 NM_SLLV = 0x02,
17095 NM_MUL = 0x03,
17096 NM_MFC0 = 0x06,
17097 NM_MFHC0 = 0x07,
17098 NM_SEH = 0x09,
17099 NM_SRLV = 0x0a,
17100 NM_MUH = 0x0b,
17101 NM_MTC0 = 0x0e,
17102 NM_MTHC0 = 0x0f,
17103 NM_SRAV = 0x12,
17104 NM_MULU = 0x13,
17105 NM_ROTRV = 0x1a,
17106 NM_MUHU = 0x1b,
17107 NM_ADD = 0x22,
17108 NM_DIV = 0x23,
17109 NM_ADDU = 0x2a,
17110 NM_MOD = 0x2b,
17111 NM_SUB = 0x32,
17112 NM_DIVU = 0x33,
17113 NM_RDHWR = 0x38,
17114 NM_SUBU = 0x3a,
17115 NM_MODU = 0x3b,
17116 NM_P_CMOVE = 0x42,
17117 NM_FORK = 0x45,
17118 NM_MFTR = 0x46,
17119 NM_MFHTR = 0x47,
17120 NM_AND = 0x4a,
17121 NM_YIELD = 0x4d,
17122 NM_MTTR = 0x4e,
17123 NM_MTHTR = 0x4f,
17124 NM_OR = 0x52,
17125 NM_D_E_MT_VPE = 0x56,
17126 NM_NOR = 0x5a,
17127 NM_XOR = 0x62,
17128 NM_SLT = 0x6a,
17129 NM_P_SLTU = 0x72,
17130 NM_SOV = 0x7a,
17133 /* POOL32A5 instruction pool */
17134 enum {
17135 NM_CMP_EQ_PH = 0x00,
17136 NM_CMP_LT_PH = 0x08,
17137 NM_CMP_LE_PH = 0x10,
17138 NM_CMPGU_EQ_QB = 0x18,
17139 NM_CMPGU_LT_QB = 0x20,
17140 NM_CMPGU_LE_QB = 0x28,
17141 NM_CMPGDU_EQ_QB = 0x30,
17142 NM_CMPGDU_LT_QB = 0x38,
17143 NM_CMPGDU_LE_QB = 0x40,
17144 NM_CMPU_EQ_QB = 0x48,
17145 NM_CMPU_LT_QB = 0x50,
17146 NM_CMPU_LE_QB = 0x58,
17147 NM_ADDQ_S_W = 0x60,
17148 NM_SUBQ_S_W = 0x68,
17149 NM_ADDSC = 0x70,
17150 NM_ADDWC = 0x78,
17152 NM_ADDQ_S_PH = 0x01,
17153 NM_ADDQH_R_PH = 0x09,
17154 NM_ADDQH_R_W = 0x11,
17155 NM_ADDU_S_QB = 0x19,
17156 NM_ADDU_S_PH = 0x21,
17157 NM_ADDUH_R_QB = 0x29,
17158 NM_SHRAV_R_PH = 0x31,
17159 NM_SHRAV_R_QB = 0x39,
17160 NM_SUBQ_S_PH = 0x41,
17161 NM_SUBQH_R_PH = 0x49,
17162 NM_SUBQH_R_W = 0x51,
17163 NM_SUBU_S_QB = 0x59,
17164 NM_SUBU_S_PH = 0x61,
17165 NM_SUBUH_R_QB = 0x69,
17166 NM_SHLLV_S_PH = 0x71,
17167 NM_PRECR_SRA_R_PH_W = 0x79,
17169 NM_MULEU_S_PH_QBL = 0x12,
17170 NM_MULEU_S_PH_QBR = 0x1a,
17171 NM_MULQ_RS_PH = 0x22,
17172 NM_MULQ_S_PH = 0x2a,
17173 NM_MULQ_RS_W = 0x32,
17174 NM_MULQ_S_W = 0x3a,
17175 NM_APPEND = 0x42,
17176 NM_MODSUB = 0x52,
17177 NM_SHRAV_R_W = 0x5a,
17178 NM_SHRLV_PH = 0x62,
17179 NM_SHRLV_QB = 0x6a,
17180 NM_SHLLV_QB = 0x72,
17181 NM_SHLLV_S_W = 0x7a,
17183 NM_SHILO = 0x03,
17185 NM_MULEQ_S_W_PHL = 0x04,
17186 NM_MULEQ_S_W_PHR = 0x0c,
17188 NM_MUL_S_PH = 0x05,
17189 NM_PRECR_QB_PH = 0x0d,
17190 NM_PRECRQ_QB_PH = 0x15,
17191 NM_PRECRQ_PH_W = 0x1d,
17192 NM_PRECRQ_RS_PH_W = 0x25,
17193 NM_PRECRQU_S_QB_PH = 0x2d,
17194 NM_PACKRL_PH = 0x35,
17195 NM_PICK_QB = 0x3d,
17196 NM_PICK_PH = 0x45,
17198 NM_SHRA_R_W = 0x5e,
17199 NM_SHRA_R_PH = 0x66,
17200 NM_SHLL_S_PH = 0x76,
17201 NM_SHLL_S_W = 0x7e,
17203 NM_REPL_PH = 0x07
17206 /* POOL32A7 instruction pool */
17207 enum {
17208 NM_P_LSX = 0x00,
17209 NM_LSA = 0x01,
17210 NM_EXTW = 0x03,
17211 NM_POOL32AXF = 0x07,
17214 /* P.SR instruction pool */
17215 enum {
17216 NM_PP_SR = 0x00,
17217 NM_P_SR_F = 0x01,
17220 /* P.SHIFT instruction pool */
17221 enum {
17222 NM_P_SLL = 0x00,
17223 NM_SRL = 0x02,
17224 NM_SRA = 0x04,
17225 NM_ROTR = 0x06,
17228 /* P.ROTX instruction pool */
17229 enum {
17230 NM_ROTX = 0x00,
17233 /* P.INS instruction pool */
17234 enum {
17235 NM_INS = 0x00,
17238 /* P.EXT instruction pool */
17239 enum {
17240 NM_EXT = 0x00,
17243 /* POOL32F_0 (fmt) instruction pool */
17244 enum {
17245 NM_RINT_S = 0x04,
17246 NM_RINT_D = 0x44,
17247 NM_ADD_S = 0x06,
17248 NM_SELEQZ_S = 0x07,
17249 NM_SELEQZ_D = 0x47,
17250 NM_CLASS_S = 0x0c,
17251 NM_CLASS_D = 0x4c,
17252 NM_SUB_S = 0x0e,
17253 NM_SELNEZ_S = 0x0f,
17254 NM_SELNEZ_D = 0x4f,
17255 NM_MUL_S = 0x16,
17256 NM_SEL_S = 0x17,
17257 NM_SEL_D = 0x57,
17258 NM_DIV_S = 0x1e,
17259 NM_ADD_D = 0x26,
17260 NM_SUB_D = 0x2e,
17261 NM_MUL_D = 0x36,
17262 NM_MADDF_S = 0x37,
17263 NM_MADDF_D = 0x77,
17264 NM_DIV_D = 0x3e,
17265 NM_MSUBF_S = 0x3f,
17266 NM_MSUBF_D = 0x7f,
17269 /* POOL32F_3 instruction pool */
17270 enum {
17271 NM_MIN_FMT = 0x00,
17272 NM_MAX_FMT = 0x01,
17273 NM_MINA_FMT = 0x04,
17274 NM_MAXA_FMT = 0x05,
17275 NM_POOL32FXF = 0x07,
17278 /* POOL32F_5 instruction pool */
17279 enum {
17280 NM_CMP_CONDN_S = 0x00,
17281 NM_CMP_CONDN_D = 0x02,
17284 /* P.GP.LH instruction pool */
17285 enum {
17286 NM_LHGP = 0x00,
17287 NM_LHUGP = 0x01,
17290 /* P.GP.SH instruction pool */
17291 enum {
17292 NM_SHGP = 0x00,
17295 /* P.GP.CP1 instruction pool */
17296 enum {
17297 NM_LWC1GP = 0x00,
17298 NM_SWC1GP = 0x01,
17299 NM_LDC1GP = 0x02,
17300 NM_SDC1GP = 0x03,
17303 /* P.LS.S0 instruction pool */
17304 enum {
17305 NM_LBS9 = 0x00,
17306 NM_LHS9 = 0x04,
17307 NM_LWS9 = 0x08,
17308 NM_LDS9 = 0x0c,
17310 NM_SBS9 = 0x01,
17311 NM_SHS9 = 0x05,
17312 NM_SWS9 = 0x09,
17313 NM_SDS9 = 0x0d,
17315 NM_LBUS9 = 0x02,
17316 NM_LHUS9 = 0x06,
17317 NM_LWC1S9 = 0x0a,
17318 NM_LDC1S9 = 0x0e,
17320 NM_P_PREFS9 = 0x03,
17321 NM_LWUS9 = 0x07,
17322 NM_SWC1S9 = 0x0b,
17323 NM_SDC1S9 = 0x0f,
17326 /* P.LS.S1 instruction pool */
17327 enum {
17328 NM_ASET_ACLR = 0x02,
17329 NM_UALH = 0x04,
17330 NM_UASH = 0x05,
17331 NM_CACHE = 0x07,
17332 NM_P_LL = 0x0a,
17333 NM_P_SC = 0x0b,
17336 /* P.LS.E0 instruction pool */
17337 enum {
17338 NM_LBE = 0x00,
17339 NM_SBE = 0x01,
17340 NM_LBUE = 0x02,
17341 NM_P_PREFE = 0x03,
17342 NM_LHE = 0x04,
17343 NM_SHE = 0x05,
17344 NM_LHUE = 0x06,
17345 NM_CACHEE = 0x07,
17346 NM_LWE = 0x08,
17347 NM_SWE = 0x09,
17348 NM_P_LLE = 0x0a,
17349 NM_P_SCE = 0x0b,
17352 /* P.PREFE instruction pool */
17353 enum {
17354 NM_SYNCIE = 0x00,
17355 NM_PREFE = 0x01,
17358 /* P.LLE instruction pool */
17359 enum {
17360 NM_LLE = 0x00,
17361 NM_LLWPE = 0x01,
17364 /* P.SCE instruction pool */
17365 enum {
17366 NM_SCE = 0x00,
17367 NM_SCWPE = 0x01,
17370 /* P.LS.WM instruction pool */
17371 enum {
17372 NM_LWM = 0x00,
17373 NM_SWM = 0x01,
17376 /* P.LS.UAWM instruction pool */
17377 enum {
17378 NM_UALWM = 0x00,
17379 NM_UASWM = 0x01,
17382 /* P.BR3A instruction pool */
17383 enum {
17384 NM_BC1EQZC = 0x00,
17385 NM_BC1NEZC = 0x01,
17386 NM_BC2EQZC = 0x02,
17387 NM_BC2NEZC = 0x03,
17388 NM_BPOSGE32C = 0x04,
17391 /* P16.RI instruction pool */
17392 enum {
17393 NM_P16_SYSCALL = 0x01,
17394 NM_BREAK16 = 0x02,
17395 NM_SDBBP16 = 0x03,
17398 /* POOL16C_0 instruction pool */
17399 enum {
17400 NM_POOL16C_00 = 0x00,
17403 /* P16.JRC instruction pool */
17404 enum {
17405 NM_JRC = 0x00,
17406 NM_JALRC16 = 0x01,
17409 /* P.SYSCALL instruction pool */
17410 enum {
17411 NM_SYSCALL = 0x00,
17412 NM_HYPCALL = 0x01,
17415 /* P.TRAP instruction pool */
17416 enum {
17417 NM_TEQ = 0x00,
17418 NM_TNE = 0x01,
17421 /* P.CMOVE instruction pool */
17422 enum {
17423 NM_MOVZ = 0x00,
17424 NM_MOVN = 0x01,
17427 /* POOL32Axf instruction pool */
17428 enum {
17429 NM_POOL32AXF_1 = 0x01,
17430 NM_POOL32AXF_2 = 0x02,
17431 NM_POOL32AXF_4 = 0x04,
17432 NM_POOL32AXF_5 = 0x05,
17433 NM_POOL32AXF_7 = 0x07,
17436 /* POOL32Axf_1 instruction pool */
17437 enum {
17438 NM_POOL32AXF_1_0 = 0x00,
17439 NM_POOL32AXF_1_1 = 0x01,
17440 NM_POOL32AXF_1_3 = 0x03,
17441 NM_POOL32AXF_1_4 = 0x04,
17442 NM_POOL32AXF_1_5 = 0x05,
17443 NM_POOL32AXF_1_7 = 0x07,
17446 /* POOL32Axf_2 instruction pool */
17447 enum {
17448 NM_POOL32AXF_2_0_7 = 0x00,
17449 NM_POOL32AXF_2_8_15 = 0x01,
17450 NM_POOL32AXF_2_16_23 = 0x02,
17451 NM_POOL32AXF_2_24_31 = 0x03,
17454 /* POOL32Axf_7 instruction pool */
17455 enum {
17456 NM_SHRA_R_QB = 0x0,
17457 NM_SHRL_PH = 0x1,
17458 NM_REPL_QB = 0x2,
17461 /* POOL32Axf_1_0 instruction pool */
17462 enum {
17463 NM_MFHI = 0x0,
17464 NM_MFLO = 0x1,
17465 NM_MTHI = 0x2,
17466 NM_MTLO = 0x3,
17469 /* POOL32Axf_1_1 instruction pool */
17470 enum {
17471 NM_MTHLIP = 0x0,
17472 NM_SHILOV = 0x1,
17475 /* POOL32Axf_1_3 instruction pool */
17476 enum {
17477 NM_RDDSP = 0x0,
17478 NM_WRDSP = 0x1,
17479 NM_EXTP = 0x2,
17480 NM_EXTPDP = 0x3,
17483 /* POOL32Axf_1_4 instruction pool */
17484 enum {
17485 NM_SHLL_QB = 0x0,
17486 NM_SHRL_QB = 0x1,
17489 /* POOL32Axf_1_5 instruction pool */
17490 enum {
17491 NM_MAQ_S_W_PHR = 0x0,
17492 NM_MAQ_S_W_PHL = 0x1,
17493 NM_MAQ_SA_W_PHR = 0x2,
17494 NM_MAQ_SA_W_PHL = 0x3,
17497 /* POOL32Axf_1_7 instruction pool */
17498 enum {
17499 NM_EXTR_W = 0x0,
17500 NM_EXTR_R_W = 0x1,
17501 NM_EXTR_RS_W = 0x2,
17502 NM_EXTR_S_H = 0x3,
17505 /* POOL32Axf_2_0_7 instruction pool */
17506 enum {
17507 NM_DPA_W_PH = 0x0,
17508 NM_DPAQ_S_W_PH = 0x1,
17509 NM_DPS_W_PH = 0x2,
17510 NM_DPSQ_S_W_PH = 0x3,
17511 NM_BALIGN = 0x4,
17512 NM_MADD = 0x5,
17513 NM_MULT = 0x6,
17514 NM_EXTRV_W = 0x7,
17517 /* POOL32Axf_2_8_15 instruction pool */
17518 enum {
17519 NM_DPAX_W_PH = 0x0,
17520 NM_DPAQ_SA_L_W = 0x1,
17521 NM_DPSX_W_PH = 0x2,
17522 NM_DPSQ_SA_L_W = 0x3,
17523 NM_MADDU = 0x5,
17524 NM_MULTU = 0x6,
17525 NM_EXTRV_R_W = 0x7,
17528 /* POOL32Axf_2_16_23 instruction pool */
17529 enum {
17530 NM_DPAU_H_QBL = 0x0,
17531 NM_DPAQX_S_W_PH = 0x1,
17532 NM_DPSU_H_QBL = 0x2,
17533 NM_DPSQX_S_W_PH = 0x3,
17534 NM_EXTPV = 0x4,
17535 NM_MSUB = 0x5,
17536 NM_MULSA_W_PH = 0x6,
17537 NM_EXTRV_RS_W = 0x7,
17540 /* POOL32Axf_2_24_31 instruction pool */
17541 enum {
17542 NM_DPAU_H_QBR = 0x0,
17543 NM_DPAQX_SA_W_PH = 0x1,
17544 NM_DPSU_H_QBR = 0x2,
17545 NM_DPSQX_SA_W_PH = 0x3,
17546 NM_EXTPDPV = 0x4,
17547 NM_MSUBU = 0x5,
17548 NM_MULSAQ_S_W_PH = 0x6,
17549 NM_EXTRV_S_H = 0x7,
17552 /* POOL32Axf_{4, 5} instruction pool */
17553 enum {
17554 NM_CLO = 0x25,
17555 NM_CLZ = 0x2d,
17557 NM_TLBP = 0x01,
17558 NM_TLBR = 0x09,
17559 NM_TLBWI = 0x11,
17560 NM_TLBWR = 0x19,
17561 NM_TLBINV = 0x03,
17562 NM_TLBINVF = 0x0b,
17563 NM_DI = 0x23,
17564 NM_EI = 0x2b,
17565 NM_RDPGPR = 0x70,
17566 NM_WRPGPR = 0x78,
17567 NM_WAIT = 0x61,
17568 NM_DERET = 0x71,
17569 NM_ERETX = 0x79,
17571 /* nanoMIPS DSP instructions */
17572 NM_ABSQ_S_QB = 0x00,
17573 NM_ABSQ_S_PH = 0x08,
17574 NM_ABSQ_S_W = 0x10,
17575 NM_PRECEQ_W_PHL = 0x28,
17576 NM_PRECEQ_W_PHR = 0x30,
17577 NM_PRECEQU_PH_QBL = 0x38,
17578 NM_PRECEQU_PH_QBR = 0x48,
17579 NM_PRECEU_PH_QBL = 0x58,
17580 NM_PRECEU_PH_QBR = 0x68,
17581 NM_PRECEQU_PH_QBLA = 0x39,
17582 NM_PRECEQU_PH_QBRA = 0x49,
17583 NM_PRECEU_PH_QBLA = 0x59,
17584 NM_PRECEU_PH_QBRA = 0x69,
17585 NM_REPLV_PH = 0x01,
17586 NM_REPLV_QB = 0x09,
17587 NM_BITREV = 0x18,
17588 NM_INSV = 0x20,
17589 NM_RADDU_W_QB = 0x78,
17591 NM_BITSWAP = 0x05,
17592 NM_WSBH = 0x3d,
17595 /* PP.SR instruction pool */
17596 enum {
17597 NM_SAVE = 0x00,
17598 NM_RESTORE = 0x02,
17599 NM_RESTORE_JRC = 0x03,
17602 /* P.SR.F instruction pool */
17603 enum {
17604 NM_SAVEF = 0x00,
17605 NM_RESTOREF = 0x01,
17608 /* P16.SYSCALL instruction pool */
17609 enum {
17610 NM_SYSCALL16 = 0x00,
17611 NM_HYPCALL16 = 0x01,
17614 /* POOL16C_00 instruction pool */
17615 enum {
17616 NM_NOT16 = 0x00,
17617 NM_XOR16 = 0x01,
17618 NM_AND16 = 0x02,
17619 NM_OR16 = 0x03,
17622 /* PP.LSX and PP.LSXS instruction pool */
17623 enum {
17624 NM_LBX = 0x00,
17625 NM_LHX = 0x04,
17626 NM_LWX = 0x08,
17627 NM_LDX = 0x0c,
17629 NM_SBX = 0x01,
17630 NM_SHX = 0x05,
17631 NM_SWX = 0x09,
17632 NM_SDX = 0x0d,
17634 NM_LBUX = 0x02,
17635 NM_LHUX = 0x06,
17636 NM_LWC1X = 0x0a,
17637 NM_LDC1X = 0x0e,
17639 NM_LWUX = 0x07,
17640 NM_SWC1X = 0x0b,
17641 NM_SDC1X = 0x0f,
17643 NM_LHXS = 0x04,
17644 NM_LWXS = 0x08,
17645 NM_LDXS = 0x0c,
17647 NM_SHXS = 0x05,
17648 NM_SWXS = 0x09,
17649 NM_SDXS = 0x0d,
17651 NM_LHUXS = 0x06,
17652 NM_LWC1XS = 0x0a,
17653 NM_LDC1XS = 0x0e,
17655 NM_LWUXS = 0x07,
17656 NM_SWC1XS = 0x0b,
17657 NM_SDC1XS = 0x0f,
17660 /* ERETx instruction pool */
17661 enum {
17662 NM_ERET = 0x00,
17663 NM_ERETNC = 0x01,
17666 /* POOL32FxF_{0, 1} insturction pool */
17667 enum {
17668 NM_CFC1 = 0x40,
17669 NM_CTC1 = 0x60,
17670 NM_MFC1 = 0x80,
17671 NM_MTC1 = 0xa0,
17672 NM_MFHC1 = 0xc0,
17673 NM_MTHC1 = 0xe0,
17675 NM_CVT_S_PL = 0x84,
17676 NM_CVT_S_PU = 0xa4,
17678 NM_CVT_L_S = 0x004,
17679 NM_CVT_L_D = 0x104,
17680 NM_CVT_W_S = 0x024,
17681 NM_CVT_W_D = 0x124,
17683 NM_RSQRT_S = 0x008,
17684 NM_RSQRT_D = 0x108,
17686 NM_SQRT_S = 0x028,
17687 NM_SQRT_D = 0x128,
17689 NM_RECIP_S = 0x048,
17690 NM_RECIP_D = 0x148,
17692 NM_FLOOR_L_S = 0x00c,
17693 NM_FLOOR_L_D = 0x10c,
17695 NM_FLOOR_W_S = 0x02c,
17696 NM_FLOOR_W_D = 0x12c,
17698 NM_CEIL_L_S = 0x04c,
17699 NM_CEIL_L_D = 0x14c,
17700 NM_CEIL_W_S = 0x06c,
17701 NM_CEIL_W_D = 0x16c,
17702 NM_TRUNC_L_S = 0x08c,
17703 NM_TRUNC_L_D = 0x18c,
17704 NM_TRUNC_W_S = 0x0ac,
17705 NM_TRUNC_W_D = 0x1ac,
17706 NM_ROUND_L_S = 0x0cc,
17707 NM_ROUND_L_D = 0x1cc,
17708 NM_ROUND_W_S = 0x0ec,
17709 NM_ROUND_W_D = 0x1ec,
17711 NM_MOV_S = 0x01,
17712 NM_MOV_D = 0x81,
17713 NM_ABS_S = 0x0d,
17714 NM_ABS_D = 0x8d,
17715 NM_NEG_S = 0x2d,
17716 NM_NEG_D = 0xad,
17717 NM_CVT_D_S = 0x04d,
17718 NM_CVT_D_W = 0x0cd,
17719 NM_CVT_D_L = 0x14d,
17720 NM_CVT_S_D = 0x06d,
17721 NM_CVT_S_W = 0x0ed,
17722 NM_CVT_S_L = 0x16d,
17725 /* P.LL instruction pool */
17726 enum {
17727 NM_LL = 0x00,
17728 NM_LLWP = 0x01,
17731 /* P.SC instruction pool */
17732 enum {
17733 NM_SC = 0x00,
17734 NM_SCWP = 0x01,
17737 /* P.DVP instruction pool */
17738 enum {
17739 NM_DVP = 0x00,
17740 NM_EVP = 0x01,
17746 * nanoMIPS decoding engine
17751 /* extraction utilities */
17753 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17754 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17755 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17756 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17757 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17758 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17760 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17761 static inline int decode_gpr_gpr3(int r)
17763 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17765 return map[r & 0x7];
17768 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17769 static inline int decode_gpr_gpr3_src_store(int r)
17771 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17773 return map[r & 0x7];
17776 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17777 static inline int decode_gpr_gpr4(int r)
17779 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17780 16, 17, 18, 19, 20, 21, 22, 23 };
17782 return map[r & 0xf];
17785 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17786 static inline int decode_gpr_gpr4_zero(int r)
17788 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17789 16, 17, 18, 19, 20, 21, 22, 23 };
17791 return map[r & 0xf];
17795 /* extraction utilities */
17797 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17798 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17799 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17800 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17801 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17802 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17805 static void gen_adjust_sp(DisasContext *ctx, int u)
17807 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17810 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17811 uint8_t gp, uint16_t u)
17813 int counter = 0;
17814 TCGv va = tcg_temp_new();
17815 TCGv t0 = tcg_temp_new();
17817 while (counter != count) {
17818 bool use_gp = gp && (counter == count - 1);
17819 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17820 int this_offset = -((counter + 1) << 2);
17821 gen_base_offset_addr(ctx, va, 29, this_offset);
17822 gen_load_gpr(t0, this_rt);
17823 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17824 (MO_TEUL | ctx->default_tcg_memop_mask));
17825 counter++;
17828 /* adjust stack pointer */
17829 gen_adjust_sp(ctx, -u);
17831 tcg_temp_free(t0);
17832 tcg_temp_free(va);
17835 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17836 uint8_t gp, uint16_t u)
17838 int counter = 0;
17839 TCGv va = tcg_temp_new();
17840 TCGv t0 = tcg_temp_new();
17842 while (counter != count) {
17843 bool use_gp = gp && (counter == count - 1);
17844 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17845 int this_offset = u - ((counter + 1) << 2);
17846 gen_base_offset_addr(ctx, va, 29, this_offset);
17847 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17848 ctx->default_tcg_memop_mask);
17849 tcg_gen_ext32s_tl(t0, t0);
17850 gen_store_gpr(t0, this_rt);
17851 counter++;
17854 /* adjust stack pointer */
17855 gen_adjust_sp(ctx, u);
17857 tcg_temp_free(t0);
17858 tcg_temp_free(va);
17861 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17863 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
17864 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
17866 switch (extract32(ctx->opcode, 2, 2)) {
17867 case NM_NOT16:
17868 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17869 break;
17870 case NM_AND16:
17871 gen_logic(ctx, OPC_AND, rt, rt, rs);
17872 break;
17873 case NM_XOR16:
17874 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17875 break;
17876 case NM_OR16:
17877 gen_logic(ctx, OPC_OR, rt, rt, rs);
17878 break;
17882 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17884 int rt = extract32(ctx->opcode, 21, 5);
17885 int rs = extract32(ctx->opcode, 16, 5);
17886 int rd = extract32(ctx->opcode, 11, 5);
17888 switch (extract32(ctx->opcode, 3, 7)) {
17889 case NM_P_TRAP:
17890 switch (extract32(ctx->opcode, 10, 1)) {
17891 case NM_TEQ:
17892 check_nms(ctx);
17893 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17894 break;
17895 case NM_TNE:
17896 check_nms(ctx);
17897 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17898 break;
17900 break;
17901 case NM_RDHWR:
17902 check_nms(ctx);
17903 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17904 break;
17905 case NM_SEB:
17906 check_nms(ctx);
17907 gen_bshfl(ctx, OPC_SEB, rs, rt);
17908 break;
17909 case NM_SEH:
17910 gen_bshfl(ctx, OPC_SEH, rs, rt);
17911 break;
17912 case NM_SLLV:
17913 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17914 break;
17915 case NM_SRLV:
17916 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17917 break;
17918 case NM_SRAV:
17919 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17920 break;
17921 case NM_ROTRV:
17922 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17923 break;
17924 case NM_ADD:
17925 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17926 break;
17927 case NM_ADDU:
17928 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17929 break;
17930 case NM_SUB:
17931 check_nms(ctx);
17932 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17933 break;
17934 case NM_SUBU:
17935 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17936 break;
17937 case NM_P_CMOVE:
17938 switch (extract32(ctx->opcode, 10, 1)) {
17939 case NM_MOVZ:
17940 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17941 break;
17942 case NM_MOVN:
17943 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17944 break;
17946 break;
17947 case NM_AND:
17948 gen_logic(ctx, OPC_AND, rd, rs, rt);
17949 break;
17950 case NM_OR:
17951 gen_logic(ctx, OPC_OR, rd, rs, rt);
17952 break;
17953 case NM_NOR:
17954 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17955 break;
17956 case NM_XOR:
17957 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17958 break;
17959 case NM_SLT:
17960 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17961 break;
17962 case NM_P_SLTU:
17963 if (rd == 0) {
17964 /* P_DVP */
17965 #ifndef CONFIG_USER_ONLY
17966 TCGv t0 = tcg_temp_new();
17967 switch (extract32(ctx->opcode, 10, 1)) {
17968 case NM_DVP:
17969 if (ctx->vp) {
17970 check_cp0_enabled(ctx);
17971 gen_helper_dvp(t0, cpu_env);
17972 gen_store_gpr(t0, rt);
17974 break;
17975 case NM_EVP:
17976 if (ctx->vp) {
17977 check_cp0_enabled(ctx);
17978 gen_helper_evp(t0, cpu_env);
17979 gen_store_gpr(t0, rt);
17981 break;
17983 tcg_temp_free(t0);
17984 #endif
17985 } else {
17986 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17988 break;
17989 case NM_SOV:
17991 TCGv t0 = tcg_temp_new();
17992 TCGv t1 = tcg_temp_new();
17993 TCGv t2 = tcg_temp_new();
17995 gen_load_gpr(t1, rs);
17996 gen_load_gpr(t2, rt);
17997 tcg_gen_add_tl(t0, t1, t2);
17998 tcg_gen_ext32s_tl(t0, t0);
17999 tcg_gen_xor_tl(t1, t1, t2);
18000 tcg_gen_xor_tl(t2, t0, t2);
18001 tcg_gen_andc_tl(t1, t2, t1);
18003 /* operands of same sign, result different sign */
18004 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18005 gen_store_gpr(t0, rd);
18007 tcg_temp_free(t0);
18008 tcg_temp_free(t1);
18009 tcg_temp_free(t2);
18011 break;
18012 case NM_MUL:
18013 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18014 break;
18015 case NM_MUH:
18016 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18017 break;
18018 case NM_MULU:
18019 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18020 break;
18021 case NM_MUHU:
18022 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18023 break;
18024 case NM_DIV:
18025 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18026 break;
18027 case NM_MOD:
18028 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18029 break;
18030 case NM_DIVU:
18031 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18032 break;
18033 case NM_MODU:
18034 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18035 break;
18036 #ifndef CONFIG_USER_ONLY
18037 case NM_MFC0:
18038 check_cp0_enabled(ctx);
18039 if (rt == 0) {
18040 /* Treat as NOP. */
18041 break;
18043 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18044 break;
18045 case NM_MTC0:
18046 check_cp0_enabled(ctx);
18048 TCGv t0 = tcg_temp_new();
18050 gen_load_gpr(t0, rt);
18051 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18052 tcg_temp_free(t0);
18054 break;
18055 case NM_D_E_MT_VPE:
18057 uint8_t sc = extract32(ctx->opcode, 10, 1);
18058 TCGv t0 = tcg_temp_new();
18060 switch (sc) {
18061 case 0:
18062 if (rs == 1) {
18063 /* DMT */
18064 check_cp0_mt(ctx);
18065 gen_helper_dmt(t0);
18066 gen_store_gpr(t0, rt);
18067 } else if (rs == 0) {
18068 /* DVPE */
18069 check_cp0_mt(ctx);
18070 gen_helper_dvpe(t0, cpu_env);
18071 gen_store_gpr(t0, rt);
18072 } else {
18073 generate_exception_end(ctx, EXCP_RI);
18075 break;
18076 case 1:
18077 if (rs == 1) {
18078 /* EMT */
18079 check_cp0_mt(ctx);
18080 gen_helper_emt(t0);
18081 gen_store_gpr(t0, rt);
18082 } else if (rs == 0) {
18083 /* EVPE */
18084 check_cp0_mt(ctx);
18085 gen_helper_evpe(t0, cpu_env);
18086 gen_store_gpr(t0, rt);
18087 } else {
18088 generate_exception_end(ctx, EXCP_RI);
18090 break;
18093 tcg_temp_free(t0);
18095 break;
18096 case NM_FORK:
18097 check_mt(ctx);
18099 TCGv t0 = tcg_temp_new();
18100 TCGv t1 = tcg_temp_new();
18102 gen_load_gpr(t0, rt);
18103 gen_load_gpr(t1, rs);
18104 gen_helper_fork(t0, t1);
18105 tcg_temp_free(t0);
18106 tcg_temp_free(t1);
18108 break;
18109 case NM_MFTR:
18110 case NM_MFHTR:
18111 check_cp0_enabled(ctx);
18112 if (rd == 0) {
18113 /* Treat as NOP. */
18114 return;
18116 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18117 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18118 break;
18119 case NM_MTTR:
18120 case NM_MTHTR:
18121 check_cp0_enabled(ctx);
18122 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18123 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18124 break;
18125 case NM_YIELD:
18126 check_mt(ctx);
18128 TCGv t0 = tcg_temp_new();
18130 gen_load_gpr(t0, rs);
18131 gen_helper_yield(t0, cpu_env, t0);
18132 gen_store_gpr(t0, rt);
18133 tcg_temp_free(t0);
18135 break;
18136 #endif
18137 default:
18138 generate_exception_end(ctx, EXCP_RI);
18139 break;
18143 /* dsp */
18144 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18145 int ret, int v1, int v2)
18147 TCGv_i32 t0;
18148 TCGv v0_t;
18149 TCGv v1_t;
18151 t0 = tcg_temp_new_i32();
18153 v0_t = tcg_temp_new();
18154 v1_t = tcg_temp_new();
18156 tcg_gen_movi_i32(t0, v2 >> 3);
18158 gen_load_gpr(v0_t, ret);
18159 gen_load_gpr(v1_t, v1);
18161 switch (opc) {
18162 case NM_MAQ_S_W_PHR:
18163 check_dsp(ctx);
18164 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18165 break;
18166 case NM_MAQ_S_W_PHL:
18167 check_dsp(ctx);
18168 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18169 break;
18170 case NM_MAQ_SA_W_PHR:
18171 check_dsp(ctx);
18172 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18173 break;
18174 case NM_MAQ_SA_W_PHL:
18175 check_dsp(ctx);
18176 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18177 break;
18178 default:
18179 generate_exception_end(ctx, EXCP_RI);
18180 break;
18183 tcg_temp_free_i32(t0);
18185 tcg_temp_free(v0_t);
18186 tcg_temp_free(v1_t);
18190 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18191 int ret, int v1, int v2)
18193 int16_t imm;
18194 TCGv t0 = tcg_temp_new();
18195 TCGv t1 = tcg_temp_new();
18196 TCGv v0_t = tcg_temp_new();
18198 gen_load_gpr(v0_t, v1);
18200 switch (opc) {
18201 case NM_POOL32AXF_1_0:
18202 check_dsp(ctx);
18203 switch (extract32(ctx->opcode, 12, 2)) {
18204 case NM_MFHI:
18205 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18206 break;
18207 case NM_MFLO:
18208 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18209 break;
18210 case NM_MTHI:
18211 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18212 break;
18213 case NM_MTLO:
18214 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18215 break;
18217 break;
18218 case NM_POOL32AXF_1_1:
18219 check_dsp(ctx);
18220 switch (extract32(ctx->opcode, 12, 2)) {
18221 case NM_MTHLIP:
18222 tcg_gen_movi_tl(t0, v2);
18223 gen_helper_mthlip(t0, v0_t, cpu_env);
18224 break;
18225 case NM_SHILOV:
18226 tcg_gen_movi_tl(t0, v2 >> 3);
18227 gen_helper_shilo(t0, v0_t, cpu_env);
18228 break;
18229 default:
18230 generate_exception_end(ctx, EXCP_RI);
18231 break;
18233 break;
18234 case NM_POOL32AXF_1_3:
18235 check_dsp(ctx);
18236 imm = extract32(ctx->opcode, 14, 7);
18237 switch (extract32(ctx->opcode, 12, 2)) {
18238 case NM_RDDSP:
18239 tcg_gen_movi_tl(t0, imm);
18240 gen_helper_rddsp(t0, t0, cpu_env);
18241 gen_store_gpr(t0, ret);
18242 break;
18243 case NM_WRDSP:
18244 gen_load_gpr(t0, ret);
18245 tcg_gen_movi_tl(t1, imm);
18246 gen_helper_wrdsp(t0, t1, cpu_env);
18247 break;
18248 case NM_EXTP:
18249 tcg_gen_movi_tl(t0, v2 >> 3);
18250 tcg_gen_movi_tl(t1, v1);
18251 gen_helper_extp(t0, t0, t1, cpu_env);
18252 gen_store_gpr(t0, ret);
18253 break;
18254 case NM_EXTPDP:
18255 tcg_gen_movi_tl(t0, v2 >> 3);
18256 tcg_gen_movi_tl(t1, v1);
18257 gen_helper_extpdp(t0, t0, t1, cpu_env);
18258 gen_store_gpr(t0, ret);
18259 break;
18261 break;
18262 case NM_POOL32AXF_1_4:
18263 check_dsp(ctx);
18264 tcg_gen_movi_tl(t0, v2 >> 2);
18265 switch (extract32(ctx->opcode, 12, 1)) {
18266 case NM_SHLL_QB:
18267 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18268 gen_store_gpr(t0, ret);
18269 break;
18270 case NM_SHRL_QB:
18271 gen_helper_shrl_qb(t0, t0, v0_t);
18272 gen_store_gpr(t0, ret);
18273 break;
18275 break;
18276 case NM_POOL32AXF_1_5:
18277 opc = extract32(ctx->opcode, 12, 2);
18278 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18279 break;
18280 case NM_POOL32AXF_1_7:
18281 check_dsp(ctx);
18282 tcg_gen_movi_tl(t0, v2 >> 3);
18283 tcg_gen_movi_tl(t1, v1);
18284 switch (extract32(ctx->opcode, 12, 2)) {
18285 case NM_EXTR_W:
18286 gen_helper_extr_w(t0, t0, t1, cpu_env);
18287 gen_store_gpr(t0, ret);
18288 break;
18289 case NM_EXTR_R_W:
18290 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18291 gen_store_gpr(t0, ret);
18292 break;
18293 case NM_EXTR_RS_W:
18294 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18295 gen_store_gpr(t0, ret);
18296 break;
18297 case NM_EXTR_S_H:
18298 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18299 gen_store_gpr(t0, ret);
18300 break;
18302 break;
18303 default:
18304 generate_exception_end(ctx, EXCP_RI);
18305 break;
18308 tcg_temp_free(t0);
18309 tcg_temp_free(t1);
18310 tcg_temp_free(v0_t);
18313 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18314 TCGv v0, TCGv v1, int rd)
18316 TCGv_i32 t0;
18318 t0 = tcg_temp_new_i32();
18320 tcg_gen_movi_i32(t0, rd >> 3);
18322 switch (opc) {
18323 case NM_POOL32AXF_2_0_7:
18324 switch (extract32(ctx->opcode, 9, 3)) {
18325 case NM_DPA_W_PH:
18326 check_dsp_r2(ctx);
18327 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18328 break;
18329 case NM_DPAQ_S_W_PH:
18330 check_dsp(ctx);
18331 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18332 break;
18333 case NM_DPS_W_PH:
18334 check_dsp_r2(ctx);
18335 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18336 break;
18337 case NM_DPSQ_S_W_PH:
18338 check_dsp(ctx);
18339 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18340 break;
18341 default:
18342 generate_exception_end(ctx, EXCP_RI);
18343 break;
18345 break;
18346 case NM_POOL32AXF_2_8_15:
18347 switch (extract32(ctx->opcode, 9, 3)) {
18348 case NM_DPAX_W_PH:
18349 check_dsp_r2(ctx);
18350 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18351 break;
18352 case NM_DPAQ_SA_L_W:
18353 check_dsp(ctx);
18354 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18355 break;
18356 case NM_DPSX_W_PH:
18357 check_dsp_r2(ctx);
18358 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18359 break;
18360 case NM_DPSQ_SA_L_W:
18361 check_dsp(ctx);
18362 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18363 break;
18364 default:
18365 generate_exception_end(ctx, EXCP_RI);
18366 break;
18368 break;
18369 case NM_POOL32AXF_2_16_23:
18370 switch (extract32(ctx->opcode, 9, 3)) {
18371 case NM_DPAU_H_QBL:
18372 check_dsp(ctx);
18373 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18374 break;
18375 case NM_DPAQX_S_W_PH:
18376 check_dsp_r2(ctx);
18377 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18378 break;
18379 case NM_DPSU_H_QBL:
18380 check_dsp(ctx);
18381 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18382 break;
18383 case NM_DPSQX_S_W_PH:
18384 check_dsp_r2(ctx);
18385 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18386 break;
18387 case NM_MULSA_W_PH:
18388 check_dsp_r2(ctx);
18389 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18390 break;
18391 default:
18392 generate_exception_end(ctx, EXCP_RI);
18393 break;
18395 break;
18396 case NM_POOL32AXF_2_24_31:
18397 switch (extract32(ctx->opcode, 9, 3)) {
18398 case NM_DPAU_H_QBR:
18399 check_dsp(ctx);
18400 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18401 break;
18402 case NM_DPAQX_SA_W_PH:
18403 check_dsp_r2(ctx);
18404 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18405 break;
18406 case NM_DPSU_H_QBR:
18407 check_dsp(ctx);
18408 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18409 break;
18410 case NM_DPSQX_SA_W_PH:
18411 check_dsp_r2(ctx);
18412 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18413 break;
18414 case NM_MULSAQ_S_W_PH:
18415 check_dsp(ctx);
18416 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18417 break;
18418 default:
18419 generate_exception_end(ctx, EXCP_RI);
18420 break;
18422 break;
18423 default:
18424 generate_exception_end(ctx, EXCP_RI);
18425 break;
18428 tcg_temp_free_i32(t0);
18431 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18432 int rt, int rs, int rd)
18434 int ret = rt;
18435 TCGv t0 = tcg_temp_new();
18436 TCGv t1 = tcg_temp_new();
18437 TCGv v0_t = tcg_temp_new();
18438 TCGv v1_t = tcg_temp_new();
18440 gen_load_gpr(v0_t, rt);
18441 gen_load_gpr(v1_t, rs);
18443 switch (opc) {
18444 case NM_POOL32AXF_2_0_7:
18445 switch (extract32(ctx->opcode, 9, 3)) {
18446 case NM_DPA_W_PH:
18447 case NM_DPAQ_S_W_PH:
18448 case NM_DPS_W_PH:
18449 case NM_DPSQ_S_W_PH:
18450 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18451 break;
18452 case NM_BALIGN:
18453 check_dsp_r2(ctx);
18454 if (rt != 0) {
18455 gen_load_gpr(t0, rs);
18456 rd &= 3;
18457 if (rd != 0 && rd != 2) {
18458 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18459 tcg_gen_ext32u_tl(t0, t0);
18460 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18461 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18463 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18465 break;
18466 case NM_MADD:
18467 check_dsp(ctx);
18469 int acc = extract32(ctx->opcode, 14, 2);
18470 TCGv_i64 t2 = tcg_temp_new_i64();
18471 TCGv_i64 t3 = tcg_temp_new_i64();
18473 gen_load_gpr(t0, rt);
18474 gen_load_gpr(t1, rs);
18475 tcg_gen_ext_tl_i64(t2, t0);
18476 tcg_gen_ext_tl_i64(t3, t1);
18477 tcg_gen_mul_i64(t2, t2, t3);
18478 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18479 tcg_gen_add_i64(t2, t2, t3);
18480 tcg_temp_free_i64(t3);
18481 gen_move_low32(cpu_LO[acc], t2);
18482 gen_move_high32(cpu_HI[acc], t2);
18483 tcg_temp_free_i64(t2);
18485 break;
18486 case NM_MULT:
18487 check_dsp(ctx);
18489 int acc = extract32(ctx->opcode, 14, 2);
18490 TCGv_i32 t2 = tcg_temp_new_i32();
18491 TCGv_i32 t3 = tcg_temp_new_i32();
18493 gen_load_gpr(t0, rs);
18494 gen_load_gpr(t1, rt);
18495 tcg_gen_trunc_tl_i32(t2, t0);
18496 tcg_gen_trunc_tl_i32(t3, t1);
18497 tcg_gen_muls2_i32(t2, t3, t2, t3);
18498 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18499 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18500 tcg_temp_free_i32(t2);
18501 tcg_temp_free_i32(t3);
18503 break;
18504 case NM_EXTRV_W:
18505 check_dsp(ctx);
18506 gen_load_gpr(v1_t, rs);
18507 tcg_gen_movi_tl(t0, rd >> 3);
18508 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18509 gen_store_gpr(t0, ret);
18510 break;
18512 break;
18513 case NM_POOL32AXF_2_8_15:
18514 switch (extract32(ctx->opcode, 9, 3)) {
18515 case NM_DPAX_W_PH:
18516 case NM_DPAQ_SA_L_W:
18517 case NM_DPSX_W_PH:
18518 case NM_DPSQ_SA_L_W:
18519 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18520 break;
18521 case NM_MADDU:
18522 check_dsp(ctx);
18524 int acc = extract32(ctx->opcode, 14, 2);
18525 TCGv_i64 t2 = tcg_temp_new_i64();
18526 TCGv_i64 t3 = tcg_temp_new_i64();
18528 gen_load_gpr(t0, rs);
18529 gen_load_gpr(t1, rt);
18530 tcg_gen_ext32u_tl(t0, t0);
18531 tcg_gen_ext32u_tl(t1, t1);
18532 tcg_gen_extu_tl_i64(t2, t0);
18533 tcg_gen_extu_tl_i64(t3, t1);
18534 tcg_gen_mul_i64(t2, t2, t3);
18535 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18536 tcg_gen_add_i64(t2, t2, t3);
18537 tcg_temp_free_i64(t3);
18538 gen_move_low32(cpu_LO[acc], t2);
18539 gen_move_high32(cpu_HI[acc], t2);
18540 tcg_temp_free_i64(t2);
18542 break;
18543 case NM_MULTU:
18544 check_dsp(ctx);
18546 int acc = extract32(ctx->opcode, 14, 2);
18547 TCGv_i32 t2 = tcg_temp_new_i32();
18548 TCGv_i32 t3 = tcg_temp_new_i32();
18550 gen_load_gpr(t0, rs);
18551 gen_load_gpr(t1, rt);
18552 tcg_gen_trunc_tl_i32(t2, t0);
18553 tcg_gen_trunc_tl_i32(t3, t1);
18554 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18555 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18556 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18557 tcg_temp_free_i32(t2);
18558 tcg_temp_free_i32(t3);
18560 break;
18561 case NM_EXTRV_R_W:
18562 check_dsp(ctx);
18563 tcg_gen_movi_tl(t0, rd >> 3);
18564 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18565 gen_store_gpr(t0, ret);
18566 break;
18567 default:
18568 generate_exception_end(ctx, EXCP_RI);
18569 break;
18571 break;
18572 case NM_POOL32AXF_2_16_23:
18573 switch (extract32(ctx->opcode, 9, 3)) {
18574 case NM_DPAU_H_QBL:
18575 case NM_DPAQX_S_W_PH:
18576 case NM_DPSU_H_QBL:
18577 case NM_DPSQX_S_W_PH:
18578 case NM_MULSA_W_PH:
18579 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18580 break;
18581 case NM_EXTPV:
18582 check_dsp(ctx);
18583 tcg_gen_movi_tl(t0, rd >> 3);
18584 gen_helper_extp(t0, t0, v1_t, cpu_env);
18585 gen_store_gpr(t0, ret);
18586 break;
18587 case NM_MSUB:
18588 check_dsp(ctx);
18590 int acc = extract32(ctx->opcode, 14, 2);
18591 TCGv_i64 t2 = tcg_temp_new_i64();
18592 TCGv_i64 t3 = tcg_temp_new_i64();
18594 gen_load_gpr(t0, rs);
18595 gen_load_gpr(t1, rt);
18596 tcg_gen_ext_tl_i64(t2, t0);
18597 tcg_gen_ext_tl_i64(t3, t1);
18598 tcg_gen_mul_i64(t2, t2, t3);
18599 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18600 tcg_gen_sub_i64(t2, t3, t2);
18601 tcg_temp_free_i64(t3);
18602 gen_move_low32(cpu_LO[acc], t2);
18603 gen_move_high32(cpu_HI[acc], t2);
18604 tcg_temp_free_i64(t2);
18606 break;
18607 case NM_EXTRV_RS_W:
18608 check_dsp(ctx);
18609 tcg_gen_movi_tl(t0, rd >> 3);
18610 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18611 gen_store_gpr(t0, ret);
18612 break;
18614 break;
18615 case NM_POOL32AXF_2_24_31:
18616 switch (extract32(ctx->opcode, 9, 3)) {
18617 case NM_DPAU_H_QBR:
18618 case NM_DPAQX_SA_W_PH:
18619 case NM_DPSU_H_QBR:
18620 case NM_DPSQX_SA_W_PH:
18621 case NM_MULSAQ_S_W_PH:
18622 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18623 break;
18624 case NM_EXTPDPV:
18625 check_dsp(ctx);
18626 tcg_gen_movi_tl(t0, rd >> 3);
18627 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18628 gen_store_gpr(t0, ret);
18629 break;
18630 case NM_MSUBU:
18631 check_dsp(ctx);
18633 int acc = extract32(ctx->opcode, 14, 2);
18634 TCGv_i64 t2 = tcg_temp_new_i64();
18635 TCGv_i64 t3 = tcg_temp_new_i64();
18637 gen_load_gpr(t0, rs);
18638 gen_load_gpr(t1, rt);
18639 tcg_gen_ext32u_tl(t0, t0);
18640 tcg_gen_ext32u_tl(t1, t1);
18641 tcg_gen_extu_tl_i64(t2, t0);
18642 tcg_gen_extu_tl_i64(t3, t1);
18643 tcg_gen_mul_i64(t2, t2, t3);
18644 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18645 tcg_gen_sub_i64(t2, t3, t2);
18646 tcg_temp_free_i64(t3);
18647 gen_move_low32(cpu_LO[acc], t2);
18648 gen_move_high32(cpu_HI[acc], t2);
18649 tcg_temp_free_i64(t2);
18651 break;
18652 case NM_EXTRV_S_H:
18653 check_dsp(ctx);
18654 tcg_gen_movi_tl(t0, rd >> 3);
18655 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18656 gen_store_gpr(t0, ret);
18657 break;
18659 break;
18660 default:
18661 generate_exception_end(ctx, EXCP_RI);
18662 break;
18665 tcg_temp_free(t0);
18666 tcg_temp_free(t1);
18668 tcg_temp_free(v0_t);
18669 tcg_temp_free(v1_t);
18672 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18673 int rt, int rs)
18675 int ret = rt;
18676 TCGv t0 = tcg_temp_new();
18677 TCGv v0_t = tcg_temp_new();
18679 gen_load_gpr(v0_t, rs);
18681 switch (opc) {
18682 case NM_ABSQ_S_QB:
18683 check_dsp_r2(ctx);
18684 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18685 gen_store_gpr(v0_t, ret);
18686 break;
18687 case NM_ABSQ_S_PH:
18688 check_dsp(ctx);
18689 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18690 gen_store_gpr(v0_t, ret);
18691 break;
18692 case NM_ABSQ_S_W:
18693 check_dsp(ctx);
18694 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18695 gen_store_gpr(v0_t, ret);
18696 break;
18697 case NM_PRECEQ_W_PHL:
18698 check_dsp(ctx);
18699 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18700 tcg_gen_ext32s_tl(v0_t, v0_t);
18701 gen_store_gpr(v0_t, ret);
18702 break;
18703 case NM_PRECEQ_W_PHR:
18704 check_dsp(ctx);
18705 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18706 tcg_gen_shli_tl(v0_t, v0_t, 16);
18707 tcg_gen_ext32s_tl(v0_t, v0_t);
18708 gen_store_gpr(v0_t, ret);
18709 break;
18710 case NM_PRECEQU_PH_QBL:
18711 check_dsp(ctx);
18712 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18713 gen_store_gpr(v0_t, ret);
18714 break;
18715 case NM_PRECEQU_PH_QBR:
18716 check_dsp(ctx);
18717 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18718 gen_store_gpr(v0_t, ret);
18719 break;
18720 case NM_PRECEQU_PH_QBLA:
18721 check_dsp(ctx);
18722 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18723 gen_store_gpr(v0_t, ret);
18724 break;
18725 case NM_PRECEQU_PH_QBRA:
18726 check_dsp(ctx);
18727 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18728 gen_store_gpr(v0_t, ret);
18729 break;
18730 case NM_PRECEU_PH_QBL:
18731 check_dsp(ctx);
18732 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18733 gen_store_gpr(v0_t, ret);
18734 break;
18735 case NM_PRECEU_PH_QBR:
18736 check_dsp(ctx);
18737 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18738 gen_store_gpr(v0_t, ret);
18739 break;
18740 case NM_PRECEU_PH_QBLA:
18741 check_dsp(ctx);
18742 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18743 gen_store_gpr(v0_t, ret);
18744 break;
18745 case NM_PRECEU_PH_QBRA:
18746 check_dsp(ctx);
18747 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18748 gen_store_gpr(v0_t, ret);
18749 break;
18750 case NM_REPLV_PH:
18751 check_dsp(ctx);
18752 tcg_gen_ext16u_tl(v0_t, v0_t);
18753 tcg_gen_shli_tl(t0, v0_t, 16);
18754 tcg_gen_or_tl(v0_t, v0_t, t0);
18755 tcg_gen_ext32s_tl(v0_t, v0_t);
18756 gen_store_gpr(v0_t, ret);
18757 break;
18758 case NM_REPLV_QB:
18759 check_dsp(ctx);
18760 tcg_gen_ext8u_tl(v0_t, v0_t);
18761 tcg_gen_shli_tl(t0, v0_t, 8);
18762 tcg_gen_or_tl(v0_t, v0_t, t0);
18763 tcg_gen_shli_tl(t0, v0_t, 16);
18764 tcg_gen_or_tl(v0_t, v0_t, t0);
18765 tcg_gen_ext32s_tl(v0_t, v0_t);
18766 gen_store_gpr(v0_t, ret);
18767 break;
18768 case NM_BITREV:
18769 check_dsp(ctx);
18770 gen_helper_bitrev(v0_t, v0_t);
18771 gen_store_gpr(v0_t, ret);
18772 break;
18773 case NM_INSV:
18774 check_dsp(ctx);
18776 TCGv tv0 = tcg_temp_new();
18778 gen_load_gpr(tv0, rt);
18779 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18780 gen_store_gpr(v0_t, ret);
18781 tcg_temp_free(tv0);
18783 break;
18784 case NM_RADDU_W_QB:
18785 check_dsp(ctx);
18786 gen_helper_raddu_w_qb(v0_t, v0_t);
18787 gen_store_gpr(v0_t, ret);
18788 break;
18789 case NM_BITSWAP:
18790 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18791 break;
18792 case NM_CLO:
18793 check_nms(ctx);
18794 gen_cl(ctx, OPC_CLO, ret, rs);
18795 break;
18796 case NM_CLZ:
18797 check_nms(ctx);
18798 gen_cl(ctx, OPC_CLZ, ret, rs);
18799 break;
18800 case NM_WSBH:
18801 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18802 break;
18803 default:
18804 generate_exception_end(ctx, EXCP_RI);
18805 break;
18808 tcg_temp_free(v0_t);
18809 tcg_temp_free(t0);
18812 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18813 int rt, int rs, int rd)
18815 TCGv t0 = tcg_temp_new();
18816 TCGv rs_t = tcg_temp_new();
18818 gen_load_gpr(rs_t, rs);
18820 switch (opc) {
18821 case NM_SHRA_R_QB:
18822 check_dsp_r2(ctx);
18823 tcg_gen_movi_tl(t0, rd >> 2);
18824 switch (extract32(ctx->opcode, 12, 1)) {
18825 case 0:
18826 /* NM_SHRA_QB */
18827 gen_helper_shra_qb(t0, t0, rs_t);
18828 gen_store_gpr(t0, rt);
18829 break;
18830 case 1:
18831 /* NM_SHRA_R_QB */
18832 gen_helper_shra_r_qb(t0, t0, rs_t);
18833 gen_store_gpr(t0, rt);
18834 break;
18836 break;
18837 case NM_SHRL_PH:
18838 check_dsp_r2(ctx);
18839 tcg_gen_movi_tl(t0, rd >> 1);
18840 gen_helper_shrl_ph(t0, t0, rs_t);
18841 gen_store_gpr(t0, rt);
18842 break;
18843 case NM_REPL_QB:
18844 check_dsp(ctx);
18846 int16_t imm;
18847 target_long result;
18848 imm = extract32(ctx->opcode, 13, 8);
18849 result = (uint32_t)imm << 24 |
18850 (uint32_t)imm << 16 |
18851 (uint32_t)imm << 8 |
18852 (uint32_t)imm;
18853 result = (int32_t)result;
18854 tcg_gen_movi_tl(t0, result);
18855 gen_store_gpr(t0, rt);
18857 break;
18858 default:
18859 generate_exception_end(ctx, EXCP_RI);
18860 break;
18862 tcg_temp_free(t0);
18863 tcg_temp_free(rs_t);
18867 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18869 int rt = extract32(ctx->opcode, 21, 5);
18870 int rs = extract32(ctx->opcode, 16, 5);
18871 int rd = extract32(ctx->opcode, 11, 5);
18873 switch (extract32(ctx->opcode, 6, 3)) {
18874 case NM_POOL32AXF_1:
18876 int32_t op1 = extract32(ctx->opcode, 9, 3);
18877 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18879 break;
18880 case NM_POOL32AXF_2:
18882 int32_t op1 = extract32(ctx->opcode, 12, 2);
18883 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18885 break;
18886 case NM_POOL32AXF_4:
18888 int32_t op1 = extract32(ctx->opcode, 9, 7);
18889 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18891 break;
18892 case NM_POOL32AXF_5:
18893 switch (extract32(ctx->opcode, 9, 7)) {
18894 #ifndef CONFIG_USER_ONLY
18895 case NM_TLBP:
18896 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18897 break;
18898 case NM_TLBR:
18899 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18900 break;
18901 case NM_TLBWI:
18902 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18903 break;
18904 case NM_TLBWR:
18905 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18906 break;
18907 case NM_TLBINV:
18908 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18909 break;
18910 case NM_TLBINVF:
18911 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18912 break;
18913 case NM_DI:
18914 check_cp0_enabled(ctx);
18916 TCGv t0 = tcg_temp_new();
18918 save_cpu_state(ctx, 1);
18919 gen_helper_di(t0, cpu_env);
18920 gen_store_gpr(t0, rt);
18921 /* Stop translation as we may have switched the execution mode */
18922 ctx->base.is_jmp = DISAS_STOP;
18923 tcg_temp_free(t0);
18925 break;
18926 case NM_EI:
18927 check_cp0_enabled(ctx);
18929 TCGv t0 = tcg_temp_new();
18931 save_cpu_state(ctx, 1);
18932 gen_helper_ei(t0, cpu_env);
18933 gen_store_gpr(t0, rt);
18934 /* Stop translation as we may have switched the execution mode */
18935 ctx->base.is_jmp = DISAS_STOP;
18936 tcg_temp_free(t0);
18938 break;
18939 case NM_RDPGPR:
18940 gen_load_srsgpr(rs, rt);
18941 break;
18942 case NM_WRPGPR:
18943 gen_store_srsgpr(rs, rt);
18944 break;
18945 case NM_WAIT:
18946 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18947 break;
18948 case NM_DERET:
18949 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18950 break;
18951 case NM_ERETX:
18952 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18953 break;
18954 #endif
18955 default:
18956 generate_exception_end(ctx, EXCP_RI);
18957 break;
18959 break;
18960 case NM_POOL32AXF_7:
18962 int32_t op1 = extract32(ctx->opcode, 9, 3);
18963 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18965 break;
18966 default:
18967 generate_exception_end(ctx, EXCP_RI);
18968 break;
18972 /* Immediate Value Compact Branches */
18973 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
18974 int rt, int32_t imm, int32_t offset)
18976 TCGCond cond;
18977 int bcond_compute = 0;
18978 TCGv t0 = tcg_temp_new();
18979 TCGv t1 = tcg_temp_new();
18981 gen_load_gpr(t0, rt);
18982 tcg_gen_movi_tl(t1, imm);
18983 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18985 /* Load needed operands and calculate btarget */
18986 switch (opc) {
18987 case NM_BEQIC:
18988 if (rt == 0 && imm == 0) {
18989 /* Unconditional branch */
18990 } else if (rt == 0 && imm != 0) {
18991 /* Treat as NOP */
18992 goto out;
18993 } else {
18994 bcond_compute = 1;
18995 cond = TCG_COND_EQ;
18997 break;
18998 case NM_BBEQZC:
18999 case NM_BBNEZC:
19000 check_nms(ctx);
19001 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19002 generate_exception_end(ctx, EXCP_RI);
19003 goto out;
19004 } else if (rt == 0 && opc == NM_BBEQZC) {
19005 /* Unconditional branch */
19006 } else if (rt == 0 && opc == NM_BBNEZC) {
19007 /* Treat as NOP */
19008 goto out;
19009 } else {
19010 tcg_gen_shri_tl(t0, t0, imm);
19011 tcg_gen_andi_tl(t0, t0, 1);
19012 tcg_gen_movi_tl(t1, 0);
19013 bcond_compute = 1;
19014 if (opc == NM_BBEQZC) {
19015 cond = TCG_COND_EQ;
19016 } else {
19017 cond = TCG_COND_NE;
19020 break;
19021 case NM_BNEIC:
19022 if (rt == 0 && imm == 0) {
19023 /* Treat as NOP */
19024 goto out;
19025 } else if (rt == 0 && imm != 0) {
19026 /* Unconditional branch */
19027 } else {
19028 bcond_compute = 1;
19029 cond = TCG_COND_NE;
19031 break;
19032 case NM_BGEIC:
19033 if (rt == 0 && imm == 0) {
19034 /* Unconditional branch */
19035 } else {
19036 bcond_compute = 1;
19037 cond = TCG_COND_GE;
19039 break;
19040 case NM_BLTIC:
19041 bcond_compute = 1;
19042 cond = TCG_COND_LT;
19043 break;
19044 case NM_BGEIUC:
19045 if (rt == 0 && imm == 0) {
19046 /* Unconditional branch */
19047 } else {
19048 bcond_compute = 1;
19049 cond = TCG_COND_GEU;
19051 break;
19052 case NM_BLTIUC:
19053 bcond_compute = 1;
19054 cond = TCG_COND_LTU;
19055 break;
19056 default:
19057 MIPS_INVAL("Immediate Value Compact branch");
19058 generate_exception_end(ctx, EXCP_RI);
19059 goto out;
19062 if (bcond_compute == 0) {
19063 /* Uncoditional compact branch */
19064 gen_goto_tb(ctx, 0, ctx->btarget);
19065 } else {
19066 /* Conditional compact branch */
19067 TCGLabel *fs = gen_new_label();
19069 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19071 gen_goto_tb(ctx, 1, ctx->btarget);
19072 gen_set_label(fs);
19074 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19077 out:
19078 tcg_temp_free(t0);
19079 tcg_temp_free(t1);
19082 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19083 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19084 int rt)
19086 TCGv t0 = tcg_temp_new();
19087 TCGv t1 = tcg_temp_new();
19089 /* load rs */
19090 gen_load_gpr(t0, rs);
19092 /* link */
19093 if (rt != 0) {
19094 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19097 /* calculate btarget */
19098 tcg_gen_shli_tl(t0, t0, 1);
19099 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19100 gen_op_addr_add(ctx, btarget, t1, t0);
19102 /* unconditional branch to register */
19103 tcg_gen_mov_tl(cpu_PC, btarget);
19104 tcg_gen_lookup_and_goto_ptr();
19106 tcg_temp_free(t0);
19107 tcg_temp_free(t1);
19110 /* nanoMIPS Branches */
19111 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19112 int rs, int rt, int32_t offset)
19114 int bcond_compute = 0;
19115 TCGv t0 = tcg_temp_new();
19116 TCGv t1 = tcg_temp_new();
19118 /* Load needed operands and calculate btarget */
19119 switch (opc) {
19120 /* compact branch */
19121 case OPC_BGEC:
19122 case OPC_BLTC:
19123 gen_load_gpr(t0, rs);
19124 gen_load_gpr(t1, rt);
19125 bcond_compute = 1;
19126 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19127 break;
19128 case OPC_BGEUC:
19129 case OPC_BLTUC:
19130 if (rs == 0 || rs == rt) {
19131 /* OPC_BLEZALC, OPC_BGEZALC */
19132 /* OPC_BGTZALC, OPC_BLTZALC */
19133 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19135 gen_load_gpr(t0, rs);
19136 gen_load_gpr(t1, rt);
19137 bcond_compute = 1;
19138 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19139 break;
19140 case OPC_BC:
19141 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19142 break;
19143 case OPC_BEQZC:
19144 if (rs != 0) {
19145 /* OPC_BEQZC, OPC_BNEZC */
19146 gen_load_gpr(t0, rs);
19147 bcond_compute = 1;
19148 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19149 } else {
19150 /* OPC_JIC, OPC_JIALC */
19151 TCGv tbase = tcg_temp_new();
19152 TCGv toffset = tcg_temp_new();
19154 gen_load_gpr(tbase, rt);
19155 tcg_gen_movi_tl(toffset, offset);
19156 gen_op_addr_add(ctx, btarget, tbase, toffset);
19157 tcg_temp_free(tbase);
19158 tcg_temp_free(toffset);
19160 break;
19161 default:
19162 MIPS_INVAL("Compact branch/jump");
19163 generate_exception_end(ctx, EXCP_RI);
19164 goto out;
19167 if (bcond_compute == 0) {
19168 /* Uncoditional compact branch */
19169 switch (opc) {
19170 case OPC_BC:
19171 gen_goto_tb(ctx, 0, ctx->btarget);
19172 break;
19173 default:
19174 MIPS_INVAL("Compact branch/jump");
19175 generate_exception_end(ctx, EXCP_RI);
19176 goto out;
19178 } else {
19179 /* Conditional compact branch */
19180 TCGLabel *fs = gen_new_label();
19182 switch (opc) {
19183 case OPC_BGEUC:
19184 if (rs == 0 && rt != 0) {
19185 /* OPC_BLEZALC */
19186 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19187 } else if (rs != 0 && rt != 0 && rs == rt) {
19188 /* OPC_BGEZALC */
19189 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19190 } else {
19191 /* OPC_BGEUC */
19192 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19194 break;
19195 case OPC_BLTUC:
19196 if (rs == 0 && rt != 0) {
19197 /* OPC_BGTZALC */
19198 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19199 } else if (rs != 0 && rt != 0 && rs == rt) {
19200 /* OPC_BLTZALC */
19201 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19202 } else {
19203 /* OPC_BLTUC */
19204 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19206 break;
19207 case OPC_BGEC:
19208 if (rs == 0 && rt != 0) {
19209 /* OPC_BLEZC */
19210 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19211 } else if (rs != 0 && rt != 0 && rs == rt) {
19212 /* OPC_BGEZC */
19213 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19214 } else {
19215 /* OPC_BGEC */
19216 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19218 break;
19219 case OPC_BLTC:
19220 if (rs == 0 && rt != 0) {
19221 /* OPC_BGTZC */
19222 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19223 } else if (rs != 0 && rt != 0 && rs == rt) {
19224 /* OPC_BLTZC */
19225 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19226 } else {
19227 /* OPC_BLTC */
19228 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19230 break;
19231 case OPC_BEQZC:
19232 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19233 break;
19234 default:
19235 MIPS_INVAL("Compact conditional branch/jump");
19236 generate_exception_end(ctx, EXCP_RI);
19237 goto out;
19240 /* Generating branch here as compact branches don't have delay slot */
19241 gen_goto_tb(ctx, 1, ctx->btarget);
19242 gen_set_label(fs);
19244 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19247 out:
19248 tcg_temp_free(t0);
19249 tcg_temp_free(t1);
19253 /* nanoMIPS CP1 Branches */
19254 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19255 int32_t ft, int32_t offset)
19257 target_ulong btarget;
19258 TCGv_i64 t0 = tcg_temp_new_i64();
19260 gen_load_fpr64(ctx, t0, ft);
19261 tcg_gen_andi_i64(t0, t0, 1);
19263 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19265 switch (op) {
19266 case NM_BC1EQZC:
19267 tcg_gen_xori_i64(t0, t0, 1);
19268 ctx->hflags |= MIPS_HFLAG_BC;
19269 break;
19270 case NM_BC1NEZC:
19271 /* t0 already set */
19272 ctx->hflags |= MIPS_HFLAG_BC;
19273 break;
19274 default:
19275 MIPS_INVAL("cp1 cond branch");
19276 generate_exception_end(ctx, EXCP_RI);
19277 goto out;
19280 tcg_gen_trunc_i64_tl(bcond, t0);
19282 ctx->btarget = btarget;
19284 out:
19285 tcg_temp_free_i64(t0);
19289 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19291 TCGv t0, t1;
19292 t0 = tcg_temp_new();
19293 t1 = tcg_temp_new();
19295 gen_load_gpr(t0, rs);
19296 gen_load_gpr(t1, rt);
19298 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19299 /* PP.LSXS instructions require shifting */
19300 switch (extract32(ctx->opcode, 7, 4)) {
19301 case NM_SHXS:
19302 check_nms(ctx);
19303 case NM_LHXS:
19304 case NM_LHUXS:
19305 tcg_gen_shli_tl(t0, t0, 1);
19306 break;
19307 case NM_SWXS:
19308 check_nms(ctx);
19309 case NM_LWXS:
19310 case NM_LWC1XS:
19311 case NM_SWC1XS:
19312 tcg_gen_shli_tl(t0, t0, 2);
19313 break;
19314 case NM_LDC1XS:
19315 case NM_SDC1XS:
19316 tcg_gen_shli_tl(t0, t0, 3);
19317 break;
19320 gen_op_addr_add(ctx, t0, t0, t1);
19322 switch (extract32(ctx->opcode, 7, 4)) {
19323 case NM_LBX:
19324 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19325 MO_SB);
19326 gen_store_gpr(t0, rd);
19327 break;
19328 case NM_LHX:
19329 /*case NM_LHXS:*/
19330 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19331 MO_TESW);
19332 gen_store_gpr(t0, rd);
19333 break;
19334 case NM_LWX:
19335 /*case NM_LWXS:*/
19336 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19337 MO_TESL);
19338 gen_store_gpr(t0, rd);
19339 break;
19340 case NM_LBUX:
19341 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19342 MO_UB);
19343 gen_store_gpr(t0, rd);
19344 break;
19345 case NM_LHUX:
19346 /*case NM_LHUXS:*/
19347 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19348 MO_TEUW);
19349 gen_store_gpr(t0, rd);
19350 break;
19351 case NM_SBX:
19352 check_nms(ctx);
19353 gen_load_gpr(t1, rd);
19354 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19355 MO_8);
19356 break;
19357 case NM_SHX:
19358 /*case NM_SHXS:*/
19359 check_nms(ctx);
19360 gen_load_gpr(t1, rd);
19361 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19362 MO_TEUW);
19363 break;
19364 case NM_SWX:
19365 /*case NM_SWXS:*/
19366 check_nms(ctx);
19367 gen_load_gpr(t1, rd);
19368 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19369 MO_TEUL);
19370 break;
19371 case NM_LWC1X:
19372 /*case NM_LWC1XS:*/
19373 case NM_LDC1X:
19374 /*case NM_LDC1XS:*/
19375 case NM_SWC1X:
19376 /*case NM_SWC1XS:*/
19377 case NM_SDC1X:
19378 /*case NM_SDC1XS:*/
19379 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19380 check_cp1_enabled(ctx);
19381 switch (extract32(ctx->opcode, 7, 4)) {
19382 case NM_LWC1X:
19383 /*case NM_LWC1XS:*/
19384 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19385 break;
19386 case NM_LDC1X:
19387 /*case NM_LDC1XS:*/
19388 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19389 break;
19390 case NM_SWC1X:
19391 /*case NM_SWC1XS:*/
19392 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19393 break;
19394 case NM_SDC1X:
19395 /*case NM_SDC1XS:*/
19396 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19397 break;
19399 } else {
19400 generate_exception_err(ctx, EXCP_CpU, 1);
19402 break;
19403 default:
19404 generate_exception_end(ctx, EXCP_RI);
19405 break;
19408 tcg_temp_free(t0);
19409 tcg_temp_free(t1);
19412 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19414 int rt, rs, rd;
19416 rt = extract32(ctx->opcode, 21, 5);
19417 rs = extract32(ctx->opcode, 16, 5);
19418 rd = extract32(ctx->opcode, 11, 5);
19420 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19421 generate_exception_end(ctx, EXCP_RI);
19422 return;
19424 check_cp1_enabled(ctx);
19425 switch (extract32(ctx->opcode, 0, 3)) {
19426 case NM_POOL32F_0:
19427 switch (extract32(ctx->opcode, 3, 7)) {
19428 case NM_RINT_S:
19429 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19430 break;
19431 case NM_RINT_D:
19432 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19433 break;
19434 case NM_CLASS_S:
19435 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19436 break;
19437 case NM_CLASS_D:
19438 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19439 break;
19440 case NM_ADD_S:
19441 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19442 break;
19443 case NM_ADD_D:
19444 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19445 break;
19446 case NM_SUB_S:
19447 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19448 break;
19449 case NM_SUB_D:
19450 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19451 break;
19452 case NM_MUL_S:
19453 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19454 break;
19455 case NM_MUL_D:
19456 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19457 break;
19458 case NM_DIV_S:
19459 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19460 break;
19461 case NM_DIV_D:
19462 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19463 break;
19464 case NM_SELEQZ_S:
19465 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19466 break;
19467 case NM_SELEQZ_D:
19468 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19469 break;
19470 case NM_SELNEZ_S:
19471 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19472 break;
19473 case NM_SELNEZ_D:
19474 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19475 break;
19476 case NM_SEL_S:
19477 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19478 break;
19479 case NM_SEL_D:
19480 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19481 break;
19482 case NM_MADDF_S:
19483 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19484 break;
19485 case NM_MADDF_D:
19486 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19487 break;
19488 case NM_MSUBF_S:
19489 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19490 break;
19491 case NM_MSUBF_D:
19492 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19493 break;
19494 default:
19495 generate_exception_end(ctx, EXCP_RI);
19496 break;
19498 break;
19499 case NM_POOL32F_3:
19500 switch (extract32(ctx->opcode, 3, 3)) {
19501 case NM_MIN_FMT:
19502 switch (extract32(ctx->opcode, 9, 1)) {
19503 case FMT_SDPS_S:
19504 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19505 break;
19506 case FMT_SDPS_D:
19507 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19508 break;
19510 break;
19511 case NM_MAX_FMT:
19512 switch (extract32(ctx->opcode, 9, 1)) {
19513 case FMT_SDPS_S:
19514 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19515 break;
19516 case FMT_SDPS_D:
19517 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19518 break;
19520 break;
19521 case NM_MINA_FMT:
19522 switch (extract32(ctx->opcode, 9, 1)) {
19523 case FMT_SDPS_S:
19524 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19525 break;
19526 case FMT_SDPS_D:
19527 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19528 break;
19530 break;
19531 case NM_MAXA_FMT:
19532 switch (extract32(ctx->opcode, 9, 1)) {
19533 case FMT_SDPS_S:
19534 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19535 break;
19536 case FMT_SDPS_D:
19537 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19538 break;
19540 break;
19541 case NM_POOL32FXF:
19542 switch (extract32(ctx->opcode, 6, 8)) {
19543 case NM_CFC1:
19544 gen_cp1(ctx, OPC_CFC1, rt, rs);
19545 break;
19546 case NM_CTC1:
19547 gen_cp1(ctx, OPC_CTC1, rt, rs);
19548 break;
19549 case NM_MFC1:
19550 gen_cp1(ctx, OPC_MFC1, rt, rs);
19551 break;
19552 case NM_MTC1:
19553 gen_cp1(ctx, OPC_MTC1, rt, rs);
19554 break;
19555 case NM_MFHC1:
19556 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19557 break;
19558 case NM_MTHC1:
19559 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19560 break;
19561 case NM_CVT_S_PL:
19562 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19563 break;
19564 case NM_CVT_S_PU:
19565 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19566 break;
19567 default:
19568 switch (extract32(ctx->opcode, 6, 9)) {
19569 case NM_CVT_L_S:
19570 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19571 break;
19572 case NM_CVT_L_D:
19573 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19574 break;
19575 case NM_CVT_W_S:
19576 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19577 break;
19578 case NM_CVT_W_D:
19579 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19580 break;
19581 case NM_RSQRT_S:
19582 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19583 break;
19584 case NM_RSQRT_D:
19585 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19586 break;
19587 case NM_SQRT_S:
19588 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19589 break;
19590 case NM_SQRT_D:
19591 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19592 break;
19593 case NM_RECIP_S:
19594 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19595 break;
19596 case NM_RECIP_D:
19597 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19598 break;
19599 case NM_FLOOR_L_S:
19600 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19601 break;
19602 case NM_FLOOR_L_D:
19603 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19604 break;
19605 case NM_FLOOR_W_S:
19606 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19607 break;
19608 case NM_FLOOR_W_D:
19609 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19610 break;
19611 case NM_CEIL_L_S:
19612 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19613 break;
19614 case NM_CEIL_L_D:
19615 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19616 break;
19617 case NM_CEIL_W_S:
19618 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19619 break;
19620 case NM_CEIL_W_D:
19621 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19622 break;
19623 case NM_TRUNC_L_S:
19624 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19625 break;
19626 case NM_TRUNC_L_D:
19627 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19628 break;
19629 case NM_TRUNC_W_S:
19630 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19631 break;
19632 case NM_TRUNC_W_D:
19633 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19634 break;
19635 case NM_ROUND_L_S:
19636 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19637 break;
19638 case NM_ROUND_L_D:
19639 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19640 break;
19641 case NM_ROUND_W_S:
19642 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19643 break;
19644 case NM_ROUND_W_D:
19645 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19646 break;
19647 case NM_MOV_S:
19648 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19649 break;
19650 case NM_MOV_D:
19651 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19652 break;
19653 case NM_ABS_S:
19654 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19655 break;
19656 case NM_ABS_D:
19657 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19658 break;
19659 case NM_NEG_S:
19660 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19661 break;
19662 case NM_NEG_D:
19663 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19664 break;
19665 case NM_CVT_D_S:
19666 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19667 break;
19668 case NM_CVT_D_W:
19669 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19670 break;
19671 case NM_CVT_D_L:
19672 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19673 break;
19674 case NM_CVT_S_D:
19675 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19676 break;
19677 case NM_CVT_S_W:
19678 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19679 break;
19680 case NM_CVT_S_L:
19681 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19682 break;
19683 default:
19684 generate_exception_end(ctx, EXCP_RI);
19685 break;
19687 break;
19689 break;
19691 break;
19692 case NM_POOL32F_5:
19693 switch (extract32(ctx->opcode, 3, 3)) {
19694 case NM_CMP_CONDN_S:
19695 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19696 break;
19697 case NM_CMP_CONDN_D:
19698 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19699 break;
19700 default:
19701 generate_exception_end(ctx, EXCP_RI);
19702 break;
19704 break;
19705 default:
19706 generate_exception_end(ctx, EXCP_RI);
19707 break;
19711 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19712 int rd, int rs, int rt)
19714 int ret = rd;
19715 TCGv t0 = tcg_temp_new();
19716 TCGv v1_t = tcg_temp_new();
19717 TCGv v2_t = tcg_temp_new();
19719 gen_load_gpr(v1_t, rs);
19720 gen_load_gpr(v2_t, rt);
19722 switch (opc) {
19723 case NM_CMP_EQ_PH:
19724 check_dsp(ctx);
19725 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19726 break;
19727 case NM_CMP_LT_PH:
19728 check_dsp(ctx);
19729 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19730 break;
19731 case NM_CMP_LE_PH:
19732 check_dsp(ctx);
19733 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19734 break;
19735 case NM_CMPU_EQ_QB:
19736 check_dsp(ctx);
19737 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19738 break;
19739 case NM_CMPU_LT_QB:
19740 check_dsp(ctx);
19741 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19742 break;
19743 case NM_CMPU_LE_QB:
19744 check_dsp(ctx);
19745 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19746 break;
19747 case NM_CMPGU_EQ_QB:
19748 check_dsp(ctx);
19749 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19750 gen_store_gpr(v1_t, ret);
19751 break;
19752 case NM_CMPGU_LT_QB:
19753 check_dsp(ctx);
19754 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19755 gen_store_gpr(v1_t, ret);
19756 break;
19757 case NM_CMPGU_LE_QB:
19758 check_dsp(ctx);
19759 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19760 gen_store_gpr(v1_t, ret);
19761 break;
19762 case NM_CMPGDU_EQ_QB:
19763 check_dsp_r2(ctx);
19764 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19765 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19766 gen_store_gpr(v1_t, ret);
19767 break;
19768 case NM_CMPGDU_LT_QB:
19769 check_dsp_r2(ctx);
19770 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19771 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19772 gen_store_gpr(v1_t, ret);
19773 break;
19774 case NM_CMPGDU_LE_QB:
19775 check_dsp_r2(ctx);
19776 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19777 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19778 gen_store_gpr(v1_t, ret);
19779 break;
19780 case NM_PACKRL_PH:
19781 check_dsp(ctx);
19782 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19783 gen_store_gpr(v1_t, ret);
19784 break;
19785 case NM_PICK_QB:
19786 check_dsp(ctx);
19787 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19788 gen_store_gpr(v1_t, ret);
19789 break;
19790 case NM_PICK_PH:
19791 check_dsp(ctx);
19792 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19793 gen_store_gpr(v1_t, ret);
19794 break;
19795 case NM_ADDQ_S_W:
19796 check_dsp(ctx);
19797 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19798 gen_store_gpr(v1_t, ret);
19799 break;
19800 case NM_SUBQ_S_W:
19801 check_dsp(ctx);
19802 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19803 gen_store_gpr(v1_t, ret);
19804 break;
19805 case NM_ADDSC:
19806 check_dsp(ctx);
19807 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19808 gen_store_gpr(v1_t, ret);
19809 break;
19810 case NM_ADDWC:
19811 check_dsp(ctx);
19812 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19813 gen_store_gpr(v1_t, ret);
19814 break;
19815 case NM_ADDQ_S_PH:
19816 check_dsp(ctx);
19817 switch (extract32(ctx->opcode, 10, 1)) {
19818 case 0:
19819 /* ADDQ_PH */
19820 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19821 gen_store_gpr(v1_t, ret);
19822 break;
19823 case 1:
19824 /* ADDQ_S_PH */
19825 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19826 gen_store_gpr(v1_t, ret);
19827 break;
19829 break;
19830 case NM_ADDQH_R_PH:
19831 check_dsp_r2(ctx);
19832 switch (extract32(ctx->opcode, 10, 1)) {
19833 case 0:
19834 /* ADDQH_PH */
19835 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19836 gen_store_gpr(v1_t, ret);
19837 break;
19838 case 1:
19839 /* ADDQH_R_PH */
19840 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19841 gen_store_gpr(v1_t, ret);
19842 break;
19844 break;
19845 case NM_ADDQH_R_W:
19846 check_dsp_r2(ctx);
19847 switch (extract32(ctx->opcode, 10, 1)) {
19848 case 0:
19849 /* ADDQH_W */
19850 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19851 gen_store_gpr(v1_t, ret);
19852 break;
19853 case 1:
19854 /* ADDQH_R_W */
19855 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19856 gen_store_gpr(v1_t, ret);
19857 break;
19859 break;
19860 case NM_ADDU_S_QB:
19861 check_dsp(ctx);
19862 switch (extract32(ctx->opcode, 10, 1)) {
19863 case 0:
19864 /* ADDU_QB */
19865 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19866 gen_store_gpr(v1_t, ret);
19867 break;
19868 case 1:
19869 /* ADDU_S_QB */
19870 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19871 gen_store_gpr(v1_t, ret);
19872 break;
19874 break;
19875 case NM_ADDU_S_PH:
19876 check_dsp_r2(ctx);
19877 switch (extract32(ctx->opcode, 10, 1)) {
19878 case 0:
19879 /* ADDU_PH */
19880 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19881 gen_store_gpr(v1_t, ret);
19882 break;
19883 case 1:
19884 /* ADDU_S_PH */
19885 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19886 gen_store_gpr(v1_t, ret);
19887 break;
19889 break;
19890 case NM_ADDUH_R_QB:
19891 check_dsp_r2(ctx);
19892 switch (extract32(ctx->opcode, 10, 1)) {
19893 case 0:
19894 /* ADDUH_QB */
19895 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19896 gen_store_gpr(v1_t, ret);
19897 break;
19898 case 1:
19899 /* ADDUH_R_QB */
19900 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19901 gen_store_gpr(v1_t, ret);
19902 break;
19904 break;
19905 case NM_SHRAV_R_PH:
19906 check_dsp(ctx);
19907 switch (extract32(ctx->opcode, 10, 1)) {
19908 case 0:
19909 /* SHRAV_PH */
19910 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19911 gen_store_gpr(v1_t, ret);
19912 break;
19913 case 1:
19914 /* SHRAV_R_PH */
19915 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19916 gen_store_gpr(v1_t, ret);
19917 break;
19919 break;
19920 case NM_SHRAV_R_QB:
19921 check_dsp_r2(ctx);
19922 switch (extract32(ctx->opcode, 10, 1)) {
19923 case 0:
19924 /* SHRAV_QB */
19925 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19926 gen_store_gpr(v1_t, ret);
19927 break;
19928 case 1:
19929 /* SHRAV_R_QB */
19930 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19931 gen_store_gpr(v1_t, ret);
19932 break;
19934 break;
19935 case NM_SUBQ_S_PH:
19936 check_dsp(ctx);
19937 switch (extract32(ctx->opcode, 10, 1)) {
19938 case 0:
19939 /* SUBQ_PH */
19940 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19941 gen_store_gpr(v1_t, ret);
19942 break;
19943 case 1:
19944 /* SUBQ_S_PH */
19945 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19946 gen_store_gpr(v1_t, ret);
19947 break;
19949 break;
19950 case NM_SUBQH_R_PH:
19951 check_dsp_r2(ctx);
19952 switch (extract32(ctx->opcode, 10, 1)) {
19953 case 0:
19954 /* SUBQH_PH */
19955 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19956 gen_store_gpr(v1_t, ret);
19957 break;
19958 case 1:
19959 /* SUBQH_R_PH */
19960 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19961 gen_store_gpr(v1_t, ret);
19962 break;
19964 break;
19965 case NM_SUBQH_R_W:
19966 check_dsp_r2(ctx);
19967 switch (extract32(ctx->opcode, 10, 1)) {
19968 case 0:
19969 /* SUBQH_W */
19970 gen_helper_subqh_w(v1_t, v1_t, v2_t);
19971 gen_store_gpr(v1_t, ret);
19972 break;
19973 case 1:
19974 /* SUBQH_R_W */
19975 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
19976 gen_store_gpr(v1_t, ret);
19977 break;
19979 break;
19980 case NM_SUBU_S_QB:
19981 check_dsp(ctx);
19982 switch (extract32(ctx->opcode, 10, 1)) {
19983 case 0:
19984 /* SUBU_QB */
19985 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
19986 gen_store_gpr(v1_t, ret);
19987 break;
19988 case 1:
19989 /* SUBU_S_QB */
19990 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19991 gen_store_gpr(v1_t, ret);
19992 break;
19994 break;
19995 case NM_SUBU_S_PH:
19996 check_dsp_r2(ctx);
19997 switch (extract32(ctx->opcode, 10, 1)) {
19998 case 0:
19999 /* SUBU_PH */
20000 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20001 gen_store_gpr(v1_t, ret);
20002 break;
20003 case 1:
20004 /* SUBU_S_PH */
20005 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20006 gen_store_gpr(v1_t, ret);
20007 break;
20009 break;
20010 case NM_SUBUH_R_QB:
20011 check_dsp_r2(ctx);
20012 switch (extract32(ctx->opcode, 10, 1)) {
20013 case 0:
20014 /* SUBUH_QB */
20015 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20016 gen_store_gpr(v1_t, ret);
20017 break;
20018 case 1:
20019 /* SUBUH_R_QB */
20020 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20021 gen_store_gpr(v1_t, ret);
20022 break;
20024 break;
20025 case NM_SHLLV_S_PH:
20026 check_dsp(ctx);
20027 switch (extract32(ctx->opcode, 10, 1)) {
20028 case 0:
20029 /* SHLLV_PH */
20030 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20031 gen_store_gpr(v1_t, ret);
20032 break;
20033 case 1:
20034 /* SHLLV_S_PH */
20035 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20036 gen_store_gpr(v1_t, ret);
20037 break;
20039 break;
20040 case NM_PRECR_SRA_R_PH_W:
20041 check_dsp_r2(ctx);
20042 switch (extract32(ctx->opcode, 10, 1)) {
20043 case 0:
20044 /* PRECR_SRA_PH_W */
20046 TCGv_i32 sa_t = tcg_const_i32(rd);
20047 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20048 cpu_gpr[rt]);
20049 gen_store_gpr(v1_t, rt);
20050 tcg_temp_free_i32(sa_t);
20052 break;
20053 case 1:
20054 /* PRECR_SRA_R_PH_W */
20056 TCGv_i32 sa_t = tcg_const_i32(rd);
20057 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20058 cpu_gpr[rt]);
20059 gen_store_gpr(v1_t, rt);
20060 tcg_temp_free_i32(sa_t);
20062 break;
20064 break;
20065 case NM_MULEU_S_PH_QBL:
20066 check_dsp(ctx);
20067 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20068 gen_store_gpr(v1_t, ret);
20069 break;
20070 case NM_MULEU_S_PH_QBR:
20071 check_dsp(ctx);
20072 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20073 gen_store_gpr(v1_t, ret);
20074 break;
20075 case NM_MULQ_RS_PH:
20076 check_dsp(ctx);
20077 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20078 gen_store_gpr(v1_t, ret);
20079 break;
20080 case NM_MULQ_S_PH:
20081 check_dsp_r2(ctx);
20082 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20083 gen_store_gpr(v1_t, ret);
20084 break;
20085 case NM_MULQ_RS_W:
20086 check_dsp_r2(ctx);
20087 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20088 gen_store_gpr(v1_t, ret);
20089 break;
20090 case NM_MULQ_S_W:
20091 check_dsp_r2(ctx);
20092 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20093 gen_store_gpr(v1_t, ret);
20094 break;
20095 case NM_APPEND:
20096 check_dsp_r2(ctx);
20097 gen_load_gpr(t0, rs);
20098 if (rd != 0) {
20099 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20101 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20102 break;
20103 case NM_MODSUB:
20104 check_dsp(ctx);
20105 gen_helper_modsub(v1_t, v1_t, v2_t);
20106 gen_store_gpr(v1_t, ret);
20107 break;
20108 case NM_SHRAV_R_W:
20109 check_dsp(ctx);
20110 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20111 gen_store_gpr(v1_t, ret);
20112 break;
20113 case NM_SHRLV_PH:
20114 check_dsp_r2(ctx);
20115 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20116 gen_store_gpr(v1_t, ret);
20117 break;
20118 case NM_SHRLV_QB:
20119 check_dsp(ctx);
20120 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20121 gen_store_gpr(v1_t, ret);
20122 break;
20123 case NM_SHLLV_QB:
20124 check_dsp(ctx);
20125 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20126 gen_store_gpr(v1_t, ret);
20127 break;
20128 case NM_SHLLV_S_W:
20129 check_dsp(ctx);
20130 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20131 gen_store_gpr(v1_t, ret);
20132 break;
20133 case NM_SHILO:
20134 check_dsp(ctx);
20136 TCGv tv0 = tcg_temp_new();
20137 TCGv tv1 = tcg_temp_new();
20138 int16_t imm = extract32(ctx->opcode, 16, 7);
20140 tcg_gen_movi_tl(tv0, rd >> 3);
20141 tcg_gen_movi_tl(tv1, imm);
20142 gen_helper_shilo(tv0, tv1, cpu_env);
20144 break;
20145 case NM_MULEQ_S_W_PHL:
20146 check_dsp(ctx);
20147 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20148 gen_store_gpr(v1_t, ret);
20149 break;
20150 case NM_MULEQ_S_W_PHR:
20151 check_dsp(ctx);
20152 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20153 gen_store_gpr(v1_t, ret);
20154 break;
20155 case NM_MUL_S_PH:
20156 check_dsp_r2(ctx);
20157 switch (extract32(ctx->opcode, 10, 1)) {
20158 case 0:
20159 /* MUL_PH */
20160 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20161 gen_store_gpr(v1_t, ret);
20162 break;
20163 case 1:
20164 /* MUL_S_PH */
20165 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20166 gen_store_gpr(v1_t, ret);
20167 break;
20169 break;
20170 case NM_PRECR_QB_PH:
20171 check_dsp_r2(ctx);
20172 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20173 gen_store_gpr(v1_t, ret);
20174 break;
20175 case NM_PRECRQ_QB_PH:
20176 check_dsp(ctx);
20177 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20178 gen_store_gpr(v1_t, ret);
20179 break;
20180 case NM_PRECRQ_PH_W:
20181 check_dsp(ctx);
20182 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20183 gen_store_gpr(v1_t, ret);
20184 break;
20185 case NM_PRECRQ_RS_PH_W:
20186 check_dsp(ctx);
20187 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20188 gen_store_gpr(v1_t, ret);
20189 break;
20190 case NM_PRECRQU_S_QB_PH:
20191 check_dsp(ctx);
20192 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20193 gen_store_gpr(v1_t, ret);
20194 break;
20195 case NM_SHRA_R_W:
20196 check_dsp(ctx);
20197 tcg_gen_movi_tl(t0, rd);
20198 gen_helper_shra_r_w(v1_t, t0, v1_t);
20199 gen_store_gpr(v1_t, rt);
20200 break;
20201 case NM_SHRA_R_PH:
20202 check_dsp(ctx);
20203 tcg_gen_movi_tl(t0, rd >> 1);
20204 switch (extract32(ctx->opcode, 10, 1)) {
20205 case 0:
20206 /* SHRA_PH */
20207 gen_helper_shra_ph(v1_t, t0, v1_t);
20208 gen_store_gpr(v1_t, rt);
20209 break;
20210 case 1:
20211 /* SHRA_R_PH */
20212 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20213 gen_store_gpr(v1_t, rt);
20214 break;
20216 break;
20217 case NM_SHLL_S_PH:
20218 check_dsp(ctx);
20219 tcg_gen_movi_tl(t0, rd >> 1);
20220 switch (extract32(ctx->opcode, 10, 2)) {
20221 case 0:
20222 /* SHLL_PH */
20223 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20224 gen_store_gpr(v1_t, rt);
20225 break;
20226 case 2:
20227 /* SHLL_S_PH */
20228 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20229 gen_store_gpr(v1_t, rt);
20230 break;
20231 default:
20232 generate_exception_end(ctx, EXCP_RI);
20233 break;
20235 break;
20236 case NM_SHLL_S_W:
20237 check_dsp(ctx);
20238 tcg_gen_movi_tl(t0, rd);
20239 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20240 gen_store_gpr(v1_t, rt);
20241 break;
20242 case NM_REPL_PH:
20243 check_dsp(ctx);
20245 int16_t imm;
20246 imm = sextract32(ctx->opcode, 11, 11);
20247 imm = (int16_t)(imm << 6) >> 6;
20248 if (rt != 0) {
20249 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20252 break;
20253 default:
20254 generate_exception_end(ctx, EXCP_RI);
20255 break;
20259 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20261 uint16_t insn;
20262 uint32_t op;
20263 int rt, rs, rd;
20264 int offset;
20265 int imm;
20267 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20268 ctx->opcode = (ctx->opcode << 16) | insn;
20270 rt = extract32(ctx->opcode, 21, 5);
20271 rs = extract32(ctx->opcode, 16, 5);
20272 rd = extract32(ctx->opcode, 11, 5);
20274 op = extract32(ctx->opcode, 26, 6);
20275 switch (op) {
20276 case NM_P_ADDIU:
20277 if (rt == 0) {
20278 /* P.RI */
20279 switch (extract32(ctx->opcode, 19, 2)) {
20280 case NM_SIGRIE:
20281 default:
20282 generate_exception_end(ctx, EXCP_RI);
20283 break;
20284 case NM_P_SYSCALL:
20285 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20286 generate_exception_end(ctx, EXCP_SYSCALL);
20287 } else {
20288 generate_exception_end(ctx, EXCP_RI);
20290 break;
20291 case NM_BREAK:
20292 generate_exception_end(ctx, EXCP_BREAK);
20293 break;
20294 case NM_SDBBP:
20295 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20296 gen_helper_do_semihosting(cpu_env);
20297 } else {
20298 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20299 generate_exception_end(ctx, EXCP_RI);
20300 } else {
20301 generate_exception_end(ctx, EXCP_DBp);
20304 break;
20306 } else {
20307 /* NM_ADDIU */
20308 imm = extract32(ctx->opcode, 0, 16);
20309 if (rs != 0) {
20310 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20311 } else {
20312 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20314 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20316 break;
20317 case NM_ADDIUPC:
20318 if (rt != 0) {
20319 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20320 extract32(ctx->opcode, 1, 20) << 1;
20321 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20322 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20324 break;
20325 case NM_POOL32A:
20326 switch (ctx->opcode & 0x07) {
20327 case NM_POOL32A0:
20328 gen_pool32a0_nanomips_insn(env, ctx);
20329 break;
20330 case NM_POOL32A5:
20332 int32_t op1 = extract32(ctx->opcode, 3, 7);
20333 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20335 break;
20336 case NM_POOL32A7:
20337 switch (extract32(ctx->opcode, 3, 3)) {
20338 case NM_P_LSX:
20339 gen_p_lsx(ctx, rd, rs, rt);
20340 break;
20341 case NM_LSA:
20342 /* In nanoMIPS, the shift field directly encodes the shift
20343 * amount, meaning that the supported shift values are in
20344 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20345 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20346 extract32(ctx->opcode, 9, 2) - 1);
20347 break;
20348 case NM_EXTW:
20349 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20350 break;
20351 case NM_POOL32AXF:
20352 gen_pool32axf_nanomips_insn(env, ctx);
20353 break;
20354 default:
20355 generate_exception_end(ctx, EXCP_RI);
20356 break;
20358 break;
20359 default:
20360 generate_exception_end(ctx, EXCP_RI);
20361 break;
20363 break;
20364 case NM_P_GP_W:
20365 switch (ctx->opcode & 0x03) {
20366 case NM_ADDIUGP_W:
20367 if (rt != 0) {
20368 offset = extract32(ctx->opcode, 0, 21);
20369 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20371 break;
20372 case NM_LWGP:
20373 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20374 break;
20375 case NM_SWGP:
20376 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20377 break;
20378 default:
20379 generate_exception_end(ctx, EXCP_RI);
20380 break;
20382 break;
20383 case NM_P48I:
20385 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20386 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20387 switch (extract32(ctx->opcode, 16, 5)) {
20388 case NM_LI48:
20389 check_nms(ctx);
20390 if (rt != 0) {
20391 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20393 break;
20394 case NM_ADDIU48:
20395 check_nms(ctx);
20396 if (rt != 0) {
20397 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20398 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20400 break;
20401 case NM_ADDIUGP48:
20402 check_nms(ctx);
20403 if (rt != 0) {
20404 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20406 break;
20407 case NM_ADDIUPC48:
20408 check_nms(ctx);
20409 if (rt != 0) {
20410 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20411 addr_off);
20413 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20415 break;
20416 case NM_LWPC48:
20417 check_nms(ctx);
20418 if (rt != 0) {
20419 TCGv t0;
20420 t0 = tcg_temp_new();
20422 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20423 addr_off);
20425 tcg_gen_movi_tl(t0, addr);
20426 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20427 tcg_temp_free(t0);
20429 break;
20430 case NM_SWPC48:
20431 check_nms(ctx);
20433 TCGv t0, t1;
20434 t0 = tcg_temp_new();
20435 t1 = tcg_temp_new();
20437 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20438 addr_off);
20440 tcg_gen_movi_tl(t0, addr);
20441 gen_load_gpr(t1, rt);
20443 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20445 tcg_temp_free(t0);
20446 tcg_temp_free(t1);
20448 break;
20449 default:
20450 generate_exception_end(ctx, EXCP_RI);
20451 break;
20453 return 6;
20455 case NM_P_U12:
20456 switch (extract32(ctx->opcode, 12, 4)) {
20457 case NM_ORI:
20458 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20459 break;
20460 case NM_XORI:
20461 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20462 break;
20463 case NM_ANDI:
20464 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20465 break;
20466 case NM_P_SR:
20467 switch (extract32(ctx->opcode, 20, 1)) {
20468 case NM_PP_SR:
20469 switch (ctx->opcode & 3) {
20470 case NM_SAVE:
20471 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20472 extract32(ctx->opcode, 2, 1),
20473 extract32(ctx->opcode, 3, 9) << 3);
20474 break;
20475 case NM_RESTORE:
20476 case NM_RESTORE_JRC:
20477 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20478 extract32(ctx->opcode, 2, 1),
20479 extract32(ctx->opcode, 3, 9) << 3);
20480 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20481 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20483 break;
20484 default:
20485 generate_exception_end(ctx, EXCP_RI);
20486 break;
20488 break;
20489 case NM_P_SR_F:
20490 generate_exception_end(ctx, EXCP_RI);
20491 break;
20493 break;
20494 case NM_SLTI:
20495 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20496 break;
20497 case NM_SLTIU:
20498 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20499 break;
20500 case NM_SEQI:
20502 TCGv t0 = tcg_temp_new();
20504 imm = extract32(ctx->opcode, 0, 12);
20505 gen_load_gpr(t0, rs);
20506 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20507 gen_store_gpr(t0, rt);
20509 tcg_temp_free(t0);
20511 break;
20512 case NM_ADDIUNEG:
20513 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20514 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20515 break;
20516 case NM_P_SHIFT:
20518 int shift = extract32(ctx->opcode, 0, 5);
20519 switch (extract32(ctx->opcode, 5, 4)) {
20520 case NM_P_SLL:
20521 if (rt == 0 && shift == 0) {
20522 /* NOP */
20523 } else if (rt == 0 && shift == 3) {
20524 /* EHB - treat as NOP */
20525 } else if (rt == 0 && shift == 5) {
20526 /* PAUSE - treat as NOP */
20527 } else if (rt == 0 && shift == 6) {
20528 /* SYNC */
20529 gen_sync(extract32(ctx->opcode, 16, 5));
20530 } else {
20531 /* SLL */
20532 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20533 extract32(ctx->opcode, 0, 5));
20535 break;
20536 case NM_SRL:
20537 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20538 extract32(ctx->opcode, 0, 5));
20539 break;
20540 case NM_SRA:
20541 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20542 extract32(ctx->opcode, 0, 5));
20543 break;
20544 case NM_ROTR:
20545 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20546 extract32(ctx->opcode, 0, 5));
20547 break;
20550 break;
20551 case NM_P_ROTX:
20552 check_nms(ctx);
20553 if (rt != 0) {
20554 TCGv t0 = tcg_temp_new();
20555 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20556 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20557 << 1);
20558 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20560 gen_load_gpr(t0, rs);
20561 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20562 tcg_temp_free(t0);
20564 tcg_temp_free_i32(shift);
20565 tcg_temp_free_i32(shiftx);
20566 tcg_temp_free_i32(stripe);
20568 break;
20569 case NM_P_INS:
20570 switch (((ctx->opcode >> 10) & 2) |
20571 (extract32(ctx->opcode, 5, 1))) {
20572 case NM_INS:
20573 check_nms(ctx);
20574 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20575 extract32(ctx->opcode, 6, 5));
20576 break;
20577 default:
20578 generate_exception_end(ctx, EXCP_RI);
20579 break;
20581 break;
20582 case NM_P_EXT:
20583 switch (((ctx->opcode >> 10) & 2) |
20584 (extract32(ctx->opcode, 5, 1))) {
20585 case NM_EXT:
20586 check_nms(ctx);
20587 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20588 extract32(ctx->opcode, 6, 5));
20589 break;
20590 default:
20591 generate_exception_end(ctx, EXCP_RI);
20592 break;
20594 break;
20595 default:
20596 generate_exception_end(ctx, EXCP_RI);
20597 break;
20599 break;
20600 case NM_POOL32F:
20601 gen_pool32f_nanomips_insn(ctx);
20602 break;
20603 case NM_POOL32S:
20604 break;
20605 case NM_P_LUI:
20606 switch (extract32(ctx->opcode, 1, 1)) {
20607 case NM_LUI:
20608 if (rt != 0) {
20609 tcg_gen_movi_tl(cpu_gpr[rt],
20610 sextract32(ctx->opcode, 0, 1) << 31 |
20611 extract32(ctx->opcode, 2, 10) << 21 |
20612 extract32(ctx->opcode, 12, 9) << 12);
20614 break;
20615 case NM_ALUIPC:
20616 if (rt != 0) {
20617 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20618 extract32(ctx->opcode, 2, 10) << 21 |
20619 extract32(ctx->opcode, 12, 9) << 12;
20620 target_long addr;
20621 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20622 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20624 break;
20626 break;
20627 case NM_P_GP_BH:
20629 uint32_t u = extract32(ctx->opcode, 0, 18);
20631 switch (extract32(ctx->opcode, 18, 3)) {
20632 case NM_LBGP:
20633 gen_ld(ctx, OPC_LB, rt, 28, u);
20634 break;
20635 case NM_SBGP:
20636 gen_st(ctx, OPC_SB, rt, 28, u);
20637 break;
20638 case NM_LBUGP:
20639 gen_ld(ctx, OPC_LBU, rt, 28, u);
20640 break;
20641 case NM_ADDIUGP_B:
20642 if (rt != 0) {
20643 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20645 break;
20646 case NM_P_GP_LH:
20647 u &= ~1;
20648 switch (ctx->opcode & 1) {
20649 case NM_LHGP:
20650 gen_ld(ctx, OPC_LH, rt, 28, u);
20651 break;
20652 case NM_LHUGP:
20653 gen_ld(ctx, OPC_LHU, rt, 28, u);
20654 break;
20656 break;
20657 case NM_P_GP_SH:
20658 u &= ~1;
20659 switch (ctx->opcode & 1) {
20660 case NM_SHGP:
20661 gen_st(ctx, OPC_SH, rt, 28, u);
20662 break;
20663 default:
20664 generate_exception_end(ctx, EXCP_RI);
20665 break;
20667 break;
20668 case NM_P_GP_CP1:
20669 u &= ~0x3;
20670 switch (ctx->opcode & 0x3) {
20671 case NM_LWC1GP:
20672 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20673 break;
20674 case NM_LDC1GP:
20675 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20676 break;
20677 case NM_SWC1GP:
20678 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20679 break;
20680 case NM_SDC1GP:
20681 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20682 break;
20684 break;
20685 default:
20686 generate_exception_end(ctx, EXCP_RI);
20687 break;
20690 break;
20691 case NM_P_LS_U12:
20693 uint32_t u = extract32(ctx->opcode, 0, 12);
20695 switch (extract32(ctx->opcode, 12, 4)) {
20696 case NM_P_PREFU12:
20697 if (rt == 31) {
20698 /* SYNCI */
20699 /* Break the TB to be able to sync copied instructions
20700 immediately */
20701 ctx->base.is_jmp = DISAS_STOP;
20702 } else {
20703 /* PREF */
20704 /* Treat as NOP. */
20706 break;
20707 case NM_LB:
20708 gen_ld(ctx, OPC_LB, rt, rs, u);
20709 break;
20710 case NM_LH:
20711 gen_ld(ctx, OPC_LH, rt, rs, u);
20712 break;
20713 case NM_LW:
20714 gen_ld(ctx, OPC_LW, rt, rs, u);
20715 break;
20716 case NM_LBU:
20717 gen_ld(ctx, OPC_LBU, rt, rs, u);
20718 break;
20719 case NM_LHU:
20720 gen_ld(ctx, OPC_LHU, rt, rs, u);
20721 break;
20722 case NM_SB:
20723 gen_st(ctx, OPC_SB, rt, rs, u);
20724 break;
20725 case NM_SH:
20726 gen_st(ctx, OPC_SH, rt, rs, u);
20727 break;
20728 case NM_SW:
20729 gen_st(ctx, OPC_SW, rt, rs, u);
20730 break;
20731 case NM_LWC1:
20732 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20733 break;
20734 case NM_LDC1:
20735 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20736 break;
20737 case NM_SWC1:
20738 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20739 break;
20740 case NM_SDC1:
20741 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20742 break;
20743 default:
20744 generate_exception_end(ctx, EXCP_RI);
20745 break;
20748 break;
20749 case NM_P_LS_S9:
20751 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20752 extract32(ctx->opcode, 0, 8);
20754 switch (extract32(ctx->opcode, 8, 3)) {
20755 case NM_P_LS_S0:
20756 switch (extract32(ctx->opcode, 11, 4)) {
20757 case NM_LBS9:
20758 gen_ld(ctx, OPC_LB, rt, rs, s);
20759 break;
20760 case NM_LHS9:
20761 gen_ld(ctx, OPC_LH, rt, rs, s);
20762 break;
20763 case NM_LWS9:
20764 gen_ld(ctx, OPC_LW, rt, rs, s);
20765 break;
20766 case NM_LBUS9:
20767 gen_ld(ctx, OPC_LBU, rt, rs, s);
20768 break;
20769 case NM_LHUS9:
20770 gen_ld(ctx, OPC_LHU, rt, rs, s);
20771 break;
20772 case NM_SBS9:
20773 gen_st(ctx, OPC_SB, rt, rs, s);
20774 break;
20775 case NM_SHS9:
20776 gen_st(ctx, OPC_SH, rt, rs, s);
20777 break;
20778 case NM_SWS9:
20779 gen_st(ctx, OPC_SW, rt, rs, s);
20780 break;
20781 case NM_LWC1S9:
20782 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20783 break;
20784 case NM_LDC1S9:
20785 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20786 break;
20787 case NM_SWC1S9:
20788 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20789 break;
20790 case NM_SDC1S9:
20791 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20792 break;
20793 case NM_P_PREFS9:
20794 if (rt == 31) {
20795 /* SYNCI */
20796 /* Break the TB to be able to sync copied instructions
20797 immediately */
20798 ctx->base.is_jmp = DISAS_STOP;
20799 } else {
20800 /* PREF */
20801 /* Treat as NOP. */
20803 break;
20804 default:
20805 generate_exception_end(ctx, EXCP_RI);
20806 break;
20808 break;
20809 case NM_P_LS_S1:
20810 switch (extract32(ctx->opcode, 11, 4)) {
20811 case NM_UALH:
20812 case NM_UASH:
20813 check_nms(ctx);
20815 TCGv t0 = tcg_temp_new();
20816 TCGv t1 = tcg_temp_new();
20818 gen_base_offset_addr(ctx, t0, rs, s);
20820 switch (extract32(ctx->opcode, 11, 4)) {
20821 case NM_UALH:
20822 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20823 MO_UNALN);
20824 gen_store_gpr(t0, rt);
20825 break;
20826 case NM_UASH:
20827 gen_load_gpr(t1, rt);
20828 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20829 MO_UNALN);
20830 break;
20832 tcg_temp_free(t0);
20833 tcg_temp_free(t1);
20835 break;
20836 case NM_P_LL:
20837 switch (ctx->opcode & 0x03) {
20838 case NM_LL:
20839 gen_ld(ctx, OPC_LL, rt, rs, s);
20840 break;
20841 case NM_LLWP:
20842 check_xnp(ctx);
20843 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20844 break;
20846 break;
20847 case NM_P_SC:
20848 switch (ctx->opcode & 0x03) {
20849 case NM_SC:
20850 gen_st_cond(ctx, OPC_SC, rt, rs, s);
20851 break;
20852 case NM_SCWP:
20853 check_xnp(ctx);
20854 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20855 break;
20857 break;
20858 case NM_CACHE:
20859 check_cp0_enabled(ctx);
20860 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20861 gen_cache_operation(ctx, rt, rs, s);
20863 break;
20865 break;
20866 case NM_P_LS_WM:
20867 case NM_P_LS_UAWM:
20868 check_nms(ctx);
20870 int count = extract32(ctx->opcode, 12, 3);
20871 int counter = 0;
20873 offset = sextract32(ctx->opcode, 15, 1) << 8 |
20874 extract32(ctx->opcode, 0, 8);
20875 TCGv va = tcg_temp_new();
20876 TCGv t1 = tcg_temp_new();
20877 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
20878 NM_P_LS_UAWM ? MO_UNALN : 0;
20880 count = (count == 0) ? 8 : count;
20881 while (counter != count) {
20882 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
20883 int this_offset = offset + (counter << 2);
20885 gen_base_offset_addr(ctx, va, rs, this_offset);
20887 switch (extract32(ctx->opcode, 11, 1)) {
20888 case NM_LWM:
20889 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
20890 memop | MO_TESL);
20891 gen_store_gpr(t1, this_rt);
20892 if ((this_rt == rs) &&
20893 (counter != (count - 1))) {
20894 /* UNPREDICTABLE */
20896 break;
20897 case NM_SWM:
20898 this_rt = (rt == 0) ? 0 : this_rt;
20899 gen_load_gpr(t1, this_rt);
20900 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
20901 memop | MO_TEUL);
20902 break;
20904 counter++;
20906 tcg_temp_free(va);
20907 tcg_temp_free(t1);
20909 break;
20910 default:
20911 generate_exception_end(ctx, EXCP_RI);
20912 break;
20915 break;
20916 case NM_MOVE_BALC:
20917 check_nms(ctx);
20919 TCGv t0 = tcg_temp_new();
20920 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
20921 extract32(ctx->opcode, 1, 20) << 1;
20922 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
20923 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
20924 extract32(ctx->opcode, 21, 3));
20925 gen_load_gpr(t0, rt);
20926 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20927 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20928 tcg_temp_free(t0);
20930 break;
20931 case NM_P_BAL:
20933 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
20934 extract32(ctx->opcode, 1, 24) << 1;
20936 if ((extract32(ctx->opcode, 25, 1)) == 0) {
20937 /* BC */
20938 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
20939 } else {
20940 /* BALC */
20941 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20944 break;
20945 case NM_P_J:
20946 switch (extract32(ctx->opcode, 12, 4)) {
20947 case NM_JALRC:
20948 case NM_JALRC_HB:
20949 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
20950 break;
20951 case NM_P_BALRSC:
20952 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
20953 break;
20954 default:
20955 generate_exception_end(ctx, EXCP_RI);
20956 break;
20958 break;
20959 case NM_P_BR1:
20961 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20962 extract32(ctx->opcode, 1, 13) << 1;
20963 switch (extract32(ctx->opcode, 14, 2)) {
20964 case NM_BEQC:
20965 check_nms(ctx);
20966 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
20967 break;
20968 case NM_P_BR3A:
20969 s = sextract32(ctx->opcode, 0, 1) << 14 |
20970 extract32(ctx->opcode, 1, 13) << 1;
20971 check_cp1_enabled(ctx);
20972 switch (extract32(ctx->opcode, 16, 5)) {
20973 case NM_BC1EQZC:
20974 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
20975 break;
20976 case NM_BC1NEZC:
20977 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
20978 break;
20979 case NM_BPOSGE32C:
20980 check_dsp_r3(ctx);
20982 int32_t imm = extract32(ctx->opcode, 1, 13) |
20983 extract32(ctx->opcode, 0, 1) << 13;
20985 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
20986 imm);
20988 break;
20989 default:
20990 generate_exception_end(ctx, EXCP_RI);
20991 break;
20993 break;
20994 case NM_BGEC:
20995 if (rs == rt) {
20996 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
20997 } else {
20998 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21000 break;
21001 case NM_BGEUC:
21002 if (rs == rt || rt == 0) {
21003 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21004 } else if (rs == 0) {
21005 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21006 } else {
21007 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21009 break;
21012 break;
21013 case NM_P_BR2:
21015 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21016 extract32(ctx->opcode, 1, 13) << 1;
21017 switch (extract32(ctx->opcode, 14, 2)) {
21018 case NM_BNEC:
21019 check_nms(ctx);
21020 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21021 break;
21022 case NM_BLTC:
21023 if (rs != 0 && rt != 0 && rs == rt) {
21024 /* NOP */
21025 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21026 } else {
21027 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21029 break;
21030 case NM_BLTUC:
21031 if (rs == 0 || rs == rt) {
21032 /* NOP */
21033 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21034 } else {
21035 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21037 break;
21038 default:
21039 generate_exception_end(ctx, EXCP_RI);
21040 break;
21043 break;
21044 case NM_P_BRI:
21046 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21047 extract32(ctx->opcode, 1, 10) << 1;
21048 uint32_t u = extract32(ctx->opcode, 11, 7);
21050 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21051 rt, u, s);
21053 break;
21054 default:
21055 generate_exception_end(ctx, EXCP_RI);
21056 break;
21058 return 4;
21061 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21063 uint32_t op;
21064 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21065 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21066 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21067 int offset;
21068 int imm;
21070 /* make sure instructions are on a halfword boundary */
21071 if (ctx->base.pc_next & 0x1) {
21072 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21073 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21074 tcg_temp_free(tmp);
21075 generate_exception_end(ctx, EXCP_AdEL);
21076 return 2;
21079 op = extract32(ctx->opcode, 10, 6);
21080 switch (op) {
21081 case NM_P16_MV:
21082 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21083 if (rt != 0) {
21084 /* MOVE */
21085 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21086 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21087 } else {
21088 /* P16.RI */
21089 switch (extract32(ctx->opcode, 3, 2)) {
21090 case NM_P16_SYSCALL:
21091 if (extract32(ctx->opcode, 2, 1) == 0) {
21092 generate_exception_end(ctx, EXCP_SYSCALL);
21093 } else {
21094 generate_exception_end(ctx, EXCP_RI);
21096 break;
21097 case NM_BREAK16:
21098 generate_exception_end(ctx, EXCP_BREAK);
21099 break;
21100 case NM_SDBBP16:
21101 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21102 gen_helper_do_semihosting(cpu_env);
21103 } else {
21104 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21105 generate_exception_end(ctx, EXCP_RI);
21106 } else {
21107 generate_exception_end(ctx, EXCP_DBp);
21110 break;
21111 default:
21112 generate_exception_end(ctx, EXCP_RI);
21113 break;
21116 break;
21117 case NM_P16_SHIFT:
21119 int shift = extract32(ctx->opcode, 0, 3);
21120 uint32_t opc = 0;
21121 shift = (shift == 0) ? 8 : shift;
21123 switch (extract32(ctx->opcode, 3, 1)) {
21124 case NM_SLL16:
21125 opc = OPC_SLL;
21126 break;
21127 case NM_SRL16:
21128 opc = OPC_SRL;
21129 break;
21131 gen_shift_imm(ctx, opc, rt, rs, shift);
21133 break;
21134 case NM_P16C:
21135 switch (ctx->opcode & 1) {
21136 case NM_POOL16C_0:
21137 gen_pool16c_nanomips_insn(ctx);
21138 break;
21139 case NM_LWXS16:
21140 gen_ldxs(ctx, rt, rs, rd);
21141 break;
21143 break;
21144 case NM_P16_A1:
21145 switch (extract32(ctx->opcode, 6, 1)) {
21146 case NM_ADDIUR1SP:
21147 imm = extract32(ctx->opcode, 0, 6) << 2;
21148 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21149 break;
21150 default:
21151 generate_exception_end(ctx, EXCP_RI);
21152 break;
21154 break;
21155 case NM_P16_A2:
21156 switch (extract32(ctx->opcode, 3, 1)) {
21157 case NM_ADDIUR2:
21158 imm = extract32(ctx->opcode, 0, 3) << 2;
21159 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21160 break;
21161 case NM_P_ADDIURS5:
21162 rt = extract32(ctx->opcode, 5, 5);
21163 if (rt != 0) {
21164 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21165 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21166 (extract32(ctx->opcode, 0, 3));
21167 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21169 break;
21171 break;
21172 case NM_P16_ADDU:
21173 switch (ctx->opcode & 0x1) {
21174 case NM_ADDU16:
21175 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21176 break;
21177 case NM_SUBU16:
21178 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21179 break;
21181 break;
21182 case NM_P16_4X4:
21183 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21184 extract32(ctx->opcode, 5, 3);
21185 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21186 extract32(ctx->opcode, 0, 3);
21187 rt = decode_gpr_gpr4(rt);
21188 rs = decode_gpr_gpr4(rs);
21189 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21190 (extract32(ctx->opcode, 3, 1))) {
21191 case NM_ADDU4X4:
21192 check_nms(ctx);
21193 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21194 break;
21195 case NM_MUL4X4:
21196 check_nms(ctx);
21197 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21198 break;
21199 default:
21200 generate_exception_end(ctx, EXCP_RI);
21201 break;
21203 break;
21204 case NM_LI16:
21206 int imm = extract32(ctx->opcode, 0, 7);
21207 imm = (imm == 0x7f ? -1 : imm);
21208 if (rt != 0) {
21209 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21212 break;
21213 case NM_ANDI16:
21215 uint32_t u = extract32(ctx->opcode, 0, 4);
21216 u = (u == 12) ? 0xff :
21217 (u == 13) ? 0xffff : u;
21218 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21220 break;
21221 case NM_P16_LB:
21222 offset = extract32(ctx->opcode, 0, 2);
21223 switch (extract32(ctx->opcode, 2, 2)) {
21224 case NM_LB16:
21225 gen_ld(ctx, OPC_LB, rt, rs, offset);
21226 break;
21227 case NM_SB16:
21228 rt = decode_gpr_gpr3_src_store(
21229 NANOMIPS_EXTRACT_RD(ctx->opcode));
21230 gen_st(ctx, OPC_SB, rt, rs, offset);
21231 break;
21232 case NM_LBU16:
21233 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21234 break;
21235 default:
21236 generate_exception_end(ctx, EXCP_RI);
21237 break;
21239 break;
21240 case NM_P16_LH:
21241 offset = extract32(ctx->opcode, 1, 2) << 1;
21242 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21243 case NM_LH16:
21244 gen_ld(ctx, OPC_LH, rt, rs, offset);
21245 break;
21246 case NM_SH16:
21247 rt = decode_gpr_gpr3_src_store(
21248 NANOMIPS_EXTRACT_RD(ctx->opcode));
21249 gen_st(ctx, OPC_SH, rt, rs, offset);
21250 break;
21251 case NM_LHU16:
21252 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21253 break;
21254 default:
21255 generate_exception_end(ctx, EXCP_RI);
21256 break;
21258 break;
21259 case NM_LW16:
21260 offset = extract32(ctx->opcode, 0, 4) << 2;
21261 gen_ld(ctx, OPC_LW, rt, rs, offset);
21262 break;
21263 case NM_LWSP16:
21264 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21265 offset = extract32(ctx->opcode, 0, 5) << 2;
21266 gen_ld(ctx, OPC_LW, rt, 29, offset);
21267 break;
21268 case NM_LW4X4:
21269 check_nms(ctx);
21270 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21271 extract32(ctx->opcode, 5, 3);
21272 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21273 extract32(ctx->opcode, 0, 3);
21274 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21275 (extract32(ctx->opcode, 8, 1) << 2);
21276 rt = decode_gpr_gpr4(rt);
21277 rs = decode_gpr_gpr4(rs);
21278 gen_ld(ctx, OPC_LW, rt, rs, offset);
21279 break;
21280 case NM_SW4X4:
21281 check_nms(ctx);
21282 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21283 extract32(ctx->opcode, 5, 3);
21284 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21285 extract32(ctx->opcode, 0, 3);
21286 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21287 (extract32(ctx->opcode, 8, 1) << 2);
21288 rt = decode_gpr_gpr4_zero(rt);
21289 rs = decode_gpr_gpr4(rs);
21290 gen_st(ctx, OPC_SW, rt, rs, offset);
21291 break;
21292 case NM_LWGP16:
21293 offset = extract32(ctx->opcode, 0, 7) << 2;
21294 gen_ld(ctx, OPC_LW, rt, 28, offset);
21295 break;
21296 case NM_SWSP16:
21297 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21298 offset = extract32(ctx->opcode, 0, 5) << 2;
21299 gen_st(ctx, OPC_SW, rt, 29, offset);
21300 break;
21301 case NM_SW16:
21302 rt = decode_gpr_gpr3_src_store(
21303 NANOMIPS_EXTRACT_RD(ctx->opcode));
21304 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21305 offset = extract32(ctx->opcode, 0, 4) << 2;
21306 gen_st(ctx, OPC_SW, rt, rs, offset);
21307 break;
21308 case NM_SWGP16:
21309 rt = decode_gpr_gpr3_src_store(
21310 NANOMIPS_EXTRACT_RD(ctx->opcode));
21311 offset = extract32(ctx->opcode, 0, 7) << 2;
21312 gen_st(ctx, OPC_SW, rt, 28, offset);
21313 break;
21314 case NM_BC16:
21315 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21316 (sextract32(ctx->opcode, 0, 1) << 10) |
21317 (extract32(ctx->opcode, 1, 9) << 1));
21318 break;
21319 case NM_BALC16:
21320 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21321 (sextract32(ctx->opcode, 0, 1) << 10) |
21322 (extract32(ctx->opcode, 1, 9) << 1));
21323 break;
21324 case NM_BEQZC16:
21325 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21326 (sextract32(ctx->opcode, 0, 1) << 7) |
21327 (extract32(ctx->opcode, 1, 6) << 1));
21328 break;
21329 case NM_BNEZC16:
21330 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21331 (sextract32(ctx->opcode, 0, 1) << 7) |
21332 (extract32(ctx->opcode, 1, 6) << 1));
21333 break;
21334 case NM_P16_BR:
21335 switch (ctx->opcode & 0xf) {
21336 case 0:
21337 /* P16.JRC */
21338 switch (extract32(ctx->opcode, 4, 1)) {
21339 case NM_JRC:
21340 gen_compute_branch_nm(ctx, OPC_JR, 2,
21341 extract32(ctx->opcode, 5, 5), 0, 0);
21342 break;
21343 case NM_JALRC16:
21344 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21345 extract32(ctx->opcode, 5, 5), 31, 0);
21346 break;
21348 break;
21349 default:
21351 /* P16.BRI */
21352 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21353 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21354 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21355 extract32(ctx->opcode, 0, 4) << 1);
21357 break;
21359 break;
21360 case NM_P16_SR:
21362 int count = extract32(ctx->opcode, 0, 4);
21363 int u = extract32(ctx->opcode, 4, 4) << 4;
21365 rt = 30 + extract32(ctx->opcode, 9, 1);
21366 switch (extract32(ctx->opcode, 8, 1)) {
21367 case NM_SAVE16:
21368 gen_save(ctx, rt, count, 0, u);
21369 break;
21370 case NM_RESTORE_JRC16:
21371 gen_restore(ctx, rt, count, 0, u);
21372 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21373 break;
21376 break;
21377 case NM_MOVEP:
21378 case NM_MOVEPREV:
21379 check_nms(ctx);
21381 static const int gpr2reg1[] = {4, 5, 6, 7};
21382 static const int gpr2reg2[] = {5, 6, 7, 8};
21383 int re;
21384 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21385 extract32(ctx->opcode, 8, 1);
21386 int r1 = gpr2reg1[rd2];
21387 int r2 = gpr2reg2[rd2];
21388 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21389 extract32(ctx->opcode, 0, 3);
21390 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21391 extract32(ctx->opcode, 5, 3);
21392 TCGv t0 = tcg_temp_new();
21393 TCGv t1 = tcg_temp_new();
21394 if (op == NM_MOVEP) {
21395 rd = r1;
21396 re = r2;
21397 rs = decode_gpr_gpr4_zero(r3);
21398 rt = decode_gpr_gpr4_zero(r4);
21399 } else {
21400 rd = decode_gpr_gpr4(r3);
21401 re = decode_gpr_gpr4(r4);
21402 rs = r1;
21403 rt = r2;
21405 gen_load_gpr(t0, rs);
21406 gen_load_gpr(t1, rt);
21407 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21408 tcg_gen_mov_tl(cpu_gpr[re], t1);
21409 tcg_temp_free(t0);
21410 tcg_temp_free(t1);
21412 break;
21413 default:
21414 return decode_nanomips_32_48_opc(env, ctx);
21417 return 2;
21421 /* SmartMIPS extension to MIPS32 */
21423 #if defined(TARGET_MIPS64)
21425 /* MDMX extension to MIPS64 */
21427 #endif
21429 /* MIPSDSP functions. */
21430 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21431 int rd, int base, int offset)
21433 TCGv t0;
21435 check_dsp(ctx);
21436 t0 = tcg_temp_new();
21438 if (base == 0) {
21439 gen_load_gpr(t0, offset);
21440 } else if (offset == 0) {
21441 gen_load_gpr(t0, base);
21442 } else {
21443 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21446 switch (opc) {
21447 case OPC_LBUX:
21448 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21449 gen_store_gpr(t0, rd);
21450 break;
21451 case OPC_LHX:
21452 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21453 gen_store_gpr(t0, rd);
21454 break;
21455 case OPC_LWX:
21456 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21457 gen_store_gpr(t0, rd);
21458 break;
21459 #if defined(TARGET_MIPS64)
21460 case OPC_LDX:
21461 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21462 gen_store_gpr(t0, rd);
21463 break;
21464 #endif
21466 tcg_temp_free(t0);
21469 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21470 int ret, int v1, int v2)
21472 TCGv v1_t;
21473 TCGv v2_t;
21475 if (ret == 0) {
21476 /* Treat as NOP. */
21477 return;
21480 v1_t = tcg_temp_new();
21481 v2_t = tcg_temp_new();
21483 gen_load_gpr(v1_t, v1);
21484 gen_load_gpr(v2_t, v2);
21486 switch (op1) {
21487 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21488 case OPC_MULT_G_2E:
21489 check_dsp_r2(ctx);
21490 switch (op2) {
21491 case OPC_ADDUH_QB:
21492 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21493 break;
21494 case OPC_ADDUH_R_QB:
21495 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21496 break;
21497 case OPC_ADDQH_PH:
21498 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21499 break;
21500 case OPC_ADDQH_R_PH:
21501 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21502 break;
21503 case OPC_ADDQH_W:
21504 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21505 break;
21506 case OPC_ADDQH_R_W:
21507 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21508 break;
21509 case OPC_SUBUH_QB:
21510 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21511 break;
21512 case OPC_SUBUH_R_QB:
21513 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21514 break;
21515 case OPC_SUBQH_PH:
21516 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21517 break;
21518 case OPC_SUBQH_R_PH:
21519 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21520 break;
21521 case OPC_SUBQH_W:
21522 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21523 break;
21524 case OPC_SUBQH_R_W:
21525 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21526 break;
21528 break;
21529 case OPC_ABSQ_S_PH_DSP:
21530 switch (op2) {
21531 case OPC_ABSQ_S_QB:
21532 check_dsp_r2(ctx);
21533 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21534 break;
21535 case OPC_ABSQ_S_PH:
21536 check_dsp(ctx);
21537 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21538 break;
21539 case OPC_ABSQ_S_W:
21540 check_dsp(ctx);
21541 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21542 break;
21543 case OPC_PRECEQ_W_PHL:
21544 check_dsp(ctx);
21545 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21546 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21547 break;
21548 case OPC_PRECEQ_W_PHR:
21549 check_dsp(ctx);
21550 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21551 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21552 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21553 break;
21554 case OPC_PRECEQU_PH_QBL:
21555 check_dsp(ctx);
21556 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21557 break;
21558 case OPC_PRECEQU_PH_QBR:
21559 check_dsp(ctx);
21560 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21561 break;
21562 case OPC_PRECEQU_PH_QBLA:
21563 check_dsp(ctx);
21564 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21565 break;
21566 case OPC_PRECEQU_PH_QBRA:
21567 check_dsp(ctx);
21568 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21569 break;
21570 case OPC_PRECEU_PH_QBL:
21571 check_dsp(ctx);
21572 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21573 break;
21574 case OPC_PRECEU_PH_QBR:
21575 check_dsp(ctx);
21576 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21577 break;
21578 case OPC_PRECEU_PH_QBLA:
21579 check_dsp(ctx);
21580 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21581 break;
21582 case OPC_PRECEU_PH_QBRA:
21583 check_dsp(ctx);
21584 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21585 break;
21587 break;
21588 case OPC_ADDU_QB_DSP:
21589 switch (op2) {
21590 case OPC_ADDQ_PH:
21591 check_dsp(ctx);
21592 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21593 break;
21594 case OPC_ADDQ_S_PH:
21595 check_dsp(ctx);
21596 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21597 break;
21598 case OPC_ADDQ_S_W:
21599 check_dsp(ctx);
21600 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21601 break;
21602 case OPC_ADDU_QB:
21603 check_dsp(ctx);
21604 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21605 break;
21606 case OPC_ADDU_S_QB:
21607 check_dsp(ctx);
21608 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21609 break;
21610 case OPC_ADDU_PH:
21611 check_dsp_r2(ctx);
21612 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21613 break;
21614 case OPC_ADDU_S_PH:
21615 check_dsp_r2(ctx);
21616 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21617 break;
21618 case OPC_SUBQ_PH:
21619 check_dsp(ctx);
21620 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21621 break;
21622 case OPC_SUBQ_S_PH:
21623 check_dsp(ctx);
21624 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21625 break;
21626 case OPC_SUBQ_S_W:
21627 check_dsp(ctx);
21628 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21629 break;
21630 case OPC_SUBU_QB:
21631 check_dsp(ctx);
21632 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21633 break;
21634 case OPC_SUBU_S_QB:
21635 check_dsp(ctx);
21636 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21637 break;
21638 case OPC_SUBU_PH:
21639 check_dsp_r2(ctx);
21640 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21641 break;
21642 case OPC_SUBU_S_PH:
21643 check_dsp_r2(ctx);
21644 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21645 break;
21646 case OPC_ADDSC:
21647 check_dsp(ctx);
21648 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21649 break;
21650 case OPC_ADDWC:
21651 check_dsp(ctx);
21652 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21653 break;
21654 case OPC_MODSUB:
21655 check_dsp(ctx);
21656 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21657 break;
21658 case OPC_RADDU_W_QB:
21659 check_dsp(ctx);
21660 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21661 break;
21663 break;
21664 case OPC_CMPU_EQ_QB_DSP:
21665 switch (op2) {
21666 case OPC_PRECR_QB_PH:
21667 check_dsp_r2(ctx);
21668 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21669 break;
21670 case OPC_PRECRQ_QB_PH:
21671 check_dsp(ctx);
21672 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21673 break;
21674 case OPC_PRECR_SRA_PH_W:
21675 check_dsp_r2(ctx);
21677 TCGv_i32 sa_t = tcg_const_i32(v2);
21678 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21679 cpu_gpr[ret]);
21680 tcg_temp_free_i32(sa_t);
21681 break;
21683 case OPC_PRECR_SRA_R_PH_W:
21684 check_dsp_r2(ctx);
21686 TCGv_i32 sa_t = tcg_const_i32(v2);
21687 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21688 cpu_gpr[ret]);
21689 tcg_temp_free_i32(sa_t);
21690 break;
21692 case OPC_PRECRQ_PH_W:
21693 check_dsp(ctx);
21694 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21695 break;
21696 case OPC_PRECRQ_RS_PH_W:
21697 check_dsp(ctx);
21698 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21699 break;
21700 case OPC_PRECRQU_S_QB_PH:
21701 check_dsp(ctx);
21702 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21703 break;
21705 break;
21706 #ifdef TARGET_MIPS64
21707 case OPC_ABSQ_S_QH_DSP:
21708 switch (op2) {
21709 case OPC_PRECEQ_L_PWL:
21710 check_dsp(ctx);
21711 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21712 break;
21713 case OPC_PRECEQ_L_PWR:
21714 check_dsp(ctx);
21715 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21716 break;
21717 case OPC_PRECEQ_PW_QHL:
21718 check_dsp(ctx);
21719 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21720 break;
21721 case OPC_PRECEQ_PW_QHR:
21722 check_dsp(ctx);
21723 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21724 break;
21725 case OPC_PRECEQ_PW_QHLA:
21726 check_dsp(ctx);
21727 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21728 break;
21729 case OPC_PRECEQ_PW_QHRA:
21730 check_dsp(ctx);
21731 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21732 break;
21733 case OPC_PRECEQU_QH_OBL:
21734 check_dsp(ctx);
21735 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21736 break;
21737 case OPC_PRECEQU_QH_OBR:
21738 check_dsp(ctx);
21739 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21740 break;
21741 case OPC_PRECEQU_QH_OBLA:
21742 check_dsp(ctx);
21743 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21744 break;
21745 case OPC_PRECEQU_QH_OBRA:
21746 check_dsp(ctx);
21747 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21748 break;
21749 case OPC_PRECEU_QH_OBL:
21750 check_dsp(ctx);
21751 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21752 break;
21753 case OPC_PRECEU_QH_OBR:
21754 check_dsp(ctx);
21755 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21756 break;
21757 case OPC_PRECEU_QH_OBLA:
21758 check_dsp(ctx);
21759 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21760 break;
21761 case OPC_PRECEU_QH_OBRA:
21762 check_dsp(ctx);
21763 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21764 break;
21765 case OPC_ABSQ_S_OB:
21766 check_dsp_r2(ctx);
21767 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21768 break;
21769 case OPC_ABSQ_S_PW:
21770 check_dsp(ctx);
21771 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21772 break;
21773 case OPC_ABSQ_S_QH:
21774 check_dsp(ctx);
21775 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21776 break;
21778 break;
21779 case OPC_ADDU_OB_DSP:
21780 switch (op2) {
21781 case OPC_RADDU_L_OB:
21782 check_dsp(ctx);
21783 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21784 break;
21785 case OPC_SUBQ_PW:
21786 check_dsp(ctx);
21787 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21788 break;
21789 case OPC_SUBQ_S_PW:
21790 check_dsp(ctx);
21791 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21792 break;
21793 case OPC_SUBQ_QH:
21794 check_dsp(ctx);
21795 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21796 break;
21797 case OPC_SUBQ_S_QH:
21798 check_dsp(ctx);
21799 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21800 break;
21801 case OPC_SUBU_OB:
21802 check_dsp(ctx);
21803 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21804 break;
21805 case OPC_SUBU_S_OB:
21806 check_dsp(ctx);
21807 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21808 break;
21809 case OPC_SUBU_QH:
21810 check_dsp_r2(ctx);
21811 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21812 break;
21813 case OPC_SUBU_S_QH:
21814 check_dsp_r2(ctx);
21815 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21816 break;
21817 case OPC_SUBUH_OB:
21818 check_dsp_r2(ctx);
21819 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21820 break;
21821 case OPC_SUBUH_R_OB:
21822 check_dsp_r2(ctx);
21823 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21824 break;
21825 case OPC_ADDQ_PW:
21826 check_dsp(ctx);
21827 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21828 break;
21829 case OPC_ADDQ_S_PW:
21830 check_dsp(ctx);
21831 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21832 break;
21833 case OPC_ADDQ_QH:
21834 check_dsp(ctx);
21835 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21836 break;
21837 case OPC_ADDQ_S_QH:
21838 check_dsp(ctx);
21839 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21840 break;
21841 case OPC_ADDU_OB:
21842 check_dsp(ctx);
21843 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21844 break;
21845 case OPC_ADDU_S_OB:
21846 check_dsp(ctx);
21847 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21848 break;
21849 case OPC_ADDU_QH:
21850 check_dsp_r2(ctx);
21851 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21852 break;
21853 case OPC_ADDU_S_QH:
21854 check_dsp_r2(ctx);
21855 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21856 break;
21857 case OPC_ADDUH_OB:
21858 check_dsp_r2(ctx);
21859 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
21860 break;
21861 case OPC_ADDUH_R_OB:
21862 check_dsp_r2(ctx);
21863 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21864 break;
21866 break;
21867 case OPC_CMPU_EQ_OB_DSP:
21868 switch (op2) {
21869 case OPC_PRECR_OB_QH:
21870 check_dsp_r2(ctx);
21871 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21872 break;
21873 case OPC_PRECR_SRA_QH_PW:
21874 check_dsp_r2(ctx);
21876 TCGv_i32 ret_t = tcg_const_i32(ret);
21877 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
21878 tcg_temp_free_i32(ret_t);
21879 break;
21881 case OPC_PRECR_SRA_R_QH_PW:
21882 check_dsp_r2(ctx);
21884 TCGv_i32 sa_v = tcg_const_i32(ret);
21885 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
21886 tcg_temp_free_i32(sa_v);
21887 break;
21889 case OPC_PRECRQ_OB_QH:
21890 check_dsp(ctx);
21891 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21892 break;
21893 case OPC_PRECRQ_PW_L:
21894 check_dsp(ctx);
21895 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
21896 break;
21897 case OPC_PRECRQ_QH_PW:
21898 check_dsp(ctx);
21899 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
21900 break;
21901 case OPC_PRECRQ_RS_QH_PW:
21902 check_dsp(ctx);
21903 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21904 break;
21905 case OPC_PRECRQU_S_OB_QH:
21906 check_dsp(ctx);
21907 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21908 break;
21910 break;
21911 #endif
21914 tcg_temp_free(v1_t);
21915 tcg_temp_free(v2_t);
21918 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
21919 int ret, int v1, int v2)
21921 uint32_t op2;
21922 TCGv t0;
21923 TCGv v1_t;
21924 TCGv v2_t;
21926 if (ret == 0) {
21927 /* Treat as NOP. */
21928 return;
21931 t0 = tcg_temp_new();
21932 v1_t = tcg_temp_new();
21933 v2_t = tcg_temp_new();
21935 tcg_gen_movi_tl(t0, v1);
21936 gen_load_gpr(v1_t, v1);
21937 gen_load_gpr(v2_t, v2);
21939 switch (opc) {
21940 case OPC_SHLL_QB_DSP:
21942 op2 = MASK_SHLL_QB(ctx->opcode);
21943 switch (op2) {
21944 case OPC_SHLL_QB:
21945 check_dsp(ctx);
21946 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
21947 break;
21948 case OPC_SHLLV_QB:
21949 check_dsp(ctx);
21950 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21951 break;
21952 case OPC_SHLL_PH:
21953 check_dsp(ctx);
21954 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21955 break;
21956 case OPC_SHLLV_PH:
21957 check_dsp(ctx);
21958 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21959 break;
21960 case OPC_SHLL_S_PH:
21961 check_dsp(ctx);
21962 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21963 break;
21964 case OPC_SHLLV_S_PH:
21965 check_dsp(ctx);
21966 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21967 break;
21968 case OPC_SHLL_S_W:
21969 check_dsp(ctx);
21970 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
21971 break;
21972 case OPC_SHLLV_S_W:
21973 check_dsp(ctx);
21974 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21975 break;
21976 case OPC_SHRL_QB:
21977 check_dsp(ctx);
21978 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
21979 break;
21980 case OPC_SHRLV_QB:
21981 check_dsp(ctx);
21982 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
21983 break;
21984 case OPC_SHRL_PH:
21985 check_dsp_r2(ctx);
21986 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
21987 break;
21988 case OPC_SHRLV_PH:
21989 check_dsp_r2(ctx);
21990 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
21991 break;
21992 case OPC_SHRA_QB:
21993 check_dsp_r2(ctx);
21994 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
21995 break;
21996 case OPC_SHRA_R_QB:
21997 check_dsp_r2(ctx);
21998 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
21999 break;
22000 case OPC_SHRAV_QB:
22001 check_dsp_r2(ctx);
22002 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22003 break;
22004 case OPC_SHRAV_R_QB:
22005 check_dsp_r2(ctx);
22006 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22007 break;
22008 case OPC_SHRA_PH:
22009 check_dsp(ctx);
22010 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22011 break;
22012 case OPC_SHRA_R_PH:
22013 check_dsp(ctx);
22014 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22015 break;
22016 case OPC_SHRAV_PH:
22017 check_dsp(ctx);
22018 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22019 break;
22020 case OPC_SHRAV_R_PH:
22021 check_dsp(ctx);
22022 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22023 break;
22024 case OPC_SHRA_R_W:
22025 check_dsp(ctx);
22026 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22027 break;
22028 case OPC_SHRAV_R_W:
22029 check_dsp(ctx);
22030 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22031 break;
22032 default: /* Invalid */
22033 MIPS_INVAL("MASK SHLL.QB");
22034 generate_exception_end(ctx, EXCP_RI);
22035 break;
22037 break;
22039 #ifdef TARGET_MIPS64
22040 case OPC_SHLL_OB_DSP:
22041 op2 = MASK_SHLL_OB(ctx->opcode);
22042 switch (op2) {
22043 case OPC_SHLL_PW:
22044 check_dsp(ctx);
22045 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22046 break;
22047 case OPC_SHLLV_PW:
22048 check_dsp(ctx);
22049 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22050 break;
22051 case OPC_SHLL_S_PW:
22052 check_dsp(ctx);
22053 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22054 break;
22055 case OPC_SHLLV_S_PW:
22056 check_dsp(ctx);
22057 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22058 break;
22059 case OPC_SHLL_OB:
22060 check_dsp(ctx);
22061 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22062 break;
22063 case OPC_SHLLV_OB:
22064 check_dsp(ctx);
22065 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22066 break;
22067 case OPC_SHLL_QH:
22068 check_dsp(ctx);
22069 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22070 break;
22071 case OPC_SHLLV_QH:
22072 check_dsp(ctx);
22073 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22074 break;
22075 case OPC_SHLL_S_QH:
22076 check_dsp(ctx);
22077 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22078 break;
22079 case OPC_SHLLV_S_QH:
22080 check_dsp(ctx);
22081 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22082 break;
22083 case OPC_SHRA_OB:
22084 check_dsp_r2(ctx);
22085 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22086 break;
22087 case OPC_SHRAV_OB:
22088 check_dsp_r2(ctx);
22089 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22090 break;
22091 case OPC_SHRA_R_OB:
22092 check_dsp_r2(ctx);
22093 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22094 break;
22095 case OPC_SHRAV_R_OB:
22096 check_dsp_r2(ctx);
22097 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22098 break;
22099 case OPC_SHRA_PW:
22100 check_dsp(ctx);
22101 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22102 break;
22103 case OPC_SHRAV_PW:
22104 check_dsp(ctx);
22105 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22106 break;
22107 case OPC_SHRA_R_PW:
22108 check_dsp(ctx);
22109 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22110 break;
22111 case OPC_SHRAV_R_PW:
22112 check_dsp(ctx);
22113 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22114 break;
22115 case OPC_SHRA_QH:
22116 check_dsp(ctx);
22117 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22118 break;
22119 case OPC_SHRAV_QH:
22120 check_dsp(ctx);
22121 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22122 break;
22123 case OPC_SHRA_R_QH:
22124 check_dsp(ctx);
22125 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22126 break;
22127 case OPC_SHRAV_R_QH:
22128 check_dsp(ctx);
22129 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22130 break;
22131 case OPC_SHRL_OB:
22132 check_dsp(ctx);
22133 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22134 break;
22135 case OPC_SHRLV_OB:
22136 check_dsp(ctx);
22137 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22138 break;
22139 case OPC_SHRL_QH:
22140 check_dsp_r2(ctx);
22141 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22142 break;
22143 case OPC_SHRLV_QH:
22144 check_dsp_r2(ctx);
22145 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22146 break;
22147 default: /* Invalid */
22148 MIPS_INVAL("MASK SHLL.OB");
22149 generate_exception_end(ctx, EXCP_RI);
22150 break;
22152 break;
22153 #endif
22156 tcg_temp_free(t0);
22157 tcg_temp_free(v1_t);
22158 tcg_temp_free(v2_t);
22161 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22162 int ret, int v1, int v2, int check_ret)
22164 TCGv_i32 t0;
22165 TCGv v1_t;
22166 TCGv v2_t;
22168 if ((ret == 0) && (check_ret == 1)) {
22169 /* Treat as NOP. */
22170 return;
22173 t0 = tcg_temp_new_i32();
22174 v1_t = tcg_temp_new();
22175 v2_t = tcg_temp_new();
22177 tcg_gen_movi_i32(t0, ret);
22178 gen_load_gpr(v1_t, v1);
22179 gen_load_gpr(v2_t, v2);
22181 switch (op1) {
22182 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22183 * the same mask and op1. */
22184 case OPC_MULT_G_2E:
22185 check_dsp_r2(ctx);
22186 switch (op2) {
22187 case OPC_MUL_PH:
22188 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22189 break;
22190 case OPC_MUL_S_PH:
22191 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22192 break;
22193 case OPC_MULQ_S_W:
22194 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22195 break;
22196 case OPC_MULQ_RS_W:
22197 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22198 break;
22200 break;
22201 case OPC_DPA_W_PH_DSP:
22202 switch (op2) {
22203 case OPC_DPAU_H_QBL:
22204 check_dsp(ctx);
22205 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22206 break;
22207 case OPC_DPAU_H_QBR:
22208 check_dsp(ctx);
22209 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22210 break;
22211 case OPC_DPSU_H_QBL:
22212 check_dsp(ctx);
22213 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22214 break;
22215 case OPC_DPSU_H_QBR:
22216 check_dsp(ctx);
22217 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22218 break;
22219 case OPC_DPA_W_PH:
22220 check_dsp_r2(ctx);
22221 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22222 break;
22223 case OPC_DPAX_W_PH:
22224 check_dsp_r2(ctx);
22225 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22226 break;
22227 case OPC_DPAQ_S_W_PH:
22228 check_dsp(ctx);
22229 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22230 break;
22231 case OPC_DPAQX_S_W_PH:
22232 check_dsp_r2(ctx);
22233 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22234 break;
22235 case OPC_DPAQX_SA_W_PH:
22236 check_dsp_r2(ctx);
22237 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22238 break;
22239 case OPC_DPS_W_PH:
22240 check_dsp_r2(ctx);
22241 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22242 break;
22243 case OPC_DPSX_W_PH:
22244 check_dsp_r2(ctx);
22245 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22246 break;
22247 case OPC_DPSQ_S_W_PH:
22248 check_dsp(ctx);
22249 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22250 break;
22251 case OPC_DPSQX_S_W_PH:
22252 check_dsp_r2(ctx);
22253 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22254 break;
22255 case OPC_DPSQX_SA_W_PH:
22256 check_dsp_r2(ctx);
22257 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22258 break;
22259 case OPC_MULSAQ_S_W_PH:
22260 check_dsp(ctx);
22261 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22262 break;
22263 case OPC_DPAQ_SA_L_W:
22264 check_dsp(ctx);
22265 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22266 break;
22267 case OPC_DPSQ_SA_L_W:
22268 check_dsp(ctx);
22269 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22270 break;
22271 case OPC_MAQ_S_W_PHL:
22272 check_dsp(ctx);
22273 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22274 break;
22275 case OPC_MAQ_S_W_PHR:
22276 check_dsp(ctx);
22277 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22278 break;
22279 case OPC_MAQ_SA_W_PHL:
22280 check_dsp(ctx);
22281 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22282 break;
22283 case OPC_MAQ_SA_W_PHR:
22284 check_dsp(ctx);
22285 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22286 break;
22287 case OPC_MULSA_W_PH:
22288 check_dsp_r2(ctx);
22289 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22290 break;
22292 break;
22293 #ifdef TARGET_MIPS64
22294 case OPC_DPAQ_W_QH_DSP:
22296 int ac = ret & 0x03;
22297 tcg_gen_movi_i32(t0, ac);
22299 switch (op2) {
22300 case OPC_DMADD:
22301 check_dsp(ctx);
22302 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22303 break;
22304 case OPC_DMADDU:
22305 check_dsp(ctx);
22306 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22307 break;
22308 case OPC_DMSUB:
22309 check_dsp(ctx);
22310 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22311 break;
22312 case OPC_DMSUBU:
22313 check_dsp(ctx);
22314 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22315 break;
22316 case OPC_DPA_W_QH:
22317 check_dsp_r2(ctx);
22318 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22319 break;
22320 case OPC_DPAQ_S_W_QH:
22321 check_dsp(ctx);
22322 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22323 break;
22324 case OPC_DPAQ_SA_L_PW:
22325 check_dsp(ctx);
22326 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22327 break;
22328 case OPC_DPAU_H_OBL:
22329 check_dsp(ctx);
22330 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22331 break;
22332 case OPC_DPAU_H_OBR:
22333 check_dsp(ctx);
22334 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22335 break;
22336 case OPC_DPS_W_QH:
22337 check_dsp_r2(ctx);
22338 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22339 break;
22340 case OPC_DPSQ_S_W_QH:
22341 check_dsp(ctx);
22342 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22343 break;
22344 case OPC_DPSQ_SA_L_PW:
22345 check_dsp(ctx);
22346 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22347 break;
22348 case OPC_DPSU_H_OBL:
22349 check_dsp(ctx);
22350 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22351 break;
22352 case OPC_DPSU_H_OBR:
22353 check_dsp(ctx);
22354 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22355 break;
22356 case OPC_MAQ_S_L_PWL:
22357 check_dsp(ctx);
22358 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22359 break;
22360 case OPC_MAQ_S_L_PWR:
22361 check_dsp(ctx);
22362 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22363 break;
22364 case OPC_MAQ_S_W_QHLL:
22365 check_dsp(ctx);
22366 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22367 break;
22368 case OPC_MAQ_SA_W_QHLL:
22369 check_dsp(ctx);
22370 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22371 break;
22372 case OPC_MAQ_S_W_QHLR:
22373 check_dsp(ctx);
22374 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22375 break;
22376 case OPC_MAQ_SA_W_QHLR:
22377 check_dsp(ctx);
22378 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22379 break;
22380 case OPC_MAQ_S_W_QHRL:
22381 check_dsp(ctx);
22382 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22383 break;
22384 case OPC_MAQ_SA_W_QHRL:
22385 check_dsp(ctx);
22386 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22387 break;
22388 case OPC_MAQ_S_W_QHRR:
22389 check_dsp(ctx);
22390 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22391 break;
22392 case OPC_MAQ_SA_W_QHRR:
22393 check_dsp(ctx);
22394 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22395 break;
22396 case OPC_MULSAQ_S_L_PW:
22397 check_dsp(ctx);
22398 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22399 break;
22400 case OPC_MULSAQ_S_W_QH:
22401 check_dsp(ctx);
22402 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22403 break;
22406 break;
22407 #endif
22408 case OPC_ADDU_QB_DSP:
22409 switch (op2) {
22410 case OPC_MULEU_S_PH_QBL:
22411 check_dsp(ctx);
22412 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22413 break;
22414 case OPC_MULEU_S_PH_QBR:
22415 check_dsp(ctx);
22416 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22417 break;
22418 case OPC_MULQ_RS_PH:
22419 check_dsp(ctx);
22420 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22421 break;
22422 case OPC_MULEQ_S_W_PHL:
22423 check_dsp(ctx);
22424 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22425 break;
22426 case OPC_MULEQ_S_W_PHR:
22427 check_dsp(ctx);
22428 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22429 break;
22430 case OPC_MULQ_S_PH:
22431 check_dsp_r2(ctx);
22432 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22433 break;
22435 break;
22436 #ifdef TARGET_MIPS64
22437 case OPC_ADDU_OB_DSP:
22438 switch (op2) {
22439 case OPC_MULEQ_S_PW_QHL:
22440 check_dsp(ctx);
22441 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22442 break;
22443 case OPC_MULEQ_S_PW_QHR:
22444 check_dsp(ctx);
22445 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22446 break;
22447 case OPC_MULEU_S_QH_OBL:
22448 check_dsp(ctx);
22449 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22450 break;
22451 case OPC_MULEU_S_QH_OBR:
22452 check_dsp(ctx);
22453 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22454 break;
22455 case OPC_MULQ_RS_QH:
22456 check_dsp(ctx);
22457 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22458 break;
22460 break;
22461 #endif
22464 tcg_temp_free_i32(t0);
22465 tcg_temp_free(v1_t);
22466 tcg_temp_free(v2_t);
22469 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22470 int ret, int val)
22472 int16_t imm;
22473 TCGv t0;
22474 TCGv val_t;
22476 if (ret == 0) {
22477 /* Treat as NOP. */
22478 return;
22481 t0 = tcg_temp_new();
22482 val_t = tcg_temp_new();
22483 gen_load_gpr(val_t, val);
22485 switch (op1) {
22486 case OPC_ABSQ_S_PH_DSP:
22487 switch (op2) {
22488 case OPC_BITREV:
22489 check_dsp(ctx);
22490 gen_helper_bitrev(cpu_gpr[ret], val_t);
22491 break;
22492 case OPC_REPL_QB:
22493 check_dsp(ctx);
22495 target_long result;
22496 imm = (ctx->opcode >> 16) & 0xFF;
22497 result = (uint32_t)imm << 24 |
22498 (uint32_t)imm << 16 |
22499 (uint32_t)imm << 8 |
22500 (uint32_t)imm;
22501 result = (int32_t)result;
22502 tcg_gen_movi_tl(cpu_gpr[ret], result);
22504 break;
22505 case OPC_REPLV_QB:
22506 check_dsp(ctx);
22507 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22508 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22509 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22510 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22511 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22512 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22513 break;
22514 case OPC_REPL_PH:
22515 check_dsp(ctx);
22517 imm = (ctx->opcode >> 16) & 0x03FF;
22518 imm = (int16_t)(imm << 6) >> 6;
22519 tcg_gen_movi_tl(cpu_gpr[ret], \
22520 (target_long)((int32_t)imm << 16 | \
22521 (uint16_t)imm));
22523 break;
22524 case OPC_REPLV_PH:
22525 check_dsp(ctx);
22526 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22527 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22528 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22529 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22530 break;
22532 break;
22533 #ifdef TARGET_MIPS64
22534 case OPC_ABSQ_S_QH_DSP:
22535 switch (op2) {
22536 case OPC_REPL_OB:
22537 check_dsp(ctx);
22539 target_long temp;
22541 imm = (ctx->opcode >> 16) & 0xFF;
22542 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22543 temp = (temp << 16) | temp;
22544 temp = (temp << 32) | temp;
22545 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22546 break;
22548 case OPC_REPL_PW:
22549 check_dsp(ctx);
22551 target_long temp;
22553 imm = (ctx->opcode >> 16) & 0x03FF;
22554 imm = (int16_t)(imm << 6) >> 6;
22555 temp = ((target_long)imm << 32) \
22556 | ((target_long)imm & 0xFFFFFFFF);
22557 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22558 break;
22560 case OPC_REPL_QH:
22561 check_dsp(ctx);
22563 target_long temp;
22565 imm = (ctx->opcode >> 16) & 0x03FF;
22566 imm = (int16_t)(imm << 6) >> 6;
22568 temp = ((uint64_t)(uint16_t)imm << 48) |
22569 ((uint64_t)(uint16_t)imm << 32) |
22570 ((uint64_t)(uint16_t)imm << 16) |
22571 (uint64_t)(uint16_t)imm;
22572 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22573 break;
22575 case OPC_REPLV_OB:
22576 check_dsp(ctx);
22577 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22578 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22579 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22580 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22581 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22582 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22583 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22584 break;
22585 case OPC_REPLV_PW:
22586 check_dsp(ctx);
22587 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22588 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22589 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22590 break;
22591 case OPC_REPLV_QH:
22592 check_dsp(ctx);
22593 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22594 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22595 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22596 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22597 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22598 break;
22600 break;
22601 #endif
22603 tcg_temp_free(t0);
22604 tcg_temp_free(val_t);
22607 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22608 uint32_t op1, uint32_t op2,
22609 int ret, int v1, int v2, int check_ret)
22611 TCGv t1;
22612 TCGv v1_t;
22613 TCGv v2_t;
22615 if ((ret == 0) && (check_ret == 1)) {
22616 /* Treat as NOP. */
22617 return;
22620 t1 = tcg_temp_new();
22621 v1_t = tcg_temp_new();
22622 v2_t = tcg_temp_new();
22624 gen_load_gpr(v1_t, v1);
22625 gen_load_gpr(v2_t, v2);
22627 switch (op1) {
22628 case OPC_CMPU_EQ_QB_DSP:
22629 switch (op2) {
22630 case OPC_CMPU_EQ_QB:
22631 check_dsp(ctx);
22632 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22633 break;
22634 case OPC_CMPU_LT_QB:
22635 check_dsp(ctx);
22636 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22637 break;
22638 case OPC_CMPU_LE_QB:
22639 check_dsp(ctx);
22640 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22641 break;
22642 case OPC_CMPGU_EQ_QB:
22643 check_dsp(ctx);
22644 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22645 break;
22646 case OPC_CMPGU_LT_QB:
22647 check_dsp(ctx);
22648 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22649 break;
22650 case OPC_CMPGU_LE_QB:
22651 check_dsp(ctx);
22652 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22653 break;
22654 case OPC_CMPGDU_EQ_QB:
22655 check_dsp_r2(ctx);
22656 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22657 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22658 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22659 tcg_gen_shli_tl(t1, t1, 24);
22660 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22661 break;
22662 case OPC_CMPGDU_LT_QB:
22663 check_dsp_r2(ctx);
22664 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22665 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22666 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22667 tcg_gen_shli_tl(t1, t1, 24);
22668 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22669 break;
22670 case OPC_CMPGDU_LE_QB:
22671 check_dsp_r2(ctx);
22672 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22673 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22674 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22675 tcg_gen_shli_tl(t1, t1, 24);
22676 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22677 break;
22678 case OPC_CMP_EQ_PH:
22679 check_dsp(ctx);
22680 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22681 break;
22682 case OPC_CMP_LT_PH:
22683 check_dsp(ctx);
22684 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22685 break;
22686 case OPC_CMP_LE_PH:
22687 check_dsp(ctx);
22688 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22689 break;
22690 case OPC_PICK_QB:
22691 check_dsp(ctx);
22692 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22693 break;
22694 case OPC_PICK_PH:
22695 check_dsp(ctx);
22696 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22697 break;
22698 case OPC_PACKRL_PH:
22699 check_dsp(ctx);
22700 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22701 break;
22703 break;
22704 #ifdef TARGET_MIPS64
22705 case OPC_CMPU_EQ_OB_DSP:
22706 switch (op2) {
22707 case OPC_CMP_EQ_PW:
22708 check_dsp(ctx);
22709 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22710 break;
22711 case OPC_CMP_LT_PW:
22712 check_dsp(ctx);
22713 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22714 break;
22715 case OPC_CMP_LE_PW:
22716 check_dsp(ctx);
22717 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22718 break;
22719 case OPC_CMP_EQ_QH:
22720 check_dsp(ctx);
22721 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22722 break;
22723 case OPC_CMP_LT_QH:
22724 check_dsp(ctx);
22725 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22726 break;
22727 case OPC_CMP_LE_QH:
22728 check_dsp(ctx);
22729 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22730 break;
22731 case OPC_CMPGDU_EQ_OB:
22732 check_dsp_r2(ctx);
22733 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22734 break;
22735 case OPC_CMPGDU_LT_OB:
22736 check_dsp_r2(ctx);
22737 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22738 break;
22739 case OPC_CMPGDU_LE_OB:
22740 check_dsp_r2(ctx);
22741 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22742 break;
22743 case OPC_CMPGU_EQ_OB:
22744 check_dsp(ctx);
22745 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22746 break;
22747 case OPC_CMPGU_LT_OB:
22748 check_dsp(ctx);
22749 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22750 break;
22751 case OPC_CMPGU_LE_OB:
22752 check_dsp(ctx);
22753 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22754 break;
22755 case OPC_CMPU_EQ_OB:
22756 check_dsp(ctx);
22757 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22758 break;
22759 case OPC_CMPU_LT_OB:
22760 check_dsp(ctx);
22761 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22762 break;
22763 case OPC_CMPU_LE_OB:
22764 check_dsp(ctx);
22765 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22766 break;
22767 case OPC_PACKRL_PW:
22768 check_dsp(ctx);
22769 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22770 break;
22771 case OPC_PICK_OB:
22772 check_dsp(ctx);
22773 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22774 break;
22775 case OPC_PICK_PW:
22776 check_dsp(ctx);
22777 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22778 break;
22779 case OPC_PICK_QH:
22780 check_dsp(ctx);
22781 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22782 break;
22784 break;
22785 #endif
22788 tcg_temp_free(t1);
22789 tcg_temp_free(v1_t);
22790 tcg_temp_free(v2_t);
22793 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22794 uint32_t op1, int rt, int rs, int sa)
22796 TCGv t0;
22798 check_dsp_r2(ctx);
22800 if (rt == 0) {
22801 /* Treat as NOP. */
22802 return;
22805 t0 = tcg_temp_new();
22806 gen_load_gpr(t0, rs);
22808 switch (op1) {
22809 case OPC_APPEND_DSP:
22810 switch (MASK_APPEND(ctx->opcode)) {
22811 case OPC_APPEND:
22812 if (sa != 0) {
22813 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22815 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22816 break;
22817 case OPC_PREPEND:
22818 if (sa != 0) {
22819 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22820 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22821 tcg_gen_shli_tl(t0, t0, 32 - sa);
22822 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22824 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22825 break;
22826 case OPC_BALIGN:
22827 sa &= 3;
22828 if (sa != 0 && sa != 2) {
22829 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22830 tcg_gen_ext32u_tl(t0, t0);
22831 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22832 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22834 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22835 break;
22836 default: /* Invalid */
22837 MIPS_INVAL("MASK APPEND");
22838 generate_exception_end(ctx, EXCP_RI);
22839 break;
22841 break;
22842 #ifdef TARGET_MIPS64
22843 case OPC_DAPPEND_DSP:
22844 switch (MASK_DAPPEND(ctx->opcode)) {
22845 case OPC_DAPPEND:
22846 if (sa != 0) {
22847 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22849 break;
22850 case OPC_PREPENDD:
22851 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22852 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
22853 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
22854 break;
22855 case OPC_PREPENDW:
22856 if (sa != 0) {
22857 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22858 tcg_gen_shli_tl(t0, t0, 64 - sa);
22859 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22861 break;
22862 case OPC_DBALIGN:
22863 sa &= 7;
22864 if (sa != 0 && sa != 2 && sa != 4) {
22865 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22866 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
22867 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22869 break;
22870 default: /* Invalid */
22871 MIPS_INVAL("MASK DAPPEND");
22872 generate_exception_end(ctx, EXCP_RI);
22873 break;
22875 break;
22876 #endif
22878 tcg_temp_free(t0);
22881 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22882 int ret, int v1, int v2, int check_ret)
22885 TCGv t0;
22886 TCGv t1;
22887 TCGv v1_t;
22888 TCGv v2_t;
22889 int16_t imm;
22891 if ((ret == 0) && (check_ret == 1)) {
22892 /* Treat as NOP. */
22893 return;
22896 t0 = tcg_temp_new();
22897 t1 = tcg_temp_new();
22898 v1_t = tcg_temp_new();
22899 v2_t = tcg_temp_new();
22901 gen_load_gpr(v1_t, v1);
22902 gen_load_gpr(v2_t, v2);
22904 switch (op1) {
22905 case OPC_EXTR_W_DSP:
22906 check_dsp(ctx);
22907 switch (op2) {
22908 case OPC_EXTR_W:
22909 tcg_gen_movi_tl(t0, v2);
22910 tcg_gen_movi_tl(t1, v1);
22911 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
22912 break;
22913 case OPC_EXTR_R_W:
22914 tcg_gen_movi_tl(t0, v2);
22915 tcg_gen_movi_tl(t1, v1);
22916 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22917 break;
22918 case OPC_EXTR_RS_W:
22919 tcg_gen_movi_tl(t0, v2);
22920 tcg_gen_movi_tl(t1, v1);
22921 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22922 break;
22923 case OPC_EXTR_S_H:
22924 tcg_gen_movi_tl(t0, v2);
22925 tcg_gen_movi_tl(t1, v1);
22926 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22927 break;
22928 case OPC_EXTRV_S_H:
22929 tcg_gen_movi_tl(t0, v2);
22930 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
22931 break;
22932 case OPC_EXTRV_W:
22933 tcg_gen_movi_tl(t0, v2);
22934 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22935 break;
22936 case OPC_EXTRV_R_W:
22937 tcg_gen_movi_tl(t0, v2);
22938 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22939 break;
22940 case OPC_EXTRV_RS_W:
22941 tcg_gen_movi_tl(t0, v2);
22942 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22943 break;
22944 case OPC_EXTP:
22945 tcg_gen_movi_tl(t0, v2);
22946 tcg_gen_movi_tl(t1, v1);
22947 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
22948 break;
22949 case OPC_EXTPV:
22950 tcg_gen_movi_tl(t0, v2);
22951 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
22952 break;
22953 case OPC_EXTPDP:
22954 tcg_gen_movi_tl(t0, v2);
22955 tcg_gen_movi_tl(t1, v1);
22956 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
22957 break;
22958 case OPC_EXTPDPV:
22959 tcg_gen_movi_tl(t0, v2);
22960 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22961 break;
22962 case OPC_SHILO:
22963 imm = (ctx->opcode >> 20) & 0x3F;
22964 tcg_gen_movi_tl(t0, ret);
22965 tcg_gen_movi_tl(t1, imm);
22966 gen_helper_shilo(t0, t1, cpu_env);
22967 break;
22968 case OPC_SHILOV:
22969 tcg_gen_movi_tl(t0, ret);
22970 gen_helper_shilo(t0, v1_t, cpu_env);
22971 break;
22972 case OPC_MTHLIP:
22973 tcg_gen_movi_tl(t0, ret);
22974 gen_helper_mthlip(t0, v1_t, cpu_env);
22975 break;
22976 case OPC_WRDSP:
22977 imm = (ctx->opcode >> 11) & 0x3FF;
22978 tcg_gen_movi_tl(t0, imm);
22979 gen_helper_wrdsp(v1_t, t0, cpu_env);
22980 break;
22981 case OPC_RDDSP:
22982 imm = (ctx->opcode >> 16) & 0x03FF;
22983 tcg_gen_movi_tl(t0, imm);
22984 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
22985 break;
22987 break;
22988 #ifdef TARGET_MIPS64
22989 case OPC_DEXTR_W_DSP:
22990 check_dsp(ctx);
22991 switch (op2) {
22992 case OPC_DMTHLIP:
22993 tcg_gen_movi_tl(t0, ret);
22994 gen_helper_dmthlip(v1_t, t0, cpu_env);
22995 break;
22996 case OPC_DSHILO:
22998 int shift = (ctx->opcode >> 19) & 0x7F;
22999 int ac = (ctx->opcode >> 11) & 0x03;
23000 tcg_gen_movi_tl(t0, shift);
23001 tcg_gen_movi_tl(t1, ac);
23002 gen_helper_dshilo(t0, t1, cpu_env);
23003 break;
23005 case OPC_DSHILOV:
23007 int ac = (ctx->opcode >> 11) & 0x03;
23008 tcg_gen_movi_tl(t0, ac);
23009 gen_helper_dshilo(v1_t, t0, cpu_env);
23010 break;
23012 case OPC_DEXTP:
23013 tcg_gen_movi_tl(t0, v2);
23014 tcg_gen_movi_tl(t1, v1);
23016 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23017 break;
23018 case OPC_DEXTPV:
23019 tcg_gen_movi_tl(t0, v2);
23020 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23021 break;
23022 case OPC_DEXTPDP:
23023 tcg_gen_movi_tl(t0, v2);
23024 tcg_gen_movi_tl(t1, v1);
23025 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23026 break;
23027 case OPC_DEXTPDPV:
23028 tcg_gen_movi_tl(t0, v2);
23029 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23030 break;
23031 case OPC_DEXTR_L:
23032 tcg_gen_movi_tl(t0, v2);
23033 tcg_gen_movi_tl(t1, v1);
23034 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23035 break;
23036 case OPC_DEXTR_R_L:
23037 tcg_gen_movi_tl(t0, v2);
23038 tcg_gen_movi_tl(t1, v1);
23039 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23040 break;
23041 case OPC_DEXTR_RS_L:
23042 tcg_gen_movi_tl(t0, v2);
23043 tcg_gen_movi_tl(t1, v1);
23044 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23045 break;
23046 case OPC_DEXTR_W:
23047 tcg_gen_movi_tl(t0, v2);
23048 tcg_gen_movi_tl(t1, v1);
23049 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23050 break;
23051 case OPC_DEXTR_R_W:
23052 tcg_gen_movi_tl(t0, v2);
23053 tcg_gen_movi_tl(t1, v1);
23054 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23055 break;
23056 case OPC_DEXTR_RS_W:
23057 tcg_gen_movi_tl(t0, v2);
23058 tcg_gen_movi_tl(t1, v1);
23059 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23060 break;
23061 case OPC_DEXTR_S_H:
23062 tcg_gen_movi_tl(t0, v2);
23063 tcg_gen_movi_tl(t1, v1);
23064 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23065 break;
23066 case OPC_DEXTRV_S_H:
23067 tcg_gen_movi_tl(t0, v2);
23068 tcg_gen_movi_tl(t1, v1);
23069 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23070 break;
23071 case OPC_DEXTRV_L:
23072 tcg_gen_movi_tl(t0, v2);
23073 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23074 break;
23075 case OPC_DEXTRV_R_L:
23076 tcg_gen_movi_tl(t0, v2);
23077 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23078 break;
23079 case OPC_DEXTRV_RS_L:
23080 tcg_gen_movi_tl(t0, v2);
23081 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23082 break;
23083 case OPC_DEXTRV_W:
23084 tcg_gen_movi_tl(t0, v2);
23085 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23086 break;
23087 case OPC_DEXTRV_R_W:
23088 tcg_gen_movi_tl(t0, v2);
23089 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23090 break;
23091 case OPC_DEXTRV_RS_W:
23092 tcg_gen_movi_tl(t0, v2);
23093 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23094 break;
23096 break;
23097 #endif
23100 tcg_temp_free(t0);
23101 tcg_temp_free(t1);
23102 tcg_temp_free(v1_t);
23103 tcg_temp_free(v2_t);
23106 /* End MIPSDSP functions. */
23108 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23110 int rs, rt, rd, sa;
23111 uint32_t op1, op2;
23113 rs = (ctx->opcode >> 21) & 0x1f;
23114 rt = (ctx->opcode >> 16) & 0x1f;
23115 rd = (ctx->opcode >> 11) & 0x1f;
23116 sa = (ctx->opcode >> 6) & 0x1f;
23118 op1 = MASK_SPECIAL(ctx->opcode);
23119 switch (op1) {
23120 case OPC_LSA:
23121 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23122 break;
23123 case OPC_MULT:
23124 case OPC_MULTU:
23125 case OPC_DIV:
23126 case OPC_DIVU:
23127 op2 = MASK_R6_MULDIV(ctx->opcode);
23128 switch (op2) {
23129 case R6_OPC_MUL:
23130 case R6_OPC_MUH:
23131 case R6_OPC_MULU:
23132 case R6_OPC_MUHU:
23133 case R6_OPC_DIV:
23134 case R6_OPC_MOD:
23135 case R6_OPC_DIVU:
23136 case R6_OPC_MODU:
23137 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23138 break;
23139 default:
23140 MIPS_INVAL("special_r6 muldiv");
23141 generate_exception_end(ctx, EXCP_RI);
23142 break;
23144 break;
23145 case OPC_SELEQZ:
23146 case OPC_SELNEZ:
23147 gen_cond_move(ctx, op1, rd, rs, rt);
23148 break;
23149 case R6_OPC_CLO:
23150 case R6_OPC_CLZ:
23151 if (rt == 0 && sa == 1) {
23152 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23153 We need additionally to check other fields */
23154 gen_cl(ctx, op1, rd, rs);
23155 } else {
23156 generate_exception_end(ctx, EXCP_RI);
23158 break;
23159 case R6_OPC_SDBBP:
23160 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23161 gen_helper_do_semihosting(cpu_env);
23162 } else {
23163 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23164 generate_exception_end(ctx, EXCP_RI);
23165 } else {
23166 generate_exception_end(ctx, EXCP_DBp);
23169 break;
23170 #if defined(TARGET_MIPS64)
23171 case OPC_DLSA:
23172 check_mips_64(ctx);
23173 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23174 break;
23175 case R6_OPC_DCLO:
23176 case R6_OPC_DCLZ:
23177 if (rt == 0 && sa == 1) {
23178 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23179 We need additionally to check other fields */
23180 check_mips_64(ctx);
23181 gen_cl(ctx, op1, rd, rs);
23182 } else {
23183 generate_exception_end(ctx, EXCP_RI);
23185 break;
23186 case OPC_DMULT:
23187 case OPC_DMULTU:
23188 case OPC_DDIV:
23189 case OPC_DDIVU:
23191 op2 = MASK_R6_MULDIV(ctx->opcode);
23192 switch (op2) {
23193 case R6_OPC_DMUL:
23194 case R6_OPC_DMUH:
23195 case R6_OPC_DMULU:
23196 case R6_OPC_DMUHU:
23197 case R6_OPC_DDIV:
23198 case R6_OPC_DMOD:
23199 case R6_OPC_DDIVU:
23200 case R6_OPC_DMODU:
23201 check_mips_64(ctx);
23202 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23203 break;
23204 default:
23205 MIPS_INVAL("special_r6 muldiv");
23206 generate_exception_end(ctx, EXCP_RI);
23207 break;
23209 break;
23210 #endif
23211 default: /* Invalid */
23212 MIPS_INVAL("special_r6");
23213 generate_exception_end(ctx, EXCP_RI);
23214 break;
23218 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23220 int rs, rt, rd, sa;
23221 uint32_t op1;
23223 rs = (ctx->opcode >> 21) & 0x1f;
23224 rt = (ctx->opcode >> 16) & 0x1f;
23225 rd = (ctx->opcode >> 11) & 0x1f;
23226 sa = (ctx->opcode >> 6) & 0x1f;
23228 op1 = MASK_SPECIAL(ctx->opcode);
23229 switch (op1) {
23230 case OPC_MOVN: /* Conditional move */
23231 case OPC_MOVZ:
23232 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23233 INSN_LOONGSON2E | INSN_LOONGSON2F);
23234 gen_cond_move(ctx, op1, rd, rs, rt);
23235 break;
23236 case OPC_MFHI: /* Move from HI/LO */
23237 case OPC_MFLO:
23238 gen_HILO(ctx, op1, rs & 3, rd);
23239 break;
23240 case OPC_MTHI:
23241 case OPC_MTLO: /* Move to HI/LO */
23242 gen_HILO(ctx, op1, rd & 3, rs);
23243 break;
23244 case OPC_MOVCI:
23245 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23246 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23247 check_cp1_enabled(ctx);
23248 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23249 (ctx->opcode >> 16) & 1);
23250 } else {
23251 generate_exception_err(ctx, EXCP_CpU, 1);
23253 break;
23254 case OPC_MULT:
23255 case OPC_MULTU:
23256 if (sa) {
23257 check_insn(ctx, INSN_VR54XX);
23258 op1 = MASK_MUL_VR54XX(ctx->opcode);
23259 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23260 } else {
23261 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23263 break;
23264 case OPC_DIV:
23265 case OPC_DIVU:
23266 gen_muldiv(ctx, op1, 0, rs, rt);
23267 break;
23268 #if defined(TARGET_MIPS64)
23269 case OPC_DMULT:
23270 case OPC_DMULTU:
23271 case OPC_DDIV:
23272 case OPC_DDIVU:
23273 check_insn(ctx, ISA_MIPS3);
23274 check_mips_64(ctx);
23275 gen_muldiv(ctx, op1, 0, rs, rt);
23276 break;
23277 #endif
23278 case OPC_JR:
23279 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23280 break;
23281 case OPC_SPIM:
23282 #ifdef MIPS_STRICT_STANDARD
23283 MIPS_INVAL("SPIM");
23284 generate_exception_end(ctx, EXCP_RI);
23285 #else
23286 /* Implemented as RI exception for now. */
23287 MIPS_INVAL("spim (unofficial)");
23288 generate_exception_end(ctx, EXCP_RI);
23289 #endif
23290 break;
23291 default: /* Invalid */
23292 MIPS_INVAL("special_legacy");
23293 generate_exception_end(ctx, EXCP_RI);
23294 break;
23298 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23300 int rs, rt, rd, sa;
23301 uint32_t op1;
23303 rs = (ctx->opcode >> 21) & 0x1f;
23304 rt = (ctx->opcode >> 16) & 0x1f;
23305 rd = (ctx->opcode >> 11) & 0x1f;
23306 sa = (ctx->opcode >> 6) & 0x1f;
23308 op1 = MASK_SPECIAL(ctx->opcode);
23309 switch (op1) {
23310 case OPC_SLL: /* Shift with immediate */
23311 if (sa == 5 && rd == 0 &&
23312 rs == 0 && rt == 0) { /* PAUSE */
23313 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23314 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23315 generate_exception_end(ctx, EXCP_RI);
23316 break;
23319 /* Fallthrough */
23320 case OPC_SRA:
23321 gen_shift_imm(ctx, op1, rd, rt, sa);
23322 break;
23323 case OPC_SRL:
23324 switch ((ctx->opcode >> 21) & 0x1f) {
23325 case 1:
23326 /* rotr is decoded as srl on non-R2 CPUs */
23327 if (ctx->insn_flags & ISA_MIPS32R2) {
23328 op1 = OPC_ROTR;
23330 /* Fallthrough */
23331 case 0:
23332 gen_shift_imm(ctx, op1, rd, rt, sa);
23333 break;
23334 default:
23335 generate_exception_end(ctx, EXCP_RI);
23336 break;
23338 break;
23339 case OPC_ADD:
23340 case OPC_ADDU:
23341 case OPC_SUB:
23342 case OPC_SUBU:
23343 gen_arith(ctx, op1, rd, rs, rt);
23344 break;
23345 case OPC_SLLV: /* Shifts */
23346 case OPC_SRAV:
23347 gen_shift(ctx, op1, rd, rs, rt);
23348 break;
23349 case OPC_SRLV:
23350 switch ((ctx->opcode >> 6) & 0x1f) {
23351 case 1:
23352 /* rotrv is decoded as srlv on non-R2 CPUs */
23353 if (ctx->insn_flags & ISA_MIPS32R2) {
23354 op1 = OPC_ROTRV;
23356 /* Fallthrough */
23357 case 0:
23358 gen_shift(ctx, op1, rd, rs, rt);
23359 break;
23360 default:
23361 generate_exception_end(ctx, EXCP_RI);
23362 break;
23364 break;
23365 case OPC_SLT: /* Set on less than */
23366 case OPC_SLTU:
23367 gen_slt(ctx, op1, rd, rs, rt);
23368 break;
23369 case OPC_AND: /* Logic*/
23370 case OPC_OR:
23371 case OPC_NOR:
23372 case OPC_XOR:
23373 gen_logic(ctx, op1, rd, rs, rt);
23374 break;
23375 case OPC_JALR:
23376 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23377 break;
23378 case OPC_TGE: /* Traps */
23379 case OPC_TGEU:
23380 case OPC_TLT:
23381 case OPC_TLTU:
23382 case OPC_TEQ:
23383 case OPC_TNE:
23384 check_insn(ctx, ISA_MIPS2);
23385 gen_trap(ctx, op1, rs, rt, -1);
23386 break;
23387 case OPC_LSA: /* OPC_PMON */
23388 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23389 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23390 decode_opc_special_r6(env, ctx);
23391 } else {
23392 /* Pmon entry point, also R4010 selsl */
23393 #ifdef MIPS_STRICT_STANDARD
23394 MIPS_INVAL("PMON / selsl");
23395 generate_exception_end(ctx, EXCP_RI);
23396 #else
23397 gen_helper_0e0i(pmon, sa);
23398 #endif
23400 break;
23401 case OPC_SYSCALL:
23402 generate_exception_end(ctx, EXCP_SYSCALL);
23403 break;
23404 case OPC_BREAK:
23405 generate_exception_end(ctx, EXCP_BREAK);
23406 break;
23407 case OPC_SYNC:
23408 check_insn(ctx, ISA_MIPS2);
23409 gen_sync(extract32(ctx->opcode, 6, 5));
23410 break;
23412 #if defined(TARGET_MIPS64)
23413 /* MIPS64 specific opcodes */
23414 case OPC_DSLL:
23415 case OPC_DSRA:
23416 case OPC_DSLL32:
23417 case OPC_DSRA32:
23418 check_insn(ctx, ISA_MIPS3);
23419 check_mips_64(ctx);
23420 gen_shift_imm(ctx, op1, rd, rt, sa);
23421 break;
23422 case OPC_DSRL:
23423 switch ((ctx->opcode >> 21) & 0x1f) {
23424 case 1:
23425 /* drotr is decoded as dsrl on non-R2 CPUs */
23426 if (ctx->insn_flags & ISA_MIPS32R2) {
23427 op1 = OPC_DROTR;
23429 /* Fallthrough */
23430 case 0:
23431 check_insn(ctx, ISA_MIPS3);
23432 check_mips_64(ctx);
23433 gen_shift_imm(ctx, op1, rd, rt, sa);
23434 break;
23435 default:
23436 generate_exception_end(ctx, EXCP_RI);
23437 break;
23439 break;
23440 case OPC_DSRL32:
23441 switch ((ctx->opcode >> 21) & 0x1f) {
23442 case 1:
23443 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23444 if (ctx->insn_flags & ISA_MIPS32R2) {
23445 op1 = OPC_DROTR32;
23447 /* Fallthrough */
23448 case 0:
23449 check_insn(ctx, ISA_MIPS3);
23450 check_mips_64(ctx);
23451 gen_shift_imm(ctx, op1, rd, rt, sa);
23452 break;
23453 default:
23454 generate_exception_end(ctx, EXCP_RI);
23455 break;
23457 break;
23458 case OPC_DADD:
23459 case OPC_DADDU:
23460 case OPC_DSUB:
23461 case OPC_DSUBU:
23462 check_insn(ctx, ISA_MIPS3);
23463 check_mips_64(ctx);
23464 gen_arith(ctx, op1, rd, rs, rt);
23465 break;
23466 case OPC_DSLLV:
23467 case OPC_DSRAV:
23468 check_insn(ctx, ISA_MIPS3);
23469 check_mips_64(ctx);
23470 gen_shift(ctx, op1, rd, rs, rt);
23471 break;
23472 case OPC_DSRLV:
23473 switch ((ctx->opcode >> 6) & 0x1f) {
23474 case 1:
23475 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23476 if (ctx->insn_flags & ISA_MIPS32R2) {
23477 op1 = OPC_DROTRV;
23479 /* Fallthrough */
23480 case 0:
23481 check_insn(ctx, ISA_MIPS3);
23482 check_mips_64(ctx);
23483 gen_shift(ctx, op1, rd, rs, rt);
23484 break;
23485 default:
23486 generate_exception_end(ctx, EXCP_RI);
23487 break;
23489 break;
23490 case OPC_DLSA:
23491 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23492 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23493 decode_opc_special_r6(env, ctx);
23495 break;
23496 #endif
23497 default:
23498 if (ctx->insn_flags & ISA_MIPS32R6) {
23499 decode_opc_special_r6(env, ctx);
23500 } else {
23501 decode_opc_special_legacy(env, ctx);
23506 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23508 int rs, rt, rd;
23509 uint32_t op1;
23511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23513 rs = (ctx->opcode >> 21) & 0x1f;
23514 rt = (ctx->opcode >> 16) & 0x1f;
23515 rd = (ctx->opcode >> 11) & 0x1f;
23517 op1 = MASK_SPECIAL2(ctx->opcode);
23518 switch (op1) {
23519 case OPC_MADD: /* Multiply and add/sub */
23520 case OPC_MADDU:
23521 case OPC_MSUB:
23522 case OPC_MSUBU:
23523 check_insn(ctx, ISA_MIPS32);
23524 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23525 break;
23526 case OPC_MUL:
23527 gen_arith(ctx, op1, rd, rs, rt);
23528 break;
23529 case OPC_DIV_G_2F:
23530 case OPC_DIVU_G_2F:
23531 case OPC_MULT_G_2F:
23532 case OPC_MULTU_G_2F:
23533 case OPC_MOD_G_2F:
23534 case OPC_MODU_G_2F:
23535 check_insn(ctx, INSN_LOONGSON2F);
23536 gen_loongson_integer(ctx, op1, rd, rs, rt);
23537 break;
23538 case OPC_CLO:
23539 case OPC_CLZ:
23540 check_insn(ctx, ISA_MIPS32);
23541 gen_cl(ctx, op1, rd, rs);
23542 break;
23543 case OPC_SDBBP:
23544 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23545 gen_helper_do_semihosting(cpu_env);
23546 } else {
23547 /* XXX: not clear which exception should be raised
23548 * when in debug mode...
23550 check_insn(ctx, ISA_MIPS32);
23551 generate_exception_end(ctx, EXCP_DBp);
23553 break;
23554 #if defined(TARGET_MIPS64)
23555 case OPC_DCLO:
23556 case OPC_DCLZ:
23557 check_insn(ctx, ISA_MIPS64);
23558 check_mips_64(ctx);
23559 gen_cl(ctx, op1, rd, rs);
23560 break;
23561 case OPC_DMULT_G_2F:
23562 case OPC_DMULTU_G_2F:
23563 case OPC_DDIV_G_2F:
23564 case OPC_DDIVU_G_2F:
23565 case OPC_DMOD_G_2F:
23566 case OPC_DMODU_G_2F:
23567 check_insn(ctx, INSN_LOONGSON2F);
23568 gen_loongson_integer(ctx, op1, rd, rs, rt);
23569 break;
23570 #endif
23571 default: /* Invalid */
23572 MIPS_INVAL("special2_legacy");
23573 generate_exception_end(ctx, EXCP_RI);
23574 break;
23578 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23580 int rs, rt, rd, sa;
23581 uint32_t op1, op2;
23582 int16_t imm;
23584 rs = (ctx->opcode >> 21) & 0x1f;
23585 rt = (ctx->opcode >> 16) & 0x1f;
23586 rd = (ctx->opcode >> 11) & 0x1f;
23587 sa = (ctx->opcode >> 6) & 0x1f;
23588 imm = (int16_t)ctx->opcode >> 7;
23590 op1 = MASK_SPECIAL3(ctx->opcode);
23591 switch (op1) {
23592 case R6_OPC_PREF:
23593 if (rt >= 24) {
23594 /* hint codes 24-31 are reserved and signal RI */
23595 generate_exception_end(ctx, EXCP_RI);
23597 /* Treat as NOP. */
23598 break;
23599 case R6_OPC_CACHE:
23600 check_cp0_enabled(ctx);
23601 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23602 gen_cache_operation(ctx, rt, rs, imm);
23604 break;
23605 case R6_OPC_SC:
23606 gen_st_cond(ctx, op1, rt, rs, imm);
23607 break;
23608 case R6_OPC_LL:
23609 gen_ld(ctx, op1, rt, rs, imm);
23610 break;
23611 case OPC_BSHFL:
23613 if (rd == 0) {
23614 /* Treat as NOP. */
23615 break;
23617 op2 = MASK_BSHFL(ctx->opcode);
23618 switch (op2) {
23619 case OPC_ALIGN:
23620 case OPC_ALIGN_END:
23621 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23622 break;
23623 case OPC_BITSWAP:
23624 gen_bitswap(ctx, op2, rd, rt);
23625 break;
23628 break;
23629 #if defined(TARGET_MIPS64)
23630 case R6_OPC_SCD:
23631 gen_st_cond(ctx, op1, rt, rs, imm);
23632 break;
23633 case R6_OPC_LLD:
23634 gen_ld(ctx, op1, rt, rs, imm);
23635 break;
23636 case OPC_DBSHFL:
23637 check_mips_64(ctx);
23639 if (rd == 0) {
23640 /* Treat as NOP. */
23641 break;
23643 op2 = MASK_DBSHFL(ctx->opcode);
23644 switch (op2) {
23645 case OPC_DALIGN:
23646 case OPC_DALIGN_END:
23647 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23648 break;
23649 case OPC_DBITSWAP:
23650 gen_bitswap(ctx, op2, rd, rt);
23651 break;
23655 break;
23656 #endif
23657 default: /* Invalid */
23658 MIPS_INVAL("special3_r6");
23659 generate_exception_end(ctx, EXCP_RI);
23660 break;
23664 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23666 int rs, rt, rd;
23667 uint32_t op1, op2;
23669 rs = (ctx->opcode >> 21) & 0x1f;
23670 rt = (ctx->opcode >> 16) & 0x1f;
23671 rd = (ctx->opcode >> 11) & 0x1f;
23673 op1 = MASK_SPECIAL3(ctx->opcode);
23674 switch (op1) {
23675 case OPC_DIV_G_2E:
23676 case OPC_DIVU_G_2E:
23677 case OPC_MOD_G_2E:
23678 case OPC_MODU_G_2E:
23679 case OPC_MULT_G_2E:
23680 case OPC_MULTU_G_2E:
23681 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23682 * the same mask and op1. */
23683 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23684 op2 = MASK_ADDUH_QB(ctx->opcode);
23685 switch (op2) {
23686 case OPC_ADDUH_QB:
23687 case OPC_ADDUH_R_QB:
23688 case OPC_ADDQH_PH:
23689 case OPC_ADDQH_R_PH:
23690 case OPC_ADDQH_W:
23691 case OPC_ADDQH_R_W:
23692 case OPC_SUBUH_QB:
23693 case OPC_SUBUH_R_QB:
23694 case OPC_SUBQH_PH:
23695 case OPC_SUBQH_R_PH:
23696 case OPC_SUBQH_W:
23697 case OPC_SUBQH_R_W:
23698 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23699 break;
23700 case OPC_MUL_PH:
23701 case OPC_MUL_S_PH:
23702 case OPC_MULQ_S_W:
23703 case OPC_MULQ_RS_W:
23704 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23705 break;
23706 default:
23707 MIPS_INVAL("MASK ADDUH.QB");
23708 generate_exception_end(ctx, EXCP_RI);
23709 break;
23711 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23712 gen_loongson_integer(ctx, op1, rd, rs, rt);
23713 } else {
23714 generate_exception_end(ctx, EXCP_RI);
23716 break;
23717 case OPC_LX_DSP:
23718 op2 = MASK_LX(ctx->opcode);
23719 switch (op2) {
23720 #if defined(TARGET_MIPS64)
23721 case OPC_LDX:
23722 #endif
23723 case OPC_LBUX:
23724 case OPC_LHX:
23725 case OPC_LWX:
23726 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23727 break;
23728 default: /* Invalid */
23729 MIPS_INVAL("MASK LX");
23730 generate_exception_end(ctx, EXCP_RI);
23731 break;
23733 break;
23734 case OPC_ABSQ_S_PH_DSP:
23735 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23736 switch (op2) {
23737 case OPC_ABSQ_S_QB:
23738 case OPC_ABSQ_S_PH:
23739 case OPC_ABSQ_S_W:
23740 case OPC_PRECEQ_W_PHL:
23741 case OPC_PRECEQ_W_PHR:
23742 case OPC_PRECEQU_PH_QBL:
23743 case OPC_PRECEQU_PH_QBR:
23744 case OPC_PRECEQU_PH_QBLA:
23745 case OPC_PRECEQU_PH_QBRA:
23746 case OPC_PRECEU_PH_QBL:
23747 case OPC_PRECEU_PH_QBR:
23748 case OPC_PRECEU_PH_QBLA:
23749 case OPC_PRECEU_PH_QBRA:
23750 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23751 break;
23752 case OPC_BITREV:
23753 case OPC_REPL_QB:
23754 case OPC_REPLV_QB:
23755 case OPC_REPL_PH:
23756 case OPC_REPLV_PH:
23757 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23758 break;
23759 default:
23760 MIPS_INVAL("MASK ABSQ_S.PH");
23761 generate_exception_end(ctx, EXCP_RI);
23762 break;
23764 break;
23765 case OPC_ADDU_QB_DSP:
23766 op2 = MASK_ADDU_QB(ctx->opcode);
23767 switch (op2) {
23768 case OPC_ADDQ_PH:
23769 case OPC_ADDQ_S_PH:
23770 case OPC_ADDQ_S_W:
23771 case OPC_ADDU_QB:
23772 case OPC_ADDU_S_QB:
23773 case OPC_ADDU_PH:
23774 case OPC_ADDU_S_PH:
23775 case OPC_SUBQ_PH:
23776 case OPC_SUBQ_S_PH:
23777 case OPC_SUBQ_S_W:
23778 case OPC_SUBU_QB:
23779 case OPC_SUBU_S_QB:
23780 case OPC_SUBU_PH:
23781 case OPC_SUBU_S_PH:
23782 case OPC_ADDSC:
23783 case OPC_ADDWC:
23784 case OPC_MODSUB:
23785 case OPC_RADDU_W_QB:
23786 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23787 break;
23788 case OPC_MULEU_S_PH_QBL:
23789 case OPC_MULEU_S_PH_QBR:
23790 case OPC_MULQ_RS_PH:
23791 case OPC_MULEQ_S_W_PHL:
23792 case OPC_MULEQ_S_W_PHR:
23793 case OPC_MULQ_S_PH:
23794 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23795 break;
23796 default: /* Invalid */
23797 MIPS_INVAL("MASK ADDU.QB");
23798 generate_exception_end(ctx, EXCP_RI);
23799 break;
23802 break;
23803 case OPC_CMPU_EQ_QB_DSP:
23804 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
23805 switch (op2) {
23806 case OPC_PRECR_SRA_PH_W:
23807 case OPC_PRECR_SRA_R_PH_W:
23808 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23809 break;
23810 case OPC_PRECR_QB_PH:
23811 case OPC_PRECRQ_QB_PH:
23812 case OPC_PRECRQ_PH_W:
23813 case OPC_PRECRQ_RS_PH_W:
23814 case OPC_PRECRQU_S_QB_PH:
23815 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23816 break;
23817 case OPC_CMPU_EQ_QB:
23818 case OPC_CMPU_LT_QB:
23819 case OPC_CMPU_LE_QB:
23820 case OPC_CMP_EQ_PH:
23821 case OPC_CMP_LT_PH:
23822 case OPC_CMP_LE_PH:
23823 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23824 break;
23825 case OPC_CMPGU_EQ_QB:
23826 case OPC_CMPGU_LT_QB:
23827 case OPC_CMPGU_LE_QB:
23828 case OPC_CMPGDU_EQ_QB:
23829 case OPC_CMPGDU_LT_QB:
23830 case OPC_CMPGDU_LE_QB:
23831 case OPC_PICK_QB:
23832 case OPC_PICK_PH:
23833 case OPC_PACKRL_PH:
23834 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23835 break;
23836 default: /* Invalid */
23837 MIPS_INVAL("MASK CMPU.EQ.QB");
23838 generate_exception_end(ctx, EXCP_RI);
23839 break;
23841 break;
23842 case OPC_SHLL_QB_DSP:
23843 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23844 break;
23845 case OPC_DPA_W_PH_DSP:
23846 op2 = MASK_DPA_W_PH(ctx->opcode);
23847 switch (op2) {
23848 case OPC_DPAU_H_QBL:
23849 case OPC_DPAU_H_QBR:
23850 case OPC_DPSU_H_QBL:
23851 case OPC_DPSU_H_QBR:
23852 case OPC_DPA_W_PH:
23853 case OPC_DPAX_W_PH:
23854 case OPC_DPAQ_S_W_PH:
23855 case OPC_DPAQX_S_W_PH:
23856 case OPC_DPAQX_SA_W_PH:
23857 case OPC_DPS_W_PH:
23858 case OPC_DPSX_W_PH:
23859 case OPC_DPSQ_S_W_PH:
23860 case OPC_DPSQX_S_W_PH:
23861 case OPC_DPSQX_SA_W_PH:
23862 case OPC_MULSAQ_S_W_PH:
23863 case OPC_DPAQ_SA_L_W:
23864 case OPC_DPSQ_SA_L_W:
23865 case OPC_MAQ_S_W_PHL:
23866 case OPC_MAQ_S_W_PHR:
23867 case OPC_MAQ_SA_W_PHL:
23868 case OPC_MAQ_SA_W_PHR:
23869 case OPC_MULSA_W_PH:
23870 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23871 break;
23872 default: /* Invalid */
23873 MIPS_INVAL("MASK DPAW.PH");
23874 generate_exception_end(ctx, EXCP_RI);
23875 break;
23877 break;
23878 case OPC_INSV_DSP:
23879 op2 = MASK_INSV(ctx->opcode);
23880 switch (op2) {
23881 case OPC_INSV:
23882 check_dsp(ctx);
23884 TCGv t0, t1;
23886 if (rt == 0) {
23887 break;
23890 t0 = tcg_temp_new();
23891 t1 = tcg_temp_new();
23893 gen_load_gpr(t0, rt);
23894 gen_load_gpr(t1, rs);
23896 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
23898 tcg_temp_free(t0);
23899 tcg_temp_free(t1);
23900 break;
23902 default: /* Invalid */
23903 MIPS_INVAL("MASK INSV");
23904 generate_exception_end(ctx, EXCP_RI);
23905 break;
23907 break;
23908 case OPC_APPEND_DSP:
23909 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23910 break;
23911 case OPC_EXTR_W_DSP:
23912 op2 = MASK_EXTR_W(ctx->opcode);
23913 switch (op2) {
23914 case OPC_EXTR_W:
23915 case OPC_EXTR_R_W:
23916 case OPC_EXTR_RS_W:
23917 case OPC_EXTR_S_H:
23918 case OPC_EXTRV_S_H:
23919 case OPC_EXTRV_W:
23920 case OPC_EXTRV_R_W:
23921 case OPC_EXTRV_RS_W:
23922 case OPC_EXTP:
23923 case OPC_EXTPV:
23924 case OPC_EXTPDP:
23925 case OPC_EXTPDPV:
23926 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23927 break;
23928 case OPC_RDDSP:
23929 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
23930 break;
23931 case OPC_SHILO:
23932 case OPC_SHILOV:
23933 case OPC_MTHLIP:
23934 case OPC_WRDSP:
23935 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23936 break;
23937 default: /* Invalid */
23938 MIPS_INVAL("MASK EXTR.W");
23939 generate_exception_end(ctx, EXCP_RI);
23940 break;
23942 break;
23943 #if defined(TARGET_MIPS64)
23944 case OPC_DDIV_G_2E:
23945 case OPC_DDIVU_G_2E:
23946 case OPC_DMULT_G_2E:
23947 case OPC_DMULTU_G_2E:
23948 case OPC_DMOD_G_2E:
23949 case OPC_DMODU_G_2E:
23950 check_insn(ctx, INSN_LOONGSON2E);
23951 gen_loongson_integer(ctx, op1, rd, rs, rt);
23952 break;
23953 case OPC_ABSQ_S_QH_DSP:
23954 op2 = MASK_ABSQ_S_QH(ctx->opcode);
23955 switch (op2) {
23956 case OPC_PRECEQ_L_PWL:
23957 case OPC_PRECEQ_L_PWR:
23958 case OPC_PRECEQ_PW_QHL:
23959 case OPC_PRECEQ_PW_QHR:
23960 case OPC_PRECEQ_PW_QHLA:
23961 case OPC_PRECEQ_PW_QHRA:
23962 case OPC_PRECEQU_QH_OBL:
23963 case OPC_PRECEQU_QH_OBR:
23964 case OPC_PRECEQU_QH_OBLA:
23965 case OPC_PRECEQU_QH_OBRA:
23966 case OPC_PRECEU_QH_OBL:
23967 case OPC_PRECEU_QH_OBR:
23968 case OPC_PRECEU_QH_OBLA:
23969 case OPC_PRECEU_QH_OBRA:
23970 case OPC_ABSQ_S_OB:
23971 case OPC_ABSQ_S_PW:
23972 case OPC_ABSQ_S_QH:
23973 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23974 break;
23975 case OPC_REPL_OB:
23976 case OPC_REPL_PW:
23977 case OPC_REPL_QH:
23978 case OPC_REPLV_OB:
23979 case OPC_REPLV_PW:
23980 case OPC_REPLV_QH:
23981 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23982 break;
23983 default: /* Invalid */
23984 MIPS_INVAL("MASK ABSQ_S.QH");
23985 generate_exception_end(ctx, EXCP_RI);
23986 break;
23988 break;
23989 case OPC_ADDU_OB_DSP:
23990 op2 = MASK_ADDU_OB(ctx->opcode);
23991 switch (op2) {
23992 case OPC_RADDU_L_OB:
23993 case OPC_SUBQ_PW:
23994 case OPC_SUBQ_S_PW:
23995 case OPC_SUBQ_QH:
23996 case OPC_SUBQ_S_QH:
23997 case OPC_SUBU_OB:
23998 case OPC_SUBU_S_OB:
23999 case OPC_SUBU_QH:
24000 case OPC_SUBU_S_QH:
24001 case OPC_SUBUH_OB:
24002 case OPC_SUBUH_R_OB:
24003 case OPC_ADDQ_PW:
24004 case OPC_ADDQ_S_PW:
24005 case OPC_ADDQ_QH:
24006 case OPC_ADDQ_S_QH:
24007 case OPC_ADDU_OB:
24008 case OPC_ADDU_S_OB:
24009 case OPC_ADDU_QH:
24010 case OPC_ADDU_S_QH:
24011 case OPC_ADDUH_OB:
24012 case OPC_ADDUH_R_OB:
24013 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24014 break;
24015 case OPC_MULEQ_S_PW_QHL:
24016 case OPC_MULEQ_S_PW_QHR:
24017 case OPC_MULEU_S_QH_OBL:
24018 case OPC_MULEU_S_QH_OBR:
24019 case OPC_MULQ_RS_QH:
24020 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24021 break;
24022 default: /* Invalid */
24023 MIPS_INVAL("MASK ADDU.OB");
24024 generate_exception_end(ctx, EXCP_RI);
24025 break;
24027 break;
24028 case OPC_CMPU_EQ_OB_DSP:
24029 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24030 switch (op2) {
24031 case OPC_PRECR_SRA_QH_PW:
24032 case OPC_PRECR_SRA_R_QH_PW:
24033 /* Return value is rt. */
24034 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24035 break;
24036 case OPC_PRECR_OB_QH:
24037 case OPC_PRECRQ_OB_QH:
24038 case OPC_PRECRQ_PW_L:
24039 case OPC_PRECRQ_QH_PW:
24040 case OPC_PRECRQ_RS_QH_PW:
24041 case OPC_PRECRQU_S_OB_QH:
24042 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24043 break;
24044 case OPC_CMPU_EQ_OB:
24045 case OPC_CMPU_LT_OB:
24046 case OPC_CMPU_LE_OB:
24047 case OPC_CMP_EQ_QH:
24048 case OPC_CMP_LT_QH:
24049 case OPC_CMP_LE_QH:
24050 case OPC_CMP_EQ_PW:
24051 case OPC_CMP_LT_PW:
24052 case OPC_CMP_LE_PW:
24053 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24054 break;
24055 case OPC_CMPGDU_EQ_OB:
24056 case OPC_CMPGDU_LT_OB:
24057 case OPC_CMPGDU_LE_OB:
24058 case OPC_CMPGU_EQ_OB:
24059 case OPC_CMPGU_LT_OB:
24060 case OPC_CMPGU_LE_OB:
24061 case OPC_PACKRL_PW:
24062 case OPC_PICK_OB:
24063 case OPC_PICK_PW:
24064 case OPC_PICK_QH:
24065 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24066 break;
24067 default: /* Invalid */
24068 MIPS_INVAL("MASK CMPU_EQ.OB");
24069 generate_exception_end(ctx, EXCP_RI);
24070 break;
24072 break;
24073 case OPC_DAPPEND_DSP:
24074 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24075 break;
24076 case OPC_DEXTR_W_DSP:
24077 op2 = MASK_DEXTR_W(ctx->opcode);
24078 switch (op2) {
24079 case OPC_DEXTP:
24080 case OPC_DEXTPDP:
24081 case OPC_DEXTPDPV:
24082 case OPC_DEXTPV:
24083 case OPC_DEXTR_L:
24084 case OPC_DEXTR_R_L:
24085 case OPC_DEXTR_RS_L:
24086 case OPC_DEXTR_W:
24087 case OPC_DEXTR_R_W:
24088 case OPC_DEXTR_RS_W:
24089 case OPC_DEXTR_S_H:
24090 case OPC_DEXTRV_L:
24091 case OPC_DEXTRV_R_L:
24092 case OPC_DEXTRV_RS_L:
24093 case OPC_DEXTRV_S_H:
24094 case OPC_DEXTRV_W:
24095 case OPC_DEXTRV_R_W:
24096 case OPC_DEXTRV_RS_W:
24097 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24098 break;
24099 case OPC_DMTHLIP:
24100 case OPC_DSHILO:
24101 case OPC_DSHILOV:
24102 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24103 break;
24104 default: /* Invalid */
24105 MIPS_INVAL("MASK EXTR.W");
24106 generate_exception_end(ctx, EXCP_RI);
24107 break;
24109 break;
24110 case OPC_DPAQ_W_QH_DSP:
24111 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24112 switch (op2) {
24113 case OPC_DPAU_H_OBL:
24114 case OPC_DPAU_H_OBR:
24115 case OPC_DPSU_H_OBL:
24116 case OPC_DPSU_H_OBR:
24117 case OPC_DPA_W_QH:
24118 case OPC_DPAQ_S_W_QH:
24119 case OPC_DPS_W_QH:
24120 case OPC_DPSQ_S_W_QH:
24121 case OPC_MULSAQ_S_W_QH:
24122 case OPC_DPAQ_SA_L_PW:
24123 case OPC_DPSQ_SA_L_PW:
24124 case OPC_MULSAQ_S_L_PW:
24125 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24126 break;
24127 case OPC_MAQ_S_W_QHLL:
24128 case OPC_MAQ_S_W_QHLR:
24129 case OPC_MAQ_S_W_QHRL:
24130 case OPC_MAQ_S_W_QHRR:
24131 case OPC_MAQ_SA_W_QHLL:
24132 case OPC_MAQ_SA_W_QHLR:
24133 case OPC_MAQ_SA_W_QHRL:
24134 case OPC_MAQ_SA_W_QHRR:
24135 case OPC_MAQ_S_L_PWL:
24136 case OPC_MAQ_S_L_PWR:
24137 case OPC_DMADD:
24138 case OPC_DMADDU:
24139 case OPC_DMSUB:
24140 case OPC_DMSUBU:
24141 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24142 break;
24143 default: /* Invalid */
24144 MIPS_INVAL("MASK DPAQ.W.QH");
24145 generate_exception_end(ctx, EXCP_RI);
24146 break;
24148 break;
24149 case OPC_DINSV_DSP:
24150 op2 = MASK_INSV(ctx->opcode);
24151 switch (op2) {
24152 case OPC_DINSV:
24154 TCGv t0, t1;
24156 if (rt == 0) {
24157 break;
24159 check_dsp(ctx);
24161 t0 = tcg_temp_new();
24162 t1 = tcg_temp_new();
24164 gen_load_gpr(t0, rt);
24165 gen_load_gpr(t1, rs);
24167 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24169 tcg_temp_free(t0);
24170 tcg_temp_free(t1);
24171 break;
24173 default: /* Invalid */
24174 MIPS_INVAL("MASK DINSV");
24175 generate_exception_end(ctx, EXCP_RI);
24176 break;
24178 break;
24179 case OPC_SHLL_OB_DSP:
24180 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24181 break;
24182 #endif
24183 default: /* Invalid */
24184 MIPS_INVAL("special3_legacy");
24185 generate_exception_end(ctx, EXCP_RI);
24186 break;
24190 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24192 int rs, rt, rd, sa;
24193 uint32_t op1, op2;
24194 int16_t imm;
24196 rs = (ctx->opcode >> 21) & 0x1f;
24197 rt = (ctx->opcode >> 16) & 0x1f;
24198 rd = (ctx->opcode >> 11) & 0x1f;
24199 sa = (ctx->opcode >> 6) & 0x1f;
24200 imm = sextract32(ctx->opcode, 7, 9);
24202 op1 = MASK_SPECIAL3(ctx->opcode);
24205 * EVA loads and stores overlap Loongson 2E instructions decoded by
24206 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24207 * EVA is absent.
24209 if (ctx->eva) {
24210 switch (op1) {
24211 case OPC_LWLE:
24212 case OPC_LWRE:
24213 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24214 /* fall through */
24215 case OPC_LBUE:
24216 case OPC_LHUE:
24217 case OPC_LBE:
24218 case OPC_LHE:
24219 case OPC_LLE:
24220 case OPC_LWE:
24221 check_cp0_enabled(ctx);
24222 gen_ld(ctx, op1, rt, rs, imm);
24223 return;
24224 case OPC_SWLE:
24225 case OPC_SWRE:
24226 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24227 /* fall through */
24228 case OPC_SBE:
24229 case OPC_SHE:
24230 case OPC_SWE:
24231 check_cp0_enabled(ctx);
24232 gen_st(ctx, op1, rt, rs, imm);
24233 return;
24234 case OPC_SCE:
24235 check_cp0_enabled(ctx);
24236 gen_st_cond(ctx, op1, rt, rs, imm);
24237 return;
24238 case OPC_CACHEE:
24239 check_cp0_enabled(ctx);
24240 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24241 gen_cache_operation(ctx, rt, rs, imm);
24243 /* Treat as NOP. */
24244 return;
24245 case OPC_PREFE:
24246 check_cp0_enabled(ctx);
24247 /* Treat as NOP. */
24248 return;
24252 switch (op1) {
24253 case OPC_EXT:
24254 case OPC_INS:
24255 check_insn(ctx, ISA_MIPS32R2);
24256 gen_bitops(ctx, op1, rt, rs, sa, rd);
24257 break;
24258 case OPC_BSHFL:
24259 op2 = MASK_BSHFL(ctx->opcode);
24260 switch (op2) {
24261 case OPC_ALIGN:
24262 case OPC_ALIGN_END:
24263 case OPC_BITSWAP:
24264 check_insn(ctx, ISA_MIPS32R6);
24265 decode_opc_special3_r6(env, ctx);
24266 break;
24267 default:
24268 check_insn(ctx, ISA_MIPS32R2);
24269 gen_bshfl(ctx, op2, rt, rd);
24270 break;
24272 break;
24273 #if defined(TARGET_MIPS64)
24274 case OPC_DEXTM:
24275 case OPC_DEXTU:
24276 case OPC_DEXT:
24277 case OPC_DINSM:
24278 case OPC_DINSU:
24279 case OPC_DINS:
24280 check_insn(ctx, ISA_MIPS64R2);
24281 check_mips_64(ctx);
24282 gen_bitops(ctx, op1, rt, rs, sa, rd);
24283 break;
24284 case OPC_DBSHFL:
24285 op2 = MASK_DBSHFL(ctx->opcode);
24286 switch (op2) {
24287 case OPC_DALIGN:
24288 case OPC_DALIGN_END:
24289 case OPC_DBITSWAP:
24290 check_insn(ctx, ISA_MIPS32R6);
24291 decode_opc_special3_r6(env, ctx);
24292 break;
24293 default:
24294 check_insn(ctx, ISA_MIPS64R2);
24295 check_mips_64(ctx);
24296 op2 = MASK_DBSHFL(ctx->opcode);
24297 gen_bshfl(ctx, op2, rt, rd);
24298 break;
24300 break;
24301 #endif
24302 case OPC_RDHWR:
24303 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24304 break;
24305 case OPC_FORK:
24306 check_mt(ctx);
24308 TCGv t0 = tcg_temp_new();
24309 TCGv t1 = tcg_temp_new();
24311 gen_load_gpr(t0, rt);
24312 gen_load_gpr(t1, rs);
24313 gen_helper_fork(t0, t1);
24314 tcg_temp_free(t0);
24315 tcg_temp_free(t1);
24317 break;
24318 case OPC_YIELD:
24319 check_mt(ctx);
24321 TCGv t0 = tcg_temp_new();
24323 gen_load_gpr(t0, rs);
24324 gen_helper_yield(t0, cpu_env, t0);
24325 gen_store_gpr(t0, rd);
24326 tcg_temp_free(t0);
24328 break;
24329 default:
24330 if (ctx->insn_flags & ISA_MIPS32R6) {
24331 decode_opc_special3_r6(env, ctx);
24332 } else {
24333 decode_opc_special3_legacy(env, ctx);
24338 /* MIPS SIMD Architecture (MSA) */
24339 static inline int check_msa_access(DisasContext *ctx)
24341 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24342 !(ctx->hflags & MIPS_HFLAG_F64))) {
24343 generate_exception_end(ctx, EXCP_RI);
24344 return 0;
24347 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24348 if (ctx->insn_flags & ASE_MSA) {
24349 generate_exception_end(ctx, EXCP_MSADIS);
24350 return 0;
24351 } else {
24352 generate_exception_end(ctx, EXCP_RI);
24353 return 0;
24356 return 1;
24359 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24361 /* generates tcg ops to check if any element is 0 */
24362 /* Note this function only works with MSA_WRLEN = 128 */
24363 uint64_t eval_zero_or_big = 0;
24364 uint64_t eval_big = 0;
24365 TCGv_i64 t0 = tcg_temp_new_i64();
24366 TCGv_i64 t1 = tcg_temp_new_i64();
24367 switch (df) {
24368 case DF_BYTE:
24369 eval_zero_or_big = 0x0101010101010101ULL;
24370 eval_big = 0x8080808080808080ULL;
24371 break;
24372 case DF_HALF:
24373 eval_zero_or_big = 0x0001000100010001ULL;
24374 eval_big = 0x8000800080008000ULL;
24375 break;
24376 case DF_WORD:
24377 eval_zero_or_big = 0x0000000100000001ULL;
24378 eval_big = 0x8000000080000000ULL;
24379 break;
24380 case DF_DOUBLE:
24381 eval_zero_or_big = 0x0000000000000001ULL;
24382 eval_big = 0x8000000000000000ULL;
24383 break;
24385 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
24386 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
24387 tcg_gen_andi_i64(t0, t0, eval_big);
24388 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
24389 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
24390 tcg_gen_andi_i64(t1, t1, eval_big);
24391 tcg_gen_or_i64(t0, t0, t1);
24392 /* if all bits are zero then all elements are not zero */
24393 /* if some bit is non-zero then some element is zero */
24394 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
24395 tcg_gen_trunc_i64_tl(tresult, t0);
24396 tcg_temp_free_i64(t0);
24397 tcg_temp_free_i64(t1);
24400 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
24402 uint8_t df = (ctx->opcode >> 21) & 0x3;
24403 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24404 int64_t s16 = (int16_t)ctx->opcode;
24406 check_msa_access(ctx);
24408 if (ctx->hflags & MIPS_HFLAG_BMASK) {
24409 generate_exception_end(ctx, EXCP_RI);
24410 return;
24412 switch (op1) {
24413 case OPC_BZ_V:
24414 case OPC_BNZ_V:
24416 TCGv_i64 t0 = tcg_temp_new_i64();
24417 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
24418 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
24419 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
24420 tcg_gen_trunc_i64_tl(bcond, t0);
24421 tcg_temp_free_i64(t0);
24423 break;
24424 case OPC_BZ_B:
24425 case OPC_BZ_H:
24426 case OPC_BZ_W:
24427 case OPC_BZ_D:
24428 gen_check_zero_element(bcond, df, wt);
24429 break;
24430 case OPC_BNZ_B:
24431 case OPC_BNZ_H:
24432 case OPC_BNZ_W:
24433 case OPC_BNZ_D:
24434 gen_check_zero_element(bcond, df, wt);
24435 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
24436 break;
24439 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
24441 ctx->hflags |= MIPS_HFLAG_BC;
24442 ctx->hflags |= MIPS_HFLAG_BDS32;
24445 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
24447 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
24448 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
24449 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24450 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24452 TCGv_i32 twd = tcg_const_i32(wd);
24453 TCGv_i32 tws = tcg_const_i32(ws);
24454 TCGv_i32 ti8 = tcg_const_i32(i8);
24456 switch (MASK_MSA_I8(ctx->opcode)) {
24457 case OPC_ANDI_B:
24458 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
24459 break;
24460 case OPC_ORI_B:
24461 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
24462 break;
24463 case OPC_NORI_B:
24464 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
24465 break;
24466 case OPC_XORI_B:
24467 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
24468 break;
24469 case OPC_BMNZI_B:
24470 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
24471 break;
24472 case OPC_BMZI_B:
24473 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
24474 break;
24475 case OPC_BSELI_B:
24476 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
24477 break;
24478 case OPC_SHF_B:
24479 case OPC_SHF_H:
24480 case OPC_SHF_W:
24482 uint8_t df = (ctx->opcode >> 24) & 0x3;
24483 if (df == DF_DOUBLE) {
24484 generate_exception_end(ctx, EXCP_RI);
24485 } else {
24486 TCGv_i32 tdf = tcg_const_i32(df);
24487 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
24488 tcg_temp_free_i32(tdf);
24491 break;
24492 default:
24493 MIPS_INVAL("MSA instruction");
24494 generate_exception_end(ctx, EXCP_RI);
24495 break;
24498 tcg_temp_free_i32(twd);
24499 tcg_temp_free_i32(tws);
24500 tcg_temp_free_i32(ti8);
24503 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
24505 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24506 uint8_t df = (ctx->opcode >> 21) & 0x3;
24507 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
24508 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
24509 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24510 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24512 TCGv_i32 tdf = tcg_const_i32(df);
24513 TCGv_i32 twd = tcg_const_i32(wd);
24514 TCGv_i32 tws = tcg_const_i32(ws);
24515 TCGv_i32 timm = tcg_temp_new_i32();
24516 tcg_gen_movi_i32(timm, u5);
24518 switch (MASK_MSA_I5(ctx->opcode)) {
24519 case OPC_ADDVI_df:
24520 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
24521 break;
24522 case OPC_SUBVI_df:
24523 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
24524 break;
24525 case OPC_MAXI_S_df:
24526 tcg_gen_movi_i32(timm, s5);
24527 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
24528 break;
24529 case OPC_MAXI_U_df:
24530 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
24531 break;
24532 case OPC_MINI_S_df:
24533 tcg_gen_movi_i32(timm, s5);
24534 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
24535 break;
24536 case OPC_MINI_U_df:
24537 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
24538 break;
24539 case OPC_CEQI_df:
24540 tcg_gen_movi_i32(timm, s5);
24541 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
24542 break;
24543 case OPC_CLTI_S_df:
24544 tcg_gen_movi_i32(timm, s5);
24545 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
24546 break;
24547 case OPC_CLTI_U_df:
24548 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
24549 break;
24550 case OPC_CLEI_S_df:
24551 tcg_gen_movi_i32(timm, s5);
24552 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
24553 break;
24554 case OPC_CLEI_U_df:
24555 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
24556 break;
24557 case OPC_LDI_df:
24559 int32_t s10 = sextract32(ctx->opcode, 11, 10);
24560 tcg_gen_movi_i32(timm, s10);
24561 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
24563 break;
24564 default:
24565 MIPS_INVAL("MSA instruction");
24566 generate_exception_end(ctx, EXCP_RI);
24567 break;
24570 tcg_temp_free_i32(tdf);
24571 tcg_temp_free_i32(twd);
24572 tcg_temp_free_i32(tws);
24573 tcg_temp_free_i32(timm);
24576 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
24578 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24579 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
24580 uint32_t df = 0, m = 0;
24581 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24582 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24584 TCGv_i32 tdf;
24585 TCGv_i32 tm;
24586 TCGv_i32 twd;
24587 TCGv_i32 tws;
24589 if ((dfm & 0x40) == 0x00) {
24590 m = dfm & 0x3f;
24591 df = DF_DOUBLE;
24592 } else if ((dfm & 0x60) == 0x40) {
24593 m = dfm & 0x1f;
24594 df = DF_WORD;
24595 } else if ((dfm & 0x70) == 0x60) {
24596 m = dfm & 0x0f;
24597 df = DF_HALF;
24598 } else if ((dfm & 0x78) == 0x70) {
24599 m = dfm & 0x7;
24600 df = DF_BYTE;
24601 } else {
24602 generate_exception_end(ctx, EXCP_RI);
24603 return;
24606 tdf = tcg_const_i32(df);
24607 tm = tcg_const_i32(m);
24608 twd = tcg_const_i32(wd);
24609 tws = tcg_const_i32(ws);
24611 switch (MASK_MSA_BIT(ctx->opcode)) {
24612 case OPC_SLLI_df:
24613 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
24614 break;
24615 case OPC_SRAI_df:
24616 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
24617 break;
24618 case OPC_SRLI_df:
24619 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
24620 break;
24621 case OPC_BCLRI_df:
24622 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
24623 break;
24624 case OPC_BSETI_df:
24625 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
24626 break;
24627 case OPC_BNEGI_df:
24628 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
24629 break;
24630 case OPC_BINSLI_df:
24631 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
24632 break;
24633 case OPC_BINSRI_df:
24634 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
24635 break;
24636 case OPC_SAT_S_df:
24637 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
24638 break;
24639 case OPC_SAT_U_df:
24640 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
24641 break;
24642 case OPC_SRARI_df:
24643 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
24644 break;
24645 case OPC_SRLRI_df:
24646 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
24647 break;
24648 default:
24649 MIPS_INVAL("MSA instruction");
24650 generate_exception_end(ctx, EXCP_RI);
24651 break;
24654 tcg_temp_free_i32(tdf);
24655 tcg_temp_free_i32(tm);
24656 tcg_temp_free_i32(twd);
24657 tcg_temp_free_i32(tws);
24660 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
24662 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24663 uint8_t df = (ctx->opcode >> 21) & 0x3;
24664 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24665 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24666 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24668 TCGv_i32 tdf = tcg_const_i32(df);
24669 TCGv_i32 twd = tcg_const_i32(wd);
24670 TCGv_i32 tws = tcg_const_i32(ws);
24671 TCGv_i32 twt = tcg_const_i32(wt);
24673 switch (MASK_MSA_3R(ctx->opcode)) {
24674 case OPC_SLL_df:
24675 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
24676 break;
24677 case OPC_ADDV_df:
24678 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
24679 break;
24680 case OPC_CEQ_df:
24681 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
24682 break;
24683 case OPC_ADD_A_df:
24684 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
24685 break;
24686 case OPC_SUBS_S_df:
24687 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
24688 break;
24689 case OPC_MULV_df:
24690 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
24691 break;
24692 case OPC_SLD_df:
24693 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
24694 break;
24695 case OPC_VSHF_df:
24696 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
24697 break;
24698 case OPC_SRA_df:
24699 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
24700 break;
24701 case OPC_SUBV_df:
24702 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
24703 break;
24704 case OPC_ADDS_A_df:
24705 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
24706 break;
24707 case OPC_SUBS_U_df:
24708 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
24709 break;
24710 case OPC_MADDV_df:
24711 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
24712 break;
24713 case OPC_SPLAT_df:
24714 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
24715 break;
24716 case OPC_SRAR_df:
24717 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
24718 break;
24719 case OPC_SRL_df:
24720 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
24721 break;
24722 case OPC_MAX_S_df:
24723 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
24724 break;
24725 case OPC_CLT_S_df:
24726 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
24727 break;
24728 case OPC_ADDS_S_df:
24729 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
24730 break;
24731 case OPC_SUBSUS_U_df:
24732 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
24733 break;
24734 case OPC_MSUBV_df:
24735 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
24736 break;
24737 case OPC_PCKEV_df:
24738 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
24739 break;
24740 case OPC_SRLR_df:
24741 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
24742 break;
24743 case OPC_BCLR_df:
24744 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
24745 break;
24746 case OPC_MAX_U_df:
24747 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
24748 break;
24749 case OPC_CLT_U_df:
24750 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
24751 break;
24752 case OPC_ADDS_U_df:
24753 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
24754 break;
24755 case OPC_SUBSUU_S_df:
24756 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
24757 break;
24758 case OPC_PCKOD_df:
24759 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
24760 break;
24761 case OPC_BSET_df:
24762 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
24763 break;
24764 case OPC_MIN_S_df:
24765 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
24766 break;
24767 case OPC_CLE_S_df:
24768 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
24769 break;
24770 case OPC_AVE_S_df:
24771 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
24772 break;
24773 case OPC_ASUB_S_df:
24774 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
24775 break;
24776 case OPC_DIV_S_df:
24777 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
24778 break;
24779 case OPC_ILVL_df:
24780 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
24781 break;
24782 case OPC_BNEG_df:
24783 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
24784 break;
24785 case OPC_MIN_U_df:
24786 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
24787 break;
24788 case OPC_CLE_U_df:
24789 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
24790 break;
24791 case OPC_AVE_U_df:
24792 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
24793 break;
24794 case OPC_ASUB_U_df:
24795 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
24796 break;
24797 case OPC_DIV_U_df:
24798 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
24799 break;
24800 case OPC_ILVR_df:
24801 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
24802 break;
24803 case OPC_BINSL_df:
24804 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
24805 break;
24806 case OPC_MAX_A_df:
24807 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
24808 break;
24809 case OPC_AVER_S_df:
24810 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
24811 break;
24812 case OPC_MOD_S_df:
24813 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
24814 break;
24815 case OPC_ILVEV_df:
24816 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
24817 break;
24818 case OPC_BINSR_df:
24819 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
24820 break;
24821 case OPC_MIN_A_df:
24822 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
24823 break;
24824 case OPC_AVER_U_df:
24825 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
24826 break;
24827 case OPC_MOD_U_df:
24828 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
24829 break;
24830 case OPC_ILVOD_df:
24831 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
24832 break;
24834 case OPC_DOTP_S_df:
24835 case OPC_DOTP_U_df:
24836 case OPC_DPADD_S_df:
24837 case OPC_DPADD_U_df:
24838 case OPC_DPSUB_S_df:
24839 case OPC_HADD_S_df:
24840 case OPC_DPSUB_U_df:
24841 case OPC_HADD_U_df:
24842 case OPC_HSUB_S_df:
24843 case OPC_HSUB_U_df:
24844 if (df == DF_BYTE) {
24845 generate_exception_end(ctx, EXCP_RI);
24846 break;
24848 switch (MASK_MSA_3R(ctx->opcode)) {
24849 case OPC_DOTP_S_df:
24850 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
24851 break;
24852 case OPC_DOTP_U_df:
24853 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
24854 break;
24855 case OPC_DPADD_S_df:
24856 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
24857 break;
24858 case OPC_DPADD_U_df:
24859 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
24860 break;
24861 case OPC_DPSUB_S_df:
24862 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
24863 break;
24864 case OPC_HADD_S_df:
24865 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
24866 break;
24867 case OPC_DPSUB_U_df:
24868 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
24869 break;
24870 case OPC_HADD_U_df:
24871 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
24872 break;
24873 case OPC_HSUB_S_df:
24874 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
24875 break;
24876 case OPC_HSUB_U_df:
24877 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
24878 break;
24880 break;
24881 default:
24882 MIPS_INVAL("MSA instruction");
24883 generate_exception_end(ctx, EXCP_RI);
24884 break;
24886 tcg_temp_free_i32(twd);
24887 tcg_temp_free_i32(tws);
24888 tcg_temp_free_i32(twt);
24889 tcg_temp_free_i32(tdf);
24892 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
24894 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
24895 uint8_t source = (ctx->opcode >> 11) & 0x1f;
24896 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
24897 TCGv telm = tcg_temp_new();
24898 TCGv_i32 tsr = tcg_const_i32(source);
24899 TCGv_i32 tdt = tcg_const_i32(dest);
24901 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
24902 case OPC_CTCMSA:
24903 gen_load_gpr(telm, source);
24904 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
24905 break;
24906 case OPC_CFCMSA:
24907 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
24908 gen_store_gpr(telm, dest);
24909 break;
24910 case OPC_MOVE_V:
24911 gen_helper_msa_move_v(cpu_env, tdt, tsr);
24912 break;
24913 default:
24914 MIPS_INVAL("MSA instruction");
24915 generate_exception_end(ctx, EXCP_RI);
24916 break;
24919 tcg_temp_free(telm);
24920 tcg_temp_free_i32(tdt);
24921 tcg_temp_free_i32(tsr);
24924 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
24925 uint32_t n)
24927 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24928 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24929 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24931 TCGv_i32 tws = tcg_const_i32(ws);
24932 TCGv_i32 twd = tcg_const_i32(wd);
24933 TCGv_i32 tn = tcg_const_i32(n);
24934 TCGv_i32 tdf = tcg_const_i32(df);
24936 switch (MASK_MSA_ELM(ctx->opcode)) {
24937 case OPC_SLDI_df:
24938 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
24939 break;
24940 case OPC_SPLATI_df:
24941 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
24942 break;
24943 case OPC_INSVE_df:
24944 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
24945 break;
24946 case OPC_COPY_S_df:
24947 case OPC_COPY_U_df:
24948 case OPC_INSERT_df:
24949 #if !defined(TARGET_MIPS64)
24950 /* Double format valid only for MIPS64 */
24951 if (df == DF_DOUBLE) {
24952 generate_exception_end(ctx, EXCP_RI);
24953 break;
24955 #endif
24956 switch (MASK_MSA_ELM(ctx->opcode)) {
24957 case OPC_COPY_S_df:
24958 if (likely(wd != 0)) {
24959 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
24961 break;
24962 case OPC_COPY_U_df:
24963 if (likely(wd != 0)) {
24964 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
24966 break;
24967 case OPC_INSERT_df:
24968 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
24969 break;
24971 break;
24972 default:
24973 MIPS_INVAL("MSA instruction");
24974 generate_exception_end(ctx, EXCP_RI);
24976 tcg_temp_free_i32(twd);
24977 tcg_temp_free_i32(tws);
24978 tcg_temp_free_i32(tn);
24979 tcg_temp_free_i32(tdf);
24982 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
24984 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
24985 uint32_t df = 0, n = 0;
24987 if ((dfn & 0x30) == 0x00) {
24988 n = dfn & 0x0f;
24989 df = DF_BYTE;
24990 } else if ((dfn & 0x38) == 0x20) {
24991 n = dfn & 0x07;
24992 df = DF_HALF;
24993 } else if ((dfn & 0x3c) == 0x30) {
24994 n = dfn & 0x03;
24995 df = DF_WORD;
24996 } else if ((dfn & 0x3e) == 0x38) {
24997 n = dfn & 0x01;
24998 df = DF_DOUBLE;
24999 } else if (dfn == 0x3E) {
25000 /* CTCMSA, CFCMSA, MOVE.V */
25001 gen_msa_elm_3e(env, ctx);
25002 return;
25003 } else {
25004 generate_exception_end(ctx, EXCP_RI);
25005 return;
25008 gen_msa_elm_df(env, ctx, df, n);
25011 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25013 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25014 uint8_t df = (ctx->opcode >> 21) & 0x1;
25015 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25016 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25017 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25019 TCGv_i32 twd = tcg_const_i32(wd);
25020 TCGv_i32 tws = tcg_const_i32(ws);
25021 TCGv_i32 twt = tcg_const_i32(wt);
25022 TCGv_i32 tdf = tcg_temp_new_i32();
25024 /* adjust df value for floating-point instruction */
25025 tcg_gen_movi_i32(tdf, df + 2);
25027 switch (MASK_MSA_3RF(ctx->opcode)) {
25028 case OPC_FCAF_df:
25029 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25030 break;
25031 case OPC_FADD_df:
25032 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25033 break;
25034 case OPC_FCUN_df:
25035 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25036 break;
25037 case OPC_FSUB_df:
25038 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25039 break;
25040 case OPC_FCOR_df:
25041 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25042 break;
25043 case OPC_FCEQ_df:
25044 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25045 break;
25046 case OPC_FMUL_df:
25047 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25048 break;
25049 case OPC_FCUNE_df:
25050 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25051 break;
25052 case OPC_FCUEQ_df:
25053 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25054 break;
25055 case OPC_FDIV_df:
25056 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25057 break;
25058 case OPC_FCNE_df:
25059 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25060 break;
25061 case OPC_FCLT_df:
25062 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25063 break;
25064 case OPC_FMADD_df:
25065 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25066 break;
25067 case OPC_MUL_Q_df:
25068 tcg_gen_movi_i32(tdf, df + 1);
25069 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25070 break;
25071 case OPC_FCULT_df:
25072 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25073 break;
25074 case OPC_FMSUB_df:
25075 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25076 break;
25077 case OPC_MADD_Q_df:
25078 tcg_gen_movi_i32(tdf, df + 1);
25079 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25080 break;
25081 case OPC_FCLE_df:
25082 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25083 break;
25084 case OPC_MSUB_Q_df:
25085 tcg_gen_movi_i32(tdf, df + 1);
25086 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25087 break;
25088 case OPC_FCULE_df:
25089 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25090 break;
25091 case OPC_FEXP2_df:
25092 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25093 break;
25094 case OPC_FSAF_df:
25095 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25096 break;
25097 case OPC_FEXDO_df:
25098 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25099 break;
25100 case OPC_FSUN_df:
25101 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25102 break;
25103 case OPC_FSOR_df:
25104 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25105 break;
25106 case OPC_FSEQ_df:
25107 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25108 break;
25109 case OPC_FTQ_df:
25110 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25111 break;
25112 case OPC_FSUNE_df:
25113 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25114 break;
25115 case OPC_FSUEQ_df:
25116 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25117 break;
25118 case OPC_FSNE_df:
25119 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25120 break;
25121 case OPC_FSLT_df:
25122 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25123 break;
25124 case OPC_FMIN_df:
25125 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25126 break;
25127 case OPC_MULR_Q_df:
25128 tcg_gen_movi_i32(tdf, df + 1);
25129 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25130 break;
25131 case OPC_FSULT_df:
25132 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25133 break;
25134 case OPC_FMIN_A_df:
25135 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25136 break;
25137 case OPC_MADDR_Q_df:
25138 tcg_gen_movi_i32(tdf, df + 1);
25139 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25140 break;
25141 case OPC_FSLE_df:
25142 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25143 break;
25144 case OPC_FMAX_df:
25145 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25146 break;
25147 case OPC_MSUBR_Q_df:
25148 tcg_gen_movi_i32(tdf, df + 1);
25149 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25150 break;
25151 case OPC_FSULE_df:
25152 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25153 break;
25154 case OPC_FMAX_A_df:
25155 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25156 break;
25157 default:
25158 MIPS_INVAL("MSA instruction");
25159 generate_exception_end(ctx, EXCP_RI);
25160 break;
25163 tcg_temp_free_i32(twd);
25164 tcg_temp_free_i32(tws);
25165 tcg_temp_free_i32(twt);
25166 tcg_temp_free_i32(tdf);
25169 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25171 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25172 (op & (0x7 << 18)))
25173 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25174 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25175 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25176 uint8_t df = (ctx->opcode >> 16) & 0x3;
25177 TCGv_i32 twd = tcg_const_i32(wd);
25178 TCGv_i32 tws = tcg_const_i32(ws);
25179 TCGv_i32 twt = tcg_const_i32(wt);
25180 TCGv_i32 tdf = tcg_const_i32(df);
25182 switch (MASK_MSA_2R(ctx->opcode)) {
25183 case OPC_FILL_df:
25184 #if !defined(TARGET_MIPS64)
25185 /* Double format valid only for MIPS64 */
25186 if (df == DF_DOUBLE) {
25187 generate_exception_end(ctx, EXCP_RI);
25188 break;
25190 #endif
25191 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25192 break;
25193 case OPC_PCNT_df:
25194 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25195 break;
25196 case OPC_NLOC_df:
25197 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25198 break;
25199 case OPC_NLZC_df:
25200 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25201 break;
25202 default:
25203 MIPS_INVAL("MSA instruction");
25204 generate_exception_end(ctx, EXCP_RI);
25205 break;
25208 tcg_temp_free_i32(twd);
25209 tcg_temp_free_i32(tws);
25210 tcg_temp_free_i32(twt);
25211 tcg_temp_free_i32(tdf);
25214 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25216 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25217 (op & (0xf << 17)))
25218 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25219 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25220 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25221 uint8_t df = (ctx->opcode >> 16) & 0x1;
25222 TCGv_i32 twd = tcg_const_i32(wd);
25223 TCGv_i32 tws = tcg_const_i32(ws);
25224 TCGv_i32 twt = tcg_const_i32(wt);
25225 /* adjust df value for floating-point instruction */
25226 TCGv_i32 tdf = tcg_const_i32(df + 2);
25228 switch (MASK_MSA_2RF(ctx->opcode)) {
25229 case OPC_FCLASS_df:
25230 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25231 break;
25232 case OPC_FTRUNC_S_df:
25233 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25234 break;
25235 case OPC_FTRUNC_U_df:
25236 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25237 break;
25238 case OPC_FSQRT_df:
25239 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25240 break;
25241 case OPC_FRSQRT_df:
25242 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25243 break;
25244 case OPC_FRCP_df:
25245 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25246 break;
25247 case OPC_FRINT_df:
25248 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25249 break;
25250 case OPC_FLOG2_df:
25251 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25252 break;
25253 case OPC_FEXUPL_df:
25254 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25255 break;
25256 case OPC_FEXUPR_df:
25257 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25258 break;
25259 case OPC_FFQL_df:
25260 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25261 break;
25262 case OPC_FFQR_df:
25263 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25264 break;
25265 case OPC_FTINT_S_df:
25266 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25267 break;
25268 case OPC_FTINT_U_df:
25269 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25270 break;
25271 case OPC_FFINT_S_df:
25272 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25273 break;
25274 case OPC_FFINT_U_df:
25275 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25276 break;
25279 tcg_temp_free_i32(twd);
25280 tcg_temp_free_i32(tws);
25281 tcg_temp_free_i32(twt);
25282 tcg_temp_free_i32(tdf);
25285 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25287 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25288 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25289 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25290 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25291 TCGv_i32 twd = tcg_const_i32(wd);
25292 TCGv_i32 tws = tcg_const_i32(ws);
25293 TCGv_i32 twt = tcg_const_i32(wt);
25295 switch (MASK_MSA_VEC(ctx->opcode)) {
25296 case OPC_AND_V:
25297 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25298 break;
25299 case OPC_OR_V:
25300 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25301 break;
25302 case OPC_NOR_V:
25303 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25304 break;
25305 case OPC_XOR_V:
25306 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25307 break;
25308 case OPC_BMNZ_V:
25309 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25310 break;
25311 case OPC_BMZ_V:
25312 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25313 break;
25314 case OPC_BSEL_V:
25315 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25316 break;
25317 default:
25318 MIPS_INVAL("MSA instruction");
25319 generate_exception_end(ctx, EXCP_RI);
25320 break;
25323 tcg_temp_free_i32(twd);
25324 tcg_temp_free_i32(tws);
25325 tcg_temp_free_i32(twt);
25328 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25330 switch (MASK_MSA_VEC(ctx->opcode)) {
25331 case OPC_AND_V:
25332 case OPC_OR_V:
25333 case OPC_NOR_V:
25334 case OPC_XOR_V:
25335 case OPC_BMNZ_V:
25336 case OPC_BMZ_V:
25337 case OPC_BSEL_V:
25338 gen_msa_vec_v(env, ctx);
25339 break;
25340 case OPC_MSA_2R:
25341 gen_msa_2r(env, ctx);
25342 break;
25343 case OPC_MSA_2RF:
25344 gen_msa_2rf(env, ctx);
25345 break;
25346 default:
25347 MIPS_INVAL("MSA instruction");
25348 generate_exception_end(ctx, EXCP_RI);
25349 break;
25353 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25355 uint32_t opcode = ctx->opcode;
25356 check_insn(ctx, ASE_MSA);
25357 check_msa_access(ctx);
25359 switch (MASK_MSA_MINOR(opcode)) {
25360 case OPC_MSA_I8_00:
25361 case OPC_MSA_I8_01:
25362 case OPC_MSA_I8_02:
25363 gen_msa_i8(env, ctx);
25364 break;
25365 case OPC_MSA_I5_06:
25366 case OPC_MSA_I5_07:
25367 gen_msa_i5(env, ctx);
25368 break;
25369 case OPC_MSA_BIT_09:
25370 case OPC_MSA_BIT_0A:
25371 gen_msa_bit(env, ctx);
25372 break;
25373 case OPC_MSA_3R_0D:
25374 case OPC_MSA_3R_0E:
25375 case OPC_MSA_3R_0F:
25376 case OPC_MSA_3R_10:
25377 case OPC_MSA_3R_11:
25378 case OPC_MSA_3R_12:
25379 case OPC_MSA_3R_13:
25380 case OPC_MSA_3R_14:
25381 case OPC_MSA_3R_15:
25382 gen_msa_3r(env, ctx);
25383 break;
25384 case OPC_MSA_ELM:
25385 gen_msa_elm(env, ctx);
25386 break;
25387 case OPC_MSA_3RF_1A:
25388 case OPC_MSA_3RF_1B:
25389 case OPC_MSA_3RF_1C:
25390 gen_msa_3rf(env, ctx);
25391 break;
25392 case OPC_MSA_VEC:
25393 gen_msa_vec(env, ctx);
25394 break;
25395 case OPC_LD_B:
25396 case OPC_LD_H:
25397 case OPC_LD_W:
25398 case OPC_LD_D:
25399 case OPC_ST_B:
25400 case OPC_ST_H:
25401 case OPC_ST_W:
25402 case OPC_ST_D:
25404 int32_t s10 = sextract32(ctx->opcode, 16, 10);
25405 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
25406 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25407 uint8_t df = (ctx->opcode >> 0) & 0x3;
25409 TCGv_i32 twd = tcg_const_i32(wd);
25410 TCGv taddr = tcg_temp_new();
25411 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
25413 switch (MASK_MSA_MINOR(opcode)) {
25414 case OPC_LD_B:
25415 gen_helper_msa_ld_b(cpu_env, twd, taddr);
25416 break;
25417 case OPC_LD_H:
25418 gen_helper_msa_ld_h(cpu_env, twd, taddr);
25419 break;
25420 case OPC_LD_W:
25421 gen_helper_msa_ld_w(cpu_env, twd, taddr);
25422 break;
25423 case OPC_LD_D:
25424 gen_helper_msa_ld_d(cpu_env, twd, taddr);
25425 break;
25426 case OPC_ST_B:
25427 gen_helper_msa_st_b(cpu_env, twd, taddr);
25428 break;
25429 case OPC_ST_H:
25430 gen_helper_msa_st_h(cpu_env, twd, taddr);
25431 break;
25432 case OPC_ST_W:
25433 gen_helper_msa_st_w(cpu_env, twd, taddr);
25434 break;
25435 case OPC_ST_D:
25436 gen_helper_msa_st_d(cpu_env, twd, taddr);
25437 break;
25440 tcg_temp_free_i32(twd);
25441 tcg_temp_free(taddr);
25443 break;
25444 default:
25445 MIPS_INVAL("MSA instruction");
25446 generate_exception_end(ctx, EXCP_RI);
25447 break;
25452 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25454 int32_t offset;
25455 int rs, rt, rd, sa;
25456 uint32_t op, op1;
25457 int16_t imm;
25459 /* make sure instructions are on a word boundary */
25460 if (ctx->base.pc_next & 0x3) {
25461 env->CP0_BadVAddr = ctx->base.pc_next;
25462 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25463 return;
25466 /* Handle blikely not taken case */
25467 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25468 TCGLabel *l1 = gen_new_label();
25470 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25471 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25472 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25473 gen_set_label(l1);
25476 op = MASK_OP_MAJOR(ctx->opcode);
25477 rs = (ctx->opcode >> 21) & 0x1f;
25478 rt = (ctx->opcode >> 16) & 0x1f;
25479 rd = (ctx->opcode >> 11) & 0x1f;
25480 sa = (ctx->opcode >> 6) & 0x1f;
25481 imm = (int16_t)ctx->opcode;
25482 switch (op) {
25483 case OPC_SPECIAL:
25484 decode_opc_special(env, ctx);
25485 break;
25486 case OPC_SPECIAL2:
25487 decode_opc_special2_legacy(env, ctx);
25488 break;
25489 case OPC_SPECIAL3:
25490 decode_opc_special3(env, ctx);
25491 break;
25492 case OPC_REGIMM:
25493 op1 = MASK_REGIMM(ctx->opcode);
25494 switch (op1) {
25495 case OPC_BLTZL: /* REGIMM branches */
25496 case OPC_BGEZL:
25497 case OPC_BLTZALL:
25498 case OPC_BGEZALL:
25499 check_insn(ctx, ISA_MIPS2);
25500 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25501 /* Fallthrough */
25502 case OPC_BLTZ:
25503 case OPC_BGEZ:
25504 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25505 break;
25506 case OPC_BLTZAL:
25507 case OPC_BGEZAL:
25508 if (ctx->insn_flags & ISA_MIPS32R6) {
25509 if (rs == 0) {
25510 /* OPC_NAL, OPC_BAL */
25511 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
25512 } else {
25513 generate_exception_end(ctx, EXCP_RI);
25515 } else {
25516 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25518 break;
25519 case OPC_TGEI: /* REGIMM traps */
25520 case OPC_TGEIU:
25521 case OPC_TLTI:
25522 case OPC_TLTIU:
25523 case OPC_TEQI:
25525 case OPC_TNEI:
25526 check_insn(ctx, ISA_MIPS2);
25527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25528 gen_trap(ctx, op1, rs, -1, imm);
25529 break;
25530 case OPC_SIGRIE:
25531 check_insn(ctx, ISA_MIPS32R6);
25532 generate_exception_end(ctx, EXCP_RI);
25533 break;
25534 case OPC_SYNCI:
25535 check_insn(ctx, ISA_MIPS32R2);
25536 /* Break the TB to be able to sync copied instructions
25537 immediately */
25538 ctx->base.is_jmp = DISAS_STOP;
25539 break;
25540 case OPC_BPOSGE32: /* MIPS DSP branch */
25541 #if defined(TARGET_MIPS64)
25542 case OPC_BPOSGE64:
25543 #endif
25544 check_dsp(ctx);
25545 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
25546 break;
25547 #if defined(TARGET_MIPS64)
25548 case OPC_DAHI:
25549 check_insn(ctx, ISA_MIPS32R6);
25550 check_mips_64(ctx);
25551 if (rs != 0) {
25552 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
25554 break;
25555 case OPC_DATI:
25556 check_insn(ctx, ISA_MIPS32R6);
25557 check_mips_64(ctx);
25558 if (rs != 0) {
25559 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
25561 break;
25562 #endif
25563 default: /* Invalid */
25564 MIPS_INVAL("regimm");
25565 generate_exception_end(ctx, EXCP_RI);
25566 break;
25568 break;
25569 case OPC_CP0:
25570 check_cp0_enabled(ctx);
25571 op1 = MASK_CP0(ctx->opcode);
25572 switch (op1) {
25573 case OPC_MFC0:
25574 case OPC_MTC0:
25575 case OPC_MFTR:
25576 case OPC_MTTR:
25577 case OPC_MFHC0:
25578 case OPC_MTHC0:
25579 #if defined(TARGET_MIPS64)
25580 case OPC_DMFC0:
25581 case OPC_DMTC0:
25582 #endif
25583 #ifndef CONFIG_USER_ONLY
25584 gen_cp0(env, ctx, op1, rt, rd);
25585 #endif /* !CONFIG_USER_ONLY */
25586 break;
25587 case OPC_C0:
25588 case OPC_C0_1:
25589 case OPC_C0_2:
25590 case OPC_C0_3:
25591 case OPC_C0_4:
25592 case OPC_C0_5:
25593 case OPC_C0_6:
25594 case OPC_C0_7:
25595 case OPC_C0_8:
25596 case OPC_C0_9:
25597 case OPC_C0_A:
25598 case OPC_C0_B:
25599 case OPC_C0_C:
25600 case OPC_C0_D:
25601 case OPC_C0_E:
25602 case OPC_C0_F:
25603 #ifndef CONFIG_USER_ONLY
25604 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
25605 #endif /* !CONFIG_USER_ONLY */
25606 break;
25607 case OPC_MFMC0:
25608 #ifndef CONFIG_USER_ONLY
25610 uint32_t op2;
25611 TCGv t0 = tcg_temp_new();
25613 op2 = MASK_MFMC0(ctx->opcode);
25614 switch (op2) {
25615 case OPC_DMT:
25616 check_cp0_mt(ctx);
25617 gen_helper_dmt(t0);
25618 gen_store_gpr(t0, rt);
25619 break;
25620 case OPC_EMT:
25621 check_cp0_mt(ctx);
25622 gen_helper_emt(t0);
25623 gen_store_gpr(t0, rt);
25624 break;
25625 case OPC_DVPE:
25626 check_cp0_mt(ctx);
25627 gen_helper_dvpe(t0, cpu_env);
25628 gen_store_gpr(t0, rt);
25629 break;
25630 case OPC_EVPE:
25631 check_cp0_mt(ctx);
25632 gen_helper_evpe(t0, cpu_env);
25633 gen_store_gpr(t0, rt);
25634 break;
25635 case OPC_DVP:
25636 check_insn(ctx, ISA_MIPS32R6);
25637 if (ctx->vp) {
25638 gen_helper_dvp(t0, cpu_env);
25639 gen_store_gpr(t0, rt);
25641 break;
25642 case OPC_EVP:
25643 check_insn(ctx, ISA_MIPS32R6);
25644 if (ctx->vp) {
25645 gen_helper_evp(t0, cpu_env);
25646 gen_store_gpr(t0, rt);
25648 break;
25649 case OPC_DI:
25650 check_insn(ctx, ISA_MIPS32R2);
25651 save_cpu_state(ctx, 1);
25652 gen_helper_di(t0, cpu_env);
25653 gen_store_gpr(t0, rt);
25654 /* Stop translation as we may have switched
25655 the execution mode. */
25656 ctx->base.is_jmp = DISAS_STOP;
25657 break;
25658 case OPC_EI:
25659 check_insn(ctx, ISA_MIPS32R2);
25660 save_cpu_state(ctx, 1);
25661 gen_helper_ei(t0, cpu_env);
25662 gen_store_gpr(t0, rt);
25663 /* DISAS_STOP isn't sufficient, we need to ensure we break
25664 out of translated code to check for pending interrupts */
25665 gen_save_pc(ctx->base.pc_next + 4);
25666 ctx->base.is_jmp = DISAS_EXIT;
25667 break;
25668 default: /* Invalid */
25669 MIPS_INVAL("mfmc0");
25670 generate_exception_end(ctx, EXCP_RI);
25671 break;
25673 tcg_temp_free(t0);
25675 #endif /* !CONFIG_USER_ONLY */
25676 break;
25677 case OPC_RDPGPR:
25678 check_insn(ctx, ISA_MIPS32R2);
25679 gen_load_srsgpr(rt, rd);
25680 break;
25681 case OPC_WRPGPR:
25682 check_insn(ctx, ISA_MIPS32R2);
25683 gen_store_srsgpr(rt, rd);
25684 break;
25685 default:
25686 MIPS_INVAL("cp0");
25687 generate_exception_end(ctx, EXCP_RI);
25688 break;
25690 break;
25691 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25692 if (ctx->insn_flags & ISA_MIPS32R6) {
25693 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25694 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25695 } else {
25696 /* OPC_ADDI */
25697 /* Arithmetic with immediate opcode */
25698 gen_arith_imm(ctx, op, rt, rs, imm);
25700 break;
25701 case OPC_ADDIU:
25702 gen_arith_imm(ctx, op, rt, rs, imm);
25703 break;
25704 case OPC_SLTI: /* Set on less than with immediate opcode */
25705 case OPC_SLTIU:
25706 gen_slt_imm(ctx, op, rt, rs, imm);
25707 break;
25708 case OPC_ANDI: /* Arithmetic with immediate opcode */
25709 case OPC_LUI: /* OPC_AUI */
25710 case OPC_ORI:
25711 case OPC_XORI:
25712 gen_logic_imm(ctx, op, rt, rs, imm);
25713 break;
25714 case OPC_J: /* Jump */
25715 case OPC_JAL:
25716 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25717 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25718 break;
25719 /* Branch */
25720 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25721 if (ctx->insn_flags & ISA_MIPS32R6) {
25722 if (rt == 0) {
25723 generate_exception_end(ctx, EXCP_RI);
25724 break;
25726 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25727 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25728 } else {
25729 /* OPC_BLEZL */
25730 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25732 break;
25733 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25734 if (ctx->insn_flags & ISA_MIPS32R6) {
25735 if (rt == 0) {
25736 generate_exception_end(ctx, EXCP_RI);
25737 break;
25739 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25740 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25741 } else {
25742 /* OPC_BGTZL */
25743 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25745 break;
25746 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25747 if (rt == 0) {
25748 /* OPC_BLEZ */
25749 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25750 } else {
25751 check_insn(ctx, ISA_MIPS32R6);
25752 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25753 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25755 break;
25756 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25757 if (rt == 0) {
25758 /* OPC_BGTZ */
25759 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25760 } else {
25761 check_insn(ctx, ISA_MIPS32R6);
25762 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25763 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25765 break;
25766 case OPC_BEQL:
25767 case OPC_BNEL:
25768 check_insn(ctx, ISA_MIPS2);
25769 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25770 /* Fallthrough */
25771 case OPC_BEQ:
25772 case OPC_BNE:
25773 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25774 break;
25775 case OPC_LL: /* Load and stores */
25776 check_insn(ctx, ISA_MIPS2);
25777 /* Fallthrough */
25778 case OPC_LWL:
25779 case OPC_LWR:
25780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25781 /* Fallthrough */
25782 case OPC_LB:
25783 case OPC_LH:
25784 case OPC_LW:
25785 case OPC_LWPC:
25786 case OPC_LBU:
25787 case OPC_LHU:
25788 gen_ld(ctx, op, rt, rs, imm);
25789 break;
25790 case OPC_SWL:
25791 case OPC_SWR:
25792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25793 /* fall through */
25794 case OPC_SB:
25795 case OPC_SH:
25796 case OPC_SW:
25797 gen_st(ctx, op, rt, rs, imm);
25798 break;
25799 case OPC_SC:
25800 check_insn(ctx, ISA_MIPS2);
25801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25802 gen_st_cond(ctx, op, rt, rs, imm);
25803 break;
25804 case OPC_CACHE:
25805 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25806 check_cp0_enabled(ctx);
25807 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
25808 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25809 gen_cache_operation(ctx, rt, rs, imm);
25811 /* Treat as NOP. */
25812 break;
25813 case OPC_PREF:
25814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25815 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
25816 /* Treat as NOP. */
25817 break;
25819 /* Floating point (COP1). */
25820 case OPC_LWC1:
25821 case OPC_LDC1:
25822 case OPC_SWC1:
25823 case OPC_SDC1:
25824 gen_cop1_ldst(ctx, op, rt, rs, imm);
25825 break;
25827 case OPC_CP1:
25828 op1 = MASK_CP1(ctx->opcode);
25830 switch (op1) {
25831 case OPC_MFHC1:
25832 case OPC_MTHC1:
25833 check_cp1_enabled(ctx);
25834 check_insn(ctx, ISA_MIPS32R2);
25835 /* fall through */
25836 case OPC_MFC1:
25837 case OPC_CFC1:
25838 case OPC_MTC1:
25839 case OPC_CTC1:
25840 check_cp1_enabled(ctx);
25841 gen_cp1(ctx, op1, rt, rd);
25842 break;
25843 #if defined(TARGET_MIPS64)
25844 case OPC_DMFC1:
25845 case OPC_DMTC1:
25846 check_cp1_enabled(ctx);
25847 check_insn(ctx, ISA_MIPS3);
25848 check_mips_64(ctx);
25849 gen_cp1(ctx, op1, rt, rd);
25850 break;
25851 #endif
25852 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25853 check_cp1_enabled(ctx);
25854 if (ctx->insn_flags & ISA_MIPS32R6) {
25855 /* OPC_BC1EQZ */
25856 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25857 rt, imm << 2, 4);
25858 } else {
25859 /* OPC_BC1ANY2 */
25860 check_cop1x(ctx);
25861 check_insn(ctx, ASE_MIPS3D);
25862 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25863 (rt >> 2) & 0x7, imm << 2);
25865 break;
25866 case OPC_BC1NEZ:
25867 check_cp1_enabled(ctx);
25868 check_insn(ctx, ISA_MIPS32R6);
25869 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25870 rt, imm << 2, 4);
25871 break;
25872 case OPC_BC1ANY4:
25873 check_cp1_enabled(ctx);
25874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25875 check_cop1x(ctx);
25876 check_insn(ctx, ASE_MIPS3D);
25877 /* fall through */
25878 case OPC_BC1:
25879 check_cp1_enabled(ctx);
25880 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25881 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25882 (rt >> 2) & 0x7, imm << 2);
25883 break;
25884 case OPC_PS_FMT:
25885 check_ps(ctx);
25886 /* fall through */
25887 case OPC_S_FMT:
25888 case OPC_D_FMT:
25889 check_cp1_enabled(ctx);
25890 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25891 (imm >> 8) & 0x7);
25892 break;
25893 case OPC_W_FMT:
25894 case OPC_L_FMT:
25896 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25897 check_cp1_enabled(ctx);
25898 if (ctx->insn_flags & ISA_MIPS32R6) {
25899 switch (r6_op) {
25900 case R6_OPC_CMP_AF_S:
25901 case R6_OPC_CMP_UN_S:
25902 case R6_OPC_CMP_EQ_S:
25903 case R6_OPC_CMP_UEQ_S:
25904 case R6_OPC_CMP_LT_S:
25905 case R6_OPC_CMP_ULT_S:
25906 case R6_OPC_CMP_LE_S:
25907 case R6_OPC_CMP_ULE_S:
25908 case R6_OPC_CMP_SAF_S:
25909 case R6_OPC_CMP_SUN_S:
25910 case R6_OPC_CMP_SEQ_S:
25911 case R6_OPC_CMP_SEUQ_S:
25912 case R6_OPC_CMP_SLT_S:
25913 case R6_OPC_CMP_SULT_S:
25914 case R6_OPC_CMP_SLE_S:
25915 case R6_OPC_CMP_SULE_S:
25916 case R6_OPC_CMP_OR_S:
25917 case R6_OPC_CMP_UNE_S:
25918 case R6_OPC_CMP_NE_S:
25919 case R6_OPC_CMP_SOR_S:
25920 case R6_OPC_CMP_SUNE_S:
25921 case R6_OPC_CMP_SNE_S:
25922 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25923 break;
25924 case R6_OPC_CMP_AF_D:
25925 case R6_OPC_CMP_UN_D:
25926 case R6_OPC_CMP_EQ_D:
25927 case R6_OPC_CMP_UEQ_D:
25928 case R6_OPC_CMP_LT_D:
25929 case R6_OPC_CMP_ULT_D:
25930 case R6_OPC_CMP_LE_D:
25931 case R6_OPC_CMP_ULE_D:
25932 case R6_OPC_CMP_SAF_D:
25933 case R6_OPC_CMP_SUN_D:
25934 case R6_OPC_CMP_SEQ_D:
25935 case R6_OPC_CMP_SEUQ_D:
25936 case R6_OPC_CMP_SLT_D:
25937 case R6_OPC_CMP_SULT_D:
25938 case R6_OPC_CMP_SLE_D:
25939 case R6_OPC_CMP_SULE_D:
25940 case R6_OPC_CMP_OR_D:
25941 case R6_OPC_CMP_UNE_D:
25942 case R6_OPC_CMP_NE_D:
25943 case R6_OPC_CMP_SOR_D:
25944 case R6_OPC_CMP_SUNE_D:
25945 case R6_OPC_CMP_SNE_D:
25946 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25947 break;
25948 default:
25949 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25950 rt, rd, sa, (imm >> 8) & 0x7);
25952 break;
25954 } else {
25955 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25956 (imm >> 8) & 0x7);
25958 break;
25960 case OPC_BZ_V:
25961 case OPC_BNZ_V:
25962 case OPC_BZ_B:
25963 case OPC_BZ_H:
25964 case OPC_BZ_W:
25965 case OPC_BZ_D:
25966 case OPC_BNZ_B:
25967 case OPC_BNZ_H:
25968 case OPC_BNZ_W:
25969 case OPC_BNZ_D:
25970 check_insn(ctx, ASE_MSA);
25971 gen_msa_branch(env, ctx, op1);
25972 break;
25973 default:
25974 MIPS_INVAL("cp1");
25975 generate_exception_end(ctx, EXCP_RI);
25976 break;
25978 break;
25980 /* Compact branches [R6] and COP2 [non-R6] */
25981 case OPC_BC: /* OPC_LWC2 */
25982 case OPC_BALC: /* OPC_SWC2 */
25983 if (ctx->insn_flags & ISA_MIPS32R6) {
25984 /* OPC_BC, OPC_BALC */
25985 gen_compute_compact_branch(ctx, op, 0, 0,
25986 sextract32(ctx->opcode << 2, 0, 28));
25987 } else {
25988 /* OPC_LWC2, OPC_SWC2 */
25989 /* COP2: Not implemented. */
25990 generate_exception_err(ctx, EXCP_CpU, 2);
25992 break;
25993 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25994 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25995 if (ctx->insn_flags & ISA_MIPS32R6) {
25996 if (rs != 0) {
25997 /* OPC_BEQZC, OPC_BNEZC */
25998 gen_compute_compact_branch(ctx, op, rs, 0,
25999 sextract32(ctx->opcode << 2, 0, 23));
26000 } else {
26001 /* OPC_JIC, OPC_JIALC */
26002 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26004 } else {
26005 /* OPC_LWC2, OPC_SWC2 */
26006 /* COP2: Not implemented. */
26007 generate_exception_err(ctx, EXCP_CpU, 2);
26009 break;
26010 case OPC_CP2:
26011 check_insn(ctx, INSN_LOONGSON2F);
26012 /* Note that these instructions use different fields. */
26013 gen_loongson_multimedia(ctx, sa, rd, rt);
26014 break;
26016 case OPC_CP3:
26017 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26018 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26019 check_cp1_enabled(ctx);
26020 op1 = MASK_CP3(ctx->opcode);
26021 switch (op1) {
26022 case OPC_LUXC1:
26023 case OPC_SUXC1:
26024 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26025 /* Fallthrough */
26026 case OPC_LWXC1:
26027 case OPC_LDXC1:
26028 case OPC_SWXC1:
26029 case OPC_SDXC1:
26030 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26031 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
26032 break;
26033 case OPC_PREFX:
26034 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26035 /* Treat as NOP. */
26036 break;
26037 case OPC_ALNV_PS:
26038 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26039 /* Fallthrough */
26040 case OPC_MADD_S:
26041 case OPC_MADD_D:
26042 case OPC_MADD_PS:
26043 case OPC_MSUB_S:
26044 case OPC_MSUB_D:
26045 case OPC_MSUB_PS:
26046 case OPC_NMADD_S:
26047 case OPC_NMADD_D:
26048 case OPC_NMADD_PS:
26049 case OPC_NMSUB_S:
26050 case OPC_NMSUB_D:
26051 case OPC_NMSUB_PS:
26052 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26053 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26054 break;
26055 default:
26056 MIPS_INVAL("cp3");
26057 generate_exception_end(ctx, EXCP_RI);
26058 break;
26060 } else {
26061 generate_exception_err(ctx, EXCP_CpU, 1);
26063 break;
26065 #if defined(TARGET_MIPS64)
26066 /* MIPS64 opcodes */
26067 case OPC_LDL:
26068 case OPC_LDR:
26069 case OPC_LLD:
26070 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26071 /* fall through */
26072 case OPC_LWU:
26073 case OPC_LD:
26074 check_insn(ctx, ISA_MIPS3);
26075 check_mips_64(ctx);
26076 gen_ld(ctx, op, rt, rs, imm);
26077 break;
26078 case OPC_SDL:
26079 case OPC_SDR:
26080 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26081 /* fall through */
26082 case OPC_SD:
26083 check_insn(ctx, ISA_MIPS3);
26084 check_mips_64(ctx);
26085 gen_st(ctx, op, rt, rs, imm);
26086 break;
26087 case OPC_SCD:
26088 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26089 check_insn(ctx, ISA_MIPS3);
26090 check_mips_64(ctx);
26091 gen_st_cond(ctx, op, rt, rs, imm);
26092 break;
26093 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26094 if (ctx->insn_flags & ISA_MIPS32R6) {
26095 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26096 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26097 } else {
26098 /* OPC_DADDI */
26099 check_insn(ctx, ISA_MIPS3);
26100 check_mips_64(ctx);
26101 gen_arith_imm(ctx, op, rt, rs, imm);
26103 break;
26104 case OPC_DADDIU:
26105 check_insn(ctx, ISA_MIPS3);
26106 check_mips_64(ctx);
26107 gen_arith_imm(ctx, op, rt, rs, imm);
26108 break;
26109 #else
26110 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26111 if (ctx->insn_flags & ISA_MIPS32R6) {
26112 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26113 } else {
26114 MIPS_INVAL("major opcode");
26115 generate_exception_end(ctx, EXCP_RI);
26117 break;
26118 #endif
26119 case OPC_DAUI: /* OPC_JALX */
26120 if (ctx->insn_flags & ISA_MIPS32R6) {
26121 #if defined(TARGET_MIPS64)
26122 /* OPC_DAUI */
26123 check_mips_64(ctx);
26124 if (rs == 0) {
26125 generate_exception(ctx, EXCP_RI);
26126 } else if (rt != 0) {
26127 TCGv t0 = tcg_temp_new();
26128 gen_load_gpr(t0, rs);
26129 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26130 tcg_temp_free(t0);
26132 #else
26133 generate_exception_end(ctx, EXCP_RI);
26134 MIPS_INVAL("major opcode");
26135 #endif
26136 } else {
26137 /* OPC_JALX */
26138 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26139 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26140 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26142 break;
26143 case OPC_MSA: /* OPC_MDMX */
26144 /* MDMX: Not implemented. */
26145 gen_msa(env, ctx);
26146 break;
26147 case OPC_PCREL:
26148 check_insn(ctx, ISA_MIPS32R6);
26149 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26150 break;
26151 default: /* Invalid */
26152 MIPS_INVAL("major opcode");
26153 generate_exception_end(ctx, EXCP_RI);
26154 break;
26158 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26160 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26161 CPUMIPSState *env = cs->env_ptr;
26163 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26164 ctx->saved_pc = -1;
26165 ctx->insn_flags = env->insn_flags;
26166 ctx->CP0_Config1 = env->CP0_Config1;
26167 ctx->CP0_Config2 = env->CP0_Config2;
26168 ctx->CP0_Config3 = env->CP0_Config3;
26169 ctx->CP0_Config5 = env->CP0_Config5;
26170 ctx->btarget = 0;
26171 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26172 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26173 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26174 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26175 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26176 ctx->PAMask = env->PAMask;
26177 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26178 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26179 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26180 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26181 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26182 /* Restore delay slot state from the tb context. */
26183 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26184 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26185 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26186 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26187 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26188 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26189 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26190 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26191 restore_cpu_state(env, ctx);
26192 #ifdef CONFIG_USER_ONLY
26193 ctx->mem_idx = MIPS_HFLAG_UM;
26194 #else
26195 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26196 #endif
26197 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26198 MO_UNALN : MO_ALIGN;
26200 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26201 ctx->hflags);
26204 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26208 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26210 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26212 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26213 ctx->btarget);
26216 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26217 const CPUBreakpoint *bp)
26219 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26221 save_cpu_state(ctx, 1);
26222 ctx->base.is_jmp = DISAS_NORETURN;
26223 gen_helper_raise_exception_debug(cpu_env);
26224 /* The address covered by the breakpoint must be included in
26225 [tb->pc, tb->pc + tb->size) in order to for it to be
26226 properly cleared -- thus we increment the PC here so that
26227 the logic setting tb->size below does the right thing. */
26228 ctx->base.pc_next += 4;
26229 return true;
26232 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26234 CPUMIPSState *env = cs->env_ptr;
26235 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26236 int insn_bytes;
26237 int is_slot;
26239 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26240 if (ctx->insn_flags & ISA_NANOMIPS32) {
26241 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26242 insn_bytes = decode_nanomips_opc(env, ctx);
26243 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26244 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26245 insn_bytes = 4;
26246 decode_opc(env, ctx);
26247 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26248 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26249 insn_bytes = decode_micromips_opc(env, ctx);
26250 } else if (ctx->insn_flags & ASE_MIPS16) {
26251 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26252 insn_bytes = decode_mips16_opc(env, ctx);
26253 } else {
26254 generate_exception_end(ctx, EXCP_RI);
26255 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26256 return;
26259 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26260 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26261 MIPS_HFLAG_FBNSLOT))) {
26262 /* force to generate branch as there is neither delay nor
26263 forbidden slot */
26264 is_slot = 1;
26266 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26267 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26268 /* Force to generate branch as microMIPS R6 doesn't restrict
26269 branches in the forbidden slot. */
26270 is_slot = 1;
26273 if (is_slot) {
26274 gen_branch(ctx, insn_bytes);
26276 ctx->base.pc_next += insn_bytes;
26278 if (ctx->base.is_jmp != DISAS_NEXT) {
26279 return;
26281 /* Execute a branch and its delay slot as a single instruction.
26282 This is what GDB expects and is consistent with what the
26283 hardware does (e.g. if a delay slot instruction faults, the
26284 reported PC is the PC of the branch). */
26285 if (ctx->base.singlestep_enabled &&
26286 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26287 ctx->base.is_jmp = DISAS_TOO_MANY;
26289 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26290 ctx->base.is_jmp = DISAS_TOO_MANY;
26294 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26296 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26298 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26299 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26300 gen_helper_raise_exception_debug(cpu_env);
26301 } else {
26302 switch (ctx->base.is_jmp) {
26303 case DISAS_STOP:
26304 gen_save_pc(ctx->base.pc_next);
26305 tcg_gen_lookup_and_goto_ptr();
26306 break;
26307 case DISAS_NEXT:
26308 case DISAS_TOO_MANY:
26309 save_cpu_state(ctx, 0);
26310 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26311 break;
26312 case DISAS_EXIT:
26313 tcg_gen_exit_tb(NULL, 0);
26314 break;
26315 case DISAS_NORETURN:
26316 break;
26317 default:
26318 g_assert_not_reached();
26323 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26325 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26326 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26329 static const TranslatorOps mips_tr_ops = {
26330 .init_disas_context = mips_tr_init_disas_context,
26331 .tb_start = mips_tr_tb_start,
26332 .insn_start = mips_tr_insn_start,
26333 .breakpoint_check = mips_tr_breakpoint_check,
26334 .translate_insn = mips_tr_translate_insn,
26335 .tb_stop = mips_tr_tb_stop,
26336 .disas_log = mips_tr_disas_log,
26339 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26341 DisasContext ctx;
26343 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26346 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26347 int flags)
26349 int i;
26350 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26352 #define printfpr(fp) \
26353 do { \
26354 if (is_fpu64) \
26355 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26356 " fd:%13g fs:%13g psu: %13g\n", \
26357 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26358 (double)(fp)->fd, \
26359 (double)(fp)->fs[FP_ENDIAN_IDX], \
26360 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26361 else { \
26362 fpr_t tmp; \
26363 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26364 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26365 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26366 " fd:%13g fs:%13g psu:%13g\n", \
26367 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26368 (double)tmp.fd, \
26369 (double)tmp.fs[FP_ENDIAN_IDX], \
26370 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26372 } while(0)
26375 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26376 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26377 get_float_exception_flags(&env->active_fpu.fp_status));
26378 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26379 fpu_fprintf(f, "%3s: ", fregnames[i]);
26380 printfpr(&env->active_fpu.fpr[i]);
26383 #undef printfpr
26386 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
26387 int flags)
26389 MIPSCPU *cpu = MIPS_CPU(cs);
26390 CPUMIPSState *env = &cpu->env;
26391 int i;
26393 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26394 " LO=0x" TARGET_FMT_lx " ds %04x "
26395 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26396 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26397 env->hflags, env->btarget, env->bcond);
26398 for (i = 0; i < 32; i++) {
26399 if ((i & 3) == 0)
26400 cpu_fprintf(f, "GPR%02d:", i);
26401 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
26402 if ((i & 3) == 3)
26403 cpu_fprintf(f, "\n");
26406 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
26407 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26408 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26409 PRIx64 "\n",
26410 env->CP0_Config0, env->CP0_Config1, env->lladdr);
26411 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26412 env->CP0_Config2, env->CP0_Config3);
26413 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26414 env->CP0_Config4, env->CP0_Config5);
26415 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26416 fpu_dump_state(env, f, cpu_fprintf, flags);
26420 void mips_tcg_init(void)
26422 int i;
26424 cpu_gpr[0] = NULL;
26425 for (i = 1; i < 32; i++)
26426 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
26427 offsetof(CPUMIPSState, active_tc.gpr[i]),
26428 regnames[i]);
26430 for (i = 0; i < 32; i++) {
26431 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
26432 msa_wr_d[i * 2] =
26433 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
26434 /* The scalar floating-point unit (FPU) registers are mapped on
26435 * the MSA vector registers. */
26436 fpu_f64[i] = msa_wr_d[i * 2];
26437 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
26438 msa_wr_d[i * 2 + 1] =
26439 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
26442 cpu_PC = tcg_global_mem_new(cpu_env,
26443 offsetof(CPUMIPSState, active_tc.PC), "PC");
26444 for (i = 0; i < MIPS_DSP_ACC; i++) {
26445 cpu_HI[i] = tcg_global_mem_new(cpu_env,
26446 offsetof(CPUMIPSState, active_tc.HI[i]),
26447 regnames_HI[i]);
26448 cpu_LO[i] = tcg_global_mem_new(cpu_env,
26449 offsetof(CPUMIPSState, active_tc.LO[i]),
26450 regnames_LO[i]);
26452 cpu_dspctrl = tcg_global_mem_new(cpu_env,
26453 offsetof(CPUMIPSState, active_tc.DSPControl),
26454 "DSPControl");
26455 bcond = tcg_global_mem_new(cpu_env,
26456 offsetof(CPUMIPSState, bcond), "bcond");
26457 btarget = tcg_global_mem_new(cpu_env,
26458 offsetof(CPUMIPSState, btarget), "btarget");
26459 hflags = tcg_global_mem_new_i32(cpu_env,
26460 offsetof(CPUMIPSState, hflags), "hflags");
26462 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
26463 offsetof(CPUMIPSState, active_fpu.fcr0),
26464 "fcr0");
26465 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
26466 offsetof(CPUMIPSState, active_fpu.fcr31),
26467 "fcr31");
26470 #include "translate_init.inc.c"
26472 void cpu_mips_realize_env(CPUMIPSState *env)
26474 env->exception_base = (int32_t)0xBFC00000;
26476 #ifndef CONFIG_USER_ONLY
26477 mmu_init(env, env->cpu_model);
26478 #endif
26479 fpu_init(env, env->cpu_model);
26480 mvp_init(env, env->cpu_model);
26483 bool cpu_supports_cps_smp(const char *cpu_type)
26485 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26486 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
26489 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
26491 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26492 return (mcc->cpu_def->insn_flags & isa) != 0;
26495 void cpu_set_exception_base(int vp_index, target_ulong address)
26497 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
26498 vp->env.exception_base = address;
26501 void cpu_state_reset(CPUMIPSState *env)
26503 MIPSCPU *cpu = mips_env_get_cpu(env);
26504 CPUState *cs = CPU(cpu);
26506 /* Reset registers to their default values */
26507 env->CP0_PRid = env->cpu_model->CP0_PRid;
26508 env->CP0_Config0 = env->cpu_model->CP0_Config0;
26509 #ifdef TARGET_WORDS_BIGENDIAN
26510 env->CP0_Config0 |= (1 << CP0C0_BE);
26511 #endif
26512 env->CP0_Config1 = env->cpu_model->CP0_Config1;
26513 env->CP0_Config2 = env->cpu_model->CP0_Config2;
26514 env->CP0_Config3 = env->cpu_model->CP0_Config3;
26515 env->CP0_Config4 = env->cpu_model->CP0_Config4;
26516 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
26517 env->CP0_Config5 = env->cpu_model->CP0_Config5;
26518 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
26519 env->CP0_Config6 = env->cpu_model->CP0_Config6;
26520 env->CP0_Config7 = env->cpu_model->CP0_Config7;
26521 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
26522 << env->cpu_model->CP0_LLAddr_shift;
26523 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
26524 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
26525 env->CCRes = env->cpu_model->CCRes;
26526 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
26527 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
26528 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
26529 env->current_tc = 0;
26530 env->SEGBITS = env->cpu_model->SEGBITS;
26531 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
26532 #if defined(TARGET_MIPS64)
26533 if (env->cpu_model->insn_flags & ISA_MIPS3) {
26534 env->SEGMask |= 3ULL << 62;
26536 #endif
26537 env->PABITS = env->cpu_model->PABITS;
26538 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
26539 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
26540 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
26541 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
26542 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
26543 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
26544 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
26545 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
26546 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
26547 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
26548 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
26549 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
26550 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
26551 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
26552 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
26553 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
26554 env->msair = env->cpu_model->MSAIR;
26555 env->insn_flags = env->cpu_model->insn_flags;
26557 #if defined(CONFIG_USER_ONLY)
26558 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
26559 # ifdef TARGET_MIPS64
26560 /* Enable 64-bit register mode. */
26561 env->CP0_Status |= (1 << CP0St_PX);
26562 # endif
26563 # ifdef TARGET_ABI_MIPSN64
26564 /* Enable 64-bit address mode. */
26565 env->CP0_Status |= (1 << CP0St_UX);
26566 # endif
26567 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
26568 hardware registers. */
26569 env->CP0_HWREna |= 0x0000000F;
26570 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
26571 env->CP0_Status |= (1 << CP0St_CU1);
26573 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
26574 env->CP0_Status |= (1 << CP0St_MX);
26576 # if defined(TARGET_MIPS64)
26577 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
26578 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
26579 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
26580 env->CP0_Status |= (1 << CP0St_FR);
26582 # endif
26583 #else
26584 if (env->hflags & MIPS_HFLAG_BMASK) {
26585 /* If the exception was raised from a delay slot,
26586 come back to the jump. */
26587 env->CP0_ErrorEPC = (env->active_tc.PC
26588 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
26589 } else {
26590 env->CP0_ErrorEPC = env->active_tc.PC;
26592 env->active_tc.PC = env->exception_base;
26593 env->CP0_Random = env->tlb->nb_tlb - 1;
26594 env->tlb->tlb_in_use = env->tlb->nb_tlb;
26595 env->CP0_Wired = 0;
26596 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
26597 env->CP0_EBase = (cs->cpu_index & 0x3FF);
26598 if (mips_um_ksegs_enabled()) {
26599 env->CP0_EBase |= 0x40000000;
26600 } else {
26601 env->CP0_EBase |= (int32_t)0x80000000;
26603 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
26604 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
26606 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
26607 0x3ff : 0xff;
26608 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
26609 /* vectored interrupts not implemented, timer on int 7,
26610 no performance counters. */
26611 env->CP0_IntCtl = 0xe0000000;
26613 int i;
26615 for (i = 0; i < 7; i++) {
26616 env->CP0_WatchLo[i] = 0;
26617 env->CP0_WatchHi[i] = 0x80000000;
26619 env->CP0_WatchLo[7] = 0;
26620 env->CP0_WatchHi[7] = 0;
26622 /* Count register increments in debug mode, EJTAG version 1 */
26623 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
26625 cpu_mips_store_count(env, 1);
26627 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
26628 int i;
26630 /* Only TC0 on VPE 0 starts as active. */
26631 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
26632 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
26633 env->tcs[i].CP0_TCHalt = 1;
26635 env->active_tc.CP0_TCHalt = 1;
26636 cs->halted = 1;
26638 if (cs->cpu_index == 0) {
26639 /* VPE0 starts up enabled. */
26640 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
26641 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
26643 /* TC0 starts up unhalted. */
26644 cs->halted = 0;
26645 env->active_tc.CP0_TCHalt = 0;
26646 env->tcs[0].CP0_TCHalt = 0;
26647 /* With thread 0 active. */
26648 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
26649 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
26654 * Configure default legacy segmentation control. We use this regardless of
26655 * whether segmentation control is presented to the guest.
26657 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
26658 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
26659 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
26660 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
26661 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
26662 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26663 (2 << CP0SC_C);
26664 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
26665 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26666 (3 << CP0SC_C)) << 16;
26667 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
26668 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26669 (1 << CP0SC_EU) | (2 << CP0SC_C);
26670 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
26671 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26672 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
26673 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
26674 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
26675 #endif
26676 if ((env->insn_flags & ISA_MIPS32R6) &&
26677 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
26678 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
26679 env->CP0_Status |= (1 << CP0St_FR);
26682 if (env->insn_flags & ISA_MIPS32R6) {
26683 /* PTW = 1 */
26684 env->CP0_PWSize = 0x40;
26685 /* GDI = 12 */
26686 /* UDI = 12 */
26687 /* MDI = 12 */
26688 /* PRI = 12 */
26689 /* PTEI = 2 */
26690 env->CP0_PWField = 0x0C30C302;
26691 } else {
26692 /* GDI = 0 */
26693 /* UDI = 0 */
26694 /* MDI = 0 */
26695 /* PRI = 0 */
26696 /* PTEI = 2 */
26697 env->CP0_PWField = 0x02;
26700 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
26701 /* microMIPS on reset when Config3.ISA is 3 */
26702 env->hflags |= MIPS_HFLAG_M16;
26705 /* MSA */
26706 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
26707 msa_reset(env);
26710 compute_hflags(env);
26711 restore_fp_status(env);
26712 restore_pamask(env);
26713 cs->exception_index = EXCP_NONE;
26715 if (semihosting_get_argc()) {
26716 /* UHI interface can be used to obtain argc and argv */
26717 env->active_tc.gpr[4] = -1;
26721 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
26722 target_ulong *data)
26724 env->active_tc.PC = data[0];
26725 env->hflags &= ~MIPS_HFLAG_BMASK;
26726 env->hflags |= data[1];
26727 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
26728 case MIPS_HFLAG_BR:
26729 break;
26730 case MIPS_HFLAG_BC:
26731 case MIPS_HFLAG_BL:
26732 case MIPS_HFLAG_B:
26733 env->btarget = data[2];
26734 break;