target/mips: Clean up handling of CP0 register 0
[qemu/ar7.git] / target / mips / translate.c
blobc3fcfb45a1678076c47e437a836fa5809d638e10
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 "hw/semihosting/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
41 #include "qemu/qemu-print.h"
43 #define MIPS_DEBUG_DISAS 0
45 /* MIPS major opcodes */
46 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
48 enum {
49 /* indirect opcode tables */
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
58 /* arithmetic with immediate */
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
63 /* logic with immediate */
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
68 /* arithmetic with immediate */
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
71 /* Jump and branches */
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
82 OPC_JALX = (0x1D << 26),
83 OPC_DAUI = (0x1D << 26),
84 /* Load and stores */
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
91 OPC_LWPC = OPC_LW | 0x5,
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
106 OPC_LDPC = OPC_LD | 0x5,
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
110 /* Floating point load/store */
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
148 /* Cache and prefetch */
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
155 /* PC-relative address computation / loads */
156 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
158 enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
172 /* MIPS special opcodes */
173 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
175 enum {
176 /* Shifts */
177 OPC_SLL = 0x00 | OPC_SPECIAL,
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
182 OPC_ROTR = OPC_SRL | (1 << 21),
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
186 OPC_ROTRV = OPC_SRLV | (1 << 6),
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
194 OPC_DROTR = OPC_DSRL | (1 << 21),
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
200 /* Multiplication / division */
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
210 /* 2 registers arithmetic / logic */
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
225 /* Jumps */
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
228 /* Traps */
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
235 /* HI / LO registers load & stores */
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
240 /* Conditional moves */
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
249 /* Special */
250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
266 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
268 enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
297 /* Multiplication variants of the vr54xx. */
298 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
300 enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
317 /* REGIMM (rt field) opcodes */
318 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
320 enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
342 /* Special2 opcodes */
343 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
345 enum {
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
365 /* Misc */
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
370 /* Special */
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
374 /* Special3 opcodes */
375 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
377 enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
392 /* Loongson 2E */
393 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
394 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
395 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
396 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
397 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
398 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
399 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
400 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
401 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
402 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
403 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
404 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
406 /* MIPS DSP Load */
407 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
408 /* MIPS DSP Arithmetic */
409 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
410 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
411 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
412 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
413 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
414 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
415 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
416 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
417 /* MIPS DSP GPR-Based Shift Sub-class */
418 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
419 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
420 /* MIPS DSP Multiply Sub-class insns */
421 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
422 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
423 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
424 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
425 /* DSP Bit/Manipulation Sub-class */
426 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
427 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
428 /* MIPS DSP Append Sub-class */
429 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
430 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
431 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
432 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
433 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
435 /* EVA */
436 OPC_LWLE = 0x19 | OPC_SPECIAL3,
437 OPC_LWRE = 0x1A | OPC_SPECIAL3,
438 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
439 OPC_SBE = 0x1C | OPC_SPECIAL3,
440 OPC_SHE = 0x1D | OPC_SPECIAL3,
441 OPC_SCE = 0x1E | OPC_SPECIAL3,
442 OPC_SWE = 0x1F | OPC_SPECIAL3,
443 OPC_SWLE = 0x21 | OPC_SPECIAL3,
444 OPC_SWRE = 0x22 | OPC_SPECIAL3,
445 OPC_PREFE = 0x23 | OPC_SPECIAL3,
446 OPC_LBUE = 0x28 | OPC_SPECIAL3,
447 OPC_LHUE = 0x29 | OPC_SPECIAL3,
448 OPC_LBE = 0x2C | OPC_SPECIAL3,
449 OPC_LHE = 0x2D | OPC_SPECIAL3,
450 OPC_LLE = 0x2E | OPC_SPECIAL3,
451 OPC_LWE = 0x2F | OPC_SPECIAL3,
453 /* R6 */
454 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
455 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
456 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
457 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
458 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
459 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
462 /* BSHFL opcodes */
463 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
465 enum {
466 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
467 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
468 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
469 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
470 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
471 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
472 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
473 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
476 /* DBSHFL opcodes */
477 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
479 enum {
480 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
481 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
482 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
483 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
484 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
485 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
486 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
487 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
488 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
489 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
490 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
493 /* MIPS DSP REGIMM opcodes */
494 enum {
495 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
496 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
499 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
500 /* MIPS DSP Load */
501 enum {
502 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
503 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
504 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
505 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
508 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
509 enum {
510 /* MIPS DSP Arithmetic Sub-class */
511 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
525 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
527 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
528 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
529 /* MIPS DSP Multiply Sub-class insns */
530 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
538 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
539 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
554 /* MIPS DSP Multiply Sub-class insns */
555 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
556 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
561 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
562 enum {
563 /* MIPS DSP Arithmetic Sub-class */
564 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
577 /* DSP Bit/Manipulation Sub-class */
578 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
585 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
586 enum {
587 /* MIPS DSP Arithmetic Sub-class */
588 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
595 /* DSP Compare-Pick Sub-class */
596 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
613 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
614 enum {
615 /* MIPS DSP GPR-Based Shift Sub-class */
616 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
640 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
641 enum {
642 /* MIPS DSP Multiply Sub-class insns */
643 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
667 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
668 enum {
669 /* DSP Bit/Manipulation Sub-class */
670 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
673 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
674 enum {
675 /* MIPS DSP Append Sub-class */
676 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
677 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
678 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
681 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
682 enum {
683 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
684 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
696 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
698 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
699 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
700 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
703 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
704 enum {
705 /* MIPS DSP Arithmetic Sub-class */
706 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
723 /* DSP Bit/Manipulation Sub-class */
724 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
732 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
733 enum {
734 /* MIPS DSP Multiply Sub-class insns */
735 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
740 /* MIPS DSP Arithmetic Sub-class */
741 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
764 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
765 enum {
766 /* DSP Compare-Pick Sub-class */
767 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
786 /* MIPS DSP Arithmetic Sub-class */
787 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
797 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
798 enum {
799 /* DSP Append Sub-class */
800 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
801 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
803 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
806 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
807 enum {
808 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
809 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
810 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
832 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
833 enum {
834 /* DSP Bit/Manipulation Sub-class */
835 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
838 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
839 enum {
840 /* MIPS DSP Multiply Sub-class insns */
841 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
869 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
870 enum {
871 /* MIPS DSP GPR-Based Shift Sub-class */
872 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
900 /* Coprocessor 0 (rs field) */
901 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
903 enum {
904 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
905 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
906 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
907 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
908 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
909 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
910 OPC_MFTR = (0x08 << 21) | OPC_CP0,
911 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
912 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
913 OPC_MTTR = (0x0C << 21) | OPC_CP0,
914 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
915 OPC_C0 = (0x10 << 21) | OPC_CP0,
916 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
917 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
918 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
919 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
920 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
921 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
922 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
923 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
924 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
925 OPC_C0_A = (0x1A << 21) | OPC_CP0,
926 OPC_C0_B = (0x1B << 21) | OPC_CP0,
927 OPC_C0_C = (0x1C << 21) | OPC_CP0,
928 OPC_C0_D = (0x1D << 21) | OPC_CP0,
929 OPC_C0_E = (0x1E << 21) | OPC_CP0,
930 OPC_C0_F = (0x1F << 21) | OPC_CP0,
933 /* MFMC0 opcodes */
934 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
936 enum {
937 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
938 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
940 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
941 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
942 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
943 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
944 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
947 /* Coprocessor 0 (with rs == C0) */
948 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
950 enum {
951 OPC_TLBR = 0x01 | OPC_C0,
952 OPC_TLBWI = 0x02 | OPC_C0,
953 OPC_TLBINV = 0x03 | OPC_C0,
954 OPC_TLBINVF = 0x04 | OPC_C0,
955 OPC_TLBWR = 0x06 | OPC_C0,
956 OPC_TLBP = 0x08 | OPC_C0,
957 OPC_RFE = 0x10 | OPC_C0,
958 OPC_ERET = 0x18 | OPC_C0,
959 OPC_DERET = 0x1F | OPC_C0,
960 OPC_WAIT = 0x20 | OPC_C0,
963 /* Coprocessor 1 (rs field) */
964 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
966 /* Values for the fmt field in FP instructions */
967 enum {
968 /* 0 - 15 are reserved */
969 FMT_S = 16, /* single fp */
970 FMT_D = 17, /* double fp */
971 FMT_E = 18, /* extended fp */
972 FMT_Q = 19, /* quad fp */
973 FMT_W = 20, /* 32-bit fixed */
974 FMT_L = 21, /* 64-bit fixed */
975 FMT_PS = 22, /* paired single fp */
976 /* 23 - 31 are reserved */
979 enum {
980 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
981 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
982 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
983 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
984 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
985 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
986 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
987 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
988 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
989 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
990 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
991 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
992 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
993 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
994 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
995 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
996 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
997 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
998 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
999 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1000 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1001 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1002 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1003 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1004 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1005 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1006 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1007 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1008 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1009 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1012 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1013 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1015 enum {
1016 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1017 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1018 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1019 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1022 enum {
1023 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1024 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1027 enum {
1028 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1029 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1032 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1034 enum {
1035 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1036 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1037 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1038 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1039 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1040 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1041 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1042 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1043 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1044 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1045 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1048 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1050 enum {
1051 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1060 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1069 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1070 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1073 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1074 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1075 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1076 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1078 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1079 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1087 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1088 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1094 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1101 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1108 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1115 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1116 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1117 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1118 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1122 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1123 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1125 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1129 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1130 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1131 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1136 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1137 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1138 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1139 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1140 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1141 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1145 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1147 enum {
1148 OPC_LWXC1 = 0x00 | OPC_CP3,
1149 OPC_LDXC1 = 0x01 | OPC_CP3,
1150 OPC_LUXC1 = 0x05 | OPC_CP3,
1151 OPC_SWXC1 = 0x08 | OPC_CP3,
1152 OPC_SDXC1 = 0x09 | OPC_CP3,
1153 OPC_SUXC1 = 0x0D | OPC_CP3,
1154 OPC_PREFX = 0x0F | OPC_CP3,
1155 OPC_ALNV_PS = 0x1E | OPC_CP3,
1156 OPC_MADD_S = 0x20 | OPC_CP3,
1157 OPC_MADD_D = 0x21 | OPC_CP3,
1158 OPC_MADD_PS = 0x26 | OPC_CP3,
1159 OPC_MSUB_S = 0x28 | OPC_CP3,
1160 OPC_MSUB_D = 0x29 | OPC_CP3,
1161 OPC_MSUB_PS = 0x2E | OPC_CP3,
1162 OPC_NMADD_S = 0x30 | OPC_CP3,
1163 OPC_NMADD_D = 0x31 | OPC_CP3,
1164 OPC_NMADD_PS = 0x36 | OPC_CP3,
1165 OPC_NMSUB_S = 0x38 | OPC_CP3,
1166 OPC_NMSUB_D = 0x39 | OPC_CP3,
1167 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1170 /* MSA Opcodes */
1171 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1172 enum {
1173 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1174 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1175 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1176 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1177 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1178 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1179 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1180 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1181 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1182 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1183 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1184 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1185 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1186 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1187 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1188 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1189 OPC_MSA_ELM = 0x19 | OPC_MSA,
1190 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1191 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1192 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1193 OPC_MSA_VEC = 0x1E | OPC_MSA,
1195 /* MI10 instruction */
1196 OPC_LD_B = (0x20) | OPC_MSA,
1197 OPC_LD_H = (0x21) | OPC_MSA,
1198 OPC_LD_W = (0x22) | OPC_MSA,
1199 OPC_LD_D = (0x23) | OPC_MSA,
1200 OPC_ST_B = (0x24) | OPC_MSA,
1201 OPC_ST_H = (0x25) | OPC_MSA,
1202 OPC_ST_W = (0x26) | OPC_MSA,
1203 OPC_ST_D = (0x27) | OPC_MSA,
1206 enum {
1207 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1208 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1209 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1210 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1211 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1212 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1213 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1214 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1215 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1216 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1217 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1218 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1219 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1221 /* I8 instruction */
1222 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1223 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1225 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1226 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1228 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1229 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1230 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1231 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1233 /* VEC/2R/2RF instruction */
1234 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1235 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1236 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1237 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1238 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1239 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1240 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1242 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1245 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1246 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1247 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1248 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1249 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1251 /* 2RF instruction df(bit 16) = _w, _d */
1252 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1253 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1255 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1256 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1257 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1258 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1259 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1260 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1262 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1263 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1264 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1266 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1269 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1270 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1271 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1272 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1273 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1274 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1275 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1276 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1277 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1278 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1279 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1280 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1281 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1282 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1283 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1284 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1285 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1286 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1287 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1288 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1289 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1290 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1291 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1292 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1293 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1294 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1295 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1296 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1297 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1298 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1299 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1300 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1301 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1302 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1303 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1304 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1305 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1306 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1307 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1308 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1309 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1310 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1311 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1312 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1313 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1314 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1315 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1316 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1317 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1318 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1319 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1320 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1321 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1322 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1323 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1324 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1325 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1326 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1327 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1328 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1329 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1330 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1331 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1332 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1334 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1335 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1336 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1337 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1338 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1339 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1341 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1345 /* 3RF instruction _df(bit 21) = _w, _d */
1346 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1348 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1361 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1362 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1363 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1364 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1365 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1366 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1367 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1368 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1369 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1370 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1372 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1373 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1375 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1378 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1381 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1384 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1385 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1386 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1388 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1389 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1390 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1391 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1392 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1393 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1394 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1395 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1396 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1397 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1398 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1399 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1406 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1407 * ============================================
1410 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1411 * instructions set. It is designed to fit the needs of signal, graphical and
1412 * video processing applications. MXU instruction set is used in Xburst family
1413 * of microprocessors by Ingenic.
1415 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1416 * the control register.
1419 * The notation used in MXU assembler mnemonics
1420 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1422 * Register operands:
1424 * XRa, XRb, XRc, XRd - MXU registers
1425 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1427 * Non-register operands:
1429 * aptn1 - 1-bit accumulate add/subtract pattern
1430 * aptn2 - 2-bit accumulate add/subtract pattern
1431 * eptn2 - 2-bit execute add/subtract pattern
1432 * optn2 - 2-bit operand pattern
1433 * optn3 - 3-bit operand pattern
1434 * sft4 - 4-bit shift amount
1435 * strd2 - 2-bit stride amount
1437 * Prefixes:
1439 * Level of parallelism: Operand size:
1440 * S - single operation at a time 32 - word
1441 * D - two operations in parallel 16 - half word
1442 * Q - four operations in parallel 8 - byte
1444 * Operations:
1446 * ADD - Add or subtract
1447 * ADDC - Add with carry-in
1448 * ACC - Accumulate
1449 * ASUM - Sum together then accumulate (add or subtract)
1450 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1451 * AVG - Average between 2 operands
1452 * ABD - Absolute difference
1453 * ALN - Align data
1454 * AND - Logical bitwise 'and' operation
1455 * CPS - Copy sign
1456 * EXTR - Extract bits
1457 * I2M - Move from GPR register to MXU register
1458 * LDD - Load data from memory to XRF
1459 * LDI - Load data from memory to XRF (and increase the address base)
1460 * LUI - Load unsigned immediate
1461 * MUL - Multiply
1462 * MULU - Unsigned multiply
1463 * MADD - 64-bit operand add 32x32 product
1464 * MSUB - 64-bit operand subtract 32x32 product
1465 * MAC - Multiply and accumulate (add or subtract)
1466 * MAD - Multiply and add or subtract
1467 * MAX - Maximum between 2 operands
1468 * MIN - Minimum between 2 operands
1469 * M2I - Move from MXU register to GPR register
1470 * MOVZ - Move if zero
1471 * MOVN - Move if non-zero
1472 * NOR - Logical bitwise 'nor' operation
1473 * OR - Logical bitwise 'or' operation
1474 * STD - Store data from XRF to memory
1475 * SDI - Store data from XRF to memory (and increase the address base)
1476 * SLT - Set of less than comparison
1477 * SAD - Sum of absolute differences
1478 * SLL - Logical shift left
1479 * SLR - Logical shift right
1480 * SAR - Arithmetic shift right
1481 * SAT - Saturation
1482 * SFL - Shuffle
1483 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1484 * XOR - Logical bitwise 'exclusive or' operation
1486 * Suffixes:
1488 * E - Expand results
1489 * F - Fixed point multiplication
1490 * L - Low part result
1491 * R - Doing rounding
1492 * V - Variable instead of immediate
1493 * W - Combine above L and V
1496 * The list of MXU instructions grouped by functionality
1497 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1499 * Load/Store instructions Multiplication instructions
1500 * ----------------------- ---------------------------
1502 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1503 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1504 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1505 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1506 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1507 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1508 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1509 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1510 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1511 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1516 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1517 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1518 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1519 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1520 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1521 * S16SDI XRa, Rb, s10, eptn2
1522 * S8LDD XRa, Rb, s8, eptn3
1523 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1524 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1525 * S8SDI XRa, Rb, s8, eptn3
1526 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1527 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1528 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1529 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1530 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1531 * S32CPS XRa, XRb, XRc
1532 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1533 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1534 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1535 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1536 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1537 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1538 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1539 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1540 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1541 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1542 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1543 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1544 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1545 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1546 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1547 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1548 * Q8SLT XRa, XRb, XRc
1549 * Q8SLTU XRa, XRb, XRc
1550 * Q8MOVZ XRa, XRb, XRc Shift instructions
1551 * Q8MOVN XRa, XRb, XRc ------------------
1553 * D32SLL XRa, XRb, XRc, XRd, sft4
1554 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1555 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1556 * D32SARL XRa, XRb, XRc, sft4
1557 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1558 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1559 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1560 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1561 * Q16SLL XRa, XRb, XRc, XRd, sft4
1562 * Q16SLR XRa, XRb, XRc, XRd, sft4
1563 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1564 * ------------------------- Q16SLLV XRa, XRb, Rb
1565 * Q16SLRV XRa, XRb, Rb
1566 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1567 * S32ALN XRa, XRb, XRc, Rb
1568 * S32ALNI XRa, XRb, XRc, s3
1569 * S32LUI XRa, s8, optn3 Move instructions
1570 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1571 * S32EXTRV XRa, XRb, Rs, Rt
1572 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1573 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1576 * The opcode organization of MXU instructions
1577 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1579 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1580 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1581 * other bits up to the instruction level is as follows:
1583 * bits
1584 * 05..00
1586 * ┌─ 000000 ─ OPC_MXU_S32MADD
1587 * ├─ 000001 ─ OPC_MXU_S32MADDU
1588 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1589 * │
1590 * │ 20..18
1591 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1592 * │ ├─ 001 ─ OPC_MXU_S32MIN
1593 * │ ├─ 010 ─ OPC_MXU_D16MAX
1594 * │ ├─ 011 ─ OPC_MXU_D16MIN
1595 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1596 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1597 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1598 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1599 * ├─ 000100 ─ OPC_MXU_S32MSUB
1600 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1601 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1602 * │ ├─ 001 ─ OPC_MXU_D16SLT
1603 * │ ├─ 010 ─ OPC_MXU_D16AVG
1604 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1605 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1606 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1607 * │ └─ 111 ─ OPC_MXU_Q8ADD
1608 * │
1609 * │ 20..18
1610 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1611 * │ ├─ 010 ─ OPC_MXU_D16CPS
1612 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1613 * │ └─ 110 ─ OPC_MXU_Q16SAT
1614 * ├─ 001000 ─ OPC_MXU_D16MUL
1615 * │ 25..24
1616 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1617 * │ └─ 01 ─ OPC_MXU_D16MULE
1618 * ├─ 001010 ─ OPC_MXU_D16MAC
1619 * ├─ 001011 ─ OPC_MXU_D16MACF
1620 * ├─ 001100 ─ OPC_MXU_D16MADL
1621 * ├─ 001101 ─ OPC_MXU_S16MAD
1622 * ├─ 001110 ─ OPC_MXU_Q16ADD
1623 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1624 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1625 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1626 * │
1627 * │ 23
1628 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1629 * │ └─ 1 ─ OPC_MXU_S32STDR
1630 * │
1631 * │ 13..10
1632 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1633 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1634 * │
1635 * │ 13..10
1636 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1637 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1638 * │
1639 * │ 23
1640 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1641 * │ └─ 1 ─ OPC_MXU_S32LDIR
1642 * │
1643 * │ 23
1644 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1645 * │ └─ 1 ─ OPC_MXU_S32SDIR
1646 * │
1647 * │ 13..10
1648 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1649 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1650 * │
1651 * │ 13..10
1652 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1653 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1654 * ├─ 011000 ─ OPC_MXU_D32ADD
1655 * │ 23..22
1656 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1657 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1658 * │ └─ 10 ─ OPC_MXU_D32ASUM
1659 * ├─ 011010 ─ <not assigned>
1660 * │ 23..22
1661 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1662 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1663 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1664 * │
1665 * │ 23..22
1666 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1667 * │ ├─ 01 ─ OPC_MXU_D8SUM
1668 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1669 * ├─ 011110 ─ <not assigned>
1670 * ├─ 011111 ─ <not assigned>
1671 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1672 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1673 * ├─ 100010 ─ OPC_MXU_S8LDD
1674 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1675 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1676 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1677 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1678 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1679 * │
1680 * │ 20..18
1681 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1682 * │ ├─ 001 ─ OPC_MXU_S32ALN
1683 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1684 * │ ├─ 011 ─ OPC_MXU_S32LUI
1685 * │ ├─ 100 ─ OPC_MXU_S32NOR
1686 * │ ├─ 101 ─ OPC_MXU_S32AND
1687 * │ ├─ 110 ─ OPC_MXU_S32OR
1688 * │ └─ 111 ─ OPC_MXU_S32XOR
1689 * │
1690 * │ 7..5
1691 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1692 * │ ├─ 001 ─ OPC_MXU_LXH
1693 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1694 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1695 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1696 * ├─ 101100 ─ OPC_MXU_S16LDI
1697 * ├─ 101101 ─ OPC_MXU_S16SDI
1698 * ├─ 101110 ─ OPC_MXU_S32M2I
1699 * ├─ 101111 ─ OPC_MXU_S32I2M
1700 * ├─ 110000 ─ OPC_MXU_D32SLL
1701 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1702 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1703 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1704 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1705 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1706 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1707 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1708 * │
1709 * ├─ 110111 ─ OPC_MXU_Q16SAR
1710 * │ 23..22
1711 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1712 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1713 * │
1714 * │ 20..18
1715 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1716 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1717 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1718 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1719 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1720 * │ └─ 101 ─ OPC_MXU_S32MOVN
1721 * │
1722 * │ 23..22
1723 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1724 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1725 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1726 * ├─ 111100 ─ OPC_MXU_Q8MADL
1727 * ├─ 111101 ─ OPC_MXU_S32SFL
1728 * ├─ 111110 ─ OPC_MXU_Q8SAD
1729 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1732 * Compiled after:
1734 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1735 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1738 enum {
1739 OPC_MXU_S32MADD = 0x00,
1740 OPC_MXU_S32MADDU = 0x01,
1741 OPC__MXU_MUL = 0x02,
1742 OPC_MXU__POOL00 = 0x03,
1743 OPC_MXU_S32MSUB = 0x04,
1744 OPC_MXU_S32MSUBU = 0x05,
1745 OPC_MXU__POOL01 = 0x06,
1746 OPC_MXU__POOL02 = 0x07,
1747 OPC_MXU_D16MUL = 0x08,
1748 OPC_MXU__POOL03 = 0x09,
1749 OPC_MXU_D16MAC = 0x0A,
1750 OPC_MXU_D16MACF = 0x0B,
1751 OPC_MXU_D16MADL = 0x0C,
1752 OPC_MXU_S16MAD = 0x0D,
1753 OPC_MXU_Q16ADD = 0x0E,
1754 OPC_MXU_D16MACE = 0x0F,
1755 OPC_MXU__POOL04 = 0x10,
1756 OPC_MXU__POOL05 = 0x11,
1757 OPC_MXU__POOL06 = 0x12,
1758 OPC_MXU__POOL07 = 0x13,
1759 OPC_MXU__POOL08 = 0x14,
1760 OPC_MXU__POOL09 = 0x15,
1761 OPC_MXU__POOL10 = 0x16,
1762 OPC_MXU__POOL11 = 0x17,
1763 OPC_MXU_D32ADD = 0x18,
1764 OPC_MXU__POOL12 = 0x19,
1765 /* not assigned 0x1A */
1766 OPC_MXU__POOL13 = 0x1B,
1767 OPC_MXU__POOL14 = 0x1C,
1768 OPC_MXU_Q8ACCE = 0x1D,
1769 /* not assigned 0x1E */
1770 /* not assigned 0x1F */
1771 /* not assigned 0x20 */
1772 /* not assigned 0x21 */
1773 OPC_MXU_S8LDD = 0x22,
1774 OPC_MXU_S8STD = 0x23,
1775 OPC_MXU_S8LDI = 0x24,
1776 OPC_MXU_S8SDI = 0x25,
1777 OPC_MXU__POOL15 = 0x26,
1778 OPC_MXU__POOL16 = 0x27,
1779 OPC_MXU__POOL17 = 0x28,
1780 /* not assigned 0x29 */
1781 OPC_MXU_S16LDD = 0x2A,
1782 OPC_MXU_S16STD = 0x2B,
1783 OPC_MXU_S16LDI = 0x2C,
1784 OPC_MXU_S16SDI = 0x2D,
1785 OPC_MXU_S32M2I = 0x2E,
1786 OPC_MXU_S32I2M = 0x2F,
1787 OPC_MXU_D32SLL = 0x30,
1788 OPC_MXU_D32SLR = 0x31,
1789 OPC_MXU_D32SARL = 0x32,
1790 OPC_MXU_D32SAR = 0x33,
1791 OPC_MXU_Q16SLL = 0x34,
1792 OPC_MXU_Q16SLR = 0x35,
1793 OPC_MXU__POOL18 = 0x36,
1794 OPC_MXU_Q16SAR = 0x37,
1795 OPC_MXU__POOL19 = 0x38,
1796 OPC_MXU__POOL20 = 0x39,
1797 OPC_MXU__POOL21 = 0x3A,
1798 OPC_MXU_Q16SCOP = 0x3B,
1799 OPC_MXU_Q8MADL = 0x3C,
1800 OPC_MXU_S32SFL = 0x3D,
1801 OPC_MXU_Q8SAD = 0x3E,
1802 /* not assigned 0x3F */
1807 * MXU pool 00
1809 enum {
1810 OPC_MXU_S32MAX = 0x00,
1811 OPC_MXU_S32MIN = 0x01,
1812 OPC_MXU_D16MAX = 0x02,
1813 OPC_MXU_D16MIN = 0x03,
1814 OPC_MXU_Q8MAX = 0x04,
1815 OPC_MXU_Q8MIN = 0x05,
1816 OPC_MXU_Q8SLT = 0x06,
1817 OPC_MXU_Q8SLTU = 0x07,
1821 * MXU pool 01
1823 enum {
1824 OPC_MXU_S32SLT = 0x00,
1825 OPC_MXU_D16SLT = 0x01,
1826 OPC_MXU_D16AVG = 0x02,
1827 OPC_MXU_D16AVGR = 0x03,
1828 OPC_MXU_Q8AVG = 0x04,
1829 OPC_MXU_Q8AVGR = 0x05,
1830 OPC_MXU_Q8ADD = 0x07,
1834 * MXU pool 02
1836 enum {
1837 OPC_MXU_S32CPS = 0x00,
1838 OPC_MXU_D16CPS = 0x02,
1839 OPC_MXU_Q8ABD = 0x04,
1840 OPC_MXU_Q16SAT = 0x06,
1844 * MXU pool 03
1846 enum {
1847 OPC_MXU_D16MULF = 0x00,
1848 OPC_MXU_D16MULE = 0x01,
1852 * MXU pool 04
1854 enum {
1855 OPC_MXU_S32LDD = 0x00,
1856 OPC_MXU_S32LDDR = 0x01,
1860 * MXU pool 05
1862 enum {
1863 OPC_MXU_S32STD = 0x00,
1864 OPC_MXU_S32STDR = 0x01,
1868 * MXU pool 06
1870 enum {
1871 OPC_MXU_S32LDDV = 0x00,
1872 OPC_MXU_S32LDDVR = 0x01,
1876 * MXU pool 07
1878 enum {
1879 OPC_MXU_S32STDV = 0x00,
1880 OPC_MXU_S32STDVR = 0x01,
1884 * MXU pool 08
1886 enum {
1887 OPC_MXU_S32LDI = 0x00,
1888 OPC_MXU_S32LDIR = 0x01,
1892 * MXU pool 09
1894 enum {
1895 OPC_MXU_S32SDI = 0x00,
1896 OPC_MXU_S32SDIR = 0x01,
1900 * MXU pool 10
1902 enum {
1903 OPC_MXU_S32LDIV = 0x00,
1904 OPC_MXU_S32LDIVR = 0x01,
1908 * MXU pool 11
1910 enum {
1911 OPC_MXU_S32SDIV = 0x00,
1912 OPC_MXU_S32SDIVR = 0x01,
1916 * MXU pool 12
1918 enum {
1919 OPC_MXU_D32ACC = 0x00,
1920 OPC_MXU_D32ACCM = 0x01,
1921 OPC_MXU_D32ASUM = 0x02,
1925 * MXU pool 13
1927 enum {
1928 OPC_MXU_Q16ACC = 0x00,
1929 OPC_MXU_Q16ACCM = 0x01,
1930 OPC_MXU_Q16ASUM = 0x02,
1934 * MXU pool 14
1936 enum {
1937 OPC_MXU_Q8ADDE = 0x00,
1938 OPC_MXU_D8SUM = 0x01,
1939 OPC_MXU_D8SUMC = 0x02,
1943 * MXU pool 15
1945 enum {
1946 OPC_MXU_S32MUL = 0x00,
1947 OPC_MXU_S32MULU = 0x01,
1948 OPC_MXU_S32EXTR = 0x02,
1949 OPC_MXU_S32EXTRV = 0x03,
1953 * MXU pool 16
1955 enum {
1956 OPC_MXU_D32SARW = 0x00,
1957 OPC_MXU_S32ALN = 0x01,
1958 OPC_MXU_S32ALNI = 0x02,
1959 OPC_MXU_S32LUI = 0x03,
1960 OPC_MXU_S32NOR = 0x04,
1961 OPC_MXU_S32AND = 0x05,
1962 OPC_MXU_S32OR = 0x06,
1963 OPC_MXU_S32XOR = 0x07,
1967 * MXU pool 17
1969 enum {
1970 OPC_MXU_LXB = 0x00,
1971 OPC_MXU_LXH = 0x01,
1972 OPC_MXU_LXW = 0x03,
1973 OPC_MXU_LXBU = 0x04,
1974 OPC_MXU_LXHU = 0x05,
1978 * MXU pool 18
1980 enum {
1981 OPC_MXU_D32SLLV = 0x00,
1982 OPC_MXU_D32SLRV = 0x01,
1983 OPC_MXU_D32SARV = 0x03,
1984 OPC_MXU_Q16SLLV = 0x04,
1985 OPC_MXU_Q16SLRV = 0x05,
1986 OPC_MXU_Q16SARV = 0x07,
1990 * MXU pool 19
1992 enum {
1993 OPC_MXU_Q8MUL = 0x00,
1994 OPC_MXU_Q8MULSU = 0x01,
1998 * MXU pool 20
2000 enum {
2001 OPC_MXU_Q8MOVZ = 0x00,
2002 OPC_MXU_Q8MOVN = 0x01,
2003 OPC_MXU_D16MOVZ = 0x02,
2004 OPC_MXU_D16MOVN = 0x03,
2005 OPC_MXU_S32MOVZ = 0x04,
2006 OPC_MXU_S32MOVN = 0x05,
2010 * MXU pool 21
2012 enum {
2013 OPC_MXU_Q8MAC = 0x00,
2014 OPC_MXU_Q8MACSU = 0x01,
2018 * Overview of the TX79-specific instruction set
2019 * =============================================
2021 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2022 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2023 * instructions and certain multimedia instructions (MMIs). These MMIs
2024 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2025 * or sixteen 8-bit paths.
2027 * Reference:
2029 * The Toshiba TX System RISC TX79 Core Architecture manual,
2030 * https://wiki.qemu.org/File:C790.pdf
2032 * Three-Operand Multiply and Multiply-Add (4 instructions)
2033 * --------------------------------------------------------
2034 * MADD [rd,] rs, rt Multiply/Add
2035 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2036 * MULT [rd,] rs, rt Multiply (3-operand)
2037 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2039 * Multiply Instructions for Pipeline 1 (10 instructions)
2040 * ------------------------------------------------------
2041 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2042 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2043 * DIV1 rs, rt Divide Pipeline 1
2044 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2045 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2046 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2047 * MFHI1 rd Move From HI1 Register
2048 * MFLO1 rd Move From LO1 Register
2049 * MTHI1 rs Move To HI1 Register
2050 * MTLO1 rs Move To LO1 Register
2052 * Arithmetic (19 instructions)
2053 * ----------------------------
2054 * PADDB rd, rs, rt Parallel Add Byte
2055 * PSUBB rd, rs, rt Parallel Subtract Byte
2056 * PADDH rd, rs, rt Parallel Add Halfword
2057 * PSUBH rd, rs, rt Parallel Subtract Halfword
2058 * PADDW rd, rs, rt Parallel Add Word
2059 * PSUBW rd, rs, rt Parallel Subtract Word
2060 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2061 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2062 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2063 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2064 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2065 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2066 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2067 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2068 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2069 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2070 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2071 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2072 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2074 * Min/Max (4 instructions)
2075 * ------------------------
2076 * PMAXH rd, rs, rt Parallel Maximum Halfword
2077 * PMINH rd, rs, rt Parallel Minimum Halfword
2078 * PMAXW rd, rs, rt Parallel Maximum Word
2079 * PMINW rd, rs, rt Parallel Minimum Word
2081 * Absolute (2 instructions)
2082 * -------------------------
2083 * PABSH rd, rt Parallel Absolute Halfword
2084 * PABSW rd, rt Parallel Absolute Word
2086 * Logical (4 instructions)
2087 * ------------------------
2088 * PAND rd, rs, rt Parallel AND
2089 * POR rd, rs, rt Parallel OR
2090 * PXOR rd, rs, rt Parallel XOR
2091 * PNOR rd, rs, rt Parallel NOR
2093 * Shift (9 instructions)
2094 * ----------------------
2095 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2096 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2097 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2098 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2099 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2100 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2101 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2102 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2103 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2105 * Compare (6 instructions)
2106 * ------------------------
2107 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2108 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2109 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2110 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2111 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2112 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2114 * LZC (1 instruction)
2115 * -------------------
2116 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2118 * Quadword Load and Store (2 instructions)
2119 * ----------------------------------------
2120 * LQ rt, offset(base) Load Quadword
2121 * SQ rt, offset(base) Store Quadword
2123 * Multiply and Divide (19 instructions)
2124 * -------------------------------------
2125 * PMULTW rd, rs, rt Parallel Multiply Word
2126 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2127 * PDIVW rs, rt Parallel Divide Word
2128 * PDIVUW rs, rt Parallel Divide Unsigned Word
2129 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2130 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2131 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2132 * PMULTH rd, rs, rt Parallel Multiply Halfword
2133 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2134 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2135 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2136 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2137 * PDIVBW rs, rt Parallel Divide Broadcast Word
2138 * PMFHI rd Parallel Move From HI Register
2139 * PMFLO rd Parallel Move From LO Register
2140 * PMTHI rs Parallel Move To HI Register
2141 * PMTLO rs Parallel Move To LO Register
2142 * PMFHL rd Parallel Move From HI/LO Register
2143 * PMTHL rs Parallel Move To HI/LO Register
2145 * Pack/Extend (11 instructions)
2146 * -----------------------------
2147 * PPAC5 rd, rt Parallel Pack to 5 bits
2148 * PPACB rd, rs, rt Parallel Pack to Byte
2149 * PPACH rd, rs, rt Parallel Pack to Halfword
2150 * PPACW rd, rs, rt Parallel Pack to Word
2151 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2152 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2153 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2154 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2155 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2156 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2157 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2159 * Others (16 instructions)
2160 * ------------------------
2161 * PCPYH rd, rt Parallel Copy Halfword
2162 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2163 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2164 * PREVH rd, rt Parallel Reverse Halfword
2165 * PINTH rd, rs, rt Parallel Interleave Halfword
2166 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2167 * PEXEH rd, rt Parallel Exchange Even Halfword
2168 * PEXCH rd, rt Parallel Exchange Center Halfword
2169 * PEXEW rd, rt Parallel Exchange Even Word
2170 * PEXCW rd, rt Parallel Exchange Center Word
2171 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2172 * MFSA rd Move from Shift Amount Register
2173 * MTSA rs Move to Shift Amount Register
2174 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2175 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2176 * PROT3W rd, rt Parallel Rotate 3 Words
2178 * MMI (MultiMedia Instruction) encodings
2179 * ======================================
2181 * MMI instructions encoding table keys:
2183 * * This code is reserved for future use. An attempt to execute it
2184 * causes a Reserved Instruction exception.
2185 * % This code indicates an instruction class. The instruction word
2186 * must be further decoded by examining additional tables that show
2187 * the values for other instruction fields.
2188 * # This code is reserved for the unsupported instructions DMULT,
2189 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2190 * to execute it causes a Reserved Instruction exception.
2192 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2194 * 31 26 0
2195 * +--------+----------------------------------------+
2196 * | opcode | |
2197 * +--------+----------------------------------------+
2199 * opcode bits 28..26
2200 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2201 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2202 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2203 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2204 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2205 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2206 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2207 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2208 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2209 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2210 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2213 enum {
2214 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2215 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2216 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2220 * MMI instructions with opcode field = MMI:
2222 * 31 26 5 0
2223 * +--------+-------------------------------+--------+
2224 * | MMI | |function|
2225 * +--------+-------------------------------+--------+
2227 * function bits 2..0
2228 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2229 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2230 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2231 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2232 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2233 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2234 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2235 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2236 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2237 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2238 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2241 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2242 enum {
2243 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2244 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2245 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2246 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2249 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2250 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2251 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2252 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2253 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2254 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2255 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2256 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2271 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2273 * 31 26 10 6 5 0
2274 * +--------+----------------------+--------+--------+
2275 * | MMI | |function| MMI0 |
2276 * +--------+----------------------+--------+--------+
2278 * function bits 7..6
2279 * bits | 0 | 1 | 2 | 3
2280 * 10..8 | 00 | 01 | 10 | 11
2281 * -------+-------+-------+-------+-------
2282 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2283 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2284 * 2 010 | PADDB | PSUBB | PCGTB | *
2285 * 3 011 | * | * | * | *
2286 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2287 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2288 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2289 * 7 111 | * | * | PEXT5 | PPAC5
2292 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2293 enum {
2294 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2322 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2324 * 31 26 10 6 5 0
2325 * +--------+----------------------+--------+--------+
2326 * | MMI | |function| MMI1 |
2327 * +--------+----------------------+--------+--------+
2329 * function bits 7..6
2330 * bits | 0 | 1 | 2 | 3
2331 * 10..8 | 00 | 01 | 10 | 11
2332 * -------+-------+-------+-------+-------
2333 * 0 000 | * | PABSW | PCEQW | PMINW
2334 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2335 * 2 010 | * | * | PCEQB | *
2336 * 3 011 | * | * | * | *
2337 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2338 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2339 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2340 * 7 111 | * | * | * | *
2343 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2344 enum {
2345 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2366 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2368 * 31 26 10 6 5 0
2369 * +--------+----------------------+--------+--------+
2370 * | MMI | |function| MMI2 |
2371 * +--------+----------------------+--------+--------+
2373 * function bits 7..6
2374 * bits | 0 | 1 | 2 | 3
2375 * 10..8 | 00 | 01 | 10 | 11
2376 * -------+-------+-------+-------+-------
2377 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2378 * 1 001 | PMSUBW| * | * | *
2379 * 2 010 | PMFHI | PMFLO | PINTH | *
2380 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2381 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2382 * 5 101 | PMSUBH| PHMSBH| * | *
2383 * 6 110 | * | * | PEXEH | PREVH
2384 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2387 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2388 enum {
2389 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2414 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2416 * 31 26 10 6 5 0
2417 * +--------+----------------------+--------+--------+
2418 * | MMI | |function| MMI3 |
2419 * +--------+----------------------+--------+--------+
2421 * function bits 7..6
2422 * bits | 0 | 1 | 2 | 3
2423 * 10..8 | 00 | 01 | 10 | 11
2424 * -------+-------+-------+-------+-------
2425 * 0 000 |PMADDUW| * | * | PSRAVW
2426 * 1 001 | * | * | * | *
2427 * 2 010 | PMTHI | PMTLO | PINTEH| *
2428 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2429 * 4 100 | * | * | POR | PNOR
2430 * 5 101 | * | * | * | *
2431 * 6 110 | * | * | PEXCH | PCPYH
2432 * 7 111 | * | * | PEXCW | *
2435 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2436 enum {
2437 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2452 /* global register indices */
2453 static TCGv cpu_gpr[32], cpu_PC;
2454 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2455 static TCGv cpu_dspctrl, btarget, bcond;
2456 static TCGv cpu_lladdr, cpu_llval;
2457 static TCGv_i32 hflags;
2458 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2459 static TCGv_i64 fpu_f64[32];
2460 static TCGv_i64 msa_wr_d[64];
2462 #if defined(TARGET_MIPS64)
2463 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2464 static TCGv_i64 cpu_mmr[32];
2465 #endif
2467 #if !defined(TARGET_MIPS64)
2468 /* MXU registers */
2469 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2470 static TCGv mxu_CR;
2471 #endif
2473 #include "exec/gen-icount.h"
2475 #define gen_helper_0e0i(name, arg) do { \
2476 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2477 gen_helper_##name(cpu_env, helper_tmp); \
2478 tcg_temp_free_i32(helper_tmp); \
2479 } while (0)
2481 #define gen_helper_0e1i(name, arg1, arg2) do { \
2482 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2483 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2484 tcg_temp_free_i32(helper_tmp); \
2485 } while (0)
2487 #define gen_helper_1e0i(name, ret, arg1) do { \
2488 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2489 gen_helper_##name(ret, cpu_env, helper_tmp); \
2490 tcg_temp_free_i32(helper_tmp); \
2491 } while (0)
2493 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2494 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2495 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2496 tcg_temp_free_i32(helper_tmp); \
2497 } while (0)
2499 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2500 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2501 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2502 tcg_temp_free_i32(helper_tmp); \
2503 } while (0)
2505 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2506 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2507 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2508 tcg_temp_free_i32(helper_tmp); \
2509 } while (0)
2511 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2512 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2513 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2514 tcg_temp_free_i32(helper_tmp); \
2515 } while (0)
2517 typedef struct DisasContext {
2518 DisasContextBase base;
2519 target_ulong saved_pc;
2520 target_ulong page_start;
2521 uint32_t opcode;
2522 uint64_t insn_flags;
2523 int32_t CP0_Config1;
2524 int32_t CP0_Config2;
2525 int32_t CP0_Config3;
2526 int32_t CP0_Config5;
2527 /* Routine used to access memory */
2528 int mem_idx;
2529 TCGMemOp default_tcg_memop_mask;
2530 uint32_t hflags, saved_hflags;
2531 target_ulong btarget;
2532 bool ulri;
2533 int kscrexist;
2534 bool rxi;
2535 int ie;
2536 bool bi;
2537 bool bp;
2538 uint64_t PAMask;
2539 bool mvh;
2540 bool eva;
2541 bool sc;
2542 int CP0_LLAddr_shift;
2543 bool ps;
2544 bool vp;
2545 bool cmgcr;
2546 bool mrp;
2547 bool nan2008;
2548 bool abs2008;
2549 bool saar;
2550 } DisasContext;
2552 #define DISAS_STOP DISAS_TARGET_0
2553 #define DISAS_EXIT DISAS_TARGET_1
2555 static const char * const regnames[] = {
2556 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2557 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2558 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2559 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2562 static const char * const regnames_HI[] = {
2563 "HI0", "HI1", "HI2", "HI3",
2566 static const char * const regnames_LO[] = {
2567 "LO0", "LO1", "LO2", "LO3",
2570 static const char * const fregnames[] = {
2571 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2572 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2573 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2574 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2577 static const char * const msaregnames[] = {
2578 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2579 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2580 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2581 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2582 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2583 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2584 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2585 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2586 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2587 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2588 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2589 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2590 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2591 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2592 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2593 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2596 #if !defined(TARGET_MIPS64)
2597 static const char * const mxuregnames[] = {
2598 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2599 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2601 #endif
2603 #define LOG_DISAS(...) \
2604 do { \
2605 if (MIPS_DEBUG_DISAS) { \
2606 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2608 } while (0)
2610 #define MIPS_INVAL(op) \
2611 do { \
2612 if (MIPS_DEBUG_DISAS) { \
2613 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2614 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2615 ctx->base.pc_next, ctx->opcode, op, \
2616 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2617 ((ctx->opcode >> 16) & 0x1F)); \
2619 } while (0)
2621 /* General purpose registers moves. */
2622 static inline void gen_load_gpr(TCGv t, int reg)
2624 if (reg == 0) {
2625 tcg_gen_movi_tl(t, 0);
2626 } else {
2627 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2631 static inline void gen_store_gpr(TCGv t, int reg)
2633 if (reg != 0) {
2634 tcg_gen_mov_tl(cpu_gpr[reg], t);
2638 /* Moves to/from shadow registers. */
2639 static inline void gen_load_srsgpr(int from, int to)
2641 TCGv t0 = tcg_temp_new();
2643 if (from == 0) {
2644 tcg_gen_movi_tl(t0, 0);
2645 } else {
2646 TCGv_i32 t2 = tcg_temp_new_i32();
2647 TCGv_ptr addr = tcg_temp_new_ptr();
2649 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2650 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2651 tcg_gen_andi_i32(t2, t2, 0xf);
2652 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2653 tcg_gen_ext_i32_ptr(addr, t2);
2654 tcg_gen_add_ptr(addr, cpu_env, addr);
2656 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2657 tcg_temp_free_ptr(addr);
2658 tcg_temp_free_i32(t2);
2660 gen_store_gpr(t0, to);
2661 tcg_temp_free(t0);
2664 static inline void gen_store_srsgpr(int from, int to)
2666 if (to != 0) {
2667 TCGv t0 = tcg_temp_new();
2668 TCGv_i32 t2 = tcg_temp_new_i32();
2669 TCGv_ptr addr = tcg_temp_new_ptr();
2671 gen_load_gpr(t0, from);
2672 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2673 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2674 tcg_gen_andi_i32(t2, t2, 0xf);
2675 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2676 tcg_gen_ext_i32_ptr(addr, t2);
2677 tcg_gen_add_ptr(addr, cpu_env, addr);
2679 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2680 tcg_temp_free_ptr(addr);
2681 tcg_temp_free_i32(t2);
2682 tcg_temp_free(t0);
2686 #if !defined(TARGET_MIPS64)
2687 /* MXU General purpose registers moves. */
2688 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2690 if (reg == 0) {
2691 tcg_gen_movi_tl(t, 0);
2692 } else if (reg <= 15) {
2693 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2697 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2699 if (reg > 0 && reg <= 15) {
2700 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2704 /* MXU control register moves. */
2705 static inline void gen_load_mxu_cr(TCGv t)
2707 tcg_gen_mov_tl(t, mxu_CR);
2710 static inline void gen_store_mxu_cr(TCGv t)
2712 /* TODO: Add handling of RW rules for MXU_CR. */
2713 tcg_gen_mov_tl(mxu_CR, t);
2715 #endif
2718 /* Tests */
2719 static inline void gen_save_pc(target_ulong pc)
2721 tcg_gen_movi_tl(cpu_PC, pc);
2724 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2726 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2727 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2728 gen_save_pc(ctx->base.pc_next);
2729 ctx->saved_pc = ctx->base.pc_next;
2731 if (ctx->hflags != ctx->saved_hflags) {
2732 tcg_gen_movi_i32(hflags, ctx->hflags);
2733 ctx->saved_hflags = ctx->hflags;
2734 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2735 case MIPS_HFLAG_BR:
2736 break;
2737 case MIPS_HFLAG_BC:
2738 case MIPS_HFLAG_BL:
2739 case MIPS_HFLAG_B:
2740 tcg_gen_movi_tl(btarget, ctx->btarget);
2741 break;
2746 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2748 ctx->saved_hflags = ctx->hflags;
2749 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2750 case MIPS_HFLAG_BR:
2751 break;
2752 case MIPS_HFLAG_BC:
2753 case MIPS_HFLAG_BL:
2754 case MIPS_HFLAG_B:
2755 ctx->btarget = env->btarget;
2756 break;
2760 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2762 TCGv_i32 texcp = tcg_const_i32(excp);
2763 TCGv_i32 terr = tcg_const_i32(err);
2764 save_cpu_state(ctx, 1);
2765 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2766 tcg_temp_free_i32(terr);
2767 tcg_temp_free_i32(texcp);
2768 ctx->base.is_jmp = DISAS_NORETURN;
2771 static inline void generate_exception(DisasContext *ctx, int excp)
2773 gen_helper_0e0i(raise_exception, excp);
2776 static inline void generate_exception_end(DisasContext *ctx, int excp)
2778 generate_exception_err(ctx, excp, 0);
2781 /* Floating point register moves. */
2782 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2784 if (ctx->hflags & MIPS_HFLAG_FRE) {
2785 generate_exception(ctx, EXCP_RI);
2787 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2790 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2792 TCGv_i64 t64;
2793 if (ctx->hflags & MIPS_HFLAG_FRE) {
2794 generate_exception(ctx, EXCP_RI);
2796 t64 = tcg_temp_new_i64();
2797 tcg_gen_extu_i32_i64(t64, t);
2798 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2799 tcg_temp_free_i64(t64);
2802 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2804 if (ctx->hflags & MIPS_HFLAG_F64) {
2805 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2806 } else {
2807 gen_load_fpr32(ctx, t, reg | 1);
2811 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2813 if (ctx->hflags & MIPS_HFLAG_F64) {
2814 TCGv_i64 t64 = tcg_temp_new_i64();
2815 tcg_gen_extu_i32_i64(t64, t);
2816 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2817 tcg_temp_free_i64(t64);
2818 } else {
2819 gen_store_fpr32(ctx, t, reg | 1);
2823 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2825 if (ctx->hflags & MIPS_HFLAG_F64) {
2826 tcg_gen_mov_i64(t, fpu_f64[reg]);
2827 } else {
2828 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2832 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2834 if (ctx->hflags & MIPS_HFLAG_F64) {
2835 tcg_gen_mov_i64(fpu_f64[reg], t);
2836 } else {
2837 TCGv_i64 t0;
2838 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2839 t0 = tcg_temp_new_i64();
2840 tcg_gen_shri_i64(t0, t, 32);
2841 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2842 tcg_temp_free_i64(t0);
2846 static inline int get_fp_bit(int cc)
2848 if (cc) {
2849 return 24 + cc;
2850 } else {
2851 return 23;
2855 /* Addresses computation */
2856 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2857 TCGv arg1)
2859 tcg_gen_add_tl(ret, arg0, arg1);
2861 #if defined(TARGET_MIPS64)
2862 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2863 tcg_gen_ext32s_i64(ret, ret);
2865 #endif
2868 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2869 target_long ofs)
2871 tcg_gen_addi_tl(ret, base, ofs);
2873 #if defined(TARGET_MIPS64)
2874 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2875 tcg_gen_ext32s_i64(ret, ret);
2877 #endif
2880 /* Addresses computation (translation time) */
2881 static target_long addr_add(DisasContext *ctx, target_long base,
2882 target_long offset)
2884 target_long sum = base + offset;
2886 #if defined(TARGET_MIPS64)
2887 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2888 sum = (int32_t)sum;
2890 #endif
2891 return sum;
2894 /* Sign-extract the low 32-bits to a target_long. */
2895 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2897 #if defined(TARGET_MIPS64)
2898 tcg_gen_ext32s_i64(ret, arg);
2899 #else
2900 tcg_gen_extrl_i64_i32(ret, arg);
2901 #endif
2904 /* Sign-extract the high 32-bits to a target_long. */
2905 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2907 #if defined(TARGET_MIPS64)
2908 tcg_gen_sari_i64(ret, arg, 32);
2909 #else
2910 tcg_gen_extrh_i64_i32(ret, arg);
2911 #endif
2914 static inline void check_cp0_enabled(DisasContext *ctx)
2916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2917 generate_exception_err(ctx, EXCP_CpU, 0);
2921 static inline void check_cp1_enabled(DisasContext *ctx)
2923 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2924 generate_exception_err(ctx, EXCP_CpU, 1);
2929 * Verify that the processor is running with COP1X instructions enabled.
2930 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2931 * opcode tables.
2933 static inline void check_cop1x(DisasContext *ctx)
2935 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2936 generate_exception_end(ctx, EXCP_RI);
2941 * Verify that the processor is running with 64-bit floating-point
2942 * operations enabled.
2944 static inline void check_cp1_64bitmode(DisasContext *ctx)
2946 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2947 generate_exception_end(ctx, EXCP_RI);
2952 * Verify if floating point register is valid; an operation is not defined
2953 * if bit 0 of any register specification is set and the FR bit in the
2954 * Status register equals zero, since the register numbers specify an
2955 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2956 * in the Status register equals one, both even and odd register numbers
2957 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2959 * Multiple 64 bit wide registers can be checked by calling
2960 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2962 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2964 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2965 generate_exception_end(ctx, EXCP_RI);
2970 * Verify that the processor is running with DSP instructions enabled.
2971 * This is enabled by CP0 Status register MX(24) bit.
2973 static inline void check_dsp(DisasContext *ctx)
2975 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2976 if (ctx->insn_flags & ASE_DSP) {
2977 generate_exception_end(ctx, EXCP_DSPDIS);
2978 } else {
2979 generate_exception_end(ctx, EXCP_RI);
2984 static inline void check_dsp_r2(DisasContext *ctx)
2986 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2987 if (ctx->insn_flags & ASE_DSP) {
2988 generate_exception_end(ctx, EXCP_DSPDIS);
2989 } else {
2990 generate_exception_end(ctx, EXCP_RI);
2995 static inline void check_dsp_r3(DisasContext *ctx)
2997 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2998 if (ctx->insn_flags & ASE_DSP) {
2999 generate_exception_end(ctx, EXCP_DSPDIS);
3000 } else {
3001 generate_exception_end(ctx, EXCP_RI);
3007 * This code generates a "reserved instruction" exception if the
3008 * CPU does not support the instruction set corresponding to flags.
3010 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3012 if (unlikely(!(ctx->insn_flags & flags))) {
3013 generate_exception_end(ctx, EXCP_RI);
3018 * This code generates a "reserved instruction" exception if the
3019 * CPU has corresponding flag set which indicates that the instruction
3020 * has been removed.
3022 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3024 if (unlikely(ctx->insn_flags & flags)) {
3025 generate_exception_end(ctx, EXCP_RI);
3030 * The Linux kernel traps certain reserved instruction exceptions to
3031 * emulate the corresponding instructions. QEMU is the kernel in user
3032 * mode, so those traps are emulated by accepting the instructions.
3034 * A reserved instruction exception is generated for flagged CPUs if
3035 * QEMU runs in system mode.
3037 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3039 #ifndef CONFIG_USER_ONLY
3040 check_insn_opc_removed(ctx, flags);
3041 #endif
3045 * This code generates a "reserved instruction" exception if the
3046 * CPU does not support 64-bit paired-single (PS) floating point data type.
3048 static inline void check_ps(DisasContext *ctx)
3050 if (unlikely(!ctx->ps)) {
3051 generate_exception(ctx, EXCP_RI);
3053 check_cp1_64bitmode(ctx);
3056 #ifdef TARGET_MIPS64
3058 * This code generates a "reserved instruction" exception if 64-bit
3059 * instructions are not enabled.
3061 static inline void check_mips_64(DisasContext *ctx)
3063 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3064 generate_exception_end(ctx, EXCP_RI);
3067 #endif
3069 #ifndef CONFIG_USER_ONLY
3070 static inline void check_mvh(DisasContext *ctx)
3072 if (unlikely(!ctx->mvh)) {
3073 generate_exception(ctx, EXCP_RI);
3076 #endif
3079 * This code generates a "reserved instruction" exception if the
3080 * Config5 XNP bit is set.
3082 static inline void check_xnp(DisasContext *ctx)
3084 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3085 generate_exception_end(ctx, EXCP_RI);
3089 #ifndef CONFIG_USER_ONLY
3091 * This code generates a "reserved instruction" exception if the
3092 * Config3 PW bit is NOT set.
3094 static inline void check_pw(DisasContext *ctx)
3096 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3097 generate_exception_end(ctx, EXCP_RI);
3100 #endif
3103 * This code generates a "reserved instruction" exception if the
3104 * Config3 MT bit is NOT set.
3106 static inline void check_mt(DisasContext *ctx)
3108 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3109 generate_exception_end(ctx, EXCP_RI);
3113 #ifndef CONFIG_USER_ONLY
3115 * This code generates a "coprocessor unusable" exception if CP0 is not
3116 * available, and, if that is not the case, generates a "reserved instruction"
3117 * exception if the Config5 MT bit is NOT set. This is needed for availability
3118 * control of some of MT ASE instructions.
3120 static inline void check_cp0_mt(DisasContext *ctx)
3122 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3123 generate_exception_err(ctx, EXCP_CpU, 0);
3124 } else {
3125 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3126 generate_exception_err(ctx, EXCP_RI, 0);
3130 #endif
3133 * This code generates a "reserved instruction" exception if the
3134 * Config5 NMS bit is set.
3136 static inline void check_nms(DisasContext *ctx)
3138 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3139 generate_exception_end(ctx, EXCP_RI);
3144 * This code generates a "reserved instruction" exception if the
3145 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3146 * Config2 TL, and Config5 L2C are unset.
3148 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3150 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3151 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3152 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3153 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3154 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3155 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3156 generate_exception_end(ctx, EXCP_RI);
3161 * This code generates a "reserved instruction" exception if the
3162 * Config5 EVA bit is NOT set.
3164 static inline void check_eva(DisasContext *ctx)
3166 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3167 generate_exception_end(ctx, EXCP_RI);
3173 * Define small wrappers for gen_load_fpr* so that we have a uniform
3174 * calling interface for 32 and 64-bit FPRs. No sense in changing
3175 * all callers for gen_load_fpr32 when we need the CTX parameter for
3176 * this one use.
3178 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3179 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3180 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3181 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3182 int ft, int fs, int cc) \
3184 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3185 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3186 switch (ifmt) { \
3187 case FMT_PS: \
3188 check_ps(ctx); \
3189 break; \
3190 case FMT_D: \
3191 if (abs) { \
3192 check_cop1x(ctx); \
3194 check_cp1_registers(ctx, fs | ft); \
3195 break; \
3196 case FMT_S: \
3197 if (abs) { \
3198 check_cop1x(ctx); \
3200 break; \
3202 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3203 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3204 switch (n) { \
3205 case 0: \
3206 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3207 break; \
3208 case 1: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3210 break; \
3211 case 2: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3213 break; \
3214 case 3: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3216 break; \
3217 case 4: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3219 break; \
3220 case 5: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3222 break; \
3223 case 6: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3225 break; \
3226 case 7: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3228 break; \
3229 case 8: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3231 break; \
3232 case 9: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3234 break; \
3235 case 10: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3237 break; \
3238 case 11: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3240 break; \
3241 case 12: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3243 break; \
3244 case 13: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3246 break; \
3247 case 14: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3249 break; \
3250 case 15: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3252 break; \
3253 default: \
3254 abort(); \
3256 tcg_temp_free_i##bits(fp0); \
3257 tcg_temp_free_i##bits(fp1); \
3260 FOP_CONDS(, 0, d, FMT_D, 64)
3261 FOP_CONDS(abs, 1, d, FMT_D, 64)
3262 FOP_CONDS(, 0, s, FMT_S, 32)
3263 FOP_CONDS(abs, 1, s, FMT_S, 32)
3264 FOP_CONDS(, 0, ps, FMT_PS, 64)
3265 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3266 #undef FOP_CONDS
3268 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3269 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3270 int ft, int fs, int fd) \
3272 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3273 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3274 if (ifmt == FMT_D) { \
3275 check_cp1_registers(ctx, fs | ft | fd); \
3277 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3278 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3279 switch (n) { \
3280 case 0: \
3281 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3282 break; \
3283 case 1: \
3284 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 2: \
3287 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 3: \
3290 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 4: \
3293 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 5: \
3296 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 6: \
3299 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 7: \
3302 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 8: \
3305 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 9: \
3308 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 10: \
3311 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 11: \
3314 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 12: \
3317 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 13: \
3320 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 14: \
3323 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 15: \
3326 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 17: \
3329 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 18: \
3332 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 19: \
3335 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 25: \
3338 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 26: \
3341 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 27: \
3344 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 default: \
3347 abort(); \
3349 STORE; \
3350 tcg_temp_free_i ## bits(fp0); \
3351 tcg_temp_free_i ## bits(fp1); \
3354 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3355 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3356 #undef FOP_CONDNS
3357 #undef gen_ldcmp_fpr32
3358 #undef gen_ldcmp_fpr64
3360 /* load/store instructions. */
3361 #ifdef CONFIG_USER_ONLY
3362 #define OP_LD_ATOMIC(insn, fname) \
3363 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3364 DisasContext *ctx) \
3366 TCGv t0 = tcg_temp_new(); \
3367 tcg_gen_mov_tl(t0, arg1); \
3368 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3369 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3370 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3371 tcg_temp_free(t0); \
3373 #else
3374 #define OP_LD_ATOMIC(insn, fname) \
3375 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3376 DisasContext *ctx) \
3378 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3380 #endif
3381 OP_LD_ATOMIC(ll, ld32s);
3382 #if defined(TARGET_MIPS64)
3383 OP_LD_ATOMIC(lld, ld64);
3384 #endif
3385 #undef OP_LD_ATOMIC
3387 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3388 int base, int offset)
3390 if (base == 0) {
3391 tcg_gen_movi_tl(addr, offset);
3392 } else if (offset == 0) {
3393 gen_load_gpr(addr, base);
3394 } else {
3395 tcg_gen_movi_tl(addr, offset);
3396 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3400 static target_ulong pc_relative_pc(DisasContext *ctx)
3402 target_ulong pc = ctx->base.pc_next;
3404 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3405 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3407 pc -= branch_bytes;
3410 pc &= ~(target_ulong)3;
3411 return pc;
3414 /* Load */
3415 static void gen_ld(DisasContext *ctx, uint32_t opc,
3416 int rt, int base, int offset)
3418 TCGv t0, t1, t2;
3419 int mem_idx = ctx->mem_idx;
3421 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3423 * Loongson CPU uses a load to zero register for prefetch.
3424 * We emulate it as a NOP. On other CPU we must perform the
3425 * actual memory access.
3427 return;
3430 t0 = tcg_temp_new();
3431 gen_base_offset_addr(ctx, t0, base, offset);
3433 switch (opc) {
3434 #if defined(TARGET_MIPS64)
3435 case OPC_LWU:
3436 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3437 ctx->default_tcg_memop_mask);
3438 gen_store_gpr(t0, rt);
3439 break;
3440 case OPC_LD:
3441 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3442 ctx->default_tcg_memop_mask);
3443 gen_store_gpr(t0, rt);
3444 break;
3445 case OPC_LLD:
3446 case R6_OPC_LLD:
3447 op_ld_lld(t0, t0, mem_idx, ctx);
3448 gen_store_gpr(t0, rt);
3449 break;
3450 case OPC_LDL:
3451 t1 = tcg_temp_new();
3453 * Do a byte access to possibly trigger a page
3454 * fault with the unaligned address.
3456 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3457 tcg_gen_andi_tl(t1, t0, 7);
3458 #ifndef TARGET_WORDS_BIGENDIAN
3459 tcg_gen_xori_tl(t1, t1, 7);
3460 #endif
3461 tcg_gen_shli_tl(t1, t1, 3);
3462 tcg_gen_andi_tl(t0, t0, ~7);
3463 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3464 tcg_gen_shl_tl(t0, t0, t1);
3465 t2 = tcg_const_tl(-1);
3466 tcg_gen_shl_tl(t2, t2, t1);
3467 gen_load_gpr(t1, rt);
3468 tcg_gen_andc_tl(t1, t1, t2);
3469 tcg_temp_free(t2);
3470 tcg_gen_or_tl(t0, t0, t1);
3471 tcg_temp_free(t1);
3472 gen_store_gpr(t0, rt);
3473 break;
3474 case OPC_LDR:
3475 t1 = tcg_temp_new();
3477 * Do a byte access to possibly trigger a page
3478 * fault with the unaligned address.
3480 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3481 tcg_gen_andi_tl(t1, t0, 7);
3482 #ifdef TARGET_WORDS_BIGENDIAN
3483 tcg_gen_xori_tl(t1, t1, 7);
3484 #endif
3485 tcg_gen_shli_tl(t1, t1, 3);
3486 tcg_gen_andi_tl(t0, t0, ~7);
3487 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3488 tcg_gen_shr_tl(t0, t0, t1);
3489 tcg_gen_xori_tl(t1, t1, 63);
3490 t2 = tcg_const_tl(0xfffffffffffffffeull);
3491 tcg_gen_shl_tl(t2, t2, t1);
3492 gen_load_gpr(t1, rt);
3493 tcg_gen_and_tl(t1, t1, t2);
3494 tcg_temp_free(t2);
3495 tcg_gen_or_tl(t0, t0, t1);
3496 tcg_temp_free(t1);
3497 gen_store_gpr(t0, rt);
3498 break;
3499 case OPC_LDPC:
3500 t1 = tcg_const_tl(pc_relative_pc(ctx));
3501 gen_op_addr_add(ctx, t0, t0, t1);
3502 tcg_temp_free(t1);
3503 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3504 gen_store_gpr(t0, rt);
3505 break;
3506 #endif
3507 case OPC_LWPC:
3508 t1 = tcg_const_tl(pc_relative_pc(ctx));
3509 gen_op_addr_add(ctx, t0, t0, t1);
3510 tcg_temp_free(t1);
3511 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3512 gen_store_gpr(t0, rt);
3513 break;
3514 case OPC_LWE:
3515 mem_idx = MIPS_HFLAG_UM;
3516 /* fall through */
3517 case OPC_LW:
3518 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3519 ctx->default_tcg_memop_mask);
3520 gen_store_gpr(t0, rt);
3521 break;
3522 case OPC_LHE:
3523 mem_idx = MIPS_HFLAG_UM;
3524 /* fall through */
3525 case OPC_LH:
3526 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3527 ctx->default_tcg_memop_mask);
3528 gen_store_gpr(t0, rt);
3529 break;
3530 case OPC_LHUE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
3533 case OPC_LHU:
3534 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3535 ctx->default_tcg_memop_mask);
3536 gen_store_gpr(t0, rt);
3537 break;
3538 case OPC_LBE:
3539 mem_idx = MIPS_HFLAG_UM;
3540 /* fall through */
3541 case OPC_LB:
3542 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3543 gen_store_gpr(t0, rt);
3544 break;
3545 case OPC_LBUE:
3546 mem_idx = MIPS_HFLAG_UM;
3547 /* fall through */
3548 case OPC_LBU:
3549 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3550 gen_store_gpr(t0, rt);
3551 break;
3552 case OPC_LWLE:
3553 mem_idx = MIPS_HFLAG_UM;
3554 /* fall through */
3555 case OPC_LWL:
3556 t1 = tcg_temp_new();
3558 * Do a byte access to possibly trigger a page
3559 * fault with the unaligned address.
3561 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3562 tcg_gen_andi_tl(t1, t0, 3);
3563 #ifndef TARGET_WORDS_BIGENDIAN
3564 tcg_gen_xori_tl(t1, t1, 3);
3565 #endif
3566 tcg_gen_shli_tl(t1, t1, 3);
3567 tcg_gen_andi_tl(t0, t0, ~3);
3568 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3569 tcg_gen_shl_tl(t0, t0, t1);
3570 t2 = tcg_const_tl(-1);
3571 tcg_gen_shl_tl(t2, t2, t1);
3572 gen_load_gpr(t1, rt);
3573 tcg_gen_andc_tl(t1, t1, t2);
3574 tcg_temp_free(t2);
3575 tcg_gen_or_tl(t0, t0, t1);
3576 tcg_temp_free(t1);
3577 tcg_gen_ext32s_tl(t0, t0);
3578 gen_store_gpr(t0, rt);
3579 break;
3580 case OPC_LWRE:
3581 mem_idx = MIPS_HFLAG_UM;
3582 /* fall through */
3583 case OPC_LWR:
3584 t1 = tcg_temp_new();
3586 * Do a byte access to possibly trigger a page
3587 * fault with the unaligned address.
3589 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3590 tcg_gen_andi_tl(t1, t0, 3);
3591 #ifdef TARGET_WORDS_BIGENDIAN
3592 tcg_gen_xori_tl(t1, t1, 3);
3593 #endif
3594 tcg_gen_shli_tl(t1, t1, 3);
3595 tcg_gen_andi_tl(t0, t0, ~3);
3596 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3597 tcg_gen_shr_tl(t0, t0, t1);
3598 tcg_gen_xori_tl(t1, t1, 31);
3599 t2 = tcg_const_tl(0xfffffffeull);
3600 tcg_gen_shl_tl(t2, t2, t1);
3601 gen_load_gpr(t1, rt);
3602 tcg_gen_and_tl(t1, t1, t2);
3603 tcg_temp_free(t2);
3604 tcg_gen_or_tl(t0, t0, t1);
3605 tcg_temp_free(t1);
3606 tcg_gen_ext32s_tl(t0, t0);
3607 gen_store_gpr(t0, rt);
3608 break;
3609 case OPC_LLE:
3610 mem_idx = MIPS_HFLAG_UM;
3611 /* fall through */
3612 case OPC_LL:
3613 case R6_OPC_LL:
3614 op_ld_ll(t0, t0, mem_idx, ctx);
3615 gen_store_gpr(t0, rt);
3616 break;
3618 tcg_temp_free(t0);
3621 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3622 uint32_t reg1, uint32_t reg2)
3624 TCGv taddr = tcg_temp_new();
3625 TCGv_i64 tval = tcg_temp_new_i64();
3626 TCGv tmp1 = tcg_temp_new();
3627 TCGv tmp2 = tcg_temp_new();
3629 gen_base_offset_addr(ctx, taddr, base, offset);
3630 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3631 #ifdef TARGET_WORDS_BIGENDIAN
3632 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3633 #else
3634 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3635 #endif
3636 gen_store_gpr(tmp1, reg1);
3637 tcg_temp_free(tmp1);
3638 gen_store_gpr(tmp2, reg2);
3639 tcg_temp_free(tmp2);
3640 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3641 tcg_temp_free_i64(tval);
3642 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3643 tcg_temp_free(taddr);
3646 /* Store */
3647 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3648 int base, int offset)
3650 TCGv t0 = tcg_temp_new();
3651 TCGv t1 = tcg_temp_new();
3652 int mem_idx = ctx->mem_idx;
3654 gen_base_offset_addr(ctx, t0, base, offset);
3655 gen_load_gpr(t1, rt);
3656 switch (opc) {
3657 #if defined(TARGET_MIPS64)
3658 case OPC_SD:
3659 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3660 ctx->default_tcg_memop_mask);
3661 break;
3662 case OPC_SDL:
3663 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3664 break;
3665 case OPC_SDR:
3666 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3667 break;
3668 #endif
3669 case OPC_SWE:
3670 mem_idx = MIPS_HFLAG_UM;
3671 /* fall through */
3672 case OPC_SW:
3673 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3674 ctx->default_tcg_memop_mask);
3675 break;
3676 case OPC_SHE:
3677 mem_idx = MIPS_HFLAG_UM;
3678 /* fall through */
3679 case OPC_SH:
3680 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3681 ctx->default_tcg_memop_mask);
3682 break;
3683 case OPC_SBE:
3684 mem_idx = MIPS_HFLAG_UM;
3685 /* fall through */
3686 case OPC_SB:
3687 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3688 break;
3689 case OPC_SWLE:
3690 mem_idx = MIPS_HFLAG_UM;
3691 /* fall through */
3692 case OPC_SWL:
3693 gen_helper_0e2i(swl, t1, t0, mem_idx);
3694 break;
3695 case OPC_SWRE:
3696 mem_idx = MIPS_HFLAG_UM;
3697 /* fall through */
3698 case OPC_SWR:
3699 gen_helper_0e2i(swr, t1, t0, mem_idx);
3700 break;
3702 tcg_temp_free(t0);
3703 tcg_temp_free(t1);
3707 /* Store conditional */
3708 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3709 TCGMemOp tcg_mo, bool eva)
3711 TCGv addr, t0, val;
3712 TCGLabel *l1 = gen_new_label();
3713 TCGLabel *done = gen_new_label();
3715 t0 = tcg_temp_new();
3716 addr = tcg_temp_new();
3717 /* compare the address against that of the preceeding LL */
3718 gen_base_offset_addr(ctx, addr, base, offset);
3719 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3720 tcg_temp_free(addr);
3721 tcg_gen_movi_tl(t0, 0);
3722 gen_store_gpr(t0, rt);
3723 tcg_gen_br(done);
3725 gen_set_label(l1);
3726 /* generate cmpxchg */
3727 val = tcg_temp_new();
3728 gen_load_gpr(val, rt);
3729 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3730 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3731 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3732 gen_store_gpr(t0, rt);
3733 tcg_temp_free(val);
3735 gen_set_label(done);
3736 tcg_temp_free(t0);
3740 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3741 uint32_t reg1, uint32_t reg2, bool eva)
3743 TCGv taddr = tcg_temp_local_new();
3744 TCGv lladdr = tcg_temp_local_new();
3745 TCGv_i64 tval = tcg_temp_new_i64();
3746 TCGv_i64 llval = tcg_temp_new_i64();
3747 TCGv_i64 val = tcg_temp_new_i64();
3748 TCGv tmp1 = tcg_temp_new();
3749 TCGv tmp2 = tcg_temp_new();
3750 TCGLabel *lab_fail = gen_new_label();
3751 TCGLabel *lab_done = gen_new_label();
3753 gen_base_offset_addr(ctx, taddr, base, offset);
3755 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3756 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3758 gen_load_gpr(tmp1, reg1);
3759 gen_load_gpr(tmp2, reg2);
3761 #ifdef TARGET_WORDS_BIGENDIAN
3762 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3763 #else
3764 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3765 #endif
3767 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3768 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3769 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3770 if (reg1 != 0) {
3771 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3773 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3775 gen_set_label(lab_fail);
3777 if (reg1 != 0) {
3778 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3780 gen_set_label(lab_done);
3781 tcg_gen_movi_tl(lladdr, -1);
3782 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3785 /* Load and store */
3786 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3787 TCGv t0)
3790 * Don't do NOP if destination is zero: we must perform the actual
3791 * memory access.
3793 switch (opc) {
3794 case OPC_LWC1:
3796 TCGv_i32 fp0 = tcg_temp_new_i32();
3797 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3798 ctx->default_tcg_memop_mask);
3799 gen_store_fpr32(ctx, fp0, ft);
3800 tcg_temp_free_i32(fp0);
3802 break;
3803 case OPC_SWC1:
3805 TCGv_i32 fp0 = tcg_temp_new_i32();
3806 gen_load_fpr32(ctx, fp0, ft);
3807 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3808 ctx->default_tcg_memop_mask);
3809 tcg_temp_free_i32(fp0);
3811 break;
3812 case OPC_LDC1:
3814 TCGv_i64 fp0 = tcg_temp_new_i64();
3815 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3816 ctx->default_tcg_memop_mask);
3817 gen_store_fpr64(ctx, fp0, ft);
3818 tcg_temp_free_i64(fp0);
3820 break;
3821 case OPC_SDC1:
3823 TCGv_i64 fp0 = tcg_temp_new_i64();
3824 gen_load_fpr64(ctx, fp0, ft);
3825 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3826 ctx->default_tcg_memop_mask);
3827 tcg_temp_free_i64(fp0);
3829 break;
3830 default:
3831 MIPS_INVAL("flt_ldst");
3832 generate_exception_end(ctx, EXCP_RI);
3833 break;
3837 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3838 int rs, int16_t imm)
3840 TCGv t0 = tcg_temp_new();
3842 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3843 check_cp1_enabled(ctx);
3844 switch (op) {
3845 case OPC_LDC1:
3846 case OPC_SDC1:
3847 check_insn(ctx, ISA_MIPS2);
3848 /* Fallthrough */
3849 default:
3850 gen_base_offset_addr(ctx, t0, rs, imm);
3851 gen_flt_ldst(ctx, op, rt, t0);
3853 } else {
3854 generate_exception_err(ctx, EXCP_CpU, 1);
3856 tcg_temp_free(t0);
3859 /* Arithmetic with immediate operand */
3860 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3861 int rt, int rs, int imm)
3863 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3865 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3867 * If no destination, treat it as a NOP.
3868 * For addi, we must generate the overflow exception when needed.
3870 return;
3872 switch (opc) {
3873 case OPC_ADDI:
3875 TCGv t0 = tcg_temp_local_new();
3876 TCGv t1 = tcg_temp_new();
3877 TCGv t2 = tcg_temp_new();
3878 TCGLabel *l1 = gen_new_label();
3880 gen_load_gpr(t1, rs);
3881 tcg_gen_addi_tl(t0, t1, uimm);
3882 tcg_gen_ext32s_tl(t0, t0);
3884 tcg_gen_xori_tl(t1, t1, ~uimm);
3885 tcg_gen_xori_tl(t2, t0, uimm);
3886 tcg_gen_and_tl(t1, t1, t2);
3887 tcg_temp_free(t2);
3888 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3889 tcg_temp_free(t1);
3890 /* operands of same sign, result different sign */
3891 generate_exception(ctx, EXCP_OVERFLOW);
3892 gen_set_label(l1);
3893 tcg_gen_ext32s_tl(t0, t0);
3894 gen_store_gpr(t0, rt);
3895 tcg_temp_free(t0);
3897 break;
3898 case OPC_ADDIU:
3899 if (rs != 0) {
3900 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3901 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3902 } else {
3903 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3905 break;
3906 #if defined(TARGET_MIPS64)
3907 case OPC_DADDI:
3909 TCGv t0 = tcg_temp_local_new();
3910 TCGv t1 = tcg_temp_new();
3911 TCGv t2 = tcg_temp_new();
3912 TCGLabel *l1 = gen_new_label();
3914 gen_load_gpr(t1, rs);
3915 tcg_gen_addi_tl(t0, t1, uimm);
3917 tcg_gen_xori_tl(t1, t1, ~uimm);
3918 tcg_gen_xori_tl(t2, t0, uimm);
3919 tcg_gen_and_tl(t1, t1, t2);
3920 tcg_temp_free(t2);
3921 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3922 tcg_temp_free(t1);
3923 /* operands of same sign, result different sign */
3924 generate_exception(ctx, EXCP_OVERFLOW);
3925 gen_set_label(l1);
3926 gen_store_gpr(t0, rt);
3927 tcg_temp_free(t0);
3929 break;
3930 case OPC_DADDIU:
3931 if (rs != 0) {
3932 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3933 } else {
3934 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3936 break;
3937 #endif
3941 /* Logic with immediate operand */
3942 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3943 int rt, int rs, int16_t imm)
3945 target_ulong uimm;
3947 if (rt == 0) {
3948 /* If no destination, treat it as a NOP. */
3949 return;
3951 uimm = (uint16_t)imm;
3952 switch (opc) {
3953 case OPC_ANDI:
3954 if (likely(rs != 0)) {
3955 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3956 } else {
3957 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3959 break;
3960 case OPC_ORI:
3961 if (rs != 0) {
3962 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3963 } else {
3964 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3966 break;
3967 case OPC_XORI:
3968 if (likely(rs != 0)) {
3969 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3970 } else {
3971 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3973 break;
3974 case OPC_LUI:
3975 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3976 /* OPC_AUI */
3977 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3978 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3979 } else {
3980 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3982 break;
3984 default:
3985 break;
3989 /* Set on less than with immediate operand */
3990 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3991 int rt, int rs, int16_t imm)
3993 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3994 TCGv t0;
3996 if (rt == 0) {
3997 /* If no destination, treat it as a NOP. */
3998 return;
4000 t0 = tcg_temp_new();
4001 gen_load_gpr(t0, rs);
4002 switch (opc) {
4003 case OPC_SLTI:
4004 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4005 break;
4006 case OPC_SLTIU:
4007 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4008 break;
4010 tcg_temp_free(t0);
4013 /* Shifts with immediate operand */
4014 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4015 int rt, int rs, int16_t imm)
4017 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4018 TCGv t0;
4020 if (rt == 0) {
4021 /* If no destination, treat it as a NOP. */
4022 return;
4025 t0 = tcg_temp_new();
4026 gen_load_gpr(t0, rs);
4027 switch (opc) {
4028 case OPC_SLL:
4029 tcg_gen_shli_tl(t0, t0, uimm);
4030 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4031 break;
4032 case OPC_SRA:
4033 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4034 break;
4035 case OPC_SRL:
4036 if (uimm != 0) {
4037 tcg_gen_ext32u_tl(t0, t0);
4038 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4039 } else {
4040 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4042 break;
4043 case OPC_ROTR:
4044 if (uimm != 0) {
4045 TCGv_i32 t1 = tcg_temp_new_i32();
4047 tcg_gen_trunc_tl_i32(t1, t0);
4048 tcg_gen_rotri_i32(t1, t1, uimm);
4049 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4050 tcg_temp_free_i32(t1);
4051 } else {
4052 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4054 break;
4055 #if defined(TARGET_MIPS64)
4056 case OPC_DSLL:
4057 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4058 break;
4059 case OPC_DSRA:
4060 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4061 break;
4062 case OPC_DSRL:
4063 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4064 break;
4065 case OPC_DROTR:
4066 if (uimm != 0) {
4067 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4068 } else {
4069 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4071 break;
4072 case OPC_DSLL32:
4073 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4074 break;
4075 case OPC_DSRA32:
4076 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4077 break;
4078 case OPC_DSRL32:
4079 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4080 break;
4081 case OPC_DROTR32:
4082 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4083 break;
4084 #endif
4086 tcg_temp_free(t0);
4089 /* Arithmetic */
4090 static void gen_arith(DisasContext *ctx, uint32_t opc,
4091 int rd, int rs, int rt)
4093 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4094 && opc != OPC_DADD && opc != OPC_DSUB) {
4096 * If no destination, treat it as a NOP.
4097 * For add & sub, we must generate the overflow exception when needed.
4099 return;
4102 switch (opc) {
4103 case OPC_ADD:
4105 TCGv t0 = tcg_temp_local_new();
4106 TCGv t1 = tcg_temp_new();
4107 TCGv t2 = tcg_temp_new();
4108 TCGLabel *l1 = gen_new_label();
4110 gen_load_gpr(t1, rs);
4111 gen_load_gpr(t2, rt);
4112 tcg_gen_add_tl(t0, t1, t2);
4113 tcg_gen_ext32s_tl(t0, t0);
4114 tcg_gen_xor_tl(t1, t1, t2);
4115 tcg_gen_xor_tl(t2, t0, t2);
4116 tcg_gen_andc_tl(t1, t2, t1);
4117 tcg_temp_free(t2);
4118 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4119 tcg_temp_free(t1);
4120 /* operands of same sign, result different sign */
4121 generate_exception(ctx, EXCP_OVERFLOW);
4122 gen_set_label(l1);
4123 gen_store_gpr(t0, rd);
4124 tcg_temp_free(t0);
4126 break;
4127 case OPC_ADDU:
4128 if (rs != 0 && rt != 0) {
4129 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4130 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4131 } else if (rs == 0 && rt != 0) {
4132 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4133 } else if (rs != 0 && rt == 0) {
4134 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4135 } else {
4136 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4138 break;
4139 case OPC_SUB:
4141 TCGv t0 = tcg_temp_local_new();
4142 TCGv t1 = tcg_temp_new();
4143 TCGv t2 = tcg_temp_new();
4144 TCGLabel *l1 = gen_new_label();
4146 gen_load_gpr(t1, rs);
4147 gen_load_gpr(t2, rt);
4148 tcg_gen_sub_tl(t0, t1, t2);
4149 tcg_gen_ext32s_tl(t0, t0);
4150 tcg_gen_xor_tl(t2, t1, t2);
4151 tcg_gen_xor_tl(t1, t0, t1);
4152 tcg_gen_and_tl(t1, t1, t2);
4153 tcg_temp_free(t2);
4154 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4155 tcg_temp_free(t1);
4157 * operands of different sign, first operand and the result
4158 * of different sign
4160 generate_exception(ctx, EXCP_OVERFLOW);
4161 gen_set_label(l1);
4162 gen_store_gpr(t0, rd);
4163 tcg_temp_free(t0);
4165 break;
4166 case OPC_SUBU:
4167 if (rs != 0 && rt != 0) {
4168 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4169 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4170 } else if (rs == 0 && rt != 0) {
4171 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4173 } else if (rs != 0 && rt == 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4175 } else {
4176 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4178 break;
4179 #if defined(TARGET_MIPS64)
4180 case OPC_DADD:
4182 TCGv t0 = tcg_temp_local_new();
4183 TCGv t1 = tcg_temp_new();
4184 TCGv t2 = tcg_temp_new();
4185 TCGLabel *l1 = gen_new_label();
4187 gen_load_gpr(t1, rs);
4188 gen_load_gpr(t2, rt);
4189 tcg_gen_add_tl(t0, t1, t2);
4190 tcg_gen_xor_tl(t1, t1, t2);
4191 tcg_gen_xor_tl(t2, t0, t2);
4192 tcg_gen_andc_tl(t1, t2, t1);
4193 tcg_temp_free(t2);
4194 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4195 tcg_temp_free(t1);
4196 /* operands of same sign, result different sign */
4197 generate_exception(ctx, EXCP_OVERFLOW);
4198 gen_set_label(l1);
4199 gen_store_gpr(t0, rd);
4200 tcg_temp_free(t0);
4202 break;
4203 case OPC_DADDU:
4204 if (rs != 0 && rt != 0) {
4205 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4206 } else if (rs == 0 && rt != 0) {
4207 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4208 } else if (rs != 0 && rt == 0) {
4209 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4210 } else {
4211 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4213 break;
4214 case OPC_DSUB:
4216 TCGv t0 = tcg_temp_local_new();
4217 TCGv t1 = tcg_temp_new();
4218 TCGv t2 = tcg_temp_new();
4219 TCGLabel *l1 = gen_new_label();
4221 gen_load_gpr(t1, rs);
4222 gen_load_gpr(t2, rt);
4223 tcg_gen_sub_tl(t0, t1, t2);
4224 tcg_gen_xor_tl(t2, t1, t2);
4225 tcg_gen_xor_tl(t1, t0, t1);
4226 tcg_gen_and_tl(t1, t1, t2);
4227 tcg_temp_free(t2);
4228 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4229 tcg_temp_free(t1);
4231 * Operands of different sign, first operand and result different
4232 * sign.
4234 generate_exception(ctx, EXCP_OVERFLOW);
4235 gen_set_label(l1);
4236 gen_store_gpr(t0, rd);
4237 tcg_temp_free(t0);
4239 break;
4240 case OPC_DSUBU:
4241 if (rs != 0 && rt != 0) {
4242 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4243 } else if (rs == 0 && rt != 0) {
4244 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4245 } else if (rs != 0 && rt == 0) {
4246 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4247 } else {
4248 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4250 break;
4251 #endif
4252 case OPC_MUL:
4253 if (likely(rs != 0 && rt != 0)) {
4254 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4255 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4256 } else {
4257 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4259 break;
4263 /* Conditional move */
4264 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4265 int rd, int rs, int rt)
4267 TCGv t0, t1, t2;
4269 if (rd == 0) {
4270 /* If no destination, treat it as a NOP. */
4271 return;
4274 t0 = tcg_temp_new();
4275 gen_load_gpr(t0, rt);
4276 t1 = tcg_const_tl(0);
4277 t2 = tcg_temp_new();
4278 gen_load_gpr(t2, rs);
4279 switch (opc) {
4280 case OPC_MOVN:
4281 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4282 break;
4283 case OPC_MOVZ:
4284 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4285 break;
4286 case OPC_SELNEZ:
4287 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4288 break;
4289 case OPC_SELEQZ:
4290 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4291 break;
4293 tcg_temp_free(t2);
4294 tcg_temp_free(t1);
4295 tcg_temp_free(t0);
4298 /* Logic */
4299 static void gen_logic(DisasContext *ctx, uint32_t opc,
4300 int rd, int rs, int rt)
4302 if (rd == 0) {
4303 /* If no destination, treat it as a NOP. */
4304 return;
4307 switch (opc) {
4308 case OPC_AND:
4309 if (likely(rs != 0 && rt != 0)) {
4310 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4311 } else {
4312 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4314 break;
4315 case OPC_NOR:
4316 if (rs != 0 && rt != 0) {
4317 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4318 } else if (rs == 0 && rt != 0) {
4319 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4320 } else if (rs != 0 && rt == 0) {
4321 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4322 } else {
4323 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4325 break;
4326 case OPC_OR:
4327 if (likely(rs != 0 && rt != 0)) {
4328 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4329 } else if (rs == 0 && rt != 0) {
4330 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4331 } else if (rs != 0 && rt == 0) {
4332 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4333 } else {
4334 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4336 break;
4337 case OPC_XOR:
4338 if (likely(rs != 0 && rt != 0)) {
4339 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4340 } else if (rs == 0 && rt != 0) {
4341 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4342 } else if (rs != 0 && rt == 0) {
4343 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4344 } else {
4345 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4347 break;
4351 /* Set on lower than */
4352 static void gen_slt(DisasContext *ctx, uint32_t opc,
4353 int rd, int rs, int rt)
4355 TCGv t0, t1;
4357 if (rd == 0) {
4358 /* If no destination, treat it as a NOP. */
4359 return;
4362 t0 = tcg_temp_new();
4363 t1 = tcg_temp_new();
4364 gen_load_gpr(t0, rs);
4365 gen_load_gpr(t1, rt);
4366 switch (opc) {
4367 case OPC_SLT:
4368 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4369 break;
4370 case OPC_SLTU:
4371 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4372 break;
4374 tcg_temp_free(t0);
4375 tcg_temp_free(t1);
4378 /* Shifts */
4379 static void gen_shift(DisasContext *ctx, uint32_t opc,
4380 int rd, int rs, int rt)
4382 TCGv t0, t1;
4384 if (rd == 0) {
4386 * If no destination, treat it as a NOP.
4387 * For add & sub, we must generate the overflow exception when needed.
4389 return;
4392 t0 = tcg_temp_new();
4393 t1 = tcg_temp_new();
4394 gen_load_gpr(t0, rs);
4395 gen_load_gpr(t1, rt);
4396 switch (opc) {
4397 case OPC_SLLV:
4398 tcg_gen_andi_tl(t0, t0, 0x1f);
4399 tcg_gen_shl_tl(t0, t1, t0);
4400 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4401 break;
4402 case OPC_SRAV:
4403 tcg_gen_andi_tl(t0, t0, 0x1f);
4404 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4405 break;
4406 case OPC_SRLV:
4407 tcg_gen_ext32u_tl(t1, t1);
4408 tcg_gen_andi_tl(t0, t0, 0x1f);
4409 tcg_gen_shr_tl(t0, t1, t0);
4410 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4411 break;
4412 case OPC_ROTRV:
4414 TCGv_i32 t2 = tcg_temp_new_i32();
4415 TCGv_i32 t3 = tcg_temp_new_i32();
4417 tcg_gen_trunc_tl_i32(t2, t0);
4418 tcg_gen_trunc_tl_i32(t3, t1);
4419 tcg_gen_andi_i32(t2, t2, 0x1f);
4420 tcg_gen_rotr_i32(t2, t3, t2);
4421 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4422 tcg_temp_free_i32(t2);
4423 tcg_temp_free_i32(t3);
4425 break;
4426 #if defined(TARGET_MIPS64)
4427 case OPC_DSLLV:
4428 tcg_gen_andi_tl(t0, t0, 0x3f);
4429 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4430 break;
4431 case OPC_DSRAV:
4432 tcg_gen_andi_tl(t0, t0, 0x3f);
4433 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4434 break;
4435 case OPC_DSRLV:
4436 tcg_gen_andi_tl(t0, t0, 0x3f);
4437 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4438 break;
4439 case OPC_DROTRV:
4440 tcg_gen_andi_tl(t0, t0, 0x3f);
4441 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4442 break;
4443 #endif
4445 tcg_temp_free(t0);
4446 tcg_temp_free(t1);
4449 #if defined(TARGET_MIPS64)
4450 /* Copy GPR to and from TX79 HI1/LO1 register. */
4451 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4453 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4454 /* Treat as NOP. */
4455 return;
4458 switch (opc) {
4459 case MMI_OPC_MFHI1:
4460 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4461 break;
4462 case MMI_OPC_MFLO1:
4463 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4464 break;
4465 case MMI_OPC_MTHI1:
4466 if (reg != 0) {
4467 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4468 } else {
4469 tcg_gen_movi_tl(cpu_HI[1], 0);
4471 break;
4472 case MMI_OPC_MTLO1:
4473 if (reg != 0) {
4474 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4475 } else {
4476 tcg_gen_movi_tl(cpu_LO[1], 0);
4478 break;
4479 default:
4480 MIPS_INVAL("mfthilo1 TX79");
4481 generate_exception_end(ctx, EXCP_RI);
4482 break;
4485 #endif
4487 /* Arithmetic on HI/LO registers */
4488 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4490 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4491 /* Treat as NOP. */
4492 return;
4495 if (acc != 0) {
4496 check_dsp(ctx);
4499 switch (opc) {
4500 case OPC_MFHI:
4501 #if defined(TARGET_MIPS64)
4502 if (acc != 0) {
4503 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4504 } else
4505 #endif
4507 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4509 break;
4510 case OPC_MFLO:
4511 #if defined(TARGET_MIPS64)
4512 if (acc != 0) {
4513 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4514 } else
4515 #endif
4517 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4519 break;
4520 case OPC_MTHI:
4521 if (reg != 0) {
4522 #if defined(TARGET_MIPS64)
4523 if (acc != 0) {
4524 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4525 } else
4526 #endif
4528 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4530 } else {
4531 tcg_gen_movi_tl(cpu_HI[acc], 0);
4533 break;
4534 case OPC_MTLO:
4535 if (reg != 0) {
4536 #if defined(TARGET_MIPS64)
4537 if (acc != 0) {
4538 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4539 } else
4540 #endif
4542 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4544 } else {
4545 tcg_gen_movi_tl(cpu_LO[acc], 0);
4547 break;
4551 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4552 TCGMemOp memop)
4554 TCGv t0 = tcg_const_tl(addr);
4555 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4556 gen_store_gpr(t0, reg);
4557 tcg_temp_free(t0);
4560 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4561 int rs)
4563 target_long offset;
4564 target_long addr;
4566 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4567 case OPC_ADDIUPC:
4568 if (rs != 0) {
4569 offset = sextract32(ctx->opcode << 2, 0, 21);
4570 addr = addr_add(ctx, pc, offset);
4571 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4573 break;
4574 case R6_OPC_LWPC:
4575 offset = sextract32(ctx->opcode << 2, 0, 21);
4576 addr = addr_add(ctx, pc, offset);
4577 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4578 break;
4579 #if defined(TARGET_MIPS64)
4580 case OPC_LWUPC:
4581 check_mips_64(ctx);
4582 offset = sextract32(ctx->opcode << 2, 0, 21);
4583 addr = addr_add(ctx, pc, offset);
4584 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4585 break;
4586 #endif
4587 default:
4588 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4589 case OPC_AUIPC:
4590 if (rs != 0) {
4591 offset = sextract32(ctx->opcode, 0, 16) << 16;
4592 addr = addr_add(ctx, pc, offset);
4593 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4595 break;
4596 case OPC_ALUIPC:
4597 if (rs != 0) {
4598 offset = sextract32(ctx->opcode, 0, 16) << 16;
4599 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4600 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4602 break;
4603 #if defined(TARGET_MIPS64)
4604 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4605 case R6_OPC_LDPC + (1 << 16):
4606 case R6_OPC_LDPC + (2 << 16):
4607 case R6_OPC_LDPC + (3 << 16):
4608 check_mips_64(ctx);
4609 offset = sextract32(ctx->opcode << 3, 0, 21);
4610 addr = addr_add(ctx, (pc & ~0x7), offset);
4611 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4612 break;
4613 #endif
4614 default:
4615 MIPS_INVAL("OPC_PCREL");
4616 generate_exception_end(ctx, EXCP_RI);
4617 break;
4619 break;
4623 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4625 TCGv t0, t1;
4627 if (rd == 0) {
4628 /* Treat as NOP. */
4629 return;
4632 t0 = tcg_temp_new();
4633 t1 = tcg_temp_new();
4635 gen_load_gpr(t0, rs);
4636 gen_load_gpr(t1, rt);
4638 switch (opc) {
4639 case R6_OPC_DIV:
4641 TCGv t2 = tcg_temp_new();
4642 TCGv t3 = tcg_temp_new();
4643 tcg_gen_ext32s_tl(t0, t0);
4644 tcg_gen_ext32s_tl(t1, t1);
4645 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4646 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4647 tcg_gen_and_tl(t2, t2, t3);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4649 tcg_gen_or_tl(t2, t2, t3);
4650 tcg_gen_movi_tl(t3, 0);
4651 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4652 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4653 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4654 tcg_temp_free(t3);
4655 tcg_temp_free(t2);
4657 break;
4658 case R6_OPC_MOD:
4660 TCGv t2 = tcg_temp_new();
4661 TCGv t3 = tcg_temp_new();
4662 tcg_gen_ext32s_tl(t0, t0);
4663 tcg_gen_ext32s_tl(t1, t1);
4664 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4665 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4666 tcg_gen_and_tl(t2, t2, t3);
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4668 tcg_gen_or_tl(t2, t2, t3);
4669 tcg_gen_movi_tl(t3, 0);
4670 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4671 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4672 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4673 tcg_temp_free(t3);
4674 tcg_temp_free(t2);
4676 break;
4677 case R6_OPC_DIVU:
4679 TCGv t2 = tcg_const_tl(0);
4680 TCGv t3 = tcg_const_tl(1);
4681 tcg_gen_ext32u_tl(t0, t0);
4682 tcg_gen_ext32u_tl(t1, t1);
4683 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4684 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4685 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4686 tcg_temp_free(t3);
4687 tcg_temp_free(t2);
4689 break;
4690 case R6_OPC_MODU:
4692 TCGv t2 = tcg_const_tl(0);
4693 TCGv t3 = tcg_const_tl(1);
4694 tcg_gen_ext32u_tl(t0, t0);
4695 tcg_gen_ext32u_tl(t1, t1);
4696 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4697 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4698 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4699 tcg_temp_free(t3);
4700 tcg_temp_free(t2);
4702 break;
4703 case R6_OPC_MUL:
4705 TCGv_i32 t2 = tcg_temp_new_i32();
4706 TCGv_i32 t3 = tcg_temp_new_i32();
4707 tcg_gen_trunc_tl_i32(t2, t0);
4708 tcg_gen_trunc_tl_i32(t3, t1);
4709 tcg_gen_mul_i32(t2, t2, t3);
4710 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4711 tcg_temp_free_i32(t2);
4712 tcg_temp_free_i32(t3);
4714 break;
4715 case R6_OPC_MUH:
4717 TCGv_i32 t2 = tcg_temp_new_i32();
4718 TCGv_i32 t3 = tcg_temp_new_i32();
4719 tcg_gen_trunc_tl_i32(t2, t0);
4720 tcg_gen_trunc_tl_i32(t3, t1);
4721 tcg_gen_muls2_i32(t2, t3, t2, t3);
4722 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4723 tcg_temp_free_i32(t2);
4724 tcg_temp_free_i32(t3);
4726 break;
4727 case R6_OPC_MULU:
4729 TCGv_i32 t2 = tcg_temp_new_i32();
4730 TCGv_i32 t3 = tcg_temp_new_i32();
4731 tcg_gen_trunc_tl_i32(t2, t0);
4732 tcg_gen_trunc_tl_i32(t3, t1);
4733 tcg_gen_mul_i32(t2, t2, t3);
4734 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4735 tcg_temp_free_i32(t2);
4736 tcg_temp_free_i32(t3);
4738 break;
4739 case R6_OPC_MUHU:
4741 TCGv_i32 t2 = tcg_temp_new_i32();
4742 TCGv_i32 t3 = tcg_temp_new_i32();
4743 tcg_gen_trunc_tl_i32(t2, t0);
4744 tcg_gen_trunc_tl_i32(t3, t1);
4745 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4746 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4747 tcg_temp_free_i32(t2);
4748 tcg_temp_free_i32(t3);
4750 break;
4751 #if defined(TARGET_MIPS64)
4752 case R6_OPC_DDIV:
4754 TCGv t2 = tcg_temp_new();
4755 TCGv t3 = tcg_temp_new();
4756 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4757 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4758 tcg_gen_and_tl(t2, t2, t3);
4759 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4760 tcg_gen_or_tl(t2, t2, t3);
4761 tcg_gen_movi_tl(t3, 0);
4762 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4763 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4764 tcg_temp_free(t3);
4765 tcg_temp_free(t2);
4767 break;
4768 case R6_OPC_DMOD:
4770 TCGv t2 = tcg_temp_new();
4771 TCGv t3 = tcg_temp_new();
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4773 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4774 tcg_gen_and_tl(t2, t2, t3);
4775 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4776 tcg_gen_or_tl(t2, t2, t3);
4777 tcg_gen_movi_tl(t3, 0);
4778 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4779 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4780 tcg_temp_free(t3);
4781 tcg_temp_free(t2);
4783 break;
4784 case R6_OPC_DDIVU:
4786 TCGv t2 = tcg_const_tl(0);
4787 TCGv t3 = tcg_const_tl(1);
4788 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4789 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4790 tcg_temp_free(t3);
4791 tcg_temp_free(t2);
4793 break;
4794 case R6_OPC_DMODU:
4796 TCGv t2 = tcg_const_tl(0);
4797 TCGv t3 = tcg_const_tl(1);
4798 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4799 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4800 tcg_temp_free(t3);
4801 tcg_temp_free(t2);
4803 break;
4804 case R6_OPC_DMUL:
4805 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4806 break;
4807 case R6_OPC_DMUH:
4809 TCGv t2 = tcg_temp_new();
4810 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4811 tcg_temp_free(t2);
4813 break;
4814 case R6_OPC_DMULU:
4815 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4816 break;
4817 case R6_OPC_DMUHU:
4819 TCGv t2 = tcg_temp_new();
4820 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4821 tcg_temp_free(t2);
4823 break;
4824 #endif
4825 default:
4826 MIPS_INVAL("r6 mul/div");
4827 generate_exception_end(ctx, EXCP_RI);
4828 goto out;
4830 out:
4831 tcg_temp_free(t0);
4832 tcg_temp_free(t1);
4835 #if defined(TARGET_MIPS64)
4836 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4838 TCGv t0, t1;
4840 t0 = tcg_temp_new();
4841 t1 = tcg_temp_new();
4843 gen_load_gpr(t0, rs);
4844 gen_load_gpr(t1, rt);
4846 switch (opc) {
4847 case MMI_OPC_DIV1:
4849 TCGv t2 = tcg_temp_new();
4850 TCGv t3 = tcg_temp_new();
4851 tcg_gen_ext32s_tl(t0, t0);
4852 tcg_gen_ext32s_tl(t1, t1);
4853 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4854 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4855 tcg_gen_and_tl(t2, t2, t3);
4856 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4857 tcg_gen_or_tl(t2, t2, t3);
4858 tcg_gen_movi_tl(t3, 0);
4859 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4860 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4861 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4862 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4863 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4864 tcg_temp_free(t3);
4865 tcg_temp_free(t2);
4867 break;
4868 case MMI_OPC_DIVU1:
4870 TCGv t2 = tcg_const_tl(0);
4871 TCGv t3 = tcg_const_tl(1);
4872 tcg_gen_ext32u_tl(t0, t0);
4873 tcg_gen_ext32u_tl(t1, t1);
4874 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4875 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4876 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4877 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4878 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4879 tcg_temp_free(t3);
4880 tcg_temp_free(t2);
4882 break;
4883 default:
4884 MIPS_INVAL("div1 TX79");
4885 generate_exception_end(ctx, EXCP_RI);
4886 goto out;
4888 out:
4889 tcg_temp_free(t0);
4890 tcg_temp_free(t1);
4892 #endif
4894 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4895 int acc, int rs, int rt)
4897 TCGv t0, t1;
4899 t0 = tcg_temp_new();
4900 t1 = tcg_temp_new();
4902 gen_load_gpr(t0, rs);
4903 gen_load_gpr(t1, rt);
4905 if (acc != 0) {
4906 check_dsp(ctx);
4909 switch (opc) {
4910 case OPC_DIV:
4912 TCGv t2 = tcg_temp_new();
4913 TCGv t3 = tcg_temp_new();
4914 tcg_gen_ext32s_tl(t0, t0);
4915 tcg_gen_ext32s_tl(t1, t1);
4916 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4917 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4918 tcg_gen_and_tl(t2, t2, t3);
4919 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4920 tcg_gen_or_tl(t2, t2, t3);
4921 tcg_gen_movi_tl(t3, 0);
4922 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4923 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4924 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4925 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4926 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4927 tcg_temp_free(t3);
4928 tcg_temp_free(t2);
4930 break;
4931 case OPC_DIVU:
4933 TCGv t2 = tcg_const_tl(0);
4934 TCGv t3 = tcg_const_tl(1);
4935 tcg_gen_ext32u_tl(t0, t0);
4936 tcg_gen_ext32u_tl(t1, t1);
4937 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4938 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4939 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4940 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4941 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4942 tcg_temp_free(t3);
4943 tcg_temp_free(t2);
4945 break;
4946 case OPC_MULT:
4948 TCGv_i32 t2 = tcg_temp_new_i32();
4949 TCGv_i32 t3 = tcg_temp_new_i32();
4950 tcg_gen_trunc_tl_i32(t2, t0);
4951 tcg_gen_trunc_tl_i32(t3, t1);
4952 tcg_gen_muls2_i32(t2, t3, t2, t3);
4953 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4954 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4955 tcg_temp_free_i32(t2);
4956 tcg_temp_free_i32(t3);
4958 break;
4959 case OPC_MULTU:
4961 TCGv_i32 t2 = tcg_temp_new_i32();
4962 TCGv_i32 t3 = tcg_temp_new_i32();
4963 tcg_gen_trunc_tl_i32(t2, t0);
4964 tcg_gen_trunc_tl_i32(t3, t1);
4965 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4966 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4967 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4968 tcg_temp_free_i32(t2);
4969 tcg_temp_free_i32(t3);
4971 break;
4972 #if defined(TARGET_MIPS64)
4973 case OPC_DDIV:
4975 TCGv t2 = tcg_temp_new();
4976 TCGv t3 = tcg_temp_new();
4977 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4978 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4979 tcg_gen_and_tl(t2, t2, t3);
4980 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4981 tcg_gen_or_tl(t2, t2, t3);
4982 tcg_gen_movi_tl(t3, 0);
4983 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4984 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4985 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4986 tcg_temp_free(t3);
4987 tcg_temp_free(t2);
4989 break;
4990 case OPC_DDIVU:
4992 TCGv t2 = tcg_const_tl(0);
4993 TCGv t3 = tcg_const_tl(1);
4994 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4995 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4996 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4997 tcg_temp_free(t3);
4998 tcg_temp_free(t2);
5000 break;
5001 case OPC_DMULT:
5002 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5003 break;
5004 case OPC_DMULTU:
5005 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5006 break;
5007 #endif
5008 case OPC_MADD:
5010 TCGv_i64 t2 = tcg_temp_new_i64();
5011 TCGv_i64 t3 = tcg_temp_new_i64();
5013 tcg_gen_ext_tl_i64(t2, t0);
5014 tcg_gen_ext_tl_i64(t3, t1);
5015 tcg_gen_mul_i64(t2, t2, t3);
5016 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5017 tcg_gen_add_i64(t2, t2, t3);
5018 tcg_temp_free_i64(t3);
5019 gen_move_low32(cpu_LO[acc], t2);
5020 gen_move_high32(cpu_HI[acc], t2);
5021 tcg_temp_free_i64(t2);
5023 break;
5024 case OPC_MADDU:
5026 TCGv_i64 t2 = tcg_temp_new_i64();
5027 TCGv_i64 t3 = tcg_temp_new_i64();
5029 tcg_gen_ext32u_tl(t0, t0);
5030 tcg_gen_ext32u_tl(t1, t1);
5031 tcg_gen_extu_tl_i64(t2, t0);
5032 tcg_gen_extu_tl_i64(t3, t1);
5033 tcg_gen_mul_i64(t2, t2, t3);
5034 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5035 tcg_gen_add_i64(t2, t2, t3);
5036 tcg_temp_free_i64(t3);
5037 gen_move_low32(cpu_LO[acc], t2);
5038 gen_move_high32(cpu_HI[acc], t2);
5039 tcg_temp_free_i64(t2);
5041 break;
5042 case OPC_MSUB:
5044 TCGv_i64 t2 = tcg_temp_new_i64();
5045 TCGv_i64 t3 = tcg_temp_new_i64();
5047 tcg_gen_ext_tl_i64(t2, t0);
5048 tcg_gen_ext_tl_i64(t3, t1);
5049 tcg_gen_mul_i64(t2, t2, t3);
5050 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5051 tcg_gen_sub_i64(t2, t3, t2);
5052 tcg_temp_free_i64(t3);
5053 gen_move_low32(cpu_LO[acc], t2);
5054 gen_move_high32(cpu_HI[acc], t2);
5055 tcg_temp_free_i64(t2);
5057 break;
5058 case OPC_MSUBU:
5060 TCGv_i64 t2 = tcg_temp_new_i64();
5061 TCGv_i64 t3 = tcg_temp_new_i64();
5063 tcg_gen_ext32u_tl(t0, t0);
5064 tcg_gen_ext32u_tl(t1, t1);
5065 tcg_gen_extu_tl_i64(t2, t0);
5066 tcg_gen_extu_tl_i64(t3, t1);
5067 tcg_gen_mul_i64(t2, t2, t3);
5068 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5069 tcg_gen_sub_i64(t2, t3, t2);
5070 tcg_temp_free_i64(t3);
5071 gen_move_low32(cpu_LO[acc], t2);
5072 gen_move_high32(cpu_HI[acc], t2);
5073 tcg_temp_free_i64(t2);
5075 break;
5076 default:
5077 MIPS_INVAL("mul/div");
5078 generate_exception_end(ctx, EXCP_RI);
5079 goto out;
5081 out:
5082 tcg_temp_free(t0);
5083 tcg_temp_free(t1);
5087 * These MULT[U] and MADD[U] instructions implemented in for example
5088 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5089 * architectures are special three-operand variants with the syntax
5091 * MULT[U][1] rd, rs, rt
5093 * such that
5095 * (rd, LO, HI) <- rs * rt
5097 * and
5099 * MADD[U][1] rd, rs, rt
5101 * such that
5103 * (rd, LO, HI) <- (LO, HI) + rs * rt
5105 * where the low-order 32-bits of the result is placed into both the
5106 * GPR rd and the special register LO. The high-order 32-bits of the
5107 * result is placed into the special register HI.
5109 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5110 * which is the zero register that always reads as 0.
5112 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5113 int rd, int rs, int rt)
5115 TCGv t0 = tcg_temp_new();
5116 TCGv t1 = tcg_temp_new();
5117 int acc = 0;
5119 gen_load_gpr(t0, rs);
5120 gen_load_gpr(t1, rt);
5122 switch (opc) {
5123 case MMI_OPC_MULT1:
5124 acc = 1;
5125 /* Fall through */
5126 case OPC_MULT:
5128 TCGv_i32 t2 = tcg_temp_new_i32();
5129 TCGv_i32 t3 = tcg_temp_new_i32();
5130 tcg_gen_trunc_tl_i32(t2, t0);
5131 tcg_gen_trunc_tl_i32(t3, t1);
5132 tcg_gen_muls2_i32(t2, t3, t2, t3);
5133 if (rd) {
5134 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5136 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5137 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5138 tcg_temp_free_i32(t2);
5139 tcg_temp_free_i32(t3);
5141 break;
5142 case MMI_OPC_MULTU1:
5143 acc = 1;
5144 /* Fall through */
5145 case OPC_MULTU:
5147 TCGv_i32 t2 = tcg_temp_new_i32();
5148 TCGv_i32 t3 = tcg_temp_new_i32();
5149 tcg_gen_trunc_tl_i32(t2, t0);
5150 tcg_gen_trunc_tl_i32(t3, t1);
5151 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5152 if (rd) {
5153 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5155 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5156 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5157 tcg_temp_free_i32(t2);
5158 tcg_temp_free_i32(t3);
5160 break;
5161 case MMI_OPC_MADD1:
5162 acc = 1;
5163 /* Fall through */
5164 case MMI_OPC_MADD:
5166 TCGv_i64 t2 = tcg_temp_new_i64();
5167 TCGv_i64 t3 = tcg_temp_new_i64();
5169 tcg_gen_ext_tl_i64(t2, t0);
5170 tcg_gen_ext_tl_i64(t3, t1);
5171 tcg_gen_mul_i64(t2, t2, t3);
5172 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5173 tcg_gen_add_i64(t2, t2, t3);
5174 tcg_temp_free_i64(t3);
5175 gen_move_low32(cpu_LO[acc], t2);
5176 gen_move_high32(cpu_HI[acc], t2);
5177 if (rd) {
5178 gen_move_low32(cpu_gpr[rd], t2);
5180 tcg_temp_free_i64(t2);
5182 break;
5183 case MMI_OPC_MADDU1:
5184 acc = 1;
5185 /* Fall through */
5186 case MMI_OPC_MADDU:
5188 TCGv_i64 t2 = tcg_temp_new_i64();
5189 TCGv_i64 t3 = tcg_temp_new_i64();
5191 tcg_gen_ext32u_tl(t0, t0);
5192 tcg_gen_ext32u_tl(t1, t1);
5193 tcg_gen_extu_tl_i64(t2, t0);
5194 tcg_gen_extu_tl_i64(t3, t1);
5195 tcg_gen_mul_i64(t2, t2, t3);
5196 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5197 tcg_gen_add_i64(t2, t2, t3);
5198 tcg_temp_free_i64(t3);
5199 gen_move_low32(cpu_LO[acc], t2);
5200 gen_move_high32(cpu_HI[acc], t2);
5201 if (rd) {
5202 gen_move_low32(cpu_gpr[rd], t2);
5204 tcg_temp_free_i64(t2);
5206 break;
5207 default:
5208 MIPS_INVAL("mul/madd TXx9");
5209 generate_exception_end(ctx, EXCP_RI);
5210 goto out;
5213 out:
5214 tcg_temp_free(t0);
5215 tcg_temp_free(t1);
5218 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5219 int rd, int rs, int rt)
5221 TCGv t0 = tcg_temp_new();
5222 TCGv t1 = tcg_temp_new();
5224 gen_load_gpr(t0, rs);
5225 gen_load_gpr(t1, rt);
5227 switch (opc) {
5228 case OPC_VR54XX_MULS:
5229 gen_helper_muls(t0, cpu_env, t0, t1);
5230 break;
5231 case OPC_VR54XX_MULSU:
5232 gen_helper_mulsu(t0, cpu_env, t0, t1);
5233 break;
5234 case OPC_VR54XX_MACC:
5235 gen_helper_macc(t0, cpu_env, t0, t1);
5236 break;
5237 case OPC_VR54XX_MACCU:
5238 gen_helper_maccu(t0, cpu_env, t0, t1);
5239 break;
5240 case OPC_VR54XX_MSAC:
5241 gen_helper_msac(t0, cpu_env, t0, t1);
5242 break;
5243 case OPC_VR54XX_MSACU:
5244 gen_helper_msacu(t0, cpu_env, t0, t1);
5245 break;
5246 case OPC_VR54XX_MULHI:
5247 gen_helper_mulhi(t0, cpu_env, t0, t1);
5248 break;
5249 case OPC_VR54XX_MULHIU:
5250 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5251 break;
5252 case OPC_VR54XX_MULSHI:
5253 gen_helper_mulshi(t0, cpu_env, t0, t1);
5254 break;
5255 case OPC_VR54XX_MULSHIU:
5256 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5257 break;
5258 case OPC_VR54XX_MACCHI:
5259 gen_helper_macchi(t0, cpu_env, t0, t1);
5260 break;
5261 case OPC_VR54XX_MACCHIU:
5262 gen_helper_macchiu(t0, cpu_env, t0, t1);
5263 break;
5264 case OPC_VR54XX_MSACHI:
5265 gen_helper_msachi(t0, cpu_env, t0, t1);
5266 break;
5267 case OPC_VR54XX_MSACHIU:
5268 gen_helper_msachiu(t0, cpu_env, t0, t1);
5269 break;
5270 default:
5271 MIPS_INVAL("mul vr54xx");
5272 generate_exception_end(ctx, EXCP_RI);
5273 goto out;
5275 gen_store_gpr(t0, rd);
5277 out:
5278 tcg_temp_free(t0);
5279 tcg_temp_free(t1);
5282 static void gen_cl(DisasContext *ctx, uint32_t opc,
5283 int rd, int rs)
5285 TCGv t0;
5287 if (rd == 0) {
5288 /* Treat as NOP. */
5289 return;
5291 t0 = cpu_gpr[rd];
5292 gen_load_gpr(t0, rs);
5294 switch (opc) {
5295 case OPC_CLO:
5296 case R6_OPC_CLO:
5297 #if defined(TARGET_MIPS64)
5298 case OPC_DCLO:
5299 case R6_OPC_DCLO:
5300 #endif
5301 tcg_gen_not_tl(t0, t0);
5302 break;
5305 switch (opc) {
5306 case OPC_CLO:
5307 case R6_OPC_CLO:
5308 case OPC_CLZ:
5309 case R6_OPC_CLZ:
5310 tcg_gen_ext32u_tl(t0, t0);
5311 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5312 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5313 break;
5314 #if defined(TARGET_MIPS64)
5315 case OPC_DCLO:
5316 case R6_OPC_DCLO:
5317 case OPC_DCLZ:
5318 case R6_OPC_DCLZ:
5319 tcg_gen_clzi_i64(t0, t0, 64);
5320 break;
5321 #endif
5325 /* Godson integer instructions */
5326 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5327 int rd, int rs, int rt)
5329 TCGv t0, t1;
5331 if (rd == 0) {
5332 /* Treat as NOP. */
5333 return;
5336 switch (opc) {
5337 case OPC_MULT_G_2E:
5338 case OPC_MULT_G_2F:
5339 case OPC_MULTU_G_2E:
5340 case OPC_MULTU_G_2F:
5341 #if defined(TARGET_MIPS64)
5342 case OPC_DMULT_G_2E:
5343 case OPC_DMULT_G_2F:
5344 case OPC_DMULTU_G_2E:
5345 case OPC_DMULTU_G_2F:
5346 #endif
5347 t0 = tcg_temp_new();
5348 t1 = tcg_temp_new();
5349 break;
5350 default:
5351 t0 = tcg_temp_local_new();
5352 t1 = tcg_temp_local_new();
5353 break;
5356 gen_load_gpr(t0, rs);
5357 gen_load_gpr(t1, rt);
5359 switch (opc) {
5360 case OPC_MULT_G_2E:
5361 case OPC_MULT_G_2F:
5362 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5363 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5364 break;
5365 case OPC_MULTU_G_2E:
5366 case OPC_MULTU_G_2F:
5367 tcg_gen_ext32u_tl(t0, t0);
5368 tcg_gen_ext32u_tl(t1, t1);
5369 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5370 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5371 break;
5372 case OPC_DIV_G_2E:
5373 case OPC_DIV_G_2F:
5375 TCGLabel *l1 = gen_new_label();
5376 TCGLabel *l2 = gen_new_label();
5377 TCGLabel *l3 = gen_new_label();
5378 tcg_gen_ext32s_tl(t0, t0);
5379 tcg_gen_ext32s_tl(t1, t1);
5380 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5381 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5382 tcg_gen_br(l3);
5383 gen_set_label(l1);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5385 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5386 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5387 tcg_gen_br(l3);
5388 gen_set_label(l2);
5389 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5390 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5391 gen_set_label(l3);
5393 break;
5394 case OPC_DIVU_G_2E:
5395 case OPC_DIVU_G_2F:
5397 TCGLabel *l1 = gen_new_label();
5398 TCGLabel *l2 = gen_new_label();
5399 tcg_gen_ext32u_tl(t0, t0);
5400 tcg_gen_ext32u_tl(t1, t1);
5401 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5402 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5403 tcg_gen_br(l2);
5404 gen_set_label(l1);
5405 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5406 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5407 gen_set_label(l2);
5409 break;
5410 case OPC_MOD_G_2E:
5411 case OPC_MOD_G_2F:
5413 TCGLabel *l1 = gen_new_label();
5414 TCGLabel *l2 = gen_new_label();
5415 TCGLabel *l3 = gen_new_label();
5416 tcg_gen_ext32u_tl(t0, t0);
5417 tcg_gen_ext32u_tl(t1, t1);
5418 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5419 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5421 gen_set_label(l1);
5422 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5423 tcg_gen_br(l3);
5424 gen_set_label(l2);
5425 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5426 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5427 gen_set_label(l3);
5429 break;
5430 case OPC_MODU_G_2E:
5431 case OPC_MODU_G_2F:
5433 TCGLabel *l1 = gen_new_label();
5434 TCGLabel *l2 = gen_new_label();
5435 tcg_gen_ext32u_tl(t0, t0);
5436 tcg_gen_ext32u_tl(t1, t1);
5437 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5439 tcg_gen_br(l2);
5440 gen_set_label(l1);
5441 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5442 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5443 gen_set_label(l2);
5445 break;
5446 #if defined(TARGET_MIPS64)
5447 case OPC_DMULT_G_2E:
5448 case OPC_DMULT_G_2F:
5449 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5450 break;
5451 case OPC_DMULTU_G_2E:
5452 case OPC_DMULTU_G_2F:
5453 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5454 break;
5455 case OPC_DDIV_G_2E:
5456 case OPC_DDIV_G_2F:
5458 TCGLabel *l1 = gen_new_label();
5459 TCGLabel *l2 = gen_new_label();
5460 TCGLabel *l3 = gen_new_label();
5461 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5462 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5463 tcg_gen_br(l3);
5464 gen_set_label(l1);
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5466 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5467 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5468 tcg_gen_br(l3);
5469 gen_set_label(l2);
5470 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5471 gen_set_label(l3);
5473 break;
5474 case OPC_DDIVU_G_2E:
5475 case OPC_DDIVU_G_2F:
5477 TCGLabel *l1 = gen_new_label();
5478 TCGLabel *l2 = gen_new_label();
5479 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5480 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5481 tcg_gen_br(l2);
5482 gen_set_label(l1);
5483 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5484 gen_set_label(l2);
5486 break;
5487 case OPC_DMOD_G_2E:
5488 case OPC_DMOD_G_2F:
5490 TCGLabel *l1 = gen_new_label();
5491 TCGLabel *l2 = gen_new_label();
5492 TCGLabel *l3 = gen_new_label();
5493 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5494 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5495 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5496 gen_set_label(l1);
5497 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5498 tcg_gen_br(l3);
5499 gen_set_label(l2);
5500 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5501 gen_set_label(l3);
5503 break;
5504 case OPC_DMODU_G_2E:
5505 case OPC_DMODU_G_2F:
5507 TCGLabel *l1 = gen_new_label();
5508 TCGLabel *l2 = gen_new_label();
5509 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5510 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5511 tcg_gen_br(l2);
5512 gen_set_label(l1);
5513 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5514 gen_set_label(l2);
5516 break;
5517 #endif
5520 tcg_temp_free(t0);
5521 tcg_temp_free(t1);
5524 /* Loongson multimedia instructions */
5525 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5527 uint32_t opc, shift_max;
5528 TCGv_i64 t0, t1;
5530 opc = MASK_LMI(ctx->opcode);
5531 switch (opc) {
5532 case OPC_ADD_CP2:
5533 case OPC_SUB_CP2:
5534 case OPC_DADD_CP2:
5535 case OPC_DSUB_CP2:
5536 t0 = tcg_temp_local_new_i64();
5537 t1 = tcg_temp_local_new_i64();
5538 break;
5539 default:
5540 t0 = tcg_temp_new_i64();
5541 t1 = tcg_temp_new_i64();
5542 break;
5545 check_cp1_enabled(ctx);
5546 gen_load_fpr64(ctx, t0, rs);
5547 gen_load_fpr64(ctx, t1, rt);
5549 #define LMI_HELPER(UP, LO) \
5550 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5551 #define LMI_HELPER_1(UP, LO) \
5552 case OPC_##UP: gen_helper_##LO(t0, t0); break
5553 #define LMI_DIRECT(UP, LO, OP) \
5554 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5556 switch (opc) {
5557 LMI_HELPER(PADDSH, paddsh);
5558 LMI_HELPER(PADDUSH, paddush);
5559 LMI_HELPER(PADDH, paddh);
5560 LMI_HELPER(PADDW, paddw);
5561 LMI_HELPER(PADDSB, paddsb);
5562 LMI_HELPER(PADDUSB, paddusb);
5563 LMI_HELPER(PADDB, paddb);
5565 LMI_HELPER(PSUBSH, psubsh);
5566 LMI_HELPER(PSUBUSH, psubush);
5567 LMI_HELPER(PSUBH, psubh);
5568 LMI_HELPER(PSUBW, psubw);
5569 LMI_HELPER(PSUBSB, psubsb);
5570 LMI_HELPER(PSUBUSB, psubusb);
5571 LMI_HELPER(PSUBB, psubb);
5573 LMI_HELPER(PSHUFH, pshufh);
5574 LMI_HELPER(PACKSSWH, packsswh);
5575 LMI_HELPER(PACKSSHB, packsshb);
5576 LMI_HELPER(PACKUSHB, packushb);
5578 LMI_HELPER(PUNPCKLHW, punpcklhw);
5579 LMI_HELPER(PUNPCKHHW, punpckhhw);
5580 LMI_HELPER(PUNPCKLBH, punpcklbh);
5581 LMI_HELPER(PUNPCKHBH, punpckhbh);
5582 LMI_HELPER(PUNPCKLWD, punpcklwd);
5583 LMI_HELPER(PUNPCKHWD, punpckhwd);
5585 LMI_HELPER(PAVGH, pavgh);
5586 LMI_HELPER(PAVGB, pavgb);
5587 LMI_HELPER(PMAXSH, pmaxsh);
5588 LMI_HELPER(PMINSH, pminsh);
5589 LMI_HELPER(PMAXUB, pmaxub);
5590 LMI_HELPER(PMINUB, pminub);
5592 LMI_HELPER(PCMPEQW, pcmpeqw);
5593 LMI_HELPER(PCMPGTW, pcmpgtw);
5594 LMI_HELPER(PCMPEQH, pcmpeqh);
5595 LMI_HELPER(PCMPGTH, pcmpgth);
5596 LMI_HELPER(PCMPEQB, pcmpeqb);
5597 LMI_HELPER(PCMPGTB, pcmpgtb);
5599 LMI_HELPER(PSLLW, psllw);
5600 LMI_HELPER(PSLLH, psllh);
5601 LMI_HELPER(PSRLW, psrlw);
5602 LMI_HELPER(PSRLH, psrlh);
5603 LMI_HELPER(PSRAW, psraw);
5604 LMI_HELPER(PSRAH, psrah);
5606 LMI_HELPER(PMULLH, pmullh);
5607 LMI_HELPER(PMULHH, pmulhh);
5608 LMI_HELPER(PMULHUH, pmulhuh);
5609 LMI_HELPER(PMADDHW, pmaddhw);
5611 LMI_HELPER(PASUBUB, pasubub);
5612 LMI_HELPER_1(BIADD, biadd);
5613 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5615 LMI_DIRECT(PADDD, paddd, add);
5616 LMI_DIRECT(PSUBD, psubd, sub);
5617 LMI_DIRECT(XOR_CP2, xor, xor);
5618 LMI_DIRECT(NOR_CP2, nor, nor);
5619 LMI_DIRECT(AND_CP2, and, and);
5620 LMI_DIRECT(OR_CP2, or, or);
5622 case OPC_PANDN:
5623 tcg_gen_andc_i64(t0, t1, t0);
5624 break;
5626 case OPC_PINSRH_0:
5627 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5628 break;
5629 case OPC_PINSRH_1:
5630 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5631 break;
5632 case OPC_PINSRH_2:
5633 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5634 break;
5635 case OPC_PINSRH_3:
5636 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5637 break;
5639 case OPC_PEXTRH:
5640 tcg_gen_andi_i64(t1, t1, 3);
5641 tcg_gen_shli_i64(t1, t1, 4);
5642 tcg_gen_shr_i64(t0, t0, t1);
5643 tcg_gen_ext16u_i64(t0, t0);
5644 break;
5646 case OPC_ADDU_CP2:
5647 tcg_gen_add_i64(t0, t0, t1);
5648 tcg_gen_ext32s_i64(t0, t0);
5649 break;
5650 case OPC_SUBU_CP2:
5651 tcg_gen_sub_i64(t0, t0, t1);
5652 tcg_gen_ext32s_i64(t0, t0);
5653 break;
5655 case OPC_SLL_CP2:
5656 shift_max = 32;
5657 goto do_shift;
5658 case OPC_SRL_CP2:
5659 shift_max = 32;
5660 goto do_shift;
5661 case OPC_SRA_CP2:
5662 shift_max = 32;
5663 goto do_shift;
5664 case OPC_DSLL_CP2:
5665 shift_max = 64;
5666 goto do_shift;
5667 case OPC_DSRL_CP2:
5668 shift_max = 64;
5669 goto do_shift;
5670 case OPC_DSRA_CP2:
5671 shift_max = 64;
5672 goto do_shift;
5673 do_shift:
5674 /* Make sure shift count isn't TCG undefined behaviour. */
5675 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5677 switch (opc) {
5678 case OPC_SLL_CP2:
5679 case OPC_DSLL_CP2:
5680 tcg_gen_shl_i64(t0, t0, t1);
5681 break;
5682 case OPC_SRA_CP2:
5683 case OPC_DSRA_CP2:
5685 * Since SRA is UndefinedResult without sign-extended inputs,
5686 * we can treat SRA and DSRA the same.
5688 tcg_gen_sar_i64(t0, t0, t1);
5689 break;
5690 case OPC_SRL_CP2:
5691 /* We want to shift in zeros for SRL; zero-extend first. */
5692 tcg_gen_ext32u_i64(t0, t0);
5693 /* FALLTHRU */
5694 case OPC_DSRL_CP2:
5695 tcg_gen_shr_i64(t0, t0, t1);
5696 break;
5699 if (shift_max == 32) {
5700 tcg_gen_ext32s_i64(t0, t0);
5703 /* Shifts larger than MAX produce zero. */
5704 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5705 tcg_gen_neg_i64(t1, t1);
5706 tcg_gen_and_i64(t0, t0, t1);
5707 break;
5709 case OPC_ADD_CP2:
5710 case OPC_DADD_CP2:
5712 TCGv_i64 t2 = tcg_temp_new_i64();
5713 TCGLabel *lab = gen_new_label();
5715 tcg_gen_mov_i64(t2, t0);
5716 tcg_gen_add_i64(t0, t1, t2);
5717 if (opc == OPC_ADD_CP2) {
5718 tcg_gen_ext32s_i64(t0, t0);
5720 tcg_gen_xor_i64(t1, t1, t2);
5721 tcg_gen_xor_i64(t2, t2, t0);
5722 tcg_gen_andc_i64(t1, t2, t1);
5723 tcg_temp_free_i64(t2);
5724 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5725 generate_exception(ctx, EXCP_OVERFLOW);
5726 gen_set_label(lab);
5727 break;
5730 case OPC_SUB_CP2:
5731 case OPC_DSUB_CP2:
5733 TCGv_i64 t2 = tcg_temp_new_i64();
5734 TCGLabel *lab = gen_new_label();
5736 tcg_gen_mov_i64(t2, t0);
5737 tcg_gen_sub_i64(t0, t1, t2);
5738 if (opc == OPC_SUB_CP2) {
5739 tcg_gen_ext32s_i64(t0, t0);
5741 tcg_gen_xor_i64(t1, t1, t2);
5742 tcg_gen_xor_i64(t2, t2, t0);
5743 tcg_gen_and_i64(t1, t1, t2);
5744 tcg_temp_free_i64(t2);
5745 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5746 generate_exception(ctx, EXCP_OVERFLOW);
5747 gen_set_label(lab);
5748 break;
5751 case OPC_PMULUW:
5752 tcg_gen_ext32u_i64(t0, t0);
5753 tcg_gen_ext32u_i64(t1, t1);
5754 tcg_gen_mul_i64(t0, t0, t1);
5755 break;
5757 case OPC_SEQU_CP2:
5758 case OPC_SEQ_CP2:
5759 case OPC_SLTU_CP2:
5760 case OPC_SLT_CP2:
5761 case OPC_SLEU_CP2:
5762 case OPC_SLE_CP2:
5764 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5765 * FD field is the CC field?
5767 default:
5768 MIPS_INVAL("loongson_cp2");
5769 generate_exception_end(ctx, EXCP_RI);
5770 return;
5773 #undef LMI_HELPER
5774 #undef LMI_DIRECT
5776 gen_store_fpr64(ctx, t0, rd);
5778 tcg_temp_free_i64(t0);
5779 tcg_temp_free_i64(t1);
5782 /* Traps */
5783 static void gen_trap(DisasContext *ctx, uint32_t opc,
5784 int rs, int rt, int16_t imm)
5786 int cond;
5787 TCGv t0 = tcg_temp_new();
5788 TCGv t1 = tcg_temp_new();
5790 cond = 0;
5791 /* Load needed operands */
5792 switch (opc) {
5793 case OPC_TEQ:
5794 case OPC_TGE:
5795 case OPC_TGEU:
5796 case OPC_TLT:
5797 case OPC_TLTU:
5798 case OPC_TNE:
5799 /* Compare two registers */
5800 if (rs != rt) {
5801 gen_load_gpr(t0, rs);
5802 gen_load_gpr(t1, rt);
5803 cond = 1;
5805 break;
5806 case OPC_TEQI:
5807 case OPC_TGEI:
5808 case OPC_TGEIU:
5809 case OPC_TLTI:
5810 case OPC_TLTIU:
5811 case OPC_TNEI:
5812 /* Compare register to immediate */
5813 if (rs != 0 || imm != 0) {
5814 gen_load_gpr(t0, rs);
5815 tcg_gen_movi_tl(t1, (int32_t)imm);
5816 cond = 1;
5818 break;
5820 if (cond == 0) {
5821 switch (opc) {
5822 case OPC_TEQ: /* rs == rs */
5823 case OPC_TEQI: /* r0 == 0 */
5824 case OPC_TGE: /* rs >= rs */
5825 case OPC_TGEI: /* r0 >= 0 */
5826 case OPC_TGEU: /* rs >= rs unsigned */
5827 case OPC_TGEIU: /* r0 >= 0 unsigned */
5828 /* Always trap */
5829 generate_exception_end(ctx, EXCP_TRAP);
5830 break;
5831 case OPC_TLT: /* rs < rs */
5832 case OPC_TLTI: /* r0 < 0 */
5833 case OPC_TLTU: /* rs < rs unsigned */
5834 case OPC_TLTIU: /* r0 < 0 unsigned */
5835 case OPC_TNE: /* rs != rs */
5836 case OPC_TNEI: /* r0 != 0 */
5837 /* Never trap: treat as NOP. */
5838 break;
5840 } else {
5841 TCGLabel *l1 = gen_new_label();
5843 switch (opc) {
5844 case OPC_TEQ:
5845 case OPC_TEQI:
5846 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5847 break;
5848 case OPC_TGE:
5849 case OPC_TGEI:
5850 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5851 break;
5852 case OPC_TGEU:
5853 case OPC_TGEIU:
5854 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5855 break;
5856 case OPC_TLT:
5857 case OPC_TLTI:
5858 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5859 break;
5860 case OPC_TLTU:
5861 case OPC_TLTIU:
5862 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5863 break;
5864 case OPC_TNE:
5865 case OPC_TNEI:
5866 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5867 break;
5869 generate_exception(ctx, EXCP_TRAP);
5870 gen_set_label(l1);
5872 tcg_temp_free(t0);
5873 tcg_temp_free(t1);
5876 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5878 if (unlikely(ctx->base.singlestep_enabled)) {
5879 return false;
5882 #ifndef CONFIG_USER_ONLY
5883 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5884 #else
5885 return true;
5886 #endif
5889 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5891 if (use_goto_tb(ctx, dest)) {
5892 tcg_gen_goto_tb(n);
5893 gen_save_pc(dest);
5894 tcg_gen_exit_tb(ctx->base.tb, n);
5895 } else {
5896 gen_save_pc(dest);
5897 if (ctx->base.singlestep_enabled) {
5898 save_cpu_state(ctx, 0);
5899 gen_helper_raise_exception_debug(cpu_env);
5901 tcg_gen_lookup_and_goto_ptr();
5905 /* Branches (before delay slot) */
5906 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5907 int insn_bytes,
5908 int rs, int rt, int32_t offset,
5909 int delayslot_size)
5911 target_ulong btgt = -1;
5912 int blink = 0;
5913 int bcond_compute = 0;
5914 TCGv t0 = tcg_temp_new();
5915 TCGv t1 = tcg_temp_new();
5917 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5918 #ifdef MIPS_DEBUG_DISAS
5919 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5920 TARGET_FMT_lx "\n", ctx->base.pc_next);
5921 #endif
5922 generate_exception_end(ctx, EXCP_RI);
5923 goto out;
5926 /* Load needed operands */
5927 switch (opc) {
5928 case OPC_BEQ:
5929 case OPC_BEQL:
5930 case OPC_BNE:
5931 case OPC_BNEL:
5932 /* Compare two registers */
5933 if (rs != rt) {
5934 gen_load_gpr(t0, rs);
5935 gen_load_gpr(t1, rt);
5936 bcond_compute = 1;
5938 btgt = ctx->base.pc_next + insn_bytes + offset;
5939 break;
5940 case OPC_BGEZ:
5941 case OPC_BGEZAL:
5942 case OPC_BGEZALL:
5943 case OPC_BGEZL:
5944 case OPC_BGTZ:
5945 case OPC_BGTZL:
5946 case OPC_BLEZ:
5947 case OPC_BLEZL:
5948 case OPC_BLTZ:
5949 case OPC_BLTZAL:
5950 case OPC_BLTZALL:
5951 case OPC_BLTZL:
5952 /* Compare to zero */
5953 if (rs != 0) {
5954 gen_load_gpr(t0, rs);
5955 bcond_compute = 1;
5957 btgt = ctx->base.pc_next + insn_bytes + offset;
5958 break;
5959 case OPC_BPOSGE32:
5960 #if defined(TARGET_MIPS64)
5961 case OPC_BPOSGE64:
5962 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5963 #else
5964 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5965 #endif
5966 bcond_compute = 1;
5967 btgt = ctx->base.pc_next + insn_bytes + offset;
5968 break;
5969 case OPC_J:
5970 case OPC_JAL:
5971 case OPC_JALX:
5972 /* Jump to immediate */
5973 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5974 (uint32_t)offset;
5975 break;
5976 case OPC_JR:
5977 case OPC_JALR:
5978 /* Jump to register */
5979 if (offset != 0 && offset != 16) {
5981 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5982 * others are reserved.
5984 MIPS_INVAL("jump hint");
5985 generate_exception_end(ctx, EXCP_RI);
5986 goto out;
5988 gen_load_gpr(btarget, rs);
5989 break;
5990 default:
5991 MIPS_INVAL("branch/jump");
5992 generate_exception_end(ctx, EXCP_RI);
5993 goto out;
5995 if (bcond_compute == 0) {
5996 /* No condition to be computed */
5997 switch (opc) {
5998 case OPC_BEQ: /* rx == rx */
5999 case OPC_BEQL: /* rx == rx likely */
6000 case OPC_BGEZ: /* 0 >= 0 */
6001 case OPC_BGEZL: /* 0 >= 0 likely */
6002 case OPC_BLEZ: /* 0 <= 0 */
6003 case OPC_BLEZL: /* 0 <= 0 likely */
6004 /* Always take */
6005 ctx->hflags |= MIPS_HFLAG_B;
6006 break;
6007 case OPC_BGEZAL: /* 0 >= 0 */
6008 case OPC_BGEZALL: /* 0 >= 0 likely */
6009 /* Always take and link */
6010 blink = 31;
6011 ctx->hflags |= MIPS_HFLAG_B;
6012 break;
6013 case OPC_BNE: /* rx != rx */
6014 case OPC_BGTZ: /* 0 > 0 */
6015 case OPC_BLTZ: /* 0 < 0 */
6016 /* Treat as NOP. */
6017 goto out;
6018 case OPC_BLTZAL: /* 0 < 0 */
6020 * Handle as an unconditional branch to get correct delay
6021 * slot checking.
6023 blink = 31;
6024 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6025 ctx->hflags |= MIPS_HFLAG_B;
6026 break;
6027 case OPC_BLTZALL: /* 0 < 0 likely */
6028 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6029 /* Skip the instruction in the delay slot */
6030 ctx->base.pc_next += 4;
6031 goto out;
6032 case OPC_BNEL: /* rx != rx likely */
6033 case OPC_BGTZL: /* 0 > 0 likely */
6034 case OPC_BLTZL: /* 0 < 0 likely */
6035 /* Skip the instruction in the delay slot */
6036 ctx->base.pc_next += 4;
6037 goto out;
6038 case OPC_J:
6039 ctx->hflags |= MIPS_HFLAG_B;
6040 break;
6041 case OPC_JALX:
6042 ctx->hflags |= MIPS_HFLAG_BX;
6043 /* Fallthrough */
6044 case OPC_JAL:
6045 blink = 31;
6046 ctx->hflags |= MIPS_HFLAG_B;
6047 break;
6048 case OPC_JR:
6049 ctx->hflags |= MIPS_HFLAG_BR;
6050 break;
6051 case OPC_JALR:
6052 blink = rt;
6053 ctx->hflags |= MIPS_HFLAG_BR;
6054 break;
6055 default:
6056 MIPS_INVAL("branch/jump");
6057 generate_exception_end(ctx, EXCP_RI);
6058 goto out;
6060 } else {
6061 switch (opc) {
6062 case OPC_BEQ:
6063 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6064 goto not_likely;
6065 case OPC_BEQL:
6066 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6067 goto likely;
6068 case OPC_BNE:
6069 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6070 goto not_likely;
6071 case OPC_BNEL:
6072 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6073 goto likely;
6074 case OPC_BGEZ:
6075 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6076 goto not_likely;
6077 case OPC_BGEZL:
6078 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6079 goto likely;
6080 case OPC_BGEZAL:
6081 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6082 blink = 31;
6083 goto not_likely;
6084 case OPC_BGEZALL:
6085 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6086 blink = 31;
6087 goto likely;
6088 case OPC_BGTZ:
6089 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6090 goto not_likely;
6091 case OPC_BGTZL:
6092 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6093 goto likely;
6094 case OPC_BLEZ:
6095 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6096 goto not_likely;
6097 case OPC_BLEZL:
6098 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6099 goto likely;
6100 case OPC_BLTZ:
6101 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6102 goto not_likely;
6103 case OPC_BLTZL:
6104 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6105 goto likely;
6106 case OPC_BPOSGE32:
6107 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6108 goto not_likely;
6109 #if defined(TARGET_MIPS64)
6110 case OPC_BPOSGE64:
6111 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6112 goto not_likely;
6113 #endif
6114 case OPC_BLTZAL:
6115 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6116 blink = 31;
6117 not_likely:
6118 ctx->hflags |= MIPS_HFLAG_BC;
6119 break;
6120 case OPC_BLTZALL:
6121 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6122 blink = 31;
6123 likely:
6124 ctx->hflags |= MIPS_HFLAG_BL;
6125 break;
6126 default:
6127 MIPS_INVAL("conditional branch/jump");
6128 generate_exception_end(ctx, EXCP_RI);
6129 goto out;
6133 ctx->btarget = btgt;
6135 switch (delayslot_size) {
6136 case 2:
6137 ctx->hflags |= MIPS_HFLAG_BDS16;
6138 break;
6139 case 4:
6140 ctx->hflags |= MIPS_HFLAG_BDS32;
6141 break;
6144 if (blink > 0) {
6145 int post_delay = insn_bytes + delayslot_size;
6146 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6148 tcg_gen_movi_tl(cpu_gpr[blink],
6149 ctx->base.pc_next + post_delay + lowbit);
6152 out:
6153 if (insn_bytes == 2) {
6154 ctx->hflags |= MIPS_HFLAG_B16;
6156 tcg_temp_free(t0);
6157 tcg_temp_free(t1);
6161 /* nanoMIPS Branches */
6162 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6163 int insn_bytes,
6164 int rs, int rt, int32_t offset)
6166 target_ulong btgt = -1;
6167 int bcond_compute = 0;
6168 TCGv t0 = tcg_temp_new();
6169 TCGv t1 = tcg_temp_new();
6171 /* Load needed operands */
6172 switch (opc) {
6173 case OPC_BEQ:
6174 case OPC_BNE:
6175 /* Compare two registers */
6176 if (rs != rt) {
6177 gen_load_gpr(t0, rs);
6178 gen_load_gpr(t1, rt);
6179 bcond_compute = 1;
6181 btgt = ctx->base.pc_next + insn_bytes + offset;
6182 break;
6183 case OPC_BGEZAL:
6184 /* Compare to zero */
6185 if (rs != 0) {
6186 gen_load_gpr(t0, rs);
6187 bcond_compute = 1;
6189 btgt = ctx->base.pc_next + insn_bytes + offset;
6190 break;
6191 case OPC_BPOSGE32:
6192 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6193 bcond_compute = 1;
6194 btgt = ctx->base.pc_next + insn_bytes + offset;
6195 break;
6196 case OPC_JR:
6197 case OPC_JALR:
6198 /* Jump to register */
6199 if (offset != 0 && offset != 16) {
6201 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6202 * others are reserved.
6204 MIPS_INVAL("jump hint");
6205 generate_exception_end(ctx, EXCP_RI);
6206 goto out;
6208 gen_load_gpr(btarget, rs);
6209 break;
6210 default:
6211 MIPS_INVAL("branch/jump");
6212 generate_exception_end(ctx, EXCP_RI);
6213 goto out;
6215 if (bcond_compute == 0) {
6216 /* No condition to be computed */
6217 switch (opc) {
6218 case OPC_BEQ: /* rx == rx */
6219 /* Always take */
6220 ctx->hflags |= MIPS_HFLAG_B;
6221 break;
6222 case OPC_BGEZAL: /* 0 >= 0 */
6223 /* Always take and link */
6224 tcg_gen_movi_tl(cpu_gpr[31],
6225 ctx->base.pc_next + insn_bytes);
6226 ctx->hflags |= MIPS_HFLAG_B;
6227 break;
6228 case OPC_BNE: /* rx != rx */
6229 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6230 /* Skip the instruction in the delay slot */
6231 ctx->base.pc_next += 4;
6232 goto out;
6233 case OPC_JR:
6234 ctx->hflags |= MIPS_HFLAG_BR;
6235 break;
6236 case OPC_JALR:
6237 if (rt > 0) {
6238 tcg_gen_movi_tl(cpu_gpr[rt],
6239 ctx->base.pc_next + insn_bytes);
6241 ctx->hflags |= MIPS_HFLAG_BR;
6242 break;
6243 default:
6244 MIPS_INVAL("branch/jump");
6245 generate_exception_end(ctx, EXCP_RI);
6246 goto out;
6248 } else {
6249 switch (opc) {
6250 case OPC_BEQ:
6251 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6252 goto not_likely;
6253 case OPC_BNE:
6254 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6255 goto not_likely;
6256 case OPC_BGEZAL:
6257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6258 tcg_gen_movi_tl(cpu_gpr[31],
6259 ctx->base.pc_next + insn_bytes);
6260 goto not_likely;
6261 case OPC_BPOSGE32:
6262 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6263 not_likely:
6264 ctx->hflags |= MIPS_HFLAG_BC;
6265 break;
6266 default:
6267 MIPS_INVAL("conditional branch/jump");
6268 generate_exception_end(ctx, EXCP_RI);
6269 goto out;
6273 ctx->btarget = btgt;
6275 out:
6276 if (insn_bytes == 2) {
6277 ctx->hflags |= MIPS_HFLAG_B16;
6279 tcg_temp_free(t0);
6280 tcg_temp_free(t1);
6284 /* special3 bitfield operations */
6285 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6286 int rs, int lsb, int msb)
6288 TCGv t0 = tcg_temp_new();
6289 TCGv t1 = tcg_temp_new();
6291 gen_load_gpr(t1, rs);
6292 switch (opc) {
6293 case OPC_EXT:
6294 if (lsb + msb > 31) {
6295 goto fail;
6297 if (msb != 31) {
6298 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6299 } else {
6301 * The two checks together imply that lsb == 0,
6302 * so this is a simple sign-extension.
6304 tcg_gen_ext32s_tl(t0, t1);
6306 break;
6307 #if defined(TARGET_MIPS64)
6308 case OPC_DEXTU:
6309 lsb += 32;
6310 goto do_dext;
6311 case OPC_DEXTM:
6312 msb += 32;
6313 goto do_dext;
6314 case OPC_DEXT:
6315 do_dext:
6316 if (lsb + msb > 63) {
6317 goto fail;
6319 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6320 break;
6321 #endif
6322 case OPC_INS:
6323 if (lsb > msb) {
6324 goto fail;
6326 gen_load_gpr(t0, rt);
6327 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6328 tcg_gen_ext32s_tl(t0, t0);
6329 break;
6330 #if defined(TARGET_MIPS64)
6331 case OPC_DINSU:
6332 lsb += 32;
6333 /* FALLTHRU */
6334 case OPC_DINSM:
6335 msb += 32;
6336 /* FALLTHRU */
6337 case OPC_DINS:
6338 if (lsb > msb) {
6339 goto fail;
6341 gen_load_gpr(t0, rt);
6342 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6343 break;
6344 #endif
6345 default:
6346 fail:
6347 MIPS_INVAL("bitops");
6348 generate_exception_end(ctx, EXCP_RI);
6349 tcg_temp_free(t0);
6350 tcg_temp_free(t1);
6351 return;
6353 gen_store_gpr(t0, rt);
6354 tcg_temp_free(t0);
6355 tcg_temp_free(t1);
6358 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6360 TCGv t0;
6362 if (rd == 0) {
6363 /* If no destination, treat it as a NOP. */
6364 return;
6367 t0 = tcg_temp_new();
6368 gen_load_gpr(t0, rt);
6369 switch (op2) {
6370 case OPC_WSBH:
6372 TCGv t1 = tcg_temp_new();
6373 TCGv t2 = tcg_const_tl(0x00FF00FF);
6375 tcg_gen_shri_tl(t1, t0, 8);
6376 tcg_gen_and_tl(t1, t1, t2);
6377 tcg_gen_and_tl(t0, t0, t2);
6378 tcg_gen_shli_tl(t0, t0, 8);
6379 tcg_gen_or_tl(t0, t0, t1);
6380 tcg_temp_free(t2);
6381 tcg_temp_free(t1);
6382 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6384 break;
6385 case OPC_SEB:
6386 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6387 break;
6388 case OPC_SEH:
6389 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6390 break;
6391 #if defined(TARGET_MIPS64)
6392 case OPC_DSBH:
6394 TCGv t1 = tcg_temp_new();
6395 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6397 tcg_gen_shri_tl(t1, t0, 8);
6398 tcg_gen_and_tl(t1, t1, t2);
6399 tcg_gen_and_tl(t0, t0, t2);
6400 tcg_gen_shli_tl(t0, t0, 8);
6401 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6402 tcg_temp_free(t2);
6403 tcg_temp_free(t1);
6405 break;
6406 case OPC_DSHD:
6408 TCGv t1 = tcg_temp_new();
6409 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6411 tcg_gen_shri_tl(t1, t0, 16);
6412 tcg_gen_and_tl(t1, t1, t2);
6413 tcg_gen_and_tl(t0, t0, t2);
6414 tcg_gen_shli_tl(t0, t0, 16);
6415 tcg_gen_or_tl(t0, t0, t1);
6416 tcg_gen_shri_tl(t1, t0, 32);
6417 tcg_gen_shli_tl(t0, t0, 32);
6418 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6419 tcg_temp_free(t2);
6420 tcg_temp_free(t1);
6422 break;
6423 #endif
6424 default:
6425 MIPS_INVAL("bsfhl");
6426 generate_exception_end(ctx, EXCP_RI);
6427 tcg_temp_free(t0);
6428 return;
6430 tcg_temp_free(t0);
6433 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6434 int imm2)
6436 TCGv t0;
6437 TCGv t1;
6438 if (rd == 0) {
6439 /* Treat as NOP. */
6440 return;
6442 t0 = tcg_temp_new();
6443 t1 = tcg_temp_new();
6444 gen_load_gpr(t0, rs);
6445 gen_load_gpr(t1, rt);
6446 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6447 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6448 if (opc == OPC_LSA) {
6449 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6452 tcg_temp_free(t1);
6453 tcg_temp_free(t0);
6455 return;
6458 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6459 int rt, int bits)
6461 TCGv t0;
6462 if (rd == 0) {
6463 /* Treat as NOP. */
6464 return;
6466 t0 = tcg_temp_new();
6467 if (bits == 0 || bits == wordsz) {
6468 if (bits == 0) {
6469 gen_load_gpr(t0, rt);
6470 } else {
6471 gen_load_gpr(t0, rs);
6473 switch (wordsz) {
6474 case 32:
6475 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6476 break;
6477 #if defined(TARGET_MIPS64)
6478 case 64:
6479 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6480 break;
6481 #endif
6483 } else {
6484 TCGv t1 = tcg_temp_new();
6485 gen_load_gpr(t0, rt);
6486 gen_load_gpr(t1, rs);
6487 switch (wordsz) {
6488 case 32:
6490 TCGv_i64 t2 = tcg_temp_new_i64();
6491 tcg_gen_concat_tl_i64(t2, t1, t0);
6492 tcg_gen_shri_i64(t2, t2, 32 - bits);
6493 gen_move_low32(cpu_gpr[rd], t2);
6494 tcg_temp_free_i64(t2);
6496 break;
6497 #if defined(TARGET_MIPS64)
6498 case 64:
6499 tcg_gen_shli_tl(t0, t0, bits);
6500 tcg_gen_shri_tl(t1, t1, 64 - bits);
6501 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6502 break;
6503 #endif
6505 tcg_temp_free(t1);
6508 tcg_temp_free(t0);
6511 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6512 int bp)
6514 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6517 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6518 int shift)
6520 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6523 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6525 TCGv t0;
6526 if (rd == 0) {
6527 /* Treat as NOP. */
6528 return;
6530 t0 = tcg_temp_new();
6531 gen_load_gpr(t0, rt);
6532 switch (opc) {
6533 case OPC_BITSWAP:
6534 gen_helper_bitswap(cpu_gpr[rd], t0);
6535 break;
6536 #if defined(TARGET_MIPS64)
6537 case OPC_DBITSWAP:
6538 gen_helper_dbitswap(cpu_gpr[rd], t0);
6539 break;
6540 #endif
6542 tcg_temp_free(t0);
6545 #ifndef CONFIG_USER_ONLY
6546 /* CP0 (MMU and control) */
6547 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6549 TCGv_i64 t0 = tcg_temp_new_i64();
6550 TCGv_i64 t1 = tcg_temp_new_i64();
6552 tcg_gen_ext_tl_i64(t0, arg);
6553 tcg_gen_ld_i64(t1, cpu_env, off);
6554 #if defined(TARGET_MIPS64)
6555 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6556 #else
6557 tcg_gen_concat32_i64(t1, t1, t0);
6558 #endif
6559 tcg_gen_st_i64(t1, cpu_env, off);
6560 tcg_temp_free_i64(t1);
6561 tcg_temp_free_i64(t0);
6564 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6566 TCGv_i64 t0 = tcg_temp_new_i64();
6567 TCGv_i64 t1 = tcg_temp_new_i64();
6569 tcg_gen_ext_tl_i64(t0, arg);
6570 tcg_gen_ld_i64(t1, cpu_env, off);
6571 tcg_gen_concat32_i64(t1, t1, t0);
6572 tcg_gen_st_i64(t1, cpu_env, off);
6573 tcg_temp_free_i64(t1);
6574 tcg_temp_free_i64(t0);
6577 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6579 TCGv_i64 t0 = tcg_temp_new_i64();
6581 tcg_gen_ld_i64(t0, cpu_env, off);
6582 #if defined(TARGET_MIPS64)
6583 tcg_gen_shri_i64(t0, t0, 30);
6584 #else
6585 tcg_gen_shri_i64(t0, t0, 32);
6586 #endif
6587 gen_move_low32(arg, t0);
6588 tcg_temp_free_i64(t0);
6591 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6593 TCGv_i64 t0 = tcg_temp_new_i64();
6595 tcg_gen_ld_i64(t0, cpu_env, off);
6596 tcg_gen_shri_i64(t0, t0, 32 + shift);
6597 gen_move_low32(arg, t0);
6598 tcg_temp_free_i64(t0);
6601 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6603 TCGv_i32 t0 = tcg_temp_new_i32();
6605 tcg_gen_ld_i32(t0, cpu_env, off);
6606 tcg_gen_ext_i32_tl(arg, t0);
6607 tcg_temp_free_i32(t0);
6610 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6612 tcg_gen_ld_tl(arg, cpu_env, off);
6613 tcg_gen_ext32s_tl(arg, arg);
6616 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6618 TCGv_i32 t0 = tcg_temp_new_i32();
6620 tcg_gen_trunc_tl_i32(t0, arg);
6621 tcg_gen_st_i32(t0, cpu_env, off);
6622 tcg_temp_free_i32(t0);
6625 #define CP0_CHECK(c) \
6626 do { \
6627 if (!(c)) { \
6628 goto cp0_unimplemented; \
6630 } while (0)
6632 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6634 const char *register_name = "invalid";
6636 switch (reg) {
6637 case CP0_REGISTER_02:
6638 switch (sel) {
6639 case 0:
6640 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6641 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6642 register_name = "EntryLo0";
6643 break;
6644 default:
6645 goto cp0_unimplemented;
6647 break;
6648 case CP0_REGISTER_03:
6649 switch (sel) {
6650 case 0:
6651 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6652 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6653 register_name = "EntryLo1";
6654 break;
6655 default:
6656 goto cp0_unimplemented;
6658 break;
6659 case CP0_REGISTER_09:
6660 switch (sel) {
6661 case 7:
6662 CP0_CHECK(ctx->saar);
6663 gen_helper_mfhc0_saar(arg, cpu_env);
6664 register_name = "SAAR";
6665 break;
6666 default:
6667 goto cp0_unimplemented;
6669 break;
6670 case CP0_REGISTER_17:
6671 switch (sel) {
6672 case 0:
6673 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6674 ctx->CP0_LLAddr_shift);
6675 register_name = "LLAddr";
6676 break;
6677 case 1:
6678 CP0_CHECK(ctx->mrp);
6679 gen_helper_mfhc0_maar(arg, cpu_env);
6680 register_name = "MAAR";
6681 break;
6682 default:
6683 goto cp0_unimplemented;
6685 break;
6686 case CP0_REGISTER_28:
6687 switch (sel) {
6688 case 0:
6689 case 2:
6690 case 4:
6691 case 6:
6692 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6693 register_name = "TagLo";
6694 break;
6695 default:
6696 goto cp0_unimplemented;
6698 break;
6699 default:
6700 goto cp0_unimplemented;
6702 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6703 return;
6705 cp0_unimplemented:
6706 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6707 register_name, reg, sel);
6708 tcg_gen_movi_tl(arg, 0);
6711 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6713 const char *register_name = "invalid";
6714 uint64_t mask = ctx->PAMask >> 36;
6716 switch (reg) {
6717 case CP0_REGISTER_02:
6718 switch (sel) {
6719 case 0:
6720 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6721 tcg_gen_andi_tl(arg, arg, mask);
6722 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6723 register_name = "EntryLo0";
6724 break;
6725 default:
6726 goto cp0_unimplemented;
6728 break;
6729 case CP0_REGISTER_03:
6730 switch (sel) {
6731 case 0:
6732 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6733 tcg_gen_andi_tl(arg, arg, mask);
6734 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6735 register_name = "EntryLo1";
6736 break;
6737 default:
6738 goto cp0_unimplemented;
6740 break;
6741 case CP0_REGISTER_09:
6742 switch (sel) {
6743 case 7:
6744 CP0_CHECK(ctx->saar);
6745 gen_helper_mthc0_saar(cpu_env, arg);
6746 register_name = "SAAR";
6747 break;
6748 default:
6749 goto cp0_unimplemented;
6751 break;
6752 case CP0_REGISTER_17:
6753 switch (sel) {
6754 case 0:
6756 * LLAddr is read-only (the only exception is bit 0 if LLB is
6757 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6758 * relevant for modern MIPS cores supporting MTHC0, therefore
6759 * treating MTHC0 to LLAddr as NOP.
6761 register_name = "LLAddr";
6762 break;
6763 case 1:
6764 CP0_CHECK(ctx->mrp);
6765 gen_helper_mthc0_maar(cpu_env, arg);
6766 register_name = "MAAR";
6767 break;
6768 default:
6769 goto cp0_unimplemented;
6771 break;
6772 case CP0_REGISTER_28:
6773 switch (sel) {
6774 case 0:
6775 case 2:
6776 case 4:
6777 case 6:
6778 tcg_gen_andi_tl(arg, arg, mask);
6779 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6780 register_name = "TagLo";
6781 break;
6782 default:
6783 goto cp0_unimplemented;
6785 break;
6786 default:
6787 goto cp0_unimplemented;
6789 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6791 cp0_unimplemented:
6792 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6793 register_name, reg, sel);
6796 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6798 if (ctx->insn_flags & ISA_MIPS32R6) {
6799 tcg_gen_movi_tl(arg, 0);
6800 } else {
6801 tcg_gen_movi_tl(arg, ~0);
6805 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6807 const char *register_name = "invalid";
6809 if (sel != 0) {
6810 check_insn(ctx, ISA_MIPS32);
6813 switch (reg) {
6814 case CP0_REGISTER_00:
6815 switch (sel) {
6816 case CP0_REG00__INDEX:
6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6818 register_name = "Index";
6819 break;
6820 case CP0_REG00__MVPCONTROL:
6821 CP0_CHECK(ctx->insn_flags & ASE_MT);
6822 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6823 register_name = "MVPControl";
6824 break;
6825 case CP0_REG00__MVPCONF0:
6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
6827 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6828 register_name = "MVPConf0";
6829 break;
6830 case CP0_REG00__MVPCONF1:
6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
6832 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6833 register_name = "MVPConf1";
6834 break;
6835 case CP0_REG00__VPCONTROL:
6836 CP0_CHECK(ctx->vp);
6837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6838 register_name = "VPControl";
6839 break;
6840 default:
6841 goto cp0_unimplemented;
6843 break;
6844 case CP0_REGISTER_01:
6845 switch (sel) {
6846 case 0:
6847 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6848 gen_helper_mfc0_random(arg, cpu_env);
6849 register_name = "Random";
6850 break;
6851 case 1:
6852 CP0_CHECK(ctx->insn_flags & ASE_MT);
6853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6854 register_name = "VPEControl";
6855 break;
6856 case 2:
6857 CP0_CHECK(ctx->insn_flags & ASE_MT);
6858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6859 register_name = "VPEConf0";
6860 break;
6861 case 3:
6862 CP0_CHECK(ctx->insn_flags & ASE_MT);
6863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6864 register_name = "VPEConf1";
6865 break;
6866 case 4:
6867 CP0_CHECK(ctx->insn_flags & ASE_MT);
6868 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6869 register_name = "YQMask";
6870 break;
6871 case 5:
6872 CP0_CHECK(ctx->insn_flags & ASE_MT);
6873 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6874 register_name = "VPESchedule";
6875 break;
6876 case 6:
6877 CP0_CHECK(ctx->insn_flags & ASE_MT);
6878 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6879 register_name = "VPEScheFBack";
6880 break;
6881 case 7:
6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
6883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6884 register_name = "VPEOpt";
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 break;
6890 case CP0_REGISTER_02:
6891 switch (sel) {
6892 case 0:
6894 TCGv_i64 tmp = tcg_temp_new_i64();
6895 tcg_gen_ld_i64(tmp, cpu_env,
6896 offsetof(CPUMIPSState, CP0_EntryLo0));
6897 #if defined(TARGET_MIPS64)
6898 if (ctx->rxi) {
6899 /* Move RI/XI fields to bits 31:30 */
6900 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6901 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6903 #endif
6904 gen_move_low32(arg, tmp);
6905 tcg_temp_free_i64(tmp);
6907 register_name = "EntryLo0";
6908 break;
6909 case 1:
6910 CP0_CHECK(ctx->insn_flags & ASE_MT);
6911 gen_helper_mfc0_tcstatus(arg, cpu_env);
6912 register_name = "TCStatus";
6913 break;
6914 case 2:
6915 CP0_CHECK(ctx->insn_flags & ASE_MT);
6916 gen_helper_mfc0_tcbind(arg, cpu_env);
6917 register_name = "TCBind";
6918 break;
6919 case 3:
6920 CP0_CHECK(ctx->insn_flags & ASE_MT);
6921 gen_helper_mfc0_tcrestart(arg, cpu_env);
6922 register_name = "TCRestart";
6923 break;
6924 case 4:
6925 CP0_CHECK(ctx->insn_flags & ASE_MT);
6926 gen_helper_mfc0_tchalt(arg, cpu_env);
6927 register_name = "TCHalt";
6928 break;
6929 case 5:
6930 CP0_CHECK(ctx->insn_flags & ASE_MT);
6931 gen_helper_mfc0_tccontext(arg, cpu_env);
6932 register_name = "TCContext";
6933 break;
6934 case 6:
6935 CP0_CHECK(ctx->insn_flags & ASE_MT);
6936 gen_helper_mfc0_tcschedule(arg, cpu_env);
6937 register_name = "TCSchedule";
6938 break;
6939 case 7:
6940 CP0_CHECK(ctx->insn_flags & ASE_MT);
6941 gen_helper_mfc0_tcschefback(arg, cpu_env);
6942 register_name = "TCScheFBack";
6943 break;
6944 default:
6945 goto cp0_unimplemented;
6947 break;
6948 case CP0_REGISTER_03:
6949 switch (sel) {
6950 case 0:
6952 TCGv_i64 tmp = tcg_temp_new_i64();
6953 tcg_gen_ld_i64(tmp, cpu_env,
6954 offsetof(CPUMIPSState, CP0_EntryLo1));
6955 #if defined(TARGET_MIPS64)
6956 if (ctx->rxi) {
6957 /* Move RI/XI fields to bits 31:30 */
6958 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6959 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6961 #endif
6962 gen_move_low32(arg, tmp);
6963 tcg_temp_free_i64(tmp);
6965 register_name = "EntryLo1";
6966 break;
6967 case 1:
6968 CP0_CHECK(ctx->vp);
6969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6970 register_name = "GlobalNumber";
6971 break;
6972 default:
6973 goto cp0_unimplemented;
6975 break;
6976 case CP0_REGISTER_04:
6977 switch (sel) {
6978 case 0:
6979 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6980 tcg_gen_ext32s_tl(arg, arg);
6981 register_name = "Context";
6982 break;
6983 case 1:
6984 /* gen_helper_mfc0_contextconfig(arg); - SmartMIPS ASE */
6985 register_name = "ContextConfig";
6986 goto cp0_unimplemented;
6987 case 2:
6988 CP0_CHECK(ctx->ulri);
6989 tcg_gen_ld_tl(arg, cpu_env,
6990 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6991 tcg_gen_ext32s_tl(arg, arg);
6992 register_name = "UserLocal";
6993 break;
6994 default:
6995 goto cp0_unimplemented;
6997 break;
6998 case CP0_REGISTER_05:
6999 switch (sel) {
7000 case 0:
7001 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7002 register_name = "PageMask";
7003 break;
7004 case 1:
7005 check_insn(ctx, ISA_MIPS32R2);
7006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7007 register_name = "PageGrain";
7008 break;
7009 case 2:
7010 CP0_CHECK(ctx->sc);
7011 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7012 tcg_gen_ext32s_tl(arg, arg);
7013 register_name = "SegCtl0";
7014 break;
7015 case 3:
7016 CP0_CHECK(ctx->sc);
7017 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7018 tcg_gen_ext32s_tl(arg, arg);
7019 register_name = "SegCtl1";
7020 break;
7021 case 4:
7022 CP0_CHECK(ctx->sc);
7023 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7024 tcg_gen_ext32s_tl(arg, arg);
7025 register_name = "SegCtl2";
7026 break;
7027 case 5:
7028 check_pw(ctx);
7029 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7030 register_name = "PWBase";
7031 break;
7032 case 6:
7033 check_pw(ctx);
7034 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7035 register_name = "PWField";
7036 break;
7037 case 7:
7038 check_pw(ctx);
7039 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7040 register_name = "PWSize";
7041 break;
7042 default:
7043 goto cp0_unimplemented;
7045 break;
7046 case CP0_REGISTER_06:
7047 switch (sel) {
7048 case 0:
7049 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7050 register_name = "Wired";
7051 break;
7052 case 1:
7053 check_insn(ctx, ISA_MIPS32R2);
7054 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7055 register_name = "SRSConf0";
7056 break;
7057 case 2:
7058 check_insn(ctx, ISA_MIPS32R2);
7059 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7060 register_name = "SRSConf1";
7061 break;
7062 case 3:
7063 check_insn(ctx, ISA_MIPS32R2);
7064 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7065 register_name = "SRSConf2";
7066 break;
7067 case 4:
7068 check_insn(ctx, ISA_MIPS32R2);
7069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7070 register_name = "SRSConf3";
7071 break;
7072 case 5:
7073 check_insn(ctx, ISA_MIPS32R2);
7074 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7075 register_name = "SRSConf4";
7076 break;
7077 case 6:
7078 check_pw(ctx);
7079 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7080 register_name = "PWCtl";
7081 break;
7082 default:
7083 goto cp0_unimplemented;
7085 break;
7086 case CP0_REGISTER_07:
7087 switch (sel) {
7088 case 0:
7089 check_insn(ctx, ISA_MIPS32R2);
7090 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7091 register_name = "HWREna";
7092 break;
7093 default:
7094 goto cp0_unimplemented;
7096 break;
7097 case CP0_REGISTER_08:
7098 switch (sel) {
7099 case 0:
7100 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7101 tcg_gen_ext32s_tl(arg, arg);
7102 register_name = "BadVAddr";
7103 break;
7104 case 1:
7105 CP0_CHECK(ctx->bi);
7106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7107 register_name = "BadInstr";
7108 break;
7109 case 2:
7110 CP0_CHECK(ctx->bp);
7111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7112 register_name = "BadInstrP";
7113 break;
7114 case 3:
7115 CP0_CHECK(ctx->bi);
7116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7117 tcg_gen_andi_tl(arg, arg, ~0xffff);
7118 register_name = "BadInstrX";
7119 break;
7120 default:
7121 goto cp0_unimplemented;
7123 break;
7124 case CP0_REGISTER_09:
7125 switch (sel) {
7126 case 0:
7127 /* Mark as an IO operation because we read the time. */
7128 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7129 gen_io_start();
7131 gen_helper_mfc0_count(arg, cpu_env);
7133 * Break the TB to be able to take timer interrupts immediately
7134 * after reading count. DISAS_STOP isn't sufficient, we need to
7135 * ensure we break completely out of translated code.
7137 gen_save_pc(ctx->base.pc_next + 4);
7138 ctx->base.is_jmp = DISAS_EXIT;
7139 register_name = "Count";
7140 break;
7141 case 6:
7142 CP0_CHECK(ctx->saar);
7143 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7144 register_name = "SAARI";
7145 break;
7146 case 7:
7147 CP0_CHECK(ctx->saar);
7148 gen_helper_mfc0_saar(arg, cpu_env);
7149 register_name = "SAAR";
7150 break;
7151 default:
7152 goto cp0_unimplemented;
7154 break;
7155 case CP0_REGISTER_10:
7156 switch (sel) {
7157 case 0:
7158 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7159 tcg_gen_ext32s_tl(arg, arg);
7160 register_name = "EntryHi";
7161 break;
7162 default:
7163 goto cp0_unimplemented;
7165 break;
7166 case CP0_REGISTER_11:
7167 switch (sel) {
7168 case 0:
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7170 register_name = "Compare";
7171 break;
7172 /* 6,7 are implementation dependent */
7173 default:
7174 goto cp0_unimplemented;
7176 break;
7177 case CP0_REGISTER_12:
7178 switch (sel) {
7179 case 0:
7180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7181 register_name = "Status";
7182 break;
7183 case 1:
7184 check_insn(ctx, ISA_MIPS32R2);
7185 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7186 register_name = "IntCtl";
7187 break;
7188 case 2:
7189 check_insn(ctx, ISA_MIPS32R2);
7190 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7191 register_name = "SRSCtl";
7192 break;
7193 case 3:
7194 check_insn(ctx, ISA_MIPS32R2);
7195 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7196 register_name = "SRSMap";
7197 break;
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 case CP0_REGISTER_13:
7203 switch (sel) {
7204 case 0:
7205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7206 register_name = "Cause";
7207 break;
7208 default:
7209 goto cp0_unimplemented;
7211 break;
7212 case CP0_REGISTER_14:
7213 switch (sel) {
7214 case 0:
7215 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7216 tcg_gen_ext32s_tl(arg, arg);
7217 register_name = "EPC";
7218 break;
7219 default:
7220 goto cp0_unimplemented;
7222 break;
7223 case CP0_REGISTER_15:
7224 switch (sel) {
7225 case 0:
7226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7227 register_name = "PRid";
7228 break;
7229 case 1:
7230 check_insn(ctx, ISA_MIPS32R2);
7231 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7232 tcg_gen_ext32s_tl(arg, arg);
7233 register_name = "EBase";
7234 break;
7235 case 3:
7236 check_insn(ctx, ISA_MIPS32R2);
7237 CP0_CHECK(ctx->cmgcr);
7238 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7239 tcg_gen_ext32s_tl(arg, arg);
7240 register_name = "CMGCRBase";
7241 break;
7242 default:
7243 goto cp0_unimplemented;
7245 break;
7246 case CP0_REGISTER_16:
7247 switch (sel) {
7248 case 0:
7249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7250 register_name = "Config";
7251 break;
7252 case 1:
7253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7254 register_name = "Config1";
7255 break;
7256 case 2:
7257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7258 register_name = "Config2";
7259 break;
7260 case 3:
7261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7262 register_name = "Config3";
7263 break;
7264 case 4:
7265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7266 register_name = "Config4";
7267 break;
7268 case 5:
7269 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7270 register_name = "Config5";
7271 break;
7272 /* 6,7 are implementation dependent */
7273 case 6:
7274 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7275 register_name = "Config6";
7276 break;
7277 case 7:
7278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7279 register_name = "Config7";
7280 break;
7281 default:
7282 goto cp0_unimplemented;
7284 break;
7285 case CP0_REGISTER_17:
7286 switch (sel) {
7287 case 0:
7288 gen_helper_mfc0_lladdr(arg, cpu_env);
7289 register_name = "LLAddr";
7290 break;
7291 case 1:
7292 CP0_CHECK(ctx->mrp);
7293 gen_helper_mfc0_maar(arg, cpu_env);
7294 register_name = "MAAR";
7295 break;
7296 case 2:
7297 CP0_CHECK(ctx->mrp);
7298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7299 register_name = "MAARI";
7300 break;
7301 default:
7302 goto cp0_unimplemented;
7304 break;
7305 case CP0_REGISTER_18:
7306 switch (sel) {
7307 case 0:
7308 case 1:
7309 case 2:
7310 case 3:
7311 case 4:
7312 case 5:
7313 case 6:
7314 case 7:
7315 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7316 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7317 register_name = "WatchLo";
7318 break;
7319 default:
7320 goto cp0_unimplemented;
7322 break;
7323 case CP0_REGISTER_19:
7324 switch (sel) {
7325 case 0:
7326 case 1:
7327 case 2:
7328 case 3:
7329 case 4:
7330 case 5:
7331 case 6:
7332 case 7:
7333 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7334 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7335 register_name = "WatchHi";
7336 break;
7337 default:
7338 goto cp0_unimplemented;
7340 break;
7341 case CP0_REGISTER_20:
7342 switch (sel) {
7343 case 0:
7344 #if defined(TARGET_MIPS64)
7345 check_insn(ctx, ISA_MIPS3);
7346 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7347 tcg_gen_ext32s_tl(arg, arg);
7348 register_name = "XContext";
7349 break;
7350 #endif
7351 default:
7352 goto cp0_unimplemented;
7354 break;
7355 case CP0_REGISTER_21:
7356 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7357 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7358 switch (sel) {
7359 case 0:
7360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7361 register_name = "Framemask";
7362 break;
7363 default:
7364 goto cp0_unimplemented;
7366 break;
7367 case CP0_REGISTER_22:
7368 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7369 register_name = "'Diagnostic"; /* implementation dependent */
7370 break;
7371 case CP0_REGISTER_23:
7372 switch (sel) {
7373 case 0:
7374 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7375 register_name = "Debug";
7376 break;
7377 case 1:
7378 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7379 register_name = "TraceControl";
7380 goto cp0_unimplemented;
7381 case 2:
7382 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7383 register_name = "TraceControl2";
7384 goto cp0_unimplemented;
7385 case 3:
7386 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7387 register_name = "UserTraceData";
7388 goto cp0_unimplemented;
7389 case 4:
7390 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7391 register_name = "TraceBPC";
7392 goto cp0_unimplemented;
7393 default:
7394 goto cp0_unimplemented;
7396 break;
7397 case CP0_REGISTER_24:
7398 switch (sel) {
7399 case 0:
7400 /* EJTAG support */
7401 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7402 tcg_gen_ext32s_tl(arg, arg);
7403 register_name = "DEPC";
7404 break;
7405 default:
7406 goto cp0_unimplemented;
7408 break;
7409 case CP0_REGISTER_25:
7410 switch (sel) {
7411 case 0:
7412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7413 register_name = "Performance0";
7414 break;
7415 case 1:
7416 /* gen_helper_mfc0_performance1(arg); */
7417 register_name = "Performance1";
7418 goto cp0_unimplemented;
7419 case 2:
7420 /* gen_helper_mfc0_performance2(arg); */
7421 register_name = "Performance2";
7422 goto cp0_unimplemented;
7423 case 3:
7424 /* gen_helper_mfc0_performance3(arg); */
7425 register_name = "Performance3";
7426 goto cp0_unimplemented;
7427 case 4:
7428 /* gen_helper_mfc0_performance4(arg); */
7429 register_name = "Performance4";
7430 goto cp0_unimplemented;
7431 case 5:
7432 /* gen_helper_mfc0_performance5(arg); */
7433 register_name = "Performance5";
7434 goto cp0_unimplemented;
7435 case 6:
7436 /* gen_helper_mfc0_performance6(arg); */
7437 register_name = "Performance6";
7438 goto cp0_unimplemented;
7439 case 7:
7440 /* gen_helper_mfc0_performance7(arg); */
7441 register_name = "Performance7";
7442 goto cp0_unimplemented;
7443 default:
7444 goto cp0_unimplemented;
7446 break;
7447 case CP0_REGISTER_26:
7448 switch (sel) {
7449 case 0:
7450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7451 register_name = "ErrCtl";
7452 break;
7453 default:
7454 goto cp0_unimplemented;
7456 break;
7457 case CP0_REGISTER_27:
7458 switch (sel) {
7459 case 0:
7460 case 1:
7461 case 2:
7462 case 3:
7463 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7464 register_name = "CacheErr";
7465 break;
7466 default:
7467 goto cp0_unimplemented;
7469 break;
7470 case CP0_REGISTER_28:
7471 switch (sel) {
7472 case 0:
7473 case 2:
7474 case 4:
7475 case 6:
7477 TCGv_i64 tmp = tcg_temp_new_i64();
7478 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7479 gen_move_low32(arg, tmp);
7480 tcg_temp_free_i64(tmp);
7482 register_name = "TagLo";
7483 break;
7484 case 1:
7485 case 3:
7486 case 5:
7487 case 7:
7488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7489 register_name = "DataLo";
7490 break;
7491 default:
7492 goto cp0_unimplemented;
7494 break;
7495 case CP0_REGISTER_29:
7496 switch (sel) {
7497 case 0:
7498 case 2:
7499 case 4:
7500 case 6:
7501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7502 register_name = "TagHi";
7503 break;
7504 case 1:
7505 case 3:
7506 case 5:
7507 case 7:
7508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7509 register_name = "DataHi";
7510 break;
7511 default:
7512 goto cp0_unimplemented;
7514 break;
7515 case CP0_REGISTER_30:
7516 switch (sel) {
7517 case 0:
7518 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7519 tcg_gen_ext32s_tl(arg, arg);
7520 register_name = "ErrorEPC";
7521 break;
7522 default:
7523 goto cp0_unimplemented;
7525 break;
7526 case CP0_REGISTER_31:
7527 switch (sel) {
7528 case 0:
7529 /* EJTAG support */
7530 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7531 register_name = "DESAVE";
7532 break;
7533 case 2:
7534 case 3:
7535 case 4:
7536 case 5:
7537 case 6:
7538 case 7:
7539 CP0_CHECK(ctx->kscrexist & (1 << sel));
7540 tcg_gen_ld_tl(arg, cpu_env,
7541 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7542 tcg_gen_ext32s_tl(arg, arg);
7543 register_name = "KScratch";
7544 break;
7545 default:
7546 goto cp0_unimplemented;
7548 break;
7549 default:
7550 goto cp0_unimplemented;
7552 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7553 return;
7555 cp0_unimplemented:
7556 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7557 register_name, reg, sel);
7558 gen_mfc0_unimplemented(ctx, arg);
7561 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7563 const char *register_name = "invalid";
7565 if (sel != 0) {
7566 check_insn(ctx, ISA_MIPS32);
7569 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7570 gen_io_start();
7573 switch (reg) {
7574 case CP0_REGISTER_00:
7575 switch (sel) {
7576 case CP0_REG00__INDEX:
7577 gen_helper_mtc0_index(cpu_env, arg);
7578 register_name = "Index";
7579 break;
7580 case CP0_REG00__MVPCONTROL:
7581 CP0_CHECK(ctx->insn_flags & ASE_MT);
7582 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7583 register_name = "MVPControl";
7584 break;
7585 case CP0_REG00__MVPCONF0:
7586 CP0_CHECK(ctx->insn_flags & ASE_MT);
7587 /* ignored */
7588 register_name = "MVPConf0";
7589 break;
7590 case CP0_REG00__MVPCONF1:
7591 CP0_CHECK(ctx->insn_flags & ASE_MT);
7592 /* ignored */
7593 register_name = "MVPConf1";
7594 break;
7595 case CP0_REG00__VPCONTROL:
7596 CP0_CHECK(ctx->vp);
7597 /* ignored */
7598 register_name = "VPControl";
7599 break;
7600 default:
7601 goto cp0_unimplemented;
7603 break;
7604 case CP0_REGISTER_01:
7605 switch (sel) {
7606 case 0:
7607 /* ignored */
7608 register_name = "Random";
7609 break;
7610 case 1:
7611 CP0_CHECK(ctx->insn_flags & ASE_MT);
7612 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7613 register_name = "VPEControl";
7614 break;
7615 case 2:
7616 CP0_CHECK(ctx->insn_flags & ASE_MT);
7617 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7618 register_name = "VPEConf0";
7619 break;
7620 case 3:
7621 CP0_CHECK(ctx->insn_flags & ASE_MT);
7622 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7623 register_name = "VPEConf1";
7624 break;
7625 case 4:
7626 CP0_CHECK(ctx->insn_flags & ASE_MT);
7627 gen_helper_mtc0_yqmask(cpu_env, arg);
7628 register_name = "YQMask";
7629 break;
7630 case 5:
7631 CP0_CHECK(ctx->insn_flags & ASE_MT);
7632 tcg_gen_st_tl(arg, cpu_env,
7633 offsetof(CPUMIPSState, CP0_VPESchedule));
7634 register_name = "VPESchedule";
7635 break;
7636 case 6:
7637 CP0_CHECK(ctx->insn_flags & ASE_MT);
7638 tcg_gen_st_tl(arg, cpu_env,
7639 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7640 register_name = "VPEScheFBack";
7641 break;
7642 case 7:
7643 CP0_CHECK(ctx->insn_flags & ASE_MT);
7644 gen_helper_mtc0_vpeopt(cpu_env, arg);
7645 register_name = "VPEOpt";
7646 break;
7647 default:
7648 goto cp0_unimplemented;
7650 break;
7651 case CP0_REGISTER_02:
7652 switch (sel) {
7653 case 0:
7654 gen_helper_mtc0_entrylo0(cpu_env, arg);
7655 register_name = "EntryLo0";
7656 break;
7657 case 1:
7658 CP0_CHECK(ctx->insn_flags & ASE_MT);
7659 gen_helper_mtc0_tcstatus(cpu_env, arg);
7660 register_name = "TCStatus";
7661 break;
7662 case 2:
7663 CP0_CHECK(ctx->insn_flags & ASE_MT);
7664 gen_helper_mtc0_tcbind(cpu_env, arg);
7665 register_name = "TCBind";
7666 break;
7667 case 3:
7668 CP0_CHECK(ctx->insn_flags & ASE_MT);
7669 gen_helper_mtc0_tcrestart(cpu_env, arg);
7670 register_name = "TCRestart";
7671 break;
7672 case 4:
7673 CP0_CHECK(ctx->insn_flags & ASE_MT);
7674 gen_helper_mtc0_tchalt(cpu_env, arg);
7675 register_name = "TCHalt";
7676 break;
7677 case 5:
7678 CP0_CHECK(ctx->insn_flags & ASE_MT);
7679 gen_helper_mtc0_tccontext(cpu_env, arg);
7680 register_name = "TCContext";
7681 break;
7682 case 6:
7683 CP0_CHECK(ctx->insn_flags & ASE_MT);
7684 gen_helper_mtc0_tcschedule(cpu_env, arg);
7685 register_name = "TCSchedule";
7686 break;
7687 case 7:
7688 CP0_CHECK(ctx->insn_flags & ASE_MT);
7689 gen_helper_mtc0_tcschefback(cpu_env, arg);
7690 register_name = "TCScheFBack";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case CP0_REGISTER_03:
7697 switch (sel) {
7698 case 0:
7699 gen_helper_mtc0_entrylo1(cpu_env, arg);
7700 register_name = "EntryLo1";
7701 break;
7702 case 1:
7703 CP0_CHECK(ctx->vp);
7704 /* ignored */
7705 register_name = "GlobalNumber";
7706 break;
7707 default:
7708 goto cp0_unimplemented;
7710 break;
7711 case CP0_REGISTER_04:
7712 switch (sel) {
7713 case 0:
7714 gen_helper_mtc0_context(cpu_env, arg);
7715 register_name = "Context";
7716 break;
7717 case 1:
7718 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7719 register_name = "ContextConfig";
7720 goto cp0_unimplemented;
7721 case 2:
7722 CP0_CHECK(ctx->ulri);
7723 tcg_gen_st_tl(arg, cpu_env,
7724 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7725 register_name = "UserLocal";
7726 break;
7727 default:
7728 goto cp0_unimplemented;
7730 break;
7731 case CP0_REGISTER_05:
7732 switch (sel) {
7733 case 0:
7734 gen_helper_mtc0_pagemask(cpu_env, arg);
7735 register_name = "PageMask";
7736 break;
7737 case 1:
7738 check_insn(ctx, ISA_MIPS32R2);
7739 gen_helper_mtc0_pagegrain(cpu_env, arg);
7740 register_name = "PageGrain";
7741 ctx->base.is_jmp = DISAS_STOP;
7742 break;
7743 case 2:
7744 CP0_CHECK(ctx->sc);
7745 gen_helper_mtc0_segctl0(cpu_env, arg);
7746 register_name = "SegCtl0";
7747 break;
7748 case 3:
7749 CP0_CHECK(ctx->sc);
7750 gen_helper_mtc0_segctl1(cpu_env, arg);
7751 register_name = "SegCtl1";
7752 break;
7753 case 4:
7754 CP0_CHECK(ctx->sc);
7755 gen_helper_mtc0_segctl2(cpu_env, arg);
7756 register_name = "SegCtl2";
7757 break;
7758 case 5:
7759 check_pw(ctx);
7760 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7761 register_name = "PWBase";
7762 break;
7763 case 6:
7764 check_pw(ctx);
7765 gen_helper_mtc0_pwfield(cpu_env, arg);
7766 register_name = "PWField";
7767 break;
7768 case 7:
7769 check_pw(ctx);
7770 gen_helper_mtc0_pwsize(cpu_env, arg);
7771 register_name = "PWSize";
7772 break;
7773 default:
7774 goto cp0_unimplemented;
7776 break;
7777 case CP0_REGISTER_06:
7778 switch (sel) {
7779 case 0:
7780 gen_helper_mtc0_wired(cpu_env, arg);
7781 register_name = "Wired";
7782 break;
7783 case 1:
7784 check_insn(ctx, ISA_MIPS32R2);
7785 gen_helper_mtc0_srsconf0(cpu_env, arg);
7786 register_name = "SRSConf0";
7787 break;
7788 case 2:
7789 check_insn(ctx, ISA_MIPS32R2);
7790 gen_helper_mtc0_srsconf1(cpu_env, arg);
7791 register_name = "SRSConf1";
7792 break;
7793 case 3:
7794 check_insn(ctx, ISA_MIPS32R2);
7795 gen_helper_mtc0_srsconf2(cpu_env, arg);
7796 register_name = "SRSConf2";
7797 break;
7798 case 4:
7799 check_insn(ctx, ISA_MIPS32R2);
7800 gen_helper_mtc0_srsconf3(cpu_env, arg);
7801 register_name = "SRSConf3";
7802 break;
7803 case 5:
7804 check_insn(ctx, ISA_MIPS32R2);
7805 gen_helper_mtc0_srsconf4(cpu_env, arg);
7806 register_name = "SRSConf4";
7807 break;
7808 case 6:
7809 check_pw(ctx);
7810 gen_helper_mtc0_pwctl(cpu_env, arg);
7811 register_name = "PWCtl";
7812 break;
7813 default:
7814 goto cp0_unimplemented;
7816 break;
7817 case CP0_REGISTER_07:
7818 switch (sel) {
7819 case 0:
7820 check_insn(ctx, ISA_MIPS32R2);
7821 gen_helper_mtc0_hwrena(cpu_env, arg);
7822 ctx->base.is_jmp = DISAS_STOP;
7823 register_name = "HWREna";
7824 break;
7825 default:
7826 goto cp0_unimplemented;
7828 break;
7829 case CP0_REGISTER_08:
7830 switch (sel) {
7831 case 0:
7832 /* ignored */
7833 register_name = "BadVAddr";
7834 break;
7835 case 1:
7836 /* ignored */
7837 register_name = "BadInstr";
7838 break;
7839 case 2:
7840 /* ignored */
7841 register_name = "BadInstrP";
7842 break;
7843 case 3:
7844 /* ignored */
7845 register_name = "BadInstrX";
7846 break;
7847 default:
7848 goto cp0_unimplemented;
7850 break;
7851 case CP0_REGISTER_09:
7852 switch (sel) {
7853 case 0:
7854 gen_helper_mtc0_count(cpu_env, arg);
7855 register_name = "Count";
7856 break;
7857 case 6:
7858 CP0_CHECK(ctx->saar);
7859 gen_helper_mtc0_saari(cpu_env, arg);
7860 register_name = "SAARI";
7861 break;
7862 case 7:
7863 CP0_CHECK(ctx->saar);
7864 gen_helper_mtc0_saar(cpu_env, arg);
7865 register_name = "SAAR";
7866 break;
7867 default:
7868 goto cp0_unimplemented;
7870 break;
7871 case CP0_REGISTER_10:
7872 switch (sel) {
7873 case 0:
7874 gen_helper_mtc0_entryhi(cpu_env, arg);
7875 register_name = "EntryHi";
7876 break;
7877 default:
7878 goto cp0_unimplemented;
7880 break;
7881 case CP0_REGISTER_11:
7882 switch (sel) {
7883 case 0:
7884 gen_helper_mtc0_compare(cpu_env, arg);
7885 register_name = "Compare";
7886 break;
7887 /* 6,7 are implementation dependent */
7888 default:
7889 goto cp0_unimplemented;
7891 break;
7892 case CP0_REGISTER_12:
7893 switch (sel) {
7894 case 0:
7895 save_cpu_state(ctx, 1);
7896 gen_helper_mtc0_status(cpu_env, arg);
7897 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7898 gen_save_pc(ctx->base.pc_next + 4);
7899 ctx->base.is_jmp = DISAS_EXIT;
7900 register_name = "Status";
7901 break;
7902 case 1:
7903 check_insn(ctx, ISA_MIPS32R2);
7904 gen_helper_mtc0_intctl(cpu_env, arg);
7905 /* Stop translation as we may have switched the execution mode */
7906 ctx->base.is_jmp = DISAS_STOP;
7907 register_name = "IntCtl";
7908 break;
7909 case 2:
7910 check_insn(ctx, ISA_MIPS32R2);
7911 gen_helper_mtc0_srsctl(cpu_env, arg);
7912 /* Stop translation as we may have switched the execution mode */
7913 ctx->base.is_jmp = DISAS_STOP;
7914 register_name = "SRSCtl";
7915 break;
7916 case 3:
7917 check_insn(ctx, ISA_MIPS32R2);
7918 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7919 /* Stop translation as we may have switched the execution mode */
7920 ctx->base.is_jmp = DISAS_STOP;
7921 register_name = "SRSMap";
7922 break;
7923 default:
7924 goto cp0_unimplemented;
7926 break;
7927 case CP0_REGISTER_13:
7928 switch (sel) {
7929 case 0:
7930 save_cpu_state(ctx, 1);
7931 gen_helper_mtc0_cause(cpu_env, arg);
7933 * Stop translation as we may have triggered an interrupt.
7934 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7935 * translated code to check for pending interrupts.
7937 gen_save_pc(ctx->base.pc_next + 4);
7938 ctx->base.is_jmp = DISAS_EXIT;
7939 register_name = "Cause";
7940 break;
7941 default:
7942 goto cp0_unimplemented;
7944 break;
7945 case CP0_REGISTER_14:
7946 switch (sel) {
7947 case 0:
7948 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7949 register_name = "EPC";
7950 break;
7951 default:
7952 goto cp0_unimplemented;
7954 break;
7955 case CP0_REGISTER_15:
7956 switch (sel) {
7957 case 0:
7958 /* ignored */
7959 register_name = "PRid";
7960 break;
7961 case 1:
7962 check_insn(ctx, ISA_MIPS32R2);
7963 gen_helper_mtc0_ebase(cpu_env, arg);
7964 register_name = "EBase";
7965 break;
7966 default:
7967 goto cp0_unimplemented;
7969 break;
7970 case CP0_REGISTER_16:
7971 switch (sel) {
7972 case 0:
7973 gen_helper_mtc0_config0(cpu_env, arg);
7974 register_name = "Config";
7975 /* Stop translation as we may have switched the execution mode */
7976 ctx->base.is_jmp = DISAS_STOP;
7977 break;
7978 case 1:
7979 /* ignored, read only */
7980 register_name = "Config1";
7981 break;
7982 case 2:
7983 gen_helper_mtc0_config2(cpu_env, arg);
7984 register_name = "Config2";
7985 /* Stop translation as we may have switched the execution mode */
7986 ctx->base.is_jmp = DISAS_STOP;
7987 break;
7988 case 3:
7989 gen_helper_mtc0_config3(cpu_env, arg);
7990 register_name = "Config3";
7991 /* Stop translation as we may have switched the execution mode */
7992 ctx->base.is_jmp = DISAS_STOP;
7993 break;
7994 case 4:
7995 gen_helper_mtc0_config4(cpu_env, arg);
7996 register_name = "Config4";
7997 ctx->base.is_jmp = DISAS_STOP;
7998 break;
7999 case 5:
8000 gen_helper_mtc0_config5(cpu_env, arg);
8001 register_name = "Config5";
8002 /* Stop translation as we may have switched the execution mode */
8003 ctx->base.is_jmp = DISAS_STOP;
8004 break;
8005 /* 6,7 are implementation dependent */
8006 case 6:
8007 /* ignored */
8008 register_name = "Config6";
8009 break;
8010 case 7:
8011 /* ignored */
8012 register_name = "Config7";
8013 break;
8014 default:
8015 register_name = "Invalid config selector";
8016 goto cp0_unimplemented;
8018 break;
8019 case CP0_REGISTER_17:
8020 switch (sel) {
8021 case 0:
8022 gen_helper_mtc0_lladdr(cpu_env, arg);
8023 register_name = "LLAddr";
8024 break;
8025 case 1:
8026 CP0_CHECK(ctx->mrp);
8027 gen_helper_mtc0_maar(cpu_env, arg);
8028 register_name = "MAAR";
8029 break;
8030 case 2:
8031 CP0_CHECK(ctx->mrp);
8032 gen_helper_mtc0_maari(cpu_env, arg);
8033 register_name = "MAARI";
8034 break;
8035 default:
8036 goto cp0_unimplemented;
8038 break;
8039 case CP0_REGISTER_18:
8040 switch (sel) {
8041 case 0:
8042 case 1:
8043 case 2:
8044 case 3:
8045 case 4:
8046 case 5:
8047 case 6:
8048 case 7:
8049 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8050 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8051 register_name = "WatchLo";
8052 break;
8053 default:
8054 goto cp0_unimplemented;
8056 break;
8057 case CP0_REGISTER_19:
8058 switch (sel) {
8059 case 0:
8060 case 1:
8061 case 2:
8062 case 3:
8063 case 4:
8064 case 5:
8065 case 6:
8066 case 7:
8067 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8068 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8069 register_name = "WatchHi";
8070 break;
8071 default:
8072 goto cp0_unimplemented;
8074 break;
8075 case CP0_REGISTER_20:
8076 switch (sel) {
8077 case 0:
8078 #if defined(TARGET_MIPS64)
8079 check_insn(ctx, ISA_MIPS3);
8080 gen_helper_mtc0_xcontext(cpu_env, arg);
8081 register_name = "XContext";
8082 break;
8083 #endif
8084 default:
8085 goto cp0_unimplemented;
8087 break;
8088 case CP0_REGISTER_21:
8089 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8090 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8091 switch (sel) {
8092 case 0:
8093 gen_helper_mtc0_framemask(cpu_env, arg);
8094 register_name = "Framemask";
8095 break;
8096 default:
8097 goto cp0_unimplemented;
8099 break;
8100 case CP0_REGISTER_22:
8101 /* ignored */
8102 register_name = "Diagnostic"; /* implementation dependent */
8103 break;
8104 case CP0_REGISTER_23:
8105 switch (sel) {
8106 case 0:
8107 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8108 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8109 gen_save_pc(ctx->base.pc_next + 4);
8110 ctx->base.is_jmp = DISAS_EXIT;
8111 register_name = "Debug";
8112 break;
8113 case 1:
8114 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8115 register_name = "TraceControl";
8116 /* Stop translation as we may have switched the execution mode */
8117 ctx->base.is_jmp = DISAS_STOP;
8118 goto cp0_unimplemented;
8119 case 2:
8120 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8121 register_name = "TraceControl2";
8122 /* Stop translation as we may have switched the execution mode */
8123 ctx->base.is_jmp = DISAS_STOP;
8124 goto cp0_unimplemented;
8125 case 3:
8126 /* Stop translation as we may have switched the execution mode */
8127 ctx->base.is_jmp = DISAS_STOP;
8128 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8129 register_name = "UserTraceData";
8130 /* Stop translation as we may have switched the execution mode */
8131 ctx->base.is_jmp = DISAS_STOP;
8132 goto cp0_unimplemented;
8133 case 4:
8134 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8135 /* Stop translation as we may have switched the execution mode */
8136 ctx->base.is_jmp = DISAS_STOP;
8137 register_name = "TraceBPC";
8138 goto cp0_unimplemented;
8139 default:
8140 goto cp0_unimplemented;
8142 break;
8143 case CP0_REGISTER_24:
8144 switch (sel) {
8145 case 0:
8146 /* EJTAG support */
8147 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8148 register_name = "DEPC";
8149 break;
8150 default:
8151 goto cp0_unimplemented;
8153 break;
8154 case CP0_REGISTER_25:
8155 switch (sel) {
8156 case 0:
8157 gen_helper_mtc0_performance0(cpu_env, arg);
8158 register_name = "Performance0";
8159 break;
8160 case 1:
8161 /* gen_helper_mtc0_performance1(arg); */
8162 register_name = "Performance1";
8163 goto cp0_unimplemented;
8164 case 2:
8165 /* gen_helper_mtc0_performance2(arg); */
8166 register_name = "Performance2";
8167 goto cp0_unimplemented;
8168 case 3:
8169 /* gen_helper_mtc0_performance3(arg); */
8170 register_name = "Performance3";
8171 goto cp0_unimplemented;
8172 case 4:
8173 /* gen_helper_mtc0_performance4(arg); */
8174 register_name = "Performance4";
8175 goto cp0_unimplemented;
8176 case 5:
8177 /* gen_helper_mtc0_performance5(arg); */
8178 register_name = "Performance5";
8179 goto cp0_unimplemented;
8180 case 6:
8181 /* gen_helper_mtc0_performance6(arg); */
8182 register_name = "Performance6";
8183 goto cp0_unimplemented;
8184 case 7:
8185 /* gen_helper_mtc0_performance7(arg); */
8186 register_name = "Performance7";
8187 goto cp0_unimplemented;
8188 default:
8189 goto cp0_unimplemented;
8191 break;
8192 case CP0_REGISTER_26:
8193 switch (sel) {
8194 case 0:
8195 gen_helper_mtc0_errctl(cpu_env, arg);
8196 ctx->base.is_jmp = DISAS_STOP;
8197 register_name = "ErrCtl";
8198 break;
8199 default:
8200 goto cp0_unimplemented;
8202 break;
8203 case CP0_REGISTER_27:
8204 switch (sel) {
8205 case 0:
8206 case 1:
8207 case 2:
8208 case 3:
8209 /* ignored */
8210 register_name = "CacheErr";
8211 break;
8212 default:
8213 goto cp0_unimplemented;
8215 break;
8216 case CP0_REGISTER_28:
8217 switch (sel) {
8218 case 0:
8219 case 2:
8220 case 4:
8221 case 6:
8222 gen_helper_mtc0_taglo(cpu_env, arg);
8223 register_name = "TagLo";
8224 break;
8225 case 1:
8226 case 3:
8227 case 5:
8228 case 7:
8229 gen_helper_mtc0_datalo(cpu_env, arg);
8230 register_name = "DataLo";
8231 break;
8232 default:
8233 goto cp0_unimplemented;
8235 break;
8236 case CP0_REGISTER_29:
8237 switch (sel) {
8238 case 0:
8239 case 2:
8240 case 4:
8241 case 6:
8242 gen_helper_mtc0_taghi(cpu_env, arg);
8243 register_name = "TagHi";
8244 break;
8245 case 1:
8246 case 3:
8247 case 5:
8248 case 7:
8249 gen_helper_mtc0_datahi(cpu_env, arg);
8250 register_name = "DataHi";
8251 break;
8252 default:
8253 register_name = "invalid sel";
8254 goto cp0_unimplemented;
8256 break;
8257 case CP0_REGISTER_30:
8258 switch (sel) {
8259 case 0:
8260 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8261 register_name = "ErrorEPC";
8262 break;
8263 default:
8264 goto cp0_unimplemented;
8266 break;
8267 case CP0_REGISTER_31:
8268 switch (sel) {
8269 case 0:
8270 /* EJTAG support */
8271 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8272 register_name = "DESAVE";
8273 break;
8274 case 2:
8275 case 3:
8276 case 4:
8277 case 5:
8278 case 6:
8279 case 7:
8280 CP0_CHECK(ctx->kscrexist & (1 << sel));
8281 tcg_gen_st_tl(arg, cpu_env,
8282 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8283 register_name = "KScratch";
8284 break;
8285 default:
8286 goto cp0_unimplemented;
8288 break;
8289 default:
8290 goto cp0_unimplemented;
8292 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8294 /* For simplicity assume that all writes can cause interrupts. */
8295 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8297 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8298 * translated code to check for pending interrupts.
8300 gen_save_pc(ctx->base.pc_next + 4);
8301 ctx->base.is_jmp = DISAS_EXIT;
8303 return;
8305 cp0_unimplemented:
8306 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8307 register_name, reg, sel);
8310 #if defined(TARGET_MIPS64)
8311 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8313 const char *register_name = "invalid";
8315 if (sel != 0) {
8316 check_insn(ctx, ISA_MIPS64);
8319 switch (reg) {
8320 case CP0_REGISTER_00:
8321 switch (sel) {
8322 case CP0_REG00__INDEX:
8323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8324 register_name = "Index";
8325 break;
8326 case CP0_REG00__MVPCONTROL:
8327 CP0_CHECK(ctx->insn_flags & ASE_MT);
8328 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8329 register_name = "MVPControl";
8330 break;
8331 case CP0_REG00__MVPCONF0:
8332 CP0_CHECK(ctx->insn_flags & ASE_MT);
8333 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8334 register_name = "MVPConf0";
8335 break;
8336 case CP0_REG00__MVPCONF1:
8337 CP0_CHECK(ctx->insn_flags & ASE_MT);
8338 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8339 register_name = "MVPConf1";
8340 break;
8341 case CP0_REG00__VPCONTROL:
8342 CP0_CHECK(ctx->vp);
8343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8344 register_name = "VPControl";
8345 break;
8346 default:
8347 goto cp0_unimplemented;
8349 break;
8350 case CP0_REGISTER_01:
8351 switch (sel) {
8352 case 0:
8353 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8354 gen_helper_mfc0_random(arg, cpu_env);
8355 register_name = "Random";
8356 break;
8357 case 1:
8358 CP0_CHECK(ctx->insn_flags & ASE_MT);
8359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8360 register_name = "VPEControl";
8361 break;
8362 case 2:
8363 CP0_CHECK(ctx->insn_flags & ASE_MT);
8364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8365 register_name = "VPEConf0";
8366 break;
8367 case 3:
8368 CP0_CHECK(ctx->insn_flags & ASE_MT);
8369 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8370 register_name = "VPEConf1";
8371 break;
8372 case 4:
8373 CP0_CHECK(ctx->insn_flags & ASE_MT);
8374 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8375 register_name = "YQMask";
8376 break;
8377 case 5:
8378 CP0_CHECK(ctx->insn_flags & ASE_MT);
8379 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8380 register_name = "VPESchedule";
8381 break;
8382 case 6:
8383 CP0_CHECK(ctx->insn_flags & ASE_MT);
8384 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8385 register_name = "VPEScheFBack";
8386 break;
8387 case 7:
8388 CP0_CHECK(ctx->insn_flags & ASE_MT);
8389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8390 register_name = "VPEOpt";
8391 break;
8392 default:
8393 goto cp0_unimplemented;
8395 break;
8396 case CP0_REGISTER_02:
8397 switch (sel) {
8398 case 0:
8399 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8400 register_name = "EntryLo0";
8401 break;
8402 case 1:
8403 CP0_CHECK(ctx->insn_flags & ASE_MT);
8404 gen_helper_mfc0_tcstatus(arg, cpu_env);
8405 register_name = "TCStatus";
8406 break;
8407 case 2:
8408 CP0_CHECK(ctx->insn_flags & ASE_MT);
8409 gen_helper_mfc0_tcbind(arg, cpu_env);
8410 register_name = "TCBind";
8411 break;
8412 case 3:
8413 CP0_CHECK(ctx->insn_flags & ASE_MT);
8414 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8415 register_name = "TCRestart";
8416 break;
8417 case 4:
8418 CP0_CHECK(ctx->insn_flags & ASE_MT);
8419 gen_helper_dmfc0_tchalt(arg, cpu_env);
8420 register_name = "TCHalt";
8421 break;
8422 case 5:
8423 CP0_CHECK(ctx->insn_flags & ASE_MT);
8424 gen_helper_dmfc0_tccontext(arg, cpu_env);
8425 register_name = "TCContext";
8426 break;
8427 case 6:
8428 CP0_CHECK(ctx->insn_flags & ASE_MT);
8429 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8430 register_name = "TCSchedule";
8431 break;
8432 case 7:
8433 CP0_CHECK(ctx->insn_flags & ASE_MT);
8434 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8435 register_name = "TCScheFBack";
8436 break;
8437 default:
8438 goto cp0_unimplemented;
8440 break;
8441 case CP0_REGISTER_03:
8442 switch (sel) {
8443 case 0:
8444 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8445 register_name = "EntryLo1";
8446 break;
8447 case 1:
8448 CP0_CHECK(ctx->vp);
8449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8450 register_name = "GlobalNumber";
8451 break;
8452 default:
8453 goto cp0_unimplemented;
8455 break;
8456 case CP0_REGISTER_04:
8457 switch (sel) {
8458 case 0:
8459 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8460 register_name = "Context";
8461 break;
8462 case 1:
8463 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8464 register_name = "ContextConfig";
8465 goto cp0_unimplemented;
8466 case 2:
8467 CP0_CHECK(ctx->ulri);
8468 tcg_gen_ld_tl(arg, cpu_env,
8469 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8470 register_name = "UserLocal";
8471 break;
8472 default:
8473 goto cp0_unimplemented;
8475 break;
8476 case CP0_REGISTER_05:
8477 switch (sel) {
8478 case 0:
8479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8480 register_name = "PageMask";
8481 break;
8482 case 1:
8483 check_insn(ctx, ISA_MIPS32R2);
8484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8485 register_name = "PageGrain";
8486 break;
8487 case 2:
8488 CP0_CHECK(ctx->sc);
8489 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8490 register_name = "SegCtl0";
8491 break;
8492 case 3:
8493 CP0_CHECK(ctx->sc);
8494 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8495 register_name = "SegCtl1";
8496 break;
8497 case 4:
8498 CP0_CHECK(ctx->sc);
8499 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8500 register_name = "SegCtl2";
8501 break;
8502 case 5:
8503 check_pw(ctx);
8504 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8505 register_name = "PWBase";
8506 break;
8507 case 6:
8508 check_pw(ctx);
8509 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8510 register_name = "PWField";
8511 break;
8512 case 7:
8513 check_pw(ctx);
8514 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8515 register_name = "PWSize";
8516 break;
8517 default:
8518 goto cp0_unimplemented;
8520 break;
8521 case CP0_REGISTER_06:
8522 switch (sel) {
8523 case 0:
8524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8525 register_name = "Wired";
8526 break;
8527 case 1:
8528 check_insn(ctx, ISA_MIPS32R2);
8529 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8530 register_name = "SRSConf0";
8531 break;
8532 case 2:
8533 check_insn(ctx, ISA_MIPS32R2);
8534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8535 register_name = "SRSConf1";
8536 break;
8537 case 3:
8538 check_insn(ctx, ISA_MIPS32R2);
8539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8540 register_name = "SRSConf2";
8541 break;
8542 case 4:
8543 check_insn(ctx, ISA_MIPS32R2);
8544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8545 register_name = "SRSConf3";
8546 break;
8547 case 5:
8548 check_insn(ctx, ISA_MIPS32R2);
8549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8550 register_name = "SRSConf4";
8551 break;
8552 case 6:
8553 check_pw(ctx);
8554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8555 register_name = "PWCtl";
8556 break;
8557 default:
8558 goto cp0_unimplemented;
8560 break;
8561 case CP0_REGISTER_07:
8562 switch (sel) {
8563 case 0:
8564 check_insn(ctx, ISA_MIPS32R2);
8565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8566 register_name = "HWREna";
8567 break;
8568 default:
8569 goto cp0_unimplemented;
8571 break;
8572 case CP0_REGISTER_08:
8573 switch (sel) {
8574 case 0:
8575 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8576 register_name = "BadVAddr";
8577 break;
8578 case 1:
8579 CP0_CHECK(ctx->bi);
8580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8581 register_name = "BadInstr";
8582 break;
8583 case 2:
8584 CP0_CHECK(ctx->bp);
8585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8586 register_name = "BadInstrP";
8587 break;
8588 case 3:
8589 CP0_CHECK(ctx->bi);
8590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8591 tcg_gen_andi_tl(arg, arg, ~0xffff);
8592 register_name = "BadInstrX";
8593 break;
8594 default:
8595 goto cp0_unimplemented;
8597 break;
8598 case CP0_REGISTER_09:
8599 switch (sel) {
8600 case 0:
8601 /* Mark as an IO operation because we read the time. */
8602 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8603 gen_io_start();
8605 gen_helper_mfc0_count(arg, cpu_env);
8607 * Break the TB to be able to take timer interrupts immediately
8608 * after reading count. DISAS_STOP isn't sufficient, we need to
8609 * ensure we break completely out of translated code.
8611 gen_save_pc(ctx->base.pc_next + 4);
8612 ctx->base.is_jmp = DISAS_EXIT;
8613 register_name = "Count";
8614 break;
8615 case 6:
8616 CP0_CHECK(ctx->saar);
8617 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8618 register_name = "SAARI";
8619 break;
8620 case 7:
8621 CP0_CHECK(ctx->saar);
8622 gen_helper_dmfc0_saar(arg, cpu_env);
8623 register_name = "SAAR";
8624 break;
8625 default:
8626 goto cp0_unimplemented;
8628 break;
8629 case CP0_REGISTER_10:
8630 switch (sel) {
8631 case 0:
8632 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8633 register_name = "EntryHi";
8634 break;
8635 default:
8636 goto cp0_unimplemented;
8638 break;
8639 case CP0_REGISTER_11:
8640 switch (sel) {
8641 case 0:
8642 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8643 register_name = "Compare";
8644 break;
8645 /* 6,7 are implementation dependent */
8646 default:
8647 goto cp0_unimplemented;
8649 break;
8650 case CP0_REGISTER_12:
8651 switch (sel) {
8652 case 0:
8653 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8654 register_name = "Status";
8655 break;
8656 case 1:
8657 check_insn(ctx, ISA_MIPS32R2);
8658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8659 register_name = "IntCtl";
8660 break;
8661 case 2:
8662 check_insn(ctx, ISA_MIPS32R2);
8663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8664 register_name = "SRSCtl";
8665 break;
8666 case 3:
8667 check_insn(ctx, ISA_MIPS32R2);
8668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8669 register_name = "SRSMap";
8670 break;
8671 default:
8672 goto cp0_unimplemented;
8674 break;
8675 case CP0_REGISTER_13:
8676 switch (sel) {
8677 case 0:
8678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8679 register_name = "Cause";
8680 break;
8681 default:
8682 goto cp0_unimplemented;
8684 break;
8685 case CP0_REGISTER_14:
8686 switch (sel) {
8687 case 0:
8688 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8689 register_name = "EPC";
8690 break;
8691 default:
8692 goto cp0_unimplemented;
8694 break;
8695 case CP0_REGISTER_15:
8696 switch (sel) {
8697 case 0:
8698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8699 register_name = "PRid";
8700 break;
8701 case 1:
8702 check_insn(ctx, ISA_MIPS32R2);
8703 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8704 register_name = "EBase";
8705 break;
8706 case 3:
8707 check_insn(ctx, ISA_MIPS32R2);
8708 CP0_CHECK(ctx->cmgcr);
8709 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8710 register_name = "CMGCRBase";
8711 break;
8712 default:
8713 goto cp0_unimplemented;
8715 break;
8716 case CP0_REGISTER_16:
8717 switch (sel) {
8718 case 0:
8719 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8720 register_name = "Config";
8721 break;
8722 case 1:
8723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8724 register_name = "Config1";
8725 break;
8726 case 2:
8727 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8728 register_name = "Config2";
8729 break;
8730 case 3:
8731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8732 register_name = "Config3";
8733 break;
8734 case 4:
8735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8736 register_name = "Config4";
8737 break;
8738 case 5:
8739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8740 register_name = "Config5";
8741 break;
8742 /* 6,7 are implementation dependent */
8743 case 6:
8744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8745 register_name = "Config6";
8746 break;
8747 case 7:
8748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8749 register_name = "Config7";
8750 break;
8751 default:
8752 goto cp0_unimplemented;
8754 break;
8755 case CP0_REGISTER_17:
8756 switch (sel) {
8757 case 0:
8758 gen_helper_dmfc0_lladdr(arg, cpu_env);
8759 register_name = "LLAddr";
8760 break;
8761 case 1:
8762 CP0_CHECK(ctx->mrp);
8763 gen_helper_dmfc0_maar(arg, cpu_env);
8764 register_name = "MAAR";
8765 break;
8766 case 2:
8767 CP0_CHECK(ctx->mrp);
8768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8769 register_name = "MAARI";
8770 break;
8771 default:
8772 goto cp0_unimplemented;
8774 break;
8775 case CP0_REGISTER_18:
8776 switch (sel) {
8777 case 0:
8778 case 1:
8779 case 2:
8780 case 3:
8781 case 4:
8782 case 5:
8783 case 6:
8784 case 7:
8785 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8786 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8787 register_name = "WatchLo";
8788 break;
8789 default:
8790 goto cp0_unimplemented;
8792 break;
8793 case CP0_REGISTER_19:
8794 switch (sel) {
8795 case 0:
8796 case 1:
8797 case 2:
8798 case 3:
8799 case 4:
8800 case 5:
8801 case 6:
8802 case 7:
8803 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8804 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8805 register_name = "WatchHi";
8806 break;
8807 default:
8808 goto cp0_unimplemented;
8810 break;
8811 case CP0_REGISTER_20:
8812 switch (sel) {
8813 case 0:
8814 check_insn(ctx, ISA_MIPS3);
8815 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8816 register_name = "XContext";
8817 break;
8818 default:
8819 goto cp0_unimplemented;
8821 break;
8822 case CP0_REGISTER_21:
8823 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8824 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8825 switch (sel) {
8826 case 0:
8827 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8828 register_name = "Framemask";
8829 break;
8830 default:
8831 goto cp0_unimplemented;
8833 break;
8834 case CP0_REGISTER_22:
8835 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8836 register_name = "'Diagnostic"; /* implementation dependent */
8837 break;
8838 case CP0_REGISTER_23:
8839 switch (sel) {
8840 case 0:
8841 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8842 register_name = "Debug";
8843 break;
8844 case 1:
8845 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8846 register_name = "TraceControl";
8847 goto cp0_unimplemented;
8848 case 2:
8849 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8850 register_name = "TraceControl2";
8851 goto cp0_unimplemented;
8852 case 3:
8853 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8854 register_name = "UserTraceData";
8855 goto cp0_unimplemented;
8856 case 4:
8857 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8858 register_name = "TraceBPC";
8859 goto cp0_unimplemented;
8860 default:
8861 goto cp0_unimplemented;
8863 break;
8864 case CP0_REGISTER_24:
8865 switch (sel) {
8866 case 0:
8867 /* EJTAG support */
8868 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8869 register_name = "DEPC";
8870 break;
8871 default:
8872 goto cp0_unimplemented;
8874 break;
8875 case CP0_REGISTER_25:
8876 switch (sel) {
8877 case 0:
8878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8879 register_name = "Performance0";
8880 break;
8881 case 1:
8882 /* gen_helper_dmfc0_performance1(arg); */
8883 register_name = "Performance1";
8884 goto cp0_unimplemented;
8885 case 2:
8886 /* gen_helper_dmfc0_performance2(arg); */
8887 register_name = "Performance2";
8888 goto cp0_unimplemented;
8889 case 3:
8890 /* gen_helper_dmfc0_performance3(arg); */
8891 register_name = "Performance3";
8892 goto cp0_unimplemented;
8893 case 4:
8894 /* gen_helper_dmfc0_performance4(arg); */
8895 register_name = "Performance4";
8896 goto cp0_unimplemented;
8897 case 5:
8898 /* gen_helper_dmfc0_performance5(arg); */
8899 register_name = "Performance5";
8900 goto cp0_unimplemented;
8901 case 6:
8902 /* gen_helper_dmfc0_performance6(arg); */
8903 register_name = "Performance6";
8904 goto cp0_unimplemented;
8905 case 7:
8906 /* gen_helper_dmfc0_performance7(arg); */
8907 register_name = "Performance7";
8908 goto cp0_unimplemented;
8909 default:
8910 goto cp0_unimplemented;
8912 break;
8913 case CP0_REGISTER_26:
8914 switch (sel) {
8915 case 0:
8916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8917 register_name = "ErrCtl";
8918 break;
8919 default:
8920 goto cp0_unimplemented;
8922 break;
8923 case CP0_REGISTER_27:
8924 switch (sel) {
8925 /* ignored */
8926 case 0:
8927 case 1:
8928 case 2:
8929 case 3:
8930 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8931 register_name = "CacheErr";
8932 break;
8933 default:
8934 goto cp0_unimplemented;
8936 break;
8937 case CP0_REGISTER_28:
8938 switch (sel) {
8939 case 0:
8940 case 2:
8941 case 4:
8942 case 6:
8943 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8944 register_name = "TagLo";
8945 break;
8946 case 1:
8947 case 3:
8948 case 5:
8949 case 7:
8950 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8951 register_name = "DataLo";
8952 break;
8953 default:
8954 goto cp0_unimplemented;
8956 break;
8957 case CP0_REGISTER_29:
8958 switch (sel) {
8959 case 0:
8960 case 2:
8961 case 4:
8962 case 6:
8963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8964 register_name = "TagHi";
8965 break;
8966 case 1:
8967 case 3:
8968 case 5:
8969 case 7:
8970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8971 register_name = "DataHi";
8972 break;
8973 default:
8974 goto cp0_unimplemented;
8976 break;
8977 case CP0_REGISTER_30:
8978 switch (sel) {
8979 case 0:
8980 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8981 register_name = "ErrorEPC";
8982 break;
8983 default:
8984 goto cp0_unimplemented;
8986 break;
8987 case CP0_REGISTER_31:
8988 switch (sel) {
8989 case 0:
8990 /* EJTAG support */
8991 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8992 register_name = "DESAVE";
8993 break;
8994 case 2:
8995 case 3:
8996 case 4:
8997 case 5:
8998 case 6:
8999 case 7:
9000 CP0_CHECK(ctx->kscrexist & (1 << sel));
9001 tcg_gen_ld_tl(arg, cpu_env,
9002 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9003 register_name = "KScratch";
9004 break;
9005 default:
9006 goto cp0_unimplemented;
9008 break;
9009 default:
9010 goto cp0_unimplemented;
9012 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9013 return;
9015 cp0_unimplemented:
9016 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9017 register_name, reg, sel);
9018 gen_mfc0_unimplemented(ctx, arg);
9021 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9023 const char *register_name = "invalid";
9025 if (sel != 0) {
9026 check_insn(ctx, ISA_MIPS64);
9029 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9030 gen_io_start();
9033 switch (reg) {
9034 case CP0_REGISTER_00:
9035 switch (sel) {
9036 case CP0_REG00__INDEX:
9037 gen_helper_mtc0_index(cpu_env, arg);
9038 register_name = "Index";
9039 break;
9040 case CP0_REG00__MVPCONTROL:
9041 CP0_CHECK(ctx->insn_flags & ASE_MT);
9042 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9043 register_name = "MVPControl";
9044 break;
9045 case CP0_REG00__MVPCONF0:
9046 CP0_CHECK(ctx->insn_flags & ASE_MT);
9047 /* ignored */
9048 register_name = "MVPConf0";
9049 break;
9050 case CP0_REG00__MVPCONF1:
9051 CP0_CHECK(ctx->insn_flags & ASE_MT);
9052 /* ignored */
9053 register_name = "MVPConf1";
9054 break;
9055 case CP0_REG00__VPCONTROL:
9056 CP0_CHECK(ctx->vp);
9057 /* ignored */
9058 register_name = "VPControl";
9059 break;
9060 default:
9061 goto cp0_unimplemented;
9063 break;
9064 case CP0_REGISTER_01:
9065 switch (sel) {
9066 case 0:
9067 /* ignored */
9068 register_name = "Random";
9069 break;
9070 case 1:
9071 CP0_CHECK(ctx->insn_flags & ASE_MT);
9072 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9073 register_name = "VPEControl";
9074 break;
9075 case 2:
9076 CP0_CHECK(ctx->insn_flags & ASE_MT);
9077 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9078 register_name = "VPEConf0";
9079 break;
9080 case 3:
9081 CP0_CHECK(ctx->insn_flags & ASE_MT);
9082 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9083 register_name = "VPEConf1";
9084 break;
9085 case 4:
9086 CP0_CHECK(ctx->insn_flags & ASE_MT);
9087 gen_helper_mtc0_yqmask(cpu_env, arg);
9088 register_name = "YQMask";
9089 break;
9090 case 5:
9091 CP0_CHECK(ctx->insn_flags & ASE_MT);
9092 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9093 register_name = "VPESchedule";
9094 break;
9095 case 6:
9096 CP0_CHECK(ctx->insn_flags & ASE_MT);
9097 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9098 register_name = "VPEScheFBack";
9099 break;
9100 case 7:
9101 CP0_CHECK(ctx->insn_flags & ASE_MT);
9102 gen_helper_mtc0_vpeopt(cpu_env, arg);
9103 register_name = "VPEOpt";
9104 break;
9105 default:
9106 goto cp0_unimplemented;
9108 break;
9109 case CP0_REGISTER_02:
9110 switch (sel) {
9111 case 0:
9112 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9113 register_name = "EntryLo0";
9114 break;
9115 case 1:
9116 CP0_CHECK(ctx->insn_flags & ASE_MT);
9117 gen_helper_mtc0_tcstatus(cpu_env, arg);
9118 register_name = "TCStatus";
9119 break;
9120 case 2:
9121 CP0_CHECK(ctx->insn_flags & ASE_MT);
9122 gen_helper_mtc0_tcbind(cpu_env, arg);
9123 register_name = "TCBind";
9124 break;
9125 case 3:
9126 CP0_CHECK(ctx->insn_flags & ASE_MT);
9127 gen_helper_mtc0_tcrestart(cpu_env, arg);
9128 register_name = "TCRestart";
9129 break;
9130 case 4:
9131 CP0_CHECK(ctx->insn_flags & ASE_MT);
9132 gen_helper_mtc0_tchalt(cpu_env, arg);
9133 register_name = "TCHalt";
9134 break;
9135 case 5:
9136 CP0_CHECK(ctx->insn_flags & ASE_MT);
9137 gen_helper_mtc0_tccontext(cpu_env, arg);
9138 register_name = "TCContext";
9139 break;
9140 case 6:
9141 CP0_CHECK(ctx->insn_flags & ASE_MT);
9142 gen_helper_mtc0_tcschedule(cpu_env, arg);
9143 register_name = "TCSchedule";
9144 break;
9145 case 7:
9146 CP0_CHECK(ctx->insn_flags & ASE_MT);
9147 gen_helper_mtc0_tcschefback(cpu_env, arg);
9148 register_name = "TCScheFBack";
9149 break;
9150 default:
9151 goto cp0_unimplemented;
9153 break;
9154 case CP0_REGISTER_03:
9155 switch (sel) {
9156 case 0:
9157 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9158 register_name = "EntryLo1";
9159 break;
9160 case 1:
9161 CP0_CHECK(ctx->vp);
9162 /* ignored */
9163 register_name = "GlobalNumber";
9164 break;
9165 default:
9166 goto cp0_unimplemented;
9168 break;
9169 case CP0_REGISTER_04:
9170 switch (sel) {
9171 case 0:
9172 gen_helper_mtc0_context(cpu_env, arg);
9173 register_name = "Context";
9174 break;
9175 case 1:
9176 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
9177 register_name = "ContextConfig";
9178 goto cp0_unimplemented;
9179 case 2:
9180 CP0_CHECK(ctx->ulri);
9181 tcg_gen_st_tl(arg, cpu_env,
9182 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9183 register_name = "UserLocal";
9184 break;
9185 default:
9186 goto cp0_unimplemented;
9188 break;
9189 case CP0_REGISTER_05:
9190 switch (sel) {
9191 case 0:
9192 gen_helper_mtc0_pagemask(cpu_env, arg);
9193 register_name = "PageMask";
9194 break;
9195 case 1:
9196 check_insn(ctx, ISA_MIPS32R2);
9197 gen_helper_mtc0_pagegrain(cpu_env, arg);
9198 register_name = "PageGrain";
9199 break;
9200 case 2:
9201 CP0_CHECK(ctx->sc);
9202 gen_helper_mtc0_segctl0(cpu_env, arg);
9203 register_name = "SegCtl0";
9204 break;
9205 case 3:
9206 CP0_CHECK(ctx->sc);
9207 gen_helper_mtc0_segctl1(cpu_env, arg);
9208 register_name = "SegCtl1";
9209 break;
9210 case 4:
9211 CP0_CHECK(ctx->sc);
9212 gen_helper_mtc0_segctl2(cpu_env, arg);
9213 register_name = "SegCtl2";
9214 break;
9215 case 5:
9216 check_pw(ctx);
9217 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9218 register_name = "PWBase";
9219 break;
9220 case 6:
9221 check_pw(ctx);
9222 gen_helper_mtc0_pwfield(cpu_env, arg);
9223 register_name = "PWField";
9224 break;
9225 case 7:
9226 check_pw(ctx);
9227 gen_helper_mtc0_pwsize(cpu_env, arg);
9228 register_name = "PWSize";
9229 break;
9230 default:
9231 goto cp0_unimplemented;
9233 break;
9234 case CP0_REGISTER_06:
9235 switch (sel) {
9236 case 0:
9237 gen_helper_mtc0_wired(cpu_env, arg);
9238 register_name = "Wired";
9239 break;
9240 case 1:
9241 check_insn(ctx, ISA_MIPS32R2);
9242 gen_helper_mtc0_srsconf0(cpu_env, arg);
9243 register_name = "SRSConf0";
9244 break;
9245 case 2:
9246 check_insn(ctx, ISA_MIPS32R2);
9247 gen_helper_mtc0_srsconf1(cpu_env, arg);
9248 register_name = "SRSConf1";
9249 break;
9250 case 3:
9251 check_insn(ctx, ISA_MIPS32R2);
9252 gen_helper_mtc0_srsconf2(cpu_env, arg);
9253 register_name = "SRSConf2";
9254 break;
9255 case 4:
9256 check_insn(ctx, ISA_MIPS32R2);
9257 gen_helper_mtc0_srsconf3(cpu_env, arg);
9258 register_name = "SRSConf3";
9259 break;
9260 case 5:
9261 check_insn(ctx, ISA_MIPS32R2);
9262 gen_helper_mtc0_srsconf4(cpu_env, arg);
9263 register_name = "SRSConf4";
9264 break;
9265 case 6:
9266 check_pw(ctx);
9267 gen_helper_mtc0_pwctl(cpu_env, arg);
9268 register_name = "PWCtl";
9269 break;
9270 default:
9271 goto cp0_unimplemented;
9273 break;
9274 case CP0_REGISTER_07:
9275 switch (sel) {
9276 case 0:
9277 check_insn(ctx, ISA_MIPS32R2);
9278 gen_helper_mtc0_hwrena(cpu_env, arg);
9279 ctx->base.is_jmp = DISAS_STOP;
9280 register_name = "HWREna";
9281 break;
9282 default:
9283 goto cp0_unimplemented;
9285 break;
9286 case CP0_REGISTER_08:
9287 switch (sel) {
9288 case 0:
9289 /* ignored */
9290 register_name = "BadVAddr";
9291 break;
9292 case 1:
9293 /* ignored */
9294 register_name = "BadInstr";
9295 break;
9296 case 2:
9297 /* ignored */
9298 register_name = "BadInstrP";
9299 break;
9300 case 3:
9301 /* ignored */
9302 register_name = "BadInstrX";
9303 break;
9304 default:
9305 goto cp0_unimplemented;
9307 break;
9308 case CP0_REGISTER_09:
9309 switch (sel) {
9310 case 0:
9311 gen_helper_mtc0_count(cpu_env, arg);
9312 register_name = "Count";
9313 break;
9314 case 6:
9315 CP0_CHECK(ctx->saar);
9316 gen_helper_mtc0_saari(cpu_env, arg);
9317 register_name = "SAARI";
9318 break;
9319 case 7:
9320 CP0_CHECK(ctx->saar);
9321 gen_helper_mtc0_saar(cpu_env, arg);
9322 register_name = "SAAR";
9323 break;
9324 default:
9325 goto cp0_unimplemented;
9327 /* Stop translation as we may have switched the execution mode */
9328 ctx->base.is_jmp = DISAS_STOP;
9329 break;
9330 case CP0_REGISTER_10:
9331 switch (sel) {
9332 case 0:
9333 gen_helper_mtc0_entryhi(cpu_env, arg);
9334 register_name = "EntryHi";
9335 break;
9336 default:
9337 goto cp0_unimplemented;
9339 break;
9340 case CP0_REGISTER_11:
9341 switch (sel) {
9342 case 0:
9343 gen_helper_mtc0_compare(cpu_env, arg);
9344 register_name = "Compare";
9345 break;
9346 /* 6,7 are implementation dependent */
9347 default:
9348 goto cp0_unimplemented;
9350 /* Stop translation as we may have switched the execution mode */
9351 ctx->base.is_jmp = DISAS_STOP;
9352 break;
9353 case CP0_REGISTER_12:
9354 switch (sel) {
9355 case 0:
9356 save_cpu_state(ctx, 1);
9357 gen_helper_mtc0_status(cpu_env, arg);
9358 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9359 gen_save_pc(ctx->base.pc_next + 4);
9360 ctx->base.is_jmp = DISAS_EXIT;
9361 register_name = "Status";
9362 break;
9363 case 1:
9364 check_insn(ctx, ISA_MIPS32R2);
9365 gen_helper_mtc0_intctl(cpu_env, arg);
9366 /* Stop translation as we may have switched the execution mode */
9367 ctx->base.is_jmp = DISAS_STOP;
9368 register_name = "IntCtl";
9369 break;
9370 case 2:
9371 check_insn(ctx, ISA_MIPS32R2);
9372 gen_helper_mtc0_srsctl(cpu_env, arg);
9373 /* Stop translation as we may have switched the execution mode */
9374 ctx->base.is_jmp = DISAS_STOP;
9375 register_name = "SRSCtl";
9376 break;
9377 case 3:
9378 check_insn(ctx, ISA_MIPS32R2);
9379 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9380 /* Stop translation as we may have switched the execution mode */
9381 ctx->base.is_jmp = DISAS_STOP;
9382 register_name = "SRSMap";
9383 break;
9384 default:
9385 goto cp0_unimplemented;
9387 break;
9388 case CP0_REGISTER_13:
9389 switch (sel) {
9390 case 0:
9391 save_cpu_state(ctx, 1);
9392 gen_helper_mtc0_cause(cpu_env, arg);
9394 * Stop translation as we may have triggered an interrupt.
9395 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9396 * translated code to check for pending interrupts.
9398 gen_save_pc(ctx->base.pc_next + 4);
9399 ctx->base.is_jmp = DISAS_EXIT;
9400 register_name = "Cause";
9401 break;
9402 default:
9403 goto cp0_unimplemented;
9405 break;
9406 case CP0_REGISTER_14:
9407 switch (sel) {
9408 case 0:
9409 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9410 register_name = "EPC";
9411 break;
9412 default:
9413 goto cp0_unimplemented;
9415 break;
9416 case CP0_REGISTER_15:
9417 switch (sel) {
9418 case 0:
9419 /* ignored */
9420 register_name = "PRid";
9421 break;
9422 case 1:
9423 check_insn(ctx, ISA_MIPS32R2);
9424 gen_helper_mtc0_ebase(cpu_env, arg);
9425 register_name = "EBase";
9426 break;
9427 default:
9428 goto cp0_unimplemented;
9430 break;
9431 case CP0_REGISTER_16:
9432 switch (sel) {
9433 case 0:
9434 gen_helper_mtc0_config0(cpu_env, arg);
9435 register_name = "Config";
9436 /* Stop translation as we may have switched the execution mode */
9437 ctx->base.is_jmp = DISAS_STOP;
9438 break;
9439 case 1:
9440 /* ignored, read only */
9441 register_name = "Config1";
9442 break;
9443 case 2:
9444 gen_helper_mtc0_config2(cpu_env, arg);
9445 register_name = "Config2";
9446 /* Stop translation as we may have switched the execution mode */
9447 ctx->base.is_jmp = DISAS_STOP;
9448 break;
9449 case 3:
9450 gen_helper_mtc0_config3(cpu_env, arg);
9451 register_name = "Config3";
9452 /* Stop translation as we may have switched the execution mode */
9453 ctx->base.is_jmp = DISAS_STOP;
9454 break;
9455 case 4:
9456 /* currently ignored */
9457 register_name = "Config4";
9458 break;
9459 case 5:
9460 gen_helper_mtc0_config5(cpu_env, arg);
9461 register_name = "Config5";
9462 /* Stop translation as we may have switched the execution mode */
9463 ctx->base.is_jmp = DISAS_STOP;
9464 break;
9465 /* 6,7 are implementation dependent */
9466 default:
9467 register_name = "Invalid config selector";
9468 goto cp0_unimplemented;
9470 break;
9471 case CP0_REGISTER_17:
9472 switch (sel) {
9473 case 0:
9474 gen_helper_mtc0_lladdr(cpu_env, arg);
9475 register_name = "LLAddr";
9476 break;
9477 case 1:
9478 CP0_CHECK(ctx->mrp);
9479 gen_helper_mtc0_maar(cpu_env, arg);
9480 register_name = "MAAR";
9481 break;
9482 case 2:
9483 CP0_CHECK(ctx->mrp);
9484 gen_helper_mtc0_maari(cpu_env, arg);
9485 register_name = "MAARI";
9486 break;
9487 default:
9488 goto cp0_unimplemented;
9490 break;
9491 case CP0_REGISTER_18:
9492 switch (sel) {
9493 case 0:
9494 case 1:
9495 case 2:
9496 case 3:
9497 case 4:
9498 case 5:
9499 case 6:
9500 case 7:
9501 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9502 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9503 register_name = "WatchLo";
9504 break;
9505 default:
9506 goto cp0_unimplemented;
9508 break;
9509 case CP0_REGISTER_19:
9510 switch (sel) {
9511 case 0:
9512 case 1:
9513 case 2:
9514 case 3:
9515 case 4:
9516 case 5:
9517 case 6:
9518 case 7:
9519 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9520 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9521 register_name = "WatchHi";
9522 break;
9523 default:
9524 goto cp0_unimplemented;
9526 break;
9527 case CP0_REGISTER_20:
9528 switch (sel) {
9529 case 0:
9530 check_insn(ctx, ISA_MIPS3);
9531 gen_helper_mtc0_xcontext(cpu_env, arg);
9532 register_name = "XContext";
9533 break;
9534 default:
9535 goto cp0_unimplemented;
9537 break;
9538 case CP0_REGISTER_21:
9539 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9540 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9541 switch (sel) {
9542 case 0:
9543 gen_helper_mtc0_framemask(cpu_env, arg);
9544 register_name = "Framemask";
9545 break;
9546 default:
9547 goto cp0_unimplemented;
9549 break;
9550 case CP0_REGISTER_22:
9551 /* ignored */
9552 register_name = "Diagnostic"; /* implementation dependent */
9553 break;
9554 case CP0_REGISTER_23:
9555 switch (sel) {
9556 case 0:
9557 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9558 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9559 gen_save_pc(ctx->base.pc_next + 4);
9560 ctx->base.is_jmp = DISAS_EXIT;
9561 register_name = "Debug";
9562 break;
9563 case 1:
9564 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9565 /* Stop translation as we may have switched the execution mode */
9566 ctx->base.is_jmp = DISAS_STOP;
9567 register_name = "TraceControl";
9568 goto cp0_unimplemented;
9569 case 2:
9570 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9571 /* Stop translation as we may have switched the execution mode */
9572 ctx->base.is_jmp = DISAS_STOP;
9573 register_name = "TraceControl2";
9574 goto cp0_unimplemented;
9575 case 3:
9576 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9577 /* Stop translation as we may have switched the execution mode */
9578 ctx->base.is_jmp = DISAS_STOP;
9579 register_name = "UserTraceData";
9580 goto cp0_unimplemented;
9581 case 4:
9582 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9583 /* Stop translation as we may have switched the execution mode */
9584 ctx->base.is_jmp = DISAS_STOP;
9585 register_name = "TraceBPC";
9586 goto cp0_unimplemented;
9587 default:
9588 goto cp0_unimplemented;
9590 break;
9591 case CP0_REGISTER_24:
9592 switch (sel) {
9593 case 0:
9594 /* EJTAG support */
9595 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9596 register_name = "DEPC";
9597 break;
9598 default:
9599 goto cp0_unimplemented;
9601 break;
9602 case CP0_REGISTER_25:
9603 switch (sel) {
9604 case 0:
9605 gen_helper_mtc0_performance0(cpu_env, arg);
9606 register_name = "Performance0";
9607 break;
9608 case 1:
9609 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9610 register_name = "Performance1";
9611 goto cp0_unimplemented;
9612 case 2:
9613 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9614 register_name = "Performance2";
9615 goto cp0_unimplemented;
9616 case 3:
9617 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9618 register_name = "Performance3";
9619 goto cp0_unimplemented;
9620 case 4:
9621 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9622 register_name = "Performance4";
9623 goto cp0_unimplemented;
9624 case 5:
9625 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9626 register_name = "Performance5";
9627 goto cp0_unimplemented;
9628 case 6:
9629 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9630 register_name = "Performance6";
9631 goto cp0_unimplemented;
9632 case 7:
9633 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9634 register_name = "Performance7";
9635 goto cp0_unimplemented;
9636 default:
9637 goto cp0_unimplemented;
9639 break;
9640 case CP0_REGISTER_26:
9641 switch (sel) {
9642 case 0:
9643 gen_helper_mtc0_errctl(cpu_env, arg);
9644 ctx->base.is_jmp = DISAS_STOP;
9645 register_name = "ErrCtl";
9646 break;
9647 default:
9648 goto cp0_unimplemented;
9650 break;
9651 case CP0_REGISTER_27:
9652 switch (sel) {
9653 case 0:
9654 case 1:
9655 case 2:
9656 case 3:
9657 /* ignored */
9658 register_name = "CacheErr";
9659 break;
9660 default:
9661 goto cp0_unimplemented;
9663 break;
9664 case CP0_REGISTER_28:
9665 switch (sel) {
9666 case 0:
9667 case 2:
9668 case 4:
9669 case 6:
9670 gen_helper_mtc0_taglo(cpu_env, arg);
9671 register_name = "TagLo";
9672 break;
9673 case 1:
9674 case 3:
9675 case 5:
9676 case 7:
9677 gen_helper_mtc0_datalo(cpu_env, arg);
9678 register_name = "DataLo";
9679 break;
9680 default:
9681 goto cp0_unimplemented;
9683 break;
9684 case CP0_REGISTER_29:
9685 switch (sel) {
9686 case 0:
9687 case 2:
9688 case 4:
9689 case 6:
9690 gen_helper_mtc0_taghi(cpu_env, arg);
9691 register_name = "TagHi";
9692 break;
9693 case 1:
9694 case 3:
9695 case 5:
9696 case 7:
9697 gen_helper_mtc0_datahi(cpu_env, arg);
9698 register_name = "DataHi";
9699 break;
9700 default:
9701 register_name = "invalid sel";
9702 goto cp0_unimplemented;
9704 break;
9705 case CP0_REGISTER_30:
9706 switch (sel) {
9707 case 0:
9708 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9709 register_name = "ErrorEPC";
9710 break;
9711 default:
9712 goto cp0_unimplemented;
9714 break;
9715 case CP0_REGISTER_31:
9716 switch (sel) {
9717 case 0:
9718 /* EJTAG support */
9719 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9720 register_name = "DESAVE";
9721 break;
9722 case 2:
9723 case 3:
9724 case 4:
9725 case 5:
9726 case 6:
9727 case 7:
9728 CP0_CHECK(ctx->kscrexist & (1 << sel));
9729 tcg_gen_st_tl(arg, cpu_env,
9730 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9731 register_name = "KScratch";
9732 break;
9733 default:
9734 goto cp0_unimplemented;
9736 break;
9737 default:
9738 goto cp0_unimplemented;
9740 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9742 /* For simplicity assume that all writes can cause interrupts. */
9743 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9745 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9746 * translated code to check for pending interrupts.
9748 gen_save_pc(ctx->base.pc_next + 4);
9749 ctx->base.is_jmp = DISAS_EXIT;
9751 return;
9753 cp0_unimplemented:
9754 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9755 register_name, reg, sel);
9757 #endif /* TARGET_MIPS64 */
9759 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9760 int u, int sel, int h)
9762 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9763 TCGv t0 = tcg_temp_local_new();
9765 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9766 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9767 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9768 tcg_gen_movi_tl(t0, -1);
9769 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9770 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9771 tcg_gen_movi_tl(t0, -1);
9772 } else if (u == 0) {
9773 switch (rt) {
9774 case 1:
9775 switch (sel) {
9776 case 1:
9777 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9778 break;
9779 case 2:
9780 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9781 break;
9782 default:
9783 goto die;
9784 break;
9786 break;
9787 case 2:
9788 switch (sel) {
9789 case 1:
9790 gen_helper_mftc0_tcstatus(t0, cpu_env);
9791 break;
9792 case 2:
9793 gen_helper_mftc0_tcbind(t0, cpu_env);
9794 break;
9795 case 3:
9796 gen_helper_mftc0_tcrestart(t0, cpu_env);
9797 break;
9798 case 4:
9799 gen_helper_mftc0_tchalt(t0, cpu_env);
9800 break;
9801 case 5:
9802 gen_helper_mftc0_tccontext(t0, cpu_env);
9803 break;
9804 case 6:
9805 gen_helper_mftc0_tcschedule(t0, cpu_env);
9806 break;
9807 case 7:
9808 gen_helper_mftc0_tcschefback(t0, cpu_env);
9809 break;
9810 default:
9811 gen_mfc0(ctx, t0, rt, sel);
9812 break;
9814 break;
9815 case 10:
9816 switch (sel) {
9817 case 0:
9818 gen_helper_mftc0_entryhi(t0, cpu_env);
9819 break;
9820 default:
9821 gen_mfc0(ctx, t0, rt, sel);
9822 break;
9824 break;
9825 case 12:
9826 switch (sel) {
9827 case 0:
9828 gen_helper_mftc0_status(t0, cpu_env);
9829 break;
9830 default:
9831 gen_mfc0(ctx, t0, rt, sel);
9832 break;
9834 break;
9835 case 13:
9836 switch (sel) {
9837 case 0:
9838 gen_helper_mftc0_cause(t0, cpu_env);
9839 break;
9840 default:
9841 goto die;
9842 break;
9844 break;
9845 case 14:
9846 switch (sel) {
9847 case 0:
9848 gen_helper_mftc0_epc(t0, cpu_env);
9849 break;
9850 default:
9851 goto die;
9852 break;
9854 break;
9855 case 15:
9856 switch (sel) {
9857 case 1:
9858 gen_helper_mftc0_ebase(t0, cpu_env);
9859 break;
9860 default:
9861 goto die;
9862 break;
9864 break;
9865 case 16:
9866 switch (sel) {
9867 case 0:
9868 case 1:
9869 case 2:
9870 case 3:
9871 case 4:
9872 case 5:
9873 case 6:
9874 case 7:
9875 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9876 break;
9877 default:
9878 goto die;
9879 break;
9881 break;
9882 case 23:
9883 switch (sel) {
9884 case 0:
9885 gen_helper_mftc0_debug(t0, cpu_env);
9886 break;
9887 default:
9888 gen_mfc0(ctx, t0, rt, sel);
9889 break;
9891 break;
9892 default:
9893 gen_mfc0(ctx, t0, rt, sel);
9895 } else {
9896 switch (sel) {
9897 /* GPR registers. */
9898 case 0:
9899 gen_helper_1e0i(mftgpr, t0, rt);
9900 break;
9901 /* Auxiliary CPU registers */
9902 case 1:
9903 switch (rt) {
9904 case 0:
9905 gen_helper_1e0i(mftlo, t0, 0);
9906 break;
9907 case 1:
9908 gen_helper_1e0i(mfthi, t0, 0);
9909 break;
9910 case 2:
9911 gen_helper_1e0i(mftacx, t0, 0);
9912 break;
9913 case 4:
9914 gen_helper_1e0i(mftlo, t0, 1);
9915 break;
9916 case 5:
9917 gen_helper_1e0i(mfthi, t0, 1);
9918 break;
9919 case 6:
9920 gen_helper_1e0i(mftacx, t0, 1);
9921 break;
9922 case 8:
9923 gen_helper_1e0i(mftlo, t0, 2);
9924 break;
9925 case 9:
9926 gen_helper_1e0i(mfthi, t0, 2);
9927 break;
9928 case 10:
9929 gen_helper_1e0i(mftacx, t0, 2);
9930 break;
9931 case 12:
9932 gen_helper_1e0i(mftlo, t0, 3);
9933 break;
9934 case 13:
9935 gen_helper_1e0i(mfthi, t0, 3);
9936 break;
9937 case 14:
9938 gen_helper_1e0i(mftacx, t0, 3);
9939 break;
9940 case 16:
9941 gen_helper_mftdsp(t0, cpu_env);
9942 break;
9943 default:
9944 goto die;
9946 break;
9947 /* Floating point (COP1). */
9948 case 2:
9949 /* XXX: For now we support only a single FPU context. */
9950 if (h == 0) {
9951 TCGv_i32 fp0 = tcg_temp_new_i32();
9953 gen_load_fpr32(ctx, fp0, rt);
9954 tcg_gen_ext_i32_tl(t0, fp0);
9955 tcg_temp_free_i32(fp0);
9956 } else {
9957 TCGv_i32 fp0 = tcg_temp_new_i32();
9959 gen_load_fpr32h(ctx, fp0, rt);
9960 tcg_gen_ext_i32_tl(t0, fp0);
9961 tcg_temp_free_i32(fp0);
9963 break;
9964 case 3:
9965 /* XXX: For now we support only a single FPU context. */
9966 gen_helper_1e0i(cfc1, t0, rt);
9967 break;
9968 /* COP2: Not implemented. */
9969 case 4:
9970 case 5:
9971 /* fall through */
9972 default:
9973 goto die;
9976 trace_mips_translate_tr("mftr", rt, u, sel, h);
9977 gen_store_gpr(t0, rd);
9978 tcg_temp_free(t0);
9979 return;
9981 die:
9982 tcg_temp_free(t0);
9983 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9984 generate_exception_end(ctx, EXCP_RI);
9987 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9988 int u, int sel, int h)
9990 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9991 TCGv t0 = tcg_temp_local_new();
9993 gen_load_gpr(t0, rt);
9994 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9995 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9996 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9997 /* NOP */
9999 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10000 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10001 /* NOP */
10003 } else if (u == 0) {
10004 switch (rd) {
10005 case 1:
10006 switch (sel) {
10007 case 1:
10008 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10009 break;
10010 case 2:
10011 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10012 break;
10013 default:
10014 goto die;
10015 break;
10017 break;
10018 case 2:
10019 switch (sel) {
10020 case 1:
10021 gen_helper_mttc0_tcstatus(cpu_env, t0);
10022 break;
10023 case 2:
10024 gen_helper_mttc0_tcbind(cpu_env, t0);
10025 break;
10026 case 3:
10027 gen_helper_mttc0_tcrestart(cpu_env, t0);
10028 break;
10029 case 4:
10030 gen_helper_mttc0_tchalt(cpu_env, t0);
10031 break;
10032 case 5:
10033 gen_helper_mttc0_tccontext(cpu_env, t0);
10034 break;
10035 case 6:
10036 gen_helper_mttc0_tcschedule(cpu_env, t0);
10037 break;
10038 case 7:
10039 gen_helper_mttc0_tcschefback(cpu_env, t0);
10040 break;
10041 default:
10042 gen_mtc0(ctx, t0, rd, sel);
10043 break;
10045 break;
10046 case 10:
10047 switch (sel) {
10048 case 0:
10049 gen_helper_mttc0_entryhi(cpu_env, t0);
10050 break;
10051 default:
10052 gen_mtc0(ctx, t0, rd, sel);
10053 break;
10055 break;
10056 case 12:
10057 switch (sel) {
10058 case 0:
10059 gen_helper_mttc0_status(cpu_env, t0);
10060 break;
10061 default:
10062 gen_mtc0(ctx, t0, rd, sel);
10063 break;
10065 break;
10066 case 13:
10067 switch (sel) {
10068 case 0:
10069 gen_helper_mttc0_cause(cpu_env, t0);
10070 break;
10071 default:
10072 goto die;
10073 break;
10075 break;
10076 case 15:
10077 switch (sel) {
10078 case 1:
10079 gen_helper_mttc0_ebase(cpu_env, t0);
10080 break;
10081 default:
10082 goto die;
10083 break;
10085 break;
10086 case 23:
10087 switch (sel) {
10088 case 0:
10089 gen_helper_mttc0_debug(cpu_env, t0);
10090 break;
10091 default:
10092 gen_mtc0(ctx, t0, rd, sel);
10093 break;
10095 break;
10096 default:
10097 gen_mtc0(ctx, t0, rd, sel);
10099 } else {
10100 switch (sel) {
10101 /* GPR registers. */
10102 case 0:
10103 gen_helper_0e1i(mttgpr, t0, rd);
10104 break;
10105 /* Auxiliary CPU registers */
10106 case 1:
10107 switch (rd) {
10108 case 0:
10109 gen_helper_0e1i(mttlo, t0, 0);
10110 break;
10111 case 1:
10112 gen_helper_0e1i(mtthi, t0, 0);
10113 break;
10114 case 2:
10115 gen_helper_0e1i(mttacx, t0, 0);
10116 break;
10117 case 4:
10118 gen_helper_0e1i(mttlo, t0, 1);
10119 break;
10120 case 5:
10121 gen_helper_0e1i(mtthi, t0, 1);
10122 break;
10123 case 6:
10124 gen_helper_0e1i(mttacx, t0, 1);
10125 break;
10126 case 8:
10127 gen_helper_0e1i(mttlo, t0, 2);
10128 break;
10129 case 9:
10130 gen_helper_0e1i(mtthi, t0, 2);
10131 break;
10132 case 10:
10133 gen_helper_0e1i(mttacx, t0, 2);
10134 break;
10135 case 12:
10136 gen_helper_0e1i(mttlo, t0, 3);
10137 break;
10138 case 13:
10139 gen_helper_0e1i(mtthi, t0, 3);
10140 break;
10141 case 14:
10142 gen_helper_0e1i(mttacx, t0, 3);
10143 break;
10144 case 16:
10145 gen_helper_mttdsp(cpu_env, t0);
10146 break;
10147 default:
10148 goto die;
10150 break;
10151 /* Floating point (COP1). */
10152 case 2:
10153 /* XXX: For now we support only a single FPU context. */
10154 if (h == 0) {
10155 TCGv_i32 fp0 = tcg_temp_new_i32();
10157 tcg_gen_trunc_tl_i32(fp0, t0);
10158 gen_store_fpr32(ctx, fp0, rd);
10159 tcg_temp_free_i32(fp0);
10160 } else {
10161 TCGv_i32 fp0 = tcg_temp_new_i32();
10163 tcg_gen_trunc_tl_i32(fp0, t0);
10164 gen_store_fpr32h(ctx, fp0, rd);
10165 tcg_temp_free_i32(fp0);
10167 break;
10168 case 3:
10169 /* XXX: For now we support only a single FPU context. */
10171 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10173 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10174 tcg_temp_free_i32(fs_tmp);
10176 /* Stop translation as we may have changed hflags */
10177 ctx->base.is_jmp = DISAS_STOP;
10178 break;
10179 /* COP2: Not implemented. */
10180 case 4:
10181 case 5:
10182 /* fall through */
10183 default:
10184 goto die;
10187 trace_mips_translate_tr("mttr", rd, u, sel, h);
10188 tcg_temp_free(t0);
10189 return;
10191 die:
10192 tcg_temp_free(t0);
10193 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10194 generate_exception_end(ctx, EXCP_RI);
10197 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10198 int rt, int rd)
10200 const char *opn = "ldst";
10202 check_cp0_enabled(ctx);
10203 switch (opc) {
10204 case OPC_MFC0:
10205 if (rt == 0) {
10206 /* Treat as NOP. */
10207 return;
10209 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10210 opn = "mfc0";
10211 break;
10212 case OPC_MTC0:
10214 TCGv t0 = tcg_temp_new();
10216 gen_load_gpr(t0, rt);
10217 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10218 tcg_temp_free(t0);
10220 opn = "mtc0";
10221 break;
10222 #if defined(TARGET_MIPS64)
10223 case OPC_DMFC0:
10224 check_insn(ctx, ISA_MIPS3);
10225 if (rt == 0) {
10226 /* Treat as NOP. */
10227 return;
10229 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10230 opn = "dmfc0";
10231 break;
10232 case OPC_DMTC0:
10233 check_insn(ctx, ISA_MIPS3);
10235 TCGv t0 = tcg_temp_new();
10237 gen_load_gpr(t0, rt);
10238 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10239 tcg_temp_free(t0);
10241 opn = "dmtc0";
10242 break;
10243 #endif
10244 case OPC_MFHC0:
10245 check_mvh(ctx);
10246 if (rt == 0) {
10247 /* Treat as NOP. */
10248 return;
10250 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10251 opn = "mfhc0";
10252 break;
10253 case OPC_MTHC0:
10254 check_mvh(ctx);
10256 TCGv t0 = tcg_temp_new();
10257 gen_load_gpr(t0, rt);
10258 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10259 tcg_temp_free(t0);
10261 opn = "mthc0";
10262 break;
10263 case OPC_MFTR:
10264 check_cp0_enabled(ctx);
10265 if (rd == 0) {
10266 /* Treat as NOP. */
10267 return;
10269 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10270 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10271 opn = "mftr";
10272 break;
10273 case OPC_MTTR:
10274 check_cp0_enabled(ctx);
10275 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10276 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10277 opn = "mttr";
10278 break;
10279 case OPC_TLBWI:
10280 opn = "tlbwi";
10281 if (!env->tlb->helper_tlbwi) {
10282 goto die;
10284 gen_helper_tlbwi(cpu_env);
10285 break;
10286 case OPC_TLBINV:
10287 opn = "tlbinv";
10288 if (ctx->ie >= 2) {
10289 if (!env->tlb->helper_tlbinv) {
10290 goto die;
10292 gen_helper_tlbinv(cpu_env);
10293 } /* treat as nop if TLBINV not supported */
10294 break;
10295 case OPC_TLBINVF:
10296 opn = "tlbinvf";
10297 if (ctx->ie >= 2) {
10298 if (!env->tlb->helper_tlbinvf) {
10299 goto die;
10301 gen_helper_tlbinvf(cpu_env);
10302 } /* treat as nop if TLBINV not supported */
10303 break;
10304 case OPC_TLBWR:
10305 opn = "tlbwr";
10306 if (!env->tlb->helper_tlbwr) {
10307 goto die;
10309 gen_helper_tlbwr(cpu_env);
10310 break;
10311 case OPC_TLBP:
10312 opn = "tlbp";
10313 if (!env->tlb->helper_tlbp) {
10314 goto die;
10316 gen_helper_tlbp(cpu_env);
10317 break;
10318 case OPC_TLBR:
10319 opn = "tlbr";
10320 if (!env->tlb->helper_tlbr) {
10321 goto die;
10323 gen_helper_tlbr(cpu_env);
10324 break;
10325 case OPC_ERET: /* OPC_ERETNC */
10326 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10327 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10328 goto die;
10329 } else {
10330 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10331 if (ctx->opcode & (1 << bit_shift)) {
10332 /* OPC_ERETNC */
10333 opn = "eretnc";
10334 check_insn(ctx, ISA_MIPS32R5);
10335 gen_helper_eretnc(cpu_env);
10336 } else {
10337 /* OPC_ERET */
10338 opn = "eret";
10339 check_insn(ctx, ISA_MIPS2);
10340 gen_helper_eret(cpu_env);
10342 ctx->base.is_jmp = DISAS_EXIT;
10344 break;
10345 case OPC_DERET:
10346 opn = "deret";
10347 check_insn(ctx, ISA_MIPS32);
10348 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10349 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10350 goto die;
10352 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10353 MIPS_INVAL(opn);
10354 generate_exception_end(ctx, EXCP_RI);
10355 } else {
10356 gen_helper_deret(cpu_env);
10357 ctx->base.is_jmp = DISAS_EXIT;
10359 break;
10360 case OPC_WAIT:
10361 opn = "wait";
10362 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10363 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10364 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10365 goto die;
10367 /* If we get an exception, we want to restart at next instruction */
10368 ctx->base.pc_next += 4;
10369 save_cpu_state(ctx, 1);
10370 ctx->base.pc_next -= 4;
10371 gen_helper_wait(cpu_env);
10372 ctx->base.is_jmp = DISAS_NORETURN;
10373 break;
10374 default:
10375 die:
10376 MIPS_INVAL(opn);
10377 generate_exception_end(ctx, EXCP_RI);
10378 return;
10380 (void)opn; /* avoid a compiler warning */
10382 #endif /* !CONFIG_USER_ONLY */
10384 /* CP1 Branches (before delay slot) */
10385 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10386 int32_t cc, int32_t offset)
10388 target_ulong btarget;
10389 TCGv_i32 t0 = tcg_temp_new_i32();
10391 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10392 generate_exception_end(ctx, EXCP_RI);
10393 goto out;
10396 if (cc != 0) {
10397 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10400 btarget = ctx->base.pc_next + 4 + offset;
10402 switch (op) {
10403 case OPC_BC1F:
10404 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10405 tcg_gen_not_i32(t0, t0);
10406 tcg_gen_andi_i32(t0, t0, 1);
10407 tcg_gen_extu_i32_tl(bcond, t0);
10408 goto not_likely;
10409 case OPC_BC1FL:
10410 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10411 tcg_gen_not_i32(t0, t0);
10412 tcg_gen_andi_i32(t0, t0, 1);
10413 tcg_gen_extu_i32_tl(bcond, t0);
10414 goto likely;
10415 case OPC_BC1T:
10416 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10417 tcg_gen_andi_i32(t0, t0, 1);
10418 tcg_gen_extu_i32_tl(bcond, t0);
10419 goto not_likely;
10420 case OPC_BC1TL:
10421 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10422 tcg_gen_andi_i32(t0, t0, 1);
10423 tcg_gen_extu_i32_tl(bcond, t0);
10424 likely:
10425 ctx->hflags |= MIPS_HFLAG_BL;
10426 break;
10427 case OPC_BC1FANY2:
10429 TCGv_i32 t1 = tcg_temp_new_i32();
10430 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10431 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10432 tcg_gen_nand_i32(t0, t0, t1);
10433 tcg_temp_free_i32(t1);
10434 tcg_gen_andi_i32(t0, t0, 1);
10435 tcg_gen_extu_i32_tl(bcond, t0);
10437 goto not_likely;
10438 case OPC_BC1TANY2:
10440 TCGv_i32 t1 = tcg_temp_new_i32();
10441 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10442 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10443 tcg_gen_or_i32(t0, t0, t1);
10444 tcg_temp_free_i32(t1);
10445 tcg_gen_andi_i32(t0, t0, 1);
10446 tcg_gen_extu_i32_tl(bcond, t0);
10448 goto not_likely;
10449 case OPC_BC1FANY4:
10451 TCGv_i32 t1 = tcg_temp_new_i32();
10452 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10453 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10454 tcg_gen_and_i32(t0, t0, t1);
10455 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10456 tcg_gen_and_i32(t0, t0, t1);
10457 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10458 tcg_gen_nand_i32(t0, t0, t1);
10459 tcg_temp_free_i32(t1);
10460 tcg_gen_andi_i32(t0, t0, 1);
10461 tcg_gen_extu_i32_tl(bcond, t0);
10463 goto not_likely;
10464 case OPC_BC1TANY4:
10466 TCGv_i32 t1 = tcg_temp_new_i32();
10467 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10468 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10469 tcg_gen_or_i32(t0, t0, t1);
10470 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10471 tcg_gen_or_i32(t0, t0, t1);
10472 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10473 tcg_gen_or_i32(t0, t0, t1);
10474 tcg_temp_free_i32(t1);
10475 tcg_gen_andi_i32(t0, t0, 1);
10476 tcg_gen_extu_i32_tl(bcond, t0);
10478 not_likely:
10479 ctx->hflags |= MIPS_HFLAG_BC;
10480 break;
10481 default:
10482 MIPS_INVAL("cp1 cond branch");
10483 generate_exception_end(ctx, EXCP_RI);
10484 goto out;
10486 ctx->btarget = btarget;
10487 ctx->hflags |= MIPS_HFLAG_BDS32;
10488 out:
10489 tcg_temp_free_i32(t0);
10492 /* R6 CP1 Branches */
10493 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10494 int32_t ft, int32_t offset,
10495 int delayslot_size)
10497 target_ulong btarget;
10498 TCGv_i64 t0 = tcg_temp_new_i64();
10500 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10501 #ifdef MIPS_DEBUG_DISAS
10502 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10503 "\n", ctx->base.pc_next);
10504 #endif
10505 generate_exception_end(ctx, EXCP_RI);
10506 goto out;
10509 gen_load_fpr64(ctx, t0, ft);
10510 tcg_gen_andi_i64(t0, t0, 1);
10512 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10514 switch (op) {
10515 case OPC_BC1EQZ:
10516 tcg_gen_xori_i64(t0, t0, 1);
10517 ctx->hflags |= MIPS_HFLAG_BC;
10518 break;
10519 case OPC_BC1NEZ:
10520 /* t0 already set */
10521 ctx->hflags |= MIPS_HFLAG_BC;
10522 break;
10523 default:
10524 MIPS_INVAL("cp1 cond branch");
10525 generate_exception_end(ctx, EXCP_RI);
10526 goto out;
10529 tcg_gen_trunc_i64_tl(bcond, t0);
10531 ctx->btarget = btarget;
10533 switch (delayslot_size) {
10534 case 2:
10535 ctx->hflags |= MIPS_HFLAG_BDS16;
10536 break;
10537 case 4:
10538 ctx->hflags |= MIPS_HFLAG_BDS32;
10539 break;
10542 out:
10543 tcg_temp_free_i64(t0);
10546 /* Coprocessor 1 (FPU) */
10548 #define FOP(func, fmt) (((fmt) << 21) | (func))
10550 enum fopcode {
10551 OPC_ADD_S = FOP(0, FMT_S),
10552 OPC_SUB_S = FOP(1, FMT_S),
10553 OPC_MUL_S = FOP(2, FMT_S),
10554 OPC_DIV_S = FOP(3, FMT_S),
10555 OPC_SQRT_S = FOP(4, FMT_S),
10556 OPC_ABS_S = FOP(5, FMT_S),
10557 OPC_MOV_S = FOP(6, FMT_S),
10558 OPC_NEG_S = FOP(7, FMT_S),
10559 OPC_ROUND_L_S = FOP(8, FMT_S),
10560 OPC_TRUNC_L_S = FOP(9, FMT_S),
10561 OPC_CEIL_L_S = FOP(10, FMT_S),
10562 OPC_FLOOR_L_S = FOP(11, FMT_S),
10563 OPC_ROUND_W_S = FOP(12, FMT_S),
10564 OPC_TRUNC_W_S = FOP(13, FMT_S),
10565 OPC_CEIL_W_S = FOP(14, FMT_S),
10566 OPC_FLOOR_W_S = FOP(15, FMT_S),
10567 OPC_SEL_S = FOP(16, FMT_S),
10568 OPC_MOVCF_S = FOP(17, FMT_S),
10569 OPC_MOVZ_S = FOP(18, FMT_S),
10570 OPC_MOVN_S = FOP(19, FMT_S),
10571 OPC_SELEQZ_S = FOP(20, FMT_S),
10572 OPC_RECIP_S = FOP(21, FMT_S),
10573 OPC_RSQRT_S = FOP(22, FMT_S),
10574 OPC_SELNEZ_S = FOP(23, FMT_S),
10575 OPC_MADDF_S = FOP(24, FMT_S),
10576 OPC_MSUBF_S = FOP(25, FMT_S),
10577 OPC_RINT_S = FOP(26, FMT_S),
10578 OPC_CLASS_S = FOP(27, FMT_S),
10579 OPC_MIN_S = FOP(28, FMT_S),
10580 OPC_RECIP2_S = FOP(28, FMT_S),
10581 OPC_MINA_S = FOP(29, FMT_S),
10582 OPC_RECIP1_S = FOP(29, FMT_S),
10583 OPC_MAX_S = FOP(30, FMT_S),
10584 OPC_RSQRT1_S = FOP(30, FMT_S),
10585 OPC_MAXA_S = FOP(31, FMT_S),
10586 OPC_RSQRT2_S = FOP(31, FMT_S),
10587 OPC_CVT_D_S = FOP(33, FMT_S),
10588 OPC_CVT_W_S = FOP(36, FMT_S),
10589 OPC_CVT_L_S = FOP(37, FMT_S),
10590 OPC_CVT_PS_S = FOP(38, FMT_S),
10591 OPC_CMP_F_S = FOP(48, FMT_S),
10592 OPC_CMP_UN_S = FOP(49, FMT_S),
10593 OPC_CMP_EQ_S = FOP(50, FMT_S),
10594 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10595 OPC_CMP_OLT_S = FOP(52, FMT_S),
10596 OPC_CMP_ULT_S = FOP(53, FMT_S),
10597 OPC_CMP_OLE_S = FOP(54, FMT_S),
10598 OPC_CMP_ULE_S = FOP(55, FMT_S),
10599 OPC_CMP_SF_S = FOP(56, FMT_S),
10600 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10601 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10602 OPC_CMP_NGL_S = FOP(59, FMT_S),
10603 OPC_CMP_LT_S = FOP(60, FMT_S),
10604 OPC_CMP_NGE_S = FOP(61, FMT_S),
10605 OPC_CMP_LE_S = FOP(62, FMT_S),
10606 OPC_CMP_NGT_S = FOP(63, FMT_S),
10608 OPC_ADD_D = FOP(0, FMT_D),
10609 OPC_SUB_D = FOP(1, FMT_D),
10610 OPC_MUL_D = FOP(2, FMT_D),
10611 OPC_DIV_D = FOP(3, FMT_D),
10612 OPC_SQRT_D = FOP(4, FMT_D),
10613 OPC_ABS_D = FOP(5, FMT_D),
10614 OPC_MOV_D = FOP(6, FMT_D),
10615 OPC_NEG_D = FOP(7, FMT_D),
10616 OPC_ROUND_L_D = FOP(8, FMT_D),
10617 OPC_TRUNC_L_D = FOP(9, FMT_D),
10618 OPC_CEIL_L_D = FOP(10, FMT_D),
10619 OPC_FLOOR_L_D = FOP(11, FMT_D),
10620 OPC_ROUND_W_D = FOP(12, FMT_D),
10621 OPC_TRUNC_W_D = FOP(13, FMT_D),
10622 OPC_CEIL_W_D = FOP(14, FMT_D),
10623 OPC_FLOOR_W_D = FOP(15, FMT_D),
10624 OPC_SEL_D = FOP(16, FMT_D),
10625 OPC_MOVCF_D = FOP(17, FMT_D),
10626 OPC_MOVZ_D = FOP(18, FMT_D),
10627 OPC_MOVN_D = FOP(19, FMT_D),
10628 OPC_SELEQZ_D = FOP(20, FMT_D),
10629 OPC_RECIP_D = FOP(21, FMT_D),
10630 OPC_RSQRT_D = FOP(22, FMT_D),
10631 OPC_SELNEZ_D = FOP(23, FMT_D),
10632 OPC_MADDF_D = FOP(24, FMT_D),
10633 OPC_MSUBF_D = FOP(25, FMT_D),
10634 OPC_RINT_D = FOP(26, FMT_D),
10635 OPC_CLASS_D = FOP(27, FMT_D),
10636 OPC_MIN_D = FOP(28, FMT_D),
10637 OPC_RECIP2_D = FOP(28, FMT_D),
10638 OPC_MINA_D = FOP(29, FMT_D),
10639 OPC_RECIP1_D = FOP(29, FMT_D),
10640 OPC_MAX_D = FOP(30, FMT_D),
10641 OPC_RSQRT1_D = FOP(30, FMT_D),
10642 OPC_MAXA_D = FOP(31, FMT_D),
10643 OPC_RSQRT2_D = FOP(31, FMT_D),
10644 OPC_CVT_S_D = FOP(32, FMT_D),
10645 OPC_CVT_W_D = FOP(36, FMT_D),
10646 OPC_CVT_L_D = FOP(37, FMT_D),
10647 OPC_CMP_F_D = FOP(48, FMT_D),
10648 OPC_CMP_UN_D = FOP(49, FMT_D),
10649 OPC_CMP_EQ_D = FOP(50, FMT_D),
10650 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10651 OPC_CMP_OLT_D = FOP(52, FMT_D),
10652 OPC_CMP_ULT_D = FOP(53, FMT_D),
10653 OPC_CMP_OLE_D = FOP(54, FMT_D),
10654 OPC_CMP_ULE_D = FOP(55, FMT_D),
10655 OPC_CMP_SF_D = FOP(56, FMT_D),
10656 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10657 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10658 OPC_CMP_NGL_D = FOP(59, FMT_D),
10659 OPC_CMP_LT_D = FOP(60, FMT_D),
10660 OPC_CMP_NGE_D = FOP(61, FMT_D),
10661 OPC_CMP_LE_D = FOP(62, FMT_D),
10662 OPC_CMP_NGT_D = FOP(63, FMT_D),
10664 OPC_CVT_S_W = FOP(32, FMT_W),
10665 OPC_CVT_D_W = FOP(33, FMT_W),
10666 OPC_CVT_S_L = FOP(32, FMT_L),
10667 OPC_CVT_D_L = FOP(33, FMT_L),
10668 OPC_CVT_PS_PW = FOP(38, FMT_W),
10670 OPC_ADD_PS = FOP(0, FMT_PS),
10671 OPC_SUB_PS = FOP(1, FMT_PS),
10672 OPC_MUL_PS = FOP(2, FMT_PS),
10673 OPC_DIV_PS = FOP(3, FMT_PS),
10674 OPC_ABS_PS = FOP(5, FMT_PS),
10675 OPC_MOV_PS = FOP(6, FMT_PS),
10676 OPC_NEG_PS = FOP(7, FMT_PS),
10677 OPC_MOVCF_PS = FOP(17, FMT_PS),
10678 OPC_MOVZ_PS = FOP(18, FMT_PS),
10679 OPC_MOVN_PS = FOP(19, FMT_PS),
10680 OPC_ADDR_PS = FOP(24, FMT_PS),
10681 OPC_MULR_PS = FOP(26, FMT_PS),
10682 OPC_RECIP2_PS = FOP(28, FMT_PS),
10683 OPC_RECIP1_PS = FOP(29, FMT_PS),
10684 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10685 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10687 OPC_CVT_S_PU = FOP(32, FMT_PS),
10688 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10689 OPC_CVT_S_PL = FOP(40, FMT_PS),
10690 OPC_PLL_PS = FOP(44, FMT_PS),
10691 OPC_PLU_PS = FOP(45, FMT_PS),
10692 OPC_PUL_PS = FOP(46, FMT_PS),
10693 OPC_PUU_PS = FOP(47, FMT_PS),
10694 OPC_CMP_F_PS = FOP(48, FMT_PS),
10695 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10696 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10697 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10698 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10699 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10700 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10701 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10702 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10703 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10704 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10705 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10706 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10707 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10708 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10709 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10712 enum r6_f_cmp_op {
10713 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10714 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10715 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10716 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10717 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10718 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10719 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10720 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10721 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10722 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10723 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10724 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10725 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10726 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10727 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10728 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10729 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10730 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10731 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10732 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10733 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10734 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10736 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10737 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10738 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10739 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10740 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10741 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10742 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10743 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10744 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10745 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10746 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10747 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10748 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10749 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10750 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10751 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10752 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10753 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10754 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10755 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10756 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10757 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10760 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10762 TCGv t0 = tcg_temp_new();
10764 switch (opc) {
10765 case OPC_MFC1:
10767 TCGv_i32 fp0 = tcg_temp_new_i32();
10769 gen_load_fpr32(ctx, fp0, fs);
10770 tcg_gen_ext_i32_tl(t0, fp0);
10771 tcg_temp_free_i32(fp0);
10773 gen_store_gpr(t0, rt);
10774 break;
10775 case OPC_MTC1:
10776 gen_load_gpr(t0, rt);
10778 TCGv_i32 fp0 = tcg_temp_new_i32();
10780 tcg_gen_trunc_tl_i32(fp0, t0);
10781 gen_store_fpr32(ctx, fp0, fs);
10782 tcg_temp_free_i32(fp0);
10784 break;
10785 case OPC_CFC1:
10786 gen_helper_1e0i(cfc1, t0, fs);
10787 gen_store_gpr(t0, rt);
10788 break;
10789 case OPC_CTC1:
10790 gen_load_gpr(t0, rt);
10791 save_cpu_state(ctx, 0);
10793 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10795 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10796 tcg_temp_free_i32(fs_tmp);
10798 /* Stop translation as we may have changed hflags */
10799 ctx->base.is_jmp = DISAS_STOP;
10800 break;
10801 #if defined(TARGET_MIPS64)
10802 case OPC_DMFC1:
10803 gen_load_fpr64(ctx, t0, fs);
10804 gen_store_gpr(t0, rt);
10805 break;
10806 case OPC_DMTC1:
10807 gen_load_gpr(t0, rt);
10808 gen_store_fpr64(ctx, t0, fs);
10809 break;
10810 #endif
10811 case OPC_MFHC1:
10813 TCGv_i32 fp0 = tcg_temp_new_i32();
10815 gen_load_fpr32h(ctx, fp0, fs);
10816 tcg_gen_ext_i32_tl(t0, fp0);
10817 tcg_temp_free_i32(fp0);
10819 gen_store_gpr(t0, rt);
10820 break;
10821 case OPC_MTHC1:
10822 gen_load_gpr(t0, rt);
10824 TCGv_i32 fp0 = tcg_temp_new_i32();
10826 tcg_gen_trunc_tl_i32(fp0, t0);
10827 gen_store_fpr32h(ctx, fp0, fs);
10828 tcg_temp_free_i32(fp0);
10830 break;
10831 default:
10832 MIPS_INVAL("cp1 move");
10833 generate_exception_end(ctx, EXCP_RI);
10834 goto out;
10837 out:
10838 tcg_temp_free(t0);
10841 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10843 TCGLabel *l1;
10844 TCGCond cond;
10845 TCGv_i32 t0;
10847 if (rd == 0) {
10848 /* Treat as NOP. */
10849 return;
10852 if (tf) {
10853 cond = TCG_COND_EQ;
10854 } else {
10855 cond = TCG_COND_NE;
10858 l1 = gen_new_label();
10859 t0 = tcg_temp_new_i32();
10860 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10861 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10862 tcg_temp_free_i32(t0);
10863 if (rs == 0) {
10864 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10865 } else {
10866 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10868 gen_set_label(l1);
10871 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10872 int tf)
10874 int cond;
10875 TCGv_i32 t0 = tcg_temp_new_i32();
10876 TCGLabel *l1 = gen_new_label();
10878 if (tf) {
10879 cond = TCG_COND_EQ;
10880 } else {
10881 cond = TCG_COND_NE;
10884 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10885 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10886 gen_load_fpr32(ctx, t0, fs);
10887 gen_store_fpr32(ctx, t0, fd);
10888 gen_set_label(l1);
10889 tcg_temp_free_i32(t0);
10892 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10893 int tf)
10895 int cond;
10896 TCGv_i32 t0 = tcg_temp_new_i32();
10897 TCGv_i64 fp0;
10898 TCGLabel *l1 = gen_new_label();
10900 if (tf) {
10901 cond = TCG_COND_EQ;
10902 } else {
10903 cond = TCG_COND_NE;
10906 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10907 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10908 tcg_temp_free_i32(t0);
10909 fp0 = tcg_temp_new_i64();
10910 gen_load_fpr64(ctx, fp0, fs);
10911 gen_store_fpr64(ctx, fp0, fd);
10912 tcg_temp_free_i64(fp0);
10913 gen_set_label(l1);
10916 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10917 int cc, int tf)
10919 int cond;
10920 TCGv_i32 t0 = tcg_temp_new_i32();
10921 TCGLabel *l1 = gen_new_label();
10922 TCGLabel *l2 = gen_new_label();
10924 if (tf) {
10925 cond = TCG_COND_EQ;
10926 } else {
10927 cond = TCG_COND_NE;
10930 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10931 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10932 gen_load_fpr32(ctx, t0, fs);
10933 gen_store_fpr32(ctx, t0, fd);
10934 gen_set_label(l1);
10936 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10937 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10938 gen_load_fpr32h(ctx, t0, fs);
10939 gen_store_fpr32h(ctx, t0, fd);
10940 tcg_temp_free_i32(t0);
10941 gen_set_label(l2);
10944 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10945 int fs)
10947 TCGv_i32 t1 = tcg_const_i32(0);
10948 TCGv_i32 fp0 = tcg_temp_new_i32();
10949 TCGv_i32 fp1 = tcg_temp_new_i32();
10950 TCGv_i32 fp2 = tcg_temp_new_i32();
10951 gen_load_fpr32(ctx, fp0, fd);
10952 gen_load_fpr32(ctx, fp1, ft);
10953 gen_load_fpr32(ctx, fp2, fs);
10955 switch (op1) {
10956 case OPC_SEL_S:
10957 tcg_gen_andi_i32(fp0, fp0, 1);
10958 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10959 break;
10960 case OPC_SELEQZ_S:
10961 tcg_gen_andi_i32(fp1, fp1, 1);
10962 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10963 break;
10964 case OPC_SELNEZ_S:
10965 tcg_gen_andi_i32(fp1, fp1, 1);
10966 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10967 break;
10968 default:
10969 MIPS_INVAL("gen_sel_s");
10970 generate_exception_end(ctx, EXCP_RI);
10971 break;
10974 gen_store_fpr32(ctx, fp0, fd);
10975 tcg_temp_free_i32(fp2);
10976 tcg_temp_free_i32(fp1);
10977 tcg_temp_free_i32(fp0);
10978 tcg_temp_free_i32(t1);
10981 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10982 int fs)
10984 TCGv_i64 t1 = tcg_const_i64(0);
10985 TCGv_i64 fp0 = tcg_temp_new_i64();
10986 TCGv_i64 fp1 = tcg_temp_new_i64();
10987 TCGv_i64 fp2 = tcg_temp_new_i64();
10988 gen_load_fpr64(ctx, fp0, fd);
10989 gen_load_fpr64(ctx, fp1, ft);
10990 gen_load_fpr64(ctx, fp2, fs);
10992 switch (op1) {
10993 case OPC_SEL_D:
10994 tcg_gen_andi_i64(fp0, fp0, 1);
10995 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10996 break;
10997 case OPC_SELEQZ_D:
10998 tcg_gen_andi_i64(fp1, fp1, 1);
10999 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11000 break;
11001 case OPC_SELNEZ_D:
11002 tcg_gen_andi_i64(fp1, fp1, 1);
11003 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11004 break;
11005 default:
11006 MIPS_INVAL("gen_sel_d");
11007 generate_exception_end(ctx, EXCP_RI);
11008 break;
11011 gen_store_fpr64(ctx, fp0, fd);
11012 tcg_temp_free_i64(fp2);
11013 tcg_temp_free_i64(fp1);
11014 tcg_temp_free_i64(fp0);
11015 tcg_temp_free_i64(t1);
11018 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11019 int ft, int fs, int fd, int cc)
11021 uint32_t func = ctx->opcode & 0x3f;
11022 switch (op1) {
11023 case OPC_ADD_S:
11025 TCGv_i32 fp0 = tcg_temp_new_i32();
11026 TCGv_i32 fp1 = tcg_temp_new_i32();
11028 gen_load_fpr32(ctx, fp0, fs);
11029 gen_load_fpr32(ctx, fp1, ft);
11030 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11031 tcg_temp_free_i32(fp1);
11032 gen_store_fpr32(ctx, fp0, fd);
11033 tcg_temp_free_i32(fp0);
11035 break;
11036 case OPC_SUB_S:
11038 TCGv_i32 fp0 = tcg_temp_new_i32();
11039 TCGv_i32 fp1 = tcg_temp_new_i32();
11041 gen_load_fpr32(ctx, fp0, fs);
11042 gen_load_fpr32(ctx, fp1, ft);
11043 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11044 tcg_temp_free_i32(fp1);
11045 gen_store_fpr32(ctx, fp0, fd);
11046 tcg_temp_free_i32(fp0);
11048 break;
11049 case OPC_MUL_S:
11051 TCGv_i32 fp0 = tcg_temp_new_i32();
11052 TCGv_i32 fp1 = tcg_temp_new_i32();
11054 gen_load_fpr32(ctx, fp0, fs);
11055 gen_load_fpr32(ctx, fp1, ft);
11056 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11057 tcg_temp_free_i32(fp1);
11058 gen_store_fpr32(ctx, fp0, fd);
11059 tcg_temp_free_i32(fp0);
11061 break;
11062 case OPC_DIV_S:
11064 TCGv_i32 fp0 = tcg_temp_new_i32();
11065 TCGv_i32 fp1 = tcg_temp_new_i32();
11067 gen_load_fpr32(ctx, fp0, fs);
11068 gen_load_fpr32(ctx, fp1, ft);
11069 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11070 tcg_temp_free_i32(fp1);
11071 gen_store_fpr32(ctx, fp0, fd);
11072 tcg_temp_free_i32(fp0);
11074 break;
11075 case OPC_SQRT_S:
11077 TCGv_i32 fp0 = tcg_temp_new_i32();
11079 gen_load_fpr32(ctx, fp0, fs);
11080 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11081 gen_store_fpr32(ctx, fp0, fd);
11082 tcg_temp_free_i32(fp0);
11084 break;
11085 case OPC_ABS_S:
11087 TCGv_i32 fp0 = tcg_temp_new_i32();
11089 gen_load_fpr32(ctx, fp0, fs);
11090 if (ctx->abs2008) {
11091 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11092 } else {
11093 gen_helper_float_abs_s(fp0, fp0);
11095 gen_store_fpr32(ctx, fp0, fd);
11096 tcg_temp_free_i32(fp0);
11098 break;
11099 case OPC_MOV_S:
11101 TCGv_i32 fp0 = tcg_temp_new_i32();
11103 gen_load_fpr32(ctx, fp0, fs);
11104 gen_store_fpr32(ctx, fp0, fd);
11105 tcg_temp_free_i32(fp0);
11107 break;
11108 case OPC_NEG_S:
11110 TCGv_i32 fp0 = tcg_temp_new_i32();
11112 gen_load_fpr32(ctx, fp0, fs);
11113 if (ctx->abs2008) {
11114 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11115 } else {
11116 gen_helper_float_chs_s(fp0, fp0);
11118 gen_store_fpr32(ctx, fp0, fd);
11119 tcg_temp_free_i32(fp0);
11121 break;
11122 case OPC_ROUND_L_S:
11123 check_cp1_64bitmode(ctx);
11125 TCGv_i32 fp32 = tcg_temp_new_i32();
11126 TCGv_i64 fp64 = tcg_temp_new_i64();
11128 gen_load_fpr32(ctx, fp32, fs);
11129 if (ctx->nan2008) {
11130 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11131 } else {
11132 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11134 tcg_temp_free_i32(fp32);
11135 gen_store_fpr64(ctx, fp64, fd);
11136 tcg_temp_free_i64(fp64);
11138 break;
11139 case OPC_TRUNC_L_S:
11140 check_cp1_64bitmode(ctx);
11142 TCGv_i32 fp32 = tcg_temp_new_i32();
11143 TCGv_i64 fp64 = tcg_temp_new_i64();
11145 gen_load_fpr32(ctx, fp32, fs);
11146 if (ctx->nan2008) {
11147 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11148 } else {
11149 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11151 tcg_temp_free_i32(fp32);
11152 gen_store_fpr64(ctx, fp64, fd);
11153 tcg_temp_free_i64(fp64);
11155 break;
11156 case OPC_CEIL_L_S:
11157 check_cp1_64bitmode(ctx);
11159 TCGv_i32 fp32 = tcg_temp_new_i32();
11160 TCGv_i64 fp64 = tcg_temp_new_i64();
11162 gen_load_fpr32(ctx, fp32, fs);
11163 if (ctx->nan2008) {
11164 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11165 } else {
11166 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11168 tcg_temp_free_i32(fp32);
11169 gen_store_fpr64(ctx, fp64, fd);
11170 tcg_temp_free_i64(fp64);
11172 break;
11173 case OPC_FLOOR_L_S:
11174 check_cp1_64bitmode(ctx);
11176 TCGv_i32 fp32 = tcg_temp_new_i32();
11177 TCGv_i64 fp64 = tcg_temp_new_i64();
11179 gen_load_fpr32(ctx, fp32, fs);
11180 if (ctx->nan2008) {
11181 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11182 } else {
11183 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11185 tcg_temp_free_i32(fp32);
11186 gen_store_fpr64(ctx, fp64, fd);
11187 tcg_temp_free_i64(fp64);
11189 break;
11190 case OPC_ROUND_W_S:
11192 TCGv_i32 fp0 = tcg_temp_new_i32();
11194 gen_load_fpr32(ctx, fp0, fs);
11195 if (ctx->nan2008) {
11196 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11197 } else {
11198 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11200 gen_store_fpr32(ctx, fp0, fd);
11201 tcg_temp_free_i32(fp0);
11203 break;
11204 case OPC_TRUNC_W_S:
11206 TCGv_i32 fp0 = tcg_temp_new_i32();
11208 gen_load_fpr32(ctx, fp0, fs);
11209 if (ctx->nan2008) {
11210 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11211 } else {
11212 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11214 gen_store_fpr32(ctx, fp0, fd);
11215 tcg_temp_free_i32(fp0);
11217 break;
11218 case OPC_CEIL_W_S:
11220 TCGv_i32 fp0 = tcg_temp_new_i32();
11222 gen_load_fpr32(ctx, fp0, fs);
11223 if (ctx->nan2008) {
11224 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11225 } else {
11226 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11228 gen_store_fpr32(ctx, fp0, fd);
11229 tcg_temp_free_i32(fp0);
11231 break;
11232 case OPC_FLOOR_W_S:
11234 TCGv_i32 fp0 = tcg_temp_new_i32();
11236 gen_load_fpr32(ctx, fp0, fs);
11237 if (ctx->nan2008) {
11238 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11239 } else {
11240 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11242 gen_store_fpr32(ctx, fp0, fd);
11243 tcg_temp_free_i32(fp0);
11245 break;
11246 case OPC_SEL_S:
11247 check_insn(ctx, ISA_MIPS32R6);
11248 gen_sel_s(ctx, op1, fd, ft, fs);
11249 break;
11250 case OPC_SELEQZ_S:
11251 check_insn(ctx, ISA_MIPS32R6);
11252 gen_sel_s(ctx, op1, fd, ft, fs);
11253 break;
11254 case OPC_SELNEZ_S:
11255 check_insn(ctx, ISA_MIPS32R6);
11256 gen_sel_s(ctx, op1, fd, ft, fs);
11257 break;
11258 case OPC_MOVCF_S:
11259 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11260 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11261 break;
11262 case OPC_MOVZ_S:
11263 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11265 TCGLabel *l1 = gen_new_label();
11266 TCGv_i32 fp0;
11268 if (ft != 0) {
11269 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11271 fp0 = tcg_temp_new_i32();
11272 gen_load_fpr32(ctx, fp0, fs);
11273 gen_store_fpr32(ctx, fp0, fd);
11274 tcg_temp_free_i32(fp0);
11275 gen_set_label(l1);
11277 break;
11278 case OPC_MOVN_S:
11279 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11281 TCGLabel *l1 = gen_new_label();
11282 TCGv_i32 fp0;
11284 if (ft != 0) {
11285 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11286 fp0 = tcg_temp_new_i32();
11287 gen_load_fpr32(ctx, fp0, fs);
11288 gen_store_fpr32(ctx, fp0, fd);
11289 tcg_temp_free_i32(fp0);
11290 gen_set_label(l1);
11293 break;
11294 case OPC_RECIP_S:
11296 TCGv_i32 fp0 = tcg_temp_new_i32();
11298 gen_load_fpr32(ctx, fp0, fs);
11299 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11300 gen_store_fpr32(ctx, fp0, fd);
11301 tcg_temp_free_i32(fp0);
11303 break;
11304 case OPC_RSQRT_S:
11306 TCGv_i32 fp0 = tcg_temp_new_i32();
11308 gen_load_fpr32(ctx, fp0, fs);
11309 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11310 gen_store_fpr32(ctx, fp0, fd);
11311 tcg_temp_free_i32(fp0);
11313 break;
11314 case OPC_MADDF_S:
11315 check_insn(ctx, ISA_MIPS32R6);
11317 TCGv_i32 fp0 = tcg_temp_new_i32();
11318 TCGv_i32 fp1 = tcg_temp_new_i32();
11319 TCGv_i32 fp2 = tcg_temp_new_i32();
11320 gen_load_fpr32(ctx, fp0, fs);
11321 gen_load_fpr32(ctx, fp1, ft);
11322 gen_load_fpr32(ctx, fp2, fd);
11323 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11324 gen_store_fpr32(ctx, fp2, fd);
11325 tcg_temp_free_i32(fp2);
11326 tcg_temp_free_i32(fp1);
11327 tcg_temp_free_i32(fp0);
11329 break;
11330 case OPC_MSUBF_S:
11331 check_insn(ctx, ISA_MIPS32R6);
11333 TCGv_i32 fp0 = tcg_temp_new_i32();
11334 TCGv_i32 fp1 = tcg_temp_new_i32();
11335 TCGv_i32 fp2 = tcg_temp_new_i32();
11336 gen_load_fpr32(ctx, fp0, fs);
11337 gen_load_fpr32(ctx, fp1, ft);
11338 gen_load_fpr32(ctx, fp2, fd);
11339 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11340 gen_store_fpr32(ctx, fp2, fd);
11341 tcg_temp_free_i32(fp2);
11342 tcg_temp_free_i32(fp1);
11343 tcg_temp_free_i32(fp0);
11345 break;
11346 case OPC_RINT_S:
11347 check_insn(ctx, ISA_MIPS32R6);
11349 TCGv_i32 fp0 = tcg_temp_new_i32();
11350 gen_load_fpr32(ctx, fp0, fs);
11351 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11352 gen_store_fpr32(ctx, fp0, fd);
11353 tcg_temp_free_i32(fp0);
11355 break;
11356 case OPC_CLASS_S:
11357 check_insn(ctx, ISA_MIPS32R6);
11359 TCGv_i32 fp0 = tcg_temp_new_i32();
11360 gen_load_fpr32(ctx, fp0, fs);
11361 gen_helper_float_class_s(fp0, cpu_env, fp0);
11362 gen_store_fpr32(ctx, fp0, fd);
11363 tcg_temp_free_i32(fp0);
11365 break;
11366 case OPC_MIN_S: /* OPC_RECIP2_S */
11367 if (ctx->insn_flags & ISA_MIPS32R6) {
11368 /* OPC_MIN_S */
11369 TCGv_i32 fp0 = tcg_temp_new_i32();
11370 TCGv_i32 fp1 = tcg_temp_new_i32();
11371 TCGv_i32 fp2 = tcg_temp_new_i32();
11372 gen_load_fpr32(ctx, fp0, fs);
11373 gen_load_fpr32(ctx, fp1, ft);
11374 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11375 gen_store_fpr32(ctx, fp2, fd);
11376 tcg_temp_free_i32(fp2);
11377 tcg_temp_free_i32(fp1);
11378 tcg_temp_free_i32(fp0);
11379 } else {
11380 /* OPC_RECIP2_S */
11381 check_cp1_64bitmode(ctx);
11383 TCGv_i32 fp0 = tcg_temp_new_i32();
11384 TCGv_i32 fp1 = tcg_temp_new_i32();
11386 gen_load_fpr32(ctx, fp0, fs);
11387 gen_load_fpr32(ctx, fp1, ft);
11388 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11389 tcg_temp_free_i32(fp1);
11390 gen_store_fpr32(ctx, fp0, fd);
11391 tcg_temp_free_i32(fp0);
11394 break;
11395 case OPC_MINA_S: /* OPC_RECIP1_S */
11396 if (ctx->insn_flags & ISA_MIPS32R6) {
11397 /* OPC_MINA_S */
11398 TCGv_i32 fp0 = tcg_temp_new_i32();
11399 TCGv_i32 fp1 = tcg_temp_new_i32();
11400 TCGv_i32 fp2 = tcg_temp_new_i32();
11401 gen_load_fpr32(ctx, fp0, fs);
11402 gen_load_fpr32(ctx, fp1, ft);
11403 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11404 gen_store_fpr32(ctx, fp2, fd);
11405 tcg_temp_free_i32(fp2);
11406 tcg_temp_free_i32(fp1);
11407 tcg_temp_free_i32(fp0);
11408 } else {
11409 /* OPC_RECIP1_S */
11410 check_cp1_64bitmode(ctx);
11412 TCGv_i32 fp0 = tcg_temp_new_i32();
11414 gen_load_fpr32(ctx, fp0, fs);
11415 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11416 gen_store_fpr32(ctx, fp0, fd);
11417 tcg_temp_free_i32(fp0);
11420 break;
11421 case OPC_MAX_S: /* OPC_RSQRT1_S */
11422 if (ctx->insn_flags & ISA_MIPS32R6) {
11423 /* OPC_MAX_S */
11424 TCGv_i32 fp0 = tcg_temp_new_i32();
11425 TCGv_i32 fp1 = tcg_temp_new_i32();
11426 gen_load_fpr32(ctx, fp0, fs);
11427 gen_load_fpr32(ctx, fp1, ft);
11428 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11429 gen_store_fpr32(ctx, fp1, fd);
11430 tcg_temp_free_i32(fp1);
11431 tcg_temp_free_i32(fp0);
11432 } else {
11433 /* OPC_RSQRT1_S */
11434 check_cp1_64bitmode(ctx);
11436 TCGv_i32 fp0 = tcg_temp_new_i32();
11438 gen_load_fpr32(ctx, fp0, fs);
11439 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11440 gen_store_fpr32(ctx, fp0, fd);
11441 tcg_temp_free_i32(fp0);
11444 break;
11445 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11446 if (ctx->insn_flags & ISA_MIPS32R6) {
11447 /* OPC_MAXA_S */
11448 TCGv_i32 fp0 = tcg_temp_new_i32();
11449 TCGv_i32 fp1 = tcg_temp_new_i32();
11450 gen_load_fpr32(ctx, fp0, fs);
11451 gen_load_fpr32(ctx, fp1, ft);
11452 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11453 gen_store_fpr32(ctx, fp1, fd);
11454 tcg_temp_free_i32(fp1);
11455 tcg_temp_free_i32(fp0);
11456 } else {
11457 /* OPC_RSQRT2_S */
11458 check_cp1_64bitmode(ctx);
11460 TCGv_i32 fp0 = tcg_temp_new_i32();
11461 TCGv_i32 fp1 = tcg_temp_new_i32();
11463 gen_load_fpr32(ctx, fp0, fs);
11464 gen_load_fpr32(ctx, fp1, ft);
11465 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11466 tcg_temp_free_i32(fp1);
11467 gen_store_fpr32(ctx, fp0, fd);
11468 tcg_temp_free_i32(fp0);
11471 break;
11472 case OPC_CVT_D_S:
11473 check_cp1_registers(ctx, fd);
11475 TCGv_i32 fp32 = tcg_temp_new_i32();
11476 TCGv_i64 fp64 = tcg_temp_new_i64();
11478 gen_load_fpr32(ctx, fp32, fs);
11479 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11480 tcg_temp_free_i32(fp32);
11481 gen_store_fpr64(ctx, fp64, fd);
11482 tcg_temp_free_i64(fp64);
11484 break;
11485 case OPC_CVT_W_S:
11487 TCGv_i32 fp0 = tcg_temp_new_i32();
11489 gen_load_fpr32(ctx, fp0, fs);
11490 if (ctx->nan2008) {
11491 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11492 } else {
11493 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11495 gen_store_fpr32(ctx, fp0, fd);
11496 tcg_temp_free_i32(fp0);
11498 break;
11499 case OPC_CVT_L_S:
11500 check_cp1_64bitmode(ctx);
11502 TCGv_i32 fp32 = tcg_temp_new_i32();
11503 TCGv_i64 fp64 = tcg_temp_new_i64();
11505 gen_load_fpr32(ctx, fp32, fs);
11506 if (ctx->nan2008) {
11507 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11508 } else {
11509 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11511 tcg_temp_free_i32(fp32);
11512 gen_store_fpr64(ctx, fp64, fd);
11513 tcg_temp_free_i64(fp64);
11515 break;
11516 case OPC_CVT_PS_S:
11517 check_ps(ctx);
11519 TCGv_i64 fp64 = tcg_temp_new_i64();
11520 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11521 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11523 gen_load_fpr32(ctx, fp32_0, fs);
11524 gen_load_fpr32(ctx, fp32_1, ft);
11525 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11526 tcg_temp_free_i32(fp32_1);
11527 tcg_temp_free_i32(fp32_0);
11528 gen_store_fpr64(ctx, fp64, fd);
11529 tcg_temp_free_i64(fp64);
11531 break;
11532 case OPC_CMP_F_S:
11533 case OPC_CMP_UN_S:
11534 case OPC_CMP_EQ_S:
11535 case OPC_CMP_UEQ_S:
11536 case OPC_CMP_OLT_S:
11537 case OPC_CMP_ULT_S:
11538 case OPC_CMP_OLE_S:
11539 case OPC_CMP_ULE_S:
11540 case OPC_CMP_SF_S:
11541 case OPC_CMP_NGLE_S:
11542 case OPC_CMP_SEQ_S:
11543 case OPC_CMP_NGL_S:
11544 case OPC_CMP_LT_S:
11545 case OPC_CMP_NGE_S:
11546 case OPC_CMP_LE_S:
11547 case OPC_CMP_NGT_S:
11548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11549 if (ctx->opcode & (1 << 6)) {
11550 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11551 } else {
11552 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11554 break;
11555 case OPC_ADD_D:
11556 check_cp1_registers(ctx, fs | ft | fd);
11558 TCGv_i64 fp0 = tcg_temp_new_i64();
11559 TCGv_i64 fp1 = tcg_temp_new_i64();
11561 gen_load_fpr64(ctx, fp0, fs);
11562 gen_load_fpr64(ctx, fp1, ft);
11563 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11564 tcg_temp_free_i64(fp1);
11565 gen_store_fpr64(ctx, fp0, fd);
11566 tcg_temp_free_i64(fp0);
11568 break;
11569 case OPC_SUB_D:
11570 check_cp1_registers(ctx, fs | ft | fd);
11572 TCGv_i64 fp0 = tcg_temp_new_i64();
11573 TCGv_i64 fp1 = tcg_temp_new_i64();
11575 gen_load_fpr64(ctx, fp0, fs);
11576 gen_load_fpr64(ctx, fp1, ft);
11577 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11578 tcg_temp_free_i64(fp1);
11579 gen_store_fpr64(ctx, fp0, fd);
11580 tcg_temp_free_i64(fp0);
11582 break;
11583 case OPC_MUL_D:
11584 check_cp1_registers(ctx, fs | ft | fd);
11586 TCGv_i64 fp0 = tcg_temp_new_i64();
11587 TCGv_i64 fp1 = tcg_temp_new_i64();
11589 gen_load_fpr64(ctx, fp0, fs);
11590 gen_load_fpr64(ctx, fp1, ft);
11591 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11592 tcg_temp_free_i64(fp1);
11593 gen_store_fpr64(ctx, fp0, fd);
11594 tcg_temp_free_i64(fp0);
11596 break;
11597 case OPC_DIV_D:
11598 check_cp1_registers(ctx, fs | ft | fd);
11600 TCGv_i64 fp0 = tcg_temp_new_i64();
11601 TCGv_i64 fp1 = tcg_temp_new_i64();
11603 gen_load_fpr64(ctx, fp0, fs);
11604 gen_load_fpr64(ctx, fp1, ft);
11605 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11606 tcg_temp_free_i64(fp1);
11607 gen_store_fpr64(ctx, fp0, fd);
11608 tcg_temp_free_i64(fp0);
11610 break;
11611 case OPC_SQRT_D:
11612 check_cp1_registers(ctx, fs | fd);
11614 TCGv_i64 fp0 = tcg_temp_new_i64();
11616 gen_load_fpr64(ctx, fp0, fs);
11617 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11618 gen_store_fpr64(ctx, fp0, fd);
11619 tcg_temp_free_i64(fp0);
11621 break;
11622 case OPC_ABS_D:
11623 check_cp1_registers(ctx, fs | fd);
11625 TCGv_i64 fp0 = tcg_temp_new_i64();
11627 gen_load_fpr64(ctx, fp0, fs);
11628 if (ctx->abs2008) {
11629 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11630 } else {
11631 gen_helper_float_abs_d(fp0, fp0);
11633 gen_store_fpr64(ctx, fp0, fd);
11634 tcg_temp_free_i64(fp0);
11636 break;
11637 case OPC_MOV_D:
11638 check_cp1_registers(ctx, fs | fd);
11640 TCGv_i64 fp0 = tcg_temp_new_i64();
11642 gen_load_fpr64(ctx, fp0, fs);
11643 gen_store_fpr64(ctx, fp0, fd);
11644 tcg_temp_free_i64(fp0);
11646 break;
11647 case OPC_NEG_D:
11648 check_cp1_registers(ctx, fs | fd);
11650 TCGv_i64 fp0 = tcg_temp_new_i64();
11652 gen_load_fpr64(ctx, fp0, fs);
11653 if (ctx->abs2008) {
11654 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11655 } else {
11656 gen_helper_float_chs_d(fp0, fp0);
11658 gen_store_fpr64(ctx, fp0, fd);
11659 tcg_temp_free_i64(fp0);
11661 break;
11662 case OPC_ROUND_L_D:
11663 check_cp1_64bitmode(ctx);
11665 TCGv_i64 fp0 = tcg_temp_new_i64();
11667 gen_load_fpr64(ctx, fp0, fs);
11668 if (ctx->nan2008) {
11669 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11670 } else {
11671 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11673 gen_store_fpr64(ctx, fp0, fd);
11674 tcg_temp_free_i64(fp0);
11676 break;
11677 case OPC_TRUNC_L_D:
11678 check_cp1_64bitmode(ctx);
11680 TCGv_i64 fp0 = tcg_temp_new_i64();
11682 gen_load_fpr64(ctx, fp0, fs);
11683 if (ctx->nan2008) {
11684 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11685 } else {
11686 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11688 gen_store_fpr64(ctx, fp0, fd);
11689 tcg_temp_free_i64(fp0);
11691 break;
11692 case OPC_CEIL_L_D:
11693 check_cp1_64bitmode(ctx);
11695 TCGv_i64 fp0 = tcg_temp_new_i64();
11697 gen_load_fpr64(ctx, fp0, fs);
11698 if (ctx->nan2008) {
11699 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11700 } else {
11701 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11703 gen_store_fpr64(ctx, fp0, fd);
11704 tcg_temp_free_i64(fp0);
11706 break;
11707 case OPC_FLOOR_L_D:
11708 check_cp1_64bitmode(ctx);
11710 TCGv_i64 fp0 = tcg_temp_new_i64();
11712 gen_load_fpr64(ctx, fp0, fs);
11713 if (ctx->nan2008) {
11714 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11715 } else {
11716 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11718 gen_store_fpr64(ctx, fp0, fd);
11719 tcg_temp_free_i64(fp0);
11721 break;
11722 case OPC_ROUND_W_D:
11723 check_cp1_registers(ctx, fs);
11725 TCGv_i32 fp32 = tcg_temp_new_i32();
11726 TCGv_i64 fp64 = tcg_temp_new_i64();
11728 gen_load_fpr64(ctx, fp64, fs);
11729 if (ctx->nan2008) {
11730 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11731 } else {
11732 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11734 tcg_temp_free_i64(fp64);
11735 gen_store_fpr32(ctx, fp32, fd);
11736 tcg_temp_free_i32(fp32);
11738 break;
11739 case OPC_TRUNC_W_D:
11740 check_cp1_registers(ctx, fs);
11742 TCGv_i32 fp32 = tcg_temp_new_i32();
11743 TCGv_i64 fp64 = tcg_temp_new_i64();
11745 gen_load_fpr64(ctx, fp64, fs);
11746 if (ctx->nan2008) {
11747 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11748 } else {
11749 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11751 tcg_temp_free_i64(fp64);
11752 gen_store_fpr32(ctx, fp32, fd);
11753 tcg_temp_free_i32(fp32);
11755 break;
11756 case OPC_CEIL_W_D:
11757 check_cp1_registers(ctx, fs);
11759 TCGv_i32 fp32 = tcg_temp_new_i32();
11760 TCGv_i64 fp64 = tcg_temp_new_i64();
11762 gen_load_fpr64(ctx, fp64, fs);
11763 if (ctx->nan2008) {
11764 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11765 } else {
11766 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11768 tcg_temp_free_i64(fp64);
11769 gen_store_fpr32(ctx, fp32, fd);
11770 tcg_temp_free_i32(fp32);
11772 break;
11773 case OPC_FLOOR_W_D:
11774 check_cp1_registers(ctx, fs);
11776 TCGv_i32 fp32 = tcg_temp_new_i32();
11777 TCGv_i64 fp64 = tcg_temp_new_i64();
11779 gen_load_fpr64(ctx, fp64, fs);
11780 if (ctx->nan2008) {
11781 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11782 } else {
11783 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11785 tcg_temp_free_i64(fp64);
11786 gen_store_fpr32(ctx, fp32, fd);
11787 tcg_temp_free_i32(fp32);
11789 break;
11790 case OPC_SEL_D:
11791 check_insn(ctx, ISA_MIPS32R6);
11792 gen_sel_d(ctx, op1, fd, ft, fs);
11793 break;
11794 case OPC_SELEQZ_D:
11795 check_insn(ctx, ISA_MIPS32R6);
11796 gen_sel_d(ctx, op1, fd, ft, fs);
11797 break;
11798 case OPC_SELNEZ_D:
11799 check_insn(ctx, ISA_MIPS32R6);
11800 gen_sel_d(ctx, op1, fd, ft, fs);
11801 break;
11802 case OPC_MOVCF_D:
11803 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11804 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11805 break;
11806 case OPC_MOVZ_D:
11807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11809 TCGLabel *l1 = gen_new_label();
11810 TCGv_i64 fp0;
11812 if (ft != 0) {
11813 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11815 fp0 = tcg_temp_new_i64();
11816 gen_load_fpr64(ctx, fp0, fs);
11817 gen_store_fpr64(ctx, fp0, fd);
11818 tcg_temp_free_i64(fp0);
11819 gen_set_label(l1);
11821 break;
11822 case OPC_MOVN_D:
11823 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11825 TCGLabel *l1 = gen_new_label();
11826 TCGv_i64 fp0;
11828 if (ft != 0) {
11829 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11830 fp0 = tcg_temp_new_i64();
11831 gen_load_fpr64(ctx, fp0, fs);
11832 gen_store_fpr64(ctx, fp0, fd);
11833 tcg_temp_free_i64(fp0);
11834 gen_set_label(l1);
11837 break;
11838 case OPC_RECIP_D:
11839 check_cp1_registers(ctx, fs | fd);
11841 TCGv_i64 fp0 = tcg_temp_new_i64();
11843 gen_load_fpr64(ctx, fp0, fs);
11844 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11845 gen_store_fpr64(ctx, fp0, fd);
11846 tcg_temp_free_i64(fp0);
11848 break;
11849 case OPC_RSQRT_D:
11850 check_cp1_registers(ctx, fs | fd);
11852 TCGv_i64 fp0 = tcg_temp_new_i64();
11854 gen_load_fpr64(ctx, fp0, fs);
11855 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11856 gen_store_fpr64(ctx, fp0, fd);
11857 tcg_temp_free_i64(fp0);
11859 break;
11860 case OPC_MADDF_D:
11861 check_insn(ctx, ISA_MIPS32R6);
11863 TCGv_i64 fp0 = tcg_temp_new_i64();
11864 TCGv_i64 fp1 = tcg_temp_new_i64();
11865 TCGv_i64 fp2 = tcg_temp_new_i64();
11866 gen_load_fpr64(ctx, fp0, fs);
11867 gen_load_fpr64(ctx, fp1, ft);
11868 gen_load_fpr64(ctx, fp2, fd);
11869 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11870 gen_store_fpr64(ctx, fp2, fd);
11871 tcg_temp_free_i64(fp2);
11872 tcg_temp_free_i64(fp1);
11873 tcg_temp_free_i64(fp0);
11875 break;
11876 case OPC_MSUBF_D:
11877 check_insn(ctx, ISA_MIPS32R6);
11879 TCGv_i64 fp0 = tcg_temp_new_i64();
11880 TCGv_i64 fp1 = tcg_temp_new_i64();
11881 TCGv_i64 fp2 = tcg_temp_new_i64();
11882 gen_load_fpr64(ctx, fp0, fs);
11883 gen_load_fpr64(ctx, fp1, ft);
11884 gen_load_fpr64(ctx, fp2, fd);
11885 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11886 gen_store_fpr64(ctx, fp2, fd);
11887 tcg_temp_free_i64(fp2);
11888 tcg_temp_free_i64(fp1);
11889 tcg_temp_free_i64(fp0);
11891 break;
11892 case OPC_RINT_D:
11893 check_insn(ctx, ISA_MIPS32R6);
11895 TCGv_i64 fp0 = tcg_temp_new_i64();
11896 gen_load_fpr64(ctx, fp0, fs);
11897 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11898 gen_store_fpr64(ctx, fp0, fd);
11899 tcg_temp_free_i64(fp0);
11901 break;
11902 case OPC_CLASS_D:
11903 check_insn(ctx, ISA_MIPS32R6);
11905 TCGv_i64 fp0 = tcg_temp_new_i64();
11906 gen_load_fpr64(ctx, fp0, fs);
11907 gen_helper_float_class_d(fp0, cpu_env, fp0);
11908 gen_store_fpr64(ctx, fp0, fd);
11909 tcg_temp_free_i64(fp0);
11911 break;
11912 case OPC_MIN_D: /* OPC_RECIP2_D */
11913 if (ctx->insn_flags & ISA_MIPS32R6) {
11914 /* OPC_MIN_D */
11915 TCGv_i64 fp0 = tcg_temp_new_i64();
11916 TCGv_i64 fp1 = tcg_temp_new_i64();
11917 gen_load_fpr64(ctx, fp0, fs);
11918 gen_load_fpr64(ctx, fp1, ft);
11919 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11920 gen_store_fpr64(ctx, fp1, fd);
11921 tcg_temp_free_i64(fp1);
11922 tcg_temp_free_i64(fp0);
11923 } else {
11924 /* OPC_RECIP2_D */
11925 check_cp1_64bitmode(ctx);
11927 TCGv_i64 fp0 = tcg_temp_new_i64();
11928 TCGv_i64 fp1 = tcg_temp_new_i64();
11930 gen_load_fpr64(ctx, fp0, fs);
11931 gen_load_fpr64(ctx, fp1, ft);
11932 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11933 tcg_temp_free_i64(fp1);
11934 gen_store_fpr64(ctx, fp0, fd);
11935 tcg_temp_free_i64(fp0);
11938 break;
11939 case OPC_MINA_D: /* OPC_RECIP1_D */
11940 if (ctx->insn_flags & ISA_MIPS32R6) {
11941 /* OPC_MINA_D */
11942 TCGv_i64 fp0 = tcg_temp_new_i64();
11943 TCGv_i64 fp1 = tcg_temp_new_i64();
11944 gen_load_fpr64(ctx, fp0, fs);
11945 gen_load_fpr64(ctx, fp1, ft);
11946 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11947 gen_store_fpr64(ctx, fp1, fd);
11948 tcg_temp_free_i64(fp1);
11949 tcg_temp_free_i64(fp0);
11950 } else {
11951 /* OPC_RECIP1_D */
11952 check_cp1_64bitmode(ctx);
11954 TCGv_i64 fp0 = tcg_temp_new_i64();
11956 gen_load_fpr64(ctx, fp0, fs);
11957 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11958 gen_store_fpr64(ctx, fp0, fd);
11959 tcg_temp_free_i64(fp0);
11962 break;
11963 case OPC_MAX_D: /* OPC_RSQRT1_D */
11964 if (ctx->insn_flags & ISA_MIPS32R6) {
11965 /* OPC_MAX_D */
11966 TCGv_i64 fp0 = tcg_temp_new_i64();
11967 TCGv_i64 fp1 = tcg_temp_new_i64();
11968 gen_load_fpr64(ctx, fp0, fs);
11969 gen_load_fpr64(ctx, fp1, ft);
11970 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11971 gen_store_fpr64(ctx, fp1, fd);
11972 tcg_temp_free_i64(fp1);
11973 tcg_temp_free_i64(fp0);
11974 } else {
11975 /* OPC_RSQRT1_D */
11976 check_cp1_64bitmode(ctx);
11978 TCGv_i64 fp0 = tcg_temp_new_i64();
11980 gen_load_fpr64(ctx, fp0, fs);
11981 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11982 gen_store_fpr64(ctx, fp0, fd);
11983 tcg_temp_free_i64(fp0);
11986 break;
11987 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11988 if (ctx->insn_flags & ISA_MIPS32R6) {
11989 /* OPC_MAXA_D */
11990 TCGv_i64 fp0 = tcg_temp_new_i64();
11991 TCGv_i64 fp1 = tcg_temp_new_i64();
11992 gen_load_fpr64(ctx, fp0, fs);
11993 gen_load_fpr64(ctx, fp1, ft);
11994 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11995 gen_store_fpr64(ctx, fp1, fd);
11996 tcg_temp_free_i64(fp1);
11997 tcg_temp_free_i64(fp0);
11998 } else {
11999 /* OPC_RSQRT2_D */
12000 check_cp1_64bitmode(ctx);
12002 TCGv_i64 fp0 = tcg_temp_new_i64();
12003 TCGv_i64 fp1 = tcg_temp_new_i64();
12005 gen_load_fpr64(ctx, fp0, fs);
12006 gen_load_fpr64(ctx, fp1, ft);
12007 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12008 tcg_temp_free_i64(fp1);
12009 gen_store_fpr64(ctx, fp0, fd);
12010 tcg_temp_free_i64(fp0);
12013 break;
12014 case OPC_CMP_F_D:
12015 case OPC_CMP_UN_D:
12016 case OPC_CMP_EQ_D:
12017 case OPC_CMP_UEQ_D:
12018 case OPC_CMP_OLT_D:
12019 case OPC_CMP_ULT_D:
12020 case OPC_CMP_OLE_D:
12021 case OPC_CMP_ULE_D:
12022 case OPC_CMP_SF_D:
12023 case OPC_CMP_NGLE_D:
12024 case OPC_CMP_SEQ_D:
12025 case OPC_CMP_NGL_D:
12026 case OPC_CMP_LT_D:
12027 case OPC_CMP_NGE_D:
12028 case OPC_CMP_LE_D:
12029 case OPC_CMP_NGT_D:
12030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12031 if (ctx->opcode & (1 << 6)) {
12032 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12033 } else {
12034 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12036 break;
12037 case OPC_CVT_S_D:
12038 check_cp1_registers(ctx, fs);
12040 TCGv_i32 fp32 = tcg_temp_new_i32();
12041 TCGv_i64 fp64 = tcg_temp_new_i64();
12043 gen_load_fpr64(ctx, fp64, fs);
12044 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12045 tcg_temp_free_i64(fp64);
12046 gen_store_fpr32(ctx, fp32, fd);
12047 tcg_temp_free_i32(fp32);
12049 break;
12050 case OPC_CVT_W_D:
12051 check_cp1_registers(ctx, fs);
12053 TCGv_i32 fp32 = tcg_temp_new_i32();
12054 TCGv_i64 fp64 = tcg_temp_new_i64();
12056 gen_load_fpr64(ctx, fp64, fs);
12057 if (ctx->nan2008) {
12058 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12059 } else {
12060 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12062 tcg_temp_free_i64(fp64);
12063 gen_store_fpr32(ctx, fp32, fd);
12064 tcg_temp_free_i32(fp32);
12066 break;
12067 case OPC_CVT_L_D:
12068 check_cp1_64bitmode(ctx);
12070 TCGv_i64 fp0 = tcg_temp_new_i64();
12072 gen_load_fpr64(ctx, fp0, fs);
12073 if (ctx->nan2008) {
12074 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12075 } else {
12076 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12078 gen_store_fpr64(ctx, fp0, fd);
12079 tcg_temp_free_i64(fp0);
12081 break;
12082 case OPC_CVT_S_W:
12084 TCGv_i32 fp0 = tcg_temp_new_i32();
12086 gen_load_fpr32(ctx, fp0, fs);
12087 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12088 gen_store_fpr32(ctx, fp0, fd);
12089 tcg_temp_free_i32(fp0);
12091 break;
12092 case OPC_CVT_D_W:
12093 check_cp1_registers(ctx, fd);
12095 TCGv_i32 fp32 = tcg_temp_new_i32();
12096 TCGv_i64 fp64 = tcg_temp_new_i64();
12098 gen_load_fpr32(ctx, fp32, fs);
12099 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12100 tcg_temp_free_i32(fp32);
12101 gen_store_fpr64(ctx, fp64, fd);
12102 tcg_temp_free_i64(fp64);
12104 break;
12105 case OPC_CVT_S_L:
12106 check_cp1_64bitmode(ctx);
12108 TCGv_i32 fp32 = tcg_temp_new_i32();
12109 TCGv_i64 fp64 = tcg_temp_new_i64();
12111 gen_load_fpr64(ctx, fp64, fs);
12112 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12113 tcg_temp_free_i64(fp64);
12114 gen_store_fpr32(ctx, fp32, fd);
12115 tcg_temp_free_i32(fp32);
12117 break;
12118 case OPC_CVT_D_L:
12119 check_cp1_64bitmode(ctx);
12121 TCGv_i64 fp0 = tcg_temp_new_i64();
12123 gen_load_fpr64(ctx, fp0, fs);
12124 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12125 gen_store_fpr64(ctx, fp0, fd);
12126 tcg_temp_free_i64(fp0);
12128 break;
12129 case OPC_CVT_PS_PW:
12130 check_ps(ctx);
12132 TCGv_i64 fp0 = tcg_temp_new_i64();
12134 gen_load_fpr64(ctx, fp0, fs);
12135 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12136 gen_store_fpr64(ctx, fp0, fd);
12137 tcg_temp_free_i64(fp0);
12139 break;
12140 case OPC_ADD_PS:
12141 check_ps(ctx);
12143 TCGv_i64 fp0 = tcg_temp_new_i64();
12144 TCGv_i64 fp1 = tcg_temp_new_i64();
12146 gen_load_fpr64(ctx, fp0, fs);
12147 gen_load_fpr64(ctx, fp1, ft);
12148 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12149 tcg_temp_free_i64(fp1);
12150 gen_store_fpr64(ctx, fp0, fd);
12151 tcg_temp_free_i64(fp0);
12153 break;
12154 case OPC_SUB_PS:
12155 check_ps(ctx);
12157 TCGv_i64 fp0 = tcg_temp_new_i64();
12158 TCGv_i64 fp1 = tcg_temp_new_i64();
12160 gen_load_fpr64(ctx, fp0, fs);
12161 gen_load_fpr64(ctx, fp1, ft);
12162 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12163 tcg_temp_free_i64(fp1);
12164 gen_store_fpr64(ctx, fp0, fd);
12165 tcg_temp_free_i64(fp0);
12167 break;
12168 case OPC_MUL_PS:
12169 check_ps(ctx);
12171 TCGv_i64 fp0 = tcg_temp_new_i64();
12172 TCGv_i64 fp1 = tcg_temp_new_i64();
12174 gen_load_fpr64(ctx, fp0, fs);
12175 gen_load_fpr64(ctx, fp1, ft);
12176 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12177 tcg_temp_free_i64(fp1);
12178 gen_store_fpr64(ctx, fp0, fd);
12179 tcg_temp_free_i64(fp0);
12181 break;
12182 case OPC_ABS_PS:
12183 check_ps(ctx);
12185 TCGv_i64 fp0 = tcg_temp_new_i64();
12187 gen_load_fpr64(ctx, fp0, fs);
12188 gen_helper_float_abs_ps(fp0, fp0);
12189 gen_store_fpr64(ctx, fp0, fd);
12190 tcg_temp_free_i64(fp0);
12192 break;
12193 case OPC_MOV_PS:
12194 check_ps(ctx);
12196 TCGv_i64 fp0 = tcg_temp_new_i64();
12198 gen_load_fpr64(ctx, fp0, fs);
12199 gen_store_fpr64(ctx, fp0, fd);
12200 tcg_temp_free_i64(fp0);
12202 break;
12203 case OPC_NEG_PS:
12204 check_ps(ctx);
12206 TCGv_i64 fp0 = tcg_temp_new_i64();
12208 gen_load_fpr64(ctx, fp0, fs);
12209 gen_helper_float_chs_ps(fp0, fp0);
12210 gen_store_fpr64(ctx, fp0, fd);
12211 tcg_temp_free_i64(fp0);
12213 break;
12214 case OPC_MOVCF_PS:
12215 check_ps(ctx);
12216 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12217 break;
12218 case OPC_MOVZ_PS:
12219 check_ps(ctx);
12221 TCGLabel *l1 = gen_new_label();
12222 TCGv_i64 fp0;
12224 if (ft != 0) {
12225 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12227 fp0 = tcg_temp_new_i64();
12228 gen_load_fpr64(ctx, fp0, fs);
12229 gen_store_fpr64(ctx, fp0, fd);
12230 tcg_temp_free_i64(fp0);
12231 gen_set_label(l1);
12233 break;
12234 case OPC_MOVN_PS:
12235 check_ps(ctx);
12237 TCGLabel *l1 = gen_new_label();
12238 TCGv_i64 fp0;
12240 if (ft != 0) {
12241 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12242 fp0 = tcg_temp_new_i64();
12243 gen_load_fpr64(ctx, fp0, fs);
12244 gen_store_fpr64(ctx, fp0, fd);
12245 tcg_temp_free_i64(fp0);
12246 gen_set_label(l1);
12249 break;
12250 case OPC_ADDR_PS:
12251 check_ps(ctx);
12253 TCGv_i64 fp0 = tcg_temp_new_i64();
12254 TCGv_i64 fp1 = tcg_temp_new_i64();
12256 gen_load_fpr64(ctx, fp0, ft);
12257 gen_load_fpr64(ctx, fp1, fs);
12258 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12259 tcg_temp_free_i64(fp1);
12260 gen_store_fpr64(ctx, fp0, fd);
12261 tcg_temp_free_i64(fp0);
12263 break;
12264 case OPC_MULR_PS:
12265 check_ps(ctx);
12267 TCGv_i64 fp0 = tcg_temp_new_i64();
12268 TCGv_i64 fp1 = tcg_temp_new_i64();
12270 gen_load_fpr64(ctx, fp0, ft);
12271 gen_load_fpr64(ctx, fp1, fs);
12272 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12273 tcg_temp_free_i64(fp1);
12274 gen_store_fpr64(ctx, fp0, fd);
12275 tcg_temp_free_i64(fp0);
12277 break;
12278 case OPC_RECIP2_PS:
12279 check_ps(ctx);
12281 TCGv_i64 fp0 = tcg_temp_new_i64();
12282 TCGv_i64 fp1 = tcg_temp_new_i64();
12284 gen_load_fpr64(ctx, fp0, fs);
12285 gen_load_fpr64(ctx, fp1, ft);
12286 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12287 tcg_temp_free_i64(fp1);
12288 gen_store_fpr64(ctx, fp0, fd);
12289 tcg_temp_free_i64(fp0);
12291 break;
12292 case OPC_RECIP1_PS:
12293 check_ps(ctx);
12295 TCGv_i64 fp0 = tcg_temp_new_i64();
12297 gen_load_fpr64(ctx, fp0, fs);
12298 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12299 gen_store_fpr64(ctx, fp0, fd);
12300 tcg_temp_free_i64(fp0);
12302 break;
12303 case OPC_RSQRT1_PS:
12304 check_ps(ctx);
12306 TCGv_i64 fp0 = tcg_temp_new_i64();
12308 gen_load_fpr64(ctx, fp0, fs);
12309 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12310 gen_store_fpr64(ctx, fp0, fd);
12311 tcg_temp_free_i64(fp0);
12313 break;
12314 case OPC_RSQRT2_PS:
12315 check_ps(ctx);
12317 TCGv_i64 fp0 = tcg_temp_new_i64();
12318 TCGv_i64 fp1 = tcg_temp_new_i64();
12320 gen_load_fpr64(ctx, fp0, fs);
12321 gen_load_fpr64(ctx, fp1, ft);
12322 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12323 tcg_temp_free_i64(fp1);
12324 gen_store_fpr64(ctx, fp0, fd);
12325 tcg_temp_free_i64(fp0);
12327 break;
12328 case OPC_CVT_S_PU:
12329 check_cp1_64bitmode(ctx);
12331 TCGv_i32 fp0 = tcg_temp_new_i32();
12333 gen_load_fpr32h(ctx, fp0, fs);
12334 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12335 gen_store_fpr32(ctx, fp0, fd);
12336 tcg_temp_free_i32(fp0);
12338 break;
12339 case OPC_CVT_PW_PS:
12340 check_ps(ctx);
12342 TCGv_i64 fp0 = tcg_temp_new_i64();
12344 gen_load_fpr64(ctx, fp0, fs);
12345 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12346 gen_store_fpr64(ctx, fp0, fd);
12347 tcg_temp_free_i64(fp0);
12349 break;
12350 case OPC_CVT_S_PL:
12351 check_cp1_64bitmode(ctx);
12353 TCGv_i32 fp0 = tcg_temp_new_i32();
12355 gen_load_fpr32(ctx, fp0, fs);
12356 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12357 gen_store_fpr32(ctx, fp0, fd);
12358 tcg_temp_free_i32(fp0);
12360 break;
12361 case OPC_PLL_PS:
12362 check_ps(ctx);
12364 TCGv_i32 fp0 = tcg_temp_new_i32();
12365 TCGv_i32 fp1 = tcg_temp_new_i32();
12367 gen_load_fpr32(ctx, fp0, fs);
12368 gen_load_fpr32(ctx, fp1, ft);
12369 gen_store_fpr32h(ctx, fp0, fd);
12370 gen_store_fpr32(ctx, fp1, fd);
12371 tcg_temp_free_i32(fp0);
12372 tcg_temp_free_i32(fp1);
12374 break;
12375 case OPC_PLU_PS:
12376 check_ps(ctx);
12378 TCGv_i32 fp0 = tcg_temp_new_i32();
12379 TCGv_i32 fp1 = tcg_temp_new_i32();
12381 gen_load_fpr32(ctx, fp0, fs);
12382 gen_load_fpr32h(ctx, fp1, ft);
12383 gen_store_fpr32(ctx, fp1, fd);
12384 gen_store_fpr32h(ctx, fp0, fd);
12385 tcg_temp_free_i32(fp0);
12386 tcg_temp_free_i32(fp1);
12388 break;
12389 case OPC_PUL_PS:
12390 check_ps(ctx);
12392 TCGv_i32 fp0 = tcg_temp_new_i32();
12393 TCGv_i32 fp1 = tcg_temp_new_i32();
12395 gen_load_fpr32h(ctx, fp0, fs);
12396 gen_load_fpr32(ctx, fp1, ft);
12397 gen_store_fpr32(ctx, fp1, fd);
12398 gen_store_fpr32h(ctx, fp0, fd);
12399 tcg_temp_free_i32(fp0);
12400 tcg_temp_free_i32(fp1);
12402 break;
12403 case OPC_PUU_PS:
12404 check_ps(ctx);
12406 TCGv_i32 fp0 = tcg_temp_new_i32();
12407 TCGv_i32 fp1 = tcg_temp_new_i32();
12409 gen_load_fpr32h(ctx, fp0, fs);
12410 gen_load_fpr32h(ctx, fp1, ft);
12411 gen_store_fpr32(ctx, fp1, fd);
12412 gen_store_fpr32h(ctx, fp0, fd);
12413 tcg_temp_free_i32(fp0);
12414 tcg_temp_free_i32(fp1);
12416 break;
12417 case OPC_CMP_F_PS:
12418 case OPC_CMP_UN_PS:
12419 case OPC_CMP_EQ_PS:
12420 case OPC_CMP_UEQ_PS:
12421 case OPC_CMP_OLT_PS:
12422 case OPC_CMP_ULT_PS:
12423 case OPC_CMP_OLE_PS:
12424 case OPC_CMP_ULE_PS:
12425 case OPC_CMP_SF_PS:
12426 case OPC_CMP_NGLE_PS:
12427 case OPC_CMP_SEQ_PS:
12428 case OPC_CMP_NGL_PS:
12429 case OPC_CMP_LT_PS:
12430 case OPC_CMP_NGE_PS:
12431 case OPC_CMP_LE_PS:
12432 case OPC_CMP_NGT_PS:
12433 if (ctx->opcode & (1 << 6)) {
12434 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12435 } else {
12436 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12438 break;
12439 default:
12440 MIPS_INVAL("farith");
12441 generate_exception_end(ctx, EXCP_RI);
12442 return;
12446 /* Coprocessor 3 (FPU) */
12447 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12448 int fd, int fs, int base, int index)
12450 TCGv t0 = tcg_temp_new();
12452 if (base == 0) {
12453 gen_load_gpr(t0, index);
12454 } else if (index == 0) {
12455 gen_load_gpr(t0, base);
12456 } else {
12457 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12460 * Don't do NOP if destination is zero: we must perform the actual
12461 * memory access.
12463 switch (opc) {
12464 case OPC_LWXC1:
12465 check_cop1x(ctx);
12467 TCGv_i32 fp0 = tcg_temp_new_i32();
12469 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12470 tcg_gen_trunc_tl_i32(fp0, t0);
12471 gen_store_fpr32(ctx, fp0, fd);
12472 tcg_temp_free_i32(fp0);
12474 break;
12475 case OPC_LDXC1:
12476 check_cop1x(ctx);
12477 check_cp1_registers(ctx, fd);
12479 TCGv_i64 fp0 = tcg_temp_new_i64();
12480 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12481 gen_store_fpr64(ctx, fp0, fd);
12482 tcg_temp_free_i64(fp0);
12484 break;
12485 case OPC_LUXC1:
12486 check_cp1_64bitmode(ctx);
12487 tcg_gen_andi_tl(t0, t0, ~0x7);
12489 TCGv_i64 fp0 = tcg_temp_new_i64();
12491 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12492 gen_store_fpr64(ctx, fp0, fd);
12493 tcg_temp_free_i64(fp0);
12495 break;
12496 case OPC_SWXC1:
12497 check_cop1x(ctx);
12499 TCGv_i32 fp0 = tcg_temp_new_i32();
12500 gen_load_fpr32(ctx, fp0, fs);
12501 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12502 tcg_temp_free_i32(fp0);
12504 break;
12505 case OPC_SDXC1:
12506 check_cop1x(ctx);
12507 check_cp1_registers(ctx, fs);
12509 TCGv_i64 fp0 = tcg_temp_new_i64();
12510 gen_load_fpr64(ctx, fp0, fs);
12511 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12512 tcg_temp_free_i64(fp0);
12514 break;
12515 case OPC_SUXC1:
12516 check_cp1_64bitmode(ctx);
12517 tcg_gen_andi_tl(t0, t0, ~0x7);
12519 TCGv_i64 fp0 = tcg_temp_new_i64();
12520 gen_load_fpr64(ctx, fp0, fs);
12521 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12522 tcg_temp_free_i64(fp0);
12524 break;
12526 tcg_temp_free(t0);
12529 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12530 int fd, int fr, int fs, int ft)
12532 switch (opc) {
12533 case OPC_ALNV_PS:
12534 check_ps(ctx);
12536 TCGv t0 = tcg_temp_local_new();
12537 TCGv_i32 fp = tcg_temp_new_i32();
12538 TCGv_i32 fph = tcg_temp_new_i32();
12539 TCGLabel *l1 = gen_new_label();
12540 TCGLabel *l2 = gen_new_label();
12542 gen_load_gpr(t0, fr);
12543 tcg_gen_andi_tl(t0, t0, 0x7);
12545 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12546 gen_load_fpr32(ctx, fp, fs);
12547 gen_load_fpr32h(ctx, fph, fs);
12548 gen_store_fpr32(ctx, fp, fd);
12549 gen_store_fpr32h(ctx, fph, fd);
12550 tcg_gen_br(l2);
12551 gen_set_label(l1);
12552 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12553 tcg_temp_free(t0);
12554 #ifdef TARGET_WORDS_BIGENDIAN
12555 gen_load_fpr32(ctx, fp, fs);
12556 gen_load_fpr32h(ctx, fph, ft);
12557 gen_store_fpr32h(ctx, fp, fd);
12558 gen_store_fpr32(ctx, fph, fd);
12559 #else
12560 gen_load_fpr32h(ctx, fph, fs);
12561 gen_load_fpr32(ctx, fp, ft);
12562 gen_store_fpr32(ctx, fph, fd);
12563 gen_store_fpr32h(ctx, fp, fd);
12564 #endif
12565 gen_set_label(l2);
12566 tcg_temp_free_i32(fp);
12567 tcg_temp_free_i32(fph);
12569 break;
12570 case OPC_MADD_S:
12571 check_cop1x(ctx);
12573 TCGv_i32 fp0 = tcg_temp_new_i32();
12574 TCGv_i32 fp1 = tcg_temp_new_i32();
12575 TCGv_i32 fp2 = tcg_temp_new_i32();
12577 gen_load_fpr32(ctx, fp0, fs);
12578 gen_load_fpr32(ctx, fp1, ft);
12579 gen_load_fpr32(ctx, fp2, fr);
12580 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12581 tcg_temp_free_i32(fp0);
12582 tcg_temp_free_i32(fp1);
12583 gen_store_fpr32(ctx, fp2, fd);
12584 tcg_temp_free_i32(fp2);
12586 break;
12587 case OPC_MADD_D:
12588 check_cop1x(ctx);
12589 check_cp1_registers(ctx, fd | fs | ft | fr);
12591 TCGv_i64 fp0 = tcg_temp_new_i64();
12592 TCGv_i64 fp1 = tcg_temp_new_i64();
12593 TCGv_i64 fp2 = tcg_temp_new_i64();
12595 gen_load_fpr64(ctx, fp0, fs);
12596 gen_load_fpr64(ctx, fp1, ft);
12597 gen_load_fpr64(ctx, fp2, fr);
12598 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12599 tcg_temp_free_i64(fp0);
12600 tcg_temp_free_i64(fp1);
12601 gen_store_fpr64(ctx, fp2, fd);
12602 tcg_temp_free_i64(fp2);
12604 break;
12605 case OPC_MADD_PS:
12606 check_ps(ctx);
12608 TCGv_i64 fp0 = tcg_temp_new_i64();
12609 TCGv_i64 fp1 = tcg_temp_new_i64();
12610 TCGv_i64 fp2 = tcg_temp_new_i64();
12612 gen_load_fpr64(ctx, fp0, fs);
12613 gen_load_fpr64(ctx, fp1, ft);
12614 gen_load_fpr64(ctx, fp2, fr);
12615 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12616 tcg_temp_free_i64(fp0);
12617 tcg_temp_free_i64(fp1);
12618 gen_store_fpr64(ctx, fp2, fd);
12619 tcg_temp_free_i64(fp2);
12621 break;
12622 case OPC_MSUB_S:
12623 check_cop1x(ctx);
12625 TCGv_i32 fp0 = tcg_temp_new_i32();
12626 TCGv_i32 fp1 = tcg_temp_new_i32();
12627 TCGv_i32 fp2 = tcg_temp_new_i32();
12629 gen_load_fpr32(ctx, fp0, fs);
12630 gen_load_fpr32(ctx, fp1, ft);
12631 gen_load_fpr32(ctx, fp2, fr);
12632 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12633 tcg_temp_free_i32(fp0);
12634 tcg_temp_free_i32(fp1);
12635 gen_store_fpr32(ctx, fp2, fd);
12636 tcg_temp_free_i32(fp2);
12638 break;
12639 case OPC_MSUB_D:
12640 check_cop1x(ctx);
12641 check_cp1_registers(ctx, fd | fs | ft | fr);
12643 TCGv_i64 fp0 = tcg_temp_new_i64();
12644 TCGv_i64 fp1 = tcg_temp_new_i64();
12645 TCGv_i64 fp2 = tcg_temp_new_i64();
12647 gen_load_fpr64(ctx, fp0, fs);
12648 gen_load_fpr64(ctx, fp1, ft);
12649 gen_load_fpr64(ctx, fp2, fr);
12650 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12651 tcg_temp_free_i64(fp0);
12652 tcg_temp_free_i64(fp1);
12653 gen_store_fpr64(ctx, fp2, fd);
12654 tcg_temp_free_i64(fp2);
12656 break;
12657 case OPC_MSUB_PS:
12658 check_ps(ctx);
12660 TCGv_i64 fp0 = tcg_temp_new_i64();
12661 TCGv_i64 fp1 = tcg_temp_new_i64();
12662 TCGv_i64 fp2 = tcg_temp_new_i64();
12664 gen_load_fpr64(ctx, fp0, fs);
12665 gen_load_fpr64(ctx, fp1, ft);
12666 gen_load_fpr64(ctx, fp2, fr);
12667 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12668 tcg_temp_free_i64(fp0);
12669 tcg_temp_free_i64(fp1);
12670 gen_store_fpr64(ctx, fp2, fd);
12671 tcg_temp_free_i64(fp2);
12673 break;
12674 case OPC_NMADD_S:
12675 check_cop1x(ctx);
12677 TCGv_i32 fp0 = tcg_temp_new_i32();
12678 TCGv_i32 fp1 = tcg_temp_new_i32();
12679 TCGv_i32 fp2 = tcg_temp_new_i32();
12681 gen_load_fpr32(ctx, fp0, fs);
12682 gen_load_fpr32(ctx, fp1, ft);
12683 gen_load_fpr32(ctx, fp2, fr);
12684 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12685 tcg_temp_free_i32(fp0);
12686 tcg_temp_free_i32(fp1);
12687 gen_store_fpr32(ctx, fp2, fd);
12688 tcg_temp_free_i32(fp2);
12690 break;
12691 case OPC_NMADD_D:
12692 check_cop1x(ctx);
12693 check_cp1_registers(ctx, fd | fs | ft | fr);
12695 TCGv_i64 fp0 = tcg_temp_new_i64();
12696 TCGv_i64 fp1 = tcg_temp_new_i64();
12697 TCGv_i64 fp2 = tcg_temp_new_i64();
12699 gen_load_fpr64(ctx, fp0, fs);
12700 gen_load_fpr64(ctx, fp1, ft);
12701 gen_load_fpr64(ctx, fp2, fr);
12702 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12703 tcg_temp_free_i64(fp0);
12704 tcg_temp_free_i64(fp1);
12705 gen_store_fpr64(ctx, fp2, fd);
12706 tcg_temp_free_i64(fp2);
12708 break;
12709 case OPC_NMADD_PS:
12710 check_ps(ctx);
12712 TCGv_i64 fp0 = tcg_temp_new_i64();
12713 TCGv_i64 fp1 = tcg_temp_new_i64();
12714 TCGv_i64 fp2 = tcg_temp_new_i64();
12716 gen_load_fpr64(ctx, fp0, fs);
12717 gen_load_fpr64(ctx, fp1, ft);
12718 gen_load_fpr64(ctx, fp2, fr);
12719 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12720 tcg_temp_free_i64(fp0);
12721 tcg_temp_free_i64(fp1);
12722 gen_store_fpr64(ctx, fp2, fd);
12723 tcg_temp_free_i64(fp2);
12725 break;
12726 case OPC_NMSUB_S:
12727 check_cop1x(ctx);
12729 TCGv_i32 fp0 = tcg_temp_new_i32();
12730 TCGv_i32 fp1 = tcg_temp_new_i32();
12731 TCGv_i32 fp2 = tcg_temp_new_i32();
12733 gen_load_fpr32(ctx, fp0, fs);
12734 gen_load_fpr32(ctx, fp1, ft);
12735 gen_load_fpr32(ctx, fp2, fr);
12736 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12737 tcg_temp_free_i32(fp0);
12738 tcg_temp_free_i32(fp1);
12739 gen_store_fpr32(ctx, fp2, fd);
12740 tcg_temp_free_i32(fp2);
12742 break;
12743 case OPC_NMSUB_D:
12744 check_cop1x(ctx);
12745 check_cp1_registers(ctx, fd | fs | ft | fr);
12747 TCGv_i64 fp0 = tcg_temp_new_i64();
12748 TCGv_i64 fp1 = tcg_temp_new_i64();
12749 TCGv_i64 fp2 = tcg_temp_new_i64();
12751 gen_load_fpr64(ctx, fp0, fs);
12752 gen_load_fpr64(ctx, fp1, ft);
12753 gen_load_fpr64(ctx, fp2, fr);
12754 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12755 tcg_temp_free_i64(fp0);
12756 tcg_temp_free_i64(fp1);
12757 gen_store_fpr64(ctx, fp2, fd);
12758 tcg_temp_free_i64(fp2);
12760 break;
12761 case OPC_NMSUB_PS:
12762 check_ps(ctx);
12764 TCGv_i64 fp0 = tcg_temp_new_i64();
12765 TCGv_i64 fp1 = tcg_temp_new_i64();
12766 TCGv_i64 fp2 = tcg_temp_new_i64();
12768 gen_load_fpr64(ctx, fp0, fs);
12769 gen_load_fpr64(ctx, fp1, ft);
12770 gen_load_fpr64(ctx, fp2, fr);
12771 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12772 tcg_temp_free_i64(fp0);
12773 tcg_temp_free_i64(fp1);
12774 gen_store_fpr64(ctx, fp2, fd);
12775 tcg_temp_free_i64(fp2);
12777 break;
12778 default:
12779 MIPS_INVAL("flt3_arith");
12780 generate_exception_end(ctx, EXCP_RI);
12781 return;
12785 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12787 TCGv t0;
12789 #if !defined(CONFIG_USER_ONLY)
12791 * The Linux kernel will emulate rdhwr if it's not supported natively.
12792 * Therefore only check the ISA in system mode.
12794 check_insn(ctx, ISA_MIPS32R2);
12795 #endif
12796 t0 = tcg_temp_new();
12798 switch (rd) {
12799 case 0:
12800 gen_helper_rdhwr_cpunum(t0, cpu_env);
12801 gen_store_gpr(t0, rt);
12802 break;
12803 case 1:
12804 gen_helper_rdhwr_synci_step(t0, cpu_env);
12805 gen_store_gpr(t0, rt);
12806 break;
12807 case 2:
12808 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12809 gen_io_start();
12811 gen_helper_rdhwr_cc(t0, cpu_env);
12812 gen_store_gpr(t0, rt);
12814 * Break the TB to be able to take timer interrupts immediately
12815 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12816 * we break completely out of translated code.
12818 gen_save_pc(ctx->base.pc_next + 4);
12819 ctx->base.is_jmp = DISAS_EXIT;
12820 break;
12821 case 3:
12822 gen_helper_rdhwr_ccres(t0, cpu_env);
12823 gen_store_gpr(t0, rt);
12824 break;
12825 case 4:
12826 check_insn(ctx, ISA_MIPS32R6);
12827 if (sel != 0) {
12829 * Performance counter registers are not implemented other than
12830 * control register 0.
12832 generate_exception(ctx, EXCP_RI);
12834 gen_helper_rdhwr_performance(t0, cpu_env);
12835 gen_store_gpr(t0, rt);
12836 break;
12837 case 5:
12838 check_insn(ctx, ISA_MIPS32R6);
12839 gen_helper_rdhwr_xnp(t0, cpu_env);
12840 gen_store_gpr(t0, rt);
12841 break;
12842 case 29:
12843 #if defined(CONFIG_USER_ONLY)
12844 tcg_gen_ld_tl(t0, cpu_env,
12845 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12846 gen_store_gpr(t0, rt);
12847 break;
12848 #else
12849 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12850 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12851 tcg_gen_ld_tl(t0, cpu_env,
12852 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12853 gen_store_gpr(t0, rt);
12854 } else {
12855 generate_exception_end(ctx, EXCP_RI);
12857 break;
12858 #endif
12859 default: /* Invalid */
12860 MIPS_INVAL("rdhwr");
12861 generate_exception_end(ctx, EXCP_RI);
12862 break;
12864 tcg_temp_free(t0);
12867 static inline void clear_branch_hflags(DisasContext *ctx)
12869 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12870 if (ctx->base.is_jmp == DISAS_NEXT) {
12871 save_cpu_state(ctx, 0);
12872 } else {
12874 * It is not safe to save ctx->hflags as hflags may be changed
12875 * in execution time by the instruction in delay / forbidden slot.
12877 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12881 static void gen_branch(DisasContext *ctx, int insn_bytes)
12883 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12884 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12885 /* Branches completion */
12886 clear_branch_hflags(ctx);
12887 ctx->base.is_jmp = DISAS_NORETURN;
12888 /* FIXME: Need to clear can_do_io. */
12889 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12890 case MIPS_HFLAG_FBNSLOT:
12891 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12892 break;
12893 case MIPS_HFLAG_B:
12894 /* unconditional branch */
12895 if (proc_hflags & MIPS_HFLAG_BX) {
12896 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12898 gen_goto_tb(ctx, 0, ctx->btarget);
12899 break;
12900 case MIPS_HFLAG_BL:
12901 /* blikely taken case */
12902 gen_goto_tb(ctx, 0, ctx->btarget);
12903 break;
12904 case MIPS_HFLAG_BC:
12905 /* Conditional branch */
12907 TCGLabel *l1 = gen_new_label();
12909 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12910 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12911 gen_set_label(l1);
12912 gen_goto_tb(ctx, 0, ctx->btarget);
12914 break;
12915 case MIPS_HFLAG_BR:
12916 /* unconditional branch to register */
12917 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12918 TCGv t0 = tcg_temp_new();
12919 TCGv_i32 t1 = tcg_temp_new_i32();
12921 tcg_gen_andi_tl(t0, btarget, 0x1);
12922 tcg_gen_trunc_tl_i32(t1, t0);
12923 tcg_temp_free(t0);
12924 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12925 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12926 tcg_gen_or_i32(hflags, hflags, t1);
12927 tcg_temp_free_i32(t1);
12929 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12930 } else {
12931 tcg_gen_mov_tl(cpu_PC, btarget);
12933 if (ctx->base.singlestep_enabled) {
12934 save_cpu_state(ctx, 0);
12935 gen_helper_raise_exception_debug(cpu_env);
12937 tcg_gen_lookup_and_goto_ptr();
12938 break;
12939 default:
12940 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12941 abort();
12946 /* Compact Branches */
12947 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12948 int rs, int rt, int32_t offset)
12950 int bcond_compute = 0;
12951 TCGv t0 = tcg_temp_new();
12952 TCGv t1 = tcg_temp_new();
12953 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12955 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12956 #ifdef MIPS_DEBUG_DISAS
12957 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12958 "\n", ctx->base.pc_next);
12959 #endif
12960 generate_exception_end(ctx, EXCP_RI);
12961 goto out;
12964 /* Load needed operands and calculate btarget */
12965 switch (opc) {
12966 /* compact branch */
12967 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12968 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12969 gen_load_gpr(t0, rs);
12970 gen_load_gpr(t1, rt);
12971 bcond_compute = 1;
12972 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12973 if (rs <= rt && rs == 0) {
12974 /* OPC_BEQZALC, OPC_BNEZALC */
12975 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12977 break;
12978 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12979 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12980 gen_load_gpr(t0, rs);
12981 gen_load_gpr(t1, rt);
12982 bcond_compute = 1;
12983 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12984 break;
12985 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12986 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12987 if (rs == 0 || rs == rt) {
12988 /* OPC_BLEZALC, OPC_BGEZALC */
12989 /* OPC_BGTZALC, OPC_BLTZALC */
12990 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12992 gen_load_gpr(t0, rs);
12993 gen_load_gpr(t1, rt);
12994 bcond_compute = 1;
12995 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12996 break;
12997 case OPC_BC:
12998 case OPC_BALC:
12999 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13000 break;
13001 case OPC_BEQZC:
13002 case OPC_BNEZC:
13003 if (rs != 0) {
13004 /* OPC_BEQZC, OPC_BNEZC */
13005 gen_load_gpr(t0, rs);
13006 bcond_compute = 1;
13007 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13008 } else {
13009 /* OPC_JIC, OPC_JIALC */
13010 TCGv tbase = tcg_temp_new();
13011 TCGv toffset = tcg_temp_new();
13013 gen_load_gpr(tbase, rt);
13014 tcg_gen_movi_tl(toffset, offset);
13015 gen_op_addr_add(ctx, btarget, tbase, toffset);
13016 tcg_temp_free(tbase);
13017 tcg_temp_free(toffset);
13019 break;
13020 default:
13021 MIPS_INVAL("Compact branch/jump");
13022 generate_exception_end(ctx, EXCP_RI);
13023 goto out;
13026 if (bcond_compute == 0) {
13027 /* Uncoditional compact branch */
13028 switch (opc) {
13029 case OPC_JIALC:
13030 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13031 /* Fallthrough */
13032 case OPC_JIC:
13033 ctx->hflags |= MIPS_HFLAG_BR;
13034 break;
13035 case OPC_BALC:
13036 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13037 /* Fallthrough */
13038 case OPC_BC:
13039 ctx->hflags |= MIPS_HFLAG_B;
13040 break;
13041 default:
13042 MIPS_INVAL("Compact branch/jump");
13043 generate_exception_end(ctx, EXCP_RI);
13044 goto out;
13047 /* Generating branch here as compact branches don't have delay slot */
13048 gen_branch(ctx, 4);
13049 } else {
13050 /* Conditional compact branch */
13051 TCGLabel *fs = gen_new_label();
13052 save_cpu_state(ctx, 0);
13054 switch (opc) {
13055 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13056 if (rs == 0 && rt != 0) {
13057 /* OPC_BLEZALC */
13058 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13059 } else if (rs != 0 && rt != 0 && rs == rt) {
13060 /* OPC_BGEZALC */
13061 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13062 } else {
13063 /* OPC_BGEUC */
13064 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13066 break;
13067 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13068 if (rs == 0 && rt != 0) {
13069 /* OPC_BGTZALC */
13070 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13071 } else if (rs != 0 && rt != 0 && rs == rt) {
13072 /* OPC_BLTZALC */
13073 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13074 } else {
13075 /* OPC_BLTUC */
13076 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13078 break;
13079 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13080 if (rs == 0 && rt != 0) {
13081 /* OPC_BLEZC */
13082 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13083 } else if (rs != 0 && rt != 0 && rs == rt) {
13084 /* OPC_BGEZC */
13085 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13086 } else {
13087 /* OPC_BGEC */
13088 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13090 break;
13091 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13092 if (rs == 0 && rt != 0) {
13093 /* OPC_BGTZC */
13094 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13095 } else if (rs != 0 && rt != 0 && rs == rt) {
13096 /* OPC_BLTZC */
13097 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13098 } else {
13099 /* OPC_BLTC */
13100 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13102 break;
13103 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13104 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13105 if (rs >= rt) {
13106 /* OPC_BOVC, OPC_BNVC */
13107 TCGv t2 = tcg_temp_new();
13108 TCGv t3 = tcg_temp_new();
13109 TCGv t4 = tcg_temp_new();
13110 TCGv input_overflow = tcg_temp_new();
13112 gen_load_gpr(t0, rs);
13113 gen_load_gpr(t1, rt);
13114 tcg_gen_ext32s_tl(t2, t0);
13115 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13116 tcg_gen_ext32s_tl(t3, t1);
13117 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13118 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13120 tcg_gen_add_tl(t4, t2, t3);
13121 tcg_gen_ext32s_tl(t4, t4);
13122 tcg_gen_xor_tl(t2, t2, t3);
13123 tcg_gen_xor_tl(t3, t4, t3);
13124 tcg_gen_andc_tl(t2, t3, t2);
13125 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13126 tcg_gen_or_tl(t4, t4, input_overflow);
13127 if (opc == OPC_BOVC) {
13128 /* OPC_BOVC */
13129 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13130 } else {
13131 /* OPC_BNVC */
13132 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13134 tcg_temp_free(input_overflow);
13135 tcg_temp_free(t4);
13136 tcg_temp_free(t3);
13137 tcg_temp_free(t2);
13138 } else if (rs < rt && rs == 0) {
13139 /* OPC_BEQZALC, OPC_BNEZALC */
13140 if (opc == OPC_BEQZALC) {
13141 /* OPC_BEQZALC */
13142 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13143 } else {
13144 /* OPC_BNEZALC */
13145 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13147 } else {
13148 /* OPC_BEQC, OPC_BNEC */
13149 if (opc == OPC_BEQC) {
13150 /* OPC_BEQC */
13151 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13152 } else {
13153 /* OPC_BNEC */
13154 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13157 break;
13158 case OPC_BEQZC:
13159 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13160 break;
13161 case OPC_BNEZC:
13162 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13163 break;
13164 default:
13165 MIPS_INVAL("Compact conditional branch/jump");
13166 generate_exception_end(ctx, EXCP_RI);
13167 goto out;
13170 /* Generating branch here as compact branches don't have delay slot */
13171 gen_goto_tb(ctx, 1, ctx->btarget);
13172 gen_set_label(fs);
13174 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13177 out:
13178 tcg_temp_free(t0);
13179 tcg_temp_free(t1);
13182 /* ISA extensions (ASEs) */
13183 /* MIPS16 extension to MIPS32 */
13185 /* MIPS16 major opcodes */
13186 enum {
13187 M16_OPC_ADDIUSP = 0x00,
13188 M16_OPC_ADDIUPC = 0x01,
13189 M16_OPC_B = 0x02,
13190 M16_OPC_JAL = 0x03,
13191 M16_OPC_BEQZ = 0x04,
13192 M16_OPC_BNEQZ = 0x05,
13193 M16_OPC_SHIFT = 0x06,
13194 M16_OPC_LD = 0x07,
13195 M16_OPC_RRIA = 0x08,
13196 M16_OPC_ADDIU8 = 0x09,
13197 M16_OPC_SLTI = 0x0a,
13198 M16_OPC_SLTIU = 0x0b,
13199 M16_OPC_I8 = 0x0c,
13200 M16_OPC_LI = 0x0d,
13201 M16_OPC_CMPI = 0x0e,
13202 M16_OPC_SD = 0x0f,
13203 M16_OPC_LB = 0x10,
13204 M16_OPC_LH = 0x11,
13205 M16_OPC_LWSP = 0x12,
13206 M16_OPC_LW = 0x13,
13207 M16_OPC_LBU = 0x14,
13208 M16_OPC_LHU = 0x15,
13209 M16_OPC_LWPC = 0x16,
13210 M16_OPC_LWU = 0x17,
13211 M16_OPC_SB = 0x18,
13212 M16_OPC_SH = 0x19,
13213 M16_OPC_SWSP = 0x1a,
13214 M16_OPC_SW = 0x1b,
13215 M16_OPC_RRR = 0x1c,
13216 M16_OPC_RR = 0x1d,
13217 M16_OPC_EXTEND = 0x1e,
13218 M16_OPC_I64 = 0x1f
13221 /* I8 funct field */
13222 enum {
13223 I8_BTEQZ = 0x0,
13224 I8_BTNEZ = 0x1,
13225 I8_SWRASP = 0x2,
13226 I8_ADJSP = 0x3,
13227 I8_SVRS = 0x4,
13228 I8_MOV32R = 0x5,
13229 I8_MOVR32 = 0x7
13232 /* RRR f field */
13233 enum {
13234 RRR_DADDU = 0x0,
13235 RRR_ADDU = 0x1,
13236 RRR_DSUBU = 0x2,
13237 RRR_SUBU = 0x3
13240 /* RR funct field */
13241 enum {
13242 RR_JR = 0x00,
13243 RR_SDBBP = 0x01,
13244 RR_SLT = 0x02,
13245 RR_SLTU = 0x03,
13246 RR_SLLV = 0x04,
13247 RR_BREAK = 0x05,
13248 RR_SRLV = 0x06,
13249 RR_SRAV = 0x07,
13250 RR_DSRL = 0x08,
13251 RR_CMP = 0x0a,
13252 RR_NEG = 0x0b,
13253 RR_AND = 0x0c,
13254 RR_OR = 0x0d,
13255 RR_XOR = 0x0e,
13256 RR_NOT = 0x0f,
13257 RR_MFHI = 0x10,
13258 RR_CNVT = 0x11,
13259 RR_MFLO = 0x12,
13260 RR_DSRA = 0x13,
13261 RR_DSLLV = 0x14,
13262 RR_DSRLV = 0x16,
13263 RR_DSRAV = 0x17,
13264 RR_MULT = 0x18,
13265 RR_MULTU = 0x19,
13266 RR_DIV = 0x1a,
13267 RR_DIVU = 0x1b,
13268 RR_DMULT = 0x1c,
13269 RR_DMULTU = 0x1d,
13270 RR_DDIV = 0x1e,
13271 RR_DDIVU = 0x1f
13274 /* I64 funct field */
13275 enum {
13276 I64_LDSP = 0x0,
13277 I64_SDSP = 0x1,
13278 I64_SDRASP = 0x2,
13279 I64_DADJSP = 0x3,
13280 I64_LDPC = 0x4,
13281 I64_DADDIU5 = 0x5,
13282 I64_DADDIUPC = 0x6,
13283 I64_DADDIUSP = 0x7
13286 /* RR ry field for CNVT */
13287 enum {
13288 RR_RY_CNVT_ZEB = 0x0,
13289 RR_RY_CNVT_ZEH = 0x1,
13290 RR_RY_CNVT_ZEW = 0x2,
13291 RR_RY_CNVT_SEB = 0x4,
13292 RR_RY_CNVT_SEH = 0x5,
13293 RR_RY_CNVT_SEW = 0x6,
13296 static int xlat(int r)
13298 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13300 return map[r];
13303 static void gen_mips16_save(DisasContext *ctx,
13304 int xsregs, int aregs,
13305 int do_ra, int do_s0, int do_s1,
13306 int framesize)
13308 TCGv t0 = tcg_temp_new();
13309 TCGv t1 = tcg_temp_new();
13310 TCGv t2 = tcg_temp_new();
13311 int args, astatic;
13313 switch (aregs) {
13314 case 0:
13315 case 1:
13316 case 2:
13317 case 3:
13318 case 11:
13319 args = 0;
13320 break;
13321 case 4:
13322 case 5:
13323 case 6:
13324 case 7:
13325 args = 1;
13326 break;
13327 case 8:
13328 case 9:
13329 case 10:
13330 args = 2;
13331 break;
13332 case 12:
13333 case 13:
13334 args = 3;
13335 break;
13336 case 14:
13337 args = 4;
13338 break;
13339 default:
13340 generate_exception_end(ctx, EXCP_RI);
13341 return;
13344 switch (args) {
13345 case 4:
13346 gen_base_offset_addr(ctx, t0, 29, 12);
13347 gen_load_gpr(t1, 7);
13348 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13349 /* Fall through */
13350 case 3:
13351 gen_base_offset_addr(ctx, t0, 29, 8);
13352 gen_load_gpr(t1, 6);
13353 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13354 /* Fall through */
13355 case 2:
13356 gen_base_offset_addr(ctx, t0, 29, 4);
13357 gen_load_gpr(t1, 5);
13358 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13359 /* Fall through */
13360 case 1:
13361 gen_base_offset_addr(ctx, t0, 29, 0);
13362 gen_load_gpr(t1, 4);
13363 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13366 gen_load_gpr(t0, 29);
13368 #define DECR_AND_STORE(reg) do { \
13369 tcg_gen_movi_tl(t2, -4); \
13370 gen_op_addr_add(ctx, t0, t0, t2); \
13371 gen_load_gpr(t1, reg); \
13372 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13373 } while (0)
13375 if (do_ra) {
13376 DECR_AND_STORE(31);
13379 switch (xsregs) {
13380 case 7:
13381 DECR_AND_STORE(30);
13382 /* Fall through */
13383 case 6:
13384 DECR_AND_STORE(23);
13385 /* Fall through */
13386 case 5:
13387 DECR_AND_STORE(22);
13388 /* Fall through */
13389 case 4:
13390 DECR_AND_STORE(21);
13391 /* Fall through */
13392 case 3:
13393 DECR_AND_STORE(20);
13394 /* Fall through */
13395 case 2:
13396 DECR_AND_STORE(19);
13397 /* Fall through */
13398 case 1:
13399 DECR_AND_STORE(18);
13402 if (do_s1) {
13403 DECR_AND_STORE(17);
13405 if (do_s0) {
13406 DECR_AND_STORE(16);
13409 switch (aregs) {
13410 case 0:
13411 case 4:
13412 case 8:
13413 case 12:
13414 case 14:
13415 astatic = 0;
13416 break;
13417 case 1:
13418 case 5:
13419 case 9:
13420 case 13:
13421 astatic = 1;
13422 break;
13423 case 2:
13424 case 6:
13425 case 10:
13426 astatic = 2;
13427 break;
13428 case 3:
13429 case 7:
13430 astatic = 3;
13431 break;
13432 case 11:
13433 astatic = 4;
13434 break;
13435 default:
13436 generate_exception_end(ctx, EXCP_RI);
13437 return;
13440 if (astatic > 0) {
13441 DECR_AND_STORE(7);
13442 if (astatic > 1) {
13443 DECR_AND_STORE(6);
13444 if (astatic > 2) {
13445 DECR_AND_STORE(5);
13446 if (astatic > 3) {
13447 DECR_AND_STORE(4);
13452 #undef DECR_AND_STORE
13454 tcg_gen_movi_tl(t2, -framesize);
13455 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13456 tcg_temp_free(t0);
13457 tcg_temp_free(t1);
13458 tcg_temp_free(t2);
13461 static void gen_mips16_restore(DisasContext *ctx,
13462 int xsregs, int aregs,
13463 int do_ra, int do_s0, int do_s1,
13464 int framesize)
13466 int astatic;
13467 TCGv t0 = tcg_temp_new();
13468 TCGv t1 = tcg_temp_new();
13469 TCGv t2 = tcg_temp_new();
13471 tcg_gen_movi_tl(t2, framesize);
13472 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13474 #define DECR_AND_LOAD(reg) do { \
13475 tcg_gen_movi_tl(t2, -4); \
13476 gen_op_addr_add(ctx, t0, t0, t2); \
13477 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13478 gen_store_gpr(t1, reg); \
13479 } while (0)
13481 if (do_ra) {
13482 DECR_AND_LOAD(31);
13485 switch (xsregs) {
13486 case 7:
13487 DECR_AND_LOAD(30);
13488 /* Fall through */
13489 case 6:
13490 DECR_AND_LOAD(23);
13491 /* Fall through */
13492 case 5:
13493 DECR_AND_LOAD(22);
13494 /* Fall through */
13495 case 4:
13496 DECR_AND_LOAD(21);
13497 /* Fall through */
13498 case 3:
13499 DECR_AND_LOAD(20);
13500 /* Fall through */
13501 case 2:
13502 DECR_AND_LOAD(19);
13503 /* Fall through */
13504 case 1:
13505 DECR_AND_LOAD(18);
13508 if (do_s1) {
13509 DECR_AND_LOAD(17);
13511 if (do_s0) {
13512 DECR_AND_LOAD(16);
13515 switch (aregs) {
13516 case 0:
13517 case 4:
13518 case 8:
13519 case 12:
13520 case 14:
13521 astatic = 0;
13522 break;
13523 case 1:
13524 case 5:
13525 case 9:
13526 case 13:
13527 astatic = 1;
13528 break;
13529 case 2:
13530 case 6:
13531 case 10:
13532 astatic = 2;
13533 break;
13534 case 3:
13535 case 7:
13536 astatic = 3;
13537 break;
13538 case 11:
13539 astatic = 4;
13540 break;
13541 default:
13542 generate_exception_end(ctx, EXCP_RI);
13543 return;
13546 if (astatic > 0) {
13547 DECR_AND_LOAD(7);
13548 if (astatic > 1) {
13549 DECR_AND_LOAD(6);
13550 if (astatic > 2) {
13551 DECR_AND_LOAD(5);
13552 if (astatic > 3) {
13553 DECR_AND_LOAD(4);
13558 #undef DECR_AND_LOAD
13560 tcg_gen_movi_tl(t2, framesize);
13561 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13562 tcg_temp_free(t0);
13563 tcg_temp_free(t1);
13564 tcg_temp_free(t2);
13567 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13568 int is_64_bit, int extended)
13570 TCGv t0;
13572 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13573 generate_exception_end(ctx, EXCP_RI);
13574 return;
13577 t0 = tcg_temp_new();
13579 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13580 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13581 if (!is_64_bit) {
13582 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13585 tcg_temp_free(t0);
13588 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13589 int16_t offset)
13591 TCGv_i32 t0 = tcg_const_i32(op);
13592 TCGv t1 = tcg_temp_new();
13593 gen_base_offset_addr(ctx, t1, base, offset);
13594 gen_helper_cache(cpu_env, t1, t0);
13597 #if defined(TARGET_MIPS64)
13598 static void decode_i64_mips16(DisasContext *ctx,
13599 int ry, int funct, int16_t offset,
13600 int extended)
13602 switch (funct) {
13603 case I64_LDSP:
13604 check_insn(ctx, ISA_MIPS3);
13605 check_mips_64(ctx);
13606 offset = extended ? offset : offset << 3;
13607 gen_ld(ctx, OPC_LD, ry, 29, offset);
13608 break;
13609 case I64_SDSP:
13610 check_insn(ctx, ISA_MIPS3);
13611 check_mips_64(ctx);
13612 offset = extended ? offset : offset << 3;
13613 gen_st(ctx, OPC_SD, ry, 29, offset);
13614 break;
13615 case I64_SDRASP:
13616 check_insn(ctx, ISA_MIPS3);
13617 check_mips_64(ctx);
13618 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13619 gen_st(ctx, OPC_SD, 31, 29, offset);
13620 break;
13621 case I64_DADJSP:
13622 check_insn(ctx, ISA_MIPS3);
13623 check_mips_64(ctx);
13624 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13625 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13626 break;
13627 case I64_LDPC:
13628 check_insn(ctx, ISA_MIPS3);
13629 check_mips_64(ctx);
13630 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13631 generate_exception_end(ctx, EXCP_RI);
13632 } else {
13633 offset = extended ? offset : offset << 3;
13634 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13636 break;
13637 case I64_DADDIU5:
13638 check_insn(ctx, ISA_MIPS3);
13639 check_mips_64(ctx);
13640 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13641 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13642 break;
13643 case I64_DADDIUPC:
13644 check_insn(ctx, ISA_MIPS3);
13645 check_mips_64(ctx);
13646 offset = extended ? offset : offset << 2;
13647 gen_addiupc(ctx, ry, offset, 1, extended);
13648 break;
13649 case I64_DADDIUSP:
13650 check_insn(ctx, ISA_MIPS3);
13651 check_mips_64(ctx);
13652 offset = extended ? offset : offset << 2;
13653 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13654 break;
13657 #endif
13659 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13661 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13662 int op, rx, ry, funct, sa;
13663 int16_t imm, offset;
13665 ctx->opcode = (ctx->opcode << 16) | extend;
13666 op = (ctx->opcode >> 11) & 0x1f;
13667 sa = (ctx->opcode >> 22) & 0x1f;
13668 funct = (ctx->opcode >> 8) & 0x7;
13669 rx = xlat((ctx->opcode >> 8) & 0x7);
13670 ry = xlat((ctx->opcode >> 5) & 0x7);
13671 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13672 | ((ctx->opcode >> 21) & 0x3f) << 5
13673 | (ctx->opcode & 0x1f));
13676 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13677 * counterparts.
13679 switch (op) {
13680 case M16_OPC_ADDIUSP:
13681 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13682 break;
13683 case M16_OPC_ADDIUPC:
13684 gen_addiupc(ctx, rx, imm, 0, 1);
13685 break;
13686 case M16_OPC_B:
13687 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13688 /* No delay slot, so just process as a normal instruction */
13689 break;
13690 case M16_OPC_BEQZ:
13691 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13692 /* No delay slot, so just process as a normal instruction */
13693 break;
13694 case M16_OPC_BNEQZ:
13695 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13696 /* No delay slot, so just process as a normal instruction */
13697 break;
13698 case M16_OPC_SHIFT:
13699 switch (ctx->opcode & 0x3) {
13700 case 0x0:
13701 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13702 break;
13703 case 0x1:
13704 #if defined(TARGET_MIPS64)
13705 check_mips_64(ctx);
13706 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13707 #else
13708 generate_exception_end(ctx, EXCP_RI);
13709 #endif
13710 break;
13711 case 0x2:
13712 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13713 break;
13714 case 0x3:
13715 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13716 break;
13718 break;
13719 #if defined(TARGET_MIPS64)
13720 case M16_OPC_LD:
13721 check_insn(ctx, ISA_MIPS3);
13722 check_mips_64(ctx);
13723 gen_ld(ctx, OPC_LD, ry, rx, offset);
13724 break;
13725 #endif
13726 case M16_OPC_RRIA:
13727 imm = ctx->opcode & 0xf;
13728 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13729 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13730 imm = (int16_t) (imm << 1) >> 1;
13731 if ((ctx->opcode >> 4) & 0x1) {
13732 #if defined(TARGET_MIPS64)
13733 check_mips_64(ctx);
13734 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13735 #else
13736 generate_exception_end(ctx, EXCP_RI);
13737 #endif
13738 } else {
13739 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13741 break;
13742 case M16_OPC_ADDIU8:
13743 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13744 break;
13745 case M16_OPC_SLTI:
13746 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13747 break;
13748 case M16_OPC_SLTIU:
13749 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13750 break;
13751 case M16_OPC_I8:
13752 switch (funct) {
13753 case I8_BTEQZ:
13754 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13755 break;
13756 case I8_BTNEZ:
13757 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13758 break;
13759 case I8_SWRASP:
13760 gen_st(ctx, OPC_SW, 31, 29, imm);
13761 break;
13762 case I8_ADJSP:
13763 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13764 break;
13765 case I8_SVRS:
13766 check_insn(ctx, ISA_MIPS32);
13768 int xsregs = (ctx->opcode >> 24) & 0x7;
13769 int aregs = (ctx->opcode >> 16) & 0xf;
13770 int do_ra = (ctx->opcode >> 6) & 0x1;
13771 int do_s0 = (ctx->opcode >> 5) & 0x1;
13772 int do_s1 = (ctx->opcode >> 4) & 0x1;
13773 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13774 | (ctx->opcode & 0xf)) << 3;
13776 if (ctx->opcode & (1 << 7)) {
13777 gen_mips16_save(ctx, xsregs, aregs,
13778 do_ra, do_s0, do_s1,
13779 framesize);
13780 } else {
13781 gen_mips16_restore(ctx, xsregs, aregs,
13782 do_ra, do_s0, do_s1,
13783 framesize);
13786 break;
13787 default:
13788 generate_exception_end(ctx, EXCP_RI);
13789 break;
13791 break;
13792 case M16_OPC_LI:
13793 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13794 break;
13795 case M16_OPC_CMPI:
13796 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13797 break;
13798 #if defined(TARGET_MIPS64)
13799 case M16_OPC_SD:
13800 check_insn(ctx, ISA_MIPS3);
13801 check_mips_64(ctx);
13802 gen_st(ctx, OPC_SD, ry, rx, offset);
13803 break;
13804 #endif
13805 case M16_OPC_LB:
13806 gen_ld(ctx, OPC_LB, ry, rx, offset);
13807 break;
13808 case M16_OPC_LH:
13809 gen_ld(ctx, OPC_LH, ry, rx, offset);
13810 break;
13811 case M16_OPC_LWSP:
13812 gen_ld(ctx, OPC_LW, rx, 29, offset);
13813 break;
13814 case M16_OPC_LW:
13815 gen_ld(ctx, OPC_LW, ry, rx, offset);
13816 break;
13817 case M16_OPC_LBU:
13818 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13819 break;
13820 case M16_OPC_LHU:
13821 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13822 break;
13823 case M16_OPC_LWPC:
13824 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13825 break;
13826 #if defined(TARGET_MIPS64)
13827 case M16_OPC_LWU:
13828 check_insn(ctx, ISA_MIPS3);
13829 check_mips_64(ctx);
13830 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13831 break;
13832 #endif
13833 case M16_OPC_SB:
13834 gen_st(ctx, OPC_SB, ry, rx, offset);
13835 break;
13836 case M16_OPC_SH:
13837 gen_st(ctx, OPC_SH, ry, rx, offset);
13838 break;
13839 case M16_OPC_SWSP:
13840 gen_st(ctx, OPC_SW, rx, 29, offset);
13841 break;
13842 case M16_OPC_SW:
13843 gen_st(ctx, OPC_SW, ry, rx, offset);
13844 break;
13845 #if defined(TARGET_MIPS64)
13846 case M16_OPC_I64:
13847 decode_i64_mips16(ctx, ry, funct, offset, 1);
13848 break;
13849 #endif
13850 default:
13851 generate_exception_end(ctx, EXCP_RI);
13852 break;
13855 return 4;
13858 static inline bool is_uhi(int sdbbp_code)
13860 #ifdef CONFIG_USER_ONLY
13861 return false;
13862 #else
13863 return semihosting_enabled() && sdbbp_code == 1;
13864 #endif
13867 #ifdef CONFIG_USER_ONLY
13868 /* The above should dead-code away any calls to this..*/
13869 static inline void gen_helper_do_semihosting(void *env)
13871 g_assert_not_reached();
13873 #endif
13875 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13877 int rx, ry;
13878 int sa;
13879 int op, cnvt_op, op1, offset;
13880 int funct;
13881 int n_bytes;
13883 op = (ctx->opcode >> 11) & 0x1f;
13884 sa = (ctx->opcode >> 2) & 0x7;
13885 sa = sa == 0 ? 8 : sa;
13886 rx = xlat((ctx->opcode >> 8) & 0x7);
13887 cnvt_op = (ctx->opcode >> 5) & 0x7;
13888 ry = xlat((ctx->opcode >> 5) & 0x7);
13889 op1 = offset = ctx->opcode & 0x1f;
13891 n_bytes = 2;
13893 switch (op) {
13894 case M16_OPC_ADDIUSP:
13896 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13898 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13900 break;
13901 case M16_OPC_ADDIUPC:
13902 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13903 break;
13904 case M16_OPC_B:
13905 offset = (ctx->opcode & 0x7ff) << 1;
13906 offset = (int16_t)(offset << 4) >> 4;
13907 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13908 /* No delay slot, so just process as a normal instruction */
13909 break;
13910 case M16_OPC_JAL:
13911 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13912 offset = (((ctx->opcode & 0x1f) << 21)
13913 | ((ctx->opcode >> 5) & 0x1f) << 16
13914 | offset) << 2;
13915 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13916 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13917 n_bytes = 4;
13918 break;
13919 case M16_OPC_BEQZ:
13920 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13921 ((int8_t)ctx->opcode) << 1, 0);
13922 /* No delay slot, so just process as a normal instruction */
13923 break;
13924 case M16_OPC_BNEQZ:
13925 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13926 ((int8_t)ctx->opcode) << 1, 0);
13927 /* No delay slot, so just process as a normal instruction */
13928 break;
13929 case M16_OPC_SHIFT:
13930 switch (ctx->opcode & 0x3) {
13931 case 0x0:
13932 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13933 break;
13934 case 0x1:
13935 #if defined(TARGET_MIPS64)
13936 check_insn(ctx, ISA_MIPS3);
13937 check_mips_64(ctx);
13938 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13939 #else
13940 generate_exception_end(ctx, EXCP_RI);
13941 #endif
13942 break;
13943 case 0x2:
13944 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13945 break;
13946 case 0x3:
13947 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13948 break;
13950 break;
13951 #if defined(TARGET_MIPS64)
13952 case M16_OPC_LD:
13953 check_insn(ctx, ISA_MIPS3);
13954 check_mips_64(ctx);
13955 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13956 break;
13957 #endif
13958 case M16_OPC_RRIA:
13960 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13962 if ((ctx->opcode >> 4) & 1) {
13963 #if defined(TARGET_MIPS64)
13964 check_insn(ctx, ISA_MIPS3);
13965 check_mips_64(ctx);
13966 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13967 #else
13968 generate_exception_end(ctx, EXCP_RI);
13969 #endif
13970 } else {
13971 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13974 break;
13975 case M16_OPC_ADDIU8:
13977 int16_t imm = (int8_t) ctx->opcode;
13979 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13981 break;
13982 case M16_OPC_SLTI:
13984 int16_t imm = (uint8_t) ctx->opcode;
13985 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13987 break;
13988 case M16_OPC_SLTIU:
13990 int16_t imm = (uint8_t) ctx->opcode;
13991 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13993 break;
13994 case M16_OPC_I8:
13996 int reg32;
13998 funct = (ctx->opcode >> 8) & 0x7;
13999 switch (funct) {
14000 case I8_BTEQZ:
14001 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14002 ((int8_t)ctx->opcode) << 1, 0);
14003 break;
14004 case I8_BTNEZ:
14005 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14006 ((int8_t)ctx->opcode) << 1, 0);
14007 break;
14008 case I8_SWRASP:
14009 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14010 break;
14011 case I8_ADJSP:
14012 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14013 ((int8_t)ctx->opcode) << 3);
14014 break;
14015 case I8_SVRS:
14016 check_insn(ctx, ISA_MIPS32);
14018 int do_ra = ctx->opcode & (1 << 6);
14019 int do_s0 = ctx->opcode & (1 << 5);
14020 int do_s1 = ctx->opcode & (1 << 4);
14021 int framesize = ctx->opcode & 0xf;
14023 if (framesize == 0) {
14024 framesize = 128;
14025 } else {
14026 framesize = framesize << 3;
14029 if (ctx->opcode & (1 << 7)) {
14030 gen_mips16_save(ctx, 0, 0,
14031 do_ra, do_s0, do_s1, framesize);
14032 } else {
14033 gen_mips16_restore(ctx, 0, 0,
14034 do_ra, do_s0, do_s1, framesize);
14037 break;
14038 case I8_MOV32R:
14040 int rz = xlat(ctx->opcode & 0x7);
14042 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14043 ((ctx->opcode >> 5) & 0x7);
14044 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14046 break;
14047 case I8_MOVR32:
14048 reg32 = ctx->opcode & 0x1f;
14049 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14050 break;
14051 default:
14052 generate_exception_end(ctx, EXCP_RI);
14053 break;
14056 break;
14057 case M16_OPC_LI:
14059 int16_t imm = (uint8_t) ctx->opcode;
14061 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14063 break;
14064 case M16_OPC_CMPI:
14066 int16_t imm = (uint8_t) ctx->opcode;
14067 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14069 break;
14070 #if defined(TARGET_MIPS64)
14071 case M16_OPC_SD:
14072 check_insn(ctx, ISA_MIPS3);
14073 check_mips_64(ctx);
14074 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14075 break;
14076 #endif
14077 case M16_OPC_LB:
14078 gen_ld(ctx, OPC_LB, ry, rx, offset);
14079 break;
14080 case M16_OPC_LH:
14081 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14082 break;
14083 case M16_OPC_LWSP:
14084 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14085 break;
14086 case M16_OPC_LW:
14087 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14088 break;
14089 case M16_OPC_LBU:
14090 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14091 break;
14092 case M16_OPC_LHU:
14093 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14094 break;
14095 case M16_OPC_LWPC:
14096 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14097 break;
14098 #if defined(TARGET_MIPS64)
14099 case M16_OPC_LWU:
14100 check_insn(ctx, ISA_MIPS3);
14101 check_mips_64(ctx);
14102 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14103 break;
14104 #endif
14105 case M16_OPC_SB:
14106 gen_st(ctx, OPC_SB, ry, rx, offset);
14107 break;
14108 case M16_OPC_SH:
14109 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14110 break;
14111 case M16_OPC_SWSP:
14112 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14113 break;
14114 case M16_OPC_SW:
14115 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14116 break;
14117 case M16_OPC_RRR:
14119 int rz = xlat((ctx->opcode >> 2) & 0x7);
14120 int mips32_op;
14122 switch (ctx->opcode & 0x3) {
14123 case RRR_ADDU:
14124 mips32_op = OPC_ADDU;
14125 break;
14126 case RRR_SUBU:
14127 mips32_op = OPC_SUBU;
14128 break;
14129 #if defined(TARGET_MIPS64)
14130 case RRR_DADDU:
14131 mips32_op = OPC_DADDU;
14132 check_insn(ctx, ISA_MIPS3);
14133 check_mips_64(ctx);
14134 break;
14135 case RRR_DSUBU:
14136 mips32_op = OPC_DSUBU;
14137 check_insn(ctx, ISA_MIPS3);
14138 check_mips_64(ctx);
14139 break;
14140 #endif
14141 default:
14142 generate_exception_end(ctx, EXCP_RI);
14143 goto done;
14146 gen_arith(ctx, mips32_op, rz, rx, ry);
14147 done:
14150 break;
14151 case M16_OPC_RR:
14152 switch (op1) {
14153 case RR_JR:
14155 int nd = (ctx->opcode >> 7) & 0x1;
14156 int link = (ctx->opcode >> 6) & 0x1;
14157 int ra = (ctx->opcode >> 5) & 0x1;
14159 if (nd) {
14160 check_insn(ctx, ISA_MIPS32);
14163 if (link) {
14164 op = OPC_JALR;
14165 } else {
14166 op = OPC_JR;
14169 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14170 (nd ? 0 : 2));
14172 break;
14173 case RR_SDBBP:
14174 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14175 gen_helper_do_semihosting(cpu_env);
14176 } else {
14178 * XXX: not clear which exception should be raised
14179 * when in debug mode...
14181 check_insn(ctx, ISA_MIPS32);
14182 generate_exception_end(ctx, EXCP_DBp);
14184 break;
14185 case RR_SLT:
14186 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14187 break;
14188 case RR_SLTU:
14189 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14190 break;
14191 case RR_BREAK:
14192 generate_exception_end(ctx, EXCP_BREAK);
14193 break;
14194 case RR_SLLV:
14195 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14196 break;
14197 case RR_SRLV:
14198 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14199 break;
14200 case RR_SRAV:
14201 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14202 break;
14203 #if defined(TARGET_MIPS64)
14204 case RR_DSRL:
14205 check_insn(ctx, ISA_MIPS3);
14206 check_mips_64(ctx);
14207 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14208 break;
14209 #endif
14210 case RR_CMP:
14211 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14212 break;
14213 case RR_NEG:
14214 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14215 break;
14216 case RR_AND:
14217 gen_logic(ctx, OPC_AND, rx, rx, ry);
14218 break;
14219 case RR_OR:
14220 gen_logic(ctx, OPC_OR, rx, rx, ry);
14221 break;
14222 case RR_XOR:
14223 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14224 break;
14225 case RR_NOT:
14226 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14227 break;
14228 case RR_MFHI:
14229 gen_HILO(ctx, OPC_MFHI, 0, rx);
14230 break;
14231 case RR_CNVT:
14232 check_insn(ctx, ISA_MIPS32);
14233 switch (cnvt_op) {
14234 case RR_RY_CNVT_ZEB:
14235 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14236 break;
14237 case RR_RY_CNVT_ZEH:
14238 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14239 break;
14240 case RR_RY_CNVT_SEB:
14241 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14242 break;
14243 case RR_RY_CNVT_SEH:
14244 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14245 break;
14246 #if defined(TARGET_MIPS64)
14247 case RR_RY_CNVT_ZEW:
14248 check_insn(ctx, ISA_MIPS64);
14249 check_mips_64(ctx);
14250 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14251 break;
14252 case RR_RY_CNVT_SEW:
14253 check_insn(ctx, ISA_MIPS64);
14254 check_mips_64(ctx);
14255 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14256 break;
14257 #endif
14258 default:
14259 generate_exception_end(ctx, EXCP_RI);
14260 break;
14262 break;
14263 case RR_MFLO:
14264 gen_HILO(ctx, OPC_MFLO, 0, rx);
14265 break;
14266 #if defined(TARGET_MIPS64)
14267 case RR_DSRA:
14268 check_insn(ctx, ISA_MIPS3);
14269 check_mips_64(ctx);
14270 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14271 break;
14272 case RR_DSLLV:
14273 check_insn(ctx, ISA_MIPS3);
14274 check_mips_64(ctx);
14275 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14276 break;
14277 case RR_DSRLV:
14278 check_insn(ctx, ISA_MIPS3);
14279 check_mips_64(ctx);
14280 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14281 break;
14282 case RR_DSRAV:
14283 check_insn(ctx, ISA_MIPS3);
14284 check_mips_64(ctx);
14285 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14286 break;
14287 #endif
14288 case RR_MULT:
14289 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14290 break;
14291 case RR_MULTU:
14292 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14293 break;
14294 case RR_DIV:
14295 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14296 break;
14297 case RR_DIVU:
14298 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14299 break;
14300 #if defined(TARGET_MIPS64)
14301 case RR_DMULT:
14302 check_insn(ctx, ISA_MIPS3);
14303 check_mips_64(ctx);
14304 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14305 break;
14306 case RR_DMULTU:
14307 check_insn(ctx, ISA_MIPS3);
14308 check_mips_64(ctx);
14309 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14310 break;
14311 case RR_DDIV:
14312 check_insn(ctx, ISA_MIPS3);
14313 check_mips_64(ctx);
14314 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14315 break;
14316 case RR_DDIVU:
14317 check_insn(ctx, ISA_MIPS3);
14318 check_mips_64(ctx);
14319 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14320 break;
14321 #endif
14322 default:
14323 generate_exception_end(ctx, EXCP_RI);
14324 break;
14326 break;
14327 case M16_OPC_EXTEND:
14328 decode_extended_mips16_opc(env, ctx);
14329 n_bytes = 4;
14330 break;
14331 #if defined(TARGET_MIPS64)
14332 case M16_OPC_I64:
14333 funct = (ctx->opcode >> 8) & 0x7;
14334 decode_i64_mips16(ctx, ry, funct, offset, 0);
14335 break;
14336 #endif
14337 default:
14338 generate_exception_end(ctx, EXCP_RI);
14339 break;
14342 return n_bytes;
14345 /* microMIPS extension to MIPS32/MIPS64 */
14348 * microMIPS32/microMIPS64 major opcodes
14350 * 1. MIPS Architecture for Programmers Volume II-B:
14351 * The microMIPS32 Instruction Set (Revision 3.05)
14353 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14355 * 2. MIPS Architecture For Programmers Volume II-A:
14356 * The MIPS64 Instruction Set (Revision 3.51)
14359 enum {
14360 POOL32A = 0x00,
14361 POOL16A = 0x01,
14362 LBU16 = 0x02,
14363 MOVE16 = 0x03,
14364 ADDI32 = 0x04,
14365 R6_LUI = 0x04,
14366 AUI = 0x04,
14367 LBU32 = 0x05,
14368 SB32 = 0x06,
14369 LB32 = 0x07,
14371 POOL32B = 0x08,
14372 POOL16B = 0x09,
14373 LHU16 = 0x0a,
14374 ANDI16 = 0x0b,
14375 ADDIU32 = 0x0c,
14376 LHU32 = 0x0d,
14377 SH32 = 0x0e,
14378 LH32 = 0x0f,
14380 POOL32I = 0x10,
14381 POOL16C = 0x11,
14382 LWSP16 = 0x12,
14383 POOL16D = 0x13,
14384 ORI32 = 0x14,
14385 POOL32F = 0x15,
14386 POOL32S = 0x16, /* MIPS64 */
14387 DADDIU32 = 0x17, /* MIPS64 */
14389 POOL32C = 0x18,
14390 LWGP16 = 0x19,
14391 LW16 = 0x1a,
14392 POOL16E = 0x1b,
14393 XORI32 = 0x1c,
14394 JALS32 = 0x1d,
14395 BOVC = 0x1d,
14396 BEQC = 0x1d,
14397 BEQZALC = 0x1d,
14398 ADDIUPC = 0x1e,
14399 PCREL = 0x1e,
14400 BNVC = 0x1f,
14401 BNEC = 0x1f,
14402 BNEZALC = 0x1f,
14404 R6_BEQZC = 0x20,
14405 JIC = 0x20,
14406 POOL16F = 0x21,
14407 SB16 = 0x22,
14408 BEQZ16 = 0x23,
14409 BEQZC16 = 0x23,
14410 SLTI32 = 0x24,
14411 BEQ32 = 0x25,
14412 BC = 0x25,
14413 SWC132 = 0x26,
14414 LWC132 = 0x27,
14416 /* 0x29 is reserved */
14417 RES_29 = 0x29,
14418 R6_BNEZC = 0x28,
14419 JIALC = 0x28,
14420 SH16 = 0x2a,
14421 BNEZ16 = 0x2b,
14422 BNEZC16 = 0x2b,
14423 SLTIU32 = 0x2c,
14424 BNE32 = 0x2d,
14425 BALC = 0x2d,
14426 SDC132 = 0x2e,
14427 LDC132 = 0x2f,
14429 /* 0x31 is reserved */
14430 RES_31 = 0x31,
14431 BLEZALC = 0x30,
14432 BGEZALC = 0x30,
14433 BGEUC = 0x30,
14434 SWSP16 = 0x32,
14435 B16 = 0x33,
14436 BC16 = 0x33,
14437 ANDI32 = 0x34,
14438 J32 = 0x35,
14439 BGTZC = 0x35,
14440 BLTZC = 0x35,
14441 BLTC = 0x35,
14442 SD32 = 0x36, /* MIPS64 */
14443 LD32 = 0x37, /* MIPS64 */
14445 /* 0x39 is reserved */
14446 RES_39 = 0x39,
14447 BGTZALC = 0x38,
14448 BLTZALC = 0x38,
14449 BLTUC = 0x38,
14450 SW16 = 0x3a,
14451 LI16 = 0x3b,
14452 JALX32 = 0x3c,
14453 JAL32 = 0x3d,
14454 BLEZC = 0x3d,
14455 BGEZC = 0x3d,
14456 BGEC = 0x3d,
14457 SW32 = 0x3e,
14458 LW32 = 0x3f
14461 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14462 enum {
14463 ADDIUPC_00 = 0x00,
14464 ADDIUPC_01 = 0x01,
14465 ADDIUPC_02 = 0x02,
14466 ADDIUPC_03 = 0x03,
14467 ADDIUPC_04 = 0x04,
14468 ADDIUPC_05 = 0x05,
14469 ADDIUPC_06 = 0x06,
14470 ADDIUPC_07 = 0x07,
14471 AUIPC = 0x1e,
14472 ALUIPC = 0x1f,
14473 LWPC_08 = 0x08,
14474 LWPC_09 = 0x09,
14475 LWPC_0A = 0x0A,
14476 LWPC_0B = 0x0B,
14477 LWPC_0C = 0x0C,
14478 LWPC_0D = 0x0D,
14479 LWPC_0E = 0x0E,
14480 LWPC_0F = 0x0F,
14483 /* POOL32A encoding of minor opcode field */
14485 enum {
14487 * These opcodes are distinguished only by bits 9..6; those bits are
14488 * what are recorded below.
14490 SLL32 = 0x0,
14491 SRL32 = 0x1,
14492 SRA = 0x2,
14493 ROTR = 0x3,
14494 SELEQZ = 0x5,
14495 SELNEZ = 0x6,
14496 R6_RDHWR = 0x7,
14498 SLLV = 0x0,
14499 SRLV = 0x1,
14500 SRAV = 0x2,
14501 ROTRV = 0x3,
14502 ADD = 0x4,
14503 ADDU32 = 0x5,
14504 SUB = 0x6,
14505 SUBU32 = 0x7,
14506 MUL = 0x8,
14507 AND = 0x9,
14508 OR32 = 0xa,
14509 NOR = 0xb,
14510 XOR32 = 0xc,
14511 SLT = 0xd,
14512 SLTU = 0xe,
14514 MOVN = 0x0,
14515 R6_MUL = 0x0,
14516 MOVZ = 0x1,
14517 MUH = 0x1,
14518 MULU = 0x2,
14519 MUHU = 0x3,
14520 LWXS = 0x4,
14521 R6_DIV = 0x4,
14522 MOD = 0x5,
14523 R6_DIVU = 0x6,
14524 MODU = 0x7,
14526 /* The following can be distinguished by their lower 6 bits. */
14527 BREAK32 = 0x07,
14528 INS = 0x0c,
14529 LSA = 0x0f,
14530 ALIGN = 0x1f,
14531 EXT = 0x2c,
14532 POOL32AXF = 0x3c,
14533 SIGRIE = 0x3f
14536 /* POOL32AXF encoding of minor opcode field extension */
14539 * 1. MIPS Architecture for Programmers Volume II-B:
14540 * The microMIPS32 Instruction Set (Revision 3.05)
14542 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14544 * 2. MIPS Architecture for Programmers VolumeIV-e:
14545 * The MIPS DSP Application-Specific Extension
14546 * to the microMIPS32 Architecture (Revision 2.34)
14548 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14551 enum {
14552 /* bits 11..6 */
14553 TEQ = 0x00,
14554 TGE = 0x08,
14555 TGEU = 0x10,
14556 TLT = 0x20,
14557 TLTU = 0x28,
14558 TNE = 0x30,
14560 MFC0 = 0x03,
14561 MTC0 = 0x0b,
14563 /* begin of microMIPS32 DSP */
14565 /* bits 13..12 for 0x01 */
14566 MFHI_ACC = 0x0,
14567 MFLO_ACC = 0x1,
14568 MTHI_ACC = 0x2,
14569 MTLO_ACC = 0x3,
14571 /* bits 13..12 for 0x2a */
14572 MADD_ACC = 0x0,
14573 MADDU_ACC = 0x1,
14574 MSUB_ACC = 0x2,
14575 MSUBU_ACC = 0x3,
14577 /* bits 13..12 for 0x32 */
14578 MULT_ACC = 0x0,
14579 MULTU_ACC = 0x1,
14581 /* end of microMIPS32 DSP */
14583 /* bits 15..12 for 0x2c */
14584 BITSWAP = 0x0,
14585 SEB = 0x2,
14586 SEH = 0x3,
14587 CLO = 0x4,
14588 CLZ = 0x5,
14589 RDHWR = 0x6,
14590 WSBH = 0x7,
14591 MULT = 0x8,
14592 MULTU = 0x9,
14593 DIV = 0xa,
14594 DIVU = 0xb,
14595 MADD = 0xc,
14596 MADDU = 0xd,
14597 MSUB = 0xe,
14598 MSUBU = 0xf,
14600 /* bits 15..12 for 0x34 */
14601 MFC2 = 0x4,
14602 MTC2 = 0x5,
14603 MFHC2 = 0x8,
14604 MTHC2 = 0x9,
14605 CFC2 = 0xc,
14606 CTC2 = 0xd,
14608 /* bits 15..12 for 0x3c */
14609 JALR = 0x0,
14610 JR = 0x0, /* alias */
14611 JALRC = 0x0,
14612 JRC = 0x0,
14613 JALR_HB = 0x1,
14614 JALRC_HB = 0x1,
14615 JALRS = 0x4,
14616 JALRS_HB = 0x5,
14618 /* bits 15..12 for 0x05 */
14619 RDPGPR = 0xe,
14620 WRPGPR = 0xf,
14622 /* bits 15..12 for 0x0d */
14623 TLBP = 0x0,
14624 TLBR = 0x1,
14625 TLBWI = 0x2,
14626 TLBWR = 0x3,
14627 TLBINV = 0x4,
14628 TLBINVF = 0x5,
14629 WAIT = 0x9,
14630 IRET = 0xd,
14631 DERET = 0xe,
14632 ERET = 0xf,
14634 /* bits 15..12 for 0x15 */
14635 DMT = 0x0,
14636 DVPE = 0x1,
14637 EMT = 0x2,
14638 EVPE = 0x3,
14640 /* bits 15..12 for 0x1d */
14641 DI = 0x4,
14642 EI = 0x5,
14644 /* bits 15..12 for 0x2d */
14645 SYNC = 0x6,
14646 SYSCALL = 0x8,
14647 SDBBP = 0xd,
14649 /* bits 15..12 for 0x35 */
14650 MFHI32 = 0x0,
14651 MFLO32 = 0x1,
14652 MTHI32 = 0x2,
14653 MTLO32 = 0x3,
14656 /* POOL32B encoding of minor opcode field (bits 15..12) */
14658 enum {
14659 LWC2 = 0x0,
14660 LWP = 0x1,
14661 LDP = 0x4,
14662 LWM32 = 0x5,
14663 CACHE = 0x6,
14664 LDM = 0x7,
14665 SWC2 = 0x8,
14666 SWP = 0x9,
14667 SDP = 0xc,
14668 SWM32 = 0xd,
14669 SDM = 0xf
14672 /* POOL32C encoding of minor opcode field (bits 15..12) */
14674 enum {
14675 LWL = 0x0,
14676 SWL = 0x8,
14677 LWR = 0x1,
14678 SWR = 0x9,
14679 PREF = 0x2,
14680 ST_EVA = 0xa,
14681 LL = 0x3,
14682 SC = 0xb,
14683 LDL = 0x4,
14684 SDL = 0xc,
14685 LDR = 0x5,
14686 SDR = 0xd,
14687 LD_EVA = 0x6,
14688 LWU = 0xe,
14689 LLD = 0x7,
14690 SCD = 0xf
14693 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14695 enum {
14696 LBUE = 0x0,
14697 LHUE = 0x1,
14698 LWLE = 0x2,
14699 LWRE = 0x3,
14700 LBE = 0x4,
14701 LHE = 0x5,
14702 LLE = 0x6,
14703 LWE = 0x7,
14706 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14708 enum {
14709 SWLE = 0x0,
14710 SWRE = 0x1,
14711 PREFE = 0x2,
14712 CACHEE = 0x3,
14713 SBE = 0x4,
14714 SHE = 0x5,
14715 SCE = 0x6,
14716 SWE = 0x7,
14719 /* POOL32F encoding of minor opcode field (bits 5..0) */
14721 enum {
14722 /* These are the bit 7..6 values */
14723 ADD_FMT = 0x0,
14725 SUB_FMT = 0x1,
14727 MUL_FMT = 0x2,
14729 DIV_FMT = 0x3,
14731 /* These are the bit 8..6 values */
14732 MOVN_FMT = 0x0,
14733 RSQRT2_FMT = 0x0,
14734 MOVF_FMT = 0x0,
14735 RINT_FMT = 0x0,
14736 SELNEZ_FMT = 0x0,
14738 MOVZ_FMT = 0x1,
14739 LWXC1 = 0x1,
14740 MOVT_FMT = 0x1,
14741 CLASS_FMT = 0x1,
14742 SELEQZ_FMT = 0x1,
14744 PLL_PS = 0x2,
14745 SWXC1 = 0x2,
14746 SEL_FMT = 0x2,
14748 PLU_PS = 0x3,
14749 LDXC1 = 0x3,
14751 MOVN_FMT_04 = 0x4,
14752 PUL_PS = 0x4,
14753 SDXC1 = 0x4,
14754 RECIP2_FMT = 0x4,
14756 MOVZ_FMT_05 = 0x05,
14757 PUU_PS = 0x5,
14758 LUXC1 = 0x5,
14760 CVT_PS_S = 0x6,
14761 SUXC1 = 0x6,
14762 ADDR_PS = 0x6,
14763 PREFX = 0x6,
14764 MADDF_FMT = 0x6,
14766 MULR_PS = 0x7,
14767 MSUBF_FMT = 0x7,
14769 MADD_S = 0x01,
14770 MADD_D = 0x09,
14771 MADD_PS = 0x11,
14772 ALNV_PS = 0x19,
14773 MSUB_S = 0x21,
14774 MSUB_D = 0x29,
14775 MSUB_PS = 0x31,
14777 NMADD_S = 0x02,
14778 NMADD_D = 0x0a,
14779 NMADD_PS = 0x12,
14780 NMSUB_S = 0x22,
14781 NMSUB_D = 0x2a,
14782 NMSUB_PS = 0x32,
14784 MIN_FMT = 0x3,
14785 MAX_FMT = 0xb,
14786 MINA_FMT = 0x23,
14787 MAXA_FMT = 0x2b,
14788 POOL32FXF = 0x3b,
14790 CABS_COND_FMT = 0x1c, /* MIPS3D */
14791 C_COND_FMT = 0x3c,
14793 CMP_CONDN_S = 0x5,
14794 CMP_CONDN_D = 0x15
14797 /* POOL32Fxf encoding of minor opcode extension field */
14799 enum {
14800 CVT_L = 0x04,
14801 RSQRT_FMT = 0x08,
14802 FLOOR_L = 0x0c,
14803 CVT_PW_PS = 0x1c,
14804 CVT_W = 0x24,
14805 SQRT_FMT = 0x28,
14806 FLOOR_W = 0x2c,
14807 CVT_PS_PW = 0x3c,
14808 CFC1 = 0x40,
14809 RECIP_FMT = 0x48,
14810 CEIL_L = 0x4c,
14811 CTC1 = 0x60,
14812 CEIL_W = 0x6c,
14813 MFC1 = 0x80,
14814 CVT_S_PL = 0x84,
14815 TRUNC_L = 0x8c,
14816 MTC1 = 0xa0,
14817 CVT_S_PU = 0xa4,
14818 TRUNC_W = 0xac,
14819 MFHC1 = 0xc0,
14820 ROUND_L = 0xcc,
14821 MTHC1 = 0xe0,
14822 ROUND_W = 0xec,
14824 MOV_FMT = 0x01,
14825 MOVF = 0x05,
14826 ABS_FMT = 0x0d,
14827 RSQRT1_FMT = 0x1d,
14828 MOVT = 0x25,
14829 NEG_FMT = 0x2d,
14830 CVT_D = 0x4d,
14831 RECIP1_FMT = 0x5d,
14832 CVT_S = 0x6d
14835 /* POOL32I encoding of minor opcode field (bits 25..21) */
14837 enum {
14838 BLTZ = 0x00,
14839 BLTZAL = 0x01,
14840 BGEZ = 0x02,
14841 BGEZAL = 0x03,
14842 BLEZ = 0x04,
14843 BNEZC = 0x05,
14844 BGTZ = 0x06,
14845 BEQZC = 0x07,
14846 TLTI = 0x08,
14847 BC1EQZC = 0x08,
14848 TGEI = 0x09,
14849 BC1NEZC = 0x09,
14850 TLTIU = 0x0a,
14851 BC2EQZC = 0x0a,
14852 TGEIU = 0x0b,
14853 BC2NEZC = 0x0a,
14854 TNEI = 0x0c,
14855 R6_SYNCI = 0x0c,
14856 LUI = 0x0d,
14857 TEQI = 0x0e,
14858 SYNCI = 0x10,
14859 BLTZALS = 0x11,
14860 BGEZALS = 0x13,
14861 BC2F = 0x14,
14862 BC2T = 0x15,
14863 BPOSGE64 = 0x1a,
14864 BPOSGE32 = 0x1b,
14865 /* These overlap and are distinguished by bit16 of the instruction */
14866 BC1F = 0x1c,
14867 BC1T = 0x1d,
14868 BC1ANY2F = 0x1c,
14869 BC1ANY2T = 0x1d,
14870 BC1ANY4F = 0x1e,
14871 BC1ANY4T = 0x1f
14874 /* POOL16A encoding of minor opcode field */
14876 enum {
14877 ADDU16 = 0x0,
14878 SUBU16 = 0x1
14881 /* POOL16B encoding of minor opcode field */
14883 enum {
14884 SLL16 = 0x0,
14885 SRL16 = 0x1
14888 /* POOL16C encoding of minor opcode field */
14890 enum {
14891 NOT16 = 0x00,
14892 XOR16 = 0x04,
14893 AND16 = 0x08,
14894 OR16 = 0x0c,
14895 LWM16 = 0x10,
14896 SWM16 = 0x14,
14897 JR16 = 0x18,
14898 JRC16 = 0x1a,
14899 JALR16 = 0x1c,
14900 JALR16S = 0x1e,
14901 MFHI16 = 0x20,
14902 MFLO16 = 0x24,
14903 BREAK16 = 0x28,
14904 SDBBP16 = 0x2c,
14905 JRADDIUSP = 0x30
14908 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14910 enum {
14911 R6_NOT16 = 0x00,
14912 R6_AND16 = 0x01,
14913 R6_LWM16 = 0x02,
14914 R6_JRC16 = 0x03,
14915 MOVEP = 0x04,
14916 MOVEP_05 = 0x05,
14917 MOVEP_06 = 0x06,
14918 MOVEP_07 = 0x07,
14919 R6_XOR16 = 0x08,
14920 R6_OR16 = 0x09,
14921 R6_SWM16 = 0x0a,
14922 JALRC16 = 0x0b,
14923 MOVEP_0C = 0x0c,
14924 MOVEP_0D = 0x0d,
14925 MOVEP_0E = 0x0e,
14926 MOVEP_0F = 0x0f,
14927 JRCADDIUSP = 0x13,
14928 R6_BREAK16 = 0x1b,
14929 R6_SDBBP16 = 0x3b
14932 /* POOL16D encoding of minor opcode field */
14934 enum {
14935 ADDIUS5 = 0x0,
14936 ADDIUSP = 0x1
14939 /* POOL16E encoding of minor opcode field */
14941 enum {
14942 ADDIUR2 = 0x0,
14943 ADDIUR1SP = 0x1
14946 static int mmreg(int r)
14948 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14950 return map[r];
14953 /* Used for 16-bit store instructions. */
14954 static int mmreg2(int r)
14956 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14958 return map[r];
14961 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14962 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14963 #define uMIPS_RS2(op) uMIPS_RS(op)
14964 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14965 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14966 #define uMIPS_RS5(op) (op & 0x1f)
14968 /* Signed immediate */
14969 #define SIMM(op, start, width) \
14970 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14971 << (32 - width)) \
14972 >> (32 - width))
14973 /* Zero-extended immediate */
14974 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14976 static void gen_addiur1sp(DisasContext *ctx)
14978 int rd = mmreg(uMIPS_RD(ctx->opcode));
14980 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14983 static void gen_addiur2(DisasContext *ctx)
14985 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14986 int rd = mmreg(uMIPS_RD(ctx->opcode));
14987 int rs = mmreg(uMIPS_RS(ctx->opcode));
14989 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14992 static void gen_addiusp(DisasContext *ctx)
14994 int encoded = ZIMM(ctx->opcode, 1, 9);
14995 int decoded;
14997 if (encoded <= 1) {
14998 decoded = 256 + encoded;
14999 } else if (encoded <= 255) {
15000 decoded = encoded;
15001 } else if (encoded <= 509) {
15002 decoded = encoded - 512;
15003 } else {
15004 decoded = encoded - 768;
15007 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15010 static void gen_addius5(DisasContext *ctx)
15012 int imm = SIMM(ctx->opcode, 1, 4);
15013 int rd = (ctx->opcode >> 5) & 0x1f;
15015 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15018 static void gen_andi16(DisasContext *ctx)
15020 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15021 31, 32, 63, 64, 255, 32768, 65535 };
15022 int rd = mmreg(uMIPS_RD(ctx->opcode));
15023 int rs = mmreg(uMIPS_RS(ctx->opcode));
15024 int encoded = ZIMM(ctx->opcode, 0, 4);
15026 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15029 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15030 int base, int16_t offset)
15032 TCGv t0, t1;
15033 TCGv_i32 t2;
15035 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15036 generate_exception_end(ctx, EXCP_RI);
15037 return;
15040 t0 = tcg_temp_new();
15042 gen_base_offset_addr(ctx, t0, base, offset);
15044 t1 = tcg_const_tl(reglist);
15045 t2 = tcg_const_i32(ctx->mem_idx);
15047 save_cpu_state(ctx, 1);
15048 switch (opc) {
15049 case LWM32:
15050 gen_helper_lwm(cpu_env, t0, t1, t2);
15051 break;
15052 case SWM32:
15053 gen_helper_swm(cpu_env, t0, t1, t2);
15054 break;
15055 #ifdef TARGET_MIPS64
15056 case LDM:
15057 gen_helper_ldm(cpu_env, t0, t1, t2);
15058 break;
15059 case SDM:
15060 gen_helper_sdm(cpu_env, t0, t1, t2);
15061 break;
15062 #endif
15064 tcg_temp_free(t0);
15065 tcg_temp_free(t1);
15066 tcg_temp_free_i32(t2);
15070 static void gen_pool16c_insn(DisasContext *ctx)
15072 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15073 int rs = mmreg(ctx->opcode & 0x7);
15075 switch (((ctx->opcode) >> 4) & 0x3f) {
15076 case NOT16 + 0:
15077 case NOT16 + 1:
15078 case NOT16 + 2:
15079 case NOT16 + 3:
15080 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15081 break;
15082 case XOR16 + 0:
15083 case XOR16 + 1:
15084 case XOR16 + 2:
15085 case XOR16 + 3:
15086 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15087 break;
15088 case AND16 + 0:
15089 case AND16 + 1:
15090 case AND16 + 2:
15091 case AND16 + 3:
15092 gen_logic(ctx, OPC_AND, rd, rd, rs);
15093 break;
15094 case OR16 + 0:
15095 case OR16 + 1:
15096 case OR16 + 2:
15097 case OR16 + 3:
15098 gen_logic(ctx, OPC_OR, rd, rd, rs);
15099 break;
15100 case LWM16 + 0:
15101 case LWM16 + 1:
15102 case LWM16 + 2:
15103 case LWM16 + 3:
15105 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15106 int offset = ZIMM(ctx->opcode, 0, 4);
15108 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15109 29, offset << 2);
15111 break;
15112 case SWM16 + 0:
15113 case SWM16 + 1:
15114 case SWM16 + 2:
15115 case SWM16 + 3:
15117 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15118 int offset = ZIMM(ctx->opcode, 0, 4);
15120 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15121 29, offset << 2);
15123 break;
15124 case JR16 + 0:
15125 case JR16 + 1:
15127 int reg = ctx->opcode & 0x1f;
15129 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15131 break;
15132 case JRC16 + 0:
15133 case JRC16 + 1:
15135 int reg = ctx->opcode & 0x1f;
15136 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15138 * Let normal delay slot handling in our caller take us
15139 * to the branch target.
15142 break;
15143 case JALR16 + 0:
15144 case JALR16 + 1:
15145 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15146 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15147 break;
15148 case JALR16S + 0:
15149 case JALR16S + 1:
15150 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15151 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15152 break;
15153 case MFHI16 + 0:
15154 case MFHI16 + 1:
15155 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15156 break;
15157 case MFLO16 + 0:
15158 case MFLO16 + 1:
15159 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15160 break;
15161 case BREAK16:
15162 generate_exception_end(ctx, EXCP_BREAK);
15163 break;
15164 case SDBBP16:
15165 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15166 gen_helper_do_semihosting(cpu_env);
15167 } else {
15169 * XXX: not clear which exception should be raised
15170 * when in debug mode...
15172 check_insn(ctx, ISA_MIPS32);
15173 generate_exception_end(ctx, EXCP_DBp);
15175 break;
15176 case JRADDIUSP + 0:
15177 case JRADDIUSP + 1:
15179 int imm = ZIMM(ctx->opcode, 0, 5);
15180 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15181 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15183 * Let normal delay slot handling in our caller take us
15184 * to the branch target.
15187 break;
15188 default:
15189 generate_exception_end(ctx, EXCP_RI);
15190 break;
15194 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15195 int enc_rs)
15197 int rd, rs, re, rt;
15198 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15199 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15200 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15201 rd = rd_enc[enc_dest];
15202 re = re_enc[enc_dest];
15203 rs = rs_rt_enc[enc_rs];
15204 rt = rs_rt_enc[enc_rt];
15205 if (rs) {
15206 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15207 } else {
15208 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15210 if (rt) {
15211 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15212 } else {
15213 tcg_gen_movi_tl(cpu_gpr[re], 0);
15217 static void gen_pool16c_r6_insn(DisasContext *ctx)
15219 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15220 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15222 switch (ctx->opcode & 0xf) {
15223 case R6_NOT16:
15224 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15225 break;
15226 case R6_AND16:
15227 gen_logic(ctx, OPC_AND, rt, rt, rs);
15228 break;
15229 case R6_LWM16:
15231 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15232 int offset = extract32(ctx->opcode, 4, 4);
15233 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15235 break;
15236 case R6_JRC16: /* JRCADDIUSP */
15237 if ((ctx->opcode >> 4) & 1) {
15238 /* JRCADDIUSP */
15239 int imm = extract32(ctx->opcode, 5, 5);
15240 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15241 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15242 } else {
15243 /* JRC16 */
15244 rs = extract32(ctx->opcode, 5, 5);
15245 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15247 break;
15248 case MOVEP:
15249 case MOVEP_05:
15250 case MOVEP_06:
15251 case MOVEP_07:
15252 case MOVEP_0C:
15253 case MOVEP_0D:
15254 case MOVEP_0E:
15255 case MOVEP_0F:
15257 int enc_dest = uMIPS_RD(ctx->opcode);
15258 int enc_rt = uMIPS_RS2(ctx->opcode);
15259 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15260 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15262 break;
15263 case R6_XOR16:
15264 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15265 break;
15266 case R6_OR16:
15267 gen_logic(ctx, OPC_OR, rt, rt, rs);
15268 break;
15269 case R6_SWM16:
15271 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15272 int offset = extract32(ctx->opcode, 4, 4);
15273 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15275 break;
15276 case JALRC16: /* BREAK16, SDBBP16 */
15277 switch (ctx->opcode & 0x3f) {
15278 case JALRC16:
15279 case JALRC16 + 0x20:
15280 /* JALRC16 */
15281 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15282 31, 0, 0);
15283 break;
15284 case R6_BREAK16:
15285 /* BREAK16 */
15286 generate_exception(ctx, EXCP_BREAK);
15287 break;
15288 case R6_SDBBP16:
15289 /* SDBBP16 */
15290 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15291 gen_helper_do_semihosting(cpu_env);
15292 } else {
15293 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15294 generate_exception(ctx, EXCP_RI);
15295 } else {
15296 generate_exception(ctx, EXCP_DBp);
15299 break;
15301 break;
15302 default:
15303 generate_exception(ctx, EXCP_RI);
15304 break;
15308 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15310 TCGv t0 = tcg_temp_new();
15311 TCGv t1 = tcg_temp_new();
15313 gen_load_gpr(t0, base);
15315 if (index != 0) {
15316 gen_load_gpr(t1, index);
15317 tcg_gen_shli_tl(t1, t1, 2);
15318 gen_op_addr_add(ctx, t0, t1, t0);
15321 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15322 gen_store_gpr(t1, rd);
15324 tcg_temp_free(t0);
15325 tcg_temp_free(t1);
15328 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15329 int base, int16_t offset)
15331 TCGv t0, t1;
15333 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15334 generate_exception_end(ctx, EXCP_RI);
15335 return;
15338 t0 = tcg_temp_new();
15339 t1 = tcg_temp_new();
15341 gen_base_offset_addr(ctx, t0, base, offset);
15343 switch (opc) {
15344 case LWP:
15345 if (rd == base) {
15346 generate_exception_end(ctx, EXCP_RI);
15347 return;
15349 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15350 gen_store_gpr(t1, rd);
15351 tcg_gen_movi_tl(t1, 4);
15352 gen_op_addr_add(ctx, t0, t0, t1);
15353 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15354 gen_store_gpr(t1, rd + 1);
15355 break;
15356 case SWP:
15357 gen_load_gpr(t1, rd);
15358 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15359 tcg_gen_movi_tl(t1, 4);
15360 gen_op_addr_add(ctx, t0, t0, t1);
15361 gen_load_gpr(t1, rd + 1);
15362 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15363 break;
15364 #ifdef TARGET_MIPS64
15365 case LDP:
15366 if (rd == base) {
15367 generate_exception_end(ctx, EXCP_RI);
15368 return;
15370 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15371 gen_store_gpr(t1, rd);
15372 tcg_gen_movi_tl(t1, 8);
15373 gen_op_addr_add(ctx, t0, t0, t1);
15374 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15375 gen_store_gpr(t1, rd + 1);
15376 break;
15377 case SDP:
15378 gen_load_gpr(t1, rd);
15379 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15380 tcg_gen_movi_tl(t1, 8);
15381 gen_op_addr_add(ctx, t0, t0, t1);
15382 gen_load_gpr(t1, rd + 1);
15383 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15384 break;
15385 #endif
15387 tcg_temp_free(t0);
15388 tcg_temp_free(t1);
15391 static void gen_sync(int stype)
15393 TCGBar tcg_mo = TCG_BAR_SC;
15395 switch (stype) {
15396 case 0x4: /* SYNC_WMB */
15397 tcg_mo |= TCG_MO_ST_ST;
15398 break;
15399 case 0x10: /* SYNC_MB */
15400 tcg_mo |= TCG_MO_ALL;
15401 break;
15402 case 0x11: /* SYNC_ACQUIRE */
15403 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15404 break;
15405 case 0x12: /* SYNC_RELEASE */
15406 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15407 break;
15408 case 0x13: /* SYNC_RMB */
15409 tcg_mo |= TCG_MO_LD_LD;
15410 break;
15411 default:
15412 tcg_mo |= TCG_MO_ALL;
15413 break;
15416 tcg_gen_mb(tcg_mo);
15419 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15421 int extension = (ctx->opcode >> 6) & 0x3f;
15422 int minor = (ctx->opcode >> 12) & 0xf;
15423 uint32_t mips32_op;
15425 switch (extension) {
15426 case TEQ:
15427 mips32_op = OPC_TEQ;
15428 goto do_trap;
15429 case TGE:
15430 mips32_op = OPC_TGE;
15431 goto do_trap;
15432 case TGEU:
15433 mips32_op = OPC_TGEU;
15434 goto do_trap;
15435 case TLT:
15436 mips32_op = OPC_TLT;
15437 goto do_trap;
15438 case TLTU:
15439 mips32_op = OPC_TLTU;
15440 goto do_trap;
15441 case TNE:
15442 mips32_op = OPC_TNE;
15443 do_trap:
15444 gen_trap(ctx, mips32_op, rs, rt, -1);
15445 break;
15446 #ifndef CONFIG_USER_ONLY
15447 case MFC0:
15448 case MFC0 + 32:
15449 check_cp0_enabled(ctx);
15450 if (rt == 0) {
15451 /* Treat as NOP. */
15452 break;
15454 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15455 break;
15456 case MTC0:
15457 case MTC0 + 32:
15458 check_cp0_enabled(ctx);
15460 TCGv t0 = tcg_temp_new();
15462 gen_load_gpr(t0, rt);
15463 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15464 tcg_temp_free(t0);
15466 break;
15467 #endif
15468 case 0x2a:
15469 switch (minor & 3) {
15470 case MADD_ACC:
15471 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15472 break;
15473 case MADDU_ACC:
15474 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15475 break;
15476 case MSUB_ACC:
15477 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15478 break;
15479 case MSUBU_ACC:
15480 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15481 break;
15482 default:
15483 goto pool32axf_invalid;
15485 break;
15486 case 0x32:
15487 switch (minor & 3) {
15488 case MULT_ACC:
15489 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15490 break;
15491 case MULTU_ACC:
15492 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15493 break;
15494 default:
15495 goto pool32axf_invalid;
15497 break;
15498 case 0x2c:
15499 switch (minor) {
15500 case BITSWAP:
15501 check_insn(ctx, ISA_MIPS32R6);
15502 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15503 break;
15504 case SEB:
15505 gen_bshfl(ctx, OPC_SEB, rs, rt);
15506 break;
15507 case SEH:
15508 gen_bshfl(ctx, OPC_SEH, rs, rt);
15509 break;
15510 case CLO:
15511 mips32_op = OPC_CLO;
15512 goto do_cl;
15513 case CLZ:
15514 mips32_op = OPC_CLZ;
15515 do_cl:
15516 check_insn(ctx, ISA_MIPS32);
15517 gen_cl(ctx, mips32_op, rt, rs);
15518 break;
15519 case RDHWR:
15520 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15521 gen_rdhwr(ctx, rt, rs, 0);
15522 break;
15523 case WSBH:
15524 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15525 break;
15526 case MULT:
15527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15528 mips32_op = OPC_MULT;
15529 goto do_mul;
15530 case MULTU:
15531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15532 mips32_op = OPC_MULTU;
15533 goto do_mul;
15534 case DIV:
15535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15536 mips32_op = OPC_DIV;
15537 goto do_div;
15538 case DIVU:
15539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15540 mips32_op = OPC_DIVU;
15541 goto do_div;
15542 do_div:
15543 check_insn(ctx, ISA_MIPS32);
15544 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15545 break;
15546 case MADD:
15547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15548 mips32_op = OPC_MADD;
15549 goto do_mul;
15550 case MADDU:
15551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15552 mips32_op = OPC_MADDU;
15553 goto do_mul;
15554 case MSUB:
15555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15556 mips32_op = OPC_MSUB;
15557 goto do_mul;
15558 case MSUBU:
15559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15560 mips32_op = OPC_MSUBU;
15561 do_mul:
15562 check_insn(ctx, ISA_MIPS32);
15563 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15564 break;
15565 default:
15566 goto pool32axf_invalid;
15568 break;
15569 case 0x34:
15570 switch (minor) {
15571 case MFC2:
15572 case MTC2:
15573 case MFHC2:
15574 case MTHC2:
15575 case CFC2:
15576 case CTC2:
15577 generate_exception_err(ctx, EXCP_CpU, 2);
15578 break;
15579 default:
15580 goto pool32axf_invalid;
15582 break;
15583 case 0x3c:
15584 switch (minor) {
15585 case JALR: /* JALRC */
15586 case JALR_HB: /* JALRC_HB */
15587 if (ctx->insn_flags & ISA_MIPS32R6) {
15588 /* JALRC, JALRC_HB */
15589 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15590 } else {
15591 /* JALR, JALR_HB */
15592 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15593 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15595 break;
15596 case JALRS:
15597 case JALRS_HB:
15598 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15599 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15600 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15601 break;
15602 default:
15603 goto pool32axf_invalid;
15605 break;
15606 case 0x05:
15607 switch (minor) {
15608 case RDPGPR:
15609 check_cp0_enabled(ctx);
15610 check_insn(ctx, ISA_MIPS32R2);
15611 gen_load_srsgpr(rs, rt);
15612 break;
15613 case WRPGPR:
15614 check_cp0_enabled(ctx);
15615 check_insn(ctx, ISA_MIPS32R2);
15616 gen_store_srsgpr(rs, rt);
15617 break;
15618 default:
15619 goto pool32axf_invalid;
15621 break;
15622 #ifndef CONFIG_USER_ONLY
15623 case 0x0d:
15624 switch (minor) {
15625 case TLBP:
15626 mips32_op = OPC_TLBP;
15627 goto do_cp0;
15628 case TLBR:
15629 mips32_op = OPC_TLBR;
15630 goto do_cp0;
15631 case TLBWI:
15632 mips32_op = OPC_TLBWI;
15633 goto do_cp0;
15634 case TLBWR:
15635 mips32_op = OPC_TLBWR;
15636 goto do_cp0;
15637 case TLBINV:
15638 mips32_op = OPC_TLBINV;
15639 goto do_cp0;
15640 case TLBINVF:
15641 mips32_op = OPC_TLBINVF;
15642 goto do_cp0;
15643 case WAIT:
15644 mips32_op = OPC_WAIT;
15645 goto do_cp0;
15646 case DERET:
15647 mips32_op = OPC_DERET;
15648 goto do_cp0;
15649 case ERET:
15650 mips32_op = OPC_ERET;
15651 do_cp0:
15652 gen_cp0(env, ctx, mips32_op, rt, rs);
15653 break;
15654 default:
15655 goto pool32axf_invalid;
15657 break;
15658 case 0x1d:
15659 switch (minor) {
15660 case DI:
15661 check_cp0_enabled(ctx);
15663 TCGv t0 = tcg_temp_new();
15665 save_cpu_state(ctx, 1);
15666 gen_helper_di(t0, cpu_env);
15667 gen_store_gpr(t0, rs);
15669 * Stop translation as we may have switched the execution
15670 * mode.
15672 ctx->base.is_jmp = DISAS_STOP;
15673 tcg_temp_free(t0);
15675 break;
15676 case EI:
15677 check_cp0_enabled(ctx);
15679 TCGv t0 = tcg_temp_new();
15681 save_cpu_state(ctx, 1);
15682 gen_helper_ei(t0, cpu_env);
15683 gen_store_gpr(t0, rs);
15685 * DISAS_STOP isn't sufficient, we need to ensure we break out
15686 * of translated code to check for pending interrupts.
15688 gen_save_pc(ctx->base.pc_next + 4);
15689 ctx->base.is_jmp = DISAS_EXIT;
15690 tcg_temp_free(t0);
15692 break;
15693 default:
15694 goto pool32axf_invalid;
15696 break;
15697 #endif
15698 case 0x2d:
15699 switch (minor) {
15700 case SYNC:
15701 gen_sync(extract32(ctx->opcode, 16, 5));
15702 break;
15703 case SYSCALL:
15704 generate_exception_end(ctx, EXCP_SYSCALL);
15705 break;
15706 case SDBBP:
15707 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15708 gen_helper_do_semihosting(cpu_env);
15709 } else {
15710 check_insn(ctx, ISA_MIPS32);
15711 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15712 generate_exception_end(ctx, EXCP_RI);
15713 } else {
15714 generate_exception_end(ctx, EXCP_DBp);
15717 break;
15718 default:
15719 goto pool32axf_invalid;
15721 break;
15722 case 0x01:
15723 switch (minor & 3) {
15724 case MFHI_ACC:
15725 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15726 break;
15727 case MFLO_ACC:
15728 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15729 break;
15730 case MTHI_ACC:
15731 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15732 break;
15733 case MTLO_ACC:
15734 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15735 break;
15736 default:
15737 goto pool32axf_invalid;
15739 break;
15740 case 0x35:
15741 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15742 switch (minor) {
15743 case MFHI32:
15744 gen_HILO(ctx, OPC_MFHI, 0, rs);
15745 break;
15746 case MFLO32:
15747 gen_HILO(ctx, OPC_MFLO, 0, rs);
15748 break;
15749 case MTHI32:
15750 gen_HILO(ctx, OPC_MTHI, 0, rs);
15751 break;
15752 case MTLO32:
15753 gen_HILO(ctx, OPC_MTLO, 0, rs);
15754 break;
15755 default:
15756 goto pool32axf_invalid;
15758 break;
15759 default:
15760 pool32axf_invalid:
15761 MIPS_INVAL("pool32axf");
15762 generate_exception_end(ctx, EXCP_RI);
15763 break;
15768 * Values for microMIPS fmt field. Variable-width, depending on which
15769 * formats the instruction supports.
15771 enum {
15772 FMT_SD_S = 0,
15773 FMT_SD_D = 1,
15775 FMT_SDPS_S = 0,
15776 FMT_SDPS_D = 1,
15777 FMT_SDPS_PS = 2,
15779 FMT_SWL_S = 0,
15780 FMT_SWL_W = 1,
15781 FMT_SWL_L = 2,
15783 FMT_DWL_D = 0,
15784 FMT_DWL_W = 1,
15785 FMT_DWL_L = 2
15788 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15790 int extension = (ctx->opcode >> 6) & 0x3ff;
15791 uint32_t mips32_op;
15793 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15794 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15795 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15797 switch (extension) {
15798 case FLOAT_1BIT_FMT(CFC1, 0):
15799 mips32_op = OPC_CFC1;
15800 goto do_cp1;
15801 case FLOAT_1BIT_FMT(CTC1, 0):
15802 mips32_op = OPC_CTC1;
15803 goto do_cp1;
15804 case FLOAT_1BIT_FMT(MFC1, 0):
15805 mips32_op = OPC_MFC1;
15806 goto do_cp1;
15807 case FLOAT_1BIT_FMT(MTC1, 0):
15808 mips32_op = OPC_MTC1;
15809 goto do_cp1;
15810 case FLOAT_1BIT_FMT(MFHC1, 0):
15811 mips32_op = OPC_MFHC1;
15812 goto do_cp1;
15813 case FLOAT_1BIT_FMT(MTHC1, 0):
15814 mips32_op = OPC_MTHC1;
15815 do_cp1:
15816 gen_cp1(ctx, mips32_op, rt, rs);
15817 break;
15819 /* Reciprocal square root */
15820 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15821 mips32_op = OPC_RSQRT_S;
15822 goto do_unaryfp;
15823 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15824 mips32_op = OPC_RSQRT_D;
15825 goto do_unaryfp;
15827 /* Square root */
15828 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15829 mips32_op = OPC_SQRT_S;
15830 goto do_unaryfp;
15831 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15832 mips32_op = OPC_SQRT_D;
15833 goto do_unaryfp;
15835 /* Reciprocal */
15836 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15837 mips32_op = OPC_RECIP_S;
15838 goto do_unaryfp;
15839 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15840 mips32_op = OPC_RECIP_D;
15841 goto do_unaryfp;
15843 /* Floor */
15844 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15845 mips32_op = OPC_FLOOR_L_S;
15846 goto do_unaryfp;
15847 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15848 mips32_op = OPC_FLOOR_L_D;
15849 goto do_unaryfp;
15850 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15851 mips32_op = OPC_FLOOR_W_S;
15852 goto do_unaryfp;
15853 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15854 mips32_op = OPC_FLOOR_W_D;
15855 goto do_unaryfp;
15857 /* Ceiling */
15858 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15859 mips32_op = OPC_CEIL_L_S;
15860 goto do_unaryfp;
15861 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15862 mips32_op = OPC_CEIL_L_D;
15863 goto do_unaryfp;
15864 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15865 mips32_op = OPC_CEIL_W_S;
15866 goto do_unaryfp;
15867 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15868 mips32_op = OPC_CEIL_W_D;
15869 goto do_unaryfp;
15871 /* Truncation */
15872 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15873 mips32_op = OPC_TRUNC_L_S;
15874 goto do_unaryfp;
15875 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15876 mips32_op = OPC_TRUNC_L_D;
15877 goto do_unaryfp;
15878 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15879 mips32_op = OPC_TRUNC_W_S;
15880 goto do_unaryfp;
15881 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15882 mips32_op = OPC_TRUNC_W_D;
15883 goto do_unaryfp;
15885 /* Round */
15886 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15887 mips32_op = OPC_ROUND_L_S;
15888 goto do_unaryfp;
15889 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15890 mips32_op = OPC_ROUND_L_D;
15891 goto do_unaryfp;
15892 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15893 mips32_op = OPC_ROUND_W_S;
15894 goto do_unaryfp;
15895 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15896 mips32_op = OPC_ROUND_W_D;
15897 goto do_unaryfp;
15899 /* Integer to floating-point conversion */
15900 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15901 mips32_op = OPC_CVT_L_S;
15902 goto do_unaryfp;
15903 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15904 mips32_op = OPC_CVT_L_D;
15905 goto do_unaryfp;
15906 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15907 mips32_op = OPC_CVT_W_S;
15908 goto do_unaryfp;
15909 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15910 mips32_op = OPC_CVT_W_D;
15911 goto do_unaryfp;
15913 /* Paired-foo conversions */
15914 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15915 mips32_op = OPC_CVT_S_PL;
15916 goto do_unaryfp;
15917 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15918 mips32_op = OPC_CVT_S_PU;
15919 goto do_unaryfp;
15920 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15921 mips32_op = OPC_CVT_PW_PS;
15922 goto do_unaryfp;
15923 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15924 mips32_op = OPC_CVT_PS_PW;
15925 goto do_unaryfp;
15927 /* Floating-point moves */
15928 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15929 mips32_op = OPC_MOV_S;
15930 goto do_unaryfp;
15931 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15932 mips32_op = OPC_MOV_D;
15933 goto do_unaryfp;
15934 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15935 mips32_op = OPC_MOV_PS;
15936 goto do_unaryfp;
15938 /* Absolute value */
15939 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15940 mips32_op = OPC_ABS_S;
15941 goto do_unaryfp;
15942 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15943 mips32_op = OPC_ABS_D;
15944 goto do_unaryfp;
15945 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15946 mips32_op = OPC_ABS_PS;
15947 goto do_unaryfp;
15949 /* Negation */
15950 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15951 mips32_op = OPC_NEG_S;
15952 goto do_unaryfp;
15953 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15954 mips32_op = OPC_NEG_D;
15955 goto do_unaryfp;
15956 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15957 mips32_op = OPC_NEG_PS;
15958 goto do_unaryfp;
15960 /* Reciprocal square root step */
15961 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15962 mips32_op = OPC_RSQRT1_S;
15963 goto do_unaryfp;
15964 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15965 mips32_op = OPC_RSQRT1_D;
15966 goto do_unaryfp;
15967 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15968 mips32_op = OPC_RSQRT1_PS;
15969 goto do_unaryfp;
15971 /* Reciprocal step */
15972 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15973 mips32_op = OPC_RECIP1_S;
15974 goto do_unaryfp;
15975 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15976 mips32_op = OPC_RECIP1_S;
15977 goto do_unaryfp;
15978 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15979 mips32_op = OPC_RECIP1_PS;
15980 goto do_unaryfp;
15982 /* Conversions from double */
15983 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15984 mips32_op = OPC_CVT_D_S;
15985 goto do_unaryfp;
15986 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15987 mips32_op = OPC_CVT_D_W;
15988 goto do_unaryfp;
15989 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15990 mips32_op = OPC_CVT_D_L;
15991 goto do_unaryfp;
15993 /* Conversions from single */
15994 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15995 mips32_op = OPC_CVT_S_D;
15996 goto do_unaryfp;
15997 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15998 mips32_op = OPC_CVT_S_W;
15999 goto do_unaryfp;
16000 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16001 mips32_op = OPC_CVT_S_L;
16002 do_unaryfp:
16003 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16004 break;
16006 /* Conditional moves on floating-point codes */
16007 case COND_FLOAT_MOV(MOVT, 0):
16008 case COND_FLOAT_MOV(MOVT, 1):
16009 case COND_FLOAT_MOV(MOVT, 2):
16010 case COND_FLOAT_MOV(MOVT, 3):
16011 case COND_FLOAT_MOV(MOVT, 4):
16012 case COND_FLOAT_MOV(MOVT, 5):
16013 case COND_FLOAT_MOV(MOVT, 6):
16014 case COND_FLOAT_MOV(MOVT, 7):
16015 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16016 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16017 break;
16018 case COND_FLOAT_MOV(MOVF, 0):
16019 case COND_FLOAT_MOV(MOVF, 1):
16020 case COND_FLOAT_MOV(MOVF, 2):
16021 case COND_FLOAT_MOV(MOVF, 3):
16022 case COND_FLOAT_MOV(MOVF, 4):
16023 case COND_FLOAT_MOV(MOVF, 5):
16024 case COND_FLOAT_MOV(MOVF, 6):
16025 case COND_FLOAT_MOV(MOVF, 7):
16026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16027 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16028 break;
16029 default:
16030 MIPS_INVAL("pool32fxf");
16031 generate_exception_end(ctx, EXCP_RI);
16032 break;
16036 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16038 int32_t offset;
16039 uint16_t insn;
16040 int rt, rs, rd, rr;
16041 int16_t imm;
16042 uint32_t op, minor, minor2, mips32_op;
16043 uint32_t cond, fmt, cc;
16045 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16046 ctx->opcode = (ctx->opcode << 16) | insn;
16048 rt = (ctx->opcode >> 21) & 0x1f;
16049 rs = (ctx->opcode >> 16) & 0x1f;
16050 rd = (ctx->opcode >> 11) & 0x1f;
16051 rr = (ctx->opcode >> 6) & 0x1f;
16052 imm = (int16_t) ctx->opcode;
16054 op = (ctx->opcode >> 26) & 0x3f;
16055 switch (op) {
16056 case POOL32A:
16057 minor = ctx->opcode & 0x3f;
16058 switch (minor) {
16059 case 0x00:
16060 minor = (ctx->opcode >> 6) & 0xf;
16061 switch (minor) {
16062 case SLL32:
16063 mips32_op = OPC_SLL;
16064 goto do_shifti;
16065 case SRA:
16066 mips32_op = OPC_SRA;
16067 goto do_shifti;
16068 case SRL32:
16069 mips32_op = OPC_SRL;
16070 goto do_shifti;
16071 case ROTR:
16072 mips32_op = OPC_ROTR;
16073 do_shifti:
16074 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16075 break;
16076 case SELEQZ:
16077 check_insn(ctx, ISA_MIPS32R6);
16078 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16079 break;
16080 case SELNEZ:
16081 check_insn(ctx, ISA_MIPS32R6);
16082 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16083 break;
16084 case R6_RDHWR:
16085 check_insn(ctx, ISA_MIPS32R6);
16086 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16087 break;
16088 default:
16089 goto pool32a_invalid;
16091 break;
16092 case 0x10:
16093 minor = (ctx->opcode >> 6) & 0xf;
16094 switch (minor) {
16095 /* Arithmetic */
16096 case ADD:
16097 mips32_op = OPC_ADD;
16098 goto do_arith;
16099 case ADDU32:
16100 mips32_op = OPC_ADDU;
16101 goto do_arith;
16102 case SUB:
16103 mips32_op = OPC_SUB;
16104 goto do_arith;
16105 case SUBU32:
16106 mips32_op = OPC_SUBU;
16107 goto do_arith;
16108 case MUL:
16109 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16110 mips32_op = OPC_MUL;
16111 do_arith:
16112 gen_arith(ctx, mips32_op, rd, rs, rt);
16113 break;
16114 /* Shifts */
16115 case SLLV:
16116 mips32_op = OPC_SLLV;
16117 goto do_shift;
16118 case SRLV:
16119 mips32_op = OPC_SRLV;
16120 goto do_shift;
16121 case SRAV:
16122 mips32_op = OPC_SRAV;
16123 goto do_shift;
16124 case ROTRV:
16125 mips32_op = OPC_ROTRV;
16126 do_shift:
16127 gen_shift(ctx, mips32_op, rd, rs, rt);
16128 break;
16129 /* Logical operations */
16130 case AND:
16131 mips32_op = OPC_AND;
16132 goto do_logic;
16133 case OR32:
16134 mips32_op = OPC_OR;
16135 goto do_logic;
16136 case NOR:
16137 mips32_op = OPC_NOR;
16138 goto do_logic;
16139 case XOR32:
16140 mips32_op = OPC_XOR;
16141 do_logic:
16142 gen_logic(ctx, mips32_op, rd, rs, rt);
16143 break;
16144 /* Set less than */
16145 case SLT:
16146 mips32_op = OPC_SLT;
16147 goto do_slt;
16148 case SLTU:
16149 mips32_op = OPC_SLTU;
16150 do_slt:
16151 gen_slt(ctx, mips32_op, rd, rs, rt);
16152 break;
16153 default:
16154 goto pool32a_invalid;
16156 break;
16157 case 0x18:
16158 minor = (ctx->opcode >> 6) & 0xf;
16159 switch (minor) {
16160 /* Conditional moves */
16161 case MOVN: /* MUL */
16162 if (ctx->insn_flags & ISA_MIPS32R6) {
16163 /* MUL */
16164 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16165 } else {
16166 /* MOVN */
16167 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16169 break;
16170 case MOVZ: /* MUH */
16171 if (ctx->insn_flags & ISA_MIPS32R6) {
16172 /* MUH */
16173 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16174 } else {
16175 /* MOVZ */
16176 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16178 break;
16179 case MULU:
16180 check_insn(ctx, ISA_MIPS32R6);
16181 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16182 break;
16183 case MUHU:
16184 check_insn(ctx, ISA_MIPS32R6);
16185 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16186 break;
16187 case LWXS: /* DIV */
16188 if (ctx->insn_flags & ISA_MIPS32R6) {
16189 /* DIV */
16190 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16191 } else {
16192 /* LWXS */
16193 gen_ldxs(ctx, rs, rt, rd);
16195 break;
16196 case MOD:
16197 check_insn(ctx, ISA_MIPS32R6);
16198 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16199 break;
16200 case R6_DIVU:
16201 check_insn(ctx, ISA_MIPS32R6);
16202 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16203 break;
16204 case MODU:
16205 check_insn(ctx, ISA_MIPS32R6);
16206 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16207 break;
16208 default:
16209 goto pool32a_invalid;
16211 break;
16212 case INS:
16213 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16214 return;
16215 case LSA:
16216 check_insn(ctx, ISA_MIPS32R6);
16217 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16218 extract32(ctx->opcode, 9, 2));
16219 break;
16220 case ALIGN:
16221 check_insn(ctx, ISA_MIPS32R6);
16222 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16223 break;
16224 case EXT:
16225 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16226 return;
16227 case POOL32AXF:
16228 gen_pool32axf(env, ctx, rt, rs);
16229 break;
16230 case BREAK32:
16231 generate_exception_end(ctx, EXCP_BREAK);
16232 break;
16233 case SIGRIE:
16234 check_insn(ctx, ISA_MIPS32R6);
16235 generate_exception_end(ctx, EXCP_RI);
16236 break;
16237 default:
16238 pool32a_invalid:
16239 MIPS_INVAL("pool32a");
16240 generate_exception_end(ctx, EXCP_RI);
16241 break;
16243 break;
16244 case POOL32B:
16245 minor = (ctx->opcode >> 12) & 0xf;
16246 switch (minor) {
16247 case CACHE:
16248 check_cp0_enabled(ctx);
16249 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16250 gen_cache_operation(ctx, rt, rs, imm);
16252 break;
16253 case LWC2:
16254 case SWC2:
16255 /* COP2: Not implemented. */
16256 generate_exception_err(ctx, EXCP_CpU, 2);
16257 break;
16258 #ifdef TARGET_MIPS64
16259 case LDP:
16260 case SDP:
16261 check_insn(ctx, ISA_MIPS3);
16262 check_mips_64(ctx);
16263 #endif
16264 /* fall through */
16265 case LWP:
16266 case SWP:
16267 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16268 break;
16269 #ifdef TARGET_MIPS64
16270 case LDM:
16271 case SDM:
16272 check_insn(ctx, ISA_MIPS3);
16273 check_mips_64(ctx);
16274 #endif
16275 /* fall through */
16276 case LWM32:
16277 case SWM32:
16278 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16279 break;
16280 default:
16281 MIPS_INVAL("pool32b");
16282 generate_exception_end(ctx, EXCP_RI);
16283 break;
16285 break;
16286 case POOL32F:
16287 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16288 minor = ctx->opcode & 0x3f;
16289 check_cp1_enabled(ctx);
16290 switch (minor) {
16291 case ALNV_PS:
16292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16293 mips32_op = OPC_ALNV_PS;
16294 goto do_madd;
16295 case MADD_S:
16296 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16297 mips32_op = OPC_MADD_S;
16298 goto do_madd;
16299 case MADD_D:
16300 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16301 mips32_op = OPC_MADD_D;
16302 goto do_madd;
16303 case MADD_PS:
16304 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16305 mips32_op = OPC_MADD_PS;
16306 goto do_madd;
16307 case MSUB_S:
16308 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16309 mips32_op = OPC_MSUB_S;
16310 goto do_madd;
16311 case MSUB_D:
16312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16313 mips32_op = OPC_MSUB_D;
16314 goto do_madd;
16315 case MSUB_PS:
16316 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16317 mips32_op = OPC_MSUB_PS;
16318 goto do_madd;
16319 case NMADD_S:
16320 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16321 mips32_op = OPC_NMADD_S;
16322 goto do_madd;
16323 case NMADD_D:
16324 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16325 mips32_op = OPC_NMADD_D;
16326 goto do_madd;
16327 case NMADD_PS:
16328 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16329 mips32_op = OPC_NMADD_PS;
16330 goto do_madd;
16331 case NMSUB_S:
16332 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16333 mips32_op = OPC_NMSUB_S;
16334 goto do_madd;
16335 case NMSUB_D:
16336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16337 mips32_op = OPC_NMSUB_D;
16338 goto do_madd;
16339 case NMSUB_PS:
16340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16341 mips32_op = OPC_NMSUB_PS;
16342 do_madd:
16343 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16344 break;
16345 case CABS_COND_FMT:
16346 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16347 cond = (ctx->opcode >> 6) & 0xf;
16348 cc = (ctx->opcode >> 13) & 0x7;
16349 fmt = (ctx->opcode >> 10) & 0x3;
16350 switch (fmt) {
16351 case 0x0:
16352 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16353 break;
16354 case 0x1:
16355 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16356 break;
16357 case 0x2:
16358 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16359 break;
16360 default:
16361 goto pool32f_invalid;
16363 break;
16364 case C_COND_FMT:
16365 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16366 cond = (ctx->opcode >> 6) & 0xf;
16367 cc = (ctx->opcode >> 13) & 0x7;
16368 fmt = (ctx->opcode >> 10) & 0x3;
16369 switch (fmt) {
16370 case 0x0:
16371 gen_cmp_s(ctx, cond, rt, rs, cc);
16372 break;
16373 case 0x1:
16374 gen_cmp_d(ctx, cond, rt, rs, cc);
16375 break;
16376 case 0x2:
16377 gen_cmp_ps(ctx, cond, rt, rs, cc);
16378 break;
16379 default:
16380 goto pool32f_invalid;
16382 break;
16383 case CMP_CONDN_S:
16384 check_insn(ctx, ISA_MIPS32R6);
16385 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16386 break;
16387 case CMP_CONDN_D:
16388 check_insn(ctx, ISA_MIPS32R6);
16389 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16390 break;
16391 case POOL32FXF:
16392 gen_pool32fxf(ctx, rt, rs);
16393 break;
16394 case 0x00:
16395 /* PLL foo */
16396 switch ((ctx->opcode >> 6) & 0x7) {
16397 case PLL_PS:
16398 mips32_op = OPC_PLL_PS;
16399 goto do_ps;
16400 case PLU_PS:
16401 mips32_op = OPC_PLU_PS;
16402 goto do_ps;
16403 case PUL_PS:
16404 mips32_op = OPC_PUL_PS;
16405 goto do_ps;
16406 case PUU_PS:
16407 mips32_op = OPC_PUU_PS;
16408 goto do_ps;
16409 case CVT_PS_S:
16410 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16411 mips32_op = OPC_CVT_PS_S;
16412 do_ps:
16413 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16414 break;
16415 default:
16416 goto pool32f_invalid;
16418 break;
16419 case MIN_FMT:
16420 check_insn(ctx, ISA_MIPS32R6);
16421 switch ((ctx->opcode >> 9) & 0x3) {
16422 case FMT_SDPS_S:
16423 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16424 break;
16425 case FMT_SDPS_D:
16426 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16427 break;
16428 default:
16429 goto pool32f_invalid;
16431 break;
16432 case 0x08:
16433 /* [LS][WDU]XC1 */
16434 switch ((ctx->opcode >> 6) & 0x7) {
16435 case LWXC1:
16436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16437 mips32_op = OPC_LWXC1;
16438 goto do_ldst_cp1;
16439 case SWXC1:
16440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16441 mips32_op = OPC_SWXC1;
16442 goto do_ldst_cp1;
16443 case LDXC1:
16444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16445 mips32_op = OPC_LDXC1;
16446 goto do_ldst_cp1;
16447 case SDXC1:
16448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16449 mips32_op = OPC_SDXC1;
16450 goto do_ldst_cp1;
16451 case LUXC1:
16452 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16453 mips32_op = OPC_LUXC1;
16454 goto do_ldst_cp1;
16455 case SUXC1:
16456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16457 mips32_op = OPC_SUXC1;
16458 do_ldst_cp1:
16459 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16460 break;
16461 default:
16462 goto pool32f_invalid;
16464 break;
16465 case MAX_FMT:
16466 check_insn(ctx, ISA_MIPS32R6);
16467 switch ((ctx->opcode >> 9) & 0x3) {
16468 case FMT_SDPS_S:
16469 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16470 break;
16471 case FMT_SDPS_D:
16472 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16473 break;
16474 default:
16475 goto pool32f_invalid;
16477 break;
16478 case 0x18:
16479 /* 3D insns */
16480 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16481 fmt = (ctx->opcode >> 9) & 0x3;
16482 switch ((ctx->opcode >> 6) & 0x7) {
16483 case RSQRT2_FMT:
16484 switch (fmt) {
16485 case FMT_SDPS_S:
16486 mips32_op = OPC_RSQRT2_S;
16487 goto do_3d;
16488 case FMT_SDPS_D:
16489 mips32_op = OPC_RSQRT2_D;
16490 goto do_3d;
16491 case FMT_SDPS_PS:
16492 mips32_op = OPC_RSQRT2_PS;
16493 goto do_3d;
16494 default:
16495 goto pool32f_invalid;
16497 break;
16498 case RECIP2_FMT:
16499 switch (fmt) {
16500 case FMT_SDPS_S:
16501 mips32_op = OPC_RECIP2_S;
16502 goto do_3d;
16503 case FMT_SDPS_D:
16504 mips32_op = OPC_RECIP2_D;
16505 goto do_3d;
16506 case FMT_SDPS_PS:
16507 mips32_op = OPC_RECIP2_PS;
16508 goto do_3d;
16509 default:
16510 goto pool32f_invalid;
16512 break;
16513 case ADDR_PS:
16514 mips32_op = OPC_ADDR_PS;
16515 goto do_3d;
16516 case MULR_PS:
16517 mips32_op = OPC_MULR_PS;
16518 do_3d:
16519 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16520 break;
16521 default:
16522 goto pool32f_invalid;
16524 break;
16525 case 0x20:
16526 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16527 cc = (ctx->opcode >> 13) & 0x7;
16528 fmt = (ctx->opcode >> 9) & 0x3;
16529 switch ((ctx->opcode >> 6) & 0x7) {
16530 case MOVF_FMT: /* RINT_FMT */
16531 if (ctx->insn_flags & ISA_MIPS32R6) {
16532 /* RINT_FMT */
16533 switch (fmt) {
16534 case FMT_SDPS_S:
16535 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16536 break;
16537 case FMT_SDPS_D:
16538 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16539 break;
16540 default:
16541 goto pool32f_invalid;
16543 } else {
16544 /* MOVF_FMT */
16545 switch (fmt) {
16546 case FMT_SDPS_S:
16547 gen_movcf_s(ctx, rs, rt, cc, 0);
16548 break;
16549 case FMT_SDPS_D:
16550 gen_movcf_d(ctx, rs, rt, cc, 0);
16551 break;
16552 case FMT_SDPS_PS:
16553 check_ps(ctx);
16554 gen_movcf_ps(ctx, rs, rt, cc, 0);
16555 break;
16556 default:
16557 goto pool32f_invalid;
16560 break;
16561 case MOVT_FMT: /* CLASS_FMT */
16562 if (ctx->insn_flags & ISA_MIPS32R6) {
16563 /* CLASS_FMT */
16564 switch (fmt) {
16565 case FMT_SDPS_S:
16566 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16567 break;
16568 case FMT_SDPS_D:
16569 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16570 break;
16571 default:
16572 goto pool32f_invalid;
16574 } else {
16575 /* MOVT_FMT */
16576 switch (fmt) {
16577 case FMT_SDPS_S:
16578 gen_movcf_s(ctx, rs, rt, cc, 1);
16579 break;
16580 case FMT_SDPS_D:
16581 gen_movcf_d(ctx, rs, rt, cc, 1);
16582 break;
16583 case FMT_SDPS_PS:
16584 check_ps(ctx);
16585 gen_movcf_ps(ctx, rs, rt, cc, 1);
16586 break;
16587 default:
16588 goto pool32f_invalid;
16591 break;
16592 case PREFX:
16593 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16594 break;
16595 default:
16596 goto pool32f_invalid;
16598 break;
16599 #define FINSN_3ARG_SDPS(prfx) \
16600 switch ((ctx->opcode >> 8) & 0x3) { \
16601 case FMT_SDPS_S: \
16602 mips32_op = OPC_##prfx##_S; \
16603 goto do_fpop; \
16604 case FMT_SDPS_D: \
16605 mips32_op = OPC_##prfx##_D; \
16606 goto do_fpop; \
16607 case FMT_SDPS_PS: \
16608 check_ps(ctx); \
16609 mips32_op = OPC_##prfx##_PS; \
16610 goto do_fpop; \
16611 default: \
16612 goto pool32f_invalid; \
16614 case MINA_FMT:
16615 check_insn(ctx, ISA_MIPS32R6);
16616 switch ((ctx->opcode >> 9) & 0x3) {
16617 case FMT_SDPS_S:
16618 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16619 break;
16620 case FMT_SDPS_D:
16621 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16622 break;
16623 default:
16624 goto pool32f_invalid;
16626 break;
16627 case MAXA_FMT:
16628 check_insn(ctx, ISA_MIPS32R6);
16629 switch ((ctx->opcode >> 9) & 0x3) {
16630 case FMT_SDPS_S:
16631 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16632 break;
16633 case FMT_SDPS_D:
16634 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16635 break;
16636 default:
16637 goto pool32f_invalid;
16639 break;
16640 case 0x30:
16641 /* regular FP ops */
16642 switch ((ctx->opcode >> 6) & 0x3) {
16643 case ADD_FMT:
16644 FINSN_3ARG_SDPS(ADD);
16645 break;
16646 case SUB_FMT:
16647 FINSN_3ARG_SDPS(SUB);
16648 break;
16649 case MUL_FMT:
16650 FINSN_3ARG_SDPS(MUL);
16651 break;
16652 case DIV_FMT:
16653 fmt = (ctx->opcode >> 8) & 0x3;
16654 if (fmt == 1) {
16655 mips32_op = OPC_DIV_D;
16656 } else if (fmt == 0) {
16657 mips32_op = OPC_DIV_S;
16658 } else {
16659 goto pool32f_invalid;
16661 goto do_fpop;
16662 default:
16663 goto pool32f_invalid;
16665 break;
16666 case 0x38:
16667 /* cmovs */
16668 switch ((ctx->opcode >> 6) & 0x7) {
16669 case MOVN_FMT: /* SELEQZ_FMT */
16670 if (ctx->insn_flags & ISA_MIPS32R6) {
16671 /* SELEQZ_FMT */
16672 switch ((ctx->opcode >> 9) & 0x3) {
16673 case FMT_SDPS_S:
16674 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16675 break;
16676 case FMT_SDPS_D:
16677 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16678 break;
16679 default:
16680 goto pool32f_invalid;
16682 } else {
16683 /* MOVN_FMT */
16684 FINSN_3ARG_SDPS(MOVN);
16686 break;
16687 case MOVN_FMT_04:
16688 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16689 FINSN_3ARG_SDPS(MOVN);
16690 break;
16691 case MOVZ_FMT: /* SELNEZ_FMT */
16692 if (ctx->insn_flags & ISA_MIPS32R6) {
16693 /* SELNEZ_FMT */
16694 switch ((ctx->opcode >> 9) & 0x3) {
16695 case FMT_SDPS_S:
16696 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16697 break;
16698 case FMT_SDPS_D:
16699 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16700 break;
16701 default:
16702 goto pool32f_invalid;
16704 } else {
16705 /* MOVZ_FMT */
16706 FINSN_3ARG_SDPS(MOVZ);
16708 break;
16709 case MOVZ_FMT_05:
16710 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16711 FINSN_3ARG_SDPS(MOVZ);
16712 break;
16713 case SEL_FMT:
16714 check_insn(ctx, ISA_MIPS32R6);
16715 switch ((ctx->opcode >> 9) & 0x3) {
16716 case FMT_SDPS_S:
16717 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16718 break;
16719 case FMT_SDPS_D:
16720 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16721 break;
16722 default:
16723 goto pool32f_invalid;
16725 break;
16726 case MADDF_FMT:
16727 check_insn(ctx, ISA_MIPS32R6);
16728 switch ((ctx->opcode >> 9) & 0x3) {
16729 case FMT_SDPS_S:
16730 mips32_op = OPC_MADDF_S;
16731 goto do_fpop;
16732 case FMT_SDPS_D:
16733 mips32_op = OPC_MADDF_D;
16734 goto do_fpop;
16735 default:
16736 goto pool32f_invalid;
16738 break;
16739 case MSUBF_FMT:
16740 check_insn(ctx, ISA_MIPS32R6);
16741 switch ((ctx->opcode >> 9) & 0x3) {
16742 case FMT_SDPS_S:
16743 mips32_op = OPC_MSUBF_S;
16744 goto do_fpop;
16745 case FMT_SDPS_D:
16746 mips32_op = OPC_MSUBF_D;
16747 goto do_fpop;
16748 default:
16749 goto pool32f_invalid;
16751 break;
16752 default:
16753 goto pool32f_invalid;
16755 break;
16756 do_fpop:
16757 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16758 break;
16759 default:
16760 pool32f_invalid:
16761 MIPS_INVAL("pool32f");
16762 generate_exception_end(ctx, EXCP_RI);
16763 break;
16765 } else {
16766 generate_exception_err(ctx, EXCP_CpU, 1);
16768 break;
16769 case POOL32I:
16770 minor = (ctx->opcode >> 21) & 0x1f;
16771 switch (minor) {
16772 case BLTZ:
16773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16774 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16775 break;
16776 case BLTZAL:
16777 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16778 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16779 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16780 break;
16781 case BLTZALS:
16782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16783 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16784 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16785 break;
16786 case BGEZ:
16787 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16788 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16789 break;
16790 case BGEZAL:
16791 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16792 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16793 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16794 break;
16795 case BGEZALS:
16796 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16797 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16798 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16799 break;
16800 case BLEZ:
16801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16802 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16803 break;
16804 case BGTZ:
16805 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16806 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16807 break;
16809 /* Traps */
16810 case TLTI: /* BC1EQZC */
16811 if (ctx->insn_flags & ISA_MIPS32R6) {
16812 /* BC1EQZC */
16813 check_cp1_enabled(ctx);
16814 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16815 } else {
16816 /* TLTI */
16817 mips32_op = OPC_TLTI;
16818 goto do_trapi;
16820 break;
16821 case TGEI: /* BC1NEZC */
16822 if (ctx->insn_flags & ISA_MIPS32R6) {
16823 /* BC1NEZC */
16824 check_cp1_enabled(ctx);
16825 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16826 } else {
16827 /* TGEI */
16828 mips32_op = OPC_TGEI;
16829 goto do_trapi;
16831 break;
16832 case TLTIU:
16833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16834 mips32_op = OPC_TLTIU;
16835 goto do_trapi;
16836 case TGEIU:
16837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16838 mips32_op = OPC_TGEIU;
16839 goto do_trapi;
16840 case TNEI: /* SYNCI */
16841 if (ctx->insn_flags & ISA_MIPS32R6) {
16842 /* SYNCI */
16844 * Break the TB to be able to sync copied instructions
16845 * immediately.
16847 ctx->base.is_jmp = DISAS_STOP;
16848 } else {
16849 /* TNEI */
16850 mips32_op = OPC_TNEI;
16851 goto do_trapi;
16853 break;
16854 case TEQI:
16855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16856 mips32_op = OPC_TEQI;
16857 do_trapi:
16858 gen_trap(ctx, mips32_op, rs, -1, imm);
16859 break;
16861 case BNEZC:
16862 case BEQZC:
16863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16864 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16865 4, rs, 0, imm << 1, 0);
16867 * Compact branches don't have a delay slot, so just let
16868 * the normal delay slot handling take us to the branch
16869 * target.
16871 break;
16872 case LUI:
16873 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16874 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16875 break;
16876 case SYNCI:
16877 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16879 * Break the TB to be able to sync copied instructions
16880 * immediately.
16882 ctx->base.is_jmp = DISAS_STOP;
16883 break;
16884 case BC2F:
16885 case BC2T:
16886 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16887 /* COP2: Not implemented. */
16888 generate_exception_err(ctx, EXCP_CpU, 2);
16889 break;
16890 case BC1F:
16891 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16892 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16893 goto do_cp1branch;
16894 case BC1T:
16895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16896 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16897 goto do_cp1branch;
16898 case BC1ANY4F:
16899 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16900 mips32_op = OPC_BC1FANY4;
16901 goto do_cp1mips3d;
16902 case BC1ANY4T:
16903 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16904 mips32_op = OPC_BC1TANY4;
16905 do_cp1mips3d:
16906 check_cop1x(ctx);
16907 check_insn(ctx, ASE_MIPS3D);
16908 /* Fall through */
16909 do_cp1branch:
16910 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16911 check_cp1_enabled(ctx);
16912 gen_compute_branch1(ctx, mips32_op,
16913 (ctx->opcode >> 18) & 0x7, imm << 1);
16914 } else {
16915 generate_exception_err(ctx, EXCP_CpU, 1);
16917 break;
16918 case BPOSGE64:
16919 case BPOSGE32:
16920 /* MIPS DSP: not implemented */
16921 /* Fall through */
16922 default:
16923 MIPS_INVAL("pool32i");
16924 generate_exception_end(ctx, EXCP_RI);
16925 break;
16927 break;
16928 case POOL32C:
16929 minor = (ctx->opcode >> 12) & 0xf;
16930 offset = sextract32(ctx->opcode, 0,
16931 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16932 switch (minor) {
16933 case LWL:
16934 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16935 mips32_op = OPC_LWL;
16936 goto do_ld_lr;
16937 case SWL:
16938 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16939 mips32_op = OPC_SWL;
16940 goto do_st_lr;
16941 case LWR:
16942 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16943 mips32_op = OPC_LWR;
16944 goto do_ld_lr;
16945 case SWR:
16946 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16947 mips32_op = OPC_SWR;
16948 goto do_st_lr;
16949 #if defined(TARGET_MIPS64)
16950 case LDL:
16951 check_insn(ctx, ISA_MIPS3);
16952 check_mips_64(ctx);
16953 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16954 mips32_op = OPC_LDL;
16955 goto do_ld_lr;
16956 case SDL:
16957 check_insn(ctx, ISA_MIPS3);
16958 check_mips_64(ctx);
16959 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16960 mips32_op = OPC_SDL;
16961 goto do_st_lr;
16962 case LDR:
16963 check_insn(ctx, ISA_MIPS3);
16964 check_mips_64(ctx);
16965 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16966 mips32_op = OPC_LDR;
16967 goto do_ld_lr;
16968 case SDR:
16969 check_insn(ctx, ISA_MIPS3);
16970 check_mips_64(ctx);
16971 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16972 mips32_op = OPC_SDR;
16973 goto do_st_lr;
16974 case LWU:
16975 check_insn(ctx, ISA_MIPS3);
16976 check_mips_64(ctx);
16977 mips32_op = OPC_LWU;
16978 goto do_ld_lr;
16979 case LLD:
16980 check_insn(ctx, ISA_MIPS3);
16981 check_mips_64(ctx);
16982 mips32_op = OPC_LLD;
16983 goto do_ld_lr;
16984 #endif
16985 case LL:
16986 mips32_op = OPC_LL;
16987 goto do_ld_lr;
16988 do_ld_lr:
16989 gen_ld(ctx, mips32_op, rt, rs, offset);
16990 break;
16991 do_st_lr:
16992 gen_st(ctx, mips32_op, rt, rs, offset);
16993 break;
16994 case SC:
16995 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16996 break;
16997 #if defined(TARGET_MIPS64)
16998 case SCD:
16999 check_insn(ctx, ISA_MIPS3);
17000 check_mips_64(ctx);
17001 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17002 break;
17003 #endif
17004 case LD_EVA:
17005 if (!ctx->eva) {
17006 MIPS_INVAL("pool32c ld-eva");
17007 generate_exception_end(ctx, EXCP_RI);
17008 break;
17010 check_cp0_enabled(ctx);
17012 minor2 = (ctx->opcode >> 9) & 0x7;
17013 offset = sextract32(ctx->opcode, 0, 9);
17014 switch (minor2) {
17015 case LBUE:
17016 mips32_op = OPC_LBUE;
17017 goto do_ld_lr;
17018 case LHUE:
17019 mips32_op = OPC_LHUE;
17020 goto do_ld_lr;
17021 case LWLE:
17022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17023 mips32_op = OPC_LWLE;
17024 goto do_ld_lr;
17025 case LWRE:
17026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17027 mips32_op = OPC_LWRE;
17028 goto do_ld_lr;
17029 case LBE:
17030 mips32_op = OPC_LBE;
17031 goto do_ld_lr;
17032 case LHE:
17033 mips32_op = OPC_LHE;
17034 goto do_ld_lr;
17035 case LLE:
17036 mips32_op = OPC_LLE;
17037 goto do_ld_lr;
17038 case LWE:
17039 mips32_op = OPC_LWE;
17040 goto do_ld_lr;
17042 break;
17043 case ST_EVA:
17044 if (!ctx->eva) {
17045 MIPS_INVAL("pool32c st-eva");
17046 generate_exception_end(ctx, EXCP_RI);
17047 break;
17049 check_cp0_enabled(ctx);
17051 minor2 = (ctx->opcode >> 9) & 0x7;
17052 offset = sextract32(ctx->opcode, 0, 9);
17053 switch (minor2) {
17054 case SWLE:
17055 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17056 mips32_op = OPC_SWLE;
17057 goto do_st_lr;
17058 case SWRE:
17059 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17060 mips32_op = OPC_SWRE;
17061 goto do_st_lr;
17062 case PREFE:
17063 /* Treat as no-op */
17064 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17065 /* hint codes 24-31 are reserved and signal RI */
17066 generate_exception(ctx, EXCP_RI);
17068 break;
17069 case CACHEE:
17070 /* Treat as no-op */
17071 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17072 gen_cache_operation(ctx, rt, rs, offset);
17074 break;
17075 case SBE:
17076 mips32_op = OPC_SBE;
17077 goto do_st_lr;
17078 case SHE:
17079 mips32_op = OPC_SHE;
17080 goto do_st_lr;
17081 case SCE:
17082 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17083 break;
17084 case SWE:
17085 mips32_op = OPC_SWE;
17086 goto do_st_lr;
17088 break;
17089 case PREF:
17090 /* Treat as no-op */
17091 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17092 /* hint codes 24-31 are reserved and signal RI */
17093 generate_exception(ctx, EXCP_RI);
17095 break;
17096 default:
17097 MIPS_INVAL("pool32c");
17098 generate_exception_end(ctx, EXCP_RI);
17099 break;
17101 break;
17102 case ADDI32: /* AUI, LUI */
17103 if (ctx->insn_flags & ISA_MIPS32R6) {
17104 /* AUI, LUI */
17105 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17106 } else {
17107 /* ADDI32 */
17108 mips32_op = OPC_ADDI;
17109 goto do_addi;
17111 break;
17112 case ADDIU32:
17113 mips32_op = OPC_ADDIU;
17114 do_addi:
17115 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17116 break;
17118 /* Logical operations */
17119 case ORI32:
17120 mips32_op = OPC_ORI;
17121 goto do_logici;
17122 case XORI32:
17123 mips32_op = OPC_XORI;
17124 goto do_logici;
17125 case ANDI32:
17126 mips32_op = OPC_ANDI;
17127 do_logici:
17128 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17129 break;
17131 /* Set less than immediate */
17132 case SLTI32:
17133 mips32_op = OPC_SLTI;
17134 goto do_slti;
17135 case SLTIU32:
17136 mips32_op = OPC_SLTIU;
17137 do_slti:
17138 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17139 break;
17140 case JALX32:
17141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17142 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17143 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17144 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17145 break;
17146 case JALS32: /* BOVC, BEQC, BEQZALC */
17147 if (ctx->insn_flags & ISA_MIPS32R6) {
17148 if (rs >= rt) {
17149 /* BOVC */
17150 mips32_op = OPC_BOVC;
17151 } else if (rs < rt && rs == 0) {
17152 /* BEQZALC */
17153 mips32_op = OPC_BEQZALC;
17154 } else {
17155 /* BEQC */
17156 mips32_op = OPC_BEQC;
17158 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17159 } else {
17160 /* JALS32 */
17161 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17162 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17163 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17165 break;
17166 case BEQ32: /* BC */
17167 if (ctx->insn_flags & ISA_MIPS32R6) {
17168 /* BC */
17169 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17170 sextract32(ctx->opcode << 1, 0, 27));
17171 } else {
17172 /* BEQ32 */
17173 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17175 break;
17176 case BNE32: /* BALC */
17177 if (ctx->insn_flags & ISA_MIPS32R6) {
17178 /* BALC */
17179 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17180 sextract32(ctx->opcode << 1, 0, 27));
17181 } else {
17182 /* BNE32 */
17183 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17185 break;
17186 case J32: /* BGTZC, BLTZC, BLTC */
17187 if (ctx->insn_flags & ISA_MIPS32R6) {
17188 if (rs == 0 && rt != 0) {
17189 /* BGTZC */
17190 mips32_op = OPC_BGTZC;
17191 } else if (rs != 0 && rt != 0 && rs == rt) {
17192 /* BLTZC */
17193 mips32_op = OPC_BLTZC;
17194 } else {
17195 /* BLTC */
17196 mips32_op = OPC_BLTC;
17198 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17199 } else {
17200 /* J32 */
17201 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17202 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17204 break;
17205 case JAL32: /* BLEZC, BGEZC, BGEC */
17206 if (ctx->insn_flags & ISA_MIPS32R6) {
17207 if (rs == 0 && rt != 0) {
17208 /* BLEZC */
17209 mips32_op = OPC_BLEZC;
17210 } else if (rs != 0 && rt != 0 && rs == rt) {
17211 /* BGEZC */
17212 mips32_op = OPC_BGEZC;
17213 } else {
17214 /* BGEC */
17215 mips32_op = OPC_BGEC;
17217 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17218 } else {
17219 /* JAL32 */
17220 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17221 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17222 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17224 break;
17225 /* Floating point (COP1) */
17226 case LWC132:
17227 mips32_op = OPC_LWC1;
17228 goto do_cop1;
17229 case LDC132:
17230 mips32_op = OPC_LDC1;
17231 goto do_cop1;
17232 case SWC132:
17233 mips32_op = OPC_SWC1;
17234 goto do_cop1;
17235 case SDC132:
17236 mips32_op = OPC_SDC1;
17237 do_cop1:
17238 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17239 break;
17240 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17241 if (ctx->insn_flags & ISA_MIPS32R6) {
17242 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17243 switch ((ctx->opcode >> 16) & 0x1f) {
17244 case ADDIUPC_00:
17245 case ADDIUPC_01:
17246 case ADDIUPC_02:
17247 case ADDIUPC_03:
17248 case ADDIUPC_04:
17249 case ADDIUPC_05:
17250 case ADDIUPC_06:
17251 case ADDIUPC_07:
17252 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17253 break;
17254 case AUIPC:
17255 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17256 break;
17257 case ALUIPC:
17258 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17259 break;
17260 case LWPC_08:
17261 case LWPC_09:
17262 case LWPC_0A:
17263 case LWPC_0B:
17264 case LWPC_0C:
17265 case LWPC_0D:
17266 case LWPC_0E:
17267 case LWPC_0F:
17268 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17269 break;
17270 default:
17271 generate_exception(ctx, EXCP_RI);
17272 break;
17274 } else {
17275 /* ADDIUPC */
17276 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17277 offset = SIMM(ctx->opcode, 0, 23) << 2;
17279 gen_addiupc(ctx, reg, offset, 0, 0);
17281 break;
17282 case BNVC: /* BNEC, BNEZALC */
17283 check_insn(ctx, ISA_MIPS32R6);
17284 if (rs >= rt) {
17285 /* BNVC */
17286 mips32_op = OPC_BNVC;
17287 } else if (rs < rt && rs == 0) {
17288 /* BNEZALC */
17289 mips32_op = OPC_BNEZALC;
17290 } else {
17291 /* BNEC */
17292 mips32_op = OPC_BNEC;
17294 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17295 break;
17296 case R6_BNEZC: /* JIALC */
17297 check_insn(ctx, ISA_MIPS32R6);
17298 if (rt != 0) {
17299 /* BNEZC */
17300 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17301 sextract32(ctx->opcode << 1, 0, 22));
17302 } else {
17303 /* JIALC */
17304 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17306 break;
17307 case R6_BEQZC: /* JIC */
17308 check_insn(ctx, ISA_MIPS32R6);
17309 if (rt != 0) {
17310 /* BEQZC */
17311 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17312 sextract32(ctx->opcode << 1, 0, 22));
17313 } else {
17314 /* JIC */
17315 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17317 break;
17318 case BLEZALC: /* BGEZALC, BGEUC */
17319 check_insn(ctx, ISA_MIPS32R6);
17320 if (rs == 0 && rt != 0) {
17321 /* BLEZALC */
17322 mips32_op = OPC_BLEZALC;
17323 } else if (rs != 0 && rt != 0 && rs == rt) {
17324 /* BGEZALC */
17325 mips32_op = OPC_BGEZALC;
17326 } else {
17327 /* BGEUC */
17328 mips32_op = OPC_BGEUC;
17330 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17331 break;
17332 case BGTZALC: /* BLTZALC, BLTUC */
17333 check_insn(ctx, ISA_MIPS32R6);
17334 if (rs == 0 && rt != 0) {
17335 /* BGTZALC */
17336 mips32_op = OPC_BGTZALC;
17337 } else if (rs != 0 && rt != 0 && rs == rt) {
17338 /* BLTZALC */
17339 mips32_op = OPC_BLTZALC;
17340 } else {
17341 /* BLTUC */
17342 mips32_op = OPC_BLTUC;
17344 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17345 break;
17346 /* Loads and stores */
17347 case LB32:
17348 mips32_op = OPC_LB;
17349 goto do_ld;
17350 case LBU32:
17351 mips32_op = OPC_LBU;
17352 goto do_ld;
17353 case LH32:
17354 mips32_op = OPC_LH;
17355 goto do_ld;
17356 case LHU32:
17357 mips32_op = OPC_LHU;
17358 goto do_ld;
17359 case LW32:
17360 mips32_op = OPC_LW;
17361 goto do_ld;
17362 #ifdef TARGET_MIPS64
17363 case LD32:
17364 check_insn(ctx, ISA_MIPS3);
17365 check_mips_64(ctx);
17366 mips32_op = OPC_LD;
17367 goto do_ld;
17368 case SD32:
17369 check_insn(ctx, ISA_MIPS3);
17370 check_mips_64(ctx);
17371 mips32_op = OPC_SD;
17372 goto do_st;
17373 #endif
17374 case SB32:
17375 mips32_op = OPC_SB;
17376 goto do_st;
17377 case SH32:
17378 mips32_op = OPC_SH;
17379 goto do_st;
17380 case SW32:
17381 mips32_op = OPC_SW;
17382 goto do_st;
17383 do_ld:
17384 gen_ld(ctx, mips32_op, rt, rs, imm);
17385 break;
17386 do_st:
17387 gen_st(ctx, mips32_op, rt, rs, imm);
17388 break;
17389 default:
17390 generate_exception_end(ctx, EXCP_RI);
17391 break;
17395 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17397 uint32_t op;
17399 /* make sure instructions are on a halfword boundary */
17400 if (ctx->base.pc_next & 0x1) {
17401 env->CP0_BadVAddr = ctx->base.pc_next;
17402 generate_exception_end(ctx, EXCP_AdEL);
17403 return 2;
17406 op = (ctx->opcode >> 10) & 0x3f;
17407 /* Enforce properly-sized instructions in a delay slot */
17408 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17409 switch (op & 0x7) { /* MSB-3..MSB-5 */
17410 case 0:
17411 /* POOL32A, POOL32B, POOL32I, POOL32C */
17412 case 4:
17413 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17414 case 5:
17415 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17416 case 6:
17417 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17418 case 7:
17419 /* LB32, LH32, LWC132, LDC132, LW32 */
17420 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17421 generate_exception_end(ctx, EXCP_RI);
17422 return 2;
17424 break;
17425 case 1:
17426 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17427 case 2:
17428 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17429 case 3:
17430 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17431 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17432 generate_exception_end(ctx, EXCP_RI);
17433 return 2;
17435 break;
17439 switch (op) {
17440 case POOL16A:
17442 int rd = mmreg(uMIPS_RD(ctx->opcode));
17443 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17444 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17445 uint32_t opc = 0;
17447 switch (ctx->opcode & 0x1) {
17448 case ADDU16:
17449 opc = OPC_ADDU;
17450 break;
17451 case SUBU16:
17452 opc = OPC_SUBU;
17453 break;
17455 if (ctx->insn_flags & ISA_MIPS32R6) {
17457 * In the Release 6, the register number location in
17458 * the instruction encoding has changed.
17460 gen_arith(ctx, opc, rs1, rd, rs2);
17461 } else {
17462 gen_arith(ctx, opc, rd, rs1, rs2);
17465 break;
17466 case POOL16B:
17468 int rd = mmreg(uMIPS_RD(ctx->opcode));
17469 int rs = mmreg(uMIPS_RS(ctx->opcode));
17470 int amount = (ctx->opcode >> 1) & 0x7;
17471 uint32_t opc = 0;
17472 amount = amount == 0 ? 8 : amount;
17474 switch (ctx->opcode & 0x1) {
17475 case SLL16:
17476 opc = OPC_SLL;
17477 break;
17478 case SRL16:
17479 opc = OPC_SRL;
17480 break;
17483 gen_shift_imm(ctx, opc, rd, rs, amount);
17485 break;
17486 case POOL16C:
17487 if (ctx->insn_flags & ISA_MIPS32R6) {
17488 gen_pool16c_r6_insn(ctx);
17489 } else {
17490 gen_pool16c_insn(ctx);
17492 break;
17493 case LWGP16:
17495 int rd = mmreg(uMIPS_RD(ctx->opcode));
17496 int rb = 28; /* GP */
17497 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17499 gen_ld(ctx, OPC_LW, rd, rb, offset);
17501 break;
17502 case POOL16F:
17503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17504 if (ctx->opcode & 1) {
17505 generate_exception_end(ctx, EXCP_RI);
17506 } else {
17507 /* MOVEP */
17508 int enc_dest = uMIPS_RD(ctx->opcode);
17509 int enc_rt = uMIPS_RS2(ctx->opcode);
17510 int enc_rs = uMIPS_RS1(ctx->opcode);
17511 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17513 break;
17514 case LBU16:
17516 int rd = mmreg(uMIPS_RD(ctx->opcode));
17517 int rb = mmreg(uMIPS_RS(ctx->opcode));
17518 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17519 offset = (offset == 0xf ? -1 : offset);
17521 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17523 break;
17524 case LHU16:
17526 int rd = mmreg(uMIPS_RD(ctx->opcode));
17527 int rb = mmreg(uMIPS_RS(ctx->opcode));
17528 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17530 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17532 break;
17533 case LWSP16:
17535 int rd = (ctx->opcode >> 5) & 0x1f;
17536 int rb = 29; /* SP */
17537 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17539 gen_ld(ctx, OPC_LW, rd, rb, offset);
17541 break;
17542 case LW16:
17544 int rd = mmreg(uMIPS_RD(ctx->opcode));
17545 int rb = mmreg(uMIPS_RS(ctx->opcode));
17546 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17548 gen_ld(ctx, OPC_LW, rd, rb, offset);
17550 break;
17551 case SB16:
17553 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17554 int rb = mmreg(uMIPS_RS(ctx->opcode));
17555 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17557 gen_st(ctx, OPC_SB, rd, rb, offset);
17559 break;
17560 case SH16:
17562 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17563 int rb = mmreg(uMIPS_RS(ctx->opcode));
17564 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17566 gen_st(ctx, OPC_SH, rd, rb, offset);
17568 break;
17569 case SWSP16:
17571 int rd = (ctx->opcode >> 5) & 0x1f;
17572 int rb = 29; /* SP */
17573 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17575 gen_st(ctx, OPC_SW, rd, rb, offset);
17577 break;
17578 case SW16:
17580 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17581 int rb = mmreg(uMIPS_RS(ctx->opcode));
17582 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17584 gen_st(ctx, OPC_SW, rd, rb, offset);
17586 break;
17587 case MOVE16:
17589 int rd = uMIPS_RD5(ctx->opcode);
17590 int rs = uMIPS_RS5(ctx->opcode);
17592 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17594 break;
17595 case ANDI16:
17596 gen_andi16(ctx);
17597 break;
17598 case POOL16D:
17599 switch (ctx->opcode & 0x1) {
17600 case ADDIUS5:
17601 gen_addius5(ctx);
17602 break;
17603 case ADDIUSP:
17604 gen_addiusp(ctx);
17605 break;
17607 break;
17608 case POOL16E:
17609 switch (ctx->opcode & 0x1) {
17610 case ADDIUR2:
17611 gen_addiur2(ctx);
17612 break;
17613 case ADDIUR1SP:
17614 gen_addiur1sp(ctx);
17615 break;
17617 break;
17618 case B16: /* BC16 */
17619 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17620 sextract32(ctx->opcode, 0, 10) << 1,
17621 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17622 break;
17623 case BNEZ16: /* BNEZC16 */
17624 case BEQZ16: /* BEQZC16 */
17625 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17626 mmreg(uMIPS_RD(ctx->opcode)),
17627 0, sextract32(ctx->opcode, 0, 7) << 1,
17628 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17630 break;
17631 case LI16:
17633 int reg = mmreg(uMIPS_RD(ctx->opcode));
17634 int imm = ZIMM(ctx->opcode, 0, 7);
17636 imm = (imm == 0x7f ? -1 : imm);
17637 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17639 break;
17640 case RES_29:
17641 case RES_31:
17642 case RES_39:
17643 generate_exception_end(ctx, EXCP_RI);
17644 break;
17645 default:
17646 decode_micromips32_opc(env, ctx);
17647 return 4;
17650 return 2;
17655 * nanoMIPS opcodes
17659 /* MAJOR, P16, and P32 pools opcodes */
17660 enum {
17661 NM_P_ADDIU = 0x00,
17662 NM_ADDIUPC = 0x01,
17663 NM_MOVE_BALC = 0x02,
17664 NM_P16_MV = 0x04,
17665 NM_LW16 = 0x05,
17666 NM_BC16 = 0x06,
17667 NM_P16_SR = 0x07,
17669 NM_POOL32A = 0x08,
17670 NM_P_BAL = 0x0a,
17671 NM_P16_SHIFT = 0x0c,
17672 NM_LWSP16 = 0x0d,
17673 NM_BALC16 = 0x0e,
17674 NM_P16_4X4 = 0x0f,
17676 NM_P_GP_W = 0x10,
17677 NM_P_GP_BH = 0x11,
17678 NM_P_J = 0x12,
17679 NM_P16C = 0x14,
17680 NM_LWGP16 = 0x15,
17681 NM_P16_LB = 0x17,
17683 NM_P48I = 0x18,
17684 NM_P16_A1 = 0x1c,
17685 NM_LW4X4 = 0x1d,
17686 NM_P16_LH = 0x1f,
17688 NM_P_U12 = 0x20,
17689 NM_P_LS_U12 = 0x21,
17690 NM_P_BR1 = 0x22,
17691 NM_P16_A2 = 0x24,
17692 NM_SW16 = 0x25,
17693 NM_BEQZC16 = 0x26,
17695 NM_POOL32F = 0x28,
17696 NM_P_LS_S9 = 0x29,
17697 NM_P_BR2 = 0x2a,
17699 NM_P16_ADDU = 0x2c,
17700 NM_SWSP16 = 0x2d,
17701 NM_BNEZC16 = 0x2e,
17702 NM_MOVEP = 0x2f,
17704 NM_POOL32S = 0x30,
17705 NM_P_BRI = 0x32,
17706 NM_LI16 = 0x34,
17707 NM_SWGP16 = 0x35,
17708 NM_P16_BR = 0x36,
17710 NM_P_LUI = 0x38,
17711 NM_ANDI16 = 0x3c,
17712 NM_SW4X4 = 0x3d,
17713 NM_MOVEPREV = 0x3f,
17716 /* POOL32A instruction pool */
17717 enum {
17718 NM_POOL32A0 = 0x00,
17719 NM_SPECIAL2 = 0x01,
17720 NM_COP2_1 = 0x02,
17721 NM_UDI = 0x03,
17722 NM_POOL32A5 = 0x05,
17723 NM_POOL32A7 = 0x07,
17726 /* P.GP.W instruction pool */
17727 enum {
17728 NM_ADDIUGP_W = 0x00,
17729 NM_LWGP = 0x02,
17730 NM_SWGP = 0x03,
17733 /* P48I instruction pool */
17734 enum {
17735 NM_LI48 = 0x00,
17736 NM_ADDIU48 = 0x01,
17737 NM_ADDIUGP48 = 0x02,
17738 NM_ADDIUPC48 = 0x03,
17739 NM_LWPC48 = 0x0b,
17740 NM_SWPC48 = 0x0f,
17743 /* P.U12 instruction pool */
17744 enum {
17745 NM_ORI = 0x00,
17746 NM_XORI = 0x01,
17747 NM_ANDI = 0x02,
17748 NM_P_SR = 0x03,
17749 NM_SLTI = 0x04,
17750 NM_SLTIU = 0x05,
17751 NM_SEQI = 0x06,
17752 NM_ADDIUNEG = 0x08,
17753 NM_P_SHIFT = 0x0c,
17754 NM_P_ROTX = 0x0d,
17755 NM_P_INS = 0x0e,
17756 NM_P_EXT = 0x0f,
17759 /* POOL32F instruction pool */
17760 enum {
17761 NM_POOL32F_0 = 0x00,
17762 NM_POOL32F_3 = 0x03,
17763 NM_POOL32F_5 = 0x05,
17766 /* POOL32S instruction pool */
17767 enum {
17768 NM_POOL32S_0 = 0x00,
17769 NM_POOL32S_4 = 0x04,
17772 /* P.LUI instruction pool */
17773 enum {
17774 NM_LUI = 0x00,
17775 NM_ALUIPC = 0x01,
17778 /* P.GP.BH instruction pool */
17779 enum {
17780 NM_LBGP = 0x00,
17781 NM_SBGP = 0x01,
17782 NM_LBUGP = 0x02,
17783 NM_ADDIUGP_B = 0x03,
17784 NM_P_GP_LH = 0x04,
17785 NM_P_GP_SH = 0x05,
17786 NM_P_GP_CP1 = 0x06,
17789 /* P.LS.U12 instruction pool */
17790 enum {
17791 NM_LB = 0x00,
17792 NM_SB = 0x01,
17793 NM_LBU = 0x02,
17794 NM_P_PREFU12 = 0x03,
17795 NM_LH = 0x04,
17796 NM_SH = 0x05,
17797 NM_LHU = 0x06,
17798 NM_LWU = 0x07,
17799 NM_LW = 0x08,
17800 NM_SW = 0x09,
17801 NM_LWC1 = 0x0a,
17802 NM_SWC1 = 0x0b,
17803 NM_LDC1 = 0x0e,
17804 NM_SDC1 = 0x0f,
17807 /* P.LS.S9 instruction pool */
17808 enum {
17809 NM_P_LS_S0 = 0x00,
17810 NM_P_LS_S1 = 0x01,
17811 NM_P_LS_E0 = 0x02,
17812 NM_P_LS_WM = 0x04,
17813 NM_P_LS_UAWM = 0x05,
17816 /* P.BAL instruction pool */
17817 enum {
17818 NM_BC = 0x00,
17819 NM_BALC = 0x01,
17822 /* P.J instruction pool */
17823 enum {
17824 NM_JALRC = 0x00,
17825 NM_JALRC_HB = 0x01,
17826 NM_P_BALRSC = 0x08,
17829 /* P.BR1 instruction pool */
17830 enum {
17831 NM_BEQC = 0x00,
17832 NM_P_BR3A = 0x01,
17833 NM_BGEC = 0x02,
17834 NM_BGEUC = 0x03,
17837 /* P.BR2 instruction pool */
17838 enum {
17839 NM_BNEC = 0x00,
17840 NM_BLTC = 0x02,
17841 NM_BLTUC = 0x03,
17844 /* P.BRI instruction pool */
17845 enum {
17846 NM_BEQIC = 0x00,
17847 NM_BBEQZC = 0x01,
17848 NM_BGEIC = 0x02,
17849 NM_BGEIUC = 0x03,
17850 NM_BNEIC = 0x04,
17851 NM_BBNEZC = 0x05,
17852 NM_BLTIC = 0x06,
17853 NM_BLTIUC = 0x07,
17856 /* P16.SHIFT instruction pool */
17857 enum {
17858 NM_SLL16 = 0x00,
17859 NM_SRL16 = 0x01,
17862 /* POOL16C instruction pool */
17863 enum {
17864 NM_POOL16C_0 = 0x00,
17865 NM_LWXS16 = 0x01,
17868 /* P16.A1 instruction pool */
17869 enum {
17870 NM_ADDIUR1SP = 0x01,
17873 /* P16.A2 instruction pool */
17874 enum {
17875 NM_ADDIUR2 = 0x00,
17876 NM_P_ADDIURS5 = 0x01,
17879 /* P16.ADDU instruction pool */
17880 enum {
17881 NM_ADDU16 = 0x00,
17882 NM_SUBU16 = 0x01,
17885 /* P16.SR instruction pool */
17886 enum {
17887 NM_SAVE16 = 0x00,
17888 NM_RESTORE_JRC16 = 0x01,
17891 /* P16.4X4 instruction pool */
17892 enum {
17893 NM_ADDU4X4 = 0x00,
17894 NM_MUL4X4 = 0x01,
17897 /* P16.LB instruction pool */
17898 enum {
17899 NM_LB16 = 0x00,
17900 NM_SB16 = 0x01,
17901 NM_LBU16 = 0x02,
17904 /* P16.LH instruction pool */
17905 enum {
17906 NM_LH16 = 0x00,
17907 NM_SH16 = 0x01,
17908 NM_LHU16 = 0x02,
17911 /* P.RI instruction pool */
17912 enum {
17913 NM_SIGRIE = 0x00,
17914 NM_P_SYSCALL = 0x01,
17915 NM_BREAK = 0x02,
17916 NM_SDBBP = 0x03,
17919 /* POOL32A0 instruction pool */
17920 enum {
17921 NM_P_TRAP = 0x00,
17922 NM_SEB = 0x01,
17923 NM_SLLV = 0x02,
17924 NM_MUL = 0x03,
17925 NM_MFC0 = 0x06,
17926 NM_MFHC0 = 0x07,
17927 NM_SEH = 0x09,
17928 NM_SRLV = 0x0a,
17929 NM_MUH = 0x0b,
17930 NM_MTC0 = 0x0e,
17931 NM_MTHC0 = 0x0f,
17932 NM_SRAV = 0x12,
17933 NM_MULU = 0x13,
17934 NM_ROTRV = 0x1a,
17935 NM_MUHU = 0x1b,
17936 NM_ADD = 0x22,
17937 NM_DIV = 0x23,
17938 NM_ADDU = 0x2a,
17939 NM_MOD = 0x2b,
17940 NM_SUB = 0x32,
17941 NM_DIVU = 0x33,
17942 NM_RDHWR = 0x38,
17943 NM_SUBU = 0x3a,
17944 NM_MODU = 0x3b,
17945 NM_P_CMOVE = 0x42,
17946 NM_FORK = 0x45,
17947 NM_MFTR = 0x46,
17948 NM_MFHTR = 0x47,
17949 NM_AND = 0x4a,
17950 NM_YIELD = 0x4d,
17951 NM_MTTR = 0x4e,
17952 NM_MTHTR = 0x4f,
17953 NM_OR = 0x52,
17954 NM_D_E_MT_VPE = 0x56,
17955 NM_NOR = 0x5a,
17956 NM_XOR = 0x62,
17957 NM_SLT = 0x6a,
17958 NM_P_SLTU = 0x72,
17959 NM_SOV = 0x7a,
17962 /* CRC32 instruction pool */
17963 enum {
17964 NM_CRC32B = 0x00,
17965 NM_CRC32H = 0x01,
17966 NM_CRC32W = 0x02,
17967 NM_CRC32CB = 0x04,
17968 NM_CRC32CH = 0x05,
17969 NM_CRC32CW = 0x06,
17972 /* POOL32A5 instruction pool */
17973 enum {
17974 NM_CMP_EQ_PH = 0x00,
17975 NM_CMP_LT_PH = 0x08,
17976 NM_CMP_LE_PH = 0x10,
17977 NM_CMPGU_EQ_QB = 0x18,
17978 NM_CMPGU_LT_QB = 0x20,
17979 NM_CMPGU_LE_QB = 0x28,
17980 NM_CMPGDU_EQ_QB = 0x30,
17981 NM_CMPGDU_LT_QB = 0x38,
17982 NM_CMPGDU_LE_QB = 0x40,
17983 NM_CMPU_EQ_QB = 0x48,
17984 NM_CMPU_LT_QB = 0x50,
17985 NM_CMPU_LE_QB = 0x58,
17986 NM_ADDQ_S_W = 0x60,
17987 NM_SUBQ_S_W = 0x68,
17988 NM_ADDSC = 0x70,
17989 NM_ADDWC = 0x78,
17991 NM_ADDQ_S_PH = 0x01,
17992 NM_ADDQH_R_PH = 0x09,
17993 NM_ADDQH_R_W = 0x11,
17994 NM_ADDU_S_QB = 0x19,
17995 NM_ADDU_S_PH = 0x21,
17996 NM_ADDUH_R_QB = 0x29,
17997 NM_SHRAV_R_PH = 0x31,
17998 NM_SHRAV_R_QB = 0x39,
17999 NM_SUBQ_S_PH = 0x41,
18000 NM_SUBQH_R_PH = 0x49,
18001 NM_SUBQH_R_W = 0x51,
18002 NM_SUBU_S_QB = 0x59,
18003 NM_SUBU_S_PH = 0x61,
18004 NM_SUBUH_R_QB = 0x69,
18005 NM_SHLLV_S_PH = 0x71,
18006 NM_PRECR_SRA_R_PH_W = 0x79,
18008 NM_MULEU_S_PH_QBL = 0x12,
18009 NM_MULEU_S_PH_QBR = 0x1a,
18010 NM_MULQ_RS_PH = 0x22,
18011 NM_MULQ_S_PH = 0x2a,
18012 NM_MULQ_RS_W = 0x32,
18013 NM_MULQ_S_W = 0x3a,
18014 NM_APPEND = 0x42,
18015 NM_MODSUB = 0x52,
18016 NM_SHRAV_R_W = 0x5a,
18017 NM_SHRLV_PH = 0x62,
18018 NM_SHRLV_QB = 0x6a,
18019 NM_SHLLV_QB = 0x72,
18020 NM_SHLLV_S_W = 0x7a,
18022 NM_SHILO = 0x03,
18024 NM_MULEQ_S_W_PHL = 0x04,
18025 NM_MULEQ_S_W_PHR = 0x0c,
18027 NM_MUL_S_PH = 0x05,
18028 NM_PRECR_QB_PH = 0x0d,
18029 NM_PRECRQ_QB_PH = 0x15,
18030 NM_PRECRQ_PH_W = 0x1d,
18031 NM_PRECRQ_RS_PH_W = 0x25,
18032 NM_PRECRQU_S_QB_PH = 0x2d,
18033 NM_PACKRL_PH = 0x35,
18034 NM_PICK_QB = 0x3d,
18035 NM_PICK_PH = 0x45,
18037 NM_SHRA_R_W = 0x5e,
18038 NM_SHRA_R_PH = 0x66,
18039 NM_SHLL_S_PH = 0x76,
18040 NM_SHLL_S_W = 0x7e,
18042 NM_REPL_PH = 0x07
18045 /* POOL32A7 instruction pool */
18046 enum {
18047 NM_P_LSX = 0x00,
18048 NM_LSA = 0x01,
18049 NM_EXTW = 0x03,
18050 NM_POOL32AXF = 0x07,
18053 /* P.SR instruction pool */
18054 enum {
18055 NM_PP_SR = 0x00,
18056 NM_P_SR_F = 0x01,
18059 /* P.SHIFT instruction pool */
18060 enum {
18061 NM_P_SLL = 0x00,
18062 NM_SRL = 0x02,
18063 NM_SRA = 0x04,
18064 NM_ROTR = 0x06,
18067 /* P.ROTX instruction pool */
18068 enum {
18069 NM_ROTX = 0x00,
18072 /* P.INS instruction pool */
18073 enum {
18074 NM_INS = 0x00,
18077 /* P.EXT instruction pool */
18078 enum {
18079 NM_EXT = 0x00,
18082 /* POOL32F_0 (fmt) instruction pool */
18083 enum {
18084 NM_RINT_S = 0x04,
18085 NM_RINT_D = 0x44,
18086 NM_ADD_S = 0x06,
18087 NM_SELEQZ_S = 0x07,
18088 NM_SELEQZ_D = 0x47,
18089 NM_CLASS_S = 0x0c,
18090 NM_CLASS_D = 0x4c,
18091 NM_SUB_S = 0x0e,
18092 NM_SELNEZ_S = 0x0f,
18093 NM_SELNEZ_D = 0x4f,
18094 NM_MUL_S = 0x16,
18095 NM_SEL_S = 0x17,
18096 NM_SEL_D = 0x57,
18097 NM_DIV_S = 0x1e,
18098 NM_ADD_D = 0x26,
18099 NM_SUB_D = 0x2e,
18100 NM_MUL_D = 0x36,
18101 NM_MADDF_S = 0x37,
18102 NM_MADDF_D = 0x77,
18103 NM_DIV_D = 0x3e,
18104 NM_MSUBF_S = 0x3f,
18105 NM_MSUBF_D = 0x7f,
18108 /* POOL32F_3 instruction pool */
18109 enum {
18110 NM_MIN_FMT = 0x00,
18111 NM_MAX_FMT = 0x01,
18112 NM_MINA_FMT = 0x04,
18113 NM_MAXA_FMT = 0x05,
18114 NM_POOL32FXF = 0x07,
18117 /* POOL32F_5 instruction pool */
18118 enum {
18119 NM_CMP_CONDN_S = 0x00,
18120 NM_CMP_CONDN_D = 0x02,
18123 /* P.GP.LH instruction pool */
18124 enum {
18125 NM_LHGP = 0x00,
18126 NM_LHUGP = 0x01,
18129 /* P.GP.SH instruction pool */
18130 enum {
18131 NM_SHGP = 0x00,
18134 /* P.GP.CP1 instruction pool */
18135 enum {
18136 NM_LWC1GP = 0x00,
18137 NM_SWC1GP = 0x01,
18138 NM_LDC1GP = 0x02,
18139 NM_SDC1GP = 0x03,
18142 /* P.LS.S0 instruction pool */
18143 enum {
18144 NM_LBS9 = 0x00,
18145 NM_LHS9 = 0x04,
18146 NM_LWS9 = 0x08,
18147 NM_LDS9 = 0x0c,
18149 NM_SBS9 = 0x01,
18150 NM_SHS9 = 0x05,
18151 NM_SWS9 = 0x09,
18152 NM_SDS9 = 0x0d,
18154 NM_LBUS9 = 0x02,
18155 NM_LHUS9 = 0x06,
18156 NM_LWC1S9 = 0x0a,
18157 NM_LDC1S9 = 0x0e,
18159 NM_P_PREFS9 = 0x03,
18160 NM_LWUS9 = 0x07,
18161 NM_SWC1S9 = 0x0b,
18162 NM_SDC1S9 = 0x0f,
18165 /* P.LS.S1 instruction pool */
18166 enum {
18167 NM_ASET_ACLR = 0x02,
18168 NM_UALH = 0x04,
18169 NM_UASH = 0x05,
18170 NM_CACHE = 0x07,
18171 NM_P_LL = 0x0a,
18172 NM_P_SC = 0x0b,
18175 /* P.LS.E0 instruction pool */
18176 enum {
18177 NM_LBE = 0x00,
18178 NM_SBE = 0x01,
18179 NM_LBUE = 0x02,
18180 NM_P_PREFE = 0x03,
18181 NM_LHE = 0x04,
18182 NM_SHE = 0x05,
18183 NM_LHUE = 0x06,
18184 NM_CACHEE = 0x07,
18185 NM_LWE = 0x08,
18186 NM_SWE = 0x09,
18187 NM_P_LLE = 0x0a,
18188 NM_P_SCE = 0x0b,
18191 /* P.PREFE instruction pool */
18192 enum {
18193 NM_SYNCIE = 0x00,
18194 NM_PREFE = 0x01,
18197 /* P.LLE instruction pool */
18198 enum {
18199 NM_LLE = 0x00,
18200 NM_LLWPE = 0x01,
18203 /* P.SCE instruction pool */
18204 enum {
18205 NM_SCE = 0x00,
18206 NM_SCWPE = 0x01,
18209 /* P.LS.WM instruction pool */
18210 enum {
18211 NM_LWM = 0x00,
18212 NM_SWM = 0x01,
18215 /* P.LS.UAWM instruction pool */
18216 enum {
18217 NM_UALWM = 0x00,
18218 NM_UASWM = 0x01,
18221 /* P.BR3A instruction pool */
18222 enum {
18223 NM_BC1EQZC = 0x00,
18224 NM_BC1NEZC = 0x01,
18225 NM_BC2EQZC = 0x02,
18226 NM_BC2NEZC = 0x03,
18227 NM_BPOSGE32C = 0x04,
18230 /* P16.RI instruction pool */
18231 enum {
18232 NM_P16_SYSCALL = 0x01,
18233 NM_BREAK16 = 0x02,
18234 NM_SDBBP16 = 0x03,
18237 /* POOL16C_0 instruction pool */
18238 enum {
18239 NM_POOL16C_00 = 0x00,
18242 /* P16.JRC instruction pool */
18243 enum {
18244 NM_JRC = 0x00,
18245 NM_JALRC16 = 0x01,
18248 /* P.SYSCALL instruction pool */
18249 enum {
18250 NM_SYSCALL = 0x00,
18251 NM_HYPCALL = 0x01,
18254 /* P.TRAP instruction pool */
18255 enum {
18256 NM_TEQ = 0x00,
18257 NM_TNE = 0x01,
18260 /* P.CMOVE instruction pool */
18261 enum {
18262 NM_MOVZ = 0x00,
18263 NM_MOVN = 0x01,
18266 /* POOL32Axf instruction pool */
18267 enum {
18268 NM_POOL32AXF_1 = 0x01,
18269 NM_POOL32AXF_2 = 0x02,
18270 NM_POOL32AXF_4 = 0x04,
18271 NM_POOL32AXF_5 = 0x05,
18272 NM_POOL32AXF_7 = 0x07,
18275 /* POOL32Axf_1 instruction pool */
18276 enum {
18277 NM_POOL32AXF_1_0 = 0x00,
18278 NM_POOL32AXF_1_1 = 0x01,
18279 NM_POOL32AXF_1_3 = 0x03,
18280 NM_POOL32AXF_1_4 = 0x04,
18281 NM_POOL32AXF_1_5 = 0x05,
18282 NM_POOL32AXF_1_7 = 0x07,
18285 /* POOL32Axf_2 instruction pool */
18286 enum {
18287 NM_POOL32AXF_2_0_7 = 0x00,
18288 NM_POOL32AXF_2_8_15 = 0x01,
18289 NM_POOL32AXF_2_16_23 = 0x02,
18290 NM_POOL32AXF_2_24_31 = 0x03,
18293 /* POOL32Axf_7 instruction pool */
18294 enum {
18295 NM_SHRA_R_QB = 0x0,
18296 NM_SHRL_PH = 0x1,
18297 NM_REPL_QB = 0x2,
18300 /* POOL32Axf_1_0 instruction pool */
18301 enum {
18302 NM_MFHI = 0x0,
18303 NM_MFLO = 0x1,
18304 NM_MTHI = 0x2,
18305 NM_MTLO = 0x3,
18308 /* POOL32Axf_1_1 instruction pool */
18309 enum {
18310 NM_MTHLIP = 0x0,
18311 NM_SHILOV = 0x1,
18314 /* POOL32Axf_1_3 instruction pool */
18315 enum {
18316 NM_RDDSP = 0x0,
18317 NM_WRDSP = 0x1,
18318 NM_EXTP = 0x2,
18319 NM_EXTPDP = 0x3,
18322 /* POOL32Axf_1_4 instruction pool */
18323 enum {
18324 NM_SHLL_QB = 0x0,
18325 NM_SHRL_QB = 0x1,
18328 /* POOL32Axf_1_5 instruction pool */
18329 enum {
18330 NM_MAQ_S_W_PHR = 0x0,
18331 NM_MAQ_S_W_PHL = 0x1,
18332 NM_MAQ_SA_W_PHR = 0x2,
18333 NM_MAQ_SA_W_PHL = 0x3,
18336 /* POOL32Axf_1_7 instruction pool */
18337 enum {
18338 NM_EXTR_W = 0x0,
18339 NM_EXTR_R_W = 0x1,
18340 NM_EXTR_RS_W = 0x2,
18341 NM_EXTR_S_H = 0x3,
18344 /* POOL32Axf_2_0_7 instruction pool */
18345 enum {
18346 NM_DPA_W_PH = 0x0,
18347 NM_DPAQ_S_W_PH = 0x1,
18348 NM_DPS_W_PH = 0x2,
18349 NM_DPSQ_S_W_PH = 0x3,
18350 NM_BALIGN = 0x4,
18351 NM_MADD = 0x5,
18352 NM_MULT = 0x6,
18353 NM_EXTRV_W = 0x7,
18356 /* POOL32Axf_2_8_15 instruction pool */
18357 enum {
18358 NM_DPAX_W_PH = 0x0,
18359 NM_DPAQ_SA_L_W = 0x1,
18360 NM_DPSX_W_PH = 0x2,
18361 NM_DPSQ_SA_L_W = 0x3,
18362 NM_MADDU = 0x5,
18363 NM_MULTU = 0x6,
18364 NM_EXTRV_R_W = 0x7,
18367 /* POOL32Axf_2_16_23 instruction pool */
18368 enum {
18369 NM_DPAU_H_QBL = 0x0,
18370 NM_DPAQX_S_W_PH = 0x1,
18371 NM_DPSU_H_QBL = 0x2,
18372 NM_DPSQX_S_W_PH = 0x3,
18373 NM_EXTPV = 0x4,
18374 NM_MSUB = 0x5,
18375 NM_MULSA_W_PH = 0x6,
18376 NM_EXTRV_RS_W = 0x7,
18379 /* POOL32Axf_2_24_31 instruction pool */
18380 enum {
18381 NM_DPAU_H_QBR = 0x0,
18382 NM_DPAQX_SA_W_PH = 0x1,
18383 NM_DPSU_H_QBR = 0x2,
18384 NM_DPSQX_SA_W_PH = 0x3,
18385 NM_EXTPDPV = 0x4,
18386 NM_MSUBU = 0x5,
18387 NM_MULSAQ_S_W_PH = 0x6,
18388 NM_EXTRV_S_H = 0x7,
18391 /* POOL32Axf_{4, 5} instruction pool */
18392 enum {
18393 NM_CLO = 0x25,
18394 NM_CLZ = 0x2d,
18396 NM_TLBP = 0x01,
18397 NM_TLBR = 0x09,
18398 NM_TLBWI = 0x11,
18399 NM_TLBWR = 0x19,
18400 NM_TLBINV = 0x03,
18401 NM_TLBINVF = 0x0b,
18402 NM_DI = 0x23,
18403 NM_EI = 0x2b,
18404 NM_RDPGPR = 0x70,
18405 NM_WRPGPR = 0x78,
18406 NM_WAIT = 0x61,
18407 NM_DERET = 0x71,
18408 NM_ERETX = 0x79,
18410 /* nanoMIPS DSP instructions */
18411 NM_ABSQ_S_QB = 0x00,
18412 NM_ABSQ_S_PH = 0x08,
18413 NM_ABSQ_S_W = 0x10,
18414 NM_PRECEQ_W_PHL = 0x28,
18415 NM_PRECEQ_W_PHR = 0x30,
18416 NM_PRECEQU_PH_QBL = 0x38,
18417 NM_PRECEQU_PH_QBR = 0x48,
18418 NM_PRECEU_PH_QBL = 0x58,
18419 NM_PRECEU_PH_QBR = 0x68,
18420 NM_PRECEQU_PH_QBLA = 0x39,
18421 NM_PRECEQU_PH_QBRA = 0x49,
18422 NM_PRECEU_PH_QBLA = 0x59,
18423 NM_PRECEU_PH_QBRA = 0x69,
18424 NM_REPLV_PH = 0x01,
18425 NM_REPLV_QB = 0x09,
18426 NM_BITREV = 0x18,
18427 NM_INSV = 0x20,
18428 NM_RADDU_W_QB = 0x78,
18430 NM_BITSWAP = 0x05,
18431 NM_WSBH = 0x3d,
18434 /* PP.SR instruction pool */
18435 enum {
18436 NM_SAVE = 0x00,
18437 NM_RESTORE = 0x02,
18438 NM_RESTORE_JRC = 0x03,
18441 /* P.SR.F instruction pool */
18442 enum {
18443 NM_SAVEF = 0x00,
18444 NM_RESTOREF = 0x01,
18447 /* P16.SYSCALL instruction pool */
18448 enum {
18449 NM_SYSCALL16 = 0x00,
18450 NM_HYPCALL16 = 0x01,
18453 /* POOL16C_00 instruction pool */
18454 enum {
18455 NM_NOT16 = 0x00,
18456 NM_XOR16 = 0x01,
18457 NM_AND16 = 0x02,
18458 NM_OR16 = 0x03,
18461 /* PP.LSX and PP.LSXS instruction pool */
18462 enum {
18463 NM_LBX = 0x00,
18464 NM_LHX = 0x04,
18465 NM_LWX = 0x08,
18466 NM_LDX = 0x0c,
18468 NM_SBX = 0x01,
18469 NM_SHX = 0x05,
18470 NM_SWX = 0x09,
18471 NM_SDX = 0x0d,
18473 NM_LBUX = 0x02,
18474 NM_LHUX = 0x06,
18475 NM_LWC1X = 0x0a,
18476 NM_LDC1X = 0x0e,
18478 NM_LWUX = 0x07,
18479 NM_SWC1X = 0x0b,
18480 NM_SDC1X = 0x0f,
18482 NM_LHXS = 0x04,
18483 NM_LWXS = 0x08,
18484 NM_LDXS = 0x0c,
18486 NM_SHXS = 0x05,
18487 NM_SWXS = 0x09,
18488 NM_SDXS = 0x0d,
18490 NM_LHUXS = 0x06,
18491 NM_LWC1XS = 0x0a,
18492 NM_LDC1XS = 0x0e,
18494 NM_LWUXS = 0x07,
18495 NM_SWC1XS = 0x0b,
18496 NM_SDC1XS = 0x0f,
18499 /* ERETx instruction pool */
18500 enum {
18501 NM_ERET = 0x00,
18502 NM_ERETNC = 0x01,
18505 /* POOL32FxF_{0, 1} insturction pool */
18506 enum {
18507 NM_CFC1 = 0x40,
18508 NM_CTC1 = 0x60,
18509 NM_MFC1 = 0x80,
18510 NM_MTC1 = 0xa0,
18511 NM_MFHC1 = 0xc0,
18512 NM_MTHC1 = 0xe0,
18514 NM_CVT_S_PL = 0x84,
18515 NM_CVT_S_PU = 0xa4,
18517 NM_CVT_L_S = 0x004,
18518 NM_CVT_L_D = 0x104,
18519 NM_CVT_W_S = 0x024,
18520 NM_CVT_W_D = 0x124,
18522 NM_RSQRT_S = 0x008,
18523 NM_RSQRT_D = 0x108,
18525 NM_SQRT_S = 0x028,
18526 NM_SQRT_D = 0x128,
18528 NM_RECIP_S = 0x048,
18529 NM_RECIP_D = 0x148,
18531 NM_FLOOR_L_S = 0x00c,
18532 NM_FLOOR_L_D = 0x10c,
18534 NM_FLOOR_W_S = 0x02c,
18535 NM_FLOOR_W_D = 0x12c,
18537 NM_CEIL_L_S = 0x04c,
18538 NM_CEIL_L_D = 0x14c,
18539 NM_CEIL_W_S = 0x06c,
18540 NM_CEIL_W_D = 0x16c,
18541 NM_TRUNC_L_S = 0x08c,
18542 NM_TRUNC_L_D = 0x18c,
18543 NM_TRUNC_W_S = 0x0ac,
18544 NM_TRUNC_W_D = 0x1ac,
18545 NM_ROUND_L_S = 0x0cc,
18546 NM_ROUND_L_D = 0x1cc,
18547 NM_ROUND_W_S = 0x0ec,
18548 NM_ROUND_W_D = 0x1ec,
18550 NM_MOV_S = 0x01,
18551 NM_MOV_D = 0x81,
18552 NM_ABS_S = 0x0d,
18553 NM_ABS_D = 0x8d,
18554 NM_NEG_S = 0x2d,
18555 NM_NEG_D = 0xad,
18556 NM_CVT_D_S = 0x04d,
18557 NM_CVT_D_W = 0x0cd,
18558 NM_CVT_D_L = 0x14d,
18559 NM_CVT_S_D = 0x06d,
18560 NM_CVT_S_W = 0x0ed,
18561 NM_CVT_S_L = 0x16d,
18564 /* P.LL instruction pool */
18565 enum {
18566 NM_LL = 0x00,
18567 NM_LLWP = 0x01,
18570 /* P.SC instruction pool */
18571 enum {
18572 NM_SC = 0x00,
18573 NM_SCWP = 0x01,
18576 /* P.DVP instruction pool */
18577 enum {
18578 NM_DVP = 0x00,
18579 NM_EVP = 0x01,
18585 * nanoMIPS decoding engine
18590 /* extraction utilities */
18592 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18593 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18594 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18595 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18596 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18598 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18599 static inline int decode_gpr_gpr3(int r)
18601 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18603 return map[r & 0x7];
18606 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18607 static inline int decode_gpr_gpr3_src_store(int r)
18609 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18611 return map[r & 0x7];
18614 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18615 static inline int decode_gpr_gpr4(int r)
18617 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18618 16, 17, 18, 19, 20, 21, 22, 23 };
18620 return map[r & 0xf];
18623 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18624 static inline int decode_gpr_gpr4_zero(int r)
18626 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18627 16, 17, 18, 19, 20, 21, 22, 23 };
18629 return map[r & 0xf];
18633 static void gen_adjust_sp(DisasContext *ctx, int u)
18635 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18638 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18639 uint8_t gp, uint16_t u)
18641 int counter = 0;
18642 TCGv va = tcg_temp_new();
18643 TCGv t0 = tcg_temp_new();
18645 while (counter != count) {
18646 bool use_gp = gp && (counter == count - 1);
18647 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18648 int this_offset = -((counter + 1) << 2);
18649 gen_base_offset_addr(ctx, va, 29, this_offset);
18650 gen_load_gpr(t0, this_rt);
18651 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18652 (MO_TEUL | ctx->default_tcg_memop_mask));
18653 counter++;
18656 /* adjust stack pointer */
18657 gen_adjust_sp(ctx, -u);
18659 tcg_temp_free(t0);
18660 tcg_temp_free(va);
18663 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18664 uint8_t gp, uint16_t u)
18666 int counter = 0;
18667 TCGv va = tcg_temp_new();
18668 TCGv t0 = tcg_temp_new();
18670 while (counter != count) {
18671 bool use_gp = gp && (counter == count - 1);
18672 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18673 int this_offset = u - ((counter + 1) << 2);
18674 gen_base_offset_addr(ctx, va, 29, this_offset);
18675 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18676 ctx->default_tcg_memop_mask);
18677 tcg_gen_ext32s_tl(t0, t0);
18678 gen_store_gpr(t0, this_rt);
18679 counter++;
18682 /* adjust stack pointer */
18683 gen_adjust_sp(ctx, u);
18685 tcg_temp_free(t0);
18686 tcg_temp_free(va);
18689 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18691 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18692 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18694 switch (extract32(ctx->opcode, 2, 2)) {
18695 case NM_NOT16:
18696 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18697 break;
18698 case NM_AND16:
18699 gen_logic(ctx, OPC_AND, rt, rt, rs);
18700 break;
18701 case NM_XOR16:
18702 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18703 break;
18704 case NM_OR16:
18705 gen_logic(ctx, OPC_OR, rt, rt, rs);
18706 break;
18710 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18712 int rt = extract32(ctx->opcode, 21, 5);
18713 int rs = extract32(ctx->opcode, 16, 5);
18714 int rd = extract32(ctx->opcode, 11, 5);
18716 switch (extract32(ctx->opcode, 3, 7)) {
18717 case NM_P_TRAP:
18718 switch (extract32(ctx->opcode, 10, 1)) {
18719 case NM_TEQ:
18720 check_nms(ctx);
18721 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18722 break;
18723 case NM_TNE:
18724 check_nms(ctx);
18725 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18726 break;
18728 break;
18729 case NM_RDHWR:
18730 check_nms(ctx);
18731 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18732 break;
18733 case NM_SEB:
18734 check_nms(ctx);
18735 gen_bshfl(ctx, OPC_SEB, rs, rt);
18736 break;
18737 case NM_SEH:
18738 gen_bshfl(ctx, OPC_SEH, rs, rt);
18739 break;
18740 case NM_SLLV:
18741 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18742 break;
18743 case NM_SRLV:
18744 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18745 break;
18746 case NM_SRAV:
18747 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18748 break;
18749 case NM_ROTRV:
18750 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18751 break;
18752 case NM_ADD:
18753 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18754 break;
18755 case NM_ADDU:
18756 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18757 break;
18758 case NM_SUB:
18759 check_nms(ctx);
18760 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18761 break;
18762 case NM_SUBU:
18763 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18764 break;
18765 case NM_P_CMOVE:
18766 switch (extract32(ctx->opcode, 10, 1)) {
18767 case NM_MOVZ:
18768 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18769 break;
18770 case NM_MOVN:
18771 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18772 break;
18774 break;
18775 case NM_AND:
18776 gen_logic(ctx, OPC_AND, rd, rs, rt);
18777 break;
18778 case NM_OR:
18779 gen_logic(ctx, OPC_OR, rd, rs, rt);
18780 break;
18781 case NM_NOR:
18782 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18783 break;
18784 case NM_XOR:
18785 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18786 break;
18787 case NM_SLT:
18788 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18789 break;
18790 case NM_P_SLTU:
18791 if (rd == 0) {
18792 /* P_DVP */
18793 #ifndef CONFIG_USER_ONLY
18794 TCGv t0 = tcg_temp_new();
18795 switch (extract32(ctx->opcode, 10, 1)) {
18796 case NM_DVP:
18797 if (ctx->vp) {
18798 check_cp0_enabled(ctx);
18799 gen_helper_dvp(t0, cpu_env);
18800 gen_store_gpr(t0, rt);
18802 break;
18803 case NM_EVP:
18804 if (ctx->vp) {
18805 check_cp0_enabled(ctx);
18806 gen_helper_evp(t0, cpu_env);
18807 gen_store_gpr(t0, rt);
18809 break;
18811 tcg_temp_free(t0);
18812 #endif
18813 } else {
18814 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18816 break;
18817 case NM_SOV:
18819 TCGv t0 = tcg_temp_new();
18820 TCGv t1 = tcg_temp_new();
18821 TCGv t2 = tcg_temp_new();
18823 gen_load_gpr(t1, rs);
18824 gen_load_gpr(t2, rt);
18825 tcg_gen_add_tl(t0, t1, t2);
18826 tcg_gen_ext32s_tl(t0, t0);
18827 tcg_gen_xor_tl(t1, t1, t2);
18828 tcg_gen_xor_tl(t2, t0, t2);
18829 tcg_gen_andc_tl(t1, t2, t1);
18831 /* operands of same sign, result different sign */
18832 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18833 gen_store_gpr(t0, rd);
18835 tcg_temp_free(t0);
18836 tcg_temp_free(t1);
18837 tcg_temp_free(t2);
18839 break;
18840 case NM_MUL:
18841 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18842 break;
18843 case NM_MUH:
18844 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18845 break;
18846 case NM_MULU:
18847 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18848 break;
18849 case NM_MUHU:
18850 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18851 break;
18852 case NM_DIV:
18853 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18854 break;
18855 case NM_MOD:
18856 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18857 break;
18858 case NM_DIVU:
18859 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18860 break;
18861 case NM_MODU:
18862 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18863 break;
18864 #ifndef CONFIG_USER_ONLY
18865 case NM_MFC0:
18866 check_cp0_enabled(ctx);
18867 if (rt == 0) {
18868 /* Treat as NOP. */
18869 break;
18871 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18872 break;
18873 case NM_MTC0:
18874 check_cp0_enabled(ctx);
18876 TCGv t0 = tcg_temp_new();
18878 gen_load_gpr(t0, rt);
18879 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18880 tcg_temp_free(t0);
18882 break;
18883 case NM_D_E_MT_VPE:
18885 uint8_t sc = extract32(ctx->opcode, 10, 1);
18886 TCGv t0 = tcg_temp_new();
18888 switch (sc) {
18889 case 0:
18890 if (rs == 1) {
18891 /* DMT */
18892 check_cp0_mt(ctx);
18893 gen_helper_dmt(t0);
18894 gen_store_gpr(t0, rt);
18895 } else if (rs == 0) {
18896 /* DVPE */
18897 check_cp0_mt(ctx);
18898 gen_helper_dvpe(t0, cpu_env);
18899 gen_store_gpr(t0, rt);
18900 } else {
18901 generate_exception_end(ctx, EXCP_RI);
18903 break;
18904 case 1:
18905 if (rs == 1) {
18906 /* EMT */
18907 check_cp0_mt(ctx);
18908 gen_helper_emt(t0);
18909 gen_store_gpr(t0, rt);
18910 } else if (rs == 0) {
18911 /* EVPE */
18912 check_cp0_mt(ctx);
18913 gen_helper_evpe(t0, cpu_env);
18914 gen_store_gpr(t0, rt);
18915 } else {
18916 generate_exception_end(ctx, EXCP_RI);
18918 break;
18921 tcg_temp_free(t0);
18923 break;
18924 case NM_FORK:
18925 check_mt(ctx);
18927 TCGv t0 = tcg_temp_new();
18928 TCGv t1 = tcg_temp_new();
18930 gen_load_gpr(t0, rt);
18931 gen_load_gpr(t1, rs);
18932 gen_helper_fork(t0, t1);
18933 tcg_temp_free(t0);
18934 tcg_temp_free(t1);
18936 break;
18937 case NM_MFTR:
18938 case NM_MFHTR:
18939 check_cp0_enabled(ctx);
18940 if (rd == 0) {
18941 /* Treat as NOP. */
18942 return;
18944 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18945 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18946 break;
18947 case NM_MTTR:
18948 case NM_MTHTR:
18949 check_cp0_enabled(ctx);
18950 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18951 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18952 break;
18953 case NM_YIELD:
18954 check_mt(ctx);
18956 TCGv t0 = tcg_temp_new();
18958 gen_load_gpr(t0, rs);
18959 gen_helper_yield(t0, cpu_env, t0);
18960 gen_store_gpr(t0, rt);
18961 tcg_temp_free(t0);
18963 break;
18964 #endif
18965 default:
18966 generate_exception_end(ctx, EXCP_RI);
18967 break;
18971 /* dsp */
18972 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18973 int ret, int v1, int v2)
18975 TCGv_i32 t0;
18976 TCGv v0_t;
18977 TCGv v1_t;
18979 t0 = tcg_temp_new_i32();
18981 v0_t = tcg_temp_new();
18982 v1_t = tcg_temp_new();
18984 tcg_gen_movi_i32(t0, v2 >> 3);
18986 gen_load_gpr(v0_t, ret);
18987 gen_load_gpr(v1_t, v1);
18989 switch (opc) {
18990 case NM_MAQ_S_W_PHR:
18991 check_dsp(ctx);
18992 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18993 break;
18994 case NM_MAQ_S_W_PHL:
18995 check_dsp(ctx);
18996 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18997 break;
18998 case NM_MAQ_SA_W_PHR:
18999 check_dsp(ctx);
19000 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19001 break;
19002 case NM_MAQ_SA_W_PHL:
19003 check_dsp(ctx);
19004 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19005 break;
19006 default:
19007 generate_exception_end(ctx, EXCP_RI);
19008 break;
19011 tcg_temp_free_i32(t0);
19013 tcg_temp_free(v0_t);
19014 tcg_temp_free(v1_t);
19018 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19019 int ret, int v1, int v2)
19021 int16_t imm;
19022 TCGv t0 = tcg_temp_new();
19023 TCGv t1 = tcg_temp_new();
19024 TCGv v0_t = tcg_temp_new();
19026 gen_load_gpr(v0_t, v1);
19028 switch (opc) {
19029 case NM_POOL32AXF_1_0:
19030 check_dsp(ctx);
19031 switch (extract32(ctx->opcode, 12, 2)) {
19032 case NM_MFHI:
19033 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19034 break;
19035 case NM_MFLO:
19036 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19037 break;
19038 case NM_MTHI:
19039 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19040 break;
19041 case NM_MTLO:
19042 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19043 break;
19045 break;
19046 case NM_POOL32AXF_1_1:
19047 check_dsp(ctx);
19048 switch (extract32(ctx->opcode, 12, 2)) {
19049 case NM_MTHLIP:
19050 tcg_gen_movi_tl(t0, v2);
19051 gen_helper_mthlip(t0, v0_t, cpu_env);
19052 break;
19053 case NM_SHILOV:
19054 tcg_gen_movi_tl(t0, v2 >> 3);
19055 gen_helper_shilo(t0, v0_t, cpu_env);
19056 break;
19057 default:
19058 generate_exception_end(ctx, EXCP_RI);
19059 break;
19061 break;
19062 case NM_POOL32AXF_1_3:
19063 check_dsp(ctx);
19064 imm = extract32(ctx->opcode, 14, 7);
19065 switch (extract32(ctx->opcode, 12, 2)) {
19066 case NM_RDDSP:
19067 tcg_gen_movi_tl(t0, imm);
19068 gen_helper_rddsp(t0, t0, cpu_env);
19069 gen_store_gpr(t0, ret);
19070 break;
19071 case NM_WRDSP:
19072 gen_load_gpr(t0, ret);
19073 tcg_gen_movi_tl(t1, imm);
19074 gen_helper_wrdsp(t0, t1, cpu_env);
19075 break;
19076 case NM_EXTP:
19077 tcg_gen_movi_tl(t0, v2 >> 3);
19078 tcg_gen_movi_tl(t1, v1);
19079 gen_helper_extp(t0, t0, t1, cpu_env);
19080 gen_store_gpr(t0, ret);
19081 break;
19082 case NM_EXTPDP:
19083 tcg_gen_movi_tl(t0, v2 >> 3);
19084 tcg_gen_movi_tl(t1, v1);
19085 gen_helper_extpdp(t0, t0, t1, cpu_env);
19086 gen_store_gpr(t0, ret);
19087 break;
19089 break;
19090 case NM_POOL32AXF_1_4:
19091 check_dsp(ctx);
19092 tcg_gen_movi_tl(t0, v2 >> 2);
19093 switch (extract32(ctx->opcode, 12, 1)) {
19094 case NM_SHLL_QB:
19095 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19096 gen_store_gpr(t0, ret);
19097 break;
19098 case NM_SHRL_QB:
19099 gen_helper_shrl_qb(t0, t0, v0_t);
19100 gen_store_gpr(t0, ret);
19101 break;
19103 break;
19104 case NM_POOL32AXF_1_5:
19105 opc = extract32(ctx->opcode, 12, 2);
19106 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19107 break;
19108 case NM_POOL32AXF_1_7:
19109 check_dsp(ctx);
19110 tcg_gen_movi_tl(t0, v2 >> 3);
19111 tcg_gen_movi_tl(t1, v1);
19112 switch (extract32(ctx->opcode, 12, 2)) {
19113 case NM_EXTR_W:
19114 gen_helper_extr_w(t0, t0, t1, cpu_env);
19115 gen_store_gpr(t0, ret);
19116 break;
19117 case NM_EXTR_R_W:
19118 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19119 gen_store_gpr(t0, ret);
19120 break;
19121 case NM_EXTR_RS_W:
19122 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19123 gen_store_gpr(t0, ret);
19124 break;
19125 case NM_EXTR_S_H:
19126 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19127 gen_store_gpr(t0, ret);
19128 break;
19130 break;
19131 default:
19132 generate_exception_end(ctx, EXCP_RI);
19133 break;
19136 tcg_temp_free(t0);
19137 tcg_temp_free(t1);
19138 tcg_temp_free(v0_t);
19141 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19142 TCGv v0, TCGv v1, int rd)
19144 TCGv_i32 t0;
19146 t0 = tcg_temp_new_i32();
19148 tcg_gen_movi_i32(t0, rd >> 3);
19150 switch (opc) {
19151 case NM_POOL32AXF_2_0_7:
19152 switch (extract32(ctx->opcode, 9, 3)) {
19153 case NM_DPA_W_PH:
19154 check_dsp_r2(ctx);
19155 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19156 break;
19157 case NM_DPAQ_S_W_PH:
19158 check_dsp(ctx);
19159 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19160 break;
19161 case NM_DPS_W_PH:
19162 check_dsp_r2(ctx);
19163 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19164 break;
19165 case NM_DPSQ_S_W_PH:
19166 check_dsp(ctx);
19167 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19168 break;
19169 default:
19170 generate_exception_end(ctx, EXCP_RI);
19171 break;
19173 break;
19174 case NM_POOL32AXF_2_8_15:
19175 switch (extract32(ctx->opcode, 9, 3)) {
19176 case NM_DPAX_W_PH:
19177 check_dsp_r2(ctx);
19178 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19179 break;
19180 case NM_DPAQ_SA_L_W:
19181 check_dsp(ctx);
19182 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19183 break;
19184 case NM_DPSX_W_PH:
19185 check_dsp_r2(ctx);
19186 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19187 break;
19188 case NM_DPSQ_SA_L_W:
19189 check_dsp(ctx);
19190 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19191 break;
19192 default:
19193 generate_exception_end(ctx, EXCP_RI);
19194 break;
19196 break;
19197 case NM_POOL32AXF_2_16_23:
19198 switch (extract32(ctx->opcode, 9, 3)) {
19199 case NM_DPAU_H_QBL:
19200 check_dsp(ctx);
19201 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19202 break;
19203 case NM_DPAQX_S_W_PH:
19204 check_dsp_r2(ctx);
19205 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19206 break;
19207 case NM_DPSU_H_QBL:
19208 check_dsp(ctx);
19209 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19210 break;
19211 case NM_DPSQX_S_W_PH:
19212 check_dsp_r2(ctx);
19213 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19214 break;
19215 case NM_MULSA_W_PH:
19216 check_dsp_r2(ctx);
19217 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19218 break;
19219 default:
19220 generate_exception_end(ctx, EXCP_RI);
19221 break;
19223 break;
19224 case NM_POOL32AXF_2_24_31:
19225 switch (extract32(ctx->opcode, 9, 3)) {
19226 case NM_DPAU_H_QBR:
19227 check_dsp(ctx);
19228 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19229 break;
19230 case NM_DPAQX_SA_W_PH:
19231 check_dsp_r2(ctx);
19232 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19233 break;
19234 case NM_DPSU_H_QBR:
19235 check_dsp(ctx);
19236 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19237 break;
19238 case NM_DPSQX_SA_W_PH:
19239 check_dsp_r2(ctx);
19240 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19241 break;
19242 case NM_MULSAQ_S_W_PH:
19243 check_dsp(ctx);
19244 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19245 break;
19246 default:
19247 generate_exception_end(ctx, EXCP_RI);
19248 break;
19250 break;
19251 default:
19252 generate_exception_end(ctx, EXCP_RI);
19253 break;
19256 tcg_temp_free_i32(t0);
19259 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19260 int rt, int rs, int rd)
19262 int ret = rt;
19263 TCGv t0 = tcg_temp_new();
19264 TCGv t1 = tcg_temp_new();
19265 TCGv v0_t = tcg_temp_new();
19266 TCGv v1_t = tcg_temp_new();
19268 gen_load_gpr(v0_t, rt);
19269 gen_load_gpr(v1_t, rs);
19271 switch (opc) {
19272 case NM_POOL32AXF_2_0_7:
19273 switch (extract32(ctx->opcode, 9, 3)) {
19274 case NM_DPA_W_PH:
19275 case NM_DPAQ_S_W_PH:
19276 case NM_DPS_W_PH:
19277 case NM_DPSQ_S_W_PH:
19278 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19279 break;
19280 case NM_BALIGN:
19281 check_dsp_r2(ctx);
19282 if (rt != 0) {
19283 gen_load_gpr(t0, rs);
19284 rd &= 3;
19285 if (rd != 0 && rd != 2) {
19286 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19287 tcg_gen_ext32u_tl(t0, t0);
19288 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19289 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19291 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19293 break;
19294 case NM_MADD:
19295 check_dsp(ctx);
19297 int acc = extract32(ctx->opcode, 14, 2);
19298 TCGv_i64 t2 = tcg_temp_new_i64();
19299 TCGv_i64 t3 = tcg_temp_new_i64();
19301 gen_load_gpr(t0, rt);
19302 gen_load_gpr(t1, rs);
19303 tcg_gen_ext_tl_i64(t2, t0);
19304 tcg_gen_ext_tl_i64(t3, t1);
19305 tcg_gen_mul_i64(t2, t2, t3);
19306 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19307 tcg_gen_add_i64(t2, t2, t3);
19308 tcg_temp_free_i64(t3);
19309 gen_move_low32(cpu_LO[acc], t2);
19310 gen_move_high32(cpu_HI[acc], t2);
19311 tcg_temp_free_i64(t2);
19313 break;
19314 case NM_MULT:
19315 check_dsp(ctx);
19317 int acc = extract32(ctx->opcode, 14, 2);
19318 TCGv_i32 t2 = tcg_temp_new_i32();
19319 TCGv_i32 t3 = tcg_temp_new_i32();
19321 gen_load_gpr(t0, rs);
19322 gen_load_gpr(t1, rt);
19323 tcg_gen_trunc_tl_i32(t2, t0);
19324 tcg_gen_trunc_tl_i32(t3, t1);
19325 tcg_gen_muls2_i32(t2, t3, t2, t3);
19326 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19327 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19328 tcg_temp_free_i32(t2);
19329 tcg_temp_free_i32(t3);
19331 break;
19332 case NM_EXTRV_W:
19333 check_dsp(ctx);
19334 gen_load_gpr(v1_t, rs);
19335 tcg_gen_movi_tl(t0, rd >> 3);
19336 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19337 gen_store_gpr(t0, ret);
19338 break;
19340 break;
19341 case NM_POOL32AXF_2_8_15:
19342 switch (extract32(ctx->opcode, 9, 3)) {
19343 case NM_DPAX_W_PH:
19344 case NM_DPAQ_SA_L_W:
19345 case NM_DPSX_W_PH:
19346 case NM_DPSQ_SA_L_W:
19347 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19348 break;
19349 case NM_MADDU:
19350 check_dsp(ctx);
19352 int acc = extract32(ctx->opcode, 14, 2);
19353 TCGv_i64 t2 = tcg_temp_new_i64();
19354 TCGv_i64 t3 = tcg_temp_new_i64();
19356 gen_load_gpr(t0, rs);
19357 gen_load_gpr(t1, rt);
19358 tcg_gen_ext32u_tl(t0, t0);
19359 tcg_gen_ext32u_tl(t1, t1);
19360 tcg_gen_extu_tl_i64(t2, t0);
19361 tcg_gen_extu_tl_i64(t3, t1);
19362 tcg_gen_mul_i64(t2, t2, t3);
19363 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19364 tcg_gen_add_i64(t2, t2, t3);
19365 tcg_temp_free_i64(t3);
19366 gen_move_low32(cpu_LO[acc], t2);
19367 gen_move_high32(cpu_HI[acc], t2);
19368 tcg_temp_free_i64(t2);
19370 break;
19371 case NM_MULTU:
19372 check_dsp(ctx);
19374 int acc = extract32(ctx->opcode, 14, 2);
19375 TCGv_i32 t2 = tcg_temp_new_i32();
19376 TCGv_i32 t3 = tcg_temp_new_i32();
19378 gen_load_gpr(t0, rs);
19379 gen_load_gpr(t1, rt);
19380 tcg_gen_trunc_tl_i32(t2, t0);
19381 tcg_gen_trunc_tl_i32(t3, t1);
19382 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19383 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19384 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19385 tcg_temp_free_i32(t2);
19386 tcg_temp_free_i32(t3);
19388 break;
19389 case NM_EXTRV_R_W:
19390 check_dsp(ctx);
19391 tcg_gen_movi_tl(t0, rd >> 3);
19392 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19393 gen_store_gpr(t0, ret);
19394 break;
19395 default:
19396 generate_exception_end(ctx, EXCP_RI);
19397 break;
19399 break;
19400 case NM_POOL32AXF_2_16_23:
19401 switch (extract32(ctx->opcode, 9, 3)) {
19402 case NM_DPAU_H_QBL:
19403 case NM_DPAQX_S_W_PH:
19404 case NM_DPSU_H_QBL:
19405 case NM_DPSQX_S_W_PH:
19406 case NM_MULSA_W_PH:
19407 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19408 break;
19409 case NM_EXTPV:
19410 check_dsp(ctx);
19411 tcg_gen_movi_tl(t0, rd >> 3);
19412 gen_helper_extp(t0, t0, v1_t, cpu_env);
19413 gen_store_gpr(t0, ret);
19414 break;
19415 case NM_MSUB:
19416 check_dsp(ctx);
19418 int acc = extract32(ctx->opcode, 14, 2);
19419 TCGv_i64 t2 = tcg_temp_new_i64();
19420 TCGv_i64 t3 = tcg_temp_new_i64();
19422 gen_load_gpr(t0, rs);
19423 gen_load_gpr(t1, rt);
19424 tcg_gen_ext_tl_i64(t2, t0);
19425 tcg_gen_ext_tl_i64(t3, t1);
19426 tcg_gen_mul_i64(t2, t2, t3);
19427 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19428 tcg_gen_sub_i64(t2, t3, t2);
19429 tcg_temp_free_i64(t3);
19430 gen_move_low32(cpu_LO[acc], t2);
19431 gen_move_high32(cpu_HI[acc], t2);
19432 tcg_temp_free_i64(t2);
19434 break;
19435 case NM_EXTRV_RS_W:
19436 check_dsp(ctx);
19437 tcg_gen_movi_tl(t0, rd >> 3);
19438 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19439 gen_store_gpr(t0, ret);
19440 break;
19442 break;
19443 case NM_POOL32AXF_2_24_31:
19444 switch (extract32(ctx->opcode, 9, 3)) {
19445 case NM_DPAU_H_QBR:
19446 case NM_DPAQX_SA_W_PH:
19447 case NM_DPSU_H_QBR:
19448 case NM_DPSQX_SA_W_PH:
19449 case NM_MULSAQ_S_W_PH:
19450 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19451 break;
19452 case NM_EXTPDPV:
19453 check_dsp(ctx);
19454 tcg_gen_movi_tl(t0, rd >> 3);
19455 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19456 gen_store_gpr(t0, ret);
19457 break;
19458 case NM_MSUBU:
19459 check_dsp(ctx);
19461 int acc = extract32(ctx->opcode, 14, 2);
19462 TCGv_i64 t2 = tcg_temp_new_i64();
19463 TCGv_i64 t3 = tcg_temp_new_i64();
19465 gen_load_gpr(t0, rs);
19466 gen_load_gpr(t1, rt);
19467 tcg_gen_ext32u_tl(t0, t0);
19468 tcg_gen_ext32u_tl(t1, t1);
19469 tcg_gen_extu_tl_i64(t2, t0);
19470 tcg_gen_extu_tl_i64(t3, t1);
19471 tcg_gen_mul_i64(t2, t2, t3);
19472 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19473 tcg_gen_sub_i64(t2, t3, t2);
19474 tcg_temp_free_i64(t3);
19475 gen_move_low32(cpu_LO[acc], t2);
19476 gen_move_high32(cpu_HI[acc], t2);
19477 tcg_temp_free_i64(t2);
19479 break;
19480 case NM_EXTRV_S_H:
19481 check_dsp(ctx);
19482 tcg_gen_movi_tl(t0, rd >> 3);
19483 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19484 gen_store_gpr(t0, ret);
19485 break;
19487 break;
19488 default:
19489 generate_exception_end(ctx, EXCP_RI);
19490 break;
19493 tcg_temp_free(t0);
19494 tcg_temp_free(t1);
19496 tcg_temp_free(v0_t);
19497 tcg_temp_free(v1_t);
19500 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19501 int rt, int rs)
19503 int ret = rt;
19504 TCGv t0 = tcg_temp_new();
19505 TCGv v0_t = tcg_temp_new();
19507 gen_load_gpr(v0_t, rs);
19509 switch (opc) {
19510 case NM_ABSQ_S_QB:
19511 check_dsp_r2(ctx);
19512 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19513 gen_store_gpr(v0_t, ret);
19514 break;
19515 case NM_ABSQ_S_PH:
19516 check_dsp(ctx);
19517 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19518 gen_store_gpr(v0_t, ret);
19519 break;
19520 case NM_ABSQ_S_W:
19521 check_dsp(ctx);
19522 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19523 gen_store_gpr(v0_t, ret);
19524 break;
19525 case NM_PRECEQ_W_PHL:
19526 check_dsp(ctx);
19527 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19528 tcg_gen_ext32s_tl(v0_t, v0_t);
19529 gen_store_gpr(v0_t, ret);
19530 break;
19531 case NM_PRECEQ_W_PHR:
19532 check_dsp(ctx);
19533 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19534 tcg_gen_shli_tl(v0_t, v0_t, 16);
19535 tcg_gen_ext32s_tl(v0_t, v0_t);
19536 gen_store_gpr(v0_t, ret);
19537 break;
19538 case NM_PRECEQU_PH_QBL:
19539 check_dsp(ctx);
19540 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19541 gen_store_gpr(v0_t, ret);
19542 break;
19543 case NM_PRECEQU_PH_QBR:
19544 check_dsp(ctx);
19545 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19546 gen_store_gpr(v0_t, ret);
19547 break;
19548 case NM_PRECEQU_PH_QBLA:
19549 check_dsp(ctx);
19550 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19551 gen_store_gpr(v0_t, ret);
19552 break;
19553 case NM_PRECEQU_PH_QBRA:
19554 check_dsp(ctx);
19555 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19556 gen_store_gpr(v0_t, ret);
19557 break;
19558 case NM_PRECEU_PH_QBL:
19559 check_dsp(ctx);
19560 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19561 gen_store_gpr(v0_t, ret);
19562 break;
19563 case NM_PRECEU_PH_QBR:
19564 check_dsp(ctx);
19565 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19566 gen_store_gpr(v0_t, ret);
19567 break;
19568 case NM_PRECEU_PH_QBLA:
19569 check_dsp(ctx);
19570 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19571 gen_store_gpr(v0_t, ret);
19572 break;
19573 case NM_PRECEU_PH_QBRA:
19574 check_dsp(ctx);
19575 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19576 gen_store_gpr(v0_t, ret);
19577 break;
19578 case NM_REPLV_PH:
19579 check_dsp(ctx);
19580 tcg_gen_ext16u_tl(v0_t, v0_t);
19581 tcg_gen_shli_tl(t0, v0_t, 16);
19582 tcg_gen_or_tl(v0_t, v0_t, t0);
19583 tcg_gen_ext32s_tl(v0_t, v0_t);
19584 gen_store_gpr(v0_t, ret);
19585 break;
19586 case NM_REPLV_QB:
19587 check_dsp(ctx);
19588 tcg_gen_ext8u_tl(v0_t, v0_t);
19589 tcg_gen_shli_tl(t0, v0_t, 8);
19590 tcg_gen_or_tl(v0_t, v0_t, t0);
19591 tcg_gen_shli_tl(t0, v0_t, 16);
19592 tcg_gen_or_tl(v0_t, v0_t, t0);
19593 tcg_gen_ext32s_tl(v0_t, v0_t);
19594 gen_store_gpr(v0_t, ret);
19595 break;
19596 case NM_BITREV:
19597 check_dsp(ctx);
19598 gen_helper_bitrev(v0_t, v0_t);
19599 gen_store_gpr(v0_t, ret);
19600 break;
19601 case NM_INSV:
19602 check_dsp(ctx);
19604 TCGv tv0 = tcg_temp_new();
19606 gen_load_gpr(tv0, rt);
19607 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19608 gen_store_gpr(v0_t, ret);
19609 tcg_temp_free(tv0);
19611 break;
19612 case NM_RADDU_W_QB:
19613 check_dsp(ctx);
19614 gen_helper_raddu_w_qb(v0_t, v0_t);
19615 gen_store_gpr(v0_t, ret);
19616 break;
19617 case NM_BITSWAP:
19618 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19619 break;
19620 case NM_CLO:
19621 check_nms(ctx);
19622 gen_cl(ctx, OPC_CLO, ret, rs);
19623 break;
19624 case NM_CLZ:
19625 check_nms(ctx);
19626 gen_cl(ctx, OPC_CLZ, ret, rs);
19627 break;
19628 case NM_WSBH:
19629 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19630 break;
19631 default:
19632 generate_exception_end(ctx, EXCP_RI);
19633 break;
19636 tcg_temp_free(v0_t);
19637 tcg_temp_free(t0);
19640 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19641 int rt, int rs, int rd)
19643 TCGv t0 = tcg_temp_new();
19644 TCGv rs_t = tcg_temp_new();
19646 gen_load_gpr(rs_t, rs);
19648 switch (opc) {
19649 case NM_SHRA_R_QB:
19650 check_dsp_r2(ctx);
19651 tcg_gen_movi_tl(t0, rd >> 2);
19652 switch (extract32(ctx->opcode, 12, 1)) {
19653 case 0:
19654 /* NM_SHRA_QB */
19655 gen_helper_shra_qb(t0, t0, rs_t);
19656 gen_store_gpr(t0, rt);
19657 break;
19658 case 1:
19659 /* NM_SHRA_R_QB */
19660 gen_helper_shra_r_qb(t0, t0, rs_t);
19661 gen_store_gpr(t0, rt);
19662 break;
19664 break;
19665 case NM_SHRL_PH:
19666 check_dsp_r2(ctx);
19667 tcg_gen_movi_tl(t0, rd >> 1);
19668 gen_helper_shrl_ph(t0, t0, rs_t);
19669 gen_store_gpr(t0, rt);
19670 break;
19671 case NM_REPL_QB:
19672 check_dsp(ctx);
19674 int16_t imm;
19675 target_long result;
19676 imm = extract32(ctx->opcode, 13, 8);
19677 result = (uint32_t)imm << 24 |
19678 (uint32_t)imm << 16 |
19679 (uint32_t)imm << 8 |
19680 (uint32_t)imm;
19681 result = (int32_t)result;
19682 tcg_gen_movi_tl(t0, result);
19683 gen_store_gpr(t0, rt);
19685 break;
19686 default:
19687 generate_exception_end(ctx, EXCP_RI);
19688 break;
19690 tcg_temp_free(t0);
19691 tcg_temp_free(rs_t);
19695 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19697 int rt = extract32(ctx->opcode, 21, 5);
19698 int rs = extract32(ctx->opcode, 16, 5);
19699 int rd = extract32(ctx->opcode, 11, 5);
19701 switch (extract32(ctx->opcode, 6, 3)) {
19702 case NM_POOL32AXF_1:
19704 int32_t op1 = extract32(ctx->opcode, 9, 3);
19705 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19707 break;
19708 case NM_POOL32AXF_2:
19710 int32_t op1 = extract32(ctx->opcode, 12, 2);
19711 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19713 break;
19714 case NM_POOL32AXF_4:
19716 int32_t op1 = extract32(ctx->opcode, 9, 7);
19717 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19719 break;
19720 case NM_POOL32AXF_5:
19721 switch (extract32(ctx->opcode, 9, 7)) {
19722 #ifndef CONFIG_USER_ONLY
19723 case NM_TLBP:
19724 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19725 break;
19726 case NM_TLBR:
19727 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19728 break;
19729 case NM_TLBWI:
19730 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19731 break;
19732 case NM_TLBWR:
19733 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19734 break;
19735 case NM_TLBINV:
19736 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19737 break;
19738 case NM_TLBINVF:
19739 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19740 break;
19741 case NM_DI:
19742 check_cp0_enabled(ctx);
19744 TCGv t0 = tcg_temp_new();
19746 save_cpu_state(ctx, 1);
19747 gen_helper_di(t0, cpu_env);
19748 gen_store_gpr(t0, rt);
19749 /* Stop translation as we may have switched the execution mode */
19750 ctx->base.is_jmp = DISAS_STOP;
19751 tcg_temp_free(t0);
19753 break;
19754 case NM_EI:
19755 check_cp0_enabled(ctx);
19757 TCGv t0 = tcg_temp_new();
19759 save_cpu_state(ctx, 1);
19760 gen_helper_ei(t0, cpu_env);
19761 gen_store_gpr(t0, rt);
19762 /* Stop translation as we may have switched the execution mode */
19763 ctx->base.is_jmp = DISAS_STOP;
19764 tcg_temp_free(t0);
19766 break;
19767 case NM_RDPGPR:
19768 gen_load_srsgpr(rs, rt);
19769 break;
19770 case NM_WRPGPR:
19771 gen_store_srsgpr(rs, rt);
19772 break;
19773 case NM_WAIT:
19774 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19775 break;
19776 case NM_DERET:
19777 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19778 break;
19779 case NM_ERETX:
19780 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19781 break;
19782 #endif
19783 default:
19784 generate_exception_end(ctx, EXCP_RI);
19785 break;
19787 break;
19788 case NM_POOL32AXF_7:
19790 int32_t op1 = extract32(ctx->opcode, 9, 3);
19791 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19793 break;
19794 default:
19795 generate_exception_end(ctx, EXCP_RI);
19796 break;
19800 /* Immediate Value Compact Branches */
19801 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19802 int rt, int32_t imm, int32_t offset)
19804 TCGCond cond;
19805 int bcond_compute = 0;
19806 TCGv t0 = tcg_temp_new();
19807 TCGv t1 = tcg_temp_new();
19809 gen_load_gpr(t0, rt);
19810 tcg_gen_movi_tl(t1, imm);
19811 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19813 /* Load needed operands and calculate btarget */
19814 switch (opc) {
19815 case NM_BEQIC:
19816 if (rt == 0 && imm == 0) {
19817 /* Unconditional branch */
19818 } else if (rt == 0 && imm != 0) {
19819 /* Treat as NOP */
19820 goto out;
19821 } else {
19822 bcond_compute = 1;
19823 cond = TCG_COND_EQ;
19825 break;
19826 case NM_BBEQZC:
19827 case NM_BBNEZC:
19828 check_nms(ctx);
19829 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19830 generate_exception_end(ctx, EXCP_RI);
19831 goto out;
19832 } else if (rt == 0 && opc == NM_BBEQZC) {
19833 /* Unconditional branch */
19834 } else if (rt == 0 && opc == NM_BBNEZC) {
19835 /* Treat as NOP */
19836 goto out;
19837 } else {
19838 tcg_gen_shri_tl(t0, t0, imm);
19839 tcg_gen_andi_tl(t0, t0, 1);
19840 tcg_gen_movi_tl(t1, 0);
19841 bcond_compute = 1;
19842 if (opc == NM_BBEQZC) {
19843 cond = TCG_COND_EQ;
19844 } else {
19845 cond = TCG_COND_NE;
19848 break;
19849 case NM_BNEIC:
19850 if (rt == 0 && imm == 0) {
19851 /* Treat as NOP */
19852 goto out;
19853 } else if (rt == 0 && imm != 0) {
19854 /* Unconditional branch */
19855 } else {
19856 bcond_compute = 1;
19857 cond = TCG_COND_NE;
19859 break;
19860 case NM_BGEIC:
19861 if (rt == 0 && imm == 0) {
19862 /* Unconditional branch */
19863 } else {
19864 bcond_compute = 1;
19865 cond = TCG_COND_GE;
19867 break;
19868 case NM_BLTIC:
19869 bcond_compute = 1;
19870 cond = TCG_COND_LT;
19871 break;
19872 case NM_BGEIUC:
19873 if (rt == 0 && imm == 0) {
19874 /* Unconditional branch */
19875 } else {
19876 bcond_compute = 1;
19877 cond = TCG_COND_GEU;
19879 break;
19880 case NM_BLTIUC:
19881 bcond_compute = 1;
19882 cond = TCG_COND_LTU;
19883 break;
19884 default:
19885 MIPS_INVAL("Immediate Value Compact branch");
19886 generate_exception_end(ctx, EXCP_RI);
19887 goto out;
19890 /* branch completion */
19891 clear_branch_hflags(ctx);
19892 ctx->base.is_jmp = DISAS_NORETURN;
19894 if (bcond_compute == 0) {
19895 /* Uncoditional compact branch */
19896 gen_goto_tb(ctx, 0, ctx->btarget);
19897 } else {
19898 /* Conditional compact branch */
19899 TCGLabel *fs = gen_new_label();
19901 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19903 gen_goto_tb(ctx, 1, ctx->btarget);
19904 gen_set_label(fs);
19906 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19909 out:
19910 tcg_temp_free(t0);
19911 tcg_temp_free(t1);
19914 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19915 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19916 int rt)
19918 TCGv t0 = tcg_temp_new();
19919 TCGv t1 = tcg_temp_new();
19921 /* load rs */
19922 gen_load_gpr(t0, rs);
19924 /* link */
19925 if (rt != 0) {
19926 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19929 /* calculate btarget */
19930 tcg_gen_shli_tl(t0, t0, 1);
19931 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19932 gen_op_addr_add(ctx, btarget, t1, t0);
19934 /* branch completion */
19935 clear_branch_hflags(ctx);
19936 ctx->base.is_jmp = DISAS_NORETURN;
19938 /* unconditional branch to register */
19939 tcg_gen_mov_tl(cpu_PC, btarget);
19940 tcg_gen_lookup_and_goto_ptr();
19942 tcg_temp_free(t0);
19943 tcg_temp_free(t1);
19946 /* nanoMIPS Branches */
19947 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19948 int rs, int rt, int32_t offset)
19950 int bcond_compute = 0;
19951 TCGv t0 = tcg_temp_new();
19952 TCGv t1 = tcg_temp_new();
19954 /* Load needed operands and calculate btarget */
19955 switch (opc) {
19956 /* compact branch */
19957 case OPC_BGEC:
19958 case OPC_BLTC:
19959 gen_load_gpr(t0, rs);
19960 gen_load_gpr(t1, rt);
19961 bcond_compute = 1;
19962 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19963 break;
19964 case OPC_BGEUC:
19965 case OPC_BLTUC:
19966 if (rs == 0 || rs == rt) {
19967 /* OPC_BLEZALC, OPC_BGEZALC */
19968 /* OPC_BGTZALC, OPC_BLTZALC */
19969 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19971 gen_load_gpr(t0, rs);
19972 gen_load_gpr(t1, rt);
19973 bcond_compute = 1;
19974 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19975 break;
19976 case OPC_BC:
19977 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19978 break;
19979 case OPC_BEQZC:
19980 if (rs != 0) {
19981 /* OPC_BEQZC, OPC_BNEZC */
19982 gen_load_gpr(t0, rs);
19983 bcond_compute = 1;
19984 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19985 } else {
19986 /* OPC_JIC, OPC_JIALC */
19987 TCGv tbase = tcg_temp_new();
19988 TCGv toffset = tcg_temp_new();
19990 gen_load_gpr(tbase, rt);
19991 tcg_gen_movi_tl(toffset, offset);
19992 gen_op_addr_add(ctx, btarget, tbase, toffset);
19993 tcg_temp_free(tbase);
19994 tcg_temp_free(toffset);
19996 break;
19997 default:
19998 MIPS_INVAL("Compact branch/jump");
19999 generate_exception_end(ctx, EXCP_RI);
20000 goto out;
20003 if (bcond_compute == 0) {
20004 /* Uncoditional compact branch */
20005 switch (opc) {
20006 case OPC_BC:
20007 gen_goto_tb(ctx, 0, ctx->btarget);
20008 break;
20009 default:
20010 MIPS_INVAL("Compact branch/jump");
20011 generate_exception_end(ctx, EXCP_RI);
20012 goto out;
20014 } else {
20015 /* Conditional compact branch */
20016 TCGLabel *fs = gen_new_label();
20018 switch (opc) {
20019 case OPC_BGEUC:
20020 if (rs == 0 && rt != 0) {
20021 /* OPC_BLEZALC */
20022 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20023 } else if (rs != 0 && rt != 0 && rs == rt) {
20024 /* OPC_BGEZALC */
20025 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20026 } else {
20027 /* OPC_BGEUC */
20028 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20030 break;
20031 case OPC_BLTUC:
20032 if (rs == 0 && rt != 0) {
20033 /* OPC_BGTZALC */
20034 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20035 } else if (rs != 0 && rt != 0 && rs == rt) {
20036 /* OPC_BLTZALC */
20037 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20038 } else {
20039 /* OPC_BLTUC */
20040 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20042 break;
20043 case OPC_BGEC:
20044 if (rs == 0 && rt != 0) {
20045 /* OPC_BLEZC */
20046 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20047 } else if (rs != 0 && rt != 0 && rs == rt) {
20048 /* OPC_BGEZC */
20049 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20050 } else {
20051 /* OPC_BGEC */
20052 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20054 break;
20055 case OPC_BLTC:
20056 if (rs == 0 && rt != 0) {
20057 /* OPC_BGTZC */
20058 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20059 } else if (rs != 0 && rt != 0 && rs == rt) {
20060 /* OPC_BLTZC */
20061 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20062 } else {
20063 /* OPC_BLTC */
20064 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20066 break;
20067 case OPC_BEQZC:
20068 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20069 break;
20070 default:
20071 MIPS_INVAL("Compact conditional branch/jump");
20072 generate_exception_end(ctx, EXCP_RI);
20073 goto out;
20076 /* branch completion */
20077 clear_branch_hflags(ctx);
20078 ctx->base.is_jmp = DISAS_NORETURN;
20080 /* Generating branch here as compact branches don't have delay slot */
20081 gen_goto_tb(ctx, 1, ctx->btarget);
20082 gen_set_label(fs);
20084 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20087 out:
20088 tcg_temp_free(t0);
20089 tcg_temp_free(t1);
20093 /* nanoMIPS CP1 Branches */
20094 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20095 int32_t ft, int32_t offset)
20097 target_ulong btarget;
20098 TCGv_i64 t0 = tcg_temp_new_i64();
20100 gen_load_fpr64(ctx, t0, ft);
20101 tcg_gen_andi_i64(t0, t0, 1);
20103 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20105 switch (op) {
20106 case NM_BC1EQZC:
20107 tcg_gen_xori_i64(t0, t0, 1);
20108 ctx->hflags |= MIPS_HFLAG_BC;
20109 break;
20110 case NM_BC1NEZC:
20111 /* t0 already set */
20112 ctx->hflags |= MIPS_HFLAG_BC;
20113 break;
20114 default:
20115 MIPS_INVAL("cp1 cond branch");
20116 generate_exception_end(ctx, EXCP_RI);
20117 goto out;
20120 tcg_gen_trunc_i64_tl(bcond, t0);
20122 ctx->btarget = btarget;
20124 out:
20125 tcg_temp_free_i64(t0);
20129 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20131 TCGv t0, t1;
20132 t0 = tcg_temp_new();
20133 t1 = tcg_temp_new();
20135 gen_load_gpr(t0, rs);
20136 gen_load_gpr(t1, rt);
20138 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20139 /* PP.LSXS instructions require shifting */
20140 switch (extract32(ctx->opcode, 7, 4)) {
20141 case NM_SHXS:
20142 check_nms(ctx);
20143 /* fall through */
20144 case NM_LHXS:
20145 case NM_LHUXS:
20146 tcg_gen_shli_tl(t0, t0, 1);
20147 break;
20148 case NM_SWXS:
20149 check_nms(ctx);
20150 /* fall through */
20151 case NM_LWXS:
20152 case NM_LWC1XS:
20153 case NM_SWC1XS:
20154 tcg_gen_shli_tl(t0, t0, 2);
20155 break;
20156 case NM_LDC1XS:
20157 case NM_SDC1XS:
20158 tcg_gen_shli_tl(t0, t0, 3);
20159 break;
20162 gen_op_addr_add(ctx, t0, t0, t1);
20164 switch (extract32(ctx->opcode, 7, 4)) {
20165 case NM_LBX:
20166 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20167 MO_SB);
20168 gen_store_gpr(t0, rd);
20169 break;
20170 case NM_LHX:
20171 /*case NM_LHXS:*/
20172 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20173 MO_TESW);
20174 gen_store_gpr(t0, rd);
20175 break;
20176 case NM_LWX:
20177 /*case NM_LWXS:*/
20178 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20179 MO_TESL);
20180 gen_store_gpr(t0, rd);
20181 break;
20182 case NM_LBUX:
20183 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20184 MO_UB);
20185 gen_store_gpr(t0, rd);
20186 break;
20187 case NM_LHUX:
20188 /*case NM_LHUXS:*/
20189 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20190 MO_TEUW);
20191 gen_store_gpr(t0, rd);
20192 break;
20193 case NM_SBX:
20194 check_nms(ctx);
20195 gen_load_gpr(t1, rd);
20196 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20197 MO_8);
20198 break;
20199 case NM_SHX:
20200 /*case NM_SHXS:*/
20201 check_nms(ctx);
20202 gen_load_gpr(t1, rd);
20203 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20204 MO_TEUW);
20205 break;
20206 case NM_SWX:
20207 /*case NM_SWXS:*/
20208 check_nms(ctx);
20209 gen_load_gpr(t1, rd);
20210 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20211 MO_TEUL);
20212 break;
20213 case NM_LWC1X:
20214 /*case NM_LWC1XS:*/
20215 case NM_LDC1X:
20216 /*case NM_LDC1XS:*/
20217 case NM_SWC1X:
20218 /*case NM_SWC1XS:*/
20219 case NM_SDC1X:
20220 /*case NM_SDC1XS:*/
20221 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20222 check_cp1_enabled(ctx);
20223 switch (extract32(ctx->opcode, 7, 4)) {
20224 case NM_LWC1X:
20225 /*case NM_LWC1XS:*/
20226 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20227 break;
20228 case NM_LDC1X:
20229 /*case NM_LDC1XS:*/
20230 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20231 break;
20232 case NM_SWC1X:
20233 /*case NM_SWC1XS:*/
20234 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20235 break;
20236 case NM_SDC1X:
20237 /*case NM_SDC1XS:*/
20238 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20239 break;
20241 } else {
20242 generate_exception_err(ctx, EXCP_CpU, 1);
20244 break;
20245 default:
20246 generate_exception_end(ctx, EXCP_RI);
20247 break;
20250 tcg_temp_free(t0);
20251 tcg_temp_free(t1);
20254 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20256 int rt, rs, rd;
20258 rt = extract32(ctx->opcode, 21, 5);
20259 rs = extract32(ctx->opcode, 16, 5);
20260 rd = extract32(ctx->opcode, 11, 5);
20262 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20263 generate_exception_end(ctx, EXCP_RI);
20264 return;
20266 check_cp1_enabled(ctx);
20267 switch (extract32(ctx->opcode, 0, 3)) {
20268 case NM_POOL32F_0:
20269 switch (extract32(ctx->opcode, 3, 7)) {
20270 case NM_RINT_S:
20271 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20272 break;
20273 case NM_RINT_D:
20274 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20275 break;
20276 case NM_CLASS_S:
20277 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20278 break;
20279 case NM_CLASS_D:
20280 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20281 break;
20282 case NM_ADD_S:
20283 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20284 break;
20285 case NM_ADD_D:
20286 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20287 break;
20288 case NM_SUB_S:
20289 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20290 break;
20291 case NM_SUB_D:
20292 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20293 break;
20294 case NM_MUL_S:
20295 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20296 break;
20297 case NM_MUL_D:
20298 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20299 break;
20300 case NM_DIV_S:
20301 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20302 break;
20303 case NM_DIV_D:
20304 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20305 break;
20306 case NM_SELEQZ_S:
20307 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20308 break;
20309 case NM_SELEQZ_D:
20310 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20311 break;
20312 case NM_SELNEZ_S:
20313 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20314 break;
20315 case NM_SELNEZ_D:
20316 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20317 break;
20318 case NM_SEL_S:
20319 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20320 break;
20321 case NM_SEL_D:
20322 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20323 break;
20324 case NM_MADDF_S:
20325 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20326 break;
20327 case NM_MADDF_D:
20328 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20329 break;
20330 case NM_MSUBF_S:
20331 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20332 break;
20333 case NM_MSUBF_D:
20334 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20335 break;
20336 default:
20337 generate_exception_end(ctx, EXCP_RI);
20338 break;
20340 break;
20341 case NM_POOL32F_3:
20342 switch (extract32(ctx->opcode, 3, 3)) {
20343 case NM_MIN_FMT:
20344 switch (extract32(ctx->opcode, 9, 1)) {
20345 case FMT_SDPS_S:
20346 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20347 break;
20348 case FMT_SDPS_D:
20349 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20350 break;
20352 break;
20353 case NM_MAX_FMT:
20354 switch (extract32(ctx->opcode, 9, 1)) {
20355 case FMT_SDPS_S:
20356 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20357 break;
20358 case FMT_SDPS_D:
20359 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20360 break;
20362 break;
20363 case NM_MINA_FMT:
20364 switch (extract32(ctx->opcode, 9, 1)) {
20365 case FMT_SDPS_S:
20366 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20367 break;
20368 case FMT_SDPS_D:
20369 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20370 break;
20372 break;
20373 case NM_MAXA_FMT:
20374 switch (extract32(ctx->opcode, 9, 1)) {
20375 case FMT_SDPS_S:
20376 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20377 break;
20378 case FMT_SDPS_D:
20379 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20380 break;
20382 break;
20383 case NM_POOL32FXF:
20384 switch (extract32(ctx->opcode, 6, 8)) {
20385 case NM_CFC1:
20386 gen_cp1(ctx, OPC_CFC1, rt, rs);
20387 break;
20388 case NM_CTC1:
20389 gen_cp1(ctx, OPC_CTC1, rt, rs);
20390 break;
20391 case NM_MFC1:
20392 gen_cp1(ctx, OPC_MFC1, rt, rs);
20393 break;
20394 case NM_MTC1:
20395 gen_cp1(ctx, OPC_MTC1, rt, rs);
20396 break;
20397 case NM_MFHC1:
20398 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20399 break;
20400 case NM_MTHC1:
20401 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20402 break;
20403 case NM_CVT_S_PL:
20404 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20405 break;
20406 case NM_CVT_S_PU:
20407 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20408 break;
20409 default:
20410 switch (extract32(ctx->opcode, 6, 9)) {
20411 case NM_CVT_L_S:
20412 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20413 break;
20414 case NM_CVT_L_D:
20415 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20416 break;
20417 case NM_CVT_W_S:
20418 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20419 break;
20420 case NM_CVT_W_D:
20421 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20422 break;
20423 case NM_RSQRT_S:
20424 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20425 break;
20426 case NM_RSQRT_D:
20427 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20428 break;
20429 case NM_SQRT_S:
20430 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20431 break;
20432 case NM_SQRT_D:
20433 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20434 break;
20435 case NM_RECIP_S:
20436 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20437 break;
20438 case NM_RECIP_D:
20439 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20440 break;
20441 case NM_FLOOR_L_S:
20442 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20443 break;
20444 case NM_FLOOR_L_D:
20445 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20446 break;
20447 case NM_FLOOR_W_S:
20448 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20449 break;
20450 case NM_FLOOR_W_D:
20451 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20452 break;
20453 case NM_CEIL_L_S:
20454 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20455 break;
20456 case NM_CEIL_L_D:
20457 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20458 break;
20459 case NM_CEIL_W_S:
20460 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20461 break;
20462 case NM_CEIL_W_D:
20463 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20464 break;
20465 case NM_TRUNC_L_S:
20466 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20467 break;
20468 case NM_TRUNC_L_D:
20469 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20470 break;
20471 case NM_TRUNC_W_S:
20472 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20473 break;
20474 case NM_TRUNC_W_D:
20475 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20476 break;
20477 case NM_ROUND_L_S:
20478 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20479 break;
20480 case NM_ROUND_L_D:
20481 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20482 break;
20483 case NM_ROUND_W_S:
20484 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20485 break;
20486 case NM_ROUND_W_D:
20487 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20488 break;
20489 case NM_MOV_S:
20490 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20491 break;
20492 case NM_MOV_D:
20493 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20494 break;
20495 case NM_ABS_S:
20496 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20497 break;
20498 case NM_ABS_D:
20499 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20500 break;
20501 case NM_NEG_S:
20502 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20503 break;
20504 case NM_NEG_D:
20505 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20506 break;
20507 case NM_CVT_D_S:
20508 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20509 break;
20510 case NM_CVT_D_W:
20511 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20512 break;
20513 case NM_CVT_D_L:
20514 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20515 break;
20516 case NM_CVT_S_D:
20517 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20518 break;
20519 case NM_CVT_S_W:
20520 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20521 break;
20522 case NM_CVT_S_L:
20523 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20524 break;
20525 default:
20526 generate_exception_end(ctx, EXCP_RI);
20527 break;
20529 break;
20531 break;
20533 break;
20534 case NM_POOL32F_5:
20535 switch (extract32(ctx->opcode, 3, 3)) {
20536 case NM_CMP_CONDN_S:
20537 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20538 break;
20539 case NM_CMP_CONDN_D:
20540 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20541 break;
20542 default:
20543 generate_exception_end(ctx, EXCP_RI);
20544 break;
20546 break;
20547 default:
20548 generate_exception_end(ctx, EXCP_RI);
20549 break;
20553 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20554 int rd, int rs, int rt)
20556 int ret = rd;
20557 TCGv t0 = tcg_temp_new();
20558 TCGv v1_t = tcg_temp_new();
20559 TCGv v2_t = tcg_temp_new();
20561 gen_load_gpr(v1_t, rs);
20562 gen_load_gpr(v2_t, rt);
20564 switch (opc) {
20565 case NM_CMP_EQ_PH:
20566 check_dsp(ctx);
20567 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20568 break;
20569 case NM_CMP_LT_PH:
20570 check_dsp(ctx);
20571 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20572 break;
20573 case NM_CMP_LE_PH:
20574 check_dsp(ctx);
20575 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20576 break;
20577 case NM_CMPU_EQ_QB:
20578 check_dsp(ctx);
20579 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20580 break;
20581 case NM_CMPU_LT_QB:
20582 check_dsp(ctx);
20583 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20584 break;
20585 case NM_CMPU_LE_QB:
20586 check_dsp(ctx);
20587 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20588 break;
20589 case NM_CMPGU_EQ_QB:
20590 check_dsp(ctx);
20591 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20592 gen_store_gpr(v1_t, ret);
20593 break;
20594 case NM_CMPGU_LT_QB:
20595 check_dsp(ctx);
20596 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20597 gen_store_gpr(v1_t, ret);
20598 break;
20599 case NM_CMPGU_LE_QB:
20600 check_dsp(ctx);
20601 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20602 gen_store_gpr(v1_t, ret);
20603 break;
20604 case NM_CMPGDU_EQ_QB:
20605 check_dsp_r2(ctx);
20606 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20607 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20608 gen_store_gpr(v1_t, ret);
20609 break;
20610 case NM_CMPGDU_LT_QB:
20611 check_dsp_r2(ctx);
20612 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20613 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20614 gen_store_gpr(v1_t, ret);
20615 break;
20616 case NM_CMPGDU_LE_QB:
20617 check_dsp_r2(ctx);
20618 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20619 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20620 gen_store_gpr(v1_t, ret);
20621 break;
20622 case NM_PACKRL_PH:
20623 check_dsp(ctx);
20624 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20625 gen_store_gpr(v1_t, ret);
20626 break;
20627 case NM_PICK_QB:
20628 check_dsp(ctx);
20629 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20630 gen_store_gpr(v1_t, ret);
20631 break;
20632 case NM_PICK_PH:
20633 check_dsp(ctx);
20634 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20635 gen_store_gpr(v1_t, ret);
20636 break;
20637 case NM_ADDQ_S_W:
20638 check_dsp(ctx);
20639 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20640 gen_store_gpr(v1_t, ret);
20641 break;
20642 case NM_SUBQ_S_W:
20643 check_dsp(ctx);
20644 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20645 gen_store_gpr(v1_t, ret);
20646 break;
20647 case NM_ADDSC:
20648 check_dsp(ctx);
20649 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20650 gen_store_gpr(v1_t, ret);
20651 break;
20652 case NM_ADDWC:
20653 check_dsp(ctx);
20654 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20655 gen_store_gpr(v1_t, ret);
20656 break;
20657 case NM_ADDQ_S_PH:
20658 check_dsp(ctx);
20659 switch (extract32(ctx->opcode, 10, 1)) {
20660 case 0:
20661 /* ADDQ_PH */
20662 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20663 gen_store_gpr(v1_t, ret);
20664 break;
20665 case 1:
20666 /* ADDQ_S_PH */
20667 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20668 gen_store_gpr(v1_t, ret);
20669 break;
20671 break;
20672 case NM_ADDQH_R_PH:
20673 check_dsp_r2(ctx);
20674 switch (extract32(ctx->opcode, 10, 1)) {
20675 case 0:
20676 /* ADDQH_PH */
20677 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20678 gen_store_gpr(v1_t, ret);
20679 break;
20680 case 1:
20681 /* ADDQH_R_PH */
20682 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20683 gen_store_gpr(v1_t, ret);
20684 break;
20686 break;
20687 case NM_ADDQH_R_W:
20688 check_dsp_r2(ctx);
20689 switch (extract32(ctx->opcode, 10, 1)) {
20690 case 0:
20691 /* ADDQH_W */
20692 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20693 gen_store_gpr(v1_t, ret);
20694 break;
20695 case 1:
20696 /* ADDQH_R_W */
20697 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20698 gen_store_gpr(v1_t, ret);
20699 break;
20701 break;
20702 case NM_ADDU_S_QB:
20703 check_dsp(ctx);
20704 switch (extract32(ctx->opcode, 10, 1)) {
20705 case 0:
20706 /* ADDU_QB */
20707 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20708 gen_store_gpr(v1_t, ret);
20709 break;
20710 case 1:
20711 /* ADDU_S_QB */
20712 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20713 gen_store_gpr(v1_t, ret);
20714 break;
20716 break;
20717 case NM_ADDU_S_PH:
20718 check_dsp_r2(ctx);
20719 switch (extract32(ctx->opcode, 10, 1)) {
20720 case 0:
20721 /* ADDU_PH */
20722 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20723 gen_store_gpr(v1_t, ret);
20724 break;
20725 case 1:
20726 /* ADDU_S_PH */
20727 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20728 gen_store_gpr(v1_t, ret);
20729 break;
20731 break;
20732 case NM_ADDUH_R_QB:
20733 check_dsp_r2(ctx);
20734 switch (extract32(ctx->opcode, 10, 1)) {
20735 case 0:
20736 /* ADDUH_QB */
20737 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20738 gen_store_gpr(v1_t, ret);
20739 break;
20740 case 1:
20741 /* ADDUH_R_QB */
20742 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20743 gen_store_gpr(v1_t, ret);
20744 break;
20746 break;
20747 case NM_SHRAV_R_PH:
20748 check_dsp(ctx);
20749 switch (extract32(ctx->opcode, 10, 1)) {
20750 case 0:
20751 /* SHRAV_PH */
20752 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20753 gen_store_gpr(v1_t, ret);
20754 break;
20755 case 1:
20756 /* SHRAV_R_PH */
20757 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20758 gen_store_gpr(v1_t, ret);
20759 break;
20761 break;
20762 case NM_SHRAV_R_QB:
20763 check_dsp_r2(ctx);
20764 switch (extract32(ctx->opcode, 10, 1)) {
20765 case 0:
20766 /* SHRAV_QB */
20767 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20768 gen_store_gpr(v1_t, ret);
20769 break;
20770 case 1:
20771 /* SHRAV_R_QB */
20772 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20773 gen_store_gpr(v1_t, ret);
20774 break;
20776 break;
20777 case NM_SUBQ_S_PH:
20778 check_dsp(ctx);
20779 switch (extract32(ctx->opcode, 10, 1)) {
20780 case 0:
20781 /* SUBQ_PH */
20782 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20783 gen_store_gpr(v1_t, ret);
20784 break;
20785 case 1:
20786 /* SUBQ_S_PH */
20787 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20788 gen_store_gpr(v1_t, ret);
20789 break;
20791 break;
20792 case NM_SUBQH_R_PH:
20793 check_dsp_r2(ctx);
20794 switch (extract32(ctx->opcode, 10, 1)) {
20795 case 0:
20796 /* SUBQH_PH */
20797 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20798 gen_store_gpr(v1_t, ret);
20799 break;
20800 case 1:
20801 /* SUBQH_R_PH */
20802 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20803 gen_store_gpr(v1_t, ret);
20804 break;
20806 break;
20807 case NM_SUBQH_R_W:
20808 check_dsp_r2(ctx);
20809 switch (extract32(ctx->opcode, 10, 1)) {
20810 case 0:
20811 /* SUBQH_W */
20812 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20813 gen_store_gpr(v1_t, ret);
20814 break;
20815 case 1:
20816 /* SUBQH_R_W */
20817 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20818 gen_store_gpr(v1_t, ret);
20819 break;
20821 break;
20822 case NM_SUBU_S_QB:
20823 check_dsp(ctx);
20824 switch (extract32(ctx->opcode, 10, 1)) {
20825 case 0:
20826 /* SUBU_QB */
20827 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20828 gen_store_gpr(v1_t, ret);
20829 break;
20830 case 1:
20831 /* SUBU_S_QB */
20832 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20833 gen_store_gpr(v1_t, ret);
20834 break;
20836 break;
20837 case NM_SUBU_S_PH:
20838 check_dsp_r2(ctx);
20839 switch (extract32(ctx->opcode, 10, 1)) {
20840 case 0:
20841 /* SUBU_PH */
20842 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20843 gen_store_gpr(v1_t, ret);
20844 break;
20845 case 1:
20846 /* SUBU_S_PH */
20847 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20848 gen_store_gpr(v1_t, ret);
20849 break;
20851 break;
20852 case NM_SUBUH_R_QB:
20853 check_dsp_r2(ctx);
20854 switch (extract32(ctx->opcode, 10, 1)) {
20855 case 0:
20856 /* SUBUH_QB */
20857 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20858 gen_store_gpr(v1_t, ret);
20859 break;
20860 case 1:
20861 /* SUBUH_R_QB */
20862 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20863 gen_store_gpr(v1_t, ret);
20864 break;
20866 break;
20867 case NM_SHLLV_S_PH:
20868 check_dsp(ctx);
20869 switch (extract32(ctx->opcode, 10, 1)) {
20870 case 0:
20871 /* SHLLV_PH */
20872 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20873 gen_store_gpr(v1_t, ret);
20874 break;
20875 case 1:
20876 /* SHLLV_S_PH */
20877 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20878 gen_store_gpr(v1_t, ret);
20879 break;
20881 break;
20882 case NM_PRECR_SRA_R_PH_W:
20883 check_dsp_r2(ctx);
20884 switch (extract32(ctx->opcode, 10, 1)) {
20885 case 0:
20886 /* PRECR_SRA_PH_W */
20888 TCGv_i32 sa_t = tcg_const_i32(rd);
20889 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20890 cpu_gpr[rt]);
20891 gen_store_gpr(v1_t, rt);
20892 tcg_temp_free_i32(sa_t);
20894 break;
20895 case 1:
20896 /* PRECR_SRA_R_PH_W */
20898 TCGv_i32 sa_t = tcg_const_i32(rd);
20899 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20900 cpu_gpr[rt]);
20901 gen_store_gpr(v1_t, rt);
20902 tcg_temp_free_i32(sa_t);
20904 break;
20906 break;
20907 case NM_MULEU_S_PH_QBL:
20908 check_dsp(ctx);
20909 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20910 gen_store_gpr(v1_t, ret);
20911 break;
20912 case NM_MULEU_S_PH_QBR:
20913 check_dsp(ctx);
20914 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20915 gen_store_gpr(v1_t, ret);
20916 break;
20917 case NM_MULQ_RS_PH:
20918 check_dsp(ctx);
20919 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20920 gen_store_gpr(v1_t, ret);
20921 break;
20922 case NM_MULQ_S_PH:
20923 check_dsp_r2(ctx);
20924 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20925 gen_store_gpr(v1_t, ret);
20926 break;
20927 case NM_MULQ_RS_W:
20928 check_dsp_r2(ctx);
20929 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20930 gen_store_gpr(v1_t, ret);
20931 break;
20932 case NM_MULQ_S_W:
20933 check_dsp_r2(ctx);
20934 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20935 gen_store_gpr(v1_t, ret);
20936 break;
20937 case NM_APPEND:
20938 check_dsp_r2(ctx);
20939 gen_load_gpr(t0, rs);
20940 if (rd != 0) {
20941 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20943 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20944 break;
20945 case NM_MODSUB:
20946 check_dsp(ctx);
20947 gen_helper_modsub(v1_t, v1_t, v2_t);
20948 gen_store_gpr(v1_t, ret);
20949 break;
20950 case NM_SHRAV_R_W:
20951 check_dsp(ctx);
20952 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20953 gen_store_gpr(v1_t, ret);
20954 break;
20955 case NM_SHRLV_PH:
20956 check_dsp_r2(ctx);
20957 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20958 gen_store_gpr(v1_t, ret);
20959 break;
20960 case NM_SHRLV_QB:
20961 check_dsp(ctx);
20962 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20963 gen_store_gpr(v1_t, ret);
20964 break;
20965 case NM_SHLLV_QB:
20966 check_dsp(ctx);
20967 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20968 gen_store_gpr(v1_t, ret);
20969 break;
20970 case NM_SHLLV_S_W:
20971 check_dsp(ctx);
20972 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20973 gen_store_gpr(v1_t, ret);
20974 break;
20975 case NM_SHILO:
20976 check_dsp(ctx);
20978 TCGv tv0 = tcg_temp_new();
20979 TCGv tv1 = tcg_temp_new();
20980 int16_t imm = extract32(ctx->opcode, 16, 7);
20982 tcg_gen_movi_tl(tv0, rd >> 3);
20983 tcg_gen_movi_tl(tv1, imm);
20984 gen_helper_shilo(tv0, tv1, cpu_env);
20986 break;
20987 case NM_MULEQ_S_W_PHL:
20988 check_dsp(ctx);
20989 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20990 gen_store_gpr(v1_t, ret);
20991 break;
20992 case NM_MULEQ_S_W_PHR:
20993 check_dsp(ctx);
20994 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20995 gen_store_gpr(v1_t, ret);
20996 break;
20997 case NM_MUL_S_PH:
20998 check_dsp_r2(ctx);
20999 switch (extract32(ctx->opcode, 10, 1)) {
21000 case 0:
21001 /* MUL_PH */
21002 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21003 gen_store_gpr(v1_t, ret);
21004 break;
21005 case 1:
21006 /* MUL_S_PH */
21007 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21008 gen_store_gpr(v1_t, ret);
21009 break;
21011 break;
21012 case NM_PRECR_QB_PH:
21013 check_dsp_r2(ctx);
21014 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21015 gen_store_gpr(v1_t, ret);
21016 break;
21017 case NM_PRECRQ_QB_PH:
21018 check_dsp(ctx);
21019 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21020 gen_store_gpr(v1_t, ret);
21021 break;
21022 case NM_PRECRQ_PH_W:
21023 check_dsp(ctx);
21024 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21025 gen_store_gpr(v1_t, ret);
21026 break;
21027 case NM_PRECRQ_RS_PH_W:
21028 check_dsp(ctx);
21029 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21030 gen_store_gpr(v1_t, ret);
21031 break;
21032 case NM_PRECRQU_S_QB_PH:
21033 check_dsp(ctx);
21034 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21035 gen_store_gpr(v1_t, ret);
21036 break;
21037 case NM_SHRA_R_W:
21038 check_dsp(ctx);
21039 tcg_gen_movi_tl(t0, rd);
21040 gen_helper_shra_r_w(v1_t, t0, v1_t);
21041 gen_store_gpr(v1_t, rt);
21042 break;
21043 case NM_SHRA_R_PH:
21044 check_dsp(ctx);
21045 tcg_gen_movi_tl(t0, rd >> 1);
21046 switch (extract32(ctx->opcode, 10, 1)) {
21047 case 0:
21048 /* SHRA_PH */
21049 gen_helper_shra_ph(v1_t, t0, v1_t);
21050 gen_store_gpr(v1_t, rt);
21051 break;
21052 case 1:
21053 /* SHRA_R_PH */
21054 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21055 gen_store_gpr(v1_t, rt);
21056 break;
21058 break;
21059 case NM_SHLL_S_PH:
21060 check_dsp(ctx);
21061 tcg_gen_movi_tl(t0, rd >> 1);
21062 switch (extract32(ctx->opcode, 10, 2)) {
21063 case 0:
21064 /* SHLL_PH */
21065 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21066 gen_store_gpr(v1_t, rt);
21067 break;
21068 case 2:
21069 /* SHLL_S_PH */
21070 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21071 gen_store_gpr(v1_t, rt);
21072 break;
21073 default:
21074 generate_exception_end(ctx, EXCP_RI);
21075 break;
21077 break;
21078 case NM_SHLL_S_W:
21079 check_dsp(ctx);
21080 tcg_gen_movi_tl(t0, rd);
21081 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21082 gen_store_gpr(v1_t, rt);
21083 break;
21084 case NM_REPL_PH:
21085 check_dsp(ctx);
21087 int16_t imm;
21088 imm = sextract32(ctx->opcode, 11, 11);
21089 imm = (int16_t)(imm << 6) >> 6;
21090 if (rt != 0) {
21091 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21094 break;
21095 default:
21096 generate_exception_end(ctx, EXCP_RI);
21097 break;
21101 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21103 uint16_t insn;
21104 uint32_t op;
21105 int rt, rs, rd;
21106 int offset;
21107 int imm;
21109 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21110 ctx->opcode = (ctx->opcode << 16) | insn;
21112 rt = extract32(ctx->opcode, 21, 5);
21113 rs = extract32(ctx->opcode, 16, 5);
21114 rd = extract32(ctx->opcode, 11, 5);
21116 op = extract32(ctx->opcode, 26, 6);
21117 switch (op) {
21118 case NM_P_ADDIU:
21119 if (rt == 0) {
21120 /* P.RI */
21121 switch (extract32(ctx->opcode, 19, 2)) {
21122 case NM_SIGRIE:
21123 default:
21124 generate_exception_end(ctx, EXCP_RI);
21125 break;
21126 case NM_P_SYSCALL:
21127 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21128 generate_exception_end(ctx, EXCP_SYSCALL);
21129 } else {
21130 generate_exception_end(ctx, EXCP_RI);
21132 break;
21133 case NM_BREAK:
21134 generate_exception_end(ctx, EXCP_BREAK);
21135 break;
21136 case NM_SDBBP:
21137 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21138 gen_helper_do_semihosting(cpu_env);
21139 } else {
21140 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21141 generate_exception_end(ctx, EXCP_RI);
21142 } else {
21143 generate_exception_end(ctx, EXCP_DBp);
21146 break;
21148 } else {
21149 /* NM_ADDIU */
21150 imm = extract32(ctx->opcode, 0, 16);
21151 if (rs != 0) {
21152 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21153 } else {
21154 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21156 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21158 break;
21159 case NM_ADDIUPC:
21160 if (rt != 0) {
21161 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21162 extract32(ctx->opcode, 1, 20) << 1;
21163 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21164 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21166 break;
21167 case NM_POOL32A:
21168 switch (ctx->opcode & 0x07) {
21169 case NM_POOL32A0:
21170 gen_pool32a0_nanomips_insn(env, ctx);
21171 break;
21172 case NM_POOL32A5:
21174 int32_t op1 = extract32(ctx->opcode, 3, 7);
21175 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21177 break;
21178 case NM_POOL32A7:
21179 switch (extract32(ctx->opcode, 3, 3)) {
21180 case NM_P_LSX:
21181 gen_p_lsx(ctx, rd, rs, rt);
21182 break;
21183 case NM_LSA:
21185 * In nanoMIPS, the shift field directly encodes the shift
21186 * amount, meaning that the supported shift values are in
21187 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21189 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21190 extract32(ctx->opcode, 9, 2) - 1);
21191 break;
21192 case NM_EXTW:
21193 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21194 break;
21195 case NM_POOL32AXF:
21196 gen_pool32axf_nanomips_insn(env, ctx);
21197 break;
21198 default:
21199 generate_exception_end(ctx, EXCP_RI);
21200 break;
21202 break;
21203 default:
21204 generate_exception_end(ctx, EXCP_RI);
21205 break;
21207 break;
21208 case NM_P_GP_W:
21209 switch (ctx->opcode & 0x03) {
21210 case NM_ADDIUGP_W:
21211 if (rt != 0) {
21212 offset = extract32(ctx->opcode, 0, 21);
21213 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21215 break;
21216 case NM_LWGP:
21217 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21218 break;
21219 case NM_SWGP:
21220 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21221 break;
21222 default:
21223 generate_exception_end(ctx, EXCP_RI);
21224 break;
21226 break;
21227 case NM_P48I:
21229 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21230 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21231 switch (extract32(ctx->opcode, 16, 5)) {
21232 case NM_LI48:
21233 check_nms(ctx);
21234 if (rt != 0) {
21235 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21237 break;
21238 case NM_ADDIU48:
21239 check_nms(ctx);
21240 if (rt != 0) {
21241 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21242 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21244 break;
21245 case NM_ADDIUGP48:
21246 check_nms(ctx);
21247 if (rt != 0) {
21248 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21250 break;
21251 case NM_ADDIUPC48:
21252 check_nms(ctx);
21253 if (rt != 0) {
21254 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21255 addr_off);
21257 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21259 break;
21260 case NM_LWPC48:
21261 check_nms(ctx);
21262 if (rt != 0) {
21263 TCGv t0;
21264 t0 = tcg_temp_new();
21266 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21267 addr_off);
21269 tcg_gen_movi_tl(t0, addr);
21270 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21271 tcg_temp_free(t0);
21273 break;
21274 case NM_SWPC48:
21275 check_nms(ctx);
21277 TCGv t0, t1;
21278 t0 = tcg_temp_new();
21279 t1 = tcg_temp_new();
21281 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21282 addr_off);
21284 tcg_gen_movi_tl(t0, addr);
21285 gen_load_gpr(t1, rt);
21287 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21289 tcg_temp_free(t0);
21290 tcg_temp_free(t1);
21292 break;
21293 default:
21294 generate_exception_end(ctx, EXCP_RI);
21295 break;
21297 return 6;
21299 case NM_P_U12:
21300 switch (extract32(ctx->opcode, 12, 4)) {
21301 case NM_ORI:
21302 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21303 break;
21304 case NM_XORI:
21305 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21306 break;
21307 case NM_ANDI:
21308 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21309 break;
21310 case NM_P_SR:
21311 switch (extract32(ctx->opcode, 20, 1)) {
21312 case NM_PP_SR:
21313 switch (ctx->opcode & 3) {
21314 case NM_SAVE:
21315 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21316 extract32(ctx->opcode, 2, 1),
21317 extract32(ctx->opcode, 3, 9) << 3);
21318 break;
21319 case NM_RESTORE:
21320 case NM_RESTORE_JRC:
21321 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21322 extract32(ctx->opcode, 2, 1),
21323 extract32(ctx->opcode, 3, 9) << 3);
21324 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21325 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21327 break;
21328 default:
21329 generate_exception_end(ctx, EXCP_RI);
21330 break;
21332 break;
21333 case NM_P_SR_F:
21334 generate_exception_end(ctx, EXCP_RI);
21335 break;
21337 break;
21338 case NM_SLTI:
21339 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21340 break;
21341 case NM_SLTIU:
21342 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21343 break;
21344 case NM_SEQI:
21346 TCGv t0 = tcg_temp_new();
21348 imm = extract32(ctx->opcode, 0, 12);
21349 gen_load_gpr(t0, rs);
21350 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21351 gen_store_gpr(t0, rt);
21353 tcg_temp_free(t0);
21355 break;
21356 case NM_ADDIUNEG:
21357 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21358 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21359 break;
21360 case NM_P_SHIFT:
21362 int shift = extract32(ctx->opcode, 0, 5);
21363 switch (extract32(ctx->opcode, 5, 4)) {
21364 case NM_P_SLL:
21365 if (rt == 0 && shift == 0) {
21366 /* NOP */
21367 } else if (rt == 0 && shift == 3) {
21368 /* EHB - treat as NOP */
21369 } else if (rt == 0 && shift == 5) {
21370 /* PAUSE - treat as NOP */
21371 } else if (rt == 0 && shift == 6) {
21372 /* SYNC */
21373 gen_sync(extract32(ctx->opcode, 16, 5));
21374 } else {
21375 /* SLL */
21376 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21377 extract32(ctx->opcode, 0, 5));
21379 break;
21380 case NM_SRL:
21381 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21382 extract32(ctx->opcode, 0, 5));
21383 break;
21384 case NM_SRA:
21385 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21386 extract32(ctx->opcode, 0, 5));
21387 break;
21388 case NM_ROTR:
21389 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21390 extract32(ctx->opcode, 0, 5));
21391 break;
21394 break;
21395 case NM_P_ROTX:
21396 check_nms(ctx);
21397 if (rt != 0) {
21398 TCGv t0 = tcg_temp_new();
21399 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21400 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21401 << 1);
21402 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21404 gen_load_gpr(t0, rs);
21405 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21406 tcg_temp_free(t0);
21408 tcg_temp_free_i32(shift);
21409 tcg_temp_free_i32(shiftx);
21410 tcg_temp_free_i32(stripe);
21412 break;
21413 case NM_P_INS:
21414 switch (((ctx->opcode >> 10) & 2) |
21415 (extract32(ctx->opcode, 5, 1))) {
21416 case NM_INS:
21417 check_nms(ctx);
21418 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21419 extract32(ctx->opcode, 6, 5));
21420 break;
21421 default:
21422 generate_exception_end(ctx, EXCP_RI);
21423 break;
21425 break;
21426 case NM_P_EXT:
21427 switch (((ctx->opcode >> 10) & 2) |
21428 (extract32(ctx->opcode, 5, 1))) {
21429 case NM_EXT:
21430 check_nms(ctx);
21431 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21432 extract32(ctx->opcode, 6, 5));
21433 break;
21434 default:
21435 generate_exception_end(ctx, EXCP_RI);
21436 break;
21438 break;
21439 default:
21440 generate_exception_end(ctx, EXCP_RI);
21441 break;
21443 break;
21444 case NM_POOL32F:
21445 gen_pool32f_nanomips_insn(ctx);
21446 break;
21447 case NM_POOL32S:
21448 break;
21449 case NM_P_LUI:
21450 switch (extract32(ctx->opcode, 1, 1)) {
21451 case NM_LUI:
21452 if (rt != 0) {
21453 tcg_gen_movi_tl(cpu_gpr[rt],
21454 sextract32(ctx->opcode, 0, 1) << 31 |
21455 extract32(ctx->opcode, 2, 10) << 21 |
21456 extract32(ctx->opcode, 12, 9) << 12);
21458 break;
21459 case NM_ALUIPC:
21460 if (rt != 0) {
21461 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21462 extract32(ctx->opcode, 2, 10) << 21 |
21463 extract32(ctx->opcode, 12, 9) << 12;
21464 target_long addr;
21465 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21466 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21468 break;
21470 break;
21471 case NM_P_GP_BH:
21473 uint32_t u = extract32(ctx->opcode, 0, 18);
21475 switch (extract32(ctx->opcode, 18, 3)) {
21476 case NM_LBGP:
21477 gen_ld(ctx, OPC_LB, rt, 28, u);
21478 break;
21479 case NM_SBGP:
21480 gen_st(ctx, OPC_SB, rt, 28, u);
21481 break;
21482 case NM_LBUGP:
21483 gen_ld(ctx, OPC_LBU, rt, 28, u);
21484 break;
21485 case NM_ADDIUGP_B:
21486 if (rt != 0) {
21487 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21489 break;
21490 case NM_P_GP_LH:
21491 u &= ~1;
21492 switch (ctx->opcode & 1) {
21493 case NM_LHGP:
21494 gen_ld(ctx, OPC_LH, rt, 28, u);
21495 break;
21496 case NM_LHUGP:
21497 gen_ld(ctx, OPC_LHU, rt, 28, u);
21498 break;
21500 break;
21501 case NM_P_GP_SH:
21502 u &= ~1;
21503 switch (ctx->opcode & 1) {
21504 case NM_SHGP:
21505 gen_st(ctx, OPC_SH, rt, 28, u);
21506 break;
21507 default:
21508 generate_exception_end(ctx, EXCP_RI);
21509 break;
21511 break;
21512 case NM_P_GP_CP1:
21513 u &= ~0x3;
21514 switch (ctx->opcode & 0x3) {
21515 case NM_LWC1GP:
21516 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21517 break;
21518 case NM_LDC1GP:
21519 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21520 break;
21521 case NM_SWC1GP:
21522 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21523 break;
21524 case NM_SDC1GP:
21525 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21526 break;
21528 break;
21529 default:
21530 generate_exception_end(ctx, EXCP_RI);
21531 break;
21534 break;
21535 case NM_P_LS_U12:
21537 uint32_t u = extract32(ctx->opcode, 0, 12);
21539 switch (extract32(ctx->opcode, 12, 4)) {
21540 case NM_P_PREFU12:
21541 if (rt == 31) {
21542 /* SYNCI */
21544 * Break the TB to be able to sync copied instructions
21545 * immediately.
21547 ctx->base.is_jmp = DISAS_STOP;
21548 } else {
21549 /* PREF */
21550 /* Treat as NOP. */
21552 break;
21553 case NM_LB:
21554 gen_ld(ctx, OPC_LB, rt, rs, u);
21555 break;
21556 case NM_LH:
21557 gen_ld(ctx, OPC_LH, rt, rs, u);
21558 break;
21559 case NM_LW:
21560 gen_ld(ctx, OPC_LW, rt, rs, u);
21561 break;
21562 case NM_LBU:
21563 gen_ld(ctx, OPC_LBU, rt, rs, u);
21564 break;
21565 case NM_LHU:
21566 gen_ld(ctx, OPC_LHU, rt, rs, u);
21567 break;
21568 case NM_SB:
21569 gen_st(ctx, OPC_SB, rt, rs, u);
21570 break;
21571 case NM_SH:
21572 gen_st(ctx, OPC_SH, rt, rs, u);
21573 break;
21574 case NM_SW:
21575 gen_st(ctx, OPC_SW, rt, rs, u);
21576 break;
21577 case NM_LWC1:
21578 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21579 break;
21580 case NM_LDC1:
21581 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21582 break;
21583 case NM_SWC1:
21584 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21585 break;
21586 case NM_SDC1:
21587 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21588 break;
21589 default:
21590 generate_exception_end(ctx, EXCP_RI);
21591 break;
21594 break;
21595 case NM_P_LS_S9:
21597 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21598 extract32(ctx->opcode, 0, 8);
21600 switch (extract32(ctx->opcode, 8, 3)) {
21601 case NM_P_LS_S0:
21602 switch (extract32(ctx->opcode, 11, 4)) {
21603 case NM_LBS9:
21604 gen_ld(ctx, OPC_LB, rt, rs, s);
21605 break;
21606 case NM_LHS9:
21607 gen_ld(ctx, OPC_LH, rt, rs, s);
21608 break;
21609 case NM_LWS9:
21610 gen_ld(ctx, OPC_LW, rt, rs, s);
21611 break;
21612 case NM_LBUS9:
21613 gen_ld(ctx, OPC_LBU, rt, rs, s);
21614 break;
21615 case NM_LHUS9:
21616 gen_ld(ctx, OPC_LHU, rt, rs, s);
21617 break;
21618 case NM_SBS9:
21619 gen_st(ctx, OPC_SB, rt, rs, s);
21620 break;
21621 case NM_SHS9:
21622 gen_st(ctx, OPC_SH, rt, rs, s);
21623 break;
21624 case NM_SWS9:
21625 gen_st(ctx, OPC_SW, rt, rs, s);
21626 break;
21627 case NM_LWC1S9:
21628 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21629 break;
21630 case NM_LDC1S9:
21631 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21632 break;
21633 case NM_SWC1S9:
21634 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21635 break;
21636 case NM_SDC1S9:
21637 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21638 break;
21639 case NM_P_PREFS9:
21640 if (rt == 31) {
21641 /* SYNCI */
21643 * Break the TB to be able to sync copied instructions
21644 * immediately.
21646 ctx->base.is_jmp = DISAS_STOP;
21647 } else {
21648 /* PREF */
21649 /* Treat as NOP. */
21651 break;
21652 default:
21653 generate_exception_end(ctx, EXCP_RI);
21654 break;
21656 break;
21657 case NM_P_LS_S1:
21658 switch (extract32(ctx->opcode, 11, 4)) {
21659 case NM_UALH:
21660 case NM_UASH:
21661 check_nms(ctx);
21663 TCGv t0 = tcg_temp_new();
21664 TCGv t1 = tcg_temp_new();
21666 gen_base_offset_addr(ctx, t0, rs, s);
21668 switch (extract32(ctx->opcode, 11, 4)) {
21669 case NM_UALH:
21670 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21671 MO_UNALN);
21672 gen_store_gpr(t0, rt);
21673 break;
21674 case NM_UASH:
21675 gen_load_gpr(t1, rt);
21676 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21677 MO_UNALN);
21678 break;
21680 tcg_temp_free(t0);
21681 tcg_temp_free(t1);
21683 break;
21684 case NM_P_LL:
21685 switch (ctx->opcode & 0x03) {
21686 case NM_LL:
21687 gen_ld(ctx, OPC_LL, rt, rs, s);
21688 break;
21689 case NM_LLWP:
21690 check_xnp(ctx);
21691 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21692 break;
21694 break;
21695 case NM_P_SC:
21696 switch (ctx->opcode & 0x03) {
21697 case NM_SC:
21698 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21699 break;
21700 case NM_SCWP:
21701 check_xnp(ctx);
21702 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21703 false);
21704 break;
21706 break;
21707 case NM_CACHE:
21708 check_cp0_enabled(ctx);
21709 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21710 gen_cache_operation(ctx, rt, rs, s);
21712 break;
21714 break;
21715 case NM_P_LS_E0:
21716 switch (extract32(ctx->opcode, 11, 4)) {
21717 case NM_LBE:
21718 check_eva(ctx);
21719 check_cp0_enabled(ctx);
21720 gen_ld(ctx, OPC_LBE, rt, rs, s);
21721 break;
21722 case NM_SBE:
21723 check_eva(ctx);
21724 check_cp0_enabled(ctx);
21725 gen_st(ctx, OPC_SBE, rt, rs, s);
21726 break;
21727 case NM_LBUE:
21728 check_eva(ctx);
21729 check_cp0_enabled(ctx);
21730 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21731 break;
21732 case NM_P_PREFE:
21733 if (rt == 31) {
21734 /* case NM_SYNCIE */
21735 check_eva(ctx);
21736 check_cp0_enabled(ctx);
21738 * Break the TB to be able to sync copied instructions
21739 * immediately.
21741 ctx->base.is_jmp = DISAS_STOP;
21742 } else {
21743 /* case NM_PREFE */
21744 check_eva(ctx);
21745 check_cp0_enabled(ctx);
21746 /* Treat as NOP. */
21748 break;
21749 case NM_LHE:
21750 check_eva(ctx);
21751 check_cp0_enabled(ctx);
21752 gen_ld(ctx, OPC_LHE, rt, rs, s);
21753 break;
21754 case NM_SHE:
21755 check_eva(ctx);
21756 check_cp0_enabled(ctx);
21757 gen_st(ctx, OPC_SHE, rt, rs, s);
21758 break;
21759 case NM_LHUE:
21760 check_eva(ctx);
21761 check_cp0_enabled(ctx);
21762 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21763 break;
21764 case NM_CACHEE:
21765 check_nms_dl_il_sl_tl_l2c(ctx);
21766 gen_cache_operation(ctx, rt, rs, s);
21767 break;
21768 case NM_LWE:
21769 check_eva(ctx);
21770 check_cp0_enabled(ctx);
21771 gen_ld(ctx, OPC_LWE, rt, rs, s);
21772 break;
21773 case NM_SWE:
21774 check_eva(ctx);
21775 check_cp0_enabled(ctx);
21776 gen_st(ctx, OPC_SWE, rt, rs, s);
21777 break;
21778 case NM_P_LLE:
21779 switch (extract32(ctx->opcode, 2, 2)) {
21780 case NM_LLE:
21781 check_xnp(ctx);
21782 check_eva(ctx);
21783 check_cp0_enabled(ctx);
21784 gen_ld(ctx, OPC_LLE, rt, rs, s);
21785 break;
21786 case NM_LLWPE:
21787 check_xnp(ctx);
21788 check_eva(ctx);
21789 check_cp0_enabled(ctx);
21790 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21791 break;
21792 default:
21793 generate_exception_end(ctx, EXCP_RI);
21794 break;
21796 break;
21797 case NM_P_SCE:
21798 switch (extract32(ctx->opcode, 2, 2)) {
21799 case NM_SCE:
21800 check_xnp(ctx);
21801 check_eva(ctx);
21802 check_cp0_enabled(ctx);
21803 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21804 break;
21805 case NM_SCWPE:
21806 check_xnp(ctx);
21807 check_eva(ctx);
21808 check_cp0_enabled(ctx);
21809 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21810 true);
21811 break;
21812 default:
21813 generate_exception_end(ctx, EXCP_RI);
21814 break;
21816 break;
21818 break;
21819 case NM_P_LS_WM:
21820 case NM_P_LS_UAWM:
21821 check_nms(ctx);
21823 int count = extract32(ctx->opcode, 12, 3);
21824 int counter = 0;
21826 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21827 extract32(ctx->opcode, 0, 8);
21828 TCGv va = tcg_temp_new();
21829 TCGv t1 = tcg_temp_new();
21830 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21831 NM_P_LS_UAWM ? MO_UNALN : 0;
21833 count = (count == 0) ? 8 : count;
21834 while (counter != count) {
21835 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21836 int this_offset = offset + (counter << 2);
21838 gen_base_offset_addr(ctx, va, rs, this_offset);
21840 switch (extract32(ctx->opcode, 11, 1)) {
21841 case NM_LWM:
21842 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21843 memop | MO_TESL);
21844 gen_store_gpr(t1, this_rt);
21845 if ((this_rt == rs) &&
21846 (counter != (count - 1))) {
21847 /* UNPREDICTABLE */
21849 break;
21850 case NM_SWM:
21851 this_rt = (rt == 0) ? 0 : this_rt;
21852 gen_load_gpr(t1, this_rt);
21853 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21854 memop | MO_TEUL);
21855 break;
21857 counter++;
21859 tcg_temp_free(va);
21860 tcg_temp_free(t1);
21862 break;
21863 default:
21864 generate_exception_end(ctx, EXCP_RI);
21865 break;
21868 break;
21869 case NM_MOVE_BALC:
21870 check_nms(ctx);
21872 TCGv t0 = tcg_temp_new();
21873 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21874 extract32(ctx->opcode, 1, 20) << 1;
21875 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21876 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21877 extract32(ctx->opcode, 21, 3));
21878 gen_load_gpr(t0, rt);
21879 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21880 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21881 tcg_temp_free(t0);
21883 break;
21884 case NM_P_BAL:
21886 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21887 extract32(ctx->opcode, 1, 24) << 1;
21889 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21890 /* BC */
21891 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21892 } else {
21893 /* BALC */
21894 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21897 break;
21898 case NM_P_J:
21899 switch (extract32(ctx->opcode, 12, 4)) {
21900 case NM_JALRC:
21901 case NM_JALRC_HB:
21902 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21903 break;
21904 case NM_P_BALRSC:
21905 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21906 break;
21907 default:
21908 generate_exception_end(ctx, EXCP_RI);
21909 break;
21911 break;
21912 case NM_P_BR1:
21914 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21915 extract32(ctx->opcode, 1, 13) << 1;
21916 switch (extract32(ctx->opcode, 14, 2)) {
21917 case NM_BEQC:
21918 check_nms(ctx);
21919 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21920 break;
21921 case NM_P_BR3A:
21922 s = sextract32(ctx->opcode, 0, 1) << 14 |
21923 extract32(ctx->opcode, 1, 13) << 1;
21924 check_cp1_enabled(ctx);
21925 switch (extract32(ctx->opcode, 16, 5)) {
21926 case NM_BC1EQZC:
21927 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21928 break;
21929 case NM_BC1NEZC:
21930 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21931 break;
21932 case NM_BPOSGE32C:
21933 check_dsp_r3(ctx);
21935 int32_t imm = extract32(ctx->opcode, 1, 13) |
21936 extract32(ctx->opcode, 0, 1) << 13;
21938 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21939 imm);
21941 break;
21942 default:
21943 generate_exception_end(ctx, EXCP_RI);
21944 break;
21946 break;
21947 case NM_BGEC:
21948 if (rs == rt) {
21949 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21950 } else {
21951 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21953 break;
21954 case NM_BGEUC:
21955 if (rs == rt || rt == 0) {
21956 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21957 } else if (rs == 0) {
21958 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21959 } else {
21960 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21962 break;
21965 break;
21966 case NM_P_BR2:
21968 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21969 extract32(ctx->opcode, 1, 13) << 1;
21970 switch (extract32(ctx->opcode, 14, 2)) {
21971 case NM_BNEC:
21972 check_nms(ctx);
21973 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21974 break;
21975 case NM_BLTC:
21976 if (rs != 0 && rt != 0 && rs == rt) {
21977 /* NOP */
21978 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21979 } else {
21980 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21982 break;
21983 case NM_BLTUC:
21984 if (rs == 0 || rs == rt) {
21985 /* NOP */
21986 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21987 } else {
21988 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21990 break;
21991 default:
21992 generate_exception_end(ctx, EXCP_RI);
21993 break;
21996 break;
21997 case NM_P_BRI:
21999 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22000 extract32(ctx->opcode, 1, 10) << 1;
22001 uint32_t u = extract32(ctx->opcode, 11, 7);
22003 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22004 rt, u, s);
22006 break;
22007 default:
22008 generate_exception_end(ctx, EXCP_RI);
22009 break;
22011 return 4;
22014 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22016 uint32_t op;
22017 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22018 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22019 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22020 int offset;
22021 int imm;
22023 /* make sure instructions are on a halfword boundary */
22024 if (ctx->base.pc_next & 0x1) {
22025 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22026 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22027 tcg_temp_free(tmp);
22028 generate_exception_end(ctx, EXCP_AdEL);
22029 return 2;
22032 op = extract32(ctx->opcode, 10, 6);
22033 switch (op) {
22034 case NM_P16_MV:
22035 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22036 if (rt != 0) {
22037 /* MOVE */
22038 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22039 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22040 } else {
22041 /* P16.RI */
22042 switch (extract32(ctx->opcode, 3, 2)) {
22043 case NM_P16_SYSCALL:
22044 if (extract32(ctx->opcode, 2, 1) == 0) {
22045 generate_exception_end(ctx, EXCP_SYSCALL);
22046 } else {
22047 generate_exception_end(ctx, EXCP_RI);
22049 break;
22050 case NM_BREAK16:
22051 generate_exception_end(ctx, EXCP_BREAK);
22052 break;
22053 case NM_SDBBP16:
22054 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22055 gen_helper_do_semihosting(cpu_env);
22056 } else {
22057 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22058 generate_exception_end(ctx, EXCP_RI);
22059 } else {
22060 generate_exception_end(ctx, EXCP_DBp);
22063 break;
22064 default:
22065 generate_exception_end(ctx, EXCP_RI);
22066 break;
22069 break;
22070 case NM_P16_SHIFT:
22072 int shift = extract32(ctx->opcode, 0, 3);
22073 uint32_t opc = 0;
22074 shift = (shift == 0) ? 8 : shift;
22076 switch (extract32(ctx->opcode, 3, 1)) {
22077 case NM_SLL16:
22078 opc = OPC_SLL;
22079 break;
22080 case NM_SRL16:
22081 opc = OPC_SRL;
22082 break;
22084 gen_shift_imm(ctx, opc, rt, rs, shift);
22086 break;
22087 case NM_P16C:
22088 switch (ctx->opcode & 1) {
22089 case NM_POOL16C_0:
22090 gen_pool16c_nanomips_insn(ctx);
22091 break;
22092 case NM_LWXS16:
22093 gen_ldxs(ctx, rt, rs, rd);
22094 break;
22096 break;
22097 case NM_P16_A1:
22098 switch (extract32(ctx->opcode, 6, 1)) {
22099 case NM_ADDIUR1SP:
22100 imm = extract32(ctx->opcode, 0, 6) << 2;
22101 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22102 break;
22103 default:
22104 generate_exception_end(ctx, EXCP_RI);
22105 break;
22107 break;
22108 case NM_P16_A2:
22109 switch (extract32(ctx->opcode, 3, 1)) {
22110 case NM_ADDIUR2:
22111 imm = extract32(ctx->opcode, 0, 3) << 2;
22112 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22113 break;
22114 case NM_P_ADDIURS5:
22115 rt = extract32(ctx->opcode, 5, 5);
22116 if (rt != 0) {
22117 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22118 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22119 (extract32(ctx->opcode, 0, 3));
22120 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22122 break;
22124 break;
22125 case NM_P16_ADDU:
22126 switch (ctx->opcode & 0x1) {
22127 case NM_ADDU16:
22128 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22129 break;
22130 case NM_SUBU16:
22131 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22132 break;
22134 break;
22135 case NM_P16_4X4:
22136 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22137 extract32(ctx->opcode, 5, 3);
22138 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22139 extract32(ctx->opcode, 0, 3);
22140 rt = decode_gpr_gpr4(rt);
22141 rs = decode_gpr_gpr4(rs);
22142 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22143 (extract32(ctx->opcode, 3, 1))) {
22144 case NM_ADDU4X4:
22145 check_nms(ctx);
22146 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22147 break;
22148 case NM_MUL4X4:
22149 check_nms(ctx);
22150 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22151 break;
22152 default:
22153 generate_exception_end(ctx, EXCP_RI);
22154 break;
22156 break;
22157 case NM_LI16:
22159 int imm = extract32(ctx->opcode, 0, 7);
22160 imm = (imm == 0x7f ? -1 : imm);
22161 if (rt != 0) {
22162 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22165 break;
22166 case NM_ANDI16:
22168 uint32_t u = extract32(ctx->opcode, 0, 4);
22169 u = (u == 12) ? 0xff :
22170 (u == 13) ? 0xffff : u;
22171 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22173 break;
22174 case NM_P16_LB:
22175 offset = extract32(ctx->opcode, 0, 2);
22176 switch (extract32(ctx->opcode, 2, 2)) {
22177 case NM_LB16:
22178 gen_ld(ctx, OPC_LB, rt, rs, offset);
22179 break;
22180 case NM_SB16:
22181 rt = decode_gpr_gpr3_src_store(
22182 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22183 gen_st(ctx, OPC_SB, rt, rs, offset);
22184 break;
22185 case NM_LBU16:
22186 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22187 break;
22188 default:
22189 generate_exception_end(ctx, EXCP_RI);
22190 break;
22192 break;
22193 case NM_P16_LH:
22194 offset = extract32(ctx->opcode, 1, 2) << 1;
22195 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22196 case NM_LH16:
22197 gen_ld(ctx, OPC_LH, rt, rs, offset);
22198 break;
22199 case NM_SH16:
22200 rt = decode_gpr_gpr3_src_store(
22201 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22202 gen_st(ctx, OPC_SH, rt, rs, offset);
22203 break;
22204 case NM_LHU16:
22205 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22206 break;
22207 default:
22208 generate_exception_end(ctx, EXCP_RI);
22209 break;
22211 break;
22212 case NM_LW16:
22213 offset = extract32(ctx->opcode, 0, 4) << 2;
22214 gen_ld(ctx, OPC_LW, rt, rs, offset);
22215 break;
22216 case NM_LWSP16:
22217 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22218 offset = extract32(ctx->opcode, 0, 5) << 2;
22219 gen_ld(ctx, OPC_LW, rt, 29, offset);
22220 break;
22221 case NM_LW4X4:
22222 check_nms(ctx);
22223 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22224 extract32(ctx->opcode, 5, 3);
22225 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22226 extract32(ctx->opcode, 0, 3);
22227 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22228 (extract32(ctx->opcode, 8, 1) << 2);
22229 rt = decode_gpr_gpr4(rt);
22230 rs = decode_gpr_gpr4(rs);
22231 gen_ld(ctx, OPC_LW, rt, rs, offset);
22232 break;
22233 case NM_SW4X4:
22234 check_nms(ctx);
22235 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22236 extract32(ctx->opcode, 5, 3);
22237 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22238 extract32(ctx->opcode, 0, 3);
22239 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22240 (extract32(ctx->opcode, 8, 1) << 2);
22241 rt = decode_gpr_gpr4_zero(rt);
22242 rs = decode_gpr_gpr4(rs);
22243 gen_st(ctx, OPC_SW, rt, rs, offset);
22244 break;
22245 case NM_LWGP16:
22246 offset = extract32(ctx->opcode, 0, 7) << 2;
22247 gen_ld(ctx, OPC_LW, rt, 28, offset);
22248 break;
22249 case NM_SWSP16:
22250 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22251 offset = extract32(ctx->opcode, 0, 5) << 2;
22252 gen_st(ctx, OPC_SW, rt, 29, offset);
22253 break;
22254 case NM_SW16:
22255 rt = decode_gpr_gpr3_src_store(
22256 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22257 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22258 offset = extract32(ctx->opcode, 0, 4) << 2;
22259 gen_st(ctx, OPC_SW, rt, rs, offset);
22260 break;
22261 case NM_SWGP16:
22262 rt = decode_gpr_gpr3_src_store(
22263 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22264 offset = extract32(ctx->opcode, 0, 7) << 2;
22265 gen_st(ctx, OPC_SW, rt, 28, offset);
22266 break;
22267 case NM_BC16:
22268 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22269 (sextract32(ctx->opcode, 0, 1) << 10) |
22270 (extract32(ctx->opcode, 1, 9) << 1));
22271 break;
22272 case NM_BALC16:
22273 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22274 (sextract32(ctx->opcode, 0, 1) << 10) |
22275 (extract32(ctx->opcode, 1, 9) << 1));
22276 break;
22277 case NM_BEQZC16:
22278 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22279 (sextract32(ctx->opcode, 0, 1) << 7) |
22280 (extract32(ctx->opcode, 1, 6) << 1));
22281 break;
22282 case NM_BNEZC16:
22283 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22284 (sextract32(ctx->opcode, 0, 1) << 7) |
22285 (extract32(ctx->opcode, 1, 6) << 1));
22286 break;
22287 case NM_P16_BR:
22288 switch (ctx->opcode & 0xf) {
22289 case 0:
22290 /* P16.JRC */
22291 switch (extract32(ctx->opcode, 4, 1)) {
22292 case NM_JRC:
22293 gen_compute_branch_nm(ctx, OPC_JR, 2,
22294 extract32(ctx->opcode, 5, 5), 0, 0);
22295 break;
22296 case NM_JALRC16:
22297 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22298 extract32(ctx->opcode, 5, 5), 31, 0);
22299 break;
22301 break;
22302 default:
22304 /* P16.BRI */
22305 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22306 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22307 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22308 extract32(ctx->opcode, 0, 4) << 1);
22310 break;
22312 break;
22313 case NM_P16_SR:
22315 int count = extract32(ctx->opcode, 0, 4);
22316 int u = extract32(ctx->opcode, 4, 4) << 4;
22318 rt = 30 + extract32(ctx->opcode, 9, 1);
22319 switch (extract32(ctx->opcode, 8, 1)) {
22320 case NM_SAVE16:
22321 gen_save(ctx, rt, count, 0, u);
22322 break;
22323 case NM_RESTORE_JRC16:
22324 gen_restore(ctx, rt, count, 0, u);
22325 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22326 break;
22329 break;
22330 case NM_MOVEP:
22331 case NM_MOVEPREV:
22332 check_nms(ctx);
22334 static const int gpr2reg1[] = {4, 5, 6, 7};
22335 static const int gpr2reg2[] = {5, 6, 7, 8};
22336 int re;
22337 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22338 extract32(ctx->opcode, 8, 1);
22339 int r1 = gpr2reg1[rd2];
22340 int r2 = gpr2reg2[rd2];
22341 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22342 extract32(ctx->opcode, 0, 3);
22343 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22344 extract32(ctx->opcode, 5, 3);
22345 TCGv t0 = tcg_temp_new();
22346 TCGv t1 = tcg_temp_new();
22347 if (op == NM_MOVEP) {
22348 rd = r1;
22349 re = r2;
22350 rs = decode_gpr_gpr4_zero(r3);
22351 rt = decode_gpr_gpr4_zero(r4);
22352 } else {
22353 rd = decode_gpr_gpr4(r3);
22354 re = decode_gpr_gpr4(r4);
22355 rs = r1;
22356 rt = r2;
22358 gen_load_gpr(t0, rs);
22359 gen_load_gpr(t1, rt);
22360 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22361 tcg_gen_mov_tl(cpu_gpr[re], t1);
22362 tcg_temp_free(t0);
22363 tcg_temp_free(t1);
22365 break;
22366 default:
22367 return decode_nanomips_32_48_opc(env, ctx);
22370 return 2;
22374 /* SmartMIPS extension to MIPS32 */
22376 #if defined(TARGET_MIPS64)
22378 /* MDMX extension to MIPS64 */
22380 #endif
22382 /* MIPSDSP functions. */
22383 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22384 int rd, int base, int offset)
22386 TCGv t0;
22388 check_dsp(ctx);
22389 t0 = tcg_temp_new();
22391 if (base == 0) {
22392 gen_load_gpr(t0, offset);
22393 } else if (offset == 0) {
22394 gen_load_gpr(t0, base);
22395 } else {
22396 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22399 switch (opc) {
22400 case OPC_LBUX:
22401 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22402 gen_store_gpr(t0, rd);
22403 break;
22404 case OPC_LHX:
22405 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22406 gen_store_gpr(t0, rd);
22407 break;
22408 case OPC_LWX:
22409 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22410 gen_store_gpr(t0, rd);
22411 break;
22412 #if defined(TARGET_MIPS64)
22413 case OPC_LDX:
22414 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22415 gen_store_gpr(t0, rd);
22416 break;
22417 #endif
22419 tcg_temp_free(t0);
22422 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22423 int ret, int v1, int v2)
22425 TCGv v1_t;
22426 TCGv v2_t;
22428 if (ret == 0) {
22429 /* Treat as NOP. */
22430 return;
22433 v1_t = tcg_temp_new();
22434 v2_t = tcg_temp_new();
22436 gen_load_gpr(v1_t, v1);
22437 gen_load_gpr(v2_t, v2);
22439 switch (op1) {
22440 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22441 case OPC_MULT_G_2E:
22442 check_dsp_r2(ctx);
22443 switch (op2) {
22444 case OPC_ADDUH_QB:
22445 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22446 break;
22447 case OPC_ADDUH_R_QB:
22448 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22449 break;
22450 case OPC_ADDQH_PH:
22451 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22452 break;
22453 case OPC_ADDQH_R_PH:
22454 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22455 break;
22456 case OPC_ADDQH_W:
22457 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22458 break;
22459 case OPC_ADDQH_R_W:
22460 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22461 break;
22462 case OPC_SUBUH_QB:
22463 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22464 break;
22465 case OPC_SUBUH_R_QB:
22466 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22467 break;
22468 case OPC_SUBQH_PH:
22469 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22470 break;
22471 case OPC_SUBQH_R_PH:
22472 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22473 break;
22474 case OPC_SUBQH_W:
22475 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22476 break;
22477 case OPC_SUBQH_R_W:
22478 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22479 break;
22481 break;
22482 case OPC_ABSQ_S_PH_DSP:
22483 switch (op2) {
22484 case OPC_ABSQ_S_QB:
22485 check_dsp_r2(ctx);
22486 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22487 break;
22488 case OPC_ABSQ_S_PH:
22489 check_dsp(ctx);
22490 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22491 break;
22492 case OPC_ABSQ_S_W:
22493 check_dsp(ctx);
22494 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22495 break;
22496 case OPC_PRECEQ_W_PHL:
22497 check_dsp(ctx);
22498 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22499 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22500 break;
22501 case OPC_PRECEQ_W_PHR:
22502 check_dsp(ctx);
22503 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22504 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22505 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22506 break;
22507 case OPC_PRECEQU_PH_QBL:
22508 check_dsp(ctx);
22509 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22510 break;
22511 case OPC_PRECEQU_PH_QBR:
22512 check_dsp(ctx);
22513 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22514 break;
22515 case OPC_PRECEQU_PH_QBLA:
22516 check_dsp(ctx);
22517 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22518 break;
22519 case OPC_PRECEQU_PH_QBRA:
22520 check_dsp(ctx);
22521 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22522 break;
22523 case OPC_PRECEU_PH_QBL:
22524 check_dsp(ctx);
22525 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22526 break;
22527 case OPC_PRECEU_PH_QBR:
22528 check_dsp(ctx);
22529 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22530 break;
22531 case OPC_PRECEU_PH_QBLA:
22532 check_dsp(ctx);
22533 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22534 break;
22535 case OPC_PRECEU_PH_QBRA:
22536 check_dsp(ctx);
22537 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22538 break;
22540 break;
22541 case OPC_ADDU_QB_DSP:
22542 switch (op2) {
22543 case OPC_ADDQ_PH:
22544 check_dsp(ctx);
22545 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22546 break;
22547 case OPC_ADDQ_S_PH:
22548 check_dsp(ctx);
22549 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22550 break;
22551 case OPC_ADDQ_S_W:
22552 check_dsp(ctx);
22553 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22554 break;
22555 case OPC_ADDU_QB:
22556 check_dsp(ctx);
22557 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22558 break;
22559 case OPC_ADDU_S_QB:
22560 check_dsp(ctx);
22561 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22562 break;
22563 case OPC_ADDU_PH:
22564 check_dsp_r2(ctx);
22565 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22566 break;
22567 case OPC_ADDU_S_PH:
22568 check_dsp_r2(ctx);
22569 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22570 break;
22571 case OPC_SUBQ_PH:
22572 check_dsp(ctx);
22573 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22574 break;
22575 case OPC_SUBQ_S_PH:
22576 check_dsp(ctx);
22577 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22578 break;
22579 case OPC_SUBQ_S_W:
22580 check_dsp(ctx);
22581 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22582 break;
22583 case OPC_SUBU_QB:
22584 check_dsp(ctx);
22585 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22586 break;
22587 case OPC_SUBU_S_QB:
22588 check_dsp(ctx);
22589 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22590 break;
22591 case OPC_SUBU_PH:
22592 check_dsp_r2(ctx);
22593 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22594 break;
22595 case OPC_SUBU_S_PH:
22596 check_dsp_r2(ctx);
22597 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22598 break;
22599 case OPC_ADDSC:
22600 check_dsp(ctx);
22601 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22602 break;
22603 case OPC_ADDWC:
22604 check_dsp(ctx);
22605 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22606 break;
22607 case OPC_MODSUB:
22608 check_dsp(ctx);
22609 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22610 break;
22611 case OPC_RADDU_W_QB:
22612 check_dsp(ctx);
22613 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22614 break;
22616 break;
22617 case OPC_CMPU_EQ_QB_DSP:
22618 switch (op2) {
22619 case OPC_PRECR_QB_PH:
22620 check_dsp_r2(ctx);
22621 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22622 break;
22623 case OPC_PRECRQ_QB_PH:
22624 check_dsp(ctx);
22625 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22626 break;
22627 case OPC_PRECR_SRA_PH_W:
22628 check_dsp_r2(ctx);
22630 TCGv_i32 sa_t = tcg_const_i32(v2);
22631 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22632 cpu_gpr[ret]);
22633 tcg_temp_free_i32(sa_t);
22634 break;
22636 case OPC_PRECR_SRA_R_PH_W:
22637 check_dsp_r2(ctx);
22639 TCGv_i32 sa_t = tcg_const_i32(v2);
22640 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22641 cpu_gpr[ret]);
22642 tcg_temp_free_i32(sa_t);
22643 break;
22645 case OPC_PRECRQ_PH_W:
22646 check_dsp(ctx);
22647 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22648 break;
22649 case OPC_PRECRQ_RS_PH_W:
22650 check_dsp(ctx);
22651 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22652 break;
22653 case OPC_PRECRQU_S_QB_PH:
22654 check_dsp(ctx);
22655 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22656 break;
22658 break;
22659 #ifdef TARGET_MIPS64
22660 case OPC_ABSQ_S_QH_DSP:
22661 switch (op2) {
22662 case OPC_PRECEQ_L_PWL:
22663 check_dsp(ctx);
22664 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22665 break;
22666 case OPC_PRECEQ_L_PWR:
22667 check_dsp(ctx);
22668 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22669 break;
22670 case OPC_PRECEQ_PW_QHL:
22671 check_dsp(ctx);
22672 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22673 break;
22674 case OPC_PRECEQ_PW_QHR:
22675 check_dsp(ctx);
22676 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22677 break;
22678 case OPC_PRECEQ_PW_QHLA:
22679 check_dsp(ctx);
22680 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22681 break;
22682 case OPC_PRECEQ_PW_QHRA:
22683 check_dsp(ctx);
22684 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22685 break;
22686 case OPC_PRECEQU_QH_OBL:
22687 check_dsp(ctx);
22688 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22689 break;
22690 case OPC_PRECEQU_QH_OBR:
22691 check_dsp(ctx);
22692 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22693 break;
22694 case OPC_PRECEQU_QH_OBLA:
22695 check_dsp(ctx);
22696 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22697 break;
22698 case OPC_PRECEQU_QH_OBRA:
22699 check_dsp(ctx);
22700 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22701 break;
22702 case OPC_PRECEU_QH_OBL:
22703 check_dsp(ctx);
22704 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22705 break;
22706 case OPC_PRECEU_QH_OBR:
22707 check_dsp(ctx);
22708 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22709 break;
22710 case OPC_PRECEU_QH_OBLA:
22711 check_dsp(ctx);
22712 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22713 break;
22714 case OPC_PRECEU_QH_OBRA:
22715 check_dsp(ctx);
22716 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22717 break;
22718 case OPC_ABSQ_S_OB:
22719 check_dsp_r2(ctx);
22720 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22721 break;
22722 case OPC_ABSQ_S_PW:
22723 check_dsp(ctx);
22724 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22725 break;
22726 case OPC_ABSQ_S_QH:
22727 check_dsp(ctx);
22728 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22729 break;
22731 break;
22732 case OPC_ADDU_OB_DSP:
22733 switch (op2) {
22734 case OPC_RADDU_L_OB:
22735 check_dsp(ctx);
22736 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22737 break;
22738 case OPC_SUBQ_PW:
22739 check_dsp(ctx);
22740 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22741 break;
22742 case OPC_SUBQ_S_PW:
22743 check_dsp(ctx);
22744 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22745 break;
22746 case OPC_SUBQ_QH:
22747 check_dsp(ctx);
22748 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22749 break;
22750 case OPC_SUBQ_S_QH:
22751 check_dsp(ctx);
22752 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22753 break;
22754 case OPC_SUBU_OB:
22755 check_dsp(ctx);
22756 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22757 break;
22758 case OPC_SUBU_S_OB:
22759 check_dsp(ctx);
22760 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22761 break;
22762 case OPC_SUBU_QH:
22763 check_dsp_r2(ctx);
22764 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_SUBU_S_QH:
22767 check_dsp_r2(ctx);
22768 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22769 break;
22770 case OPC_SUBUH_OB:
22771 check_dsp_r2(ctx);
22772 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22773 break;
22774 case OPC_SUBUH_R_OB:
22775 check_dsp_r2(ctx);
22776 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22777 break;
22778 case OPC_ADDQ_PW:
22779 check_dsp(ctx);
22780 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_ADDQ_S_PW:
22783 check_dsp(ctx);
22784 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_ADDQ_QH:
22787 check_dsp(ctx);
22788 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_ADDQ_S_QH:
22791 check_dsp(ctx);
22792 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_ADDU_OB:
22795 check_dsp(ctx);
22796 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_ADDU_S_OB:
22799 check_dsp(ctx);
22800 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_ADDU_QH:
22803 check_dsp_r2(ctx);
22804 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_ADDU_S_QH:
22807 check_dsp_r2(ctx);
22808 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_ADDUH_OB:
22811 check_dsp_r2(ctx);
22812 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22813 break;
22814 case OPC_ADDUH_R_OB:
22815 check_dsp_r2(ctx);
22816 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22817 break;
22819 break;
22820 case OPC_CMPU_EQ_OB_DSP:
22821 switch (op2) {
22822 case OPC_PRECR_OB_QH:
22823 check_dsp_r2(ctx);
22824 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22825 break;
22826 case OPC_PRECR_SRA_QH_PW:
22827 check_dsp_r2(ctx);
22829 TCGv_i32 ret_t = tcg_const_i32(ret);
22830 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22831 tcg_temp_free_i32(ret_t);
22832 break;
22834 case OPC_PRECR_SRA_R_QH_PW:
22835 check_dsp_r2(ctx);
22837 TCGv_i32 sa_v = tcg_const_i32(ret);
22838 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22839 tcg_temp_free_i32(sa_v);
22840 break;
22842 case OPC_PRECRQ_OB_QH:
22843 check_dsp(ctx);
22844 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22845 break;
22846 case OPC_PRECRQ_PW_L:
22847 check_dsp(ctx);
22848 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22849 break;
22850 case OPC_PRECRQ_QH_PW:
22851 check_dsp(ctx);
22852 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22853 break;
22854 case OPC_PRECRQ_RS_QH_PW:
22855 check_dsp(ctx);
22856 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22857 break;
22858 case OPC_PRECRQU_S_OB_QH:
22859 check_dsp(ctx);
22860 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22861 break;
22863 break;
22864 #endif
22867 tcg_temp_free(v1_t);
22868 tcg_temp_free(v2_t);
22871 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22872 int ret, int v1, int v2)
22874 uint32_t op2;
22875 TCGv t0;
22876 TCGv v1_t;
22877 TCGv v2_t;
22879 if (ret == 0) {
22880 /* Treat as NOP. */
22881 return;
22884 t0 = tcg_temp_new();
22885 v1_t = tcg_temp_new();
22886 v2_t = tcg_temp_new();
22888 tcg_gen_movi_tl(t0, v1);
22889 gen_load_gpr(v1_t, v1);
22890 gen_load_gpr(v2_t, v2);
22892 switch (opc) {
22893 case OPC_SHLL_QB_DSP:
22895 op2 = MASK_SHLL_QB(ctx->opcode);
22896 switch (op2) {
22897 case OPC_SHLL_QB:
22898 check_dsp(ctx);
22899 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22900 break;
22901 case OPC_SHLLV_QB:
22902 check_dsp(ctx);
22903 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22904 break;
22905 case OPC_SHLL_PH:
22906 check_dsp(ctx);
22907 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22908 break;
22909 case OPC_SHLLV_PH:
22910 check_dsp(ctx);
22911 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22912 break;
22913 case OPC_SHLL_S_PH:
22914 check_dsp(ctx);
22915 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22916 break;
22917 case OPC_SHLLV_S_PH:
22918 check_dsp(ctx);
22919 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22920 break;
22921 case OPC_SHLL_S_W:
22922 check_dsp(ctx);
22923 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22924 break;
22925 case OPC_SHLLV_S_W:
22926 check_dsp(ctx);
22927 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22928 break;
22929 case OPC_SHRL_QB:
22930 check_dsp(ctx);
22931 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22932 break;
22933 case OPC_SHRLV_QB:
22934 check_dsp(ctx);
22935 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22936 break;
22937 case OPC_SHRL_PH:
22938 check_dsp_r2(ctx);
22939 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22940 break;
22941 case OPC_SHRLV_PH:
22942 check_dsp_r2(ctx);
22943 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22944 break;
22945 case OPC_SHRA_QB:
22946 check_dsp_r2(ctx);
22947 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22948 break;
22949 case OPC_SHRA_R_QB:
22950 check_dsp_r2(ctx);
22951 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22952 break;
22953 case OPC_SHRAV_QB:
22954 check_dsp_r2(ctx);
22955 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22956 break;
22957 case OPC_SHRAV_R_QB:
22958 check_dsp_r2(ctx);
22959 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22960 break;
22961 case OPC_SHRA_PH:
22962 check_dsp(ctx);
22963 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22964 break;
22965 case OPC_SHRA_R_PH:
22966 check_dsp(ctx);
22967 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22968 break;
22969 case OPC_SHRAV_PH:
22970 check_dsp(ctx);
22971 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22972 break;
22973 case OPC_SHRAV_R_PH:
22974 check_dsp(ctx);
22975 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22976 break;
22977 case OPC_SHRA_R_W:
22978 check_dsp(ctx);
22979 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22980 break;
22981 case OPC_SHRAV_R_W:
22982 check_dsp(ctx);
22983 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22984 break;
22985 default: /* Invalid */
22986 MIPS_INVAL("MASK SHLL.QB");
22987 generate_exception_end(ctx, EXCP_RI);
22988 break;
22990 break;
22992 #ifdef TARGET_MIPS64
22993 case OPC_SHLL_OB_DSP:
22994 op2 = MASK_SHLL_OB(ctx->opcode);
22995 switch (op2) {
22996 case OPC_SHLL_PW:
22997 check_dsp(ctx);
22998 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22999 break;
23000 case OPC_SHLLV_PW:
23001 check_dsp(ctx);
23002 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23003 break;
23004 case OPC_SHLL_S_PW:
23005 check_dsp(ctx);
23006 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23007 break;
23008 case OPC_SHLLV_S_PW:
23009 check_dsp(ctx);
23010 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23011 break;
23012 case OPC_SHLL_OB:
23013 check_dsp(ctx);
23014 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23015 break;
23016 case OPC_SHLLV_OB:
23017 check_dsp(ctx);
23018 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23019 break;
23020 case OPC_SHLL_QH:
23021 check_dsp(ctx);
23022 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23023 break;
23024 case OPC_SHLLV_QH:
23025 check_dsp(ctx);
23026 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23027 break;
23028 case OPC_SHLL_S_QH:
23029 check_dsp(ctx);
23030 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23031 break;
23032 case OPC_SHLLV_S_QH:
23033 check_dsp(ctx);
23034 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23035 break;
23036 case OPC_SHRA_OB:
23037 check_dsp_r2(ctx);
23038 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23039 break;
23040 case OPC_SHRAV_OB:
23041 check_dsp_r2(ctx);
23042 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23043 break;
23044 case OPC_SHRA_R_OB:
23045 check_dsp_r2(ctx);
23046 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23047 break;
23048 case OPC_SHRAV_R_OB:
23049 check_dsp_r2(ctx);
23050 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23051 break;
23052 case OPC_SHRA_PW:
23053 check_dsp(ctx);
23054 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23055 break;
23056 case OPC_SHRAV_PW:
23057 check_dsp(ctx);
23058 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23059 break;
23060 case OPC_SHRA_R_PW:
23061 check_dsp(ctx);
23062 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23063 break;
23064 case OPC_SHRAV_R_PW:
23065 check_dsp(ctx);
23066 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23067 break;
23068 case OPC_SHRA_QH:
23069 check_dsp(ctx);
23070 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23071 break;
23072 case OPC_SHRAV_QH:
23073 check_dsp(ctx);
23074 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23075 break;
23076 case OPC_SHRA_R_QH:
23077 check_dsp(ctx);
23078 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23079 break;
23080 case OPC_SHRAV_R_QH:
23081 check_dsp(ctx);
23082 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23083 break;
23084 case OPC_SHRL_OB:
23085 check_dsp(ctx);
23086 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23087 break;
23088 case OPC_SHRLV_OB:
23089 check_dsp(ctx);
23090 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23091 break;
23092 case OPC_SHRL_QH:
23093 check_dsp_r2(ctx);
23094 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23095 break;
23096 case OPC_SHRLV_QH:
23097 check_dsp_r2(ctx);
23098 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23099 break;
23100 default: /* Invalid */
23101 MIPS_INVAL("MASK SHLL.OB");
23102 generate_exception_end(ctx, EXCP_RI);
23103 break;
23105 break;
23106 #endif
23109 tcg_temp_free(t0);
23110 tcg_temp_free(v1_t);
23111 tcg_temp_free(v2_t);
23114 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23115 int ret, int v1, int v2, int check_ret)
23117 TCGv_i32 t0;
23118 TCGv v1_t;
23119 TCGv v2_t;
23121 if ((ret == 0) && (check_ret == 1)) {
23122 /* Treat as NOP. */
23123 return;
23126 t0 = tcg_temp_new_i32();
23127 v1_t = tcg_temp_new();
23128 v2_t = tcg_temp_new();
23130 tcg_gen_movi_i32(t0, ret);
23131 gen_load_gpr(v1_t, v1);
23132 gen_load_gpr(v2_t, v2);
23134 switch (op1) {
23136 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23137 * the same mask and op1.
23139 case OPC_MULT_G_2E:
23140 check_dsp_r2(ctx);
23141 switch (op2) {
23142 case OPC_MUL_PH:
23143 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23144 break;
23145 case OPC_MUL_S_PH:
23146 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23147 break;
23148 case OPC_MULQ_S_W:
23149 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23150 break;
23151 case OPC_MULQ_RS_W:
23152 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23153 break;
23155 break;
23156 case OPC_DPA_W_PH_DSP:
23157 switch (op2) {
23158 case OPC_DPAU_H_QBL:
23159 check_dsp(ctx);
23160 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23161 break;
23162 case OPC_DPAU_H_QBR:
23163 check_dsp(ctx);
23164 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23165 break;
23166 case OPC_DPSU_H_QBL:
23167 check_dsp(ctx);
23168 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23169 break;
23170 case OPC_DPSU_H_QBR:
23171 check_dsp(ctx);
23172 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23173 break;
23174 case OPC_DPA_W_PH:
23175 check_dsp_r2(ctx);
23176 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23177 break;
23178 case OPC_DPAX_W_PH:
23179 check_dsp_r2(ctx);
23180 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23181 break;
23182 case OPC_DPAQ_S_W_PH:
23183 check_dsp(ctx);
23184 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23185 break;
23186 case OPC_DPAQX_S_W_PH:
23187 check_dsp_r2(ctx);
23188 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23189 break;
23190 case OPC_DPAQX_SA_W_PH:
23191 check_dsp_r2(ctx);
23192 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23193 break;
23194 case OPC_DPS_W_PH:
23195 check_dsp_r2(ctx);
23196 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23197 break;
23198 case OPC_DPSX_W_PH:
23199 check_dsp_r2(ctx);
23200 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23201 break;
23202 case OPC_DPSQ_S_W_PH:
23203 check_dsp(ctx);
23204 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23205 break;
23206 case OPC_DPSQX_S_W_PH:
23207 check_dsp_r2(ctx);
23208 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23209 break;
23210 case OPC_DPSQX_SA_W_PH:
23211 check_dsp_r2(ctx);
23212 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23213 break;
23214 case OPC_MULSAQ_S_W_PH:
23215 check_dsp(ctx);
23216 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23217 break;
23218 case OPC_DPAQ_SA_L_W:
23219 check_dsp(ctx);
23220 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23221 break;
23222 case OPC_DPSQ_SA_L_W:
23223 check_dsp(ctx);
23224 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23225 break;
23226 case OPC_MAQ_S_W_PHL:
23227 check_dsp(ctx);
23228 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23229 break;
23230 case OPC_MAQ_S_W_PHR:
23231 check_dsp(ctx);
23232 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23233 break;
23234 case OPC_MAQ_SA_W_PHL:
23235 check_dsp(ctx);
23236 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23237 break;
23238 case OPC_MAQ_SA_W_PHR:
23239 check_dsp(ctx);
23240 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23241 break;
23242 case OPC_MULSA_W_PH:
23243 check_dsp_r2(ctx);
23244 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23245 break;
23247 break;
23248 #ifdef TARGET_MIPS64
23249 case OPC_DPAQ_W_QH_DSP:
23251 int ac = ret & 0x03;
23252 tcg_gen_movi_i32(t0, ac);
23254 switch (op2) {
23255 case OPC_DMADD:
23256 check_dsp(ctx);
23257 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23258 break;
23259 case OPC_DMADDU:
23260 check_dsp(ctx);
23261 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23262 break;
23263 case OPC_DMSUB:
23264 check_dsp(ctx);
23265 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23266 break;
23267 case OPC_DMSUBU:
23268 check_dsp(ctx);
23269 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23270 break;
23271 case OPC_DPA_W_QH:
23272 check_dsp_r2(ctx);
23273 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23274 break;
23275 case OPC_DPAQ_S_W_QH:
23276 check_dsp(ctx);
23277 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23278 break;
23279 case OPC_DPAQ_SA_L_PW:
23280 check_dsp(ctx);
23281 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23282 break;
23283 case OPC_DPAU_H_OBL:
23284 check_dsp(ctx);
23285 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23286 break;
23287 case OPC_DPAU_H_OBR:
23288 check_dsp(ctx);
23289 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23290 break;
23291 case OPC_DPS_W_QH:
23292 check_dsp_r2(ctx);
23293 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23294 break;
23295 case OPC_DPSQ_S_W_QH:
23296 check_dsp(ctx);
23297 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23298 break;
23299 case OPC_DPSQ_SA_L_PW:
23300 check_dsp(ctx);
23301 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23302 break;
23303 case OPC_DPSU_H_OBL:
23304 check_dsp(ctx);
23305 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23306 break;
23307 case OPC_DPSU_H_OBR:
23308 check_dsp(ctx);
23309 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23310 break;
23311 case OPC_MAQ_S_L_PWL:
23312 check_dsp(ctx);
23313 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23314 break;
23315 case OPC_MAQ_S_L_PWR:
23316 check_dsp(ctx);
23317 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23318 break;
23319 case OPC_MAQ_S_W_QHLL:
23320 check_dsp(ctx);
23321 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23322 break;
23323 case OPC_MAQ_SA_W_QHLL:
23324 check_dsp(ctx);
23325 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23326 break;
23327 case OPC_MAQ_S_W_QHLR:
23328 check_dsp(ctx);
23329 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23330 break;
23331 case OPC_MAQ_SA_W_QHLR:
23332 check_dsp(ctx);
23333 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23334 break;
23335 case OPC_MAQ_S_W_QHRL:
23336 check_dsp(ctx);
23337 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23338 break;
23339 case OPC_MAQ_SA_W_QHRL:
23340 check_dsp(ctx);
23341 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23342 break;
23343 case OPC_MAQ_S_W_QHRR:
23344 check_dsp(ctx);
23345 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23346 break;
23347 case OPC_MAQ_SA_W_QHRR:
23348 check_dsp(ctx);
23349 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23350 break;
23351 case OPC_MULSAQ_S_L_PW:
23352 check_dsp(ctx);
23353 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23354 break;
23355 case OPC_MULSAQ_S_W_QH:
23356 check_dsp(ctx);
23357 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23358 break;
23361 break;
23362 #endif
23363 case OPC_ADDU_QB_DSP:
23364 switch (op2) {
23365 case OPC_MULEU_S_PH_QBL:
23366 check_dsp(ctx);
23367 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23368 break;
23369 case OPC_MULEU_S_PH_QBR:
23370 check_dsp(ctx);
23371 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23372 break;
23373 case OPC_MULQ_RS_PH:
23374 check_dsp(ctx);
23375 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23376 break;
23377 case OPC_MULEQ_S_W_PHL:
23378 check_dsp(ctx);
23379 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23380 break;
23381 case OPC_MULEQ_S_W_PHR:
23382 check_dsp(ctx);
23383 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23384 break;
23385 case OPC_MULQ_S_PH:
23386 check_dsp_r2(ctx);
23387 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23388 break;
23390 break;
23391 #ifdef TARGET_MIPS64
23392 case OPC_ADDU_OB_DSP:
23393 switch (op2) {
23394 case OPC_MULEQ_S_PW_QHL:
23395 check_dsp(ctx);
23396 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23397 break;
23398 case OPC_MULEQ_S_PW_QHR:
23399 check_dsp(ctx);
23400 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23401 break;
23402 case OPC_MULEU_S_QH_OBL:
23403 check_dsp(ctx);
23404 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23405 break;
23406 case OPC_MULEU_S_QH_OBR:
23407 check_dsp(ctx);
23408 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23409 break;
23410 case OPC_MULQ_RS_QH:
23411 check_dsp(ctx);
23412 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23413 break;
23415 break;
23416 #endif
23419 tcg_temp_free_i32(t0);
23420 tcg_temp_free(v1_t);
23421 tcg_temp_free(v2_t);
23424 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23425 int ret, int val)
23427 int16_t imm;
23428 TCGv t0;
23429 TCGv val_t;
23431 if (ret == 0) {
23432 /* Treat as NOP. */
23433 return;
23436 t0 = tcg_temp_new();
23437 val_t = tcg_temp_new();
23438 gen_load_gpr(val_t, val);
23440 switch (op1) {
23441 case OPC_ABSQ_S_PH_DSP:
23442 switch (op2) {
23443 case OPC_BITREV:
23444 check_dsp(ctx);
23445 gen_helper_bitrev(cpu_gpr[ret], val_t);
23446 break;
23447 case OPC_REPL_QB:
23448 check_dsp(ctx);
23450 target_long result;
23451 imm = (ctx->opcode >> 16) & 0xFF;
23452 result = (uint32_t)imm << 24 |
23453 (uint32_t)imm << 16 |
23454 (uint32_t)imm << 8 |
23455 (uint32_t)imm;
23456 result = (int32_t)result;
23457 tcg_gen_movi_tl(cpu_gpr[ret], result);
23459 break;
23460 case OPC_REPLV_QB:
23461 check_dsp(ctx);
23462 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23463 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23464 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23465 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23466 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23467 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23468 break;
23469 case OPC_REPL_PH:
23470 check_dsp(ctx);
23472 imm = (ctx->opcode >> 16) & 0x03FF;
23473 imm = (int16_t)(imm << 6) >> 6;
23474 tcg_gen_movi_tl(cpu_gpr[ret], \
23475 (target_long)((int32_t)imm << 16 | \
23476 (uint16_t)imm));
23478 break;
23479 case OPC_REPLV_PH:
23480 check_dsp(ctx);
23481 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23482 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23483 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23484 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23485 break;
23487 break;
23488 #ifdef TARGET_MIPS64
23489 case OPC_ABSQ_S_QH_DSP:
23490 switch (op2) {
23491 case OPC_REPL_OB:
23492 check_dsp(ctx);
23494 target_long temp;
23496 imm = (ctx->opcode >> 16) & 0xFF;
23497 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23498 temp = (temp << 16) | temp;
23499 temp = (temp << 32) | temp;
23500 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23501 break;
23503 case OPC_REPL_PW:
23504 check_dsp(ctx);
23506 target_long temp;
23508 imm = (ctx->opcode >> 16) & 0x03FF;
23509 imm = (int16_t)(imm << 6) >> 6;
23510 temp = ((target_long)imm << 32) \
23511 | ((target_long)imm & 0xFFFFFFFF);
23512 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23513 break;
23515 case OPC_REPL_QH:
23516 check_dsp(ctx);
23518 target_long temp;
23520 imm = (ctx->opcode >> 16) & 0x03FF;
23521 imm = (int16_t)(imm << 6) >> 6;
23523 temp = ((uint64_t)(uint16_t)imm << 48) |
23524 ((uint64_t)(uint16_t)imm << 32) |
23525 ((uint64_t)(uint16_t)imm << 16) |
23526 (uint64_t)(uint16_t)imm;
23527 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23528 break;
23530 case OPC_REPLV_OB:
23531 check_dsp(ctx);
23532 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23533 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23534 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23535 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23536 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23537 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23538 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23539 break;
23540 case OPC_REPLV_PW:
23541 check_dsp(ctx);
23542 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23543 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23544 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23545 break;
23546 case OPC_REPLV_QH:
23547 check_dsp(ctx);
23548 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23549 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23550 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23551 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23552 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23553 break;
23555 break;
23556 #endif
23558 tcg_temp_free(t0);
23559 tcg_temp_free(val_t);
23562 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23563 uint32_t op1, uint32_t op2,
23564 int ret, int v1, int v2, int check_ret)
23566 TCGv t1;
23567 TCGv v1_t;
23568 TCGv v2_t;
23570 if ((ret == 0) && (check_ret == 1)) {
23571 /* Treat as NOP. */
23572 return;
23575 t1 = tcg_temp_new();
23576 v1_t = tcg_temp_new();
23577 v2_t = tcg_temp_new();
23579 gen_load_gpr(v1_t, v1);
23580 gen_load_gpr(v2_t, v2);
23582 switch (op1) {
23583 case OPC_CMPU_EQ_QB_DSP:
23584 switch (op2) {
23585 case OPC_CMPU_EQ_QB:
23586 check_dsp(ctx);
23587 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23588 break;
23589 case OPC_CMPU_LT_QB:
23590 check_dsp(ctx);
23591 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23592 break;
23593 case OPC_CMPU_LE_QB:
23594 check_dsp(ctx);
23595 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23596 break;
23597 case OPC_CMPGU_EQ_QB:
23598 check_dsp(ctx);
23599 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23600 break;
23601 case OPC_CMPGU_LT_QB:
23602 check_dsp(ctx);
23603 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23604 break;
23605 case OPC_CMPGU_LE_QB:
23606 check_dsp(ctx);
23607 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23608 break;
23609 case OPC_CMPGDU_EQ_QB:
23610 check_dsp_r2(ctx);
23611 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23612 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23613 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23614 tcg_gen_shli_tl(t1, t1, 24);
23615 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23616 break;
23617 case OPC_CMPGDU_LT_QB:
23618 check_dsp_r2(ctx);
23619 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23620 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23621 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23622 tcg_gen_shli_tl(t1, t1, 24);
23623 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23624 break;
23625 case OPC_CMPGDU_LE_QB:
23626 check_dsp_r2(ctx);
23627 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23628 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23629 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23630 tcg_gen_shli_tl(t1, t1, 24);
23631 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23632 break;
23633 case OPC_CMP_EQ_PH:
23634 check_dsp(ctx);
23635 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23636 break;
23637 case OPC_CMP_LT_PH:
23638 check_dsp(ctx);
23639 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23640 break;
23641 case OPC_CMP_LE_PH:
23642 check_dsp(ctx);
23643 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23644 break;
23645 case OPC_PICK_QB:
23646 check_dsp(ctx);
23647 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23648 break;
23649 case OPC_PICK_PH:
23650 check_dsp(ctx);
23651 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23652 break;
23653 case OPC_PACKRL_PH:
23654 check_dsp(ctx);
23655 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23656 break;
23658 break;
23659 #ifdef TARGET_MIPS64
23660 case OPC_CMPU_EQ_OB_DSP:
23661 switch (op2) {
23662 case OPC_CMP_EQ_PW:
23663 check_dsp(ctx);
23664 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23665 break;
23666 case OPC_CMP_LT_PW:
23667 check_dsp(ctx);
23668 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23669 break;
23670 case OPC_CMP_LE_PW:
23671 check_dsp(ctx);
23672 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23673 break;
23674 case OPC_CMP_EQ_QH:
23675 check_dsp(ctx);
23676 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23677 break;
23678 case OPC_CMP_LT_QH:
23679 check_dsp(ctx);
23680 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23681 break;
23682 case OPC_CMP_LE_QH:
23683 check_dsp(ctx);
23684 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23685 break;
23686 case OPC_CMPGDU_EQ_OB:
23687 check_dsp_r2(ctx);
23688 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23689 break;
23690 case OPC_CMPGDU_LT_OB:
23691 check_dsp_r2(ctx);
23692 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23693 break;
23694 case OPC_CMPGDU_LE_OB:
23695 check_dsp_r2(ctx);
23696 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23697 break;
23698 case OPC_CMPGU_EQ_OB:
23699 check_dsp(ctx);
23700 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23701 break;
23702 case OPC_CMPGU_LT_OB:
23703 check_dsp(ctx);
23704 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23705 break;
23706 case OPC_CMPGU_LE_OB:
23707 check_dsp(ctx);
23708 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23709 break;
23710 case OPC_CMPU_EQ_OB:
23711 check_dsp(ctx);
23712 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23713 break;
23714 case OPC_CMPU_LT_OB:
23715 check_dsp(ctx);
23716 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23717 break;
23718 case OPC_CMPU_LE_OB:
23719 check_dsp(ctx);
23720 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23721 break;
23722 case OPC_PACKRL_PW:
23723 check_dsp(ctx);
23724 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23725 break;
23726 case OPC_PICK_OB:
23727 check_dsp(ctx);
23728 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23729 break;
23730 case OPC_PICK_PW:
23731 check_dsp(ctx);
23732 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23733 break;
23734 case OPC_PICK_QH:
23735 check_dsp(ctx);
23736 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23737 break;
23739 break;
23740 #endif
23743 tcg_temp_free(t1);
23744 tcg_temp_free(v1_t);
23745 tcg_temp_free(v2_t);
23748 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23749 uint32_t op1, int rt, int rs, int sa)
23751 TCGv t0;
23753 check_dsp_r2(ctx);
23755 if (rt == 0) {
23756 /* Treat as NOP. */
23757 return;
23760 t0 = tcg_temp_new();
23761 gen_load_gpr(t0, rs);
23763 switch (op1) {
23764 case OPC_APPEND_DSP:
23765 switch (MASK_APPEND(ctx->opcode)) {
23766 case OPC_APPEND:
23767 if (sa != 0) {
23768 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23770 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23771 break;
23772 case OPC_PREPEND:
23773 if (sa != 0) {
23774 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23775 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23776 tcg_gen_shli_tl(t0, t0, 32 - sa);
23777 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23779 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23780 break;
23781 case OPC_BALIGN:
23782 sa &= 3;
23783 if (sa != 0 && sa != 2) {
23784 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23785 tcg_gen_ext32u_tl(t0, t0);
23786 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23787 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23789 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23790 break;
23791 default: /* Invalid */
23792 MIPS_INVAL("MASK APPEND");
23793 generate_exception_end(ctx, EXCP_RI);
23794 break;
23796 break;
23797 #ifdef TARGET_MIPS64
23798 case OPC_DAPPEND_DSP:
23799 switch (MASK_DAPPEND(ctx->opcode)) {
23800 case OPC_DAPPEND:
23801 if (sa != 0) {
23802 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23804 break;
23805 case OPC_PREPENDD:
23806 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23807 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23808 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23809 break;
23810 case OPC_PREPENDW:
23811 if (sa != 0) {
23812 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23813 tcg_gen_shli_tl(t0, t0, 64 - sa);
23814 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23816 break;
23817 case OPC_DBALIGN:
23818 sa &= 7;
23819 if (sa != 0 && sa != 2 && sa != 4) {
23820 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23821 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23822 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23824 break;
23825 default: /* Invalid */
23826 MIPS_INVAL("MASK DAPPEND");
23827 generate_exception_end(ctx, EXCP_RI);
23828 break;
23830 break;
23831 #endif
23833 tcg_temp_free(t0);
23836 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23837 int ret, int v1, int v2, int check_ret)
23840 TCGv t0;
23841 TCGv t1;
23842 TCGv v1_t;
23843 TCGv v2_t;
23844 int16_t imm;
23846 if ((ret == 0) && (check_ret == 1)) {
23847 /* Treat as NOP. */
23848 return;
23851 t0 = tcg_temp_new();
23852 t1 = tcg_temp_new();
23853 v1_t = tcg_temp_new();
23854 v2_t = tcg_temp_new();
23856 gen_load_gpr(v1_t, v1);
23857 gen_load_gpr(v2_t, v2);
23859 switch (op1) {
23860 case OPC_EXTR_W_DSP:
23861 check_dsp(ctx);
23862 switch (op2) {
23863 case OPC_EXTR_W:
23864 tcg_gen_movi_tl(t0, v2);
23865 tcg_gen_movi_tl(t1, v1);
23866 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23867 break;
23868 case OPC_EXTR_R_W:
23869 tcg_gen_movi_tl(t0, v2);
23870 tcg_gen_movi_tl(t1, v1);
23871 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23872 break;
23873 case OPC_EXTR_RS_W:
23874 tcg_gen_movi_tl(t0, v2);
23875 tcg_gen_movi_tl(t1, v1);
23876 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23877 break;
23878 case OPC_EXTR_S_H:
23879 tcg_gen_movi_tl(t0, v2);
23880 tcg_gen_movi_tl(t1, v1);
23881 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23882 break;
23883 case OPC_EXTRV_S_H:
23884 tcg_gen_movi_tl(t0, v2);
23885 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23886 break;
23887 case OPC_EXTRV_W:
23888 tcg_gen_movi_tl(t0, v2);
23889 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23890 break;
23891 case OPC_EXTRV_R_W:
23892 tcg_gen_movi_tl(t0, v2);
23893 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23894 break;
23895 case OPC_EXTRV_RS_W:
23896 tcg_gen_movi_tl(t0, v2);
23897 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23898 break;
23899 case OPC_EXTP:
23900 tcg_gen_movi_tl(t0, v2);
23901 tcg_gen_movi_tl(t1, v1);
23902 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23903 break;
23904 case OPC_EXTPV:
23905 tcg_gen_movi_tl(t0, v2);
23906 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23907 break;
23908 case OPC_EXTPDP:
23909 tcg_gen_movi_tl(t0, v2);
23910 tcg_gen_movi_tl(t1, v1);
23911 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23912 break;
23913 case OPC_EXTPDPV:
23914 tcg_gen_movi_tl(t0, v2);
23915 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23916 break;
23917 case OPC_SHILO:
23918 imm = (ctx->opcode >> 20) & 0x3F;
23919 tcg_gen_movi_tl(t0, ret);
23920 tcg_gen_movi_tl(t1, imm);
23921 gen_helper_shilo(t0, t1, cpu_env);
23922 break;
23923 case OPC_SHILOV:
23924 tcg_gen_movi_tl(t0, ret);
23925 gen_helper_shilo(t0, v1_t, cpu_env);
23926 break;
23927 case OPC_MTHLIP:
23928 tcg_gen_movi_tl(t0, ret);
23929 gen_helper_mthlip(t0, v1_t, cpu_env);
23930 break;
23931 case OPC_WRDSP:
23932 imm = (ctx->opcode >> 11) & 0x3FF;
23933 tcg_gen_movi_tl(t0, imm);
23934 gen_helper_wrdsp(v1_t, t0, cpu_env);
23935 break;
23936 case OPC_RDDSP:
23937 imm = (ctx->opcode >> 16) & 0x03FF;
23938 tcg_gen_movi_tl(t0, imm);
23939 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23940 break;
23942 break;
23943 #ifdef TARGET_MIPS64
23944 case OPC_DEXTR_W_DSP:
23945 check_dsp(ctx);
23946 switch (op2) {
23947 case OPC_DMTHLIP:
23948 tcg_gen_movi_tl(t0, ret);
23949 gen_helper_dmthlip(v1_t, t0, cpu_env);
23950 break;
23951 case OPC_DSHILO:
23953 int shift = (ctx->opcode >> 19) & 0x7F;
23954 int ac = (ctx->opcode >> 11) & 0x03;
23955 tcg_gen_movi_tl(t0, shift);
23956 tcg_gen_movi_tl(t1, ac);
23957 gen_helper_dshilo(t0, t1, cpu_env);
23958 break;
23960 case OPC_DSHILOV:
23962 int ac = (ctx->opcode >> 11) & 0x03;
23963 tcg_gen_movi_tl(t0, ac);
23964 gen_helper_dshilo(v1_t, t0, cpu_env);
23965 break;
23967 case OPC_DEXTP:
23968 tcg_gen_movi_tl(t0, v2);
23969 tcg_gen_movi_tl(t1, v1);
23971 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23972 break;
23973 case OPC_DEXTPV:
23974 tcg_gen_movi_tl(t0, v2);
23975 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23976 break;
23977 case OPC_DEXTPDP:
23978 tcg_gen_movi_tl(t0, v2);
23979 tcg_gen_movi_tl(t1, v1);
23980 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23981 break;
23982 case OPC_DEXTPDPV:
23983 tcg_gen_movi_tl(t0, v2);
23984 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23985 break;
23986 case OPC_DEXTR_L:
23987 tcg_gen_movi_tl(t0, v2);
23988 tcg_gen_movi_tl(t1, v1);
23989 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23990 break;
23991 case OPC_DEXTR_R_L:
23992 tcg_gen_movi_tl(t0, v2);
23993 tcg_gen_movi_tl(t1, v1);
23994 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23995 break;
23996 case OPC_DEXTR_RS_L:
23997 tcg_gen_movi_tl(t0, v2);
23998 tcg_gen_movi_tl(t1, v1);
23999 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24000 break;
24001 case OPC_DEXTR_W:
24002 tcg_gen_movi_tl(t0, v2);
24003 tcg_gen_movi_tl(t1, v1);
24004 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24005 break;
24006 case OPC_DEXTR_R_W:
24007 tcg_gen_movi_tl(t0, v2);
24008 tcg_gen_movi_tl(t1, v1);
24009 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24010 break;
24011 case OPC_DEXTR_RS_W:
24012 tcg_gen_movi_tl(t0, v2);
24013 tcg_gen_movi_tl(t1, v1);
24014 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24015 break;
24016 case OPC_DEXTR_S_H:
24017 tcg_gen_movi_tl(t0, v2);
24018 tcg_gen_movi_tl(t1, v1);
24019 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24020 break;
24021 case OPC_DEXTRV_S_H:
24022 tcg_gen_movi_tl(t0, v2);
24023 tcg_gen_movi_tl(t1, v1);
24024 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24025 break;
24026 case OPC_DEXTRV_L:
24027 tcg_gen_movi_tl(t0, v2);
24028 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24029 break;
24030 case OPC_DEXTRV_R_L:
24031 tcg_gen_movi_tl(t0, v2);
24032 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24033 break;
24034 case OPC_DEXTRV_RS_L:
24035 tcg_gen_movi_tl(t0, v2);
24036 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24037 break;
24038 case OPC_DEXTRV_W:
24039 tcg_gen_movi_tl(t0, v2);
24040 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24041 break;
24042 case OPC_DEXTRV_R_W:
24043 tcg_gen_movi_tl(t0, v2);
24044 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24045 break;
24046 case OPC_DEXTRV_RS_W:
24047 tcg_gen_movi_tl(t0, v2);
24048 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24049 break;
24051 break;
24052 #endif
24055 tcg_temp_free(t0);
24056 tcg_temp_free(t1);
24057 tcg_temp_free(v1_t);
24058 tcg_temp_free(v2_t);
24061 /* End MIPSDSP functions. */
24063 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24065 int rs, rt, rd, sa;
24066 uint32_t op1, op2;
24068 rs = (ctx->opcode >> 21) & 0x1f;
24069 rt = (ctx->opcode >> 16) & 0x1f;
24070 rd = (ctx->opcode >> 11) & 0x1f;
24071 sa = (ctx->opcode >> 6) & 0x1f;
24073 op1 = MASK_SPECIAL(ctx->opcode);
24074 switch (op1) {
24075 case OPC_LSA:
24076 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24077 break;
24078 case OPC_MULT:
24079 case OPC_MULTU:
24080 case OPC_DIV:
24081 case OPC_DIVU:
24082 op2 = MASK_R6_MULDIV(ctx->opcode);
24083 switch (op2) {
24084 case R6_OPC_MUL:
24085 case R6_OPC_MUH:
24086 case R6_OPC_MULU:
24087 case R6_OPC_MUHU:
24088 case R6_OPC_DIV:
24089 case R6_OPC_MOD:
24090 case R6_OPC_DIVU:
24091 case R6_OPC_MODU:
24092 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24093 break;
24094 default:
24095 MIPS_INVAL("special_r6 muldiv");
24096 generate_exception_end(ctx, EXCP_RI);
24097 break;
24099 break;
24100 case OPC_SELEQZ:
24101 case OPC_SELNEZ:
24102 gen_cond_move(ctx, op1, rd, rs, rt);
24103 break;
24104 case R6_OPC_CLO:
24105 case R6_OPC_CLZ:
24106 if (rt == 0 && sa == 1) {
24108 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24109 * We need additionally to check other fields.
24111 gen_cl(ctx, op1, rd, rs);
24112 } else {
24113 generate_exception_end(ctx, EXCP_RI);
24115 break;
24116 case R6_OPC_SDBBP:
24117 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24118 gen_helper_do_semihosting(cpu_env);
24119 } else {
24120 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24121 generate_exception_end(ctx, EXCP_RI);
24122 } else {
24123 generate_exception_end(ctx, EXCP_DBp);
24126 break;
24127 #if defined(TARGET_MIPS64)
24128 case OPC_DLSA:
24129 check_mips_64(ctx);
24130 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24131 break;
24132 case R6_OPC_DCLO:
24133 case R6_OPC_DCLZ:
24134 if (rt == 0 && sa == 1) {
24136 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24137 * We need additionally to check other fields.
24139 check_mips_64(ctx);
24140 gen_cl(ctx, op1, rd, rs);
24141 } else {
24142 generate_exception_end(ctx, EXCP_RI);
24144 break;
24145 case OPC_DMULT:
24146 case OPC_DMULTU:
24147 case OPC_DDIV:
24148 case OPC_DDIVU:
24150 op2 = MASK_R6_MULDIV(ctx->opcode);
24151 switch (op2) {
24152 case R6_OPC_DMUL:
24153 case R6_OPC_DMUH:
24154 case R6_OPC_DMULU:
24155 case R6_OPC_DMUHU:
24156 case R6_OPC_DDIV:
24157 case R6_OPC_DMOD:
24158 case R6_OPC_DDIVU:
24159 case R6_OPC_DMODU:
24160 check_mips_64(ctx);
24161 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24162 break;
24163 default:
24164 MIPS_INVAL("special_r6 muldiv");
24165 generate_exception_end(ctx, EXCP_RI);
24166 break;
24168 break;
24169 #endif
24170 default: /* Invalid */
24171 MIPS_INVAL("special_r6");
24172 generate_exception_end(ctx, EXCP_RI);
24173 break;
24177 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24179 int rs = extract32(ctx->opcode, 21, 5);
24180 int rt = extract32(ctx->opcode, 16, 5);
24181 int rd = extract32(ctx->opcode, 11, 5);
24182 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24184 switch (op1) {
24185 case OPC_MOVN: /* Conditional move */
24186 case OPC_MOVZ:
24187 gen_cond_move(ctx, op1, rd, rs, rt);
24188 break;
24189 case OPC_MFHI: /* Move from HI/LO */
24190 case OPC_MFLO:
24191 gen_HILO(ctx, op1, 0, rd);
24192 break;
24193 case OPC_MTHI:
24194 case OPC_MTLO: /* Move to HI/LO */
24195 gen_HILO(ctx, op1, 0, rs);
24196 break;
24197 case OPC_MULT:
24198 case OPC_MULTU:
24199 gen_mul_txx9(ctx, op1, rd, rs, rt);
24200 break;
24201 case OPC_DIV:
24202 case OPC_DIVU:
24203 gen_muldiv(ctx, op1, 0, rs, rt);
24204 break;
24205 #if defined(TARGET_MIPS64)
24206 case OPC_DMULT:
24207 case OPC_DMULTU:
24208 case OPC_DDIV:
24209 case OPC_DDIVU:
24210 check_insn_opc_user_only(ctx, INSN_R5900);
24211 gen_muldiv(ctx, op1, 0, rs, rt);
24212 break;
24213 #endif
24214 case OPC_JR:
24215 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24216 break;
24217 default: /* Invalid */
24218 MIPS_INVAL("special_tx79");
24219 generate_exception_end(ctx, EXCP_RI);
24220 break;
24224 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24226 int rs, rt, rd, sa;
24227 uint32_t op1;
24229 rs = (ctx->opcode >> 21) & 0x1f;
24230 rt = (ctx->opcode >> 16) & 0x1f;
24231 rd = (ctx->opcode >> 11) & 0x1f;
24232 sa = (ctx->opcode >> 6) & 0x1f;
24234 op1 = MASK_SPECIAL(ctx->opcode);
24235 switch (op1) {
24236 case OPC_MOVN: /* Conditional move */
24237 case OPC_MOVZ:
24238 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24239 INSN_LOONGSON2E | INSN_LOONGSON2F);
24240 gen_cond_move(ctx, op1, rd, rs, rt);
24241 break;
24242 case OPC_MFHI: /* Move from HI/LO */
24243 case OPC_MFLO:
24244 gen_HILO(ctx, op1, rs & 3, rd);
24245 break;
24246 case OPC_MTHI:
24247 case OPC_MTLO: /* Move to HI/LO */
24248 gen_HILO(ctx, op1, rd & 3, rs);
24249 break;
24250 case OPC_MOVCI:
24251 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24252 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24253 check_cp1_enabled(ctx);
24254 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24255 (ctx->opcode >> 16) & 1);
24256 } else {
24257 generate_exception_err(ctx, EXCP_CpU, 1);
24259 break;
24260 case OPC_MULT:
24261 case OPC_MULTU:
24262 if (sa) {
24263 check_insn(ctx, INSN_VR54XX);
24264 op1 = MASK_MUL_VR54XX(ctx->opcode);
24265 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24266 } else {
24267 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24269 break;
24270 case OPC_DIV:
24271 case OPC_DIVU:
24272 gen_muldiv(ctx, op1, 0, rs, rt);
24273 break;
24274 #if defined(TARGET_MIPS64)
24275 case OPC_DMULT:
24276 case OPC_DMULTU:
24277 case OPC_DDIV:
24278 case OPC_DDIVU:
24279 check_insn(ctx, ISA_MIPS3);
24280 check_mips_64(ctx);
24281 gen_muldiv(ctx, op1, 0, rs, rt);
24282 break;
24283 #endif
24284 case OPC_JR:
24285 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24286 break;
24287 case OPC_SPIM:
24288 #ifdef MIPS_STRICT_STANDARD
24289 MIPS_INVAL("SPIM");
24290 generate_exception_end(ctx, EXCP_RI);
24291 #else
24292 /* Implemented as RI exception for now. */
24293 MIPS_INVAL("spim (unofficial)");
24294 generate_exception_end(ctx, EXCP_RI);
24295 #endif
24296 break;
24297 default: /* Invalid */
24298 MIPS_INVAL("special_legacy");
24299 generate_exception_end(ctx, EXCP_RI);
24300 break;
24304 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24306 int rs, rt, rd, sa;
24307 uint32_t op1;
24309 rs = (ctx->opcode >> 21) & 0x1f;
24310 rt = (ctx->opcode >> 16) & 0x1f;
24311 rd = (ctx->opcode >> 11) & 0x1f;
24312 sa = (ctx->opcode >> 6) & 0x1f;
24314 op1 = MASK_SPECIAL(ctx->opcode);
24315 switch (op1) {
24316 case OPC_SLL: /* Shift with immediate */
24317 if (sa == 5 && rd == 0 &&
24318 rs == 0 && rt == 0) { /* PAUSE */
24319 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24320 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24321 generate_exception_end(ctx, EXCP_RI);
24322 break;
24325 /* Fallthrough */
24326 case OPC_SRA:
24327 gen_shift_imm(ctx, op1, rd, rt, sa);
24328 break;
24329 case OPC_SRL:
24330 switch ((ctx->opcode >> 21) & 0x1f) {
24331 case 1:
24332 /* rotr is decoded as srl on non-R2 CPUs */
24333 if (ctx->insn_flags & ISA_MIPS32R2) {
24334 op1 = OPC_ROTR;
24336 /* Fallthrough */
24337 case 0:
24338 gen_shift_imm(ctx, op1, rd, rt, sa);
24339 break;
24340 default:
24341 generate_exception_end(ctx, EXCP_RI);
24342 break;
24344 break;
24345 case OPC_ADD:
24346 case OPC_ADDU:
24347 case OPC_SUB:
24348 case OPC_SUBU:
24349 gen_arith(ctx, op1, rd, rs, rt);
24350 break;
24351 case OPC_SLLV: /* Shifts */
24352 case OPC_SRAV:
24353 gen_shift(ctx, op1, rd, rs, rt);
24354 break;
24355 case OPC_SRLV:
24356 switch ((ctx->opcode >> 6) & 0x1f) {
24357 case 1:
24358 /* rotrv is decoded as srlv on non-R2 CPUs */
24359 if (ctx->insn_flags & ISA_MIPS32R2) {
24360 op1 = OPC_ROTRV;
24362 /* Fallthrough */
24363 case 0:
24364 gen_shift(ctx, op1, rd, rs, rt);
24365 break;
24366 default:
24367 generate_exception_end(ctx, EXCP_RI);
24368 break;
24370 break;
24371 case OPC_SLT: /* Set on less than */
24372 case OPC_SLTU:
24373 gen_slt(ctx, op1, rd, rs, rt);
24374 break;
24375 case OPC_AND: /* Logic*/
24376 case OPC_OR:
24377 case OPC_NOR:
24378 case OPC_XOR:
24379 gen_logic(ctx, op1, rd, rs, rt);
24380 break;
24381 case OPC_JALR:
24382 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24383 break;
24384 case OPC_TGE: /* Traps */
24385 case OPC_TGEU:
24386 case OPC_TLT:
24387 case OPC_TLTU:
24388 case OPC_TEQ:
24389 case OPC_TNE:
24390 check_insn(ctx, ISA_MIPS2);
24391 gen_trap(ctx, op1, rs, rt, -1);
24392 break;
24393 case OPC_LSA: /* OPC_PMON */
24394 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24395 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24396 decode_opc_special_r6(env, ctx);
24397 } else {
24398 /* Pmon entry point, also R4010 selsl */
24399 #ifdef MIPS_STRICT_STANDARD
24400 MIPS_INVAL("PMON / selsl");
24401 generate_exception_end(ctx, EXCP_RI);
24402 #else
24403 gen_helper_0e0i(pmon, sa);
24404 #endif
24406 break;
24407 case OPC_SYSCALL:
24408 generate_exception_end(ctx, EXCP_SYSCALL);
24409 break;
24410 case OPC_BREAK:
24411 generate_exception_end(ctx, EXCP_BREAK);
24412 break;
24413 case OPC_SYNC:
24414 check_insn(ctx, ISA_MIPS2);
24415 gen_sync(extract32(ctx->opcode, 6, 5));
24416 break;
24418 #if defined(TARGET_MIPS64)
24419 /* MIPS64 specific opcodes */
24420 case OPC_DSLL:
24421 case OPC_DSRA:
24422 case OPC_DSLL32:
24423 case OPC_DSRA32:
24424 check_insn(ctx, ISA_MIPS3);
24425 check_mips_64(ctx);
24426 gen_shift_imm(ctx, op1, rd, rt, sa);
24427 break;
24428 case OPC_DSRL:
24429 switch ((ctx->opcode >> 21) & 0x1f) {
24430 case 1:
24431 /* drotr is decoded as dsrl on non-R2 CPUs */
24432 if (ctx->insn_flags & ISA_MIPS32R2) {
24433 op1 = OPC_DROTR;
24435 /* Fallthrough */
24436 case 0:
24437 check_insn(ctx, ISA_MIPS3);
24438 check_mips_64(ctx);
24439 gen_shift_imm(ctx, op1, rd, rt, sa);
24440 break;
24441 default:
24442 generate_exception_end(ctx, EXCP_RI);
24443 break;
24445 break;
24446 case OPC_DSRL32:
24447 switch ((ctx->opcode >> 21) & 0x1f) {
24448 case 1:
24449 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24450 if (ctx->insn_flags & ISA_MIPS32R2) {
24451 op1 = OPC_DROTR32;
24453 /* Fallthrough */
24454 case 0:
24455 check_insn(ctx, ISA_MIPS3);
24456 check_mips_64(ctx);
24457 gen_shift_imm(ctx, op1, rd, rt, sa);
24458 break;
24459 default:
24460 generate_exception_end(ctx, EXCP_RI);
24461 break;
24463 break;
24464 case OPC_DADD:
24465 case OPC_DADDU:
24466 case OPC_DSUB:
24467 case OPC_DSUBU:
24468 check_insn(ctx, ISA_MIPS3);
24469 check_mips_64(ctx);
24470 gen_arith(ctx, op1, rd, rs, rt);
24471 break;
24472 case OPC_DSLLV:
24473 case OPC_DSRAV:
24474 check_insn(ctx, ISA_MIPS3);
24475 check_mips_64(ctx);
24476 gen_shift(ctx, op1, rd, rs, rt);
24477 break;
24478 case OPC_DSRLV:
24479 switch ((ctx->opcode >> 6) & 0x1f) {
24480 case 1:
24481 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24482 if (ctx->insn_flags & ISA_MIPS32R2) {
24483 op1 = OPC_DROTRV;
24485 /* Fallthrough */
24486 case 0:
24487 check_insn(ctx, ISA_MIPS3);
24488 check_mips_64(ctx);
24489 gen_shift(ctx, op1, rd, rs, rt);
24490 break;
24491 default:
24492 generate_exception_end(ctx, EXCP_RI);
24493 break;
24495 break;
24496 case OPC_DLSA:
24497 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24498 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24499 decode_opc_special_r6(env, ctx);
24501 break;
24502 #endif
24503 default:
24504 if (ctx->insn_flags & ISA_MIPS32R6) {
24505 decode_opc_special_r6(env, ctx);
24506 } else if (ctx->insn_flags & INSN_R5900) {
24507 decode_opc_special_tx79(env, ctx);
24508 } else {
24509 decode_opc_special_legacy(env, ctx);
24515 #if defined(TARGET_MIPS64)
24519 * MMI (MultiMedia Interface) ASE instructions
24520 * ===========================================
24524 * MMI instructions category: data communication
24525 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24527 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24528 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24529 * PCPYUD PEXEH PEXTLW PPACW
24530 * PEXEW PEXTUB
24531 * PEXTUH
24532 * PEXTUW
24536 * PCPYH rd, rt
24538 * Parallel Copy Halfword
24540 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24541 * +-----------+---------+---------+---------+---------+-----------+
24542 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24543 * +-----------+---------+---------+---------+---------+-----------+
24545 static void gen_mmi_pcpyh(DisasContext *ctx)
24547 uint32_t pd, rt, rd;
24548 uint32_t opcode;
24550 opcode = ctx->opcode;
24552 pd = extract32(opcode, 21, 5);
24553 rt = extract32(opcode, 16, 5);
24554 rd = extract32(opcode, 11, 5);
24556 if (unlikely(pd != 0)) {
24557 generate_exception_end(ctx, EXCP_RI);
24558 } else if (rd == 0) {
24559 /* nop */
24560 } else if (rt == 0) {
24561 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24562 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24563 } else {
24564 TCGv_i64 t0 = tcg_temp_new();
24565 TCGv_i64 t1 = tcg_temp_new();
24566 uint64_t mask = (1ULL << 16) - 1;
24568 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24569 tcg_gen_movi_i64(t1, 0);
24570 tcg_gen_or_i64(t1, t0, t1);
24571 tcg_gen_shli_i64(t0, t0, 16);
24572 tcg_gen_or_i64(t1, t0, t1);
24573 tcg_gen_shli_i64(t0, t0, 16);
24574 tcg_gen_or_i64(t1, t0, t1);
24575 tcg_gen_shli_i64(t0, t0, 16);
24576 tcg_gen_or_i64(t1, t0, t1);
24578 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24580 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24581 tcg_gen_movi_i64(t1, 0);
24582 tcg_gen_or_i64(t1, t0, t1);
24583 tcg_gen_shli_i64(t0, t0, 16);
24584 tcg_gen_or_i64(t1, t0, t1);
24585 tcg_gen_shli_i64(t0, t0, 16);
24586 tcg_gen_or_i64(t1, t0, t1);
24587 tcg_gen_shli_i64(t0, t0, 16);
24588 tcg_gen_or_i64(t1, t0, t1);
24590 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24592 tcg_temp_free(t0);
24593 tcg_temp_free(t1);
24598 * PCPYLD rd, rs, rt
24600 * Parallel Copy Lower Doubleword
24602 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24603 * +-----------+---------+---------+---------+---------+-----------+
24604 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24605 * +-----------+---------+---------+---------+---------+-----------+
24607 static void gen_mmi_pcpyld(DisasContext *ctx)
24609 uint32_t rs, rt, rd;
24610 uint32_t opcode;
24612 opcode = ctx->opcode;
24614 rs = extract32(opcode, 21, 5);
24615 rt = extract32(opcode, 16, 5);
24616 rd = extract32(opcode, 11, 5);
24618 if (rd == 0) {
24619 /* nop */
24620 } else {
24621 if (rs == 0) {
24622 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24623 } else {
24624 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24626 if (rt == 0) {
24627 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24628 } else {
24629 if (rd != rt) {
24630 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24637 * PCPYUD rd, rs, rt
24639 * Parallel Copy Upper Doubleword
24641 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24642 * +-----------+---------+---------+---------+---------+-----------+
24643 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24644 * +-----------+---------+---------+---------+---------+-----------+
24646 static void gen_mmi_pcpyud(DisasContext *ctx)
24648 uint32_t rs, rt, rd;
24649 uint32_t opcode;
24651 opcode = ctx->opcode;
24653 rs = extract32(opcode, 21, 5);
24654 rt = extract32(opcode, 16, 5);
24655 rd = extract32(opcode, 11, 5);
24657 if (rd == 0) {
24658 /* nop */
24659 } else {
24660 if (rs == 0) {
24661 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24662 } else {
24663 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24665 if (rt == 0) {
24666 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24667 } else {
24668 if (rd != rt) {
24669 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24675 #endif
24678 #if !defined(TARGET_MIPS64)
24680 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24681 #define MXU_APTN1_A 0
24682 #define MXU_APTN1_S 1
24684 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24685 #define MXU_APTN2_AA 0
24686 #define MXU_APTN2_AS 1
24687 #define MXU_APTN2_SA 2
24688 #define MXU_APTN2_SS 3
24690 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24691 #define MXU_EPTN2_AA 0
24692 #define MXU_EPTN2_AS 1
24693 #define MXU_EPTN2_SA 2
24694 #define MXU_EPTN2_SS 3
24696 /* MXU operand getting pattern 'optn2' */
24697 #define MXU_OPTN2_PTN0 0
24698 #define MXU_OPTN2_PTN1 1
24699 #define MXU_OPTN2_PTN2 2
24700 #define MXU_OPTN2_PTN3 3
24701 /* alternative naming scheme for 'optn2' */
24702 #define MXU_OPTN2_WW 0
24703 #define MXU_OPTN2_LW 1
24704 #define MXU_OPTN2_HW 2
24705 #define MXU_OPTN2_XW 3
24707 /* MXU operand getting pattern 'optn3' */
24708 #define MXU_OPTN3_PTN0 0
24709 #define MXU_OPTN3_PTN1 1
24710 #define MXU_OPTN3_PTN2 2
24711 #define MXU_OPTN3_PTN3 3
24712 #define MXU_OPTN3_PTN4 4
24713 #define MXU_OPTN3_PTN5 5
24714 #define MXU_OPTN3_PTN6 6
24715 #define MXU_OPTN3_PTN7 7
24719 * S32I2M XRa, rb - Register move from GRF to XRF
24721 static void gen_mxu_s32i2m(DisasContext *ctx)
24723 TCGv t0;
24724 uint32_t XRa, Rb;
24726 t0 = tcg_temp_new();
24728 XRa = extract32(ctx->opcode, 6, 5);
24729 Rb = extract32(ctx->opcode, 16, 5);
24731 gen_load_gpr(t0, Rb);
24732 if (XRa <= 15) {
24733 gen_store_mxu_gpr(t0, XRa);
24734 } else if (XRa == 16) {
24735 gen_store_mxu_cr(t0);
24738 tcg_temp_free(t0);
24742 * S32M2I XRa, rb - Register move from XRF to GRF
24744 static void gen_mxu_s32m2i(DisasContext *ctx)
24746 TCGv t0;
24747 uint32_t XRa, Rb;
24749 t0 = tcg_temp_new();
24751 XRa = extract32(ctx->opcode, 6, 5);
24752 Rb = extract32(ctx->opcode, 16, 5);
24754 if (XRa <= 15) {
24755 gen_load_mxu_gpr(t0, XRa);
24756 } else if (XRa == 16) {
24757 gen_load_mxu_cr(t0);
24760 gen_store_gpr(t0, Rb);
24762 tcg_temp_free(t0);
24766 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24768 static void gen_mxu_s8ldd(DisasContext *ctx)
24770 TCGv t0, t1;
24771 uint32_t XRa, Rb, s8, optn3;
24773 t0 = tcg_temp_new();
24774 t1 = tcg_temp_new();
24776 XRa = extract32(ctx->opcode, 6, 4);
24777 s8 = extract32(ctx->opcode, 10, 8);
24778 optn3 = extract32(ctx->opcode, 18, 3);
24779 Rb = extract32(ctx->opcode, 21, 5);
24781 gen_load_gpr(t0, Rb);
24782 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24784 switch (optn3) {
24785 /* XRa[7:0] = tmp8 */
24786 case MXU_OPTN3_PTN0:
24787 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24788 gen_load_mxu_gpr(t0, XRa);
24789 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24790 break;
24791 /* XRa[15:8] = tmp8 */
24792 case MXU_OPTN3_PTN1:
24793 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24794 gen_load_mxu_gpr(t0, XRa);
24795 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24796 break;
24797 /* XRa[23:16] = tmp8 */
24798 case MXU_OPTN3_PTN2:
24799 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24800 gen_load_mxu_gpr(t0, XRa);
24801 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24802 break;
24803 /* XRa[31:24] = tmp8 */
24804 case MXU_OPTN3_PTN3:
24805 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24806 gen_load_mxu_gpr(t0, XRa);
24807 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24808 break;
24809 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24810 case MXU_OPTN3_PTN4:
24811 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24812 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24813 break;
24814 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24815 case MXU_OPTN3_PTN5:
24816 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24817 tcg_gen_shli_tl(t1, t1, 8);
24818 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24819 break;
24820 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24821 case MXU_OPTN3_PTN6:
24822 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24823 tcg_gen_mov_tl(t0, t1);
24824 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24825 tcg_gen_shli_tl(t1, t1, 16);
24826 tcg_gen_or_tl(t0, t0, t1);
24827 break;
24828 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24829 case MXU_OPTN3_PTN7:
24830 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24831 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24832 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24833 break;
24836 gen_store_mxu_gpr(t0, XRa);
24838 tcg_temp_free(t0);
24839 tcg_temp_free(t1);
24843 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24845 static void gen_mxu_d16mul(DisasContext *ctx)
24847 TCGv t0, t1, t2, t3;
24848 uint32_t XRa, XRb, XRc, XRd, optn2;
24850 t0 = tcg_temp_new();
24851 t1 = tcg_temp_new();
24852 t2 = tcg_temp_new();
24853 t3 = tcg_temp_new();
24855 XRa = extract32(ctx->opcode, 6, 4);
24856 XRb = extract32(ctx->opcode, 10, 4);
24857 XRc = extract32(ctx->opcode, 14, 4);
24858 XRd = extract32(ctx->opcode, 18, 4);
24859 optn2 = extract32(ctx->opcode, 22, 2);
24861 gen_load_mxu_gpr(t1, XRb);
24862 tcg_gen_sextract_tl(t0, t1, 0, 16);
24863 tcg_gen_sextract_tl(t1, t1, 16, 16);
24864 gen_load_mxu_gpr(t3, XRc);
24865 tcg_gen_sextract_tl(t2, t3, 0, 16);
24866 tcg_gen_sextract_tl(t3, t3, 16, 16);
24868 switch (optn2) {
24869 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24870 tcg_gen_mul_tl(t3, t1, t3);
24871 tcg_gen_mul_tl(t2, t0, t2);
24872 break;
24873 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24874 tcg_gen_mul_tl(t3, t0, t3);
24875 tcg_gen_mul_tl(t2, t0, t2);
24876 break;
24877 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24878 tcg_gen_mul_tl(t3, t1, t3);
24879 tcg_gen_mul_tl(t2, t1, t2);
24880 break;
24881 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24882 tcg_gen_mul_tl(t3, t0, t3);
24883 tcg_gen_mul_tl(t2, t1, t2);
24884 break;
24886 gen_store_mxu_gpr(t3, XRa);
24887 gen_store_mxu_gpr(t2, XRd);
24889 tcg_temp_free(t0);
24890 tcg_temp_free(t1);
24891 tcg_temp_free(t2);
24892 tcg_temp_free(t3);
24896 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24897 * and accumulate
24899 static void gen_mxu_d16mac(DisasContext *ctx)
24901 TCGv t0, t1, t2, t3;
24902 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24904 t0 = tcg_temp_new();
24905 t1 = tcg_temp_new();
24906 t2 = tcg_temp_new();
24907 t3 = tcg_temp_new();
24909 XRa = extract32(ctx->opcode, 6, 4);
24910 XRb = extract32(ctx->opcode, 10, 4);
24911 XRc = extract32(ctx->opcode, 14, 4);
24912 XRd = extract32(ctx->opcode, 18, 4);
24913 optn2 = extract32(ctx->opcode, 22, 2);
24914 aptn2 = extract32(ctx->opcode, 24, 2);
24916 gen_load_mxu_gpr(t1, XRb);
24917 tcg_gen_sextract_tl(t0, t1, 0, 16);
24918 tcg_gen_sextract_tl(t1, t1, 16, 16);
24920 gen_load_mxu_gpr(t3, XRc);
24921 tcg_gen_sextract_tl(t2, t3, 0, 16);
24922 tcg_gen_sextract_tl(t3, t3, 16, 16);
24924 switch (optn2) {
24925 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24926 tcg_gen_mul_tl(t3, t1, t3);
24927 tcg_gen_mul_tl(t2, t0, t2);
24928 break;
24929 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24930 tcg_gen_mul_tl(t3, t0, t3);
24931 tcg_gen_mul_tl(t2, t0, t2);
24932 break;
24933 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24934 tcg_gen_mul_tl(t3, t1, t3);
24935 tcg_gen_mul_tl(t2, t1, t2);
24936 break;
24937 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24938 tcg_gen_mul_tl(t3, t0, t3);
24939 tcg_gen_mul_tl(t2, t1, t2);
24940 break;
24942 gen_load_mxu_gpr(t0, XRa);
24943 gen_load_mxu_gpr(t1, XRd);
24945 switch (aptn2) {
24946 case MXU_APTN2_AA:
24947 tcg_gen_add_tl(t3, t0, t3);
24948 tcg_gen_add_tl(t2, t1, t2);
24949 break;
24950 case MXU_APTN2_AS:
24951 tcg_gen_add_tl(t3, t0, t3);
24952 tcg_gen_sub_tl(t2, t1, t2);
24953 break;
24954 case MXU_APTN2_SA:
24955 tcg_gen_sub_tl(t3, t0, t3);
24956 tcg_gen_add_tl(t2, t1, t2);
24957 break;
24958 case MXU_APTN2_SS:
24959 tcg_gen_sub_tl(t3, t0, t3);
24960 tcg_gen_sub_tl(t2, t1, t2);
24961 break;
24963 gen_store_mxu_gpr(t3, XRa);
24964 gen_store_mxu_gpr(t2, XRd);
24966 tcg_temp_free(t0);
24967 tcg_temp_free(t1);
24968 tcg_temp_free(t2);
24969 tcg_temp_free(t3);
24973 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24974 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24976 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24978 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24979 uint32_t XRa, XRb, XRc, XRd, sel;
24981 t0 = tcg_temp_new();
24982 t1 = tcg_temp_new();
24983 t2 = tcg_temp_new();
24984 t3 = tcg_temp_new();
24985 t4 = tcg_temp_new();
24986 t5 = tcg_temp_new();
24987 t6 = tcg_temp_new();
24988 t7 = tcg_temp_new();
24990 XRa = extract32(ctx->opcode, 6, 4);
24991 XRb = extract32(ctx->opcode, 10, 4);
24992 XRc = extract32(ctx->opcode, 14, 4);
24993 XRd = extract32(ctx->opcode, 18, 4);
24994 sel = extract32(ctx->opcode, 22, 2);
24996 gen_load_mxu_gpr(t3, XRb);
24997 gen_load_mxu_gpr(t7, XRc);
24999 if (sel == 0x2) {
25000 /* Q8MULSU */
25001 tcg_gen_ext8s_tl(t0, t3);
25002 tcg_gen_shri_tl(t3, t3, 8);
25003 tcg_gen_ext8s_tl(t1, t3);
25004 tcg_gen_shri_tl(t3, t3, 8);
25005 tcg_gen_ext8s_tl(t2, t3);
25006 tcg_gen_shri_tl(t3, t3, 8);
25007 tcg_gen_ext8s_tl(t3, t3);
25008 } else {
25009 /* Q8MUL */
25010 tcg_gen_ext8u_tl(t0, t3);
25011 tcg_gen_shri_tl(t3, t3, 8);
25012 tcg_gen_ext8u_tl(t1, t3);
25013 tcg_gen_shri_tl(t3, t3, 8);
25014 tcg_gen_ext8u_tl(t2, t3);
25015 tcg_gen_shri_tl(t3, t3, 8);
25016 tcg_gen_ext8u_tl(t3, t3);
25019 tcg_gen_ext8u_tl(t4, t7);
25020 tcg_gen_shri_tl(t7, t7, 8);
25021 tcg_gen_ext8u_tl(t5, t7);
25022 tcg_gen_shri_tl(t7, t7, 8);
25023 tcg_gen_ext8u_tl(t6, t7);
25024 tcg_gen_shri_tl(t7, t7, 8);
25025 tcg_gen_ext8u_tl(t7, t7);
25027 tcg_gen_mul_tl(t0, t0, t4);
25028 tcg_gen_mul_tl(t1, t1, t5);
25029 tcg_gen_mul_tl(t2, t2, t6);
25030 tcg_gen_mul_tl(t3, t3, t7);
25032 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25033 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25034 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25035 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25037 tcg_gen_shli_tl(t1, t1, 16);
25038 tcg_gen_shli_tl(t3, t3, 16);
25040 tcg_gen_or_tl(t0, t0, t1);
25041 tcg_gen_or_tl(t1, t2, t3);
25043 gen_store_mxu_gpr(t0, XRd);
25044 gen_store_mxu_gpr(t1, XRa);
25046 tcg_temp_free(t0);
25047 tcg_temp_free(t1);
25048 tcg_temp_free(t2);
25049 tcg_temp_free(t3);
25050 tcg_temp_free(t4);
25051 tcg_temp_free(t5);
25052 tcg_temp_free(t6);
25053 tcg_temp_free(t7);
25057 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25058 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25060 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25062 TCGv t0, t1;
25063 uint32_t XRa, Rb, s12, sel;
25065 t0 = tcg_temp_new();
25066 t1 = tcg_temp_new();
25068 XRa = extract32(ctx->opcode, 6, 4);
25069 s12 = extract32(ctx->opcode, 10, 10);
25070 sel = extract32(ctx->opcode, 20, 1);
25071 Rb = extract32(ctx->opcode, 21, 5);
25073 gen_load_gpr(t0, Rb);
25075 tcg_gen_movi_tl(t1, s12);
25076 tcg_gen_shli_tl(t1, t1, 2);
25077 if (s12 & 0x200) {
25078 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25080 tcg_gen_add_tl(t1, t0, t1);
25081 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25083 if (sel == 1) {
25084 /* S32LDDR */
25085 tcg_gen_bswap32_tl(t1, t1);
25087 gen_store_mxu_gpr(t1, XRa);
25089 tcg_temp_free(t0);
25090 tcg_temp_free(t1);
25095 * MXU instruction category: logic
25096 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25098 * S32NOR S32AND S32OR S32XOR
25102 * S32NOR XRa, XRb, XRc
25103 * Update XRa with the result of logical bitwise 'nor' operation
25104 * applied to the content of XRb and XRc.
25106 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25107 * +-----------+---------+-----+-------+-------+-------+-----------+
25108 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25109 * +-----------+---------+-----+-------+-------+-------+-----------+
25111 static void gen_mxu_S32NOR(DisasContext *ctx)
25113 uint32_t pad, XRc, XRb, XRa;
25115 pad = extract32(ctx->opcode, 21, 5);
25116 XRc = extract32(ctx->opcode, 14, 4);
25117 XRb = extract32(ctx->opcode, 10, 4);
25118 XRa = extract32(ctx->opcode, 6, 4);
25120 if (unlikely(pad != 0)) {
25121 /* opcode padding incorrect -> do nothing */
25122 } else if (unlikely(XRa == 0)) {
25123 /* destination is zero register -> do nothing */
25124 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25125 /* both operands zero registers -> just set destination to all 1s */
25126 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25127 } else if (unlikely(XRb == 0)) {
25128 /* XRb zero register -> just set destination to the negation of XRc */
25129 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25130 } else if (unlikely(XRc == 0)) {
25131 /* XRa zero register -> just set destination to the negation of XRb */
25132 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25133 } else if (unlikely(XRb == XRc)) {
25134 /* both operands same -> just set destination to the negation of XRb */
25135 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25136 } else {
25137 /* the most general case */
25138 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25143 * S32AND XRa, XRb, XRc
25144 * Update XRa with the result of logical bitwise 'and' operation
25145 * applied to the content of XRb and XRc.
25147 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25148 * +-----------+---------+-----+-------+-------+-------+-----------+
25149 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25150 * +-----------+---------+-----+-------+-------+-------+-----------+
25152 static void gen_mxu_S32AND(DisasContext *ctx)
25154 uint32_t pad, XRc, XRb, XRa;
25156 pad = extract32(ctx->opcode, 21, 5);
25157 XRc = extract32(ctx->opcode, 14, 4);
25158 XRb = extract32(ctx->opcode, 10, 4);
25159 XRa = extract32(ctx->opcode, 6, 4);
25161 if (unlikely(pad != 0)) {
25162 /* opcode padding incorrect -> do nothing */
25163 } else if (unlikely(XRa == 0)) {
25164 /* destination is zero register -> do nothing */
25165 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25166 /* one of operands zero register -> just set destination to all 0s */
25167 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25168 } else if (unlikely(XRb == XRc)) {
25169 /* both operands same -> just set destination to one of them */
25170 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25171 } else {
25172 /* the most general case */
25173 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25178 * S32OR XRa, XRb, XRc
25179 * Update XRa with the result of logical bitwise 'or' operation
25180 * applied to the content of XRb and XRc.
25182 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25183 * +-----------+---------+-----+-------+-------+-------+-----------+
25184 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25185 * +-----------+---------+-----+-------+-------+-------+-----------+
25187 static void gen_mxu_S32OR(DisasContext *ctx)
25189 uint32_t pad, XRc, XRb, XRa;
25191 pad = extract32(ctx->opcode, 21, 5);
25192 XRc = extract32(ctx->opcode, 14, 4);
25193 XRb = extract32(ctx->opcode, 10, 4);
25194 XRa = extract32(ctx->opcode, 6, 4);
25196 if (unlikely(pad != 0)) {
25197 /* opcode padding incorrect -> do nothing */
25198 } else if (unlikely(XRa == 0)) {
25199 /* destination is zero register -> do nothing */
25200 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25201 /* both operands zero registers -> just set destination to all 0s */
25202 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25203 } else if (unlikely(XRb == 0)) {
25204 /* XRb zero register -> just set destination to the content of XRc */
25205 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25206 } else if (unlikely(XRc == 0)) {
25207 /* XRc zero register -> just set destination to the content of XRb */
25208 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25209 } else if (unlikely(XRb == XRc)) {
25210 /* both operands same -> just set destination to one of them */
25211 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25212 } else {
25213 /* the most general case */
25214 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25219 * S32XOR XRa, XRb, XRc
25220 * Update XRa with the result of logical bitwise 'xor' operation
25221 * applied to the content of XRb and XRc.
25223 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25224 * +-----------+---------+-----+-------+-------+-------+-----------+
25225 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25226 * +-----------+---------+-----+-------+-------+-------+-----------+
25228 static void gen_mxu_S32XOR(DisasContext *ctx)
25230 uint32_t pad, XRc, XRb, XRa;
25232 pad = extract32(ctx->opcode, 21, 5);
25233 XRc = extract32(ctx->opcode, 14, 4);
25234 XRb = extract32(ctx->opcode, 10, 4);
25235 XRa = extract32(ctx->opcode, 6, 4);
25237 if (unlikely(pad != 0)) {
25238 /* opcode padding incorrect -> do nothing */
25239 } else if (unlikely(XRa == 0)) {
25240 /* destination is zero register -> do nothing */
25241 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25242 /* both operands zero registers -> just set destination to all 0s */
25243 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25244 } else if (unlikely(XRb == 0)) {
25245 /* XRb zero register -> just set destination to the content of XRc */
25246 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25247 } else if (unlikely(XRc == 0)) {
25248 /* XRc zero register -> just set destination to the content of XRb */
25249 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25250 } else if (unlikely(XRb == XRc)) {
25251 /* both operands same -> just set destination to all 0s */
25252 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25253 } else {
25254 /* the most general case */
25255 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25261 * MXU instruction category max/min
25262 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25264 * S32MAX D16MAX Q8MAX
25265 * S32MIN D16MIN Q8MIN
25269 * S32MAX XRa, XRb, XRc
25270 * Update XRa with the maximum of signed 32-bit integers contained
25271 * in XRb and XRc.
25273 * S32MIN XRa, XRb, XRc
25274 * Update XRa with the minimum of signed 32-bit integers contained
25275 * in XRb and XRc.
25277 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25278 * +-----------+---------+-----+-------+-------+-------+-----------+
25279 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25280 * +-----------+---------+-----+-------+-------+-------+-----------+
25282 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25284 uint32_t pad, opc, XRc, XRb, XRa;
25286 pad = extract32(ctx->opcode, 21, 5);
25287 opc = extract32(ctx->opcode, 18, 3);
25288 XRc = extract32(ctx->opcode, 14, 4);
25289 XRb = extract32(ctx->opcode, 10, 4);
25290 XRa = extract32(ctx->opcode, 6, 4);
25292 if (unlikely(pad != 0)) {
25293 /* opcode padding incorrect -> do nothing */
25294 } else if (unlikely(XRa == 0)) {
25295 /* destination is zero register -> do nothing */
25296 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25297 /* both operands zero registers -> just set destination to zero */
25298 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25299 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25300 /* exactly one operand is zero register - find which one is not...*/
25301 uint32_t XRx = XRb ? XRb : XRc;
25302 /* ...and do max/min operation with one operand 0 */
25303 if (opc == OPC_MXU_S32MAX) {
25304 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25305 } else {
25306 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25308 } else if (unlikely(XRb == XRc)) {
25309 /* both operands same -> just set destination to one of them */
25310 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25311 } else {
25312 /* the most general case */
25313 if (opc == OPC_MXU_S32MAX) {
25314 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25315 mxu_gpr[XRc - 1]);
25316 } else {
25317 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25318 mxu_gpr[XRc - 1]);
25324 * D16MAX
25325 * Update XRa with the 16-bit-wise maximums of signed integers
25326 * contained in XRb and XRc.
25328 * D16MIN
25329 * Update XRa with the 16-bit-wise minimums of signed integers
25330 * contained in XRb and XRc.
25332 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25333 * +-----------+---------+-----+-------+-------+-------+-----------+
25334 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25335 * +-----------+---------+-----+-------+-------+-------+-----------+
25337 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25339 uint32_t pad, opc, XRc, XRb, XRa;
25341 pad = extract32(ctx->opcode, 21, 5);
25342 opc = extract32(ctx->opcode, 18, 3);
25343 XRc = extract32(ctx->opcode, 14, 4);
25344 XRb = extract32(ctx->opcode, 10, 4);
25345 XRa = extract32(ctx->opcode, 6, 4);
25347 if (unlikely(pad != 0)) {
25348 /* opcode padding incorrect -> do nothing */
25349 } else if (unlikely(XRc == 0)) {
25350 /* destination is zero register -> do nothing */
25351 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25352 /* both operands zero registers -> just set destination to zero */
25353 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25354 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25355 /* exactly one operand is zero register - find which one is not...*/
25356 uint32_t XRx = XRb ? XRb : XRc;
25357 /* ...and do half-word-wise max/min with one operand 0 */
25358 TCGv_i32 t0 = tcg_temp_new();
25359 TCGv_i32 t1 = tcg_const_i32(0);
25361 /* the left half-word first */
25362 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25363 if (opc == OPC_MXU_D16MAX) {
25364 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25365 } else {
25366 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25369 /* the right half-word */
25370 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25371 /* move half-words to the leftmost position */
25372 tcg_gen_shli_i32(t0, t0, 16);
25373 /* t0 will be max/min of t0 and t1 */
25374 if (opc == OPC_MXU_D16MAX) {
25375 tcg_gen_smax_i32(t0, t0, t1);
25376 } else {
25377 tcg_gen_smin_i32(t0, t0, t1);
25379 /* return resulting half-words to its original position */
25380 tcg_gen_shri_i32(t0, t0, 16);
25381 /* finaly update the destination */
25382 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25384 tcg_temp_free(t1);
25385 tcg_temp_free(t0);
25386 } else if (unlikely(XRb == XRc)) {
25387 /* both operands same -> just set destination to one of them */
25388 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25389 } else {
25390 /* the most general case */
25391 TCGv_i32 t0 = tcg_temp_new();
25392 TCGv_i32 t1 = tcg_temp_new();
25394 /* the left half-word first */
25395 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25396 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25397 if (opc == OPC_MXU_D16MAX) {
25398 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25399 } else {
25400 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25403 /* the right half-word */
25404 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25405 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25406 /* move half-words to the leftmost position */
25407 tcg_gen_shli_i32(t0, t0, 16);
25408 tcg_gen_shli_i32(t1, t1, 16);
25409 /* t0 will be max/min of t0 and t1 */
25410 if (opc == OPC_MXU_D16MAX) {
25411 tcg_gen_smax_i32(t0, t0, t1);
25412 } else {
25413 tcg_gen_smin_i32(t0, t0, t1);
25415 /* return resulting half-words to its original position */
25416 tcg_gen_shri_i32(t0, t0, 16);
25417 /* finaly update the destination */
25418 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25420 tcg_temp_free(t1);
25421 tcg_temp_free(t0);
25426 * Q8MAX
25427 * Update XRa with the 8-bit-wise maximums of signed integers
25428 * contained in XRb and XRc.
25430 * Q8MIN
25431 * Update XRa with the 8-bit-wise minimums of signed integers
25432 * contained in XRb and XRc.
25434 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25435 * +-----------+---------+-----+-------+-------+-------+-----------+
25436 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25437 * +-----------+---------+-----+-------+-------+-------+-----------+
25439 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25441 uint32_t pad, opc, XRc, XRb, XRa;
25443 pad = extract32(ctx->opcode, 21, 5);
25444 opc = extract32(ctx->opcode, 18, 3);
25445 XRc = extract32(ctx->opcode, 14, 4);
25446 XRb = extract32(ctx->opcode, 10, 4);
25447 XRa = extract32(ctx->opcode, 6, 4);
25449 if (unlikely(pad != 0)) {
25450 /* opcode padding incorrect -> do nothing */
25451 } else if (unlikely(XRa == 0)) {
25452 /* destination is zero register -> do nothing */
25453 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25454 /* both operands zero registers -> just set destination to zero */
25455 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25456 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25457 /* exactly one operand is zero register - make it be the first...*/
25458 uint32_t XRx = XRb ? XRb : XRc;
25459 /* ...and do byte-wise max/min with one operand 0 */
25460 TCGv_i32 t0 = tcg_temp_new();
25461 TCGv_i32 t1 = tcg_const_i32(0);
25462 int32_t i;
25464 /* the leftmost byte (byte 3) first */
25465 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25466 if (opc == OPC_MXU_Q8MAX) {
25467 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25468 } else {
25469 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25472 /* bytes 2, 1, 0 */
25473 for (i = 2; i >= 0; i--) {
25474 /* extract the byte */
25475 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25476 /* move the byte to the leftmost position */
25477 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25478 /* t0 will be max/min of t0 and t1 */
25479 if (opc == OPC_MXU_Q8MAX) {
25480 tcg_gen_smax_i32(t0, t0, t1);
25481 } else {
25482 tcg_gen_smin_i32(t0, t0, t1);
25484 /* return resulting byte to its original position */
25485 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25486 /* finaly update the destination */
25487 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25490 tcg_temp_free(t1);
25491 tcg_temp_free(t0);
25492 } else if (unlikely(XRb == XRc)) {
25493 /* both operands same -> just set destination to one of them */
25494 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25495 } else {
25496 /* the most general case */
25497 TCGv_i32 t0 = tcg_temp_new();
25498 TCGv_i32 t1 = tcg_temp_new();
25499 int32_t i;
25501 /* the leftmost bytes (bytes 3) first */
25502 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25503 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25504 if (opc == OPC_MXU_Q8MAX) {
25505 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25506 } else {
25507 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25510 /* bytes 2, 1, 0 */
25511 for (i = 2; i >= 0; i--) {
25512 /* extract corresponding bytes */
25513 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25514 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25515 /* move the bytes to the leftmost position */
25516 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25517 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25518 /* t0 will be max/min of t0 and t1 */
25519 if (opc == OPC_MXU_Q8MAX) {
25520 tcg_gen_smax_i32(t0, t0, t1);
25521 } else {
25522 tcg_gen_smin_i32(t0, t0, t1);
25524 /* return resulting byte to its original position */
25525 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25526 /* finaly update the destination */
25527 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25530 tcg_temp_free(t1);
25531 tcg_temp_free(t0);
25537 * MXU instruction category: align
25538 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25540 * S32ALN S32ALNI
25544 * S32ALNI XRc, XRb, XRa, optn3
25545 * Arrange bytes from XRb and XRc according to one of five sets of
25546 * rules determined by optn3, and place the result in XRa.
25548 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25549 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25550 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25551 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25554 static void gen_mxu_S32ALNI(DisasContext *ctx)
25556 uint32_t optn3, pad, XRc, XRb, XRa;
25558 optn3 = extract32(ctx->opcode, 23, 3);
25559 pad = extract32(ctx->opcode, 21, 2);
25560 XRc = extract32(ctx->opcode, 14, 4);
25561 XRb = extract32(ctx->opcode, 10, 4);
25562 XRa = extract32(ctx->opcode, 6, 4);
25564 if (unlikely(pad != 0)) {
25565 /* opcode padding incorrect -> do nothing */
25566 } else if (unlikely(XRa == 0)) {
25567 /* destination is zero register -> do nothing */
25568 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25569 /* both operands zero registers -> just set destination to all 0s */
25570 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25571 } else if (unlikely(XRb == 0)) {
25572 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25573 switch (optn3) {
25574 case MXU_OPTN3_PTN0:
25575 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25576 break;
25577 case MXU_OPTN3_PTN1:
25578 case MXU_OPTN3_PTN2:
25579 case MXU_OPTN3_PTN3:
25580 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25581 8 * (4 - optn3));
25582 break;
25583 case MXU_OPTN3_PTN4:
25584 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25585 break;
25587 } else if (unlikely(XRc == 0)) {
25588 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25589 switch (optn3) {
25590 case MXU_OPTN3_PTN0:
25591 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25592 break;
25593 case MXU_OPTN3_PTN1:
25594 case MXU_OPTN3_PTN2:
25595 case MXU_OPTN3_PTN3:
25596 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25597 break;
25598 case MXU_OPTN3_PTN4:
25599 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25600 break;
25602 } else if (unlikely(XRb == XRc)) {
25603 /* both operands same -> just rotation or moving from any of them */
25604 switch (optn3) {
25605 case MXU_OPTN3_PTN0:
25606 case MXU_OPTN3_PTN4:
25607 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25608 break;
25609 case MXU_OPTN3_PTN1:
25610 case MXU_OPTN3_PTN2:
25611 case MXU_OPTN3_PTN3:
25612 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25613 break;
25615 } else {
25616 /* the most general case */
25617 switch (optn3) {
25618 case MXU_OPTN3_PTN0:
25620 /* */
25621 /* XRb XRc */
25622 /* +---------------+ */
25623 /* | A B C D | E F G H */
25624 /* +-------+-------+ */
25625 /* | */
25626 /* XRa */
25627 /* */
25629 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25631 break;
25632 case MXU_OPTN3_PTN1:
25634 /* */
25635 /* XRb XRc */
25636 /* +-------------------+ */
25637 /* A | B C D E | F G H */
25638 /* +---------+---------+ */
25639 /* | */
25640 /* XRa */
25641 /* */
25643 TCGv_i32 t0 = tcg_temp_new();
25644 TCGv_i32 t1 = tcg_temp_new();
25646 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25647 tcg_gen_shli_i32(t0, t0, 8);
25649 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25650 tcg_gen_shri_i32(t1, t1, 24);
25652 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25654 tcg_temp_free(t1);
25655 tcg_temp_free(t0);
25657 break;
25658 case MXU_OPTN3_PTN2:
25660 /* */
25661 /* XRb XRc */
25662 /* +-------------------+ */
25663 /* A B | C D E F | G H */
25664 /* +---------+---------+ */
25665 /* | */
25666 /* XRa */
25667 /* */
25669 TCGv_i32 t0 = tcg_temp_new();
25670 TCGv_i32 t1 = tcg_temp_new();
25672 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25673 tcg_gen_shli_i32(t0, t0, 16);
25675 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25676 tcg_gen_shri_i32(t1, t1, 16);
25678 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25680 tcg_temp_free(t1);
25681 tcg_temp_free(t0);
25683 break;
25684 case MXU_OPTN3_PTN3:
25686 /* */
25687 /* XRb XRc */
25688 /* +-------------------+ */
25689 /* A B C | D E F G | H */
25690 /* +---------+---------+ */
25691 /* | */
25692 /* XRa */
25693 /* */
25695 TCGv_i32 t0 = tcg_temp_new();
25696 TCGv_i32 t1 = tcg_temp_new();
25698 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25699 tcg_gen_shli_i32(t0, t0, 24);
25701 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25702 tcg_gen_shri_i32(t1, t1, 8);
25704 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25706 tcg_temp_free(t1);
25707 tcg_temp_free(t0);
25709 break;
25710 case MXU_OPTN3_PTN4:
25712 /* */
25713 /* XRb XRc */
25714 /* +---------------+ */
25715 /* A B C D | E F G H | */
25716 /* +-------+-------+ */
25717 /* | */
25718 /* XRa */
25719 /* */
25721 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25723 break;
25730 * Decoding engine for MXU
25731 * =======================
25736 * Decode MXU pool00
25738 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25739 * +-----------+---------+-----+-------+-------+-------+-----------+
25740 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25741 * +-----------+---------+-----+-------+-------+-------+-----------+
25744 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25746 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25748 switch (opcode) {
25749 case OPC_MXU_S32MAX:
25750 case OPC_MXU_S32MIN:
25751 gen_mxu_S32MAX_S32MIN(ctx);
25752 break;
25753 case OPC_MXU_D16MAX:
25754 case OPC_MXU_D16MIN:
25755 gen_mxu_D16MAX_D16MIN(ctx);
25756 break;
25757 case OPC_MXU_Q8MAX:
25758 case OPC_MXU_Q8MIN:
25759 gen_mxu_Q8MAX_Q8MIN(ctx);
25760 break;
25761 case OPC_MXU_Q8SLT:
25762 /* TODO: Implement emulation of Q8SLT instruction. */
25763 MIPS_INVAL("OPC_MXU_Q8SLT");
25764 generate_exception_end(ctx, EXCP_RI);
25765 break;
25766 case OPC_MXU_Q8SLTU:
25767 /* TODO: Implement emulation of Q8SLTU instruction. */
25768 MIPS_INVAL("OPC_MXU_Q8SLTU");
25769 generate_exception_end(ctx, EXCP_RI);
25770 break;
25771 default:
25772 MIPS_INVAL("decode_opc_mxu");
25773 generate_exception_end(ctx, EXCP_RI);
25774 break;
25780 * Decode MXU pool01
25782 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25783 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25784 * +-----------+---------+-----+-------+-------+-------+-----------+
25785 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25786 * +-----------+---------+-----+-------+-------+-------+-----------+
25788 * Q8ADD:
25789 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25790 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25791 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25792 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25795 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25797 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25799 switch (opcode) {
25800 case OPC_MXU_S32SLT:
25801 /* TODO: Implement emulation of S32SLT instruction. */
25802 MIPS_INVAL("OPC_MXU_S32SLT");
25803 generate_exception_end(ctx, EXCP_RI);
25804 break;
25805 case OPC_MXU_D16SLT:
25806 /* TODO: Implement emulation of D16SLT instruction. */
25807 MIPS_INVAL("OPC_MXU_D16SLT");
25808 generate_exception_end(ctx, EXCP_RI);
25809 break;
25810 case OPC_MXU_D16AVG:
25811 /* TODO: Implement emulation of D16AVG instruction. */
25812 MIPS_INVAL("OPC_MXU_D16AVG");
25813 generate_exception_end(ctx, EXCP_RI);
25814 break;
25815 case OPC_MXU_D16AVGR:
25816 /* TODO: Implement emulation of D16AVGR instruction. */
25817 MIPS_INVAL("OPC_MXU_D16AVGR");
25818 generate_exception_end(ctx, EXCP_RI);
25819 break;
25820 case OPC_MXU_Q8AVG:
25821 /* TODO: Implement emulation of Q8AVG instruction. */
25822 MIPS_INVAL("OPC_MXU_Q8AVG");
25823 generate_exception_end(ctx, EXCP_RI);
25824 break;
25825 case OPC_MXU_Q8AVGR:
25826 /* TODO: Implement emulation of Q8AVGR instruction. */
25827 MIPS_INVAL("OPC_MXU_Q8AVGR");
25828 generate_exception_end(ctx, EXCP_RI);
25829 break;
25830 case OPC_MXU_Q8ADD:
25831 /* TODO: Implement emulation of Q8ADD instruction. */
25832 MIPS_INVAL("OPC_MXU_Q8ADD");
25833 generate_exception_end(ctx, EXCP_RI);
25834 break;
25835 default:
25836 MIPS_INVAL("decode_opc_mxu");
25837 generate_exception_end(ctx, EXCP_RI);
25838 break;
25844 * Decode MXU pool02
25846 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25847 * +-----------+---------+-----+-------+-------+-------+-----------+
25848 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25849 * +-----------+---------+-----+-------+-------+-------+-----------+
25852 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25854 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25856 switch (opcode) {
25857 case OPC_MXU_S32CPS:
25858 /* TODO: Implement emulation of S32CPS instruction. */
25859 MIPS_INVAL("OPC_MXU_S32CPS");
25860 generate_exception_end(ctx, EXCP_RI);
25861 break;
25862 case OPC_MXU_D16CPS:
25863 /* TODO: Implement emulation of D16CPS instruction. */
25864 MIPS_INVAL("OPC_MXU_D16CPS");
25865 generate_exception_end(ctx, EXCP_RI);
25866 break;
25867 case OPC_MXU_Q8ABD:
25868 /* TODO: Implement emulation of Q8ABD instruction. */
25869 MIPS_INVAL("OPC_MXU_Q8ABD");
25870 generate_exception_end(ctx, EXCP_RI);
25871 break;
25872 case OPC_MXU_Q16SAT:
25873 /* TODO: Implement emulation of Q16SAT instruction. */
25874 MIPS_INVAL("OPC_MXU_Q16SAT");
25875 generate_exception_end(ctx, EXCP_RI);
25876 break;
25877 default:
25878 MIPS_INVAL("decode_opc_mxu");
25879 generate_exception_end(ctx, EXCP_RI);
25880 break;
25886 * Decode MXU pool03
25888 * D16MULF:
25889 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25890 * +-----------+---+---+-------+-------+-------+-------+-----------+
25891 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25892 * +-----------+---+---+-------+-------+-------+-------+-----------+
25894 * D16MULE:
25895 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25896 * +-----------+---+---+-------+-------+-------+-------+-----------+
25897 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25898 * +-----------+---+---+-------+-------+-------+-------+-----------+
25901 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25903 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25905 switch (opcode) {
25906 case OPC_MXU_D16MULF:
25907 /* TODO: Implement emulation of D16MULF instruction. */
25908 MIPS_INVAL("OPC_MXU_D16MULF");
25909 generate_exception_end(ctx, EXCP_RI);
25910 break;
25911 case OPC_MXU_D16MULE:
25912 /* TODO: Implement emulation of D16MULE instruction. */
25913 MIPS_INVAL("OPC_MXU_D16MULE");
25914 generate_exception_end(ctx, EXCP_RI);
25915 break;
25916 default:
25917 MIPS_INVAL("decode_opc_mxu");
25918 generate_exception_end(ctx, EXCP_RI);
25919 break;
25925 * Decode MXU pool04
25927 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25928 * +-----------+---------+-+-------------------+-------+-----------+
25929 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25930 * +-----------+---------+-+-------------------+-------+-----------+
25933 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25935 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25937 switch (opcode) {
25938 case OPC_MXU_S32LDD:
25939 case OPC_MXU_S32LDDR:
25940 gen_mxu_s32ldd_s32lddr(ctx);
25941 break;
25942 default:
25943 MIPS_INVAL("decode_opc_mxu");
25944 generate_exception_end(ctx, EXCP_RI);
25945 break;
25951 * Decode MXU pool05
25953 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25954 * +-----------+---------+-+-------------------+-------+-----------+
25955 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25956 * +-----------+---------+-+-------------------+-------+-----------+
25959 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25961 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25963 switch (opcode) {
25964 case OPC_MXU_S32STD:
25965 /* TODO: Implement emulation of S32STD instruction. */
25966 MIPS_INVAL("OPC_MXU_S32STD");
25967 generate_exception_end(ctx, EXCP_RI);
25968 break;
25969 case OPC_MXU_S32STDR:
25970 /* TODO: Implement emulation of S32STDR instruction. */
25971 MIPS_INVAL("OPC_MXU_S32STDR");
25972 generate_exception_end(ctx, EXCP_RI);
25973 break;
25974 default:
25975 MIPS_INVAL("decode_opc_mxu");
25976 generate_exception_end(ctx, EXCP_RI);
25977 break;
25983 * Decode MXU pool06
25985 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25986 * +-----------+---------+---------+---+-------+-------+-----------+
25987 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25988 * +-----------+---------+---------+---+-------+-------+-----------+
25991 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25993 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25995 switch (opcode) {
25996 case OPC_MXU_S32LDDV:
25997 /* TODO: Implement emulation of S32LDDV instruction. */
25998 MIPS_INVAL("OPC_MXU_S32LDDV");
25999 generate_exception_end(ctx, EXCP_RI);
26000 break;
26001 case OPC_MXU_S32LDDVR:
26002 /* TODO: Implement emulation of S32LDDVR instruction. */
26003 MIPS_INVAL("OPC_MXU_S32LDDVR");
26004 generate_exception_end(ctx, EXCP_RI);
26005 break;
26006 default:
26007 MIPS_INVAL("decode_opc_mxu");
26008 generate_exception_end(ctx, EXCP_RI);
26009 break;
26015 * Decode MXU pool07
26017 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26018 * +-----------+---------+---------+---+-------+-------+-----------+
26019 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26020 * +-----------+---------+---------+---+-------+-------+-----------+
26023 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26025 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26027 switch (opcode) {
26028 case OPC_MXU_S32STDV:
26029 /* TODO: Implement emulation of S32TDV instruction. */
26030 MIPS_INVAL("OPC_MXU_S32TDV");
26031 generate_exception_end(ctx, EXCP_RI);
26032 break;
26033 case OPC_MXU_S32STDVR:
26034 /* TODO: Implement emulation of S32TDVR instruction. */
26035 MIPS_INVAL("OPC_MXU_S32TDVR");
26036 generate_exception_end(ctx, EXCP_RI);
26037 break;
26038 default:
26039 MIPS_INVAL("decode_opc_mxu");
26040 generate_exception_end(ctx, EXCP_RI);
26041 break;
26047 * Decode MXU pool08
26049 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26050 * +-----------+---------+-+-------------------+-------+-----------+
26051 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26052 * +-----------+---------+-+-------------------+-------+-----------+
26055 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26057 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26059 switch (opcode) {
26060 case OPC_MXU_S32LDI:
26061 /* TODO: Implement emulation of S32LDI instruction. */
26062 MIPS_INVAL("OPC_MXU_S32LDI");
26063 generate_exception_end(ctx, EXCP_RI);
26064 break;
26065 case OPC_MXU_S32LDIR:
26066 /* TODO: Implement emulation of S32LDIR instruction. */
26067 MIPS_INVAL("OPC_MXU_S32LDIR");
26068 generate_exception_end(ctx, EXCP_RI);
26069 break;
26070 default:
26071 MIPS_INVAL("decode_opc_mxu");
26072 generate_exception_end(ctx, EXCP_RI);
26073 break;
26079 * Decode MXU pool09
26081 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26082 * +-----------+---------+-+-------------------+-------+-----------+
26083 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26084 * +-----------+---------+-+-------------------+-------+-----------+
26087 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26089 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26091 switch (opcode) {
26092 case OPC_MXU_S32SDI:
26093 /* TODO: Implement emulation of S32SDI instruction. */
26094 MIPS_INVAL("OPC_MXU_S32SDI");
26095 generate_exception_end(ctx, EXCP_RI);
26096 break;
26097 case OPC_MXU_S32SDIR:
26098 /* TODO: Implement emulation of S32SDIR instruction. */
26099 MIPS_INVAL("OPC_MXU_S32SDIR");
26100 generate_exception_end(ctx, EXCP_RI);
26101 break;
26102 default:
26103 MIPS_INVAL("decode_opc_mxu");
26104 generate_exception_end(ctx, EXCP_RI);
26105 break;
26111 * Decode MXU pool10
26113 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26114 * +-----------+---------+---------+---+-------+-------+-----------+
26115 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26116 * +-----------+---------+---------+---+-------+-------+-----------+
26119 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26121 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26123 switch (opcode) {
26124 case OPC_MXU_S32LDIV:
26125 /* TODO: Implement emulation of S32LDIV instruction. */
26126 MIPS_INVAL("OPC_MXU_S32LDIV");
26127 generate_exception_end(ctx, EXCP_RI);
26128 break;
26129 case OPC_MXU_S32LDIVR:
26130 /* TODO: Implement emulation of S32LDIVR instruction. */
26131 MIPS_INVAL("OPC_MXU_S32LDIVR");
26132 generate_exception_end(ctx, EXCP_RI);
26133 break;
26134 default:
26135 MIPS_INVAL("decode_opc_mxu");
26136 generate_exception_end(ctx, EXCP_RI);
26137 break;
26143 * Decode MXU pool11
26145 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26146 * +-----------+---------+---------+---+-------+-------+-----------+
26147 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26148 * +-----------+---------+---------+---+-------+-------+-----------+
26151 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26153 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26155 switch (opcode) {
26156 case OPC_MXU_S32SDIV:
26157 /* TODO: Implement emulation of S32SDIV instruction. */
26158 MIPS_INVAL("OPC_MXU_S32SDIV");
26159 generate_exception_end(ctx, EXCP_RI);
26160 break;
26161 case OPC_MXU_S32SDIVR:
26162 /* TODO: Implement emulation of S32SDIVR instruction. */
26163 MIPS_INVAL("OPC_MXU_S32SDIVR");
26164 generate_exception_end(ctx, EXCP_RI);
26165 break;
26166 default:
26167 MIPS_INVAL("decode_opc_mxu");
26168 generate_exception_end(ctx, EXCP_RI);
26169 break;
26175 * Decode MXU pool12
26177 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26178 * +-----------+---+---+-------+-------+-------+-------+-----------+
26179 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26180 * +-----------+---+---+-------+-------+-------+-------+-----------+
26183 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26185 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26187 switch (opcode) {
26188 case OPC_MXU_D32ACC:
26189 /* TODO: Implement emulation of D32ACC instruction. */
26190 MIPS_INVAL("OPC_MXU_D32ACC");
26191 generate_exception_end(ctx, EXCP_RI);
26192 break;
26193 case OPC_MXU_D32ACCM:
26194 /* TODO: Implement emulation of D32ACCM instruction. */
26195 MIPS_INVAL("OPC_MXU_D32ACCM");
26196 generate_exception_end(ctx, EXCP_RI);
26197 break;
26198 case OPC_MXU_D32ASUM:
26199 /* TODO: Implement emulation of D32ASUM instruction. */
26200 MIPS_INVAL("OPC_MXU_D32ASUM");
26201 generate_exception_end(ctx, EXCP_RI);
26202 break;
26203 default:
26204 MIPS_INVAL("decode_opc_mxu");
26205 generate_exception_end(ctx, EXCP_RI);
26206 break;
26212 * Decode MXU pool13
26214 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26215 * +-----------+---+---+-------+-------+-------+-------+-----------+
26216 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26217 * +-----------+---+---+-------+-------+-------+-------+-----------+
26220 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26222 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26224 switch (opcode) {
26225 case OPC_MXU_Q16ACC:
26226 /* TODO: Implement emulation of Q16ACC instruction. */
26227 MIPS_INVAL("OPC_MXU_Q16ACC");
26228 generate_exception_end(ctx, EXCP_RI);
26229 break;
26230 case OPC_MXU_Q16ACCM:
26231 /* TODO: Implement emulation of Q16ACCM instruction. */
26232 MIPS_INVAL("OPC_MXU_Q16ACCM");
26233 generate_exception_end(ctx, EXCP_RI);
26234 break;
26235 case OPC_MXU_Q16ASUM:
26236 /* TODO: Implement emulation of Q16ASUM instruction. */
26237 MIPS_INVAL("OPC_MXU_Q16ASUM");
26238 generate_exception_end(ctx, EXCP_RI);
26239 break;
26240 default:
26241 MIPS_INVAL("decode_opc_mxu");
26242 generate_exception_end(ctx, EXCP_RI);
26243 break;
26249 * Decode MXU pool14
26251 * Q8ADDE, Q8ACCE:
26252 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26253 * +-----------+---+---+-------+-------+-------+-------+-----------+
26254 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26255 * +-----------+---+---+-------+-------+-------+-------+-----------+
26257 * D8SUM, D8SUMC:
26258 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26259 * +-----------+---+---+-------+-------+-------+-------+-----------+
26260 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26261 * +-----------+---+---+-------+-------+-------+-------+-----------+
26264 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26266 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26268 switch (opcode) {
26269 case OPC_MXU_Q8ADDE:
26270 /* TODO: Implement emulation of Q8ADDE instruction. */
26271 MIPS_INVAL("OPC_MXU_Q8ADDE");
26272 generate_exception_end(ctx, EXCP_RI);
26273 break;
26274 case OPC_MXU_D8SUM:
26275 /* TODO: Implement emulation of D8SUM instruction. */
26276 MIPS_INVAL("OPC_MXU_D8SUM");
26277 generate_exception_end(ctx, EXCP_RI);
26278 break;
26279 case OPC_MXU_D8SUMC:
26280 /* TODO: Implement emulation of D8SUMC instruction. */
26281 MIPS_INVAL("OPC_MXU_D8SUMC");
26282 generate_exception_end(ctx, EXCP_RI);
26283 break;
26284 default:
26285 MIPS_INVAL("decode_opc_mxu");
26286 generate_exception_end(ctx, EXCP_RI);
26287 break;
26293 * Decode MXU pool15
26295 * S32MUL, S32MULU, S32EXTRV:
26296 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26297 * +-----------+---------+---------+---+-------+-------+-----------+
26298 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26299 * +-----------+---------+---------+---+-------+-------+-----------+
26301 * S32EXTR:
26302 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26303 * +-----------+---------+---------+---+-------+-------+-----------+
26304 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26305 * +-----------+---------+---------+---+-------+-------+-----------+
26308 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26310 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26312 switch (opcode) {
26313 case OPC_MXU_S32MUL:
26314 /* TODO: Implement emulation of S32MUL instruction. */
26315 MIPS_INVAL("OPC_MXU_S32MUL");
26316 generate_exception_end(ctx, EXCP_RI);
26317 break;
26318 case OPC_MXU_S32MULU:
26319 /* TODO: Implement emulation of S32MULU instruction. */
26320 MIPS_INVAL("OPC_MXU_S32MULU");
26321 generate_exception_end(ctx, EXCP_RI);
26322 break;
26323 case OPC_MXU_S32EXTR:
26324 /* TODO: Implement emulation of S32EXTR instruction. */
26325 MIPS_INVAL("OPC_MXU_S32EXTR");
26326 generate_exception_end(ctx, EXCP_RI);
26327 break;
26328 case OPC_MXU_S32EXTRV:
26329 /* TODO: Implement emulation of S32EXTRV instruction. */
26330 MIPS_INVAL("OPC_MXU_S32EXTRV");
26331 generate_exception_end(ctx, EXCP_RI);
26332 break;
26333 default:
26334 MIPS_INVAL("decode_opc_mxu");
26335 generate_exception_end(ctx, EXCP_RI);
26336 break;
26342 * Decode MXU pool16
26344 * D32SARW:
26345 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26346 * +-----------+---------+-----+-------+-------+-------+-----------+
26347 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26348 * +-----------+---------+-----+-------+-------+-------+-----------+
26350 * S32ALN:
26351 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26352 * +-----------+---------+-----+-------+-------+-------+-----------+
26353 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26354 * +-----------+---------+-----+-------+-------+-------+-----------+
26356 * S32ALNI:
26357 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26358 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26359 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26360 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26362 * S32LUI:
26363 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26364 * +-----------+-----+---+-----+-------+---------------+-----------+
26365 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26366 * +-----------+-----+---+-----+-------+---------------+-----------+
26368 * S32NOR, S32AND, S32OR, S32XOR:
26369 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26370 * +-----------+---------+-----+-------+-------+-------+-----------+
26371 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26372 * +-----------+---------+-----+-------+-------+-------+-----------+
26375 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26377 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26379 switch (opcode) {
26380 case OPC_MXU_D32SARW:
26381 /* TODO: Implement emulation of D32SARW instruction. */
26382 MIPS_INVAL("OPC_MXU_D32SARW");
26383 generate_exception_end(ctx, EXCP_RI);
26384 break;
26385 case OPC_MXU_S32ALN:
26386 /* TODO: Implement emulation of S32ALN instruction. */
26387 MIPS_INVAL("OPC_MXU_S32ALN");
26388 generate_exception_end(ctx, EXCP_RI);
26389 break;
26390 case OPC_MXU_S32ALNI:
26391 gen_mxu_S32ALNI(ctx);
26392 break;
26393 case OPC_MXU_S32LUI:
26394 /* TODO: Implement emulation of S32LUI instruction. */
26395 MIPS_INVAL("OPC_MXU_S32LUI");
26396 generate_exception_end(ctx, EXCP_RI);
26397 break;
26398 case OPC_MXU_S32NOR:
26399 gen_mxu_S32NOR(ctx);
26400 break;
26401 case OPC_MXU_S32AND:
26402 gen_mxu_S32AND(ctx);
26403 break;
26404 case OPC_MXU_S32OR:
26405 gen_mxu_S32OR(ctx);
26406 break;
26407 case OPC_MXU_S32XOR:
26408 gen_mxu_S32XOR(ctx);
26409 break;
26410 default:
26411 MIPS_INVAL("decode_opc_mxu");
26412 generate_exception_end(ctx, EXCP_RI);
26413 break;
26419 * Decode MXU pool17
26421 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26422 * +-----------+---------+---------+---+---------+-----+-----------+
26423 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26424 * +-----------+---------+---------+---+---------+-----+-----------+
26427 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26429 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26431 switch (opcode) {
26432 case OPC_MXU_LXW:
26433 /* TODO: Implement emulation of LXW instruction. */
26434 MIPS_INVAL("OPC_MXU_LXW");
26435 generate_exception_end(ctx, EXCP_RI);
26436 break;
26437 case OPC_MXU_LXH:
26438 /* TODO: Implement emulation of LXH instruction. */
26439 MIPS_INVAL("OPC_MXU_LXH");
26440 generate_exception_end(ctx, EXCP_RI);
26441 break;
26442 case OPC_MXU_LXHU:
26443 /* TODO: Implement emulation of LXHU instruction. */
26444 MIPS_INVAL("OPC_MXU_LXHU");
26445 generate_exception_end(ctx, EXCP_RI);
26446 break;
26447 case OPC_MXU_LXB:
26448 /* TODO: Implement emulation of LXB instruction. */
26449 MIPS_INVAL("OPC_MXU_LXB");
26450 generate_exception_end(ctx, EXCP_RI);
26451 break;
26452 case OPC_MXU_LXBU:
26453 /* TODO: Implement emulation of LXBU instruction. */
26454 MIPS_INVAL("OPC_MXU_LXBU");
26455 generate_exception_end(ctx, EXCP_RI);
26456 break;
26457 default:
26458 MIPS_INVAL("decode_opc_mxu");
26459 generate_exception_end(ctx, EXCP_RI);
26460 break;
26465 * Decode MXU pool18
26467 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26468 * +-----------+---------+-----+-------+-------+-------+-----------+
26469 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26470 * +-----------+---------+-----+-------+-------+-------+-----------+
26473 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26475 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26477 switch (opcode) {
26478 case OPC_MXU_D32SLLV:
26479 /* TODO: Implement emulation of D32SLLV instruction. */
26480 MIPS_INVAL("OPC_MXU_D32SLLV");
26481 generate_exception_end(ctx, EXCP_RI);
26482 break;
26483 case OPC_MXU_D32SLRV:
26484 /* TODO: Implement emulation of D32SLRV instruction. */
26485 MIPS_INVAL("OPC_MXU_D32SLRV");
26486 generate_exception_end(ctx, EXCP_RI);
26487 break;
26488 case OPC_MXU_D32SARV:
26489 /* TODO: Implement emulation of D32SARV instruction. */
26490 MIPS_INVAL("OPC_MXU_D32SARV");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26493 case OPC_MXU_Q16SLLV:
26494 /* TODO: Implement emulation of Q16SLLV instruction. */
26495 MIPS_INVAL("OPC_MXU_Q16SLLV");
26496 generate_exception_end(ctx, EXCP_RI);
26497 break;
26498 case OPC_MXU_Q16SLRV:
26499 /* TODO: Implement emulation of Q16SLRV instruction. */
26500 MIPS_INVAL("OPC_MXU_Q16SLRV");
26501 generate_exception_end(ctx, EXCP_RI);
26502 break;
26503 case OPC_MXU_Q16SARV:
26504 /* TODO: Implement emulation of Q16SARV instruction. */
26505 MIPS_INVAL("OPC_MXU_Q16SARV");
26506 generate_exception_end(ctx, EXCP_RI);
26507 break;
26508 default:
26509 MIPS_INVAL("decode_opc_mxu");
26510 generate_exception_end(ctx, EXCP_RI);
26511 break;
26517 * Decode MXU pool19
26519 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26520 * +-----------+---+---+-------+-------+-------+-------+-----------+
26521 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26522 * +-----------+---+---+-------+-------+-------+-------+-----------+
26525 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26527 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26529 switch (opcode) {
26530 case OPC_MXU_Q8MUL:
26531 case OPC_MXU_Q8MULSU:
26532 gen_mxu_q8mul_q8mulsu(ctx);
26533 break;
26534 default:
26535 MIPS_INVAL("decode_opc_mxu");
26536 generate_exception_end(ctx, EXCP_RI);
26537 break;
26543 * Decode MXU pool20
26545 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26546 * +-----------+---------+-----+-------+-------+-------+-----------+
26547 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26548 * +-----------+---------+-----+-------+-------+-------+-----------+
26551 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26553 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26555 switch (opcode) {
26556 case OPC_MXU_Q8MOVZ:
26557 /* TODO: Implement emulation of Q8MOVZ instruction. */
26558 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26559 generate_exception_end(ctx, EXCP_RI);
26560 break;
26561 case OPC_MXU_Q8MOVN:
26562 /* TODO: Implement emulation of Q8MOVN instruction. */
26563 MIPS_INVAL("OPC_MXU_Q8MOVN");
26564 generate_exception_end(ctx, EXCP_RI);
26565 break;
26566 case OPC_MXU_D16MOVZ:
26567 /* TODO: Implement emulation of D16MOVZ instruction. */
26568 MIPS_INVAL("OPC_MXU_D16MOVZ");
26569 generate_exception_end(ctx, EXCP_RI);
26570 break;
26571 case OPC_MXU_D16MOVN:
26572 /* TODO: Implement emulation of D16MOVN instruction. */
26573 MIPS_INVAL("OPC_MXU_D16MOVN");
26574 generate_exception_end(ctx, EXCP_RI);
26575 break;
26576 case OPC_MXU_S32MOVZ:
26577 /* TODO: Implement emulation of S32MOVZ instruction. */
26578 MIPS_INVAL("OPC_MXU_S32MOVZ");
26579 generate_exception_end(ctx, EXCP_RI);
26580 break;
26581 case OPC_MXU_S32MOVN:
26582 /* TODO: Implement emulation of S32MOVN instruction. */
26583 MIPS_INVAL("OPC_MXU_S32MOVN");
26584 generate_exception_end(ctx, EXCP_RI);
26585 break;
26586 default:
26587 MIPS_INVAL("decode_opc_mxu");
26588 generate_exception_end(ctx, EXCP_RI);
26589 break;
26595 * Decode MXU pool21
26597 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26598 * +-----------+---+---+-------+-------+-------+-------+-----------+
26599 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26600 * +-----------+---+---+-------+-------+-------+-------+-----------+
26603 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26605 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26607 switch (opcode) {
26608 case OPC_MXU_Q8MAC:
26609 /* TODO: Implement emulation of Q8MAC instruction. */
26610 MIPS_INVAL("OPC_MXU_Q8MAC");
26611 generate_exception_end(ctx, EXCP_RI);
26612 break;
26613 case OPC_MXU_Q8MACSU:
26614 /* TODO: Implement emulation of Q8MACSU instruction. */
26615 MIPS_INVAL("OPC_MXU_Q8MACSU");
26616 generate_exception_end(ctx, EXCP_RI);
26617 break;
26618 default:
26619 MIPS_INVAL("decode_opc_mxu");
26620 generate_exception_end(ctx, EXCP_RI);
26621 break;
26627 * Main MXU decoding function
26629 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26630 * +-----------+---------------------------------------+-----------+
26631 * | SPECIAL2 | |x x x x x x|
26632 * +-----------+---------------------------------------+-----------+
26635 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26638 * TODO: Investigate necessity of including handling of
26639 * CLZ, CLO, SDBB in this function, as they belong to
26640 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26642 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26644 if (opcode == OPC__MXU_MUL) {
26645 uint32_t rs, rt, rd, op1;
26647 rs = extract32(ctx->opcode, 21, 5);
26648 rt = extract32(ctx->opcode, 16, 5);
26649 rd = extract32(ctx->opcode, 11, 5);
26650 op1 = MASK_SPECIAL2(ctx->opcode);
26652 gen_arith(ctx, op1, rd, rs, rt);
26654 return;
26657 if (opcode == OPC_MXU_S32M2I) {
26658 gen_mxu_s32m2i(ctx);
26659 return;
26662 if (opcode == OPC_MXU_S32I2M) {
26663 gen_mxu_s32i2m(ctx);
26664 return;
26668 TCGv t_mxu_cr = tcg_temp_new();
26669 TCGLabel *l_exit = gen_new_label();
26671 gen_load_mxu_cr(t_mxu_cr);
26672 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26673 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26675 switch (opcode) {
26676 case OPC_MXU_S32MADD:
26677 /* TODO: Implement emulation of S32MADD instruction. */
26678 MIPS_INVAL("OPC_MXU_S32MADD");
26679 generate_exception_end(ctx, EXCP_RI);
26680 break;
26681 case OPC_MXU_S32MADDU:
26682 /* TODO: Implement emulation of S32MADDU instruction. */
26683 MIPS_INVAL("OPC_MXU_S32MADDU");
26684 generate_exception_end(ctx, EXCP_RI);
26685 break;
26686 case OPC_MXU__POOL00:
26687 decode_opc_mxu__pool00(env, ctx);
26688 break;
26689 case OPC_MXU_S32MSUB:
26690 /* TODO: Implement emulation of S32MSUB instruction. */
26691 MIPS_INVAL("OPC_MXU_S32MSUB");
26692 generate_exception_end(ctx, EXCP_RI);
26693 break;
26694 case OPC_MXU_S32MSUBU:
26695 /* TODO: Implement emulation of S32MSUBU instruction. */
26696 MIPS_INVAL("OPC_MXU_S32MSUBU");
26697 generate_exception_end(ctx, EXCP_RI);
26698 break;
26699 case OPC_MXU__POOL01:
26700 decode_opc_mxu__pool01(env, ctx);
26701 break;
26702 case OPC_MXU__POOL02:
26703 decode_opc_mxu__pool02(env, ctx);
26704 break;
26705 case OPC_MXU_D16MUL:
26706 gen_mxu_d16mul(ctx);
26707 break;
26708 case OPC_MXU__POOL03:
26709 decode_opc_mxu__pool03(env, ctx);
26710 break;
26711 case OPC_MXU_D16MAC:
26712 gen_mxu_d16mac(ctx);
26713 break;
26714 case OPC_MXU_D16MACF:
26715 /* TODO: Implement emulation of D16MACF instruction. */
26716 MIPS_INVAL("OPC_MXU_D16MACF");
26717 generate_exception_end(ctx, EXCP_RI);
26718 break;
26719 case OPC_MXU_D16MADL:
26720 /* TODO: Implement emulation of D16MADL instruction. */
26721 MIPS_INVAL("OPC_MXU_D16MADL");
26722 generate_exception_end(ctx, EXCP_RI);
26723 break;
26724 case OPC_MXU_S16MAD:
26725 /* TODO: Implement emulation of S16MAD instruction. */
26726 MIPS_INVAL("OPC_MXU_S16MAD");
26727 generate_exception_end(ctx, EXCP_RI);
26728 break;
26729 case OPC_MXU_Q16ADD:
26730 /* TODO: Implement emulation of Q16ADD instruction. */
26731 MIPS_INVAL("OPC_MXU_Q16ADD");
26732 generate_exception_end(ctx, EXCP_RI);
26733 break;
26734 case OPC_MXU_D16MACE:
26735 /* TODO: Implement emulation of D16MACE instruction. */
26736 MIPS_INVAL("OPC_MXU_D16MACE");
26737 generate_exception_end(ctx, EXCP_RI);
26738 break;
26739 case OPC_MXU__POOL04:
26740 decode_opc_mxu__pool04(env, ctx);
26741 break;
26742 case OPC_MXU__POOL05:
26743 decode_opc_mxu__pool05(env, ctx);
26744 break;
26745 case OPC_MXU__POOL06:
26746 decode_opc_mxu__pool06(env, ctx);
26747 break;
26748 case OPC_MXU__POOL07:
26749 decode_opc_mxu__pool07(env, ctx);
26750 break;
26751 case OPC_MXU__POOL08:
26752 decode_opc_mxu__pool08(env, ctx);
26753 break;
26754 case OPC_MXU__POOL09:
26755 decode_opc_mxu__pool09(env, ctx);
26756 break;
26757 case OPC_MXU__POOL10:
26758 decode_opc_mxu__pool10(env, ctx);
26759 break;
26760 case OPC_MXU__POOL11:
26761 decode_opc_mxu__pool11(env, ctx);
26762 break;
26763 case OPC_MXU_D32ADD:
26764 /* TODO: Implement emulation of D32ADD instruction. */
26765 MIPS_INVAL("OPC_MXU_D32ADD");
26766 generate_exception_end(ctx, EXCP_RI);
26767 break;
26768 case OPC_MXU__POOL12:
26769 decode_opc_mxu__pool12(env, ctx);
26770 break;
26771 case OPC_MXU__POOL13:
26772 decode_opc_mxu__pool13(env, ctx);
26773 break;
26774 case OPC_MXU__POOL14:
26775 decode_opc_mxu__pool14(env, ctx);
26776 break;
26777 case OPC_MXU_Q8ACCE:
26778 /* TODO: Implement emulation of Q8ACCE instruction. */
26779 MIPS_INVAL("OPC_MXU_Q8ACCE");
26780 generate_exception_end(ctx, EXCP_RI);
26781 break;
26782 case OPC_MXU_S8LDD:
26783 gen_mxu_s8ldd(ctx);
26784 break;
26785 case OPC_MXU_S8STD:
26786 /* TODO: Implement emulation of S8STD instruction. */
26787 MIPS_INVAL("OPC_MXU_S8STD");
26788 generate_exception_end(ctx, EXCP_RI);
26789 break;
26790 case OPC_MXU_S8LDI:
26791 /* TODO: Implement emulation of S8LDI instruction. */
26792 MIPS_INVAL("OPC_MXU_S8LDI");
26793 generate_exception_end(ctx, EXCP_RI);
26794 break;
26795 case OPC_MXU_S8SDI:
26796 /* TODO: Implement emulation of S8SDI instruction. */
26797 MIPS_INVAL("OPC_MXU_S8SDI");
26798 generate_exception_end(ctx, EXCP_RI);
26799 break;
26800 case OPC_MXU__POOL15:
26801 decode_opc_mxu__pool15(env, ctx);
26802 break;
26803 case OPC_MXU__POOL16:
26804 decode_opc_mxu__pool16(env, ctx);
26805 break;
26806 case OPC_MXU__POOL17:
26807 decode_opc_mxu__pool17(env, ctx);
26808 break;
26809 case OPC_MXU_S16LDD:
26810 /* TODO: Implement emulation of S16LDD instruction. */
26811 MIPS_INVAL("OPC_MXU_S16LDD");
26812 generate_exception_end(ctx, EXCP_RI);
26813 break;
26814 case OPC_MXU_S16STD:
26815 /* TODO: Implement emulation of S16STD instruction. */
26816 MIPS_INVAL("OPC_MXU_S16STD");
26817 generate_exception_end(ctx, EXCP_RI);
26818 break;
26819 case OPC_MXU_S16LDI:
26820 /* TODO: Implement emulation of S16LDI instruction. */
26821 MIPS_INVAL("OPC_MXU_S16LDI");
26822 generate_exception_end(ctx, EXCP_RI);
26823 break;
26824 case OPC_MXU_S16SDI:
26825 /* TODO: Implement emulation of S16SDI instruction. */
26826 MIPS_INVAL("OPC_MXU_S16SDI");
26827 generate_exception_end(ctx, EXCP_RI);
26828 break;
26829 case OPC_MXU_D32SLL:
26830 /* TODO: Implement emulation of D32SLL instruction. */
26831 MIPS_INVAL("OPC_MXU_D32SLL");
26832 generate_exception_end(ctx, EXCP_RI);
26833 break;
26834 case OPC_MXU_D32SLR:
26835 /* TODO: Implement emulation of D32SLR instruction. */
26836 MIPS_INVAL("OPC_MXU_D32SLR");
26837 generate_exception_end(ctx, EXCP_RI);
26838 break;
26839 case OPC_MXU_D32SARL:
26840 /* TODO: Implement emulation of D32SARL instruction. */
26841 MIPS_INVAL("OPC_MXU_D32SARL");
26842 generate_exception_end(ctx, EXCP_RI);
26843 break;
26844 case OPC_MXU_D32SAR:
26845 /* TODO: Implement emulation of D32SAR instruction. */
26846 MIPS_INVAL("OPC_MXU_D32SAR");
26847 generate_exception_end(ctx, EXCP_RI);
26848 break;
26849 case OPC_MXU_Q16SLL:
26850 /* TODO: Implement emulation of Q16SLL instruction. */
26851 MIPS_INVAL("OPC_MXU_Q16SLL");
26852 generate_exception_end(ctx, EXCP_RI);
26853 break;
26854 case OPC_MXU_Q16SLR:
26855 /* TODO: Implement emulation of Q16SLR instruction. */
26856 MIPS_INVAL("OPC_MXU_Q16SLR");
26857 generate_exception_end(ctx, EXCP_RI);
26858 break;
26859 case OPC_MXU__POOL18:
26860 decode_opc_mxu__pool18(env, ctx);
26861 break;
26862 case OPC_MXU_Q16SAR:
26863 /* TODO: Implement emulation of Q16SAR instruction. */
26864 MIPS_INVAL("OPC_MXU_Q16SAR");
26865 generate_exception_end(ctx, EXCP_RI);
26866 break;
26867 case OPC_MXU__POOL19:
26868 decode_opc_mxu__pool19(env, ctx);
26869 break;
26870 case OPC_MXU__POOL20:
26871 decode_opc_mxu__pool20(env, ctx);
26872 break;
26873 case OPC_MXU__POOL21:
26874 decode_opc_mxu__pool21(env, ctx);
26875 break;
26876 case OPC_MXU_Q16SCOP:
26877 /* TODO: Implement emulation of Q16SCOP instruction. */
26878 MIPS_INVAL("OPC_MXU_Q16SCOP");
26879 generate_exception_end(ctx, EXCP_RI);
26880 break;
26881 case OPC_MXU_Q8MADL:
26882 /* TODO: Implement emulation of Q8MADL instruction. */
26883 MIPS_INVAL("OPC_MXU_Q8MADL");
26884 generate_exception_end(ctx, EXCP_RI);
26885 break;
26886 case OPC_MXU_S32SFL:
26887 /* TODO: Implement emulation of S32SFL instruction. */
26888 MIPS_INVAL("OPC_MXU_S32SFL");
26889 generate_exception_end(ctx, EXCP_RI);
26890 break;
26891 case OPC_MXU_Q8SAD:
26892 /* TODO: Implement emulation of Q8SAD instruction. */
26893 MIPS_INVAL("OPC_MXU_Q8SAD");
26894 generate_exception_end(ctx, EXCP_RI);
26895 break;
26896 default:
26897 MIPS_INVAL("decode_opc_mxu");
26898 generate_exception_end(ctx, EXCP_RI);
26901 gen_set_label(l_exit);
26902 tcg_temp_free(t_mxu_cr);
26906 #endif /* !defined(TARGET_MIPS64) */
26909 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26911 int rs, rt, rd;
26912 uint32_t op1;
26914 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26916 rs = (ctx->opcode >> 21) & 0x1f;
26917 rt = (ctx->opcode >> 16) & 0x1f;
26918 rd = (ctx->opcode >> 11) & 0x1f;
26920 op1 = MASK_SPECIAL2(ctx->opcode);
26921 switch (op1) {
26922 case OPC_MADD: /* Multiply and add/sub */
26923 case OPC_MADDU:
26924 case OPC_MSUB:
26925 case OPC_MSUBU:
26926 check_insn(ctx, ISA_MIPS32);
26927 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26928 break;
26929 case OPC_MUL:
26930 gen_arith(ctx, op1, rd, rs, rt);
26931 break;
26932 case OPC_DIV_G_2F:
26933 case OPC_DIVU_G_2F:
26934 case OPC_MULT_G_2F:
26935 case OPC_MULTU_G_2F:
26936 case OPC_MOD_G_2F:
26937 case OPC_MODU_G_2F:
26938 check_insn(ctx, INSN_LOONGSON2F);
26939 gen_loongson_integer(ctx, op1, rd, rs, rt);
26940 break;
26941 case OPC_CLO:
26942 case OPC_CLZ:
26943 check_insn(ctx, ISA_MIPS32);
26944 gen_cl(ctx, op1, rd, rs);
26945 break;
26946 case OPC_SDBBP:
26947 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26948 gen_helper_do_semihosting(cpu_env);
26949 } else {
26951 * XXX: not clear which exception should be raised
26952 * when in debug mode...
26954 check_insn(ctx, ISA_MIPS32);
26955 generate_exception_end(ctx, EXCP_DBp);
26957 break;
26958 #if defined(TARGET_MIPS64)
26959 case OPC_DCLO:
26960 case OPC_DCLZ:
26961 check_insn(ctx, ISA_MIPS64);
26962 check_mips_64(ctx);
26963 gen_cl(ctx, op1, rd, rs);
26964 break;
26965 case OPC_DMULT_G_2F:
26966 case OPC_DMULTU_G_2F:
26967 case OPC_DDIV_G_2F:
26968 case OPC_DDIVU_G_2F:
26969 case OPC_DMOD_G_2F:
26970 case OPC_DMODU_G_2F:
26971 check_insn(ctx, INSN_LOONGSON2F);
26972 gen_loongson_integer(ctx, op1, rd, rs, rt);
26973 break;
26974 #endif
26975 default: /* Invalid */
26976 MIPS_INVAL("special2_legacy");
26977 generate_exception_end(ctx, EXCP_RI);
26978 break;
26982 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26984 int rs, rt, rd, sa;
26985 uint32_t op1, op2;
26986 int16_t imm;
26988 rs = (ctx->opcode >> 21) & 0x1f;
26989 rt = (ctx->opcode >> 16) & 0x1f;
26990 rd = (ctx->opcode >> 11) & 0x1f;
26991 sa = (ctx->opcode >> 6) & 0x1f;
26992 imm = (int16_t)ctx->opcode >> 7;
26994 op1 = MASK_SPECIAL3(ctx->opcode);
26995 switch (op1) {
26996 case R6_OPC_PREF:
26997 if (rt >= 24) {
26998 /* hint codes 24-31 are reserved and signal RI */
26999 generate_exception_end(ctx, EXCP_RI);
27001 /* Treat as NOP. */
27002 break;
27003 case R6_OPC_CACHE:
27004 check_cp0_enabled(ctx);
27005 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27006 gen_cache_operation(ctx, rt, rs, imm);
27008 break;
27009 case R6_OPC_SC:
27010 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27011 break;
27012 case R6_OPC_LL:
27013 gen_ld(ctx, op1, rt, rs, imm);
27014 break;
27015 case OPC_BSHFL:
27017 if (rd == 0) {
27018 /* Treat as NOP. */
27019 break;
27021 op2 = MASK_BSHFL(ctx->opcode);
27022 switch (op2) {
27023 case OPC_ALIGN:
27024 case OPC_ALIGN_1:
27025 case OPC_ALIGN_2:
27026 case OPC_ALIGN_3:
27027 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27028 break;
27029 case OPC_BITSWAP:
27030 gen_bitswap(ctx, op2, rd, rt);
27031 break;
27034 break;
27035 #if defined(TARGET_MIPS64)
27036 case R6_OPC_SCD:
27037 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27038 break;
27039 case R6_OPC_LLD:
27040 gen_ld(ctx, op1, rt, rs, imm);
27041 break;
27042 case OPC_DBSHFL:
27043 check_mips_64(ctx);
27045 if (rd == 0) {
27046 /* Treat as NOP. */
27047 break;
27049 op2 = MASK_DBSHFL(ctx->opcode);
27050 switch (op2) {
27051 case OPC_DALIGN:
27052 case OPC_DALIGN_1:
27053 case OPC_DALIGN_2:
27054 case OPC_DALIGN_3:
27055 case OPC_DALIGN_4:
27056 case OPC_DALIGN_5:
27057 case OPC_DALIGN_6:
27058 case OPC_DALIGN_7:
27059 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27060 break;
27061 case OPC_DBITSWAP:
27062 gen_bitswap(ctx, op2, rd, rt);
27063 break;
27067 break;
27068 #endif
27069 default: /* Invalid */
27070 MIPS_INVAL("special3_r6");
27071 generate_exception_end(ctx, EXCP_RI);
27072 break;
27076 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27078 int rs, rt, rd;
27079 uint32_t op1, op2;
27081 rs = (ctx->opcode >> 21) & 0x1f;
27082 rt = (ctx->opcode >> 16) & 0x1f;
27083 rd = (ctx->opcode >> 11) & 0x1f;
27085 op1 = MASK_SPECIAL3(ctx->opcode);
27086 switch (op1) {
27087 case OPC_DIV_G_2E:
27088 case OPC_DIVU_G_2E:
27089 case OPC_MOD_G_2E:
27090 case OPC_MODU_G_2E:
27091 case OPC_MULT_G_2E:
27092 case OPC_MULTU_G_2E:
27094 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27095 * the same mask and op1.
27097 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27098 op2 = MASK_ADDUH_QB(ctx->opcode);
27099 switch (op2) {
27100 case OPC_ADDUH_QB:
27101 case OPC_ADDUH_R_QB:
27102 case OPC_ADDQH_PH:
27103 case OPC_ADDQH_R_PH:
27104 case OPC_ADDQH_W:
27105 case OPC_ADDQH_R_W:
27106 case OPC_SUBUH_QB:
27107 case OPC_SUBUH_R_QB:
27108 case OPC_SUBQH_PH:
27109 case OPC_SUBQH_R_PH:
27110 case OPC_SUBQH_W:
27111 case OPC_SUBQH_R_W:
27112 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27113 break;
27114 case OPC_MUL_PH:
27115 case OPC_MUL_S_PH:
27116 case OPC_MULQ_S_W:
27117 case OPC_MULQ_RS_W:
27118 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27119 break;
27120 default:
27121 MIPS_INVAL("MASK ADDUH.QB");
27122 generate_exception_end(ctx, EXCP_RI);
27123 break;
27125 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27126 gen_loongson_integer(ctx, op1, rd, rs, rt);
27127 } else {
27128 generate_exception_end(ctx, EXCP_RI);
27130 break;
27131 case OPC_LX_DSP:
27132 op2 = MASK_LX(ctx->opcode);
27133 switch (op2) {
27134 #if defined(TARGET_MIPS64)
27135 case OPC_LDX:
27136 #endif
27137 case OPC_LBUX:
27138 case OPC_LHX:
27139 case OPC_LWX:
27140 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27141 break;
27142 default: /* Invalid */
27143 MIPS_INVAL("MASK LX");
27144 generate_exception_end(ctx, EXCP_RI);
27145 break;
27147 break;
27148 case OPC_ABSQ_S_PH_DSP:
27149 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27150 switch (op2) {
27151 case OPC_ABSQ_S_QB:
27152 case OPC_ABSQ_S_PH:
27153 case OPC_ABSQ_S_W:
27154 case OPC_PRECEQ_W_PHL:
27155 case OPC_PRECEQ_W_PHR:
27156 case OPC_PRECEQU_PH_QBL:
27157 case OPC_PRECEQU_PH_QBR:
27158 case OPC_PRECEQU_PH_QBLA:
27159 case OPC_PRECEQU_PH_QBRA:
27160 case OPC_PRECEU_PH_QBL:
27161 case OPC_PRECEU_PH_QBR:
27162 case OPC_PRECEU_PH_QBLA:
27163 case OPC_PRECEU_PH_QBRA:
27164 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27165 break;
27166 case OPC_BITREV:
27167 case OPC_REPL_QB:
27168 case OPC_REPLV_QB:
27169 case OPC_REPL_PH:
27170 case OPC_REPLV_PH:
27171 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27172 break;
27173 default:
27174 MIPS_INVAL("MASK ABSQ_S.PH");
27175 generate_exception_end(ctx, EXCP_RI);
27176 break;
27178 break;
27179 case OPC_ADDU_QB_DSP:
27180 op2 = MASK_ADDU_QB(ctx->opcode);
27181 switch (op2) {
27182 case OPC_ADDQ_PH:
27183 case OPC_ADDQ_S_PH:
27184 case OPC_ADDQ_S_W:
27185 case OPC_ADDU_QB:
27186 case OPC_ADDU_S_QB:
27187 case OPC_ADDU_PH:
27188 case OPC_ADDU_S_PH:
27189 case OPC_SUBQ_PH:
27190 case OPC_SUBQ_S_PH:
27191 case OPC_SUBQ_S_W:
27192 case OPC_SUBU_QB:
27193 case OPC_SUBU_S_QB:
27194 case OPC_SUBU_PH:
27195 case OPC_SUBU_S_PH:
27196 case OPC_ADDSC:
27197 case OPC_ADDWC:
27198 case OPC_MODSUB:
27199 case OPC_RADDU_W_QB:
27200 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27201 break;
27202 case OPC_MULEU_S_PH_QBL:
27203 case OPC_MULEU_S_PH_QBR:
27204 case OPC_MULQ_RS_PH:
27205 case OPC_MULEQ_S_W_PHL:
27206 case OPC_MULEQ_S_W_PHR:
27207 case OPC_MULQ_S_PH:
27208 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27209 break;
27210 default: /* Invalid */
27211 MIPS_INVAL("MASK ADDU.QB");
27212 generate_exception_end(ctx, EXCP_RI);
27213 break;
27216 break;
27217 case OPC_CMPU_EQ_QB_DSP:
27218 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27219 switch (op2) {
27220 case OPC_PRECR_SRA_PH_W:
27221 case OPC_PRECR_SRA_R_PH_W:
27222 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27223 break;
27224 case OPC_PRECR_QB_PH:
27225 case OPC_PRECRQ_QB_PH:
27226 case OPC_PRECRQ_PH_W:
27227 case OPC_PRECRQ_RS_PH_W:
27228 case OPC_PRECRQU_S_QB_PH:
27229 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27230 break;
27231 case OPC_CMPU_EQ_QB:
27232 case OPC_CMPU_LT_QB:
27233 case OPC_CMPU_LE_QB:
27234 case OPC_CMP_EQ_PH:
27235 case OPC_CMP_LT_PH:
27236 case OPC_CMP_LE_PH:
27237 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27238 break;
27239 case OPC_CMPGU_EQ_QB:
27240 case OPC_CMPGU_LT_QB:
27241 case OPC_CMPGU_LE_QB:
27242 case OPC_CMPGDU_EQ_QB:
27243 case OPC_CMPGDU_LT_QB:
27244 case OPC_CMPGDU_LE_QB:
27245 case OPC_PICK_QB:
27246 case OPC_PICK_PH:
27247 case OPC_PACKRL_PH:
27248 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27249 break;
27250 default: /* Invalid */
27251 MIPS_INVAL("MASK CMPU.EQ.QB");
27252 generate_exception_end(ctx, EXCP_RI);
27253 break;
27255 break;
27256 case OPC_SHLL_QB_DSP:
27257 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27258 break;
27259 case OPC_DPA_W_PH_DSP:
27260 op2 = MASK_DPA_W_PH(ctx->opcode);
27261 switch (op2) {
27262 case OPC_DPAU_H_QBL:
27263 case OPC_DPAU_H_QBR:
27264 case OPC_DPSU_H_QBL:
27265 case OPC_DPSU_H_QBR:
27266 case OPC_DPA_W_PH:
27267 case OPC_DPAX_W_PH:
27268 case OPC_DPAQ_S_W_PH:
27269 case OPC_DPAQX_S_W_PH:
27270 case OPC_DPAQX_SA_W_PH:
27271 case OPC_DPS_W_PH:
27272 case OPC_DPSX_W_PH:
27273 case OPC_DPSQ_S_W_PH:
27274 case OPC_DPSQX_S_W_PH:
27275 case OPC_DPSQX_SA_W_PH:
27276 case OPC_MULSAQ_S_W_PH:
27277 case OPC_DPAQ_SA_L_W:
27278 case OPC_DPSQ_SA_L_W:
27279 case OPC_MAQ_S_W_PHL:
27280 case OPC_MAQ_S_W_PHR:
27281 case OPC_MAQ_SA_W_PHL:
27282 case OPC_MAQ_SA_W_PHR:
27283 case OPC_MULSA_W_PH:
27284 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27285 break;
27286 default: /* Invalid */
27287 MIPS_INVAL("MASK DPAW.PH");
27288 generate_exception_end(ctx, EXCP_RI);
27289 break;
27291 break;
27292 case OPC_INSV_DSP:
27293 op2 = MASK_INSV(ctx->opcode);
27294 switch (op2) {
27295 case OPC_INSV:
27296 check_dsp(ctx);
27298 TCGv t0, t1;
27300 if (rt == 0) {
27301 break;
27304 t0 = tcg_temp_new();
27305 t1 = tcg_temp_new();
27307 gen_load_gpr(t0, rt);
27308 gen_load_gpr(t1, rs);
27310 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27312 tcg_temp_free(t0);
27313 tcg_temp_free(t1);
27314 break;
27316 default: /* Invalid */
27317 MIPS_INVAL("MASK INSV");
27318 generate_exception_end(ctx, EXCP_RI);
27319 break;
27321 break;
27322 case OPC_APPEND_DSP:
27323 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27324 break;
27325 case OPC_EXTR_W_DSP:
27326 op2 = MASK_EXTR_W(ctx->opcode);
27327 switch (op2) {
27328 case OPC_EXTR_W:
27329 case OPC_EXTR_R_W:
27330 case OPC_EXTR_RS_W:
27331 case OPC_EXTR_S_H:
27332 case OPC_EXTRV_S_H:
27333 case OPC_EXTRV_W:
27334 case OPC_EXTRV_R_W:
27335 case OPC_EXTRV_RS_W:
27336 case OPC_EXTP:
27337 case OPC_EXTPV:
27338 case OPC_EXTPDP:
27339 case OPC_EXTPDPV:
27340 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27341 break;
27342 case OPC_RDDSP:
27343 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27344 break;
27345 case OPC_SHILO:
27346 case OPC_SHILOV:
27347 case OPC_MTHLIP:
27348 case OPC_WRDSP:
27349 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27350 break;
27351 default: /* Invalid */
27352 MIPS_INVAL("MASK EXTR.W");
27353 generate_exception_end(ctx, EXCP_RI);
27354 break;
27356 break;
27357 #if defined(TARGET_MIPS64)
27358 case OPC_DDIV_G_2E:
27359 case OPC_DDIVU_G_2E:
27360 case OPC_DMULT_G_2E:
27361 case OPC_DMULTU_G_2E:
27362 case OPC_DMOD_G_2E:
27363 case OPC_DMODU_G_2E:
27364 check_insn(ctx, INSN_LOONGSON2E);
27365 gen_loongson_integer(ctx, op1, rd, rs, rt);
27366 break;
27367 case OPC_ABSQ_S_QH_DSP:
27368 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27369 switch (op2) {
27370 case OPC_PRECEQ_L_PWL:
27371 case OPC_PRECEQ_L_PWR:
27372 case OPC_PRECEQ_PW_QHL:
27373 case OPC_PRECEQ_PW_QHR:
27374 case OPC_PRECEQ_PW_QHLA:
27375 case OPC_PRECEQ_PW_QHRA:
27376 case OPC_PRECEQU_QH_OBL:
27377 case OPC_PRECEQU_QH_OBR:
27378 case OPC_PRECEQU_QH_OBLA:
27379 case OPC_PRECEQU_QH_OBRA:
27380 case OPC_PRECEU_QH_OBL:
27381 case OPC_PRECEU_QH_OBR:
27382 case OPC_PRECEU_QH_OBLA:
27383 case OPC_PRECEU_QH_OBRA:
27384 case OPC_ABSQ_S_OB:
27385 case OPC_ABSQ_S_PW:
27386 case OPC_ABSQ_S_QH:
27387 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27388 break;
27389 case OPC_REPL_OB:
27390 case OPC_REPL_PW:
27391 case OPC_REPL_QH:
27392 case OPC_REPLV_OB:
27393 case OPC_REPLV_PW:
27394 case OPC_REPLV_QH:
27395 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27396 break;
27397 default: /* Invalid */
27398 MIPS_INVAL("MASK ABSQ_S.QH");
27399 generate_exception_end(ctx, EXCP_RI);
27400 break;
27402 break;
27403 case OPC_ADDU_OB_DSP:
27404 op2 = MASK_ADDU_OB(ctx->opcode);
27405 switch (op2) {
27406 case OPC_RADDU_L_OB:
27407 case OPC_SUBQ_PW:
27408 case OPC_SUBQ_S_PW:
27409 case OPC_SUBQ_QH:
27410 case OPC_SUBQ_S_QH:
27411 case OPC_SUBU_OB:
27412 case OPC_SUBU_S_OB:
27413 case OPC_SUBU_QH:
27414 case OPC_SUBU_S_QH:
27415 case OPC_SUBUH_OB:
27416 case OPC_SUBUH_R_OB:
27417 case OPC_ADDQ_PW:
27418 case OPC_ADDQ_S_PW:
27419 case OPC_ADDQ_QH:
27420 case OPC_ADDQ_S_QH:
27421 case OPC_ADDU_OB:
27422 case OPC_ADDU_S_OB:
27423 case OPC_ADDU_QH:
27424 case OPC_ADDU_S_QH:
27425 case OPC_ADDUH_OB:
27426 case OPC_ADDUH_R_OB:
27427 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27428 break;
27429 case OPC_MULEQ_S_PW_QHL:
27430 case OPC_MULEQ_S_PW_QHR:
27431 case OPC_MULEU_S_QH_OBL:
27432 case OPC_MULEU_S_QH_OBR:
27433 case OPC_MULQ_RS_QH:
27434 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27435 break;
27436 default: /* Invalid */
27437 MIPS_INVAL("MASK ADDU.OB");
27438 generate_exception_end(ctx, EXCP_RI);
27439 break;
27441 break;
27442 case OPC_CMPU_EQ_OB_DSP:
27443 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27444 switch (op2) {
27445 case OPC_PRECR_SRA_QH_PW:
27446 case OPC_PRECR_SRA_R_QH_PW:
27447 /* Return value is rt. */
27448 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27449 break;
27450 case OPC_PRECR_OB_QH:
27451 case OPC_PRECRQ_OB_QH:
27452 case OPC_PRECRQ_PW_L:
27453 case OPC_PRECRQ_QH_PW:
27454 case OPC_PRECRQ_RS_QH_PW:
27455 case OPC_PRECRQU_S_OB_QH:
27456 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27457 break;
27458 case OPC_CMPU_EQ_OB:
27459 case OPC_CMPU_LT_OB:
27460 case OPC_CMPU_LE_OB:
27461 case OPC_CMP_EQ_QH:
27462 case OPC_CMP_LT_QH:
27463 case OPC_CMP_LE_QH:
27464 case OPC_CMP_EQ_PW:
27465 case OPC_CMP_LT_PW:
27466 case OPC_CMP_LE_PW:
27467 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27468 break;
27469 case OPC_CMPGDU_EQ_OB:
27470 case OPC_CMPGDU_LT_OB:
27471 case OPC_CMPGDU_LE_OB:
27472 case OPC_CMPGU_EQ_OB:
27473 case OPC_CMPGU_LT_OB:
27474 case OPC_CMPGU_LE_OB:
27475 case OPC_PACKRL_PW:
27476 case OPC_PICK_OB:
27477 case OPC_PICK_PW:
27478 case OPC_PICK_QH:
27479 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27480 break;
27481 default: /* Invalid */
27482 MIPS_INVAL("MASK CMPU_EQ.OB");
27483 generate_exception_end(ctx, EXCP_RI);
27484 break;
27486 break;
27487 case OPC_DAPPEND_DSP:
27488 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27489 break;
27490 case OPC_DEXTR_W_DSP:
27491 op2 = MASK_DEXTR_W(ctx->opcode);
27492 switch (op2) {
27493 case OPC_DEXTP:
27494 case OPC_DEXTPDP:
27495 case OPC_DEXTPDPV:
27496 case OPC_DEXTPV:
27497 case OPC_DEXTR_L:
27498 case OPC_DEXTR_R_L:
27499 case OPC_DEXTR_RS_L:
27500 case OPC_DEXTR_W:
27501 case OPC_DEXTR_R_W:
27502 case OPC_DEXTR_RS_W:
27503 case OPC_DEXTR_S_H:
27504 case OPC_DEXTRV_L:
27505 case OPC_DEXTRV_R_L:
27506 case OPC_DEXTRV_RS_L:
27507 case OPC_DEXTRV_S_H:
27508 case OPC_DEXTRV_W:
27509 case OPC_DEXTRV_R_W:
27510 case OPC_DEXTRV_RS_W:
27511 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27512 break;
27513 case OPC_DMTHLIP:
27514 case OPC_DSHILO:
27515 case OPC_DSHILOV:
27516 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27517 break;
27518 default: /* Invalid */
27519 MIPS_INVAL("MASK EXTR.W");
27520 generate_exception_end(ctx, EXCP_RI);
27521 break;
27523 break;
27524 case OPC_DPAQ_W_QH_DSP:
27525 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27526 switch (op2) {
27527 case OPC_DPAU_H_OBL:
27528 case OPC_DPAU_H_OBR:
27529 case OPC_DPSU_H_OBL:
27530 case OPC_DPSU_H_OBR:
27531 case OPC_DPA_W_QH:
27532 case OPC_DPAQ_S_W_QH:
27533 case OPC_DPS_W_QH:
27534 case OPC_DPSQ_S_W_QH:
27535 case OPC_MULSAQ_S_W_QH:
27536 case OPC_DPAQ_SA_L_PW:
27537 case OPC_DPSQ_SA_L_PW:
27538 case OPC_MULSAQ_S_L_PW:
27539 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27540 break;
27541 case OPC_MAQ_S_W_QHLL:
27542 case OPC_MAQ_S_W_QHLR:
27543 case OPC_MAQ_S_W_QHRL:
27544 case OPC_MAQ_S_W_QHRR:
27545 case OPC_MAQ_SA_W_QHLL:
27546 case OPC_MAQ_SA_W_QHLR:
27547 case OPC_MAQ_SA_W_QHRL:
27548 case OPC_MAQ_SA_W_QHRR:
27549 case OPC_MAQ_S_L_PWL:
27550 case OPC_MAQ_S_L_PWR:
27551 case OPC_DMADD:
27552 case OPC_DMADDU:
27553 case OPC_DMSUB:
27554 case OPC_DMSUBU:
27555 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27556 break;
27557 default: /* Invalid */
27558 MIPS_INVAL("MASK DPAQ.W.QH");
27559 generate_exception_end(ctx, EXCP_RI);
27560 break;
27562 break;
27563 case OPC_DINSV_DSP:
27564 op2 = MASK_INSV(ctx->opcode);
27565 switch (op2) {
27566 case OPC_DINSV:
27568 TCGv t0, t1;
27570 if (rt == 0) {
27571 break;
27573 check_dsp(ctx);
27575 t0 = tcg_temp_new();
27576 t1 = tcg_temp_new();
27578 gen_load_gpr(t0, rt);
27579 gen_load_gpr(t1, rs);
27581 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27583 tcg_temp_free(t0);
27584 tcg_temp_free(t1);
27585 break;
27587 default: /* Invalid */
27588 MIPS_INVAL("MASK DINSV");
27589 generate_exception_end(ctx, EXCP_RI);
27590 break;
27592 break;
27593 case OPC_SHLL_OB_DSP:
27594 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27595 break;
27596 #endif
27597 default: /* Invalid */
27598 MIPS_INVAL("special3_legacy");
27599 generate_exception_end(ctx, EXCP_RI);
27600 break;
27605 #if defined(TARGET_MIPS64)
27607 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27609 uint32_t opc = MASK_MMI0(ctx->opcode);
27611 switch (opc) {
27612 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27613 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27614 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27615 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27616 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27617 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27618 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27619 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27620 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27621 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27622 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27623 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27624 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27625 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27626 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27627 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27628 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27629 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27630 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27631 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27632 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27633 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27634 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27635 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27636 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27637 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27638 break;
27639 default:
27640 MIPS_INVAL("TX79 MMI class MMI0");
27641 generate_exception_end(ctx, EXCP_RI);
27642 break;
27646 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27648 uint32_t opc = MASK_MMI1(ctx->opcode);
27650 switch (opc) {
27651 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27652 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27653 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27654 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27655 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27656 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27657 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27658 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27659 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27660 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27661 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27662 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27663 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27664 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27665 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27666 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27667 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27668 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27669 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27670 break;
27671 default:
27672 MIPS_INVAL("TX79 MMI class MMI1");
27673 generate_exception_end(ctx, EXCP_RI);
27674 break;
27678 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27680 uint32_t opc = MASK_MMI2(ctx->opcode);
27682 switch (opc) {
27683 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27684 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27685 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27686 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27687 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27688 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27689 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27690 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27691 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27692 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27693 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27694 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27695 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27696 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27697 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27698 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27699 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27700 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27701 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27702 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27703 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27704 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27705 break;
27706 case MMI_OPC_2_PCPYLD:
27707 gen_mmi_pcpyld(ctx);
27708 break;
27709 default:
27710 MIPS_INVAL("TX79 MMI class MMI2");
27711 generate_exception_end(ctx, EXCP_RI);
27712 break;
27716 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27718 uint32_t opc = MASK_MMI3(ctx->opcode);
27720 switch (opc) {
27721 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27722 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27723 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27724 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27725 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27726 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27727 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27728 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27729 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27730 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27731 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27732 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27733 break;
27734 case MMI_OPC_3_PCPYH:
27735 gen_mmi_pcpyh(ctx);
27736 break;
27737 case MMI_OPC_3_PCPYUD:
27738 gen_mmi_pcpyud(ctx);
27739 break;
27740 default:
27741 MIPS_INVAL("TX79 MMI class MMI3");
27742 generate_exception_end(ctx, EXCP_RI);
27743 break;
27747 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27749 uint32_t opc = MASK_MMI(ctx->opcode);
27750 int rs = extract32(ctx->opcode, 21, 5);
27751 int rt = extract32(ctx->opcode, 16, 5);
27752 int rd = extract32(ctx->opcode, 11, 5);
27754 switch (opc) {
27755 case MMI_OPC_CLASS_MMI0:
27756 decode_mmi0(env, ctx);
27757 break;
27758 case MMI_OPC_CLASS_MMI1:
27759 decode_mmi1(env, ctx);
27760 break;
27761 case MMI_OPC_CLASS_MMI2:
27762 decode_mmi2(env, ctx);
27763 break;
27764 case MMI_OPC_CLASS_MMI3:
27765 decode_mmi3(env, ctx);
27766 break;
27767 case MMI_OPC_MULT1:
27768 case MMI_OPC_MULTU1:
27769 case MMI_OPC_MADD:
27770 case MMI_OPC_MADDU:
27771 case MMI_OPC_MADD1:
27772 case MMI_OPC_MADDU1:
27773 gen_mul_txx9(ctx, opc, rd, rs, rt);
27774 break;
27775 case MMI_OPC_DIV1:
27776 case MMI_OPC_DIVU1:
27777 gen_div1_tx79(ctx, opc, rs, rt);
27778 break;
27779 case MMI_OPC_MTLO1:
27780 case MMI_OPC_MTHI1:
27781 gen_HILO1_tx79(ctx, opc, rs);
27782 break;
27783 case MMI_OPC_MFLO1:
27784 case MMI_OPC_MFHI1:
27785 gen_HILO1_tx79(ctx, opc, rd);
27786 break;
27787 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27788 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27789 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27790 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27791 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27792 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27793 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27794 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27795 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27796 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27797 break;
27798 default:
27799 MIPS_INVAL("TX79 MMI class");
27800 generate_exception_end(ctx, EXCP_RI);
27801 break;
27805 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27807 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27810 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27812 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27816 * The TX79-specific instruction Store Quadword
27818 * +--------+-------+-------+------------------------+
27819 * | 011111 | base | rt | offset | SQ
27820 * +--------+-------+-------+------------------------+
27821 * 6 5 5 16
27823 * has the same opcode as the Read Hardware Register instruction
27825 * +--------+-------+-------+-------+-------+--------+
27826 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27827 * +--------+-------+-------+-------+-------+--------+
27828 * 6 5 5 5 5 6
27830 * that is required, trapped and emulated by the Linux kernel. However, all
27831 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27832 * offset is odd. Therefore all valid SQ instructions can execute normally.
27833 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27834 * between SQ and RDHWR, as the Linux kernel does.
27836 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27838 int base = extract32(ctx->opcode, 21, 5);
27839 int rt = extract32(ctx->opcode, 16, 5);
27840 int offset = extract32(ctx->opcode, 0, 16);
27842 #ifdef CONFIG_USER_ONLY
27843 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27844 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27846 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27847 int rd = extract32(ctx->opcode, 11, 5);
27849 gen_rdhwr(ctx, rt, rd, 0);
27850 return;
27852 #endif
27854 gen_mmi_sq(ctx, base, rt, offset);
27857 #endif
27859 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27861 int rs, rt, rd, sa;
27862 uint32_t op1, op2;
27863 int16_t imm;
27865 rs = (ctx->opcode >> 21) & 0x1f;
27866 rt = (ctx->opcode >> 16) & 0x1f;
27867 rd = (ctx->opcode >> 11) & 0x1f;
27868 sa = (ctx->opcode >> 6) & 0x1f;
27869 imm = sextract32(ctx->opcode, 7, 9);
27871 op1 = MASK_SPECIAL3(ctx->opcode);
27874 * EVA loads and stores overlap Loongson 2E instructions decoded by
27875 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27876 * EVA is absent.
27878 if (ctx->eva) {
27879 switch (op1) {
27880 case OPC_LWLE:
27881 case OPC_LWRE:
27882 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27883 /* fall through */
27884 case OPC_LBUE:
27885 case OPC_LHUE:
27886 case OPC_LBE:
27887 case OPC_LHE:
27888 case OPC_LLE:
27889 case OPC_LWE:
27890 check_cp0_enabled(ctx);
27891 gen_ld(ctx, op1, rt, rs, imm);
27892 return;
27893 case OPC_SWLE:
27894 case OPC_SWRE:
27895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27896 /* fall through */
27897 case OPC_SBE:
27898 case OPC_SHE:
27899 case OPC_SWE:
27900 check_cp0_enabled(ctx);
27901 gen_st(ctx, op1, rt, rs, imm);
27902 return;
27903 case OPC_SCE:
27904 check_cp0_enabled(ctx);
27905 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
27906 return;
27907 case OPC_CACHEE:
27908 check_cp0_enabled(ctx);
27909 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27910 gen_cache_operation(ctx, rt, rs, imm);
27912 /* Treat as NOP. */
27913 return;
27914 case OPC_PREFE:
27915 check_cp0_enabled(ctx);
27916 /* Treat as NOP. */
27917 return;
27921 switch (op1) {
27922 case OPC_EXT:
27923 case OPC_INS:
27924 check_insn(ctx, ISA_MIPS32R2);
27925 gen_bitops(ctx, op1, rt, rs, sa, rd);
27926 break;
27927 case OPC_BSHFL:
27928 op2 = MASK_BSHFL(ctx->opcode);
27929 switch (op2) {
27930 case OPC_ALIGN:
27931 case OPC_ALIGN_1:
27932 case OPC_ALIGN_2:
27933 case OPC_ALIGN_3:
27934 case OPC_BITSWAP:
27935 check_insn(ctx, ISA_MIPS32R6);
27936 decode_opc_special3_r6(env, ctx);
27937 break;
27938 default:
27939 check_insn(ctx, ISA_MIPS32R2);
27940 gen_bshfl(ctx, op2, rt, rd);
27941 break;
27943 break;
27944 #if defined(TARGET_MIPS64)
27945 case OPC_DEXTM:
27946 case OPC_DEXTU:
27947 case OPC_DEXT:
27948 case OPC_DINSM:
27949 case OPC_DINSU:
27950 case OPC_DINS:
27951 check_insn(ctx, ISA_MIPS64R2);
27952 check_mips_64(ctx);
27953 gen_bitops(ctx, op1, rt, rs, sa, rd);
27954 break;
27955 case OPC_DBSHFL:
27956 op2 = MASK_DBSHFL(ctx->opcode);
27957 switch (op2) {
27958 case OPC_DALIGN:
27959 case OPC_DALIGN_1:
27960 case OPC_DALIGN_2:
27961 case OPC_DALIGN_3:
27962 case OPC_DALIGN_4:
27963 case OPC_DALIGN_5:
27964 case OPC_DALIGN_6:
27965 case OPC_DALIGN_7:
27966 case OPC_DBITSWAP:
27967 check_insn(ctx, ISA_MIPS32R6);
27968 decode_opc_special3_r6(env, ctx);
27969 break;
27970 default:
27971 check_insn(ctx, ISA_MIPS64R2);
27972 check_mips_64(ctx);
27973 op2 = MASK_DBSHFL(ctx->opcode);
27974 gen_bshfl(ctx, op2, rt, rd);
27975 break;
27977 break;
27978 #endif
27979 case OPC_RDHWR:
27980 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27981 break;
27982 case OPC_FORK:
27983 check_mt(ctx);
27985 TCGv t0 = tcg_temp_new();
27986 TCGv t1 = tcg_temp_new();
27988 gen_load_gpr(t0, rt);
27989 gen_load_gpr(t1, rs);
27990 gen_helper_fork(t0, t1);
27991 tcg_temp_free(t0);
27992 tcg_temp_free(t1);
27994 break;
27995 case OPC_YIELD:
27996 check_mt(ctx);
27998 TCGv t0 = tcg_temp_new();
28000 gen_load_gpr(t0, rs);
28001 gen_helper_yield(t0, cpu_env, t0);
28002 gen_store_gpr(t0, rd);
28003 tcg_temp_free(t0);
28005 break;
28006 default:
28007 if (ctx->insn_flags & ISA_MIPS32R6) {
28008 decode_opc_special3_r6(env, ctx);
28009 } else {
28010 decode_opc_special3_legacy(env, ctx);
28015 /* MIPS SIMD Architecture (MSA) */
28016 static inline int check_msa_access(DisasContext *ctx)
28018 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28019 !(ctx->hflags & MIPS_HFLAG_F64))) {
28020 generate_exception_end(ctx, EXCP_RI);
28021 return 0;
28024 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28025 if (ctx->insn_flags & ASE_MSA) {
28026 generate_exception_end(ctx, EXCP_MSADIS);
28027 return 0;
28028 } else {
28029 generate_exception_end(ctx, EXCP_RI);
28030 return 0;
28033 return 1;
28036 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28038 /* generates tcg ops to check if any element is 0 */
28039 /* Note this function only works with MSA_WRLEN = 128 */
28040 uint64_t eval_zero_or_big = 0;
28041 uint64_t eval_big = 0;
28042 TCGv_i64 t0 = tcg_temp_new_i64();
28043 TCGv_i64 t1 = tcg_temp_new_i64();
28044 switch (df) {
28045 case DF_BYTE:
28046 eval_zero_or_big = 0x0101010101010101ULL;
28047 eval_big = 0x8080808080808080ULL;
28048 break;
28049 case DF_HALF:
28050 eval_zero_or_big = 0x0001000100010001ULL;
28051 eval_big = 0x8000800080008000ULL;
28052 break;
28053 case DF_WORD:
28054 eval_zero_or_big = 0x0000000100000001ULL;
28055 eval_big = 0x8000000080000000ULL;
28056 break;
28057 case DF_DOUBLE:
28058 eval_zero_or_big = 0x0000000000000001ULL;
28059 eval_big = 0x8000000000000000ULL;
28060 break;
28062 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28063 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28064 tcg_gen_andi_i64(t0, t0, eval_big);
28065 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28066 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28067 tcg_gen_andi_i64(t1, t1, eval_big);
28068 tcg_gen_or_i64(t0, t0, t1);
28069 /* if all bits are zero then all elements are not zero */
28070 /* if some bit is non-zero then some element is zero */
28071 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28072 tcg_gen_trunc_i64_tl(tresult, t0);
28073 tcg_temp_free_i64(t0);
28074 tcg_temp_free_i64(t1);
28077 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28079 uint8_t df = (ctx->opcode >> 21) & 0x3;
28080 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28081 int64_t s16 = (int16_t)ctx->opcode;
28083 check_msa_access(ctx);
28085 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28086 generate_exception_end(ctx, EXCP_RI);
28087 return;
28089 switch (op1) {
28090 case OPC_BZ_V:
28091 case OPC_BNZ_V:
28093 TCGv_i64 t0 = tcg_temp_new_i64();
28094 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28095 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28096 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28097 tcg_gen_trunc_i64_tl(bcond, t0);
28098 tcg_temp_free_i64(t0);
28100 break;
28101 case OPC_BZ_B:
28102 case OPC_BZ_H:
28103 case OPC_BZ_W:
28104 case OPC_BZ_D:
28105 gen_check_zero_element(bcond, df, wt);
28106 break;
28107 case OPC_BNZ_B:
28108 case OPC_BNZ_H:
28109 case OPC_BNZ_W:
28110 case OPC_BNZ_D:
28111 gen_check_zero_element(bcond, df, wt);
28112 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28113 break;
28116 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28118 ctx->hflags |= MIPS_HFLAG_BC;
28119 ctx->hflags |= MIPS_HFLAG_BDS32;
28122 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28124 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28125 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28126 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28127 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28129 TCGv_i32 twd = tcg_const_i32(wd);
28130 TCGv_i32 tws = tcg_const_i32(ws);
28131 TCGv_i32 ti8 = tcg_const_i32(i8);
28133 switch (MASK_MSA_I8(ctx->opcode)) {
28134 case OPC_ANDI_B:
28135 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28136 break;
28137 case OPC_ORI_B:
28138 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28139 break;
28140 case OPC_NORI_B:
28141 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28142 break;
28143 case OPC_XORI_B:
28144 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28145 break;
28146 case OPC_BMNZI_B:
28147 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28148 break;
28149 case OPC_BMZI_B:
28150 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28151 break;
28152 case OPC_BSELI_B:
28153 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28154 break;
28155 case OPC_SHF_B:
28156 case OPC_SHF_H:
28157 case OPC_SHF_W:
28159 uint8_t df = (ctx->opcode >> 24) & 0x3;
28160 if (df == DF_DOUBLE) {
28161 generate_exception_end(ctx, EXCP_RI);
28162 } else {
28163 TCGv_i32 tdf = tcg_const_i32(df);
28164 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28165 tcg_temp_free_i32(tdf);
28168 break;
28169 default:
28170 MIPS_INVAL("MSA instruction");
28171 generate_exception_end(ctx, EXCP_RI);
28172 break;
28175 tcg_temp_free_i32(twd);
28176 tcg_temp_free_i32(tws);
28177 tcg_temp_free_i32(ti8);
28180 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28182 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28183 uint8_t df = (ctx->opcode >> 21) & 0x3;
28184 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28185 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28186 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28187 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28189 TCGv_i32 tdf = tcg_const_i32(df);
28190 TCGv_i32 twd = tcg_const_i32(wd);
28191 TCGv_i32 tws = tcg_const_i32(ws);
28192 TCGv_i32 timm = tcg_temp_new_i32();
28193 tcg_gen_movi_i32(timm, u5);
28195 switch (MASK_MSA_I5(ctx->opcode)) {
28196 case OPC_ADDVI_df:
28197 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28198 break;
28199 case OPC_SUBVI_df:
28200 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28201 break;
28202 case OPC_MAXI_S_df:
28203 tcg_gen_movi_i32(timm, s5);
28204 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28205 break;
28206 case OPC_MAXI_U_df:
28207 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28208 break;
28209 case OPC_MINI_S_df:
28210 tcg_gen_movi_i32(timm, s5);
28211 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28212 break;
28213 case OPC_MINI_U_df:
28214 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28215 break;
28216 case OPC_CEQI_df:
28217 tcg_gen_movi_i32(timm, s5);
28218 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28219 break;
28220 case OPC_CLTI_S_df:
28221 tcg_gen_movi_i32(timm, s5);
28222 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28223 break;
28224 case OPC_CLTI_U_df:
28225 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28226 break;
28227 case OPC_CLEI_S_df:
28228 tcg_gen_movi_i32(timm, s5);
28229 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28230 break;
28231 case OPC_CLEI_U_df:
28232 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28233 break;
28234 case OPC_LDI_df:
28236 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28237 tcg_gen_movi_i32(timm, s10);
28238 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28240 break;
28241 default:
28242 MIPS_INVAL("MSA instruction");
28243 generate_exception_end(ctx, EXCP_RI);
28244 break;
28247 tcg_temp_free_i32(tdf);
28248 tcg_temp_free_i32(twd);
28249 tcg_temp_free_i32(tws);
28250 tcg_temp_free_i32(timm);
28253 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28255 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28256 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28257 uint32_t df = 0, m = 0;
28258 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28259 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28261 TCGv_i32 tdf;
28262 TCGv_i32 tm;
28263 TCGv_i32 twd;
28264 TCGv_i32 tws;
28266 if ((dfm & 0x40) == 0x00) {
28267 m = dfm & 0x3f;
28268 df = DF_DOUBLE;
28269 } else if ((dfm & 0x60) == 0x40) {
28270 m = dfm & 0x1f;
28271 df = DF_WORD;
28272 } else if ((dfm & 0x70) == 0x60) {
28273 m = dfm & 0x0f;
28274 df = DF_HALF;
28275 } else if ((dfm & 0x78) == 0x70) {
28276 m = dfm & 0x7;
28277 df = DF_BYTE;
28278 } else {
28279 generate_exception_end(ctx, EXCP_RI);
28280 return;
28283 tdf = tcg_const_i32(df);
28284 tm = tcg_const_i32(m);
28285 twd = tcg_const_i32(wd);
28286 tws = tcg_const_i32(ws);
28288 switch (MASK_MSA_BIT(ctx->opcode)) {
28289 case OPC_SLLI_df:
28290 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28291 break;
28292 case OPC_SRAI_df:
28293 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28294 break;
28295 case OPC_SRLI_df:
28296 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28297 break;
28298 case OPC_BCLRI_df:
28299 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28300 break;
28301 case OPC_BSETI_df:
28302 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28303 break;
28304 case OPC_BNEGI_df:
28305 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28306 break;
28307 case OPC_BINSLI_df:
28308 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28309 break;
28310 case OPC_BINSRI_df:
28311 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28312 break;
28313 case OPC_SAT_S_df:
28314 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28315 break;
28316 case OPC_SAT_U_df:
28317 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28318 break;
28319 case OPC_SRARI_df:
28320 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28321 break;
28322 case OPC_SRLRI_df:
28323 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28324 break;
28325 default:
28326 MIPS_INVAL("MSA instruction");
28327 generate_exception_end(ctx, EXCP_RI);
28328 break;
28331 tcg_temp_free_i32(tdf);
28332 tcg_temp_free_i32(tm);
28333 tcg_temp_free_i32(twd);
28334 tcg_temp_free_i32(tws);
28337 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28339 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28340 uint8_t df = (ctx->opcode >> 21) & 0x3;
28341 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28342 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28343 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28345 TCGv_i32 tdf = tcg_const_i32(df);
28346 TCGv_i32 twd = tcg_const_i32(wd);
28347 TCGv_i32 tws = tcg_const_i32(ws);
28348 TCGv_i32 twt = tcg_const_i32(wt);
28350 switch (MASK_MSA_3R(ctx->opcode)) {
28351 case OPC_SLL_df:
28352 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28353 break;
28354 case OPC_ADDV_df:
28355 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28356 break;
28357 case OPC_CEQ_df:
28358 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28359 break;
28360 case OPC_ADD_A_df:
28361 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28362 break;
28363 case OPC_SUBS_S_df:
28364 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28365 break;
28366 case OPC_MULV_df:
28367 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28368 break;
28369 case OPC_SLD_df:
28370 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28371 break;
28372 case OPC_VSHF_df:
28373 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28374 break;
28375 case OPC_SRA_df:
28376 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28377 break;
28378 case OPC_SUBV_df:
28379 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28380 break;
28381 case OPC_ADDS_A_df:
28382 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28383 break;
28384 case OPC_SUBS_U_df:
28385 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28386 break;
28387 case OPC_MADDV_df:
28388 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28389 break;
28390 case OPC_SPLAT_df:
28391 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28392 break;
28393 case OPC_SRAR_df:
28394 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28395 break;
28396 case OPC_SRL_df:
28397 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28398 break;
28399 case OPC_MAX_S_df:
28400 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28401 break;
28402 case OPC_CLT_S_df:
28403 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28404 break;
28405 case OPC_ADDS_S_df:
28406 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28407 break;
28408 case OPC_SUBSUS_U_df:
28409 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28410 break;
28411 case OPC_MSUBV_df:
28412 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28413 break;
28414 case OPC_PCKEV_df:
28415 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28416 break;
28417 case OPC_SRLR_df:
28418 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28419 break;
28420 case OPC_BCLR_df:
28421 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28422 break;
28423 case OPC_MAX_U_df:
28424 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28425 break;
28426 case OPC_CLT_U_df:
28427 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28428 break;
28429 case OPC_ADDS_U_df:
28430 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28431 break;
28432 case OPC_SUBSUU_S_df:
28433 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28434 break;
28435 case OPC_PCKOD_df:
28436 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28437 break;
28438 case OPC_BSET_df:
28439 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28440 break;
28441 case OPC_MIN_S_df:
28442 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28443 break;
28444 case OPC_CLE_S_df:
28445 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28446 break;
28447 case OPC_AVE_S_df:
28448 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28449 break;
28450 case OPC_ASUB_S_df:
28451 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28452 break;
28453 case OPC_DIV_S_df:
28454 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28455 break;
28456 case OPC_ILVL_df:
28457 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28458 break;
28459 case OPC_BNEG_df:
28460 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28461 break;
28462 case OPC_MIN_U_df:
28463 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28464 break;
28465 case OPC_CLE_U_df:
28466 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28467 break;
28468 case OPC_AVE_U_df:
28469 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28470 break;
28471 case OPC_ASUB_U_df:
28472 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28473 break;
28474 case OPC_DIV_U_df:
28475 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28476 break;
28477 case OPC_ILVR_df:
28478 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28479 break;
28480 case OPC_BINSL_df:
28481 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28482 break;
28483 case OPC_MAX_A_df:
28484 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28485 break;
28486 case OPC_AVER_S_df:
28487 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28488 break;
28489 case OPC_MOD_S_df:
28490 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28491 break;
28492 case OPC_ILVEV_df:
28493 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28494 break;
28495 case OPC_BINSR_df:
28496 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28497 break;
28498 case OPC_MIN_A_df:
28499 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28500 break;
28501 case OPC_AVER_U_df:
28502 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28503 break;
28504 case OPC_MOD_U_df:
28505 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28506 break;
28507 case OPC_ILVOD_df:
28508 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28509 break;
28511 case OPC_DOTP_S_df:
28512 case OPC_DOTP_U_df:
28513 case OPC_DPADD_S_df:
28514 case OPC_DPADD_U_df:
28515 case OPC_DPSUB_S_df:
28516 case OPC_HADD_S_df:
28517 case OPC_DPSUB_U_df:
28518 case OPC_HADD_U_df:
28519 case OPC_HSUB_S_df:
28520 case OPC_HSUB_U_df:
28521 if (df == DF_BYTE) {
28522 generate_exception_end(ctx, EXCP_RI);
28523 break;
28525 switch (MASK_MSA_3R(ctx->opcode)) {
28526 case OPC_DOTP_S_df:
28527 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28528 break;
28529 case OPC_DOTP_U_df:
28530 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28531 break;
28532 case OPC_DPADD_S_df:
28533 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28534 break;
28535 case OPC_DPADD_U_df:
28536 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28537 break;
28538 case OPC_DPSUB_S_df:
28539 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28540 break;
28541 case OPC_HADD_S_df:
28542 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28543 break;
28544 case OPC_DPSUB_U_df:
28545 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28546 break;
28547 case OPC_HADD_U_df:
28548 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28549 break;
28550 case OPC_HSUB_S_df:
28551 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28552 break;
28553 case OPC_HSUB_U_df:
28554 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28555 break;
28557 break;
28558 default:
28559 MIPS_INVAL("MSA instruction");
28560 generate_exception_end(ctx, EXCP_RI);
28561 break;
28563 tcg_temp_free_i32(twd);
28564 tcg_temp_free_i32(tws);
28565 tcg_temp_free_i32(twt);
28566 tcg_temp_free_i32(tdf);
28569 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28571 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28572 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28573 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28574 TCGv telm = tcg_temp_new();
28575 TCGv_i32 tsr = tcg_const_i32(source);
28576 TCGv_i32 tdt = tcg_const_i32(dest);
28578 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28579 case OPC_CTCMSA:
28580 gen_load_gpr(telm, source);
28581 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28582 break;
28583 case OPC_CFCMSA:
28584 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28585 gen_store_gpr(telm, dest);
28586 break;
28587 case OPC_MOVE_V:
28588 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28589 break;
28590 default:
28591 MIPS_INVAL("MSA instruction");
28592 generate_exception_end(ctx, EXCP_RI);
28593 break;
28596 tcg_temp_free(telm);
28597 tcg_temp_free_i32(tdt);
28598 tcg_temp_free_i32(tsr);
28601 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28602 uint32_t n)
28604 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28605 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28606 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28608 TCGv_i32 tws = tcg_const_i32(ws);
28609 TCGv_i32 twd = tcg_const_i32(wd);
28610 TCGv_i32 tn = tcg_const_i32(n);
28611 TCGv_i32 tdf = tcg_const_i32(df);
28613 switch (MASK_MSA_ELM(ctx->opcode)) {
28614 case OPC_SLDI_df:
28615 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28616 break;
28617 case OPC_SPLATI_df:
28618 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28619 break;
28620 case OPC_INSVE_df:
28621 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28622 break;
28623 case OPC_COPY_S_df:
28624 case OPC_COPY_U_df:
28625 case OPC_INSERT_df:
28626 #if !defined(TARGET_MIPS64)
28627 /* Double format valid only for MIPS64 */
28628 if (df == DF_DOUBLE) {
28629 generate_exception_end(ctx, EXCP_RI);
28630 break;
28632 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
28633 (df == DF_WORD)) {
28634 generate_exception_end(ctx, EXCP_RI);
28635 break;
28637 #endif
28638 switch (MASK_MSA_ELM(ctx->opcode)) {
28639 case OPC_COPY_S_df:
28640 if (likely(wd != 0)) {
28641 switch (df) {
28642 case DF_BYTE:
28643 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
28644 break;
28645 case DF_HALF:
28646 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
28647 break;
28648 case DF_WORD:
28649 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
28650 break;
28651 #if defined(TARGET_MIPS64)
28652 case DF_DOUBLE:
28653 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
28654 break;
28655 #endif
28656 default:
28657 assert(0);
28660 break;
28661 case OPC_COPY_U_df:
28662 if (likely(wd != 0)) {
28663 switch (df) {
28664 case DF_BYTE:
28665 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
28666 break;
28667 case DF_HALF:
28668 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
28669 break;
28670 #if defined(TARGET_MIPS64)
28671 case DF_WORD:
28672 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
28673 break;
28674 #endif
28675 default:
28676 assert(0);
28679 break;
28680 case OPC_INSERT_df:
28681 switch (df) {
28682 case DF_BYTE:
28683 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
28684 break;
28685 case DF_HALF:
28686 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
28687 break;
28688 case DF_WORD:
28689 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
28690 break;
28691 #if defined(TARGET_MIPS64)
28692 case DF_DOUBLE:
28693 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
28694 break;
28695 #endif
28696 default:
28697 assert(0);
28699 break;
28701 break;
28702 default:
28703 MIPS_INVAL("MSA instruction");
28704 generate_exception_end(ctx, EXCP_RI);
28706 tcg_temp_free_i32(twd);
28707 tcg_temp_free_i32(tws);
28708 tcg_temp_free_i32(tn);
28709 tcg_temp_free_i32(tdf);
28712 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28714 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28715 uint32_t df = 0, n = 0;
28717 if ((dfn & 0x30) == 0x00) {
28718 n = dfn & 0x0f;
28719 df = DF_BYTE;
28720 } else if ((dfn & 0x38) == 0x20) {
28721 n = dfn & 0x07;
28722 df = DF_HALF;
28723 } else if ((dfn & 0x3c) == 0x30) {
28724 n = dfn & 0x03;
28725 df = DF_WORD;
28726 } else if ((dfn & 0x3e) == 0x38) {
28727 n = dfn & 0x01;
28728 df = DF_DOUBLE;
28729 } else if (dfn == 0x3E) {
28730 /* CTCMSA, CFCMSA, MOVE.V */
28731 gen_msa_elm_3e(env, ctx);
28732 return;
28733 } else {
28734 generate_exception_end(ctx, EXCP_RI);
28735 return;
28738 gen_msa_elm_df(env, ctx, df, n);
28741 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28743 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28744 uint8_t df = (ctx->opcode >> 21) & 0x1;
28745 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28746 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28747 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28749 TCGv_i32 twd = tcg_const_i32(wd);
28750 TCGv_i32 tws = tcg_const_i32(ws);
28751 TCGv_i32 twt = tcg_const_i32(wt);
28752 TCGv_i32 tdf = tcg_temp_new_i32();
28754 /* adjust df value for floating-point instruction */
28755 tcg_gen_movi_i32(tdf, df + 2);
28757 switch (MASK_MSA_3RF(ctx->opcode)) {
28758 case OPC_FCAF_df:
28759 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28760 break;
28761 case OPC_FADD_df:
28762 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28763 break;
28764 case OPC_FCUN_df:
28765 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28766 break;
28767 case OPC_FSUB_df:
28768 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28769 break;
28770 case OPC_FCOR_df:
28771 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28772 break;
28773 case OPC_FCEQ_df:
28774 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28775 break;
28776 case OPC_FMUL_df:
28777 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28778 break;
28779 case OPC_FCUNE_df:
28780 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28781 break;
28782 case OPC_FCUEQ_df:
28783 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28784 break;
28785 case OPC_FDIV_df:
28786 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28787 break;
28788 case OPC_FCNE_df:
28789 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28790 break;
28791 case OPC_FCLT_df:
28792 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28793 break;
28794 case OPC_FMADD_df:
28795 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28796 break;
28797 case OPC_MUL_Q_df:
28798 tcg_gen_movi_i32(tdf, df + 1);
28799 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28800 break;
28801 case OPC_FCULT_df:
28802 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28803 break;
28804 case OPC_FMSUB_df:
28805 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28806 break;
28807 case OPC_MADD_Q_df:
28808 tcg_gen_movi_i32(tdf, df + 1);
28809 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28810 break;
28811 case OPC_FCLE_df:
28812 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28813 break;
28814 case OPC_MSUB_Q_df:
28815 tcg_gen_movi_i32(tdf, df + 1);
28816 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28817 break;
28818 case OPC_FCULE_df:
28819 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28820 break;
28821 case OPC_FEXP2_df:
28822 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28823 break;
28824 case OPC_FSAF_df:
28825 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28826 break;
28827 case OPC_FEXDO_df:
28828 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28829 break;
28830 case OPC_FSUN_df:
28831 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28832 break;
28833 case OPC_FSOR_df:
28834 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28835 break;
28836 case OPC_FSEQ_df:
28837 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28838 break;
28839 case OPC_FTQ_df:
28840 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28841 break;
28842 case OPC_FSUNE_df:
28843 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28844 break;
28845 case OPC_FSUEQ_df:
28846 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28847 break;
28848 case OPC_FSNE_df:
28849 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28850 break;
28851 case OPC_FSLT_df:
28852 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28853 break;
28854 case OPC_FMIN_df:
28855 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28856 break;
28857 case OPC_MULR_Q_df:
28858 tcg_gen_movi_i32(tdf, df + 1);
28859 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28860 break;
28861 case OPC_FSULT_df:
28862 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28863 break;
28864 case OPC_FMIN_A_df:
28865 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28866 break;
28867 case OPC_MADDR_Q_df:
28868 tcg_gen_movi_i32(tdf, df + 1);
28869 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28870 break;
28871 case OPC_FSLE_df:
28872 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28873 break;
28874 case OPC_FMAX_df:
28875 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28876 break;
28877 case OPC_MSUBR_Q_df:
28878 tcg_gen_movi_i32(tdf, df + 1);
28879 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28880 break;
28881 case OPC_FSULE_df:
28882 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28883 break;
28884 case OPC_FMAX_A_df:
28885 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28886 break;
28887 default:
28888 MIPS_INVAL("MSA instruction");
28889 generate_exception_end(ctx, EXCP_RI);
28890 break;
28893 tcg_temp_free_i32(twd);
28894 tcg_temp_free_i32(tws);
28895 tcg_temp_free_i32(twt);
28896 tcg_temp_free_i32(tdf);
28899 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28901 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28902 (op & (0x7 << 18)))
28903 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28904 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28905 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28906 uint8_t df = (ctx->opcode >> 16) & 0x3;
28907 TCGv_i32 twd = tcg_const_i32(wd);
28908 TCGv_i32 tws = tcg_const_i32(ws);
28909 TCGv_i32 twt = tcg_const_i32(wt);
28910 TCGv_i32 tdf = tcg_const_i32(df);
28912 switch (MASK_MSA_2R(ctx->opcode)) {
28913 case OPC_FILL_df:
28914 #if !defined(TARGET_MIPS64)
28915 /* Double format valid only for MIPS64 */
28916 if (df == DF_DOUBLE) {
28917 generate_exception_end(ctx, EXCP_RI);
28918 break;
28920 #endif
28921 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28922 break;
28923 case OPC_PCNT_df:
28924 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28925 break;
28926 case OPC_NLOC_df:
28927 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28928 break;
28929 case OPC_NLZC_df:
28930 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28931 break;
28932 default:
28933 MIPS_INVAL("MSA instruction");
28934 generate_exception_end(ctx, EXCP_RI);
28935 break;
28938 tcg_temp_free_i32(twd);
28939 tcg_temp_free_i32(tws);
28940 tcg_temp_free_i32(twt);
28941 tcg_temp_free_i32(tdf);
28944 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28946 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28947 (op & (0xf << 17)))
28948 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28949 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28950 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28951 uint8_t df = (ctx->opcode >> 16) & 0x1;
28952 TCGv_i32 twd = tcg_const_i32(wd);
28953 TCGv_i32 tws = tcg_const_i32(ws);
28954 TCGv_i32 twt = tcg_const_i32(wt);
28955 /* adjust df value for floating-point instruction */
28956 TCGv_i32 tdf = tcg_const_i32(df + 2);
28958 switch (MASK_MSA_2RF(ctx->opcode)) {
28959 case OPC_FCLASS_df:
28960 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28961 break;
28962 case OPC_FTRUNC_S_df:
28963 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28964 break;
28965 case OPC_FTRUNC_U_df:
28966 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28967 break;
28968 case OPC_FSQRT_df:
28969 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28970 break;
28971 case OPC_FRSQRT_df:
28972 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28973 break;
28974 case OPC_FRCP_df:
28975 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28976 break;
28977 case OPC_FRINT_df:
28978 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28979 break;
28980 case OPC_FLOG2_df:
28981 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28982 break;
28983 case OPC_FEXUPL_df:
28984 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28985 break;
28986 case OPC_FEXUPR_df:
28987 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28988 break;
28989 case OPC_FFQL_df:
28990 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28991 break;
28992 case OPC_FFQR_df:
28993 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28994 break;
28995 case OPC_FTINT_S_df:
28996 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28997 break;
28998 case OPC_FTINT_U_df:
28999 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29000 break;
29001 case OPC_FFINT_S_df:
29002 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29003 break;
29004 case OPC_FFINT_U_df:
29005 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29006 break;
29009 tcg_temp_free_i32(twd);
29010 tcg_temp_free_i32(tws);
29011 tcg_temp_free_i32(twt);
29012 tcg_temp_free_i32(tdf);
29015 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29017 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29018 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29019 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29020 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29021 TCGv_i32 twd = tcg_const_i32(wd);
29022 TCGv_i32 tws = tcg_const_i32(ws);
29023 TCGv_i32 twt = tcg_const_i32(wt);
29025 switch (MASK_MSA_VEC(ctx->opcode)) {
29026 case OPC_AND_V:
29027 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29028 break;
29029 case OPC_OR_V:
29030 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29031 break;
29032 case OPC_NOR_V:
29033 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29034 break;
29035 case OPC_XOR_V:
29036 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29037 break;
29038 case OPC_BMNZ_V:
29039 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29040 break;
29041 case OPC_BMZ_V:
29042 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29043 break;
29044 case OPC_BSEL_V:
29045 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29046 break;
29047 default:
29048 MIPS_INVAL("MSA instruction");
29049 generate_exception_end(ctx, EXCP_RI);
29050 break;
29053 tcg_temp_free_i32(twd);
29054 tcg_temp_free_i32(tws);
29055 tcg_temp_free_i32(twt);
29058 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29060 switch (MASK_MSA_VEC(ctx->opcode)) {
29061 case OPC_AND_V:
29062 case OPC_OR_V:
29063 case OPC_NOR_V:
29064 case OPC_XOR_V:
29065 case OPC_BMNZ_V:
29066 case OPC_BMZ_V:
29067 case OPC_BSEL_V:
29068 gen_msa_vec_v(env, ctx);
29069 break;
29070 case OPC_MSA_2R:
29071 gen_msa_2r(env, ctx);
29072 break;
29073 case OPC_MSA_2RF:
29074 gen_msa_2rf(env, ctx);
29075 break;
29076 default:
29077 MIPS_INVAL("MSA instruction");
29078 generate_exception_end(ctx, EXCP_RI);
29079 break;
29083 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29085 uint32_t opcode = ctx->opcode;
29086 check_insn(ctx, ASE_MSA);
29087 check_msa_access(ctx);
29089 switch (MASK_MSA_MINOR(opcode)) {
29090 case OPC_MSA_I8_00:
29091 case OPC_MSA_I8_01:
29092 case OPC_MSA_I8_02:
29093 gen_msa_i8(env, ctx);
29094 break;
29095 case OPC_MSA_I5_06:
29096 case OPC_MSA_I5_07:
29097 gen_msa_i5(env, ctx);
29098 break;
29099 case OPC_MSA_BIT_09:
29100 case OPC_MSA_BIT_0A:
29101 gen_msa_bit(env, ctx);
29102 break;
29103 case OPC_MSA_3R_0D:
29104 case OPC_MSA_3R_0E:
29105 case OPC_MSA_3R_0F:
29106 case OPC_MSA_3R_10:
29107 case OPC_MSA_3R_11:
29108 case OPC_MSA_3R_12:
29109 case OPC_MSA_3R_13:
29110 case OPC_MSA_3R_14:
29111 case OPC_MSA_3R_15:
29112 gen_msa_3r(env, ctx);
29113 break;
29114 case OPC_MSA_ELM:
29115 gen_msa_elm(env, ctx);
29116 break;
29117 case OPC_MSA_3RF_1A:
29118 case OPC_MSA_3RF_1B:
29119 case OPC_MSA_3RF_1C:
29120 gen_msa_3rf(env, ctx);
29121 break;
29122 case OPC_MSA_VEC:
29123 gen_msa_vec(env, ctx);
29124 break;
29125 case OPC_LD_B:
29126 case OPC_LD_H:
29127 case OPC_LD_W:
29128 case OPC_LD_D:
29129 case OPC_ST_B:
29130 case OPC_ST_H:
29131 case OPC_ST_W:
29132 case OPC_ST_D:
29134 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29135 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29136 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29137 uint8_t df = (ctx->opcode >> 0) & 0x3;
29139 TCGv_i32 twd = tcg_const_i32(wd);
29140 TCGv taddr = tcg_temp_new();
29141 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
29143 switch (MASK_MSA_MINOR(opcode)) {
29144 case OPC_LD_B:
29145 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29146 break;
29147 case OPC_LD_H:
29148 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29149 break;
29150 case OPC_LD_W:
29151 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29152 break;
29153 case OPC_LD_D:
29154 gen_helper_msa_ld_d(cpu_env, twd, taddr);
29155 break;
29156 case OPC_ST_B:
29157 gen_helper_msa_st_b(cpu_env, twd, taddr);
29158 break;
29159 case OPC_ST_H:
29160 gen_helper_msa_st_h(cpu_env, twd, taddr);
29161 break;
29162 case OPC_ST_W:
29163 gen_helper_msa_st_w(cpu_env, twd, taddr);
29164 break;
29165 case OPC_ST_D:
29166 gen_helper_msa_st_d(cpu_env, twd, taddr);
29167 break;
29170 tcg_temp_free_i32(twd);
29171 tcg_temp_free(taddr);
29173 break;
29174 default:
29175 MIPS_INVAL("MSA instruction");
29176 generate_exception_end(ctx, EXCP_RI);
29177 break;
29182 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
29184 int32_t offset;
29185 int rs, rt, rd, sa;
29186 uint32_t op, op1;
29187 int16_t imm;
29189 /* make sure instructions are on a word boundary */
29190 if (ctx->base.pc_next & 0x3) {
29191 env->CP0_BadVAddr = ctx->base.pc_next;
29192 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
29193 return;
29196 /* Handle blikely not taken case */
29197 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
29198 TCGLabel *l1 = gen_new_label();
29200 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29201 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
29202 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
29203 gen_set_label(l1);
29206 op = MASK_OP_MAJOR(ctx->opcode);
29207 rs = (ctx->opcode >> 21) & 0x1f;
29208 rt = (ctx->opcode >> 16) & 0x1f;
29209 rd = (ctx->opcode >> 11) & 0x1f;
29210 sa = (ctx->opcode >> 6) & 0x1f;
29211 imm = (int16_t)ctx->opcode;
29212 switch (op) {
29213 case OPC_SPECIAL:
29214 decode_opc_special(env, ctx);
29215 break;
29216 case OPC_SPECIAL2:
29217 #if defined(TARGET_MIPS64)
29218 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
29219 decode_mmi(env, ctx);
29220 #else
29221 if (ctx->insn_flags & ASE_MXU) {
29222 decode_opc_mxu(env, ctx);
29223 #endif
29224 } else {
29225 decode_opc_special2_legacy(env, ctx);
29227 break;
29228 case OPC_SPECIAL3:
29229 #if defined(TARGET_MIPS64)
29230 if (ctx->insn_flags & INSN_R5900) {
29231 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
29232 } else {
29233 decode_opc_special3(env, ctx);
29235 #else
29236 decode_opc_special3(env, ctx);
29237 #endif
29238 break;
29239 case OPC_REGIMM:
29240 op1 = MASK_REGIMM(ctx->opcode);
29241 switch (op1) {
29242 case OPC_BLTZL: /* REGIMM branches */
29243 case OPC_BGEZL:
29244 case OPC_BLTZALL:
29245 case OPC_BGEZALL:
29246 check_insn(ctx, ISA_MIPS2);
29247 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29248 /* Fallthrough */
29249 case OPC_BLTZ:
29250 case OPC_BGEZ:
29251 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29252 break;
29253 case OPC_BLTZAL:
29254 case OPC_BGEZAL:
29255 if (ctx->insn_flags & ISA_MIPS32R6) {
29256 if (rs == 0) {
29257 /* OPC_NAL, OPC_BAL */
29258 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
29259 } else {
29260 generate_exception_end(ctx, EXCP_RI);
29262 } else {
29263 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29265 break;
29266 case OPC_TGEI: /* REGIMM traps */
29267 case OPC_TGEIU:
29268 case OPC_TLTI:
29269 case OPC_TLTIU:
29270 case OPC_TEQI:
29272 case OPC_TNEI:
29273 check_insn(ctx, ISA_MIPS2);
29274 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29275 gen_trap(ctx, op1, rs, -1, imm);
29276 break;
29277 case OPC_SIGRIE:
29278 check_insn(ctx, ISA_MIPS32R6);
29279 generate_exception_end(ctx, EXCP_RI);
29280 break;
29281 case OPC_SYNCI:
29282 check_insn(ctx, ISA_MIPS32R2);
29284 * Break the TB to be able to sync copied instructions
29285 * immediately.
29287 ctx->base.is_jmp = DISAS_STOP;
29288 break;
29289 case OPC_BPOSGE32: /* MIPS DSP branch */
29290 #if defined(TARGET_MIPS64)
29291 case OPC_BPOSGE64:
29292 #endif
29293 check_dsp(ctx);
29294 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
29295 break;
29296 #if defined(TARGET_MIPS64)
29297 case OPC_DAHI:
29298 check_insn(ctx, ISA_MIPS32R6);
29299 check_mips_64(ctx);
29300 if (rs != 0) {
29301 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
29303 break;
29304 case OPC_DATI:
29305 check_insn(ctx, ISA_MIPS32R6);
29306 check_mips_64(ctx);
29307 if (rs != 0) {
29308 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
29310 break;
29311 #endif
29312 default: /* Invalid */
29313 MIPS_INVAL("regimm");
29314 generate_exception_end(ctx, EXCP_RI);
29315 break;
29317 break;
29318 case OPC_CP0:
29319 check_cp0_enabled(ctx);
29320 op1 = MASK_CP0(ctx->opcode);
29321 switch (op1) {
29322 case OPC_MFC0:
29323 case OPC_MTC0:
29324 case OPC_MFTR:
29325 case OPC_MTTR:
29326 case OPC_MFHC0:
29327 case OPC_MTHC0:
29328 #if defined(TARGET_MIPS64)
29329 case OPC_DMFC0:
29330 case OPC_DMTC0:
29331 #endif
29332 #ifndef CONFIG_USER_ONLY
29333 gen_cp0(env, ctx, op1, rt, rd);
29334 #endif /* !CONFIG_USER_ONLY */
29335 break;
29336 case OPC_C0:
29337 case OPC_C0_1:
29338 case OPC_C0_2:
29339 case OPC_C0_3:
29340 case OPC_C0_4:
29341 case OPC_C0_5:
29342 case OPC_C0_6:
29343 case OPC_C0_7:
29344 case OPC_C0_8:
29345 case OPC_C0_9:
29346 case OPC_C0_A:
29347 case OPC_C0_B:
29348 case OPC_C0_C:
29349 case OPC_C0_D:
29350 case OPC_C0_E:
29351 case OPC_C0_F:
29352 #ifndef CONFIG_USER_ONLY
29353 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
29354 #endif /* !CONFIG_USER_ONLY */
29355 break;
29356 case OPC_MFMC0:
29357 #ifndef CONFIG_USER_ONLY
29359 uint32_t op2;
29360 TCGv t0 = tcg_temp_new();
29362 op2 = MASK_MFMC0(ctx->opcode);
29363 switch (op2) {
29364 case OPC_DMT:
29365 check_cp0_mt(ctx);
29366 gen_helper_dmt(t0);
29367 gen_store_gpr(t0, rt);
29368 break;
29369 case OPC_EMT:
29370 check_cp0_mt(ctx);
29371 gen_helper_emt(t0);
29372 gen_store_gpr(t0, rt);
29373 break;
29374 case OPC_DVPE:
29375 check_cp0_mt(ctx);
29376 gen_helper_dvpe(t0, cpu_env);
29377 gen_store_gpr(t0, rt);
29378 break;
29379 case OPC_EVPE:
29380 check_cp0_mt(ctx);
29381 gen_helper_evpe(t0, cpu_env);
29382 gen_store_gpr(t0, rt);
29383 break;
29384 case OPC_DVP:
29385 check_insn(ctx, ISA_MIPS32R6);
29386 if (ctx->vp) {
29387 gen_helper_dvp(t0, cpu_env);
29388 gen_store_gpr(t0, rt);
29390 break;
29391 case OPC_EVP:
29392 check_insn(ctx, ISA_MIPS32R6);
29393 if (ctx->vp) {
29394 gen_helper_evp(t0, cpu_env);
29395 gen_store_gpr(t0, rt);
29397 break;
29398 case OPC_DI:
29399 check_insn(ctx, ISA_MIPS32R2);
29400 save_cpu_state(ctx, 1);
29401 gen_helper_di(t0, cpu_env);
29402 gen_store_gpr(t0, rt);
29404 * Stop translation as we may have switched
29405 * the execution mode.
29407 ctx->base.is_jmp = DISAS_STOP;
29408 break;
29409 case OPC_EI:
29410 check_insn(ctx, ISA_MIPS32R2);
29411 save_cpu_state(ctx, 1);
29412 gen_helper_ei(t0, cpu_env);
29413 gen_store_gpr(t0, rt);
29415 * DISAS_STOP isn't sufficient, we need to ensure we break
29416 * out of translated code to check for pending interrupts.
29418 gen_save_pc(ctx->base.pc_next + 4);
29419 ctx->base.is_jmp = DISAS_EXIT;
29420 break;
29421 default: /* Invalid */
29422 MIPS_INVAL("mfmc0");
29423 generate_exception_end(ctx, EXCP_RI);
29424 break;
29426 tcg_temp_free(t0);
29428 #endif /* !CONFIG_USER_ONLY */
29429 break;
29430 case OPC_RDPGPR:
29431 check_insn(ctx, ISA_MIPS32R2);
29432 gen_load_srsgpr(rt, rd);
29433 break;
29434 case OPC_WRPGPR:
29435 check_insn(ctx, ISA_MIPS32R2);
29436 gen_store_srsgpr(rt, rd);
29437 break;
29438 default:
29439 MIPS_INVAL("cp0");
29440 generate_exception_end(ctx, EXCP_RI);
29441 break;
29443 break;
29444 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29445 if (ctx->insn_flags & ISA_MIPS32R6) {
29446 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29447 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29448 } else {
29449 /* OPC_ADDI */
29450 /* Arithmetic with immediate opcode */
29451 gen_arith_imm(ctx, op, rt, rs, imm);
29453 break;
29454 case OPC_ADDIU:
29455 gen_arith_imm(ctx, op, rt, rs, imm);
29456 break;
29457 case OPC_SLTI: /* Set on less than with immediate opcode */
29458 case OPC_SLTIU:
29459 gen_slt_imm(ctx, op, rt, rs, imm);
29460 break;
29461 case OPC_ANDI: /* Arithmetic with immediate opcode */
29462 case OPC_LUI: /* OPC_AUI */
29463 case OPC_ORI:
29464 case OPC_XORI:
29465 gen_logic_imm(ctx, op, rt, rs, imm);
29466 break;
29467 case OPC_J: /* Jump */
29468 case OPC_JAL:
29469 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29470 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29471 break;
29472 /* Branch */
29473 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29474 if (ctx->insn_flags & ISA_MIPS32R6) {
29475 if (rt == 0) {
29476 generate_exception_end(ctx, EXCP_RI);
29477 break;
29479 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29480 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29481 } else {
29482 /* OPC_BLEZL */
29483 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29485 break;
29486 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29487 if (ctx->insn_flags & ISA_MIPS32R6) {
29488 if (rt == 0) {
29489 generate_exception_end(ctx, EXCP_RI);
29490 break;
29492 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29493 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29494 } else {
29495 /* OPC_BGTZL */
29496 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29498 break;
29499 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29500 if (rt == 0) {
29501 /* OPC_BLEZ */
29502 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29503 } else {
29504 check_insn(ctx, ISA_MIPS32R6);
29505 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29506 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29508 break;
29509 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29510 if (rt == 0) {
29511 /* OPC_BGTZ */
29512 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29513 } else {
29514 check_insn(ctx, ISA_MIPS32R6);
29515 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29516 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29518 break;
29519 case OPC_BEQL:
29520 case OPC_BNEL:
29521 check_insn(ctx, ISA_MIPS2);
29522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29523 /* Fallthrough */
29524 case OPC_BEQ:
29525 case OPC_BNE:
29526 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29527 break;
29528 case OPC_LL: /* Load and stores */
29529 check_insn(ctx, ISA_MIPS2);
29530 if (ctx->insn_flags & INSN_R5900) {
29531 check_insn_opc_user_only(ctx, INSN_R5900);
29533 /* Fallthrough */
29534 case OPC_LWL:
29535 case OPC_LWR:
29536 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29537 /* Fallthrough */
29538 case OPC_LB:
29539 case OPC_LH:
29540 case OPC_LW:
29541 case OPC_LWPC:
29542 case OPC_LBU:
29543 case OPC_LHU:
29544 gen_ld(ctx, op, rt, rs, imm);
29545 break;
29546 case OPC_SWL:
29547 case OPC_SWR:
29548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29549 /* fall through */
29550 case OPC_SB:
29551 case OPC_SH:
29552 case OPC_SW:
29553 gen_st(ctx, op, rt, rs, imm);
29554 break;
29555 case OPC_SC:
29556 check_insn(ctx, ISA_MIPS2);
29557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29558 if (ctx->insn_flags & INSN_R5900) {
29559 check_insn_opc_user_only(ctx, INSN_R5900);
29561 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29562 break;
29563 case OPC_CACHE:
29564 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29565 check_cp0_enabled(ctx);
29566 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29567 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29568 gen_cache_operation(ctx, rt, rs, imm);
29570 /* Treat as NOP. */
29571 break;
29572 case OPC_PREF:
29573 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29574 if (ctx->insn_flags & INSN_R5900) {
29575 /* Treat as NOP. */
29576 } else {
29577 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29578 /* Treat as NOP. */
29580 break;
29582 /* Floating point (COP1). */
29583 case OPC_LWC1:
29584 case OPC_LDC1:
29585 case OPC_SWC1:
29586 case OPC_SDC1:
29587 gen_cop1_ldst(ctx, op, rt, rs, imm);
29588 break;
29590 case OPC_CP1:
29591 op1 = MASK_CP1(ctx->opcode);
29593 switch (op1) {
29594 case OPC_MFHC1:
29595 case OPC_MTHC1:
29596 check_cp1_enabled(ctx);
29597 check_insn(ctx, ISA_MIPS32R2);
29598 /* fall through */
29599 case OPC_MFC1:
29600 case OPC_CFC1:
29601 case OPC_MTC1:
29602 case OPC_CTC1:
29603 check_cp1_enabled(ctx);
29604 gen_cp1(ctx, op1, rt, rd);
29605 break;
29606 #if defined(TARGET_MIPS64)
29607 case OPC_DMFC1:
29608 case OPC_DMTC1:
29609 check_cp1_enabled(ctx);
29610 check_insn(ctx, ISA_MIPS3);
29611 check_mips_64(ctx);
29612 gen_cp1(ctx, op1, rt, rd);
29613 break;
29614 #endif
29615 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29616 check_cp1_enabled(ctx);
29617 if (ctx->insn_flags & ISA_MIPS32R6) {
29618 /* OPC_BC1EQZ */
29619 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29620 rt, imm << 2, 4);
29621 } else {
29622 /* OPC_BC1ANY2 */
29623 check_cop1x(ctx);
29624 check_insn(ctx, ASE_MIPS3D);
29625 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29626 (rt >> 2) & 0x7, imm << 2);
29628 break;
29629 case OPC_BC1NEZ:
29630 check_cp1_enabled(ctx);
29631 check_insn(ctx, ISA_MIPS32R6);
29632 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29633 rt, imm << 2, 4);
29634 break;
29635 case OPC_BC1ANY4:
29636 check_cp1_enabled(ctx);
29637 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29638 check_cop1x(ctx);
29639 check_insn(ctx, ASE_MIPS3D);
29640 /* fall through */
29641 case OPC_BC1:
29642 check_cp1_enabled(ctx);
29643 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29644 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29645 (rt >> 2) & 0x7, imm << 2);
29646 break;
29647 case OPC_PS_FMT:
29648 check_ps(ctx);
29649 /* fall through */
29650 case OPC_S_FMT:
29651 case OPC_D_FMT:
29652 check_cp1_enabled(ctx);
29653 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29654 (imm >> 8) & 0x7);
29655 break;
29656 case OPC_W_FMT:
29657 case OPC_L_FMT:
29659 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29660 check_cp1_enabled(ctx);
29661 if (ctx->insn_flags & ISA_MIPS32R6) {
29662 switch (r6_op) {
29663 case R6_OPC_CMP_AF_S:
29664 case R6_OPC_CMP_UN_S:
29665 case R6_OPC_CMP_EQ_S:
29666 case R6_OPC_CMP_UEQ_S:
29667 case R6_OPC_CMP_LT_S:
29668 case R6_OPC_CMP_ULT_S:
29669 case R6_OPC_CMP_LE_S:
29670 case R6_OPC_CMP_ULE_S:
29671 case R6_OPC_CMP_SAF_S:
29672 case R6_OPC_CMP_SUN_S:
29673 case R6_OPC_CMP_SEQ_S:
29674 case R6_OPC_CMP_SEUQ_S:
29675 case R6_OPC_CMP_SLT_S:
29676 case R6_OPC_CMP_SULT_S:
29677 case R6_OPC_CMP_SLE_S:
29678 case R6_OPC_CMP_SULE_S:
29679 case R6_OPC_CMP_OR_S:
29680 case R6_OPC_CMP_UNE_S:
29681 case R6_OPC_CMP_NE_S:
29682 case R6_OPC_CMP_SOR_S:
29683 case R6_OPC_CMP_SUNE_S:
29684 case R6_OPC_CMP_SNE_S:
29685 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29686 break;
29687 case R6_OPC_CMP_AF_D:
29688 case R6_OPC_CMP_UN_D:
29689 case R6_OPC_CMP_EQ_D:
29690 case R6_OPC_CMP_UEQ_D:
29691 case R6_OPC_CMP_LT_D:
29692 case R6_OPC_CMP_ULT_D:
29693 case R6_OPC_CMP_LE_D:
29694 case R6_OPC_CMP_ULE_D:
29695 case R6_OPC_CMP_SAF_D:
29696 case R6_OPC_CMP_SUN_D:
29697 case R6_OPC_CMP_SEQ_D:
29698 case R6_OPC_CMP_SEUQ_D:
29699 case R6_OPC_CMP_SLT_D:
29700 case R6_OPC_CMP_SULT_D:
29701 case R6_OPC_CMP_SLE_D:
29702 case R6_OPC_CMP_SULE_D:
29703 case R6_OPC_CMP_OR_D:
29704 case R6_OPC_CMP_UNE_D:
29705 case R6_OPC_CMP_NE_D:
29706 case R6_OPC_CMP_SOR_D:
29707 case R6_OPC_CMP_SUNE_D:
29708 case R6_OPC_CMP_SNE_D:
29709 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29710 break;
29711 default:
29712 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29713 rt, rd, sa, (imm >> 8) & 0x7);
29715 break;
29717 } else {
29718 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29719 (imm >> 8) & 0x7);
29721 break;
29723 case OPC_BZ_V:
29724 case OPC_BNZ_V:
29725 case OPC_BZ_B:
29726 case OPC_BZ_H:
29727 case OPC_BZ_W:
29728 case OPC_BZ_D:
29729 case OPC_BNZ_B:
29730 case OPC_BNZ_H:
29731 case OPC_BNZ_W:
29732 case OPC_BNZ_D:
29733 check_insn(ctx, ASE_MSA);
29734 gen_msa_branch(env, ctx, op1);
29735 break;
29736 default:
29737 MIPS_INVAL("cp1");
29738 generate_exception_end(ctx, EXCP_RI);
29739 break;
29741 break;
29743 /* Compact branches [R6] and COP2 [non-R6] */
29744 case OPC_BC: /* OPC_LWC2 */
29745 case OPC_BALC: /* OPC_SWC2 */
29746 if (ctx->insn_flags & ISA_MIPS32R6) {
29747 /* OPC_BC, OPC_BALC */
29748 gen_compute_compact_branch(ctx, op, 0, 0,
29749 sextract32(ctx->opcode << 2, 0, 28));
29750 } else {
29751 /* OPC_LWC2, OPC_SWC2 */
29752 /* COP2: Not implemented. */
29753 generate_exception_err(ctx, EXCP_CpU, 2);
29755 break;
29756 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29757 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29758 if (ctx->insn_flags & ISA_MIPS32R6) {
29759 if (rs != 0) {
29760 /* OPC_BEQZC, OPC_BNEZC */
29761 gen_compute_compact_branch(ctx, op, rs, 0,
29762 sextract32(ctx->opcode << 2, 0, 23));
29763 } else {
29764 /* OPC_JIC, OPC_JIALC */
29765 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29767 } else {
29768 /* OPC_LWC2, OPC_SWC2 */
29769 /* COP2: Not implemented. */
29770 generate_exception_err(ctx, EXCP_CpU, 2);
29772 break;
29773 case OPC_CP2:
29774 check_insn(ctx, INSN_LOONGSON2F);
29775 /* Note that these instructions use different fields. */
29776 gen_loongson_multimedia(ctx, sa, rd, rt);
29777 break;
29779 case OPC_CP3:
29780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29781 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29782 check_cp1_enabled(ctx);
29783 op1 = MASK_CP3(ctx->opcode);
29784 switch (op1) {
29785 case OPC_LUXC1:
29786 case OPC_SUXC1:
29787 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29788 /* Fallthrough */
29789 case OPC_LWXC1:
29790 case OPC_LDXC1:
29791 case OPC_SWXC1:
29792 case OPC_SDXC1:
29793 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29794 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29795 break;
29796 case OPC_PREFX:
29797 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29798 /* Treat as NOP. */
29799 break;
29800 case OPC_ALNV_PS:
29801 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29802 /* Fallthrough */
29803 case OPC_MADD_S:
29804 case OPC_MADD_D:
29805 case OPC_MADD_PS:
29806 case OPC_MSUB_S:
29807 case OPC_MSUB_D:
29808 case OPC_MSUB_PS:
29809 case OPC_NMADD_S:
29810 case OPC_NMADD_D:
29811 case OPC_NMADD_PS:
29812 case OPC_NMSUB_S:
29813 case OPC_NMSUB_D:
29814 case OPC_NMSUB_PS:
29815 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29816 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29817 break;
29818 default:
29819 MIPS_INVAL("cp3");
29820 generate_exception_end(ctx, EXCP_RI);
29821 break;
29823 } else {
29824 generate_exception_err(ctx, EXCP_CpU, 1);
29826 break;
29828 #if defined(TARGET_MIPS64)
29829 /* MIPS64 opcodes */
29830 case OPC_LLD:
29831 if (ctx->insn_flags & INSN_R5900) {
29832 check_insn_opc_user_only(ctx, INSN_R5900);
29834 /* fall through */
29835 case OPC_LDL:
29836 case OPC_LDR:
29837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29838 /* fall through */
29839 case OPC_LWU:
29840 case OPC_LD:
29841 check_insn(ctx, ISA_MIPS3);
29842 check_mips_64(ctx);
29843 gen_ld(ctx, op, rt, rs, imm);
29844 break;
29845 case OPC_SDL:
29846 case OPC_SDR:
29847 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29848 /* fall through */
29849 case OPC_SD:
29850 check_insn(ctx, ISA_MIPS3);
29851 check_mips_64(ctx);
29852 gen_st(ctx, op, rt, rs, imm);
29853 break;
29854 case OPC_SCD:
29855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29856 check_insn(ctx, ISA_MIPS3);
29857 if (ctx->insn_flags & INSN_R5900) {
29858 check_insn_opc_user_only(ctx, INSN_R5900);
29860 check_mips_64(ctx);
29861 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
29862 break;
29863 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29864 if (ctx->insn_flags & ISA_MIPS32R6) {
29865 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29866 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29867 } else {
29868 /* OPC_DADDI */
29869 check_insn(ctx, ISA_MIPS3);
29870 check_mips_64(ctx);
29871 gen_arith_imm(ctx, op, rt, rs, imm);
29873 break;
29874 case OPC_DADDIU:
29875 check_insn(ctx, ISA_MIPS3);
29876 check_mips_64(ctx);
29877 gen_arith_imm(ctx, op, rt, rs, imm);
29878 break;
29879 #else
29880 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29881 if (ctx->insn_flags & ISA_MIPS32R6) {
29882 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29883 } else {
29884 MIPS_INVAL("major opcode");
29885 generate_exception_end(ctx, EXCP_RI);
29887 break;
29888 #endif
29889 case OPC_DAUI: /* OPC_JALX */
29890 if (ctx->insn_flags & ISA_MIPS32R6) {
29891 #if defined(TARGET_MIPS64)
29892 /* OPC_DAUI */
29893 check_mips_64(ctx);
29894 if (rs == 0) {
29895 generate_exception(ctx, EXCP_RI);
29896 } else if (rt != 0) {
29897 TCGv t0 = tcg_temp_new();
29898 gen_load_gpr(t0, rs);
29899 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29900 tcg_temp_free(t0);
29902 #else
29903 generate_exception_end(ctx, EXCP_RI);
29904 MIPS_INVAL("major opcode");
29905 #endif
29906 } else {
29907 /* OPC_JALX */
29908 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29909 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29910 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29912 break;
29913 case OPC_MSA: /* OPC_MDMX */
29914 if (ctx->insn_flags & INSN_R5900) {
29915 #if defined(TARGET_MIPS64)
29916 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29917 #endif
29918 } else {
29919 /* MDMX: Not implemented. */
29920 gen_msa(env, ctx);
29922 break;
29923 case OPC_PCREL:
29924 check_insn(ctx, ISA_MIPS32R6);
29925 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29926 break;
29927 default: /* Invalid */
29928 MIPS_INVAL("major opcode");
29929 generate_exception_end(ctx, EXCP_RI);
29930 break;
29934 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29936 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29937 CPUMIPSState *env = cs->env_ptr;
29939 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29940 ctx->saved_pc = -1;
29941 ctx->insn_flags = env->insn_flags;
29942 ctx->CP0_Config1 = env->CP0_Config1;
29943 ctx->CP0_Config2 = env->CP0_Config2;
29944 ctx->CP0_Config3 = env->CP0_Config3;
29945 ctx->CP0_Config5 = env->CP0_Config5;
29946 ctx->btarget = 0;
29947 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29948 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29949 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29950 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29951 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29952 ctx->PAMask = env->PAMask;
29953 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29954 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29955 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29956 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29957 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29958 /* Restore delay slot state from the tb context. */
29959 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29960 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29961 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29962 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29963 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29964 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29965 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29966 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29967 restore_cpu_state(env, ctx);
29968 #ifdef CONFIG_USER_ONLY
29969 ctx->mem_idx = MIPS_HFLAG_UM;
29970 #else
29971 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29972 #endif
29973 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29974 MO_UNALN : MO_ALIGN;
29976 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29977 ctx->hflags);
29980 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29984 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29986 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29988 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29989 ctx->btarget);
29992 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29993 const CPUBreakpoint *bp)
29995 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29997 save_cpu_state(ctx, 1);
29998 ctx->base.is_jmp = DISAS_NORETURN;
29999 gen_helper_raise_exception_debug(cpu_env);
30001 * The address covered by the breakpoint must be included in
30002 * [tb->pc, tb->pc + tb->size) in order to for it to be
30003 * properly cleared -- thus we increment the PC here so that
30004 * the logic setting tb->size below does the right thing.
30006 ctx->base.pc_next += 4;
30007 return true;
30010 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30012 CPUMIPSState *env = cs->env_ptr;
30013 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30014 int insn_bytes;
30015 int is_slot;
30017 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
30018 if (ctx->insn_flags & ISA_NANOMIPS32) {
30019 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30020 insn_bytes = decode_nanomips_opc(env, ctx);
30021 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
30022 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30023 insn_bytes = 4;
30024 decode_opc(env, ctx);
30025 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30026 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30027 insn_bytes = decode_micromips_opc(env, ctx);
30028 } else if (ctx->insn_flags & ASE_MIPS16) {
30029 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30030 insn_bytes = decode_mips16_opc(env, ctx);
30031 } else {
30032 generate_exception_end(ctx, EXCP_RI);
30033 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30034 return;
30037 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30038 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30039 MIPS_HFLAG_FBNSLOT))) {
30041 * Force to generate branch as there is neither delay nor
30042 * forbidden slot.
30044 is_slot = 1;
30046 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30047 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
30049 * Force to generate branch as microMIPS R6 doesn't restrict
30050 * branches in the forbidden slot.
30052 is_slot = 1;
30055 if (is_slot) {
30056 gen_branch(ctx, insn_bytes);
30058 ctx->base.pc_next += insn_bytes;
30060 if (ctx->base.is_jmp != DISAS_NEXT) {
30061 return;
30064 * Execute a branch and its delay slot as a single instruction.
30065 * This is what GDB expects and is consistent with what the
30066 * hardware does (e.g. if a delay slot instruction faults, the
30067 * reported PC is the PC of the branch).
30069 if (ctx->base.singlestep_enabled &&
30070 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30071 ctx->base.is_jmp = DISAS_TOO_MANY;
30073 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30074 ctx->base.is_jmp = DISAS_TOO_MANY;
30078 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30080 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30082 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30083 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
30084 gen_helper_raise_exception_debug(cpu_env);
30085 } else {
30086 switch (ctx->base.is_jmp) {
30087 case DISAS_STOP:
30088 gen_save_pc(ctx->base.pc_next);
30089 tcg_gen_lookup_and_goto_ptr();
30090 break;
30091 case DISAS_NEXT:
30092 case DISAS_TOO_MANY:
30093 save_cpu_state(ctx, 0);
30094 gen_goto_tb(ctx, 0, ctx->base.pc_next);
30095 break;
30096 case DISAS_EXIT:
30097 tcg_gen_exit_tb(NULL, 0);
30098 break;
30099 case DISAS_NORETURN:
30100 break;
30101 default:
30102 g_assert_not_reached();
30107 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30109 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30110 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30113 static const TranslatorOps mips_tr_ops = {
30114 .init_disas_context = mips_tr_init_disas_context,
30115 .tb_start = mips_tr_tb_start,
30116 .insn_start = mips_tr_insn_start,
30117 .breakpoint_check = mips_tr_breakpoint_check,
30118 .translate_insn = mips_tr_translate_insn,
30119 .tb_stop = mips_tr_tb_stop,
30120 .disas_log = mips_tr_disas_log,
30123 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30125 DisasContext ctx;
30127 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
30130 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
30132 int i;
30133 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
30135 #define printfpr(fp) \
30136 do { \
30137 if (is_fpu64) \
30138 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30139 " fd:%13g fs:%13g psu: %13g\n", \
30140 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30141 (double)(fp)->fd, \
30142 (double)(fp)->fs[FP_ENDIAN_IDX], \
30143 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
30144 else { \
30145 fpr_t tmp; \
30146 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30147 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
30148 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30149 " fd:%13g fs:%13g psu:%13g\n", \
30150 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30151 (double)tmp.fd, \
30152 (double)tmp.fs[FP_ENDIAN_IDX], \
30153 (double)tmp.fs[!FP_ENDIAN_IDX]); \
30155 } while (0)
30158 qemu_fprintf(f,
30159 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30160 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30161 get_float_exception_flags(&env->active_fpu.fp_status));
30162 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
30163 qemu_fprintf(f, "%3s: ", fregnames[i]);
30164 printfpr(&env->active_fpu.fpr[i]);
30167 #undef printfpr
30170 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
30172 MIPSCPU *cpu = MIPS_CPU(cs);
30173 CPUMIPSState *env = &cpu->env;
30174 int i;
30176 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30177 " LO=0x" TARGET_FMT_lx " ds %04x "
30178 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30179 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30180 env->hflags, env->btarget, env->bcond);
30181 for (i = 0; i < 32; i++) {
30182 if ((i & 3) == 0) {
30183 qemu_fprintf(f, "GPR%02d:", i);
30185 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30186 regnames[i], env->active_tc.gpr[i]);
30187 if ((i & 3) == 3) {
30188 qemu_fprintf(f, "\n");
30192 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
30193 TARGET_FMT_lx "\n",
30194 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30195 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30196 PRIx64 "\n",
30197 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30198 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30199 env->CP0_Config2, env->CP0_Config3);
30200 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30201 env->CP0_Config4, env->CP0_Config5);
30202 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
30203 fpu_dump_state(env, f, flags);
30207 void mips_tcg_init(void)
30209 int i;
30211 cpu_gpr[0] = NULL;
30212 for (i = 1; i < 32; i++)
30213 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
30214 offsetof(CPUMIPSState,
30215 active_tc.gpr[i]),
30216 regnames[i]);
30218 for (i = 0; i < 32; i++) {
30219 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30220 msa_wr_d[i * 2] =
30221 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
30223 * The scalar floating-point unit (FPU) registers are mapped on
30224 * the MSA vector registers.
30226 fpu_f64[i] = msa_wr_d[i * 2];
30227 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30228 msa_wr_d[i * 2 + 1] =
30229 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
30232 cpu_PC = tcg_global_mem_new(cpu_env,
30233 offsetof(CPUMIPSState, active_tc.PC), "PC");
30234 for (i = 0; i < MIPS_DSP_ACC; i++) {
30235 cpu_HI[i] = tcg_global_mem_new(cpu_env,
30236 offsetof(CPUMIPSState, active_tc.HI[i]),
30237 regnames_HI[i]);
30238 cpu_LO[i] = tcg_global_mem_new(cpu_env,
30239 offsetof(CPUMIPSState, active_tc.LO[i]),
30240 regnames_LO[i]);
30242 cpu_dspctrl = tcg_global_mem_new(cpu_env,
30243 offsetof(CPUMIPSState,
30244 active_tc.DSPControl),
30245 "DSPControl");
30246 bcond = tcg_global_mem_new(cpu_env,
30247 offsetof(CPUMIPSState, bcond), "bcond");
30248 btarget = tcg_global_mem_new(cpu_env,
30249 offsetof(CPUMIPSState, btarget), "btarget");
30250 hflags = tcg_global_mem_new_i32(cpu_env,
30251 offsetof(CPUMIPSState, hflags), "hflags");
30253 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
30254 offsetof(CPUMIPSState, active_fpu.fcr0),
30255 "fcr0");
30256 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
30257 offsetof(CPUMIPSState, active_fpu.fcr31),
30258 "fcr31");
30259 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
30260 "lladdr");
30261 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
30262 "llval");
30264 #if defined(TARGET_MIPS64)
30265 cpu_mmr[0] = NULL;
30266 for (i = 1; i < 32; i++) {
30267 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
30268 offsetof(CPUMIPSState,
30269 active_tc.mmr[i]),
30270 regnames[i]);
30272 #endif
30274 #if !defined(TARGET_MIPS64)
30275 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
30276 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
30277 offsetof(CPUMIPSState,
30278 active_tc.mxu_gpr[i]),
30279 mxuregnames[i]);
30282 mxu_CR = tcg_global_mem_new(cpu_env,
30283 offsetof(CPUMIPSState, active_tc.mxu_cr),
30284 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
30285 #endif
30288 #include "translate_init.inc.c"
30290 void cpu_mips_realize_env(CPUMIPSState *env)
30292 env->exception_base = (int32_t)0xBFC00000;
30294 #ifndef CONFIG_USER_ONLY
30295 mmu_init(env, env->cpu_model);
30296 #endif
30297 fpu_init(env, env->cpu_model);
30298 mvp_init(env, env->cpu_model);
30301 bool cpu_supports_cps_smp(const char *cpu_type)
30303 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30304 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
30307 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
30309 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30310 return (mcc->cpu_def->insn_flags & isa) != 0;
30313 void cpu_set_exception_base(int vp_index, target_ulong address)
30315 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
30316 vp->env.exception_base = address;
30319 void cpu_state_reset(CPUMIPSState *env)
30321 CPUState *cs = env_cpu(env);
30323 /* Reset registers to their default values */
30324 env->CP0_PRid = env->cpu_model->CP0_PRid;
30325 env->CP0_Config0 = env->cpu_model->CP0_Config0;
30326 #ifdef TARGET_WORDS_BIGENDIAN
30327 env->CP0_Config0 |= (1 << CP0C0_BE);
30328 #endif
30329 env->CP0_Config1 = env->cpu_model->CP0_Config1;
30330 env->CP0_Config2 = env->cpu_model->CP0_Config2;
30331 env->CP0_Config3 = env->cpu_model->CP0_Config3;
30332 env->CP0_Config4 = env->cpu_model->CP0_Config4;
30333 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
30334 env->CP0_Config5 = env->cpu_model->CP0_Config5;
30335 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
30336 env->CP0_Config6 = env->cpu_model->CP0_Config6;
30337 env->CP0_Config7 = env->cpu_model->CP0_Config7;
30338 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
30339 << env->cpu_model->CP0_LLAddr_shift;
30340 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
30341 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
30342 env->CCRes = env->cpu_model->CCRes;
30343 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
30344 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
30345 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
30346 env->current_tc = 0;
30347 env->SEGBITS = env->cpu_model->SEGBITS;
30348 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
30349 #if defined(TARGET_MIPS64)
30350 if (env->cpu_model->insn_flags & ISA_MIPS3) {
30351 env->SEGMask |= 3ULL << 62;
30353 #endif
30354 env->PABITS = env->cpu_model->PABITS;
30355 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
30356 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
30357 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
30358 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
30359 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
30360 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
30361 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
30362 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
30363 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
30364 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
30365 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
30366 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
30367 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
30368 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
30369 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
30370 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
30371 env->msair = env->cpu_model->MSAIR;
30372 env->insn_flags = env->cpu_model->insn_flags;
30374 #if defined(CONFIG_USER_ONLY)
30375 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
30376 # ifdef TARGET_MIPS64
30377 /* Enable 64-bit register mode. */
30378 env->CP0_Status |= (1 << CP0St_PX);
30379 # endif
30380 # ifdef TARGET_ABI_MIPSN64
30381 /* Enable 64-bit address mode. */
30382 env->CP0_Status |= (1 << CP0St_UX);
30383 # endif
30385 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
30386 * hardware registers.
30388 env->CP0_HWREna |= 0x0000000F;
30389 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
30390 env->CP0_Status |= (1 << CP0St_CU1);
30392 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
30393 env->CP0_Status |= (1 << CP0St_MX);
30395 # if defined(TARGET_MIPS64)
30396 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
30397 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
30398 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
30399 env->CP0_Status |= (1 << CP0St_FR);
30401 # endif
30402 #else
30403 if (env->hflags & MIPS_HFLAG_BMASK) {
30405 * If the exception was raised from a delay slot,
30406 * come back to the jump.
30408 env->CP0_ErrorEPC = (env->active_tc.PC
30409 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
30410 } else {
30411 env->CP0_ErrorEPC = env->active_tc.PC;
30413 env->active_tc.PC = env->exception_base;
30414 env->CP0_Random = env->tlb->nb_tlb - 1;
30415 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30416 env->CP0_Wired = 0;
30417 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30418 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30419 if (mips_um_ksegs_enabled()) {
30420 env->CP0_EBase |= 0x40000000;
30421 } else {
30422 env->CP0_EBase |= (int32_t)0x80000000;
30424 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30425 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30427 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30428 0x3ff : 0xff;
30429 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30431 * Vectored interrupts not implemented, timer on int 7,
30432 * no performance counters.
30434 env->CP0_IntCtl = 0xe0000000;
30436 int i;
30438 for (i = 0; i < 7; i++) {
30439 env->CP0_WatchLo[i] = 0;
30440 env->CP0_WatchHi[i] = 0x80000000;
30442 env->CP0_WatchLo[7] = 0;
30443 env->CP0_WatchHi[7] = 0;
30445 /* Count register increments in debug mode, EJTAG version 1 */
30446 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30448 cpu_mips_store_count(env, 1);
30450 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30451 int i;
30453 /* Only TC0 on VPE 0 starts as active. */
30454 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30455 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30456 env->tcs[i].CP0_TCHalt = 1;
30458 env->active_tc.CP0_TCHalt = 1;
30459 cs->halted = 1;
30461 if (cs->cpu_index == 0) {
30462 /* VPE0 starts up enabled. */
30463 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30464 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30466 /* TC0 starts up unhalted. */
30467 cs->halted = 0;
30468 env->active_tc.CP0_TCHalt = 0;
30469 env->tcs[0].CP0_TCHalt = 0;
30470 /* With thread 0 active. */
30471 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30472 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30477 * Configure default legacy segmentation control. We use this regardless of
30478 * whether segmentation control is presented to the guest.
30480 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30481 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30482 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30483 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30484 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30485 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30486 (2 << CP0SC_C);
30487 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30488 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30489 (3 << CP0SC_C)) << 16;
30490 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30491 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30492 (1 << CP0SC_EU) | (2 << CP0SC_C);
30493 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30494 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30495 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30496 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30497 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30498 #endif
30499 if ((env->insn_flags & ISA_MIPS32R6) &&
30500 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30501 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30502 env->CP0_Status |= (1 << CP0St_FR);
30505 if (env->insn_flags & ISA_MIPS32R6) {
30506 /* PTW = 1 */
30507 env->CP0_PWSize = 0x40;
30508 /* GDI = 12 */
30509 /* UDI = 12 */
30510 /* MDI = 12 */
30511 /* PRI = 12 */
30512 /* PTEI = 2 */
30513 env->CP0_PWField = 0x0C30C302;
30514 } else {
30515 /* GDI = 0 */
30516 /* UDI = 0 */
30517 /* MDI = 0 */
30518 /* PRI = 0 */
30519 /* PTEI = 2 */
30520 env->CP0_PWField = 0x02;
30523 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30524 /* microMIPS on reset when Config3.ISA is 3 */
30525 env->hflags |= MIPS_HFLAG_M16;
30528 /* MSA */
30529 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30530 msa_reset(env);
30533 compute_hflags(env);
30534 restore_fp_status(env);
30535 restore_pamask(env);
30536 cs->exception_index = EXCP_NONE;
30538 if (semihosting_get_argc()) {
30539 /* UHI interface can be used to obtain argc and argv */
30540 env->active_tc.gpr[4] = -1;
30544 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30545 target_ulong *data)
30547 env->active_tc.PC = data[0];
30548 env->hflags &= ~MIPS_HFLAG_BMASK;
30549 env->hflags |= data[1];
30550 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30551 case MIPS_HFLAG_BR:
30552 break;
30553 case MIPS_HFLAG_BC:
30554 case MIPS_HFLAG_BL:
30555 case MIPS_HFLAG_B:
30556 env->btarget = data[2];
30557 break;