target/mips: Introduce MXU registers
[qemu/ar7.git] / target / mips / translate.c
blobd6e733f36c19c709623b702f2d3c93972031ae83
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
467 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
468 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
469 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
470 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
473 /* DBSHFL opcodes */
474 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
476 enum {
477 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
478 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
479 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
480 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
481 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
482 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
483 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
484 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
485 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
486 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
487 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
490 /* MIPS DSP REGIMM opcodes */
491 enum {
492 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
493 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
496 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497 /* MIPS DSP Load */
498 enum {
499 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
500 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
501 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
502 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
505 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
522 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
525 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
526 /* MIPS DSP Multiply Sub-class insns */
527 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
535 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
536 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
537 enum {
538 /* MIPS DSP Arithmetic Sub-class */
539 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
553 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
558 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
559 enum {
560 /* MIPS DSP Arithmetic Sub-class */
561 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
574 /* DSP Bit/Manipulation Sub-class */
575 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
582 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
592 /* DSP Compare-Pick Sub-class */
593 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
610 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
611 enum {
612 /* MIPS DSP GPR-Based Shift Sub-class */
613 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
637 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
638 enum {
639 /* MIPS DSP Multiply Sub-class insns */
640 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
664 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665 enum {
666 /* DSP Bit/Manipulation Sub-class */
667 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
670 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Append Sub-class */
673 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
674 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
675 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
678 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679 enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
693 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
695 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
696 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
697 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
700 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Arithmetic Sub-class */
703 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
720 /* DSP Bit/Manipulation Sub-class */
721 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
729 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* MIPS DSP Multiply Sub-class insns */
732 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
733 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
737 /* MIPS DSP Arithmetic Sub-class */
738 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
761 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
762 enum {
763 /* DSP Compare-Pick Sub-class */
764 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
794 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795 enum {
796 /* DSP Append Sub-class */
797 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
798 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
800 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
803 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
806 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
807 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
829 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* DSP Bit/Manipulation Sub-class */
832 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
835 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP Multiply Sub-class insns */
838 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
866 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
867 enum {
868 /* MIPS DSP GPR-Based Shift Sub-class */
869 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
897 /* Coprocessor 0 (rs field) */
898 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
900 enum {
901 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
902 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
903 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
904 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
905 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
906 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
907 OPC_MFTR = (0x08 << 21) | OPC_CP0,
908 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
909 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
910 OPC_MTTR = (0x0C << 21) | OPC_CP0,
911 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
912 OPC_C0 = (0x10 << 21) | OPC_CP0,
913 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
914 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
915 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
916 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
917 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
918 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
919 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
920 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
921 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
922 OPC_C0_A = (0x1A << 21) | OPC_CP0,
923 OPC_C0_B = (0x1B << 21) | OPC_CP0,
924 OPC_C0_C = (0x1C << 21) | OPC_CP0,
925 OPC_C0_D = (0x1D << 21) | OPC_CP0,
926 OPC_C0_E = (0x1E << 21) | OPC_CP0,
927 OPC_C0_F = (0x1F << 21) | OPC_CP0,
930 /* MFMC0 opcodes */
931 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
933 enum {
934 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
935 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
937 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
938 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
939 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
941 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
944 /* Coprocessor 0 (with rs == C0) */
945 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
947 enum {
948 OPC_TLBR = 0x01 | OPC_C0,
949 OPC_TLBWI = 0x02 | OPC_C0,
950 OPC_TLBINV = 0x03 | OPC_C0,
951 OPC_TLBINVF = 0x04 | OPC_C0,
952 OPC_TLBWR = 0x06 | OPC_C0,
953 OPC_TLBP = 0x08 | OPC_C0,
954 OPC_RFE = 0x10 | OPC_C0,
955 OPC_ERET = 0x18 | OPC_C0,
956 OPC_DERET = 0x1F | OPC_C0,
957 OPC_WAIT = 0x20 | OPC_C0,
960 /* Coprocessor 1 (rs field) */
961 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
963 /* Values for the fmt field in FP instructions */
964 enum {
965 /* 0 - 15 are reserved */
966 FMT_S = 16, /* single fp */
967 FMT_D = 17, /* double fp */
968 FMT_E = 18, /* extended fp */
969 FMT_Q = 19, /* quad fp */
970 FMT_W = 20, /* 32-bit fixed */
971 FMT_L = 21, /* 64-bit fixed */
972 FMT_PS = 22, /* paired single fp */
973 /* 23 - 31 are reserved */
976 enum {
977 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
978 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
979 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
980 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
981 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
982 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
983 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
984 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
985 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
986 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
987 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
988 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
989 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
990 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
991 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
992 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
993 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
994 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
995 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
996 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
997 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
998 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
999 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1000 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1001 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1002 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1003 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1004 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1005 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1006 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1009 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1010 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1012 enum {
1013 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1014 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1015 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1016 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1019 enum {
1020 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1021 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1024 enum {
1025 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1026 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1029 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1031 enum {
1032 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1033 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1034 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1035 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1036 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1037 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1038 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1039 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1040 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1041 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1042 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1045 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1047 enum {
1048 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1049 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1057 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1067 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1070 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1071 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1072 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1073 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1075 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1076 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1079 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1084 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1085 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1086 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1091 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1092 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1098 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1099 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1106 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1112 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1113 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1114 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1115 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1116 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1120 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1121 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1122 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1123 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1127 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1128 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1130 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1134 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1135 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1136 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1137 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1138 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1142 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1144 enum {
1145 OPC_LWXC1 = 0x00 | OPC_CP3,
1146 OPC_LDXC1 = 0x01 | OPC_CP3,
1147 OPC_LUXC1 = 0x05 | OPC_CP3,
1148 OPC_SWXC1 = 0x08 | OPC_CP3,
1149 OPC_SDXC1 = 0x09 | OPC_CP3,
1150 OPC_SUXC1 = 0x0D | OPC_CP3,
1151 OPC_PREFX = 0x0F | OPC_CP3,
1152 OPC_ALNV_PS = 0x1E | OPC_CP3,
1153 OPC_MADD_S = 0x20 | OPC_CP3,
1154 OPC_MADD_D = 0x21 | OPC_CP3,
1155 OPC_MADD_PS = 0x26 | OPC_CP3,
1156 OPC_MSUB_S = 0x28 | OPC_CP3,
1157 OPC_MSUB_D = 0x29 | OPC_CP3,
1158 OPC_MSUB_PS = 0x2E | OPC_CP3,
1159 OPC_NMADD_S = 0x30 | OPC_CP3,
1160 OPC_NMADD_D = 0x31 | OPC_CP3,
1161 OPC_NMADD_PS= 0x36 | OPC_CP3,
1162 OPC_NMSUB_S = 0x38 | OPC_CP3,
1163 OPC_NMSUB_D = 0x39 | OPC_CP3,
1164 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1167 /* MSA Opcodes */
1168 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1169 enum {
1170 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1171 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1172 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1173 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1174 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1175 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1176 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1177 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1178 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1179 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1180 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1181 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1182 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1183 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1184 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1185 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1186 OPC_MSA_ELM = 0x19 | OPC_MSA,
1187 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1188 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1189 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1190 OPC_MSA_VEC = 0x1E | OPC_MSA,
1192 /* MI10 instruction */
1193 OPC_LD_B = (0x20) | OPC_MSA,
1194 OPC_LD_H = (0x21) | OPC_MSA,
1195 OPC_LD_W = (0x22) | OPC_MSA,
1196 OPC_LD_D = (0x23) | OPC_MSA,
1197 OPC_ST_B = (0x24) | OPC_MSA,
1198 OPC_ST_H = (0x25) | OPC_MSA,
1199 OPC_ST_W = (0x26) | OPC_MSA,
1200 OPC_ST_D = (0x27) | OPC_MSA,
1203 enum {
1204 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1205 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1206 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1207 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1208 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1209 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1210 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1211 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1212 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1213 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1214 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1215 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1216 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1218 /* I8 instruction */
1219 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1220 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1221 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1222 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1223 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1225 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1226 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1228 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1230 /* VEC/2R/2RF instruction */
1231 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1232 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1233 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1234 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1235 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1236 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1237 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1239 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1242 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1243 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1244 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1245 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1246 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1248 /* 2RF instruction df(bit 16) = _w, _d */
1249 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1250 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1252 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1253 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1254 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1255 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1256 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1257 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1259 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1260 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1261 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1263 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1266 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1267 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1268 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1269 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1270 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1272 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1274 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1275 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1276 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1277 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1278 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1279 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1280 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1281 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1282 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1283 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1284 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1285 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1286 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1287 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1288 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1289 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1290 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1292 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1293 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1294 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1295 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1296 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1297 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1298 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1299 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1300 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1301 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1302 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1303 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1304 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1305 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1306 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1307 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1308 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1309 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1310 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1311 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1312 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1313 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1314 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1315 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1316 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1317 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1318 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1319 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1320 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1321 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1322 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1323 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1324 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1325 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1326 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1327 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1328 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1329 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1331 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1332 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1334 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1335 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1336 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 /* 3RF instruction _df(bit 21) = _w, _d */
1343 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1346 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1347 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1348 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1356 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1361 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1362 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1363 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1364 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1365 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1366 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1369 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1372 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1373 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1374 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1375 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1378 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1381 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1385 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1386 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1387 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1388 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1389 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1390 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1391 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1392 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1393 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1394 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1395 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1396 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1402 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1403 * ============================================
1405 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1406 * instructions set. It is designed to fit the needs of signal, graphical and
1407 * video processing applications. MXU instruction set is used in Xburst family
1408 * of microprocessors by Ingenic.
1410 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1411 * the control register.
1413 * The notation used in MXU assembler mnemonics:
1415 * XRa, XRb, XRc, XRd - MXU registers
1416 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1417 * s12 - a subfield of an instruction code
1418 * strd2 - a subfield of an instruction code
1419 * eptn2 - a subfield of an instruction code
1420 * eptn3 - a subfield of an instruction code
1421 * optn2 - a subfield of an instruction code
1422 * optn3 - a subfield of an instruction code
1423 * sft4 - a subfield of an instruction code
1425 * Load/Store instructions Multiplication instructions
1426 * ----------------------- ---------------------------
1428 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1429 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1430 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1431 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1432 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1433 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1434 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1435 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1436 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1437 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1438 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1439 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1440 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1441 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1442 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1443 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1444 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1445 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1446 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1447 * S16SDI XRa, Rb, s10, eptn2
1448 * S8LDD XRa, Rb, s8, eptn3
1449 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1450 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1451 * S8SDI XRa, Rb, s8, eptn3
1452 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1453 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1454 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1455 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1456 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1457 * S32CPS XRa, XRb, XRc
1458 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1459 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1460 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1461 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1462 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1463 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1464 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1465 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1466 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1467 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1468 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1469 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1470 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1471 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1472 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1473 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1474 * Q8SLT XRa, XRb, XRc
1475 * Q8SLTU XRa, XRb, XRc
1476 * Q8MOVZ XRa, XRb, XRc Shift instructions
1477 * Q8MOVN XRa, XRb, XRc ------------------
1479 * D32SLL XRa, XRb, XRc, XRd, sft4
1480 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1481 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1482 * D32SARL XRa, XRb, XRc, sft4
1483 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1484 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1485 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1486 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1487 * Q16SLL XRa, XRb, XRc, XRd, sft4
1488 * Q16SLR XRa, XRb, XRc, XRd, sft4
1489 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1490 * ------------------------- Q16SLLV XRa, XRb, Rb
1491 * Q16SLRV XRa, XRb, Rb
1492 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1493 * S32ALN XRa, XRb, XRc, Rb
1494 * S32ALNI XRa, XRb, XRc, s3
1495 * S32LUI XRa, s8, optn3 Move instructions
1496 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1497 * S32EXTRV XRa, XRb, Rs, Rt
1498 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1499 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1502 * bits
1503 * 05..00
1505 * ┌─ 000000 ─ OPC_MXU_S32MADD
1506 * ├─ 000001 ─ OPC_MXU_S32MADDU
1507 * ├─ 000010 ─ <not assigned>
1508 * │ 20..18
1509 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1510 * │ ├─ 001 ─ OPC_MXU_S32MIN
1511 * │ ├─ 010 ─ OPC_MXU_D16MAX
1512 * │ ├─ 011 ─ OPC_MXU_D16MIN
1513 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1514 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1515 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1516 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1517 * ├─ 000100 ─ OPC_MXU_S32MSUB
1518 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1519 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1520 * │ ├─ 001 ─ OPC_MXU_D16SLT
1521 * │ ├─ 010 ─ OPC_MXU_D16AVG
1522 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1523 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1524 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1525 * │ └─ 111 ─ OPC_MXU_Q8ADD
1526 * │
1527 * │ 20..18
1528 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1529 * │ ├─ 010 ─ OPC_MXU_D16CPS
1530 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1531 * │ └─ 110 ─ OPC_MXU_Q16SAT
1532 * ├─ 001000 ─ OPC_MXU_D16MUL
1533 * │ 25..24
1534 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1535 * │ └─ 01 ─ OPC_MXU_D16MULE
1536 * ├─ 001010 ─ OPC_MXU_D16MAC
1537 * ├─ 001011 ─ OPC_MXU_D16MACF
1538 * ├─ 001100 ─ OPC_MXU_D16MADL
1539 * │ 25..24
1540 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1541 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1542 * ├─ 001110 ─ OPC_MXU_Q16ADD
1543 * ├─ 001111 ─ OPC_MXU_D16MACE
1544 * │ 23
1545 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1546 * │ └─ 1 ─ OPC_MXU_S32LDDR
1547 * │
1548 * │ 23
1549 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1550 * │ └─ 1 ─ OPC_MXU_S32STDR
1551 * │
1552 * │ 13..10
1553 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1554 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1555 * │
1556 * │ 13..10
1557 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1558 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1559 * │
1560 * │ 23
1561 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1562 * │ └─ 1 ─ OPC_MXU_S32LDIR
1563 * │
1564 * │ 23
1565 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1566 * │ └─ 1 ─ OPC_MXU_S32SDIR
1567 * │
1568 * │ 13..10
1569 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1570 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1571 * │
1572 * │ 13..10
1573 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1574 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1575 * ├─ 011000 ─ OPC_MXU_D32ADD
1576 * │ 23..22
1577 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1578 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1579 * │ └─ 10 ─ OPC_MXU_D32ASUM
1580 * ├─ 011010 ─ <not assigned>
1581 * │ 23..22
1582 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1583 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1584 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1585 * │
1586 * │ 23..22
1587 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1588 * │ ├─ 01 ─ OPC_MXU_D8SUM
1589 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1590 * ├─ 011110 ─ <not assigned>
1591 * ├─ 011111 ─ <not assigned>
1592 * ├─ 100000 ─ <not assigned>
1593 * ├─ 100001 ─ <not assigned>
1594 * ├─ 100010 ─ OPC_MXU_S8LDD
1595 * ├─ 100011 ─ OPC_MXU_S8STD
1596 * ├─ 100100 ─ OPC_MXU_S8LDI
1597 * ├─ 100101 ─ OPC_MXU_S8SDI
1598 * │ 15..14
1599 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1600 * │ ├─ 00 ─ OPC_MXU_S32MULU
1601 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1602 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1603 * │
1604 * │ 20..18
1605 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1606 * │ ├─ 001 ─ OPC_MXU_S32ALN
1607 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1608 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1609 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1610 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1611 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1612 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1613 * ├─ 101000 ─ <not assigned>
1614 * ├─ 101001 ─ <not assigned>
1615 * ├─ 101010 ─ <not assigned>
1616 * ├─ 101011 ─ <not assigned>
1617 * ├─ 101100 ─ <not assigned>
1618 * ├─ 101101 ─ <not assigned>
1619 * ├─ 101110 ─ OPC_MXU_S32M2I
1620 * ├─ 101111 ─ OPC_MXU_S32I2M
1621 * ├─ 110000 ─ OPC_MXU_D32SLL
1622 * ├─ 110001 ─ OPC_MXU_D32SLR
1623 * ├─ 110010 ─ OPC_MXU_D32SARL
1624 * ├─ 110011 ─ OPC_MXU_D32SAR
1625 * ├─ 110100 ─ OPC_MXU_Q16SLL
1626 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1627 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1628 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1629 * │ ├─ 010 ─ OPC_MXU_D32SARV
1630 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1631 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1632 * │ └─ 101 ─ OPC_MXU_Q16SARV
1633 * ├─ 110111 ─ OPC_MXU_Q16SAR
1634 * │ 23..22
1635 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1636 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1637 * │
1638 * │ 20..18
1639 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1640 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1641 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1642 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1643 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1644 * │ └─ 101 ─ OPC_MXU_S32MOV
1645 * │
1646 * │ 23..22
1647 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1648 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1649 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1650 * ├─ 111100 ─ OPC_MXU_Q8MADL
1651 * ├─ 111101 ─ OPC_MXU_S32SFL
1652 * ├─ 111110 ─ OPC_MXU_Q8SAD
1653 * └─ 111111 ─ <not assigned>
1656 * Compiled after:
1658 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1659 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1662 enum {
1663 OPC_MXU_S32MADD = 0x00,
1664 OPC_MXU_S32MADDU = 0x01,
1665 /* not assigned 0x02 */
1666 OPC_MXU__POOL00 = 0x03,
1667 OPC_MXU_S32MSUB = 0x04,
1668 OPC_MXU_S32MSUBU = 0x05,
1669 OPC_MXU__POOL01 = 0x06,
1670 OPC_MXU__POOL02 = 0x07,
1671 OPC_MXU_D16MUL = 0x08,
1672 OPC_MXU__POOL03 = 0x09,
1673 OPC_MXU_D16MAC = 0x0A,
1674 OPC_MXU_D16MACF = 0x0B,
1675 OPC_MXU_D16MADL = 0x0C,
1676 OPC_MXU__POOL04 = 0x0D,
1677 OPC_MXU_Q16ADD = 0x0E,
1678 OPC_MXU_D16MACE = 0x0F,
1679 OPC_MXU__POOL05 = 0x10,
1680 OPC_MXU__POOL06 = 0x11,
1681 OPC_MXU__POOL07 = 0x12,
1682 OPC_MXU__POOL08 = 0x13,
1683 OPC_MXU__POOL09 = 0x14,
1684 OPC_MXU__POOL10 = 0x15,
1685 OPC_MXU__POOL11 = 0x16,
1686 OPC_MXU__POOL12 = 0x17,
1687 OPC_MXU_D32ADD = 0x18,
1688 OPC_MXU__POOL13 = 0x19,
1689 /* not assigned 0x1A */
1690 OPC_MXU__POOL14 = 0x1B,
1691 OPC_MXU__POOL15 = 0x1C,
1692 OPC_MXU_Q8ACCE = 0x1D,
1693 /* not assigned 0x1E */
1694 /* not assigned 0x1F */
1695 /* not assigned 0x20 */
1696 /* not assigned 0x21 */
1697 OPC_MXU_S8LDD = 0x22,
1698 OPC_MXU_S8STD = 0x23,
1699 OPC_MXU_S8LDI = 0x24,
1700 OPC_MXU_S8SDI = 0x25,
1701 OPC_MXU__POOL16 = 0x26,
1702 OPC_MXU__POOL17 = 0x27,
1703 OPC_MXU_LXB = 0x28,
1704 /* not assigned 0x29 */
1705 OPC_MXU_S16LDD = 0x2A,
1706 OPC_MXU_S16STD = 0x2B,
1707 OPC_MXU_S16LDI = 0x2C,
1708 OPC_MXU_S16SDI = 0x2D,
1709 OPC_MXU_S32M2I = 0x2E,
1710 OPC_MXU_S32I2M = 0x2F,
1711 OPC_MXU_D32SLL = 0x30,
1712 OPC_MXU_D32SLR = 0x31,
1713 OPC_MXU_D32SARL = 0x32,
1714 OPC_MXU_D32SAR = 0x33,
1715 OPC_MXU_Q16SLL = 0x34,
1716 OPC_MXU_Q16SLR = 0x35,
1717 OPC_MXU__POOL18 = 0x36,
1718 OPC_MXU_Q16SAR = 0x37,
1719 OPC_MXU__POOL19 = 0x38,
1720 OPC_MXU__POOL20 = 0x39,
1721 OPC_MXU__POOL21 = 0x3A,
1722 OPC_MXU_Q16SCOP = 0x3B,
1723 OPC_MXU_Q8MADL = 0x3C,
1724 OPC_MXU_S32SFL = 0x3D,
1725 OPC_MXU_Q8SAD = 0x3E,
1726 /* not assigned 0x3F */
1731 * MXU pool 00
1733 enum {
1734 OPC_MXU_S32MAX = 0x00,
1735 OPC_MXU_S32MIN = 0x01,
1736 OPC_MXU_D16MAX = 0x02,
1737 OPC_MXU_D16MIN = 0x03,
1738 OPC_MXU_Q8MAX = 0x04,
1739 OPC_MXU_Q8MIN = 0x05,
1740 OPC_MXU_Q8SLT = 0x06,
1741 OPC_MXU_Q8SLTU = 0x07,
1745 * MXU pool 01
1747 enum {
1748 OPC_MXU_S32SLT = 0x00,
1749 OPC_MXU_D16SLT = 0x01,
1750 OPC_MXU_D16AVG = 0x02,
1751 OPC_MXU_D16AVGR = 0x03,
1752 OPC_MXU_Q8AVG = 0x04,
1753 OPC_MXU_Q8AVGR = 0x05,
1754 OPC_MXU_Q8ADD = 0x07,
1758 * MXU pool 02
1760 enum {
1761 OPC_MXU_S32CPS = 0x00,
1762 OPC_MXU_D16CPS = 0x02,
1763 OPC_MXU_Q8ABD = 0x04,
1764 OPC_MXU_Q16SAT = 0x06,
1768 * MXU pool 03
1770 enum {
1771 OPC_MXU_D16MULF = 0x00,
1772 OPC_MXU_D16MULE = 0x01,
1776 * MXU pool 04
1778 enum {
1779 OPC_MXU_S16MAD = 0x00,
1780 OPC_MXU_S16MAD_1 = 0x01,
1784 * MXU pool 05
1786 enum {
1787 OPC_MXU_S32LDD = 0x00,
1788 OPC_MXU_S32LDDR = 0x01,
1792 * MXU pool 06
1794 enum {
1795 OPC_MXU_S32STD = 0x00,
1796 OPC_MXU_S32STDR = 0x01,
1800 * MXU pool 07
1802 enum {
1803 OPC_MXU_S32LDDV = 0x00,
1804 OPC_MXU_S32LDDVR = 0x01,
1808 * MXU pool 08
1810 enum {
1811 OPC_MXU_S32STDV = 0x00,
1812 OPC_MXU_S32STDVR = 0x01,
1816 * MXU pool 09
1818 enum {
1819 OPC_MXU_S32LDI = 0x00,
1820 OPC_MXU_S32LDIR = 0x01,
1824 * MXU pool 10
1826 enum {
1827 OPC_MXU_S32SDI = 0x00,
1828 OPC_MXU_S32SDIR = 0x01,
1832 * MXU pool 11
1834 enum {
1835 OPC_MXU_S32LDIV = 0x00,
1836 OPC_MXU_S32LDIVR = 0x01,
1840 * MXU pool 12
1842 enum {
1843 OPC_MXU_S32SDIV = 0x00,
1844 OPC_MXU_S32SDIVR = 0x01,
1848 * MXU pool 13
1850 enum {
1851 OPC_MXU_D32ACC = 0x00,
1852 OPC_MXU_D32ACCM = 0x01,
1853 OPC_MXU_D32ASUM = 0x02,
1857 * MXU pool 14
1859 enum {
1860 OPC_MXU_Q16ACC = 0x00,
1861 OPC_MXU_Q16ACCM = 0x01,
1862 OPC_MXU_Q16ASUM = 0x02,
1866 * MXU pool 15
1868 enum {
1869 OPC_MXU_Q8ADDE = 0x00,
1870 OPC_MXU_D8SUM = 0x01,
1871 OPC_MXU_D8SUMC = 0x02,
1875 * MXU pool 16
1877 enum {
1878 OPC_MXU_S32MUL = 0x00,
1879 OPC_MXU_S32MULU = 0x01,
1880 OPC_MXU_S32EXTR = 0x02,
1881 OPC_MXU_S32EXTRV = 0x03,
1885 * MXU pool 17
1887 enum {
1888 OPC_MXU_D32SARW = 0x00,
1889 OPC_MXU_S32ALN = 0x01,
1890 OPC_MXU_S32ALNI = 0x02,
1891 OPC_MXU_S32NOR = 0x03,
1892 OPC_MXU_S32AND = 0x04,
1893 OPC_MXU_S32OR = 0x05,
1894 OPC_MXU_S32XOR = 0x06,
1895 OPC_MXU_S32LUI = 0x07,
1899 * MXU pool 18
1901 enum {
1902 OPC_MXU_D32SLLV = 0x00,
1903 OPC_MXU_D32SLRV = 0x01,
1904 OPC_MXU_D32SARV = 0x03,
1905 OPC_MXU_Q16SLLV = 0x04,
1906 OPC_MXU_Q16SLRV = 0x05,
1907 OPC_MXU_Q16SARV = 0x07,
1911 * MXU pool 19
1913 enum {
1914 OPC_MXU_Q8MUL = 0x00,
1915 OPC_MXU_Q8MULSU = 0x01,
1919 * MXU pool 20
1921 enum {
1922 OPC_MXU_Q8MOVZ = 0x00,
1923 OPC_MXU_Q8MOVN = 0x01,
1924 OPC_MXU_D16MOVZ = 0x02,
1925 OPC_MXU_D16MOVN = 0x03,
1926 OPC_MXU_S32MOVZ = 0x04,
1927 OPC_MXU_S32MOVN = 0x05,
1931 * MXU pool 21
1933 enum {
1934 OPC_MXU_Q8MAC = 0x00,
1935 OPC_MXU_Q8MACSU = 0x01,
1939 * Overview of the TX79-specific instruction set
1940 * =============================================
1942 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1943 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1944 * instructions and certain multimedia instructions (MMIs). These MMIs
1945 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1946 * or sixteen 8-bit paths.
1948 * Reference:
1950 * The Toshiba TX System RISC TX79 Core Architecture manual,
1951 * https://wiki.qemu.org/File:C790.pdf
1953 * Three-Operand Multiply and Multiply-Add (4 instructions)
1954 * --------------------------------------------------------
1955 * MADD [rd,] rs, rt Multiply/Add
1956 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1957 * MULT [rd,] rs, rt Multiply (3-operand)
1958 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1960 * Multiply Instructions for Pipeline 1 (10 instructions)
1961 * ------------------------------------------------------
1962 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1963 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1964 * DIV1 rs, rt Divide Pipeline 1
1965 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1966 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1967 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1968 * MFHI1 rd Move From HI1 Register
1969 * MFLO1 rd Move From LO1 Register
1970 * MTHI1 rs Move To HI1 Register
1971 * MTLO1 rs Move To LO1 Register
1973 * Arithmetic (19 instructions)
1974 * ----------------------------
1975 * PADDB rd, rs, rt Parallel Add Byte
1976 * PSUBB rd, rs, rt Parallel Subtract Byte
1977 * PADDH rd, rs, rt Parallel Add Halfword
1978 * PSUBH rd, rs, rt Parallel Subtract Halfword
1979 * PADDW rd, rs, rt Parallel Add Word
1980 * PSUBW rd, rs, rt Parallel Subtract Word
1981 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1982 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1983 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1984 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1985 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1986 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1987 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1988 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1989 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1990 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1991 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1992 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1993 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1995 * Min/Max (4 instructions)
1996 * ------------------------
1997 * PMAXH rd, rs, rt Parallel Maximum Halfword
1998 * PMINH rd, rs, rt Parallel Minimum Halfword
1999 * PMAXW rd, rs, rt Parallel Maximum Word
2000 * PMINW rd, rs, rt Parallel Minimum Word
2002 * Absolute (2 instructions)
2003 * -------------------------
2004 * PABSH rd, rt Parallel Absolute Halfword
2005 * PABSW rd, rt Parallel Absolute Word
2007 * Logical (4 instructions)
2008 * ------------------------
2009 * PAND rd, rs, rt Parallel AND
2010 * POR rd, rs, rt Parallel OR
2011 * PXOR rd, rs, rt Parallel XOR
2012 * PNOR rd, rs, rt Parallel NOR
2014 * Shift (9 instructions)
2015 * ----------------------
2016 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2017 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2018 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2019 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2020 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2021 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2022 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2023 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2024 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2026 * Compare (6 instructions)
2027 * ------------------------
2028 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2029 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2030 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2031 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2032 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2033 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2035 * LZC (1 instruction)
2036 * -------------------
2037 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2039 * Quadword Load and Store (2 instructions)
2040 * ----------------------------------------
2041 * LQ rt, offset(base) Load Quadword
2042 * SQ rt, offset(base) Store Quadword
2044 * Multiply and Divide (19 instructions)
2045 * -------------------------------------
2046 * PMULTW rd, rs, rt Parallel Multiply Word
2047 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2048 * PDIVW rs, rt Parallel Divide Word
2049 * PDIVUW rs, rt Parallel Divide Unsigned Word
2050 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2051 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2052 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2053 * PMULTH rd, rs, rt Parallel Multiply Halfword
2054 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2055 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2056 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2057 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2058 * PDIVBW rs, rt Parallel Divide Broadcast Word
2059 * PMFHI rd Parallel Move From HI Register
2060 * PMFLO rd Parallel Move From LO Register
2061 * PMTHI rs Parallel Move To HI Register
2062 * PMTLO rs Parallel Move To LO Register
2063 * PMFHL rd Parallel Move From HI/LO Register
2064 * PMTHL rs Parallel Move To HI/LO Register
2066 * Pack/Extend (11 instructions)
2067 * -----------------------------
2068 * PPAC5 rd, rt Parallel Pack to 5 bits
2069 * PPACB rd, rs, rt Parallel Pack to Byte
2070 * PPACH rd, rs, rt Parallel Pack to Halfword
2071 * PPACW rd, rs, rt Parallel Pack to Word
2072 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2073 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2074 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2075 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2076 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2077 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2078 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2080 * Others (16 instructions)
2081 * ------------------------
2082 * PCPYH rd, rt Parallel Copy Halfword
2083 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2084 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2085 * PREVH rd, rt Parallel Reverse Halfword
2086 * PINTH rd, rs, rt Parallel Interleave Halfword
2087 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2088 * PEXEH rd, rt Parallel Exchange Even Halfword
2089 * PEXCH rd, rt Parallel Exchange Center Halfword
2090 * PEXEW rd, rt Parallel Exchange Even Word
2091 * PEXCW rd, rt Parallel Exchange Center Word
2092 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2093 * MFSA rd Move from Shift Amount Register
2094 * MTSA rs Move to Shift Amount Register
2095 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2096 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2097 * PROT3W rd, rt Parallel Rotate 3 Words
2099 * The TX79-specific Multimedia Instruction encodings
2100 * ==================================================
2102 * TX79 Multimedia Instruction encoding table keys:
2104 * * This code is reserved for future use. An attempt to execute it
2105 * causes a Reserved Instruction exception.
2106 * % This code indicates an instruction class. The instruction word
2107 * must be further decoded by examining additional tables that show
2108 * the values for other instruction fields.
2109 * # This code is reserved for the unsupported instructions DMULT,
2110 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2111 * to execute it causes a Reserved Instruction exception.
2113 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2115 * 31 26 0
2116 * +--------+----------------------------------------+
2117 * | opcode | |
2118 * +--------+----------------------------------------+
2120 * opcode bits 28..26
2121 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2122 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2123 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2124 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2125 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2126 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2127 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2128 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2129 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2130 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2131 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2134 enum {
2135 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2136 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2137 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2141 * TX79 Multimedia Instructions with opcode field = MMI:
2143 * 31 26 5 0
2144 * +--------+-------------------------------+--------+
2145 * | MMI | |function|
2146 * +--------+-------------------------------+--------+
2148 * function bits 2..0
2149 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2150 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2151 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2152 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2153 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2154 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2155 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2156 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2157 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2158 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2159 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2162 #define MASK_TX79_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2163 enum {
2164 TX79_MMI_MADD = 0x00 | TX79_CLASS_MMI, /* Same as OPC_MADD */
2165 TX79_MMI_MADDU = 0x01 | TX79_CLASS_MMI, /* Same as OPC_MADDU */
2166 TX79_MMI_PLZCW = 0x04 | TX79_CLASS_MMI,
2167 TX79_MMI_CLASS_MMI0 = 0x08 | TX79_CLASS_MMI,
2168 TX79_MMI_CLASS_MMI2 = 0x09 | TX79_CLASS_MMI,
2169 TX79_MMI_MFHI1 = 0x10 | TX79_CLASS_MMI, /* Same minor as OPC_MFHI */
2170 TX79_MMI_MTHI1 = 0x11 | TX79_CLASS_MMI, /* Same minor as OPC_MTHI */
2171 TX79_MMI_MFLO1 = 0x12 | TX79_CLASS_MMI, /* Same minor as OPC_MFLO */
2172 TX79_MMI_MTLO1 = 0x13 | TX79_CLASS_MMI, /* Same minor as OPC_MTLO */
2173 TX79_MMI_MULT1 = 0x18 | TX79_CLASS_MMI, /* Same minor as OPC_MULT */
2174 TX79_MMI_MULTU1 = 0x19 | TX79_CLASS_MMI, /* Same minor as OPC_MULTU */
2175 TX79_MMI_DIV1 = 0x1A | TX79_CLASS_MMI, /* Same minor as OPC_DIV */
2176 TX79_MMI_DIVU1 = 0x1B | TX79_CLASS_MMI, /* Same minor as OPC_DIVU */
2177 TX79_MMI_MADD1 = 0x20 | TX79_CLASS_MMI,
2178 TX79_MMI_MADDU1 = 0x21 | TX79_CLASS_MMI,
2179 TX79_MMI_CLASS_MMI1 = 0x28 | TX79_CLASS_MMI,
2180 TX79_MMI_CLASS_MMI3 = 0x29 | TX79_CLASS_MMI,
2181 TX79_MMI_PMFHL = 0x30 | TX79_CLASS_MMI,
2182 TX79_MMI_PMTHL = 0x31 | TX79_CLASS_MMI,
2183 TX79_MMI_PSLLH = 0x34 | TX79_CLASS_MMI,
2184 TX79_MMI_PSRLH = 0x36 | TX79_CLASS_MMI,
2185 TX79_MMI_PSRAH = 0x37 | TX79_CLASS_MMI,
2186 TX79_MMI_PSLLW = 0x3C | TX79_CLASS_MMI,
2187 TX79_MMI_PSRLW = 0x3E | TX79_CLASS_MMI,
2188 TX79_MMI_PSRAW = 0x3F | TX79_CLASS_MMI,
2192 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI0:
2194 * 31 26 10 6 5 0
2195 * +--------+----------------------+--------+--------+
2196 * | MMI | |function| MMI0 |
2197 * +--------+----------------------+--------+--------+
2199 * function bits 7..6
2200 * bits | 0 | 1 | 2 | 3
2201 * 10..8 | 00 | 01 | 10 | 11
2202 * -------+-------+-------+-------+-------
2203 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2204 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2205 * 2 010 | PADDB | PSUBB | PCGTB | *
2206 * 3 011 | * | * | * | *
2207 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2208 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2209 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2210 * 7 111 | * | * | PEXT5 | PPAC5
2213 #define MASK_TX79_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2214 enum {
2215 TX79_MMI0_PADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI0,
2216 TX79_MMI0_PSUBW = (0x01 << 6) | TX79_MMI_CLASS_MMI0,
2217 TX79_MMI0_PCGTW = (0x02 << 6) | TX79_MMI_CLASS_MMI0,
2218 TX79_MMI0_PMAXW = (0x03 << 6) | TX79_MMI_CLASS_MMI0,
2219 TX79_MMI0_PADDH = (0x04 << 6) | TX79_MMI_CLASS_MMI0,
2220 TX79_MMI0_PSUBH = (0x05 << 6) | TX79_MMI_CLASS_MMI0,
2221 TX79_MMI0_PCGTH = (0x06 << 6) | TX79_MMI_CLASS_MMI0,
2222 TX79_MMI0_PMAXH = (0x07 << 6) | TX79_MMI_CLASS_MMI0,
2223 TX79_MMI0_PADDB = (0x08 << 6) | TX79_MMI_CLASS_MMI0,
2224 TX79_MMI0_PSUBB = (0x09 << 6) | TX79_MMI_CLASS_MMI0,
2225 TX79_MMI0_PCGTB = (0x0A << 6) | TX79_MMI_CLASS_MMI0,
2226 TX79_MMI0_PADDSW = (0x10 << 6) | TX79_MMI_CLASS_MMI0,
2227 TX79_MMI0_PSUBSW = (0x11 << 6) | TX79_MMI_CLASS_MMI0,
2228 TX79_MMI0_PEXTLW = (0x12 << 6) | TX79_MMI_CLASS_MMI0,
2229 TX79_MMI0_PPACW = (0x13 << 6) | TX79_MMI_CLASS_MMI0,
2230 TX79_MMI0_PADDSH = (0x14 << 6) | TX79_MMI_CLASS_MMI0,
2231 TX79_MMI0_PSUBSH = (0x15 << 6) | TX79_MMI_CLASS_MMI0,
2232 TX79_MMI0_PEXTLH = (0x16 << 6) | TX79_MMI_CLASS_MMI0,
2233 TX79_MMI0_PPACH = (0x17 << 6) | TX79_MMI_CLASS_MMI0,
2234 TX79_MMI0_PADDSB = (0x18 << 6) | TX79_MMI_CLASS_MMI0,
2235 TX79_MMI0_PSUBSB = (0x19 << 6) | TX79_MMI_CLASS_MMI0,
2236 TX79_MMI0_PEXTLB = (0x1A << 6) | TX79_MMI_CLASS_MMI0,
2237 TX79_MMI0_PPACB = (0x1B << 6) | TX79_MMI_CLASS_MMI0,
2238 TX79_MMI0_PEXT5 = (0x1E << 6) | TX79_MMI_CLASS_MMI0,
2239 TX79_MMI0_PPAC5 = (0x1F << 6) | TX79_MMI_CLASS_MMI0,
2243 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI1:
2245 * 31 26 10 6 5 0
2246 * +--------+----------------------+--------+--------+
2247 * | MMI | |function| MMI1 |
2248 * +--------+----------------------+--------+--------+
2250 * function bits 7..6
2251 * bits | 0 | 1 | 2 | 3
2252 * 10..8 | 00 | 01 | 10 | 11
2253 * -------+-------+-------+-------+-------
2254 * 0 000 | * | PABSW | PCEQW | PMINW
2255 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2256 * 2 010 | * | * | PCEQB | *
2257 * 3 011 | * | * | * | *
2258 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2259 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2260 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2261 * 7 111 | * | * | * | *
2264 #define MASK_TX79_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2265 enum {
2266 TX79_MMI1_PABSW = (0x01 << 6) | TX79_MMI_CLASS_MMI1,
2267 TX79_MMI1_PCEQW = (0x02 << 6) | TX79_MMI_CLASS_MMI1,
2268 TX79_MMI1_PMINW = (0x03 << 6) | TX79_MMI_CLASS_MMI1,
2269 TX79_MMI1_PADSBH = (0x04 << 6) | TX79_MMI_CLASS_MMI1,
2270 TX79_MMI1_PABSH = (0x05 << 6) | TX79_MMI_CLASS_MMI1,
2271 TX79_MMI1_PCEQH = (0x06 << 6) | TX79_MMI_CLASS_MMI1,
2272 TX79_MMI1_PMINH = (0x07 << 6) | TX79_MMI_CLASS_MMI1,
2273 TX79_MMI1_PCEQB = (0x0A << 6) | TX79_MMI_CLASS_MMI1,
2274 TX79_MMI1_PADDUW = (0x10 << 6) | TX79_MMI_CLASS_MMI1,
2275 TX79_MMI1_PSUBUW = (0x11 << 6) | TX79_MMI_CLASS_MMI1,
2276 TX79_MMI1_PEXTUW = (0x12 << 6) | TX79_MMI_CLASS_MMI1,
2277 TX79_MMI1_PADDUH = (0x14 << 6) | TX79_MMI_CLASS_MMI1,
2278 TX79_MMI1_PSUBUH = (0x15 << 6) | TX79_MMI_CLASS_MMI1,
2279 TX79_MMI1_PEXTUH = (0x16 << 6) | TX79_MMI_CLASS_MMI1,
2280 TX79_MMI1_PADDUB = (0x18 << 6) | TX79_MMI_CLASS_MMI1,
2281 TX79_MMI1_PSUBUB = (0x19 << 6) | TX79_MMI_CLASS_MMI1,
2282 TX79_MMI1_PEXTUB = (0x1A << 6) | TX79_MMI_CLASS_MMI1,
2283 TX79_MMI1_QFSRV = (0x1B << 6) | TX79_MMI_CLASS_MMI1,
2287 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI2:
2289 * 31 26 10 6 5 0
2290 * +--------+----------------------+--------+--------+
2291 * | MMI | |function| MMI2 |
2292 * +--------+----------------------+--------+--------+
2294 * function bits 7..6
2295 * bits | 0 | 1 | 2 | 3
2296 * 10..8 | 00 | 01 | 10 | 11
2297 * -------+-------+-------+-------+-------
2298 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2299 * 1 001 | PMSUBW| * | * | *
2300 * 2 010 | PMFHI | PMFLO | PINTH | *
2301 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2302 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2303 * 5 101 | PMSUBH| PHMSBH| * | *
2304 * 6 110 | * | * | PEXEH | PREVH
2305 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2308 #define MASK_TX79_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2309 enum {
2310 TX79_MMI2_PMADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI2,
2311 TX79_MMI2_PSLLVW = (0x02 << 6) | TX79_MMI_CLASS_MMI2,
2312 TX79_MMI2_PSRLVW = (0x03 << 6) | TX79_MMI_CLASS_MMI2,
2313 TX79_MMI2_PMSUBW = (0x04 << 6) | TX79_MMI_CLASS_MMI2,
2314 TX79_MMI2_PMFHI = (0x08 << 6) | TX79_MMI_CLASS_MMI2,
2315 TX79_MMI2_PMFLO = (0x09 << 6) | TX79_MMI_CLASS_MMI2,
2316 TX79_MMI2_PINTH = (0x0A << 6) | TX79_MMI_CLASS_MMI2,
2317 TX79_MMI2_PMULTW = (0x0C << 6) | TX79_MMI_CLASS_MMI2,
2318 TX79_MMI2_PDIVW = (0x0D << 6) | TX79_MMI_CLASS_MMI2,
2319 TX79_MMI2_PCPYLD = (0x0E << 6) | TX79_MMI_CLASS_MMI2,
2320 TX79_MMI2_PMADDH = (0x10 << 6) | TX79_MMI_CLASS_MMI2,
2321 TX79_MMI2_PHMADH = (0x11 << 6) | TX79_MMI_CLASS_MMI2,
2322 TX79_MMI2_PAND = (0x12 << 6) | TX79_MMI_CLASS_MMI2,
2323 TX79_MMI2_PXOR = (0x13 << 6) | TX79_MMI_CLASS_MMI2,
2324 TX79_MMI2_PMSUBH = (0x14 << 6) | TX79_MMI_CLASS_MMI2,
2325 TX79_MMI2_PHMSBH = (0x15 << 6) | TX79_MMI_CLASS_MMI2,
2326 TX79_MMI2_PEXEH = (0x1A << 6) | TX79_MMI_CLASS_MMI2,
2327 TX79_MMI2_PREVH = (0x1B << 6) | TX79_MMI_CLASS_MMI2,
2328 TX79_MMI2_PMULTH = (0x1C << 6) | TX79_MMI_CLASS_MMI2,
2329 TX79_MMI2_PDIVBW = (0x1D << 6) | TX79_MMI_CLASS_MMI2,
2330 TX79_MMI2_PEXEW = (0x1E << 6) | TX79_MMI_CLASS_MMI2,
2331 TX79_MMI2_PROT3W = (0x1F << 6) | TX79_MMI_CLASS_MMI2,
2335 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI3:
2337 * 31 26 10 6 5 0
2338 * +--------+----------------------+--------+--------+
2339 * | MMI | |function| MMI3 |
2340 * +--------+----------------------+--------+--------+
2342 * function bits 7..6
2343 * bits | 0 | 1 | 2 | 3
2344 * 10..8 | 00 | 01 | 10 | 11
2345 * -------+-------+-------+-------+-------
2346 * 0 000 |PMADDUW| * | * | PSRAVW
2347 * 1 001 | * | * | * | *
2348 * 2 010 | PMTHI | PMTLO | PINTEH| *
2349 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2350 * 4 100 | * | * | POR | PNOR
2351 * 5 101 | * | * | * | *
2352 * 6 110 | * | * | PEXCH | PCPYH
2353 * 7 111 | * | * | PEXCW | *
2356 #define MASK_TX79_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2357 enum {
2358 TX79_MMI3_PMADDUW = (0x00 << 6) | TX79_MMI_CLASS_MMI3,
2359 TX79_MMI3_PSRAVW = (0x03 << 6) | TX79_MMI_CLASS_MMI3,
2360 TX79_MMI3_PMTHI = (0x08 << 6) | TX79_MMI_CLASS_MMI3,
2361 TX79_MMI3_PMTLO = (0x09 << 6) | TX79_MMI_CLASS_MMI3,
2362 TX79_MMI3_PINTEH = (0x0A << 6) | TX79_MMI_CLASS_MMI3,
2363 TX79_MMI3_PMULTUW = (0x0C << 6) | TX79_MMI_CLASS_MMI3,
2364 TX79_MMI3_PDIVUW = (0x0D << 6) | TX79_MMI_CLASS_MMI3,
2365 TX79_MMI3_PCPYUD = (0x0E << 6) | TX79_MMI_CLASS_MMI3,
2366 TX79_MMI3_POR = (0x12 << 6) | TX79_MMI_CLASS_MMI3,
2367 TX79_MMI3_PNOR = (0x13 << 6) | TX79_MMI_CLASS_MMI3,
2368 TX79_MMI3_PEXCH = (0x1A << 6) | TX79_MMI_CLASS_MMI3,
2369 TX79_MMI3_PCPYH = (0x1B << 6) | TX79_MMI_CLASS_MMI3,
2370 TX79_MMI3_PEXCW = (0x1E << 6) | TX79_MMI_CLASS_MMI3,
2373 /* global register indices */
2374 static TCGv cpu_gpr[32], cpu_PC;
2375 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2376 static TCGv cpu_dspctrl, btarget, bcond;
2377 static TCGv_i32 hflags;
2378 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2379 static TCGv_i64 fpu_f64[32];
2380 static TCGv_i64 msa_wr_d[64];
2382 /* MXU registers */
2383 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2384 static TCGv mxu_CR;
2386 #include "exec/gen-icount.h"
2388 #define gen_helper_0e0i(name, arg) do { \
2389 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2390 gen_helper_##name(cpu_env, helper_tmp); \
2391 tcg_temp_free_i32(helper_tmp); \
2392 } while(0)
2394 #define gen_helper_0e1i(name, arg1, arg2) do { \
2395 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2396 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2397 tcg_temp_free_i32(helper_tmp); \
2398 } while(0)
2400 #define gen_helper_1e0i(name, ret, arg1) do { \
2401 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2402 gen_helper_##name(ret, cpu_env, helper_tmp); \
2403 tcg_temp_free_i32(helper_tmp); \
2404 } while(0)
2406 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2407 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2408 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2409 tcg_temp_free_i32(helper_tmp); \
2410 } while(0)
2412 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2413 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2414 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2415 tcg_temp_free_i32(helper_tmp); \
2416 } while(0)
2418 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2419 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2420 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2421 tcg_temp_free_i32(helper_tmp); \
2422 } while(0)
2424 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2425 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2426 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2427 tcg_temp_free_i32(helper_tmp); \
2428 } while(0)
2430 typedef struct DisasContext {
2431 DisasContextBase base;
2432 target_ulong saved_pc;
2433 target_ulong page_start;
2434 uint32_t opcode;
2435 uint64_t insn_flags;
2436 int32_t CP0_Config1;
2437 int32_t CP0_Config2;
2438 int32_t CP0_Config3;
2439 int32_t CP0_Config5;
2440 /* Routine used to access memory */
2441 int mem_idx;
2442 TCGMemOp default_tcg_memop_mask;
2443 uint32_t hflags, saved_hflags;
2444 target_ulong btarget;
2445 bool ulri;
2446 int kscrexist;
2447 bool rxi;
2448 int ie;
2449 bool bi;
2450 bool bp;
2451 uint64_t PAMask;
2452 bool mvh;
2453 bool eva;
2454 bool sc;
2455 int CP0_LLAddr_shift;
2456 bool ps;
2457 bool vp;
2458 bool cmgcr;
2459 bool mrp;
2460 bool nan2008;
2461 bool abs2008;
2462 } DisasContext;
2464 #define DISAS_STOP DISAS_TARGET_0
2465 #define DISAS_EXIT DISAS_TARGET_1
2467 static const char * const regnames[] = {
2468 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2469 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2470 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2471 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2474 static const char * const regnames_HI[] = {
2475 "HI0", "HI1", "HI2", "HI3",
2478 static const char * const regnames_LO[] = {
2479 "LO0", "LO1", "LO2", "LO3",
2482 static const char * const fregnames[] = {
2483 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2484 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2485 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2486 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2489 static const char * const msaregnames[] = {
2490 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2491 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2492 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2493 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2494 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2495 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2496 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2497 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2498 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2499 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2500 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2501 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2502 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2503 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2504 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2505 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2508 static const char * const mxuregnames[] = {
2509 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2510 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2513 #define LOG_DISAS(...) \
2514 do { \
2515 if (MIPS_DEBUG_DISAS) { \
2516 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2518 } while (0)
2520 #define MIPS_INVAL(op) \
2521 do { \
2522 if (MIPS_DEBUG_DISAS) { \
2523 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2524 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2525 ctx->base.pc_next, ctx->opcode, op, \
2526 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2527 ((ctx->opcode >> 16) & 0x1F)); \
2529 } while (0)
2531 /* General purpose registers moves. */
2532 static inline void gen_load_gpr (TCGv t, int reg)
2534 if (reg == 0)
2535 tcg_gen_movi_tl(t, 0);
2536 else
2537 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2540 static inline void gen_store_gpr (TCGv t, int reg)
2542 if (reg != 0)
2543 tcg_gen_mov_tl(cpu_gpr[reg], t);
2546 /* Moves to/from shadow registers. */
2547 static inline void gen_load_srsgpr (int from, int to)
2549 TCGv t0 = tcg_temp_new();
2551 if (from == 0)
2552 tcg_gen_movi_tl(t0, 0);
2553 else {
2554 TCGv_i32 t2 = tcg_temp_new_i32();
2555 TCGv_ptr addr = tcg_temp_new_ptr();
2557 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2558 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2559 tcg_gen_andi_i32(t2, t2, 0xf);
2560 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2561 tcg_gen_ext_i32_ptr(addr, t2);
2562 tcg_gen_add_ptr(addr, cpu_env, addr);
2564 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2565 tcg_temp_free_ptr(addr);
2566 tcg_temp_free_i32(t2);
2568 gen_store_gpr(t0, to);
2569 tcg_temp_free(t0);
2572 static inline void gen_store_srsgpr (int from, int to)
2574 if (to != 0) {
2575 TCGv t0 = tcg_temp_new();
2576 TCGv_i32 t2 = tcg_temp_new_i32();
2577 TCGv_ptr addr = tcg_temp_new_ptr();
2579 gen_load_gpr(t0, from);
2580 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2581 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2582 tcg_gen_andi_i32(t2, t2, 0xf);
2583 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2584 tcg_gen_ext_i32_ptr(addr, t2);
2585 tcg_gen_add_ptr(addr, cpu_env, addr);
2587 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2588 tcg_temp_free_ptr(addr);
2589 tcg_temp_free_i32(t2);
2590 tcg_temp_free(t0);
2594 /* Tests */
2595 static inline void gen_save_pc(target_ulong pc)
2597 tcg_gen_movi_tl(cpu_PC, pc);
2600 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2602 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2603 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2604 gen_save_pc(ctx->base.pc_next);
2605 ctx->saved_pc = ctx->base.pc_next;
2607 if (ctx->hflags != ctx->saved_hflags) {
2608 tcg_gen_movi_i32(hflags, ctx->hflags);
2609 ctx->saved_hflags = ctx->hflags;
2610 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2611 case MIPS_HFLAG_BR:
2612 break;
2613 case MIPS_HFLAG_BC:
2614 case MIPS_HFLAG_BL:
2615 case MIPS_HFLAG_B:
2616 tcg_gen_movi_tl(btarget, ctx->btarget);
2617 break;
2622 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2624 ctx->saved_hflags = ctx->hflags;
2625 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2626 case MIPS_HFLAG_BR:
2627 break;
2628 case MIPS_HFLAG_BC:
2629 case MIPS_HFLAG_BL:
2630 case MIPS_HFLAG_B:
2631 ctx->btarget = env->btarget;
2632 break;
2636 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2638 TCGv_i32 texcp = tcg_const_i32(excp);
2639 TCGv_i32 terr = tcg_const_i32(err);
2640 save_cpu_state(ctx, 1);
2641 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2642 tcg_temp_free_i32(terr);
2643 tcg_temp_free_i32(texcp);
2644 ctx->base.is_jmp = DISAS_NORETURN;
2647 static inline void generate_exception(DisasContext *ctx, int excp)
2649 gen_helper_0e0i(raise_exception, excp);
2652 static inline void generate_exception_end(DisasContext *ctx, int excp)
2654 generate_exception_err(ctx, excp, 0);
2657 /* Floating point register moves. */
2658 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2660 if (ctx->hflags & MIPS_HFLAG_FRE) {
2661 generate_exception(ctx, EXCP_RI);
2663 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2666 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2668 TCGv_i64 t64;
2669 if (ctx->hflags & MIPS_HFLAG_FRE) {
2670 generate_exception(ctx, EXCP_RI);
2672 t64 = tcg_temp_new_i64();
2673 tcg_gen_extu_i32_i64(t64, t);
2674 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2675 tcg_temp_free_i64(t64);
2678 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2680 if (ctx->hflags & MIPS_HFLAG_F64) {
2681 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2682 } else {
2683 gen_load_fpr32(ctx, t, reg | 1);
2687 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2689 if (ctx->hflags & MIPS_HFLAG_F64) {
2690 TCGv_i64 t64 = tcg_temp_new_i64();
2691 tcg_gen_extu_i32_i64(t64, t);
2692 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2693 tcg_temp_free_i64(t64);
2694 } else {
2695 gen_store_fpr32(ctx, t, reg | 1);
2699 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2701 if (ctx->hflags & MIPS_HFLAG_F64) {
2702 tcg_gen_mov_i64(t, fpu_f64[reg]);
2703 } else {
2704 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2708 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2710 if (ctx->hflags & MIPS_HFLAG_F64) {
2711 tcg_gen_mov_i64(fpu_f64[reg], t);
2712 } else {
2713 TCGv_i64 t0;
2714 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2715 t0 = tcg_temp_new_i64();
2716 tcg_gen_shri_i64(t0, t, 32);
2717 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2718 tcg_temp_free_i64(t0);
2722 static inline int get_fp_bit (int cc)
2724 if (cc)
2725 return 24 + cc;
2726 else
2727 return 23;
2730 /* Addresses computation */
2731 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2733 tcg_gen_add_tl(ret, arg0, arg1);
2735 #if defined(TARGET_MIPS64)
2736 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2737 tcg_gen_ext32s_i64(ret, ret);
2739 #endif
2742 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2743 target_long ofs)
2745 tcg_gen_addi_tl(ret, base, ofs);
2747 #if defined(TARGET_MIPS64)
2748 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2749 tcg_gen_ext32s_i64(ret, ret);
2751 #endif
2754 /* Addresses computation (translation time) */
2755 static target_long addr_add(DisasContext *ctx, target_long base,
2756 target_long offset)
2758 target_long sum = base + offset;
2760 #if defined(TARGET_MIPS64)
2761 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2762 sum = (int32_t)sum;
2764 #endif
2765 return sum;
2768 /* Sign-extract the low 32-bits to a target_long. */
2769 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2771 #if defined(TARGET_MIPS64)
2772 tcg_gen_ext32s_i64(ret, arg);
2773 #else
2774 tcg_gen_extrl_i64_i32(ret, arg);
2775 #endif
2778 /* Sign-extract the high 32-bits to a target_long. */
2779 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2781 #if defined(TARGET_MIPS64)
2782 tcg_gen_sari_i64(ret, arg, 32);
2783 #else
2784 tcg_gen_extrh_i64_i32(ret, arg);
2785 #endif
2788 static inline void check_cp0_enabled(DisasContext *ctx)
2790 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2791 generate_exception_err(ctx, EXCP_CpU, 0);
2794 static inline void check_cp1_enabled(DisasContext *ctx)
2796 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2797 generate_exception_err(ctx, EXCP_CpU, 1);
2800 /* Verify that the processor is running with COP1X instructions enabled.
2801 This is associated with the nabla symbol in the MIPS32 and MIPS64
2802 opcode tables. */
2804 static inline void check_cop1x(DisasContext *ctx)
2806 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2807 generate_exception_end(ctx, EXCP_RI);
2810 /* Verify that the processor is running with 64-bit floating-point
2811 operations enabled. */
2813 static inline void check_cp1_64bitmode(DisasContext *ctx)
2815 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2816 generate_exception_end(ctx, EXCP_RI);
2820 * Verify if floating point register is valid; an operation is not defined
2821 * if bit 0 of any register specification is set and the FR bit in the
2822 * Status register equals zero, since the register numbers specify an
2823 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2824 * in the Status register equals one, both even and odd register numbers
2825 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2827 * Multiple 64 bit wide registers can be checked by calling
2828 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2830 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2832 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2833 generate_exception_end(ctx, EXCP_RI);
2836 /* Verify that the processor is running with DSP instructions enabled.
2837 This is enabled by CP0 Status register MX(24) bit.
2840 static inline void check_dsp(DisasContext *ctx)
2842 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2843 if (ctx->insn_flags & ASE_DSP) {
2844 generate_exception_end(ctx, EXCP_DSPDIS);
2845 } else {
2846 generate_exception_end(ctx, EXCP_RI);
2851 static inline void check_dsp_r2(DisasContext *ctx)
2853 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2854 if (ctx->insn_flags & ASE_DSP) {
2855 generate_exception_end(ctx, EXCP_DSPDIS);
2856 } else {
2857 generate_exception_end(ctx, EXCP_RI);
2862 static inline void check_dsp_r3(DisasContext *ctx)
2864 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2865 if (ctx->insn_flags & ASE_DSP) {
2866 generate_exception_end(ctx, EXCP_DSPDIS);
2867 } else {
2868 generate_exception_end(ctx, EXCP_RI);
2873 /* This code generates a "reserved instruction" exception if the
2874 CPU does not support the instruction set corresponding to flags. */
2875 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2877 if (unlikely(!(ctx->insn_flags & flags))) {
2878 generate_exception_end(ctx, EXCP_RI);
2882 /* This code generates a "reserved instruction" exception if the
2883 CPU has corresponding flag set which indicates that the instruction
2884 has been removed. */
2885 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2887 if (unlikely(ctx->insn_flags & flags)) {
2888 generate_exception_end(ctx, EXCP_RI);
2893 * The Linux kernel traps certain reserved instruction exceptions to
2894 * emulate the corresponding instructions. QEMU is the kernel in user
2895 * mode, so those traps are emulated by accepting the instructions.
2897 * A reserved instruction exception is generated for flagged CPUs if
2898 * QEMU runs in system mode.
2900 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2902 #ifndef CONFIG_USER_ONLY
2903 check_insn_opc_removed(ctx, flags);
2904 #endif
2907 /* This code generates a "reserved instruction" exception if the
2908 CPU does not support 64-bit paired-single (PS) floating point data type */
2909 static inline void check_ps(DisasContext *ctx)
2911 if (unlikely(!ctx->ps)) {
2912 generate_exception(ctx, EXCP_RI);
2914 check_cp1_64bitmode(ctx);
2917 #ifdef TARGET_MIPS64
2918 /* This code generates a "reserved instruction" exception if 64-bit
2919 instructions are not enabled. */
2920 static inline void check_mips_64(DisasContext *ctx)
2922 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2923 generate_exception_end(ctx, EXCP_RI);
2925 #endif
2927 #ifndef CONFIG_USER_ONLY
2928 static inline void check_mvh(DisasContext *ctx)
2930 if (unlikely(!ctx->mvh)) {
2931 generate_exception(ctx, EXCP_RI);
2934 #endif
2937 * This code generates a "reserved instruction" exception if the
2938 * Config5 XNP bit is set.
2940 static inline void check_xnp(DisasContext *ctx)
2942 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2943 generate_exception_end(ctx, EXCP_RI);
2947 #ifndef CONFIG_USER_ONLY
2949 * This code generates a "reserved instruction" exception if the
2950 * Config3 PW bit is NOT set.
2952 static inline void check_pw(DisasContext *ctx)
2954 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2955 generate_exception_end(ctx, EXCP_RI);
2958 #endif
2961 * This code generates a "reserved instruction" exception if the
2962 * Config3 MT bit is NOT set.
2964 static inline void check_mt(DisasContext *ctx)
2966 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2967 generate_exception_end(ctx, EXCP_RI);
2971 #ifndef CONFIG_USER_ONLY
2973 * This code generates a "coprocessor unusable" exception if CP0 is not
2974 * available, and, if that is not the case, generates a "reserved instruction"
2975 * exception if the Config5 MT bit is NOT set. This is needed for availability
2976 * control of some of MT ASE instructions.
2978 static inline void check_cp0_mt(DisasContext *ctx)
2980 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2981 generate_exception_err(ctx, EXCP_CpU, 0);
2982 } else {
2983 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2984 generate_exception_err(ctx, EXCP_RI, 0);
2988 #endif
2991 * This code generates a "reserved instruction" exception if the
2992 * Config5 NMS bit is set.
2994 static inline void check_nms(DisasContext *ctx)
2996 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2997 generate_exception_end(ctx, EXCP_RI);
3002 * This code generates a "reserved instruction" exception if the
3003 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3004 * Config2 TL, and Config5 L2C are unset.
3006 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3008 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3009 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3010 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3011 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3012 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3013 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3015 generate_exception_end(ctx, EXCP_RI);
3020 * This code generates a "reserved instruction" exception if the
3021 * Config5 EVA bit is NOT set.
3023 static inline void check_eva(DisasContext *ctx)
3025 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3026 generate_exception_end(ctx, EXCP_RI);
3031 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3032 calling interface for 32 and 64-bit FPRs. No sense in changing
3033 all callers for gen_load_fpr32 when we need the CTX parameter for
3034 this one use. */
3035 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3036 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3037 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3038 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3039 int ft, int fs, int cc) \
3041 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3042 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3043 switch (ifmt) { \
3044 case FMT_PS: \
3045 check_ps(ctx); \
3046 break; \
3047 case FMT_D: \
3048 if (abs) { \
3049 check_cop1x(ctx); \
3051 check_cp1_registers(ctx, fs | ft); \
3052 break; \
3053 case FMT_S: \
3054 if (abs) { \
3055 check_cop1x(ctx); \
3057 break; \
3059 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3060 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3061 switch (n) { \
3062 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3063 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3064 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3065 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3066 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3067 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3068 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3069 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3070 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3071 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3072 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3073 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3074 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3075 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3076 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3077 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3078 default: abort(); \
3080 tcg_temp_free_i##bits (fp0); \
3081 tcg_temp_free_i##bits (fp1); \
3084 FOP_CONDS(, 0, d, FMT_D, 64)
3085 FOP_CONDS(abs, 1, d, FMT_D, 64)
3086 FOP_CONDS(, 0, s, FMT_S, 32)
3087 FOP_CONDS(abs, 1, s, FMT_S, 32)
3088 FOP_CONDS(, 0, ps, FMT_PS, 64)
3089 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3090 #undef FOP_CONDS
3092 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3093 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3094 int ft, int fs, int fd) \
3096 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3097 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3098 if (ifmt == FMT_D) { \
3099 check_cp1_registers(ctx, fs | ft | fd); \
3101 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3102 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3103 switch (n) { \
3104 case 0: \
3105 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3106 break; \
3107 case 1: \
3108 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3109 break; \
3110 case 2: \
3111 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3112 break; \
3113 case 3: \
3114 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3115 break; \
3116 case 4: \
3117 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3118 break; \
3119 case 5: \
3120 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3121 break; \
3122 case 6: \
3123 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3124 break; \
3125 case 7: \
3126 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3127 break; \
3128 case 8: \
3129 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3130 break; \
3131 case 9: \
3132 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3133 break; \
3134 case 10: \
3135 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3136 break; \
3137 case 11: \
3138 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3139 break; \
3140 case 12: \
3141 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3142 break; \
3143 case 13: \
3144 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3145 break; \
3146 case 14: \
3147 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3148 break; \
3149 case 15: \
3150 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3151 break; \
3152 case 17: \
3153 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3154 break; \
3155 case 18: \
3156 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3157 break; \
3158 case 19: \
3159 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3160 break; \
3161 case 25: \
3162 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3163 break; \
3164 case 26: \
3165 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3166 break; \
3167 case 27: \
3168 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3169 break; \
3170 default: \
3171 abort(); \
3173 STORE; \
3174 tcg_temp_free_i ## bits (fp0); \
3175 tcg_temp_free_i ## bits (fp1); \
3178 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3179 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3180 #undef FOP_CONDNS
3181 #undef gen_ldcmp_fpr32
3182 #undef gen_ldcmp_fpr64
3184 /* load/store instructions. */
3185 #ifdef CONFIG_USER_ONLY
3186 #define OP_LD_ATOMIC(insn,fname) \
3187 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3188 DisasContext *ctx) \
3190 TCGv t0 = tcg_temp_new(); \
3191 tcg_gen_mov_tl(t0, arg1); \
3192 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3193 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3194 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3195 tcg_temp_free(t0); \
3197 #else
3198 #define OP_LD_ATOMIC(insn,fname) \
3199 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3200 DisasContext *ctx) \
3202 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3204 #endif
3205 OP_LD_ATOMIC(ll,ld32s);
3206 #if defined(TARGET_MIPS64)
3207 OP_LD_ATOMIC(lld,ld64);
3208 #endif
3209 #undef OP_LD_ATOMIC
3211 #ifdef CONFIG_USER_ONLY
3212 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3213 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3214 DisasContext *ctx) \
3216 TCGv t0 = tcg_temp_new(); \
3217 TCGLabel *l1 = gen_new_label(); \
3218 TCGLabel *l2 = gen_new_label(); \
3220 tcg_gen_andi_tl(t0, arg2, almask); \
3221 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3222 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3223 generate_exception(ctx, EXCP_AdES); \
3224 gen_set_label(l1); \
3225 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3226 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3227 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3228 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3229 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3230 generate_exception_end(ctx, EXCP_SC); \
3231 gen_set_label(l2); \
3232 tcg_gen_movi_tl(t0, 0); \
3233 gen_store_gpr(t0, rt); \
3234 tcg_temp_free(t0); \
3236 #else
3237 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3238 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3239 DisasContext *ctx) \
3241 TCGv t0 = tcg_temp_new(); \
3242 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3243 gen_store_gpr(t0, rt); \
3244 tcg_temp_free(t0); \
3246 #endif
3247 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3248 #if defined(TARGET_MIPS64)
3249 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3250 #endif
3251 #undef OP_ST_ATOMIC
3253 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3254 int base, int offset)
3256 if (base == 0) {
3257 tcg_gen_movi_tl(addr, offset);
3258 } else if (offset == 0) {
3259 gen_load_gpr(addr, base);
3260 } else {
3261 tcg_gen_movi_tl(addr, offset);
3262 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3266 static target_ulong pc_relative_pc (DisasContext *ctx)
3268 target_ulong pc = ctx->base.pc_next;
3270 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3271 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3273 pc -= branch_bytes;
3276 pc &= ~(target_ulong)3;
3277 return pc;
3280 /* Load */
3281 static void gen_ld(DisasContext *ctx, uint32_t opc,
3282 int rt, int base, int offset)
3284 TCGv t0, t1, t2;
3285 int mem_idx = ctx->mem_idx;
3287 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3288 /* Loongson CPU uses a load to zero register for prefetch.
3289 We emulate it as a NOP. On other CPU we must perform the
3290 actual memory access. */
3291 return;
3294 t0 = tcg_temp_new();
3295 gen_base_offset_addr(ctx, t0, base, offset);
3297 switch (opc) {
3298 #if defined(TARGET_MIPS64)
3299 case OPC_LWU:
3300 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3301 ctx->default_tcg_memop_mask);
3302 gen_store_gpr(t0, rt);
3303 break;
3304 case OPC_LD:
3305 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3306 ctx->default_tcg_memop_mask);
3307 gen_store_gpr(t0, rt);
3308 break;
3309 case OPC_LLD:
3310 case R6_OPC_LLD:
3311 op_ld_lld(t0, t0, mem_idx, ctx);
3312 gen_store_gpr(t0, rt);
3313 break;
3314 case OPC_LDL:
3315 t1 = tcg_temp_new();
3316 /* Do a byte access to possibly trigger a page
3317 fault with the unaligned address. */
3318 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3319 tcg_gen_andi_tl(t1, t0, 7);
3320 #ifndef TARGET_WORDS_BIGENDIAN
3321 tcg_gen_xori_tl(t1, t1, 7);
3322 #endif
3323 tcg_gen_shli_tl(t1, t1, 3);
3324 tcg_gen_andi_tl(t0, t0, ~7);
3325 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3326 tcg_gen_shl_tl(t0, t0, t1);
3327 t2 = tcg_const_tl(-1);
3328 tcg_gen_shl_tl(t2, t2, t1);
3329 gen_load_gpr(t1, rt);
3330 tcg_gen_andc_tl(t1, t1, t2);
3331 tcg_temp_free(t2);
3332 tcg_gen_or_tl(t0, t0, t1);
3333 tcg_temp_free(t1);
3334 gen_store_gpr(t0, rt);
3335 break;
3336 case OPC_LDR:
3337 t1 = tcg_temp_new();
3338 /* Do a byte access to possibly trigger a page
3339 fault with the unaligned address. */
3340 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3341 tcg_gen_andi_tl(t1, t0, 7);
3342 #ifdef TARGET_WORDS_BIGENDIAN
3343 tcg_gen_xori_tl(t1, t1, 7);
3344 #endif
3345 tcg_gen_shli_tl(t1, t1, 3);
3346 tcg_gen_andi_tl(t0, t0, ~7);
3347 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3348 tcg_gen_shr_tl(t0, t0, t1);
3349 tcg_gen_xori_tl(t1, t1, 63);
3350 t2 = tcg_const_tl(0xfffffffffffffffeull);
3351 tcg_gen_shl_tl(t2, t2, t1);
3352 gen_load_gpr(t1, rt);
3353 tcg_gen_and_tl(t1, t1, t2);
3354 tcg_temp_free(t2);
3355 tcg_gen_or_tl(t0, t0, t1);
3356 tcg_temp_free(t1);
3357 gen_store_gpr(t0, rt);
3358 break;
3359 case OPC_LDPC:
3360 t1 = tcg_const_tl(pc_relative_pc(ctx));
3361 gen_op_addr_add(ctx, t0, t0, t1);
3362 tcg_temp_free(t1);
3363 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3364 gen_store_gpr(t0, rt);
3365 break;
3366 #endif
3367 case OPC_LWPC:
3368 t1 = tcg_const_tl(pc_relative_pc(ctx));
3369 gen_op_addr_add(ctx, t0, t0, t1);
3370 tcg_temp_free(t1);
3371 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3372 gen_store_gpr(t0, rt);
3373 break;
3374 case OPC_LWE:
3375 mem_idx = MIPS_HFLAG_UM;
3376 /* fall through */
3377 case OPC_LW:
3378 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3379 ctx->default_tcg_memop_mask);
3380 gen_store_gpr(t0, rt);
3381 break;
3382 case OPC_LHE:
3383 mem_idx = MIPS_HFLAG_UM;
3384 /* fall through */
3385 case OPC_LH:
3386 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3387 ctx->default_tcg_memop_mask);
3388 gen_store_gpr(t0, rt);
3389 break;
3390 case OPC_LHUE:
3391 mem_idx = MIPS_HFLAG_UM;
3392 /* fall through */
3393 case OPC_LHU:
3394 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3395 ctx->default_tcg_memop_mask);
3396 gen_store_gpr(t0, rt);
3397 break;
3398 case OPC_LBE:
3399 mem_idx = MIPS_HFLAG_UM;
3400 /* fall through */
3401 case OPC_LB:
3402 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3403 gen_store_gpr(t0, rt);
3404 break;
3405 case OPC_LBUE:
3406 mem_idx = MIPS_HFLAG_UM;
3407 /* fall through */
3408 case OPC_LBU:
3409 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3410 gen_store_gpr(t0, rt);
3411 break;
3412 case OPC_LWLE:
3413 mem_idx = MIPS_HFLAG_UM;
3414 /* fall through */
3415 case OPC_LWL:
3416 t1 = tcg_temp_new();
3417 /* Do a byte access to possibly trigger a page
3418 fault with the unaligned address. */
3419 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3420 tcg_gen_andi_tl(t1, t0, 3);
3421 #ifndef TARGET_WORDS_BIGENDIAN
3422 tcg_gen_xori_tl(t1, t1, 3);
3423 #endif
3424 tcg_gen_shli_tl(t1, t1, 3);
3425 tcg_gen_andi_tl(t0, t0, ~3);
3426 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3427 tcg_gen_shl_tl(t0, t0, t1);
3428 t2 = tcg_const_tl(-1);
3429 tcg_gen_shl_tl(t2, t2, t1);
3430 gen_load_gpr(t1, rt);
3431 tcg_gen_andc_tl(t1, t1, t2);
3432 tcg_temp_free(t2);
3433 tcg_gen_or_tl(t0, t0, t1);
3434 tcg_temp_free(t1);
3435 tcg_gen_ext32s_tl(t0, t0);
3436 gen_store_gpr(t0, rt);
3437 break;
3438 case OPC_LWRE:
3439 mem_idx = MIPS_HFLAG_UM;
3440 /* fall through */
3441 case OPC_LWR:
3442 t1 = tcg_temp_new();
3443 /* Do a byte access to possibly trigger a page
3444 fault with the unaligned address. */
3445 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3446 tcg_gen_andi_tl(t1, t0, 3);
3447 #ifdef TARGET_WORDS_BIGENDIAN
3448 tcg_gen_xori_tl(t1, t1, 3);
3449 #endif
3450 tcg_gen_shli_tl(t1, t1, 3);
3451 tcg_gen_andi_tl(t0, t0, ~3);
3452 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3453 tcg_gen_shr_tl(t0, t0, t1);
3454 tcg_gen_xori_tl(t1, t1, 31);
3455 t2 = tcg_const_tl(0xfffffffeull);
3456 tcg_gen_shl_tl(t2, t2, t1);
3457 gen_load_gpr(t1, rt);
3458 tcg_gen_and_tl(t1, t1, t2);
3459 tcg_temp_free(t2);
3460 tcg_gen_or_tl(t0, t0, t1);
3461 tcg_temp_free(t1);
3462 tcg_gen_ext32s_tl(t0, t0);
3463 gen_store_gpr(t0, rt);
3464 break;
3465 case OPC_LLE:
3466 mem_idx = MIPS_HFLAG_UM;
3467 /* fall through */
3468 case OPC_LL:
3469 case R6_OPC_LL:
3470 op_ld_ll(t0, t0, mem_idx, ctx);
3471 gen_store_gpr(t0, rt);
3472 break;
3474 tcg_temp_free(t0);
3477 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3478 uint32_t reg1, uint32_t reg2)
3480 TCGv taddr = tcg_temp_new();
3481 TCGv_i64 tval = tcg_temp_new_i64();
3482 TCGv tmp1 = tcg_temp_new();
3483 TCGv tmp2 = tcg_temp_new();
3485 gen_base_offset_addr(ctx, taddr, base, offset);
3486 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3487 #ifdef TARGET_WORDS_BIGENDIAN
3488 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3489 #else
3490 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3491 #endif
3492 gen_store_gpr(tmp1, reg1);
3493 tcg_temp_free(tmp1);
3494 gen_store_gpr(tmp2, reg2);
3495 tcg_temp_free(tmp2);
3496 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3497 tcg_temp_free_i64(tval);
3498 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3499 tcg_temp_free(taddr);
3502 /* Store */
3503 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3504 int base, int offset)
3506 TCGv t0 = tcg_temp_new();
3507 TCGv t1 = tcg_temp_new();
3508 int mem_idx = ctx->mem_idx;
3510 gen_base_offset_addr(ctx, t0, base, offset);
3511 gen_load_gpr(t1, rt);
3512 switch (opc) {
3513 #if defined(TARGET_MIPS64)
3514 case OPC_SD:
3515 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3516 ctx->default_tcg_memop_mask);
3517 break;
3518 case OPC_SDL:
3519 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3520 break;
3521 case OPC_SDR:
3522 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3523 break;
3524 #endif
3525 case OPC_SWE:
3526 mem_idx = MIPS_HFLAG_UM;
3527 /* fall through */
3528 case OPC_SW:
3529 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3530 ctx->default_tcg_memop_mask);
3531 break;
3532 case OPC_SHE:
3533 mem_idx = MIPS_HFLAG_UM;
3534 /* fall through */
3535 case OPC_SH:
3536 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3537 ctx->default_tcg_memop_mask);
3538 break;
3539 case OPC_SBE:
3540 mem_idx = MIPS_HFLAG_UM;
3541 /* fall through */
3542 case OPC_SB:
3543 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3544 break;
3545 case OPC_SWLE:
3546 mem_idx = MIPS_HFLAG_UM;
3547 /* fall through */
3548 case OPC_SWL:
3549 gen_helper_0e2i(swl, t1, t0, mem_idx);
3550 break;
3551 case OPC_SWRE:
3552 mem_idx = MIPS_HFLAG_UM;
3553 /* fall through */
3554 case OPC_SWR:
3555 gen_helper_0e2i(swr, t1, t0, mem_idx);
3556 break;
3558 tcg_temp_free(t0);
3559 tcg_temp_free(t1);
3563 /* Store conditional */
3564 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3565 int base, int16_t offset)
3567 TCGv t0, t1;
3568 int mem_idx = ctx->mem_idx;
3570 #ifdef CONFIG_USER_ONLY
3571 t0 = tcg_temp_local_new();
3572 t1 = tcg_temp_local_new();
3573 #else
3574 t0 = tcg_temp_new();
3575 t1 = tcg_temp_new();
3576 #endif
3577 gen_base_offset_addr(ctx, t0, base, offset);
3578 gen_load_gpr(t1, rt);
3579 switch (opc) {
3580 #if defined(TARGET_MIPS64)
3581 case OPC_SCD:
3582 case R6_OPC_SCD:
3583 op_st_scd(t1, t0, rt, mem_idx, ctx);
3584 break;
3585 #endif
3586 case OPC_SCE:
3587 mem_idx = MIPS_HFLAG_UM;
3588 /* fall through */
3589 case OPC_SC:
3590 case R6_OPC_SC:
3591 op_st_sc(t1, t0, rt, mem_idx, ctx);
3592 break;
3594 tcg_temp_free(t1);
3595 tcg_temp_free(t0);
3598 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3599 uint32_t reg1, uint32_t reg2)
3601 TCGv taddr = tcg_temp_local_new();
3602 TCGv lladdr = tcg_temp_local_new();
3603 TCGv_i64 tval = tcg_temp_new_i64();
3604 TCGv_i64 llval = tcg_temp_new_i64();
3605 TCGv_i64 val = tcg_temp_new_i64();
3606 TCGv tmp1 = tcg_temp_new();
3607 TCGv tmp2 = tcg_temp_new();
3608 TCGLabel *lab_fail = gen_new_label();
3609 TCGLabel *lab_done = gen_new_label();
3611 gen_base_offset_addr(ctx, taddr, base, offset);
3613 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3614 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3616 gen_load_gpr(tmp1, reg1);
3617 gen_load_gpr(tmp2, reg2);
3619 #ifdef TARGET_WORDS_BIGENDIAN
3620 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3621 #else
3622 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3623 #endif
3625 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3626 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3627 ctx->mem_idx, MO_64);
3628 if (reg1 != 0) {
3629 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3631 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3633 gen_set_label(lab_fail);
3635 if (reg1 != 0) {
3636 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3638 gen_set_label(lab_done);
3639 tcg_gen_movi_tl(lladdr, -1);
3640 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3643 /* Load and store */
3644 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3645 TCGv t0)
3647 /* Don't do NOP if destination is zero: we must perform the actual
3648 memory access. */
3649 switch (opc) {
3650 case OPC_LWC1:
3652 TCGv_i32 fp0 = tcg_temp_new_i32();
3653 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3654 ctx->default_tcg_memop_mask);
3655 gen_store_fpr32(ctx, fp0, ft);
3656 tcg_temp_free_i32(fp0);
3658 break;
3659 case OPC_SWC1:
3661 TCGv_i32 fp0 = tcg_temp_new_i32();
3662 gen_load_fpr32(ctx, fp0, ft);
3663 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3664 ctx->default_tcg_memop_mask);
3665 tcg_temp_free_i32(fp0);
3667 break;
3668 case OPC_LDC1:
3670 TCGv_i64 fp0 = tcg_temp_new_i64();
3671 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3672 ctx->default_tcg_memop_mask);
3673 gen_store_fpr64(ctx, fp0, ft);
3674 tcg_temp_free_i64(fp0);
3676 break;
3677 case OPC_SDC1:
3679 TCGv_i64 fp0 = tcg_temp_new_i64();
3680 gen_load_fpr64(ctx, fp0, ft);
3681 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3682 ctx->default_tcg_memop_mask);
3683 tcg_temp_free_i64(fp0);
3685 break;
3686 default:
3687 MIPS_INVAL("flt_ldst");
3688 generate_exception_end(ctx, EXCP_RI);
3689 break;
3693 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3694 int rs, int16_t imm)
3696 TCGv t0 = tcg_temp_new();
3698 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3699 check_cp1_enabled(ctx);
3700 switch (op) {
3701 case OPC_LDC1:
3702 case OPC_SDC1:
3703 check_insn(ctx, ISA_MIPS2);
3704 /* Fallthrough */
3705 default:
3706 gen_base_offset_addr(ctx, t0, rs, imm);
3707 gen_flt_ldst(ctx, op, rt, t0);
3709 } else {
3710 generate_exception_err(ctx, EXCP_CpU, 1);
3712 tcg_temp_free(t0);
3715 /* Arithmetic with immediate operand */
3716 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3717 int rt, int rs, int imm)
3719 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3721 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3722 /* If no destination, treat it as a NOP.
3723 For addi, we must generate the overflow exception when needed. */
3724 return;
3726 switch (opc) {
3727 case OPC_ADDI:
3729 TCGv t0 = tcg_temp_local_new();
3730 TCGv t1 = tcg_temp_new();
3731 TCGv t2 = tcg_temp_new();
3732 TCGLabel *l1 = gen_new_label();
3734 gen_load_gpr(t1, rs);
3735 tcg_gen_addi_tl(t0, t1, uimm);
3736 tcg_gen_ext32s_tl(t0, t0);
3738 tcg_gen_xori_tl(t1, t1, ~uimm);
3739 tcg_gen_xori_tl(t2, t0, uimm);
3740 tcg_gen_and_tl(t1, t1, t2);
3741 tcg_temp_free(t2);
3742 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3743 tcg_temp_free(t1);
3744 /* operands of same sign, result different sign */
3745 generate_exception(ctx, EXCP_OVERFLOW);
3746 gen_set_label(l1);
3747 tcg_gen_ext32s_tl(t0, t0);
3748 gen_store_gpr(t0, rt);
3749 tcg_temp_free(t0);
3751 break;
3752 case OPC_ADDIU:
3753 if (rs != 0) {
3754 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3755 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3756 } else {
3757 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3759 break;
3760 #if defined(TARGET_MIPS64)
3761 case OPC_DADDI:
3763 TCGv t0 = tcg_temp_local_new();
3764 TCGv t1 = tcg_temp_new();
3765 TCGv t2 = tcg_temp_new();
3766 TCGLabel *l1 = gen_new_label();
3768 gen_load_gpr(t1, rs);
3769 tcg_gen_addi_tl(t0, t1, uimm);
3771 tcg_gen_xori_tl(t1, t1, ~uimm);
3772 tcg_gen_xori_tl(t2, t0, uimm);
3773 tcg_gen_and_tl(t1, t1, t2);
3774 tcg_temp_free(t2);
3775 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3776 tcg_temp_free(t1);
3777 /* operands of same sign, result different sign */
3778 generate_exception(ctx, EXCP_OVERFLOW);
3779 gen_set_label(l1);
3780 gen_store_gpr(t0, rt);
3781 tcg_temp_free(t0);
3783 break;
3784 case OPC_DADDIU:
3785 if (rs != 0) {
3786 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3787 } else {
3788 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3790 break;
3791 #endif
3795 /* Logic with immediate operand */
3796 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3797 int rt, int rs, int16_t imm)
3799 target_ulong uimm;
3801 if (rt == 0) {
3802 /* If no destination, treat it as a NOP. */
3803 return;
3805 uimm = (uint16_t)imm;
3806 switch (opc) {
3807 case OPC_ANDI:
3808 if (likely(rs != 0))
3809 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3810 else
3811 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3812 break;
3813 case OPC_ORI:
3814 if (rs != 0)
3815 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3816 else
3817 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3818 break;
3819 case OPC_XORI:
3820 if (likely(rs != 0))
3821 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3822 else
3823 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3824 break;
3825 case OPC_LUI:
3826 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3827 /* OPC_AUI */
3828 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3829 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3830 } else {
3831 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3833 break;
3835 default:
3836 break;
3840 /* Set on less than with immediate operand */
3841 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3842 int rt, int rs, int16_t imm)
3844 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3845 TCGv t0;
3847 if (rt == 0) {
3848 /* If no destination, treat it as a NOP. */
3849 return;
3851 t0 = tcg_temp_new();
3852 gen_load_gpr(t0, rs);
3853 switch (opc) {
3854 case OPC_SLTI:
3855 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3856 break;
3857 case OPC_SLTIU:
3858 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3859 break;
3861 tcg_temp_free(t0);
3864 /* Shifts with immediate operand */
3865 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3866 int rt, int rs, int16_t imm)
3868 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3869 TCGv t0;
3871 if (rt == 0) {
3872 /* If no destination, treat it as a NOP. */
3873 return;
3876 t0 = tcg_temp_new();
3877 gen_load_gpr(t0, rs);
3878 switch (opc) {
3879 case OPC_SLL:
3880 tcg_gen_shli_tl(t0, t0, uimm);
3881 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3882 break;
3883 case OPC_SRA:
3884 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3885 break;
3886 case OPC_SRL:
3887 if (uimm != 0) {
3888 tcg_gen_ext32u_tl(t0, t0);
3889 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3890 } else {
3891 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3893 break;
3894 case OPC_ROTR:
3895 if (uimm != 0) {
3896 TCGv_i32 t1 = tcg_temp_new_i32();
3898 tcg_gen_trunc_tl_i32(t1, t0);
3899 tcg_gen_rotri_i32(t1, t1, uimm);
3900 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3901 tcg_temp_free_i32(t1);
3902 } else {
3903 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3905 break;
3906 #if defined(TARGET_MIPS64)
3907 case OPC_DSLL:
3908 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3909 break;
3910 case OPC_DSRA:
3911 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3912 break;
3913 case OPC_DSRL:
3914 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3915 break;
3916 case OPC_DROTR:
3917 if (uimm != 0) {
3918 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3919 } else {
3920 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3922 break;
3923 case OPC_DSLL32:
3924 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3925 break;
3926 case OPC_DSRA32:
3927 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3928 break;
3929 case OPC_DSRL32:
3930 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3931 break;
3932 case OPC_DROTR32:
3933 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3934 break;
3935 #endif
3937 tcg_temp_free(t0);
3940 /* Arithmetic */
3941 static void gen_arith(DisasContext *ctx, uint32_t opc,
3942 int rd, int rs, int rt)
3944 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3945 && opc != OPC_DADD && opc != OPC_DSUB) {
3946 /* If no destination, treat it as a NOP.
3947 For add & sub, we must generate the overflow exception when needed. */
3948 return;
3951 switch (opc) {
3952 case OPC_ADD:
3954 TCGv t0 = tcg_temp_local_new();
3955 TCGv t1 = tcg_temp_new();
3956 TCGv t2 = tcg_temp_new();
3957 TCGLabel *l1 = gen_new_label();
3959 gen_load_gpr(t1, rs);
3960 gen_load_gpr(t2, rt);
3961 tcg_gen_add_tl(t0, t1, t2);
3962 tcg_gen_ext32s_tl(t0, t0);
3963 tcg_gen_xor_tl(t1, t1, t2);
3964 tcg_gen_xor_tl(t2, t0, t2);
3965 tcg_gen_andc_tl(t1, t2, t1);
3966 tcg_temp_free(t2);
3967 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3968 tcg_temp_free(t1);
3969 /* operands of same sign, result different sign */
3970 generate_exception(ctx, EXCP_OVERFLOW);
3971 gen_set_label(l1);
3972 gen_store_gpr(t0, rd);
3973 tcg_temp_free(t0);
3975 break;
3976 case OPC_ADDU:
3977 if (rs != 0 && rt != 0) {
3978 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3979 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3980 } else if (rs == 0 && rt != 0) {
3981 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3982 } else if (rs != 0 && rt == 0) {
3983 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3984 } else {
3985 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3987 break;
3988 case OPC_SUB:
3990 TCGv t0 = tcg_temp_local_new();
3991 TCGv t1 = tcg_temp_new();
3992 TCGv t2 = tcg_temp_new();
3993 TCGLabel *l1 = gen_new_label();
3995 gen_load_gpr(t1, rs);
3996 gen_load_gpr(t2, rt);
3997 tcg_gen_sub_tl(t0, t1, t2);
3998 tcg_gen_ext32s_tl(t0, t0);
3999 tcg_gen_xor_tl(t2, t1, t2);
4000 tcg_gen_xor_tl(t1, t0, t1);
4001 tcg_gen_and_tl(t1, t1, t2);
4002 tcg_temp_free(t2);
4003 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4004 tcg_temp_free(t1);
4005 /* operands of different sign, first operand and result different sign */
4006 generate_exception(ctx, EXCP_OVERFLOW);
4007 gen_set_label(l1);
4008 gen_store_gpr(t0, rd);
4009 tcg_temp_free(t0);
4011 break;
4012 case OPC_SUBU:
4013 if (rs != 0 && rt != 0) {
4014 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4015 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4016 } else if (rs == 0 && rt != 0) {
4017 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4018 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4019 } else if (rs != 0 && rt == 0) {
4020 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4021 } else {
4022 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4024 break;
4025 #if defined(TARGET_MIPS64)
4026 case OPC_DADD:
4028 TCGv t0 = tcg_temp_local_new();
4029 TCGv t1 = tcg_temp_new();
4030 TCGv t2 = tcg_temp_new();
4031 TCGLabel *l1 = gen_new_label();
4033 gen_load_gpr(t1, rs);
4034 gen_load_gpr(t2, rt);
4035 tcg_gen_add_tl(t0, t1, t2);
4036 tcg_gen_xor_tl(t1, t1, t2);
4037 tcg_gen_xor_tl(t2, t0, t2);
4038 tcg_gen_andc_tl(t1, t2, t1);
4039 tcg_temp_free(t2);
4040 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4041 tcg_temp_free(t1);
4042 /* operands of same sign, result different sign */
4043 generate_exception(ctx, EXCP_OVERFLOW);
4044 gen_set_label(l1);
4045 gen_store_gpr(t0, rd);
4046 tcg_temp_free(t0);
4048 break;
4049 case OPC_DADDU:
4050 if (rs != 0 && rt != 0) {
4051 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4052 } else if (rs == 0 && rt != 0) {
4053 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4054 } else if (rs != 0 && rt == 0) {
4055 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4056 } else {
4057 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4059 break;
4060 case OPC_DSUB:
4062 TCGv t0 = tcg_temp_local_new();
4063 TCGv t1 = tcg_temp_new();
4064 TCGv t2 = tcg_temp_new();
4065 TCGLabel *l1 = gen_new_label();
4067 gen_load_gpr(t1, rs);
4068 gen_load_gpr(t2, rt);
4069 tcg_gen_sub_tl(t0, t1, t2);
4070 tcg_gen_xor_tl(t2, t1, t2);
4071 tcg_gen_xor_tl(t1, t0, t1);
4072 tcg_gen_and_tl(t1, t1, t2);
4073 tcg_temp_free(t2);
4074 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4075 tcg_temp_free(t1);
4076 /* operands of different sign, first operand and result different sign */
4077 generate_exception(ctx, EXCP_OVERFLOW);
4078 gen_set_label(l1);
4079 gen_store_gpr(t0, rd);
4080 tcg_temp_free(t0);
4082 break;
4083 case OPC_DSUBU:
4084 if (rs != 0 && rt != 0) {
4085 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4086 } else if (rs == 0 && rt != 0) {
4087 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4088 } else if (rs != 0 && rt == 0) {
4089 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4090 } else {
4091 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4093 break;
4094 #endif
4095 case OPC_MUL:
4096 if (likely(rs != 0 && rt != 0)) {
4097 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4098 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4099 } else {
4100 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4102 break;
4106 /* Conditional move */
4107 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4108 int rd, int rs, int rt)
4110 TCGv t0, t1, t2;
4112 if (rd == 0) {
4113 /* If no destination, treat it as a NOP. */
4114 return;
4117 t0 = tcg_temp_new();
4118 gen_load_gpr(t0, rt);
4119 t1 = tcg_const_tl(0);
4120 t2 = tcg_temp_new();
4121 gen_load_gpr(t2, rs);
4122 switch (opc) {
4123 case OPC_MOVN:
4124 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4125 break;
4126 case OPC_MOVZ:
4127 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4128 break;
4129 case OPC_SELNEZ:
4130 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4131 break;
4132 case OPC_SELEQZ:
4133 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4134 break;
4136 tcg_temp_free(t2);
4137 tcg_temp_free(t1);
4138 tcg_temp_free(t0);
4141 /* Logic */
4142 static void gen_logic(DisasContext *ctx, uint32_t opc,
4143 int rd, int rs, int rt)
4145 if (rd == 0) {
4146 /* If no destination, treat it as a NOP. */
4147 return;
4150 switch (opc) {
4151 case OPC_AND:
4152 if (likely(rs != 0 && rt != 0)) {
4153 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4154 } else {
4155 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4157 break;
4158 case OPC_NOR:
4159 if (rs != 0 && rt != 0) {
4160 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4161 } else if (rs == 0 && rt != 0) {
4162 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4163 } else if (rs != 0 && rt == 0) {
4164 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4165 } else {
4166 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4168 break;
4169 case OPC_OR:
4170 if (likely(rs != 0 && rt != 0)) {
4171 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4172 } else if (rs == 0 && rt != 0) {
4173 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4174 } else if (rs != 0 && rt == 0) {
4175 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4176 } else {
4177 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4179 break;
4180 case OPC_XOR:
4181 if (likely(rs != 0 && rt != 0)) {
4182 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4183 } else if (rs == 0 && rt != 0) {
4184 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4185 } else if (rs != 0 && rt == 0) {
4186 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4187 } else {
4188 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4190 break;
4194 /* Set on lower than */
4195 static void gen_slt(DisasContext *ctx, uint32_t opc,
4196 int rd, int rs, int rt)
4198 TCGv t0, t1;
4200 if (rd == 0) {
4201 /* If no destination, treat it as a NOP. */
4202 return;
4205 t0 = tcg_temp_new();
4206 t1 = tcg_temp_new();
4207 gen_load_gpr(t0, rs);
4208 gen_load_gpr(t1, rt);
4209 switch (opc) {
4210 case OPC_SLT:
4211 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4212 break;
4213 case OPC_SLTU:
4214 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4215 break;
4217 tcg_temp_free(t0);
4218 tcg_temp_free(t1);
4221 /* Shifts */
4222 static void gen_shift(DisasContext *ctx, uint32_t opc,
4223 int rd, int rs, int rt)
4225 TCGv t0, t1;
4227 if (rd == 0) {
4228 /* If no destination, treat it as a NOP.
4229 For add & sub, we must generate the overflow exception when needed. */
4230 return;
4233 t0 = tcg_temp_new();
4234 t1 = tcg_temp_new();
4235 gen_load_gpr(t0, rs);
4236 gen_load_gpr(t1, rt);
4237 switch (opc) {
4238 case OPC_SLLV:
4239 tcg_gen_andi_tl(t0, t0, 0x1f);
4240 tcg_gen_shl_tl(t0, t1, t0);
4241 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4242 break;
4243 case OPC_SRAV:
4244 tcg_gen_andi_tl(t0, t0, 0x1f);
4245 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4246 break;
4247 case OPC_SRLV:
4248 tcg_gen_ext32u_tl(t1, t1);
4249 tcg_gen_andi_tl(t0, t0, 0x1f);
4250 tcg_gen_shr_tl(t0, t1, t0);
4251 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4252 break;
4253 case OPC_ROTRV:
4255 TCGv_i32 t2 = tcg_temp_new_i32();
4256 TCGv_i32 t3 = tcg_temp_new_i32();
4258 tcg_gen_trunc_tl_i32(t2, t0);
4259 tcg_gen_trunc_tl_i32(t3, t1);
4260 tcg_gen_andi_i32(t2, t2, 0x1f);
4261 tcg_gen_rotr_i32(t2, t3, t2);
4262 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4263 tcg_temp_free_i32(t2);
4264 tcg_temp_free_i32(t3);
4266 break;
4267 #if defined(TARGET_MIPS64)
4268 case OPC_DSLLV:
4269 tcg_gen_andi_tl(t0, t0, 0x3f);
4270 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4271 break;
4272 case OPC_DSRAV:
4273 tcg_gen_andi_tl(t0, t0, 0x3f);
4274 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4275 break;
4276 case OPC_DSRLV:
4277 tcg_gen_andi_tl(t0, t0, 0x3f);
4278 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4279 break;
4280 case OPC_DROTRV:
4281 tcg_gen_andi_tl(t0, t0, 0x3f);
4282 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4283 break;
4284 #endif
4286 tcg_temp_free(t0);
4287 tcg_temp_free(t1);
4290 /* Arithmetic on HI/LO registers */
4291 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4293 if (reg == 0 && (opc == OPC_MFHI || opc == TX79_MMI_MFHI1 ||
4294 opc == OPC_MFLO || opc == TX79_MMI_MFLO1)) {
4295 /* Treat as NOP. */
4296 return;
4299 if (acc != 0) {
4300 if (!(ctx->insn_flags & INSN_R5900)) {
4301 check_dsp(ctx);
4305 switch (opc) {
4306 case OPC_MFHI:
4307 case TX79_MMI_MFHI1:
4308 #if defined(TARGET_MIPS64)
4309 if (acc != 0) {
4310 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4311 } else
4312 #endif
4314 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4316 break;
4317 case OPC_MFLO:
4318 case TX79_MMI_MFLO1:
4319 #if defined(TARGET_MIPS64)
4320 if (acc != 0) {
4321 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4322 } else
4323 #endif
4325 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4327 break;
4328 case OPC_MTHI:
4329 case TX79_MMI_MTHI1:
4330 if (reg != 0) {
4331 #if defined(TARGET_MIPS64)
4332 if (acc != 0) {
4333 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4334 } else
4335 #endif
4337 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4339 } else {
4340 tcg_gen_movi_tl(cpu_HI[acc], 0);
4342 break;
4343 case OPC_MTLO:
4344 case TX79_MMI_MTLO1:
4345 if (reg != 0) {
4346 #if defined(TARGET_MIPS64)
4347 if (acc != 0) {
4348 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4349 } else
4350 #endif
4352 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4354 } else {
4355 tcg_gen_movi_tl(cpu_LO[acc], 0);
4357 break;
4361 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4362 TCGMemOp memop)
4364 TCGv t0 = tcg_const_tl(addr);
4365 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4366 gen_store_gpr(t0, reg);
4367 tcg_temp_free(t0);
4370 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4371 int rs)
4373 target_long offset;
4374 target_long addr;
4376 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4377 case OPC_ADDIUPC:
4378 if (rs != 0) {
4379 offset = sextract32(ctx->opcode << 2, 0, 21);
4380 addr = addr_add(ctx, pc, offset);
4381 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4383 break;
4384 case R6_OPC_LWPC:
4385 offset = sextract32(ctx->opcode << 2, 0, 21);
4386 addr = addr_add(ctx, pc, offset);
4387 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4388 break;
4389 #if defined(TARGET_MIPS64)
4390 case OPC_LWUPC:
4391 check_mips_64(ctx);
4392 offset = sextract32(ctx->opcode << 2, 0, 21);
4393 addr = addr_add(ctx, pc, offset);
4394 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4395 break;
4396 #endif
4397 default:
4398 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4399 case OPC_AUIPC:
4400 if (rs != 0) {
4401 offset = sextract32(ctx->opcode, 0, 16) << 16;
4402 addr = addr_add(ctx, pc, offset);
4403 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4405 break;
4406 case OPC_ALUIPC:
4407 if (rs != 0) {
4408 offset = sextract32(ctx->opcode, 0, 16) << 16;
4409 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4410 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4412 break;
4413 #if defined(TARGET_MIPS64)
4414 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4415 case R6_OPC_LDPC + (1 << 16):
4416 case R6_OPC_LDPC + (2 << 16):
4417 case R6_OPC_LDPC + (3 << 16):
4418 check_mips_64(ctx);
4419 offset = sextract32(ctx->opcode << 3, 0, 21);
4420 addr = addr_add(ctx, (pc & ~0x7), offset);
4421 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4422 break;
4423 #endif
4424 default:
4425 MIPS_INVAL("OPC_PCREL");
4426 generate_exception_end(ctx, EXCP_RI);
4427 break;
4429 break;
4433 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4435 TCGv t0, t1;
4437 if (rd == 0) {
4438 /* Treat as NOP. */
4439 return;
4442 t0 = tcg_temp_new();
4443 t1 = tcg_temp_new();
4445 gen_load_gpr(t0, rs);
4446 gen_load_gpr(t1, rt);
4448 switch (opc) {
4449 case R6_OPC_DIV:
4451 TCGv t2 = tcg_temp_new();
4452 TCGv t3 = tcg_temp_new();
4453 tcg_gen_ext32s_tl(t0, t0);
4454 tcg_gen_ext32s_tl(t1, t1);
4455 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4456 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4457 tcg_gen_and_tl(t2, t2, t3);
4458 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4459 tcg_gen_or_tl(t2, t2, t3);
4460 tcg_gen_movi_tl(t3, 0);
4461 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4462 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4463 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4464 tcg_temp_free(t3);
4465 tcg_temp_free(t2);
4467 break;
4468 case R6_OPC_MOD:
4470 TCGv t2 = tcg_temp_new();
4471 TCGv t3 = tcg_temp_new();
4472 tcg_gen_ext32s_tl(t0, t0);
4473 tcg_gen_ext32s_tl(t1, t1);
4474 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4475 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4476 tcg_gen_and_tl(t2, t2, t3);
4477 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4478 tcg_gen_or_tl(t2, t2, t3);
4479 tcg_gen_movi_tl(t3, 0);
4480 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4481 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4482 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4483 tcg_temp_free(t3);
4484 tcg_temp_free(t2);
4486 break;
4487 case R6_OPC_DIVU:
4489 TCGv t2 = tcg_const_tl(0);
4490 TCGv t3 = tcg_const_tl(1);
4491 tcg_gen_ext32u_tl(t0, t0);
4492 tcg_gen_ext32u_tl(t1, t1);
4493 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4494 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4495 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4496 tcg_temp_free(t3);
4497 tcg_temp_free(t2);
4499 break;
4500 case R6_OPC_MODU:
4502 TCGv t2 = tcg_const_tl(0);
4503 TCGv t3 = tcg_const_tl(1);
4504 tcg_gen_ext32u_tl(t0, t0);
4505 tcg_gen_ext32u_tl(t1, t1);
4506 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4507 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4508 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4509 tcg_temp_free(t3);
4510 tcg_temp_free(t2);
4512 break;
4513 case R6_OPC_MUL:
4515 TCGv_i32 t2 = tcg_temp_new_i32();
4516 TCGv_i32 t3 = tcg_temp_new_i32();
4517 tcg_gen_trunc_tl_i32(t2, t0);
4518 tcg_gen_trunc_tl_i32(t3, t1);
4519 tcg_gen_mul_i32(t2, t2, t3);
4520 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4521 tcg_temp_free_i32(t2);
4522 tcg_temp_free_i32(t3);
4524 break;
4525 case R6_OPC_MUH:
4527 TCGv_i32 t2 = tcg_temp_new_i32();
4528 TCGv_i32 t3 = tcg_temp_new_i32();
4529 tcg_gen_trunc_tl_i32(t2, t0);
4530 tcg_gen_trunc_tl_i32(t3, t1);
4531 tcg_gen_muls2_i32(t2, t3, t2, t3);
4532 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4533 tcg_temp_free_i32(t2);
4534 tcg_temp_free_i32(t3);
4536 break;
4537 case R6_OPC_MULU:
4539 TCGv_i32 t2 = tcg_temp_new_i32();
4540 TCGv_i32 t3 = tcg_temp_new_i32();
4541 tcg_gen_trunc_tl_i32(t2, t0);
4542 tcg_gen_trunc_tl_i32(t3, t1);
4543 tcg_gen_mul_i32(t2, t2, t3);
4544 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4545 tcg_temp_free_i32(t2);
4546 tcg_temp_free_i32(t3);
4548 break;
4549 case R6_OPC_MUHU:
4551 TCGv_i32 t2 = tcg_temp_new_i32();
4552 TCGv_i32 t3 = tcg_temp_new_i32();
4553 tcg_gen_trunc_tl_i32(t2, t0);
4554 tcg_gen_trunc_tl_i32(t3, t1);
4555 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4556 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4557 tcg_temp_free_i32(t2);
4558 tcg_temp_free_i32(t3);
4560 break;
4561 #if defined(TARGET_MIPS64)
4562 case R6_OPC_DDIV:
4564 TCGv t2 = tcg_temp_new();
4565 TCGv t3 = tcg_temp_new();
4566 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4567 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4568 tcg_gen_and_tl(t2, t2, t3);
4569 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4570 tcg_gen_or_tl(t2, t2, t3);
4571 tcg_gen_movi_tl(t3, 0);
4572 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4573 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4574 tcg_temp_free(t3);
4575 tcg_temp_free(t2);
4577 break;
4578 case R6_OPC_DMOD:
4580 TCGv t2 = tcg_temp_new();
4581 TCGv t3 = tcg_temp_new();
4582 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4583 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4584 tcg_gen_and_tl(t2, t2, t3);
4585 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4586 tcg_gen_or_tl(t2, t2, t3);
4587 tcg_gen_movi_tl(t3, 0);
4588 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4589 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4590 tcg_temp_free(t3);
4591 tcg_temp_free(t2);
4593 break;
4594 case R6_OPC_DDIVU:
4596 TCGv t2 = tcg_const_tl(0);
4597 TCGv t3 = tcg_const_tl(1);
4598 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4599 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4600 tcg_temp_free(t3);
4601 tcg_temp_free(t2);
4603 break;
4604 case R6_OPC_DMODU:
4606 TCGv t2 = tcg_const_tl(0);
4607 TCGv t3 = tcg_const_tl(1);
4608 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4609 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4610 tcg_temp_free(t3);
4611 tcg_temp_free(t2);
4613 break;
4614 case R6_OPC_DMUL:
4615 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4616 break;
4617 case R6_OPC_DMUH:
4619 TCGv t2 = tcg_temp_new();
4620 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4621 tcg_temp_free(t2);
4623 break;
4624 case R6_OPC_DMULU:
4625 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4626 break;
4627 case R6_OPC_DMUHU:
4629 TCGv t2 = tcg_temp_new();
4630 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4631 tcg_temp_free(t2);
4633 break;
4634 #endif
4635 default:
4636 MIPS_INVAL("r6 mul/div");
4637 generate_exception_end(ctx, EXCP_RI);
4638 goto out;
4640 out:
4641 tcg_temp_free(t0);
4642 tcg_temp_free(t1);
4645 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4646 int acc, int rs, int rt)
4648 TCGv t0, t1;
4650 t0 = tcg_temp_new();
4651 t1 = tcg_temp_new();
4653 gen_load_gpr(t0, rs);
4654 gen_load_gpr(t1, rt);
4656 if (acc != 0) {
4657 if (!(ctx->insn_flags & INSN_R5900)) {
4658 check_dsp(ctx);
4662 switch (opc) {
4663 case OPC_DIV:
4664 case TX79_MMI_DIV1:
4666 TCGv t2 = tcg_temp_new();
4667 TCGv t3 = tcg_temp_new();
4668 tcg_gen_ext32s_tl(t0, t0);
4669 tcg_gen_ext32s_tl(t1, t1);
4670 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4671 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4672 tcg_gen_and_tl(t2, t2, t3);
4673 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4674 tcg_gen_or_tl(t2, t2, t3);
4675 tcg_gen_movi_tl(t3, 0);
4676 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4677 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4678 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4679 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4680 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4681 tcg_temp_free(t3);
4682 tcg_temp_free(t2);
4684 break;
4685 case OPC_DIVU:
4686 case TX79_MMI_DIVU1:
4688 TCGv t2 = tcg_const_tl(0);
4689 TCGv t3 = tcg_const_tl(1);
4690 tcg_gen_ext32u_tl(t0, t0);
4691 tcg_gen_ext32u_tl(t1, t1);
4692 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4693 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4694 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4695 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4696 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4697 tcg_temp_free(t3);
4698 tcg_temp_free(t2);
4700 break;
4701 case OPC_MULT:
4703 TCGv_i32 t2 = tcg_temp_new_i32();
4704 TCGv_i32 t3 = tcg_temp_new_i32();
4705 tcg_gen_trunc_tl_i32(t2, t0);
4706 tcg_gen_trunc_tl_i32(t3, t1);
4707 tcg_gen_muls2_i32(t2, t3, t2, t3);
4708 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4709 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4710 tcg_temp_free_i32(t2);
4711 tcg_temp_free_i32(t3);
4713 break;
4714 case OPC_MULTU:
4716 TCGv_i32 t2 = tcg_temp_new_i32();
4717 TCGv_i32 t3 = tcg_temp_new_i32();
4718 tcg_gen_trunc_tl_i32(t2, t0);
4719 tcg_gen_trunc_tl_i32(t3, t1);
4720 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4721 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4722 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4723 tcg_temp_free_i32(t2);
4724 tcg_temp_free_i32(t3);
4726 break;
4727 #if defined(TARGET_MIPS64)
4728 case OPC_DDIV:
4730 TCGv t2 = tcg_temp_new();
4731 TCGv t3 = tcg_temp_new();
4732 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4733 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4734 tcg_gen_and_tl(t2, t2, t3);
4735 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4736 tcg_gen_or_tl(t2, t2, t3);
4737 tcg_gen_movi_tl(t3, 0);
4738 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4739 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4740 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4741 tcg_temp_free(t3);
4742 tcg_temp_free(t2);
4744 break;
4745 case OPC_DDIVU:
4747 TCGv t2 = tcg_const_tl(0);
4748 TCGv t3 = tcg_const_tl(1);
4749 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4750 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4751 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4752 tcg_temp_free(t3);
4753 tcg_temp_free(t2);
4755 break;
4756 case OPC_DMULT:
4757 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4758 break;
4759 case OPC_DMULTU:
4760 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4761 break;
4762 #endif
4763 case OPC_MADD:
4765 TCGv_i64 t2 = tcg_temp_new_i64();
4766 TCGv_i64 t3 = tcg_temp_new_i64();
4768 tcg_gen_ext_tl_i64(t2, t0);
4769 tcg_gen_ext_tl_i64(t3, t1);
4770 tcg_gen_mul_i64(t2, t2, t3);
4771 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4772 tcg_gen_add_i64(t2, t2, t3);
4773 tcg_temp_free_i64(t3);
4774 gen_move_low32(cpu_LO[acc], t2);
4775 gen_move_high32(cpu_HI[acc], t2);
4776 tcg_temp_free_i64(t2);
4778 break;
4779 case OPC_MADDU:
4781 TCGv_i64 t2 = tcg_temp_new_i64();
4782 TCGv_i64 t3 = tcg_temp_new_i64();
4784 tcg_gen_ext32u_tl(t0, t0);
4785 tcg_gen_ext32u_tl(t1, t1);
4786 tcg_gen_extu_tl_i64(t2, t0);
4787 tcg_gen_extu_tl_i64(t3, t1);
4788 tcg_gen_mul_i64(t2, t2, t3);
4789 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4790 tcg_gen_add_i64(t2, t2, t3);
4791 tcg_temp_free_i64(t3);
4792 gen_move_low32(cpu_LO[acc], t2);
4793 gen_move_high32(cpu_HI[acc], t2);
4794 tcg_temp_free_i64(t2);
4796 break;
4797 case OPC_MSUB:
4799 TCGv_i64 t2 = tcg_temp_new_i64();
4800 TCGv_i64 t3 = tcg_temp_new_i64();
4802 tcg_gen_ext_tl_i64(t2, t0);
4803 tcg_gen_ext_tl_i64(t3, t1);
4804 tcg_gen_mul_i64(t2, t2, t3);
4805 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4806 tcg_gen_sub_i64(t2, t3, t2);
4807 tcg_temp_free_i64(t3);
4808 gen_move_low32(cpu_LO[acc], t2);
4809 gen_move_high32(cpu_HI[acc], t2);
4810 tcg_temp_free_i64(t2);
4812 break;
4813 case OPC_MSUBU:
4815 TCGv_i64 t2 = tcg_temp_new_i64();
4816 TCGv_i64 t3 = tcg_temp_new_i64();
4818 tcg_gen_ext32u_tl(t0, t0);
4819 tcg_gen_ext32u_tl(t1, t1);
4820 tcg_gen_extu_tl_i64(t2, t0);
4821 tcg_gen_extu_tl_i64(t3, t1);
4822 tcg_gen_mul_i64(t2, t2, t3);
4823 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4824 tcg_gen_sub_i64(t2, t3, t2);
4825 tcg_temp_free_i64(t3);
4826 gen_move_low32(cpu_LO[acc], t2);
4827 gen_move_high32(cpu_HI[acc], t2);
4828 tcg_temp_free_i64(t2);
4830 break;
4831 default:
4832 MIPS_INVAL("mul/div");
4833 generate_exception_end(ctx, EXCP_RI);
4834 goto out;
4836 out:
4837 tcg_temp_free(t0);
4838 tcg_temp_free(t1);
4842 * These MULT and MULTU instructions implemented in for example the
4843 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4844 * architectures are special three-operand variants with the syntax
4846 * MULT[U][1] rd, rs, rt
4848 * such that
4850 * (rd, LO, HI) <- rs * rt
4852 * where the low-order 32-bits of the result is placed into both the
4853 * GPR rd and the special register LO. The high-order 32-bits of the
4854 * result is placed into the special register HI.
4856 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4857 * which is the zero register that always reads as 0.
4859 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4860 int rd, int rs, int rt)
4862 TCGv t0 = tcg_temp_new();
4863 TCGv t1 = tcg_temp_new();
4864 int acc = 0;
4866 gen_load_gpr(t0, rs);
4867 gen_load_gpr(t1, rt);
4869 switch (opc) {
4870 case TX79_MMI_MULT1:
4871 acc = 1;
4872 /* Fall through */
4873 case OPC_MULT:
4875 TCGv_i32 t2 = tcg_temp_new_i32();
4876 TCGv_i32 t3 = tcg_temp_new_i32();
4877 tcg_gen_trunc_tl_i32(t2, t0);
4878 tcg_gen_trunc_tl_i32(t3, t1);
4879 tcg_gen_muls2_i32(t2, t3, t2, t3);
4880 if (rd) {
4881 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4883 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4884 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4885 tcg_temp_free_i32(t2);
4886 tcg_temp_free_i32(t3);
4888 break;
4889 case TX79_MMI_MULTU1:
4890 acc = 1;
4891 /* Fall through */
4892 case OPC_MULTU:
4894 TCGv_i32 t2 = tcg_temp_new_i32();
4895 TCGv_i32 t3 = tcg_temp_new_i32();
4896 tcg_gen_trunc_tl_i32(t2, t0);
4897 tcg_gen_trunc_tl_i32(t3, t1);
4898 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4899 if (rd) {
4900 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4902 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4903 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4904 tcg_temp_free_i32(t2);
4905 tcg_temp_free_i32(t3);
4907 break;
4908 default:
4909 MIPS_INVAL("mul TXx9");
4910 generate_exception_end(ctx, EXCP_RI);
4911 goto out;
4914 out:
4915 tcg_temp_free(t0);
4916 tcg_temp_free(t1);
4919 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4920 int rd, int rs, int rt)
4922 TCGv t0 = tcg_temp_new();
4923 TCGv t1 = tcg_temp_new();
4925 gen_load_gpr(t0, rs);
4926 gen_load_gpr(t1, rt);
4928 switch (opc) {
4929 case OPC_VR54XX_MULS:
4930 gen_helper_muls(t0, cpu_env, t0, t1);
4931 break;
4932 case OPC_VR54XX_MULSU:
4933 gen_helper_mulsu(t0, cpu_env, t0, t1);
4934 break;
4935 case OPC_VR54XX_MACC:
4936 gen_helper_macc(t0, cpu_env, t0, t1);
4937 break;
4938 case OPC_VR54XX_MACCU:
4939 gen_helper_maccu(t0, cpu_env, t0, t1);
4940 break;
4941 case OPC_VR54XX_MSAC:
4942 gen_helper_msac(t0, cpu_env, t0, t1);
4943 break;
4944 case OPC_VR54XX_MSACU:
4945 gen_helper_msacu(t0, cpu_env, t0, t1);
4946 break;
4947 case OPC_VR54XX_MULHI:
4948 gen_helper_mulhi(t0, cpu_env, t0, t1);
4949 break;
4950 case OPC_VR54XX_MULHIU:
4951 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4952 break;
4953 case OPC_VR54XX_MULSHI:
4954 gen_helper_mulshi(t0, cpu_env, t0, t1);
4955 break;
4956 case OPC_VR54XX_MULSHIU:
4957 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4958 break;
4959 case OPC_VR54XX_MACCHI:
4960 gen_helper_macchi(t0, cpu_env, t0, t1);
4961 break;
4962 case OPC_VR54XX_MACCHIU:
4963 gen_helper_macchiu(t0, cpu_env, t0, t1);
4964 break;
4965 case OPC_VR54XX_MSACHI:
4966 gen_helper_msachi(t0, cpu_env, t0, t1);
4967 break;
4968 case OPC_VR54XX_MSACHIU:
4969 gen_helper_msachiu(t0, cpu_env, t0, t1);
4970 break;
4971 default:
4972 MIPS_INVAL("mul vr54xx");
4973 generate_exception_end(ctx, EXCP_RI);
4974 goto out;
4976 gen_store_gpr(t0, rd);
4978 out:
4979 tcg_temp_free(t0);
4980 tcg_temp_free(t1);
4983 static void gen_cl (DisasContext *ctx, uint32_t opc,
4984 int rd, int rs)
4986 TCGv t0;
4988 if (rd == 0) {
4989 /* Treat as NOP. */
4990 return;
4992 t0 = cpu_gpr[rd];
4993 gen_load_gpr(t0, rs);
4995 switch (opc) {
4996 case OPC_CLO:
4997 case R6_OPC_CLO:
4998 #if defined(TARGET_MIPS64)
4999 case OPC_DCLO:
5000 case R6_OPC_DCLO:
5001 #endif
5002 tcg_gen_not_tl(t0, t0);
5003 break;
5006 switch (opc) {
5007 case OPC_CLO:
5008 case R6_OPC_CLO:
5009 case OPC_CLZ:
5010 case R6_OPC_CLZ:
5011 tcg_gen_ext32u_tl(t0, t0);
5012 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5013 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5014 break;
5015 #if defined(TARGET_MIPS64)
5016 case OPC_DCLO:
5017 case R6_OPC_DCLO:
5018 case OPC_DCLZ:
5019 case R6_OPC_DCLZ:
5020 tcg_gen_clzi_i64(t0, t0, 64);
5021 break;
5022 #endif
5026 /* Godson integer instructions */
5027 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5028 int rd, int rs, int rt)
5030 TCGv t0, t1;
5032 if (rd == 0) {
5033 /* Treat as NOP. */
5034 return;
5037 switch (opc) {
5038 case OPC_MULT_G_2E:
5039 case OPC_MULT_G_2F:
5040 case OPC_MULTU_G_2E:
5041 case OPC_MULTU_G_2F:
5042 #if defined(TARGET_MIPS64)
5043 case OPC_DMULT_G_2E:
5044 case OPC_DMULT_G_2F:
5045 case OPC_DMULTU_G_2E:
5046 case OPC_DMULTU_G_2F:
5047 #endif
5048 t0 = tcg_temp_new();
5049 t1 = tcg_temp_new();
5050 break;
5051 default:
5052 t0 = tcg_temp_local_new();
5053 t1 = tcg_temp_local_new();
5054 break;
5057 gen_load_gpr(t0, rs);
5058 gen_load_gpr(t1, rt);
5060 switch (opc) {
5061 case OPC_MULT_G_2E:
5062 case OPC_MULT_G_2F:
5063 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5064 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5065 break;
5066 case OPC_MULTU_G_2E:
5067 case OPC_MULTU_G_2F:
5068 tcg_gen_ext32u_tl(t0, t0);
5069 tcg_gen_ext32u_tl(t1, t1);
5070 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5071 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5072 break;
5073 case OPC_DIV_G_2E:
5074 case OPC_DIV_G_2F:
5076 TCGLabel *l1 = gen_new_label();
5077 TCGLabel *l2 = gen_new_label();
5078 TCGLabel *l3 = gen_new_label();
5079 tcg_gen_ext32s_tl(t0, t0);
5080 tcg_gen_ext32s_tl(t1, t1);
5081 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5082 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5083 tcg_gen_br(l3);
5084 gen_set_label(l1);
5085 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5086 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5087 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5088 tcg_gen_br(l3);
5089 gen_set_label(l2);
5090 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5091 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5092 gen_set_label(l3);
5094 break;
5095 case OPC_DIVU_G_2E:
5096 case OPC_DIVU_G_2F:
5098 TCGLabel *l1 = gen_new_label();
5099 TCGLabel *l2 = gen_new_label();
5100 tcg_gen_ext32u_tl(t0, t0);
5101 tcg_gen_ext32u_tl(t1, t1);
5102 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5103 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5104 tcg_gen_br(l2);
5105 gen_set_label(l1);
5106 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5107 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5108 gen_set_label(l2);
5110 break;
5111 case OPC_MOD_G_2E:
5112 case OPC_MOD_G_2F:
5114 TCGLabel *l1 = gen_new_label();
5115 TCGLabel *l2 = gen_new_label();
5116 TCGLabel *l3 = gen_new_label();
5117 tcg_gen_ext32u_tl(t0, t0);
5118 tcg_gen_ext32u_tl(t1, t1);
5119 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5120 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5121 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5122 gen_set_label(l1);
5123 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5124 tcg_gen_br(l3);
5125 gen_set_label(l2);
5126 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5127 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5128 gen_set_label(l3);
5130 break;
5131 case OPC_MODU_G_2E:
5132 case OPC_MODU_G_2F:
5134 TCGLabel *l1 = gen_new_label();
5135 TCGLabel *l2 = gen_new_label();
5136 tcg_gen_ext32u_tl(t0, t0);
5137 tcg_gen_ext32u_tl(t1, t1);
5138 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5139 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5140 tcg_gen_br(l2);
5141 gen_set_label(l1);
5142 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5143 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5144 gen_set_label(l2);
5146 break;
5147 #if defined(TARGET_MIPS64)
5148 case OPC_DMULT_G_2E:
5149 case OPC_DMULT_G_2F:
5150 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5151 break;
5152 case OPC_DMULTU_G_2E:
5153 case OPC_DMULTU_G_2F:
5154 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5155 break;
5156 case OPC_DDIV_G_2E:
5157 case OPC_DDIV_G_2F:
5159 TCGLabel *l1 = gen_new_label();
5160 TCGLabel *l2 = gen_new_label();
5161 TCGLabel *l3 = gen_new_label();
5162 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5163 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5164 tcg_gen_br(l3);
5165 gen_set_label(l1);
5166 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5167 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5168 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5169 tcg_gen_br(l3);
5170 gen_set_label(l2);
5171 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5172 gen_set_label(l3);
5174 break;
5175 case OPC_DDIVU_G_2E:
5176 case OPC_DDIVU_G_2F:
5178 TCGLabel *l1 = gen_new_label();
5179 TCGLabel *l2 = gen_new_label();
5180 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5181 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5182 tcg_gen_br(l2);
5183 gen_set_label(l1);
5184 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5185 gen_set_label(l2);
5187 break;
5188 case OPC_DMOD_G_2E:
5189 case OPC_DMOD_G_2F:
5191 TCGLabel *l1 = gen_new_label();
5192 TCGLabel *l2 = gen_new_label();
5193 TCGLabel *l3 = gen_new_label();
5194 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5195 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5196 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5197 gen_set_label(l1);
5198 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5199 tcg_gen_br(l3);
5200 gen_set_label(l2);
5201 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5202 gen_set_label(l3);
5204 break;
5205 case OPC_DMODU_G_2E:
5206 case OPC_DMODU_G_2F:
5208 TCGLabel *l1 = gen_new_label();
5209 TCGLabel *l2 = gen_new_label();
5210 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5211 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5212 tcg_gen_br(l2);
5213 gen_set_label(l1);
5214 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5215 gen_set_label(l2);
5217 break;
5218 #endif
5221 tcg_temp_free(t0);
5222 tcg_temp_free(t1);
5225 /* Loongson multimedia instructions */
5226 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5228 uint32_t opc, shift_max;
5229 TCGv_i64 t0, t1;
5231 opc = MASK_LMI(ctx->opcode);
5232 switch (opc) {
5233 case OPC_ADD_CP2:
5234 case OPC_SUB_CP2:
5235 case OPC_DADD_CP2:
5236 case OPC_DSUB_CP2:
5237 t0 = tcg_temp_local_new_i64();
5238 t1 = tcg_temp_local_new_i64();
5239 break;
5240 default:
5241 t0 = tcg_temp_new_i64();
5242 t1 = tcg_temp_new_i64();
5243 break;
5246 check_cp1_enabled(ctx);
5247 gen_load_fpr64(ctx, t0, rs);
5248 gen_load_fpr64(ctx, t1, rt);
5250 #define LMI_HELPER(UP, LO) \
5251 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5252 #define LMI_HELPER_1(UP, LO) \
5253 case OPC_##UP: gen_helper_##LO(t0, t0); break
5254 #define LMI_DIRECT(UP, LO, OP) \
5255 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5257 switch (opc) {
5258 LMI_HELPER(PADDSH, paddsh);
5259 LMI_HELPER(PADDUSH, paddush);
5260 LMI_HELPER(PADDH, paddh);
5261 LMI_HELPER(PADDW, paddw);
5262 LMI_HELPER(PADDSB, paddsb);
5263 LMI_HELPER(PADDUSB, paddusb);
5264 LMI_HELPER(PADDB, paddb);
5266 LMI_HELPER(PSUBSH, psubsh);
5267 LMI_HELPER(PSUBUSH, psubush);
5268 LMI_HELPER(PSUBH, psubh);
5269 LMI_HELPER(PSUBW, psubw);
5270 LMI_HELPER(PSUBSB, psubsb);
5271 LMI_HELPER(PSUBUSB, psubusb);
5272 LMI_HELPER(PSUBB, psubb);
5274 LMI_HELPER(PSHUFH, pshufh);
5275 LMI_HELPER(PACKSSWH, packsswh);
5276 LMI_HELPER(PACKSSHB, packsshb);
5277 LMI_HELPER(PACKUSHB, packushb);
5279 LMI_HELPER(PUNPCKLHW, punpcklhw);
5280 LMI_HELPER(PUNPCKHHW, punpckhhw);
5281 LMI_HELPER(PUNPCKLBH, punpcklbh);
5282 LMI_HELPER(PUNPCKHBH, punpckhbh);
5283 LMI_HELPER(PUNPCKLWD, punpcklwd);
5284 LMI_HELPER(PUNPCKHWD, punpckhwd);
5286 LMI_HELPER(PAVGH, pavgh);
5287 LMI_HELPER(PAVGB, pavgb);
5288 LMI_HELPER(PMAXSH, pmaxsh);
5289 LMI_HELPER(PMINSH, pminsh);
5290 LMI_HELPER(PMAXUB, pmaxub);
5291 LMI_HELPER(PMINUB, pminub);
5293 LMI_HELPER(PCMPEQW, pcmpeqw);
5294 LMI_HELPER(PCMPGTW, pcmpgtw);
5295 LMI_HELPER(PCMPEQH, pcmpeqh);
5296 LMI_HELPER(PCMPGTH, pcmpgth);
5297 LMI_HELPER(PCMPEQB, pcmpeqb);
5298 LMI_HELPER(PCMPGTB, pcmpgtb);
5300 LMI_HELPER(PSLLW, psllw);
5301 LMI_HELPER(PSLLH, psllh);
5302 LMI_HELPER(PSRLW, psrlw);
5303 LMI_HELPER(PSRLH, psrlh);
5304 LMI_HELPER(PSRAW, psraw);
5305 LMI_HELPER(PSRAH, psrah);
5307 LMI_HELPER(PMULLH, pmullh);
5308 LMI_HELPER(PMULHH, pmulhh);
5309 LMI_HELPER(PMULHUH, pmulhuh);
5310 LMI_HELPER(PMADDHW, pmaddhw);
5312 LMI_HELPER(PASUBUB, pasubub);
5313 LMI_HELPER_1(BIADD, biadd);
5314 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5316 LMI_DIRECT(PADDD, paddd, add);
5317 LMI_DIRECT(PSUBD, psubd, sub);
5318 LMI_DIRECT(XOR_CP2, xor, xor);
5319 LMI_DIRECT(NOR_CP2, nor, nor);
5320 LMI_DIRECT(AND_CP2, and, and);
5321 LMI_DIRECT(OR_CP2, or, or);
5323 case OPC_PANDN:
5324 tcg_gen_andc_i64(t0, t1, t0);
5325 break;
5327 case OPC_PINSRH_0:
5328 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5329 break;
5330 case OPC_PINSRH_1:
5331 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5332 break;
5333 case OPC_PINSRH_2:
5334 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5335 break;
5336 case OPC_PINSRH_3:
5337 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5338 break;
5340 case OPC_PEXTRH:
5341 tcg_gen_andi_i64(t1, t1, 3);
5342 tcg_gen_shli_i64(t1, t1, 4);
5343 tcg_gen_shr_i64(t0, t0, t1);
5344 tcg_gen_ext16u_i64(t0, t0);
5345 break;
5347 case OPC_ADDU_CP2:
5348 tcg_gen_add_i64(t0, t0, t1);
5349 tcg_gen_ext32s_i64(t0, t0);
5350 break;
5351 case OPC_SUBU_CP2:
5352 tcg_gen_sub_i64(t0, t0, t1);
5353 tcg_gen_ext32s_i64(t0, t0);
5354 break;
5356 case OPC_SLL_CP2:
5357 shift_max = 32;
5358 goto do_shift;
5359 case OPC_SRL_CP2:
5360 shift_max = 32;
5361 goto do_shift;
5362 case OPC_SRA_CP2:
5363 shift_max = 32;
5364 goto do_shift;
5365 case OPC_DSLL_CP2:
5366 shift_max = 64;
5367 goto do_shift;
5368 case OPC_DSRL_CP2:
5369 shift_max = 64;
5370 goto do_shift;
5371 case OPC_DSRA_CP2:
5372 shift_max = 64;
5373 goto do_shift;
5374 do_shift:
5375 /* Make sure shift count isn't TCG undefined behaviour. */
5376 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5378 switch (opc) {
5379 case OPC_SLL_CP2:
5380 case OPC_DSLL_CP2:
5381 tcg_gen_shl_i64(t0, t0, t1);
5382 break;
5383 case OPC_SRA_CP2:
5384 case OPC_DSRA_CP2:
5385 /* Since SRA is UndefinedResult without sign-extended inputs,
5386 we can treat SRA and DSRA the same. */
5387 tcg_gen_sar_i64(t0, t0, t1);
5388 break;
5389 case OPC_SRL_CP2:
5390 /* We want to shift in zeros for SRL; zero-extend first. */
5391 tcg_gen_ext32u_i64(t0, t0);
5392 /* FALLTHRU */
5393 case OPC_DSRL_CP2:
5394 tcg_gen_shr_i64(t0, t0, t1);
5395 break;
5398 if (shift_max == 32) {
5399 tcg_gen_ext32s_i64(t0, t0);
5402 /* Shifts larger than MAX produce zero. */
5403 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5404 tcg_gen_neg_i64(t1, t1);
5405 tcg_gen_and_i64(t0, t0, t1);
5406 break;
5408 case OPC_ADD_CP2:
5409 case OPC_DADD_CP2:
5411 TCGv_i64 t2 = tcg_temp_new_i64();
5412 TCGLabel *lab = gen_new_label();
5414 tcg_gen_mov_i64(t2, t0);
5415 tcg_gen_add_i64(t0, t1, t2);
5416 if (opc == OPC_ADD_CP2) {
5417 tcg_gen_ext32s_i64(t0, t0);
5419 tcg_gen_xor_i64(t1, t1, t2);
5420 tcg_gen_xor_i64(t2, t2, t0);
5421 tcg_gen_andc_i64(t1, t2, t1);
5422 tcg_temp_free_i64(t2);
5423 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5424 generate_exception(ctx, EXCP_OVERFLOW);
5425 gen_set_label(lab);
5426 break;
5429 case OPC_SUB_CP2:
5430 case OPC_DSUB_CP2:
5432 TCGv_i64 t2 = tcg_temp_new_i64();
5433 TCGLabel *lab = gen_new_label();
5435 tcg_gen_mov_i64(t2, t0);
5436 tcg_gen_sub_i64(t0, t1, t2);
5437 if (opc == OPC_SUB_CP2) {
5438 tcg_gen_ext32s_i64(t0, t0);
5440 tcg_gen_xor_i64(t1, t1, t2);
5441 tcg_gen_xor_i64(t2, t2, t0);
5442 tcg_gen_and_i64(t1, t1, t2);
5443 tcg_temp_free_i64(t2);
5444 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5445 generate_exception(ctx, EXCP_OVERFLOW);
5446 gen_set_label(lab);
5447 break;
5450 case OPC_PMULUW:
5451 tcg_gen_ext32u_i64(t0, t0);
5452 tcg_gen_ext32u_i64(t1, t1);
5453 tcg_gen_mul_i64(t0, t0, t1);
5454 break;
5456 case OPC_SEQU_CP2:
5457 case OPC_SEQ_CP2:
5458 case OPC_SLTU_CP2:
5459 case OPC_SLT_CP2:
5460 case OPC_SLEU_CP2:
5461 case OPC_SLE_CP2:
5462 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5463 FD field is the CC field? */
5464 default:
5465 MIPS_INVAL("loongson_cp2");
5466 generate_exception_end(ctx, EXCP_RI);
5467 return;
5470 #undef LMI_HELPER
5471 #undef LMI_DIRECT
5473 gen_store_fpr64(ctx, t0, rd);
5475 tcg_temp_free_i64(t0);
5476 tcg_temp_free_i64(t1);
5479 /* Traps */
5480 static void gen_trap (DisasContext *ctx, uint32_t opc,
5481 int rs, int rt, int16_t imm)
5483 int cond;
5484 TCGv t0 = tcg_temp_new();
5485 TCGv t1 = tcg_temp_new();
5487 cond = 0;
5488 /* Load needed operands */
5489 switch (opc) {
5490 case OPC_TEQ:
5491 case OPC_TGE:
5492 case OPC_TGEU:
5493 case OPC_TLT:
5494 case OPC_TLTU:
5495 case OPC_TNE:
5496 /* Compare two registers */
5497 if (rs != rt) {
5498 gen_load_gpr(t0, rs);
5499 gen_load_gpr(t1, rt);
5500 cond = 1;
5502 break;
5503 case OPC_TEQI:
5504 case OPC_TGEI:
5505 case OPC_TGEIU:
5506 case OPC_TLTI:
5507 case OPC_TLTIU:
5508 case OPC_TNEI:
5509 /* Compare register to immediate */
5510 if (rs != 0 || imm != 0) {
5511 gen_load_gpr(t0, rs);
5512 tcg_gen_movi_tl(t1, (int32_t)imm);
5513 cond = 1;
5515 break;
5517 if (cond == 0) {
5518 switch (opc) {
5519 case OPC_TEQ: /* rs == rs */
5520 case OPC_TEQI: /* r0 == 0 */
5521 case OPC_TGE: /* rs >= rs */
5522 case OPC_TGEI: /* r0 >= 0 */
5523 case OPC_TGEU: /* rs >= rs unsigned */
5524 case OPC_TGEIU: /* r0 >= 0 unsigned */
5525 /* Always trap */
5526 generate_exception_end(ctx, EXCP_TRAP);
5527 break;
5528 case OPC_TLT: /* rs < rs */
5529 case OPC_TLTI: /* r0 < 0 */
5530 case OPC_TLTU: /* rs < rs unsigned */
5531 case OPC_TLTIU: /* r0 < 0 unsigned */
5532 case OPC_TNE: /* rs != rs */
5533 case OPC_TNEI: /* r0 != 0 */
5534 /* Never trap: treat as NOP. */
5535 break;
5537 } else {
5538 TCGLabel *l1 = gen_new_label();
5540 switch (opc) {
5541 case OPC_TEQ:
5542 case OPC_TEQI:
5543 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5544 break;
5545 case OPC_TGE:
5546 case OPC_TGEI:
5547 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5548 break;
5549 case OPC_TGEU:
5550 case OPC_TGEIU:
5551 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5552 break;
5553 case OPC_TLT:
5554 case OPC_TLTI:
5555 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5556 break;
5557 case OPC_TLTU:
5558 case OPC_TLTIU:
5559 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5560 break;
5561 case OPC_TNE:
5562 case OPC_TNEI:
5563 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5564 break;
5566 generate_exception(ctx, EXCP_TRAP);
5567 gen_set_label(l1);
5569 tcg_temp_free(t0);
5570 tcg_temp_free(t1);
5573 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5575 if (unlikely(ctx->base.singlestep_enabled)) {
5576 return false;
5579 #ifndef CONFIG_USER_ONLY
5580 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5581 #else
5582 return true;
5583 #endif
5586 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5588 if (use_goto_tb(ctx, dest)) {
5589 tcg_gen_goto_tb(n);
5590 gen_save_pc(dest);
5591 tcg_gen_exit_tb(ctx->base.tb, n);
5592 } else {
5593 gen_save_pc(dest);
5594 if (ctx->base.singlestep_enabled) {
5595 save_cpu_state(ctx, 0);
5596 gen_helper_raise_exception_debug(cpu_env);
5598 tcg_gen_lookup_and_goto_ptr();
5602 /* Branches (before delay slot) */
5603 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5604 int insn_bytes,
5605 int rs, int rt, int32_t offset,
5606 int delayslot_size)
5608 target_ulong btgt = -1;
5609 int blink = 0;
5610 int bcond_compute = 0;
5611 TCGv t0 = tcg_temp_new();
5612 TCGv t1 = tcg_temp_new();
5614 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5615 #ifdef MIPS_DEBUG_DISAS
5616 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5617 TARGET_FMT_lx "\n", ctx->base.pc_next);
5618 #endif
5619 generate_exception_end(ctx, EXCP_RI);
5620 goto out;
5623 /* Load needed operands */
5624 switch (opc) {
5625 case OPC_BEQ:
5626 case OPC_BEQL:
5627 case OPC_BNE:
5628 case OPC_BNEL:
5629 /* Compare two registers */
5630 if (rs != rt) {
5631 gen_load_gpr(t0, rs);
5632 gen_load_gpr(t1, rt);
5633 bcond_compute = 1;
5635 btgt = ctx->base.pc_next + insn_bytes + offset;
5636 break;
5637 case OPC_BGEZ:
5638 case OPC_BGEZAL:
5639 case OPC_BGEZALL:
5640 case OPC_BGEZL:
5641 case OPC_BGTZ:
5642 case OPC_BGTZL:
5643 case OPC_BLEZ:
5644 case OPC_BLEZL:
5645 case OPC_BLTZ:
5646 case OPC_BLTZAL:
5647 case OPC_BLTZALL:
5648 case OPC_BLTZL:
5649 /* Compare to zero */
5650 if (rs != 0) {
5651 gen_load_gpr(t0, rs);
5652 bcond_compute = 1;
5654 btgt = ctx->base.pc_next + insn_bytes + offset;
5655 break;
5656 case OPC_BPOSGE32:
5657 #if defined(TARGET_MIPS64)
5658 case OPC_BPOSGE64:
5659 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5660 #else
5661 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5662 #endif
5663 bcond_compute = 1;
5664 btgt = ctx->base.pc_next + insn_bytes + offset;
5665 break;
5666 case OPC_J:
5667 case OPC_JAL:
5668 case OPC_JALX:
5669 /* Jump to immediate */
5670 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5671 (uint32_t)offset;
5672 break;
5673 case OPC_JR:
5674 case OPC_JALR:
5675 /* Jump to register */
5676 if (offset != 0 && offset != 16) {
5677 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5678 others are reserved. */
5679 MIPS_INVAL("jump hint");
5680 generate_exception_end(ctx, EXCP_RI);
5681 goto out;
5683 gen_load_gpr(btarget, rs);
5684 break;
5685 default:
5686 MIPS_INVAL("branch/jump");
5687 generate_exception_end(ctx, EXCP_RI);
5688 goto out;
5690 if (bcond_compute == 0) {
5691 /* No condition to be computed */
5692 switch (opc) {
5693 case OPC_BEQ: /* rx == rx */
5694 case OPC_BEQL: /* rx == rx likely */
5695 case OPC_BGEZ: /* 0 >= 0 */
5696 case OPC_BGEZL: /* 0 >= 0 likely */
5697 case OPC_BLEZ: /* 0 <= 0 */
5698 case OPC_BLEZL: /* 0 <= 0 likely */
5699 /* Always take */
5700 ctx->hflags |= MIPS_HFLAG_B;
5701 break;
5702 case OPC_BGEZAL: /* 0 >= 0 */
5703 case OPC_BGEZALL: /* 0 >= 0 likely */
5704 /* Always take and link */
5705 blink = 31;
5706 ctx->hflags |= MIPS_HFLAG_B;
5707 break;
5708 case OPC_BNE: /* rx != rx */
5709 case OPC_BGTZ: /* 0 > 0 */
5710 case OPC_BLTZ: /* 0 < 0 */
5711 /* Treat as NOP. */
5712 goto out;
5713 case OPC_BLTZAL: /* 0 < 0 */
5714 /* Handle as an unconditional branch to get correct delay
5715 slot checking. */
5716 blink = 31;
5717 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5718 ctx->hflags |= MIPS_HFLAG_B;
5719 break;
5720 case OPC_BLTZALL: /* 0 < 0 likely */
5721 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5722 /* Skip the instruction in the delay slot */
5723 ctx->base.pc_next += 4;
5724 goto out;
5725 case OPC_BNEL: /* rx != rx likely */
5726 case OPC_BGTZL: /* 0 > 0 likely */
5727 case OPC_BLTZL: /* 0 < 0 likely */
5728 /* Skip the instruction in the delay slot */
5729 ctx->base.pc_next += 4;
5730 goto out;
5731 case OPC_J:
5732 ctx->hflags |= MIPS_HFLAG_B;
5733 break;
5734 case OPC_JALX:
5735 ctx->hflags |= MIPS_HFLAG_BX;
5736 /* Fallthrough */
5737 case OPC_JAL:
5738 blink = 31;
5739 ctx->hflags |= MIPS_HFLAG_B;
5740 break;
5741 case OPC_JR:
5742 ctx->hflags |= MIPS_HFLAG_BR;
5743 break;
5744 case OPC_JALR:
5745 blink = rt;
5746 ctx->hflags |= MIPS_HFLAG_BR;
5747 break;
5748 default:
5749 MIPS_INVAL("branch/jump");
5750 generate_exception_end(ctx, EXCP_RI);
5751 goto out;
5753 } else {
5754 switch (opc) {
5755 case OPC_BEQ:
5756 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5757 goto not_likely;
5758 case OPC_BEQL:
5759 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5760 goto likely;
5761 case OPC_BNE:
5762 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5763 goto not_likely;
5764 case OPC_BNEL:
5765 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5766 goto likely;
5767 case OPC_BGEZ:
5768 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5769 goto not_likely;
5770 case OPC_BGEZL:
5771 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5772 goto likely;
5773 case OPC_BGEZAL:
5774 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5775 blink = 31;
5776 goto not_likely;
5777 case OPC_BGEZALL:
5778 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5779 blink = 31;
5780 goto likely;
5781 case OPC_BGTZ:
5782 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5783 goto not_likely;
5784 case OPC_BGTZL:
5785 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5786 goto likely;
5787 case OPC_BLEZ:
5788 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5789 goto not_likely;
5790 case OPC_BLEZL:
5791 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5792 goto likely;
5793 case OPC_BLTZ:
5794 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5795 goto not_likely;
5796 case OPC_BLTZL:
5797 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5798 goto likely;
5799 case OPC_BPOSGE32:
5800 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5801 goto not_likely;
5802 #if defined(TARGET_MIPS64)
5803 case OPC_BPOSGE64:
5804 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5805 goto not_likely;
5806 #endif
5807 case OPC_BLTZAL:
5808 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5809 blink = 31;
5810 not_likely:
5811 ctx->hflags |= MIPS_HFLAG_BC;
5812 break;
5813 case OPC_BLTZALL:
5814 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5815 blink = 31;
5816 likely:
5817 ctx->hflags |= MIPS_HFLAG_BL;
5818 break;
5819 default:
5820 MIPS_INVAL("conditional branch/jump");
5821 generate_exception_end(ctx, EXCP_RI);
5822 goto out;
5826 ctx->btarget = btgt;
5828 switch (delayslot_size) {
5829 case 2:
5830 ctx->hflags |= MIPS_HFLAG_BDS16;
5831 break;
5832 case 4:
5833 ctx->hflags |= MIPS_HFLAG_BDS32;
5834 break;
5837 if (blink > 0) {
5838 int post_delay = insn_bytes + delayslot_size;
5839 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5841 tcg_gen_movi_tl(cpu_gpr[blink],
5842 ctx->base.pc_next + post_delay + lowbit);
5845 out:
5846 if (insn_bytes == 2)
5847 ctx->hflags |= MIPS_HFLAG_B16;
5848 tcg_temp_free(t0);
5849 tcg_temp_free(t1);
5853 /* nanoMIPS Branches */
5854 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5855 int insn_bytes,
5856 int rs, int rt, int32_t offset)
5858 target_ulong btgt = -1;
5859 int bcond_compute = 0;
5860 TCGv t0 = tcg_temp_new();
5861 TCGv t1 = tcg_temp_new();
5863 /* Load needed operands */
5864 switch (opc) {
5865 case OPC_BEQ:
5866 case OPC_BNE:
5867 /* Compare two registers */
5868 if (rs != rt) {
5869 gen_load_gpr(t0, rs);
5870 gen_load_gpr(t1, rt);
5871 bcond_compute = 1;
5873 btgt = ctx->base.pc_next + insn_bytes + offset;
5874 break;
5875 case OPC_BGEZAL:
5876 /* Compare to zero */
5877 if (rs != 0) {
5878 gen_load_gpr(t0, rs);
5879 bcond_compute = 1;
5881 btgt = ctx->base.pc_next + insn_bytes + offset;
5882 break;
5883 case OPC_BPOSGE32:
5884 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5885 bcond_compute = 1;
5886 btgt = ctx->base.pc_next + insn_bytes + offset;
5887 break;
5888 case OPC_JR:
5889 case OPC_JALR:
5890 /* Jump to register */
5891 if (offset != 0 && offset != 16) {
5892 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5893 others are reserved. */
5894 MIPS_INVAL("jump hint");
5895 generate_exception_end(ctx, EXCP_RI);
5896 goto out;
5898 gen_load_gpr(btarget, rs);
5899 break;
5900 default:
5901 MIPS_INVAL("branch/jump");
5902 generate_exception_end(ctx, EXCP_RI);
5903 goto out;
5905 if (bcond_compute == 0) {
5906 /* No condition to be computed */
5907 switch (opc) {
5908 case OPC_BEQ: /* rx == rx */
5909 /* Always take */
5910 ctx->hflags |= MIPS_HFLAG_B;
5911 break;
5912 case OPC_BGEZAL: /* 0 >= 0 */
5913 /* Always take and link */
5914 tcg_gen_movi_tl(cpu_gpr[31],
5915 ctx->base.pc_next + insn_bytes);
5916 ctx->hflags |= MIPS_HFLAG_B;
5917 break;
5918 case OPC_BNE: /* rx != rx */
5919 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5920 /* Skip the instruction in the delay slot */
5921 ctx->base.pc_next += 4;
5922 goto out;
5923 case OPC_JR:
5924 ctx->hflags |= MIPS_HFLAG_BR;
5925 break;
5926 case OPC_JALR:
5927 if (rt > 0) {
5928 tcg_gen_movi_tl(cpu_gpr[rt],
5929 ctx->base.pc_next + insn_bytes);
5931 ctx->hflags |= MIPS_HFLAG_BR;
5932 break;
5933 default:
5934 MIPS_INVAL("branch/jump");
5935 generate_exception_end(ctx, EXCP_RI);
5936 goto out;
5938 } else {
5939 switch (opc) {
5940 case OPC_BEQ:
5941 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5942 goto not_likely;
5943 case OPC_BNE:
5944 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5945 goto not_likely;
5946 case OPC_BGEZAL:
5947 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5948 tcg_gen_movi_tl(cpu_gpr[31],
5949 ctx->base.pc_next + insn_bytes);
5950 goto not_likely;
5951 case OPC_BPOSGE32:
5952 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5953 not_likely:
5954 ctx->hflags |= MIPS_HFLAG_BC;
5955 break;
5956 default:
5957 MIPS_INVAL("conditional branch/jump");
5958 generate_exception_end(ctx, EXCP_RI);
5959 goto out;
5963 ctx->btarget = btgt;
5965 out:
5966 if (insn_bytes == 2) {
5967 ctx->hflags |= MIPS_HFLAG_B16;
5969 tcg_temp_free(t0);
5970 tcg_temp_free(t1);
5974 /* special3 bitfield operations */
5975 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5976 int rs, int lsb, int msb)
5978 TCGv t0 = tcg_temp_new();
5979 TCGv t1 = tcg_temp_new();
5981 gen_load_gpr(t1, rs);
5982 switch (opc) {
5983 case OPC_EXT:
5984 if (lsb + msb > 31) {
5985 goto fail;
5987 if (msb != 31) {
5988 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5989 } else {
5990 /* The two checks together imply that lsb == 0,
5991 so this is a simple sign-extension. */
5992 tcg_gen_ext32s_tl(t0, t1);
5994 break;
5995 #if defined(TARGET_MIPS64)
5996 case OPC_DEXTU:
5997 lsb += 32;
5998 goto do_dext;
5999 case OPC_DEXTM:
6000 msb += 32;
6001 goto do_dext;
6002 case OPC_DEXT:
6003 do_dext:
6004 if (lsb + msb > 63) {
6005 goto fail;
6007 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6008 break;
6009 #endif
6010 case OPC_INS:
6011 if (lsb > msb) {
6012 goto fail;
6014 gen_load_gpr(t0, rt);
6015 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6016 tcg_gen_ext32s_tl(t0, t0);
6017 break;
6018 #if defined(TARGET_MIPS64)
6019 case OPC_DINSU:
6020 lsb += 32;
6021 /* FALLTHRU */
6022 case OPC_DINSM:
6023 msb += 32;
6024 /* FALLTHRU */
6025 case OPC_DINS:
6026 if (lsb > msb) {
6027 goto fail;
6029 gen_load_gpr(t0, rt);
6030 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6031 break;
6032 #endif
6033 default:
6034 fail:
6035 MIPS_INVAL("bitops");
6036 generate_exception_end(ctx, EXCP_RI);
6037 tcg_temp_free(t0);
6038 tcg_temp_free(t1);
6039 return;
6041 gen_store_gpr(t0, rt);
6042 tcg_temp_free(t0);
6043 tcg_temp_free(t1);
6046 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6048 TCGv t0;
6050 if (rd == 0) {
6051 /* If no destination, treat it as a NOP. */
6052 return;
6055 t0 = tcg_temp_new();
6056 gen_load_gpr(t0, rt);
6057 switch (op2) {
6058 case OPC_WSBH:
6060 TCGv t1 = tcg_temp_new();
6061 TCGv t2 = tcg_const_tl(0x00FF00FF);
6063 tcg_gen_shri_tl(t1, t0, 8);
6064 tcg_gen_and_tl(t1, t1, t2);
6065 tcg_gen_and_tl(t0, t0, t2);
6066 tcg_gen_shli_tl(t0, t0, 8);
6067 tcg_gen_or_tl(t0, t0, t1);
6068 tcg_temp_free(t2);
6069 tcg_temp_free(t1);
6070 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6072 break;
6073 case OPC_SEB:
6074 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6075 break;
6076 case OPC_SEH:
6077 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6078 break;
6079 #if defined(TARGET_MIPS64)
6080 case OPC_DSBH:
6082 TCGv t1 = tcg_temp_new();
6083 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6085 tcg_gen_shri_tl(t1, t0, 8);
6086 tcg_gen_and_tl(t1, t1, t2);
6087 tcg_gen_and_tl(t0, t0, t2);
6088 tcg_gen_shli_tl(t0, t0, 8);
6089 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6090 tcg_temp_free(t2);
6091 tcg_temp_free(t1);
6093 break;
6094 case OPC_DSHD:
6096 TCGv t1 = tcg_temp_new();
6097 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6099 tcg_gen_shri_tl(t1, t0, 16);
6100 tcg_gen_and_tl(t1, t1, t2);
6101 tcg_gen_and_tl(t0, t0, t2);
6102 tcg_gen_shli_tl(t0, t0, 16);
6103 tcg_gen_or_tl(t0, t0, t1);
6104 tcg_gen_shri_tl(t1, t0, 32);
6105 tcg_gen_shli_tl(t0, t0, 32);
6106 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6107 tcg_temp_free(t2);
6108 tcg_temp_free(t1);
6110 break;
6111 #endif
6112 default:
6113 MIPS_INVAL("bsfhl");
6114 generate_exception_end(ctx, EXCP_RI);
6115 tcg_temp_free(t0);
6116 return;
6118 tcg_temp_free(t0);
6121 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6122 int imm2)
6124 TCGv t0;
6125 TCGv t1;
6126 if (rd == 0) {
6127 /* Treat as NOP. */
6128 return;
6130 t0 = tcg_temp_new();
6131 t1 = tcg_temp_new();
6132 gen_load_gpr(t0, rs);
6133 gen_load_gpr(t1, rt);
6134 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6135 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6136 if (opc == OPC_LSA) {
6137 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6140 tcg_temp_free(t1);
6141 tcg_temp_free(t0);
6143 return;
6146 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6147 int rt, int bits)
6149 TCGv t0;
6150 if (rd == 0) {
6151 /* Treat as NOP. */
6152 return;
6154 t0 = tcg_temp_new();
6155 if (bits == 0 || bits == wordsz) {
6156 if (bits == 0) {
6157 gen_load_gpr(t0, rt);
6158 } else {
6159 gen_load_gpr(t0, rs);
6161 switch (wordsz) {
6162 case 32:
6163 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6164 break;
6165 #if defined(TARGET_MIPS64)
6166 case 64:
6167 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6168 break;
6169 #endif
6171 } else {
6172 TCGv t1 = tcg_temp_new();
6173 gen_load_gpr(t0, rt);
6174 gen_load_gpr(t1, rs);
6175 switch (wordsz) {
6176 case 32:
6178 TCGv_i64 t2 = tcg_temp_new_i64();
6179 tcg_gen_concat_tl_i64(t2, t1, t0);
6180 tcg_gen_shri_i64(t2, t2, 32 - bits);
6181 gen_move_low32(cpu_gpr[rd], t2);
6182 tcg_temp_free_i64(t2);
6184 break;
6185 #if defined(TARGET_MIPS64)
6186 case 64:
6187 tcg_gen_shli_tl(t0, t0, bits);
6188 tcg_gen_shri_tl(t1, t1, 64 - bits);
6189 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6190 break;
6191 #endif
6193 tcg_temp_free(t1);
6196 tcg_temp_free(t0);
6199 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6200 int bp)
6202 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6205 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6206 int shift)
6208 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6211 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6213 TCGv t0;
6214 if (rd == 0) {
6215 /* Treat as NOP. */
6216 return;
6218 t0 = tcg_temp_new();
6219 gen_load_gpr(t0, rt);
6220 switch (opc) {
6221 case OPC_BITSWAP:
6222 gen_helper_bitswap(cpu_gpr[rd], t0);
6223 break;
6224 #if defined(TARGET_MIPS64)
6225 case OPC_DBITSWAP:
6226 gen_helper_dbitswap(cpu_gpr[rd], t0);
6227 break;
6228 #endif
6230 tcg_temp_free(t0);
6233 #ifndef CONFIG_USER_ONLY
6234 /* CP0 (MMU and control) */
6235 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6237 TCGv_i64 t0 = tcg_temp_new_i64();
6238 TCGv_i64 t1 = tcg_temp_new_i64();
6240 tcg_gen_ext_tl_i64(t0, arg);
6241 tcg_gen_ld_i64(t1, cpu_env, off);
6242 #if defined(TARGET_MIPS64)
6243 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6244 #else
6245 tcg_gen_concat32_i64(t1, t1, t0);
6246 #endif
6247 tcg_gen_st_i64(t1, cpu_env, off);
6248 tcg_temp_free_i64(t1);
6249 tcg_temp_free_i64(t0);
6252 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6254 TCGv_i64 t0 = tcg_temp_new_i64();
6255 TCGv_i64 t1 = tcg_temp_new_i64();
6257 tcg_gen_ext_tl_i64(t0, arg);
6258 tcg_gen_ld_i64(t1, cpu_env, off);
6259 tcg_gen_concat32_i64(t1, t1, t0);
6260 tcg_gen_st_i64(t1, cpu_env, off);
6261 tcg_temp_free_i64(t1);
6262 tcg_temp_free_i64(t0);
6265 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6267 TCGv_i64 t0 = tcg_temp_new_i64();
6269 tcg_gen_ld_i64(t0, cpu_env, off);
6270 #if defined(TARGET_MIPS64)
6271 tcg_gen_shri_i64(t0, t0, 30);
6272 #else
6273 tcg_gen_shri_i64(t0, t0, 32);
6274 #endif
6275 gen_move_low32(arg, t0);
6276 tcg_temp_free_i64(t0);
6279 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6281 TCGv_i64 t0 = tcg_temp_new_i64();
6283 tcg_gen_ld_i64(t0, cpu_env, off);
6284 tcg_gen_shri_i64(t0, t0, 32 + shift);
6285 gen_move_low32(arg, t0);
6286 tcg_temp_free_i64(t0);
6289 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6291 TCGv_i32 t0 = tcg_temp_new_i32();
6293 tcg_gen_ld_i32(t0, cpu_env, off);
6294 tcg_gen_ext_i32_tl(arg, t0);
6295 tcg_temp_free_i32(t0);
6298 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6300 tcg_gen_ld_tl(arg, cpu_env, off);
6301 tcg_gen_ext32s_tl(arg, arg);
6304 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6306 TCGv_i32 t0 = tcg_temp_new_i32();
6308 tcg_gen_trunc_tl_i32(t0, arg);
6309 tcg_gen_st_i32(t0, cpu_env, off);
6310 tcg_temp_free_i32(t0);
6313 #define CP0_CHECK(c) \
6314 do { \
6315 if (!(c)) { \
6316 goto cp0_unimplemented; \
6318 } while (0)
6320 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6322 const char *rn = "invalid";
6324 switch (reg) {
6325 case 2:
6326 switch (sel) {
6327 case 0:
6328 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6329 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6330 rn = "EntryLo0";
6331 break;
6332 default:
6333 goto cp0_unimplemented;
6335 break;
6336 case 3:
6337 switch (sel) {
6338 case 0:
6339 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6340 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6341 rn = "EntryLo1";
6342 break;
6343 default:
6344 goto cp0_unimplemented;
6346 break;
6347 case 17:
6348 switch (sel) {
6349 case 0:
6350 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6351 ctx->CP0_LLAddr_shift);
6352 rn = "LLAddr";
6353 break;
6354 case 1:
6355 CP0_CHECK(ctx->mrp);
6356 gen_helper_mfhc0_maar(arg, cpu_env);
6357 rn = "MAAR";
6358 break;
6359 default:
6360 goto cp0_unimplemented;
6362 break;
6363 case 28:
6364 switch (sel) {
6365 case 0:
6366 case 2:
6367 case 4:
6368 case 6:
6369 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6370 rn = "TagLo";
6371 break;
6372 default:
6373 goto cp0_unimplemented;
6375 break;
6376 default:
6377 goto cp0_unimplemented;
6379 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6380 return;
6382 cp0_unimplemented:
6383 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6384 tcg_gen_movi_tl(arg, 0);
6387 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6389 const char *rn = "invalid";
6390 uint64_t mask = ctx->PAMask >> 36;
6392 switch (reg) {
6393 case 2:
6394 switch (sel) {
6395 case 0:
6396 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6397 tcg_gen_andi_tl(arg, arg, mask);
6398 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6399 rn = "EntryLo0";
6400 break;
6401 default:
6402 goto cp0_unimplemented;
6404 break;
6405 case 3:
6406 switch (sel) {
6407 case 0:
6408 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6409 tcg_gen_andi_tl(arg, arg, mask);
6410 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6411 rn = "EntryLo1";
6412 break;
6413 default:
6414 goto cp0_unimplemented;
6416 break;
6417 case 17:
6418 switch (sel) {
6419 case 0:
6420 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6421 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6422 relevant for modern MIPS cores supporting MTHC0, therefore
6423 treating MTHC0 to LLAddr as NOP. */
6424 rn = "LLAddr";
6425 break;
6426 case 1:
6427 CP0_CHECK(ctx->mrp);
6428 gen_helper_mthc0_maar(cpu_env, arg);
6429 rn = "MAAR";
6430 break;
6431 default:
6432 goto cp0_unimplemented;
6434 break;
6435 case 28:
6436 switch (sel) {
6437 case 0:
6438 case 2:
6439 case 4:
6440 case 6:
6441 tcg_gen_andi_tl(arg, arg, mask);
6442 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6443 rn = "TagLo";
6444 break;
6445 default:
6446 goto cp0_unimplemented;
6448 break;
6449 default:
6450 goto cp0_unimplemented;
6452 trace_mips_translate_c0("mthc0", rn, reg, sel);
6454 cp0_unimplemented:
6455 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6458 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6460 if (ctx->insn_flags & ISA_MIPS32R6) {
6461 tcg_gen_movi_tl(arg, 0);
6462 } else {
6463 tcg_gen_movi_tl(arg, ~0);
6467 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6469 const char *rn = "invalid";
6471 if (sel != 0)
6472 check_insn(ctx, ISA_MIPS32);
6474 switch (reg) {
6475 case 0:
6476 switch (sel) {
6477 case 0:
6478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6479 rn = "Index";
6480 break;
6481 case 1:
6482 CP0_CHECK(ctx->insn_flags & ASE_MT);
6483 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6484 rn = "MVPControl";
6485 break;
6486 case 2:
6487 CP0_CHECK(ctx->insn_flags & ASE_MT);
6488 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6489 rn = "MVPConf0";
6490 break;
6491 case 3:
6492 CP0_CHECK(ctx->insn_flags & ASE_MT);
6493 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6494 rn = "MVPConf1";
6495 break;
6496 case 4:
6497 CP0_CHECK(ctx->vp);
6498 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6499 rn = "VPControl";
6500 break;
6501 default:
6502 goto cp0_unimplemented;
6504 break;
6505 case 1:
6506 switch (sel) {
6507 case 0:
6508 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6509 gen_helper_mfc0_random(arg, cpu_env);
6510 rn = "Random";
6511 break;
6512 case 1:
6513 CP0_CHECK(ctx->insn_flags & ASE_MT);
6514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6515 rn = "VPEControl";
6516 break;
6517 case 2:
6518 CP0_CHECK(ctx->insn_flags & ASE_MT);
6519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6520 rn = "VPEConf0";
6521 break;
6522 case 3:
6523 CP0_CHECK(ctx->insn_flags & ASE_MT);
6524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6525 rn = "VPEConf1";
6526 break;
6527 case 4:
6528 CP0_CHECK(ctx->insn_flags & ASE_MT);
6529 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6530 rn = "YQMask";
6531 break;
6532 case 5:
6533 CP0_CHECK(ctx->insn_flags & ASE_MT);
6534 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6535 rn = "VPESchedule";
6536 break;
6537 case 6:
6538 CP0_CHECK(ctx->insn_flags & ASE_MT);
6539 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6540 rn = "VPEScheFBack";
6541 break;
6542 case 7:
6543 CP0_CHECK(ctx->insn_flags & ASE_MT);
6544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6545 rn = "VPEOpt";
6546 break;
6547 default:
6548 goto cp0_unimplemented;
6550 break;
6551 case 2:
6552 switch (sel) {
6553 case 0:
6555 TCGv_i64 tmp = tcg_temp_new_i64();
6556 tcg_gen_ld_i64(tmp, cpu_env,
6557 offsetof(CPUMIPSState, CP0_EntryLo0));
6558 #if defined(TARGET_MIPS64)
6559 if (ctx->rxi) {
6560 /* Move RI/XI fields to bits 31:30 */
6561 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6562 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6564 #endif
6565 gen_move_low32(arg, tmp);
6566 tcg_temp_free_i64(tmp);
6568 rn = "EntryLo0";
6569 break;
6570 case 1:
6571 CP0_CHECK(ctx->insn_flags & ASE_MT);
6572 gen_helper_mfc0_tcstatus(arg, cpu_env);
6573 rn = "TCStatus";
6574 break;
6575 case 2:
6576 CP0_CHECK(ctx->insn_flags & ASE_MT);
6577 gen_helper_mfc0_tcbind(arg, cpu_env);
6578 rn = "TCBind";
6579 break;
6580 case 3:
6581 CP0_CHECK(ctx->insn_flags & ASE_MT);
6582 gen_helper_mfc0_tcrestart(arg, cpu_env);
6583 rn = "TCRestart";
6584 break;
6585 case 4:
6586 CP0_CHECK(ctx->insn_flags & ASE_MT);
6587 gen_helper_mfc0_tchalt(arg, cpu_env);
6588 rn = "TCHalt";
6589 break;
6590 case 5:
6591 CP0_CHECK(ctx->insn_flags & ASE_MT);
6592 gen_helper_mfc0_tccontext(arg, cpu_env);
6593 rn = "TCContext";
6594 break;
6595 case 6:
6596 CP0_CHECK(ctx->insn_flags & ASE_MT);
6597 gen_helper_mfc0_tcschedule(arg, cpu_env);
6598 rn = "TCSchedule";
6599 break;
6600 case 7:
6601 CP0_CHECK(ctx->insn_flags & ASE_MT);
6602 gen_helper_mfc0_tcschefback(arg, cpu_env);
6603 rn = "TCScheFBack";
6604 break;
6605 default:
6606 goto cp0_unimplemented;
6608 break;
6609 case 3:
6610 switch (sel) {
6611 case 0:
6613 TCGv_i64 tmp = tcg_temp_new_i64();
6614 tcg_gen_ld_i64(tmp, cpu_env,
6615 offsetof(CPUMIPSState, CP0_EntryLo1));
6616 #if defined(TARGET_MIPS64)
6617 if (ctx->rxi) {
6618 /* Move RI/XI fields to bits 31:30 */
6619 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6620 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6622 #endif
6623 gen_move_low32(arg, tmp);
6624 tcg_temp_free_i64(tmp);
6626 rn = "EntryLo1";
6627 break;
6628 case 1:
6629 CP0_CHECK(ctx->vp);
6630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6631 rn = "GlobalNumber";
6632 break;
6633 default:
6634 goto cp0_unimplemented;
6636 break;
6637 case 4:
6638 switch (sel) {
6639 case 0:
6640 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6641 tcg_gen_ext32s_tl(arg, arg);
6642 rn = "Context";
6643 break;
6644 case 1:
6645 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6646 rn = "ContextConfig";
6647 goto cp0_unimplemented;
6648 case 2:
6649 CP0_CHECK(ctx->ulri);
6650 tcg_gen_ld_tl(arg, cpu_env,
6651 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6652 tcg_gen_ext32s_tl(arg, arg);
6653 rn = "UserLocal";
6654 break;
6655 default:
6656 goto cp0_unimplemented;
6658 break;
6659 case 5:
6660 switch (sel) {
6661 case 0:
6662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6663 rn = "PageMask";
6664 break;
6665 case 1:
6666 check_insn(ctx, ISA_MIPS32R2);
6667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6668 rn = "PageGrain";
6669 break;
6670 case 2:
6671 CP0_CHECK(ctx->sc);
6672 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6673 tcg_gen_ext32s_tl(arg, arg);
6674 rn = "SegCtl0";
6675 break;
6676 case 3:
6677 CP0_CHECK(ctx->sc);
6678 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6679 tcg_gen_ext32s_tl(arg, arg);
6680 rn = "SegCtl1";
6681 break;
6682 case 4:
6683 CP0_CHECK(ctx->sc);
6684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6685 tcg_gen_ext32s_tl(arg, arg);
6686 rn = "SegCtl2";
6687 break;
6688 case 5:
6689 check_pw(ctx);
6690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6691 rn = "PWBase";
6692 break;
6693 case 6:
6694 check_pw(ctx);
6695 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6696 rn = "PWField";
6697 break;
6698 case 7:
6699 check_pw(ctx);
6700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6701 rn = "PWSize";
6702 break;
6703 default:
6704 goto cp0_unimplemented;
6706 break;
6707 case 6:
6708 switch (sel) {
6709 case 0:
6710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6711 rn = "Wired";
6712 break;
6713 case 1:
6714 check_insn(ctx, ISA_MIPS32R2);
6715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6716 rn = "SRSConf0";
6717 break;
6718 case 2:
6719 check_insn(ctx, ISA_MIPS32R2);
6720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6721 rn = "SRSConf1";
6722 break;
6723 case 3:
6724 check_insn(ctx, ISA_MIPS32R2);
6725 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6726 rn = "SRSConf2";
6727 break;
6728 case 4:
6729 check_insn(ctx, ISA_MIPS32R2);
6730 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6731 rn = "SRSConf3";
6732 break;
6733 case 5:
6734 check_insn(ctx, ISA_MIPS32R2);
6735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6736 rn = "SRSConf4";
6737 break;
6738 case 6:
6739 check_pw(ctx);
6740 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6741 rn = "PWCtl";
6742 break;
6743 default:
6744 goto cp0_unimplemented;
6746 break;
6747 case 7:
6748 switch (sel) {
6749 case 0:
6750 check_insn(ctx, ISA_MIPS32R2);
6751 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6752 rn = "HWREna";
6753 break;
6754 default:
6755 goto cp0_unimplemented;
6757 break;
6758 case 8:
6759 switch (sel) {
6760 case 0:
6761 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6762 tcg_gen_ext32s_tl(arg, arg);
6763 rn = "BadVAddr";
6764 break;
6765 case 1:
6766 CP0_CHECK(ctx->bi);
6767 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6768 rn = "BadInstr";
6769 break;
6770 case 2:
6771 CP0_CHECK(ctx->bp);
6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6773 rn = "BadInstrP";
6774 break;
6775 case 3:
6776 CP0_CHECK(ctx->bi);
6777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6778 tcg_gen_andi_tl(arg, arg, ~0xffff);
6779 rn = "BadInstrX";
6780 break;
6781 default:
6782 goto cp0_unimplemented;
6784 break;
6785 case 9:
6786 switch (sel) {
6787 case 0:
6788 /* Mark as an IO operation because we read the time. */
6789 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6790 gen_io_start();
6792 gen_helper_mfc0_count(arg, cpu_env);
6793 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6794 gen_io_end();
6796 /* Break the TB to be able to take timer interrupts immediately
6797 after reading count. DISAS_STOP isn't sufficient, we need to
6798 ensure we break completely out of translated code. */
6799 gen_save_pc(ctx->base.pc_next + 4);
6800 ctx->base.is_jmp = DISAS_EXIT;
6801 rn = "Count";
6802 break;
6803 /* 6,7 are implementation dependent */
6804 default:
6805 goto cp0_unimplemented;
6807 break;
6808 case 10:
6809 switch (sel) {
6810 case 0:
6811 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6812 tcg_gen_ext32s_tl(arg, arg);
6813 rn = "EntryHi";
6814 break;
6815 default:
6816 goto cp0_unimplemented;
6818 break;
6819 case 11:
6820 switch (sel) {
6821 case 0:
6822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6823 rn = "Compare";
6824 break;
6825 /* 6,7 are implementation dependent */
6826 default:
6827 goto cp0_unimplemented;
6829 break;
6830 case 12:
6831 switch (sel) {
6832 case 0:
6833 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6834 rn = "Status";
6835 break;
6836 case 1:
6837 check_insn(ctx, ISA_MIPS32R2);
6838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6839 rn = "IntCtl";
6840 break;
6841 case 2:
6842 check_insn(ctx, ISA_MIPS32R2);
6843 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6844 rn = "SRSCtl";
6845 break;
6846 case 3:
6847 check_insn(ctx, ISA_MIPS32R2);
6848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6849 rn = "SRSMap";
6850 break;
6851 default:
6852 goto cp0_unimplemented;
6854 break;
6855 case 13:
6856 switch (sel) {
6857 case 0:
6858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6859 rn = "Cause";
6860 break;
6861 default:
6862 goto cp0_unimplemented;
6864 break;
6865 case 14:
6866 switch (sel) {
6867 case 0:
6868 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6869 tcg_gen_ext32s_tl(arg, arg);
6870 rn = "EPC";
6871 break;
6872 default:
6873 goto cp0_unimplemented;
6875 break;
6876 case 15:
6877 switch (sel) {
6878 case 0:
6879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6880 rn = "PRid";
6881 break;
6882 case 1:
6883 check_insn(ctx, ISA_MIPS32R2);
6884 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6885 tcg_gen_ext32s_tl(arg, arg);
6886 rn = "EBase";
6887 break;
6888 case 3:
6889 check_insn(ctx, ISA_MIPS32R2);
6890 CP0_CHECK(ctx->cmgcr);
6891 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6892 tcg_gen_ext32s_tl(arg, arg);
6893 rn = "CMGCRBase";
6894 break;
6895 default:
6896 goto cp0_unimplemented;
6898 break;
6899 case 16:
6900 switch (sel) {
6901 case 0:
6902 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6903 rn = "Config";
6904 break;
6905 case 1:
6906 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6907 rn = "Config1";
6908 break;
6909 case 2:
6910 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6911 rn = "Config2";
6912 break;
6913 case 3:
6914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6915 rn = "Config3";
6916 break;
6917 case 4:
6918 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6919 rn = "Config4";
6920 break;
6921 case 5:
6922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6923 rn = "Config5";
6924 break;
6925 /* 6,7 are implementation dependent */
6926 case 6:
6927 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6928 rn = "Config6";
6929 break;
6930 case 7:
6931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6932 rn = "Config7";
6933 break;
6934 default:
6935 goto cp0_unimplemented;
6937 break;
6938 case 17:
6939 switch (sel) {
6940 case 0:
6941 gen_helper_mfc0_lladdr(arg, cpu_env);
6942 rn = "LLAddr";
6943 break;
6944 case 1:
6945 CP0_CHECK(ctx->mrp);
6946 gen_helper_mfc0_maar(arg, cpu_env);
6947 rn = "MAAR";
6948 break;
6949 case 2:
6950 CP0_CHECK(ctx->mrp);
6951 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6952 rn = "MAARI";
6953 break;
6954 default:
6955 goto cp0_unimplemented;
6957 break;
6958 case 18:
6959 switch (sel) {
6960 case 0:
6961 case 1:
6962 case 2:
6963 case 3:
6964 case 4:
6965 case 5:
6966 case 6:
6967 case 7:
6968 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6969 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6970 rn = "WatchLo";
6971 break;
6972 default:
6973 goto cp0_unimplemented;
6975 break;
6976 case 19:
6977 switch (sel) {
6978 case 0:
6979 case 1:
6980 case 2:
6981 case 3:
6982 case 4:
6983 case 5:
6984 case 6:
6985 case 7:
6986 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6987 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6988 rn = "WatchHi";
6989 break;
6990 default:
6991 goto cp0_unimplemented;
6993 break;
6994 case 20:
6995 switch (sel) {
6996 case 0:
6997 #if defined(TARGET_MIPS64)
6998 check_insn(ctx, ISA_MIPS3);
6999 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7000 tcg_gen_ext32s_tl(arg, arg);
7001 rn = "XContext";
7002 break;
7003 #endif
7004 default:
7005 goto cp0_unimplemented;
7007 break;
7008 case 21:
7009 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7010 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7011 switch (sel) {
7012 case 0:
7013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7014 rn = "Framemask";
7015 break;
7016 default:
7017 goto cp0_unimplemented;
7019 break;
7020 case 22:
7021 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7022 rn = "'Diagnostic"; /* implementation dependent */
7023 break;
7024 case 23:
7025 switch (sel) {
7026 case 0:
7027 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7028 rn = "Debug";
7029 break;
7030 case 1:
7031 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7032 rn = "TraceControl";
7033 goto cp0_unimplemented;
7034 case 2:
7035 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7036 rn = "TraceControl2";
7037 goto cp0_unimplemented;
7038 case 3:
7039 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7040 rn = "UserTraceData";
7041 goto cp0_unimplemented;
7042 case 4:
7043 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7044 rn = "TraceBPC";
7045 goto cp0_unimplemented;
7046 default:
7047 goto cp0_unimplemented;
7049 break;
7050 case 24:
7051 switch (sel) {
7052 case 0:
7053 /* EJTAG support */
7054 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7055 tcg_gen_ext32s_tl(arg, arg);
7056 rn = "DEPC";
7057 break;
7058 default:
7059 goto cp0_unimplemented;
7061 break;
7062 case 25:
7063 switch (sel) {
7064 case 0:
7065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7066 rn = "Performance0";
7067 break;
7068 case 1:
7069 // gen_helper_mfc0_performance1(arg);
7070 rn = "Performance1";
7071 goto cp0_unimplemented;
7072 case 2:
7073 // gen_helper_mfc0_performance2(arg);
7074 rn = "Performance2";
7075 goto cp0_unimplemented;
7076 case 3:
7077 // gen_helper_mfc0_performance3(arg);
7078 rn = "Performance3";
7079 goto cp0_unimplemented;
7080 case 4:
7081 // gen_helper_mfc0_performance4(arg);
7082 rn = "Performance4";
7083 goto cp0_unimplemented;
7084 case 5:
7085 // gen_helper_mfc0_performance5(arg);
7086 rn = "Performance5";
7087 goto cp0_unimplemented;
7088 case 6:
7089 // gen_helper_mfc0_performance6(arg);
7090 rn = "Performance6";
7091 goto cp0_unimplemented;
7092 case 7:
7093 // gen_helper_mfc0_performance7(arg);
7094 rn = "Performance7";
7095 goto cp0_unimplemented;
7096 default:
7097 goto cp0_unimplemented;
7099 break;
7100 case 26:
7101 switch (sel) {
7102 case 0:
7103 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7104 rn = "ErrCtl";
7105 break;
7106 default:
7107 goto cp0_unimplemented;
7109 break;
7110 case 27:
7111 switch (sel) {
7112 case 0:
7113 case 1:
7114 case 2:
7115 case 3:
7116 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7117 rn = "CacheErr";
7118 break;
7119 default:
7120 goto cp0_unimplemented;
7122 break;
7123 case 28:
7124 switch (sel) {
7125 case 0:
7126 case 2:
7127 case 4:
7128 case 6:
7130 TCGv_i64 tmp = tcg_temp_new_i64();
7131 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7132 gen_move_low32(arg, tmp);
7133 tcg_temp_free_i64(tmp);
7135 rn = "TagLo";
7136 break;
7137 case 1:
7138 case 3:
7139 case 5:
7140 case 7:
7141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7142 rn = "DataLo";
7143 break;
7144 default:
7145 goto cp0_unimplemented;
7147 break;
7148 case 29:
7149 switch (sel) {
7150 case 0:
7151 case 2:
7152 case 4:
7153 case 6:
7154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7155 rn = "TagHi";
7156 break;
7157 case 1:
7158 case 3:
7159 case 5:
7160 case 7:
7161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7162 rn = "DataHi";
7163 break;
7164 default:
7165 goto cp0_unimplemented;
7167 break;
7168 case 30:
7169 switch (sel) {
7170 case 0:
7171 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7172 tcg_gen_ext32s_tl(arg, arg);
7173 rn = "ErrorEPC";
7174 break;
7175 default:
7176 goto cp0_unimplemented;
7178 break;
7179 case 31:
7180 switch (sel) {
7181 case 0:
7182 /* EJTAG support */
7183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7184 rn = "DESAVE";
7185 break;
7186 case 2:
7187 case 3:
7188 case 4:
7189 case 5:
7190 case 6:
7191 case 7:
7192 CP0_CHECK(ctx->kscrexist & (1 << sel));
7193 tcg_gen_ld_tl(arg, cpu_env,
7194 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7195 tcg_gen_ext32s_tl(arg, arg);
7196 rn = "KScratch";
7197 break;
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 default:
7203 goto cp0_unimplemented;
7205 trace_mips_translate_c0("mfc0", rn, reg, sel);
7206 return;
7208 cp0_unimplemented:
7209 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7210 gen_mfc0_unimplemented(ctx, arg);
7213 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7215 const char *rn = "invalid";
7217 if (sel != 0)
7218 check_insn(ctx, ISA_MIPS32);
7220 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7221 gen_io_start();
7224 switch (reg) {
7225 case 0:
7226 switch (sel) {
7227 case 0:
7228 gen_helper_mtc0_index(cpu_env, arg);
7229 rn = "Index";
7230 break;
7231 case 1:
7232 CP0_CHECK(ctx->insn_flags & ASE_MT);
7233 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7234 rn = "MVPControl";
7235 break;
7236 case 2:
7237 CP0_CHECK(ctx->insn_flags & ASE_MT);
7238 /* ignored */
7239 rn = "MVPConf0";
7240 break;
7241 case 3:
7242 CP0_CHECK(ctx->insn_flags & ASE_MT);
7243 /* ignored */
7244 rn = "MVPConf1";
7245 break;
7246 case 4:
7247 CP0_CHECK(ctx->vp);
7248 /* ignored */
7249 rn = "VPControl";
7250 break;
7251 default:
7252 goto cp0_unimplemented;
7254 break;
7255 case 1:
7256 switch (sel) {
7257 case 0:
7258 /* ignored */
7259 rn = "Random";
7260 break;
7261 case 1:
7262 CP0_CHECK(ctx->insn_flags & ASE_MT);
7263 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7264 rn = "VPEControl";
7265 break;
7266 case 2:
7267 CP0_CHECK(ctx->insn_flags & ASE_MT);
7268 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7269 rn = "VPEConf0";
7270 break;
7271 case 3:
7272 CP0_CHECK(ctx->insn_flags & ASE_MT);
7273 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7274 rn = "VPEConf1";
7275 break;
7276 case 4:
7277 CP0_CHECK(ctx->insn_flags & ASE_MT);
7278 gen_helper_mtc0_yqmask(cpu_env, arg);
7279 rn = "YQMask";
7280 break;
7281 case 5:
7282 CP0_CHECK(ctx->insn_flags & ASE_MT);
7283 tcg_gen_st_tl(arg, cpu_env,
7284 offsetof(CPUMIPSState, CP0_VPESchedule));
7285 rn = "VPESchedule";
7286 break;
7287 case 6:
7288 CP0_CHECK(ctx->insn_flags & ASE_MT);
7289 tcg_gen_st_tl(arg, cpu_env,
7290 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7291 rn = "VPEScheFBack";
7292 break;
7293 case 7:
7294 CP0_CHECK(ctx->insn_flags & ASE_MT);
7295 gen_helper_mtc0_vpeopt(cpu_env, arg);
7296 rn = "VPEOpt";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case 2:
7303 switch (sel) {
7304 case 0:
7305 gen_helper_mtc0_entrylo0(cpu_env, arg);
7306 rn = "EntryLo0";
7307 break;
7308 case 1:
7309 CP0_CHECK(ctx->insn_flags & ASE_MT);
7310 gen_helper_mtc0_tcstatus(cpu_env, arg);
7311 rn = "TCStatus";
7312 break;
7313 case 2:
7314 CP0_CHECK(ctx->insn_flags & ASE_MT);
7315 gen_helper_mtc0_tcbind(cpu_env, arg);
7316 rn = "TCBind";
7317 break;
7318 case 3:
7319 CP0_CHECK(ctx->insn_flags & ASE_MT);
7320 gen_helper_mtc0_tcrestart(cpu_env, arg);
7321 rn = "TCRestart";
7322 break;
7323 case 4:
7324 CP0_CHECK(ctx->insn_flags & ASE_MT);
7325 gen_helper_mtc0_tchalt(cpu_env, arg);
7326 rn = "TCHalt";
7327 break;
7328 case 5:
7329 CP0_CHECK(ctx->insn_flags & ASE_MT);
7330 gen_helper_mtc0_tccontext(cpu_env, arg);
7331 rn = "TCContext";
7332 break;
7333 case 6:
7334 CP0_CHECK(ctx->insn_flags & ASE_MT);
7335 gen_helper_mtc0_tcschedule(cpu_env, arg);
7336 rn = "TCSchedule";
7337 break;
7338 case 7:
7339 CP0_CHECK(ctx->insn_flags & ASE_MT);
7340 gen_helper_mtc0_tcschefback(cpu_env, arg);
7341 rn = "TCScheFBack";
7342 break;
7343 default:
7344 goto cp0_unimplemented;
7346 break;
7347 case 3:
7348 switch (sel) {
7349 case 0:
7350 gen_helper_mtc0_entrylo1(cpu_env, arg);
7351 rn = "EntryLo1";
7352 break;
7353 case 1:
7354 CP0_CHECK(ctx->vp);
7355 /* ignored */
7356 rn = "GlobalNumber";
7357 break;
7358 default:
7359 goto cp0_unimplemented;
7361 break;
7362 case 4:
7363 switch (sel) {
7364 case 0:
7365 gen_helper_mtc0_context(cpu_env, arg);
7366 rn = "Context";
7367 break;
7368 case 1:
7369 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7370 rn = "ContextConfig";
7371 goto cp0_unimplemented;
7372 case 2:
7373 CP0_CHECK(ctx->ulri);
7374 tcg_gen_st_tl(arg, cpu_env,
7375 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7376 rn = "UserLocal";
7377 break;
7378 default:
7379 goto cp0_unimplemented;
7381 break;
7382 case 5:
7383 switch (sel) {
7384 case 0:
7385 gen_helper_mtc0_pagemask(cpu_env, arg);
7386 rn = "PageMask";
7387 break;
7388 case 1:
7389 check_insn(ctx, ISA_MIPS32R2);
7390 gen_helper_mtc0_pagegrain(cpu_env, arg);
7391 rn = "PageGrain";
7392 ctx->base.is_jmp = DISAS_STOP;
7393 break;
7394 case 2:
7395 CP0_CHECK(ctx->sc);
7396 gen_helper_mtc0_segctl0(cpu_env, arg);
7397 rn = "SegCtl0";
7398 break;
7399 case 3:
7400 CP0_CHECK(ctx->sc);
7401 gen_helper_mtc0_segctl1(cpu_env, arg);
7402 rn = "SegCtl1";
7403 break;
7404 case 4:
7405 CP0_CHECK(ctx->sc);
7406 gen_helper_mtc0_segctl2(cpu_env, arg);
7407 rn = "SegCtl2";
7408 break;
7409 case 5:
7410 check_pw(ctx);
7411 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7412 rn = "PWBase";
7413 break;
7414 case 6:
7415 check_pw(ctx);
7416 gen_helper_mtc0_pwfield(cpu_env, arg);
7417 rn = "PWField";
7418 break;
7419 case 7:
7420 check_pw(ctx);
7421 gen_helper_mtc0_pwsize(cpu_env, arg);
7422 rn = "PWSize";
7423 break;
7424 default:
7425 goto cp0_unimplemented;
7427 break;
7428 case 6:
7429 switch (sel) {
7430 case 0:
7431 gen_helper_mtc0_wired(cpu_env, arg);
7432 rn = "Wired";
7433 break;
7434 case 1:
7435 check_insn(ctx, ISA_MIPS32R2);
7436 gen_helper_mtc0_srsconf0(cpu_env, arg);
7437 rn = "SRSConf0";
7438 break;
7439 case 2:
7440 check_insn(ctx, ISA_MIPS32R2);
7441 gen_helper_mtc0_srsconf1(cpu_env, arg);
7442 rn = "SRSConf1";
7443 break;
7444 case 3:
7445 check_insn(ctx, ISA_MIPS32R2);
7446 gen_helper_mtc0_srsconf2(cpu_env, arg);
7447 rn = "SRSConf2";
7448 break;
7449 case 4:
7450 check_insn(ctx, ISA_MIPS32R2);
7451 gen_helper_mtc0_srsconf3(cpu_env, arg);
7452 rn = "SRSConf3";
7453 break;
7454 case 5:
7455 check_insn(ctx, ISA_MIPS32R2);
7456 gen_helper_mtc0_srsconf4(cpu_env, arg);
7457 rn = "SRSConf4";
7458 break;
7459 case 6:
7460 check_pw(ctx);
7461 gen_helper_mtc0_pwctl(cpu_env, arg);
7462 rn = "PWCtl";
7463 break;
7464 default:
7465 goto cp0_unimplemented;
7467 break;
7468 case 7:
7469 switch (sel) {
7470 case 0:
7471 check_insn(ctx, ISA_MIPS32R2);
7472 gen_helper_mtc0_hwrena(cpu_env, arg);
7473 ctx->base.is_jmp = DISAS_STOP;
7474 rn = "HWREna";
7475 break;
7476 default:
7477 goto cp0_unimplemented;
7479 break;
7480 case 8:
7481 switch (sel) {
7482 case 0:
7483 /* ignored */
7484 rn = "BadVAddr";
7485 break;
7486 case 1:
7487 /* ignored */
7488 rn = "BadInstr";
7489 break;
7490 case 2:
7491 /* ignored */
7492 rn = "BadInstrP";
7493 break;
7494 case 3:
7495 /* ignored */
7496 rn = "BadInstrX";
7497 break;
7498 default:
7499 goto cp0_unimplemented;
7501 break;
7502 case 9:
7503 switch (sel) {
7504 case 0:
7505 gen_helper_mtc0_count(cpu_env, arg);
7506 rn = "Count";
7507 break;
7508 /* 6,7 are implementation dependent */
7509 default:
7510 goto cp0_unimplemented;
7512 break;
7513 case 10:
7514 switch (sel) {
7515 case 0:
7516 gen_helper_mtc0_entryhi(cpu_env, arg);
7517 rn = "EntryHi";
7518 break;
7519 default:
7520 goto cp0_unimplemented;
7522 break;
7523 case 11:
7524 switch (sel) {
7525 case 0:
7526 gen_helper_mtc0_compare(cpu_env, arg);
7527 rn = "Compare";
7528 break;
7529 /* 6,7 are implementation dependent */
7530 default:
7531 goto cp0_unimplemented;
7533 break;
7534 case 12:
7535 switch (sel) {
7536 case 0:
7537 save_cpu_state(ctx, 1);
7538 gen_helper_mtc0_status(cpu_env, arg);
7539 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7540 gen_save_pc(ctx->base.pc_next + 4);
7541 ctx->base.is_jmp = DISAS_EXIT;
7542 rn = "Status";
7543 break;
7544 case 1:
7545 check_insn(ctx, ISA_MIPS32R2);
7546 gen_helper_mtc0_intctl(cpu_env, arg);
7547 /* Stop translation as we may have switched the execution mode */
7548 ctx->base.is_jmp = DISAS_STOP;
7549 rn = "IntCtl";
7550 break;
7551 case 2:
7552 check_insn(ctx, ISA_MIPS32R2);
7553 gen_helper_mtc0_srsctl(cpu_env, arg);
7554 /* Stop translation as we may have switched the execution mode */
7555 ctx->base.is_jmp = DISAS_STOP;
7556 rn = "SRSCtl";
7557 break;
7558 case 3:
7559 check_insn(ctx, ISA_MIPS32R2);
7560 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7561 /* Stop translation as we may have switched the execution mode */
7562 ctx->base.is_jmp = DISAS_STOP;
7563 rn = "SRSMap";
7564 break;
7565 default:
7566 goto cp0_unimplemented;
7568 break;
7569 case 13:
7570 switch (sel) {
7571 case 0:
7572 save_cpu_state(ctx, 1);
7573 gen_helper_mtc0_cause(cpu_env, arg);
7574 /* Stop translation as we may have triggered an interrupt.
7575 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7576 * translated code to check for pending interrupts. */
7577 gen_save_pc(ctx->base.pc_next + 4);
7578 ctx->base.is_jmp = DISAS_EXIT;
7579 rn = "Cause";
7580 break;
7581 default:
7582 goto cp0_unimplemented;
7584 break;
7585 case 14:
7586 switch (sel) {
7587 case 0:
7588 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7589 rn = "EPC";
7590 break;
7591 default:
7592 goto cp0_unimplemented;
7594 break;
7595 case 15:
7596 switch (sel) {
7597 case 0:
7598 /* ignored */
7599 rn = "PRid";
7600 break;
7601 case 1:
7602 check_insn(ctx, ISA_MIPS32R2);
7603 gen_helper_mtc0_ebase(cpu_env, arg);
7604 rn = "EBase";
7605 break;
7606 default:
7607 goto cp0_unimplemented;
7609 break;
7610 case 16:
7611 switch (sel) {
7612 case 0:
7613 gen_helper_mtc0_config0(cpu_env, arg);
7614 rn = "Config";
7615 /* Stop translation as we may have switched the execution mode */
7616 ctx->base.is_jmp = DISAS_STOP;
7617 break;
7618 case 1:
7619 /* ignored, read only */
7620 rn = "Config1";
7621 break;
7622 case 2:
7623 gen_helper_mtc0_config2(cpu_env, arg);
7624 rn = "Config2";
7625 /* Stop translation as we may have switched the execution mode */
7626 ctx->base.is_jmp = DISAS_STOP;
7627 break;
7628 case 3:
7629 gen_helper_mtc0_config3(cpu_env, arg);
7630 rn = "Config3";
7631 /* Stop translation as we may have switched the execution mode */
7632 ctx->base.is_jmp = DISAS_STOP;
7633 break;
7634 case 4:
7635 gen_helper_mtc0_config4(cpu_env, arg);
7636 rn = "Config4";
7637 ctx->base.is_jmp = DISAS_STOP;
7638 break;
7639 case 5:
7640 gen_helper_mtc0_config5(cpu_env, arg);
7641 rn = "Config5";
7642 /* Stop translation as we may have switched the execution mode */
7643 ctx->base.is_jmp = DISAS_STOP;
7644 break;
7645 /* 6,7 are implementation dependent */
7646 case 6:
7647 /* ignored */
7648 rn = "Config6";
7649 break;
7650 case 7:
7651 /* ignored */
7652 rn = "Config7";
7653 break;
7654 default:
7655 rn = "Invalid config selector";
7656 goto cp0_unimplemented;
7658 break;
7659 case 17:
7660 switch (sel) {
7661 case 0:
7662 gen_helper_mtc0_lladdr(cpu_env, arg);
7663 rn = "LLAddr";
7664 break;
7665 case 1:
7666 CP0_CHECK(ctx->mrp);
7667 gen_helper_mtc0_maar(cpu_env, arg);
7668 rn = "MAAR";
7669 break;
7670 case 2:
7671 CP0_CHECK(ctx->mrp);
7672 gen_helper_mtc0_maari(cpu_env, arg);
7673 rn = "MAARI";
7674 break;
7675 default:
7676 goto cp0_unimplemented;
7678 break;
7679 case 18:
7680 switch (sel) {
7681 case 0:
7682 case 1:
7683 case 2:
7684 case 3:
7685 case 4:
7686 case 5:
7687 case 6:
7688 case 7:
7689 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7690 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7691 rn = "WatchLo";
7692 break;
7693 default:
7694 goto cp0_unimplemented;
7696 break;
7697 case 19:
7698 switch (sel) {
7699 case 0:
7700 case 1:
7701 case 2:
7702 case 3:
7703 case 4:
7704 case 5:
7705 case 6:
7706 case 7:
7707 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7708 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7709 rn = "WatchHi";
7710 break;
7711 default:
7712 goto cp0_unimplemented;
7714 break;
7715 case 20:
7716 switch (sel) {
7717 case 0:
7718 #if defined(TARGET_MIPS64)
7719 check_insn(ctx, ISA_MIPS3);
7720 gen_helper_mtc0_xcontext(cpu_env, arg);
7721 rn = "XContext";
7722 break;
7723 #endif
7724 default:
7725 goto cp0_unimplemented;
7727 break;
7728 case 21:
7729 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7730 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7731 switch (sel) {
7732 case 0:
7733 gen_helper_mtc0_framemask(cpu_env, arg);
7734 rn = "Framemask";
7735 break;
7736 default:
7737 goto cp0_unimplemented;
7739 break;
7740 case 22:
7741 /* ignored */
7742 rn = "Diagnostic"; /* implementation dependent */
7743 break;
7744 case 23:
7745 switch (sel) {
7746 case 0:
7747 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7748 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7749 gen_save_pc(ctx->base.pc_next + 4);
7750 ctx->base.is_jmp = DISAS_EXIT;
7751 rn = "Debug";
7752 break;
7753 case 1:
7754 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7755 rn = "TraceControl";
7756 /* Stop translation as we may have switched the execution mode */
7757 ctx->base.is_jmp = DISAS_STOP;
7758 goto cp0_unimplemented;
7759 case 2:
7760 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7761 rn = "TraceControl2";
7762 /* Stop translation as we may have switched the execution mode */
7763 ctx->base.is_jmp = DISAS_STOP;
7764 goto cp0_unimplemented;
7765 case 3:
7766 /* Stop translation as we may have switched the execution mode */
7767 ctx->base.is_jmp = DISAS_STOP;
7768 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7769 rn = "UserTraceData";
7770 /* Stop translation as we may have switched the execution mode */
7771 ctx->base.is_jmp = DISAS_STOP;
7772 goto cp0_unimplemented;
7773 case 4:
7774 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7775 /* Stop translation as we may have switched the execution mode */
7776 ctx->base.is_jmp = DISAS_STOP;
7777 rn = "TraceBPC";
7778 goto cp0_unimplemented;
7779 default:
7780 goto cp0_unimplemented;
7782 break;
7783 case 24:
7784 switch (sel) {
7785 case 0:
7786 /* EJTAG support */
7787 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7788 rn = "DEPC";
7789 break;
7790 default:
7791 goto cp0_unimplemented;
7793 break;
7794 case 25:
7795 switch (sel) {
7796 case 0:
7797 gen_helper_mtc0_performance0(cpu_env, arg);
7798 rn = "Performance0";
7799 break;
7800 case 1:
7801 // gen_helper_mtc0_performance1(arg);
7802 rn = "Performance1";
7803 goto cp0_unimplemented;
7804 case 2:
7805 // gen_helper_mtc0_performance2(arg);
7806 rn = "Performance2";
7807 goto cp0_unimplemented;
7808 case 3:
7809 // gen_helper_mtc0_performance3(arg);
7810 rn = "Performance3";
7811 goto cp0_unimplemented;
7812 case 4:
7813 // gen_helper_mtc0_performance4(arg);
7814 rn = "Performance4";
7815 goto cp0_unimplemented;
7816 case 5:
7817 // gen_helper_mtc0_performance5(arg);
7818 rn = "Performance5";
7819 goto cp0_unimplemented;
7820 case 6:
7821 // gen_helper_mtc0_performance6(arg);
7822 rn = "Performance6";
7823 goto cp0_unimplemented;
7824 case 7:
7825 // gen_helper_mtc0_performance7(arg);
7826 rn = "Performance7";
7827 goto cp0_unimplemented;
7828 default:
7829 goto cp0_unimplemented;
7831 break;
7832 case 26:
7833 switch (sel) {
7834 case 0:
7835 gen_helper_mtc0_errctl(cpu_env, arg);
7836 ctx->base.is_jmp = DISAS_STOP;
7837 rn = "ErrCtl";
7838 break;
7839 default:
7840 goto cp0_unimplemented;
7842 break;
7843 case 27:
7844 switch (sel) {
7845 case 0:
7846 case 1:
7847 case 2:
7848 case 3:
7849 /* ignored */
7850 rn = "CacheErr";
7851 break;
7852 default:
7853 goto cp0_unimplemented;
7855 break;
7856 case 28:
7857 switch (sel) {
7858 case 0:
7859 case 2:
7860 case 4:
7861 case 6:
7862 gen_helper_mtc0_taglo(cpu_env, arg);
7863 rn = "TagLo";
7864 break;
7865 case 1:
7866 case 3:
7867 case 5:
7868 case 7:
7869 gen_helper_mtc0_datalo(cpu_env, arg);
7870 rn = "DataLo";
7871 break;
7872 default:
7873 goto cp0_unimplemented;
7875 break;
7876 case 29:
7877 switch (sel) {
7878 case 0:
7879 case 2:
7880 case 4:
7881 case 6:
7882 gen_helper_mtc0_taghi(cpu_env, arg);
7883 rn = "TagHi";
7884 break;
7885 case 1:
7886 case 3:
7887 case 5:
7888 case 7:
7889 gen_helper_mtc0_datahi(cpu_env, arg);
7890 rn = "DataHi";
7891 break;
7892 default:
7893 rn = "invalid sel";
7894 goto cp0_unimplemented;
7896 break;
7897 case 30:
7898 switch (sel) {
7899 case 0:
7900 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7901 rn = "ErrorEPC";
7902 break;
7903 default:
7904 goto cp0_unimplemented;
7906 break;
7907 case 31:
7908 switch (sel) {
7909 case 0:
7910 /* EJTAG support */
7911 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7912 rn = "DESAVE";
7913 break;
7914 case 2:
7915 case 3:
7916 case 4:
7917 case 5:
7918 case 6:
7919 case 7:
7920 CP0_CHECK(ctx->kscrexist & (1 << sel));
7921 tcg_gen_st_tl(arg, cpu_env,
7922 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7923 rn = "KScratch";
7924 break;
7925 default:
7926 goto cp0_unimplemented;
7928 break;
7929 default:
7930 goto cp0_unimplemented;
7932 trace_mips_translate_c0("mtc0", rn, reg, sel);
7934 /* For simplicity assume that all writes can cause interrupts. */
7935 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7936 gen_io_end();
7937 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7938 * translated code to check for pending interrupts. */
7939 gen_save_pc(ctx->base.pc_next + 4);
7940 ctx->base.is_jmp = DISAS_EXIT;
7942 return;
7944 cp0_unimplemented:
7945 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7948 #if defined(TARGET_MIPS64)
7949 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7951 const char *rn = "invalid";
7953 if (sel != 0)
7954 check_insn(ctx, ISA_MIPS64);
7956 switch (reg) {
7957 case 0:
7958 switch (sel) {
7959 case 0:
7960 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7961 rn = "Index";
7962 break;
7963 case 1:
7964 CP0_CHECK(ctx->insn_flags & ASE_MT);
7965 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7966 rn = "MVPControl";
7967 break;
7968 case 2:
7969 CP0_CHECK(ctx->insn_flags & ASE_MT);
7970 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7971 rn = "MVPConf0";
7972 break;
7973 case 3:
7974 CP0_CHECK(ctx->insn_flags & ASE_MT);
7975 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7976 rn = "MVPConf1";
7977 break;
7978 case 4:
7979 CP0_CHECK(ctx->vp);
7980 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7981 rn = "VPControl";
7982 break;
7983 default:
7984 goto cp0_unimplemented;
7986 break;
7987 case 1:
7988 switch (sel) {
7989 case 0:
7990 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7991 gen_helper_mfc0_random(arg, cpu_env);
7992 rn = "Random";
7993 break;
7994 case 1:
7995 CP0_CHECK(ctx->insn_flags & ASE_MT);
7996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7997 rn = "VPEControl";
7998 break;
7999 case 2:
8000 CP0_CHECK(ctx->insn_flags & ASE_MT);
8001 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8002 rn = "VPEConf0";
8003 break;
8004 case 3:
8005 CP0_CHECK(ctx->insn_flags & ASE_MT);
8006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8007 rn = "VPEConf1";
8008 break;
8009 case 4:
8010 CP0_CHECK(ctx->insn_flags & ASE_MT);
8011 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8012 rn = "YQMask";
8013 break;
8014 case 5:
8015 CP0_CHECK(ctx->insn_flags & ASE_MT);
8016 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8017 rn = "VPESchedule";
8018 break;
8019 case 6:
8020 CP0_CHECK(ctx->insn_flags & ASE_MT);
8021 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8022 rn = "VPEScheFBack";
8023 break;
8024 case 7:
8025 CP0_CHECK(ctx->insn_flags & ASE_MT);
8026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8027 rn = "VPEOpt";
8028 break;
8029 default:
8030 goto cp0_unimplemented;
8032 break;
8033 case 2:
8034 switch (sel) {
8035 case 0:
8036 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8037 rn = "EntryLo0";
8038 break;
8039 case 1:
8040 CP0_CHECK(ctx->insn_flags & ASE_MT);
8041 gen_helper_mfc0_tcstatus(arg, cpu_env);
8042 rn = "TCStatus";
8043 break;
8044 case 2:
8045 CP0_CHECK(ctx->insn_flags & ASE_MT);
8046 gen_helper_mfc0_tcbind(arg, cpu_env);
8047 rn = "TCBind";
8048 break;
8049 case 3:
8050 CP0_CHECK(ctx->insn_flags & ASE_MT);
8051 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8052 rn = "TCRestart";
8053 break;
8054 case 4:
8055 CP0_CHECK(ctx->insn_flags & ASE_MT);
8056 gen_helper_dmfc0_tchalt(arg, cpu_env);
8057 rn = "TCHalt";
8058 break;
8059 case 5:
8060 CP0_CHECK(ctx->insn_flags & ASE_MT);
8061 gen_helper_dmfc0_tccontext(arg, cpu_env);
8062 rn = "TCContext";
8063 break;
8064 case 6:
8065 CP0_CHECK(ctx->insn_flags & ASE_MT);
8066 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8067 rn = "TCSchedule";
8068 break;
8069 case 7:
8070 CP0_CHECK(ctx->insn_flags & ASE_MT);
8071 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8072 rn = "TCScheFBack";
8073 break;
8074 default:
8075 goto cp0_unimplemented;
8077 break;
8078 case 3:
8079 switch (sel) {
8080 case 0:
8081 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8082 rn = "EntryLo1";
8083 break;
8084 case 1:
8085 CP0_CHECK(ctx->vp);
8086 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8087 rn = "GlobalNumber";
8088 break;
8089 default:
8090 goto cp0_unimplemented;
8092 break;
8093 case 4:
8094 switch (sel) {
8095 case 0:
8096 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8097 rn = "Context";
8098 break;
8099 case 1:
8100 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8101 rn = "ContextConfig";
8102 goto cp0_unimplemented;
8103 case 2:
8104 CP0_CHECK(ctx->ulri);
8105 tcg_gen_ld_tl(arg, cpu_env,
8106 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8107 rn = "UserLocal";
8108 break;
8109 default:
8110 goto cp0_unimplemented;
8112 break;
8113 case 5:
8114 switch (sel) {
8115 case 0:
8116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8117 rn = "PageMask";
8118 break;
8119 case 1:
8120 check_insn(ctx, ISA_MIPS32R2);
8121 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8122 rn = "PageGrain";
8123 break;
8124 case 2:
8125 CP0_CHECK(ctx->sc);
8126 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8127 rn = "SegCtl0";
8128 break;
8129 case 3:
8130 CP0_CHECK(ctx->sc);
8131 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8132 rn = "SegCtl1";
8133 break;
8134 case 4:
8135 CP0_CHECK(ctx->sc);
8136 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8137 rn = "SegCtl2";
8138 break;
8139 case 5:
8140 check_pw(ctx);
8141 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8142 rn = "PWBase";
8143 break;
8144 case 6:
8145 check_pw(ctx);
8146 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8147 rn = "PWField";
8148 break;
8149 case 7:
8150 check_pw(ctx);
8151 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8152 rn = "PWSize";
8153 break;
8154 default:
8155 goto cp0_unimplemented;
8157 break;
8158 case 6:
8159 switch (sel) {
8160 case 0:
8161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8162 rn = "Wired";
8163 break;
8164 case 1:
8165 check_insn(ctx, ISA_MIPS32R2);
8166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8167 rn = "SRSConf0";
8168 break;
8169 case 2:
8170 check_insn(ctx, ISA_MIPS32R2);
8171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8172 rn = "SRSConf1";
8173 break;
8174 case 3:
8175 check_insn(ctx, ISA_MIPS32R2);
8176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8177 rn = "SRSConf2";
8178 break;
8179 case 4:
8180 check_insn(ctx, ISA_MIPS32R2);
8181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8182 rn = "SRSConf3";
8183 break;
8184 case 5:
8185 check_insn(ctx, ISA_MIPS32R2);
8186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8187 rn = "SRSConf4";
8188 break;
8189 case 6:
8190 check_pw(ctx);
8191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8192 rn = "PWCtl";
8193 break;
8194 default:
8195 goto cp0_unimplemented;
8197 break;
8198 case 7:
8199 switch (sel) {
8200 case 0:
8201 check_insn(ctx, ISA_MIPS32R2);
8202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8203 rn = "HWREna";
8204 break;
8205 default:
8206 goto cp0_unimplemented;
8208 break;
8209 case 8:
8210 switch (sel) {
8211 case 0:
8212 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8213 rn = "BadVAddr";
8214 break;
8215 case 1:
8216 CP0_CHECK(ctx->bi);
8217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8218 rn = "BadInstr";
8219 break;
8220 case 2:
8221 CP0_CHECK(ctx->bp);
8222 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8223 rn = "BadInstrP";
8224 break;
8225 case 3:
8226 CP0_CHECK(ctx->bi);
8227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8228 tcg_gen_andi_tl(arg, arg, ~0xffff);
8229 rn = "BadInstrX";
8230 break;
8231 default:
8232 goto cp0_unimplemented;
8234 break;
8235 case 9:
8236 switch (sel) {
8237 case 0:
8238 /* Mark as an IO operation because we read the time. */
8239 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8240 gen_io_start();
8242 gen_helper_mfc0_count(arg, cpu_env);
8243 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8244 gen_io_end();
8246 /* Break the TB to be able to take timer interrupts immediately
8247 after reading count. DISAS_STOP isn't sufficient, we need to
8248 ensure we break completely out of translated code. */
8249 gen_save_pc(ctx->base.pc_next + 4);
8250 ctx->base.is_jmp = DISAS_EXIT;
8251 rn = "Count";
8252 break;
8253 /* 6,7 are implementation dependent */
8254 default:
8255 goto cp0_unimplemented;
8257 break;
8258 case 10:
8259 switch (sel) {
8260 case 0:
8261 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8262 rn = "EntryHi";
8263 break;
8264 default:
8265 goto cp0_unimplemented;
8267 break;
8268 case 11:
8269 switch (sel) {
8270 case 0:
8271 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8272 rn = "Compare";
8273 break;
8274 /* 6,7 are implementation dependent */
8275 default:
8276 goto cp0_unimplemented;
8278 break;
8279 case 12:
8280 switch (sel) {
8281 case 0:
8282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8283 rn = "Status";
8284 break;
8285 case 1:
8286 check_insn(ctx, ISA_MIPS32R2);
8287 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8288 rn = "IntCtl";
8289 break;
8290 case 2:
8291 check_insn(ctx, ISA_MIPS32R2);
8292 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8293 rn = "SRSCtl";
8294 break;
8295 case 3:
8296 check_insn(ctx, ISA_MIPS32R2);
8297 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8298 rn = "SRSMap";
8299 break;
8300 default:
8301 goto cp0_unimplemented;
8303 break;
8304 case 13:
8305 switch (sel) {
8306 case 0:
8307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8308 rn = "Cause";
8309 break;
8310 default:
8311 goto cp0_unimplemented;
8313 break;
8314 case 14:
8315 switch (sel) {
8316 case 0:
8317 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8318 rn = "EPC";
8319 break;
8320 default:
8321 goto cp0_unimplemented;
8323 break;
8324 case 15:
8325 switch (sel) {
8326 case 0:
8327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8328 rn = "PRid";
8329 break;
8330 case 1:
8331 check_insn(ctx, ISA_MIPS32R2);
8332 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8333 rn = "EBase";
8334 break;
8335 case 3:
8336 check_insn(ctx, ISA_MIPS32R2);
8337 CP0_CHECK(ctx->cmgcr);
8338 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8339 rn = "CMGCRBase";
8340 break;
8341 default:
8342 goto cp0_unimplemented;
8344 break;
8345 case 16:
8346 switch (sel) {
8347 case 0:
8348 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8349 rn = "Config";
8350 break;
8351 case 1:
8352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8353 rn = "Config1";
8354 break;
8355 case 2:
8356 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8357 rn = "Config2";
8358 break;
8359 case 3:
8360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8361 rn = "Config3";
8362 break;
8363 case 4:
8364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8365 rn = "Config4";
8366 break;
8367 case 5:
8368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8369 rn = "Config5";
8370 break;
8371 /* 6,7 are implementation dependent */
8372 case 6:
8373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8374 rn = "Config6";
8375 break;
8376 case 7:
8377 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8378 rn = "Config7";
8379 break;
8380 default:
8381 goto cp0_unimplemented;
8383 break;
8384 case 17:
8385 switch (sel) {
8386 case 0:
8387 gen_helper_dmfc0_lladdr(arg, cpu_env);
8388 rn = "LLAddr";
8389 break;
8390 case 1:
8391 CP0_CHECK(ctx->mrp);
8392 gen_helper_dmfc0_maar(arg, cpu_env);
8393 rn = "MAAR";
8394 break;
8395 case 2:
8396 CP0_CHECK(ctx->mrp);
8397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8398 rn = "MAARI";
8399 break;
8400 default:
8401 goto cp0_unimplemented;
8403 break;
8404 case 18:
8405 switch (sel) {
8406 case 0:
8407 case 1:
8408 case 2:
8409 case 3:
8410 case 4:
8411 case 5:
8412 case 6:
8413 case 7:
8414 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8415 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8416 rn = "WatchLo";
8417 break;
8418 default:
8419 goto cp0_unimplemented;
8421 break;
8422 case 19:
8423 switch (sel) {
8424 case 0:
8425 case 1:
8426 case 2:
8427 case 3:
8428 case 4:
8429 case 5:
8430 case 6:
8431 case 7:
8432 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8433 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8434 rn = "WatchHi";
8435 break;
8436 default:
8437 goto cp0_unimplemented;
8439 break;
8440 case 20:
8441 switch (sel) {
8442 case 0:
8443 check_insn(ctx, ISA_MIPS3);
8444 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8445 rn = "XContext";
8446 break;
8447 default:
8448 goto cp0_unimplemented;
8450 break;
8451 case 21:
8452 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8453 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8454 switch (sel) {
8455 case 0:
8456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8457 rn = "Framemask";
8458 break;
8459 default:
8460 goto cp0_unimplemented;
8462 break;
8463 case 22:
8464 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8465 rn = "'Diagnostic"; /* implementation dependent */
8466 break;
8467 case 23:
8468 switch (sel) {
8469 case 0:
8470 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8471 rn = "Debug";
8472 break;
8473 case 1:
8474 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8475 rn = "TraceControl";
8476 goto cp0_unimplemented;
8477 case 2:
8478 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8479 rn = "TraceControl2";
8480 goto cp0_unimplemented;
8481 case 3:
8482 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8483 rn = "UserTraceData";
8484 goto cp0_unimplemented;
8485 case 4:
8486 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8487 rn = "TraceBPC";
8488 goto cp0_unimplemented;
8489 default:
8490 goto cp0_unimplemented;
8492 break;
8493 case 24:
8494 switch (sel) {
8495 case 0:
8496 /* EJTAG support */
8497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8498 rn = "DEPC";
8499 break;
8500 default:
8501 goto cp0_unimplemented;
8503 break;
8504 case 25:
8505 switch (sel) {
8506 case 0:
8507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8508 rn = "Performance0";
8509 break;
8510 case 1:
8511 // gen_helper_dmfc0_performance1(arg);
8512 rn = "Performance1";
8513 goto cp0_unimplemented;
8514 case 2:
8515 // gen_helper_dmfc0_performance2(arg);
8516 rn = "Performance2";
8517 goto cp0_unimplemented;
8518 case 3:
8519 // gen_helper_dmfc0_performance3(arg);
8520 rn = "Performance3";
8521 goto cp0_unimplemented;
8522 case 4:
8523 // gen_helper_dmfc0_performance4(arg);
8524 rn = "Performance4";
8525 goto cp0_unimplemented;
8526 case 5:
8527 // gen_helper_dmfc0_performance5(arg);
8528 rn = "Performance5";
8529 goto cp0_unimplemented;
8530 case 6:
8531 // gen_helper_dmfc0_performance6(arg);
8532 rn = "Performance6";
8533 goto cp0_unimplemented;
8534 case 7:
8535 // gen_helper_dmfc0_performance7(arg);
8536 rn = "Performance7";
8537 goto cp0_unimplemented;
8538 default:
8539 goto cp0_unimplemented;
8541 break;
8542 case 26:
8543 switch (sel) {
8544 case 0:
8545 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8546 rn = "ErrCtl";
8547 break;
8548 default:
8549 goto cp0_unimplemented;
8551 break;
8552 case 27:
8553 switch (sel) {
8554 /* ignored */
8555 case 0:
8556 case 1:
8557 case 2:
8558 case 3:
8559 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8560 rn = "CacheErr";
8561 break;
8562 default:
8563 goto cp0_unimplemented;
8565 break;
8566 case 28:
8567 switch (sel) {
8568 case 0:
8569 case 2:
8570 case 4:
8571 case 6:
8572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8573 rn = "TagLo";
8574 break;
8575 case 1:
8576 case 3:
8577 case 5:
8578 case 7:
8579 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8580 rn = "DataLo";
8581 break;
8582 default:
8583 goto cp0_unimplemented;
8585 break;
8586 case 29:
8587 switch (sel) {
8588 case 0:
8589 case 2:
8590 case 4:
8591 case 6:
8592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8593 rn = "TagHi";
8594 break;
8595 case 1:
8596 case 3:
8597 case 5:
8598 case 7:
8599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8600 rn = "DataHi";
8601 break;
8602 default:
8603 goto cp0_unimplemented;
8605 break;
8606 case 30:
8607 switch (sel) {
8608 case 0:
8609 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8610 rn = "ErrorEPC";
8611 break;
8612 default:
8613 goto cp0_unimplemented;
8615 break;
8616 case 31:
8617 switch (sel) {
8618 case 0:
8619 /* EJTAG support */
8620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8621 rn = "DESAVE";
8622 break;
8623 case 2:
8624 case 3:
8625 case 4:
8626 case 5:
8627 case 6:
8628 case 7:
8629 CP0_CHECK(ctx->kscrexist & (1 << sel));
8630 tcg_gen_ld_tl(arg, cpu_env,
8631 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8632 rn = "KScratch";
8633 break;
8634 default:
8635 goto cp0_unimplemented;
8637 break;
8638 default:
8639 goto cp0_unimplemented;
8641 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8642 return;
8644 cp0_unimplemented:
8645 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8646 gen_mfc0_unimplemented(ctx, arg);
8649 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8651 const char *rn = "invalid";
8653 if (sel != 0)
8654 check_insn(ctx, ISA_MIPS64);
8656 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8657 gen_io_start();
8660 switch (reg) {
8661 case 0:
8662 switch (sel) {
8663 case 0:
8664 gen_helper_mtc0_index(cpu_env, arg);
8665 rn = "Index";
8666 break;
8667 case 1:
8668 CP0_CHECK(ctx->insn_flags & ASE_MT);
8669 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8670 rn = "MVPControl";
8671 break;
8672 case 2:
8673 CP0_CHECK(ctx->insn_flags & ASE_MT);
8674 /* ignored */
8675 rn = "MVPConf0";
8676 break;
8677 case 3:
8678 CP0_CHECK(ctx->insn_flags & ASE_MT);
8679 /* ignored */
8680 rn = "MVPConf1";
8681 break;
8682 case 4:
8683 CP0_CHECK(ctx->vp);
8684 /* ignored */
8685 rn = "VPControl";
8686 break;
8687 default:
8688 goto cp0_unimplemented;
8690 break;
8691 case 1:
8692 switch (sel) {
8693 case 0:
8694 /* ignored */
8695 rn = "Random";
8696 break;
8697 case 1:
8698 CP0_CHECK(ctx->insn_flags & ASE_MT);
8699 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8700 rn = "VPEControl";
8701 break;
8702 case 2:
8703 CP0_CHECK(ctx->insn_flags & ASE_MT);
8704 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8705 rn = "VPEConf0";
8706 break;
8707 case 3:
8708 CP0_CHECK(ctx->insn_flags & ASE_MT);
8709 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8710 rn = "VPEConf1";
8711 break;
8712 case 4:
8713 CP0_CHECK(ctx->insn_flags & ASE_MT);
8714 gen_helper_mtc0_yqmask(cpu_env, arg);
8715 rn = "YQMask";
8716 break;
8717 case 5:
8718 CP0_CHECK(ctx->insn_flags & ASE_MT);
8719 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8720 rn = "VPESchedule";
8721 break;
8722 case 6:
8723 CP0_CHECK(ctx->insn_flags & ASE_MT);
8724 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8725 rn = "VPEScheFBack";
8726 break;
8727 case 7:
8728 CP0_CHECK(ctx->insn_flags & ASE_MT);
8729 gen_helper_mtc0_vpeopt(cpu_env, arg);
8730 rn = "VPEOpt";
8731 break;
8732 default:
8733 goto cp0_unimplemented;
8735 break;
8736 case 2:
8737 switch (sel) {
8738 case 0:
8739 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8740 rn = "EntryLo0";
8741 break;
8742 case 1:
8743 CP0_CHECK(ctx->insn_flags & ASE_MT);
8744 gen_helper_mtc0_tcstatus(cpu_env, arg);
8745 rn = "TCStatus";
8746 break;
8747 case 2:
8748 CP0_CHECK(ctx->insn_flags & ASE_MT);
8749 gen_helper_mtc0_tcbind(cpu_env, arg);
8750 rn = "TCBind";
8751 break;
8752 case 3:
8753 CP0_CHECK(ctx->insn_flags & ASE_MT);
8754 gen_helper_mtc0_tcrestart(cpu_env, arg);
8755 rn = "TCRestart";
8756 break;
8757 case 4:
8758 CP0_CHECK(ctx->insn_flags & ASE_MT);
8759 gen_helper_mtc0_tchalt(cpu_env, arg);
8760 rn = "TCHalt";
8761 break;
8762 case 5:
8763 CP0_CHECK(ctx->insn_flags & ASE_MT);
8764 gen_helper_mtc0_tccontext(cpu_env, arg);
8765 rn = "TCContext";
8766 break;
8767 case 6:
8768 CP0_CHECK(ctx->insn_flags & ASE_MT);
8769 gen_helper_mtc0_tcschedule(cpu_env, arg);
8770 rn = "TCSchedule";
8771 break;
8772 case 7:
8773 CP0_CHECK(ctx->insn_flags & ASE_MT);
8774 gen_helper_mtc0_tcschefback(cpu_env, arg);
8775 rn = "TCScheFBack";
8776 break;
8777 default:
8778 goto cp0_unimplemented;
8780 break;
8781 case 3:
8782 switch (sel) {
8783 case 0:
8784 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8785 rn = "EntryLo1";
8786 break;
8787 case 1:
8788 CP0_CHECK(ctx->vp);
8789 /* ignored */
8790 rn = "GlobalNumber";
8791 break;
8792 default:
8793 goto cp0_unimplemented;
8795 break;
8796 case 4:
8797 switch (sel) {
8798 case 0:
8799 gen_helper_mtc0_context(cpu_env, arg);
8800 rn = "Context";
8801 break;
8802 case 1:
8803 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8804 rn = "ContextConfig";
8805 goto cp0_unimplemented;
8806 case 2:
8807 CP0_CHECK(ctx->ulri);
8808 tcg_gen_st_tl(arg, cpu_env,
8809 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8810 rn = "UserLocal";
8811 break;
8812 default:
8813 goto cp0_unimplemented;
8815 break;
8816 case 5:
8817 switch (sel) {
8818 case 0:
8819 gen_helper_mtc0_pagemask(cpu_env, arg);
8820 rn = "PageMask";
8821 break;
8822 case 1:
8823 check_insn(ctx, ISA_MIPS32R2);
8824 gen_helper_mtc0_pagegrain(cpu_env, arg);
8825 rn = "PageGrain";
8826 break;
8827 case 2:
8828 CP0_CHECK(ctx->sc);
8829 gen_helper_mtc0_segctl0(cpu_env, arg);
8830 rn = "SegCtl0";
8831 break;
8832 case 3:
8833 CP0_CHECK(ctx->sc);
8834 gen_helper_mtc0_segctl1(cpu_env, arg);
8835 rn = "SegCtl1";
8836 break;
8837 case 4:
8838 CP0_CHECK(ctx->sc);
8839 gen_helper_mtc0_segctl2(cpu_env, arg);
8840 rn = "SegCtl2";
8841 break;
8842 case 5:
8843 check_pw(ctx);
8844 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8845 rn = "PWBase";
8846 break;
8847 case 6:
8848 check_pw(ctx);
8849 gen_helper_mtc0_pwfield(cpu_env, arg);
8850 rn = "PWField";
8851 break;
8852 case 7:
8853 check_pw(ctx);
8854 gen_helper_mtc0_pwsize(cpu_env, arg);
8855 rn = "PWSize";
8856 break;
8857 default:
8858 goto cp0_unimplemented;
8860 break;
8861 case 6:
8862 switch (sel) {
8863 case 0:
8864 gen_helper_mtc0_wired(cpu_env, arg);
8865 rn = "Wired";
8866 break;
8867 case 1:
8868 check_insn(ctx, ISA_MIPS32R2);
8869 gen_helper_mtc0_srsconf0(cpu_env, arg);
8870 rn = "SRSConf0";
8871 break;
8872 case 2:
8873 check_insn(ctx, ISA_MIPS32R2);
8874 gen_helper_mtc0_srsconf1(cpu_env, arg);
8875 rn = "SRSConf1";
8876 break;
8877 case 3:
8878 check_insn(ctx, ISA_MIPS32R2);
8879 gen_helper_mtc0_srsconf2(cpu_env, arg);
8880 rn = "SRSConf2";
8881 break;
8882 case 4:
8883 check_insn(ctx, ISA_MIPS32R2);
8884 gen_helper_mtc0_srsconf3(cpu_env, arg);
8885 rn = "SRSConf3";
8886 break;
8887 case 5:
8888 check_insn(ctx, ISA_MIPS32R2);
8889 gen_helper_mtc0_srsconf4(cpu_env, arg);
8890 rn = "SRSConf4";
8891 break;
8892 case 6:
8893 check_pw(ctx);
8894 gen_helper_mtc0_pwctl(cpu_env, arg);
8895 rn = "PWCtl";
8896 break;
8897 default:
8898 goto cp0_unimplemented;
8900 break;
8901 case 7:
8902 switch (sel) {
8903 case 0:
8904 check_insn(ctx, ISA_MIPS32R2);
8905 gen_helper_mtc0_hwrena(cpu_env, arg);
8906 ctx->base.is_jmp = DISAS_STOP;
8907 rn = "HWREna";
8908 break;
8909 default:
8910 goto cp0_unimplemented;
8912 break;
8913 case 8:
8914 switch (sel) {
8915 case 0:
8916 /* ignored */
8917 rn = "BadVAddr";
8918 break;
8919 case 1:
8920 /* ignored */
8921 rn = "BadInstr";
8922 break;
8923 case 2:
8924 /* ignored */
8925 rn = "BadInstrP";
8926 break;
8927 case 3:
8928 /* ignored */
8929 rn = "BadInstrX";
8930 break;
8931 default:
8932 goto cp0_unimplemented;
8934 break;
8935 case 9:
8936 switch (sel) {
8937 case 0:
8938 gen_helper_mtc0_count(cpu_env, arg);
8939 rn = "Count";
8940 break;
8941 /* 6,7 are implementation dependent */
8942 default:
8943 goto cp0_unimplemented;
8945 /* Stop translation as we may have switched the execution mode */
8946 ctx->base.is_jmp = DISAS_STOP;
8947 break;
8948 case 10:
8949 switch (sel) {
8950 case 0:
8951 gen_helper_mtc0_entryhi(cpu_env, arg);
8952 rn = "EntryHi";
8953 break;
8954 default:
8955 goto cp0_unimplemented;
8957 break;
8958 case 11:
8959 switch (sel) {
8960 case 0:
8961 gen_helper_mtc0_compare(cpu_env, arg);
8962 rn = "Compare";
8963 break;
8964 /* 6,7 are implementation dependent */
8965 default:
8966 goto cp0_unimplemented;
8968 /* Stop translation as we may have switched the execution mode */
8969 ctx->base.is_jmp = DISAS_STOP;
8970 break;
8971 case 12:
8972 switch (sel) {
8973 case 0:
8974 save_cpu_state(ctx, 1);
8975 gen_helper_mtc0_status(cpu_env, arg);
8976 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8977 gen_save_pc(ctx->base.pc_next + 4);
8978 ctx->base.is_jmp = DISAS_EXIT;
8979 rn = "Status";
8980 break;
8981 case 1:
8982 check_insn(ctx, ISA_MIPS32R2);
8983 gen_helper_mtc0_intctl(cpu_env, arg);
8984 /* Stop translation as we may have switched the execution mode */
8985 ctx->base.is_jmp = DISAS_STOP;
8986 rn = "IntCtl";
8987 break;
8988 case 2:
8989 check_insn(ctx, ISA_MIPS32R2);
8990 gen_helper_mtc0_srsctl(cpu_env, arg);
8991 /* Stop translation as we may have switched the execution mode */
8992 ctx->base.is_jmp = DISAS_STOP;
8993 rn = "SRSCtl";
8994 break;
8995 case 3:
8996 check_insn(ctx, ISA_MIPS32R2);
8997 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8998 /* Stop translation as we may have switched the execution mode */
8999 ctx->base.is_jmp = DISAS_STOP;
9000 rn = "SRSMap";
9001 break;
9002 default:
9003 goto cp0_unimplemented;
9005 break;
9006 case 13:
9007 switch (sel) {
9008 case 0:
9009 save_cpu_state(ctx, 1);
9010 gen_helper_mtc0_cause(cpu_env, arg);
9011 /* Stop translation as we may have triggered an interrupt.
9012 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9013 * translated code to check for pending interrupts. */
9014 gen_save_pc(ctx->base.pc_next + 4);
9015 ctx->base.is_jmp = DISAS_EXIT;
9016 rn = "Cause";
9017 break;
9018 default:
9019 goto cp0_unimplemented;
9021 break;
9022 case 14:
9023 switch (sel) {
9024 case 0:
9025 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9026 rn = "EPC";
9027 break;
9028 default:
9029 goto cp0_unimplemented;
9031 break;
9032 case 15:
9033 switch (sel) {
9034 case 0:
9035 /* ignored */
9036 rn = "PRid";
9037 break;
9038 case 1:
9039 check_insn(ctx, ISA_MIPS32R2);
9040 gen_helper_mtc0_ebase(cpu_env, arg);
9041 rn = "EBase";
9042 break;
9043 default:
9044 goto cp0_unimplemented;
9046 break;
9047 case 16:
9048 switch (sel) {
9049 case 0:
9050 gen_helper_mtc0_config0(cpu_env, arg);
9051 rn = "Config";
9052 /* Stop translation as we may have switched the execution mode */
9053 ctx->base.is_jmp = DISAS_STOP;
9054 break;
9055 case 1:
9056 /* ignored, read only */
9057 rn = "Config1";
9058 break;
9059 case 2:
9060 gen_helper_mtc0_config2(cpu_env, arg);
9061 rn = "Config2";
9062 /* Stop translation as we may have switched the execution mode */
9063 ctx->base.is_jmp = DISAS_STOP;
9064 break;
9065 case 3:
9066 gen_helper_mtc0_config3(cpu_env, arg);
9067 rn = "Config3";
9068 /* Stop translation as we may have switched the execution mode */
9069 ctx->base.is_jmp = DISAS_STOP;
9070 break;
9071 case 4:
9072 /* currently ignored */
9073 rn = "Config4";
9074 break;
9075 case 5:
9076 gen_helper_mtc0_config5(cpu_env, arg);
9077 rn = "Config5";
9078 /* Stop translation as we may have switched the execution mode */
9079 ctx->base.is_jmp = DISAS_STOP;
9080 break;
9081 /* 6,7 are implementation dependent */
9082 default:
9083 rn = "Invalid config selector";
9084 goto cp0_unimplemented;
9086 break;
9087 case 17:
9088 switch (sel) {
9089 case 0:
9090 gen_helper_mtc0_lladdr(cpu_env, arg);
9091 rn = "LLAddr";
9092 break;
9093 case 1:
9094 CP0_CHECK(ctx->mrp);
9095 gen_helper_mtc0_maar(cpu_env, arg);
9096 rn = "MAAR";
9097 break;
9098 case 2:
9099 CP0_CHECK(ctx->mrp);
9100 gen_helper_mtc0_maari(cpu_env, arg);
9101 rn = "MAARI";
9102 break;
9103 default:
9104 goto cp0_unimplemented;
9106 break;
9107 case 18:
9108 switch (sel) {
9109 case 0:
9110 case 1:
9111 case 2:
9112 case 3:
9113 case 4:
9114 case 5:
9115 case 6:
9116 case 7:
9117 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9118 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9119 rn = "WatchLo";
9120 break;
9121 default:
9122 goto cp0_unimplemented;
9124 break;
9125 case 19:
9126 switch (sel) {
9127 case 0:
9128 case 1:
9129 case 2:
9130 case 3:
9131 case 4:
9132 case 5:
9133 case 6:
9134 case 7:
9135 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9136 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9137 rn = "WatchHi";
9138 break;
9139 default:
9140 goto cp0_unimplemented;
9142 break;
9143 case 20:
9144 switch (sel) {
9145 case 0:
9146 check_insn(ctx, ISA_MIPS3);
9147 gen_helper_mtc0_xcontext(cpu_env, arg);
9148 rn = "XContext";
9149 break;
9150 default:
9151 goto cp0_unimplemented;
9153 break;
9154 case 21:
9155 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9156 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9157 switch (sel) {
9158 case 0:
9159 gen_helper_mtc0_framemask(cpu_env, arg);
9160 rn = "Framemask";
9161 break;
9162 default:
9163 goto cp0_unimplemented;
9165 break;
9166 case 22:
9167 /* ignored */
9168 rn = "Diagnostic"; /* implementation dependent */
9169 break;
9170 case 23:
9171 switch (sel) {
9172 case 0:
9173 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9174 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9175 gen_save_pc(ctx->base.pc_next + 4);
9176 ctx->base.is_jmp = DISAS_EXIT;
9177 rn = "Debug";
9178 break;
9179 case 1:
9180 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9181 /* Stop translation as we may have switched the execution mode */
9182 ctx->base.is_jmp = DISAS_STOP;
9183 rn = "TraceControl";
9184 goto cp0_unimplemented;
9185 case 2:
9186 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9187 /* Stop translation as we may have switched the execution mode */
9188 ctx->base.is_jmp = DISAS_STOP;
9189 rn = "TraceControl2";
9190 goto cp0_unimplemented;
9191 case 3:
9192 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9193 /* Stop translation as we may have switched the execution mode */
9194 ctx->base.is_jmp = DISAS_STOP;
9195 rn = "UserTraceData";
9196 goto cp0_unimplemented;
9197 case 4:
9198 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9199 /* Stop translation as we may have switched the execution mode */
9200 ctx->base.is_jmp = DISAS_STOP;
9201 rn = "TraceBPC";
9202 goto cp0_unimplemented;
9203 default:
9204 goto cp0_unimplemented;
9206 break;
9207 case 24:
9208 switch (sel) {
9209 case 0:
9210 /* EJTAG support */
9211 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9212 rn = "DEPC";
9213 break;
9214 default:
9215 goto cp0_unimplemented;
9217 break;
9218 case 25:
9219 switch (sel) {
9220 case 0:
9221 gen_helper_mtc0_performance0(cpu_env, arg);
9222 rn = "Performance0";
9223 break;
9224 case 1:
9225 // gen_helper_mtc0_performance1(cpu_env, arg);
9226 rn = "Performance1";
9227 goto cp0_unimplemented;
9228 case 2:
9229 // gen_helper_mtc0_performance2(cpu_env, arg);
9230 rn = "Performance2";
9231 goto cp0_unimplemented;
9232 case 3:
9233 // gen_helper_mtc0_performance3(cpu_env, arg);
9234 rn = "Performance3";
9235 goto cp0_unimplemented;
9236 case 4:
9237 // gen_helper_mtc0_performance4(cpu_env, arg);
9238 rn = "Performance4";
9239 goto cp0_unimplemented;
9240 case 5:
9241 // gen_helper_mtc0_performance5(cpu_env, arg);
9242 rn = "Performance5";
9243 goto cp0_unimplemented;
9244 case 6:
9245 // gen_helper_mtc0_performance6(cpu_env, arg);
9246 rn = "Performance6";
9247 goto cp0_unimplemented;
9248 case 7:
9249 // gen_helper_mtc0_performance7(cpu_env, arg);
9250 rn = "Performance7";
9251 goto cp0_unimplemented;
9252 default:
9253 goto cp0_unimplemented;
9255 break;
9256 case 26:
9257 switch (sel) {
9258 case 0:
9259 gen_helper_mtc0_errctl(cpu_env, arg);
9260 ctx->base.is_jmp = DISAS_STOP;
9261 rn = "ErrCtl";
9262 break;
9263 default:
9264 goto cp0_unimplemented;
9266 break;
9267 case 27:
9268 switch (sel) {
9269 case 0:
9270 case 1:
9271 case 2:
9272 case 3:
9273 /* ignored */
9274 rn = "CacheErr";
9275 break;
9276 default:
9277 goto cp0_unimplemented;
9279 break;
9280 case 28:
9281 switch (sel) {
9282 case 0:
9283 case 2:
9284 case 4:
9285 case 6:
9286 gen_helper_mtc0_taglo(cpu_env, arg);
9287 rn = "TagLo";
9288 break;
9289 case 1:
9290 case 3:
9291 case 5:
9292 case 7:
9293 gen_helper_mtc0_datalo(cpu_env, arg);
9294 rn = "DataLo";
9295 break;
9296 default:
9297 goto cp0_unimplemented;
9299 break;
9300 case 29:
9301 switch (sel) {
9302 case 0:
9303 case 2:
9304 case 4:
9305 case 6:
9306 gen_helper_mtc0_taghi(cpu_env, arg);
9307 rn = "TagHi";
9308 break;
9309 case 1:
9310 case 3:
9311 case 5:
9312 case 7:
9313 gen_helper_mtc0_datahi(cpu_env, arg);
9314 rn = "DataHi";
9315 break;
9316 default:
9317 rn = "invalid sel";
9318 goto cp0_unimplemented;
9320 break;
9321 case 30:
9322 switch (sel) {
9323 case 0:
9324 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9325 rn = "ErrorEPC";
9326 break;
9327 default:
9328 goto cp0_unimplemented;
9330 break;
9331 case 31:
9332 switch (sel) {
9333 case 0:
9334 /* EJTAG support */
9335 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9336 rn = "DESAVE";
9337 break;
9338 case 2:
9339 case 3:
9340 case 4:
9341 case 5:
9342 case 6:
9343 case 7:
9344 CP0_CHECK(ctx->kscrexist & (1 << sel));
9345 tcg_gen_st_tl(arg, cpu_env,
9346 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9347 rn = "KScratch";
9348 break;
9349 default:
9350 goto cp0_unimplemented;
9352 break;
9353 default:
9354 goto cp0_unimplemented;
9356 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9358 /* For simplicity assume that all writes can cause interrupts. */
9359 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9360 gen_io_end();
9361 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9362 * translated code to check for pending interrupts. */
9363 gen_save_pc(ctx->base.pc_next + 4);
9364 ctx->base.is_jmp = DISAS_EXIT;
9366 return;
9368 cp0_unimplemented:
9369 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9371 #endif /* TARGET_MIPS64 */
9373 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9374 int u, int sel, int h)
9376 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9377 TCGv t0 = tcg_temp_local_new();
9379 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9380 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9381 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9382 tcg_gen_movi_tl(t0, -1);
9383 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9384 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9385 tcg_gen_movi_tl(t0, -1);
9386 else if (u == 0) {
9387 switch (rt) {
9388 case 1:
9389 switch (sel) {
9390 case 1:
9391 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9392 break;
9393 case 2:
9394 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9395 break;
9396 default:
9397 goto die;
9398 break;
9400 break;
9401 case 2:
9402 switch (sel) {
9403 case 1:
9404 gen_helper_mftc0_tcstatus(t0, cpu_env);
9405 break;
9406 case 2:
9407 gen_helper_mftc0_tcbind(t0, cpu_env);
9408 break;
9409 case 3:
9410 gen_helper_mftc0_tcrestart(t0, cpu_env);
9411 break;
9412 case 4:
9413 gen_helper_mftc0_tchalt(t0, cpu_env);
9414 break;
9415 case 5:
9416 gen_helper_mftc0_tccontext(t0, cpu_env);
9417 break;
9418 case 6:
9419 gen_helper_mftc0_tcschedule(t0, cpu_env);
9420 break;
9421 case 7:
9422 gen_helper_mftc0_tcschefback(t0, cpu_env);
9423 break;
9424 default:
9425 gen_mfc0(ctx, t0, rt, sel);
9426 break;
9428 break;
9429 case 10:
9430 switch (sel) {
9431 case 0:
9432 gen_helper_mftc0_entryhi(t0, cpu_env);
9433 break;
9434 default:
9435 gen_mfc0(ctx, t0, rt, sel);
9436 break;
9438 case 12:
9439 switch (sel) {
9440 case 0:
9441 gen_helper_mftc0_status(t0, cpu_env);
9442 break;
9443 default:
9444 gen_mfc0(ctx, t0, rt, sel);
9445 break;
9447 case 13:
9448 switch (sel) {
9449 case 0:
9450 gen_helper_mftc0_cause(t0, cpu_env);
9451 break;
9452 default:
9453 goto die;
9454 break;
9456 break;
9457 case 14:
9458 switch (sel) {
9459 case 0:
9460 gen_helper_mftc0_epc(t0, cpu_env);
9461 break;
9462 default:
9463 goto die;
9464 break;
9466 break;
9467 case 15:
9468 switch (sel) {
9469 case 1:
9470 gen_helper_mftc0_ebase(t0, cpu_env);
9471 break;
9472 default:
9473 goto die;
9474 break;
9476 break;
9477 case 16:
9478 switch (sel) {
9479 case 0:
9480 case 1:
9481 case 2:
9482 case 3:
9483 case 4:
9484 case 5:
9485 case 6:
9486 case 7:
9487 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9488 break;
9489 default:
9490 goto die;
9491 break;
9493 break;
9494 case 23:
9495 switch (sel) {
9496 case 0:
9497 gen_helper_mftc0_debug(t0, cpu_env);
9498 break;
9499 default:
9500 gen_mfc0(ctx, t0, rt, sel);
9501 break;
9503 break;
9504 default:
9505 gen_mfc0(ctx, t0, rt, sel);
9507 } else switch (sel) {
9508 /* GPR registers. */
9509 case 0:
9510 gen_helper_1e0i(mftgpr, t0, rt);
9511 break;
9512 /* Auxiliary CPU registers */
9513 case 1:
9514 switch (rt) {
9515 case 0:
9516 gen_helper_1e0i(mftlo, t0, 0);
9517 break;
9518 case 1:
9519 gen_helper_1e0i(mfthi, t0, 0);
9520 break;
9521 case 2:
9522 gen_helper_1e0i(mftacx, t0, 0);
9523 break;
9524 case 4:
9525 gen_helper_1e0i(mftlo, t0, 1);
9526 break;
9527 case 5:
9528 gen_helper_1e0i(mfthi, t0, 1);
9529 break;
9530 case 6:
9531 gen_helper_1e0i(mftacx, t0, 1);
9532 break;
9533 case 8:
9534 gen_helper_1e0i(mftlo, t0, 2);
9535 break;
9536 case 9:
9537 gen_helper_1e0i(mfthi, t0, 2);
9538 break;
9539 case 10:
9540 gen_helper_1e0i(mftacx, t0, 2);
9541 break;
9542 case 12:
9543 gen_helper_1e0i(mftlo, t0, 3);
9544 break;
9545 case 13:
9546 gen_helper_1e0i(mfthi, t0, 3);
9547 break;
9548 case 14:
9549 gen_helper_1e0i(mftacx, t0, 3);
9550 break;
9551 case 16:
9552 gen_helper_mftdsp(t0, cpu_env);
9553 break;
9554 default:
9555 goto die;
9557 break;
9558 /* Floating point (COP1). */
9559 case 2:
9560 /* XXX: For now we support only a single FPU context. */
9561 if (h == 0) {
9562 TCGv_i32 fp0 = tcg_temp_new_i32();
9564 gen_load_fpr32(ctx, fp0, rt);
9565 tcg_gen_ext_i32_tl(t0, fp0);
9566 tcg_temp_free_i32(fp0);
9567 } else {
9568 TCGv_i32 fp0 = tcg_temp_new_i32();
9570 gen_load_fpr32h(ctx, fp0, rt);
9571 tcg_gen_ext_i32_tl(t0, fp0);
9572 tcg_temp_free_i32(fp0);
9574 break;
9575 case 3:
9576 /* XXX: For now we support only a single FPU context. */
9577 gen_helper_1e0i(cfc1, t0, rt);
9578 break;
9579 /* COP2: Not implemented. */
9580 case 4:
9581 case 5:
9582 /* fall through */
9583 default:
9584 goto die;
9586 trace_mips_translate_tr("mftr", rt, u, sel, h);
9587 gen_store_gpr(t0, rd);
9588 tcg_temp_free(t0);
9589 return;
9591 die:
9592 tcg_temp_free(t0);
9593 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9594 generate_exception_end(ctx, EXCP_RI);
9597 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9598 int u, int sel, int h)
9600 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9601 TCGv t0 = tcg_temp_local_new();
9603 gen_load_gpr(t0, rt);
9604 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9605 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9606 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9607 /* NOP */ ;
9608 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9609 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9610 /* NOP */ ;
9611 else if (u == 0) {
9612 switch (rd) {
9613 case 1:
9614 switch (sel) {
9615 case 1:
9616 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9617 break;
9618 case 2:
9619 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9620 break;
9621 default:
9622 goto die;
9623 break;
9625 break;
9626 case 2:
9627 switch (sel) {
9628 case 1:
9629 gen_helper_mttc0_tcstatus(cpu_env, t0);
9630 break;
9631 case 2:
9632 gen_helper_mttc0_tcbind(cpu_env, t0);
9633 break;
9634 case 3:
9635 gen_helper_mttc0_tcrestart(cpu_env, t0);
9636 break;
9637 case 4:
9638 gen_helper_mttc0_tchalt(cpu_env, t0);
9639 break;
9640 case 5:
9641 gen_helper_mttc0_tccontext(cpu_env, t0);
9642 break;
9643 case 6:
9644 gen_helper_mttc0_tcschedule(cpu_env, t0);
9645 break;
9646 case 7:
9647 gen_helper_mttc0_tcschefback(cpu_env, t0);
9648 break;
9649 default:
9650 gen_mtc0(ctx, t0, rd, sel);
9651 break;
9653 break;
9654 case 10:
9655 switch (sel) {
9656 case 0:
9657 gen_helper_mttc0_entryhi(cpu_env, t0);
9658 break;
9659 default:
9660 gen_mtc0(ctx, t0, rd, sel);
9661 break;
9663 case 12:
9664 switch (sel) {
9665 case 0:
9666 gen_helper_mttc0_status(cpu_env, t0);
9667 break;
9668 default:
9669 gen_mtc0(ctx, t0, rd, sel);
9670 break;
9672 case 13:
9673 switch (sel) {
9674 case 0:
9675 gen_helper_mttc0_cause(cpu_env, t0);
9676 break;
9677 default:
9678 goto die;
9679 break;
9681 break;
9682 case 15:
9683 switch (sel) {
9684 case 1:
9685 gen_helper_mttc0_ebase(cpu_env, t0);
9686 break;
9687 default:
9688 goto die;
9689 break;
9691 break;
9692 case 23:
9693 switch (sel) {
9694 case 0:
9695 gen_helper_mttc0_debug(cpu_env, t0);
9696 break;
9697 default:
9698 gen_mtc0(ctx, t0, rd, sel);
9699 break;
9701 break;
9702 default:
9703 gen_mtc0(ctx, t0, rd, sel);
9705 } else switch (sel) {
9706 /* GPR registers. */
9707 case 0:
9708 gen_helper_0e1i(mttgpr, t0, rd);
9709 break;
9710 /* Auxiliary CPU registers */
9711 case 1:
9712 switch (rd) {
9713 case 0:
9714 gen_helper_0e1i(mttlo, t0, 0);
9715 break;
9716 case 1:
9717 gen_helper_0e1i(mtthi, t0, 0);
9718 break;
9719 case 2:
9720 gen_helper_0e1i(mttacx, t0, 0);
9721 break;
9722 case 4:
9723 gen_helper_0e1i(mttlo, t0, 1);
9724 break;
9725 case 5:
9726 gen_helper_0e1i(mtthi, t0, 1);
9727 break;
9728 case 6:
9729 gen_helper_0e1i(mttacx, t0, 1);
9730 break;
9731 case 8:
9732 gen_helper_0e1i(mttlo, t0, 2);
9733 break;
9734 case 9:
9735 gen_helper_0e1i(mtthi, t0, 2);
9736 break;
9737 case 10:
9738 gen_helper_0e1i(mttacx, t0, 2);
9739 break;
9740 case 12:
9741 gen_helper_0e1i(mttlo, t0, 3);
9742 break;
9743 case 13:
9744 gen_helper_0e1i(mtthi, t0, 3);
9745 break;
9746 case 14:
9747 gen_helper_0e1i(mttacx, t0, 3);
9748 break;
9749 case 16:
9750 gen_helper_mttdsp(cpu_env, t0);
9751 break;
9752 default:
9753 goto die;
9755 break;
9756 /* Floating point (COP1). */
9757 case 2:
9758 /* XXX: For now we support only a single FPU context. */
9759 if (h == 0) {
9760 TCGv_i32 fp0 = tcg_temp_new_i32();
9762 tcg_gen_trunc_tl_i32(fp0, t0);
9763 gen_store_fpr32(ctx, fp0, rd);
9764 tcg_temp_free_i32(fp0);
9765 } else {
9766 TCGv_i32 fp0 = tcg_temp_new_i32();
9768 tcg_gen_trunc_tl_i32(fp0, t0);
9769 gen_store_fpr32h(ctx, fp0, rd);
9770 tcg_temp_free_i32(fp0);
9772 break;
9773 case 3:
9774 /* XXX: For now we support only a single FPU context. */
9776 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9778 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9779 tcg_temp_free_i32(fs_tmp);
9781 /* Stop translation as we may have changed hflags */
9782 ctx->base.is_jmp = DISAS_STOP;
9783 break;
9784 /* COP2: Not implemented. */
9785 case 4:
9786 case 5:
9787 /* fall through */
9788 default:
9789 goto die;
9791 trace_mips_translate_tr("mttr", rd, u, sel, h);
9792 tcg_temp_free(t0);
9793 return;
9795 die:
9796 tcg_temp_free(t0);
9797 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9798 generate_exception_end(ctx, EXCP_RI);
9801 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9803 const char *opn = "ldst";
9805 check_cp0_enabled(ctx);
9806 switch (opc) {
9807 case OPC_MFC0:
9808 if (rt == 0) {
9809 /* Treat as NOP. */
9810 return;
9812 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9813 opn = "mfc0";
9814 break;
9815 case OPC_MTC0:
9817 TCGv t0 = tcg_temp_new();
9819 gen_load_gpr(t0, rt);
9820 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9821 tcg_temp_free(t0);
9823 opn = "mtc0";
9824 break;
9825 #if defined(TARGET_MIPS64)
9826 case OPC_DMFC0:
9827 check_insn(ctx, ISA_MIPS3);
9828 if (rt == 0) {
9829 /* Treat as NOP. */
9830 return;
9832 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9833 opn = "dmfc0";
9834 break;
9835 case OPC_DMTC0:
9836 check_insn(ctx, ISA_MIPS3);
9838 TCGv t0 = tcg_temp_new();
9840 gen_load_gpr(t0, rt);
9841 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9842 tcg_temp_free(t0);
9844 opn = "dmtc0";
9845 break;
9846 #endif
9847 case OPC_MFHC0:
9848 check_mvh(ctx);
9849 if (rt == 0) {
9850 /* Treat as NOP. */
9851 return;
9853 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9854 opn = "mfhc0";
9855 break;
9856 case OPC_MTHC0:
9857 check_mvh(ctx);
9859 TCGv t0 = tcg_temp_new();
9860 gen_load_gpr(t0, rt);
9861 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9862 tcg_temp_free(t0);
9864 opn = "mthc0";
9865 break;
9866 case OPC_MFTR:
9867 check_cp0_enabled(ctx);
9868 if (rd == 0) {
9869 /* Treat as NOP. */
9870 return;
9872 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9873 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9874 opn = "mftr";
9875 break;
9876 case OPC_MTTR:
9877 check_cp0_enabled(ctx);
9878 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9879 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9880 opn = "mttr";
9881 break;
9882 case OPC_TLBWI:
9883 opn = "tlbwi";
9884 if (!env->tlb->helper_tlbwi)
9885 goto die;
9886 gen_helper_tlbwi(cpu_env);
9887 break;
9888 case OPC_TLBINV:
9889 opn = "tlbinv";
9890 if (ctx->ie >= 2) {
9891 if (!env->tlb->helper_tlbinv) {
9892 goto die;
9894 gen_helper_tlbinv(cpu_env);
9895 } /* treat as nop if TLBINV not supported */
9896 break;
9897 case OPC_TLBINVF:
9898 opn = "tlbinvf";
9899 if (ctx->ie >= 2) {
9900 if (!env->tlb->helper_tlbinvf) {
9901 goto die;
9903 gen_helper_tlbinvf(cpu_env);
9904 } /* treat as nop if TLBINV not supported */
9905 break;
9906 case OPC_TLBWR:
9907 opn = "tlbwr";
9908 if (!env->tlb->helper_tlbwr)
9909 goto die;
9910 gen_helper_tlbwr(cpu_env);
9911 break;
9912 case OPC_TLBP:
9913 opn = "tlbp";
9914 if (!env->tlb->helper_tlbp)
9915 goto die;
9916 gen_helper_tlbp(cpu_env);
9917 break;
9918 case OPC_TLBR:
9919 opn = "tlbr";
9920 if (!env->tlb->helper_tlbr)
9921 goto die;
9922 gen_helper_tlbr(cpu_env);
9923 break;
9924 case OPC_ERET: /* OPC_ERETNC */
9925 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9926 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9927 goto die;
9928 } else {
9929 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9930 if (ctx->opcode & (1 << bit_shift)) {
9931 /* OPC_ERETNC */
9932 opn = "eretnc";
9933 check_insn(ctx, ISA_MIPS32R5);
9934 gen_helper_eretnc(cpu_env);
9935 } else {
9936 /* OPC_ERET */
9937 opn = "eret";
9938 check_insn(ctx, ISA_MIPS2);
9939 gen_helper_eret(cpu_env);
9941 ctx->base.is_jmp = DISAS_EXIT;
9943 break;
9944 case OPC_DERET:
9945 opn = "deret";
9946 check_insn(ctx, ISA_MIPS32);
9947 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9948 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9949 goto die;
9951 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9952 MIPS_INVAL(opn);
9953 generate_exception_end(ctx, EXCP_RI);
9954 } else {
9955 gen_helper_deret(cpu_env);
9956 ctx->base.is_jmp = DISAS_EXIT;
9958 break;
9959 case OPC_WAIT:
9960 opn = "wait";
9961 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9962 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9963 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9964 goto die;
9966 /* If we get an exception, we want to restart at next instruction */
9967 ctx->base.pc_next += 4;
9968 save_cpu_state(ctx, 1);
9969 ctx->base.pc_next -= 4;
9970 gen_helper_wait(cpu_env);
9971 ctx->base.is_jmp = DISAS_NORETURN;
9972 break;
9973 default:
9974 die:
9975 MIPS_INVAL(opn);
9976 generate_exception_end(ctx, EXCP_RI);
9977 return;
9979 (void)opn; /* avoid a compiler warning */
9981 #endif /* !CONFIG_USER_ONLY */
9983 /* CP1 Branches (before delay slot) */
9984 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9985 int32_t cc, int32_t offset)
9987 target_ulong btarget;
9988 TCGv_i32 t0 = tcg_temp_new_i32();
9990 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9991 generate_exception_end(ctx, EXCP_RI);
9992 goto out;
9995 if (cc != 0)
9996 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9998 btarget = ctx->base.pc_next + 4 + offset;
10000 switch (op) {
10001 case OPC_BC1F:
10002 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10003 tcg_gen_not_i32(t0, t0);
10004 tcg_gen_andi_i32(t0, t0, 1);
10005 tcg_gen_extu_i32_tl(bcond, t0);
10006 goto not_likely;
10007 case OPC_BC1FL:
10008 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10009 tcg_gen_not_i32(t0, t0);
10010 tcg_gen_andi_i32(t0, t0, 1);
10011 tcg_gen_extu_i32_tl(bcond, t0);
10012 goto likely;
10013 case OPC_BC1T:
10014 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10015 tcg_gen_andi_i32(t0, t0, 1);
10016 tcg_gen_extu_i32_tl(bcond, t0);
10017 goto not_likely;
10018 case OPC_BC1TL:
10019 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10020 tcg_gen_andi_i32(t0, t0, 1);
10021 tcg_gen_extu_i32_tl(bcond, t0);
10022 likely:
10023 ctx->hflags |= MIPS_HFLAG_BL;
10024 break;
10025 case OPC_BC1FANY2:
10027 TCGv_i32 t1 = tcg_temp_new_i32();
10028 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10029 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10030 tcg_gen_nand_i32(t0, t0, t1);
10031 tcg_temp_free_i32(t1);
10032 tcg_gen_andi_i32(t0, t0, 1);
10033 tcg_gen_extu_i32_tl(bcond, t0);
10035 goto not_likely;
10036 case OPC_BC1TANY2:
10038 TCGv_i32 t1 = tcg_temp_new_i32();
10039 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10040 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10041 tcg_gen_or_i32(t0, t0, t1);
10042 tcg_temp_free_i32(t1);
10043 tcg_gen_andi_i32(t0, t0, 1);
10044 tcg_gen_extu_i32_tl(bcond, t0);
10046 goto not_likely;
10047 case OPC_BC1FANY4:
10049 TCGv_i32 t1 = tcg_temp_new_i32();
10050 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10051 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10052 tcg_gen_and_i32(t0, t0, t1);
10053 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10054 tcg_gen_and_i32(t0, t0, t1);
10055 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10056 tcg_gen_nand_i32(t0, t0, t1);
10057 tcg_temp_free_i32(t1);
10058 tcg_gen_andi_i32(t0, t0, 1);
10059 tcg_gen_extu_i32_tl(bcond, t0);
10061 goto not_likely;
10062 case OPC_BC1TANY4:
10064 TCGv_i32 t1 = tcg_temp_new_i32();
10065 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10066 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10067 tcg_gen_or_i32(t0, t0, t1);
10068 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10069 tcg_gen_or_i32(t0, t0, t1);
10070 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10071 tcg_gen_or_i32(t0, t0, t1);
10072 tcg_temp_free_i32(t1);
10073 tcg_gen_andi_i32(t0, t0, 1);
10074 tcg_gen_extu_i32_tl(bcond, t0);
10076 not_likely:
10077 ctx->hflags |= MIPS_HFLAG_BC;
10078 break;
10079 default:
10080 MIPS_INVAL("cp1 cond branch");
10081 generate_exception_end(ctx, EXCP_RI);
10082 goto out;
10084 ctx->btarget = btarget;
10085 ctx->hflags |= MIPS_HFLAG_BDS32;
10086 out:
10087 tcg_temp_free_i32(t0);
10090 /* R6 CP1 Branches */
10091 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10092 int32_t ft, int32_t offset,
10093 int delayslot_size)
10095 target_ulong btarget;
10096 TCGv_i64 t0 = tcg_temp_new_i64();
10098 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10099 #ifdef MIPS_DEBUG_DISAS
10100 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10101 "\n", ctx->base.pc_next);
10102 #endif
10103 generate_exception_end(ctx, EXCP_RI);
10104 goto out;
10107 gen_load_fpr64(ctx, t0, ft);
10108 tcg_gen_andi_i64(t0, t0, 1);
10110 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10112 switch (op) {
10113 case OPC_BC1EQZ:
10114 tcg_gen_xori_i64(t0, t0, 1);
10115 ctx->hflags |= MIPS_HFLAG_BC;
10116 break;
10117 case OPC_BC1NEZ:
10118 /* t0 already set */
10119 ctx->hflags |= MIPS_HFLAG_BC;
10120 break;
10121 default:
10122 MIPS_INVAL("cp1 cond branch");
10123 generate_exception_end(ctx, EXCP_RI);
10124 goto out;
10127 tcg_gen_trunc_i64_tl(bcond, t0);
10129 ctx->btarget = btarget;
10131 switch (delayslot_size) {
10132 case 2:
10133 ctx->hflags |= MIPS_HFLAG_BDS16;
10134 break;
10135 case 4:
10136 ctx->hflags |= MIPS_HFLAG_BDS32;
10137 break;
10140 out:
10141 tcg_temp_free_i64(t0);
10144 /* Coprocessor 1 (FPU) */
10146 #define FOP(func, fmt) (((fmt) << 21) | (func))
10148 enum fopcode {
10149 OPC_ADD_S = FOP(0, FMT_S),
10150 OPC_SUB_S = FOP(1, FMT_S),
10151 OPC_MUL_S = FOP(2, FMT_S),
10152 OPC_DIV_S = FOP(3, FMT_S),
10153 OPC_SQRT_S = FOP(4, FMT_S),
10154 OPC_ABS_S = FOP(5, FMT_S),
10155 OPC_MOV_S = FOP(6, FMT_S),
10156 OPC_NEG_S = FOP(7, FMT_S),
10157 OPC_ROUND_L_S = FOP(8, FMT_S),
10158 OPC_TRUNC_L_S = FOP(9, FMT_S),
10159 OPC_CEIL_L_S = FOP(10, FMT_S),
10160 OPC_FLOOR_L_S = FOP(11, FMT_S),
10161 OPC_ROUND_W_S = FOP(12, FMT_S),
10162 OPC_TRUNC_W_S = FOP(13, FMT_S),
10163 OPC_CEIL_W_S = FOP(14, FMT_S),
10164 OPC_FLOOR_W_S = FOP(15, FMT_S),
10165 OPC_SEL_S = FOP(16, FMT_S),
10166 OPC_MOVCF_S = FOP(17, FMT_S),
10167 OPC_MOVZ_S = FOP(18, FMT_S),
10168 OPC_MOVN_S = FOP(19, FMT_S),
10169 OPC_SELEQZ_S = FOP(20, FMT_S),
10170 OPC_RECIP_S = FOP(21, FMT_S),
10171 OPC_RSQRT_S = FOP(22, FMT_S),
10172 OPC_SELNEZ_S = FOP(23, FMT_S),
10173 OPC_MADDF_S = FOP(24, FMT_S),
10174 OPC_MSUBF_S = FOP(25, FMT_S),
10175 OPC_RINT_S = FOP(26, FMT_S),
10176 OPC_CLASS_S = FOP(27, FMT_S),
10177 OPC_MIN_S = FOP(28, FMT_S),
10178 OPC_RECIP2_S = FOP(28, FMT_S),
10179 OPC_MINA_S = FOP(29, FMT_S),
10180 OPC_RECIP1_S = FOP(29, FMT_S),
10181 OPC_MAX_S = FOP(30, FMT_S),
10182 OPC_RSQRT1_S = FOP(30, FMT_S),
10183 OPC_MAXA_S = FOP(31, FMT_S),
10184 OPC_RSQRT2_S = FOP(31, FMT_S),
10185 OPC_CVT_D_S = FOP(33, FMT_S),
10186 OPC_CVT_W_S = FOP(36, FMT_S),
10187 OPC_CVT_L_S = FOP(37, FMT_S),
10188 OPC_CVT_PS_S = FOP(38, FMT_S),
10189 OPC_CMP_F_S = FOP (48, FMT_S),
10190 OPC_CMP_UN_S = FOP (49, FMT_S),
10191 OPC_CMP_EQ_S = FOP (50, FMT_S),
10192 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10193 OPC_CMP_OLT_S = FOP (52, FMT_S),
10194 OPC_CMP_ULT_S = FOP (53, FMT_S),
10195 OPC_CMP_OLE_S = FOP (54, FMT_S),
10196 OPC_CMP_ULE_S = FOP (55, FMT_S),
10197 OPC_CMP_SF_S = FOP (56, FMT_S),
10198 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10199 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10200 OPC_CMP_NGL_S = FOP (59, FMT_S),
10201 OPC_CMP_LT_S = FOP (60, FMT_S),
10202 OPC_CMP_NGE_S = FOP (61, FMT_S),
10203 OPC_CMP_LE_S = FOP (62, FMT_S),
10204 OPC_CMP_NGT_S = FOP (63, FMT_S),
10206 OPC_ADD_D = FOP(0, FMT_D),
10207 OPC_SUB_D = FOP(1, FMT_D),
10208 OPC_MUL_D = FOP(2, FMT_D),
10209 OPC_DIV_D = FOP(3, FMT_D),
10210 OPC_SQRT_D = FOP(4, FMT_D),
10211 OPC_ABS_D = FOP(5, FMT_D),
10212 OPC_MOV_D = FOP(6, FMT_D),
10213 OPC_NEG_D = FOP(7, FMT_D),
10214 OPC_ROUND_L_D = FOP(8, FMT_D),
10215 OPC_TRUNC_L_D = FOP(9, FMT_D),
10216 OPC_CEIL_L_D = FOP(10, FMT_D),
10217 OPC_FLOOR_L_D = FOP(11, FMT_D),
10218 OPC_ROUND_W_D = FOP(12, FMT_D),
10219 OPC_TRUNC_W_D = FOP(13, FMT_D),
10220 OPC_CEIL_W_D = FOP(14, FMT_D),
10221 OPC_FLOOR_W_D = FOP(15, FMT_D),
10222 OPC_SEL_D = FOP(16, FMT_D),
10223 OPC_MOVCF_D = FOP(17, FMT_D),
10224 OPC_MOVZ_D = FOP(18, FMT_D),
10225 OPC_MOVN_D = FOP(19, FMT_D),
10226 OPC_SELEQZ_D = FOP(20, FMT_D),
10227 OPC_RECIP_D = FOP(21, FMT_D),
10228 OPC_RSQRT_D = FOP(22, FMT_D),
10229 OPC_SELNEZ_D = FOP(23, FMT_D),
10230 OPC_MADDF_D = FOP(24, FMT_D),
10231 OPC_MSUBF_D = FOP(25, FMT_D),
10232 OPC_RINT_D = FOP(26, FMT_D),
10233 OPC_CLASS_D = FOP(27, FMT_D),
10234 OPC_MIN_D = FOP(28, FMT_D),
10235 OPC_RECIP2_D = FOP(28, FMT_D),
10236 OPC_MINA_D = FOP(29, FMT_D),
10237 OPC_RECIP1_D = FOP(29, FMT_D),
10238 OPC_MAX_D = FOP(30, FMT_D),
10239 OPC_RSQRT1_D = FOP(30, FMT_D),
10240 OPC_MAXA_D = FOP(31, FMT_D),
10241 OPC_RSQRT2_D = FOP(31, FMT_D),
10242 OPC_CVT_S_D = FOP(32, FMT_D),
10243 OPC_CVT_W_D = FOP(36, FMT_D),
10244 OPC_CVT_L_D = FOP(37, FMT_D),
10245 OPC_CMP_F_D = FOP (48, FMT_D),
10246 OPC_CMP_UN_D = FOP (49, FMT_D),
10247 OPC_CMP_EQ_D = FOP (50, FMT_D),
10248 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10249 OPC_CMP_OLT_D = FOP (52, FMT_D),
10250 OPC_CMP_ULT_D = FOP (53, FMT_D),
10251 OPC_CMP_OLE_D = FOP (54, FMT_D),
10252 OPC_CMP_ULE_D = FOP (55, FMT_D),
10253 OPC_CMP_SF_D = FOP (56, FMT_D),
10254 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10255 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10256 OPC_CMP_NGL_D = FOP (59, FMT_D),
10257 OPC_CMP_LT_D = FOP (60, FMT_D),
10258 OPC_CMP_NGE_D = FOP (61, FMT_D),
10259 OPC_CMP_LE_D = FOP (62, FMT_D),
10260 OPC_CMP_NGT_D = FOP (63, FMT_D),
10262 OPC_CVT_S_W = FOP(32, FMT_W),
10263 OPC_CVT_D_W = FOP(33, FMT_W),
10264 OPC_CVT_S_L = FOP(32, FMT_L),
10265 OPC_CVT_D_L = FOP(33, FMT_L),
10266 OPC_CVT_PS_PW = FOP(38, FMT_W),
10268 OPC_ADD_PS = FOP(0, FMT_PS),
10269 OPC_SUB_PS = FOP(1, FMT_PS),
10270 OPC_MUL_PS = FOP(2, FMT_PS),
10271 OPC_DIV_PS = FOP(3, FMT_PS),
10272 OPC_ABS_PS = FOP(5, FMT_PS),
10273 OPC_MOV_PS = FOP(6, FMT_PS),
10274 OPC_NEG_PS = FOP(7, FMT_PS),
10275 OPC_MOVCF_PS = FOP(17, FMT_PS),
10276 OPC_MOVZ_PS = FOP(18, FMT_PS),
10277 OPC_MOVN_PS = FOP(19, FMT_PS),
10278 OPC_ADDR_PS = FOP(24, FMT_PS),
10279 OPC_MULR_PS = FOP(26, FMT_PS),
10280 OPC_RECIP2_PS = FOP(28, FMT_PS),
10281 OPC_RECIP1_PS = FOP(29, FMT_PS),
10282 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10283 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10285 OPC_CVT_S_PU = FOP(32, FMT_PS),
10286 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10287 OPC_CVT_S_PL = FOP(40, FMT_PS),
10288 OPC_PLL_PS = FOP(44, FMT_PS),
10289 OPC_PLU_PS = FOP(45, FMT_PS),
10290 OPC_PUL_PS = FOP(46, FMT_PS),
10291 OPC_PUU_PS = FOP(47, FMT_PS),
10292 OPC_CMP_F_PS = FOP (48, FMT_PS),
10293 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10294 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10295 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10296 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10297 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10298 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10299 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10300 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10301 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10302 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10303 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10304 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10305 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10306 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10307 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10310 enum r6_f_cmp_op {
10311 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10312 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10313 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10314 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10315 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10316 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10317 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10318 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10319 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10320 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10321 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10322 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10323 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10324 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10325 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10326 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10327 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10328 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10329 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10330 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10331 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10332 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10334 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10335 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10336 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10337 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10338 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10339 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10340 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10341 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10342 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10343 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10344 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10345 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10346 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10347 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10348 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10349 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10350 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10351 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10352 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10353 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10354 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10355 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10357 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10359 TCGv t0 = tcg_temp_new();
10361 switch (opc) {
10362 case OPC_MFC1:
10364 TCGv_i32 fp0 = tcg_temp_new_i32();
10366 gen_load_fpr32(ctx, fp0, fs);
10367 tcg_gen_ext_i32_tl(t0, fp0);
10368 tcg_temp_free_i32(fp0);
10370 gen_store_gpr(t0, rt);
10371 break;
10372 case OPC_MTC1:
10373 gen_load_gpr(t0, rt);
10375 TCGv_i32 fp0 = tcg_temp_new_i32();
10377 tcg_gen_trunc_tl_i32(fp0, t0);
10378 gen_store_fpr32(ctx, fp0, fs);
10379 tcg_temp_free_i32(fp0);
10381 break;
10382 case OPC_CFC1:
10383 gen_helper_1e0i(cfc1, t0, fs);
10384 gen_store_gpr(t0, rt);
10385 break;
10386 case OPC_CTC1:
10387 gen_load_gpr(t0, rt);
10388 save_cpu_state(ctx, 0);
10390 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10392 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10393 tcg_temp_free_i32(fs_tmp);
10395 /* Stop translation as we may have changed hflags */
10396 ctx->base.is_jmp = DISAS_STOP;
10397 break;
10398 #if defined(TARGET_MIPS64)
10399 case OPC_DMFC1:
10400 gen_load_fpr64(ctx, t0, fs);
10401 gen_store_gpr(t0, rt);
10402 break;
10403 case OPC_DMTC1:
10404 gen_load_gpr(t0, rt);
10405 gen_store_fpr64(ctx, t0, fs);
10406 break;
10407 #endif
10408 case OPC_MFHC1:
10410 TCGv_i32 fp0 = tcg_temp_new_i32();
10412 gen_load_fpr32h(ctx, fp0, fs);
10413 tcg_gen_ext_i32_tl(t0, fp0);
10414 tcg_temp_free_i32(fp0);
10416 gen_store_gpr(t0, rt);
10417 break;
10418 case OPC_MTHC1:
10419 gen_load_gpr(t0, rt);
10421 TCGv_i32 fp0 = tcg_temp_new_i32();
10423 tcg_gen_trunc_tl_i32(fp0, t0);
10424 gen_store_fpr32h(ctx, fp0, fs);
10425 tcg_temp_free_i32(fp0);
10427 break;
10428 default:
10429 MIPS_INVAL("cp1 move");
10430 generate_exception_end(ctx, EXCP_RI);
10431 goto out;
10434 out:
10435 tcg_temp_free(t0);
10438 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10440 TCGLabel *l1;
10441 TCGCond cond;
10442 TCGv_i32 t0;
10444 if (rd == 0) {
10445 /* Treat as NOP. */
10446 return;
10449 if (tf)
10450 cond = TCG_COND_EQ;
10451 else
10452 cond = TCG_COND_NE;
10454 l1 = gen_new_label();
10455 t0 = tcg_temp_new_i32();
10456 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10457 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10458 tcg_temp_free_i32(t0);
10459 if (rs == 0) {
10460 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10461 } else {
10462 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10464 gen_set_label(l1);
10467 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10468 int tf)
10470 int cond;
10471 TCGv_i32 t0 = tcg_temp_new_i32();
10472 TCGLabel *l1 = gen_new_label();
10474 if (tf)
10475 cond = TCG_COND_EQ;
10476 else
10477 cond = TCG_COND_NE;
10479 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10480 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10481 gen_load_fpr32(ctx, t0, fs);
10482 gen_store_fpr32(ctx, t0, fd);
10483 gen_set_label(l1);
10484 tcg_temp_free_i32(t0);
10487 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10489 int cond;
10490 TCGv_i32 t0 = tcg_temp_new_i32();
10491 TCGv_i64 fp0;
10492 TCGLabel *l1 = gen_new_label();
10494 if (tf)
10495 cond = TCG_COND_EQ;
10496 else
10497 cond = TCG_COND_NE;
10499 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10500 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10501 tcg_temp_free_i32(t0);
10502 fp0 = tcg_temp_new_i64();
10503 gen_load_fpr64(ctx, fp0, fs);
10504 gen_store_fpr64(ctx, fp0, fd);
10505 tcg_temp_free_i64(fp0);
10506 gen_set_label(l1);
10509 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10510 int cc, int tf)
10512 int cond;
10513 TCGv_i32 t0 = tcg_temp_new_i32();
10514 TCGLabel *l1 = gen_new_label();
10515 TCGLabel *l2 = gen_new_label();
10517 if (tf)
10518 cond = TCG_COND_EQ;
10519 else
10520 cond = TCG_COND_NE;
10522 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10523 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10524 gen_load_fpr32(ctx, t0, fs);
10525 gen_store_fpr32(ctx, t0, fd);
10526 gen_set_label(l1);
10528 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10529 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10530 gen_load_fpr32h(ctx, t0, fs);
10531 gen_store_fpr32h(ctx, t0, fd);
10532 tcg_temp_free_i32(t0);
10533 gen_set_label(l2);
10536 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10537 int fs)
10539 TCGv_i32 t1 = tcg_const_i32(0);
10540 TCGv_i32 fp0 = tcg_temp_new_i32();
10541 TCGv_i32 fp1 = tcg_temp_new_i32();
10542 TCGv_i32 fp2 = tcg_temp_new_i32();
10543 gen_load_fpr32(ctx, fp0, fd);
10544 gen_load_fpr32(ctx, fp1, ft);
10545 gen_load_fpr32(ctx, fp2, fs);
10547 switch (op1) {
10548 case OPC_SEL_S:
10549 tcg_gen_andi_i32(fp0, fp0, 1);
10550 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10551 break;
10552 case OPC_SELEQZ_S:
10553 tcg_gen_andi_i32(fp1, fp1, 1);
10554 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10555 break;
10556 case OPC_SELNEZ_S:
10557 tcg_gen_andi_i32(fp1, fp1, 1);
10558 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10559 break;
10560 default:
10561 MIPS_INVAL("gen_sel_s");
10562 generate_exception_end(ctx, EXCP_RI);
10563 break;
10566 gen_store_fpr32(ctx, fp0, fd);
10567 tcg_temp_free_i32(fp2);
10568 tcg_temp_free_i32(fp1);
10569 tcg_temp_free_i32(fp0);
10570 tcg_temp_free_i32(t1);
10573 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10574 int fs)
10576 TCGv_i64 t1 = tcg_const_i64(0);
10577 TCGv_i64 fp0 = tcg_temp_new_i64();
10578 TCGv_i64 fp1 = tcg_temp_new_i64();
10579 TCGv_i64 fp2 = tcg_temp_new_i64();
10580 gen_load_fpr64(ctx, fp0, fd);
10581 gen_load_fpr64(ctx, fp1, ft);
10582 gen_load_fpr64(ctx, fp2, fs);
10584 switch (op1) {
10585 case OPC_SEL_D:
10586 tcg_gen_andi_i64(fp0, fp0, 1);
10587 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10588 break;
10589 case OPC_SELEQZ_D:
10590 tcg_gen_andi_i64(fp1, fp1, 1);
10591 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10592 break;
10593 case OPC_SELNEZ_D:
10594 tcg_gen_andi_i64(fp1, fp1, 1);
10595 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10596 break;
10597 default:
10598 MIPS_INVAL("gen_sel_d");
10599 generate_exception_end(ctx, EXCP_RI);
10600 break;
10603 gen_store_fpr64(ctx, fp0, fd);
10604 tcg_temp_free_i64(fp2);
10605 tcg_temp_free_i64(fp1);
10606 tcg_temp_free_i64(fp0);
10607 tcg_temp_free_i64(t1);
10610 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10611 int ft, int fs, int fd, int cc)
10613 uint32_t func = ctx->opcode & 0x3f;
10614 switch (op1) {
10615 case OPC_ADD_S:
10617 TCGv_i32 fp0 = tcg_temp_new_i32();
10618 TCGv_i32 fp1 = tcg_temp_new_i32();
10620 gen_load_fpr32(ctx, fp0, fs);
10621 gen_load_fpr32(ctx, fp1, ft);
10622 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10623 tcg_temp_free_i32(fp1);
10624 gen_store_fpr32(ctx, fp0, fd);
10625 tcg_temp_free_i32(fp0);
10627 break;
10628 case OPC_SUB_S:
10630 TCGv_i32 fp0 = tcg_temp_new_i32();
10631 TCGv_i32 fp1 = tcg_temp_new_i32();
10633 gen_load_fpr32(ctx, fp0, fs);
10634 gen_load_fpr32(ctx, fp1, ft);
10635 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10636 tcg_temp_free_i32(fp1);
10637 gen_store_fpr32(ctx, fp0, fd);
10638 tcg_temp_free_i32(fp0);
10640 break;
10641 case OPC_MUL_S:
10643 TCGv_i32 fp0 = tcg_temp_new_i32();
10644 TCGv_i32 fp1 = tcg_temp_new_i32();
10646 gen_load_fpr32(ctx, fp0, fs);
10647 gen_load_fpr32(ctx, fp1, ft);
10648 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10649 tcg_temp_free_i32(fp1);
10650 gen_store_fpr32(ctx, fp0, fd);
10651 tcg_temp_free_i32(fp0);
10653 break;
10654 case OPC_DIV_S:
10656 TCGv_i32 fp0 = tcg_temp_new_i32();
10657 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_div_s(fp0, cpu_env, fp0, fp1);
10662 tcg_temp_free_i32(fp1);
10663 gen_store_fpr32(ctx, fp0, fd);
10664 tcg_temp_free_i32(fp0);
10666 break;
10667 case OPC_SQRT_S:
10669 TCGv_i32 fp0 = tcg_temp_new_i32();
10671 gen_load_fpr32(ctx, fp0, fs);
10672 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10673 gen_store_fpr32(ctx, fp0, fd);
10674 tcg_temp_free_i32(fp0);
10676 break;
10677 case OPC_ABS_S:
10679 TCGv_i32 fp0 = tcg_temp_new_i32();
10681 gen_load_fpr32(ctx, fp0, fs);
10682 if (ctx->abs2008) {
10683 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10684 } else {
10685 gen_helper_float_abs_s(fp0, fp0);
10687 gen_store_fpr32(ctx, fp0, fd);
10688 tcg_temp_free_i32(fp0);
10690 break;
10691 case OPC_MOV_S:
10693 TCGv_i32 fp0 = tcg_temp_new_i32();
10695 gen_load_fpr32(ctx, fp0, fs);
10696 gen_store_fpr32(ctx, fp0, fd);
10697 tcg_temp_free_i32(fp0);
10699 break;
10700 case OPC_NEG_S:
10702 TCGv_i32 fp0 = tcg_temp_new_i32();
10704 gen_load_fpr32(ctx, fp0, fs);
10705 if (ctx->abs2008) {
10706 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10707 } else {
10708 gen_helper_float_chs_s(fp0, fp0);
10710 gen_store_fpr32(ctx, fp0, fd);
10711 tcg_temp_free_i32(fp0);
10713 break;
10714 case OPC_ROUND_L_S:
10715 check_cp1_64bitmode(ctx);
10717 TCGv_i32 fp32 = tcg_temp_new_i32();
10718 TCGv_i64 fp64 = tcg_temp_new_i64();
10720 gen_load_fpr32(ctx, fp32, fs);
10721 if (ctx->nan2008) {
10722 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10723 } else {
10724 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10726 tcg_temp_free_i32(fp32);
10727 gen_store_fpr64(ctx, fp64, fd);
10728 tcg_temp_free_i64(fp64);
10730 break;
10731 case OPC_TRUNC_L_S:
10732 check_cp1_64bitmode(ctx);
10734 TCGv_i32 fp32 = tcg_temp_new_i32();
10735 TCGv_i64 fp64 = tcg_temp_new_i64();
10737 gen_load_fpr32(ctx, fp32, fs);
10738 if (ctx->nan2008) {
10739 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10740 } else {
10741 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10743 tcg_temp_free_i32(fp32);
10744 gen_store_fpr64(ctx, fp64, fd);
10745 tcg_temp_free_i64(fp64);
10747 break;
10748 case OPC_CEIL_L_S:
10749 check_cp1_64bitmode(ctx);
10751 TCGv_i32 fp32 = tcg_temp_new_i32();
10752 TCGv_i64 fp64 = tcg_temp_new_i64();
10754 gen_load_fpr32(ctx, fp32, fs);
10755 if (ctx->nan2008) {
10756 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10757 } else {
10758 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10760 tcg_temp_free_i32(fp32);
10761 gen_store_fpr64(ctx, fp64, fd);
10762 tcg_temp_free_i64(fp64);
10764 break;
10765 case OPC_FLOOR_L_S:
10766 check_cp1_64bitmode(ctx);
10768 TCGv_i32 fp32 = tcg_temp_new_i32();
10769 TCGv_i64 fp64 = tcg_temp_new_i64();
10771 gen_load_fpr32(ctx, fp32, fs);
10772 if (ctx->nan2008) {
10773 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10774 } else {
10775 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10777 tcg_temp_free_i32(fp32);
10778 gen_store_fpr64(ctx, fp64, fd);
10779 tcg_temp_free_i64(fp64);
10781 break;
10782 case OPC_ROUND_W_S:
10784 TCGv_i32 fp0 = tcg_temp_new_i32();
10786 gen_load_fpr32(ctx, fp0, fs);
10787 if (ctx->nan2008) {
10788 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10789 } else {
10790 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10792 gen_store_fpr32(ctx, fp0, fd);
10793 tcg_temp_free_i32(fp0);
10795 break;
10796 case OPC_TRUNC_W_S:
10798 TCGv_i32 fp0 = tcg_temp_new_i32();
10800 gen_load_fpr32(ctx, fp0, fs);
10801 if (ctx->nan2008) {
10802 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10803 } else {
10804 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10806 gen_store_fpr32(ctx, fp0, fd);
10807 tcg_temp_free_i32(fp0);
10809 break;
10810 case OPC_CEIL_W_S:
10812 TCGv_i32 fp0 = tcg_temp_new_i32();
10814 gen_load_fpr32(ctx, fp0, fs);
10815 if (ctx->nan2008) {
10816 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10817 } else {
10818 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10820 gen_store_fpr32(ctx, fp0, fd);
10821 tcg_temp_free_i32(fp0);
10823 break;
10824 case OPC_FLOOR_W_S:
10826 TCGv_i32 fp0 = tcg_temp_new_i32();
10828 gen_load_fpr32(ctx, fp0, fs);
10829 if (ctx->nan2008) {
10830 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10831 } else {
10832 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10834 gen_store_fpr32(ctx, fp0, fd);
10835 tcg_temp_free_i32(fp0);
10837 break;
10838 case OPC_SEL_S:
10839 check_insn(ctx, ISA_MIPS32R6);
10840 gen_sel_s(ctx, op1, fd, ft, fs);
10841 break;
10842 case OPC_SELEQZ_S:
10843 check_insn(ctx, ISA_MIPS32R6);
10844 gen_sel_s(ctx, op1, fd, ft, fs);
10845 break;
10846 case OPC_SELNEZ_S:
10847 check_insn(ctx, ISA_MIPS32R6);
10848 gen_sel_s(ctx, op1, fd, ft, fs);
10849 break;
10850 case OPC_MOVCF_S:
10851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10852 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10853 break;
10854 case OPC_MOVZ_S:
10855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10857 TCGLabel *l1 = gen_new_label();
10858 TCGv_i32 fp0;
10860 if (ft != 0) {
10861 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10863 fp0 = tcg_temp_new_i32();
10864 gen_load_fpr32(ctx, fp0, fs);
10865 gen_store_fpr32(ctx, fp0, fd);
10866 tcg_temp_free_i32(fp0);
10867 gen_set_label(l1);
10869 break;
10870 case OPC_MOVN_S:
10871 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10873 TCGLabel *l1 = gen_new_label();
10874 TCGv_i32 fp0;
10876 if (ft != 0) {
10877 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10878 fp0 = tcg_temp_new_i32();
10879 gen_load_fpr32(ctx, fp0, fs);
10880 gen_store_fpr32(ctx, fp0, fd);
10881 tcg_temp_free_i32(fp0);
10882 gen_set_label(l1);
10885 break;
10886 case OPC_RECIP_S:
10888 TCGv_i32 fp0 = tcg_temp_new_i32();
10890 gen_load_fpr32(ctx, fp0, fs);
10891 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10892 gen_store_fpr32(ctx, fp0, fd);
10893 tcg_temp_free_i32(fp0);
10895 break;
10896 case OPC_RSQRT_S:
10898 TCGv_i32 fp0 = tcg_temp_new_i32();
10900 gen_load_fpr32(ctx, fp0, fs);
10901 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10902 gen_store_fpr32(ctx, fp0, fd);
10903 tcg_temp_free_i32(fp0);
10905 break;
10906 case OPC_MADDF_S:
10907 check_insn(ctx, ISA_MIPS32R6);
10909 TCGv_i32 fp0 = tcg_temp_new_i32();
10910 TCGv_i32 fp1 = tcg_temp_new_i32();
10911 TCGv_i32 fp2 = tcg_temp_new_i32();
10912 gen_load_fpr32(ctx, fp0, fs);
10913 gen_load_fpr32(ctx, fp1, ft);
10914 gen_load_fpr32(ctx, fp2, fd);
10915 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10916 gen_store_fpr32(ctx, fp2, fd);
10917 tcg_temp_free_i32(fp2);
10918 tcg_temp_free_i32(fp1);
10919 tcg_temp_free_i32(fp0);
10921 break;
10922 case OPC_MSUBF_S:
10923 check_insn(ctx, ISA_MIPS32R6);
10925 TCGv_i32 fp0 = tcg_temp_new_i32();
10926 TCGv_i32 fp1 = tcg_temp_new_i32();
10927 TCGv_i32 fp2 = tcg_temp_new_i32();
10928 gen_load_fpr32(ctx, fp0, fs);
10929 gen_load_fpr32(ctx, fp1, ft);
10930 gen_load_fpr32(ctx, fp2, fd);
10931 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10932 gen_store_fpr32(ctx, fp2, fd);
10933 tcg_temp_free_i32(fp2);
10934 tcg_temp_free_i32(fp1);
10935 tcg_temp_free_i32(fp0);
10937 break;
10938 case OPC_RINT_S:
10939 check_insn(ctx, ISA_MIPS32R6);
10941 TCGv_i32 fp0 = tcg_temp_new_i32();
10942 gen_load_fpr32(ctx, fp0, fs);
10943 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10944 gen_store_fpr32(ctx, fp0, fd);
10945 tcg_temp_free_i32(fp0);
10947 break;
10948 case OPC_CLASS_S:
10949 check_insn(ctx, ISA_MIPS32R6);
10951 TCGv_i32 fp0 = tcg_temp_new_i32();
10952 gen_load_fpr32(ctx, fp0, fs);
10953 gen_helper_float_class_s(fp0, cpu_env, fp0);
10954 gen_store_fpr32(ctx, fp0, fd);
10955 tcg_temp_free_i32(fp0);
10957 break;
10958 case OPC_MIN_S: /* OPC_RECIP2_S */
10959 if (ctx->insn_flags & ISA_MIPS32R6) {
10960 /* OPC_MIN_S */
10961 TCGv_i32 fp0 = tcg_temp_new_i32();
10962 TCGv_i32 fp1 = tcg_temp_new_i32();
10963 TCGv_i32 fp2 = tcg_temp_new_i32();
10964 gen_load_fpr32(ctx, fp0, fs);
10965 gen_load_fpr32(ctx, fp1, ft);
10966 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10967 gen_store_fpr32(ctx, fp2, fd);
10968 tcg_temp_free_i32(fp2);
10969 tcg_temp_free_i32(fp1);
10970 tcg_temp_free_i32(fp0);
10971 } else {
10972 /* OPC_RECIP2_S */
10973 check_cp1_64bitmode(ctx);
10975 TCGv_i32 fp0 = tcg_temp_new_i32();
10976 TCGv_i32 fp1 = tcg_temp_new_i32();
10978 gen_load_fpr32(ctx, fp0, fs);
10979 gen_load_fpr32(ctx, fp1, ft);
10980 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10981 tcg_temp_free_i32(fp1);
10982 gen_store_fpr32(ctx, fp0, fd);
10983 tcg_temp_free_i32(fp0);
10986 break;
10987 case OPC_MINA_S: /* OPC_RECIP1_S */
10988 if (ctx->insn_flags & ISA_MIPS32R6) {
10989 /* OPC_MINA_S */
10990 TCGv_i32 fp0 = tcg_temp_new_i32();
10991 TCGv_i32 fp1 = tcg_temp_new_i32();
10992 TCGv_i32 fp2 = tcg_temp_new_i32();
10993 gen_load_fpr32(ctx, fp0, fs);
10994 gen_load_fpr32(ctx, fp1, ft);
10995 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10996 gen_store_fpr32(ctx, fp2, fd);
10997 tcg_temp_free_i32(fp2);
10998 tcg_temp_free_i32(fp1);
10999 tcg_temp_free_i32(fp0);
11000 } else {
11001 /* OPC_RECIP1_S */
11002 check_cp1_64bitmode(ctx);
11004 TCGv_i32 fp0 = tcg_temp_new_i32();
11006 gen_load_fpr32(ctx, fp0, fs);
11007 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11008 gen_store_fpr32(ctx, fp0, fd);
11009 tcg_temp_free_i32(fp0);
11012 break;
11013 case OPC_MAX_S: /* OPC_RSQRT1_S */
11014 if (ctx->insn_flags & ISA_MIPS32R6) {
11015 /* OPC_MAX_S */
11016 TCGv_i32 fp0 = tcg_temp_new_i32();
11017 TCGv_i32 fp1 = tcg_temp_new_i32();
11018 gen_load_fpr32(ctx, fp0, fs);
11019 gen_load_fpr32(ctx, fp1, ft);
11020 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11021 gen_store_fpr32(ctx, fp1, fd);
11022 tcg_temp_free_i32(fp1);
11023 tcg_temp_free_i32(fp0);
11024 } else {
11025 /* OPC_RSQRT1_S */
11026 check_cp1_64bitmode(ctx);
11028 TCGv_i32 fp0 = tcg_temp_new_i32();
11030 gen_load_fpr32(ctx, fp0, fs);
11031 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11032 gen_store_fpr32(ctx, fp0, fd);
11033 tcg_temp_free_i32(fp0);
11036 break;
11037 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11038 if (ctx->insn_flags & ISA_MIPS32R6) {
11039 /* OPC_MAXA_S */
11040 TCGv_i32 fp0 = tcg_temp_new_i32();
11041 TCGv_i32 fp1 = tcg_temp_new_i32();
11042 gen_load_fpr32(ctx, fp0, fs);
11043 gen_load_fpr32(ctx, fp1, ft);
11044 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11045 gen_store_fpr32(ctx, fp1, fd);
11046 tcg_temp_free_i32(fp1);
11047 tcg_temp_free_i32(fp0);
11048 } else {
11049 /* OPC_RSQRT2_S */
11050 check_cp1_64bitmode(ctx);
11052 TCGv_i32 fp0 = tcg_temp_new_i32();
11053 TCGv_i32 fp1 = tcg_temp_new_i32();
11055 gen_load_fpr32(ctx, fp0, fs);
11056 gen_load_fpr32(ctx, fp1, ft);
11057 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11058 tcg_temp_free_i32(fp1);
11059 gen_store_fpr32(ctx, fp0, fd);
11060 tcg_temp_free_i32(fp0);
11063 break;
11064 case OPC_CVT_D_S:
11065 check_cp1_registers(ctx, fd);
11067 TCGv_i32 fp32 = tcg_temp_new_i32();
11068 TCGv_i64 fp64 = tcg_temp_new_i64();
11070 gen_load_fpr32(ctx, fp32, fs);
11071 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11072 tcg_temp_free_i32(fp32);
11073 gen_store_fpr64(ctx, fp64, fd);
11074 tcg_temp_free_i64(fp64);
11076 break;
11077 case OPC_CVT_W_S:
11079 TCGv_i32 fp0 = tcg_temp_new_i32();
11081 gen_load_fpr32(ctx, fp0, fs);
11082 if (ctx->nan2008) {
11083 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11084 } else {
11085 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11087 gen_store_fpr32(ctx, fp0, fd);
11088 tcg_temp_free_i32(fp0);
11090 break;
11091 case OPC_CVT_L_S:
11092 check_cp1_64bitmode(ctx);
11094 TCGv_i32 fp32 = tcg_temp_new_i32();
11095 TCGv_i64 fp64 = tcg_temp_new_i64();
11097 gen_load_fpr32(ctx, fp32, fs);
11098 if (ctx->nan2008) {
11099 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11100 } else {
11101 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11103 tcg_temp_free_i32(fp32);
11104 gen_store_fpr64(ctx, fp64, fd);
11105 tcg_temp_free_i64(fp64);
11107 break;
11108 case OPC_CVT_PS_S:
11109 check_ps(ctx);
11111 TCGv_i64 fp64 = tcg_temp_new_i64();
11112 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11113 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11115 gen_load_fpr32(ctx, fp32_0, fs);
11116 gen_load_fpr32(ctx, fp32_1, ft);
11117 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11118 tcg_temp_free_i32(fp32_1);
11119 tcg_temp_free_i32(fp32_0);
11120 gen_store_fpr64(ctx, fp64, fd);
11121 tcg_temp_free_i64(fp64);
11123 break;
11124 case OPC_CMP_F_S:
11125 case OPC_CMP_UN_S:
11126 case OPC_CMP_EQ_S:
11127 case OPC_CMP_UEQ_S:
11128 case OPC_CMP_OLT_S:
11129 case OPC_CMP_ULT_S:
11130 case OPC_CMP_OLE_S:
11131 case OPC_CMP_ULE_S:
11132 case OPC_CMP_SF_S:
11133 case OPC_CMP_NGLE_S:
11134 case OPC_CMP_SEQ_S:
11135 case OPC_CMP_NGL_S:
11136 case OPC_CMP_LT_S:
11137 case OPC_CMP_NGE_S:
11138 case OPC_CMP_LE_S:
11139 case OPC_CMP_NGT_S:
11140 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11141 if (ctx->opcode & (1 << 6)) {
11142 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11143 } else {
11144 gen_cmp_s(ctx, func-48, ft, fs, cc);
11146 break;
11147 case OPC_ADD_D:
11148 check_cp1_registers(ctx, fs | ft | fd);
11150 TCGv_i64 fp0 = tcg_temp_new_i64();
11151 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_add_d(fp0, cpu_env, fp0, fp1);
11156 tcg_temp_free_i64(fp1);
11157 gen_store_fpr64(ctx, fp0, fd);
11158 tcg_temp_free_i64(fp0);
11160 break;
11161 case OPC_SUB_D:
11162 check_cp1_registers(ctx, fs | ft | fd);
11164 TCGv_i64 fp0 = tcg_temp_new_i64();
11165 TCGv_i64 fp1 = tcg_temp_new_i64();
11167 gen_load_fpr64(ctx, fp0, fs);
11168 gen_load_fpr64(ctx, fp1, ft);
11169 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11170 tcg_temp_free_i64(fp1);
11171 gen_store_fpr64(ctx, fp0, fd);
11172 tcg_temp_free_i64(fp0);
11174 break;
11175 case OPC_MUL_D:
11176 check_cp1_registers(ctx, fs | ft | fd);
11178 TCGv_i64 fp0 = tcg_temp_new_i64();
11179 TCGv_i64 fp1 = tcg_temp_new_i64();
11181 gen_load_fpr64(ctx, fp0, fs);
11182 gen_load_fpr64(ctx, fp1, ft);
11183 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11184 tcg_temp_free_i64(fp1);
11185 gen_store_fpr64(ctx, fp0, fd);
11186 tcg_temp_free_i64(fp0);
11188 break;
11189 case OPC_DIV_D:
11190 check_cp1_registers(ctx, fs | ft | fd);
11192 TCGv_i64 fp0 = tcg_temp_new_i64();
11193 TCGv_i64 fp1 = tcg_temp_new_i64();
11195 gen_load_fpr64(ctx, fp0, fs);
11196 gen_load_fpr64(ctx, fp1, ft);
11197 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11198 tcg_temp_free_i64(fp1);
11199 gen_store_fpr64(ctx, fp0, fd);
11200 tcg_temp_free_i64(fp0);
11202 break;
11203 case OPC_SQRT_D:
11204 check_cp1_registers(ctx, fs | fd);
11206 TCGv_i64 fp0 = tcg_temp_new_i64();
11208 gen_load_fpr64(ctx, fp0, fs);
11209 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11210 gen_store_fpr64(ctx, fp0, fd);
11211 tcg_temp_free_i64(fp0);
11213 break;
11214 case OPC_ABS_D:
11215 check_cp1_registers(ctx, fs | fd);
11217 TCGv_i64 fp0 = tcg_temp_new_i64();
11219 gen_load_fpr64(ctx, fp0, fs);
11220 if (ctx->abs2008) {
11221 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11222 } else {
11223 gen_helper_float_abs_d(fp0, fp0);
11225 gen_store_fpr64(ctx, fp0, fd);
11226 tcg_temp_free_i64(fp0);
11228 break;
11229 case OPC_MOV_D:
11230 check_cp1_registers(ctx, fs | fd);
11232 TCGv_i64 fp0 = tcg_temp_new_i64();
11234 gen_load_fpr64(ctx, fp0, fs);
11235 gen_store_fpr64(ctx, fp0, fd);
11236 tcg_temp_free_i64(fp0);
11238 break;
11239 case OPC_NEG_D:
11240 check_cp1_registers(ctx, fs | fd);
11242 TCGv_i64 fp0 = tcg_temp_new_i64();
11244 gen_load_fpr64(ctx, fp0, fs);
11245 if (ctx->abs2008) {
11246 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11247 } else {
11248 gen_helper_float_chs_d(fp0, fp0);
11250 gen_store_fpr64(ctx, fp0, fd);
11251 tcg_temp_free_i64(fp0);
11253 break;
11254 case OPC_ROUND_L_D:
11255 check_cp1_64bitmode(ctx);
11257 TCGv_i64 fp0 = tcg_temp_new_i64();
11259 gen_load_fpr64(ctx, fp0, fs);
11260 if (ctx->nan2008) {
11261 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11262 } else {
11263 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11265 gen_store_fpr64(ctx, fp0, fd);
11266 tcg_temp_free_i64(fp0);
11268 break;
11269 case OPC_TRUNC_L_D:
11270 check_cp1_64bitmode(ctx);
11272 TCGv_i64 fp0 = tcg_temp_new_i64();
11274 gen_load_fpr64(ctx, fp0, fs);
11275 if (ctx->nan2008) {
11276 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11277 } else {
11278 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11280 gen_store_fpr64(ctx, fp0, fd);
11281 tcg_temp_free_i64(fp0);
11283 break;
11284 case OPC_CEIL_L_D:
11285 check_cp1_64bitmode(ctx);
11287 TCGv_i64 fp0 = tcg_temp_new_i64();
11289 gen_load_fpr64(ctx, fp0, fs);
11290 if (ctx->nan2008) {
11291 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11292 } else {
11293 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11295 gen_store_fpr64(ctx, fp0, fd);
11296 tcg_temp_free_i64(fp0);
11298 break;
11299 case OPC_FLOOR_L_D:
11300 check_cp1_64bitmode(ctx);
11302 TCGv_i64 fp0 = tcg_temp_new_i64();
11304 gen_load_fpr64(ctx, fp0, fs);
11305 if (ctx->nan2008) {
11306 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11307 } else {
11308 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11310 gen_store_fpr64(ctx, fp0, fd);
11311 tcg_temp_free_i64(fp0);
11313 break;
11314 case OPC_ROUND_W_D:
11315 check_cp1_registers(ctx, fs);
11317 TCGv_i32 fp32 = tcg_temp_new_i32();
11318 TCGv_i64 fp64 = tcg_temp_new_i64();
11320 gen_load_fpr64(ctx, fp64, fs);
11321 if (ctx->nan2008) {
11322 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11323 } else {
11324 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11326 tcg_temp_free_i64(fp64);
11327 gen_store_fpr32(ctx, fp32, fd);
11328 tcg_temp_free_i32(fp32);
11330 break;
11331 case OPC_TRUNC_W_D:
11332 check_cp1_registers(ctx, fs);
11334 TCGv_i32 fp32 = tcg_temp_new_i32();
11335 TCGv_i64 fp64 = tcg_temp_new_i64();
11337 gen_load_fpr64(ctx, fp64, fs);
11338 if (ctx->nan2008) {
11339 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11340 } else {
11341 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11343 tcg_temp_free_i64(fp64);
11344 gen_store_fpr32(ctx, fp32, fd);
11345 tcg_temp_free_i32(fp32);
11347 break;
11348 case OPC_CEIL_W_D:
11349 check_cp1_registers(ctx, fs);
11351 TCGv_i32 fp32 = tcg_temp_new_i32();
11352 TCGv_i64 fp64 = tcg_temp_new_i64();
11354 gen_load_fpr64(ctx, fp64, fs);
11355 if (ctx->nan2008) {
11356 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11357 } else {
11358 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11360 tcg_temp_free_i64(fp64);
11361 gen_store_fpr32(ctx, fp32, fd);
11362 tcg_temp_free_i32(fp32);
11364 break;
11365 case OPC_FLOOR_W_D:
11366 check_cp1_registers(ctx, fs);
11368 TCGv_i32 fp32 = tcg_temp_new_i32();
11369 TCGv_i64 fp64 = tcg_temp_new_i64();
11371 gen_load_fpr64(ctx, fp64, fs);
11372 if (ctx->nan2008) {
11373 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11374 } else {
11375 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11377 tcg_temp_free_i64(fp64);
11378 gen_store_fpr32(ctx, fp32, fd);
11379 tcg_temp_free_i32(fp32);
11381 break;
11382 case OPC_SEL_D:
11383 check_insn(ctx, ISA_MIPS32R6);
11384 gen_sel_d(ctx, op1, fd, ft, fs);
11385 break;
11386 case OPC_SELEQZ_D:
11387 check_insn(ctx, ISA_MIPS32R6);
11388 gen_sel_d(ctx, op1, fd, ft, fs);
11389 break;
11390 case OPC_SELNEZ_D:
11391 check_insn(ctx, ISA_MIPS32R6);
11392 gen_sel_d(ctx, op1, fd, ft, fs);
11393 break;
11394 case OPC_MOVCF_D:
11395 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11396 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11397 break;
11398 case OPC_MOVZ_D:
11399 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11401 TCGLabel *l1 = gen_new_label();
11402 TCGv_i64 fp0;
11404 if (ft != 0) {
11405 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11407 fp0 = tcg_temp_new_i64();
11408 gen_load_fpr64(ctx, fp0, fs);
11409 gen_store_fpr64(ctx, fp0, fd);
11410 tcg_temp_free_i64(fp0);
11411 gen_set_label(l1);
11413 break;
11414 case OPC_MOVN_D:
11415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11417 TCGLabel *l1 = gen_new_label();
11418 TCGv_i64 fp0;
11420 if (ft != 0) {
11421 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11422 fp0 = tcg_temp_new_i64();
11423 gen_load_fpr64(ctx, fp0, fs);
11424 gen_store_fpr64(ctx, fp0, fd);
11425 tcg_temp_free_i64(fp0);
11426 gen_set_label(l1);
11429 break;
11430 case OPC_RECIP_D:
11431 check_cp1_registers(ctx, fs | fd);
11433 TCGv_i64 fp0 = tcg_temp_new_i64();
11435 gen_load_fpr64(ctx, fp0, fs);
11436 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11437 gen_store_fpr64(ctx, fp0, fd);
11438 tcg_temp_free_i64(fp0);
11440 break;
11441 case OPC_RSQRT_D:
11442 check_cp1_registers(ctx, fs | fd);
11444 TCGv_i64 fp0 = tcg_temp_new_i64();
11446 gen_load_fpr64(ctx, fp0, fs);
11447 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11448 gen_store_fpr64(ctx, fp0, fd);
11449 tcg_temp_free_i64(fp0);
11451 break;
11452 case OPC_MADDF_D:
11453 check_insn(ctx, ISA_MIPS32R6);
11455 TCGv_i64 fp0 = tcg_temp_new_i64();
11456 TCGv_i64 fp1 = tcg_temp_new_i64();
11457 TCGv_i64 fp2 = tcg_temp_new_i64();
11458 gen_load_fpr64(ctx, fp0, fs);
11459 gen_load_fpr64(ctx, fp1, ft);
11460 gen_load_fpr64(ctx, fp2, fd);
11461 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11462 gen_store_fpr64(ctx, fp2, fd);
11463 tcg_temp_free_i64(fp2);
11464 tcg_temp_free_i64(fp1);
11465 tcg_temp_free_i64(fp0);
11467 break;
11468 case OPC_MSUBF_D:
11469 check_insn(ctx, ISA_MIPS32R6);
11471 TCGv_i64 fp0 = tcg_temp_new_i64();
11472 TCGv_i64 fp1 = tcg_temp_new_i64();
11473 TCGv_i64 fp2 = tcg_temp_new_i64();
11474 gen_load_fpr64(ctx, fp0, fs);
11475 gen_load_fpr64(ctx, fp1, ft);
11476 gen_load_fpr64(ctx, fp2, fd);
11477 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11478 gen_store_fpr64(ctx, fp2, fd);
11479 tcg_temp_free_i64(fp2);
11480 tcg_temp_free_i64(fp1);
11481 tcg_temp_free_i64(fp0);
11483 break;
11484 case OPC_RINT_D:
11485 check_insn(ctx, ISA_MIPS32R6);
11487 TCGv_i64 fp0 = tcg_temp_new_i64();
11488 gen_load_fpr64(ctx, fp0, fs);
11489 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11490 gen_store_fpr64(ctx, fp0, fd);
11491 tcg_temp_free_i64(fp0);
11493 break;
11494 case OPC_CLASS_D:
11495 check_insn(ctx, ISA_MIPS32R6);
11497 TCGv_i64 fp0 = tcg_temp_new_i64();
11498 gen_load_fpr64(ctx, fp0, fs);
11499 gen_helper_float_class_d(fp0, cpu_env, fp0);
11500 gen_store_fpr64(ctx, fp0, fd);
11501 tcg_temp_free_i64(fp0);
11503 break;
11504 case OPC_MIN_D: /* OPC_RECIP2_D */
11505 if (ctx->insn_flags & ISA_MIPS32R6) {
11506 /* OPC_MIN_D */
11507 TCGv_i64 fp0 = tcg_temp_new_i64();
11508 TCGv_i64 fp1 = tcg_temp_new_i64();
11509 gen_load_fpr64(ctx, fp0, fs);
11510 gen_load_fpr64(ctx, fp1, ft);
11511 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11512 gen_store_fpr64(ctx, fp1, fd);
11513 tcg_temp_free_i64(fp1);
11514 tcg_temp_free_i64(fp0);
11515 } else {
11516 /* OPC_RECIP2_D */
11517 check_cp1_64bitmode(ctx);
11519 TCGv_i64 fp0 = tcg_temp_new_i64();
11520 TCGv_i64 fp1 = tcg_temp_new_i64();
11522 gen_load_fpr64(ctx, fp0, fs);
11523 gen_load_fpr64(ctx, fp1, ft);
11524 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11525 tcg_temp_free_i64(fp1);
11526 gen_store_fpr64(ctx, fp0, fd);
11527 tcg_temp_free_i64(fp0);
11530 break;
11531 case OPC_MINA_D: /* OPC_RECIP1_D */
11532 if (ctx->insn_flags & ISA_MIPS32R6) {
11533 /* OPC_MINA_D */
11534 TCGv_i64 fp0 = tcg_temp_new_i64();
11535 TCGv_i64 fp1 = tcg_temp_new_i64();
11536 gen_load_fpr64(ctx, fp0, fs);
11537 gen_load_fpr64(ctx, fp1, ft);
11538 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11539 gen_store_fpr64(ctx, fp1, fd);
11540 tcg_temp_free_i64(fp1);
11541 tcg_temp_free_i64(fp0);
11542 } else {
11543 /* OPC_RECIP1_D */
11544 check_cp1_64bitmode(ctx);
11546 TCGv_i64 fp0 = tcg_temp_new_i64();
11548 gen_load_fpr64(ctx, fp0, fs);
11549 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11550 gen_store_fpr64(ctx, fp0, fd);
11551 tcg_temp_free_i64(fp0);
11554 break;
11555 case OPC_MAX_D: /* OPC_RSQRT1_D */
11556 if (ctx->insn_flags & ISA_MIPS32R6) {
11557 /* OPC_MAX_D */
11558 TCGv_i64 fp0 = tcg_temp_new_i64();
11559 TCGv_i64 fp1 = tcg_temp_new_i64();
11560 gen_load_fpr64(ctx, fp0, fs);
11561 gen_load_fpr64(ctx, fp1, ft);
11562 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11563 gen_store_fpr64(ctx, fp1, fd);
11564 tcg_temp_free_i64(fp1);
11565 tcg_temp_free_i64(fp0);
11566 } else {
11567 /* OPC_RSQRT1_D */
11568 check_cp1_64bitmode(ctx);
11570 TCGv_i64 fp0 = tcg_temp_new_i64();
11572 gen_load_fpr64(ctx, fp0, fs);
11573 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11574 gen_store_fpr64(ctx, fp0, fd);
11575 tcg_temp_free_i64(fp0);
11578 break;
11579 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11580 if (ctx->insn_flags & ISA_MIPS32R6) {
11581 /* OPC_MAXA_D */
11582 TCGv_i64 fp0 = tcg_temp_new_i64();
11583 TCGv_i64 fp1 = tcg_temp_new_i64();
11584 gen_load_fpr64(ctx, fp0, fs);
11585 gen_load_fpr64(ctx, fp1, ft);
11586 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11587 gen_store_fpr64(ctx, fp1, fd);
11588 tcg_temp_free_i64(fp1);
11589 tcg_temp_free_i64(fp0);
11590 } else {
11591 /* OPC_RSQRT2_D */
11592 check_cp1_64bitmode(ctx);
11594 TCGv_i64 fp0 = tcg_temp_new_i64();
11595 TCGv_i64 fp1 = tcg_temp_new_i64();
11597 gen_load_fpr64(ctx, fp0, fs);
11598 gen_load_fpr64(ctx, fp1, ft);
11599 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11600 tcg_temp_free_i64(fp1);
11601 gen_store_fpr64(ctx, fp0, fd);
11602 tcg_temp_free_i64(fp0);
11605 break;
11606 case OPC_CMP_F_D:
11607 case OPC_CMP_UN_D:
11608 case OPC_CMP_EQ_D:
11609 case OPC_CMP_UEQ_D:
11610 case OPC_CMP_OLT_D:
11611 case OPC_CMP_ULT_D:
11612 case OPC_CMP_OLE_D:
11613 case OPC_CMP_ULE_D:
11614 case OPC_CMP_SF_D:
11615 case OPC_CMP_NGLE_D:
11616 case OPC_CMP_SEQ_D:
11617 case OPC_CMP_NGL_D:
11618 case OPC_CMP_LT_D:
11619 case OPC_CMP_NGE_D:
11620 case OPC_CMP_LE_D:
11621 case OPC_CMP_NGT_D:
11622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11623 if (ctx->opcode & (1 << 6)) {
11624 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11625 } else {
11626 gen_cmp_d(ctx, func-48, ft, fs, cc);
11628 break;
11629 case OPC_CVT_S_D:
11630 check_cp1_registers(ctx, fs);
11632 TCGv_i32 fp32 = tcg_temp_new_i32();
11633 TCGv_i64 fp64 = tcg_temp_new_i64();
11635 gen_load_fpr64(ctx, fp64, fs);
11636 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11637 tcg_temp_free_i64(fp64);
11638 gen_store_fpr32(ctx, fp32, fd);
11639 tcg_temp_free_i32(fp32);
11641 break;
11642 case OPC_CVT_W_D:
11643 check_cp1_registers(ctx, fs);
11645 TCGv_i32 fp32 = tcg_temp_new_i32();
11646 TCGv_i64 fp64 = tcg_temp_new_i64();
11648 gen_load_fpr64(ctx, fp64, fs);
11649 if (ctx->nan2008) {
11650 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11651 } else {
11652 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11654 tcg_temp_free_i64(fp64);
11655 gen_store_fpr32(ctx, fp32, fd);
11656 tcg_temp_free_i32(fp32);
11658 break;
11659 case OPC_CVT_L_D:
11660 check_cp1_64bitmode(ctx);
11662 TCGv_i64 fp0 = tcg_temp_new_i64();
11664 gen_load_fpr64(ctx, fp0, fs);
11665 if (ctx->nan2008) {
11666 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11667 } else {
11668 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11670 gen_store_fpr64(ctx, fp0, fd);
11671 tcg_temp_free_i64(fp0);
11673 break;
11674 case OPC_CVT_S_W:
11676 TCGv_i32 fp0 = tcg_temp_new_i32();
11678 gen_load_fpr32(ctx, fp0, fs);
11679 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11680 gen_store_fpr32(ctx, fp0, fd);
11681 tcg_temp_free_i32(fp0);
11683 break;
11684 case OPC_CVT_D_W:
11685 check_cp1_registers(ctx, fd);
11687 TCGv_i32 fp32 = tcg_temp_new_i32();
11688 TCGv_i64 fp64 = tcg_temp_new_i64();
11690 gen_load_fpr32(ctx, fp32, fs);
11691 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11692 tcg_temp_free_i32(fp32);
11693 gen_store_fpr64(ctx, fp64, fd);
11694 tcg_temp_free_i64(fp64);
11696 break;
11697 case OPC_CVT_S_L:
11698 check_cp1_64bitmode(ctx);
11700 TCGv_i32 fp32 = tcg_temp_new_i32();
11701 TCGv_i64 fp64 = tcg_temp_new_i64();
11703 gen_load_fpr64(ctx, fp64, fs);
11704 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11705 tcg_temp_free_i64(fp64);
11706 gen_store_fpr32(ctx, fp32, fd);
11707 tcg_temp_free_i32(fp32);
11709 break;
11710 case OPC_CVT_D_L:
11711 check_cp1_64bitmode(ctx);
11713 TCGv_i64 fp0 = tcg_temp_new_i64();
11715 gen_load_fpr64(ctx, fp0, fs);
11716 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11717 gen_store_fpr64(ctx, fp0, fd);
11718 tcg_temp_free_i64(fp0);
11720 break;
11721 case OPC_CVT_PS_PW:
11722 check_ps(ctx);
11724 TCGv_i64 fp0 = tcg_temp_new_i64();
11726 gen_load_fpr64(ctx, fp0, fs);
11727 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11728 gen_store_fpr64(ctx, fp0, fd);
11729 tcg_temp_free_i64(fp0);
11731 break;
11732 case OPC_ADD_PS:
11733 check_ps(ctx);
11735 TCGv_i64 fp0 = tcg_temp_new_i64();
11736 TCGv_i64 fp1 = tcg_temp_new_i64();
11738 gen_load_fpr64(ctx, fp0, fs);
11739 gen_load_fpr64(ctx, fp1, ft);
11740 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11741 tcg_temp_free_i64(fp1);
11742 gen_store_fpr64(ctx, fp0, fd);
11743 tcg_temp_free_i64(fp0);
11745 break;
11746 case OPC_SUB_PS:
11747 check_ps(ctx);
11749 TCGv_i64 fp0 = tcg_temp_new_i64();
11750 TCGv_i64 fp1 = tcg_temp_new_i64();
11752 gen_load_fpr64(ctx, fp0, fs);
11753 gen_load_fpr64(ctx, fp1, ft);
11754 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11755 tcg_temp_free_i64(fp1);
11756 gen_store_fpr64(ctx, fp0, fd);
11757 tcg_temp_free_i64(fp0);
11759 break;
11760 case OPC_MUL_PS:
11761 check_ps(ctx);
11763 TCGv_i64 fp0 = tcg_temp_new_i64();
11764 TCGv_i64 fp1 = tcg_temp_new_i64();
11766 gen_load_fpr64(ctx, fp0, fs);
11767 gen_load_fpr64(ctx, fp1, ft);
11768 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11769 tcg_temp_free_i64(fp1);
11770 gen_store_fpr64(ctx, fp0, fd);
11771 tcg_temp_free_i64(fp0);
11773 break;
11774 case OPC_ABS_PS:
11775 check_ps(ctx);
11777 TCGv_i64 fp0 = tcg_temp_new_i64();
11779 gen_load_fpr64(ctx, fp0, fs);
11780 gen_helper_float_abs_ps(fp0, fp0);
11781 gen_store_fpr64(ctx, fp0, fd);
11782 tcg_temp_free_i64(fp0);
11784 break;
11785 case OPC_MOV_PS:
11786 check_ps(ctx);
11788 TCGv_i64 fp0 = tcg_temp_new_i64();
11790 gen_load_fpr64(ctx, fp0, fs);
11791 gen_store_fpr64(ctx, fp0, fd);
11792 tcg_temp_free_i64(fp0);
11794 break;
11795 case OPC_NEG_PS:
11796 check_ps(ctx);
11798 TCGv_i64 fp0 = tcg_temp_new_i64();
11800 gen_load_fpr64(ctx, fp0, fs);
11801 gen_helper_float_chs_ps(fp0, fp0);
11802 gen_store_fpr64(ctx, fp0, fd);
11803 tcg_temp_free_i64(fp0);
11805 break;
11806 case OPC_MOVCF_PS:
11807 check_ps(ctx);
11808 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11809 break;
11810 case OPC_MOVZ_PS:
11811 check_ps(ctx);
11813 TCGLabel *l1 = gen_new_label();
11814 TCGv_i64 fp0;
11816 if (ft != 0)
11817 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11818 fp0 = tcg_temp_new_i64();
11819 gen_load_fpr64(ctx, fp0, fs);
11820 gen_store_fpr64(ctx, fp0, fd);
11821 tcg_temp_free_i64(fp0);
11822 gen_set_label(l1);
11824 break;
11825 case OPC_MOVN_PS:
11826 check_ps(ctx);
11828 TCGLabel *l1 = gen_new_label();
11829 TCGv_i64 fp0;
11831 if (ft != 0) {
11832 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11833 fp0 = tcg_temp_new_i64();
11834 gen_load_fpr64(ctx, fp0, fs);
11835 gen_store_fpr64(ctx, fp0, fd);
11836 tcg_temp_free_i64(fp0);
11837 gen_set_label(l1);
11840 break;
11841 case OPC_ADDR_PS:
11842 check_ps(ctx);
11844 TCGv_i64 fp0 = tcg_temp_new_i64();
11845 TCGv_i64 fp1 = tcg_temp_new_i64();
11847 gen_load_fpr64(ctx, fp0, ft);
11848 gen_load_fpr64(ctx, fp1, fs);
11849 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11850 tcg_temp_free_i64(fp1);
11851 gen_store_fpr64(ctx, fp0, fd);
11852 tcg_temp_free_i64(fp0);
11854 break;
11855 case OPC_MULR_PS:
11856 check_ps(ctx);
11858 TCGv_i64 fp0 = tcg_temp_new_i64();
11859 TCGv_i64 fp1 = tcg_temp_new_i64();
11861 gen_load_fpr64(ctx, fp0, ft);
11862 gen_load_fpr64(ctx, fp1, fs);
11863 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11864 tcg_temp_free_i64(fp1);
11865 gen_store_fpr64(ctx, fp0, fd);
11866 tcg_temp_free_i64(fp0);
11868 break;
11869 case OPC_RECIP2_PS:
11870 check_ps(ctx);
11872 TCGv_i64 fp0 = tcg_temp_new_i64();
11873 TCGv_i64 fp1 = tcg_temp_new_i64();
11875 gen_load_fpr64(ctx, fp0, fs);
11876 gen_load_fpr64(ctx, fp1, ft);
11877 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11878 tcg_temp_free_i64(fp1);
11879 gen_store_fpr64(ctx, fp0, fd);
11880 tcg_temp_free_i64(fp0);
11882 break;
11883 case OPC_RECIP1_PS:
11884 check_ps(ctx);
11886 TCGv_i64 fp0 = tcg_temp_new_i64();
11888 gen_load_fpr64(ctx, fp0, fs);
11889 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11890 gen_store_fpr64(ctx, fp0, fd);
11891 tcg_temp_free_i64(fp0);
11893 break;
11894 case OPC_RSQRT1_PS:
11895 check_ps(ctx);
11897 TCGv_i64 fp0 = tcg_temp_new_i64();
11899 gen_load_fpr64(ctx, fp0, fs);
11900 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11901 gen_store_fpr64(ctx, fp0, fd);
11902 tcg_temp_free_i64(fp0);
11904 break;
11905 case OPC_RSQRT2_PS:
11906 check_ps(ctx);
11908 TCGv_i64 fp0 = tcg_temp_new_i64();
11909 TCGv_i64 fp1 = tcg_temp_new_i64();
11911 gen_load_fpr64(ctx, fp0, fs);
11912 gen_load_fpr64(ctx, fp1, ft);
11913 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11914 tcg_temp_free_i64(fp1);
11915 gen_store_fpr64(ctx, fp0, fd);
11916 tcg_temp_free_i64(fp0);
11918 break;
11919 case OPC_CVT_S_PU:
11920 check_cp1_64bitmode(ctx);
11922 TCGv_i32 fp0 = tcg_temp_new_i32();
11924 gen_load_fpr32h(ctx, fp0, fs);
11925 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11926 gen_store_fpr32(ctx, fp0, fd);
11927 tcg_temp_free_i32(fp0);
11929 break;
11930 case OPC_CVT_PW_PS:
11931 check_ps(ctx);
11933 TCGv_i64 fp0 = tcg_temp_new_i64();
11935 gen_load_fpr64(ctx, fp0, fs);
11936 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11937 gen_store_fpr64(ctx, fp0, fd);
11938 tcg_temp_free_i64(fp0);
11940 break;
11941 case OPC_CVT_S_PL:
11942 check_cp1_64bitmode(ctx);
11944 TCGv_i32 fp0 = tcg_temp_new_i32();
11946 gen_load_fpr32(ctx, fp0, fs);
11947 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11948 gen_store_fpr32(ctx, fp0, fd);
11949 tcg_temp_free_i32(fp0);
11951 break;
11952 case OPC_PLL_PS:
11953 check_ps(ctx);
11955 TCGv_i32 fp0 = tcg_temp_new_i32();
11956 TCGv_i32 fp1 = tcg_temp_new_i32();
11958 gen_load_fpr32(ctx, fp0, fs);
11959 gen_load_fpr32(ctx, fp1, ft);
11960 gen_store_fpr32h(ctx, fp0, fd);
11961 gen_store_fpr32(ctx, fp1, fd);
11962 tcg_temp_free_i32(fp0);
11963 tcg_temp_free_i32(fp1);
11965 break;
11966 case OPC_PLU_PS:
11967 check_ps(ctx);
11969 TCGv_i32 fp0 = tcg_temp_new_i32();
11970 TCGv_i32 fp1 = tcg_temp_new_i32();
11972 gen_load_fpr32(ctx, fp0, fs);
11973 gen_load_fpr32h(ctx, fp1, ft);
11974 gen_store_fpr32(ctx, fp1, fd);
11975 gen_store_fpr32h(ctx, fp0, fd);
11976 tcg_temp_free_i32(fp0);
11977 tcg_temp_free_i32(fp1);
11979 break;
11980 case OPC_PUL_PS:
11981 check_ps(ctx);
11983 TCGv_i32 fp0 = tcg_temp_new_i32();
11984 TCGv_i32 fp1 = tcg_temp_new_i32();
11986 gen_load_fpr32h(ctx, fp0, fs);
11987 gen_load_fpr32(ctx, fp1, ft);
11988 gen_store_fpr32(ctx, fp1, fd);
11989 gen_store_fpr32h(ctx, fp0, fd);
11990 tcg_temp_free_i32(fp0);
11991 tcg_temp_free_i32(fp1);
11993 break;
11994 case OPC_PUU_PS:
11995 check_ps(ctx);
11997 TCGv_i32 fp0 = tcg_temp_new_i32();
11998 TCGv_i32 fp1 = tcg_temp_new_i32();
12000 gen_load_fpr32h(ctx, fp0, fs);
12001 gen_load_fpr32h(ctx, fp1, ft);
12002 gen_store_fpr32(ctx, fp1, fd);
12003 gen_store_fpr32h(ctx, fp0, fd);
12004 tcg_temp_free_i32(fp0);
12005 tcg_temp_free_i32(fp1);
12007 break;
12008 case OPC_CMP_F_PS:
12009 case OPC_CMP_UN_PS:
12010 case OPC_CMP_EQ_PS:
12011 case OPC_CMP_UEQ_PS:
12012 case OPC_CMP_OLT_PS:
12013 case OPC_CMP_ULT_PS:
12014 case OPC_CMP_OLE_PS:
12015 case OPC_CMP_ULE_PS:
12016 case OPC_CMP_SF_PS:
12017 case OPC_CMP_NGLE_PS:
12018 case OPC_CMP_SEQ_PS:
12019 case OPC_CMP_NGL_PS:
12020 case OPC_CMP_LT_PS:
12021 case OPC_CMP_NGE_PS:
12022 case OPC_CMP_LE_PS:
12023 case OPC_CMP_NGT_PS:
12024 if (ctx->opcode & (1 << 6)) {
12025 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12026 } else {
12027 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12029 break;
12030 default:
12031 MIPS_INVAL("farith");
12032 generate_exception_end(ctx, EXCP_RI);
12033 return;
12037 /* Coprocessor 3 (FPU) */
12038 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12039 int fd, int fs, int base, int index)
12041 TCGv t0 = tcg_temp_new();
12043 if (base == 0) {
12044 gen_load_gpr(t0, index);
12045 } else if (index == 0) {
12046 gen_load_gpr(t0, base);
12047 } else {
12048 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12050 /* Don't do NOP if destination is zero: we must perform the actual
12051 memory access. */
12052 switch (opc) {
12053 case OPC_LWXC1:
12054 check_cop1x(ctx);
12056 TCGv_i32 fp0 = tcg_temp_new_i32();
12058 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12059 tcg_gen_trunc_tl_i32(fp0, t0);
12060 gen_store_fpr32(ctx, fp0, fd);
12061 tcg_temp_free_i32(fp0);
12063 break;
12064 case OPC_LDXC1:
12065 check_cop1x(ctx);
12066 check_cp1_registers(ctx, fd);
12068 TCGv_i64 fp0 = tcg_temp_new_i64();
12069 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12070 gen_store_fpr64(ctx, fp0, fd);
12071 tcg_temp_free_i64(fp0);
12073 break;
12074 case OPC_LUXC1:
12075 check_cp1_64bitmode(ctx);
12076 tcg_gen_andi_tl(t0, t0, ~0x7);
12078 TCGv_i64 fp0 = tcg_temp_new_i64();
12080 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12081 gen_store_fpr64(ctx, fp0, fd);
12082 tcg_temp_free_i64(fp0);
12084 break;
12085 case OPC_SWXC1:
12086 check_cop1x(ctx);
12088 TCGv_i32 fp0 = tcg_temp_new_i32();
12089 gen_load_fpr32(ctx, fp0, fs);
12090 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12091 tcg_temp_free_i32(fp0);
12093 break;
12094 case OPC_SDXC1:
12095 check_cop1x(ctx);
12096 check_cp1_registers(ctx, fs);
12098 TCGv_i64 fp0 = tcg_temp_new_i64();
12099 gen_load_fpr64(ctx, fp0, fs);
12100 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12101 tcg_temp_free_i64(fp0);
12103 break;
12104 case OPC_SUXC1:
12105 check_cp1_64bitmode(ctx);
12106 tcg_gen_andi_tl(t0, t0, ~0x7);
12108 TCGv_i64 fp0 = tcg_temp_new_i64();
12109 gen_load_fpr64(ctx, fp0, fs);
12110 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12111 tcg_temp_free_i64(fp0);
12113 break;
12115 tcg_temp_free(t0);
12118 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12119 int fd, int fr, int fs, int ft)
12121 switch (opc) {
12122 case OPC_ALNV_PS:
12123 check_ps(ctx);
12125 TCGv t0 = tcg_temp_local_new();
12126 TCGv_i32 fp = tcg_temp_new_i32();
12127 TCGv_i32 fph = tcg_temp_new_i32();
12128 TCGLabel *l1 = gen_new_label();
12129 TCGLabel *l2 = gen_new_label();
12131 gen_load_gpr(t0, fr);
12132 tcg_gen_andi_tl(t0, t0, 0x7);
12134 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12135 gen_load_fpr32(ctx, fp, fs);
12136 gen_load_fpr32h(ctx, fph, fs);
12137 gen_store_fpr32(ctx, fp, fd);
12138 gen_store_fpr32h(ctx, fph, fd);
12139 tcg_gen_br(l2);
12140 gen_set_label(l1);
12141 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12142 tcg_temp_free(t0);
12143 #ifdef TARGET_WORDS_BIGENDIAN
12144 gen_load_fpr32(ctx, fp, fs);
12145 gen_load_fpr32h(ctx, fph, ft);
12146 gen_store_fpr32h(ctx, fp, fd);
12147 gen_store_fpr32(ctx, fph, fd);
12148 #else
12149 gen_load_fpr32h(ctx, fph, fs);
12150 gen_load_fpr32(ctx, fp, ft);
12151 gen_store_fpr32(ctx, fph, fd);
12152 gen_store_fpr32h(ctx, fp, fd);
12153 #endif
12154 gen_set_label(l2);
12155 tcg_temp_free_i32(fp);
12156 tcg_temp_free_i32(fph);
12158 break;
12159 case OPC_MADD_S:
12160 check_cop1x(ctx);
12162 TCGv_i32 fp0 = tcg_temp_new_i32();
12163 TCGv_i32 fp1 = tcg_temp_new_i32();
12164 TCGv_i32 fp2 = tcg_temp_new_i32();
12166 gen_load_fpr32(ctx, fp0, fs);
12167 gen_load_fpr32(ctx, fp1, ft);
12168 gen_load_fpr32(ctx, fp2, fr);
12169 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12170 tcg_temp_free_i32(fp0);
12171 tcg_temp_free_i32(fp1);
12172 gen_store_fpr32(ctx, fp2, fd);
12173 tcg_temp_free_i32(fp2);
12175 break;
12176 case OPC_MADD_D:
12177 check_cop1x(ctx);
12178 check_cp1_registers(ctx, fd | fs | ft | fr);
12180 TCGv_i64 fp0 = tcg_temp_new_i64();
12181 TCGv_i64 fp1 = tcg_temp_new_i64();
12182 TCGv_i64 fp2 = tcg_temp_new_i64();
12184 gen_load_fpr64(ctx, fp0, fs);
12185 gen_load_fpr64(ctx, fp1, ft);
12186 gen_load_fpr64(ctx, fp2, fr);
12187 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12188 tcg_temp_free_i64(fp0);
12189 tcg_temp_free_i64(fp1);
12190 gen_store_fpr64(ctx, fp2, fd);
12191 tcg_temp_free_i64(fp2);
12193 break;
12194 case OPC_MADD_PS:
12195 check_ps(ctx);
12197 TCGv_i64 fp0 = tcg_temp_new_i64();
12198 TCGv_i64 fp1 = tcg_temp_new_i64();
12199 TCGv_i64 fp2 = tcg_temp_new_i64();
12201 gen_load_fpr64(ctx, fp0, fs);
12202 gen_load_fpr64(ctx, fp1, ft);
12203 gen_load_fpr64(ctx, fp2, fr);
12204 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12205 tcg_temp_free_i64(fp0);
12206 tcg_temp_free_i64(fp1);
12207 gen_store_fpr64(ctx, fp2, fd);
12208 tcg_temp_free_i64(fp2);
12210 break;
12211 case OPC_MSUB_S:
12212 check_cop1x(ctx);
12214 TCGv_i32 fp0 = tcg_temp_new_i32();
12215 TCGv_i32 fp1 = tcg_temp_new_i32();
12216 TCGv_i32 fp2 = tcg_temp_new_i32();
12218 gen_load_fpr32(ctx, fp0, fs);
12219 gen_load_fpr32(ctx, fp1, ft);
12220 gen_load_fpr32(ctx, fp2, fr);
12221 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12222 tcg_temp_free_i32(fp0);
12223 tcg_temp_free_i32(fp1);
12224 gen_store_fpr32(ctx, fp2, fd);
12225 tcg_temp_free_i32(fp2);
12227 break;
12228 case OPC_MSUB_D:
12229 check_cop1x(ctx);
12230 check_cp1_registers(ctx, fd | fs | ft | fr);
12232 TCGv_i64 fp0 = tcg_temp_new_i64();
12233 TCGv_i64 fp1 = tcg_temp_new_i64();
12234 TCGv_i64 fp2 = tcg_temp_new_i64();
12236 gen_load_fpr64(ctx, fp0, fs);
12237 gen_load_fpr64(ctx, fp1, ft);
12238 gen_load_fpr64(ctx, fp2, fr);
12239 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12240 tcg_temp_free_i64(fp0);
12241 tcg_temp_free_i64(fp1);
12242 gen_store_fpr64(ctx, fp2, fd);
12243 tcg_temp_free_i64(fp2);
12245 break;
12246 case OPC_MSUB_PS:
12247 check_ps(ctx);
12249 TCGv_i64 fp0 = tcg_temp_new_i64();
12250 TCGv_i64 fp1 = tcg_temp_new_i64();
12251 TCGv_i64 fp2 = tcg_temp_new_i64();
12253 gen_load_fpr64(ctx, fp0, fs);
12254 gen_load_fpr64(ctx, fp1, ft);
12255 gen_load_fpr64(ctx, fp2, fr);
12256 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12257 tcg_temp_free_i64(fp0);
12258 tcg_temp_free_i64(fp1);
12259 gen_store_fpr64(ctx, fp2, fd);
12260 tcg_temp_free_i64(fp2);
12262 break;
12263 case OPC_NMADD_S:
12264 check_cop1x(ctx);
12266 TCGv_i32 fp0 = tcg_temp_new_i32();
12267 TCGv_i32 fp1 = tcg_temp_new_i32();
12268 TCGv_i32 fp2 = tcg_temp_new_i32();
12270 gen_load_fpr32(ctx, fp0, fs);
12271 gen_load_fpr32(ctx, fp1, ft);
12272 gen_load_fpr32(ctx, fp2, fr);
12273 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12274 tcg_temp_free_i32(fp0);
12275 tcg_temp_free_i32(fp1);
12276 gen_store_fpr32(ctx, fp2, fd);
12277 tcg_temp_free_i32(fp2);
12279 break;
12280 case OPC_NMADD_D:
12281 check_cop1x(ctx);
12282 check_cp1_registers(ctx, fd | fs | ft | fr);
12284 TCGv_i64 fp0 = tcg_temp_new_i64();
12285 TCGv_i64 fp1 = tcg_temp_new_i64();
12286 TCGv_i64 fp2 = tcg_temp_new_i64();
12288 gen_load_fpr64(ctx, fp0, fs);
12289 gen_load_fpr64(ctx, fp1, ft);
12290 gen_load_fpr64(ctx, fp2, fr);
12291 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12292 tcg_temp_free_i64(fp0);
12293 tcg_temp_free_i64(fp1);
12294 gen_store_fpr64(ctx, fp2, fd);
12295 tcg_temp_free_i64(fp2);
12297 break;
12298 case OPC_NMADD_PS:
12299 check_ps(ctx);
12301 TCGv_i64 fp0 = tcg_temp_new_i64();
12302 TCGv_i64 fp1 = tcg_temp_new_i64();
12303 TCGv_i64 fp2 = tcg_temp_new_i64();
12305 gen_load_fpr64(ctx, fp0, fs);
12306 gen_load_fpr64(ctx, fp1, ft);
12307 gen_load_fpr64(ctx, fp2, fr);
12308 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12309 tcg_temp_free_i64(fp0);
12310 tcg_temp_free_i64(fp1);
12311 gen_store_fpr64(ctx, fp2, fd);
12312 tcg_temp_free_i64(fp2);
12314 break;
12315 case OPC_NMSUB_S:
12316 check_cop1x(ctx);
12318 TCGv_i32 fp0 = tcg_temp_new_i32();
12319 TCGv_i32 fp1 = tcg_temp_new_i32();
12320 TCGv_i32 fp2 = tcg_temp_new_i32();
12322 gen_load_fpr32(ctx, fp0, fs);
12323 gen_load_fpr32(ctx, fp1, ft);
12324 gen_load_fpr32(ctx, fp2, fr);
12325 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12326 tcg_temp_free_i32(fp0);
12327 tcg_temp_free_i32(fp1);
12328 gen_store_fpr32(ctx, fp2, fd);
12329 tcg_temp_free_i32(fp2);
12331 break;
12332 case OPC_NMSUB_D:
12333 check_cop1x(ctx);
12334 check_cp1_registers(ctx, fd | fs | ft | fr);
12336 TCGv_i64 fp0 = tcg_temp_new_i64();
12337 TCGv_i64 fp1 = tcg_temp_new_i64();
12338 TCGv_i64 fp2 = tcg_temp_new_i64();
12340 gen_load_fpr64(ctx, fp0, fs);
12341 gen_load_fpr64(ctx, fp1, ft);
12342 gen_load_fpr64(ctx, fp2, fr);
12343 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12344 tcg_temp_free_i64(fp0);
12345 tcg_temp_free_i64(fp1);
12346 gen_store_fpr64(ctx, fp2, fd);
12347 tcg_temp_free_i64(fp2);
12349 break;
12350 case OPC_NMSUB_PS:
12351 check_ps(ctx);
12353 TCGv_i64 fp0 = tcg_temp_new_i64();
12354 TCGv_i64 fp1 = tcg_temp_new_i64();
12355 TCGv_i64 fp2 = tcg_temp_new_i64();
12357 gen_load_fpr64(ctx, fp0, fs);
12358 gen_load_fpr64(ctx, fp1, ft);
12359 gen_load_fpr64(ctx, fp2, fr);
12360 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12361 tcg_temp_free_i64(fp0);
12362 tcg_temp_free_i64(fp1);
12363 gen_store_fpr64(ctx, fp2, fd);
12364 tcg_temp_free_i64(fp2);
12366 break;
12367 default:
12368 MIPS_INVAL("flt3_arith");
12369 generate_exception_end(ctx, EXCP_RI);
12370 return;
12374 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12376 TCGv t0;
12378 #if !defined(CONFIG_USER_ONLY)
12379 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12380 Therefore only check the ISA in system mode. */
12381 check_insn(ctx, ISA_MIPS32R2);
12382 #endif
12383 t0 = tcg_temp_new();
12385 switch (rd) {
12386 case 0:
12387 gen_helper_rdhwr_cpunum(t0, cpu_env);
12388 gen_store_gpr(t0, rt);
12389 break;
12390 case 1:
12391 gen_helper_rdhwr_synci_step(t0, cpu_env);
12392 gen_store_gpr(t0, rt);
12393 break;
12394 case 2:
12395 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12396 gen_io_start();
12398 gen_helper_rdhwr_cc(t0, cpu_env);
12399 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12400 gen_io_end();
12402 gen_store_gpr(t0, rt);
12403 /* Break the TB to be able to take timer interrupts immediately
12404 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12405 we break completely out of translated code. */
12406 gen_save_pc(ctx->base.pc_next + 4);
12407 ctx->base.is_jmp = DISAS_EXIT;
12408 break;
12409 case 3:
12410 gen_helper_rdhwr_ccres(t0, cpu_env);
12411 gen_store_gpr(t0, rt);
12412 break;
12413 case 4:
12414 check_insn(ctx, ISA_MIPS32R6);
12415 if (sel != 0) {
12416 /* Performance counter registers are not implemented other than
12417 * control register 0.
12419 generate_exception(ctx, EXCP_RI);
12421 gen_helper_rdhwr_performance(t0, cpu_env);
12422 gen_store_gpr(t0, rt);
12423 break;
12424 case 5:
12425 check_insn(ctx, ISA_MIPS32R6);
12426 gen_helper_rdhwr_xnp(t0, cpu_env);
12427 gen_store_gpr(t0, rt);
12428 break;
12429 case 29:
12430 #if defined(CONFIG_USER_ONLY)
12431 tcg_gen_ld_tl(t0, cpu_env,
12432 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12433 gen_store_gpr(t0, rt);
12434 break;
12435 #else
12436 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12437 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12438 tcg_gen_ld_tl(t0, cpu_env,
12439 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12440 gen_store_gpr(t0, rt);
12441 } else {
12442 generate_exception_end(ctx, EXCP_RI);
12444 break;
12445 #endif
12446 default: /* Invalid */
12447 MIPS_INVAL("rdhwr");
12448 generate_exception_end(ctx, EXCP_RI);
12449 break;
12451 tcg_temp_free(t0);
12454 static inline void clear_branch_hflags(DisasContext *ctx)
12456 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12457 if (ctx->base.is_jmp == DISAS_NEXT) {
12458 save_cpu_state(ctx, 0);
12459 } else {
12460 /* it is not safe to save ctx->hflags as hflags may be changed
12461 in execution time by the instruction in delay / forbidden slot. */
12462 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12466 static void gen_branch(DisasContext *ctx, int insn_bytes)
12468 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12469 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12470 /* Branches completion */
12471 clear_branch_hflags(ctx);
12472 ctx->base.is_jmp = DISAS_NORETURN;
12473 /* FIXME: Need to clear can_do_io. */
12474 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12475 case MIPS_HFLAG_FBNSLOT:
12476 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12477 break;
12478 case MIPS_HFLAG_B:
12479 /* unconditional branch */
12480 if (proc_hflags & MIPS_HFLAG_BX) {
12481 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12483 gen_goto_tb(ctx, 0, ctx->btarget);
12484 break;
12485 case MIPS_HFLAG_BL:
12486 /* blikely taken case */
12487 gen_goto_tb(ctx, 0, ctx->btarget);
12488 break;
12489 case MIPS_HFLAG_BC:
12490 /* Conditional branch */
12492 TCGLabel *l1 = gen_new_label();
12494 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12495 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12496 gen_set_label(l1);
12497 gen_goto_tb(ctx, 0, ctx->btarget);
12499 break;
12500 case MIPS_HFLAG_BR:
12501 /* unconditional branch to register */
12502 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12503 TCGv t0 = tcg_temp_new();
12504 TCGv_i32 t1 = tcg_temp_new_i32();
12506 tcg_gen_andi_tl(t0, btarget, 0x1);
12507 tcg_gen_trunc_tl_i32(t1, t0);
12508 tcg_temp_free(t0);
12509 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12510 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12511 tcg_gen_or_i32(hflags, hflags, t1);
12512 tcg_temp_free_i32(t1);
12514 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12515 } else {
12516 tcg_gen_mov_tl(cpu_PC, btarget);
12518 if (ctx->base.singlestep_enabled) {
12519 save_cpu_state(ctx, 0);
12520 gen_helper_raise_exception_debug(cpu_env);
12522 tcg_gen_lookup_and_goto_ptr();
12523 break;
12524 default:
12525 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12526 abort();
12531 /* Compact Branches */
12532 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12533 int rs, int rt, int32_t offset)
12535 int bcond_compute = 0;
12536 TCGv t0 = tcg_temp_new();
12537 TCGv t1 = tcg_temp_new();
12538 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12540 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12541 #ifdef MIPS_DEBUG_DISAS
12542 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12543 "\n", ctx->base.pc_next);
12544 #endif
12545 generate_exception_end(ctx, EXCP_RI);
12546 goto out;
12549 /* Load needed operands and calculate btarget */
12550 switch (opc) {
12551 /* compact branch */
12552 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12553 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12554 gen_load_gpr(t0, rs);
12555 gen_load_gpr(t1, rt);
12556 bcond_compute = 1;
12557 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12558 if (rs <= rt && rs == 0) {
12559 /* OPC_BEQZALC, OPC_BNEZALC */
12560 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12562 break;
12563 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12564 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12565 gen_load_gpr(t0, rs);
12566 gen_load_gpr(t1, rt);
12567 bcond_compute = 1;
12568 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12569 break;
12570 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12571 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12572 if (rs == 0 || rs == rt) {
12573 /* OPC_BLEZALC, OPC_BGEZALC */
12574 /* OPC_BGTZALC, OPC_BLTZALC */
12575 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12577 gen_load_gpr(t0, rs);
12578 gen_load_gpr(t1, rt);
12579 bcond_compute = 1;
12580 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12581 break;
12582 case OPC_BC:
12583 case OPC_BALC:
12584 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12585 break;
12586 case OPC_BEQZC:
12587 case OPC_BNEZC:
12588 if (rs != 0) {
12589 /* OPC_BEQZC, OPC_BNEZC */
12590 gen_load_gpr(t0, rs);
12591 bcond_compute = 1;
12592 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12593 } else {
12594 /* OPC_JIC, OPC_JIALC */
12595 TCGv tbase = tcg_temp_new();
12596 TCGv toffset = tcg_temp_new();
12598 gen_load_gpr(tbase, rt);
12599 tcg_gen_movi_tl(toffset, offset);
12600 gen_op_addr_add(ctx, btarget, tbase, toffset);
12601 tcg_temp_free(tbase);
12602 tcg_temp_free(toffset);
12604 break;
12605 default:
12606 MIPS_INVAL("Compact branch/jump");
12607 generate_exception_end(ctx, EXCP_RI);
12608 goto out;
12611 if (bcond_compute == 0) {
12612 /* Uncoditional compact branch */
12613 switch (opc) {
12614 case OPC_JIALC:
12615 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12616 /* Fallthrough */
12617 case OPC_JIC:
12618 ctx->hflags |= MIPS_HFLAG_BR;
12619 break;
12620 case OPC_BALC:
12621 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12622 /* Fallthrough */
12623 case OPC_BC:
12624 ctx->hflags |= MIPS_HFLAG_B;
12625 break;
12626 default:
12627 MIPS_INVAL("Compact branch/jump");
12628 generate_exception_end(ctx, EXCP_RI);
12629 goto out;
12632 /* Generating branch here as compact branches don't have delay slot */
12633 gen_branch(ctx, 4);
12634 } else {
12635 /* Conditional compact branch */
12636 TCGLabel *fs = gen_new_label();
12637 save_cpu_state(ctx, 0);
12639 switch (opc) {
12640 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12641 if (rs == 0 && rt != 0) {
12642 /* OPC_BLEZALC */
12643 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12644 } else if (rs != 0 && rt != 0 && rs == rt) {
12645 /* OPC_BGEZALC */
12646 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12647 } else {
12648 /* OPC_BGEUC */
12649 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12651 break;
12652 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12653 if (rs == 0 && rt != 0) {
12654 /* OPC_BGTZALC */
12655 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12656 } else if (rs != 0 && rt != 0 && rs == rt) {
12657 /* OPC_BLTZALC */
12658 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12659 } else {
12660 /* OPC_BLTUC */
12661 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12663 break;
12664 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12665 if (rs == 0 && rt != 0) {
12666 /* OPC_BLEZC */
12667 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12668 } else if (rs != 0 && rt != 0 && rs == rt) {
12669 /* OPC_BGEZC */
12670 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12671 } else {
12672 /* OPC_BGEC */
12673 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12675 break;
12676 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12677 if (rs == 0 && rt != 0) {
12678 /* OPC_BGTZC */
12679 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12680 } else if (rs != 0 && rt != 0 && rs == rt) {
12681 /* OPC_BLTZC */
12682 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12683 } else {
12684 /* OPC_BLTC */
12685 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12687 break;
12688 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12689 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12690 if (rs >= rt) {
12691 /* OPC_BOVC, OPC_BNVC */
12692 TCGv t2 = tcg_temp_new();
12693 TCGv t3 = tcg_temp_new();
12694 TCGv t4 = tcg_temp_new();
12695 TCGv input_overflow = tcg_temp_new();
12697 gen_load_gpr(t0, rs);
12698 gen_load_gpr(t1, rt);
12699 tcg_gen_ext32s_tl(t2, t0);
12700 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12701 tcg_gen_ext32s_tl(t3, t1);
12702 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12703 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12705 tcg_gen_add_tl(t4, t2, t3);
12706 tcg_gen_ext32s_tl(t4, t4);
12707 tcg_gen_xor_tl(t2, t2, t3);
12708 tcg_gen_xor_tl(t3, t4, t3);
12709 tcg_gen_andc_tl(t2, t3, t2);
12710 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12711 tcg_gen_or_tl(t4, t4, input_overflow);
12712 if (opc == OPC_BOVC) {
12713 /* OPC_BOVC */
12714 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12715 } else {
12716 /* OPC_BNVC */
12717 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12719 tcg_temp_free(input_overflow);
12720 tcg_temp_free(t4);
12721 tcg_temp_free(t3);
12722 tcg_temp_free(t2);
12723 } else if (rs < rt && rs == 0) {
12724 /* OPC_BEQZALC, OPC_BNEZALC */
12725 if (opc == OPC_BEQZALC) {
12726 /* OPC_BEQZALC */
12727 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12728 } else {
12729 /* OPC_BNEZALC */
12730 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12732 } else {
12733 /* OPC_BEQC, OPC_BNEC */
12734 if (opc == OPC_BEQC) {
12735 /* OPC_BEQC */
12736 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12737 } else {
12738 /* OPC_BNEC */
12739 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12742 break;
12743 case OPC_BEQZC:
12744 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12745 break;
12746 case OPC_BNEZC:
12747 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12748 break;
12749 default:
12750 MIPS_INVAL("Compact conditional branch/jump");
12751 generate_exception_end(ctx, EXCP_RI);
12752 goto out;
12755 /* Generating branch here as compact branches don't have delay slot */
12756 gen_goto_tb(ctx, 1, ctx->btarget);
12757 gen_set_label(fs);
12759 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12762 out:
12763 tcg_temp_free(t0);
12764 tcg_temp_free(t1);
12767 /* ISA extensions (ASEs) */
12768 /* MIPS16 extension to MIPS32 */
12770 /* MIPS16 major opcodes */
12771 enum {
12772 M16_OPC_ADDIUSP = 0x00,
12773 M16_OPC_ADDIUPC = 0x01,
12774 M16_OPC_B = 0x02,
12775 M16_OPC_JAL = 0x03,
12776 M16_OPC_BEQZ = 0x04,
12777 M16_OPC_BNEQZ = 0x05,
12778 M16_OPC_SHIFT = 0x06,
12779 M16_OPC_LD = 0x07,
12780 M16_OPC_RRIA = 0x08,
12781 M16_OPC_ADDIU8 = 0x09,
12782 M16_OPC_SLTI = 0x0a,
12783 M16_OPC_SLTIU = 0x0b,
12784 M16_OPC_I8 = 0x0c,
12785 M16_OPC_LI = 0x0d,
12786 M16_OPC_CMPI = 0x0e,
12787 M16_OPC_SD = 0x0f,
12788 M16_OPC_LB = 0x10,
12789 M16_OPC_LH = 0x11,
12790 M16_OPC_LWSP = 0x12,
12791 M16_OPC_LW = 0x13,
12792 M16_OPC_LBU = 0x14,
12793 M16_OPC_LHU = 0x15,
12794 M16_OPC_LWPC = 0x16,
12795 M16_OPC_LWU = 0x17,
12796 M16_OPC_SB = 0x18,
12797 M16_OPC_SH = 0x19,
12798 M16_OPC_SWSP = 0x1a,
12799 M16_OPC_SW = 0x1b,
12800 M16_OPC_RRR = 0x1c,
12801 M16_OPC_RR = 0x1d,
12802 M16_OPC_EXTEND = 0x1e,
12803 M16_OPC_I64 = 0x1f
12806 /* I8 funct field */
12807 enum {
12808 I8_BTEQZ = 0x0,
12809 I8_BTNEZ = 0x1,
12810 I8_SWRASP = 0x2,
12811 I8_ADJSP = 0x3,
12812 I8_SVRS = 0x4,
12813 I8_MOV32R = 0x5,
12814 I8_MOVR32 = 0x7
12817 /* RRR f field */
12818 enum {
12819 RRR_DADDU = 0x0,
12820 RRR_ADDU = 0x1,
12821 RRR_DSUBU = 0x2,
12822 RRR_SUBU = 0x3
12825 /* RR funct field */
12826 enum {
12827 RR_JR = 0x00,
12828 RR_SDBBP = 0x01,
12829 RR_SLT = 0x02,
12830 RR_SLTU = 0x03,
12831 RR_SLLV = 0x04,
12832 RR_BREAK = 0x05,
12833 RR_SRLV = 0x06,
12834 RR_SRAV = 0x07,
12835 RR_DSRL = 0x08,
12836 RR_CMP = 0x0a,
12837 RR_NEG = 0x0b,
12838 RR_AND = 0x0c,
12839 RR_OR = 0x0d,
12840 RR_XOR = 0x0e,
12841 RR_NOT = 0x0f,
12842 RR_MFHI = 0x10,
12843 RR_CNVT = 0x11,
12844 RR_MFLO = 0x12,
12845 RR_DSRA = 0x13,
12846 RR_DSLLV = 0x14,
12847 RR_DSRLV = 0x16,
12848 RR_DSRAV = 0x17,
12849 RR_MULT = 0x18,
12850 RR_MULTU = 0x19,
12851 RR_DIV = 0x1a,
12852 RR_DIVU = 0x1b,
12853 RR_DMULT = 0x1c,
12854 RR_DMULTU = 0x1d,
12855 RR_DDIV = 0x1e,
12856 RR_DDIVU = 0x1f
12859 /* I64 funct field */
12860 enum {
12861 I64_LDSP = 0x0,
12862 I64_SDSP = 0x1,
12863 I64_SDRASP = 0x2,
12864 I64_DADJSP = 0x3,
12865 I64_LDPC = 0x4,
12866 I64_DADDIU5 = 0x5,
12867 I64_DADDIUPC = 0x6,
12868 I64_DADDIUSP = 0x7
12871 /* RR ry field for CNVT */
12872 enum {
12873 RR_RY_CNVT_ZEB = 0x0,
12874 RR_RY_CNVT_ZEH = 0x1,
12875 RR_RY_CNVT_ZEW = 0x2,
12876 RR_RY_CNVT_SEB = 0x4,
12877 RR_RY_CNVT_SEH = 0x5,
12878 RR_RY_CNVT_SEW = 0x6,
12881 static int xlat (int r)
12883 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12885 return map[r];
12888 static void gen_mips16_save (DisasContext *ctx,
12889 int xsregs, int aregs,
12890 int do_ra, int do_s0, int do_s1,
12891 int framesize)
12893 TCGv t0 = tcg_temp_new();
12894 TCGv t1 = tcg_temp_new();
12895 TCGv t2 = tcg_temp_new();
12896 int args, astatic;
12898 switch (aregs) {
12899 case 0:
12900 case 1:
12901 case 2:
12902 case 3:
12903 case 11:
12904 args = 0;
12905 break;
12906 case 4:
12907 case 5:
12908 case 6:
12909 case 7:
12910 args = 1;
12911 break;
12912 case 8:
12913 case 9:
12914 case 10:
12915 args = 2;
12916 break;
12917 case 12:
12918 case 13:
12919 args = 3;
12920 break;
12921 case 14:
12922 args = 4;
12923 break;
12924 default:
12925 generate_exception_end(ctx, EXCP_RI);
12926 return;
12929 switch (args) {
12930 case 4:
12931 gen_base_offset_addr(ctx, t0, 29, 12);
12932 gen_load_gpr(t1, 7);
12933 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12934 /* Fall through */
12935 case 3:
12936 gen_base_offset_addr(ctx, t0, 29, 8);
12937 gen_load_gpr(t1, 6);
12938 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12939 /* Fall through */
12940 case 2:
12941 gen_base_offset_addr(ctx, t0, 29, 4);
12942 gen_load_gpr(t1, 5);
12943 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12944 /* Fall through */
12945 case 1:
12946 gen_base_offset_addr(ctx, t0, 29, 0);
12947 gen_load_gpr(t1, 4);
12948 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12951 gen_load_gpr(t0, 29);
12953 #define DECR_AND_STORE(reg) do { \
12954 tcg_gen_movi_tl(t2, -4); \
12955 gen_op_addr_add(ctx, t0, t0, t2); \
12956 gen_load_gpr(t1, reg); \
12957 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12958 } while (0)
12960 if (do_ra) {
12961 DECR_AND_STORE(31);
12964 switch (xsregs) {
12965 case 7:
12966 DECR_AND_STORE(30);
12967 /* Fall through */
12968 case 6:
12969 DECR_AND_STORE(23);
12970 /* Fall through */
12971 case 5:
12972 DECR_AND_STORE(22);
12973 /* Fall through */
12974 case 4:
12975 DECR_AND_STORE(21);
12976 /* Fall through */
12977 case 3:
12978 DECR_AND_STORE(20);
12979 /* Fall through */
12980 case 2:
12981 DECR_AND_STORE(19);
12982 /* Fall through */
12983 case 1:
12984 DECR_AND_STORE(18);
12987 if (do_s1) {
12988 DECR_AND_STORE(17);
12990 if (do_s0) {
12991 DECR_AND_STORE(16);
12994 switch (aregs) {
12995 case 0:
12996 case 4:
12997 case 8:
12998 case 12:
12999 case 14:
13000 astatic = 0;
13001 break;
13002 case 1:
13003 case 5:
13004 case 9:
13005 case 13:
13006 astatic = 1;
13007 break;
13008 case 2:
13009 case 6:
13010 case 10:
13011 astatic = 2;
13012 break;
13013 case 3:
13014 case 7:
13015 astatic = 3;
13016 break;
13017 case 11:
13018 astatic = 4;
13019 break;
13020 default:
13021 generate_exception_end(ctx, EXCP_RI);
13022 return;
13025 if (astatic > 0) {
13026 DECR_AND_STORE(7);
13027 if (astatic > 1) {
13028 DECR_AND_STORE(6);
13029 if (astatic > 2) {
13030 DECR_AND_STORE(5);
13031 if (astatic > 3) {
13032 DECR_AND_STORE(4);
13037 #undef DECR_AND_STORE
13039 tcg_gen_movi_tl(t2, -framesize);
13040 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13041 tcg_temp_free(t0);
13042 tcg_temp_free(t1);
13043 tcg_temp_free(t2);
13046 static void gen_mips16_restore (DisasContext *ctx,
13047 int xsregs, int aregs,
13048 int do_ra, int do_s0, int do_s1,
13049 int framesize)
13051 int astatic;
13052 TCGv t0 = tcg_temp_new();
13053 TCGv t1 = tcg_temp_new();
13054 TCGv t2 = tcg_temp_new();
13056 tcg_gen_movi_tl(t2, framesize);
13057 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13059 #define DECR_AND_LOAD(reg) do { \
13060 tcg_gen_movi_tl(t2, -4); \
13061 gen_op_addr_add(ctx, t0, t0, t2); \
13062 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13063 gen_store_gpr(t1, reg); \
13064 } while (0)
13066 if (do_ra) {
13067 DECR_AND_LOAD(31);
13070 switch (xsregs) {
13071 case 7:
13072 DECR_AND_LOAD(30);
13073 /* Fall through */
13074 case 6:
13075 DECR_AND_LOAD(23);
13076 /* Fall through */
13077 case 5:
13078 DECR_AND_LOAD(22);
13079 /* Fall through */
13080 case 4:
13081 DECR_AND_LOAD(21);
13082 /* Fall through */
13083 case 3:
13084 DECR_AND_LOAD(20);
13085 /* Fall through */
13086 case 2:
13087 DECR_AND_LOAD(19);
13088 /* Fall through */
13089 case 1:
13090 DECR_AND_LOAD(18);
13093 if (do_s1) {
13094 DECR_AND_LOAD(17);
13096 if (do_s0) {
13097 DECR_AND_LOAD(16);
13100 switch (aregs) {
13101 case 0:
13102 case 4:
13103 case 8:
13104 case 12:
13105 case 14:
13106 astatic = 0;
13107 break;
13108 case 1:
13109 case 5:
13110 case 9:
13111 case 13:
13112 astatic = 1;
13113 break;
13114 case 2:
13115 case 6:
13116 case 10:
13117 astatic = 2;
13118 break;
13119 case 3:
13120 case 7:
13121 astatic = 3;
13122 break;
13123 case 11:
13124 astatic = 4;
13125 break;
13126 default:
13127 generate_exception_end(ctx, EXCP_RI);
13128 return;
13131 if (astatic > 0) {
13132 DECR_AND_LOAD(7);
13133 if (astatic > 1) {
13134 DECR_AND_LOAD(6);
13135 if (astatic > 2) {
13136 DECR_AND_LOAD(5);
13137 if (astatic > 3) {
13138 DECR_AND_LOAD(4);
13143 #undef DECR_AND_LOAD
13145 tcg_gen_movi_tl(t2, framesize);
13146 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13147 tcg_temp_free(t0);
13148 tcg_temp_free(t1);
13149 tcg_temp_free(t2);
13152 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13153 int is_64_bit, int extended)
13155 TCGv t0;
13157 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13158 generate_exception_end(ctx, EXCP_RI);
13159 return;
13162 t0 = tcg_temp_new();
13164 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13165 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13166 if (!is_64_bit) {
13167 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13170 tcg_temp_free(t0);
13173 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13174 int16_t offset)
13176 TCGv_i32 t0 = tcg_const_i32(op);
13177 TCGv t1 = tcg_temp_new();
13178 gen_base_offset_addr(ctx, t1, base, offset);
13179 gen_helper_cache(cpu_env, t1, t0);
13182 #if defined(TARGET_MIPS64)
13183 static void decode_i64_mips16 (DisasContext *ctx,
13184 int ry, int funct, int16_t offset,
13185 int extended)
13187 switch (funct) {
13188 case I64_LDSP:
13189 check_insn(ctx, ISA_MIPS3);
13190 check_mips_64(ctx);
13191 offset = extended ? offset : offset << 3;
13192 gen_ld(ctx, OPC_LD, ry, 29, offset);
13193 break;
13194 case I64_SDSP:
13195 check_insn(ctx, ISA_MIPS3);
13196 check_mips_64(ctx);
13197 offset = extended ? offset : offset << 3;
13198 gen_st(ctx, OPC_SD, ry, 29, offset);
13199 break;
13200 case I64_SDRASP:
13201 check_insn(ctx, ISA_MIPS3);
13202 check_mips_64(ctx);
13203 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13204 gen_st(ctx, OPC_SD, 31, 29, offset);
13205 break;
13206 case I64_DADJSP:
13207 check_insn(ctx, ISA_MIPS3);
13208 check_mips_64(ctx);
13209 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13210 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13211 break;
13212 case I64_LDPC:
13213 check_insn(ctx, ISA_MIPS3);
13214 check_mips_64(ctx);
13215 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13216 generate_exception_end(ctx, EXCP_RI);
13217 } else {
13218 offset = extended ? offset : offset << 3;
13219 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13221 break;
13222 case I64_DADDIU5:
13223 check_insn(ctx, ISA_MIPS3);
13224 check_mips_64(ctx);
13225 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13226 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13227 break;
13228 case I64_DADDIUPC:
13229 check_insn(ctx, ISA_MIPS3);
13230 check_mips_64(ctx);
13231 offset = extended ? offset : offset << 2;
13232 gen_addiupc(ctx, ry, offset, 1, extended);
13233 break;
13234 case I64_DADDIUSP:
13235 check_insn(ctx, ISA_MIPS3);
13236 check_mips_64(ctx);
13237 offset = extended ? offset : offset << 2;
13238 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13239 break;
13242 #endif
13244 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13246 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13247 int op, rx, ry, funct, sa;
13248 int16_t imm, offset;
13250 ctx->opcode = (ctx->opcode << 16) | extend;
13251 op = (ctx->opcode >> 11) & 0x1f;
13252 sa = (ctx->opcode >> 22) & 0x1f;
13253 funct = (ctx->opcode >> 8) & 0x7;
13254 rx = xlat((ctx->opcode >> 8) & 0x7);
13255 ry = xlat((ctx->opcode >> 5) & 0x7);
13256 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13257 | ((ctx->opcode >> 21) & 0x3f) << 5
13258 | (ctx->opcode & 0x1f));
13260 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13261 counterparts. */
13262 switch (op) {
13263 case M16_OPC_ADDIUSP:
13264 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13265 break;
13266 case M16_OPC_ADDIUPC:
13267 gen_addiupc(ctx, rx, imm, 0, 1);
13268 break;
13269 case M16_OPC_B:
13270 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13271 /* No delay slot, so just process as a normal instruction */
13272 break;
13273 case M16_OPC_BEQZ:
13274 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13275 /* No delay slot, so just process as a normal instruction */
13276 break;
13277 case M16_OPC_BNEQZ:
13278 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13279 /* No delay slot, so just process as a normal instruction */
13280 break;
13281 case M16_OPC_SHIFT:
13282 switch (ctx->opcode & 0x3) {
13283 case 0x0:
13284 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13285 break;
13286 case 0x1:
13287 #if defined(TARGET_MIPS64)
13288 check_mips_64(ctx);
13289 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13290 #else
13291 generate_exception_end(ctx, EXCP_RI);
13292 #endif
13293 break;
13294 case 0x2:
13295 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13296 break;
13297 case 0x3:
13298 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13299 break;
13301 break;
13302 #if defined(TARGET_MIPS64)
13303 case M16_OPC_LD:
13304 check_insn(ctx, ISA_MIPS3);
13305 check_mips_64(ctx);
13306 gen_ld(ctx, OPC_LD, ry, rx, offset);
13307 break;
13308 #endif
13309 case M16_OPC_RRIA:
13310 imm = ctx->opcode & 0xf;
13311 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13312 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13313 imm = (int16_t) (imm << 1) >> 1;
13314 if ((ctx->opcode >> 4) & 0x1) {
13315 #if defined(TARGET_MIPS64)
13316 check_mips_64(ctx);
13317 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13318 #else
13319 generate_exception_end(ctx, EXCP_RI);
13320 #endif
13321 } else {
13322 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13324 break;
13325 case M16_OPC_ADDIU8:
13326 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13327 break;
13328 case M16_OPC_SLTI:
13329 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13330 break;
13331 case M16_OPC_SLTIU:
13332 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13333 break;
13334 case M16_OPC_I8:
13335 switch (funct) {
13336 case I8_BTEQZ:
13337 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13338 break;
13339 case I8_BTNEZ:
13340 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13341 break;
13342 case I8_SWRASP:
13343 gen_st(ctx, OPC_SW, 31, 29, imm);
13344 break;
13345 case I8_ADJSP:
13346 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13347 break;
13348 case I8_SVRS:
13349 check_insn(ctx, ISA_MIPS32);
13351 int xsregs = (ctx->opcode >> 24) & 0x7;
13352 int aregs = (ctx->opcode >> 16) & 0xf;
13353 int do_ra = (ctx->opcode >> 6) & 0x1;
13354 int do_s0 = (ctx->opcode >> 5) & 0x1;
13355 int do_s1 = (ctx->opcode >> 4) & 0x1;
13356 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13357 | (ctx->opcode & 0xf)) << 3;
13359 if (ctx->opcode & (1 << 7)) {
13360 gen_mips16_save(ctx, xsregs, aregs,
13361 do_ra, do_s0, do_s1,
13362 framesize);
13363 } else {
13364 gen_mips16_restore(ctx, xsregs, aregs,
13365 do_ra, do_s0, do_s1,
13366 framesize);
13369 break;
13370 default:
13371 generate_exception_end(ctx, EXCP_RI);
13372 break;
13374 break;
13375 case M16_OPC_LI:
13376 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13377 break;
13378 case M16_OPC_CMPI:
13379 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13380 break;
13381 #if defined(TARGET_MIPS64)
13382 case M16_OPC_SD:
13383 check_insn(ctx, ISA_MIPS3);
13384 check_mips_64(ctx);
13385 gen_st(ctx, OPC_SD, ry, rx, offset);
13386 break;
13387 #endif
13388 case M16_OPC_LB:
13389 gen_ld(ctx, OPC_LB, ry, rx, offset);
13390 break;
13391 case M16_OPC_LH:
13392 gen_ld(ctx, OPC_LH, ry, rx, offset);
13393 break;
13394 case M16_OPC_LWSP:
13395 gen_ld(ctx, OPC_LW, rx, 29, offset);
13396 break;
13397 case M16_OPC_LW:
13398 gen_ld(ctx, OPC_LW, ry, rx, offset);
13399 break;
13400 case M16_OPC_LBU:
13401 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13402 break;
13403 case M16_OPC_LHU:
13404 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13405 break;
13406 case M16_OPC_LWPC:
13407 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13408 break;
13409 #if defined(TARGET_MIPS64)
13410 case M16_OPC_LWU:
13411 check_insn(ctx, ISA_MIPS3);
13412 check_mips_64(ctx);
13413 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13414 break;
13415 #endif
13416 case M16_OPC_SB:
13417 gen_st(ctx, OPC_SB, ry, rx, offset);
13418 break;
13419 case M16_OPC_SH:
13420 gen_st(ctx, OPC_SH, ry, rx, offset);
13421 break;
13422 case M16_OPC_SWSP:
13423 gen_st(ctx, OPC_SW, rx, 29, offset);
13424 break;
13425 case M16_OPC_SW:
13426 gen_st(ctx, OPC_SW, ry, rx, offset);
13427 break;
13428 #if defined(TARGET_MIPS64)
13429 case M16_OPC_I64:
13430 decode_i64_mips16(ctx, ry, funct, offset, 1);
13431 break;
13432 #endif
13433 default:
13434 generate_exception_end(ctx, EXCP_RI);
13435 break;
13438 return 4;
13441 static inline bool is_uhi(int sdbbp_code)
13443 #ifdef CONFIG_USER_ONLY
13444 return false;
13445 #else
13446 return semihosting_enabled() && sdbbp_code == 1;
13447 #endif
13450 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13452 int rx, ry;
13453 int sa;
13454 int op, cnvt_op, op1, offset;
13455 int funct;
13456 int n_bytes;
13458 op = (ctx->opcode >> 11) & 0x1f;
13459 sa = (ctx->opcode >> 2) & 0x7;
13460 sa = sa == 0 ? 8 : sa;
13461 rx = xlat((ctx->opcode >> 8) & 0x7);
13462 cnvt_op = (ctx->opcode >> 5) & 0x7;
13463 ry = xlat((ctx->opcode >> 5) & 0x7);
13464 op1 = offset = ctx->opcode & 0x1f;
13466 n_bytes = 2;
13468 switch (op) {
13469 case M16_OPC_ADDIUSP:
13471 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13473 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13475 break;
13476 case M16_OPC_ADDIUPC:
13477 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13478 break;
13479 case M16_OPC_B:
13480 offset = (ctx->opcode & 0x7ff) << 1;
13481 offset = (int16_t)(offset << 4) >> 4;
13482 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13483 /* No delay slot, so just process as a normal instruction */
13484 break;
13485 case M16_OPC_JAL:
13486 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13487 offset = (((ctx->opcode & 0x1f) << 21)
13488 | ((ctx->opcode >> 5) & 0x1f) << 16
13489 | offset) << 2;
13490 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13491 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13492 n_bytes = 4;
13493 break;
13494 case M16_OPC_BEQZ:
13495 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13496 ((int8_t)ctx->opcode) << 1, 0);
13497 /* No delay slot, so just process as a normal instruction */
13498 break;
13499 case M16_OPC_BNEQZ:
13500 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13501 ((int8_t)ctx->opcode) << 1, 0);
13502 /* No delay slot, so just process as a normal instruction */
13503 break;
13504 case M16_OPC_SHIFT:
13505 switch (ctx->opcode & 0x3) {
13506 case 0x0:
13507 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13508 break;
13509 case 0x1:
13510 #if defined(TARGET_MIPS64)
13511 check_insn(ctx, ISA_MIPS3);
13512 check_mips_64(ctx);
13513 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13514 #else
13515 generate_exception_end(ctx, EXCP_RI);
13516 #endif
13517 break;
13518 case 0x2:
13519 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13520 break;
13521 case 0x3:
13522 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13523 break;
13525 break;
13526 #if defined(TARGET_MIPS64)
13527 case M16_OPC_LD:
13528 check_insn(ctx, ISA_MIPS3);
13529 check_mips_64(ctx);
13530 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13531 break;
13532 #endif
13533 case M16_OPC_RRIA:
13535 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13537 if ((ctx->opcode >> 4) & 1) {
13538 #if defined(TARGET_MIPS64)
13539 check_insn(ctx, ISA_MIPS3);
13540 check_mips_64(ctx);
13541 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13542 #else
13543 generate_exception_end(ctx, EXCP_RI);
13544 #endif
13545 } else {
13546 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13549 break;
13550 case M16_OPC_ADDIU8:
13552 int16_t imm = (int8_t) ctx->opcode;
13554 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13556 break;
13557 case M16_OPC_SLTI:
13559 int16_t imm = (uint8_t) ctx->opcode;
13560 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13562 break;
13563 case M16_OPC_SLTIU:
13565 int16_t imm = (uint8_t) ctx->opcode;
13566 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13568 break;
13569 case M16_OPC_I8:
13571 int reg32;
13573 funct = (ctx->opcode >> 8) & 0x7;
13574 switch (funct) {
13575 case I8_BTEQZ:
13576 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13577 ((int8_t)ctx->opcode) << 1, 0);
13578 break;
13579 case I8_BTNEZ:
13580 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13581 ((int8_t)ctx->opcode) << 1, 0);
13582 break;
13583 case I8_SWRASP:
13584 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13585 break;
13586 case I8_ADJSP:
13587 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13588 ((int8_t)ctx->opcode) << 3);
13589 break;
13590 case I8_SVRS:
13591 check_insn(ctx, ISA_MIPS32);
13593 int do_ra = ctx->opcode & (1 << 6);
13594 int do_s0 = ctx->opcode & (1 << 5);
13595 int do_s1 = ctx->opcode & (1 << 4);
13596 int framesize = ctx->opcode & 0xf;
13598 if (framesize == 0) {
13599 framesize = 128;
13600 } else {
13601 framesize = framesize << 3;
13604 if (ctx->opcode & (1 << 7)) {
13605 gen_mips16_save(ctx, 0, 0,
13606 do_ra, do_s0, do_s1, framesize);
13607 } else {
13608 gen_mips16_restore(ctx, 0, 0,
13609 do_ra, do_s0, do_s1, framesize);
13612 break;
13613 case I8_MOV32R:
13615 int rz = xlat(ctx->opcode & 0x7);
13617 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13618 ((ctx->opcode >> 5) & 0x7);
13619 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13621 break;
13622 case I8_MOVR32:
13623 reg32 = ctx->opcode & 0x1f;
13624 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13625 break;
13626 default:
13627 generate_exception_end(ctx, EXCP_RI);
13628 break;
13631 break;
13632 case M16_OPC_LI:
13634 int16_t imm = (uint8_t) ctx->opcode;
13636 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13638 break;
13639 case M16_OPC_CMPI:
13641 int16_t imm = (uint8_t) ctx->opcode;
13642 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13644 break;
13645 #if defined(TARGET_MIPS64)
13646 case M16_OPC_SD:
13647 check_insn(ctx, ISA_MIPS3);
13648 check_mips_64(ctx);
13649 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13650 break;
13651 #endif
13652 case M16_OPC_LB:
13653 gen_ld(ctx, OPC_LB, ry, rx, offset);
13654 break;
13655 case M16_OPC_LH:
13656 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13657 break;
13658 case M16_OPC_LWSP:
13659 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13660 break;
13661 case M16_OPC_LW:
13662 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13663 break;
13664 case M16_OPC_LBU:
13665 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13666 break;
13667 case M16_OPC_LHU:
13668 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13669 break;
13670 case M16_OPC_LWPC:
13671 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13672 break;
13673 #if defined (TARGET_MIPS64)
13674 case M16_OPC_LWU:
13675 check_insn(ctx, ISA_MIPS3);
13676 check_mips_64(ctx);
13677 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13678 break;
13679 #endif
13680 case M16_OPC_SB:
13681 gen_st(ctx, OPC_SB, ry, rx, offset);
13682 break;
13683 case M16_OPC_SH:
13684 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13685 break;
13686 case M16_OPC_SWSP:
13687 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13688 break;
13689 case M16_OPC_SW:
13690 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13691 break;
13692 case M16_OPC_RRR:
13694 int rz = xlat((ctx->opcode >> 2) & 0x7);
13695 int mips32_op;
13697 switch (ctx->opcode & 0x3) {
13698 case RRR_ADDU:
13699 mips32_op = OPC_ADDU;
13700 break;
13701 case RRR_SUBU:
13702 mips32_op = OPC_SUBU;
13703 break;
13704 #if defined(TARGET_MIPS64)
13705 case RRR_DADDU:
13706 mips32_op = OPC_DADDU;
13707 check_insn(ctx, ISA_MIPS3);
13708 check_mips_64(ctx);
13709 break;
13710 case RRR_DSUBU:
13711 mips32_op = OPC_DSUBU;
13712 check_insn(ctx, ISA_MIPS3);
13713 check_mips_64(ctx);
13714 break;
13715 #endif
13716 default:
13717 generate_exception_end(ctx, EXCP_RI);
13718 goto done;
13721 gen_arith(ctx, mips32_op, rz, rx, ry);
13722 done:
13725 break;
13726 case M16_OPC_RR:
13727 switch (op1) {
13728 case RR_JR:
13730 int nd = (ctx->opcode >> 7) & 0x1;
13731 int link = (ctx->opcode >> 6) & 0x1;
13732 int ra = (ctx->opcode >> 5) & 0x1;
13734 if (nd) {
13735 check_insn(ctx, ISA_MIPS32);
13738 if (link) {
13739 op = OPC_JALR;
13740 } else {
13741 op = OPC_JR;
13744 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13745 (nd ? 0 : 2));
13747 break;
13748 case RR_SDBBP:
13749 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13750 gen_helper_do_semihosting(cpu_env);
13751 } else {
13752 /* XXX: not clear which exception should be raised
13753 * when in debug mode...
13755 check_insn(ctx, ISA_MIPS32);
13756 generate_exception_end(ctx, EXCP_DBp);
13758 break;
13759 case RR_SLT:
13760 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13761 break;
13762 case RR_SLTU:
13763 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13764 break;
13765 case RR_BREAK:
13766 generate_exception_end(ctx, EXCP_BREAK);
13767 break;
13768 case RR_SLLV:
13769 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13770 break;
13771 case RR_SRLV:
13772 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13773 break;
13774 case RR_SRAV:
13775 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13776 break;
13777 #if defined (TARGET_MIPS64)
13778 case RR_DSRL:
13779 check_insn(ctx, ISA_MIPS3);
13780 check_mips_64(ctx);
13781 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13782 break;
13783 #endif
13784 case RR_CMP:
13785 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13786 break;
13787 case RR_NEG:
13788 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13789 break;
13790 case RR_AND:
13791 gen_logic(ctx, OPC_AND, rx, rx, ry);
13792 break;
13793 case RR_OR:
13794 gen_logic(ctx, OPC_OR, rx, rx, ry);
13795 break;
13796 case RR_XOR:
13797 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13798 break;
13799 case RR_NOT:
13800 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13801 break;
13802 case RR_MFHI:
13803 gen_HILO(ctx, OPC_MFHI, 0, rx);
13804 break;
13805 case RR_CNVT:
13806 check_insn(ctx, ISA_MIPS32);
13807 switch (cnvt_op) {
13808 case RR_RY_CNVT_ZEB:
13809 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13810 break;
13811 case RR_RY_CNVT_ZEH:
13812 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13813 break;
13814 case RR_RY_CNVT_SEB:
13815 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13816 break;
13817 case RR_RY_CNVT_SEH:
13818 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13819 break;
13820 #if defined (TARGET_MIPS64)
13821 case RR_RY_CNVT_ZEW:
13822 check_insn(ctx, ISA_MIPS64);
13823 check_mips_64(ctx);
13824 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13825 break;
13826 case RR_RY_CNVT_SEW:
13827 check_insn(ctx, ISA_MIPS64);
13828 check_mips_64(ctx);
13829 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13830 break;
13831 #endif
13832 default:
13833 generate_exception_end(ctx, EXCP_RI);
13834 break;
13836 break;
13837 case RR_MFLO:
13838 gen_HILO(ctx, OPC_MFLO, 0, rx);
13839 break;
13840 #if defined (TARGET_MIPS64)
13841 case RR_DSRA:
13842 check_insn(ctx, ISA_MIPS3);
13843 check_mips_64(ctx);
13844 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13845 break;
13846 case RR_DSLLV:
13847 check_insn(ctx, ISA_MIPS3);
13848 check_mips_64(ctx);
13849 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13850 break;
13851 case RR_DSRLV:
13852 check_insn(ctx, ISA_MIPS3);
13853 check_mips_64(ctx);
13854 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13855 break;
13856 case RR_DSRAV:
13857 check_insn(ctx, ISA_MIPS3);
13858 check_mips_64(ctx);
13859 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13860 break;
13861 #endif
13862 case RR_MULT:
13863 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13864 break;
13865 case RR_MULTU:
13866 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13867 break;
13868 case RR_DIV:
13869 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13870 break;
13871 case RR_DIVU:
13872 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13873 break;
13874 #if defined (TARGET_MIPS64)
13875 case RR_DMULT:
13876 check_insn(ctx, ISA_MIPS3);
13877 check_mips_64(ctx);
13878 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13879 break;
13880 case RR_DMULTU:
13881 check_insn(ctx, ISA_MIPS3);
13882 check_mips_64(ctx);
13883 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13884 break;
13885 case RR_DDIV:
13886 check_insn(ctx, ISA_MIPS3);
13887 check_mips_64(ctx);
13888 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13889 break;
13890 case RR_DDIVU:
13891 check_insn(ctx, ISA_MIPS3);
13892 check_mips_64(ctx);
13893 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13894 break;
13895 #endif
13896 default:
13897 generate_exception_end(ctx, EXCP_RI);
13898 break;
13900 break;
13901 case M16_OPC_EXTEND:
13902 decode_extended_mips16_opc(env, ctx);
13903 n_bytes = 4;
13904 break;
13905 #if defined(TARGET_MIPS64)
13906 case M16_OPC_I64:
13907 funct = (ctx->opcode >> 8) & 0x7;
13908 decode_i64_mips16(ctx, ry, funct, offset, 0);
13909 break;
13910 #endif
13911 default:
13912 generate_exception_end(ctx, EXCP_RI);
13913 break;
13916 return n_bytes;
13919 /* microMIPS extension to MIPS32/MIPS64 */
13922 * microMIPS32/microMIPS64 major opcodes
13924 * 1. MIPS Architecture for Programmers Volume II-B:
13925 * The microMIPS32 Instruction Set (Revision 3.05)
13927 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13929 * 2. MIPS Architecture For Programmers Volume II-A:
13930 * The MIPS64 Instruction Set (Revision 3.51)
13933 enum {
13934 POOL32A = 0x00,
13935 POOL16A = 0x01,
13936 LBU16 = 0x02,
13937 MOVE16 = 0x03,
13938 ADDI32 = 0x04,
13939 R6_LUI = 0x04,
13940 AUI = 0x04,
13941 LBU32 = 0x05,
13942 SB32 = 0x06,
13943 LB32 = 0x07,
13945 POOL32B = 0x08,
13946 POOL16B = 0x09,
13947 LHU16 = 0x0a,
13948 ANDI16 = 0x0b,
13949 ADDIU32 = 0x0c,
13950 LHU32 = 0x0d,
13951 SH32 = 0x0e,
13952 LH32 = 0x0f,
13954 POOL32I = 0x10,
13955 POOL16C = 0x11,
13956 LWSP16 = 0x12,
13957 POOL16D = 0x13,
13958 ORI32 = 0x14,
13959 POOL32F = 0x15,
13960 POOL32S = 0x16, /* MIPS64 */
13961 DADDIU32 = 0x17, /* MIPS64 */
13963 POOL32C = 0x18,
13964 LWGP16 = 0x19,
13965 LW16 = 0x1a,
13966 POOL16E = 0x1b,
13967 XORI32 = 0x1c,
13968 JALS32 = 0x1d,
13969 BOVC = 0x1d,
13970 BEQC = 0x1d,
13971 BEQZALC = 0x1d,
13972 ADDIUPC = 0x1e,
13973 PCREL = 0x1e,
13974 BNVC = 0x1f,
13975 BNEC = 0x1f,
13976 BNEZALC = 0x1f,
13978 R6_BEQZC = 0x20,
13979 JIC = 0x20,
13980 POOL16F = 0x21,
13981 SB16 = 0x22,
13982 BEQZ16 = 0x23,
13983 BEQZC16 = 0x23,
13984 SLTI32 = 0x24,
13985 BEQ32 = 0x25,
13986 BC = 0x25,
13987 SWC132 = 0x26,
13988 LWC132 = 0x27,
13990 /* 0x29 is reserved */
13991 RES_29 = 0x29,
13992 R6_BNEZC = 0x28,
13993 JIALC = 0x28,
13994 SH16 = 0x2a,
13995 BNEZ16 = 0x2b,
13996 BNEZC16 = 0x2b,
13997 SLTIU32 = 0x2c,
13998 BNE32 = 0x2d,
13999 BALC = 0x2d,
14000 SDC132 = 0x2e,
14001 LDC132 = 0x2f,
14003 /* 0x31 is reserved */
14004 RES_31 = 0x31,
14005 BLEZALC = 0x30,
14006 BGEZALC = 0x30,
14007 BGEUC = 0x30,
14008 SWSP16 = 0x32,
14009 B16 = 0x33,
14010 BC16 = 0x33,
14011 ANDI32 = 0x34,
14012 J32 = 0x35,
14013 BGTZC = 0x35,
14014 BLTZC = 0x35,
14015 BLTC = 0x35,
14016 SD32 = 0x36, /* MIPS64 */
14017 LD32 = 0x37, /* MIPS64 */
14019 /* 0x39 is reserved */
14020 RES_39 = 0x39,
14021 BGTZALC = 0x38,
14022 BLTZALC = 0x38,
14023 BLTUC = 0x38,
14024 SW16 = 0x3a,
14025 LI16 = 0x3b,
14026 JALX32 = 0x3c,
14027 JAL32 = 0x3d,
14028 BLEZC = 0x3d,
14029 BGEZC = 0x3d,
14030 BGEC = 0x3d,
14031 SW32 = 0x3e,
14032 LW32 = 0x3f
14035 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14036 enum {
14037 ADDIUPC_00 = 0x00,
14038 ADDIUPC_01 = 0x01,
14039 ADDIUPC_02 = 0x02,
14040 ADDIUPC_03 = 0x03,
14041 ADDIUPC_04 = 0x04,
14042 ADDIUPC_05 = 0x05,
14043 ADDIUPC_06 = 0x06,
14044 ADDIUPC_07 = 0x07,
14045 AUIPC = 0x1e,
14046 ALUIPC = 0x1f,
14047 LWPC_08 = 0x08,
14048 LWPC_09 = 0x09,
14049 LWPC_0A = 0x0A,
14050 LWPC_0B = 0x0B,
14051 LWPC_0C = 0x0C,
14052 LWPC_0D = 0x0D,
14053 LWPC_0E = 0x0E,
14054 LWPC_0F = 0x0F,
14057 /* POOL32A encoding of minor opcode field */
14059 enum {
14060 /* These opcodes are distinguished only by bits 9..6; those bits are
14061 * what are recorded below. */
14062 SLL32 = 0x0,
14063 SRL32 = 0x1,
14064 SRA = 0x2,
14065 ROTR = 0x3,
14066 SELEQZ = 0x5,
14067 SELNEZ = 0x6,
14068 R6_RDHWR = 0x7,
14070 SLLV = 0x0,
14071 SRLV = 0x1,
14072 SRAV = 0x2,
14073 ROTRV = 0x3,
14074 ADD = 0x4,
14075 ADDU32 = 0x5,
14076 SUB = 0x6,
14077 SUBU32 = 0x7,
14078 MUL = 0x8,
14079 AND = 0x9,
14080 OR32 = 0xa,
14081 NOR = 0xb,
14082 XOR32 = 0xc,
14083 SLT = 0xd,
14084 SLTU = 0xe,
14086 MOVN = 0x0,
14087 R6_MUL = 0x0,
14088 MOVZ = 0x1,
14089 MUH = 0x1,
14090 MULU = 0x2,
14091 MUHU = 0x3,
14092 LWXS = 0x4,
14093 R6_DIV = 0x4,
14094 MOD = 0x5,
14095 R6_DIVU = 0x6,
14096 MODU = 0x7,
14098 /* The following can be distinguished by their lower 6 bits. */
14099 BREAK32 = 0x07,
14100 INS = 0x0c,
14101 LSA = 0x0f,
14102 ALIGN = 0x1f,
14103 EXT = 0x2c,
14104 POOL32AXF = 0x3c,
14105 SIGRIE = 0x3f
14108 /* POOL32AXF encoding of minor opcode field extension */
14111 * 1. MIPS Architecture for Programmers Volume II-B:
14112 * The microMIPS32 Instruction Set (Revision 3.05)
14114 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14116 * 2. MIPS Architecture for Programmers VolumeIV-e:
14117 * The MIPS DSP Application-Specific Extension
14118 * to the microMIPS32 Architecture (Revision 2.34)
14120 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14123 enum {
14124 /* bits 11..6 */
14125 TEQ = 0x00,
14126 TGE = 0x08,
14127 TGEU = 0x10,
14128 TLT = 0x20,
14129 TLTU = 0x28,
14130 TNE = 0x30,
14132 MFC0 = 0x03,
14133 MTC0 = 0x0b,
14135 /* begin of microMIPS32 DSP */
14137 /* bits 13..12 for 0x01 */
14138 MFHI_ACC = 0x0,
14139 MFLO_ACC = 0x1,
14140 MTHI_ACC = 0x2,
14141 MTLO_ACC = 0x3,
14143 /* bits 13..12 for 0x2a */
14144 MADD_ACC = 0x0,
14145 MADDU_ACC = 0x1,
14146 MSUB_ACC = 0x2,
14147 MSUBU_ACC = 0x3,
14149 /* bits 13..12 for 0x32 */
14150 MULT_ACC = 0x0,
14151 MULTU_ACC = 0x1,
14153 /* end of microMIPS32 DSP */
14155 /* bits 15..12 for 0x2c */
14156 BITSWAP = 0x0,
14157 SEB = 0x2,
14158 SEH = 0x3,
14159 CLO = 0x4,
14160 CLZ = 0x5,
14161 RDHWR = 0x6,
14162 WSBH = 0x7,
14163 MULT = 0x8,
14164 MULTU = 0x9,
14165 DIV = 0xa,
14166 DIVU = 0xb,
14167 MADD = 0xc,
14168 MADDU = 0xd,
14169 MSUB = 0xe,
14170 MSUBU = 0xf,
14172 /* bits 15..12 for 0x34 */
14173 MFC2 = 0x4,
14174 MTC2 = 0x5,
14175 MFHC2 = 0x8,
14176 MTHC2 = 0x9,
14177 CFC2 = 0xc,
14178 CTC2 = 0xd,
14180 /* bits 15..12 for 0x3c */
14181 JALR = 0x0,
14182 JR = 0x0, /* alias */
14183 JALRC = 0x0,
14184 JRC = 0x0,
14185 JALR_HB = 0x1,
14186 JALRC_HB = 0x1,
14187 JALRS = 0x4,
14188 JALRS_HB = 0x5,
14190 /* bits 15..12 for 0x05 */
14191 RDPGPR = 0xe,
14192 WRPGPR = 0xf,
14194 /* bits 15..12 for 0x0d */
14195 TLBP = 0x0,
14196 TLBR = 0x1,
14197 TLBWI = 0x2,
14198 TLBWR = 0x3,
14199 TLBINV = 0x4,
14200 TLBINVF = 0x5,
14201 WAIT = 0x9,
14202 IRET = 0xd,
14203 DERET = 0xe,
14204 ERET = 0xf,
14206 /* bits 15..12 for 0x15 */
14207 DMT = 0x0,
14208 DVPE = 0x1,
14209 EMT = 0x2,
14210 EVPE = 0x3,
14212 /* bits 15..12 for 0x1d */
14213 DI = 0x4,
14214 EI = 0x5,
14216 /* bits 15..12 for 0x2d */
14217 SYNC = 0x6,
14218 SYSCALL = 0x8,
14219 SDBBP = 0xd,
14221 /* bits 15..12 for 0x35 */
14222 MFHI32 = 0x0,
14223 MFLO32 = 0x1,
14224 MTHI32 = 0x2,
14225 MTLO32 = 0x3,
14228 /* POOL32B encoding of minor opcode field (bits 15..12) */
14230 enum {
14231 LWC2 = 0x0,
14232 LWP = 0x1,
14233 LDP = 0x4,
14234 LWM32 = 0x5,
14235 CACHE = 0x6,
14236 LDM = 0x7,
14237 SWC2 = 0x8,
14238 SWP = 0x9,
14239 SDP = 0xc,
14240 SWM32 = 0xd,
14241 SDM = 0xf
14244 /* POOL32C encoding of minor opcode field (bits 15..12) */
14246 enum {
14247 LWL = 0x0,
14248 SWL = 0x8,
14249 LWR = 0x1,
14250 SWR = 0x9,
14251 PREF = 0x2,
14252 ST_EVA = 0xa,
14253 LL = 0x3,
14254 SC = 0xb,
14255 LDL = 0x4,
14256 SDL = 0xc,
14257 LDR = 0x5,
14258 SDR = 0xd,
14259 LD_EVA = 0x6,
14260 LWU = 0xe,
14261 LLD = 0x7,
14262 SCD = 0xf
14265 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14267 enum {
14268 LBUE = 0x0,
14269 LHUE = 0x1,
14270 LWLE = 0x2,
14271 LWRE = 0x3,
14272 LBE = 0x4,
14273 LHE = 0x5,
14274 LLE = 0x6,
14275 LWE = 0x7,
14278 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14280 enum {
14281 SWLE = 0x0,
14282 SWRE = 0x1,
14283 PREFE = 0x2,
14284 CACHEE = 0x3,
14285 SBE = 0x4,
14286 SHE = 0x5,
14287 SCE = 0x6,
14288 SWE = 0x7,
14291 /* POOL32F encoding of minor opcode field (bits 5..0) */
14293 enum {
14294 /* These are the bit 7..6 values */
14295 ADD_FMT = 0x0,
14297 SUB_FMT = 0x1,
14299 MUL_FMT = 0x2,
14301 DIV_FMT = 0x3,
14303 /* These are the bit 8..6 values */
14304 MOVN_FMT = 0x0,
14305 RSQRT2_FMT = 0x0,
14306 MOVF_FMT = 0x0,
14307 RINT_FMT = 0x0,
14308 SELNEZ_FMT = 0x0,
14310 MOVZ_FMT = 0x1,
14311 LWXC1 = 0x1,
14312 MOVT_FMT = 0x1,
14313 CLASS_FMT = 0x1,
14314 SELEQZ_FMT = 0x1,
14316 PLL_PS = 0x2,
14317 SWXC1 = 0x2,
14318 SEL_FMT = 0x2,
14320 PLU_PS = 0x3,
14321 LDXC1 = 0x3,
14323 MOVN_FMT_04 = 0x4,
14324 PUL_PS = 0x4,
14325 SDXC1 = 0x4,
14326 RECIP2_FMT = 0x4,
14328 MOVZ_FMT_05 = 0x05,
14329 PUU_PS = 0x5,
14330 LUXC1 = 0x5,
14332 CVT_PS_S = 0x6,
14333 SUXC1 = 0x6,
14334 ADDR_PS = 0x6,
14335 PREFX = 0x6,
14336 MADDF_FMT = 0x6,
14338 MULR_PS = 0x7,
14339 MSUBF_FMT = 0x7,
14341 MADD_S = 0x01,
14342 MADD_D = 0x09,
14343 MADD_PS = 0x11,
14344 ALNV_PS = 0x19,
14345 MSUB_S = 0x21,
14346 MSUB_D = 0x29,
14347 MSUB_PS = 0x31,
14349 NMADD_S = 0x02,
14350 NMADD_D = 0x0a,
14351 NMADD_PS = 0x12,
14352 NMSUB_S = 0x22,
14353 NMSUB_D = 0x2a,
14354 NMSUB_PS = 0x32,
14356 MIN_FMT = 0x3,
14357 MAX_FMT = 0xb,
14358 MINA_FMT = 0x23,
14359 MAXA_FMT = 0x2b,
14360 POOL32FXF = 0x3b,
14362 CABS_COND_FMT = 0x1c, /* MIPS3D */
14363 C_COND_FMT = 0x3c,
14365 CMP_CONDN_S = 0x5,
14366 CMP_CONDN_D = 0x15
14369 /* POOL32Fxf encoding of minor opcode extension field */
14371 enum {
14372 CVT_L = 0x04,
14373 RSQRT_FMT = 0x08,
14374 FLOOR_L = 0x0c,
14375 CVT_PW_PS = 0x1c,
14376 CVT_W = 0x24,
14377 SQRT_FMT = 0x28,
14378 FLOOR_W = 0x2c,
14379 CVT_PS_PW = 0x3c,
14380 CFC1 = 0x40,
14381 RECIP_FMT = 0x48,
14382 CEIL_L = 0x4c,
14383 CTC1 = 0x60,
14384 CEIL_W = 0x6c,
14385 MFC1 = 0x80,
14386 CVT_S_PL = 0x84,
14387 TRUNC_L = 0x8c,
14388 MTC1 = 0xa0,
14389 CVT_S_PU = 0xa4,
14390 TRUNC_W = 0xac,
14391 MFHC1 = 0xc0,
14392 ROUND_L = 0xcc,
14393 MTHC1 = 0xe0,
14394 ROUND_W = 0xec,
14396 MOV_FMT = 0x01,
14397 MOVF = 0x05,
14398 ABS_FMT = 0x0d,
14399 RSQRT1_FMT = 0x1d,
14400 MOVT = 0x25,
14401 NEG_FMT = 0x2d,
14402 CVT_D = 0x4d,
14403 RECIP1_FMT = 0x5d,
14404 CVT_S = 0x6d
14407 /* POOL32I encoding of minor opcode field (bits 25..21) */
14409 enum {
14410 BLTZ = 0x00,
14411 BLTZAL = 0x01,
14412 BGEZ = 0x02,
14413 BGEZAL = 0x03,
14414 BLEZ = 0x04,
14415 BNEZC = 0x05,
14416 BGTZ = 0x06,
14417 BEQZC = 0x07,
14418 TLTI = 0x08,
14419 BC1EQZC = 0x08,
14420 TGEI = 0x09,
14421 BC1NEZC = 0x09,
14422 TLTIU = 0x0a,
14423 BC2EQZC = 0x0a,
14424 TGEIU = 0x0b,
14425 BC2NEZC = 0x0a,
14426 TNEI = 0x0c,
14427 R6_SYNCI = 0x0c,
14428 LUI = 0x0d,
14429 TEQI = 0x0e,
14430 SYNCI = 0x10,
14431 BLTZALS = 0x11,
14432 BGEZALS = 0x13,
14433 BC2F = 0x14,
14434 BC2T = 0x15,
14435 BPOSGE64 = 0x1a,
14436 BPOSGE32 = 0x1b,
14437 /* These overlap and are distinguished by bit16 of the instruction */
14438 BC1F = 0x1c,
14439 BC1T = 0x1d,
14440 BC1ANY2F = 0x1c,
14441 BC1ANY2T = 0x1d,
14442 BC1ANY4F = 0x1e,
14443 BC1ANY4T = 0x1f
14446 /* POOL16A encoding of minor opcode field */
14448 enum {
14449 ADDU16 = 0x0,
14450 SUBU16 = 0x1
14453 /* POOL16B encoding of minor opcode field */
14455 enum {
14456 SLL16 = 0x0,
14457 SRL16 = 0x1
14460 /* POOL16C encoding of minor opcode field */
14462 enum {
14463 NOT16 = 0x00,
14464 XOR16 = 0x04,
14465 AND16 = 0x08,
14466 OR16 = 0x0c,
14467 LWM16 = 0x10,
14468 SWM16 = 0x14,
14469 JR16 = 0x18,
14470 JRC16 = 0x1a,
14471 JALR16 = 0x1c,
14472 JALR16S = 0x1e,
14473 MFHI16 = 0x20,
14474 MFLO16 = 0x24,
14475 BREAK16 = 0x28,
14476 SDBBP16 = 0x2c,
14477 JRADDIUSP = 0x30
14480 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14482 enum {
14483 R6_NOT16 = 0x00,
14484 R6_AND16 = 0x01,
14485 R6_LWM16 = 0x02,
14486 R6_JRC16 = 0x03,
14487 MOVEP = 0x04,
14488 MOVEP_05 = 0x05,
14489 MOVEP_06 = 0x06,
14490 MOVEP_07 = 0x07,
14491 R6_XOR16 = 0x08,
14492 R6_OR16 = 0x09,
14493 R6_SWM16 = 0x0a,
14494 JALRC16 = 0x0b,
14495 MOVEP_0C = 0x0c,
14496 MOVEP_0D = 0x0d,
14497 MOVEP_0E = 0x0e,
14498 MOVEP_0F = 0x0f,
14499 JRCADDIUSP = 0x13,
14500 R6_BREAK16 = 0x1b,
14501 R6_SDBBP16 = 0x3b
14504 /* POOL16D encoding of minor opcode field */
14506 enum {
14507 ADDIUS5 = 0x0,
14508 ADDIUSP = 0x1
14511 /* POOL16E encoding of minor opcode field */
14513 enum {
14514 ADDIUR2 = 0x0,
14515 ADDIUR1SP = 0x1
14518 static int mmreg (int r)
14520 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14522 return map[r];
14525 /* Used for 16-bit store instructions. */
14526 static int mmreg2 (int r)
14528 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14530 return map[r];
14533 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14534 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14535 #define uMIPS_RS2(op) uMIPS_RS(op)
14536 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14537 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14538 #define uMIPS_RS5(op) (op & 0x1f)
14540 /* Signed immediate */
14541 #define SIMM(op, start, width) \
14542 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14543 << (32-width)) \
14544 >> (32-width))
14545 /* Zero-extended immediate */
14546 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14548 static void gen_addiur1sp(DisasContext *ctx)
14550 int rd = mmreg(uMIPS_RD(ctx->opcode));
14552 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14555 static void gen_addiur2(DisasContext *ctx)
14557 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14558 int rd = mmreg(uMIPS_RD(ctx->opcode));
14559 int rs = mmreg(uMIPS_RS(ctx->opcode));
14561 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14564 static void gen_addiusp(DisasContext *ctx)
14566 int encoded = ZIMM(ctx->opcode, 1, 9);
14567 int decoded;
14569 if (encoded <= 1) {
14570 decoded = 256 + encoded;
14571 } else if (encoded <= 255) {
14572 decoded = encoded;
14573 } else if (encoded <= 509) {
14574 decoded = encoded - 512;
14575 } else {
14576 decoded = encoded - 768;
14579 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14582 static void gen_addius5(DisasContext *ctx)
14584 int imm = SIMM(ctx->opcode, 1, 4);
14585 int rd = (ctx->opcode >> 5) & 0x1f;
14587 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14590 static void gen_andi16(DisasContext *ctx)
14592 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14593 31, 32, 63, 64, 255, 32768, 65535 };
14594 int rd = mmreg(uMIPS_RD(ctx->opcode));
14595 int rs = mmreg(uMIPS_RS(ctx->opcode));
14596 int encoded = ZIMM(ctx->opcode, 0, 4);
14598 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14601 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14602 int base, int16_t offset)
14604 TCGv t0, t1;
14605 TCGv_i32 t2;
14607 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14608 generate_exception_end(ctx, EXCP_RI);
14609 return;
14612 t0 = tcg_temp_new();
14614 gen_base_offset_addr(ctx, t0, base, offset);
14616 t1 = tcg_const_tl(reglist);
14617 t2 = tcg_const_i32(ctx->mem_idx);
14619 save_cpu_state(ctx, 1);
14620 switch (opc) {
14621 case LWM32:
14622 gen_helper_lwm(cpu_env, t0, t1, t2);
14623 break;
14624 case SWM32:
14625 gen_helper_swm(cpu_env, t0, t1, t2);
14626 break;
14627 #ifdef TARGET_MIPS64
14628 case LDM:
14629 gen_helper_ldm(cpu_env, t0, t1, t2);
14630 break;
14631 case SDM:
14632 gen_helper_sdm(cpu_env, t0, t1, t2);
14633 break;
14634 #endif
14636 tcg_temp_free(t0);
14637 tcg_temp_free(t1);
14638 tcg_temp_free_i32(t2);
14642 static void gen_pool16c_insn(DisasContext *ctx)
14644 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14645 int rs = mmreg(ctx->opcode & 0x7);
14647 switch (((ctx->opcode) >> 4) & 0x3f) {
14648 case NOT16 + 0:
14649 case NOT16 + 1:
14650 case NOT16 + 2:
14651 case NOT16 + 3:
14652 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14653 break;
14654 case XOR16 + 0:
14655 case XOR16 + 1:
14656 case XOR16 + 2:
14657 case XOR16 + 3:
14658 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14659 break;
14660 case AND16 + 0:
14661 case AND16 + 1:
14662 case AND16 + 2:
14663 case AND16 + 3:
14664 gen_logic(ctx, OPC_AND, rd, rd, rs);
14665 break;
14666 case OR16 + 0:
14667 case OR16 + 1:
14668 case OR16 + 2:
14669 case OR16 + 3:
14670 gen_logic(ctx, OPC_OR, rd, rd, rs);
14671 break;
14672 case LWM16 + 0:
14673 case LWM16 + 1:
14674 case LWM16 + 2:
14675 case LWM16 + 3:
14677 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14678 int offset = ZIMM(ctx->opcode, 0, 4);
14680 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14681 29, offset << 2);
14683 break;
14684 case SWM16 + 0:
14685 case SWM16 + 1:
14686 case SWM16 + 2:
14687 case SWM16 + 3:
14689 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14690 int offset = ZIMM(ctx->opcode, 0, 4);
14692 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14693 29, offset << 2);
14695 break;
14696 case JR16 + 0:
14697 case JR16 + 1:
14699 int reg = ctx->opcode & 0x1f;
14701 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14703 break;
14704 case JRC16 + 0:
14705 case JRC16 + 1:
14707 int reg = ctx->opcode & 0x1f;
14708 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14709 /* Let normal delay slot handling in our caller take us
14710 to the branch target. */
14712 break;
14713 case JALR16 + 0:
14714 case JALR16 + 1:
14715 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14716 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14717 break;
14718 case JALR16S + 0:
14719 case JALR16S + 1:
14720 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14721 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14722 break;
14723 case MFHI16 + 0:
14724 case MFHI16 + 1:
14725 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14726 break;
14727 case MFLO16 + 0:
14728 case MFLO16 + 1:
14729 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14730 break;
14731 case BREAK16:
14732 generate_exception_end(ctx, EXCP_BREAK);
14733 break;
14734 case SDBBP16:
14735 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14736 gen_helper_do_semihosting(cpu_env);
14737 } else {
14738 /* XXX: not clear which exception should be raised
14739 * when in debug mode...
14741 check_insn(ctx, ISA_MIPS32);
14742 generate_exception_end(ctx, EXCP_DBp);
14744 break;
14745 case JRADDIUSP + 0:
14746 case JRADDIUSP + 1:
14748 int imm = ZIMM(ctx->opcode, 0, 5);
14749 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14750 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14751 /* Let normal delay slot handling in our caller take us
14752 to the branch target. */
14754 break;
14755 default:
14756 generate_exception_end(ctx, EXCP_RI);
14757 break;
14761 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14762 int enc_rs)
14764 int rd, rs, re, rt;
14765 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14766 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14767 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14768 rd = rd_enc[enc_dest];
14769 re = re_enc[enc_dest];
14770 rs = rs_rt_enc[enc_rs];
14771 rt = rs_rt_enc[enc_rt];
14772 if (rs) {
14773 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14774 } else {
14775 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14777 if (rt) {
14778 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14779 } else {
14780 tcg_gen_movi_tl(cpu_gpr[re], 0);
14784 static void gen_pool16c_r6_insn(DisasContext *ctx)
14786 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14787 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14789 switch (ctx->opcode & 0xf) {
14790 case R6_NOT16:
14791 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14792 break;
14793 case R6_AND16:
14794 gen_logic(ctx, OPC_AND, rt, rt, rs);
14795 break;
14796 case R6_LWM16:
14798 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14799 int offset = extract32(ctx->opcode, 4, 4);
14800 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14802 break;
14803 case R6_JRC16: /* JRCADDIUSP */
14804 if ((ctx->opcode >> 4) & 1) {
14805 /* JRCADDIUSP */
14806 int imm = extract32(ctx->opcode, 5, 5);
14807 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14808 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14809 } else {
14810 /* JRC16 */
14811 rs = extract32(ctx->opcode, 5, 5);
14812 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14814 break;
14815 case MOVEP:
14816 case MOVEP_05:
14817 case MOVEP_06:
14818 case MOVEP_07:
14819 case MOVEP_0C:
14820 case MOVEP_0D:
14821 case MOVEP_0E:
14822 case MOVEP_0F:
14824 int enc_dest = uMIPS_RD(ctx->opcode);
14825 int enc_rt = uMIPS_RS2(ctx->opcode);
14826 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14827 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14829 break;
14830 case R6_XOR16:
14831 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14832 break;
14833 case R6_OR16:
14834 gen_logic(ctx, OPC_OR, rt, rt, rs);
14835 break;
14836 case R6_SWM16:
14838 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14839 int offset = extract32(ctx->opcode, 4, 4);
14840 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14842 break;
14843 case JALRC16: /* BREAK16, SDBBP16 */
14844 switch (ctx->opcode & 0x3f) {
14845 case JALRC16:
14846 case JALRC16 + 0x20:
14847 /* JALRC16 */
14848 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14849 31, 0, 0);
14850 break;
14851 case R6_BREAK16:
14852 /* BREAK16 */
14853 generate_exception(ctx, EXCP_BREAK);
14854 break;
14855 case R6_SDBBP16:
14856 /* SDBBP16 */
14857 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14858 gen_helper_do_semihosting(cpu_env);
14859 } else {
14860 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14861 generate_exception(ctx, EXCP_RI);
14862 } else {
14863 generate_exception(ctx, EXCP_DBp);
14866 break;
14868 break;
14869 default:
14870 generate_exception(ctx, EXCP_RI);
14871 break;
14875 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14877 TCGv t0 = tcg_temp_new();
14878 TCGv t1 = tcg_temp_new();
14880 gen_load_gpr(t0, base);
14882 if (index != 0) {
14883 gen_load_gpr(t1, index);
14884 tcg_gen_shli_tl(t1, t1, 2);
14885 gen_op_addr_add(ctx, t0, t1, t0);
14888 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14889 gen_store_gpr(t1, rd);
14891 tcg_temp_free(t0);
14892 tcg_temp_free(t1);
14895 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14896 int base, int16_t offset)
14898 TCGv t0, t1;
14900 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14901 generate_exception_end(ctx, EXCP_RI);
14902 return;
14905 t0 = tcg_temp_new();
14906 t1 = tcg_temp_new();
14908 gen_base_offset_addr(ctx, t0, base, offset);
14910 switch (opc) {
14911 case LWP:
14912 if (rd == base) {
14913 generate_exception_end(ctx, EXCP_RI);
14914 return;
14916 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14917 gen_store_gpr(t1, rd);
14918 tcg_gen_movi_tl(t1, 4);
14919 gen_op_addr_add(ctx, t0, t0, t1);
14920 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14921 gen_store_gpr(t1, rd+1);
14922 break;
14923 case SWP:
14924 gen_load_gpr(t1, rd);
14925 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14926 tcg_gen_movi_tl(t1, 4);
14927 gen_op_addr_add(ctx, t0, t0, t1);
14928 gen_load_gpr(t1, rd+1);
14929 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14930 break;
14931 #ifdef TARGET_MIPS64
14932 case LDP:
14933 if (rd == base) {
14934 generate_exception_end(ctx, EXCP_RI);
14935 return;
14937 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14938 gen_store_gpr(t1, rd);
14939 tcg_gen_movi_tl(t1, 8);
14940 gen_op_addr_add(ctx, t0, t0, t1);
14941 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14942 gen_store_gpr(t1, rd+1);
14943 break;
14944 case SDP:
14945 gen_load_gpr(t1, rd);
14946 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14947 tcg_gen_movi_tl(t1, 8);
14948 gen_op_addr_add(ctx, t0, t0, t1);
14949 gen_load_gpr(t1, rd+1);
14950 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14951 break;
14952 #endif
14954 tcg_temp_free(t0);
14955 tcg_temp_free(t1);
14958 static void gen_sync(int stype)
14960 TCGBar tcg_mo = TCG_BAR_SC;
14962 switch (stype) {
14963 case 0x4: /* SYNC_WMB */
14964 tcg_mo |= TCG_MO_ST_ST;
14965 break;
14966 case 0x10: /* SYNC_MB */
14967 tcg_mo |= TCG_MO_ALL;
14968 break;
14969 case 0x11: /* SYNC_ACQUIRE */
14970 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14971 break;
14972 case 0x12: /* SYNC_RELEASE */
14973 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14974 break;
14975 case 0x13: /* SYNC_RMB */
14976 tcg_mo |= TCG_MO_LD_LD;
14977 break;
14978 default:
14979 tcg_mo |= TCG_MO_ALL;
14980 break;
14983 tcg_gen_mb(tcg_mo);
14986 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14988 int extension = (ctx->opcode >> 6) & 0x3f;
14989 int minor = (ctx->opcode >> 12) & 0xf;
14990 uint32_t mips32_op;
14992 switch (extension) {
14993 case TEQ:
14994 mips32_op = OPC_TEQ;
14995 goto do_trap;
14996 case TGE:
14997 mips32_op = OPC_TGE;
14998 goto do_trap;
14999 case TGEU:
15000 mips32_op = OPC_TGEU;
15001 goto do_trap;
15002 case TLT:
15003 mips32_op = OPC_TLT;
15004 goto do_trap;
15005 case TLTU:
15006 mips32_op = OPC_TLTU;
15007 goto do_trap;
15008 case TNE:
15009 mips32_op = OPC_TNE;
15010 do_trap:
15011 gen_trap(ctx, mips32_op, rs, rt, -1);
15012 break;
15013 #ifndef CONFIG_USER_ONLY
15014 case MFC0:
15015 case MFC0 + 32:
15016 check_cp0_enabled(ctx);
15017 if (rt == 0) {
15018 /* Treat as NOP. */
15019 break;
15021 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15022 break;
15023 case MTC0:
15024 case MTC0 + 32:
15025 check_cp0_enabled(ctx);
15027 TCGv t0 = tcg_temp_new();
15029 gen_load_gpr(t0, rt);
15030 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15031 tcg_temp_free(t0);
15033 break;
15034 #endif
15035 case 0x2a:
15036 switch (minor & 3) {
15037 case MADD_ACC:
15038 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15039 break;
15040 case MADDU_ACC:
15041 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15042 break;
15043 case MSUB_ACC:
15044 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15045 break;
15046 case MSUBU_ACC:
15047 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15048 break;
15049 default:
15050 goto pool32axf_invalid;
15052 break;
15053 case 0x32:
15054 switch (minor & 3) {
15055 case MULT_ACC:
15056 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15057 break;
15058 case MULTU_ACC:
15059 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15060 break;
15061 default:
15062 goto pool32axf_invalid;
15064 break;
15065 case 0x2c:
15066 switch (minor) {
15067 case BITSWAP:
15068 check_insn(ctx, ISA_MIPS32R6);
15069 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15070 break;
15071 case SEB:
15072 gen_bshfl(ctx, OPC_SEB, rs, rt);
15073 break;
15074 case SEH:
15075 gen_bshfl(ctx, OPC_SEH, rs, rt);
15076 break;
15077 case CLO:
15078 mips32_op = OPC_CLO;
15079 goto do_cl;
15080 case CLZ:
15081 mips32_op = OPC_CLZ;
15082 do_cl:
15083 check_insn(ctx, ISA_MIPS32);
15084 gen_cl(ctx, mips32_op, rt, rs);
15085 break;
15086 case RDHWR:
15087 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15088 gen_rdhwr(ctx, rt, rs, 0);
15089 break;
15090 case WSBH:
15091 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15092 break;
15093 case MULT:
15094 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15095 mips32_op = OPC_MULT;
15096 goto do_mul;
15097 case MULTU:
15098 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15099 mips32_op = OPC_MULTU;
15100 goto do_mul;
15101 case DIV:
15102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15103 mips32_op = OPC_DIV;
15104 goto do_div;
15105 case DIVU:
15106 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15107 mips32_op = OPC_DIVU;
15108 goto do_div;
15109 do_div:
15110 check_insn(ctx, ISA_MIPS32);
15111 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15112 break;
15113 case MADD:
15114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15115 mips32_op = OPC_MADD;
15116 goto do_mul;
15117 case MADDU:
15118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15119 mips32_op = OPC_MADDU;
15120 goto do_mul;
15121 case MSUB:
15122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15123 mips32_op = OPC_MSUB;
15124 goto do_mul;
15125 case MSUBU:
15126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15127 mips32_op = OPC_MSUBU;
15128 do_mul:
15129 check_insn(ctx, ISA_MIPS32);
15130 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15131 break;
15132 default:
15133 goto pool32axf_invalid;
15135 break;
15136 case 0x34:
15137 switch (minor) {
15138 case MFC2:
15139 case MTC2:
15140 case MFHC2:
15141 case MTHC2:
15142 case CFC2:
15143 case CTC2:
15144 generate_exception_err(ctx, EXCP_CpU, 2);
15145 break;
15146 default:
15147 goto pool32axf_invalid;
15149 break;
15150 case 0x3c:
15151 switch (minor) {
15152 case JALR: /* JALRC */
15153 case JALR_HB: /* JALRC_HB */
15154 if (ctx->insn_flags & ISA_MIPS32R6) {
15155 /* JALRC, JALRC_HB */
15156 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15157 } else {
15158 /* JALR, JALR_HB */
15159 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15160 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15162 break;
15163 case JALRS:
15164 case JALRS_HB:
15165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15166 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15167 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15168 break;
15169 default:
15170 goto pool32axf_invalid;
15172 break;
15173 case 0x05:
15174 switch (minor) {
15175 case RDPGPR:
15176 check_cp0_enabled(ctx);
15177 check_insn(ctx, ISA_MIPS32R2);
15178 gen_load_srsgpr(rs, rt);
15179 break;
15180 case WRPGPR:
15181 check_cp0_enabled(ctx);
15182 check_insn(ctx, ISA_MIPS32R2);
15183 gen_store_srsgpr(rs, rt);
15184 break;
15185 default:
15186 goto pool32axf_invalid;
15188 break;
15189 #ifndef CONFIG_USER_ONLY
15190 case 0x0d:
15191 switch (minor) {
15192 case TLBP:
15193 mips32_op = OPC_TLBP;
15194 goto do_cp0;
15195 case TLBR:
15196 mips32_op = OPC_TLBR;
15197 goto do_cp0;
15198 case TLBWI:
15199 mips32_op = OPC_TLBWI;
15200 goto do_cp0;
15201 case TLBWR:
15202 mips32_op = OPC_TLBWR;
15203 goto do_cp0;
15204 case TLBINV:
15205 mips32_op = OPC_TLBINV;
15206 goto do_cp0;
15207 case TLBINVF:
15208 mips32_op = OPC_TLBINVF;
15209 goto do_cp0;
15210 case WAIT:
15211 mips32_op = OPC_WAIT;
15212 goto do_cp0;
15213 case DERET:
15214 mips32_op = OPC_DERET;
15215 goto do_cp0;
15216 case ERET:
15217 mips32_op = OPC_ERET;
15218 do_cp0:
15219 gen_cp0(env, ctx, mips32_op, rt, rs);
15220 break;
15221 default:
15222 goto pool32axf_invalid;
15224 break;
15225 case 0x1d:
15226 switch (minor) {
15227 case DI:
15228 check_cp0_enabled(ctx);
15230 TCGv t0 = tcg_temp_new();
15232 save_cpu_state(ctx, 1);
15233 gen_helper_di(t0, cpu_env);
15234 gen_store_gpr(t0, rs);
15235 /* Stop translation as we may have switched the execution mode */
15236 ctx->base.is_jmp = DISAS_STOP;
15237 tcg_temp_free(t0);
15239 break;
15240 case EI:
15241 check_cp0_enabled(ctx);
15243 TCGv t0 = tcg_temp_new();
15245 save_cpu_state(ctx, 1);
15246 gen_helper_ei(t0, cpu_env);
15247 gen_store_gpr(t0, rs);
15248 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15249 of translated code to check for pending interrupts. */
15250 gen_save_pc(ctx->base.pc_next + 4);
15251 ctx->base.is_jmp = DISAS_EXIT;
15252 tcg_temp_free(t0);
15254 break;
15255 default:
15256 goto pool32axf_invalid;
15258 break;
15259 #endif
15260 case 0x2d:
15261 switch (minor) {
15262 case SYNC:
15263 gen_sync(extract32(ctx->opcode, 16, 5));
15264 break;
15265 case SYSCALL:
15266 generate_exception_end(ctx, EXCP_SYSCALL);
15267 break;
15268 case SDBBP:
15269 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15270 gen_helper_do_semihosting(cpu_env);
15271 } else {
15272 check_insn(ctx, ISA_MIPS32);
15273 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15274 generate_exception_end(ctx, EXCP_RI);
15275 } else {
15276 generate_exception_end(ctx, EXCP_DBp);
15279 break;
15280 default:
15281 goto pool32axf_invalid;
15283 break;
15284 case 0x01:
15285 switch (minor & 3) {
15286 case MFHI_ACC:
15287 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15288 break;
15289 case MFLO_ACC:
15290 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15291 break;
15292 case MTHI_ACC:
15293 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15294 break;
15295 case MTLO_ACC:
15296 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15297 break;
15298 default:
15299 goto pool32axf_invalid;
15301 break;
15302 case 0x35:
15303 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15304 switch (minor) {
15305 case MFHI32:
15306 gen_HILO(ctx, OPC_MFHI, 0, rs);
15307 break;
15308 case MFLO32:
15309 gen_HILO(ctx, OPC_MFLO, 0, rs);
15310 break;
15311 case MTHI32:
15312 gen_HILO(ctx, OPC_MTHI, 0, rs);
15313 break;
15314 case MTLO32:
15315 gen_HILO(ctx, OPC_MTLO, 0, rs);
15316 break;
15317 default:
15318 goto pool32axf_invalid;
15320 break;
15321 default:
15322 pool32axf_invalid:
15323 MIPS_INVAL("pool32axf");
15324 generate_exception_end(ctx, EXCP_RI);
15325 break;
15329 /* Values for microMIPS fmt field. Variable-width, depending on which
15330 formats the instruction supports. */
15332 enum {
15333 FMT_SD_S = 0,
15334 FMT_SD_D = 1,
15336 FMT_SDPS_S = 0,
15337 FMT_SDPS_D = 1,
15338 FMT_SDPS_PS = 2,
15340 FMT_SWL_S = 0,
15341 FMT_SWL_W = 1,
15342 FMT_SWL_L = 2,
15344 FMT_DWL_D = 0,
15345 FMT_DWL_W = 1,
15346 FMT_DWL_L = 2
15349 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15351 int extension = (ctx->opcode >> 6) & 0x3ff;
15352 uint32_t mips32_op;
15354 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15355 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15356 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15358 switch (extension) {
15359 case FLOAT_1BIT_FMT(CFC1, 0):
15360 mips32_op = OPC_CFC1;
15361 goto do_cp1;
15362 case FLOAT_1BIT_FMT(CTC1, 0):
15363 mips32_op = OPC_CTC1;
15364 goto do_cp1;
15365 case FLOAT_1BIT_FMT(MFC1, 0):
15366 mips32_op = OPC_MFC1;
15367 goto do_cp1;
15368 case FLOAT_1BIT_FMT(MTC1, 0):
15369 mips32_op = OPC_MTC1;
15370 goto do_cp1;
15371 case FLOAT_1BIT_FMT(MFHC1, 0):
15372 mips32_op = OPC_MFHC1;
15373 goto do_cp1;
15374 case FLOAT_1BIT_FMT(MTHC1, 0):
15375 mips32_op = OPC_MTHC1;
15376 do_cp1:
15377 gen_cp1(ctx, mips32_op, rt, rs);
15378 break;
15380 /* Reciprocal square root */
15381 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15382 mips32_op = OPC_RSQRT_S;
15383 goto do_unaryfp;
15384 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15385 mips32_op = OPC_RSQRT_D;
15386 goto do_unaryfp;
15388 /* Square root */
15389 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15390 mips32_op = OPC_SQRT_S;
15391 goto do_unaryfp;
15392 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15393 mips32_op = OPC_SQRT_D;
15394 goto do_unaryfp;
15396 /* Reciprocal */
15397 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15398 mips32_op = OPC_RECIP_S;
15399 goto do_unaryfp;
15400 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15401 mips32_op = OPC_RECIP_D;
15402 goto do_unaryfp;
15404 /* Floor */
15405 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15406 mips32_op = OPC_FLOOR_L_S;
15407 goto do_unaryfp;
15408 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15409 mips32_op = OPC_FLOOR_L_D;
15410 goto do_unaryfp;
15411 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15412 mips32_op = OPC_FLOOR_W_S;
15413 goto do_unaryfp;
15414 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15415 mips32_op = OPC_FLOOR_W_D;
15416 goto do_unaryfp;
15418 /* Ceiling */
15419 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15420 mips32_op = OPC_CEIL_L_S;
15421 goto do_unaryfp;
15422 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15423 mips32_op = OPC_CEIL_L_D;
15424 goto do_unaryfp;
15425 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15426 mips32_op = OPC_CEIL_W_S;
15427 goto do_unaryfp;
15428 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15429 mips32_op = OPC_CEIL_W_D;
15430 goto do_unaryfp;
15432 /* Truncation */
15433 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15434 mips32_op = OPC_TRUNC_L_S;
15435 goto do_unaryfp;
15436 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15437 mips32_op = OPC_TRUNC_L_D;
15438 goto do_unaryfp;
15439 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15440 mips32_op = OPC_TRUNC_W_S;
15441 goto do_unaryfp;
15442 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15443 mips32_op = OPC_TRUNC_W_D;
15444 goto do_unaryfp;
15446 /* Round */
15447 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15448 mips32_op = OPC_ROUND_L_S;
15449 goto do_unaryfp;
15450 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15451 mips32_op = OPC_ROUND_L_D;
15452 goto do_unaryfp;
15453 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15454 mips32_op = OPC_ROUND_W_S;
15455 goto do_unaryfp;
15456 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15457 mips32_op = OPC_ROUND_W_D;
15458 goto do_unaryfp;
15460 /* Integer to floating-point conversion */
15461 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15462 mips32_op = OPC_CVT_L_S;
15463 goto do_unaryfp;
15464 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15465 mips32_op = OPC_CVT_L_D;
15466 goto do_unaryfp;
15467 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15468 mips32_op = OPC_CVT_W_S;
15469 goto do_unaryfp;
15470 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15471 mips32_op = OPC_CVT_W_D;
15472 goto do_unaryfp;
15474 /* Paired-foo conversions */
15475 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15476 mips32_op = OPC_CVT_S_PL;
15477 goto do_unaryfp;
15478 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15479 mips32_op = OPC_CVT_S_PU;
15480 goto do_unaryfp;
15481 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15482 mips32_op = OPC_CVT_PW_PS;
15483 goto do_unaryfp;
15484 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15485 mips32_op = OPC_CVT_PS_PW;
15486 goto do_unaryfp;
15488 /* Floating-point moves */
15489 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15490 mips32_op = OPC_MOV_S;
15491 goto do_unaryfp;
15492 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15493 mips32_op = OPC_MOV_D;
15494 goto do_unaryfp;
15495 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15496 mips32_op = OPC_MOV_PS;
15497 goto do_unaryfp;
15499 /* Absolute value */
15500 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15501 mips32_op = OPC_ABS_S;
15502 goto do_unaryfp;
15503 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15504 mips32_op = OPC_ABS_D;
15505 goto do_unaryfp;
15506 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15507 mips32_op = OPC_ABS_PS;
15508 goto do_unaryfp;
15510 /* Negation */
15511 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15512 mips32_op = OPC_NEG_S;
15513 goto do_unaryfp;
15514 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15515 mips32_op = OPC_NEG_D;
15516 goto do_unaryfp;
15517 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15518 mips32_op = OPC_NEG_PS;
15519 goto do_unaryfp;
15521 /* Reciprocal square root step */
15522 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15523 mips32_op = OPC_RSQRT1_S;
15524 goto do_unaryfp;
15525 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15526 mips32_op = OPC_RSQRT1_D;
15527 goto do_unaryfp;
15528 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15529 mips32_op = OPC_RSQRT1_PS;
15530 goto do_unaryfp;
15532 /* Reciprocal step */
15533 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15534 mips32_op = OPC_RECIP1_S;
15535 goto do_unaryfp;
15536 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15537 mips32_op = OPC_RECIP1_S;
15538 goto do_unaryfp;
15539 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15540 mips32_op = OPC_RECIP1_PS;
15541 goto do_unaryfp;
15543 /* Conversions from double */
15544 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15545 mips32_op = OPC_CVT_D_S;
15546 goto do_unaryfp;
15547 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15548 mips32_op = OPC_CVT_D_W;
15549 goto do_unaryfp;
15550 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15551 mips32_op = OPC_CVT_D_L;
15552 goto do_unaryfp;
15554 /* Conversions from single */
15555 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15556 mips32_op = OPC_CVT_S_D;
15557 goto do_unaryfp;
15558 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15559 mips32_op = OPC_CVT_S_W;
15560 goto do_unaryfp;
15561 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15562 mips32_op = OPC_CVT_S_L;
15563 do_unaryfp:
15564 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15565 break;
15567 /* Conditional moves on floating-point codes */
15568 case COND_FLOAT_MOV(MOVT, 0):
15569 case COND_FLOAT_MOV(MOVT, 1):
15570 case COND_FLOAT_MOV(MOVT, 2):
15571 case COND_FLOAT_MOV(MOVT, 3):
15572 case COND_FLOAT_MOV(MOVT, 4):
15573 case COND_FLOAT_MOV(MOVT, 5):
15574 case COND_FLOAT_MOV(MOVT, 6):
15575 case COND_FLOAT_MOV(MOVT, 7):
15576 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15577 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15578 break;
15579 case COND_FLOAT_MOV(MOVF, 0):
15580 case COND_FLOAT_MOV(MOVF, 1):
15581 case COND_FLOAT_MOV(MOVF, 2):
15582 case COND_FLOAT_MOV(MOVF, 3):
15583 case COND_FLOAT_MOV(MOVF, 4):
15584 case COND_FLOAT_MOV(MOVF, 5):
15585 case COND_FLOAT_MOV(MOVF, 6):
15586 case COND_FLOAT_MOV(MOVF, 7):
15587 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15588 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15589 break;
15590 default:
15591 MIPS_INVAL("pool32fxf");
15592 generate_exception_end(ctx, EXCP_RI);
15593 break;
15597 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15599 int32_t offset;
15600 uint16_t insn;
15601 int rt, rs, rd, rr;
15602 int16_t imm;
15603 uint32_t op, minor, minor2, mips32_op;
15604 uint32_t cond, fmt, cc;
15606 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15607 ctx->opcode = (ctx->opcode << 16) | insn;
15609 rt = (ctx->opcode >> 21) & 0x1f;
15610 rs = (ctx->opcode >> 16) & 0x1f;
15611 rd = (ctx->opcode >> 11) & 0x1f;
15612 rr = (ctx->opcode >> 6) & 0x1f;
15613 imm = (int16_t) ctx->opcode;
15615 op = (ctx->opcode >> 26) & 0x3f;
15616 switch (op) {
15617 case POOL32A:
15618 minor = ctx->opcode & 0x3f;
15619 switch (minor) {
15620 case 0x00:
15621 minor = (ctx->opcode >> 6) & 0xf;
15622 switch (minor) {
15623 case SLL32:
15624 mips32_op = OPC_SLL;
15625 goto do_shifti;
15626 case SRA:
15627 mips32_op = OPC_SRA;
15628 goto do_shifti;
15629 case SRL32:
15630 mips32_op = OPC_SRL;
15631 goto do_shifti;
15632 case ROTR:
15633 mips32_op = OPC_ROTR;
15634 do_shifti:
15635 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15636 break;
15637 case SELEQZ:
15638 check_insn(ctx, ISA_MIPS32R6);
15639 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15640 break;
15641 case SELNEZ:
15642 check_insn(ctx, ISA_MIPS32R6);
15643 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15644 break;
15645 case R6_RDHWR:
15646 check_insn(ctx, ISA_MIPS32R6);
15647 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15648 break;
15649 default:
15650 goto pool32a_invalid;
15652 break;
15653 case 0x10:
15654 minor = (ctx->opcode >> 6) & 0xf;
15655 switch (minor) {
15656 /* Arithmetic */
15657 case ADD:
15658 mips32_op = OPC_ADD;
15659 goto do_arith;
15660 case ADDU32:
15661 mips32_op = OPC_ADDU;
15662 goto do_arith;
15663 case SUB:
15664 mips32_op = OPC_SUB;
15665 goto do_arith;
15666 case SUBU32:
15667 mips32_op = OPC_SUBU;
15668 goto do_arith;
15669 case MUL:
15670 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15671 mips32_op = OPC_MUL;
15672 do_arith:
15673 gen_arith(ctx, mips32_op, rd, rs, rt);
15674 break;
15675 /* Shifts */
15676 case SLLV:
15677 mips32_op = OPC_SLLV;
15678 goto do_shift;
15679 case SRLV:
15680 mips32_op = OPC_SRLV;
15681 goto do_shift;
15682 case SRAV:
15683 mips32_op = OPC_SRAV;
15684 goto do_shift;
15685 case ROTRV:
15686 mips32_op = OPC_ROTRV;
15687 do_shift:
15688 gen_shift(ctx, mips32_op, rd, rs, rt);
15689 break;
15690 /* Logical operations */
15691 case AND:
15692 mips32_op = OPC_AND;
15693 goto do_logic;
15694 case OR32:
15695 mips32_op = OPC_OR;
15696 goto do_logic;
15697 case NOR:
15698 mips32_op = OPC_NOR;
15699 goto do_logic;
15700 case XOR32:
15701 mips32_op = OPC_XOR;
15702 do_logic:
15703 gen_logic(ctx, mips32_op, rd, rs, rt);
15704 break;
15705 /* Set less than */
15706 case SLT:
15707 mips32_op = OPC_SLT;
15708 goto do_slt;
15709 case SLTU:
15710 mips32_op = OPC_SLTU;
15711 do_slt:
15712 gen_slt(ctx, mips32_op, rd, rs, rt);
15713 break;
15714 default:
15715 goto pool32a_invalid;
15717 break;
15718 case 0x18:
15719 minor = (ctx->opcode >> 6) & 0xf;
15720 switch (minor) {
15721 /* Conditional moves */
15722 case MOVN: /* MUL */
15723 if (ctx->insn_flags & ISA_MIPS32R6) {
15724 /* MUL */
15725 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15726 } else {
15727 /* MOVN */
15728 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15730 break;
15731 case MOVZ: /* MUH */
15732 if (ctx->insn_flags & ISA_MIPS32R6) {
15733 /* MUH */
15734 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15735 } else {
15736 /* MOVZ */
15737 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15739 break;
15740 case MULU:
15741 check_insn(ctx, ISA_MIPS32R6);
15742 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15743 break;
15744 case MUHU:
15745 check_insn(ctx, ISA_MIPS32R6);
15746 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15747 break;
15748 case LWXS: /* DIV */
15749 if (ctx->insn_flags & ISA_MIPS32R6) {
15750 /* DIV */
15751 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15752 } else {
15753 /* LWXS */
15754 gen_ldxs(ctx, rs, rt, rd);
15756 break;
15757 case MOD:
15758 check_insn(ctx, ISA_MIPS32R6);
15759 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15760 break;
15761 case R6_DIVU:
15762 check_insn(ctx, ISA_MIPS32R6);
15763 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15764 break;
15765 case MODU:
15766 check_insn(ctx, ISA_MIPS32R6);
15767 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15768 break;
15769 default:
15770 goto pool32a_invalid;
15772 break;
15773 case INS:
15774 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15775 return;
15776 case LSA:
15777 check_insn(ctx, ISA_MIPS32R6);
15778 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15779 extract32(ctx->opcode, 9, 2));
15780 break;
15781 case ALIGN:
15782 check_insn(ctx, ISA_MIPS32R6);
15783 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15784 break;
15785 case EXT:
15786 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15787 return;
15788 case POOL32AXF:
15789 gen_pool32axf(env, ctx, rt, rs);
15790 break;
15791 case BREAK32:
15792 generate_exception_end(ctx, EXCP_BREAK);
15793 break;
15794 case SIGRIE:
15795 check_insn(ctx, ISA_MIPS32R6);
15796 generate_exception_end(ctx, EXCP_RI);
15797 break;
15798 default:
15799 pool32a_invalid:
15800 MIPS_INVAL("pool32a");
15801 generate_exception_end(ctx, EXCP_RI);
15802 break;
15804 break;
15805 case POOL32B:
15806 minor = (ctx->opcode >> 12) & 0xf;
15807 switch (minor) {
15808 case CACHE:
15809 check_cp0_enabled(ctx);
15810 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15811 gen_cache_operation(ctx, rt, rs, imm);
15813 break;
15814 case LWC2:
15815 case SWC2:
15816 /* COP2: Not implemented. */
15817 generate_exception_err(ctx, EXCP_CpU, 2);
15818 break;
15819 #ifdef TARGET_MIPS64
15820 case LDP:
15821 case SDP:
15822 check_insn(ctx, ISA_MIPS3);
15823 check_mips_64(ctx);
15824 #endif
15825 /* fall through */
15826 case LWP:
15827 case SWP:
15828 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15829 break;
15830 #ifdef TARGET_MIPS64
15831 case LDM:
15832 case SDM:
15833 check_insn(ctx, ISA_MIPS3);
15834 check_mips_64(ctx);
15835 #endif
15836 /* fall through */
15837 case LWM32:
15838 case SWM32:
15839 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15840 break;
15841 default:
15842 MIPS_INVAL("pool32b");
15843 generate_exception_end(ctx, EXCP_RI);
15844 break;
15846 break;
15847 case POOL32F:
15848 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15849 minor = ctx->opcode & 0x3f;
15850 check_cp1_enabled(ctx);
15851 switch (minor) {
15852 case ALNV_PS:
15853 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15854 mips32_op = OPC_ALNV_PS;
15855 goto do_madd;
15856 case MADD_S:
15857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15858 mips32_op = OPC_MADD_S;
15859 goto do_madd;
15860 case MADD_D:
15861 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15862 mips32_op = OPC_MADD_D;
15863 goto do_madd;
15864 case MADD_PS:
15865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15866 mips32_op = OPC_MADD_PS;
15867 goto do_madd;
15868 case MSUB_S:
15869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15870 mips32_op = OPC_MSUB_S;
15871 goto do_madd;
15872 case MSUB_D:
15873 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15874 mips32_op = OPC_MSUB_D;
15875 goto do_madd;
15876 case MSUB_PS:
15877 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15878 mips32_op = OPC_MSUB_PS;
15879 goto do_madd;
15880 case NMADD_S:
15881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15882 mips32_op = OPC_NMADD_S;
15883 goto do_madd;
15884 case NMADD_D:
15885 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15886 mips32_op = OPC_NMADD_D;
15887 goto do_madd;
15888 case NMADD_PS:
15889 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15890 mips32_op = OPC_NMADD_PS;
15891 goto do_madd;
15892 case NMSUB_S:
15893 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15894 mips32_op = OPC_NMSUB_S;
15895 goto do_madd;
15896 case NMSUB_D:
15897 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15898 mips32_op = OPC_NMSUB_D;
15899 goto do_madd;
15900 case NMSUB_PS:
15901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15902 mips32_op = OPC_NMSUB_PS;
15903 do_madd:
15904 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15905 break;
15906 case CABS_COND_FMT:
15907 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15908 cond = (ctx->opcode >> 6) & 0xf;
15909 cc = (ctx->opcode >> 13) & 0x7;
15910 fmt = (ctx->opcode >> 10) & 0x3;
15911 switch (fmt) {
15912 case 0x0:
15913 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15914 break;
15915 case 0x1:
15916 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15917 break;
15918 case 0x2:
15919 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15920 break;
15921 default:
15922 goto pool32f_invalid;
15924 break;
15925 case C_COND_FMT:
15926 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15927 cond = (ctx->opcode >> 6) & 0xf;
15928 cc = (ctx->opcode >> 13) & 0x7;
15929 fmt = (ctx->opcode >> 10) & 0x3;
15930 switch (fmt) {
15931 case 0x0:
15932 gen_cmp_s(ctx, cond, rt, rs, cc);
15933 break;
15934 case 0x1:
15935 gen_cmp_d(ctx, cond, rt, rs, cc);
15936 break;
15937 case 0x2:
15938 gen_cmp_ps(ctx, cond, rt, rs, cc);
15939 break;
15940 default:
15941 goto pool32f_invalid;
15943 break;
15944 case CMP_CONDN_S:
15945 check_insn(ctx, ISA_MIPS32R6);
15946 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15947 break;
15948 case CMP_CONDN_D:
15949 check_insn(ctx, ISA_MIPS32R6);
15950 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15951 break;
15952 case POOL32FXF:
15953 gen_pool32fxf(ctx, rt, rs);
15954 break;
15955 case 0x00:
15956 /* PLL foo */
15957 switch ((ctx->opcode >> 6) & 0x7) {
15958 case PLL_PS:
15959 mips32_op = OPC_PLL_PS;
15960 goto do_ps;
15961 case PLU_PS:
15962 mips32_op = OPC_PLU_PS;
15963 goto do_ps;
15964 case PUL_PS:
15965 mips32_op = OPC_PUL_PS;
15966 goto do_ps;
15967 case PUU_PS:
15968 mips32_op = OPC_PUU_PS;
15969 goto do_ps;
15970 case CVT_PS_S:
15971 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15972 mips32_op = OPC_CVT_PS_S;
15973 do_ps:
15974 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15975 break;
15976 default:
15977 goto pool32f_invalid;
15979 break;
15980 case MIN_FMT:
15981 check_insn(ctx, ISA_MIPS32R6);
15982 switch ((ctx->opcode >> 9) & 0x3) {
15983 case FMT_SDPS_S:
15984 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15985 break;
15986 case FMT_SDPS_D:
15987 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15988 break;
15989 default:
15990 goto pool32f_invalid;
15992 break;
15993 case 0x08:
15994 /* [LS][WDU]XC1 */
15995 switch ((ctx->opcode >> 6) & 0x7) {
15996 case LWXC1:
15997 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15998 mips32_op = OPC_LWXC1;
15999 goto do_ldst_cp1;
16000 case SWXC1:
16001 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16002 mips32_op = OPC_SWXC1;
16003 goto do_ldst_cp1;
16004 case LDXC1:
16005 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16006 mips32_op = OPC_LDXC1;
16007 goto do_ldst_cp1;
16008 case SDXC1:
16009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16010 mips32_op = OPC_SDXC1;
16011 goto do_ldst_cp1;
16012 case LUXC1:
16013 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16014 mips32_op = OPC_LUXC1;
16015 goto do_ldst_cp1;
16016 case SUXC1:
16017 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16018 mips32_op = OPC_SUXC1;
16019 do_ldst_cp1:
16020 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16021 break;
16022 default:
16023 goto pool32f_invalid;
16025 break;
16026 case MAX_FMT:
16027 check_insn(ctx, ISA_MIPS32R6);
16028 switch ((ctx->opcode >> 9) & 0x3) {
16029 case FMT_SDPS_S:
16030 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16031 break;
16032 case FMT_SDPS_D:
16033 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16034 break;
16035 default:
16036 goto pool32f_invalid;
16038 break;
16039 case 0x18:
16040 /* 3D insns */
16041 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16042 fmt = (ctx->opcode >> 9) & 0x3;
16043 switch ((ctx->opcode >> 6) & 0x7) {
16044 case RSQRT2_FMT:
16045 switch (fmt) {
16046 case FMT_SDPS_S:
16047 mips32_op = OPC_RSQRT2_S;
16048 goto do_3d;
16049 case FMT_SDPS_D:
16050 mips32_op = OPC_RSQRT2_D;
16051 goto do_3d;
16052 case FMT_SDPS_PS:
16053 mips32_op = OPC_RSQRT2_PS;
16054 goto do_3d;
16055 default:
16056 goto pool32f_invalid;
16058 break;
16059 case RECIP2_FMT:
16060 switch (fmt) {
16061 case FMT_SDPS_S:
16062 mips32_op = OPC_RECIP2_S;
16063 goto do_3d;
16064 case FMT_SDPS_D:
16065 mips32_op = OPC_RECIP2_D;
16066 goto do_3d;
16067 case FMT_SDPS_PS:
16068 mips32_op = OPC_RECIP2_PS;
16069 goto do_3d;
16070 default:
16071 goto pool32f_invalid;
16073 break;
16074 case ADDR_PS:
16075 mips32_op = OPC_ADDR_PS;
16076 goto do_3d;
16077 case MULR_PS:
16078 mips32_op = OPC_MULR_PS;
16079 do_3d:
16080 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16081 break;
16082 default:
16083 goto pool32f_invalid;
16085 break;
16086 case 0x20:
16087 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16088 cc = (ctx->opcode >> 13) & 0x7;
16089 fmt = (ctx->opcode >> 9) & 0x3;
16090 switch ((ctx->opcode >> 6) & 0x7) {
16091 case MOVF_FMT: /* RINT_FMT */
16092 if (ctx->insn_flags & ISA_MIPS32R6) {
16093 /* RINT_FMT */
16094 switch (fmt) {
16095 case FMT_SDPS_S:
16096 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16097 break;
16098 case FMT_SDPS_D:
16099 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16100 break;
16101 default:
16102 goto pool32f_invalid;
16104 } else {
16105 /* MOVF_FMT */
16106 switch (fmt) {
16107 case FMT_SDPS_S:
16108 gen_movcf_s(ctx, rs, rt, cc, 0);
16109 break;
16110 case FMT_SDPS_D:
16111 gen_movcf_d(ctx, rs, rt, cc, 0);
16112 break;
16113 case FMT_SDPS_PS:
16114 check_ps(ctx);
16115 gen_movcf_ps(ctx, rs, rt, cc, 0);
16116 break;
16117 default:
16118 goto pool32f_invalid;
16121 break;
16122 case MOVT_FMT: /* CLASS_FMT */
16123 if (ctx->insn_flags & ISA_MIPS32R6) {
16124 /* CLASS_FMT */
16125 switch (fmt) {
16126 case FMT_SDPS_S:
16127 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16128 break;
16129 case FMT_SDPS_D:
16130 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16131 break;
16132 default:
16133 goto pool32f_invalid;
16135 } else {
16136 /* MOVT_FMT */
16137 switch (fmt) {
16138 case FMT_SDPS_S:
16139 gen_movcf_s(ctx, rs, rt, cc, 1);
16140 break;
16141 case FMT_SDPS_D:
16142 gen_movcf_d(ctx, rs, rt, cc, 1);
16143 break;
16144 case FMT_SDPS_PS:
16145 check_ps(ctx);
16146 gen_movcf_ps(ctx, rs, rt, cc, 1);
16147 break;
16148 default:
16149 goto pool32f_invalid;
16152 break;
16153 case PREFX:
16154 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16155 break;
16156 default:
16157 goto pool32f_invalid;
16159 break;
16160 #define FINSN_3ARG_SDPS(prfx) \
16161 switch ((ctx->opcode >> 8) & 0x3) { \
16162 case FMT_SDPS_S: \
16163 mips32_op = OPC_##prfx##_S; \
16164 goto do_fpop; \
16165 case FMT_SDPS_D: \
16166 mips32_op = OPC_##prfx##_D; \
16167 goto do_fpop; \
16168 case FMT_SDPS_PS: \
16169 check_ps(ctx); \
16170 mips32_op = OPC_##prfx##_PS; \
16171 goto do_fpop; \
16172 default: \
16173 goto pool32f_invalid; \
16175 case MINA_FMT:
16176 check_insn(ctx, ISA_MIPS32R6);
16177 switch ((ctx->opcode >> 9) & 0x3) {
16178 case FMT_SDPS_S:
16179 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16180 break;
16181 case FMT_SDPS_D:
16182 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16183 break;
16184 default:
16185 goto pool32f_invalid;
16187 break;
16188 case MAXA_FMT:
16189 check_insn(ctx, ISA_MIPS32R6);
16190 switch ((ctx->opcode >> 9) & 0x3) {
16191 case FMT_SDPS_S:
16192 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16193 break;
16194 case FMT_SDPS_D:
16195 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16196 break;
16197 default:
16198 goto pool32f_invalid;
16200 break;
16201 case 0x30:
16202 /* regular FP ops */
16203 switch ((ctx->opcode >> 6) & 0x3) {
16204 case ADD_FMT:
16205 FINSN_3ARG_SDPS(ADD);
16206 break;
16207 case SUB_FMT:
16208 FINSN_3ARG_SDPS(SUB);
16209 break;
16210 case MUL_FMT:
16211 FINSN_3ARG_SDPS(MUL);
16212 break;
16213 case DIV_FMT:
16214 fmt = (ctx->opcode >> 8) & 0x3;
16215 if (fmt == 1) {
16216 mips32_op = OPC_DIV_D;
16217 } else if (fmt == 0) {
16218 mips32_op = OPC_DIV_S;
16219 } else {
16220 goto pool32f_invalid;
16222 goto do_fpop;
16223 default:
16224 goto pool32f_invalid;
16226 break;
16227 case 0x38:
16228 /* cmovs */
16229 switch ((ctx->opcode >> 6) & 0x7) {
16230 case MOVN_FMT: /* SELEQZ_FMT */
16231 if (ctx->insn_flags & ISA_MIPS32R6) {
16232 /* SELEQZ_FMT */
16233 switch ((ctx->opcode >> 9) & 0x3) {
16234 case FMT_SDPS_S:
16235 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16236 break;
16237 case FMT_SDPS_D:
16238 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16239 break;
16240 default:
16241 goto pool32f_invalid;
16243 } else {
16244 /* MOVN_FMT */
16245 FINSN_3ARG_SDPS(MOVN);
16247 break;
16248 case MOVN_FMT_04:
16249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16250 FINSN_3ARG_SDPS(MOVN);
16251 break;
16252 case MOVZ_FMT: /* SELNEZ_FMT */
16253 if (ctx->insn_flags & ISA_MIPS32R6) {
16254 /* SELNEZ_FMT */
16255 switch ((ctx->opcode >> 9) & 0x3) {
16256 case FMT_SDPS_S:
16257 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16258 break;
16259 case FMT_SDPS_D:
16260 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16261 break;
16262 default:
16263 goto pool32f_invalid;
16265 } else {
16266 /* MOVZ_FMT */
16267 FINSN_3ARG_SDPS(MOVZ);
16269 break;
16270 case MOVZ_FMT_05:
16271 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16272 FINSN_3ARG_SDPS(MOVZ);
16273 break;
16274 case SEL_FMT:
16275 check_insn(ctx, ISA_MIPS32R6);
16276 switch ((ctx->opcode >> 9) & 0x3) {
16277 case FMT_SDPS_S:
16278 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16279 break;
16280 case FMT_SDPS_D:
16281 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16282 break;
16283 default:
16284 goto pool32f_invalid;
16286 break;
16287 case MADDF_FMT:
16288 check_insn(ctx, ISA_MIPS32R6);
16289 switch ((ctx->opcode >> 9) & 0x3) {
16290 case FMT_SDPS_S:
16291 mips32_op = OPC_MADDF_S;
16292 goto do_fpop;
16293 case FMT_SDPS_D:
16294 mips32_op = OPC_MADDF_D;
16295 goto do_fpop;
16296 default:
16297 goto pool32f_invalid;
16299 break;
16300 case MSUBF_FMT:
16301 check_insn(ctx, ISA_MIPS32R6);
16302 switch ((ctx->opcode >> 9) & 0x3) {
16303 case FMT_SDPS_S:
16304 mips32_op = OPC_MSUBF_S;
16305 goto do_fpop;
16306 case FMT_SDPS_D:
16307 mips32_op = OPC_MSUBF_D;
16308 goto do_fpop;
16309 default:
16310 goto pool32f_invalid;
16312 break;
16313 default:
16314 goto pool32f_invalid;
16316 break;
16317 do_fpop:
16318 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16319 break;
16320 default:
16321 pool32f_invalid:
16322 MIPS_INVAL("pool32f");
16323 generate_exception_end(ctx, EXCP_RI);
16324 break;
16326 } else {
16327 generate_exception_err(ctx, EXCP_CpU, 1);
16329 break;
16330 case POOL32I:
16331 minor = (ctx->opcode >> 21) & 0x1f;
16332 switch (minor) {
16333 case BLTZ:
16334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16335 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16336 break;
16337 case BLTZAL:
16338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16339 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16340 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16341 break;
16342 case BLTZALS:
16343 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16344 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16345 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16346 break;
16347 case BGEZ:
16348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16349 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16350 break;
16351 case BGEZAL:
16352 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16353 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16354 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16355 break;
16356 case BGEZALS:
16357 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16358 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16359 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16360 break;
16361 case BLEZ:
16362 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16363 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16364 break;
16365 case BGTZ:
16366 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16367 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16368 break;
16370 /* Traps */
16371 case TLTI: /* BC1EQZC */
16372 if (ctx->insn_flags & ISA_MIPS32R6) {
16373 /* BC1EQZC */
16374 check_cp1_enabled(ctx);
16375 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16376 } else {
16377 /* TLTI */
16378 mips32_op = OPC_TLTI;
16379 goto do_trapi;
16381 break;
16382 case TGEI: /* BC1NEZC */
16383 if (ctx->insn_flags & ISA_MIPS32R6) {
16384 /* BC1NEZC */
16385 check_cp1_enabled(ctx);
16386 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16387 } else {
16388 /* TGEI */
16389 mips32_op = OPC_TGEI;
16390 goto do_trapi;
16392 break;
16393 case TLTIU:
16394 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16395 mips32_op = OPC_TLTIU;
16396 goto do_trapi;
16397 case TGEIU:
16398 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16399 mips32_op = OPC_TGEIU;
16400 goto do_trapi;
16401 case TNEI: /* SYNCI */
16402 if (ctx->insn_flags & ISA_MIPS32R6) {
16403 /* SYNCI */
16404 /* Break the TB to be able to sync copied instructions
16405 immediately */
16406 ctx->base.is_jmp = DISAS_STOP;
16407 } else {
16408 /* TNEI */
16409 mips32_op = OPC_TNEI;
16410 goto do_trapi;
16412 break;
16413 case TEQI:
16414 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16415 mips32_op = OPC_TEQI;
16416 do_trapi:
16417 gen_trap(ctx, mips32_op, rs, -1, imm);
16418 break;
16420 case BNEZC:
16421 case BEQZC:
16422 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16423 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16424 4, rs, 0, imm << 1, 0);
16425 /* Compact branches don't have a delay slot, so just let
16426 the normal delay slot handling take us to the branch
16427 target. */
16428 break;
16429 case LUI:
16430 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16431 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16432 break;
16433 case SYNCI:
16434 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16435 /* Break the TB to be able to sync copied instructions
16436 immediately */
16437 ctx->base.is_jmp = DISAS_STOP;
16438 break;
16439 case BC2F:
16440 case BC2T:
16441 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16442 /* COP2: Not implemented. */
16443 generate_exception_err(ctx, EXCP_CpU, 2);
16444 break;
16445 case BC1F:
16446 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16447 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16448 goto do_cp1branch;
16449 case BC1T:
16450 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16451 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16452 goto do_cp1branch;
16453 case BC1ANY4F:
16454 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16455 mips32_op = OPC_BC1FANY4;
16456 goto do_cp1mips3d;
16457 case BC1ANY4T:
16458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16459 mips32_op = OPC_BC1TANY4;
16460 do_cp1mips3d:
16461 check_cop1x(ctx);
16462 check_insn(ctx, ASE_MIPS3D);
16463 /* Fall through */
16464 do_cp1branch:
16465 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16466 check_cp1_enabled(ctx);
16467 gen_compute_branch1(ctx, mips32_op,
16468 (ctx->opcode >> 18) & 0x7, imm << 1);
16469 } else {
16470 generate_exception_err(ctx, EXCP_CpU, 1);
16472 break;
16473 case BPOSGE64:
16474 case BPOSGE32:
16475 /* MIPS DSP: not implemented */
16476 /* Fall through */
16477 default:
16478 MIPS_INVAL("pool32i");
16479 generate_exception_end(ctx, EXCP_RI);
16480 break;
16482 break;
16483 case POOL32C:
16484 minor = (ctx->opcode >> 12) & 0xf;
16485 offset = sextract32(ctx->opcode, 0,
16486 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16487 switch (minor) {
16488 case LWL:
16489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16490 mips32_op = OPC_LWL;
16491 goto do_ld_lr;
16492 case SWL:
16493 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16494 mips32_op = OPC_SWL;
16495 goto do_st_lr;
16496 case LWR:
16497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16498 mips32_op = OPC_LWR;
16499 goto do_ld_lr;
16500 case SWR:
16501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16502 mips32_op = OPC_SWR;
16503 goto do_st_lr;
16504 #if defined(TARGET_MIPS64)
16505 case LDL:
16506 check_insn(ctx, ISA_MIPS3);
16507 check_mips_64(ctx);
16508 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16509 mips32_op = OPC_LDL;
16510 goto do_ld_lr;
16511 case SDL:
16512 check_insn(ctx, ISA_MIPS3);
16513 check_mips_64(ctx);
16514 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16515 mips32_op = OPC_SDL;
16516 goto do_st_lr;
16517 case LDR:
16518 check_insn(ctx, ISA_MIPS3);
16519 check_mips_64(ctx);
16520 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16521 mips32_op = OPC_LDR;
16522 goto do_ld_lr;
16523 case SDR:
16524 check_insn(ctx, ISA_MIPS3);
16525 check_mips_64(ctx);
16526 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16527 mips32_op = OPC_SDR;
16528 goto do_st_lr;
16529 case LWU:
16530 check_insn(ctx, ISA_MIPS3);
16531 check_mips_64(ctx);
16532 mips32_op = OPC_LWU;
16533 goto do_ld_lr;
16534 case LLD:
16535 check_insn(ctx, ISA_MIPS3);
16536 check_mips_64(ctx);
16537 mips32_op = OPC_LLD;
16538 goto do_ld_lr;
16539 #endif
16540 case LL:
16541 mips32_op = OPC_LL;
16542 goto do_ld_lr;
16543 do_ld_lr:
16544 gen_ld(ctx, mips32_op, rt, rs, offset);
16545 break;
16546 do_st_lr:
16547 gen_st(ctx, mips32_op, rt, rs, offset);
16548 break;
16549 case SC:
16550 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16551 break;
16552 #if defined(TARGET_MIPS64)
16553 case SCD:
16554 check_insn(ctx, ISA_MIPS3);
16555 check_mips_64(ctx);
16556 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16557 break;
16558 #endif
16559 case LD_EVA:
16560 if (!ctx->eva) {
16561 MIPS_INVAL("pool32c ld-eva");
16562 generate_exception_end(ctx, EXCP_RI);
16563 break;
16565 check_cp0_enabled(ctx);
16567 minor2 = (ctx->opcode >> 9) & 0x7;
16568 offset = sextract32(ctx->opcode, 0, 9);
16569 switch (minor2) {
16570 case LBUE:
16571 mips32_op = OPC_LBUE;
16572 goto do_ld_lr;
16573 case LHUE:
16574 mips32_op = OPC_LHUE;
16575 goto do_ld_lr;
16576 case LWLE:
16577 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16578 mips32_op = OPC_LWLE;
16579 goto do_ld_lr;
16580 case LWRE:
16581 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16582 mips32_op = OPC_LWRE;
16583 goto do_ld_lr;
16584 case LBE:
16585 mips32_op = OPC_LBE;
16586 goto do_ld_lr;
16587 case LHE:
16588 mips32_op = OPC_LHE;
16589 goto do_ld_lr;
16590 case LLE:
16591 mips32_op = OPC_LLE;
16592 goto do_ld_lr;
16593 case LWE:
16594 mips32_op = OPC_LWE;
16595 goto do_ld_lr;
16597 break;
16598 case ST_EVA:
16599 if (!ctx->eva) {
16600 MIPS_INVAL("pool32c st-eva");
16601 generate_exception_end(ctx, EXCP_RI);
16602 break;
16604 check_cp0_enabled(ctx);
16606 minor2 = (ctx->opcode >> 9) & 0x7;
16607 offset = sextract32(ctx->opcode, 0, 9);
16608 switch (minor2) {
16609 case SWLE:
16610 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16611 mips32_op = OPC_SWLE;
16612 goto do_st_lr;
16613 case SWRE:
16614 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16615 mips32_op = OPC_SWRE;
16616 goto do_st_lr;
16617 case PREFE:
16618 /* Treat as no-op */
16619 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16620 /* hint codes 24-31 are reserved and signal RI */
16621 generate_exception(ctx, EXCP_RI);
16623 break;
16624 case CACHEE:
16625 /* Treat as no-op */
16626 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16627 gen_cache_operation(ctx, rt, rs, offset);
16629 break;
16630 case SBE:
16631 mips32_op = OPC_SBE;
16632 goto do_st_lr;
16633 case SHE:
16634 mips32_op = OPC_SHE;
16635 goto do_st_lr;
16636 case SCE:
16637 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16638 break;
16639 case SWE:
16640 mips32_op = OPC_SWE;
16641 goto do_st_lr;
16643 break;
16644 case PREF:
16645 /* Treat as no-op */
16646 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16647 /* hint codes 24-31 are reserved and signal RI */
16648 generate_exception(ctx, EXCP_RI);
16650 break;
16651 default:
16652 MIPS_INVAL("pool32c");
16653 generate_exception_end(ctx, EXCP_RI);
16654 break;
16656 break;
16657 case ADDI32: /* AUI, LUI */
16658 if (ctx->insn_flags & ISA_MIPS32R6) {
16659 /* AUI, LUI */
16660 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16661 } else {
16662 /* ADDI32 */
16663 mips32_op = OPC_ADDI;
16664 goto do_addi;
16666 break;
16667 case ADDIU32:
16668 mips32_op = OPC_ADDIU;
16669 do_addi:
16670 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16671 break;
16673 /* Logical operations */
16674 case ORI32:
16675 mips32_op = OPC_ORI;
16676 goto do_logici;
16677 case XORI32:
16678 mips32_op = OPC_XORI;
16679 goto do_logici;
16680 case ANDI32:
16681 mips32_op = OPC_ANDI;
16682 do_logici:
16683 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16684 break;
16686 /* Set less than immediate */
16687 case SLTI32:
16688 mips32_op = OPC_SLTI;
16689 goto do_slti;
16690 case SLTIU32:
16691 mips32_op = OPC_SLTIU;
16692 do_slti:
16693 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16694 break;
16695 case JALX32:
16696 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16697 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16698 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16699 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16700 break;
16701 case JALS32: /* BOVC, BEQC, BEQZALC */
16702 if (ctx->insn_flags & ISA_MIPS32R6) {
16703 if (rs >= rt) {
16704 /* BOVC */
16705 mips32_op = OPC_BOVC;
16706 } else if (rs < rt && rs == 0) {
16707 /* BEQZALC */
16708 mips32_op = OPC_BEQZALC;
16709 } else {
16710 /* BEQC */
16711 mips32_op = OPC_BEQC;
16713 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16714 } else {
16715 /* JALS32 */
16716 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16717 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16718 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16720 break;
16721 case BEQ32: /* BC */
16722 if (ctx->insn_flags & ISA_MIPS32R6) {
16723 /* BC */
16724 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16725 sextract32(ctx->opcode << 1, 0, 27));
16726 } else {
16727 /* BEQ32 */
16728 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16730 break;
16731 case BNE32: /* BALC */
16732 if (ctx->insn_flags & ISA_MIPS32R6) {
16733 /* BALC */
16734 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16735 sextract32(ctx->opcode << 1, 0, 27));
16736 } else {
16737 /* BNE32 */
16738 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16740 break;
16741 case J32: /* BGTZC, BLTZC, BLTC */
16742 if (ctx->insn_flags & ISA_MIPS32R6) {
16743 if (rs == 0 && rt != 0) {
16744 /* BGTZC */
16745 mips32_op = OPC_BGTZC;
16746 } else if (rs != 0 && rt != 0 && rs == rt) {
16747 /* BLTZC */
16748 mips32_op = OPC_BLTZC;
16749 } else {
16750 /* BLTC */
16751 mips32_op = OPC_BLTC;
16753 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16754 } else {
16755 /* J32 */
16756 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16757 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16759 break;
16760 case JAL32: /* BLEZC, BGEZC, BGEC */
16761 if (ctx->insn_flags & ISA_MIPS32R6) {
16762 if (rs == 0 && rt != 0) {
16763 /* BLEZC */
16764 mips32_op = OPC_BLEZC;
16765 } else if (rs != 0 && rt != 0 && rs == rt) {
16766 /* BGEZC */
16767 mips32_op = OPC_BGEZC;
16768 } else {
16769 /* BGEC */
16770 mips32_op = OPC_BGEC;
16772 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16773 } else {
16774 /* JAL32 */
16775 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16776 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16777 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16779 break;
16780 /* Floating point (COP1) */
16781 case LWC132:
16782 mips32_op = OPC_LWC1;
16783 goto do_cop1;
16784 case LDC132:
16785 mips32_op = OPC_LDC1;
16786 goto do_cop1;
16787 case SWC132:
16788 mips32_op = OPC_SWC1;
16789 goto do_cop1;
16790 case SDC132:
16791 mips32_op = OPC_SDC1;
16792 do_cop1:
16793 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16794 break;
16795 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16796 if (ctx->insn_flags & ISA_MIPS32R6) {
16797 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16798 switch ((ctx->opcode >> 16) & 0x1f) {
16799 case ADDIUPC_00:
16800 case ADDIUPC_01:
16801 case ADDIUPC_02:
16802 case ADDIUPC_03:
16803 case ADDIUPC_04:
16804 case ADDIUPC_05:
16805 case ADDIUPC_06:
16806 case ADDIUPC_07:
16807 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16808 break;
16809 case AUIPC:
16810 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16811 break;
16812 case ALUIPC:
16813 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16814 break;
16815 case LWPC_08:
16816 case LWPC_09:
16817 case LWPC_0A:
16818 case LWPC_0B:
16819 case LWPC_0C:
16820 case LWPC_0D:
16821 case LWPC_0E:
16822 case LWPC_0F:
16823 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16824 break;
16825 default:
16826 generate_exception(ctx, EXCP_RI);
16827 break;
16829 } else {
16830 /* ADDIUPC */
16831 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16832 offset = SIMM(ctx->opcode, 0, 23) << 2;
16834 gen_addiupc(ctx, reg, offset, 0, 0);
16836 break;
16837 case BNVC: /* BNEC, BNEZALC */
16838 check_insn(ctx, ISA_MIPS32R6);
16839 if (rs >= rt) {
16840 /* BNVC */
16841 mips32_op = OPC_BNVC;
16842 } else if (rs < rt && rs == 0) {
16843 /* BNEZALC */
16844 mips32_op = OPC_BNEZALC;
16845 } else {
16846 /* BNEC */
16847 mips32_op = OPC_BNEC;
16849 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16850 break;
16851 case R6_BNEZC: /* JIALC */
16852 check_insn(ctx, ISA_MIPS32R6);
16853 if (rt != 0) {
16854 /* BNEZC */
16855 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16856 sextract32(ctx->opcode << 1, 0, 22));
16857 } else {
16858 /* JIALC */
16859 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16861 break;
16862 case R6_BEQZC: /* JIC */
16863 check_insn(ctx, ISA_MIPS32R6);
16864 if (rt != 0) {
16865 /* BEQZC */
16866 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16867 sextract32(ctx->opcode << 1, 0, 22));
16868 } else {
16869 /* JIC */
16870 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16872 break;
16873 case BLEZALC: /* BGEZALC, BGEUC */
16874 check_insn(ctx, ISA_MIPS32R6);
16875 if (rs == 0 && rt != 0) {
16876 /* BLEZALC */
16877 mips32_op = OPC_BLEZALC;
16878 } else if (rs != 0 && rt != 0 && rs == rt) {
16879 /* BGEZALC */
16880 mips32_op = OPC_BGEZALC;
16881 } else {
16882 /* BGEUC */
16883 mips32_op = OPC_BGEUC;
16885 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16886 break;
16887 case BGTZALC: /* BLTZALC, BLTUC */
16888 check_insn(ctx, ISA_MIPS32R6);
16889 if (rs == 0 && rt != 0) {
16890 /* BGTZALC */
16891 mips32_op = OPC_BGTZALC;
16892 } else if (rs != 0 && rt != 0 && rs == rt) {
16893 /* BLTZALC */
16894 mips32_op = OPC_BLTZALC;
16895 } else {
16896 /* BLTUC */
16897 mips32_op = OPC_BLTUC;
16899 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16900 break;
16901 /* Loads and stores */
16902 case LB32:
16903 mips32_op = OPC_LB;
16904 goto do_ld;
16905 case LBU32:
16906 mips32_op = OPC_LBU;
16907 goto do_ld;
16908 case LH32:
16909 mips32_op = OPC_LH;
16910 goto do_ld;
16911 case LHU32:
16912 mips32_op = OPC_LHU;
16913 goto do_ld;
16914 case LW32:
16915 mips32_op = OPC_LW;
16916 goto do_ld;
16917 #ifdef TARGET_MIPS64
16918 case LD32:
16919 check_insn(ctx, ISA_MIPS3);
16920 check_mips_64(ctx);
16921 mips32_op = OPC_LD;
16922 goto do_ld;
16923 case SD32:
16924 check_insn(ctx, ISA_MIPS3);
16925 check_mips_64(ctx);
16926 mips32_op = OPC_SD;
16927 goto do_st;
16928 #endif
16929 case SB32:
16930 mips32_op = OPC_SB;
16931 goto do_st;
16932 case SH32:
16933 mips32_op = OPC_SH;
16934 goto do_st;
16935 case SW32:
16936 mips32_op = OPC_SW;
16937 goto do_st;
16938 do_ld:
16939 gen_ld(ctx, mips32_op, rt, rs, imm);
16940 break;
16941 do_st:
16942 gen_st(ctx, mips32_op, rt, rs, imm);
16943 break;
16944 default:
16945 generate_exception_end(ctx, EXCP_RI);
16946 break;
16950 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16952 uint32_t op;
16954 /* make sure instructions are on a halfword boundary */
16955 if (ctx->base.pc_next & 0x1) {
16956 env->CP0_BadVAddr = ctx->base.pc_next;
16957 generate_exception_end(ctx, EXCP_AdEL);
16958 return 2;
16961 op = (ctx->opcode >> 10) & 0x3f;
16962 /* Enforce properly-sized instructions in a delay slot */
16963 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16964 switch (op & 0x7) { /* MSB-3..MSB-5 */
16965 case 0:
16966 /* POOL32A, POOL32B, POOL32I, POOL32C */
16967 case 4:
16968 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16969 case 5:
16970 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16971 case 6:
16972 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16973 case 7:
16974 /* LB32, LH32, LWC132, LDC132, LW32 */
16975 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16976 generate_exception_end(ctx, EXCP_RI);
16977 return 2;
16979 break;
16980 case 1:
16981 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16982 case 2:
16983 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16984 case 3:
16985 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16986 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16987 generate_exception_end(ctx, EXCP_RI);
16988 return 2;
16990 break;
16994 switch (op) {
16995 case POOL16A:
16997 int rd = mmreg(uMIPS_RD(ctx->opcode));
16998 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16999 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17000 uint32_t opc = 0;
17002 switch (ctx->opcode & 0x1) {
17003 case ADDU16:
17004 opc = OPC_ADDU;
17005 break;
17006 case SUBU16:
17007 opc = OPC_SUBU;
17008 break;
17010 if (ctx->insn_flags & ISA_MIPS32R6) {
17011 /* In the Release 6 the register number location in
17012 * the instruction encoding has changed.
17014 gen_arith(ctx, opc, rs1, rd, rs2);
17015 } else {
17016 gen_arith(ctx, opc, rd, rs1, rs2);
17019 break;
17020 case POOL16B:
17022 int rd = mmreg(uMIPS_RD(ctx->opcode));
17023 int rs = mmreg(uMIPS_RS(ctx->opcode));
17024 int amount = (ctx->opcode >> 1) & 0x7;
17025 uint32_t opc = 0;
17026 amount = amount == 0 ? 8 : amount;
17028 switch (ctx->opcode & 0x1) {
17029 case SLL16:
17030 opc = OPC_SLL;
17031 break;
17032 case SRL16:
17033 opc = OPC_SRL;
17034 break;
17037 gen_shift_imm(ctx, opc, rd, rs, amount);
17039 break;
17040 case POOL16C:
17041 if (ctx->insn_flags & ISA_MIPS32R6) {
17042 gen_pool16c_r6_insn(ctx);
17043 } else {
17044 gen_pool16c_insn(ctx);
17046 break;
17047 case LWGP16:
17049 int rd = mmreg(uMIPS_RD(ctx->opcode));
17050 int rb = 28; /* GP */
17051 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17053 gen_ld(ctx, OPC_LW, rd, rb, offset);
17055 break;
17056 case POOL16F:
17057 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17058 if (ctx->opcode & 1) {
17059 generate_exception_end(ctx, EXCP_RI);
17060 } else {
17061 /* MOVEP */
17062 int enc_dest = uMIPS_RD(ctx->opcode);
17063 int enc_rt = uMIPS_RS2(ctx->opcode);
17064 int enc_rs = uMIPS_RS1(ctx->opcode);
17065 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17067 break;
17068 case LBU16:
17070 int rd = mmreg(uMIPS_RD(ctx->opcode));
17071 int rb = mmreg(uMIPS_RS(ctx->opcode));
17072 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17073 offset = (offset == 0xf ? -1 : offset);
17075 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17077 break;
17078 case LHU16:
17080 int rd = mmreg(uMIPS_RD(ctx->opcode));
17081 int rb = mmreg(uMIPS_RS(ctx->opcode));
17082 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17084 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17086 break;
17087 case LWSP16:
17089 int rd = (ctx->opcode >> 5) & 0x1f;
17090 int rb = 29; /* SP */
17091 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17093 gen_ld(ctx, OPC_LW, rd, rb, offset);
17095 break;
17096 case LW16:
17098 int rd = mmreg(uMIPS_RD(ctx->opcode));
17099 int rb = mmreg(uMIPS_RS(ctx->opcode));
17100 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17102 gen_ld(ctx, OPC_LW, rd, rb, offset);
17104 break;
17105 case SB16:
17107 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17108 int rb = mmreg(uMIPS_RS(ctx->opcode));
17109 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17111 gen_st(ctx, OPC_SB, rd, rb, offset);
17113 break;
17114 case SH16:
17116 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17117 int rb = mmreg(uMIPS_RS(ctx->opcode));
17118 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17120 gen_st(ctx, OPC_SH, rd, rb, offset);
17122 break;
17123 case SWSP16:
17125 int rd = (ctx->opcode >> 5) & 0x1f;
17126 int rb = 29; /* SP */
17127 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17129 gen_st(ctx, OPC_SW, rd, rb, offset);
17131 break;
17132 case SW16:
17134 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17135 int rb = mmreg(uMIPS_RS(ctx->opcode));
17136 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17138 gen_st(ctx, OPC_SW, rd, rb, offset);
17140 break;
17141 case MOVE16:
17143 int rd = uMIPS_RD5(ctx->opcode);
17144 int rs = uMIPS_RS5(ctx->opcode);
17146 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17148 break;
17149 case ANDI16:
17150 gen_andi16(ctx);
17151 break;
17152 case POOL16D:
17153 switch (ctx->opcode & 0x1) {
17154 case ADDIUS5:
17155 gen_addius5(ctx);
17156 break;
17157 case ADDIUSP:
17158 gen_addiusp(ctx);
17159 break;
17161 break;
17162 case POOL16E:
17163 switch (ctx->opcode & 0x1) {
17164 case ADDIUR2:
17165 gen_addiur2(ctx);
17166 break;
17167 case ADDIUR1SP:
17168 gen_addiur1sp(ctx);
17169 break;
17171 break;
17172 case B16: /* BC16 */
17173 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17174 sextract32(ctx->opcode, 0, 10) << 1,
17175 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17176 break;
17177 case BNEZ16: /* BNEZC16 */
17178 case BEQZ16: /* BEQZC16 */
17179 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17180 mmreg(uMIPS_RD(ctx->opcode)),
17181 0, sextract32(ctx->opcode, 0, 7) << 1,
17182 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17184 break;
17185 case LI16:
17187 int reg = mmreg(uMIPS_RD(ctx->opcode));
17188 int imm = ZIMM(ctx->opcode, 0, 7);
17190 imm = (imm == 0x7f ? -1 : imm);
17191 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17193 break;
17194 case RES_29:
17195 case RES_31:
17196 case RES_39:
17197 generate_exception_end(ctx, EXCP_RI);
17198 break;
17199 default:
17200 decode_micromips32_opc(env, ctx);
17201 return 4;
17204 return 2;
17209 * nanoMIPS opcodes
17213 /* MAJOR, P16, and P32 pools opcodes */
17214 enum {
17215 NM_P_ADDIU = 0x00,
17216 NM_ADDIUPC = 0x01,
17217 NM_MOVE_BALC = 0x02,
17218 NM_P16_MV = 0x04,
17219 NM_LW16 = 0x05,
17220 NM_BC16 = 0x06,
17221 NM_P16_SR = 0x07,
17223 NM_POOL32A = 0x08,
17224 NM_P_BAL = 0x0a,
17225 NM_P16_SHIFT = 0x0c,
17226 NM_LWSP16 = 0x0d,
17227 NM_BALC16 = 0x0e,
17228 NM_P16_4X4 = 0x0f,
17230 NM_P_GP_W = 0x10,
17231 NM_P_GP_BH = 0x11,
17232 NM_P_J = 0x12,
17233 NM_P16C = 0x14,
17234 NM_LWGP16 = 0x15,
17235 NM_P16_LB = 0x17,
17237 NM_P48I = 0x18,
17238 NM_P16_A1 = 0x1c,
17239 NM_LW4X4 = 0x1d,
17240 NM_P16_LH = 0x1f,
17242 NM_P_U12 = 0x20,
17243 NM_P_LS_U12 = 0x21,
17244 NM_P_BR1 = 0x22,
17245 NM_P16_A2 = 0x24,
17246 NM_SW16 = 0x25,
17247 NM_BEQZC16 = 0x26,
17249 NM_POOL32F = 0x28,
17250 NM_P_LS_S9 = 0x29,
17251 NM_P_BR2 = 0x2a,
17253 NM_P16_ADDU = 0x2c,
17254 NM_SWSP16 = 0x2d,
17255 NM_BNEZC16 = 0x2e,
17256 NM_MOVEP = 0x2f,
17258 NM_POOL32S = 0x30,
17259 NM_P_BRI = 0x32,
17260 NM_LI16 = 0x34,
17261 NM_SWGP16 = 0x35,
17262 NM_P16_BR = 0x36,
17264 NM_P_LUI = 0x38,
17265 NM_ANDI16 = 0x3c,
17266 NM_SW4X4 = 0x3d,
17267 NM_MOVEPREV = 0x3f,
17270 /* POOL32A instruction pool */
17271 enum {
17272 NM_POOL32A0 = 0x00,
17273 NM_SPECIAL2 = 0x01,
17274 NM_COP2_1 = 0x02,
17275 NM_UDI = 0x03,
17276 NM_POOL32A5 = 0x05,
17277 NM_POOL32A7 = 0x07,
17280 /* P.GP.W instruction pool */
17281 enum {
17282 NM_ADDIUGP_W = 0x00,
17283 NM_LWGP = 0x02,
17284 NM_SWGP = 0x03,
17287 /* P48I instruction pool */
17288 enum {
17289 NM_LI48 = 0x00,
17290 NM_ADDIU48 = 0x01,
17291 NM_ADDIUGP48 = 0x02,
17292 NM_ADDIUPC48 = 0x03,
17293 NM_LWPC48 = 0x0b,
17294 NM_SWPC48 = 0x0f,
17297 /* P.U12 instruction pool */
17298 enum {
17299 NM_ORI = 0x00,
17300 NM_XORI = 0x01,
17301 NM_ANDI = 0x02,
17302 NM_P_SR = 0x03,
17303 NM_SLTI = 0x04,
17304 NM_SLTIU = 0x05,
17305 NM_SEQI = 0x06,
17306 NM_ADDIUNEG = 0x08,
17307 NM_P_SHIFT = 0x0c,
17308 NM_P_ROTX = 0x0d,
17309 NM_P_INS = 0x0e,
17310 NM_P_EXT = 0x0f,
17313 /* POOL32F instruction pool */
17314 enum {
17315 NM_POOL32F_0 = 0x00,
17316 NM_POOL32F_3 = 0x03,
17317 NM_POOL32F_5 = 0x05,
17320 /* POOL32S instruction pool */
17321 enum {
17322 NM_POOL32S_0 = 0x00,
17323 NM_POOL32S_4 = 0x04,
17326 /* P.LUI instruction pool */
17327 enum {
17328 NM_LUI = 0x00,
17329 NM_ALUIPC = 0x01,
17332 /* P.GP.BH instruction pool */
17333 enum {
17334 NM_LBGP = 0x00,
17335 NM_SBGP = 0x01,
17336 NM_LBUGP = 0x02,
17337 NM_ADDIUGP_B = 0x03,
17338 NM_P_GP_LH = 0x04,
17339 NM_P_GP_SH = 0x05,
17340 NM_P_GP_CP1 = 0x06,
17343 /* P.LS.U12 instruction pool */
17344 enum {
17345 NM_LB = 0x00,
17346 NM_SB = 0x01,
17347 NM_LBU = 0x02,
17348 NM_P_PREFU12 = 0x03,
17349 NM_LH = 0x04,
17350 NM_SH = 0x05,
17351 NM_LHU = 0x06,
17352 NM_LWU = 0x07,
17353 NM_LW = 0x08,
17354 NM_SW = 0x09,
17355 NM_LWC1 = 0x0a,
17356 NM_SWC1 = 0x0b,
17357 NM_LDC1 = 0x0e,
17358 NM_SDC1 = 0x0f,
17361 /* P.LS.S9 instruction pool */
17362 enum {
17363 NM_P_LS_S0 = 0x00,
17364 NM_P_LS_S1 = 0x01,
17365 NM_P_LS_E0 = 0x02,
17366 NM_P_LS_WM = 0x04,
17367 NM_P_LS_UAWM = 0x05,
17370 /* P.BAL instruction pool */
17371 enum {
17372 NM_BC = 0x00,
17373 NM_BALC = 0x01,
17376 /* P.J instruction pool */
17377 enum {
17378 NM_JALRC = 0x00,
17379 NM_JALRC_HB = 0x01,
17380 NM_P_BALRSC = 0x08,
17383 /* P.BR1 instruction pool */
17384 enum {
17385 NM_BEQC = 0x00,
17386 NM_P_BR3A = 0x01,
17387 NM_BGEC = 0x02,
17388 NM_BGEUC = 0x03,
17391 /* P.BR2 instruction pool */
17392 enum {
17393 NM_BNEC = 0x00,
17394 NM_BLTC = 0x02,
17395 NM_BLTUC = 0x03,
17398 /* P.BRI instruction pool */
17399 enum {
17400 NM_BEQIC = 0x00,
17401 NM_BBEQZC = 0x01,
17402 NM_BGEIC = 0x02,
17403 NM_BGEIUC = 0x03,
17404 NM_BNEIC = 0x04,
17405 NM_BBNEZC = 0x05,
17406 NM_BLTIC = 0x06,
17407 NM_BLTIUC = 0x07,
17410 /* P16.SHIFT instruction pool */
17411 enum {
17412 NM_SLL16 = 0x00,
17413 NM_SRL16 = 0x01,
17416 /* POOL16C instruction pool */
17417 enum {
17418 NM_POOL16C_0 = 0x00,
17419 NM_LWXS16 = 0x01,
17422 /* P16.A1 instruction pool */
17423 enum {
17424 NM_ADDIUR1SP = 0x01,
17427 /* P16.A2 instruction pool */
17428 enum {
17429 NM_ADDIUR2 = 0x00,
17430 NM_P_ADDIURS5 = 0x01,
17433 /* P16.ADDU instruction pool */
17434 enum {
17435 NM_ADDU16 = 0x00,
17436 NM_SUBU16 = 0x01,
17439 /* P16.SR instruction pool */
17440 enum {
17441 NM_SAVE16 = 0x00,
17442 NM_RESTORE_JRC16 = 0x01,
17445 /* P16.4X4 instruction pool */
17446 enum {
17447 NM_ADDU4X4 = 0x00,
17448 NM_MUL4X4 = 0x01,
17451 /* P16.LB instruction pool */
17452 enum {
17453 NM_LB16 = 0x00,
17454 NM_SB16 = 0x01,
17455 NM_LBU16 = 0x02,
17458 /* P16.LH instruction pool */
17459 enum {
17460 NM_LH16 = 0x00,
17461 NM_SH16 = 0x01,
17462 NM_LHU16 = 0x02,
17465 /* P.RI instruction pool */
17466 enum {
17467 NM_SIGRIE = 0x00,
17468 NM_P_SYSCALL = 0x01,
17469 NM_BREAK = 0x02,
17470 NM_SDBBP = 0x03,
17473 /* POOL32A0 instruction pool */
17474 enum {
17475 NM_P_TRAP = 0x00,
17476 NM_SEB = 0x01,
17477 NM_SLLV = 0x02,
17478 NM_MUL = 0x03,
17479 NM_MFC0 = 0x06,
17480 NM_MFHC0 = 0x07,
17481 NM_SEH = 0x09,
17482 NM_SRLV = 0x0a,
17483 NM_MUH = 0x0b,
17484 NM_MTC0 = 0x0e,
17485 NM_MTHC0 = 0x0f,
17486 NM_SRAV = 0x12,
17487 NM_MULU = 0x13,
17488 NM_ROTRV = 0x1a,
17489 NM_MUHU = 0x1b,
17490 NM_ADD = 0x22,
17491 NM_DIV = 0x23,
17492 NM_ADDU = 0x2a,
17493 NM_MOD = 0x2b,
17494 NM_SUB = 0x32,
17495 NM_DIVU = 0x33,
17496 NM_RDHWR = 0x38,
17497 NM_SUBU = 0x3a,
17498 NM_MODU = 0x3b,
17499 NM_P_CMOVE = 0x42,
17500 NM_FORK = 0x45,
17501 NM_MFTR = 0x46,
17502 NM_MFHTR = 0x47,
17503 NM_AND = 0x4a,
17504 NM_YIELD = 0x4d,
17505 NM_MTTR = 0x4e,
17506 NM_MTHTR = 0x4f,
17507 NM_OR = 0x52,
17508 NM_D_E_MT_VPE = 0x56,
17509 NM_NOR = 0x5a,
17510 NM_XOR = 0x62,
17511 NM_SLT = 0x6a,
17512 NM_P_SLTU = 0x72,
17513 NM_SOV = 0x7a,
17516 /* CRC32 instruction pool */
17517 enum {
17518 NM_CRC32B = 0x00,
17519 NM_CRC32H = 0x01,
17520 NM_CRC32W = 0x02,
17521 NM_CRC32CB = 0x04,
17522 NM_CRC32CH = 0x05,
17523 NM_CRC32CW = 0x06,
17526 /* POOL32A5 instruction pool */
17527 enum {
17528 NM_CMP_EQ_PH = 0x00,
17529 NM_CMP_LT_PH = 0x08,
17530 NM_CMP_LE_PH = 0x10,
17531 NM_CMPGU_EQ_QB = 0x18,
17532 NM_CMPGU_LT_QB = 0x20,
17533 NM_CMPGU_LE_QB = 0x28,
17534 NM_CMPGDU_EQ_QB = 0x30,
17535 NM_CMPGDU_LT_QB = 0x38,
17536 NM_CMPGDU_LE_QB = 0x40,
17537 NM_CMPU_EQ_QB = 0x48,
17538 NM_CMPU_LT_QB = 0x50,
17539 NM_CMPU_LE_QB = 0x58,
17540 NM_ADDQ_S_W = 0x60,
17541 NM_SUBQ_S_W = 0x68,
17542 NM_ADDSC = 0x70,
17543 NM_ADDWC = 0x78,
17545 NM_ADDQ_S_PH = 0x01,
17546 NM_ADDQH_R_PH = 0x09,
17547 NM_ADDQH_R_W = 0x11,
17548 NM_ADDU_S_QB = 0x19,
17549 NM_ADDU_S_PH = 0x21,
17550 NM_ADDUH_R_QB = 0x29,
17551 NM_SHRAV_R_PH = 0x31,
17552 NM_SHRAV_R_QB = 0x39,
17553 NM_SUBQ_S_PH = 0x41,
17554 NM_SUBQH_R_PH = 0x49,
17555 NM_SUBQH_R_W = 0x51,
17556 NM_SUBU_S_QB = 0x59,
17557 NM_SUBU_S_PH = 0x61,
17558 NM_SUBUH_R_QB = 0x69,
17559 NM_SHLLV_S_PH = 0x71,
17560 NM_PRECR_SRA_R_PH_W = 0x79,
17562 NM_MULEU_S_PH_QBL = 0x12,
17563 NM_MULEU_S_PH_QBR = 0x1a,
17564 NM_MULQ_RS_PH = 0x22,
17565 NM_MULQ_S_PH = 0x2a,
17566 NM_MULQ_RS_W = 0x32,
17567 NM_MULQ_S_W = 0x3a,
17568 NM_APPEND = 0x42,
17569 NM_MODSUB = 0x52,
17570 NM_SHRAV_R_W = 0x5a,
17571 NM_SHRLV_PH = 0x62,
17572 NM_SHRLV_QB = 0x6a,
17573 NM_SHLLV_QB = 0x72,
17574 NM_SHLLV_S_W = 0x7a,
17576 NM_SHILO = 0x03,
17578 NM_MULEQ_S_W_PHL = 0x04,
17579 NM_MULEQ_S_W_PHR = 0x0c,
17581 NM_MUL_S_PH = 0x05,
17582 NM_PRECR_QB_PH = 0x0d,
17583 NM_PRECRQ_QB_PH = 0x15,
17584 NM_PRECRQ_PH_W = 0x1d,
17585 NM_PRECRQ_RS_PH_W = 0x25,
17586 NM_PRECRQU_S_QB_PH = 0x2d,
17587 NM_PACKRL_PH = 0x35,
17588 NM_PICK_QB = 0x3d,
17589 NM_PICK_PH = 0x45,
17591 NM_SHRA_R_W = 0x5e,
17592 NM_SHRA_R_PH = 0x66,
17593 NM_SHLL_S_PH = 0x76,
17594 NM_SHLL_S_W = 0x7e,
17596 NM_REPL_PH = 0x07
17599 /* POOL32A7 instruction pool */
17600 enum {
17601 NM_P_LSX = 0x00,
17602 NM_LSA = 0x01,
17603 NM_EXTW = 0x03,
17604 NM_POOL32AXF = 0x07,
17607 /* P.SR instruction pool */
17608 enum {
17609 NM_PP_SR = 0x00,
17610 NM_P_SR_F = 0x01,
17613 /* P.SHIFT instruction pool */
17614 enum {
17615 NM_P_SLL = 0x00,
17616 NM_SRL = 0x02,
17617 NM_SRA = 0x04,
17618 NM_ROTR = 0x06,
17621 /* P.ROTX instruction pool */
17622 enum {
17623 NM_ROTX = 0x00,
17626 /* P.INS instruction pool */
17627 enum {
17628 NM_INS = 0x00,
17631 /* P.EXT instruction pool */
17632 enum {
17633 NM_EXT = 0x00,
17636 /* POOL32F_0 (fmt) instruction pool */
17637 enum {
17638 NM_RINT_S = 0x04,
17639 NM_RINT_D = 0x44,
17640 NM_ADD_S = 0x06,
17641 NM_SELEQZ_S = 0x07,
17642 NM_SELEQZ_D = 0x47,
17643 NM_CLASS_S = 0x0c,
17644 NM_CLASS_D = 0x4c,
17645 NM_SUB_S = 0x0e,
17646 NM_SELNEZ_S = 0x0f,
17647 NM_SELNEZ_D = 0x4f,
17648 NM_MUL_S = 0x16,
17649 NM_SEL_S = 0x17,
17650 NM_SEL_D = 0x57,
17651 NM_DIV_S = 0x1e,
17652 NM_ADD_D = 0x26,
17653 NM_SUB_D = 0x2e,
17654 NM_MUL_D = 0x36,
17655 NM_MADDF_S = 0x37,
17656 NM_MADDF_D = 0x77,
17657 NM_DIV_D = 0x3e,
17658 NM_MSUBF_S = 0x3f,
17659 NM_MSUBF_D = 0x7f,
17662 /* POOL32F_3 instruction pool */
17663 enum {
17664 NM_MIN_FMT = 0x00,
17665 NM_MAX_FMT = 0x01,
17666 NM_MINA_FMT = 0x04,
17667 NM_MAXA_FMT = 0x05,
17668 NM_POOL32FXF = 0x07,
17671 /* POOL32F_5 instruction pool */
17672 enum {
17673 NM_CMP_CONDN_S = 0x00,
17674 NM_CMP_CONDN_D = 0x02,
17677 /* P.GP.LH instruction pool */
17678 enum {
17679 NM_LHGP = 0x00,
17680 NM_LHUGP = 0x01,
17683 /* P.GP.SH instruction pool */
17684 enum {
17685 NM_SHGP = 0x00,
17688 /* P.GP.CP1 instruction pool */
17689 enum {
17690 NM_LWC1GP = 0x00,
17691 NM_SWC1GP = 0x01,
17692 NM_LDC1GP = 0x02,
17693 NM_SDC1GP = 0x03,
17696 /* P.LS.S0 instruction pool */
17697 enum {
17698 NM_LBS9 = 0x00,
17699 NM_LHS9 = 0x04,
17700 NM_LWS9 = 0x08,
17701 NM_LDS9 = 0x0c,
17703 NM_SBS9 = 0x01,
17704 NM_SHS9 = 0x05,
17705 NM_SWS9 = 0x09,
17706 NM_SDS9 = 0x0d,
17708 NM_LBUS9 = 0x02,
17709 NM_LHUS9 = 0x06,
17710 NM_LWC1S9 = 0x0a,
17711 NM_LDC1S9 = 0x0e,
17713 NM_P_PREFS9 = 0x03,
17714 NM_LWUS9 = 0x07,
17715 NM_SWC1S9 = 0x0b,
17716 NM_SDC1S9 = 0x0f,
17719 /* P.LS.S1 instruction pool */
17720 enum {
17721 NM_ASET_ACLR = 0x02,
17722 NM_UALH = 0x04,
17723 NM_UASH = 0x05,
17724 NM_CACHE = 0x07,
17725 NM_P_LL = 0x0a,
17726 NM_P_SC = 0x0b,
17729 /* P.LS.E0 instruction pool */
17730 enum {
17731 NM_LBE = 0x00,
17732 NM_SBE = 0x01,
17733 NM_LBUE = 0x02,
17734 NM_P_PREFE = 0x03,
17735 NM_LHE = 0x04,
17736 NM_SHE = 0x05,
17737 NM_LHUE = 0x06,
17738 NM_CACHEE = 0x07,
17739 NM_LWE = 0x08,
17740 NM_SWE = 0x09,
17741 NM_P_LLE = 0x0a,
17742 NM_P_SCE = 0x0b,
17745 /* P.PREFE instruction pool */
17746 enum {
17747 NM_SYNCIE = 0x00,
17748 NM_PREFE = 0x01,
17751 /* P.LLE instruction pool */
17752 enum {
17753 NM_LLE = 0x00,
17754 NM_LLWPE = 0x01,
17757 /* P.SCE instruction pool */
17758 enum {
17759 NM_SCE = 0x00,
17760 NM_SCWPE = 0x01,
17763 /* P.LS.WM instruction pool */
17764 enum {
17765 NM_LWM = 0x00,
17766 NM_SWM = 0x01,
17769 /* P.LS.UAWM instruction pool */
17770 enum {
17771 NM_UALWM = 0x00,
17772 NM_UASWM = 0x01,
17775 /* P.BR3A instruction pool */
17776 enum {
17777 NM_BC1EQZC = 0x00,
17778 NM_BC1NEZC = 0x01,
17779 NM_BC2EQZC = 0x02,
17780 NM_BC2NEZC = 0x03,
17781 NM_BPOSGE32C = 0x04,
17784 /* P16.RI instruction pool */
17785 enum {
17786 NM_P16_SYSCALL = 0x01,
17787 NM_BREAK16 = 0x02,
17788 NM_SDBBP16 = 0x03,
17791 /* POOL16C_0 instruction pool */
17792 enum {
17793 NM_POOL16C_00 = 0x00,
17796 /* P16.JRC instruction pool */
17797 enum {
17798 NM_JRC = 0x00,
17799 NM_JALRC16 = 0x01,
17802 /* P.SYSCALL instruction pool */
17803 enum {
17804 NM_SYSCALL = 0x00,
17805 NM_HYPCALL = 0x01,
17808 /* P.TRAP instruction pool */
17809 enum {
17810 NM_TEQ = 0x00,
17811 NM_TNE = 0x01,
17814 /* P.CMOVE instruction pool */
17815 enum {
17816 NM_MOVZ = 0x00,
17817 NM_MOVN = 0x01,
17820 /* POOL32Axf instruction pool */
17821 enum {
17822 NM_POOL32AXF_1 = 0x01,
17823 NM_POOL32AXF_2 = 0x02,
17824 NM_POOL32AXF_4 = 0x04,
17825 NM_POOL32AXF_5 = 0x05,
17826 NM_POOL32AXF_7 = 0x07,
17829 /* POOL32Axf_1 instruction pool */
17830 enum {
17831 NM_POOL32AXF_1_0 = 0x00,
17832 NM_POOL32AXF_1_1 = 0x01,
17833 NM_POOL32AXF_1_3 = 0x03,
17834 NM_POOL32AXF_1_4 = 0x04,
17835 NM_POOL32AXF_1_5 = 0x05,
17836 NM_POOL32AXF_1_7 = 0x07,
17839 /* POOL32Axf_2 instruction pool */
17840 enum {
17841 NM_POOL32AXF_2_0_7 = 0x00,
17842 NM_POOL32AXF_2_8_15 = 0x01,
17843 NM_POOL32AXF_2_16_23 = 0x02,
17844 NM_POOL32AXF_2_24_31 = 0x03,
17847 /* POOL32Axf_7 instruction pool */
17848 enum {
17849 NM_SHRA_R_QB = 0x0,
17850 NM_SHRL_PH = 0x1,
17851 NM_REPL_QB = 0x2,
17854 /* POOL32Axf_1_0 instruction pool */
17855 enum {
17856 NM_MFHI = 0x0,
17857 NM_MFLO = 0x1,
17858 NM_MTHI = 0x2,
17859 NM_MTLO = 0x3,
17862 /* POOL32Axf_1_1 instruction pool */
17863 enum {
17864 NM_MTHLIP = 0x0,
17865 NM_SHILOV = 0x1,
17868 /* POOL32Axf_1_3 instruction pool */
17869 enum {
17870 NM_RDDSP = 0x0,
17871 NM_WRDSP = 0x1,
17872 NM_EXTP = 0x2,
17873 NM_EXTPDP = 0x3,
17876 /* POOL32Axf_1_4 instruction pool */
17877 enum {
17878 NM_SHLL_QB = 0x0,
17879 NM_SHRL_QB = 0x1,
17882 /* POOL32Axf_1_5 instruction pool */
17883 enum {
17884 NM_MAQ_S_W_PHR = 0x0,
17885 NM_MAQ_S_W_PHL = 0x1,
17886 NM_MAQ_SA_W_PHR = 0x2,
17887 NM_MAQ_SA_W_PHL = 0x3,
17890 /* POOL32Axf_1_7 instruction pool */
17891 enum {
17892 NM_EXTR_W = 0x0,
17893 NM_EXTR_R_W = 0x1,
17894 NM_EXTR_RS_W = 0x2,
17895 NM_EXTR_S_H = 0x3,
17898 /* POOL32Axf_2_0_7 instruction pool */
17899 enum {
17900 NM_DPA_W_PH = 0x0,
17901 NM_DPAQ_S_W_PH = 0x1,
17902 NM_DPS_W_PH = 0x2,
17903 NM_DPSQ_S_W_PH = 0x3,
17904 NM_BALIGN = 0x4,
17905 NM_MADD = 0x5,
17906 NM_MULT = 0x6,
17907 NM_EXTRV_W = 0x7,
17910 /* POOL32Axf_2_8_15 instruction pool */
17911 enum {
17912 NM_DPAX_W_PH = 0x0,
17913 NM_DPAQ_SA_L_W = 0x1,
17914 NM_DPSX_W_PH = 0x2,
17915 NM_DPSQ_SA_L_W = 0x3,
17916 NM_MADDU = 0x5,
17917 NM_MULTU = 0x6,
17918 NM_EXTRV_R_W = 0x7,
17921 /* POOL32Axf_2_16_23 instruction pool */
17922 enum {
17923 NM_DPAU_H_QBL = 0x0,
17924 NM_DPAQX_S_W_PH = 0x1,
17925 NM_DPSU_H_QBL = 0x2,
17926 NM_DPSQX_S_W_PH = 0x3,
17927 NM_EXTPV = 0x4,
17928 NM_MSUB = 0x5,
17929 NM_MULSA_W_PH = 0x6,
17930 NM_EXTRV_RS_W = 0x7,
17933 /* POOL32Axf_2_24_31 instruction pool */
17934 enum {
17935 NM_DPAU_H_QBR = 0x0,
17936 NM_DPAQX_SA_W_PH = 0x1,
17937 NM_DPSU_H_QBR = 0x2,
17938 NM_DPSQX_SA_W_PH = 0x3,
17939 NM_EXTPDPV = 0x4,
17940 NM_MSUBU = 0x5,
17941 NM_MULSAQ_S_W_PH = 0x6,
17942 NM_EXTRV_S_H = 0x7,
17945 /* POOL32Axf_{4, 5} instruction pool */
17946 enum {
17947 NM_CLO = 0x25,
17948 NM_CLZ = 0x2d,
17950 NM_TLBP = 0x01,
17951 NM_TLBR = 0x09,
17952 NM_TLBWI = 0x11,
17953 NM_TLBWR = 0x19,
17954 NM_TLBINV = 0x03,
17955 NM_TLBINVF = 0x0b,
17956 NM_DI = 0x23,
17957 NM_EI = 0x2b,
17958 NM_RDPGPR = 0x70,
17959 NM_WRPGPR = 0x78,
17960 NM_WAIT = 0x61,
17961 NM_DERET = 0x71,
17962 NM_ERETX = 0x79,
17964 /* nanoMIPS DSP instructions */
17965 NM_ABSQ_S_QB = 0x00,
17966 NM_ABSQ_S_PH = 0x08,
17967 NM_ABSQ_S_W = 0x10,
17968 NM_PRECEQ_W_PHL = 0x28,
17969 NM_PRECEQ_W_PHR = 0x30,
17970 NM_PRECEQU_PH_QBL = 0x38,
17971 NM_PRECEQU_PH_QBR = 0x48,
17972 NM_PRECEU_PH_QBL = 0x58,
17973 NM_PRECEU_PH_QBR = 0x68,
17974 NM_PRECEQU_PH_QBLA = 0x39,
17975 NM_PRECEQU_PH_QBRA = 0x49,
17976 NM_PRECEU_PH_QBLA = 0x59,
17977 NM_PRECEU_PH_QBRA = 0x69,
17978 NM_REPLV_PH = 0x01,
17979 NM_REPLV_QB = 0x09,
17980 NM_BITREV = 0x18,
17981 NM_INSV = 0x20,
17982 NM_RADDU_W_QB = 0x78,
17984 NM_BITSWAP = 0x05,
17985 NM_WSBH = 0x3d,
17988 /* PP.SR instruction pool */
17989 enum {
17990 NM_SAVE = 0x00,
17991 NM_RESTORE = 0x02,
17992 NM_RESTORE_JRC = 0x03,
17995 /* P.SR.F instruction pool */
17996 enum {
17997 NM_SAVEF = 0x00,
17998 NM_RESTOREF = 0x01,
18001 /* P16.SYSCALL instruction pool */
18002 enum {
18003 NM_SYSCALL16 = 0x00,
18004 NM_HYPCALL16 = 0x01,
18007 /* POOL16C_00 instruction pool */
18008 enum {
18009 NM_NOT16 = 0x00,
18010 NM_XOR16 = 0x01,
18011 NM_AND16 = 0x02,
18012 NM_OR16 = 0x03,
18015 /* PP.LSX and PP.LSXS instruction pool */
18016 enum {
18017 NM_LBX = 0x00,
18018 NM_LHX = 0x04,
18019 NM_LWX = 0x08,
18020 NM_LDX = 0x0c,
18022 NM_SBX = 0x01,
18023 NM_SHX = 0x05,
18024 NM_SWX = 0x09,
18025 NM_SDX = 0x0d,
18027 NM_LBUX = 0x02,
18028 NM_LHUX = 0x06,
18029 NM_LWC1X = 0x0a,
18030 NM_LDC1X = 0x0e,
18032 NM_LWUX = 0x07,
18033 NM_SWC1X = 0x0b,
18034 NM_SDC1X = 0x0f,
18036 NM_LHXS = 0x04,
18037 NM_LWXS = 0x08,
18038 NM_LDXS = 0x0c,
18040 NM_SHXS = 0x05,
18041 NM_SWXS = 0x09,
18042 NM_SDXS = 0x0d,
18044 NM_LHUXS = 0x06,
18045 NM_LWC1XS = 0x0a,
18046 NM_LDC1XS = 0x0e,
18048 NM_LWUXS = 0x07,
18049 NM_SWC1XS = 0x0b,
18050 NM_SDC1XS = 0x0f,
18053 /* ERETx instruction pool */
18054 enum {
18055 NM_ERET = 0x00,
18056 NM_ERETNC = 0x01,
18059 /* POOL32FxF_{0, 1} insturction pool */
18060 enum {
18061 NM_CFC1 = 0x40,
18062 NM_CTC1 = 0x60,
18063 NM_MFC1 = 0x80,
18064 NM_MTC1 = 0xa0,
18065 NM_MFHC1 = 0xc0,
18066 NM_MTHC1 = 0xe0,
18068 NM_CVT_S_PL = 0x84,
18069 NM_CVT_S_PU = 0xa4,
18071 NM_CVT_L_S = 0x004,
18072 NM_CVT_L_D = 0x104,
18073 NM_CVT_W_S = 0x024,
18074 NM_CVT_W_D = 0x124,
18076 NM_RSQRT_S = 0x008,
18077 NM_RSQRT_D = 0x108,
18079 NM_SQRT_S = 0x028,
18080 NM_SQRT_D = 0x128,
18082 NM_RECIP_S = 0x048,
18083 NM_RECIP_D = 0x148,
18085 NM_FLOOR_L_S = 0x00c,
18086 NM_FLOOR_L_D = 0x10c,
18088 NM_FLOOR_W_S = 0x02c,
18089 NM_FLOOR_W_D = 0x12c,
18091 NM_CEIL_L_S = 0x04c,
18092 NM_CEIL_L_D = 0x14c,
18093 NM_CEIL_W_S = 0x06c,
18094 NM_CEIL_W_D = 0x16c,
18095 NM_TRUNC_L_S = 0x08c,
18096 NM_TRUNC_L_D = 0x18c,
18097 NM_TRUNC_W_S = 0x0ac,
18098 NM_TRUNC_W_D = 0x1ac,
18099 NM_ROUND_L_S = 0x0cc,
18100 NM_ROUND_L_D = 0x1cc,
18101 NM_ROUND_W_S = 0x0ec,
18102 NM_ROUND_W_D = 0x1ec,
18104 NM_MOV_S = 0x01,
18105 NM_MOV_D = 0x81,
18106 NM_ABS_S = 0x0d,
18107 NM_ABS_D = 0x8d,
18108 NM_NEG_S = 0x2d,
18109 NM_NEG_D = 0xad,
18110 NM_CVT_D_S = 0x04d,
18111 NM_CVT_D_W = 0x0cd,
18112 NM_CVT_D_L = 0x14d,
18113 NM_CVT_S_D = 0x06d,
18114 NM_CVT_S_W = 0x0ed,
18115 NM_CVT_S_L = 0x16d,
18118 /* P.LL instruction pool */
18119 enum {
18120 NM_LL = 0x00,
18121 NM_LLWP = 0x01,
18124 /* P.SC instruction pool */
18125 enum {
18126 NM_SC = 0x00,
18127 NM_SCWP = 0x01,
18130 /* P.DVP instruction pool */
18131 enum {
18132 NM_DVP = 0x00,
18133 NM_EVP = 0x01,
18139 * nanoMIPS decoding engine
18144 /* extraction utilities */
18146 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18147 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18148 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18149 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18150 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18151 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18153 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18154 static inline int decode_gpr_gpr3(int r)
18156 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18158 return map[r & 0x7];
18161 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18162 static inline int decode_gpr_gpr3_src_store(int r)
18164 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18166 return map[r & 0x7];
18169 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18170 static inline int decode_gpr_gpr4(int r)
18172 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18173 16, 17, 18, 19, 20, 21, 22, 23 };
18175 return map[r & 0xf];
18178 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18179 static inline int decode_gpr_gpr4_zero(int r)
18181 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18182 16, 17, 18, 19, 20, 21, 22, 23 };
18184 return map[r & 0xf];
18188 /* extraction utilities */
18190 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18191 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18192 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18193 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18194 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18195 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18198 static void gen_adjust_sp(DisasContext *ctx, int u)
18200 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18203 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18204 uint8_t gp, uint16_t u)
18206 int counter = 0;
18207 TCGv va = tcg_temp_new();
18208 TCGv t0 = tcg_temp_new();
18210 while (counter != count) {
18211 bool use_gp = gp && (counter == count - 1);
18212 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18213 int this_offset = -((counter + 1) << 2);
18214 gen_base_offset_addr(ctx, va, 29, this_offset);
18215 gen_load_gpr(t0, this_rt);
18216 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18217 (MO_TEUL | ctx->default_tcg_memop_mask));
18218 counter++;
18221 /* adjust stack pointer */
18222 gen_adjust_sp(ctx, -u);
18224 tcg_temp_free(t0);
18225 tcg_temp_free(va);
18228 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18229 uint8_t gp, uint16_t u)
18231 int counter = 0;
18232 TCGv va = tcg_temp_new();
18233 TCGv t0 = tcg_temp_new();
18235 while (counter != count) {
18236 bool use_gp = gp && (counter == count - 1);
18237 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18238 int this_offset = u - ((counter + 1) << 2);
18239 gen_base_offset_addr(ctx, va, 29, this_offset);
18240 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18241 ctx->default_tcg_memop_mask);
18242 tcg_gen_ext32s_tl(t0, t0);
18243 gen_store_gpr(t0, this_rt);
18244 counter++;
18247 /* adjust stack pointer */
18248 gen_adjust_sp(ctx, u);
18250 tcg_temp_free(t0);
18251 tcg_temp_free(va);
18254 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18256 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18257 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18259 switch (extract32(ctx->opcode, 2, 2)) {
18260 case NM_NOT16:
18261 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18262 break;
18263 case NM_AND16:
18264 gen_logic(ctx, OPC_AND, rt, rt, rs);
18265 break;
18266 case NM_XOR16:
18267 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18268 break;
18269 case NM_OR16:
18270 gen_logic(ctx, OPC_OR, rt, rt, rs);
18271 break;
18275 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18277 int rt = extract32(ctx->opcode, 21, 5);
18278 int rs = extract32(ctx->opcode, 16, 5);
18279 int rd = extract32(ctx->opcode, 11, 5);
18281 switch (extract32(ctx->opcode, 3, 7)) {
18282 case NM_P_TRAP:
18283 switch (extract32(ctx->opcode, 10, 1)) {
18284 case NM_TEQ:
18285 check_nms(ctx);
18286 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18287 break;
18288 case NM_TNE:
18289 check_nms(ctx);
18290 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18291 break;
18293 break;
18294 case NM_RDHWR:
18295 check_nms(ctx);
18296 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18297 break;
18298 case NM_SEB:
18299 check_nms(ctx);
18300 gen_bshfl(ctx, OPC_SEB, rs, rt);
18301 break;
18302 case NM_SEH:
18303 gen_bshfl(ctx, OPC_SEH, rs, rt);
18304 break;
18305 case NM_SLLV:
18306 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18307 break;
18308 case NM_SRLV:
18309 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18310 break;
18311 case NM_SRAV:
18312 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18313 break;
18314 case NM_ROTRV:
18315 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18316 break;
18317 case NM_ADD:
18318 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18319 break;
18320 case NM_ADDU:
18321 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18322 break;
18323 case NM_SUB:
18324 check_nms(ctx);
18325 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18326 break;
18327 case NM_SUBU:
18328 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18329 break;
18330 case NM_P_CMOVE:
18331 switch (extract32(ctx->opcode, 10, 1)) {
18332 case NM_MOVZ:
18333 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18334 break;
18335 case NM_MOVN:
18336 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18337 break;
18339 break;
18340 case NM_AND:
18341 gen_logic(ctx, OPC_AND, rd, rs, rt);
18342 break;
18343 case NM_OR:
18344 gen_logic(ctx, OPC_OR, rd, rs, rt);
18345 break;
18346 case NM_NOR:
18347 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18348 break;
18349 case NM_XOR:
18350 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18351 break;
18352 case NM_SLT:
18353 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18354 break;
18355 case NM_P_SLTU:
18356 if (rd == 0) {
18357 /* P_DVP */
18358 #ifndef CONFIG_USER_ONLY
18359 TCGv t0 = tcg_temp_new();
18360 switch (extract32(ctx->opcode, 10, 1)) {
18361 case NM_DVP:
18362 if (ctx->vp) {
18363 check_cp0_enabled(ctx);
18364 gen_helper_dvp(t0, cpu_env);
18365 gen_store_gpr(t0, rt);
18367 break;
18368 case NM_EVP:
18369 if (ctx->vp) {
18370 check_cp0_enabled(ctx);
18371 gen_helper_evp(t0, cpu_env);
18372 gen_store_gpr(t0, rt);
18374 break;
18376 tcg_temp_free(t0);
18377 #endif
18378 } else {
18379 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18381 break;
18382 case NM_SOV:
18384 TCGv t0 = tcg_temp_new();
18385 TCGv t1 = tcg_temp_new();
18386 TCGv t2 = tcg_temp_new();
18388 gen_load_gpr(t1, rs);
18389 gen_load_gpr(t2, rt);
18390 tcg_gen_add_tl(t0, t1, t2);
18391 tcg_gen_ext32s_tl(t0, t0);
18392 tcg_gen_xor_tl(t1, t1, t2);
18393 tcg_gen_xor_tl(t2, t0, t2);
18394 tcg_gen_andc_tl(t1, t2, t1);
18396 /* operands of same sign, result different sign */
18397 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18398 gen_store_gpr(t0, rd);
18400 tcg_temp_free(t0);
18401 tcg_temp_free(t1);
18402 tcg_temp_free(t2);
18404 break;
18405 case NM_MUL:
18406 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18407 break;
18408 case NM_MUH:
18409 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18410 break;
18411 case NM_MULU:
18412 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18413 break;
18414 case NM_MUHU:
18415 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18416 break;
18417 case NM_DIV:
18418 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18419 break;
18420 case NM_MOD:
18421 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18422 break;
18423 case NM_DIVU:
18424 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18425 break;
18426 case NM_MODU:
18427 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18428 break;
18429 #ifndef CONFIG_USER_ONLY
18430 case NM_MFC0:
18431 check_cp0_enabled(ctx);
18432 if (rt == 0) {
18433 /* Treat as NOP. */
18434 break;
18436 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18437 break;
18438 case NM_MTC0:
18439 check_cp0_enabled(ctx);
18441 TCGv t0 = tcg_temp_new();
18443 gen_load_gpr(t0, rt);
18444 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18445 tcg_temp_free(t0);
18447 break;
18448 case NM_D_E_MT_VPE:
18450 uint8_t sc = extract32(ctx->opcode, 10, 1);
18451 TCGv t0 = tcg_temp_new();
18453 switch (sc) {
18454 case 0:
18455 if (rs == 1) {
18456 /* DMT */
18457 check_cp0_mt(ctx);
18458 gen_helper_dmt(t0);
18459 gen_store_gpr(t0, rt);
18460 } else if (rs == 0) {
18461 /* DVPE */
18462 check_cp0_mt(ctx);
18463 gen_helper_dvpe(t0, cpu_env);
18464 gen_store_gpr(t0, rt);
18465 } else {
18466 generate_exception_end(ctx, EXCP_RI);
18468 break;
18469 case 1:
18470 if (rs == 1) {
18471 /* EMT */
18472 check_cp0_mt(ctx);
18473 gen_helper_emt(t0);
18474 gen_store_gpr(t0, rt);
18475 } else if (rs == 0) {
18476 /* EVPE */
18477 check_cp0_mt(ctx);
18478 gen_helper_evpe(t0, cpu_env);
18479 gen_store_gpr(t0, rt);
18480 } else {
18481 generate_exception_end(ctx, EXCP_RI);
18483 break;
18486 tcg_temp_free(t0);
18488 break;
18489 case NM_FORK:
18490 check_mt(ctx);
18492 TCGv t0 = tcg_temp_new();
18493 TCGv t1 = tcg_temp_new();
18495 gen_load_gpr(t0, rt);
18496 gen_load_gpr(t1, rs);
18497 gen_helper_fork(t0, t1);
18498 tcg_temp_free(t0);
18499 tcg_temp_free(t1);
18501 break;
18502 case NM_MFTR:
18503 case NM_MFHTR:
18504 check_cp0_enabled(ctx);
18505 if (rd == 0) {
18506 /* Treat as NOP. */
18507 return;
18509 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18510 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18511 break;
18512 case NM_MTTR:
18513 case NM_MTHTR:
18514 check_cp0_enabled(ctx);
18515 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18516 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18517 break;
18518 case NM_YIELD:
18519 check_mt(ctx);
18521 TCGv t0 = tcg_temp_new();
18523 gen_load_gpr(t0, rs);
18524 gen_helper_yield(t0, cpu_env, t0);
18525 gen_store_gpr(t0, rt);
18526 tcg_temp_free(t0);
18528 break;
18529 #endif
18530 default:
18531 generate_exception_end(ctx, EXCP_RI);
18532 break;
18536 /* dsp */
18537 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18538 int ret, int v1, int v2)
18540 TCGv_i32 t0;
18541 TCGv v0_t;
18542 TCGv v1_t;
18544 t0 = tcg_temp_new_i32();
18546 v0_t = tcg_temp_new();
18547 v1_t = tcg_temp_new();
18549 tcg_gen_movi_i32(t0, v2 >> 3);
18551 gen_load_gpr(v0_t, ret);
18552 gen_load_gpr(v1_t, v1);
18554 switch (opc) {
18555 case NM_MAQ_S_W_PHR:
18556 check_dsp(ctx);
18557 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18558 break;
18559 case NM_MAQ_S_W_PHL:
18560 check_dsp(ctx);
18561 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18562 break;
18563 case NM_MAQ_SA_W_PHR:
18564 check_dsp(ctx);
18565 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18566 break;
18567 case NM_MAQ_SA_W_PHL:
18568 check_dsp(ctx);
18569 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18570 break;
18571 default:
18572 generate_exception_end(ctx, EXCP_RI);
18573 break;
18576 tcg_temp_free_i32(t0);
18578 tcg_temp_free(v0_t);
18579 tcg_temp_free(v1_t);
18583 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18584 int ret, int v1, int v2)
18586 int16_t imm;
18587 TCGv t0 = tcg_temp_new();
18588 TCGv t1 = tcg_temp_new();
18589 TCGv v0_t = tcg_temp_new();
18591 gen_load_gpr(v0_t, v1);
18593 switch (opc) {
18594 case NM_POOL32AXF_1_0:
18595 check_dsp(ctx);
18596 switch (extract32(ctx->opcode, 12, 2)) {
18597 case NM_MFHI:
18598 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18599 break;
18600 case NM_MFLO:
18601 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18602 break;
18603 case NM_MTHI:
18604 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18605 break;
18606 case NM_MTLO:
18607 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18608 break;
18610 break;
18611 case NM_POOL32AXF_1_1:
18612 check_dsp(ctx);
18613 switch (extract32(ctx->opcode, 12, 2)) {
18614 case NM_MTHLIP:
18615 tcg_gen_movi_tl(t0, v2);
18616 gen_helper_mthlip(t0, v0_t, cpu_env);
18617 break;
18618 case NM_SHILOV:
18619 tcg_gen_movi_tl(t0, v2 >> 3);
18620 gen_helper_shilo(t0, v0_t, cpu_env);
18621 break;
18622 default:
18623 generate_exception_end(ctx, EXCP_RI);
18624 break;
18626 break;
18627 case NM_POOL32AXF_1_3:
18628 check_dsp(ctx);
18629 imm = extract32(ctx->opcode, 14, 7);
18630 switch (extract32(ctx->opcode, 12, 2)) {
18631 case NM_RDDSP:
18632 tcg_gen_movi_tl(t0, imm);
18633 gen_helper_rddsp(t0, t0, cpu_env);
18634 gen_store_gpr(t0, ret);
18635 break;
18636 case NM_WRDSP:
18637 gen_load_gpr(t0, ret);
18638 tcg_gen_movi_tl(t1, imm);
18639 gen_helper_wrdsp(t0, t1, cpu_env);
18640 break;
18641 case NM_EXTP:
18642 tcg_gen_movi_tl(t0, v2 >> 3);
18643 tcg_gen_movi_tl(t1, v1);
18644 gen_helper_extp(t0, t0, t1, cpu_env);
18645 gen_store_gpr(t0, ret);
18646 break;
18647 case NM_EXTPDP:
18648 tcg_gen_movi_tl(t0, v2 >> 3);
18649 tcg_gen_movi_tl(t1, v1);
18650 gen_helper_extpdp(t0, t0, t1, cpu_env);
18651 gen_store_gpr(t0, ret);
18652 break;
18654 break;
18655 case NM_POOL32AXF_1_4:
18656 check_dsp(ctx);
18657 tcg_gen_movi_tl(t0, v2 >> 2);
18658 switch (extract32(ctx->opcode, 12, 1)) {
18659 case NM_SHLL_QB:
18660 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18661 gen_store_gpr(t0, ret);
18662 break;
18663 case NM_SHRL_QB:
18664 gen_helper_shrl_qb(t0, t0, v0_t);
18665 gen_store_gpr(t0, ret);
18666 break;
18668 break;
18669 case NM_POOL32AXF_1_5:
18670 opc = extract32(ctx->opcode, 12, 2);
18671 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18672 break;
18673 case NM_POOL32AXF_1_7:
18674 check_dsp(ctx);
18675 tcg_gen_movi_tl(t0, v2 >> 3);
18676 tcg_gen_movi_tl(t1, v1);
18677 switch (extract32(ctx->opcode, 12, 2)) {
18678 case NM_EXTR_W:
18679 gen_helper_extr_w(t0, t0, t1, cpu_env);
18680 gen_store_gpr(t0, ret);
18681 break;
18682 case NM_EXTR_R_W:
18683 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18684 gen_store_gpr(t0, ret);
18685 break;
18686 case NM_EXTR_RS_W:
18687 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18688 gen_store_gpr(t0, ret);
18689 break;
18690 case NM_EXTR_S_H:
18691 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18692 gen_store_gpr(t0, ret);
18693 break;
18695 break;
18696 default:
18697 generate_exception_end(ctx, EXCP_RI);
18698 break;
18701 tcg_temp_free(t0);
18702 tcg_temp_free(t1);
18703 tcg_temp_free(v0_t);
18706 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18707 TCGv v0, TCGv v1, int rd)
18709 TCGv_i32 t0;
18711 t0 = tcg_temp_new_i32();
18713 tcg_gen_movi_i32(t0, rd >> 3);
18715 switch (opc) {
18716 case NM_POOL32AXF_2_0_7:
18717 switch (extract32(ctx->opcode, 9, 3)) {
18718 case NM_DPA_W_PH:
18719 check_dsp_r2(ctx);
18720 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18721 break;
18722 case NM_DPAQ_S_W_PH:
18723 check_dsp(ctx);
18724 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18725 break;
18726 case NM_DPS_W_PH:
18727 check_dsp_r2(ctx);
18728 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18729 break;
18730 case NM_DPSQ_S_W_PH:
18731 check_dsp(ctx);
18732 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18733 break;
18734 default:
18735 generate_exception_end(ctx, EXCP_RI);
18736 break;
18738 break;
18739 case NM_POOL32AXF_2_8_15:
18740 switch (extract32(ctx->opcode, 9, 3)) {
18741 case NM_DPAX_W_PH:
18742 check_dsp_r2(ctx);
18743 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18744 break;
18745 case NM_DPAQ_SA_L_W:
18746 check_dsp(ctx);
18747 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18748 break;
18749 case NM_DPSX_W_PH:
18750 check_dsp_r2(ctx);
18751 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18752 break;
18753 case NM_DPSQ_SA_L_W:
18754 check_dsp(ctx);
18755 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18756 break;
18757 default:
18758 generate_exception_end(ctx, EXCP_RI);
18759 break;
18761 break;
18762 case NM_POOL32AXF_2_16_23:
18763 switch (extract32(ctx->opcode, 9, 3)) {
18764 case NM_DPAU_H_QBL:
18765 check_dsp(ctx);
18766 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18767 break;
18768 case NM_DPAQX_S_W_PH:
18769 check_dsp_r2(ctx);
18770 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18771 break;
18772 case NM_DPSU_H_QBL:
18773 check_dsp(ctx);
18774 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18775 break;
18776 case NM_DPSQX_S_W_PH:
18777 check_dsp_r2(ctx);
18778 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18779 break;
18780 case NM_MULSA_W_PH:
18781 check_dsp_r2(ctx);
18782 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18783 break;
18784 default:
18785 generate_exception_end(ctx, EXCP_RI);
18786 break;
18788 break;
18789 case NM_POOL32AXF_2_24_31:
18790 switch (extract32(ctx->opcode, 9, 3)) {
18791 case NM_DPAU_H_QBR:
18792 check_dsp(ctx);
18793 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18794 break;
18795 case NM_DPAQX_SA_W_PH:
18796 check_dsp_r2(ctx);
18797 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18798 break;
18799 case NM_DPSU_H_QBR:
18800 check_dsp(ctx);
18801 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18802 break;
18803 case NM_DPSQX_SA_W_PH:
18804 check_dsp_r2(ctx);
18805 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18806 break;
18807 case NM_MULSAQ_S_W_PH:
18808 check_dsp(ctx);
18809 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18810 break;
18811 default:
18812 generate_exception_end(ctx, EXCP_RI);
18813 break;
18815 break;
18816 default:
18817 generate_exception_end(ctx, EXCP_RI);
18818 break;
18821 tcg_temp_free_i32(t0);
18824 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18825 int rt, int rs, int rd)
18827 int ret = rt;
18828 TCGv t0 = tcg_temp_new();
18829 TCGv t1 = tcg_temp_new();
18830 TCGv v0_t = tcg_temp_new();
18831 TCGv v1_t = tcg_temp_new();
18833 gen_load_gpr(v0_t, rt);
18834 gen_load_gpr(v1_t, rs);
18836 switch (opc) {
18837 case NM_POOL32AXF_2_0_7:
18838 switch (extract32(ctx->opcode, 9, 3)) {
18839 case NM_DPA_W_PH:
18840 case NM_DPAQ_S_W_PH:
18841 case NM_DPS_W_PH:
18842 case NM_DPSQ_S_W_PH:
18843 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18844 break;
18845 case NM_BALIGN:
18846 check_dsp_r2(ctx);
18847 if (rt != 0) {
18848 gen_load_gpr(t0, rs);
18849 rd &= 3;
18850 if (rd != 0 && rd != 2) {
18851 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18852 tcg_gen_ext32u_tl(t0, t0);
18853 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18854 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18856 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18858 break;
18859 case NM_MADD:
18860 check_dsp(ctx);
18862 int acc = extract32(ctx->opcode, 14, 2);
18863 TCGv_i64 t2 = tcg_temp_new_i64();
18864 TCGv_i64 t3 = tcg_temp_new_i64();
18866 gen_load_gpr(t0, rt);
18867 gen_load_gpr(t1, rs);
18868 tcg_gen_ext_tl_i64(t2, t0);
18869 tcg_gen_ext_tl_i64(t3, t1);
18870 tcg_gen_mul_i64(t2, t2, t3);
18871 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18872 tcg_gen_add_i64(t2, t2, t3);
18873 tcg_temp_free_i64(t3);
18874 gen_move_low32(cpu_LO[acc], t2);
18875 gen_move_high32(cpu_HI[acc], t2);
18876 tcg_temp_free_i64(t2);
18878 break;
18879 case NM_MULT:
18880 check_dsp(ctx);
18882 int acc = extract32(ctx->opcode, 14, 2);
18883 TCGv_i32 t2 = tcg_temp_new_i32();
18884 TCGv_i32 t3 = tcg_temp_new_i32();
18886 gen_load_gpr(t0, rs);
18887 gen_load_gpr(t1, rt);
18888 tcg_gen_trunc_tl_i32(t2, t0);
18889 tcg_gen_trunc_tl_i32(t3, t1);
18890 tcg_gen_muls2_i32(t2, t3, t2, t3);
18891 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18892 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18893 tcg_temp_free_i32(t2);
18894 tcg_temp_free_i32(t3);
18896 break;
18897 case NM_EXTRV_W:
18898 check_dsp(ctx);
18899 gen_load_gpr(v1_t, rs);
18900 tcg_gen_movi_tl(t0, rd >> 3);
18901 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18902 gen_store_gpr(t0, ret);
18903 break;
18905 break;
18906 case NM_POOL32AXF_2_8_15:
18907 switch (extract32(ctx->opcode, 9, 3)) {
18908 case NM_DPAX_W_PH:
18909 case NM_DPAQ_SA_L_W:
18910 case NM_DPSX_W_PH:
18911 case NM_DPSQ_SA_L_W:
18912 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18913 break;
18914 case NM_MADDU:
18915 check_dsp(ctx);
18917 int acc = extract32(ctx->opcode, 14, 2);
18918 TCGv_i64 t2 = tcg_temp_new_i64();
18919 TCGv_i64 t3 = tcg_temp_new_i64();
18921 gen_load_gpr(t0, rs);
18922 gen_load_gpr(t1, rt);
18923 tcg_gen_ext32u_tl(t0, t0);
18924 tcg_gen_ext32u_tl(t1, t1);
18925 tcg_gen_extu_tl_i64(t2, t0);
18926 tcg_gen_extu_tl_i64(t3, t1);
18927 tcg_gen_mul_i64(t2, t2, t3);
18928 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18929 tcg_gen_add_i64(t2, t2, t3);
18930 tcg_temp_free_i64(t3);
18931 gen_move_low32(cpu_LO[acc], t2);
18932 gen_move_high32(cpu_HI[acc], t2);
18933 tcg_temp_free_i64(t2);
18935 break;
18936 case NM_MULTU:
18937 check_dsp(ctx);
18939 int acc = extract32(ctx->opcode, 14, 2);
18940 TCGv_i32 t2 = tcg_temp_new_i32();
18941 TCGv_i32 t3 = tcg_temp_new_i32();
18943 gen_load_gpr(t0, rs);
18944 gen_load_gpr(t1, rt);
18945 tcg_gen_trunc_tl_i32(t2, t0);
18946 tcg_gen_trunc_tl_i32(t3, t1);
18947 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18948 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18949 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18950 tcg_temp_free_i32(t2);
18951 tcg_temp_free_i32(t3);
18953 break;
18954 case NM_EXTRV_R_W:
18955 check_dsp(ctx);
18956 tcg_gen_movi_tl(t0, rd >> 3);
18957 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18958 gen_store_gpr(t0, ret);
18959 break;
18960 default:
18961 generate_exception_end(ctx, EXCP_RI);
18962 break;
18964 break;
18965 case NM_POOL32AXF_2_16_23:
18966 switch (extract32(ctx->opcode, 9, 3)) {
18967 case NM_DPAU_H_QBL:
18968 case NM_DPAQX_S_W_PH:
18969 case NM_DPSU_H_QBL:
18970 case NM_DPSQX_S_W_PH:
18971 case NM_MULSA_W_PH:
18972 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18973 break;
18974 case NM_EXTPV:
18975 check_dsp(ctx);
18976 tcg_gen_movi_tl(t0, rd >> 3);
18977 gen_helper_extp(t0, t0, v1_t, cpu_env);
18978 gen_store_gpr(t0, ret);
18979 break;
18980 case NM_MSUB:
18981 check_dsp(ctx);
18983 int acc = extract32(ctx->opcode, 14, 2);
18984 TCGv_i64 t2 = tcg_temp_new_i64();
18985 TCGv_i64 t3 = tcg_temp_new_i64();
18987 gen_load_gpr(t0, rs);
18988 gen_load_gpr(t1, rt);
18989 tcg_gen_ext_tl_i64(t2, t0);
18990 tcg_gen_ext_tl_i64(t3, t1);
18991 tcg_gen_mul_i64(t2, t2, t3);
18992 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18993 tcg_gen_sub_i64(t2, t3, t2);
18994 tcg_temp_free_i64(t3);
18995 gen_move_low32(cpu_LO[acc], t2);
18996 gen_move_high32(cpu_HI[acc], t2);
18997 tcg_temp_free_i64(t2);
18999 break;
19000 case NM_EXTRV_RS_W:
19001 check_dsp(ctx);
19002 tcg_gen_movi_tl(t0, rd >> 3);
19003 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19004 gen_store_gpr(t0, ret);
19005 break;
19007 break;
19008 case NM_POOL32AXF_2_24_31:
19009 switch (extract32(ctx->opcode, 9, 3)) {
19010 case NM_DPAU_H_QBR:
19011 case NM_DPAQX_SA_W_PH:
19012 case NM_DPSU_H_QBR:
19013 case NM_DPSQX_SA_W_PH:
19014 case NM_MULSAQ_S_W_PH:
19015 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19016 break;
19017 case NM_EXTPDPV:
19018 check_dsp(ctx);
19019 tcg_gen_movi_tl(t0, rd >> 3);
19020 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19021 gen_store_gpr(t0, ret);
19022 break;
19023 case NM_MSUBU:
19024 check_dsp(ctx);
19026 int acc = extract32(ctx->opcode, 14, 2);
19027 TCGv_i64 t2 = tcg_temp_new_i64();
19028 TCGv_i64 t3 = tcg_temp_new_i64();
19030 gen_load_gpr(t0, rs);
19031 gen_load_gpr(t1, rt);
19032 tcg_gen_ext32u_tl(t0, t0);
19033 tcg_gen_ext32u_tl(t1, t1);
19034 tcg_gen_extu_tl_i64(t2, t0);
19035 tcg_gen_extu_tl_i64(t3, t1);
19036 tcg_gen_mul_i64(t2, t2, t3);
19037 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19038 tcg_gen_sub_i64(t2, t3, t2);
19039 tcg_temp_free_i64(t3);
19040 gen_move_low32(cpu_LO[acc], t2);
19041 gen_move_high32(cpu_HI[acc], t2);
19042 tcg_temp_free_i64(t2);
19044 break;
19045 case NM_EXTRV_S_H:
19046 check_dsp(ctx);
19047 tcg_gen_movi_tl(t0, rd >> 3);
19048 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19049 gen_store_gpr(t0, ret);
19050 break;
19052 break;
19053 default:
19054 generate_exception_end(ctx, EXCP_RI);
19055 break;
19058 tcg_temp_free(t0);
19059 tcg_temp_free(t1);
19061 tcg_temp_free(v0_t);
19062 tcg_temp_free(v1_t);
19065 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19066 int rt, int rs)
19068 int ret = rt;
19069 TCGv t0 = tcg_temp_new();
19070 TCGv v0_t = tcg_temp_new();
19072 gen_load_gpr(v0_t, rs);
19074 switch (opc) {
19075 case NM_ABSQ_S_QB:
19076 check_dsp_r2(ctx);
19077 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19078 gen_store_gpr(v0_t, ret);
19079 break;
19080 case NM_ABSQ_S_PH:
19081 check_dsp(ctx);
19082 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19083 gen_store_gpr(v0_t, ret);
19084 break;
19085 case NM_ABSQ_S_W:
19086 check_dsp(ctx);
19087 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19088 gen_store_gpr(v0_t, ret);
19089 break;
19090 case NM_PRECEQ_W_PHL:
19091 check_dsp(ctx);
19092 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19093 tcg_gen_ext32s_tl(v0_t, v0_t);
19094 gen_store_gpr(v0_t, ret);
19095 break;
19096 case NM_PRECEQ_W_PHR:
19097 check_dsp(ctx);
19098 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19099 tcg_gen_shli_tl(v0_t, v0_t, 16);
19100 tcg_gen_ext32s_tl(v0_t, v0_t);
19101 gen_store_gpr(v0_t, ret);
19102 break;
19103 case NM_PRECEQU_PH_QBL:
19104 check_dsp(ctx);
19105 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19106 gen_store_gpr(v0_t, ret);
19107 break;
19108 case NM_PRECEQU_PH_QBR:
19109 check_dsp(ctx);
19110 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19111 gen_store_gpr(v0_t, ret);
19112 break;
19113 case NM_PRECEQU_PH_QBLA:
19114 check_dsp(ctx);
19115 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19116 gen_store_gpr(v0_t, ret);
19117 break;
19118 case NM_PRECEQU_PH_QBRA:
19119 check_dsp(ctx);
19120 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19121 gen_store_gpr(v0_t, ret);
19122 break;
19123 case NM_PRECEU_PH_QBL:
19124 check_dsp(ctx);
19125 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19126 gen_store_gpr(v0_t, ret);
19127 break;
19128 case NM_PRECEU_PH_QBR:
19129 check_dsp(ctx);
19130 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19131 gen_store_gpr(v0_t, ret);
19132 break;
19133 case NM_PRECEU_PH_QBLA:
19134 check_dsp(ctx);
19135 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19136 gen_store_gpr(v0_t, ret);
19137 break;
19138 case NM_PRECEU_PH_QBRA:
19139 check_dsp(ctx);
19140 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19141 gen_store_gpr(v0_t, ret);
19142 break;
19143 case NM_REPLV_PH:
19144 check_dsp(ctx);
19145 tcg_gen_ext16u_tl(v0_t, v0_t);
19146 tcg_gen_shli_tl(t0, v0_t, 16);
19147 tcg_gen_or_tl(v0_t, v0_t, t0);
19148 tcg_gen_ext32s_tl(v0_t, v0_t);
19149 gen_store_gpr(v0_t, ret);
19150 break;
19151 case NM_REPLV_QB:
19152 check_dsp(ctx);
19153 tcg_gen_ext8u_tl(v0_t, v0_t);
19154 tcg_gen_shli_tl(t0, v0_t, 8);
19155 tcg_gen_or_tl(v0_t, v0_t, t0);
19156 tcg_gen_shli_tl(t0, v0_t, 16);
19157 tcg_gen_or_tl(v0_t, v0_t, t0);
19158 tcg_gen_ext32s_tl(v0_t, v0_t);
19159 gen_store_gpr(v0_t, ret);
19160 break;
19161 case NM_BITREV:
19162 check_dsp(ctx);
19163 gen_helper_bitrev(v0_t, v0_t);
19164 gen_store_gpr(v0_t, ret);
19165 break;
19166 case NM_INSV:
19167 check_dsp(ctx);
19169 TCGv tv0 = tcg_temp_new();
19171 gen_load_gpr(tv0, rt);
19172 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19173 gen_store_gpr(v0_t, ret);
19174 tcg_temp_free(tv0);
19176 break;
19177 case NM_RADDU_W_QB:
19178 check_dsp(ctx);
19179 gen_helper_raddu_w_qb(v0_t, v0_t);
19180 gen_store_gpr(v0_t, ret);
19181 break;
19182 case NM_BITSWAP:
19183 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19184 break;
19185 case NM_CLO:
19186 check_nms(ctx);
19187 gen_cl(ctx, OPC_CLO, ret, rs);
19188 break;
19189 case NM_CLZ:
19190 check_nms(ctx);
19191 gen_cl(ctx, OPC_CLZ, ret, rs);
19192 break;
19193 case NM_WSBH:
19194 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19195 break;
19196 default:
19197 generate_exception_end(ctx, EXCP_RI);
19198 break;
19201 tcg_temp_free(v0_t);
19202 tcg_temp_free(t0);
19205 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19206 int rt, int rs, int rd)
19208 TCGv t0 = tcg_temp_new();
19209 TCGv rs_t = tcg_temp_new();
19211 gen_load_gpr(rs_t, rs);
19213 switch (opc) {
19214 case NM_SHRA_R_QB:
19215 check_dsp_r2(ctx);
19216 tcg_gen_movi_tl(t0, rd >> 2);
19217 switch (extract32(ctx->opcode, 12, 1)) {
19218 case 0:
19219 /* NM_SHRA_QB */
19220 gen_helper_shra_qb(t0, t0, rs_t);
19221 gen_store_gpr(t0, rt);
19222 break;
19223 case 1:
19224 /* NM_SHRA_R_QB */
19225 gen_helper_shra_r_qb(t0, t0, rs_t);
19226 gen_store_gpr(t0, rt);
19227 break;
19229 break;
19230 case NM_SHRL_PH:
19231 check_dsp_r2(ctx);
19232 tcg_gen_movi_tl(t0, rd >> 1);
19233 gen_helper_shrl_ph(t0, t0, rs_t);
19234 gen_store_gpr(t0, rt);
19235 break;
19236 case NM_REPL_QB:
19237 check_dsp(ctx);
19239 int16_t imm;
19240 target_long result;
19241 imm = extract32(ctx->opcode, 13, 8);
19242 result = (uint32_t)imm << 24 |
19243 (uint32_t)imm << 16 |
19244 (uint32_t)imm << 8 |
19245 (uint32_t)imm;
19246 result = (int32_t)result;
19247 tcg_gen_movi_tl(t0, result);
19248 gen_store_gpr(t0, rt);
19250 break;
19251 default:
19252 generate_exception_end(ctx, EXCP_RI);
19253 break;
19255 tcg_temp_free(t0);
19256 tcg_temp_free(rs_t);
19260 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19262 int rt = extract32(ctx->opcode, 21, 5);
19263 int rs = extract32(ctx->opcode, 16, 5);
19264 int rd = extract32(ctx->opcode, 11, 5);
19266 switch (extract32(ctx->opcode, 6, 3)) {
19267 case NM_POOL32AXF_1:
19269 int32_t op1 = extract32(ctx->opcode, 9, 3);
19270 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19272 break;
19273 case NM_POOL32AXF_2:
19275 int32_t op1 = extract32(ctx->opcode, 12, 2);
19276 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19278 break;
19279 case NM_POOL32AXF_4:
19281 int32_t op1 = extract32(ctx->opcode, 9, 7);
19282 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19284 break;
19285 case NM_POOL32AXF_5:
19286 switch (extract32(ctx->opcode, 9, 7)) {
19287 #ifndef CONFIG_USER_ONLY
19288 case NM_TLBP:
19289 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19290 break;
19291 case NM_TLBR:
19292 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19293 break;
19294 case NM_TLBWI:
19295 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19296 break;
19297 case NM_TLBWR:
19298 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19299 break;
19300 case NM_TLBINV:
19301 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19302 break;
19303 case NM_TLBINVF:
19304 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19305 break;
19306 case NM_DI:
19307 check_cp0_enabled(ctx);
19309 TCGv t0 = tcg_temp_new();
19311 save_cpu_state(ctx, 1);
19312 gen_helper_di(t0, cpu_env);
19313 gen_store_gpr(t0, rt);
19314 /* Stop translation as we may have switched the execution mode */
19315 ctx->base.is_jmp = DISAS_STOP;
19316 tcg_temp_free(t0);
19318 break;
19319 case NM_EI:
19320 check_cp0_enabled(ctx);
19322 TCGv t0 = tcg_temp_new();
19324 save_cpu_state(ctx, 1);
19325 gen_helper_ei(t0, cpu_env);
19326 gen_store_gpr(t0, rt);
19327 /* Stop translation as we may have switched the execution mode */
19328 ctx->base.is_jmp = DISAS_STOP;
19329 tcg_temp_free(t0);
19331 break;
19332 case NM_RDPGPR:
19333 gen_load_srsgpr(rs, rt);
19334 break;
19335 case NM_WRPGPR:
19336 gen_store_srsgpr(rs, rt);
19337 break;
19338 case NM_WAIT:
19339 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19340 break;
19341 case NM_DERET:
19342 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19343 break;
19344 case NM_ERETX:
19345 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19346 break;
19347 #endif
19348 default:
19349 generate_exception_end(ctx, EXCP_RI);
19350 break;
19352 break;
19353 case NM_POOL32AXF_7:
19355 int32_t op1 = extract32(ctx->opcode, 9, 3);
19356 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19358 break;
19359 default:
19360 generate_exception_end(ctx, EXCP_RI);
19361 break;
19365 /* Immediate Value Compact Branches */
19366 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19367 int rt, int32_t imm, int32_t offset)
19369 TCGCond cond;
19370 int bcond_compute = 0;
19371 TCGv t0 = tcg_temp_new();
19372 TCGv t1 = tcg_temp_new();
19374 gen_load_gpr(t0, rt);
19375 tcg_gen_movi_tl(t1, imm);
19376 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19378 /* Load needed operands and calculate btarget */
19379 switch (opc) {
19380 case NM_BEQIC:
19381 if (rt == 0 && imm == 0) {
19382 /* Unconditional branch */
19383 } else if (rt == 0 && imm != 0) {
19384 /* Treat as NOP */
19385 goto out;
19386 } else {
19387 bcond_compute = 1;
19388 cond = TCG_COND_EQ;
19390 break;
19391 case NM_BBEQZC:
19392 case NM_BBNEZC:
19393 check_nms(ctx);
19394 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19395 generate_exception_end(ctx, EXCP_RI);
19396 goto out;
19397 } else if (rt == 0 && opc == NM_BBEQZC) {
19398 /* Unconditional branch */
19399 } else if (rt == 0 && opc == NM_BBNEZC) {
19400 /* Treat as NOP */
19401 goto out;
19402 } else {
19403 tcg_gen_shri_tl(t0, t0, imm);
19404 tcg_gen_andi_tl(t0, t0, 1);
19405 tcg_gen_movi_tl(t1, 0);
19406 bcond_compute = 1;
19407 if (opc == NM_BBEQZC) {
19408 cond = TCG_COND_EQ;
19409 } else {
19410 cond = TCG_COND_NE;
19413 break;
19414 case NM_BNEIC:
19415 if (rt == 0 && imm == 0) {
19416 /* Treat as NOP */
19417 goto out;
19418 } else if (rt == 0 && imm != 0) {
19419 /* Unconditional branch */
19420 } else {
19421 bcond_compute = 1;
19422 cond = TCG_COND_NE;
19424 break;
19425 case NM_BGEIC:
19426 if (rt == 0 && imm == 0) {
19427 /* Unconditional branch */
19428 } else {
19429 bcond_compute = 1;
19430 cond = TCG_COND_GE;
19432 break;
19433 case NM_BLTIC:
19434 bcond_compute = 1;
19435 cond = TCG_COND_LT;
19436 break;
19437 case NM_BGEIUC:
19438 if (rt == 0 && imm == 0) {
19439 /* Unconditional branch */
19440 } else {
19441 bcond_compute = 1;
19442 cond = TCG_COND_GEU;
19444 break;
19445 case NM_BLTIUC:
19446 bcond_compute = 1;
19447 cond = TCG_COND_LTU;
19448 break;
19449 default:
19450 MIPS_INVAL("Immediate Value Compact branch");
19451 generate_exception_end(ctx, EXCP_RI);
19452 goto out;
19455 if (bcond_compute == 0) {
19456 /* Uncoditional compact branch */
19457 gen_goto_tb(ctx, 0, ctx->btarget);
19458 } else {
19459 /* Conditional compact branch */
19460 TCGLabel *fs = gen_new_label();
19462 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19464 gen_goto_tb(ctx, 1, ctx->btarget);
19465 gen_set_label(fs);
19467 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19470 out:
19471 tcg_temp_free(t0);
19472 tcg_temp_free(t1);
19475 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19476 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19477 int rt)
19479 TCGv t0 = tcg_temp_new();
19480 TCGv t1 = tcg_temp_new();
19482 /* load rs */
19483 gen_load_gpr(t0, rs);
19485 /* link */
19486 if (rt != 0) {
19487 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19490 /* calculate btarget */
19491 tcg_gen_shli_tl(t0, t0, 1);
19492 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19493 gen_op_addr_add(ctx, btarget, t1, t0);
19495 /* unconditional branch to register */
19496 tcg_gen_mov_tl(cpu_PC, btarget);
19497 tcg_gen_lookup_and_goto_ptr();
19499 tcg_temp_free(t0);
19500 tcg_temp_free(t1);
19503 /* nanoMIPS Branches */
19504 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19505 int rs, int rt, int32_t offset)
19507 int bcond_compute = 0;
19508 TCGv t0 = tcg_temp_new();
19509 TCGv t1 = tcg_temp_new();
19511 /* Load needed operands and calculate btarget */
19512 switch (opc) {
19513 /* compact branch */
19514 case OPC_BGEC:
19515 case OPC_BLTC:
19516 gen_load_gpr(t0, rs);
19517 gen_load_gpr(t1, rt);
19518 bcond_compute = 1;
19519 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19520 break;
19521 case OPC_BGEUC:
19522 case OPC_BLTUC:
19523 if (rs == 0 || rs == rt) {
19524 /* OPC_BLEZALC, OPC_BGEZALC */
19525 /* OPC_BGTZALC, OPC_BLTZALC */
19526 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19528 gen_load_gpr(t0, rs);
19529 gen_load_gpr(t1, rt);
19530 bcond_compute = 1;
19531 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19532 break;
19533 case OPC_BC:
19534 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19535 break;
19536 case OPC_BEQZC:
19537 if (rs != 0) {
19538 /* OPC_BEQZC, OPC_BNEZC */
19539 gen_load_gpr(t0, rs);
19540 bcond_compute = 1;
19541 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19542 } else {
19543 /* OPC_JIC, OPC_JIALC */
19544 TCGv tbase = tcg_temp_new();
19545 TCGv toffset = tcg_temp_new();
19547 gen_load_gpr(tbase, rt);
19548 tcg_gen_movi_tl(toffset, offset);
19549 gen_op_addr_add(ctx, btarget, tbase, toffset);
19550 tcg_temp_free(tbase);
19551 tcg_temp_free(toffset);
19553 break;
19554 default:
19555 MIPS_INVAL("Compact branch/jump");
19556 generate_exception_end(ctx, EXCP_RI);
19557 goto out;
19560 if (bcond_compute == 0) {
19561 /* Uncoditional compact branch */
19562 switch (opc) {
19563 case OPC_BC:
19564 gen_goto_tb(ctx, 0, ctx->btarget);
19565 break;
19566 default:
19567 MIPS_INVAL("Compact branch/jump");
19568 generate_exception_end(ctx, EXCP_RI);
19569 goto out;
19571 } else {
19572 /* Conditional compact branch */
19573 TCGLabel *fs = gen_new_label();
19575 switch (opc) {
19576 case OPC_BGEUC:
19577 if (rs == 0 && rt != 0) {
19578 /* OPC_BLEZALC */
19579 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19580 } else if (rs != 0 && rt != 0 && rs == rt) {
19581 /* OPC_BGEZALC */
19582 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19583 } else {
19584 /* OPC_BGEUC */
19585 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19587 break;
19588 case OPC_BLTUC:
19589 if (rs == 0 && rt != 0) {
19590 /* OPC_BGTZALC */
19591 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19592 } else if (rs != 0 && rt != 0 && rs == rt) {
19593 /* OPC_BLTZALC */
19594 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19595 } else {
19596 /* OPC_BLTUC */
19597 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19599 break;
19600 case OPC_BGEC:
19601 if (rs == 0 && rt != 0) {
19602 /* OPC_BLEZC */
19603 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19604 } else if (rs != 0 && rt != 0 && rs == rt) {
19605 /* OPC_BGEZC */
19606 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19607 } else {
19608 /* OPC_BGEC */
19609 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19611 break;
19612 case OPC_BLTC:
19613 if (rs == 0 && rt != 0) {
19614 /* OPC_BGTZC */
19615 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19616 } else if (rs != 0 && rt != 0 && rs == rt) {
19617 /* OPC_BLTZC */
19618 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19619 } else {
19620 /* OPC_BLTC */
19621 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19623 break;
19624 case OPC_BEQZC:
19625 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19626 break;
19627 default:
19628 MIPS_INVAL("Compact conditional branch/jump");
19629 generate_exception_end(ctx, EXCP_RI);
19630 goto out;
19633 /* Generating branch here as compact branches don't have delay slot */
19634 gen_goto_tb(ctx, 1, ctx->btarget);
19635 gen_set_label(fs);
19637 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19640 out:
19641 tcg_temp_free(t0);
19642 tcg_temp_free(t1);
19646 /* nanoMIPS CP1 Branches */
19647 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19648 int32_t ft, int32_t offset)
19650 target_ulong btarget;
19651 TCGv_i64 t0 = tcg_temp_new_i64();
19653 gen_load_fpr64(ctx, t0, ft);
19654 tcg_gen_andi_i64(t0, t0, 1);
19656 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19658 switch (op) {
19659 case NM_BC1EQZC:
19660 tcg_gen_xori_i64(t0, t0, 1);
19661 ctx->hflags |= MIPS_HFLAG_BC;
19662 break;
19663 case NM_BC1NEZC:
19664 /* t0 already set */
19665 ctx->hflags |= MIPS_HFLAG_BC;
19666 break;
19667 default:
19668 MIPS_INVAL("cp1 cond branch");
19669 generate_exception_end(ctx, EXCP_RI);
19670 goto out;
19673 tcg_gen_trunc_i64_tl(bcond, t0);
19675 ctx->btarget = btarget;
19677 out:
19678 tcg_temp_free_i64(t0);
19682 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19684 TCGv t0, t1;
19685 t0 = tcg_temp_new();
19686 t1 = tcg_temp_new();
19688 gen_load_gpr(t0, rs);
19689 gen_load_gpr(t1, rt);
19691 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19692 /* PP.LSXS instructions require shifting */
19693 switch (extract32(ctx->opcode, 7, 4)) {
19694 case NM_SHXS:
19695 check_nms(ctx);
19696 case NM_LHXS:
19697 case NM_LHUXS:
19698 tcg_gen_shli_tl(t0, t0, 1);
19699 break;
19700 case NM_SWXS:
19701 check_nms(ctx);
19702 case NM_LWXS:
19703 case NM_LWC1XS:
19704 case NM_SWC1XS:
19705 tcg_gen_shli_tl(t0, t0, 2);
19706 break;
19707 case NM_LDC1XS:
19708 case NM_SDC1XS:
19709 tcg_gen_shli_tl(t0, t0, 3);
19710 break;
19713 gen_op_addr_add(ctx, t0, t0, t1);
19715 switch (extract32(ctx->opcode, 7, 4)) {
19716 case NM_LBX:
19717 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19718 MO_SB);
19719 gen_store_gpr(t0, rd);
19720 break;
19721 case NM_LHX:
19722 /*case NM_LHXS:*/
19723 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19724 MO_TESW);
19725 gen_store_gpr(t0, rd);
19726 break;
19727 case NM_LWX:
19728 /*case NM_LWXS:*/
19729 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19730 MO_TESL);
19731 gen_store_gpr(t0, rd);
19732 break;
19733 case NM_LBUX:
19734 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19735 MO_UB);
19736 gen_store_gpr(t0, rd);
19737 break;
19738 case NM_LHUX:
19739 /*case NM_LHUXS:*/
19740 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19741 MO_TEUW);
19742 gen_store_gpr(t0, rd);
19743 break;
19744 case NM_SBX:
19745 check_nms(ctx);
19746 gen_load_gpr(t1, rd);
19747 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19748 MO_8);
19749 break;
19750 case NM_SHX:
19751 /*case NM_SHXS:*/
19752 check_nms(ctx);
19753 gen_load_gpr(t1, rd);
19754 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19755 MO_TEUW);
19756 break;
19757 case NM_SWX:
19758 /*case NM_SWXS:*/
19759 check_nms(ctx);
19760 gen_load_gpr(t1, rd);
19761 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19762 MO_TEUL);
19763 break;
19764 case NM_LWC1X:
19765 /*case NM_LWC1XS:*/
19766 case NM_LDC1X:
19767 /*case NM_LDC1XS:*/
19768 case NM_SWC1X:
19769 /*case NM_SWC1XS:*/
19770 case NM_SDC1X:
19771 /*case NM_SDC1XS:*/
19772 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19773 check_cp1_enabled(ctx);
19774 switch (extract32(ctx->opcode, 7, 4)) {
19775 case NM_LWC1X:
19776 /*case NM_LWC1XS:*/
19777 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19778 break;
19779 case NM_LDC1X:
19780 /*case NM_LDC1XS:*/
19781 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19782 break;
19783 case NM_SWC1X:
19784 /*case NM_SWC1XS:*/
19785 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19786 break;
19787 case NM_SDC1X:
19788 /*case NM_SDC1XS:*/
19789 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19790 break;
19792 } else {
19793 generate_exception_err(ctx, EXCP_CpU, 1);
19795 break;
19796 default:
19797 generate_exception_end(ctx, EXCP_RI);
19798 break;
19801 tcg_temp_free(t0);
19802 tcg_temp_free(t1);
19805 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19807 int rt, rs, rd;
19809 rt = extract32(ctx->opcode, 21, 5);
19810 rs = extract32(ctx->opcode, 16, 5);
19811 rd = extract32(ctx->opcode, 11, 5);
19813 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19814 generate_exception_end(ctx, EXCP_RI);
19815 return;
19817 check_cp1_enabled(ctx);
19818 switch (extract32(ctx->opcode, 0, 3)) {
19819 case NM_POOL32F_0:
19820 switch (extract32(ctx->opcode, 3, 7)) {
19821 case NM_RINT_S:
19822 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19823 break;
19824 case NM_RINT_D:
19825 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19826 break;
19827 case NM_CLASS_S:
19828 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19829 break;
19830 case NM_CLASS_D:
19831 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19832 break;
19833 case NM_ADD_S:
19834 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19835 break;
19836 case NM_ADD_D:
19837 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19838 break;
19839 case NM_SUB_S:
19840 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19841 break;
19842 case NM_SUB_D:
19843 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19844 break;
19845 case NM_MUL_S:
19846 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19847 break;
19848 case NM_MUL_D:
19849 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19850 break;
19851 case NM_DIV_S:
19852 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19853 break;
19854 case NM_DIV_D:
19855 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19856 break;
19857 case NM_SELEQZ_S:
19858 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19859 break;
19860 case NM_SELEQZ_D:
19861 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19862 break;
19863 case NM_SELNEZ_S:
19864 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19865 break;
19866 case NM_SELNEZ_D:
19867 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19868 break;
19869 case NM_SEL_S:
19870 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19871 break;
19872 case NM_SEL_D:
19873 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19874 break;
19875 case NM_MADDF_S:
19876 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19877 break;
19878 case NM_MADDF_D:
19879 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19880 break;
19881 case NM_MSUBF_S:
19882 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19883 break;
19884 case NM_MSUBF_D:
19885 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19886 break;
19887 default:
19888 generate_exception_end(ctx, EXCP_RI);
19889 break;
19891 break;
19892 case NM_POOL32F_3:
19893 switch (extract32(ctx->opcode, 3, 3)) {
19894 case NM_MIN_FMT:
19895 switch (extract32(ctx->opcode, 9, 1)) {
19896 case FMT_SDPS_S:
19897 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19898 break;
19899 case FMT_SDPS_D:
19900 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19901 break;
19903 break;
19904 case NM_MAX_FMT:
19905 switch (extract32(ctx->opcode, 9, 1)) {
19906 case FMT_SDPS_S:
19907 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19908 break;
19909 case FMT_SDPS_D:
19910 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19911 break;
19913 break;
19914 case NM_MINA_FMT:
19915 switch (extract32(ctx->opcode, 9, 1)) {
19916 case FMT_SDPS_S:
19917 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19918 break;
19919 case FMT_SDPS_D:
19920 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19921 break;
19923 break;
19924 case NM_MAXA_FMT:
19925 switch (extract32(ctx->opcode, 9, 1)) {
19926 case FMT_SDPS_S:
19927 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19928 break;
19929 case FMT_SDPS_D:
19930 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19931 break;
19933 break;
19934 case NM_POOL32FXF:
19935 switch (extract32(ctx->opcode, 6, 8)) {
19936 case NM_CFC1:
19937 gen_cp1(ctx, OPC_CFC1, rt, rs);
19938 break;
19939 case NM_CTC1:
19940 gen_cp1(ctx, OPC_CTC1, rt, rs);
19941 break;
19942 case NM_MFC1:
19943 gen_cp1(ctx, OPC_MFC1, rt, rs);
19944 break;
19945 case NM_MTC1:
19946 gen_cp1(ctx, OPC_MTC1, rt, rs);
19947 break;
19948 case NM_MFHC1:
19949 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19950 break;
19951 case NM_MTHC1:
19952 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19953 break;
19954 case NM_CVT_S_PL:
19955 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19956 break;
19957 case NM_CVT_S_PU:
19958 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19959 break;
19960 default:
19961 switch (extract32(ctx->opcode, 6, 9)) {
19962 case NM_CVT_L_S:
19963 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19964 break;
19965 case NM_CVT_L_D:
19966 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19967 break;
19968 case NM_CVT_W_S:
19969 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19970 break;
19971 case NM_CVT_W_D:
19972 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19973 break;
19974 case NM_RSQRT_S:
19975 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19976 break;
19977 case NM_RSQRT_D:
19978 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19979 break;
19980 case NM_SQRT_S:
19981 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19982 break;
19983 case NM_SQRT_D:
19984 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19985 break;
19986 case NM_RECIP_S:
19987 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19988 break;
19989 case NM_RECIP_D:
19990 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19991 break;
19992 case NM_FLOOR_L_S:
19993 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19994 break;
19995 case NM_FLOOR_L_D:
19996 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19997 break;
19998 case NM_FLOOR_W_S:
19999 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20000 break;
20001 case NM_FLOOR_W_D:
20002 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20003 break;
20004 case NM_CEIL_L_S:
20005 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20006 break;
20007 case NM_CEIL_L_D:
20008 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20009 break;
20010 case NM_CEIL_W_S:
20011 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20012 break;
20013 case NM_CEIL_W_D:
20014 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20015 break;
20016 case NM_TRUNC_L_S:
20017 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20018 break;
20019 case NM_TRUNC_L_D:
20020 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20021 break;
20022 case NM_TRUNC_W_S:
20023 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20024 break;
20025 case NM_TRUNC_W_D:
20026 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20027 break;
20028 case NM_ROUND_L_S:
20029 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20030 break;
20031 case NM_ROUND_L_D:
20032 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20033 break;
20034 case NM_ROUND_W_S:
20035 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20036 break;
20037 case NM_ROUND_W_D:
20038 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20039 break;
20040 case NM_MOV_S:
20041 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20042 break;
20043 case NM_MOV_D:
20044 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20045 break;
20046 case NM_ABS_S:
20047 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20048 break;
20049 case NM_ABS_D:
20050 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20051 break;
20052 case NM_NEG_S:
20053 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20054 break;
20055 case NM_NEG_D:
20056 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20057 break;
20058 case NM_CVT_D_S:
20059 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20060 break;
20061 case NM_CVT_D_W:
20062 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20063 break;
20064 case NM_CVT_D_L:
20065 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20066 break;
20067 case NM_CVT_S_D:
20068 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20069 break;
20070 case NM_CVT_S_W:
20071 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20072 break;
20073 case NM_CVT_S_L:
20074 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20075 break;
20076 default:
20077 generate_exception_end(ctx, EXCP_RI);
20078 break;
20080 break;
20082 break;
20084 break;
20085 case NM_POOL32F_5:
20086 switch (extract32(ctx->opcode, 3, 3)) {
20087 case NM_CMP_CONDN_S:
20088 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20089 break;
20090 case NM_CMP_CONDN_D:
20091 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20092 break;
20093 default:
20094 generate_exception_end(ctx, EXCP_RI);
20095 break;
20097 break;
20098 default:
20099 generate_exception_end(ctx, EXCP_RI);
20100 break;
20104 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20105 int rd, int rs, int rt)
20107 int ret = rd;
20108 TCGv t0 = tcg_temp_new();
20109 TCGv v1_t = tcg_temp_new();
20110 TCGv v2_t = tcg_temp_new();
20112 gen_load_gpr(v1_t, rs);
20113 gen_load_gpr(v2_t, rt);
20115 switch (opc) {
20116 case NM_CMP_EQ_PH:
20117 check_dsp(ctx);
20118 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20119 break;
20120 case NM_CMP_LT_PH:
20121 check_dsp(ctx);
20122 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20123 break;
20124 case NM_CMP_LE_PH:
20125 check_dsp(ctx);
20126 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20127 break;
20128 case NM_CMPU_EQ_QB:
20129 check_dsp(ctx);
20130 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20131 break;
20132 case NM_CMPU_LT_QB:
20133 check_dsp(ctx);
20134 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20135 break;
20136 case NM_CMPU_LE_QB:
20137 check_dsp(ctx);
20138 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20139 break;
20140 case NM_CMPGU_EQ_QB:
20141 check_dsp(ctx);
20142 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20143 gen_store_gpr(v1_t, ret);
20144 break;
20145 case NM_CMPGU_LT_QB:
20146 check_dsp(ctx);
20147 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20148 gen_store_gpr(v1_t, ret);
20149 break;
20150 case NM_CMPGU_LE_QB:
20151 check_dsp(ctx);
20152 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20153 gen_store_gpr(v1_t, ret);
20154 break;
20155 case NM_CMPGDU_EQ_QB:
20156 check_dsp_r2(ctx);
20157 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20158 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20159 gen_store_gpr(v1_t, ret);
20160 break;
20161 case NM_CMPGDU_LT_QB:
20162 check_dsp_r2(ctx);
20163 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20164 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20165 gen_store_gpr(v1_t, ret);
20166 break;
20167 case NM_CMPGDU_LE_QB:
20168 check_dsp_r2(ctx);
20169 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20170 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20171 gen_store_gpr(v1_t, ret);
20172 break;
20173 case NM_PACKRL_PH:
20174 check_dsp(ctx);
20175 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20176 gen_store_gpr(v1_t, ret);
20177 break;
20178 case NM_PICK_QB:
20179 check_dsp(ctx);
20180 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20181 gen_store_gpr(v1_t, ret);
20182 break;
20183 case NM_PICK_PH:
20184 check_dsp(ctx);
20185 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20186 gen_store_gpr(v1_t, ret);
20187 break;
20188 case NM_ADDQ_S_W:
20189 check_dsp(ctx);
20190 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20191 gen_store_gpr(v1_t, ret);
20192 break;
20193 case NM_SUBQ_S_W:
20194 check_dsp(ctx);
20195 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20196 gen_store_gpr(v1_t, ret);
20197 break;
20198 case NM_ADDSC:
20199 check_dsp(ctx);
20200 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20201 gen_store_gpr(v1_t, ret);
20202 break;
20203 case NM_ADDWC:
20204 check_dsp(ctx);
20205 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20206 gen_store_gpr(v1_t, ret);
20207 break;
20208 case NM_ADDQ_S_PH:
20209 check_dsp(ctx);
20210 switch (extract32(ctx->opcode, 10, 1)) {
20211 case 0:
20212 /* ADDQ_PH */
20213 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20214 gen_store_gpr(v1_t, ret);
20215 break;
20216 case 1:
20217 /* ADDQ_S_PH */
20218 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20219 gen_store_gpr(v1_t, ret);
20220 break;
20222 break;
20223 case NM_ADDQH_R_PH:
20224 check_dsp_r2(ctx);
20225 switch (extract32(ctx->opcode, 10, 1)) {
20226 case 0:
20227 /* ADDQH_PH */
20228 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20229 gen_store_gpr(v1_t, ret);
20230 break;
20231 case 1:
20232 /* ADDQH_R_PH */
20233 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20234 gen_store_gpr(v1_t, ret);
20235 break;
20237 break;
20238 case NM_ADDQH_R_W:
20239 check_dsp_r2(ctx);
20240 switch (extract32(ctx->opcode, 10, 1)) {
20241 case 0:
20242 /* ADDQH_W */
20243 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20244 gen_store_gpr(v1_t, ret);
20245 break;
20246 case 1:
20247 /* ADDQH_R_W */
20248 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20249 gen_store_gpr(v1_t, ret);
20250 break;
20252 break;
20253 case NM_ADDU_S_QB:
20254 check_dsp(ctx);
20255 switch (extract32(ctx->opcode, 10, 1)) {
20256 case 0:
20257 /* ADDU_QB */
20258 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20259 gen_store_gpr(v1_t, ret);
20260 break;
20261 case 1:
20262 /* ADDU_S_QB */
20263 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20264 gen_store_gpr(v1_t, ret);
20265 break;
20267 break;
20268 case NM_ADDU_S_PH:
20269 check_dsp_r2(ctx);
20270 switch (extract32(ctx->opcode, 10, 1)) {
20271 case 0:
20272 /* ADDU_PH */
20273 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20274 gen_store_gpr(v1_t, ret);
20275 break;
20276 case 1:
20277 /* ADDU_S_PH */
20278 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20279 gen_store_gpr(v1_t, ret);
20280 break;
20282 break;
20283 case NM_ADDUH_R_QB:
20284 check_dsp_r2(ctx);
20285 switch (extract32(ctx->opcode, 10, 1)) {
20286 case 0:
20287 /* ADDUH_QB */
20288 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20289 gen_store_gpr(v1_t, ret);
20290 break;
20291 case 1:
20292 /* ADDUH_R_QB */
20293 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20294 gen_store_gpr(v1_t, ret);
20295 break;
20297 break;
20298 case NM_SHRAV_R_PH:
20299 check_dsp(ctx);
20300 switch (extract32(ctx->opcode, 10, 1)) {
20301 case 0:
20302 /* SHRAV_PH */
20303 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20304 gen_store_gpr(v1_t, ret);
20305 break;
20306 case 1:
20307 /* SHRAV_R_PH */
20308 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20309 gen_store_gpr(v1_t, ret);
20310 break;
20312 break;
20313 case NM_SHRAV_R_QB:
20314 check_dsp_r2(ctx);
20315 switch (extract32(ctx->opcode, 10, 1)) {
20316 case 0:
20317 /* SHRAV_QB */
20318 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20319 gen_store_gpr(v1_t, ret);
20320 break;
20321 case 1:
20322 /* SHRAV_R_QB */
20323 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20324 gen_store_gpr(v1_t, ret);
20325 break;
20327 break;
20328 case NM_SUBQ_S_PH:
20329 check_dsp(ctx);
20330 switch (extract32(ctx->opcode, 10, 1)) {
20331 case 0:
20332 /* SUBQ_PH */
20333 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20334 gen_store_gpr(v1_t, ret);
20335 break;
20336 case 1:
20337 /* SUBQ_S_PH */
20338 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20339 gen_store_gpr(v1_t, ret);
20340 break;
20342 break;
20343 case NM_SUBQH_R_PH:
20344 check_dsp_r2(ctx);
20345 switch (extract32(ctx->opcode, 10, 1)) {
20346 case 0:
20347 /* SUBQH_PH */
20348 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20349 gen_store_gpr(v1_t, ret);
20350 break;
20351 case 1:
20352 /* SUBQH_R_PH */
20353 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20354 gen_store_gpr(v1_t, ret);
20355 break;
20357 break;
20358 case NM_SUBQH_R_W:
20359 check_dsp_r2(ctx);
20360 switch (extract32(ctx->opcode, 10, 1)) {
20361 case 0:
20362 /* SUBQH_W */
20363 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20364 gen_store_gpr(v1_t, ret);
20365 break;
20366 case 1:
20367 /* SUBQH_R_W */
20368 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20369 gen_store_gpr(v1_t, ret);
20370 break;
20372 break;
20373 case NM_SUBU_S_QB:
20374 check_dsp(ctx);
20375 switch (extract32(ctx->opcode, 10, 1)) {
20376 case 0:
20377 /* SUBU_QB */
20378 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20379 gen_store_gpr(v1_t, ret);
20380 break;
20381 case 1:
20382 /* SUBU_S_QB */
20383 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20384 gen_store_gpr(v1_t, ret);
20385 break;
20387 break;
20388 case NM_SUBU_S_PH:
20389 check_dsp_r2(ctx);
20390 switch (extract32(ctx->opcode, 10, 1)) {
20391 case 0:
20392 /* SUBU_PH */
20393 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20394 gen_store_gpr(v1_t, ret);
20395 break;
20396 case 1:
20397 /* SUBU_S_PH */
20398 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20399 gen_store_gpr(v1_t, ret);
20400 break;
20402 break;
20403 case NM_SUBUH_R_QB:
20404 check_dsp_r2(ctx);
20405 switch (extract32(ctx->opcode, 10, 1)) {
20406 case 0:
20407 /* SUBUH_QB */
20408 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20409 gen_store_gpr(v1_t, ret);
20410 break;
20411 case 1:
20412 /* SUBUH_R_QB */
20413 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20414 gen_store_gpr(v1_t, ret);
20415 break;
20417 break;
20418 case NM_SHLLV_S_PH:
20419 check_dsp(ctx);
20420 switch (extract32(ctx->opcode, 10, 1)) {
20421 case 0:
20422 /* SHLLV_PH */
20423 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20424 gen_store_gpr(v1_t, ret);
20425 break;
20426 case 1:
20427 /* SHLLV_S_PH */
20428 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20429 gen_store_gpr(v1_t, ret);
20430 break;
20432 break;
20433 case NM_PRECR_SRA_R_PH_W:
20434 check_dsp_r2(ctx);
20435 switch (extract32(ctx->opcode, 10, 1)) {
20436 case 0:
20437 /* PRECR_SRA_PH_W */
20439 TCGv_i32 sa_t = tcg_const_i32(rd);
20440 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20441 cpu_gpr[rt]);
20442 gen_store_gpr(v1_t, rt);
20443 tcg_temp_free_i32(sa_t);
20445 break;
20446 case 1:
20447 /* PRECR_SRA_R_PH_W */
20449 TCGv_i32 sa_t = tcg_const_i32(rd);
20450 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20451 cpu_gpr[rt]);
20452 gen_store_gpr(v1_t, rt);
20453 tcg_temp_free_i32(sa_t);
20455 break;
20457 break;
20458 case NM_MULEU_S_PH_QBL:
20459 check_dsp(ctx);
20460 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20461 gen_store_gpr(v1_t, ret);
20462 break;
20463 case NM_MULEU_S_PH_QBR:
20464 check_dsp(ctx);
20465 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20466 gen_store_gpr(v1_t, ret);
20467 break;
20468 case NM_MULQ_RS_PH:
20469 check_dsp(ctx);
20470 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20471 gen_store_gpr(v1_t, ret);
20472 break;
20473 case NM_MULQ_S_PH:
20474 check_dsp_r2(ctx);
20475 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20476 gen_store_gpr(v1_t, ret);
20477 break;
20478 case NM_MULQ_RS_W:
20479 check_dsp_r2(ctx);
20480 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20481 gen_store_gpr(v1_t, ret);
20482 break;
20483 case NM_MULQ_S_W:
20484 check_dsp_r2(ctx);
20485 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20486 gen_store_gpr(v1_t, ret);
20487 break;
20488 case NM_APPEND:
20489 check_dsp_r2(ctx);
20490 gen_load_gpr(t0, rs);
20491 if (rd != 0) {
20492 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20494 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20495 break;
20496 case NM_MODSUB:
20497 check_dsp(ctx);
20498 gen_helper_modsub(v1_t, v1_t, v2_t);
20499 gen_store_gpr(v1_t, ret);
20500 break;
20501 case NM_SHRAV_R_W:
20502 check_dsp(ctx);
20503 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20504 gen_store_gpr(v1_t, ret);
20505 break;
20506 case NM_SHRLV_PH:
20507 check_dsp_r2(ctx);
20508 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20509 gen_store_gpr(v1_t, ret);
20510 break;
20511 case NM_SHRLV_QB:
20512 check_dsp(ctx);
20513 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20514 gen_store_gpr(v1_t, ret);
20515 break;
20516 case NM_SHLLV_QB:
20517 check_dsp(ctx);
20518 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20519 gen_store_gpr(v1_t, ret);
20520 break;
20521 case NM_SHLLV_S_W:
20522 check_dsp(ctx);
20523 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20524 gen_store_gpr(v1_t, ret);
20525 break;
20526 case NM_SHILO:
20527 check_dsp(ctx);
20529 TCGv tv0 = tcg_temp_new();
20530 TCGv tv1 = tcg_temp_new();
20531 int16_t imm = extract32(ctx->opcode, 16, 7);
20533 tcg_gen_movi_tl(tv0, rd >> 3);
20534 tcg_gen_movi_tl(tv1, imm);
20535 gen_helper_shilo(tv0, tv1, cpu_env);
20537 break;
20538 case NM_MULEQ_S_W_PHL:
20539 check_dsp(ctx);
20540 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20541 gen_store_gpr(v1_t, ret);
20542 break;
20543 case NM_MULEQ_S_W_PHR:
20544 check_dsp(ctx);
20545 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20546 gen_store_gpr(v1_t, ret);
20547 break;
20548 case NM_MUL_S_PH:
20549 check_dsp_r2(ctx);
20550 switch (extract32(ctx->opcode, 10, 1)) {
20551 case 0:
20552 /* MUL_PH */
20553 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20554 gen_store_gpr(v1_t, ret);
20555 break;
20556 case 1:
20557 /* MUL_S_PH */
20558 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20559 gen_store_gpr(v1_t, ret);
20560 break;
20562 break;
20563 case NM_PRECR_QB_PH:
20564 check_dsp_r2(ctx);
20565 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20566 gen_store_gpr(v1_t, ret);
20567 break;
20568 case NM_PRECRQ_QB_PH:
20569 check_dsp(ctx);
20570 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20571 gen_store_gpr(v1_t, ret);
20572 break;
20573 case NM_PRECRQ_PH_W:
20574 check_dsp(ctx);
20575 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20576 gen_store_gpr(v1_t, ret);
20577 break;
20578 case NM_PRECRQ_RS_PH_W:
20579 check_dsp(ctx);
20580 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20581 gen_store_gpr(v1_t, ret);
20582 break;
20583 case NM_PRECRQU_S_QB_PH:
20584 check_dsp(ctx);
20585 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20586 gen_store_gpr(v1_t, ret);
20587 break;
20588 case NM_SHRA_R_W:
20589 check_dsp(ctx);
20590 tcg_gen_movi_tl(t0, rd);
20591 gen_helper_shra_r_w(v1_t, t0, v1_t);
20592 gen_store_gpr(v1_t, rt);
20593 break;
20594 case NM_SHRA_R_PH:
20595 check_dsp(ctx);
20596 tcg_gen_movi_tl(t0, rd >> 1);
20597 switch (extract32(ctx->opcode, 10, 1)) {
20598 case 0:
20599 /* SHRA_PH */
20600 gen_helper_shra_ph(v1_t, t0, v1_t);
20601 gen_store_gpr(v1_t, rt);
20602 break;
20603 case 1:
20604 /* SHRA_R_PH */
20605 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20606 gen_store_gpr(v1_t, rt);
20607 break;
20609 break;
20610 case NM_SHLL_S_PH:
20611 check_dsp(ctx);
20612 tcg_gen_movi_tl(t0, rd >> 1);
20613 switch (extract32(ctx->opcode, 10, 2)) {
20614 case 0:
20615 /* SHLL_PH */
20616 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20617 gen_store_gpr(v1_t, rt);
20618 break;
20619 case 2:
20620 /* SHLL_S_PH */
20621 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20622 gen_store_gpr(v1_t, rt);
20623 break;
20624 default:
20625 generate_exception_end(ctx, EXCP_RI);
20626 break;
20628 break;
20629 case NM_SHLL_S_W:
20630 check_dsp(ctx);
20631 tcg_gen_movi_tl(t0, rd);
20632 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20633 gen_store_gpr(v1_t, rt);
20634 break;
20635 case NM_REPL_PH:
20636 check_dsp(ctx);
20638 int16_t imm;
20639 imm = sextract32(ctx->opcode, 11, 11);
20640 imm = (int16_t)(imm << 6) >> 6;
20641 if (rt != 0) {
20642 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20645 break;
20646 default:
20647 generate_exception_end(ctx, EXCP_RI);
20648 break;
20652 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20654 uint16_t insn;
20655 uint32_t op;
20656 int rt, rs, rd;
20657 int offset;
20658 int imm;
20660 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20661 ctx->opcode = (ctx->opcode << 16) | insn;
20663 rt = extract32(ctx->opcode, 21, 5);
20664 rs = extract32(ctx->opcode, 16, 5);
20665 rd = extract32(ctx->opcode, 11, 5);
20667 op = extract32(ctx->opcode, 26, 6);
20668 switch (op) {
20669 case NM_P_ADDIU:
20670 if (rt == 0) {
20671 /* P.RI */
20672 switch (extract32(ctx->opcode, 19, 2)) {
20673 case NM_SIGRIE:
20674 default:
20675 generate_exception_end(ctx, EXCP_RI);
20676 break;
20677 case NM_P_SYSCALL:
20678 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20679 generate_exception_end(ctx, EXCP_SYSCALL);
20680 } else {
20681 generate_exception_end(ctx, EXCP_RI);
20683 break;
20684 case NM_BREAK:
20685 generate_exception_end(ctx, EXCP_BREAK);
20686 break;
20687 case NM_SDBBP:
20688 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20689 gen_helper_do_semihosting(cpu_env);
20690 } else {
20691 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20692 generate_exception_end(ctx, EXCP_RI);
20693 } else {
20694 generate_exception_end(ctx, EXCP_DBp);
20697 break;
20699 } else {
20700 /* NM_ADDIU */
20701 imm = extract32(ctx->opcode, 0, 16);
20702 if (rs != 0) {
20703 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20704 } else {
20705 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20707 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20709 break;
20710 case NM_ADDIUPC:
20711 if (rt != 0) {
20712 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20713 extract32(ctx->opcode, 1, 20) << 1;
20714 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20715 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20717 break;
20718 case NM_POOL32A:
20719 switch (ctx->opcode & 0x07) {
20720 case NM_POOL32A0:
20721 gen_pool32a0_nanomips_insn(env, ctx);
20722 break;
20723 case NM_POOL32A5:
20725 int32_t op1 = extract32(ctx->opcode, 3, 7);
20726 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20728 break;
20729 case NM_POOL32A7:
20730 switch (extract32(ctx->opcode, 3, 3)) {
20731 case NM_P_LSX:
20732 gen_p_lsx(ctx, rd, rs, rt);
20733 break;
20734 case NM_LSA:
20735 /* In nanoMIPS, the shift field directly encodes the shift
20736 * amount, meaning that the supported shift values are in
20737 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20738 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20739 extract32(ctx->opcode, 9, 2) - 1);
20740 break;
20741 case NM_EXTW:
20742 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20743 break;
20744 case NM_POOL32AXF:
20745 gen_pool32axf_nanomips_insn(env, ctx);
20746 break;
20747 default:
20748 generate_exception_end(ctx, EXCP_RI);
20749 break;
20751 break;
20752 default:
20753 generate_exception_end(ctx, EXCP_RI);
20754 break;
20756 break;
20757 case NM_P_GP_W:
20758 switch (ctx->opcode & 0x03) {
20759 case NM_ADDIUGP_W:
20760 if (rt != 0) {
20761 offset = extract32(ctx->opcode, 0, 21);
20762 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20764 break;
20765 case NM_LWGP:
20766 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20767 break;
20768 case NM_SWGP:
20769 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20770 break;
20771 default:
20772 generate_exception_end(ctx, EXCP_RI);
20773 break;
20775 break;
20776 case NM_P48I:
20778 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20779 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20780 switch (extract32(ctx->opcode, 16, 5)) {
20781 case NM_LI48:
20782 check_nms(ctx);
20783 if (rt != 0) {
20784 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20786 break;
20787 case NM_ADDIU48:
20788 check_nms(ctx);
20789 if (rt != 0) {
20790 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20791 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20793 break;
20794 case NM_ADDIUGP48:
20795 check_nms(ctx);
20796 if (rt != 0) {
20797 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20799 break;
20800 case NM_ADDIUPC48:
20801 check_nms(ctx);
20802 if (rt != 0) {
20803 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20804 addr_off);
20806 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20808 break;
20809 case NM_LWPC48:
20810 check_nms(ctx);
20811 if (rt != 0) {
20812 TCGv t0;
20813 t0 = tcg_temp_new();
20815 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20816 addr_off);
20818 tcg_gen_movi_tl(t0, addr);
20819 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20820 tcg_temp_free(t0);
20822 break;
20823 case NM_SWPC48:
20824 check_nms(ctx);
20826 TCGv t0, t1;
20827 t0 = tcg_temp_new();
20828 t1 = tcg_temp_new();
20830 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20831 addr_off);
20833 tcg_gen_movi_tl(t0, addr);
20834 gen_load_gpr(t1, rt);
20836 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20838 tcg_temp_free(t0);
20839 tcg_temp_free(t1);
20841 break;
20842 default:
20843 generate_exception_end(ctx, EXCP_RI);
20844 break;
20846 return 6;
20848 case NM_P_U12:
20849 switch (extract32(ctx->opcode, 12, 4)) {
20850 case NM_ORI:
20851 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20852 break;
20853 case NM_XORI:
20854 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20855 break;
20856 case NM_ANDI:
20857 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20858 break;
20859 case NM_P_SR:
20860 switch (extract32(ctx->opcode, 20, 1)) {
20861 case NM_PP_SR:
20862 switch (ctx->opcode & 3) {
20863 case NM_SAVE:
20864 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20865 extract32(ctx->opcode, 2, 1),
20866 extract32(ctx->opcode, 3, 9) << 3);
20867 break;
20868 case NM_RESTORE:
20869 case NM_RESTORE_JRC:
20870 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20871 extract32(ctx->opcode, 2, 1),
20872 extract32(ctx->opcode, 3, 9) << 3);
20873 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20874 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20876 break;
20877 default:
20878 generate_exception_end(ctx, EXCP_RI);
20879 break;
20881 break;
20882 case NM_P_SR_F:
20883 generate_exception_end(ctx, EXCP_RI);
20884 break;
20886 break;
20887 case NM_SLTI:
20888 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20889 break;
20890 case NM_SLTIU:
20891 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20892 break;
20893 case NM_SEQI:
20895 TCGv t0 = tcg_temp_new();
20897 imm = extract32(ctx->opcode, 0, 12);
20898 gen_load_gpr(t0, rs);
20899 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20900 gen_store_gpr(t0, rt);
20902 tcg_temp_free(t0);
20904 break;
20905 case NM_ADDIUNEG:
20906 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20907 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20908 break;
20909 case NM_P_SHIFT:
20911 int shift = extract32(ctx->opcode, 0, 5);
20912 switch (extract32(ctx->opcode, 5, 4)) {
20913 case NM_P_SLL:
20914 if (rt == 0 && shift == 0) {
20915 /* NOP */
20916 } else if (rt == 0 && shift == 3) {
20917 /* EHB - treat as NOP */
20918 } else if (rt == 0 && shift == 5) {
20919 /* PAUSE - treat as NOP */
20920 } else if (rt == 0 && shift == 6) {
20921 /* SYNC */
20922 gen_sync(extract32(ctx->opcode, 16, 5));
20923 } else {
20924 /* SLL */
20925 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20926 extract32(ctx->opcode, 0, 5));
20928 break;
20929 case NM_SRL:
20930 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20931 extract32(ctx->opcode, 0, 5));
20932 break;
20933 case NM_SRA:
20934 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20935 extract32(ctx->opcode, 0, 5));
20936 break;
20937 case NM_ROTR:
20938 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20939 extract32(ctx->opcode, 0, 5));
20940 break;
20943 break;
20944 case NM_P_ROTX:
20945 check_nms(ctx);
20946 if (rt != 0) {
20947 TCGv t0 = tcg_temp_new();
20948 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20949 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20950 << 1);
20951 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20953 gen_load_gpr(t0, rs);
20954 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20955 tcg_temp_free(t0);
20957 tcg_temp_free_i32(shift);
20958 tcg_temp_free_i32(shiftx);
20959 tcg_temp_free_i32(stripe);
20961 break;
20962 case NM_P_INS:
20963 switch (((ctx->opcode >> 10) & 2) |
20964 (extract32(ctx->opcode, 5, 1))) {
20965 case NM_INS:
20966 check_nms(ctx);
20967 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20968 extract32(ctx->opcode, 6, 5));
20969 break;
20970 default:
20971 generate_exception_end(ctx, EXCP_RI);
20972 break;
20974 break;
20975 case NM_P_EXT:
20976 switch (((ctx->opcode >> 10) & 2) |
20977 (extract32(ctx->opcode, 5, 1))) {
20978 case NM_EXT:
20979 check_nms(ctx);
20980 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20981 extract32(ctx->opcode, 6, 5));
20982 break;
20983 default:
20984 generate_exception_end(ctx, EXCP_RI);
20985 break;
20987 break;
20988 default:
20989 generate_exception_end(ctx, EXCP_RI);
20990 break;
20992 break;
20993 case NM_POOL32F:
20994 gen_pool32f_nanomips_insn(ctx);
20995 break;
20996 case NM_POOL32S:
20997 break;
20998 case NM_P_LUI:
20999 switch (extract32(ctx->opcode, 1, 1)) {
21000 case NM_LUI:
21001 if (rt != 0) {
21002 tcg_gen_movi_tl(cpu_gpr[rt],
21003 sextract32(ctx->opcode, 0, 1) << 31 |
21004 extract32(ctx->opcode, 2, 10) << 21 |
21005 extract32(ctx->opcode, 12, 9) << 12);
21007 break;
21008 case NM_ALUIPC:
21009 if (rt != 0) {
21010 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21011 extract32(ctx->opcode, 2, 10) << 21 |
21012 extract32(ctx->opcode, 12, 9) << 12;
21013 target_long addr;
21014 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21015 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21017 break;
21019 break;
21020 case NM_P_GP_BH:
21022 uint32_t u = extract32(ctx->opcode, 0, 18);
21024 switch (extract32(ctx->opcode, 18, 3)) {
21025 case NM_LBGP:
21026 gen_ld(ctx, OPC_LB, rt, 28, u);
21027 break;
21028 case NM_SBGP:
21029 gen_st(ctx, OPC_SB, rt, 28, u);
21030 break;
21031 case NM_LBUGP:
21032 gen_ld(ctx, OPC_LBU, rt, 28, u);
21033 break;
21034 case NM_ADDIUGP_B:
21035 if (rt != 0) {
21036 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21038 break;
21039 case NM_P_GP_LH:
21040 u &= ~1;
21041 switch (ctx->opcode & 1) {
21042 case NM_LHGP:
21043 gen_ld(ctx, OPC_LH, rt, 28, u);
21044 break;
21045 case NM_LHUGP:
21046 gen_ld(ctx, OPC_LHU, rt, 28, u);
21047 break;
21049 break;
21050 case NM_P_GP_SH:
21051 u &= ~1;
21052 switch (ctx->opcode & 1) {
21053 case NM_SHGP:
21054 gen_st(ctx, OPC_SH, rt, 28, u);
21055 break;
21056 default:
21057 generate_exception_end(ctx, EXCP_RI);
21058 break;
21060 break;
21061 case NM_P_GP_CP1:
21062 u &= ~0x3;
21063 switch (ctx->opcode & 0x3) {
21064 case NM_LWC1GP:
21065 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21066 break;
21067 case NM_LDC1GP:
21068 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21069 break;
21070 case NM_SWC1GP:
21071 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21072 break;
21073 case NM_SDC1GP:
21074 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21075 break;
21077 break;
21078 default:
21079 generate_exception_end(ctx, EXCP_RI);
21080 break;
21083 break;
21084 case NM_P_LS_U12:
21086 uint32_t u = extract32(ctx->opcode, 0, 12);
21088 switch (extract32(ctx->opcode, 12, 4)) {
21089 case NM_P_PREFU12:
21090 if (rt == 31) {
21091 /* SYNCI */
21092 /* Break the TB to be able to sync copied instructions
21093 immediately */
21094 ctx->base.is_jmp = DISAS_STOP;
21095 } else {
21096 /* PREF */
21097 /* Treat as NOP. */
21099 break;
21100 case NM_LB:
21101 gen_ld(ctx, OPC_LB, rt, rs, u);
21102 break;
21103 case NM_LH:
21104 gen_ld(ctx, OPC_LH, rt, rs, u);
21105 break;
21106 case NM_LW:
21107 gen_ld(ctx, OPC_LW, rt, rs, u);
21108 break;
21109 case NM_LBU:
21110 gen_ld(ctx, OPC_LBU, rt, rs, u);
21111 break;
21112 case NM_LHU:
21113 gen_ld(ctx, OPC_LHU, rt, rs, u);
21114 break;
21115 case NM_SB:
21116 gen_st(ctx, OPC_SB, rt, rs, u);
21117 break;
21118 case NM_SH:
21119 gen_st(ctx, OPC_SH, rt, rs, u);
21120 break;
21121 case NM_SW:
21122 gen_st(ctx, OPC_SW, rt, rs, u);
21123 break;
21124 case NM_LWC1:
21125 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21126 break;
21127 case NM_LDC1:
21128 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21129 break;
21130 case NM_SWC1:
21131 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21132 break;
21133 case NM_SDC1:
21134 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21135 break;
21136 default:
21137 generate_exception_end(ctx, EXCP_RI);
21138 break;
21141 break;
21142 case NM_P_LS_S9:
21144 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21145 extract32(ctx->opcode, 0, 8);
21147 switch (extract32(ctx->opcode, 8, 3)) {
21148 case NM_P_LS_S0:
21149 switch (extract32(ctx->opcode, 11, 4)) {
21150 case NM_LBS9:
21151 gen_ld(ctx, OPC_LB, rt, rs, s);
21152 break;
21153 case NM_LHS9:
21154 gen_ld(ctx, OPC_LH, rt, rs, s);
21155 break;
21156 case NM_LWS9:
21157 gen_ld(ctx, OPC_LW, rt, rs, s);
21158 break;
21159 case NM_LBUS9:
21160 gen_ld(ctx, OPC_LBU, rt, rs, s);
21161 break;
21162 case NM_LHUS9:
21163 gen_ld(ctx, OPC_LHU, rt, rs, s);
21164 break;
21165 case NM_SBS9:
21166 gen_st(ctx, OPC_SB, rt, rs, s);
21167 break;
21168 case NM_SHS9:
21169 gen_st(ctx, OPC_SH, rt, rs, s);
21170 break;
21171 case NM_SWS9:
21172 gen_st(ctx, OPC_SW, rt, rs, s);
21173 break;
21174 case NM_LWC1S9:
21175 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21176 break;
21177 case NM_LDC1S9:
21178 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21179 break;
21180 case NM_SWC1S9:
21181 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21182 break;
21183 case NM_SDC1S9:
21184 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21185 break;
21186 case NM_P_PREFS9:
21187 if (rt == 31) {
21188 /* SYNCI */
21189 /* Break the TB to be able to sync copied instructions
21190 immediately */
21191 ctx->base.is_jmp = DISAS_STOP;
21192 } else {
21193 /* PREF */
21194 /* Treat as NOP. */
21196 break;
21197 default:
21198 generate_exception_end(ctx, EXCP_RI);
21199 break;
21201 break;
21202 case NM_P_LS_S1:
21203 switch (extract32(ctx->opcode, 11, 4)) {
21204 case NM_UALH:
21205 case NM_UASH:
21206 check_nms(ctx);
21208 TCGv t0 = tcg_temp_new();
21209 TCGv t1 = tcg_temp_new();
21211 gen_base_offset_addr(ctx, t0, rs, s);
21213 switch (extract32(ctx->opcode, 11, 4)) {
21214 case NM_UALH:
21215 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21216 MO_UNALN);
21217 gen_store_gpr(t0, rt);
21218 break;
21219 case NM_UASH:
21220 gen_load_gpr(t1, rt);
21221 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21222 MO_UNALN);
21223 break;
21225 tcg_temp_free(t0);
21226 tcg_temp_free(t1);
21228 break;
21229 case NM_P_LL:
21230 switch (ctx->opcode & 0x03) {
21231 case NM_LL:
21232 gen_ld(ctx, OPC_LL, rt, rs, s);
21233 break;
21234 case NM_LLWP:
21235 check_xnp(ctx);
21236 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21237 break;
21239 break;
21240 case NM_P_SC:
21241 switch (ctx->opcode & 0x03) {
21242 case NM_SC:
21243 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21244 break;
21245 case NM_SCWP:
21246 check_xnp(ctx);
21247 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21248 break;
21250 break;
21251 case NM_CACHE:
21252 check_cp0_enabled(ctx);
21253 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21254 gen_cache_operation(ctx, rt, rs, s);
21256 break;
21258 break;
21259 case NM_P_LS_E0:
21260 switch (extract32(ctx->opcode, 11, 4)) {
21261 case NM_LBE:
21262 check_eva(ctx);
21263 check_cp0_enabled(ctx);
21264 gen_ld(ctx, OPC_LBE, rt, rs, s);
21265 break;
21266 case NM_SBE:
21267 check_eva(ctx);
21268 check_cp0_enabled(ctx);
21269 gen_st(ctx, OPC_SBE, rt, rs, s);
21270 break;
21271 case NM_LBUE:
21272 check_eva(ctx);
21273 check_cp0_enabled(ctx);
21274 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21275 break;
21276 case NM_P_PREFE:
21277 if (rt == 31) {
21278 /* case NM_SYNCIE */
21279 check_eva(ctx);
21280 check_cp0_enabled(ctx);
21281 /* Break the TB to be able to sync copied instructions
21282 immediately */
21283 ctx->base.is_jmp = DISAS_STOP;
21284 } else {
21285 /* case NM_PREFE */
21286 check_eva(ctx);
21287 check_cp0_enabled(ctx);
21288 /* Treat as NOP. */
21290 break;
21291 case NM_LHE:
21292 check_eva(ctx);
21293 check_cp0_enabled(ctx);
21294 gen_ld(ctx, OPC_LHE, rt, rs, s);
21295 break;
21296 case NM_SHE:
21297 check_eva(ctx);
21298 check_cp0_enabled(ctx);
21299 gen_st(ctx, OPC_SHE, rt, rs, s);
21300 break;
21301 case NM_LHUE:
21302 check_eva(ctx);
21303 check_cp0_enabled(ctx);
21304 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21305 break;
21306 case NM_CACHEE:
21307 check_nms_dl_il_sl_tl_l2c(ctx);
21308 gen_cache_operation(ctx, rt, rs, s);
21309 break;
21310 case NM_LWE:
21311 check_eva(ctx);
21312 check_cp0_enabled(ctx);
21313 gen_ld(ctx, OPC_LWE, rt, rs, s);
21314 break;
21315 case NM_SWE:
21316 check_eva(ctx);
21317 check_cp0_enabled(ctx);
21318 gen_st(ctx, OPC_SWE, rt, rs, s);
21319 break;
21320 case NM_P_LLE:
21321 switch (extract32(ctx->opcode, 2, 2)) {
21322 case NM_LLE:
21323 check_xnp(ctx);
21324 check_eva(ctx);
21325 check_cp0_enabled(ctx);
21326 gen_ld(ctx, OPC_LLE, rt, rs, s);
21327 break;
21328 case NM_LLWPE:
21329 check_xnp(ctx);
21330 check_eva(ctx);
21331 check_cp0_enabled(ctx);
21332 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21333 break;
21334 default:
21335 generate_exception_end(ctx, EXCP_RI);
21336 break;
21338 break;
21339 case NM_P_SCE:
21340 switch (extract32(ctx->opcode, 2, 2)) {
21341 case NM_SCE:
21342 check_xnp(ctx);
21343 check_eva(ctx);
21344 check_cp0_enabled(ctx);
21345 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21346 break;
21347 case NM_SCWPE:
21348 check_xnp(ctx);
21349 check_eva(ctx);
21350 check_cp0_enabled(ctx);
21351 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21352 break;
21353 default:
21354 generate_exception_end(ctx, EXCP_RI);
21355 break;
21357 break;
21359 break;
21360 case NM_P_LS_WM:
21361 case NM_P_LS_UAWM:
21362 check_nms(ctx);
21364 int count = extract32(ctx->opcode, 12, 3);
21365 int counter = 0;
21367 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21368 extract32(ctx->opcode, 0, 8);
21369 TCGv va = tcg_temp_new();
21370 TCGv t1 = tcg_temp_new();
21371 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21372 NM_P_LS_UAWM ? MO_UNALN : 0;
21374 count = (count == 0) ? 8 : count;
21375 while (counter != count) {
21376 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21377 int this_offset = offset + (counter << 2);
21379 gen_base_offset_addr(ctx, va, rs, this_offset);
21381 switch (extract32(ctx->opcode, 11, 1)) {
21382 case NM_LWM:
21383 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21384 memop | MO_TESL);
21385 gen_store_gpr(t1, this_rt);
21386 if ((this_rt == rs) &&
21387 (counter != (count - 1))) {
21388 /* UNPREDICTABLE */
21390 break;
21391 case NM_SWM:
21392 this_rt = (rt == 0) ? 0 : this_rt;
21393 gen_load_gpr(t1, this_rt);
21394 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21395 memop | MO_TEUL);
21396 break;
21398 counter++;
21400 tcg_temp_free(va);
21401 tcg_temp_free(t1);
21403 break;
21404 default:
21405 generate_exception_end(ctx, EXCP_RI);
21406 break;
21409 break;
21410 case NM_MOVE_BALC:
21411 check_nms(ctx);
21413 TCGv t0 = tcg_temp_new();
21414 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21415 extract32(ctx->opcode, 1, 20) << 1;
21416 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21417 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21418 extract32(ctx->opcode, 21, 3));
21419 gen_load_gpr(t0, rt);
21420 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21421 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21422 tcg_temp_free(t0);
21424 break;
21425 case NM_P_BAL:
21427 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21428 extract32(ctx->opcode, 1, 24) << 1;
21430 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21431 /* BC */
21432 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21433 } else {
21434 /* BALC */
21435 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21438 break;
21439 case NM_P_J:
21440 switch (extract32(ctx->opcode, 12, 4)) {
21441 case NM_JALRC:
21442 case NM_JALRC_HB:
21443 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21444 break;
21445 case NM_P_BALRSC:
21446 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21447 break;
21448 default:
21449 generate_exception_end(ctx, EXCP_RI);
21450 break;
21452 break;
21453 case NM_P_BR1:
21455 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21456 extract32(ctx->opcode, 1, 13) << 1;
21457 switch (extract32(ctx->opcode, 14, 2)) {
21458 case NM_BEQC:
21459 check_nms(ctx);
21460 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21461 break;
21462 case NM_P_BR3A:
21463 s = sextract32(ctx->opcode, 0, 1) << 14 |
21464 extract32(ctx->opcode, 1, 13) << 1;
21465 check_cp1_enabled(ctx);
21466 switch (extract32(ctx->opcode, 16, 5)) {
21467 case NM_BC1EQZC:
21468 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21469 break;
21470 case NM_BC1NEZC:
21471 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21472 break;
21473 case NM_BPOSGE32C:
21474 check_dsp_r3(ctx);
21476 int32_t imm = extract32(ctx->opcode, 1, 13) |
21477 extract32(ctx->opcode, 0, 1) << 13;
21479 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21480 imm);
21482 break;
21483 default:
21484 generate_exception_end(ctx, EXCP_RI);
21485 break;
21487 break;
21488 case NM_BGEC:
21489 if (rs == rt) {
21490 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21491 } else {
21492 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21494 break;
21495 case NM_BGEUC:
21496 if (rs == rt || rt == 0) {
21497 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21498 } else if (rs == 0) {
21499 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21500 } else {
21501 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21503 break;
21506 break;
21507 case NM_P_BR2:
21509 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21510 extract32(ctx->opcode, 1, 13) << 1;
21511 switch (extract32(ctx->opcode, 14, 2)) {
21512 case NM_BNEC:
21513 check_nms(ctx);
21514 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21515 break;
21516 case NM_BLTC:
21517 if (rs != 0 && rt != 0 && rs == rt) {
21518 /* NOP */
21519 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21520 } else {
21521 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21523 break;
21524 case NM_BLTUC:
21525 if (rs == 0 || rs == rt) {
21526 /* NOP */
21527 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21528 } else {
21529 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21531 break;
21532 default:
21533 generate_exception_end(ctx, EXCP_RI);
21534 break;
21537 break;
21538 case NM_P_BRI:
21540 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21541 extract32(ctx->opcode, 1, 10) << 1;
21542 uint32_t u = extract32(ctx->opcode, 11, 7);
21544 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21545 rt, u, s);
21547 break;
21548 default:
21549 generate_exception_end(ctx, EXCP_RI);
21550 break;
21552 return 4;
21555 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21557 uint32_t op;
21558 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21559 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21560 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21561 int offset;
21562 int imm;
21564 /* make sure instructions are on a halfword boundary */
21565 if (ctx->base.pc_next & 0x1) {
21566 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21567 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21568 tcg_temp_free(tmp);
21569 generate_exception_end(ctx, EXCP_AdEL);
21570 return 2;
21573 op = extract32(ctx->opcode, 10, 6);
21574 switch (op) {
21575 case NM_P16_MV:
21576 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21577 if (rt != 0) {
21578 /* MOVE */
21579 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21580 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21581 } else {
21582 /* P16.RI */
21583 switch (extract32(ctx->opcode, 3, 2)) {
21584 case NM_P16_SYSCALL:
21585 if (extract32(ctx->opcode, 2, 1) == 0) {
21586 generate_exception_end(ctx, EXCP_SYSCALL);
21587 } else {
21588 generate_exception_end(ctx, EXCP_RI);
21590 break;
21591 case NM_BREAK16:
21592 generate_exception_end(ctx, EXCP_BREAK);
21593 break;
21594 case NM_SDBBP16:
21595 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21596 gen_helper_do_semihosting(cpu_env);
21597 } else {
21598 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21599 generate_exception_end(ctx, EXCP_RI);
21600 } else {
21601 generate_exception_end(ctx, EXCP_DBp);
21604 break;
21605 default:
21606 generate_exception_end(ctx, EXCP_RI);
21607 break;
21610 break;
21611 case NM_P16_SHIFT:
21613 int shift = extract32(ctx->opcode, 0, 3);
21614 uint32_t opc = 0;
21615 shift = (shift == 0) ? 8 : shift;
21617 switch (extract32(ctx->opcode, 3, 1)) {
21618 case NM_SLL16:
21619 opc = OPC_SLL;
21620 break;
21621 case NM_SRL16:
21622 opc = OPC_SRL;
21623 break;
21625 gen_shift_imm(ctx, opc, rt, rs, shift);
21627 break;
21628 case NM_P16C:
21629 switch (ctx->opcode & 1) {
21630 case NM_POOL16C_0:
21631 gen_pool16c_nanomips_insn(ctx);
21632 break;
21633 case NM_LWXS16:
21634 gen_ldxs(ctx, rt, rs, rd);
21635 break;
21637 break;
21638 case NM_P16_A1:
21639 switch (extract32(ctx->opcode, 6, 1)) {
21640 case NM_ADDIUR1SP:
21641 imm = extract32(ctx->opcode, 0, 6) << 2;
21642 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21643 break;
21644 default:
21645 generate_exception_end(ctx, EXCP_RI);
21646 break;
21648 break;
21649 case NM_P16_A2:
21650 switch (extract32(ctx->opcode, 3, 1)) {
21651 case NM_ADDIUR2:
21652 imm = extract32(ctx->opcode, 0, 3) << 2;
21653 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21654 break;
21655 case NM_P_ADDIURS5:
21656 rt = extract32(ctx->opcode, 5, 5);
21657 if (rt != 0) {
21658 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21659 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21660 (extract32(ctx->opcode, 0, 3));
21661 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21663 break;
21665 break;
21666 case NM_P16_ADDU:
21667 switch (ctx->opcode & 0x1) {
21668 case NM_ADDU16:
21669 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21670 break;
21671 case NM_SUBU16:
21672 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21673 break;
21675 break;
21676 case NM_P16_4X4:
21677 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21678 extract32(ctx->opcode, 5, 3);
21679 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21680 extract32(ctx->opcode, 0, 3);
21681 rt = decode_gpr_gpr4(rt);
21682 rs = decode_gpr_gpr4(rs);
21683 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21684 (extract32(ctx->opcode, 3, 1))) {
21685 case NM_ADDU4X4:
21686 check_nms(ctx);
21687 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21688 break;
21689 case NM_MUL4X4:
21690 check_nms(ctx);
21691 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21692 break;
21693 default:
21694 generate_exception_end(ctx, EXCP_RI);
21695 break;
21697 break;
21698 case NM_LI16:
21700 int imm = extract32(ctx->opcode, 0, 7);
21701 imm = (imm == 0x7f ? -1 : imm);
21702 if (rt != 0) {
21703 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21706 break;
21707 case NM_ANDI16:
21709 uint32_t u = extract32(ctx->opcode, 0, 4);
21710 u = (u == 12) ? 0xff :
21711 (u == 13) ? 0xffff : u;
21712 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21714 break;
21715 case NM_P16_LB:
21716 offset = extract32(ctx->opcode, 0, 2);
21717 switch (extract32(ctx->opcode, 2, 2)) {
21718 case NM_LB16:
21719 gen_ld(ctx, OPC_LB, rt, rs, offset);
21720 break;
21721 case NM_SB16:
21722 rt = decode_gpr_gpr3_src_store(
21723 NANOMIPS_EXTRACT_RD(ctx->opcode));
21724 gen_st(ctx, OPC_SB, rt, rs, offset);
21725 break;
21726 case NM_LBU16:
21727 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21728 break;
21729 default:
21730 generate_exception_end(ctx, EXCP_RI);
21731 break;
21733 break;
21734 case NM_P16_LH:
21735 offset = extract32(ctx->opcode, 1, 2) << 1;
21736 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21737 case NM_LH16:
21738 gen_ld(ctx, OPC_LH, rt, rs, offset);
21739 break;
21740 case NM_SH16:
21741 rt = decode_gpr_gpr3_src_store(
21742 NANOMIPS_EXTRACT_RD(ctx->opcode));
21743 gen_st(ctx, OPC_SH, rt, rs, offset);
21744 break;
21745 case NM_LHU16:
21746 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21747 break;
21748 default:
21749 generate_exception_end(ctx, EXCP_RI);
21750 break;
21752 break;
21753 case NM_LW16:
21754 offset = extract32(ctx->opcode, 0, 4) << 2;
21755 gen_ld(ctx, OPC_LW, rt, rs, offset);
21756 break;
21757 case NM_LWSP16:
21758 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21759 offset = extract32(ctx->opcode, 0, 5) << 2;
21760 gen_ld(ctx, OPC_LW, rt, 29, offset);
21761 break;
21762 case NM_LW4X4:
21763 check_nms(ctx);
21764 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21765 extract32(ctx->opcode, 5, 3);
21766 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21767 extract32(ctx->opcode, 0, 3);
21768 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21769 (extract32(ctx->opcode, 8, 1) << 2);
21770 rt = decode_gpr_gpr4(rt);
21771 rs = decode_gpr_gpr4(rs);
21772 gen_ld(ctx, OPC_LW, rt, rs, offset);
21773 break;
21774 case NM_SW4X4:
21775 check_nms(ctx);
21776 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21777 extract32(ctx->opcode, 5, 3);
21778 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21779 extract32(ctx->opcode, 0, 3);
21780 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21781 (extract32(ctx->opcode, 8, 1) << 2);
21782 rt = decode_gpr_gpr4_zero(rt);
21783 rs = decode_gpr_gpr4(rs);
21784 gen_st(ctx, OPC_SW, rt, rs, offset);
21785 break;
21786 case NM_LWGP16:
21787 offset = extract32(ctx->opcode, 0, 7) << 2;
21788 gen_ld(ctx, OPC_LW, rt, 28, offset);
21789 break;
21790 case NM_SWSP16:
21791 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21792 offset = extract32(ctx->opcode, 0, 5) << 2;
21793 gen_st(ctx, OPC_SW, rt, 29, offset);
21794 break;
21795 case NM_SW16:
21796 rt = decode_gpr_gpr3_src_store(
21797 NANOMIPS_EXTRACT_RD(ctx->opcode));
21798 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21799 offset = extract32(ctx->opcode, 0, 4) << 2;
21800 gen_st(ctx, OPC_SW, rt, rs, offset);
21801 break;
21802 case NM_SWGP16:
21803 rt = decode_gpr_gpr3_src_store(
21804 NANOMIPS_EXTRACT_RD(ctx->opcode));
21805 offset = extract32(ctx->opcode, 0, 7) << 2;
21806 gen_st(ctx, OPC_SW, rt, 28, offset);
21807 break;
21808 case NM_BC16:
21809 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21810 (sextract32(ctx->opcode, 0, 1) << 10) |
21811 (extract32(ctx->opcode, 1, 9) << 1));
21812 break;
21813 case NM_BALC16:
21814 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21815 (sextract32(ctx->opcode, 0, 1) << 10) |
21816 (extract32(ctx->opcode, 1, 9) << 1));
21817 break;
21818 case NM_BEQZC16:
21819 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21820 (sextract32(ctx->opcode, 0, 1) << 7) |
21821 (extract32(ctx->opcode, 1, 6) << 1));
21822 break;
21823 case NM_BNEZC16:
21824 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21825 (sextract32(ctx->opcode, 0, 1) << 7) |
21826 (extract32(ctx->opcode, 1, 6) << 1));
21827 break;
21828 case NM_P16_BR:
21829 switch (ctx->opcode & 0xf) {
21830 case 0:
21831 /* P16.JRC */
21832 switch (extract32(ctx->opcode, 4, 1)) {
21833 case NM_JRC:
21834 gen_compute_branch_nm(ctx, OPC_JR, 2,
21835 extract32(ctx->opcode, 5, 5), 0, 0);
21836 break;
21837 case NM_JALRC16:
21838 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21839 extract32(ctx->opcode, 5, 5), 31, 0);
21840 break;
21842 break;
21843 default:
21845 /* P16.BRI */
21846 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21847 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21848 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21849 extract32(ctx->opcode, 0, 4) << 1);
21851 break;
21853 break;
21854 case NM_P16_SR:
21856 int count = extract32(ctx->opcode, 0, 4);
21857 int u = extract32(ctx->opcode, 4, 4) << 4;
21859 rt = 30 + extract32(ctx->opcode, 9, 1);
21860 switch (extract32(ctx->opcode, 8, 1)) {
21861 case NM_SAVE16:
21862 gen_save(ctx, rt, count, 0, u);
21863 break;
21864 case NM_RESTORE_JRC16:
21865 gen_restore(ctx, rt, count, 0, u);
21866 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21867 break;
21870 break;
21871 case NM_MOVEP:
21872 case NM_MOVEPREV:
21873 check_nms(ctx);
21875 static const int gpr2reg1[] = {4, 5, 6, 7};
21876 static const int gpr2reg2[] = {5, 6, 7, 8};
21877 int re;
21878 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21879 extract32(ctx->opcode, 8, 1);
21880 int r1 = gpr2reg1[rd2];
21881 int r2 = gpr2reg2[rd2];
21882 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21883 extract32(ctx->opcode, 0, 3);
21884 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21885 extract32(ctx->opcode, 5, 3);
21886 TCGv t0 = tcg_temp_new();
21887 TCGv t1 = tcg_temp_new();
21888 if (op == NM_MOVEP) {
21889 rd = r1;
21890 re = r2;
21891 rs = decode_gpr_gpr4_zero(r3);
21892 rt = decode_gpr_gpr4_zero(r4);
21893 } else {
21894 rd = decode_gpr_gpr4(r3);
21895 re = decode_gpr_gpr4(r4);
21896 rs = r1;
21897 rt = r2;
21899 gen_load_gpr(t0, rs);
21900 gen_load_gpr(t1, rt);
21901 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21902 tcg_gen_mov_tl(cpu_gpr[re], t1);
21903 tcg_temp_free(t0);
21904 tcg_temp_free(t1);
21906 break;
21907 default:
21908 return decode_nanomips_32_48_opc(env, ctx);
21911 return 2;
21915 /* SmartMIPS extension to MIPS32 */
21917 #if defined(TARGET_MIPS64)
21919 /* MDMX extension to MIPS64 */
21921 #endif
21923 /* MIPSDSP functions. */
21924 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21925 int rd, int base, int offset)
21927 TCGv t0;
21929 check_dsp(ctx);
21930 t0 = tcg_temp_new();
21932 if (base == 0) {
21933 gen_load_gpr(t0, offset);
21934 } else if (offset == 0) {
21935 gen_load_gpr(t0, base);
21936 } else {
21937 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21940 switch (opc) {
21941 case OPC_LBUX:
21942 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21943 gen_store_gpr(t0, rd);
21944 break;
21945 case OPC_LHX:
21946 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21947 gen_store_gpr(t0, rd);
21948 break;
21949 case OPC_LWX:
21950 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21951 gen_store_gpr(t0, rd);
21952 break;
21953 #if defined(TARGET_MIPS64)
21954 case OPC_LDX:
21955 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21956 gen_store_gpr(t0, rd);
21957 break;
21958 #endif
21960 tcg_temp_free(t0);
21963 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21964 int ret, int v1, int v2)
21966 TCGv v1_t;
21967 TCGv v2_t;
21969 if (ret == 0) {
21970 /* Treat as NOP. */
21971 return;
21974 v1_t = tcg_temp_new();
21975 v2_t = tcg_temp_new();
21977 gen_load_gpr(v1_t, v1);
21978 gen_load_gpr(v2_t, v2);
21980 switch (op1) {
21981 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21982 case OPC_MULT_G_2E:
21983 check_dsp_r2(ctx);
21984 switch (op2) {
21985 case OPC_ADDUH_QB:
21986 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21987 break;
21988 case OPC_ADDUH_R_QB:
21989 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21990 break;
21991 case OPC_ADDQH_PH:
21992 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21993 break;
21994 case OPC_ADDQH_R_PH:
21995 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21996 break;
21997 case OPC_ADDQH_W:
21998 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21999 break;
22000 case OPC_ADDQH_R_W:
22001 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22002 break;
22003 case OPC_SUBUH_QB:
22004 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22005 break;
22006 case OPC_SUBUH_R_QB:
22007 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22008 break;
22009 case OPC_SUBQH_PH:
22010 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22011 break;
22012 case OPC_SUBQH_R_PH:
22013 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22014 break;
22015 case OPC_SUBQH_W:
22016 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22017 break;
22018 case OPC_SUBQH_R_W:
22019 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22020 break;
22022 break;
22023 case OPC_ABSQ_S_PH_DSP:
22024 switch (op2) {
22025 case OPC_ABSQ_S_QB:
22026 check_dsp_r2(ctx);
22027 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22028 break;
22029 case OPC_ABSQ_S_PH:
22030 check_dsp(ctx);
22031 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22032 break;
22033 case OPC_ABSQ_S_W:
22034 check_dsp(ctx);
22035 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22036 break;
22037 case OPC_PRECEQ_W_PHL:
22038 check_dsp(ctx);
22039 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22040 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22041 break;
22042 case OPC_PRECEQ_W_PHR:
22043 check_dsp(ctx);
22044 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22045 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22046 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22047 break;
22048 case OPC_PRECEQU_PH_QBL:
22049 check_dsp(ctx);
22050 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22051 break;
22052 case OPC_PRECEQU_PH_QBR:
22053 check_dsp(ctx);
22054 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22055 break;
22056 case OPC_PRECEQU_PH_QBLA:
22057 check_dsp(ctx);
22058 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22059 break;
22060 case OPC_PRECEQU_PH_QBRA:
22061 check_dsp(ctx);
22062 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22063 break;
22064 case OPC_PRECEU_PH_QBL:
22065 check_dsp(ctx);
22066 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22067 break;
22068 case OPC_PRECEU_PH_QBR:
22069 check_dsp(ctx);
22070 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22071 break;
22072 case OPC_PRECEU_PH_QBLA:
22073 check_dsp(ctx);
22074 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22075 break;
22076 case OPC_PRECEU_PH_QBRA:
22077 check_dsp(ctx);
22078 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22079 break;
22081 break;
22082 case OPC_ADDU_QB_DSP:
22083 switch (op2) {
22084 case OPC_ADDQ_PH:
22085 check_dsp(ctx);
22086 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22087 break;
22088 case OPC_ADDQ_S_PH:
22089 check_dsp(ctx);
22090 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22091 break;
22092 case OPC_ADDQ_S_W:
22093 check_dsp(ctx);
22094 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22095 break;
22096 case OPC_ADDU_QB:
22097 check_dsp(ctx);
22098 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22099 break;
22100 case OPC_ADDU_S_QB:
22101 check_dsp(ctx);
22102 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22103 break;
22104 case OPC_ADDU_PH:
22105 check_dsp_r2(ctx);
22106 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22107 break;
22108 case OPC_ADDU_S_PH:
22109 check_dsp_r2(ctx);
22110 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22111 break;
22112 case OPC_SUBQ_PH:
22113 check_dsp(ctx);
22114 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22115 break;
22116 case OPC_SUBQ_S_PH:
22117 check_dsp(ctx);
22118 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22119 break;
22120 case OPC_SUBQ_S_W:
22121 check_dsp(ctx);
22122 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22123 break;
22124 case OPC_SUBU_QB:
22125 check_dsp(ctx);
22126 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22127 break;
22128 case OPC_SUBU_S_QB:
22129 check_dsp(ctx);
22130 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22131 break;
22132 case OPC_SUBU_PH:
22133 check_dsp_r2(ctx);
22134 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22135 break;
22136 case OPC_SUBU_S_PH:
22137 check_dsp_r2(ctx);
22138 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22139 break;
22140 case OPC_ADDSC:
22141 check_dsp(ctx);
22142 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22143 break;
22144 case OPC_ADDWC:
22145 check_dsp(ctx);
22146 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22147 break;
22148 case OPC_MODSUB:
22149 check_dsp(ctx);
22150 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22151 break;
22152 case OPC_RADDU_W_QB:
22153 check_dsp(ctx);
22154 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22155 break;
22157 break;
22158 case OPC_CMPU_EQ_QB_DSP:
22159 switch (op2) {
22160 case OPC_PRECR_QB_PH:
22161 check_dsp_r2(ctx);
22162 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22163 break;
22164 case OPC_PRECRQ_QB_PH:
22165 check_dsp(ctx);
22166 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22167 break;
22168 case OPC_PRECR_SRA_PH_W:
22169 check_dsp_r2(ctx);
22171 TCGv_i32 sa_t = tcg_const_i32(v2);
22172 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22173 cpu_gpr[ret]);
22174 tcg_temp_free_i32(sa_t);
22175 break;
22177 case OPC_PRECR_SRA_R_PH_W:
22178 check_dsp_r2(ctx);
22180 TCGv_i32 sa_t = tcg_const_i32(v2);
22181 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22182 cpu_gpr[ret]);
22183 tcg_temp_free_i32(sa_t);
22184 break;
22186 case OPC_PRECRQ_PH_W:
22187 check_dsp(ctx);
22188 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22189 break;
22190 case OPC_PRECRQ_RS_PH_W:
22191 check_dsp(ctx);
22192 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22193 break;
22194 case OPC_PRECRQU_S_QB_PH:
22195 check_dsp(ctx);
22196 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22197 break;
22199 break;
22200 #ifdef TARGET_MIPS64
22201 case OPC_ABSQ_S_QH_DSP:
22202 switch (op2) {
22203 case OPC_PRECEQ_L_PWL:
22204 check_dsp(ctx);
22205 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22206 break;
22207 case OPC_PRECEQ_L_PWR:
22208 check_dsp(ctx);
22209 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22210 break;
22211 case OPC_PRECEQ_PW_QHL:
22212 check_dsp(ctx);
22213 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22214 break;
22215 case OPC_PRECEQ_PW_QHR:
22216 check_dsp(ctx);
22217 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22218 break;
22219 case OPC_PRECEQ_PW_QHLA:
22220 check_dsp(ctx);
22221 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22222 break;
22223 case OPC_PRECEQ_PW_QHRA:
22224 check_dsp(ctx);
22225 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22226 break;
22227 case OPC_PRECEQU_QH_OBL:
22228 check_dsp(ctx);
22229 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22230 break;
22231 case OPC_PRECEQU_QH_OBR:
22232 check_dsp(ctx);
22233 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22234 break;
22235 case OPC_PRECEQU_QH_OBLA:
22236 check_dsp(ctx);
22237 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22238 break;
22239 case OPC_PRECEQU_QH_OBRA:
22240 check_dsp(ctx);
22241 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22242 break;
22243 case OPC_PRECEU_QH_OBL:
22244 check_dsp(ctx);
22245 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22246 break;
22247 case OPC_PRECEU_QH_OBR:
22248 check_dsp(ctx);
22249 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22250 break;
22251 case OPC_PRECEU_QH_OBLA:
22252 check_dsp(ctx);
22253 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22254 break;
22255 case OPC_PRECEU_QH_OBRA:
22256 check_dsp(ctx);
22257 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22258 break;
22259 case OPC_ABSQ_S_OB:
22260 check_dsp_r2(ctx);
22261 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22262 break;
22263 case OPC_ABSQ_S_PW:
22264 check_dsp(ctx);
22265 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22266 break;
22267 case OPC_ABSQ_S_QH:
22268 check_dsp(ctx);
22269 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22270 break;
22272 break;
22273 case OPC_ADDU_OB_DSP:
22274 switch (op2) {
22275 case OPC_RADDU_L_OB:
22276 check_dsp(ctx);
22277 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22278 break;
22279 case OPC_SUBQ_PW:
22280 check_dsp(ctx);
22281 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22282 break;
22283 case OPC_SUBQ_S_PW:
22284 check_dsp(ctx);
22285 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22286 break;
22287 case OPC_SUBQ_QH:
22288 check_dsp(ctx);
22289 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22290 break;
22291 case OPC_SUBQ_S_QH:
22292 check_dsp(ctx);
22293 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22294 break;
22295 case OPC_SUBU_OB:
22296 check_dsp(ctx);
22297 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22298 break;
22299 case OPC_SUBU_S_OB:
22300 check_dsp(ctx);
22301 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22302 break;
22303 case OPC_SUBU_QH:
22304 check_dsp_r2(ctx);
22305 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22306 break;
22307 case OPC_SUBU_S_QH:
22308 check_dsp_r2(ctx);
22309 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22310 break;
22311 case OPC_SUBUH_OB:
22312 check_dsp_r2(ctx);
22313 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22314 break;
22315 case OPC_SUBUH_R_OB:
22316 check_dsp_r2(ctx);
22317 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22318 break;
22319 case OPC_ADDQ_PW:
22320 check_dsp(ctx);
22321 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22322 break;
22323 case OPC_ADDQ_S_PW:
22324 check_dsp(ctx);
22325 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22326 break;
22327 case OPC_ADDQ_QH:
22328 check_dsp(ctx);
22329 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22330 break;
22331 case OPC_ADDQ_S_QH:
22332 check_dsp(ctx);
22333 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22334 break;
22335 case OPC_ADDU_OB:
22336 check_dsp(ctx);
22337 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22338 break;
22339 case OPC_ADDU_S_OB:
22340 check_dsp(ctx);
22341 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22342 break;
22343 case OPC_ADDU_QH:
22344 check_dsp_r2(ctx);
22345 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22346 break;
22347 case OPC_ADDU_S_QH:
22348 check_dsp_r2(ctx);
22349 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22350 break;
22351 case OPC_ADDUH_OB:
22352 check_dsp_r2(ctx);
22353 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22354 break;
22355 case OPC_ADDUH_R_OB:
22356 check_dsp_r2(ctx);
22357 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22358 break;
22360 break;
22361 case OPC_CMPU_EQ_OB_DSP:
22362 switch (op2) {
22363 case OPC_PRECR_OB_QH:
22364 check_dsp_r2(ctx);
22365 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22366 break;
22367 case OPC_PRECR_SRA_QH_PW:
22368 check_dsp_r2(ctx);
22370 TCGv_i32 ret_t = tcg_const_i32(ret);
22371 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22372 tcg_temp_free_i32(ret_t);
22373 break;
22375 case OPC_PRECR_SRA_R_QH_PW:
22376 check_dsp_r2(ctx);
22378 TCGv_i32 sa_v = tcg_const_i32(ret);
22379 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22380 tcg_temp_free_i32(sa_v);
22381 break;
22383 case OPC_PRECRQ_OB_QH:
22384 check_dsp(ctx);
22385 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22386 break;
22387 case OPC_PRECRQ_PW_L:
22388 check_dsp(ctx);
22389 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22390 break;
22391 case OPC_PRECRQ_QH_PW:
22392 check_dsp(ctx);
22393 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22394 break;
22395 case OPC_PRECRQ_RS_QH_PW:
22396 check_dsp(ctx);
22397 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22398 break;
22399 case OPC_PRECRQU_S_OB_QH:
22400 check_dsp(ctx);
22401 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22402 break;
22404 break;
22405 #endif
22408 tcg_temp_free(v1_t);
22409 tcg_temp_free(v2_t);
22412 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22413 int ret, int v1, int v2)
22415 uint32_t op2;
22416 TCGv t0;
22417 TCGv v1_t;
22418 TCGv v2_t;
22420 if (ret == 0) {
22421 /* Treat as NOP. */
22422 return;
22425 t0 = tcg_temp_new();
22426 v1_t = tcg_temp_new();
22427 v2_t = tcg_temp_new();
22429 tcg_gen_movi_tl(t0, v1);
22430 gen_load_gpr(v1_t, v1);
22431 gen_load_gpr(v2_t, v2);
22433 switch (opc) {
22434 case OPC_SHLL_QB_DSP:
22436 op2 = MASK_SHLL_QB(ctx->opcode);
22437 switch (op2) {
22438 case OPC_SHLL_QB:
22439 check_dsp(ctx);
22440 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22441 break;
22442 case OPC_SHLLV_QB:
22443 check_dsp(ctx);
22444 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22445 break;
22446 case OPC_SHLL_PH:
22447 check_dsp(ctx);
22448 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22449 break;
22450 case OPC_SHLLV_PH:
22451 check_dsp(ctx);
22452 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22453 break;
22454 case OPC_SHLL_S_PH:
22455 check_dsp(ctx);
22456 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22457 break;
22458 case OPC_SHLLV_S_PH:
22459 check_dsp(ctx);
22460 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22461 break;
22462 case OPC_SHLL_S_W:
22463 check_dsp(ctx);
22464 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22465 break;
22466 case OPC_SHLLV_S_W:
22467 check_dsp(ctx);
22468 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22469 break;
22470 case OPC_SHRL_QB:
22471 check_dsp(ctx);
22472 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22473 break;
22474 case OPC_SHRLV_QB:
22475 check_dsp(ctx);
22476 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22477 break;
22478 case OPC_SHRL_PH:
22479 check_dsp_r2(ctx);
22480 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22481 break;
22482 case OPC_SHRLV_PH:
22483 check_dsp_r2(ctx);
22484 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22485 break;
22486 case OPC_SHRA_QB:
22487 check_dsp_r2(ctx);
22488 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22489 break;
22490 case OPC_SHRA_R_QB:
22491 check_dsp_r2(ctx);
22492 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22493 break;
22494 case OPC_SHRAV_QB:
22495 check_dsp_r2(ctx);
22496 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22497 break;
22498 case OPC_SHRAV_R_QB:
22499 check_dsp_r2(ctx);
22500 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22501 break;
22502 case OPC_SHRA_PH:
22503 check_dsp(ctx);
22504 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22505 break;
22506 case OPC_SHRA_R_PH:
22507 check_dsp(ctx);
22508 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22509 break;
22510 case OPC_SHRAV_PH:
22511 check_dsp(ctx);
22512 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22513 break;
22514 case OPC_SHRAV_R_PH:
22515 check_dsp(ctx);
22516 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22517 break;
22518 case OPC_SHRA_R_W:
22519 check_dsp(ctx);
22520 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22521 break;
22522 case OPC_SHRAV_R_W:
22523 check_dsp(ctx);
22524 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22525 break;
22526 default: /* Invalid */
22527 MIPS_INVAL("MASK SHLL.QB");
22528 generate_exception_end(ctx, EXCP_RI);
22529 break;
22531 break;
22533 #ifdef TARGET_MIPS64
22534 case OPC_SHLL_OB_DSP:
22535 op2 = MASK_SHLL_OB(ctx->opcode);
22536 switch (op2) {
22537 case OPC_SHLL_PW:
22538 check_dsp(ctx);
22539 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22540 break;
22541 case OPC_SHLLV_PW:
22542 check_dsp(ctx);
22543 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22544 break;
22545 case OPC_SHLL_S_PW:
22546 check_dsp(ctx);
22547 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22548 break;
22549 case OPC_SHLLV_S_PW:
22550 check_dsp(ctx);
22551 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22552 break;
22553 case OPC_SHLL_OB:
22554 check_dsp(ctx);
22555 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22556 break;
22557 case OPC_SHLLV_OB:
22558 check_dsp(ctx);
22559 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22560 break;
22561 case OPC_SHLL_QH:
22562 check_dsp(ctx);
22563 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22564 break;
22565 case OPC_SHLLV_QH:
22566 check_dsp(ctx);
22567 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22568 break;
22569 case OPC_SHLL_S_QH:
22570 check_dsp(ctx);
22571 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22572 break;
22573 case OPC_SHLLV_S_QH:
22574 check_dsp(ctx);
22575 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22576 break;
22577 case OPC_SHRA_OB:
22578 check_dsp_r2(ctx);
22579 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22580 break;
22581 case OPC_SHRAV_OB:
22582 check_dsp_r2(ctx);
22583 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22584 break;
22585 case OPC_SHRA_R_OB:
22586 check_dsp_r2(ctx);
22587 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22588 break;
22589 case OPC_SHRAV_R_OB:
22590 check_dsp_r2(ctx);
22591 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22592 break;
22593 case OPC_SHRA_PW:
22594 check_dsp(ctx);
22595 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22596 break;
22597 case OPC_SHRAV_PW:
22598 check_dsp(ctx);
22599 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22600 break;
22601 case OPC_SHRA_R_PW:
22602 check_dsp(ctx);
22603 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22604 break;
22605 case OPC_SHRAV_R_PW:
22606 check_dsp(ctx);
22607 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22608 break;
22609 case OPC_SHRA_QH:
22610 check_dsp(ctx);
22611 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22612 break;
22613 case OPC_SHRAV_QH:
22614 check_dsp(ctx);
22615 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22616 break;
22617 case OPC_SHRA_R_QH:
22618 check_dsp(ctx);
22619 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22620 break;
22621 case OPC_SHRAV_R_QH:
22622 check_dsp(ctx);
22623 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22624 break;
22625 case OPC_SHRL_OB:
22626 check_dsp(ctx);
22627 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22628 break;
22629 case OPC_SHRLV_OB:
22630 check_dsp(ctx);
22631 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22632 break;
22633 case OPC_SHRL_QH:
22634 check_dsp_r2(ctx);
22635 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22636 break;
22637 case OPC_SHRLV_QH:
22638 check_dsp_r2(ctx);
22639 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22640 break;
22641 default: /* Invalid */
22642 MIPS_INVAL("MASK SHLL.OB");
22643 generate_exception_end(ctx, EXCP_RI);
22644 break;
22646 break;
22647 #endif
22650 tcg_temp_free(t0);
22651 tcg_temp_free(v1_t);
22652 tcg_temp_free(v2_t);
22655 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22656 int ret, int v1, int v2, int check_ret)
22658 TCGv_i32 t0;
22659 TCGv v1_t;
22660 TCGv v2_t;
22662 if ((ret == 0) && (check_ret == 1)) {
22663 /* Treat as NOP. */
22664 return;
22667 t0 = tcg_temp_new_i32();
22668 v1_t = tcg_temp_new();
22669 v2_t = tcg_temp_new();
22671 tcg_gen_movi_i32(t0, ret);
22672 gen_load_gpr(v1_t, v1);
22673 gen_load_gpr(v2_t, v2);
22675 switch (op1) {
22676 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22677 * the same mask and op1. */
22678 case OPC_MULT_G_2E:
22679 check_dsp_r2(ctx);
22680 switch (op2) {
22681 case OPC_MUL_PH:
22682 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22683 break;
22684 case OPC_MUL_S_PH:
22685 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22686 break;
22687 case OPC_MULQ_S_W:
22688 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22689 break;
22690 case OPC_MULQ_RS_W:
22691 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22692 break;
22694 break;
22695 case OPC_DPA_W_PH_DSP:
22696 switch (op2) {
22697 case OPC_DPAU_H_QBL:
22698 check_dsp(ctx);
22699 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22700 break;
22701 case OPC_DPAU_H_QBR:
22702 check_dsp(ctx);
22703 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22704 break;
22705 case OPC_DPSU_H_QBL:
22706 check_dsp(ctx);
22707 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22708 break;
22709 case OPC_DPSU_H_QBR:
22710 check_dsp(ctx);
22711 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22712 break;
22713 case OPC_DPA_W_PH:
22714 check_dsp_r2(ctx);
22715 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22716 break;
22717 case OPC_DPAX_W_PH:
22718 check_dsp_r2(ctx);
22719 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22720 break;
22721 case OPC_DPAQ_S_W_PH:
22722 check_dsp(ctx);
22723 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22724 break;
22725 case OPC_DPAQX_S_W_PH:
22726 check_dsp_r2(ctx);
22727 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22728 break;
22729 case OPC_DPAQX_SA_W_PH:
22730 check_dsp_r2(ctx);
22731 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22732 break;
22733 case OPC_DPS_W_PH:
22734 check_dsp_r2(ctx);
22735 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22736 break;
22737 case OPC_DPSX_W_PH:
22738 check_dsp_r2(ctx);
22739 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22740 break;
22741 case OPC_DPSQ_S_W_PH:
22742 check_dsp(ctx);
22743 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22744 break;
22745 case OPC_DPSQX_S_W_PH:
22746 check_dsp_r2(ctx);
22747 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22748 break;
22749 case OPC_DPSQX_SA_W_PH:
22750 check_dsp_r2(ctx);
22751 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22752 break;
22753 case OPC_MULSAQ_S_W_PH:
22754 check_dsp(ctx);
22755 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22756 break;
22757 case OPC_DPAQ_SA_L_W:
22758 check_dsp(ctx);
22759 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22760 break;
22761 case OPC_DPSQ_SA_L_W:
22762 check_dsp(ctx);
22763 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22764 break;
22765 case OPC_MAQ_S_W_PHL:
22766 check_dsp(ctx);
22767 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22768 break;
22769 case OPC_MAQ_S_W_PHR:
22770 check_dsp(ctx);
22771 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22772 break;
22773 case OPC_MAQ_SA_W_PHL:
22774 check_dsp(ctx);
22775 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_MAQ_SA_W_PHR:
22778 check_dsp(ctx);
22779 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_MULSA_W_PH:
22782 check_dsp_r2(ctx);
22783 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22784 break;
22786 break;
22787 #ifdef TARGET_MIPS64
22788 case OPC_DPAQ_W_QH_DSP:
22790 int ac = ret & 0x03;
22791 tcg_gen_movi_i32(t0, ac);
22793 switch (op2) {
22794 case OPC_DMADD:
22795 check_dsp(ctx);
22796 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22797 break;
22798 case OPC_DMADDU:
22799 check_dsp(ctx);
22800 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22801 break;
22802 case OPC_DMSUB:
22803 check_dsp(ctx);
22804 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22805 break;
22806 case OPC_DMSUBU:
22807 check_dsp(ctx);
22808 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22809 break;
22810 case OPC_DPA_W_QH:
22811 check_dsp_r2(ctx);
22812 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22813 break;
22814 case OPC_DPAQ_S_W_QH:
22815 check_dsp(ctx);
22816 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22817 break;
22818 case OPC_DPAQ_SA_L_PW:
22819 check_dsp(ctx);
22820 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22821 break;
22822 case OPC_DPAU_H_OBL:
22823 check_dsp(ctx);
22824 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22825 break;
22826 case OPC_DPAU_H_OBR:
22827 check_dsp(ctx);
22828 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22829 break;
22830 case OPC_DPS_W_QH:
22831 check_dsp_r2(ctx);
22832 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22833 break;
22834 case OPC_DPSQ_S_W_QH:
22835 check_dsp(ctx);
22836 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22837 break;
22838 case OPC_DPSQ_SA_L_PW:
22839 check_dsp(ctx);
22840 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22841 break;
22842 case OPC_DPSU_H_OBL:
22843 check_dsp(ctx);
22844 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22845 break;
22846 case OPC_DPSU_H_OBR:
22847 check_dsp(ctx);
22848 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22849 break;
22850 case OPC_MAQ_S_L_PWL:
22851 check_dsp(ctx);
22852 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22853 break;
22854 case OPC_MAQ_S_L_PWR:
22855 check_dsp(ctx);
22856 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22857 break;
22858 case OPC_MAQ_S_W_QHLL:
22859 check_dsp(ctx);
22860 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22861 break;
22862 case OPC_MAQ_SA_W_QHLL:
22863 check_dsp(ctx);
22864 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22865 break;
22866 case OPC_MAQ_S_W_QHLR:
22867 check_dsp(ctx);
22868 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22869 break;
22870 case OPC_MAQ_SA_W_QHLR:
22871 check_dsp(ctx);
22872 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22873 break;
22874 case OPC_MAQ_S_W_QHRL:
22875 check_dsp(ctx);
22876 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22877 break;
22878 case OPC_MAQ_SA_W_QHRL:
22879 check_dsp(ctx);
22880 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22881 break;
22882 case OPC_MAQ_S_W_QHRR:
22883 check_dsp(ctx);
22884 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22885 break;
22886 case OPC_MAQ_SA_W_QHRR:
22887 check_dsp(ctx);
22888 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22889 break;
22890 case OPC_MULSAQ_S_L_PW:
22891 check_dsp(ctx);
22892 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22893 break;
22894 case OPC_MULSAQ_S_W_QH:
22895 check_dsp(ctx);
22896 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22897 break;
22900 break;
22901 #endif
22902 case OPC_ADDU_QB_DSP:
22903 switch (op2) {
22904 case OPC_MULEU_S_PH_QBL:
22905 check_dsp(ctx);
22906 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22907 break;
22908 case OPC_MULEU_S_PH_QBR:
22909 check_dsp(ctx);
22910 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22911 break;
22912 case OPC_MULQ_RS_PH:
22913 check_dsp(ctx);
22914 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22915 break;
22916 case OPC_MULEQ_S_W_PHL:
22917 check_dsp(ctx);
22918 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22919 break;
22920 case OPC_MULEQ_S_W_PHR:
22921 check_dsp(ctx);
22922 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22923 break;
22924 case OPC_MULQ_S_PH:
22925 check_dsp_r2(ctx);
22926 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22927 break;
22929 break;
22930 #ifdef TARGET_MIPS64
22931 case OPC_ADDU_OB_DSP:
22932 switch (op2) {
22933 case OPC_MULEQ_S_PW_QHL:
22934 check_dsp(ctx);
22935 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22936 break;
22937 case OPC_MULEQ_S_PW_QHR:
22938 check_dsp(ctx);
22939 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22940 break;
22941 case OPC_MULEU_S_QH_OBL:
22942 check_dsp(ctx);
22943 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22944 break;
22945 case OPC_MULEU_S_QH_OBR:
22946 check_dsp(ctx);
22947 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22948 break;
22949 case OPC_MULQ_RS_QH:
22950 check_dsp(ctx);
22951 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22952 break;
22954 break;
22955 #endif
22958 tcg_temp_free_i32(t0);
22959 tcg_temp_free(v1_t);
22960 tcg_temp_free(v2_t);
22963 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22964 int ret, int val)
22966 int16_t imm;
22967 TCGv t0;
22968 TCGv val_t;
22970 if (ret == 0) {
22971 /* Treat as NOP. */
22972 return;
22975 t0 = tcg_temp_new();
22976 val_t = tcg_temp_new();
22977 gen_load_gpr(val_t, val);
22979 switch (op1) {
22980 case OPC_ABSQ_S_PH_DSP:
22981 switch (op2) {
22982 case OPC_BITREV:
22983 check_dsp(ctx);
22984 gen_helper_bitrev(cpu_gpr[ret], val_t);
22985 break;
22986 case OPC_REPL_QB:
22987 check_dsp(ctx);
22989 target_long result;
22990 imm = (ctx->opcode >> 16) & 0xFF;
22991 result = (uint32_t)imm << 24 |
22992 (uint32_t)imm << 16 |
22993 (uint32_t)imm << 8 |
22994 (uint32_t)imm;
22995 result = (int32_t)result;
22996 tcg_gen_movi_tl(cpu_gpr[ret], result);
22998 break;
22999 case OPC_REPLV_QB:
23000 check_dsp(ctx);
23001 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23002 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23003 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23004 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23005 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23006 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23007 break;
23008 case OPC_REPL_PH:
23009 check_dsp(ctx);
23011 imm = (ctx->opcode >> 16) & 0x03FF;
23012 imm = (int16_t)(imm << 6) >> 6;
23013 tcg_gen_movi_tl(cpu_gpr[ret], \
23014 (target_long)((int32_t)imm << 16 | \
23015 (uint16_t)imm));
23017 break;
23018 case OPC_REPLV_PH:
23019 check_dsp(ctx);
23020 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23021 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23022 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23023 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23024 break;
23026 break;
23027 #ifdef TARGET_MIPS64
23028 case OPC_ABSQ_S_QH_DSP:
23029 switch (op2) {
23030 case OPC_REPL_OB:
23031 check_dsp(ctx);
23033 target_long temp;
23035 imm = (ctx->opcode >> 16) & 0xFF;
23036 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23037 temp = (temp << 16) | temp;
23038 temp = (temp << 32) | temp;
23039 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23040 break;
23042 case OPC_REPL_PW:
23043 check_dsp(ctx);
23045 target_long temp;
23047 imm = (ctx->opcode >> 16) & 0x03FF;
23048 imm = (int16_t)(imm << 6) >> 6;
23049 temp = ((target_long)imm << 32) \
23050 | ((target_long)imm & 0xFFFFFFFF);
23051 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23052 break;
23054 case OPC_REPL_QH:
23055 check_dsp(ctx);
23057 target_long temp;
23059 imm = (ctx->opcode >> 16) & 0x03FF;
23060 imm = (int16_t)(imm << 6) >> 6;
23062 temp = ((uint64_t)(uint16_t)imm << 48) |
23063 ((uint64_t)(uint16_t)imm << 32) |
23064 ((uint64_t)(uint16_t)imm << 16) |
23065 (uint64_t)(uint16_t)imm;
23066 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23067 break;
23069 case OPC_REPLV_OB:
23070 check_dsp(ctx);
23071 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23072 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23073 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23074 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23075 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23076 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23077 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23078 break;
23079 case OPC_REPLV_PW:
23080 check_dsp(ctx);
23081 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23082 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23083 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23084 break;
23085 case OPC_REPLV_QH:
23086 check_dsp(ctx);
23087 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23088 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23089 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23090 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23091 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23092 break;
23094 break;
23095 #endif
23097 tcg_temp_free(t0);
23098 tcg_temp_free(val_t);
23101 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23102 uint32_t op1, uint32_t op2,
23103 int ret, int v1, int v2, int check_ret)
23105 TCGv t1;
23106 TCGv v1_t;
23107 TCGv v2_t;
23109 if ((ret == 0) && (check_ret == 1)) {
23110 /* Treat as NOP. */
23111 return;
23114 t1 = tcg_temp_new();
23115 v1_t = tcg_temp_new();
23116 v2_t = tcg_temp_new();
23118 gen_load_gpr(v1_t, v1);
23119 gen_load_gpr(v2_t, v2);
23121 switch (op1) {
23122 case OPC_CMPU_EQ_QB_DSP:
23123 switch (op2) {
23124 case OPC_CMPU_EQ_QB:
23125 check_dsp(ctx);
23126 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23127 break;
23128 case OPC_CMPU_LT_QB:
23129 check_dsp(ctx);
23130 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23131 break;
23132 case OPC_CMPU_LE_QB:
23133 check_dsp(ctx);
23134 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23135 break;
23136 case OPC_CMPGU_EQ_QB:
23137 check_dsp(ctx);
23138 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23139 break;
23140 case OPC_CMPGU_LT_QB:
23141 check_dsp(ctx);
23142 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23143 break;
23144 case OPC_CMPGU_LE_QB:
23145 check_dsp(ctx);
23146 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23147 break;
23148 case OPC_CMPGDU_EQ_QB:
23149 check_dsp_r2(ctx);
23150 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23151 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23152 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23153 tcg_gen_shli_tl(t1, t1, 24);
23154 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23155 break;
23156 case OPC_CMPGDU_LT_QB:
23157 check_dsp_r2(ctx);
23158 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23159 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23160 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23161 tcg_gen_shli_tl(t1, t1, 24);
23162 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23163 break;
23164 case OPC_CMPGDU_LE_QB:
23165 check_dsp_r2(ctx);
23166 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23167 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23168 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23169 tcg_gen_shli_tl(t1, t1, 24);
23170 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23171 break;
23172 case OPC_CMP_EQ_PH:
23173 check_dsp(ctx);
23174 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23175 break;
23176 case OPC_CMP_LT_PH:
23177 check_dsp(ctx);
23178 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23179 break;
23180 case OPC_CMP_LE_PH:
23181 check_dsp(ctx);
23182 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23183 break;
23184 case OPC_PICK_QB:
23185 check_dsp(ctx);
23186 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23187 break;
23188 case OPC_PICK_PH:
23189 check_dsp(ctx);
23190 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23191 break;
23192 case OPC_PACKRL_PH:
23193 check_dsp(ctx);
23194 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23195 break;
23197 break;
23198 #ifdef TARGET_MIPS64
23199 case OPC_CMPU_EQ_OB_DSP:
23200 switch (op2) {
23201 case OPC_CMP_EQ_PW:
23202 check_dsp(ctx);
23203 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23204 break;
23205 case OPC_CMP_LT_PW:
23206 check_dsp(ctx);
23207 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23208 break;
23209 case OPC_CMP_LE_PW:
23210 check_dsp(ctx);
23211 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23212 break;
23213 case OPC_CMP_EQ_QH:
23214 check_dsp(ctx);
23215 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23216 break;
23217 case OPC_CMP_LT_QH:
23218 check_dsp(ctx);
23219 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23220 break;
23221 case OPC_CMP_LE_QH:
23222 check_dsp(ctx);
23223 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23224 break;
23225 case OPC_CMPGDU_EQ_OB:
23226 check_dsp_r2(ctx);
23227 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23228 break;
23229 case OPC_CMPGDU_LT_OB:
23230 check_dsp_r2(ctx);
23231 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23232 break;
23233 case OPC_CMPGDU_LE_OB:
23234 check_dsp_r2(ctx);
23235 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23236 break;
23237 case OPC_CMPGU_EQ_OB:
23238 check_dsp(ctx);
23239 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23240 break;
23241 case OPC_CMPGU_LT_OB:
23242 check_dsp(ctx);
23243 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23244 break;
23245 case OPC_CMPGU_LE_OB:
23246 check_dsp(ctx);
23247 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23248 break;
23249 case OPC_CMPU_EQ_OB:
23250 check_dsp(ctx);
23251 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23252 break;
23253 case OPC_CMPU_LT_OB:
23254 check_dsp(ctx);
23255 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23256 break;
23257 case OPC_CMPU_LE_OB:
23258 check_dsp(ctx);
23259 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_PACKRL_PW:
23262 check_dsp(ctx);
23263 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23264 break;
23265 case OPC_PICK_OB:
23266 check_dsp(ctx);
23267 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23268 break;
23269 case OPC_PICK_PW:
23270 check_dsp(ctx);
23271 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23272 break;
23273 case OPC_PICK_QH:
23274 check_dsp(ctx);
23275 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23276 break;
23278 break;
23279 #endif
23282 tcg_temp_free(t1);
23283 tcg_temp_free(v1_t);
23284 tcg_temp_free(v2_t);
23287 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23288 uint32_t op1, int rt, int rs, int sa)
23290 TCGv t0;
23292 check_dsp_r2(ctx);
23294 if (rt == 0) {
23295 /* Treat as NOP. */
23296 return;
23299 t0 = tcg_temp_new();
23300 gen_load_gpr(t0, rs);
23302 switch (op1) {
23303 case OPC_APPEND_DSP:
23304 switch (MASK_APPEND(ctx->opcode)) {
23305 case OPC_APPEND:
23306 if (sa != 0) {
23307 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23309 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23310 break;
23311 case OPC_PREPEND:
23312 if (sa != 0) {
23313 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23314 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23315 tcg_gen_shli_tl(t0, t0, 32 - sa);
23316 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23318 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23319 break;
23320 case OPC_BALIGN:
23321 sa &= 3;
23322 if (sa != 0 && sa != 2) {
23323 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23324 tcg_gen_ext32u_tl(t0, t0);
23325 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23326 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23328 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23329 break;
23330 default: /* Invalid */
23331 MIPS_INVAL("MASK APPEND");
23332 generate_exception_end(ctx, EXCP_RI);
23333 break;
23335 break;
23336 #ifdef TARGET_MIPS64
23337 case OPC_DAPPEND_DSP:
23338 switch (MASK_DAPPEND(ctx->opcode)) {
23339 case OPC_DAPPEND:
23340 if (sa != 0) {
23341 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23343 break;
23344 case OPC_PREPENDD:
23345 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23346 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23347 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23348 break;
23349 case OPC_PREPENDW:
23350 if (sa != 0) {
23351 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23352 tcg_gen_shli_tl(t0, t0, 64 - sa);
23353 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23355 break;
23356 case OPC_DBALIGN:
23357 sa &= 7;
23358 if (sa != 0 && sa != 2 && sa != 4) {
23359 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23360 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23361 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23363 break;
23364 default: /* Invalid */
23365 MIPS_INVAL("MASK DAPPEND");
23366 generate_exception_end(ctx, EXCP_RI);
23367 break;
23369 break;
23370 #endif
23372 tcg_temp_free(t0);
23375 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23376 int ret, int v1, int v2, int check_ret)
23379 TCGv t0;
23380 TCGv t1;
23381 TCGv v1_t;
23382 TCGv v2_t;
23383 int16_t imm;
23385 if ((ret == 0) && (check_ret == 1)) {
23386 /* Treat as NOP. */
23387 return;
23390 t0 = tcg_temp_new();
23391 t1 = tcg_temp_new();
23392 v1_t = tcg_temp_new();
23393 v2_t = tcg_temp_new();
23395 gen_load_gpr(v1_t, v1);
23396 gen_load_gpr(v2_t, v2);
23398 switch (op1) {
23399 case OPC_EXTR_W_DSP:
23400 check_dsp(ctx);
23401 switch (op2) {
23402 case OPC_EXTR_W:
23403 tcg_gen_movi_tl(t0, v2);
23404 tcg_gen_movi_tl(t1, v1);
23405 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23406 break;
23407 case OPC_EXTR_R_W:
23408 tcg_gen_movi_tl(t0, v2);
23409 tcg_gen_movi_tl(t1, v1);
23410 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23411 break;
23412 case OPC_EXTR_RS_W:
23413 tcg_gen_movi_tl(t0, v2);
23414 tcg_gen_movi_tl(t1, v1);
23415 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23416 break;
23417 case OPC_EXTR_S_H:
23418 tcg_gen_movi_tl(t0, v2);
23419 tcg_gen_movi_tl(t1, v1);
23420 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23421 break;
23422 case OPC_EXTRV_S_H:
23423 tcg_gen_movi_tl(t0, v2);
23424 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23425 break;
23426 case OPC_EXTRV_W:
23427 tcg_gen_movi_tl(t0, v2);
23428 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23429 break;
23430 case OPC_EXTRV_R_W:
23431 tcg_gen_movi_tl(t0, v2);
23432 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23433 break;
23434 case OPC_EXTRV_RS_W:
23435 tcg_gen_movi_tl(t0, v2);
23436 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23437 break;
23438 case OPC_EXTP:
23439 tcg_gen_movi_tl(t0, v2);
23440 tcg_gen_movi_tl(t1, v1);
23441 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23442 break;
23443 case OPC_EXTPV:
23444 tcg_gen_movi_tl(t0, v2);
23445 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23446 break;
23447 case OPC_EXTPDP:
23448 tcg_gen_movi_tl(t0, v2);
23449 tcg_gen_movi_tl(t1, v1);
23450 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23451 break;
23452 case OPC_EXTPDPV:
23453 tcg_gen_movi_tl(t0, v2);
23454 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23455 break;
23456 case OPC_SHILO:
23457 imm = (ctx->opcode >> 20) & 0x3F;
23458 tcg_gen_movi_tl(t0, ret);
23459 tcg_gen_movi_tl(t1, imm);
23460 gen_helper_shilo(t0, t1, cpu_env);
23461 break;
23462 case OPC_SHILOV:
23463 tcg_gen_movi_tl(t0, ret);
23464 gen_helper_shilo(t0, v1_t, cpu_env);
23465 break;
23466 case OPC_MTHLIP:
23467 tcg_gen_movi_tl(t0, ret);
23468 gen_helper_mthlip(t0, v1_t, cpu_env);
23469 break;
23470 case OPC_WRDSP:
23471 imm = (ctx->opcode >> 11) & 0x3FF;
23472 tcg_gen_movi_tl(t0, imm);
23473 gen_helper_wrdsp(v1_t, t0, cpu_env);
23474 break;
23475 case OPC_RDDSP:
23476 imm = (ctx->opcode >> 16) & 0x03FF;
23477 tcg_gen_movi_tl(t0, imm);
23478 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23479 break;
23481 break;
23482 #ifdef TARGET_MIPS64
23483 case OPC_DEXTR_W_DSP:
23484 check_dsp(ctx);
23485 switch (op2) {
23486 case OPC_DMTHLIP:
23487 tcg_gen_movi_tl(t0, ret);
23488 gen_helper_dmthlip(v1_t, t0, cpu_env);
23489 break;
23490 case OPC_DSHILO:
23492 int shift = (ctx->opcode >> 19) & 0x7F;
23493 int ac = (ctx->opcode >> 11) & 0x03;
23494 tcg_gen_movi_tl(t0, shift);
23495 tcg_gen_movi_tl(t1, ac);
23496 gen_helper_dshilo(t0, t1, cpu_env);
23497 break;
23499 case OPC_DSHILOV:
23501 int ac = (ctx->opcode >> 11) & 0x03;
23502 tcg_gen_movi_tl(t0, ac);
23503 gen_helper_dshilo(v1_t, t0, cpu_env);
23504 break;
23506 case OPC_DEXTP:
23507 tcg_gen_movi_tl(t0, v2);
23508 tcg_gen_movi_tl(t1, v1);
23510 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23511 break;
23512 case OPC_DEXTPV:
23513 tcg_gen_movi_tl(t0, v2);
23514 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23515 break;
23516 case OPC_DEXTPDP:
23517 tcg_gen_movi_tl(t0, v2);
23518 tcg_gen_movi_tl(t1, v1);
23519 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23520 break;
23521 case OPC_DEXTPDPV:
23522 tcg_gen_movi_tl(t0, v2);
23523 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23524 break;
23525 case OPC_DEXTR_L:
23526 tcg_gen_movi_tl(t0, v2);
23527 tcg_gen_movi_tl(t1, v1);
23528 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23529 break;
23530 case OPC_DEXTR_R_L:
23531 tcg_gen_movi_tl(t0, v2);
23532 tcg_gen_movi_tl(t1, v1);
23533 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23534 break;
23535 case OPC_DEXTR_RS_L:
23536 tcg_gen_movi_tl(t0, v2);
23537 tcg_gen_movi_tl(t1, v1);
23538 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23539 break;
23540 case OPC_DEXTR_W:
23541 tcg_gen_movi_tl(t0, v2);
23542 tcg_gen_movi_tl(t1, v1);
23543 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23544 break;
23545 case OPC_DEXTR_R_W:
23546 tcg_gen_movi_tl(t0, v2);
23547 tcg_gen_movi_tl(t1, v1);
23548 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23549 break;
23550 case OPC_DEXTR_RS_W:
23551 tcg_gen_movi_tl(t0, v2);
23552 tcg_gen_movi_tl(t1, v1);
23553 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23554 break;
23555 case OPC_DEXTR_S_H:
23556 tcg_gen_movi_tl(t0, v2);
23557 tcg_gen_movi_tl(t1, v1);
23558 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23559 break;
23560 case OPC_DEXTRV_S_H:
23561 tcg_gen_movi_tl(t0, v2);
23562 tcg_gen_movi_tl(t1, v1);
23563 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23564 break;
23565 case OPC_DEXTRV_L:
23566 tcg_gen_movi_tl(t0, v2);
23567 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23568 break;
23569 case OPC_DEXTRV_R_L:
23570 tcg_gen_movi_tl(t0, v2);
23571 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23572 break;
23573 case OPC_DEXTRV_RS_L:
23574 tcg_gen_movi_tl(t0, v2);
23575 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23576 break;
23577 case OPC_DEXTRV_W:
23578 tcg_gen_movi_tl(t0, v2);
23579 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23580 break;
23581 case OPC_DEXTRV_R_W:
23582 tcg_gen_movi_tl(t0, v2);
23583 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23584 break;
23585 case OPC_DEXTRV_RS_W:
23586 tcg_gen_movi_tl(t0, v2);
23587 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23588 break;
23590 break;
23591 #endif
23594 tcg_temp_free(t0);
23595 tcg_temp_free(t1);
23596 tcg_temp_free(v1_t);
23597 tcg_temp_free(v2_t);
23600 /* End MIPSDSP functions. */
23602 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23604 int rs, rt, rd, sa;
23605 uint32_t op1, op2;
23607 rs = (ctx->opcode >> 21) & 0x1f;
23608 rt = (ctx->opcode >> 16) & 0x1f;
23609 rd = (ctx->opcode >> 11) & 0x1f;
23610 sa = (ctx->opcode >> 6) & 0x1f;
23612 op1 = MASK_SPECIAL(ctx->opcode);
23613 switch (op1) {
23614 case OPC_LSA:
23615 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23616 break;
23617 case OPC_MULT:
23618 case OPC_MULTU:
23619 case OPC_DIV:
23620 case OPC_DIVU:
23621 op2 = MASK_R6_MULDIV(ctx->opcode);
23622 switch (op2) {
23623 case R6_OPC_MUL:
23624 case R6_OPC_MUH:
23625 case R6_OPC_MULU:
23626 case R6_OPC_MUHU:
23627 case R6_OPC_DIV:
23628 case R6_OPC_MOD:
23629 case R6_OPC_DIVU:
23630 case R6_OPC_MODU:
23631 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23632 break;
23633 default:
23634 MIPS_INVAL("special_r6 muldiv");
23635 generate_exception_end(ctx, EXCP_RI);
23636 break;
23638 break;
23639 case OPC_SELEQZ:
23640 case OPC_SELNEZ:
23641 gen_cond_move(ctx, op1, rd, rs, rt);
23642 break;
23643 case R6_OPC_CLO:
23644 case R6_OPC_CLZ:
23645 if (rt == 0 && sa == 1) {
23646 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23647 We need additionally to check other fields */
23648 gen_cl(ctx, op1, rd, rs);
23649 } else {
23650 generate_exception_end(ctx, EXCP_RI);
23652 break;
23653 case R6_OPC_SDBBP:
23654 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23655 gen_helper_do_semihosting(cpu_env);
23656 } else {
23657 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23658 generate_exception_end(ctx, EXCP_RI);
23659 } else {
23660 generate_exception_end(ctx, EXCP_DBp);
23663 break;
23664 #if defined(TARGET_MIPS64)
23665 case OPC_DLSA:
23666 check_mips_64(ctx);
23667 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23668 break;
23669 case R6_OPC_DCLO:
23670 case R6_OPC_DCLZ:
23671 if (rt == 0 && sa == 1) {
23672 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23673 We need additionally to check other fields */
23674 check_mips_64(ctx);
23675 gen_cl(ctx, op1, rd, rs);
23676 } else {
23677 generate_exception_end(ctx, EXCP_RI);
23679 break;
23680 case OPC_DMULT:
23681 case OPC_DMULTU:
23682 case OPC_DDIV:
23683 case OPC_DDIVU:
23685 op2 = MASK_R6_MULDIV(ctx->opcode);
23686 switch (op2) {
23687 case R6_OPC_DMUL:
23688 case R6_OPC_DMUH:
23689 case R6_OPC_DMULU:
23690 case R6_OPC_DMUHU:
23691 case R6_OPC_DDIV:
23692 case R6_OPC_DMOD:
23693 case R6_OPC_DDIVU:
23694 case R6_OPC_DMODU:
23695 check_mips_64(ctx);
23696 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23697 break;
23698 default:
23699 MIPS_INVAL("special_r6 muldiv");
23700 generate_exception_end(ctx, EXCP_RI);
23701 break;
23703 break;
23704 #endif
23705 default: /* Invalid */
23706 MIPS_INVAL("special_r6");
23707 generate_exception_end(ctx, EXCP_RI);
23708 break;
23712 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23714 int rs, rt, rd, sa;
23715 uint32_t op1;
23717 rs = (ctx->opcode >> 21) & 0x1f;
23718 rt = (ctx->opcode >> 16) & 0x1f;
23719 rd = (ctx->opcode >> 11) & 0x1f;
23720 sa = (ctx->opcode >> 6) & 0x1f;
23722 op1 = MASK_SPECIAL(ctx->opcode);
23723 switch (op1) {
23724 case OPC_MOVN: /* Conditional move */
23725 case OPC_MOVZ:
23726 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23727 INSN_LOONGSON2E | INSN_LOONGSON2F | INSN_R5900);
23728 gen_cond_move(ctx, op1, rd, rs, rt);
23729 break;
23730 case OPC_MFHI: /* Move from HI/LO */
23731 case OPC_MFLO:
23732 gen_HILO(ctx, op1, rs & 3, rd);
23733 break;
23734 case OPC_MTHI:
23735 case OPC_MTLO: /* Move to HI/LO */
23736 gen_HILO(ctx, op1, rd & 3, rs);
23737 break;
23738 case OPC_MOVCI:
23739 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23740 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23741 check_cp1_enabled(ctx);
23742 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23743 (ctx->opcode >> 16) & 1);
23744 } else {
23745 generate_exception_err(ctx, EXCP_CpU, 1);
23747 break;
23748 case OPC_MULT:
23749 case OPC_MULTU:
23750 if (sa) {
23751 check_insn(ctx, INSN_VR54XX);
23752 op1 = MASK_MUL_VR54XX(ctx->opcode);
23753 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23754 } else if (ctx->insn_flags & INSN_R5900) {
23755 gen_mul_txx9(ctx, op1, rd, rs, rt);
23756 } else {
23757 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23759 break;
23760 case OPC_DIV:
23761 case OPC_DIVU:
23762 gen_muldiv(ctx, op1, 0, rs, rt);
23763 break;
23764 #if defined(TARGET_MIPS64)
23765 case OPC_DMULT:
23766 case OPC_DMULTU:
23767 case OPC_DDIV:
23768 case OPC_DDIVU:
23769 check_insn(ctx, ISA_MIPS3);
23770 check_insn_opc_user_only(ctx, INSN_R5900);
23771 check_mips_64(ctx);
23772 gen_muldiv(ctx, op1, 0, rs, rt);
23773 break;
23774 #endif
23775 case OPC_JR:
23776 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23777 break;
23778 case OPC_SPIM:
23779 #ifdef MIPS_STRICT_STANDARD
23780 MIPS_INVAL("SPIM");
23781 generate_exception_end(ctx, EXCP_RI);
23782 #else
23783 /* Implemented as RI exception for now. */
23784 MIPS_INVAL("spim (unofficial)");
23785 generate_exception_end(ctx, EXCP_RI);
23786 #endif
23787 break;
23788 default: /* Invalid */
23789 MIPS_INVAL("special_legacy");
23790 generate_exception_end(ctx, EXCP_RI);
23791 break;
23795 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23797 int rs, rt, rd, sa;
23798 uint32_t op1;
23800 rs = (ctx->opcode >> 21) & 0x1f;
23801 rt = (ctx->opcode >> 16) & 0x1f;
23802 rd = (ctx->opcode >> 11) & 0x1f;
23803 sa = (ctx->opcode >> 6) & 0x1f;
23805 op1 = MASK_SPECIAL(ctx->opcode);
23806 switch (op1) {
23807 case OPC_SLL: /* Shift with immediate */
23808 if (sa == 5 && rd == 0 &&
23809 rs == 0 && rt == 0) { /* PAUSE */
23810 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23811 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23812 generate_exception_end(ctx, EXCP_RI);
23813 break;
23816 /* Fallthrough */
23817 case OPC_SRA:
23818 gen_shift_imm(ctx, op1, rd, rt, sa);
23819 break;
23820 case OPC_SRL:
23821 switch ((ctx->opcode >> 21) & 0x1f) {
23822 case 1:
23823 /* rotr is decoded as srl on non-R2 CPUs */
23824 if (ctx->insn_flags & ISA_MIPS32R2) {
23825 op1 = OPC_ROTR;
23827 /* Fallthrough */
23828 case 0:
23829 gen_shift_imm(ctx, op1, rd, rt, sa);
23830 break;
23831 default:
23832 generate_exception_end(ctx, EXCP_RI);
23833 break;
23835 break;
23836 case OPC_ADD:
23837 case OPC_ADDU:
23838 case OPC_SUB:
23839 case OPC_SUBU:
23840 gen_arith(ctx, op1, rd, rs, rt);
23841 break;
23842 case OPC_SLLV: /* Shifts */
23843 case OPC_SRAV:
23844 gen_shift(ctx, op1, rd, rs, rt);
23845 break;
23846 case OPC_SRLV:
23847 switch ((ctx->opcode >> 6) & 0x1f) {
23848 case 1:
23849 /* rotrv is decoded as srlv on non-R2 CPUs */
23850 if (ctx->insn_flags & ISA_MIPS32R2) {
23851 op1 = OPC_ROTRV;
23853 /* Fallthrough */
23854 case 0:
23855 gen_shift(ctx, op1, rd, rs, rt);
23856 break;
23857 default:
23858 generate_exception_end(ctx, EXCP_RI);
23859 break;
23861 break;
23862 case OPC_SLT: /* Set on less than */
23863 case OPC_SLTU:
23864 gen_slt(ctx, op1, rd, rs, rt);
23865 break;
23866 case OPC_AND: /* Logic*/
23867 case OPC_OR:
23868 case OPC_NOR:
23869 case OPC_XOR:
23870 gen_logic(ctx, op1, rd, rs, rt);
23871 break;
23872 case OPC_JALR:
23873 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23874 break;
23875 case OPC_TGE: /* Traps */
23876 case OPC_TGEU:
23877 case OPC_TLT:
23878 case OPC_TLTU:
23879 case OPC_TEQ:
23880 case OPC_TNE:
23881 check_insn(ctx, ISA_MIPS2);
23882 gen_trap(ctx, op1, rs, rt, -1);
23883 break;
23884 case OPC_LSA: /* OPC_PMON */
23885 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23886 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23887 decode_opc_special_r6(env, ctx);
23888 } else {
23889 /* Pmon entry point, also R4010 selsl */
23890 #ifdef MIPS_STRICT_STANDARD
23891 MIPS_INVAL("PMON / selsl");
23892 generate_exception_end(ctx, EXCP_RI);
23893 #else
23894 gen_helper_0e0i(pmon, sa);
23895 #endif
23897 break;
23898 case OPC_SYSCALL:
23899 generate_exception_end(ctx, EXCP_SYSCALL);
23900 break;
23901 case OPC_BREAK:
23902 generate_exception_end(ctx, EXCP_BREAK);
23903 break;
23904 case OPC_SYNC:
23905 check_insn(ctx, ISA_MIPS2);
23906 gen_sync(extract32(ctx->opcode, 6, 5));
23907 break;
23909 #if defined(TARGET_MIPS64)
23910 /* MIPS64 specific opcodes */
23911 case OPC_DSLL:
23912 case OPC_DSRA:
23913 case OPC_DSLL32:
23914 case OPC_DSRA32:
23915 check_insn(ctx, ISA_MIPS3);
23916 check_mips_64(ctx);
23917 gen_shift_imm(ctx, op1, rd, rt, sa);
23918 break;
23919 case OPC_DSRL:
23920 switch ((ctx->opcode >> 21) & 0x1f) {
23921 case 1:
23922 /* drotr is decoded as dsrl on non-R2 CPUs */
23923 if (ctx->insn_flags & ISA_MIPS32R2) {
23924 op1 = OPC_DROTR;
23926 /* Fallthrough */
23927 case 0:
23928 check_insn(ctx, ISA_MIPS3);
23929 check_mips_64(ctx);
23930 gen_shift_imm(ctx, op1, rd, rt, sa);
23931 break;
23932 default:
23933 generate_exception_end(ctx, EXCP_RI);
23934 break;
23936 break;
23937 case OPC_DSRL32:
23938 switch ((ctx->opcode >> 21) & 0x1f) {
23939 case 1:
23940 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23941 if (ctx->insn_flags & ISA_MIPS32R2) {
23942 op1 = OPC_DROTR32;
23944 /* Fallthrough */
23945 case 0:
23946 check_insn(ctx, ISA_MIPS3);
23947 check_mips_64(ctx);
23948 gen_shift_imm(ctx, op1, rd, rt, sa);
23949 break;
23950 default:
23951 generate_exception_end(ctx, EXCP_RI);
23952 break;
23954 break;
23955 case OPC_DADD:
23956 case OPC_DADDU:
23957 case OPC_DSUB:
23958 case OPC_DSUBU:
23959 check_insn(ctx, ISA_MIPS3);
23960 check_mips_64(ctx);
23961 gen_arith(ctx, op1, rd, rs, rt);
23962 break;
23963 case OPC_DSLLV:
23964 case OPC_DSRAV:
23965 check_insn(ctx, ISA_MIPS3);
23966 check_mips_64(ctx);
23967 gen_shift(ctx, op1, rd, rs, rt);
23968 break;
23969 case OPC_DSRLV:
23970 switch ((ctx->opcode >> 6) & 0x1f) {
23971 case 1:
23972 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23973 if (ctx->insn_flags & ISA_MIPS32R2) {
23974 op1 = OPC_DROTRV;
23976 /* Fallthrough */
23977 case 0:
23978 check_insn(ctx, ISA_MIPS3);
23979 check_mips_64(ctx);
23980 gen_shift(ctx, op1, rd, rs, rt);
23981 break;
23982 default:
23983 generate_exception_end(ctx, EXCP_RI);
23984 break;
23986 break;
23987 case OPC_DLSA:
23988 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23989 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23990 decode_opc_special_r6(env, ctx);
23992 break;
23993 #endif
23994 default:
23995 if (ctx->insn_flags & ISA_MIPS32R6) {
23996 decode_opc_special_r6(env, ctx);
23997 } else {
23998 decode_opc_special_legacy(env, ctx);
24003 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
24005 int rs, rt, rd;
24006 uint32_t op1;
24008 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24010 rs = (ctx->opcode >> 21) & 0x1f;
24011 rt = (ctx->opcode >> 16) & 0x1f;
24012 rd = (ctx->opcode >> 11) & 0x1f;
24014 op1 = MASK_SPECIAL2(ctx->opcode);
24015 switch (op1) {
24016 case OPC_MADD: /* Multiply and add/sub */
24017 case OPC_MADDU:
24018 case OPC_MSUB:
24019 case OPC_MSUBU:
24020 check_insn(ctx, ISA_MIPS32);
24021 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24022 break;
24023 case OPC_MUL:
24024 gen_arith(ctx, op1, rd, rs, rt);
24025 break;
24026 case OPC_DIV_G_2F:
24027 case OPC_DIVU_G_2F:
24028 case OPC_MULT_G_2F:
24029 case OPC_MULTU_G_2F:
24030 case OPC_MOD_G_2F:
24031 case OPC_MODU_G_2F:
24032 check_insn(ctx, INSN_LOONGSON2F);
24033 gen_loongson_integer(ctx, op1, rd, rs, rt);
24034 break;
24035 case OPC_CLO:
24036 case OPC_CLZ:
24037 check_insn(ctx, ISA_MIPS32);
24038 gen_cl(ctx, op1, rd, rs);
24039 break;
24040 case OPC_SDBBP:
24041 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24042 gen_helper_do_semihosting(cpu_env);
24043 } else {
24044 /* XXX: not clear which exception should be raised
24045 * when in debug mode...
24047 check_insn(ctx, ISA_MIPS32);
24048 generate_exception_end(ctx, EXCP_DBp);
24050 break;
24051 #if defined(TARGET_MIPS64)
24052 case OPC_DCLO:
24053 case OPC_DCLZ:
24054 check_insn(ctx, ISA_MIPS64);
24055 check_mips_64(ctx);
24056 gen_cl(ctx, op1, rd, rs);
24057 break;
24058 case OPC_DMULT_G_2F:
24059 case OPC_DMULTU_G_2F:
24060 case OPC_DDIV_G_2F:
24061 case OPC_DDIVU_G_2F:
24062 case OPC_DMOD_G_2F:
24063 case OPC_DMODU_G_2F:
24064 check_insn(ctx, INSN_LOONGSON2F);
24065 gen_loongson_integer(ctx, op1, rd, rs, rt);
24066 break;
24067 #endif
24068 default: /* Invalid */
24069 MIPS_INVAL("special2_legacy");
24070 generate_exception_end(ctx, EXCP_RI);
24071 break;
24075 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
24077 int rs, rt, rd, sa;
24078 uint32_t op1, op2;
24079 int16_t imm;
24081 rs = (ctx->opcode >> 21) & 0x1f;
24082 rt = (ctx->opcode >> 16) & 0x1f;
24083 rd = (ctx->opcode >> 11) & 0x1f;
24084 sa = (ctx->opcode >> 6) & 0x1f;
24085 imm = (int16_t)ctx->opcode >> 7;
24087 op1 = MASK_SPECIAL3(ctx->opcode);
24088 switch (op1) {
24089 case R6_OPC_PREF:
24090 if (rt >= 24) {
24091 /* hint codes 24-31 are reserved and signal RI */
24092 generate_exception_end(ctx, EXCP_RI);
24094 /* Treat as NOP. */
24095 break;
24096 case R6_OPC_CACHE:
24097 check_cp0_enabled(ctx);
24098 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24099 gen_cache_operation(ctx, rt, rs, imm);
24101 break;
24102 case R6_OPC_SC:
24103 gen_st_cond(ctx, op1, rt, rs, imm);
24104 break;
24105 case R6_OPC_LL:
24106 gen_ld(ctx, op1, rt, rs, imm);
24107 break;
24108 case OPC_BSHFL:
24110 if (rd == 0) {
24111 /* Treat as NOP. */
24112 break;
24114 op2 = MASK_BSHFL(ctx->opcode);
24115 switch (op2) {
24116 case OPC_ALIGN:
24117 case OPC_ALIGN_1:
24118 case OPC_ALIGN_2:
24119 case OPC_ALIGN_3:
24120 gen_align(ctx, 32, rd, rs, rt, sa & 3);
24121 break;
24122 case OPC_BITSWAP:
24123 gen_bitswap(ctx, op2, rd, rt);
24124 break;
24127 break;
24128 #if defined(TARGET_MIPS64)
24129 case R6_OPC_SCD:
24130 gen_st_cond(ctx, op1, rt, rs, imm);
24131 break;
24132 case R6_OPC_LLD:
24133 gen_ld(ctx, op1, rt, rs, imm);
24134 break;
24135 case OPC_DBSHFL:
24136 check_mips_64(ctx);
24138 if (rd == 0) {
24139 /* Treat as NOP. */
24140 break;
24142 op2 = MASK_DBSHFL(ctx->opcode);
24143 switch (op2) {
24144 case OPC_DALIGN:
24145 case OPC_DALIGN_1:
24146 case OPC_DALIGN_2:
24147 case OPC_DALIGN_3:
24148 case OPC_DALIGN_4:
24149 case OPC_DALIGN_5:
24150 case OPC_DALIGN_6:
24151 case OPC_DALIGN_7:
24152 gen_align(ctx, 64, rd, rs, rt, sa & 7);
24153 break;
24154 case OPC_DBITSWAP:
24155 gen_bitswap(ctx, op2, rd, rt);
24156 break;
24160 break;
24161 #endif
24162 default: /* Invalid */
24163 MIPS_INVAL("special3_r6");
24164 generate_exception_end(ctx, EXCP_RI);
24165 break;
24169 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
24171 int rs, rt, rd;
24172 uint32_t op1, op2;
24174 rs = (ctx->opcode >> 21) & 0x1f;
24175 rt = (ctx->opcode >> 16) & 0x1f;
24176 rd = (ctx->opcode >> 11) & 0x1f;
24178 op1 = MASK_SPECIAL3(ctx->opcode);
24179 switch (op1) {
24180 case OPC_DIV_G_2E:
24181 case OPC_DIVU_G_2E:
24182 case OPC_MOD_G_2E:
24183 case OPC_MODU_G_2E:
24184 case OPC_MULT_G_2E:
24185 case OPC_MULTU_G_2E:
24186 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24187 * the same mask and op1. */
24188 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
24189 op2 = MASK_ADDUH_QB(ctx->opcode);
24190 switch (op2) {
24191 case OPC_ADDUH_QB:
24192 case OPC_ADDUH_R_QB:
24193 case OPC_ADDQH_PH:
24194 case OPC_ADDQH_R_PH:
24195 case OPC_ADDQH_W:
24196 case OPC_ADDQH_R_W:
24197 case OPC_SUBUH_QB:
24198 case OPC_SUBUH_R_QB:
24199 case OPC_SUBQH_PH:
24200 case OPC_SUBQH_R_PH:
24201 case OPC_SUBQH_W:
24202 case OPC_SUBQH_R_W:
24203 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24204 break;
24205 case OPC_MUL_PH:
24206 case OPC_MUL_S_PH:
24207 case OPC_MULQ_S_W:
24208 case OPC_MULQ_RS_W:
24209 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24210 break;
24211 default:
24212 MIPS_INVAL("MASK ADDUH.QB");
24213 generate_exception_end(ctx, EXCP_RI);
24214 break;
24216 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24217 gen_loongson_integer(ctx, op1, rd, rs, rt);
24218 } else {
24219 generate_exception_end(ctx, EXCP_RI);
24221 break;
24222 case OPC_LX_DSP:
24223 op2 = MASK_LX(ctx->opcode);
24224 switch (op2) {
24225 #if defined(TARGET_MIPS64)
24226 case OPC_LDX:
24227 #endif
24228 case OPC_LBUX:
24229 case OPC_LHX:
24230 case OPC_LWX:
24231 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24232 break;
24233 default: /* Invalid */
24234 MIPS_INVAL("MASK LX");
24235 generate_exception_end(ctx, EXCP_RI);
24236 break;
24238 break;
24239 case OPC_ABSQ_S_PH_DSP:
24240 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24241 switch (op2) {
24242 case OPC_ABSQ_S_QB:
24243 case OPC_ABSQ_S_PH:
24244 case OPC_ABSQ_S_W:
24245 case OPC_PRECEQ_W_PHL:
24246 case OPC_PRECEQ_W_PHR:
24247 case OPC_PRECEQU_PH_QBL:
24248 case OPC_PRECEQU_PH_QBR:
24249 case OPC_PRECEQU_PH_QBLA:
24250 case OPC_PRECEQU_PH_QBRA:
24251 case OPC_PRECEU_PH_QBL:
24252 case OPC_PRECEU_PH_QBR:
24253 case OPC_PRECEU_PH_QBLA:
24254 case OPC_PRECEU_PH_QBRA:
24255 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24256 break;
24257 case OPC_BITREV:
24258 case OPC_REPL_QB:
24259 case OPC_REPLV_QB:
24260 case OPC_REPL_PH:
24261 case OPC_REPLV_PH:
24262 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24263 break;
24264 default:
24265 MIPS_INVAL("MASK ABSQ_S.PH");
24266 generate_exception_end(ctx, EXCP_RI);
24267 break;
24269 break;
24270 case OPC_ADDU_QB_DSP:
24271 op2 = MASK_ADDU_QB(ctx->opcode);
24272 switch (op2) {
24273 case OPC_ADDQ_PH:
24274 case OPC_ADDQ_S_PH:
24275 case OPC_ADDQ_S_W:
24276 case OPC_ADDU_QB:
24277 case OPC_ADDU_S_QB:
24278 case OPC_ADDU_PH:
24279 case OPC_ADDU_S_PH:
24280 case OPC_SUBQ_PH:
24281 case OPC_SUBQ_S_PH:
24282 case OPC_SUBQ_S_W:
24283 case OPC_SUBU_QB:
24284 case OPC_SUBU_S_QB:
24285 case OPC_SUBU_PH:
24286 case OPC_SUBU_S_PH:
24287 case OPC_ADDSC:
24288 case OPC_ADDWC:
24289 case OPC_MODSUB:
24290 case OPC_RADDU_W_QB:
24291 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24292 break;
24293 case OPC_MULEU_S_PH_QBL:
24294 case OPC_MULEU_S_PH_QBR:
24295 case OPC_MULQ_RS_PH:
24296 case OPC_MULEQ_S_W_PHL:
24297 case OPC_MULEQ_S_W_PHR:
24298 case OPC_MULQ_S_PH:
24299 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24300 break;
24301 default: /* Invalid */
24302 MIPS_INVAL("MASK ADDU.QB");
24303 generate_exception_end(ctx, EXCP_RI);
24304 break;
24307 break;
24308 case OPC_CMPU_EQ_QB_DSP:
24309 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24310 switch (op2) {
24311 case OPC_PRECR_SRA_PH_W:
24312 case OPC_PRECR_SRA_R_PH_W:
24313 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24314 break;
24315 case OPC_PRECR_QB_PH:
24316 case OPC_PRECRQ_QB_PH:
24317 case OPC_PRECRQ_PH_W:
24318 case OPC_PRECRQ_RS_PH_W:
24319 case OPC_PRECRQU_S_QB_PH:
24320 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24321 break;
24322 case OPC_CMPU_EQ_QB:
24323 case OPC_CMPU_LT_QB:
24324 case OPC_CMPU_LE_QB:
24325 case OPC_CMP_EQ_PH:
24326 case OPC_CMP_LT_PH:
24327 case OPC_CMP_LE_PH:
24328 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24329 break;
24330 case OPC_CMPGU_EQ_QB:
24331 case OPC_CMPGU_LT_QB:
24332 case OPC_CMPGU_LE_QB:
24333 case OPC_CMPGDU_EQ_QB:
24334 case OPC_CMPGDU_LT_QB:
24335 case OPC_CMPGDU_LE_QB:
24336 case OPC_PICK_QB:
24337 case OPC_PICK_PH:
24338 case OPC_PACKRL_PH:
24339 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24340 break;
24341 default: /* Invalid */
24342 MIPS_INVAL("MASK CMPU.EQ.QB");
24343 generate_exception_end(ctx, EXCP_RI);
24344 break;
24346 break;
24347 case OPC_SHLL_QB_DSP:
24348 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24349 break;
24350 case OPC_DPA_W_PH_DSP:
24351 op2 = MASK_DPA_W_PH(ctx->opcode);
24352 switch (op2) {
24353 case OPC_DPAU_H_QBL:
24354 case OPC_DPAU_H_QBR:
24355 case OPC_DPSU_H_QBL:
24356 case OPC_DPSU_H_QBR:
24357 case OPC_DPA_W_PH:
24358 case OPC_DPAX_W_PH:
24359 case OPC_DPAQ_S_W_PH:
24360 case OPC_DPAQX_S_W_PH:
24361 case OPC_DPAQX_SA_W_PH:
24362 case OPC_DPS_W_PH:
24363 case OPC_DPSX_W_PH:
24364 case OPC_DPSQ_S_W_PH:
24365 case OPC_DPSQX_S_W_PH:
24366 case OPC_DPSQX_SA_W_PH:
24367 case OPC_MULSAQ_S_W_PH:
24368 case OPC_DPAQ_SA_L_W:
24369 case OPC_DPSQ_SA_L_W:
24370 case OPC_MAQ_S_W_PHL:
24371 case OPC_MAQ_S_W_PHR:
24372 case OPC_MAQ_SA_W_PHL:
24373 case OPC_MAQ_SA_W_PHR:
24374 case OPC_MULSA_W_PH:
24375 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24376 break;
24377 default: /* Invalid */
24378 MIPS_INVAL("MASK DPAW.PH");
24379 generate_exception_end(ctx, EXCP_RI);
24380 break;
24382 break;
24383 case OPC_INSV_DSP:
24384 op2 = MASK_INSV(ctx->opcode);
24385 switch (op2) {
24386 case OPC_INSV:
24387 check_dsp(ctx);
24389 TCGv t0, t1;
24391 if (rt == 0) {
24392 break;
24395 t0 = tcg_temp_new();
24396 t1 = tcg_temp_new();
24398 gen_load_gpr(t0, rt);
24399 gen_load_gpr(t1, rs);
24401 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24403 tcg_temp_free(t0);
24404 tcg_temp_free(t1);
24405 break;
24407 default: /* Invalid */
24408 MIPS_INVAL("MASK INSV");
24409 generate_exception_end(ctx, EXCP_RI);
24410 break;
24412 break;
24413 case OPC_APPEND_DSP:
24414 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24415 break;
24416 case OPC_EXTR_W_DSP:
24417 op2 = MASK_EXTR_W(ctx->opcode);
24418 switch (op2) {
24419 case OPC_EXTR_W:
24420 case OPC_EXTR_R_W:
24421 case OPC_EXTR_RS_W:
24422 case OPC_EXTR_S_H:
24423 case OPC_EXTRV_S_H:
24424 case OPC_EXTRV_W:
24425 case OPC_EXTRV_R_W:
24426 case OPC_EXTRV_RS_W:
24427 case OPC_EXTP:
24428 case OPC_EXTPV:
24429 case OPC_EXTPDP:
24430 case OPC_EXTPDPV:
24431 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24432 break;
24433 case OPC_RDDSP:
24434 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24435 break;
24436 case OPC_SHILO:
24437 case OPC_SHILOV:
24438 case OPC_MTHLIP:
24439 case OPC_WRDSP:
24440 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24441 break;
24442 default: /* Invalid */
24443 MIPS_INVAL("MASK EXTR.W");
24444 generate_exception_end(ctx, EXCP_RI);
24445 break;
24447 break;
24448 #if defined(TARGET_MIPS64)
24449 case OPC_DDIV_G_2E:
24450 case OPC_DDIVU_G_2E:
24451 case OPC_DMULT_G_2E:
24452 case OPC_DMULTU_G_2E:
24453 case OPC_DMOD_G_2E:
24454 case OPC_DMODU_G_2E:
24455 check_insn(ctx, INSN_LOONGSON2E);
24456 gen_loongson_integer(ctx, op1, rd, rs, rt);
24457 break;
24458 case OPC_ABSQ_S_QH_DSP:
24459 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24460 switch (op2) {
24461 case OPC_PRECEQ_L_PWL:
24462 case OPC_PRECEQ_L_PWR:
24463 case OPC_PRECEQ_PW_QHL:
24464 case OPC_PRECEQ_PW_QHR:
24465 case OPC_PRECEQ_PW_QHLA:
24466 case OPC_PRECEQ_PW_QHRA:
24467 case OPC_PRECEQU_QH_OBL:
24468 case OPC_PRECEQU_QH_OBR:
24469 case OPC_PRECEQU_QH_OBLA:
24470 case OPC_PRECEQU_QH_OBRA:
24471 case OPC_PRECEU_QH_OBL:
24472 case OPC_PRECEU_QH_OBR:
24473 case OPC_PRECEU_QH_OBLA:
24474 case OPC_PRECEU_QH_OBRA:
24475 case OPC_ABSQ_S_OB:
24476 case OPC_ABSQ_S_PW:
24477 case OPC_ABSQ_S_QH:
24478 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24479 break;
24480 case OPC_REPL_OB:
24481 case OPC_REPL_PW:
24482 case OPC_REPL_QH:
24483 case OPC_REPLV_OB:
24484 case OPC_REPLV_PW:
24485 case OPC_REPLV_QH:
24486 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24487 break;
24488 default: /* Invalid */
24489 MIPS_INVAL("MASK ABSQ_S.QH");
24490 generate_exception_end(ctx, EXCP_RI);
24491 break;
24493 break;
24494 case OPC_ADDU_OB_DSP:
24495 op2 = MASK_ADDU_OB(ctx->opcode);
24496 switch (op2) {
24497 case OPC_RADDU_L_OB:
24498 case OPC_SUBQ_PW:
24499 case OPC_SUBQ_S_PW:
24500 case OPC_SUBQ_QH:
24501 case OPC_SUBQ_S_QH:
24502 case OPC_SUBU_OB:
24503 case OPC_SUBU_S_OB:
24504 case OPC_SUBU_QH:
24505 case OPC_SUBU_S_QH:
24506 case OPC_SUBUH_OB:
24507 case OPC_SUBUH_R_OB:
24508 case OPC_ADDQ_PW:
24509 case OPC_ADDQ_S_PW:
24510 case OPC_ADDQ_QH:
24511 case OPC_ADDQ_S_QH:
24512 case OPC_ADDU_OB:
24513 case OPC_ADDU_S_OB:
24514 case OPC_ADDU_QH:
24515 case OPC_ADDU_S_QH:
24516 case OPC_ADDUH_OB:
24517 case OPC_ADDUH_R_OB:
24518 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24519 break;
24520 case OPC_MULEQ_S_PW_QHL:
24521 case OPC_MULEQ_S_PW_QHR:
24522 case OPC_MULEU_S_QH_OBL:
24523 case OPC_MULEU_S_QH_OBR:
24524 case OPC_MULQ_RS_QH:
24525 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24526 break;
24527 default: /* Invalid */
24528 MIPS_INVAL("MASK ADDU.OB");
24529 generate_exception_end(ctx, EXCP_RI);
24530 break;
24532 break;
24533 case OPC_CMPU_EQ_OB_DSP:
24534 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24535 switch (op2) {
24536 case OPC_PRECR_SRA_QH_PW:
24537 case OPC_PRECR_SRA_R_QH_PW:
24538 /* Return value is rt. */
24539 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24540 break;
24541 case OPC_PRECR_OB_QH:
24542 case OPC_PRECRQ_OB_QH:
24543 case OPC_PRECRQ_PW_L:
24544 case OPC_PRECRQ_QH_PW:
24545 case OPC_PRECRQ_RS_QH_PW:
24546 case OPC_PRECRQU_S_OB_QH:
24547 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24548 break;
24549 case OPC_CMPU_EQ_OB:
24550 case OPC_CMPU_LT_OB:
24551 case OPC_CMPU_LE_OB:
24552 case OPC_CMP_EQ_QH:
24553 case OPC_CMP_LT_QH:
24554 case OPC_CMP_LE_QH:
24555 case OPC_CMP_EQ_PW:
24556 case OPC_CMP_LT_PW:
24557 case OPC_CMP_LE_PW:
24558 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24559 break;
24560 case OPC_CMPGDU_EQ_OB:
24561 case OPC_CMPGDU_LT_OB:
24562 case OPC_CMPGDU_LE_OB:
24563 case OPC_CMPGU_EQ_OB:
24564 case OPC_CMPGU_LT_OB:
24565 case OPC_CMPGU_LE_OB:
24566 case OPC_PACKRL_PW:
24567 case OPC_PICK_OB:
24568 case OPC_PICK_PW:
24569 case OPC_PICK_QH:
24570 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24571 break;
24572 default: /* Invalid */
24573 MIPS_INVAL("MASK CMPU_EQ.OB");
24574 generate_exception_end(ctx, EXCP_RI);
24575 break;
24577 break;
24578 case OPC_DAPPEND_DSP:
24579 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24580 break;
24581 case OPC_DEXTR_W_DSP:
24582 op2 = MASK_DEXTR_W(ctx->opcode);
24583 switch (op2) {
24584 case OPC_DEXTP:
24585 case OPC_DEXTPDP:
24586 case OPC_DEXTPDPV:
24587 case OPC_DEXTPV:
24588 case OPC_DEXTR_L:
24589 case OPC_DEXTR_R_L:
24590 case OPC_DEXTR_RS_L:
24591 case OPC_DEXTR_W:
24592 case OPC_DEXTR_R_W:
24593 case OPC_DEXTR_RS_W:
24594 case OPC_DEXTR_S_H:
24595 case OPC_DEXTRV_L:
24596 case OPC_DEXTRV_R_L:
24597 case OPC_DEXTRV_RS_L:
24598 case OPC_DEXTRV_S_H:
24599 case OPC_DEXTRV_W:
24600 case OPC_DEXTRV_R_W:
24601 case OPC_DEXTRV_RS_W:
24602 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24603 break;
24604 case OPC_DMTHLIP:
24605 case OPC_DSHILO:
24606 case OPC_DSHILOV:
24607 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24608 break;
24609 default: /* Invalid */
24610 MIPS_INVAL("MASK EXTR.W");
24611 generate_exception_end(ctx, EXCP_RI);
24612 break;
24614 break;
24615 case OPC_DPAQ_W_QH_DSP:
24616 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24617 switch (op2) {
24618 case OPC_DPAU_H_OBL:
24619 case OPC_DPAU_H_OBR:
24620 case OPC_DPSU_H_OBL:
24621 case OPC_DPSU_H_OBR:
24622 case OPC_DPA_W_QH:
24623 case OPC_DPAQ_S_W_QH:
24624 case OPC_DPS_W_QH:
24625 case OPC_DPSQ_S_W_QH:
24626 case OPC_MULSAQ_S_W_QH:
24627 case OPC_DPAQ_SA_L_PW:
24628 case OPC_DPSQ_SA_L_PW:
24629 case OPC_MULSAQ_S_L_PW:
24630 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24631 break;
24632 case OPC_MAQ_S_W_QHLL:
24633 case OPC_MAQ_S_W_QHLR:
24634 case OPC_MAQ_S_W_QHRL:
24635 case OPC_MAQ_S_W_QHRR:
24636 case OPC_MAQ_SA_W_QHLL:
24637 case OPC_MAQ_SA_W_QHLR:
24638 case OPC_MAQ_SA_W_QHRL:
24639 case OPC_MAQ_SA_W_QHRR:
24640 case OPC_MAQ_S_L_PWL:
24641 case OPC_MAQ_S_L_PWR:
24642 case OPC_DMADD:
24643 case OPC_DMADDU:
24644 case OPC_DMSUB:
24645 case OPC_DMSUBU:
24646 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24647 break;
24648 default: /* Invalid */
24649 MIPS_INVAL("MASK DPAQ.W.QH");
24650 generate_exception_end(ctx, EXCP_RI);
24651 break;
24653 break;
24654 case OPC_DINSV_DSP:
24655 op2 = MASK_INSV(ctx->opcode);
24656 switch (op2) {
24657 case OPC_DINSV:
24659 TCGv t0, t1;
24661 if (rt == 0) {
24662 break;
24664 check_dsp(ctx);
24666 t0 = tcg_temp_new();
24667 t1 = tcg_temp_new();
24669 gen_load_gpr(t0, rt);
24670 gen_load_gpr(t1, rs);
24672 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24674 tcg_temp_free(t0);
24675 tcg_temp_free(t1);
24676 break;
24678 default: /* Invalid */
24679 MIPS_INVAL("MASK DINSV");
24680 generate_exception_end(ctx, EXCP_RI);
24681 break;
24683 break;
24684 case OPC_SHLL_OB_DSP:
24685 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24686 break;
24687 #endif
24688 default: /* Invalid */
24689 MIPS_INVAL("special3_legacy");
24690 generate_exception_end(ctx, EXCP_RI);
24691 break;
24695 static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
24697 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
24699 switch (opc) {
24700 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
24701 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
24702 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
24703 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
24704 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
24705 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
24706 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
24707 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
24708 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
24709 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
24710 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
24711 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
24712 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
24713 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
24714 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
24715 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
24716 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
24717 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
24718 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
24719 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
24720 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
24721 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
24722 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
24723 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
24724 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
24725 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
24726 break;
24727 default:
24728 MIPS_INVAL("TX79 MMI class MMI0");
24729 generate_exception_end(ctx, EXCP_RI);
24730 break;
24734 static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
24736 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
24738 switch (opc) {
24739 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
24740 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
24741 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
24742 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
24743 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
24744 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
24745 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
24746 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
24747 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
24748 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
24749 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
24750 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
24751 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
24752 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
24753 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
24754 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
24755 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
24756 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
24757 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
24758 break;
24759 default:
24760 MIPS_INVAL("TX79 MMI class MMI1");
24761 generate_exception_end(ctx, EXCP_RI);
24762 break;
24766 static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
24768 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
24770 switch (opc) {
24771 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
24772 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
24773 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
24774 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
24775 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
24776 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
24777 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
24778 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
24779 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
24780 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
24781 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
24782 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
24783 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
24784 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
24785 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
24786 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
24787 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
24788 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
24789 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
24790 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
24791 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
24792 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
24793 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
24794 break;
24795 default:
24796 MIPS_INVAL("TX79 MMI class MMI2");
24797 generate_exception_end(ctx, EXCP_RI);
24798 break;
24802 static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
24804 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
24806 switch (opc) {
24807 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
24808 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
24809 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
24810 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
24811 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
24812 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
24813 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
24814 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
24815 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
24816 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
24817 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
24818 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
24819 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
24820 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
24821 break;
24822 default:
24823 MIPS_INVAL("TX79 MMI class MMI3");
24824 generate_exception_end(ctx, EXCP_RI);
24825 break;
24829 static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
24831 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
24832 int rs = extract32(ctx->opcode, 21, 5);
24833 int rt = extract32(ctx->opcode, 16, 5);
24834 int rd = extract32(ctx->opcode, 11, 5);
24836 switch (opc) {
24837 case TX79_MMI_CLASS_MMI0:
24838 decode_tx79_mmi0(env, ctx);
24839 break;
24840 case TX79_MMI_CLASS_MMI1:
24841 decode_tx79_mmi1(env, ctx);
24842 break;
24843 case TX79_MMI_CLASS_MMI2:
24844 decode_tx79_mmi2(env, ctx);
24845 break;
24846 case TX79_MMI_CLASS_MMI3:
24847 decode_tx79_mmi3(env, ctx);
24848 break;
24849 case TX79_MMI_MULT1:
24850 case TX79_MMI_MULTU1:
24851 gen_mul_txx9(ctx, opc, rd, rs, rt);
24852 break;
24853 case TX79_MMI_DIV1:
24854 case TX79_MMI_DIVU1:
24855 gen_muldiv(ctx, opc, 1, rs, rt);
24856 break;
24857 case TX79_MMI_MTLO1:
24858 case TX79_MMI_MTHI1:
24859 gen_HILO(ctx, opc, 1, rs);
24860 break;
24861 case TX79_MMI_MFLO1:
24862 case TX79_MMI_MFHI1:
24863 gen_HILO(ctx, opc, 1, rd);
24864 break;
24865 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
24866 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
24867 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
24868 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
24869 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
24870 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
24871 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
24872 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
24873 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
24874 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
24875 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
24876 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
24877 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
24878 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
24879 break;
24880 default:
24881 MIPS_INVAL("TX79 MMI class");
24882 generate_exception_end(ctx, EXCP_RI);
24883 break;
24887 static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
24889 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
24892 static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
24894 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
24898 * The TX79-specific instruction Store Quadword
24900 * +--------+-------+-------+------------------------+
24901 * | 011111 | base | rt | offset | SQ
24902 * +--------+-------+-------+------------------------+
24903 * 6 5 5 16
24905 * has the same opcode as the Read Hardware Register instruction
24907 * +--------+-------+-------+-------+-------+--------+
24908 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24909 * +--------+-------+-------+-------+-------+--------+
24910 * 6 5 5 5 5 6
24912 * that is required, trapped and emulated by the Linux kernel. However, all
24913 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24914 * offset is odd. Therefore all valid SQ instructions can execute normally.
24915 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24916 * between SQ and RDHWR, as the Linux kernel does.
24918 static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
24920 int base = extract32(ctx->opcode, 21, 5);
24921 int rt = extract32(ctx->opcode, 16, 5);
24922 int offset = extract32(ctx->opcode, 0, 16);
24924 #ifdef CONFIG_USER_ONLY
24925 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24926 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24928 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24929 int rd = extract32(ctx->opcode, 11, 5);
24931 gen_rdhwr(ctx, rt, rd, 0);
24932 return;
24934 #endif
24936 gen_tx79_sq(ctx, base, rt, offset);
24939 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24941 int rs, rt, rd, sa;
24942 uint32_t op1, op2;
24943 int16_t imm;
24945 rs = (ctx->opcode >> 21) & 0x1f;
24946 rt = (ctx->opcode >> 16) & 0x1f;
24947 rd = (ctx->opcode >> 11) & 0x1f;
24948 sa = (ctx->opcode >> 6) & 0x1f;
24949 imm = sextract32(ctx->opcode, 7, 9);
24951 op1 = MASK_SPECIAL3(ctx->opcode);
24954 * EVA loads and stores overlap Loongson 2E instructions decoded by
24955 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24956 * EVA is absent.
24958 if (ctx->eva) {
24959 switch (op1) {
24960 case OPC_LWLE:
24961 case OPC_LWRE:
24962 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24963 /* fall through */
24964 case OPC_LBUE:
24965 case OPC_LHUE:
24966 case OPC_LBE:
24967 case OPC_LHE:
24968 case OPC_LLE:
24969 case OPC_LWE:
24970 check_cp0_enabled(ctx);
24971 gen_ld(ctx, op1, rt, rs, imm);
24972 return;
24973 case OPC_SWLE:
24974 case OPC_SWRE:
24975 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24976 /* fall through */
24977 case OPC_SBE:
24978 case OPC_SHE:
24979 case OPC_SWE:
24980 check_cp0_enabled(ctx);
24981 gen_st(ctx, op1, rt, rs, imm);
24982 return;
24983 case OPC_SCE:
24984 check_cp0_enabled(ctx);
24985 gen_st_cond(ctx, op1, rt, rs, imm);
24986 return;
24987 case OPC_CACHEE:
24988 check_cp0_enabled(ctx);
24989 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24990 gen_cache_operation(ctx, rt, rs, imm);
24992 /* Treat as NOP. */
24993 return;
24994 case OPC_PREFE:
24995 check_cp0_enabled(ctx);
24996 /* Treat as NOP. */
24997 return;
25001 switch (op1) {
25002 case OPC_EXT:
25003 case OPC_INS:
25004 check_insn(ctx, ISA_MIPS32R2);
25005 gen_bitops(ctx, op1, rt, rs, sa, rd);
25006 break;
25007 case OPC_BSHFL:
25008 op2 = MASK_BSHFL(ctx->opcode);
25009 switch (op2) {
25010 case OPC_ALIGN:
25011 case OPC_ALIGN_1:
25012 case OPC_ALIGN_2:
25013 case OPC_ALIGN_3:
25014 case OPC_BITSWAP:
25015 check_insn(ctx, ISA_MIPS32R6);
25016 decode_opc_special3_r6(env, ctx);
25017 break;
25018 default:
25019 check_insn(ctx, ISA_MIPS32R2);
25020 gen_bshfl(ctx, op2, rt, rd);
25021 break;
25023 break;
25024 #if defined(TARGET_MIPS64)
25025 case OPC_DEXTM:
25026 case OPC_DEXTU:
25027 case OPC_DEXT:
25028 case OPC_DINSM:
25029 case OPC_DINSU:
25030 case OPC_DINS:
25031 check_insn(ctx, ISA_MIPS64R2);
25032 check_mips_64(ctx);
25033 gen_bitops(ctx, op1, rt, rs, sa, rd);
25034 break;
25035 case OPC_DBSHFL:
25036 op2 = MASK_DBSHFL(ctx->opcode);
25037 switch (op2) {
25038 case OPC_DALIGN:
25039 case OPC_DALIGN_1:
25040 case OPC_DALIGN_2:
25041 case OPC_DALIGN_3:
25042 case OPC_DALIGN_4:
25043 case OPC_DALIGN_5:
25044 case OPC_DALIGN_6:
25045 case OPC_DALIGN_7:
25046 case OPC_DBITSWAP:
25047 check_insn(ctx, ISA_MIPS32R6);
25048 decode_opc_special3_r6(env, ctx);
25049 break;
25050 default:
25051 check_insn(ctx, ISA_MIPS64R2);
25052 check_mips_64(ctx);
25053 op2 = MASK_DBSHFL(ctx->opcode);
25054 gen_bshfl(ctx, op2, rt, rd);
25055 break;
25057 break;
25058 #endif
25059 case OPC_RDHWR:
25060 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
25061 break;
25062 case OPC_FORK:
25063 check_mt(ctx);
25065 TCGv t0 = tcg_temp_new();
25066 TCGv t1 = tcg_temp_new();
25068 gen_load_gpr(t0, rt);
25069 gen_load_gpr(t1, rs);
25070 gen_helper_fork(t0, t1);
25071 tcg_temp_free(t0);
25072 tcg_temp_free(t1);
25074 break;
25075 case OPC_YIELD:
25076 check_mt(ctx);
25078 TCGv t0 = tcg_temp_new();
25080 gen_load_gpr(t0, rs);
25081 gen_helper_yield(t0, cpu_env, t0);
25082 gen_store_gpr(t0, rd);
25083 tcg_temp_free(t0);
25085 break;
25086 default:
25087 if (ctx->insn_flags & ISA_MIPS32R6) {
25088 decode_opc_special3_r6(env, ctx);
25089 } else {
25090 decode_opc_special3_legacy(env, ctx);
25095 /* MIPS SIMD Architecture (MSA) */
25096 static inline int check_msa_access(DisasContext *ctx)
25098 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
25099 !(ctx->hflags & MIPS_HFLAG_F64))) {
25100 generate_exception_end(ctx, EXCP_RI);
25101 return 0;
25104 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
25105 if (ctx->insn_flags & ASE_MSA) {
25106 generate_exception_end(ctx, EXCP_MSADIS);
25107 return 0;
25108 } else {
25109 generate_exception_end(ctx, EXCP_RI);
25110 return 0;
25113 return 1;
25116 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
25118 /* generates tcg ops to check if any element is 0 */
25119 /* Note this function only works with MSA_WRLEN = 128 */
25120 uint64_t eval_zero_or_big = 0;
25121 uint64_t eval_big = 0;
25122 TCGv_i64 t0 = tcg_temp_new_i64();
25123 TCGv_i64 t1 = tcg_temp_new_i64();
25124 switch (df) {
25125 case DF_BYTE:
25126 eval_zero_or_big = 0x0101010101010101ULL;
25127 eval_big = 0x8080808080808080ULL;
25128 break;
25129 case DF_HALF:
25130 eval_zero_or_big = 0x0001000100010001ULL;
25131 eval_big = 0x8000800080008000ULL;
25132 break;
25133 case DF_WORD:
25134 eval_zero_or_big = 0x0000000100000001ULL;
25135 eval_big = 0x8000000080000000ULL;
25136 break;
25137 case DF_DOUBLE:
25138 eval_zero_or_big = 0x0000000000000001ULL;
25139 eval_big = 0x8000000000000000ULL;
25140 break;
25142 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
25143 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
25144 tcg_gen_andi_i64(t0, t0, eval_big);
25145 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
25146 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
25147 tcg_gen_andi_i64(t1, t1, eval_big);
25148 tcg_gen_or_i64(t0, t0, t1);
25149 /* if all bits are zero then all elements are not zero */
25150 /* if some bit is non-zero then some element is zero */
25151 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
25152 tcg_gen_trunc_i64_tl(tresult, t0);
25153 tcg_temp_free_i64(t0);
25154 tcg_temp_free_i64(t1);
25157 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
25159 uint8_t df = (ctx->opcode >> 21) & 0x3;
25160 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25161 int64_t s16 = (int16_t)ctx->opcode;
25163 check_msa_access(ctx);
25165 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25166 generate_exception_end(ctx, EXCP_RI);
25167 return;
25169 switch (op1) {
25170 case OPC_BZ_V:
25171 case OPC_BNZ_V:
25173 TCGv_i64 t0 = tcg_temp_new_i64();
25174 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
25175 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
25176 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
25177 tcg_gen_trunc_i64_tl(bcond, t0);
25178 tcg_temp_free_i64(t0);
25180 break;
25181 case OPC_BZ_B:
25182 case OPC_BZ_H:
25183 case OPC_BZ_W:
25184 case OPC_BZ_D:
25185 gen_check_zero_element(bcond, df, wt);
25186 break;
25187 case OPC_BNZ_B:
25188 case OPC_BNZ_H:
25189 case OPC_BNZ_W:
25190 case OPC_BNZ_D:
25191 gen_check_zero_element(bcond, df, wt);
25192 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
25193 break;
25196 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
25198 ctx->hflags |= MIPS_HFLAG_BC;
25199 ctx->hflags |= MIPS_HFLAG_BDS32;
25202 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
25204 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
25205 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
25206 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25207 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25209 TCGv_i32 twd = tcg_const_i32(wd);
25210 TCGv_i32 tws = tcg_const_i32(ws);
25211 TCGv_i32 ti8 = tcg_const_i32(i8);
25213 switch (MASK_MSA_I8(ctx->opcode)) {
25214 case OPC_ANDI_B:
25215 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
25216 break;
25217 case OPC_ORI_B:
25218 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
25219 break;
25220 case OPC_NORI_B:
25221 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
25222 break;
25223 case OPC_XORI_B:
25224 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
25225 break;
25226 case OPC_BMNZI_B:
25227 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
25228 break;
25229 case OPC_BMZI_B:
25230 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
25231 break;
25232 case OPC_BSELI_B:
25233 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
25234 break;
25235 case OPC_SHF_B:
25236 case OPC_SHF_H:
25237 case OPC_SHF_W:
25239 uint8_t df = (ctx->opcode >> 24) & 0x3;
25240 if (df == DF_DOUBLE) {
25241 generate_exception_end(ctx, EXCP_RI);
25242 } else {
25243 TCGv_i32 tdf = tcg_const_i32(df);
25244 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
25245 tcg_temp_free_i32(tdf);
25248 break;
25249 default:
25250 MIPS_INVAL("MSA instruction");
25251 generate_exception_end(ctx, EXCP_RI);
25252 break;
25255 tcg_temp_free_i32(twd);
25256 tcg_temp_free_i32(tws);
25257 tcg_temp_free_i32(ti8);
25260 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
25262 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25263 uint8_t df = (ctx->opcode >> 21) & 0x3;
25264 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
25265 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
25266 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25267 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25269 TCGv_i32 tdf = tcg_const_i32(df);
25270 TCGv_i32 twd = tcg_const_i32(wd);
25271 TCGv_i32 tws = tcg_const_i32(ws);
25272 TCGv_i32 timm = tcg_temp_new_i32();
25273 tcg_gen_movi_i32(timm, u5);
25275 switch (MASK_MSA_I5(ctx->opcode)) {
25276 case OPC_ADDVI_df:
25277 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
25278 break;
25279 case OPC_SUBVI_df:
25280 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
25281 break;
25282 case OPC_MAXI_S_df:
25283 tcg_gen_movi_i32(timm, s5);
25284 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
25285 break;
25286 case OPC_MAXI_U_df:
25287 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
25288 break;
25289 case OPC_MINI_S_df:
25290 tcg_gen_movi_i32(timm, s5);
25291 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
25292 break;
25293 case OPC_MINI_U_df:
25294 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
25295 break;
25296 case OPC_CEQI_df:
25297 tcg_gen_movi_i32(timm, s5);
25298 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
25299 break;
25300 case OPC_CLTI_S_df:
25301 tcg_gen_movi_i32(timm, s5);
25302 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
25303 break;
25304 case OPC_CLTI_U_df:
25305 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
25306 break;
25307 case OPC_CLEI_S_df:
25308 tcg_gen_movi_i32(timm, s5);
25309 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
25310 break;
25311 case OPC_CLEI_U_df:
25312 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
25313 break;
25314 case OPC_LDI_df:
25316 int32_t s10 = sextract32(ctx->opcode, 11, 10);
25317 tcg_gen_movi_i32(timm, s10);
25318 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
25320 break;
25321 default:
25322 MIPS_INVAL("MSA instruction");
25323 generate_exception_end(ctx, EXCP_RI);
25324 break;
25327 tcg_temp_free_i32(tdf);
25328 tcg_temp_free_i32(twd);
25329 tcg_temp_free_i32(tws);
25330 tcg_temp_free_i32(timm);
25333 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
25335 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25336 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
25337 uint32_t df = 0, m = 0;
25338 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25339 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25341 TCGv_i32 tdf;
25342 TCGv_i32 tm;
25343 TCGv_i32 twd;
25344 TCGv_i32 tws;
25346 if ((dfm & 0x40) == 0x00) {
25347 m = dfm & 0x3f;
25348 df = DF_DOUBLE;
25349 } else if ((dfm & 0x60) == 0x40) {
25350 m = dfm & 0x1f;
25351 df = DF_WORD;
25352 } else if ((dfm & 0x70) == 0x60) {
25353 m = dfm & 0x0f;
25354 df = DF_HALF;
25355 } else if ((dfm & 0x78) == 0x70) {
25356 m = dfm & 0x7;
25357 df = DF_BYTE;
25358 } else {
25359 generate_exception_end(ctx, EXCP_RI);
25360 return;
25363 tdf = tcg_const_i32(df);
25364 tm = tcg_const_i32(m);
25365 twd = tcg_const_i32(wd);
25366 tws = tcg_const_i32(ws);
25368 switch (MASK_MSA_BIT(ctx->opcode)) {
25369 case OPC_SLLI_df:
25370 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
25371 break;
25372 case OPC_SRAI_df:
25373 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
25374 break;
25375 case OPC_SRLI_df:
25376 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
25377 break;
25378 case OPC_BCLRI_df:
25379 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
25380 break;
25381 case OPC_BSETI_df:
25382 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
25383 break;
25384 case OPC_BNEGI_df:
25385 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
25386 break;
25387 case OPC_BINSLI_df:
25388 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
25389 break;
25390 case OPC_BINSRI_df:
25391 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
25392 break;
25393 case OPC_SAT_S_df:
25394 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
25395 break;
25396 case OPC_SAT_U_df:
25397 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
25398 break;
25399 case OPC_SRARI_df:
25400 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
25401 break;
25402 case OPC_SRLRI_df:
25403 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
25404 break;
25405 default:
25406 MIPS_INVAL("MSA instruction");
25407 generate_exception_end(ctx, EXCP_RI);
25408 break;
25411 tcg_temp_free_i32(tdf);
25412 tcg_temp_free_i32(tm);
25413 tcg_temp_free_i32(twd);
25414 tcg_temp_free_i32(tws);
25417 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
25419 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25420 uint8_t df = (ctx->opcode >> 21) & 0x3;
25421 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25422 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25423 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25425 TCGv_i32 tdf = tcg_const_i32(df);
25426 TCGv_i32 twd = tcg_const_i32(wd);
25427 TCGv_i32 tws = tcg_const_i32(ws);
25428 TCGv_i32 twt = tcg_const_i32(wt);
25430 switch (MASK_MSA_3R(ctx->opcode)) {
25431 case OPC_SLL_df:
25432 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
25433 break;
25434 case OPC_ADDV_df:
25435 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
25436 break;
25437 case OPC_CEQ_df:
25438 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
25439 break;
25440 case OPC_ADD_A_df:
25441 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
25442 break;
25443 case OPC_SUBS_S_df:
25444 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
25445 break;
25446 case OPC_MULV_df:
25447 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
25448 break;
25449 case OPC_SLD_df:
25450 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
25451 break;
25452 case OPC_VSHF_df:
25453 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
25454 break;
25455 case OPC_SRA_df:
25456 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
25457 break;
25458 case OPC_SUBV_df:
25459 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
25460 break;
25461 case OPC_ADDS_A_df:
25462 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
25463 break;
25464 case OPC_SUBS_U_df:
25465 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
25466 break;
25467 case OPC_MADDV_df:
25468 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
25469 break;
25470 case OPC_SPLAT_df:
25471 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
25472 break;
25473 case OPC_SRAR_df:
25474 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
25475 break;
25476 case OPC_SRL_df:
25477 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
25478 break;
25479 case OPC_MAX_S_df:
25480 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
25481 break;
25482 case OPC_CLT_S_df:
25483 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
25484 break;
25485 case OPC_ADDS_S_df:
25486 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
25487 break;
25488 case OPC_SUBSUS_U_df:
25489 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
25490 break;
25491 case OPC_MSUBV_df:
25492 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
25493 break;
25494 case OPC_PCKEV_df:
25495 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
25496 break;
25497 case OPC_SRLR_df:
25498 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
25499 break;
25500 case OPC_BCLR_df:
25501 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
25502 break;
25503 case OPC_MAX_U_df:
25504 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
25505 break;
25506 case OPC_CLT_U_df:
25507 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
25508 break;
25509 case OPC_ADDS_U_df:
25510 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
25511 break;
25512 case OPC_SUBSUU_S_df:
25513 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
25514 break;
25515 case OPC_PCKOD_df:
25516 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
25517 break;
25518 case OPC_BSET_df:
25519 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
25520 break;
25521 case OPC_MIN_S_df:
25522 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
25523 break;
25524 case OPC_CLE_S_df:
25525 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
25526 break;
25527 case OPC_AVE_S_df:
25528 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
25529 break;
25530 case OPC_ASUB_S_df:
25531 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
25532 break;
25533 case OPC_DIV_S_df:
25534 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
25535 break;
25536 case OPC_ILVL_df:
25537 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
25538 break;
25539 case OPC_BNEG_df:
25540 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
25541 break;
25542 case OPC_MIN_U_df:
25543 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
25544 break;
25545 case OPC_CLE_U_df:
25546 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
25547 break;
25548 case OPC_AVE_U_df:
25549 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
25550 break;
25551 case OPC_ASUB_U_df:
25552 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
25553 break;
25554 case OPC_DIV_U_df:
25555 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
25556 break;
25557 case OPC_ILVR_df:
25558 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
25559 break;
25560 case OPC_BINSL_df:
25561 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
25562 break;
25563 case OPC_MAX_A_df:
25564 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
25565 break;
25566 case OPC_AVER_S_df:
25567 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
25568 break;
25569 case OPC_MOD_S_df:
25570 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
25571 break;
25572 case OPC_ILVEV_df:
25573 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
25574 break;
25575 case OPC_BINSR_df:
25576 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
25577 break;
25578 case OPC_MIN_A_df:
25579 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
25580 break;
25581 case OPC_AVER_U_df:
25582 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
25583 break;
25584 case OPC_MOD_U_df:
25585 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
25586 break;
25587 case OPC_ILVOD_df:
25588 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
25589 break;
25591 case OPC_DOTP_S_df:
25592 case OPC_DOTP_U_df:
25593 case OPC_DPADD_S_df:
25594 case OPC_DPADD_U_df:
25595 case OPC_DPSUB_S_df:
25596 case OPC_HADD_S_df:
25597 case OPC_DPSUB_U_df:
25598 case OPC_HADD_U_df:
25599 case OPC_HSUB_S_df:
25600 case OPC_HSUB_U_df:
25601 if (df == DF_BYTE) {
25602 generate_exception_end(ctx, EXCP_RI);
25603 break;
25605 switch (MASK_MSA_3R(ctx->opcode)) {
25606 case OPC_DOTP_S_df:
25607 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
25608 break;
25609 case OPC_DOTP_U_df:
25610 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
25611 break;
25612 case OPC_DPADD_S_df:
25613 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
25614 break;
25615 case OPC_DPADD_U_df:
25616 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
25617 break;
25618 case OPC_DPSUB_S_df:
25619 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
25620 break;
25621 case OPC_HADD_S_df:
25622 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
25623 break;
25624 case OPC_DPSUB_U_df:
25625 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
25626 break;
25627 case OPC_HADD_U_df:
25628 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
25629 break;
25630 case OPC_HSUB_S_df:
25631 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
25632 break;
25633 case OPC_HSUB_U_df:
25634 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
25635 break;
25637 break;
25638 default:
25639 MIPS_INVAL("MSA instruction");
25640 generate_exception_end(ctx, EXCP_RI);
25641 break;
25643 tcg_temp_free_i32(twd);
25644 tcg_temp_free_i32(tws);
25645 tcg_temp_free_i32(twt);
25646 tcg_temp_free_i32(tdf);
25649 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
25651 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
25652 uint8_t source = (ctx->opcode >> 11) & 0x1f;
25653 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
25654 TCGv telm = tcg_temp_new();
25655 TCGv_i32 tsr = tcg_const_i32(source);
25656 TCGv_i32 tdt = tcg_const_i32(dest);
25658 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
25659 case OPC_CTCMSA:
25660 gen_load_gpr(telm, source);
25661 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
25662 break;
25663 case OPC_CFCMSA:
25664 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
25665 gen_store_gpr(telm, dest);
25666 break;
25667 case OPC_MOVE_V:
25668 gen_helper_msa_move_v(cpu_env, tdt, tsr);
25669 break;
25670 default:
25671 MIPS_INVAL("MSA instruction");
25672 generate_exception_end(ctx, EXCP_RI);
25673 break;
25676 tcg_temp_free(telm);
25677 tcg_temp_free_i32(tdt);
25678 tcg_temp_free_i32(tsr);
25681 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
25682 uint32_t n)
25684 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25685 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25686 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25688 TCGv_i32 tws = tcg_const_i32(ws);
25689 TCGv_i32 twd = tcg_const_i32(wd);
25690 TCGv_i32 tn = tcg_const_i32(n);
25691 TCGv_i32 tdf = tcg_const_i32(df);
25693 switch (MASK_MSA_ELM(ctx->opcode)) {
25694 case OPC_SLDI_df:
25695 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
25696 break;
25697 case OPC_SPLATI_df:
25698 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
25699 break;
25700 case OPC_INSVE_df:
25701 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
25702 break;
25703 case OPC_COPY_S_df:
25704 case OPC_COPY_U_df:
25705 case OPC_INSERT_df:
25706 #if !defined(TARGET_MIPS64)
25707 /* Double format valid only for MIPS64 */
25708 if (df == DF_DOUBLE) {
25709 generate_exception_end(ctx, EXCP_RI);
25710 break;
25712 #endif
25713 switch (MASK_MSA_ELM(ctx->opcode)) {
25714 case OPC_COPY_S_df:
25715 if (likely(wd != 0)) {
25716 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
25718 break;
25719 case OPC_COPY_U_df:
25720 if (likely(wd != 0)) {
25721 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
25723 break;
25724 case OPC_INSERT_df:
25725 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
25726 break;
25728 break;
25729 default:
25730 MIPS_INVAL("MSA instruction");
25731 generate_exception_end(ctx, EXCP_RI);
25733 tcg_temp_free_i32(twd);
25734 tcg_temp_free_i32(tws);
25735 tcg_temp_free_i32(tn);
25736 tcg_temp_free_i32(tdf);
25739 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
25741 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
25742 uint32_t df = 0, n = 0;
25744 if ((dfn & 0x30) == 0x00) {
25745 n = dfn & 0x0f;
25746 df = DF_BYTE;
25747 } else if ((dfn & 0x38) == 0x20) {
25748 n = dfn & 0x07;
25749 df = DF_HALF;
25750 } else if ((dfn & 0x3c) == 0x30) {
25751 n = dfn & 0x03;
25752 df = DF_WORD;
25753 } else if ((dfn & 0x3e) == 0x38) {
25754 n = dfn & 0x01;
25755 df = DF_DOUBLE;
25756 } else if (dfn == 0x3E) {
25757 /* CTCMSA, CFCMSA, MOVE.V */
25758 gen_msa_elm_3e(env, ctx);
25759 return;
25760 } else {
25761 generate_exception_end(ctx, EXCP_RI);
25762 return;
25765 gen_msa_elm_df(env, ctx, df, n);
25768 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25770 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25771 uint8_t df = (ctx->opcode >> 21) & 0x1;
25772 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25773 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25774 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25776 TCGv_i32 twd = tcg_const_i32(wd);
25777 TCGv_i32 tws = tcg_const_i32(ws);
25778 TCGv_i32 twt = tcg_const_i32(wt);
25779 TCGv_i32 tdf = tcg_temp_new_i32();
25781 /* adjust df value for floating-point instruction */
25782 tcg_gen_movi_i32(tdf, df + 2);
25784 switch (MASK_MSA_3RF(ctx->opcode)) {
25785 case OPC_FCAF_df:
25786 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25787 break;
25788 case OPC_FADD_df:
25789 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25790 break;
25791 case OPC_FCUN_df:
25792 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25793 break;
25794 case OPC_FSUB_df:
25795 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25796 break;
25797 case OPC_FCOR_df:
25798 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25799 break;
25800 case OPC_FCEQ_df:
25801 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25802 break;
25803 case OPC_FMUL_df:
25804 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25805 break;
25806 case OPC_FCUNE_df:
25807 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25808 break;
25809 case OPC_FCUEQ_df:
25810 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25811 break;
25812 case OPC_FDIV_df:
25813 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25814 break;
25815 case OPC_FCNE_df:
25816 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25817 break;
25818 case OPC_FCLT_df:
25819 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25820 break;
25821 case OPC_FMADD_df:
25822 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25823 break;
25824 case OPC_MUL_Q_df:
25825 tcg_gen_movi_i32(tdf, df + 1);
25826 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25827 break;
25828 case OPC_FCULT_df:
25829 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25830 break;
25831 case OPC_FMSUB_df:
25832 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25833 break;
25834 case OPC_MADD_Q_df:
25835 tcg_gen_movi_i32(tdf, df + 1);
25836 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25837 break;
25838 case OPC_FCLE_df:
25839 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25840 break;
25841 case OPC_MSUB_Q_df:
25842 tcg_gen_movi_i32(tdf, df + 1);
25843 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25844 break;
25845 case OPC_FCULE_df:
25846 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25847 break;
25848 case OPC_FEXP2_df:
25849 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25850 break;
25851 case OPC_FSAF_df:
25852 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25853 break;
25854 case OPC_FEXDO_df:
25855 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25856 break;
25857 case OPC_FSUN_df:
25858 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25859 break;
25860 case OPC_FSOR_df:
25861 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25862 break;
25863 case OPC_FSEQ_df:
25864 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25865 break;
25866 case OPC_FTQ_df:
25867 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25868 break;
25869 case OPC_FSUNE_df:
25870 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25871 break;
25872 case OPC_FSUEQ_df:
25873 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25874 break;
25875 case OPC_FSNE_df:
25876 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25877 break;
25878 case OPC_FSLT_df:
25879 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25880 break;
25881 case OPC_FMIN_df:
25882 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25883 break;
25884 case OPC_MULR_Q_df:
25885 tcg_gen_movi_i32(tdf, df + 1);
25886 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25887 break;
25888 case OPC_FSULT_df:
25889 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25890 break;
25891 case OPC_FMIN_A_df:
25892 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25893 break;
25894 case OPC_MADDR_Q_df:
25895 tcg_gen_movi_i32(tdf, df + 1);
25896 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25897 break;
25898 case OPC_FSLE_df:
25899 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25900 break;
25901 case OPC_FMAX_df:
25902 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25903 break;
25904 case OPC_MSUBR_Q_df:
25905 tcg_gen_movi_i32(tdf, df + 1);
25906 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25907 break;
25908 case OPC_FSULE_df:
25909 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25910 break;
25911 case OPC_FMAX_A_df:
25912 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25913 break;
25914 default:
25915 MIPS_INVAL("MSA instruction");
25916 generate_exception_end(ctx, EXCP_RI);
25917 break;
25920 tcg_temp_free_i32(twd);
25921 tcg_temp_free_i32(tws);
25922 tcg_temp_free_i32(twt);
25923 tcg_temp_free_i32(tdf);
25926 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25928 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25929 (op & (0x7 << 18)))
25930 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25931 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25932 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25933 uint8_t df = (ctx->opcode >> 16) & 0x3;
25934 TCGv_i32 twd = tcg_const_i32(wd);
25935 TCGv_i32 tws = tcg_const_i32(ws);
25936 TCGv_i32 twt = tcg_const_i32(wt);
25937 TCGv_i32 tdf = tcg_const_i32(df);
25939 switch (MASK_MSA_2R(ctx->opcode)) {
25940 case OPC_FILL_df:
25941 #if !defined(TARGET_MIPS64)
25942 /* Double format valid only for MIPS64 */
25943 if (df == DF_DOUBLE) {
25944 generate_exception_end(ctx, EXCP_RI);
25945 break;
25947 #endif
25948 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25949 break;
25950 case OPC_PCNT_df:
25951 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25952 break;
25953 case OPC_NLOC_df:
25954 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25955 break;
25956 case OPC_NLZC_df:
25957 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25958 break;
25959 default:
25960 MIPS_INVAL("MSA instruction");
25961 generate_exception_end(ctx, EXCP_RI);
25962 break;
25965 tcg_temp_free_i32(twd);
25966 tcg_temp_free_i32(tws);
25967 tcg_temp_free_i32(twt);
25968 tcg_temp_free_i32(tdf);
25971 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25973 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25974 (op & (0xf << 17)))
25975 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25976 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25977 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25978 uint8_t df = (ctx->opcode >> 16) & 0x1;
25979 TCGv_i32 twd = tcg_const_i32(wd);
25980 TCGv_i32 tws = tcg_const_i32(ws);
25981 TCGv_i32 twt = tcg_const_i32(wt);
25982 /* adjust df value for floating-point instruction */
25983 TCGv_i32 tdf = tcg_const_i32(df + 2);
25985 switch (MASK_MSA_2RF(ctx->opcode)) {
25986 case OPC_FCLASS_df:
25987 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25988 break;
25989 case OPC_FTRUNC_S_df:
25990 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25991 break;
25992 case OPC_FTRUNC_U_df:
25993 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25994 break;
25995 case OPC_FSQRT_df:
25996 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25997 break;
25998 case OPC_FRSQRT_df:
25999 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
26000 break;
26001 case OPC_FRCP_df:
26002 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
26003 break;
26004 case OPC_FRINT_df:
26005 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
26006 break;
26007 case OPC_FLOG2_df:
26008 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
26009 break;
26010 case OPC_FEXUPL_df:
26011 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
26012 break;
26013 case OPC_FEXUPR_df:
26014 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
26015 break;
26016 case OPC_FFQL_df:
26017 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
26018 break;
26019 case OPC_FFQR_df:
26020 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
26021 break;
26022 case OPC_FTINT_S_df:
26023 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
26024 break;
26025 case OPC_FTINT_U_df:
26026 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
26027 break;
26028 case OPC_FFINT_S_df:
26029 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
26030 break;
26031 case OPC_FFINT_U_df:
26032 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
26033 break;
26036 tcg_temp_free_i32(twd);
26037 tcg_temp_free_i32(tws);
26038 tcg_temp_free_i32(twt);
26039 tcg_temp_free_i32(tdf);
26042 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
26044 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
26045 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26046 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26047 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26048 TCGv_i32 twd = tcg_const_i32(wd);
26049 TCGv_i32 tws = tcg_const_i32(ws);
26050 TCGv_i32 twt = tcg_const_i32(wt);
26052 switch (MASK_MSA_VEC(ctx->opcode)) {
26053 case OPC_AND_V:
26054 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
26055 break;
26056 case OPC_OR_V:
26057 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
26058 break;
26059 case OPC_NOR_V:
26060 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
26061 break;
26062 case OPC_XOR_V:
26063 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
26064 break;
26065 case OPC_BMNZ_V:
26066 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
26067 break;
26068 case OPC_BMZ_V:
26069 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
26070 break;
26071 case OPC_BSEL_V:
26072 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
26073 break;
26074 default:
26075 MIPS_INVAL("MSA instruction");
26076 generate_exception_end(ctx, EXCP_RI);
26077 break;
26080 tcg_temp_free_i32(twd);
26081 tcg_temp_free_i32(tws);
26082 tcg_temp_free_i32(twt);
26085 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
26087 switch (MASK_MSA_VEC(ctx->opcode)) {
26088 case OPC_AND_V:
26089 case OPC_OR_V:
26090 case OPC_NOR_V:
26091 case OPC_XOR_V:
26092 case OPC_BMNZ_V:
26093 case OPC_BMZ_V:
26094 case OPC_BSEL_V:
26095 gen_msa_vec_v(env, ctx);
26096 break;
26097 case OPC_MSA_2R:
26098 gen_msa_2r(env, ctx);
26099 break;
26100 case OPC_MSA_2RF:
26101 gen_msa_2rf(env, ctx);
26102 break;
26103 default:
26104 MIPS_INVAL("MSA instruction");
26105 generate_exception_end(ctx, EXCP_RI);
26106 break;
26110 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
26112 uint32_t opcode = ctx->opcode;
26113 check_insn(ctx, ASE_MSA);
26114 check_msa_access(ctx);
26116 switch (MASK_MSA_MINOR(opcode)) {
26117 case OPC_MSA_I8_00:
26118 case OPC_MSA_I8_01:
26119 case OPC_MSA_I8_02:
26120 gen_msa_i8(env, ctx);
26121 break;
26122 case OPC_MSA_I5_06:
26123 case OPC_MSA_I5_07:
26124 gen_msa_i5(env, ctx);
26125 break;
26126 case OPC_MSA_BIT_09:
26127 case OPC_MSA_BIT_0A:
26128 gen_msa_bit(env, ctx);
26129 break;
26130 case OPC_MSA_3R_0D:
26131 case OPC_MSA_3R_0E:
26132 case OPC_MSA_3R_0F:
26133 case OPC_MSA_3R_10:
26134 case OPC_MSA_3R_11:
26135 case OPC_MSA_3R_12:
26136 case OPC_MSA_3R_13:
26137 case OPC_MSA_3R_14:
26138 case OPC_MSA_3R_15:
26139 gen_msa_3r(env, ctx);
26140 break;
26141 case OPC_MSA_ELM:
26142 gen_msa_elm(env, ctx);
26143 break;
26144 case OPC_MSA_3RF_1A:
26145 case OPC_MSA_3RF_1B:
26146 case OPC_MSA_3RF_1C:
26147 gen_msa_3rf(env, ctx);
26148 break;
26149 case OPC_MSA_VEC:
26150 gen_msa_vec(env, ctx);
26151 break;
26152 case OPC_LD_B:
26153 case OPC_LD_H:
26154 case OPC_LD_W:
26155 case OPC_LD_D:
26156 case OPC_ST_B:
26157 case OPC_ST_H:
26158 case OPC_ST_W:
26159 case OPC_ST_D:
26161 int32_t s10 = sextract32(ctx->opcode, 16, 10);
26162 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
26163 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26164 uint8_t df = (ctx->opcode >> 0) & 0x3;
26166 TCGv_i32 twd = tcg_const_i32(wd);
26167 TCGv taddr = tcg_temp_new();
26168 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
26170 switch (MASK_MSA_MINOR(opcode)) {
26171 case OPC_LD_B:
26172 gen_helper_msa_ld_b(cpu_env, twd, taddr);
26173 break;
26174 case OPC_LD_H:
26175 gen_helper_msa_ld_h(cpu_env, twd, taddr);
26176 break;
26177 case OPC_LD_W:
26178 gen_helper_msa_ld_w(cpu_env, twd, taddr);
26179 break;
26180 case OPC_LD_D:
26181 gen_helper_msa_ld_d(cpu_env, twd, taddr);
26182 break;
26183 case OPC_ST_B:
26184 gen_helper_msa_st_b(cpu_env, twd, taddr);
26185 break;
26186 case OPC_ST_H:
26187 gen_helper_msa_st_h(cpu_env, twd, taddr);
26188 break;
26189 case OPC_ST_W:
26190 gen_helper_msa_st_w(cpu_env, twd, taddr);
26191 break;
26192 case OPC_ST_D:
26193 gen_helper_msa_st_d(cpu_env, twd, taddr);
26194 break;
26197 tcg_temp_free_i32(twd);
26198 tcg_temp_free(taddr);
26200 break;
26201 default:
26202 MIPS_INVAL("MSA instruction");
26203 generate_exception_end(ctx, EXCP_RI);
26204 break;
26209 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
26211 int32_t offset;
26212 int rs, rt, rd, sa;
26213 uint32_t op, op1;
26214 int16_t imm;
26216 /* make sure instructions are on a word boundary */
26217 if (ctx->base.pc_next & 0x3) {
26218 env->CP0_BadVAddr = ctx->base.pc_next;
26219 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
26220 return;
26223 /* Handle blikely not taken case */
26224 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
26225 TCGLabel *l1 = gen_new_label();
26227 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
26228 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
26229 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
26230 gen_set_label(l1);
26233 op = MASK_OP_MAJOR(ctx->opcode);
26234 rs = (ctx->opcode >> 21) & 0x1f;
26235 rt = (ctx->opcode >> 16) & 0x1f;
26236 rd = (ctx->opcode >> 11) & 0x1f;
26237 sa = (ctx->opcode >> 6) & 0x1f;
26238 imm = (int16_t)ctx->opcode;
26239 switch (op) {
26240 case OPC_SPECIAL:
26241 decode_opc_special(env, ctx);
26242 break;
26243 case OPC_SPECIAL2:
26244 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26245 decode_tx79_mmi(env, ctx);
26246 } else {
26247 decode_opc_special2_legacy(env, ctx);
26249 break;
26250 case OPC_SPECIAL3:
26251 if (ctx->insn_flags & INSN_R5900) {
26252 decode_tx79_sq(env, ctx); /* TX79_SQ */
26253 } else {
26254 decode_opc_special3(env, ctx);
26256 break;
26257 case OPC_REGIMM:
26258 op1 = MASK_REGIMM(ctx->opcode);
26259 switch (op1) {
26260 case OPC_BLTZL: /* REGIMM branches */
26261 case OPC_BGEZL:
26262 case OPC_BLTZALL:
26263 case OPC_BGEZALL:
26264 check_insn(ctx, ISA_MIPS2);
26265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26266 /* Fallthrough */
26267 case OPC_BLTZ:
26268 case OPC_BGEZ:
26269 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26270 break;
26271 case OPC_BLTZAL:
26272 case OPC_BGEZAL:
26273 if (ctx->insn_flags & ISA_MIPS32R6) {
26274 if (rs == 0) {
26275 /* OPC_NAL, OPC_BAL */
26276 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
26277 } else {
26278 generate_exception_end(ctx, EXCP_RI);
26280 } else {
26281 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26283 break;
26284 case OPC_TGEI: /* REGIMM traps */
26285 case OPC_TGEIU:
26286 case OPC_TLTI:
26287 case OPC_TLTIU:
26288 case OPC_TEQI:
26290 case OPC_TNEI:
26291 check_insn(ctx, ISA_MIPS2);
26292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26293 gen_trap(ctx, op1, rs, -1, imm);
26294 break;
26295 case OPC_SIGRIE:
26296 check_insn(ctx, ISA_MIPS32R6);
26297 generate_exception_end(ctx, EXCP_RI);
26298 break;
26299 case OPC_SYNCI:
26300 check_insn(ctx, ISA_MIPS32R2);
26301 /* Break the TB to be able to sync copied instructions
26302 immediately */
26303 ctx->base.is_jmp = DISAS_STOP;
26304 break;
26305 case OPC_BPOSGE32: /* MIPS DSP branch */
26306 #if defined(TARGET_MIPS64)
26307 case OPC_BPOSGE64:
26308 #endif
26309 check_dsp(ctx);
26310 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
26311 break;
26312 #if defined(TARGET_MIPS64)
26313 case OPC_DAHI:
26314 check_insn(ctx, ISA_MIPS32R6);
26315 check_mips_64(ctx);
26316 if (rs != 0) {
26317 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
26319 break;
26320 case OPC_DATI:
26321 check_insn(ctx, ISA_MIPS32R6);
26322 check_mips_64(ctx);
26323 if (rs != 0) {
26324 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
26326 break;
26327 #endif
26328 default: /* Invalid */
26329 MIPS_INVAL("regimm");
26330 generate_exception_end(ctx, EXCP_RI);
26331 break;
26333 break;
26334 case OPC_CP0:
26335 check_cp0_enabled(ctx);
26336 op1 = MASK_CP0(ctx->opcode);
26337 switch (op1) {
26338 case OPC_MFC0:
26339 case OPC_MTC0:
26340 case OPC_MFTR:
26341 case OPC_MTTR:
26342 case OPC_MFHC0:
26343 case OPC_MTHC0:
26344 #if defined(TARGET_MIPS64)
26345 case OPC_DMFC0:
26346 case OPC_DMTC0:
26347 #endif
26348 #ifndef CONFIG_USER_ONLY
26349 gen_cp0(env, ctx, op1, rt, rd);
26350 #endif /* !CONFIG_USER_ONLY */
26351 break;
26352 case OPC_C0:
26353 case OPC_C0_1:
26354 case OPC_C0_2:
26355 case OPC_C0_3:
26356 case OPC_C0_4:
26357 case OPC_C0_5:
26358 case OPC_C0_6:
26359 case OPC_C0_7:
26360 case OPC_C0_8:
26361 case OPC_C0_9:
26362 case OPC_C0_A:
26363 case OPC_C0_B:
26364 case OPC_C0_C:
26365 case OPC_C0_D:
26366 case OPC_C0_E:
26367 case OPC_C0_F:
26368 #ifndef CONFIG_USER_ONLY
26369 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
26370 #endif /* !CONFIG_USER_ONLY */
26371 break;
26372 case OPC_MFMC0:
26373 #ifndef CONFIG_USER_ONLY
26375 uint32_t op2;
26376 TCGv t0 = tcg_temp_new();
26378 op2 = MASK_MFMC0(ctx->opcode);
26379 switch (op2) {
26380 case OPC_DMT:
26381 check_cp0_mt(ctx);
26382 gen_helper_dmt(t0);
26383 gen_store_gpr(t0, rt);
26384 break;
26385 case OPC_EMT:
26386 check_cp0_mt(ctx);
26387 gen_helper_emt(t0);
26388 gen_store_gpr(t0, rt);
26389 break;
26390 case OPC_DVPE:
26391 check_cp0_mt(ctx);
26392 gen_helper_dvpe(t0, cpu_env);
26393 gen_store_gpr(t0, rt);
26394 break;
26395 case OPC_EVPE:
26396 check_cp0_mt(ctx);
26397 gen_helper_evpe(t0, cpu_env);
26398 gen_store_gpr(t0, rt);
26399 break;
26400 case OPC_DVP:
26401 check_insn(ctx, ISA_MIPS32R6);
26402 if (ctx->vp) {
26403 gen_helper_dvp(t0, cpu_env);
26404 gen_store_gpr(t0, rt);
26406 break;
26407 case OPC_EVP:
26408 check_insn(ctx, ISA_MIPS32R6);
26409 if (ctx->vp) {
26410 gen_helper_evp(t0, cpu_env);
26411 gen_store_gpr(t0, rt);
26413 break;
26414 case OPC_DI:
26415 check_insn(ctx, ISA_MIPS32R2);
26416 save_cpu_state(ctx, 1);
26417 gen_helper_di(t0, cpu_env);
26418 gen_store_gpr(t0, rt);
26419 /* Stop translation as we may have switched
26420 the execution mode. */
26421 ctx->base.is_jmp = DISAS_STOP;
26422 break;
26423 case OPC_EI:
26424 check_insn(ctx, ISA_MIPS32R2);
26425 save_cpu_state(ctx, 1);
26426 gen_helper_ei(t0, cpu_env);
26427 gen_store_gpr(t0, rt);
26428 /* DISAS_STOP isn't sufficient, we need to ensure we break
26429 out of translated code to check for pending interrupts */
26430 gen_save_pc(ctx->base.pc_next + 4);
26431 ctx->base.is_jmp = DISAS_EXIT;
26432 break;
26433 default: /* Invalid */
26434 MIPS_INVAL("mfmc0");
26435 generate_exception_end(ctx, EXCP_RI);
26436 break;
26438 tcg_temp_free(t0);
26440 #endif /* !CONFIG_USER_ONLY */
26441 break;
26442 case OPC_RDPGPR:
26443 check_insn(ctx, ISA_MIPS32R2);
26444 gen_load_srsgpr(rt, rd);
26445 break;
26446 case OPC_WRPGPR:
26447 check_insn(ctx, ISA_MIPS32R2);
26448 gen_store_srsgpr(rt, rd);
26449 break;
26450 default:
26451 MIPS_INVAL("cp0");
26452 generate_exception_end(ctx, EXCP_RI);
26453 break;
26455 break;
26456 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
26457 if (ctx->insn_flags & ISA_MIPS32R6) {
26458 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
26459 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26460 } else {
26461 /* OPC_ADDI */
26462 /* Arithmetic with immediate opcode */
26463 gen_arith_imm(ctx, op, rt, rs, imm);
26465 break;
26466 case OPC_ADDIU:
26467 gen_arith_imm(ctx, op, rt, rs, imm);
26468 break;
26469 case OPC_SLTI: /* Set on less than with immediate opcode */
26470 case OPC_SLTIU:
26471 gen_slt_imm(ctx, op, rt, rs, imm);
26472 break;
26473 case OPC_ANDI: /* Arithmetic with immediate opcode */
26474 case OPC_LUI: /* OPC_AUI */
26475 case OPC_ORI:
26476 case OPC_XORI:
26477 gen_logic_imm(ctx, op, rt, rs, imm);
26478 break;
26479 case OPC_J: /* Jump */
26480 case OPC_JAL:
26481 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26482 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26483 break;
26484 /* Branch */
26485 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
26486 if (ctx->insn_flags & ISA_MIPS32R6) {
26487 if (rt == 0) {
26488 generate_exception_end(ctx, EXCP_RI);
26489 break;
26491 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
26492 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26493 } else {
26494 /* OPC_BLEZL */
26495 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26497 break;
26498 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
26499 if (ctx->insn_flags & ISA_MIPS32R6) {
26500 if (rt == 0) {
26501 generate_exception_end(ctx, EXCP_RI);
26502 break;
26504 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
26505 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26506 } else {
26507 /* OPC_BGTZL */
26508 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26510 break;
26511 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
26512 if (rt == 0) {
26513 /* OPC_BLEZ */
26514 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26515 } else {
26516 check_insn(ctx, ISA_MIPS32R6);
26517 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
26518 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26520 break;
26521 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
26522 if (rt == 0) {
26523 /* OPC_BGTZ */
26524 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26525 } else {
26526 check_insn(ctx, ISA_MIPS32R6);
26527 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
26528 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26530 break;
26531 case OPC_BEQL:
26532 case OPC_BNEL:
26533 check_insn(ctx, ISA_MIPS2);
26534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26535 /* Fallthrough */
26536 case OPC_BEQ:
26537 case OPC_BNE:
26538 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26539 break;
26540 case OPC_LL: /* Load and stores */
26541 check_insn(ctx, ISA_MIPS2);
26542 check_insn_opc_user_only(ctx, INSN_R5900);
26543 /* Fallthrough */
26544 case OPC_LWL:
26545 case OPC_LWR:
26546 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26547 /* Fallthrough */
26548 case OPC_LB:
26549 case OPC_LH:
26550 case OPC_LW:
26551 case OPC_LWPC:
26552 case OPC_LBU:
26553 case OPC_LHU:
26554 gen_ld(ctx, op, rt, rs, imm);
26555 break;
26556 case OPC_SWL:
26557 case OPC_SWR:
26558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26559 /* fall through */
26560 case OPC_SB:
26561 case OPC_SH:
26562 case OPC_SW:
26563 gen_st(ctx, op, rt, rs, imm);
26564 break;
26565 case OPC_SC:
26566 check_insn(ctx, ISA_MIPS2);
26567 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26568 check_insn_opc_user_only(ctx, INSN_R5900);
26569 gen_st_cond(ctx, op, rt, rs, imm);
26570 break;
26571 case OPC_CACHE:
26572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26573 check_cp0_enabled(ctx);
26574 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
26575 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26576 gen_cache_operation(ctx, rt, rs, imm);
26578 /* Treat as NOP. */
26579 break;
26580 case OPC_PREF:
26581 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26582 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
26583 INSN_R5900);
26584 /* Treat as NOP. */
26585 break;
26587 /* Floating point (COP1). */
26588 case OPC_LWC1:
26589 case OPC_LDC1:
26590 case OPC_SWC1:
26591 case OPC_SDC1:
26592 gen_cop1_ldst(ctx, op, rt, rs, imm);
26593 break;
26595 case OPC_CP1:
26596 op1 = MASK_CP1(ctx->opcode);
26598 switch (op1) {
26599 case OPC_MFHC1:
26600 case OPC_MTHC1:
26601 check_cp1_enabled(ctx);
26602 check_insn(ctx, ISA_MIPS32R2);
26603 /* fall through */
26604 case OPC_MFC1:
26605 case OPC_CFC1:
26606 case OPC_MTC1:
26607 case OPC_CTC1:
26608 check_cp1_enabled(ctx);
26609 gen_cp1(ctx, op1, rt, rd);
26610 break;
26611 #if defined(TARGET_MIPS64)
26612 case OPC_DMFC1:
26613 case OPC_DMTC1:
26614 check_cp1_enabled(ctx);
26615 check_insn(ctx, ISA_MIPS3);
26616 check_mips_64(ctx);
26617 gen_cp1(ctx, op1, rt, rd);
26618 break;
26619 #endif
26620 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
26621 check_cp1_enabled(ctx);
26622 if (ctx->insn_flags & ISA_MIPS32R6) {
26623 /* OPC_BC1EQZ */
26624 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26625 rt, imm << 2, 4);
26626 } else {
26627 /* OPC_BC1ANY2 */
26628 check_cop1x(ctx);
26629 check_insn(ctx, ASE_MIPS3D);
26630 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26631 (rt >> 2) & 0x7, imm << 2);
26633 break;
26634 case OPC_BC1NEZ:
26635 check_cp1_enabled(ctx);
26636 check_insn(ctx, ISA_MIPS32R6);
26637 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26638 rt, imm << 2, 4);
26639 break;
26640 case OPC_BC1ANY4:
26641 check_cp1_enabled(ctx);
26642 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26643 check_cop1x(ctx);
26644 check_insn(ctx, ASE_MIPS3D);
26645 /* fall through */
26646 case OPC_BC1:
26647 check_cp1_enabled(ctx);
26648 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26649 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26650 (rt >> 2) & 0x7, imm << 2);
26651 break;
26652 case OPC_PS_FMT:
26653 check_ps(ctx);
26654 /* fall through */
26655 case OPC_S_FMT:
26656 case OPC_D_FMT:
26657 check_cp1_enabled(ctx);
26658 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26659 (imm >> 8) & 0x7);
26660 break;
26661 case OPC_W_FMT:
26662 case OPC_L_FMT:
26664 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
26665 check_cp1_enabled(ctx);
26666 if (ctx->insn_flags & ISA_MIPS32R6) {
26667 switch (r6_op) {
26668 case R6_OPC_CMP_AF_S:
26669 case R6_OPC_CMP_UN_S:
26670 case R6_OPC_CMP_EQ_S:
26671 case R6_OPC_CMP_UEQ_S:
26672 case R6_OPC_CMP_LT_S:
26673 case R6_OPC_CMP_ULT_S:
26674 case R6_OPC_CMP_LE_S:
26675 case R6_OPC_CMP_ULE_S:
26676 case R6_OPC_CMP_SAF_S:
26677 case R6_OPC_CMP_SUN_S:
26678 case R6_OPC_CMP_SEQ_S:
26679 case R6_OPC_CMP_SEUQ_S:
26680 case R6_OPC_CMP_SLT_S:
26681 case R6_OPC_CMP_SULT_S:
26682 case R6_OPC_CMP_SLE_S:
26683 case R6_OPC_CMP_SULE_S:
26684 case R6_OPC_CMP_OR_S:
26685 case R6_OPC_CMP_UNE_S:
26686 case R6_OPC_CMP_NE_S:
26687 case R6_OPC_CMP_SOR_S:
26688 case R6_OPC_CMP_SUNE_S:
26689 case R6_OPC_CMP_SNE_S:
26690 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26691 break;
26692 case R6_OPC_CMP_AF_D:
26693 case R6_OPC_CMP_UN_D:
26694 case R6_OPC_CMP_EQ_D:
26695 case R6_OPC_CMP_UEQ_D:
26696 case R6_OPC_CMP_LT_D:
26697 case R6_OPC_CMP_ULT_D:
26698 case R6_OPC_CMP_LE_D:
26699 case R6_OPC_CMP_ULE_D:
26700 case R6_OPC_CMP_SAF_D:
26701 case R6_OPC_CMP_SUN_D:
26702 case R6_OPC_CMP_SEQ_D:
26703 case R6_OPC_CMP_SEUQ_D:
26704 case R6_OPC_CMP_SLT_D:
26705 case R6_OPC_CMP_SULT_D:
26706 case R6_OPC_CMP_SLE_D:
26707 case R6_OPC_CMP_SULE_D:
26708 case R6_OPC_CMP_OR_D:
26709 case R6_OPC_CMP_UNE_D:
26710 case R6_OPC_CMP_NE_D:
26711 case R6_OPC_CMP_SOR_D:
26712 case R6_OPC_CMP_SUNE_D:
26713 case R6_OPC_CMP_SNE_D:
26714 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26715 break;
26716 default:
26717 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
26718 rt, rd, sa, (imm >> 8) & 0x7);
26720 break;
26722 } else {
26723 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26724 (imm >> 8) & 0x7);
26726 break;
26728 case OPC_BZ_V:
26729 case OPC_BNZ_V:
26730 case OPC_BZ_B:
26731 case OPC_BZ_H:
26732 case OPC_BZ_W:
26733 case OPC_BZ_D:
26734 case OPC_BNZ_B:
26735 case OPC_BNZ_H:
26736 case OPC_BNZ_W:
26737 case OPC_BNZ_D:
26738 check_insn(ctx, ASE_MSA);
26739 gen_msa_branch(env, ctx, op1);
26740 break;
26741 default:
26742 MIPS_INVAL("cp1");
26743 generate_exception_end(ctx, EXCP_RI);
26744 break;
26746 break;
26748 /* Compact branches [R6] and COP2 [non-R6] */
26749 case OPC_BC: /* OPC_LWC2 */
26750 case OPC_BALC: /* OPC_SWC2 */
26751 if (ctx->insn_flags & ISA_MIPS32R6) {
26752 /* OPC_BC, OPC_BALC */
26753 gen_compute_compact_branch(ctx, op, 0, 0,
26754 sextract32(ctx->opcode << 2, 0, 28));
26755 } else {
26756 /* OPC_LWC2, OPC_SWC2 */
26757 /* COP2: Not implemented. */
26758 generate_exception_err(ctx, EXCP_CpU, 2);
26760 break;
26761 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
26762 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
26763 if (ctx->insn_flags & ISA_MIPS32R6) {
26764 if (rs != 0) {
26765 /* OPC_BEQZC, OPC_BNEZC */
26766 gen_compute_compact_branch(ctx, op, rs, 0,
26767 sextract32(ctx->opcode << 2, 0, 23));
26768 } else {
26769 /* OPC_JIC, OPC_JIALC */
26770 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26772 } else {
26773 /* OPC_LWC2, OPC_SWC2 */
26774 /* COP2: Not implemented. */
26775 generate_exception_err(ctx, EXCP_CpU, 2);
26777 break;
26778 case OPC_CP2:
26779 check_insn(ctx, INSN_LOONGSON2F);
26780 /* Note that these instructions use different fields. */
26781 gen_loongson_multimedia(ctx, sa, rd, rt);
26782 break;
26784 case OPC_CP3:
26785 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26786 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26787 check_cp1_enabled(ctx);
26788 op1 = MASK_CP3(ctx->opcode);
26789 switch (op1) {
26790 case OPC_LUXC1:
26791 case OPC_SUXC1:
26792 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26793 /* Fallthrough */
26794 case OPC_LWXC1:
26795 case OPC_LDXC1:
26796 case OPC_SWXC1:
26797 case OPC_SDXC1:
26798 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26799 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
26800 break;
26801 case OPC_PREFX:
26802 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26803 /* Treat as NOP. */
26804 break;
26805 case OPC_ALNV_PS:
26806 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26807 /* Fallthrough */
26808 case OPC_MADD_S:
26809 case OPC_MADD_D:
26810 case OPC_MADD_PS:
26811 case OPC_MSUB_S:
26812 case OPC_MSUB_D:
26813 case OPC_MSUB_PS:
26814 case OPC_NMADD_S:
26815 case OPC_NMADD_D:
26816 case OPC_NMADD_PS:
26817 case OPC_NMSUB_S:
26818 case OPC_NMSUB_D:
26819 case OPC_NMSUB_PS:
26820 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26821 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26822 break;
26823 default:
26824 MIPS_INVAL("cp3");
26825 generate_exception_end(ctx, EXCP_RI);
26826 break;
26828 } else {
26829 generate_exception_err(ctx, EXCP_CpU, 1);
26831 break;
26833 #if defined(TARGET_MIPS64)
26834 /* MIPS64 opcodes */
26835 case OPC_LLD:
26836 check_insn_opc_user_only(ctx, INSN_R5900);
26837 /* fall through */
26838 case OPC_LDL:
26839 case OPC_LDR:
26840 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26841 /* fall through */
26842 case OPC_LWU:
26843 case OPC_LD:
26844 check_insn(ctx, ISA_MIPS3);
26845 check_mips_64(ctx);
26846 gen_ld(ctx, op, rt, rs, imm);
26847 break;
26848 case OPC_SDL:
26849 case OPC_SDR:
26850 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26851 /* fall through */
26852 case OPC_SD:
26853 check_insn(ctx, ISA_MIPS3);
26854 check_mips_64(ctx);
26855 gen_st(ctx, op, rt, rs, imm);
26856 break;
26857 case OPC_SCD:
26858 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26859 check_insn(ctx, ISA_MIPS3);
26860 check_insn_opc_user_only(ctx, INSN_R5900);
26861 check_mips_64(ctx);
26862 gen_st_cond(ctx, op, rt, rs, imm);
26863 break;
26864 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26865 if (ctx->insn_flags & ISA_MIPS32R6) {
26866 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26867 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26868 } else {
26869 /* OPC_DADDI */
26870 check_insn(ctx, ISA_MIPS3);
26871 check_mips_64(ctx);
26872 gen_arith_imm(ctx, op, rt, rs, imm);
26874 break;
26875 case OPC_DADDIU:
26876 check_insn(ctx, ISA_MIPS3);
26877 check_mips_64(ctx);
26878 gen_arith_imm(ctx, op, rt, rs, imm);
26879 break;
26880 #else
26881 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26882 if (ctx->insn_flags & ISA_MIPS32R6) {
26883 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26884 } else {
26885 MIPS_INVAL("major opcode");
26886 generate_exception_end(ctx, EXCP_RI);
26888 break;
26889 #endif
26890 case OPC_DAUI: /* OPC_JALX */
26891 if (ctx->insn_flags & ISA_MIPS32R6) {
26892 #if defined(TARGET_MIPS64)
26893 /* OPC_DAUI */
26894 check_mips_64(ctx);
26895 if (rs == 0) {
26896 generate_exception(ctx, EXCP_RI);
26897 } else if (rt != 0) {
26898 TCGv t0 = tcg_temp_new();
26899 gen_load_gpr(t0, rs);
26900 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26901 tcg_temp_free(t0);
26903 #else
26904 generate_exception_end(ctx, EXCP_RI);
26905 MIPS_INVAL("major opcode");
26906 #endif
26907 } else {
26908 /* OPC_JALX */
26909 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26910 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26911 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26913 break;
26914 case OPC_MSA: /* OPC_MDMX */
26915 if (ctx->insn_flags & INSN_R5900) {
26916 decode_tx79_lq(env, ctx); /* TX79_LQ */
26917 } else {
26918 /* MDMX: Not implemented. */
26919 gen_msa(env, ctx);
26921 break;
26922 case OPC_PCREL:
26923 check_insn(ctx, ISA_MIPS32R6);
26924 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26925 break;
26926 default: /* Invalid */
26927 MIPS_INVAL("major opcode");
26928 generate_exception_end(ctx, EXCP_RI);
26929 break;
26933 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26935 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26936 CPUMIPSState *env = cs->env_ptr;
26938 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26939 ctx->saved_pc = -1;
26940 ctx->insn_flags = env->insn_flags;
26941 ctx->CP0_Config1 = env->CP0_Config1;
26942 ctx->CP0_Config2 = env->CP0_Config2;
26943 ctx->CP0_Config3 = env->CP0_Config3;
26944 ctx->CP0_Config5 = env->CP0_Config5;
26945 ctx->btarget = 0;
26946 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26947 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26948 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26949 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26950 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26951 ctx->PAMask = env->PAMask;
26952 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26953 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26954 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26955 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26956 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26957 /* Restore delay slot state from the tb context. */
26958 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26959 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26960 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26961 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26962 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26963 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26964 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26965 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26966 restore_cpu_state(env, ctx);
26967 #ifdef CONFIG_USER_ONLY
26968 ctx->mem_idx = MIPS_HFLAG_UM;
26969 #else
26970 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26971 #endif
26972 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26973 MO_UNALN : MO_ALIGN;
26975 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26976 ctx->hflags);
26979 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26983 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26985 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26987 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26988 ctx->btarget);
26991 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26992 const CPUBreakpoint *bp)
26994 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26996 save_cpu_state(ctx, 1);
26997 ctx->base.is_jmp = DISAS_NORETURN;
26998 gen_helper_raise_exception_debug(cpu_env);
26999 /* The address covered by the breakpoint must be included in
27000 [tb->pc, tb->pc + tb->size) in order to for it to be
27001 properly cleared -- thus we increment the PC here so that
27002 the logic setting tb->size below does the right thing. */
27003 ctx->base.pc_next += 4;
27004 return true;
27007 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
27009 CPUMIPSState *env = cs->env_ptr;
27010 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27011 int insn_bytes;
27012 int is_slot;
27014 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
27015 if (ctx->insn_flags & ISA_NANOMIPS32) {
27016 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
27017 insn_bytes = decode_nanomips_opc(env, ctx);
27018 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
27019 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
27020 insn_bytes = 4;
27021 decode_opc(env, ctx);
27022 } else if (ctx->insn_flags & ASE_MICROMIPS) {
27023 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
27024 insn_bytes = decode_micromips_opc(env, ctx);
27025 } else if (ctx->insn_flags & ASE_MIPS16) {
27026 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
27027 insn_bytes = decode_mips16_opc(env, ctx);
27028 } else {
27029 generate_exception_end(ctx, EXCP_RI);
27030 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
27031 return;
27034 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27035 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
27036 MIPS_HFLAG_FBNSLOT))) {
27037 /* force to generate branch as there is neither delay nor
27038 forbidden slot */
27039 is_slot = 1;
27041 if ((ctx->hflags & MIPS_HFLAG_M16) &&
27042 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
27043 /* Force to generate branch as microMIPS R6 doesn't restrict
27044 branches in the forbidden slot. */
27045 is_slot = 1;
27048 if (is_slot) {
27049 gen_branch(ctx, insn_bytes);
27051 ctx->base.pc_next += insn_bytes;
27053 if (ctx->base.is_jmp != DISAS_NEXT) {
27054 return;
27056 /* Execute a branch and its delay slot as a single instruction.
27057 This is what GDB expects and is consistent with what the
27058 hardware does (e.g. if a delay slot instruction faults, the
27059 reported PC is the PC of the branch). */
27060 if (ctx->base.singlestep_enabled &&
27061 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
27062 ctx->base.is_jmp = DISAS_TOO_MANY;
27064 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
27065 ctx->base.is_jmp = DISAS_TOO_MANY;
27069 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
27071 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27073 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
27074 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
27075 gen_helper_raise_exception_debug(cpu_env);
27076 } else {
27077 switch (ctx->base.is_jmp) {
27078 case DISAS_STOP:
27079 gen_save_pc(ctx->base.pc_next);
27080 tcg_gen_lookup_and_goto_ptr();
27081 break;
27082 case DISAS_NEXT:
27083 case DISAS_TOO_MANY:
27084 save_cpu_state(ctx, 0);
27085 gen_goto_tb(ctx, 0, ctx->base.pc_next);
27086 break;
27087 case DISAS_EXIT:
27088 tcg_gen_exit_tb(NULL, 0);
27089 break;
27090 case DISAS_NORETURN:
27091 break;
27092 default:
27093 g_assert_not_reached();
27098 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
27100 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
27101 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
27104 static const TranslatorOps mips_tr_ops = {
27105 .init_disas_context = mips_tr_init_disas_context,
27106 .tb_start = mips_tr_tb_start,
27107 .insn_start = mips_tr_insn_start,
27108 .breakpoint_check = mips_tr_breakpoint_check,
27109 .translate_insn = mips_tr_translate_insn,
27110 .tb_stop = mips_tr_tb_stop,
27111 .disas_log = mips_tr_disas_log,
27114 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
27116 DisasContext ctx;
27118 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
27121 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
27122 int flags)
27124 int i;
27125 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
27127 #define printfpr(fp) \
27128 do { \
27129 if (is_fpu64) \
27130 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
27131 " fd:%13g fs:%13g psu: %13g\n", \
27132 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
27133 (double)(fp)->fd, \
27134 (double)(fp)->fs[FP_ENDIAN_IDX], \
27135 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
27136 else { \
27137 fpr_t tmp; \
27138 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
27139 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
27140 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
27141 " fd:%13g fs:%13g psu:%13g\n", \
27142 tmp.w[FP_ENDIAN_IDX], tmp.d, \
27143 (double)tmp.fd, \
27144 (double)tmp.fs[FP_ENDIAN_IDX], \
27145 (double)tmp.fs[!FP_ENDIAN_IDX]); \
27147 } while(0)
27150 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
27151 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
27152 get_float_exception_flags(&env->active_fpu.fp_status));
27153 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
27154 fpu_fprintf(f, "%3s: ", fregnames[i]);
27155 printfpr(&env->active_fpu.fpr[i]);
27158 #undef printfpr
27161 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
27162 int flags)
27164 MIPSCPU *cpu = MIPS_CPU(cs);
27165 CPUMIPSState *env = &cpu->env;
27166 int i;
27168 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
27169 " LO=0x" TARGET_FMT_lx " ds %04x "
27170 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
27171 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
27172 env->hflags, env->btarget, env->bcond);
27173 for (i = 0; i < 32; i++) {
27174 if ((i & 3) == 0)
27175 cpu_fprintf(f, "GPR%02d:", i);
27176 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
27177 if ((i & 3) == 3)
27178 cpu_fprintf(f, "\n");
27181 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
27182 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
27183 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
27184 PRIx64 "\n",
27185 env->CP0_Config0, env->CP0_Config1, env->lladdr);
27186 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
27187 env->CP0_Config2, env->CP0_Config3);
27188 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
27189 env->CP0_Config4, env->CP0_Config5);
27190 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
27191 fpu_dump_state(env, f, cpu_fprintf, flags);
27195 void mips_tcg_init(void)
27197 int i;
27199 cpu_gpr[0] = NULL;
27200 for (i = 1; i < 32; i++)
27201 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
27202 offsetof(CPUMIPSState, active_tc.gpr[i]),
27203 regnames[i]);
27205 for (i = 0; i < 32; i++) {
27206 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
27207 msa_wr_d[i * 2] =
27208 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
27209 /* The scalar floating-point unit (FPU) registers are mapped on
27210 * the MSA vector registers. */
27211 fpu_f64[i] = msa_wr_d[i * 2];
27212 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
27213 msa_wr_d[i * 2 + 1] =
27214 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
27217 cpu_PC = tcg_global_mem_new(cpu_env,
27218 offsetof(CPUMIPSState, active_tc.PC), "PC");
27219 for (i = 0; i < MIPS_DSP_ACC; i++) {
27220 cpu_HI[i] = tcg_global_mem_new(cpu_env,
27221 offsetof(CPUMIPSState, active_tc.HI[i]),
27222 regnames_HI[i]);
27223 cpu_LO[i] = tcg_global_mem_new(cpu_env,
27224 offsetof(CPUMIPSState, active_tc.LO[i]),
27225 regnames_LO[i]);
27227 cpu_dspctrl = tcg_global_mem_new(cpu_env,
27228 offsetof(CPUMIPSState, active_tc.DSPControl),
27229 "DSPControl");
27230 bcond = tcg_global_mem_new(cpu_env,
27231 offsetof(CPUMIPSState, bcond), "bcond");
27232 btarget = tcg_global_mem_new(cpu_env,
27233 offsetof(CPUMIPSState, btarget), "btarget");
27234 hflags = tcg_global_mem_new_i32(cpu_env,
27235 offsetof(CPUMIPSState, hflags), "hflags");
27237 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
27238 offsetof(CPUMIPSState, active_fpu.fcr0),
27239 "fcr0");
27240 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
27241 offsetof(CPUMIPSState, active_fpu.fcr31),
27242 "fcr31");
27244 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
27245 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
27246 offsetof(CPUMIPSState,
27247 active_tc.mxu_gpr[i]),
27248 mxuregnames[i]);
27251 mxu_CR = tcg_global_mem_new(cpu_env,
27252 offsetof(CPUMIPSState, active_tc.mxu_cr),
27253 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
27256 #include "translate_init.inc.c"
27258 void cpu_mips_realize_env(CPUMIPSState *env)
27260 env->exception_base = (int32_t)0xBFC00000;
27262 #ifndef CONFIG_USER_ONLY
27263 mmu_init(env, env->cpu_model);
27264 #endif
27265 fpu_init(env, env->cpu_model);
27266 mvp_init(env, env->cpu_model);
27269 bool cpu_supports_cps_smp(const char *cpu_type)
27271 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27272 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
27275 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
27277 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27278 return (mcc->cpu_def->insn_flags & isa) != 0;
27281 void cpu_set_exception_base(int vp_index, target_ulong address)
27283 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
27284 vp->env.exception_base = address;
27287 void cpu_state_reset(CPUMIPSState *env)
27289 MIPSCPU *cpu = mips_env_get_cpu(env);
27290 CPUState *cs = CPU(cpu);
27292 /* Reset registers to their default values */
27293 env->CP0_PRid = env->cpu_model->CP0_PRid;
27294 env->CP0_Config0 = env->cpu_model->CP0_Config0;
27295 #ifdef TARGET_WORDS_BIGENDIAN
27296 env->CP0_Config0 |= (1 << CP0C0_BE);
27297 #endif
27298 env->CP0_Config1 = env->cpu_model->CP0_Config1;
27299 env->CP0_Config2 = env->cpu_model->CP0_Config2;
27300 env->CP0_Config3 = env->cpu_model->CP0_Config3;
27301 env->CP0_Config4 = env->cpu_model->CP0_Config4;
27302 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
27303 env->CP0_Config5 = env->cpu_model->CP0_Config5;
27304 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
27305 env->CP0_Config6 = env->cpu_model->CP0_Config6;
27306 env->CP0_Config7 = env->cpu_model->CP0_Config7;
27307 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
27308 << env->cpu_model->CP0_LLAddr_shift;
27309 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
27310 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
27311 env->CCRes = env->cpu_model->CCRes;
27312 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
27313 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
27314 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
27315 env->current_tc = 0;
27316 env->SEGBITS = env->cpu_model->SEGBITS;
27317 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
27318 #if defined(TARGET_MIPS64)
27319 if (env->cpu_model->insn_flags & ISA_MIPS3) {
27320 env->SEGMask |= 3ULL << 62;
27322 #endif
27323 env->PABITS = env->cpu_model->PABITS;
27324 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
27325 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
27326 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
27327 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
27328 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
27329 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
27330 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
27331 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
27332 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
27333 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
27334 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
27335 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
27336 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
27337 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
27338 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
27339 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
27340 env->msair = env->cpu_model->MSAIR;
27341 env->insn_flags = env->cpu_model->insn_flags;
27343 #if defined(CONFIG_USER_ONLY)
27344 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
27345 # ifdef TARGET_MIPS64
27346 /* Enable 64-bit register mode. */
27347 env->CP0_Status |= (1 << CP0St_PX);
27348 # endif
27349 # ifdef TARGET_ABI_MIPSN64
27350 /* Enable 64-bit address mode. */
27351 env->CP0_Status |= (1 << CP0St_UX);
27352 # endif
27353 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
27354 hardware registers. */
27355 env->CP0_HWREna |= 0x0000000F;
27356 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
27357 env->CP0_Status |= (1 << CP0St_CU1);
27359 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
27360 env->CP0_Status |= (1 << CP0St_MX);
27362 # if defined(TARGET_MIPS64)
27363 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
27364 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
27365 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
27366 env->CP0_Status |= (1 << CP0St_FR);
27368 # endif
27369 #else
27370 if (env->hflags & MIPS_HFLAG_BMASK) {
27371 /* If the exception was raised from a delay slot,
27372 come back to the jump. */
27373 env->CP0_ErrorEPC = (env->active_tc.PC
27374 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
27375 } else {
27376 env->CP0_ErrorEPC = env->active_tc.PC;
27378 env->active_tc.PC = env->exception_base;
27379 env->CP0_Random = env->tlb->nb_tlb - 1;
27380 env->tlb->tlb_in_use = env->tlb->nb_tlb;
27381 env->CP0_Wired = 0;
27382 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
27383 env->CP0_EBase = (cs->cpu_index & 0x3FF);
27384 if (mips_um_ksegs_enabled()) {
27385 env->CP0_EBase |= 0x40000000;
27386 } else {
27387 env->CP0_EBase |= (int32_t)0x80000000;
27389 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
27390 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
27392 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
27393 0x3ff : 0xff;
27394 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
27395 /* vectored interrupts not implemented, timer on int 7,
27396 no performance counters. */
27397 env->CP0_IntCtl = 0xe0000000;
27399 int i;
27401 for (i = 0; i < 7; i++) {
27402 env->CP0_WatchLo[i] = 0;
27403 env->CP0_WatchHi[i] = 0x80000000;
27405 env->CP0_WatchLo[7] = 0;
27406 env->CP0_WatchHi[7] = 0;
27408 /* Count register increments in debug mode, EJTAG version 1 */
27409 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
27411 cpu_mips_store_count(env, 1);
27413 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
27414 int i;
27416 /* Only TC0 on VPE 0 starts as active. */
27417 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
27418 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
27419 env->tcs[i].CP0_TCHalt = 1;
27421 env->active_tc.CP0_TCHalt = 1;
27422 cs->halted = 1;
27424 if (cs->cpu_index == 0) {
27425 /* VPE0 starts up enabled. */
27426 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
27427 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
27429 /* TC0 starts up unhalted. */
27430 cs->halted = 0;
27431 env->active_tc.CP0_TCHalt = 0;
27432 env->tcs[0].CP0_TCHalt = 0;
27433 /* With thread 0 active. */
27434 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
27435 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
27440 * Configure default legacy segmentation control. We use this regardless of
27441 * whether segmentation control is presented to the guest.
27443 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
27444 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
27445 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
27446 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
27447 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
27448 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27449 (2 << CP0SC_C);
27450 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
27451 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27452 (3 << CP0SC_C)) << 16;
27453 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
27454 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27455 (1 << CP0SC_EU) | (2 << CP0SC_C);
27456 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
27457 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27458 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
27459 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
27460 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
27461 #endif
27462 if ((env->insn_flags & ISA_MIPS32R6) &&
27463 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
27464 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
27465 env->CP0_Status |= (1 << CP0St_FR);
27468 if (env->insn_flags & ISA_MIPS32R6) {
27469 /* PTW = 1 */
27470 env->CP0_PWSize = 0x40;
27471 /* GDI = 12 */
27472 /* UDI = 12 */
27473 /* MDI = 12 */
27474 /* PRI = 12 */
27475 /* PTEI = 2 */
27476 env->CP0_PWField = 0x0C30C302;
27477 } else {
27478 /* GDI = 0 */
27479 /* UDI = 0 */
27480 /* MDI = 0 */
27481 /* PRI = 0 */
27482 /* PTEI = 2 */
27483 env->CP0_PWField = 0x02;
27486 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
27487 /* microMIPS on reset when Config3.ISA is 3 */
27488 env->hflags |= MIPS_HFLAG_M16;
27491 /* MSA */
27492 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
27493 msa_reset(env);
27496 compute_hflags(env);
27497 restore_fp_status(env);
27498 restore_pamask(env);
27499 cs->exception_index = EXCP_NONE;
27501 if (semihosting_get_argc()) {
27502 /* UHI interface can be used to obtain argc and argv */
27503 env->active_tc.gpr[4] = -1;
27507 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
27508 target_ulong *data)
27510 env->active_tc.PC = data[0];
27511 env->hflags &= ~MIPS_HFLAG_BMASK;
27512 env->hflags |= data[1];
27513 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
27514 case MIPS_HFLAG_BR:
27515 break;
27516 case MIPS_HFLAG_BC:
27517 case MIPS_HFLAG_BL:
27518 case MIPS_HFLAG_B:
27519 env->btarget = data[2];
27520 break;