virtio-crypto: don't modify elem->in/out_sg
[qemu/kevin.git] / target / mips / translate.c
blob398edf728980c56a7aae0e2e7c5afab21e01ebb5
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/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,
391 OPC_GINV = 0x3D | OPC_SPECIAL3,
393 /* Loongson 2E */
394 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
395 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
396 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
397 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
398 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
399 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
400 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
401 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
402 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
403 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
404 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
405 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
407 /* MIPS DSP Load */
408 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
409 /* MIPS DSP Arithmetic */
410 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
411 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
412 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
413 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
414 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
415 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
417 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
418 /* MIPS DSP GPR-Based Shift Sub-class */
419 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
420 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
421 /* MIPS DSP Multiply Sub-class insns */
422 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
423 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
424 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
425 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
426 /* DSP Bit/Manipulation Sub-class */
427 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
428 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
429 /* MIPS DSP Append Sub-class */
430 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
431 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
432 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
433 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
434 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
436 /* EVA */
437 OPC_LWLE = 0x19 | OPC_SPECIAL3,
438 OPC_LWRE = 0x1A | OPC_SPECIAL3,
439 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
440 OPC_SBE = 0x1C | OPC_SPECIAL3,
441 OPC_SHE = 0x1D | OPC_SPECIAL3,
442 OPC_SCE = 0x1E | OPC_SPECIAL3,
443 OPC_SWE = 0x1F | OPC_SPECIAL3,
444 OPC_SWLE = 0x21 | OPC_SPECIAL3,
445 OPC_SWRE = 0x22 | OPC_SPECIAL3,
446 OPC_PREFE = 0x23 | OPC_SPECIAL3,
447 OPC_LBUE = 0x28 | OPC_SPECIAL3,
448 OPC_LHUE = 0x29 | OPC_SPECIAL3,
449 OPC_LBE = 0x2C | OPC_SPECIAL3,
450 OPC_LHE = 0x2D | OPC_SPECIAL3,
451 OPC_LLE = 0x2E | OPC_SPECIAL3,
452 OPC_LWE = 0x2F | OPC_SPECIAL3,
454 /* R6 */
455 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
456 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
457 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
458 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
459 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
460 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
463 /* BSHFL opcodes */
464 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
466 enum {
467 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
468 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
469 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
470 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
471 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
472 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
473 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
474 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
477 /* DBSHFL opcodes */
478 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
480 enum {
481 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
482 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
483 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
484 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
485 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
486 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
487 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
488 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
489 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
490 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
491 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
494 /* MIPS DSP REGIMM opcodes */
495 enum {
496 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
497 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
500 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
501 /* MIPS DSP Load */
502 enum {
503 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
504 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
505 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
506 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
509 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 /* MIPS DSP Arithmetic Sub-class */
512 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
518 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
525 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
527 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
529 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
530 /* MIPS DSP Multiply Sub-class insns */
531 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
536 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
539 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
540 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
541 enum {
542 /* MIPS DSP Arithmetic Sub-class */
543 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
554 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
555 /* MIPS DSP Multiply Sub-class insns */
556 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
559 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
562 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
563 enum {
564 /* MIPS DSP Arithmetic Sub-class */
565 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
578 /* DSP Bit/Manipulation Sub-class */
579 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
583 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
586 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
587 enum {
588 /* MIPS DSP Arithmetic Sub-class */
589 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
596 /* DSP Compare-Pick Sub-class */
597 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
611 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
614 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
615 enum {
616 /* MIPS DSP GPR-Based Shift Sub-class */
617 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
638 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
641 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
642 enum {
643 /* MIPS DSP Multiply Sub-class insns */
644 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
657 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
660 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
665 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
668 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* DSP Bit/Manipulation Sub-class */
671 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
674 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
675 enum {
676 /* MIPS DSP Append Sub-class */
677 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
678 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
679 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
682 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
683 enum {
684 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
685 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
696 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
698 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
699 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
700 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
701 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
704 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Arithmetic Sub-class */
707 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
724 /* DSP Bit/Manipulation Sub-class */
725 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
730 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
733 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
734 enum {
735 /* MIPS DSP Multiply Sub-class insns */
736 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
740 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
741 /* MIPS DSP Arithmetic Sub-class */
742 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
752 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
762 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
765 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
766 enum {
767 /* DSP Compare-Pick Sub-class */
768 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
787 /* MIPS DSP Arithmetic Sub-class */
788 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
795 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
798 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
799 enum {
800 /* DSP Append Sub-class */
801 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
803 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
804 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
807 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
808 enum {
809 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
810 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
811 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
830 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
833 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
834 enum {
835 /* DSP Bit/Manipulation Sub-class */
836 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
839 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
840 enum {
841 /* MIPS DSP Multiply Sub-class insns */
842 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
867 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
870 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
871 enum {
872 /* MIPS DSP GPR-Based Shift Sub-class */
873 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
898 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
901 /* Coprocessor 0 (rs field) */
902 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
904 enum {
905 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
906 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
907 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
908 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
909 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
910 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
911 OPC_MFTR = (0x08 << 21) | OPC_CP0,
912 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
913 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
914 OPC_MTTR = (0x0C << 21) | OPC_CP0,
915 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
916 OPC_C0 = (0x10 << 21) | OPC_CP0,
917 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
918 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
919 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
920 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
921 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
922 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
923 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
924 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
925 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
926 OPC_C0_A = (0x1A << 21) | OPC_CP0,
927 OPC_C0_B = (0x1B << 21) | OPC_CP0,
928 OPC_C0_C = (0x1C << 21) | OPC_CP0,
929 OPC_C0_D = (0x1D << 21) | OPC_CP0,
930 OPC_C0_E = (0x1E << 21) | OPC_CP0,
931 OPC_C0_F = (0x1F << 21) | OPC_CP0,
934 /* MFMC0 opcodes */
935 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
937 enum {
938 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
940 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
941 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
942 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
943 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
944 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
945 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
948 /* Coprocessor 0 (with rs == C0) */
949 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
951 enum {
952 OPC_TLBR = 0x01 | OPC_C0,
953 OPC_TLBWI = 0x02 | OPC_C0,
954 OPC_TLBINV = 0x03 | OPC_C0,
955 OPC_TLBINVF = 0x04 | OPC_C0,
956 OPC_TLBWR = 0x06 | OPC_C0,
957 OPC_TLBP = 0x08 | OPC_C0,
958 OPC_RFE = 0x10 | OPC_C0,
959 OPC_ERET = 0x18 | OPC_C0,
960 OPC_DERET = 0x1F | OPC_C0,
961 OPC_WAIT = 0x20 | OPC_C0,
964 /* Coprocessor 1 (rs field) */
965 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
967 /* Values for the fmt field in FP instructions */
968 enum {
969 /* 0 - 15 are reserved */
970 FMT_S = 16, /* single fp */
971 FMT_D = 17, /* double fp */
972 FMT_E = 18, /* extended fp */
973 FMT_Q = 19, /* quad fp */
974 FMT_W = 20, /* 32-bit fixed */
975 FMT_L = 21, /* 64-bit fixed */
976 FMT_PS = 22, /* paired single fp */
977 /* 23 - 31 are reserved */
980 enum {
981 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
982 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
983 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
984 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
985 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
986 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
987 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
988 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
989 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
990 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
991 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
992 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
993 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
994 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
995 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
996 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
997 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
998 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
999 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1000 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1001 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1002 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1003 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1004 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1005 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1006 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1007 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1008 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1009 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1010 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1013 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1014 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1016 enum {
1017 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1018 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1019 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1020 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1023 enum {
1024 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1025 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1028 enum {
1029 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1030 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1033 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1035 enum {
1036 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1037 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1038 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1039 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1040 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1041 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1042 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1043 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1044 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1045 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1046 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1049 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1051 enum {
1052 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1059 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1061 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1068 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1070 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1073 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1074 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1075 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1076 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1077 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1079 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1082 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1086 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1088 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1089 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1093 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1095 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1100 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1102 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1107 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1109 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1114 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1116 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1117 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1118 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1119 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1121 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1123 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1124 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1125 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1126 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1128 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1130 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1131 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1133 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1135 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1137 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1138 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1139 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1140 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1141 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1142 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1146 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1148 enum {
1149 OPC_LWXC1 = 0x00 | OPC_CP3,
1150 OPC_LDXC1 = 0x01 | OPC_CP3,
1151 OPC_LUXC1 = 0x05 | OPC_CP3,
1152 OPC_SWXC1 = 0x08 | OPC_CP3,
1153 OPC_SDXC1 = 0x09 | OPC_CP3,
1154 OPC_SUXC1 = 0x0D | OPC_CP3,
1155 OPC_PREFX = 0x0F | OPC_CP3,
1156 OPC_ALNV_PS = 0x1E | OPC_CP3,
1157 OPC_MADD_S = 0x20 | OPC_CP3,
1158 OPC_MADD_D = 0x21 | OPC_CP3,
1159 OPC_MADD_PS = 0x26 | OPC_CP3,
1160 OPC_MSUB_S = 0x28 | OPC_CP3,
1161 OPC_MSUB_D = 0x29 | OPC_CP3,
1162 OPC_MSUB_PS = 0x2E | OPC_CP3,
1163 OPC_NMADD_S = 0x30 | OPC_CP3,
1164 OPC_NMADD_D = 0x31 | OPC_CP3,
1165 OPC_NMADD_PS = 0x36 | OPC_CP3,
1166 OPC_NMSUB_S = 0x38 | OPC_CP3,
1167 OPC_NMSUB_D = 0x39 | OPC_CP3,
1168 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1171 /* MSA Opcodes */
1172 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1173 enum {
1174 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1175 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1176 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1177 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1178 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1179 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1180 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1181 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1182 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1183 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1184 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1185 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1186 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1187 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1188 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1189 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1190 OPC_MSA_ELM = 0x19 | OPC_MSA,
1191 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1192 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1193 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1194 OPC_MSA_VEC = 0x1E | OPC_MSA,
1196 /* MI10 instruction */
1197 OPC_LD_B = (0x20) | OPC_MSA,
1198 OPC_LD_H = (0x21) | OPC_MSA,
1199 OPC_LD_W = (0x22) | OPC_MSA,
1200 OPC_LD_D = (0x23) | OPC_MSA,
1201 OPC_ST_B = (0x24) | OPC_MSA,
1202 OPC_ST_H = (0x25) | OPC_MSA,
1203 OPC_ST_W = (0x26) | OPC_MSA,
1204 OPC_ST_D = (0x27) | OPC_MSA,
1207 enum {
1208 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1209 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1210 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1211 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1212 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1213 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1214 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1215 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1216 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1217 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1218 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1219 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1220 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1222 /* I8 instruction */
1223 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1224 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1225 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1226 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1227 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1228 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1229 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1230 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1231 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1232 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1234 /* VEC/2R/2RF instruction */
1235 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1236 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1237 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1238 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1239 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1240 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1241 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1244 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1246 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1247 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1248 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1249 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1250 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1252 /* 2RF instruction df(bit 16) = _w, _d */
1253 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1255 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1256 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1257 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1258 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1259 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1260 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1262 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1263 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1264 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1266 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1268 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1270 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1271 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1272 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1273 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1274 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1275 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1276 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1277 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1278 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1279 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1280 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1281 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1282 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1283 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1284 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1285 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1286 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1287 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1288 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1289 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1290 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1291 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1292 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1293 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1294 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1295 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1296 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1297 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1298 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1299 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1300 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1301 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1302 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1303 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1304 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1305 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1306 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1307 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1308 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1309 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1310 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1311 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1312 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1313 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1314 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1315 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1316 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1317 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1318 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1319 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1320 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1321 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1322 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1323 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1324 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1325 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1326 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1327 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1328 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1329 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1330 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1331 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1332 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1333 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1335 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1336 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1340 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1342 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1344 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1346 /* 3RF instruction _df(bit 21) = _w, _d */
1347 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1348 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1349 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1351 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1353 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1354 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1355 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1356 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1357 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1358 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1360 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1361 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1362 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1363 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1364 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1365 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1366 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1368 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1369 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1371 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1372 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1373 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1374 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1375 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1376 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1377 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1378 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1379 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1380 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1381 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1382 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1383 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1384 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1385 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1386 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1387 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1389 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1390 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1391 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1392 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1393 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1394 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1395 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1396 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1397 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1398 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1399 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1401 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1407 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1408 * ============================================
1411 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1412 * instructions set. It is designed to fit the needs of signal, graphical and
1413 * video processing applications. MXU instruction set is used in Xburst family
1414 * of microprocessors by Ingenic.
1416 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1417 * the control register.
1420 * The notation used in MXU assembler mnemonics
1421 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1423 * Register operands:
1425 * XRa, XRb, XRc, XRd - MXU registers
1426 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1428 * Non-register operands:
1430 * aptn1 - 1-bit accumulate add/subtract pattern
1431 * aptn2 - 2-bit accumulate add/subtract pattern
1432 * eptn2 - 2-bit execute add/subtract pattern
1433 * optn2 - 2-bit operand pattern
1434 * optn3 - 3-bit operand pattern
1435 * sft4 - 4-bit shift amount
1436 * strd2 - 2-bit stride amount
1438 * Prefixes:
1440 * Level of parallelism: Operand size:
1441 * S - single operation at a time 32 - word
1442 * D - two operations in parallel 16 - half word
1443 * Q - four operations in parallel 8 - byte
1445 * Operations:
1447 * ADD - Add or subtract
1448 * ADDC - Add with carry-in
1449 * ACC - Accumulate
1450 * ASUM - Sum together then accumulate (add or subtract)
1451 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1452 * AVG - Average between 2 operands
1453 * ABD - Absolute difference
1454 * ALN - Align data
1455 * AND - Logical bitwise 'and' operation
1456 * CPS - Copy sign
1457 * EXTR - Extract bits
1458 * I2M - Move from GPR register to MXU register
1459 * LDD - Load data from memory to XRF
1460 * LDI - Load data from memory to XRF (and increase the address base)
1461 * LUI - Load unsigned immediate
1462 * MUL - Multiply
1463 * MULU - Unsigned multiply
1464 * MADD - 64-bit operand add 32x32 product
1465 * MSUB - 64-bit operand subtract 32x32 product
1466 * MAC - Multiply and accumulate (add or subtract)
1467 * MAD - Multiply and add or subtract
1468 * MAX - Maximum between 2 operands
1469 * MIN - Minimum between 2 operands
1470 * M2I - Move from MXU register to GPR register
1471 * MOVZ - Move if zero
1472 * MOVN - Move if non-zero
1473 * NOR - Logical bitwise 'nor' operation
1474 * OR - Logical bitwise 'or' operation
1475 * STD - Store data from XRF to memory
1476 * SDI - Store data from XRF to memory (and increase the address base)
1477 * SLT - Set of less than comparison
1478 * SAD - Sum of absolute differences
1479 * SLL - Logical shift left
1480 * SLR - Logical shift right
1481 * SAR - Arithmetic shift right
1482 * SAT - Saturation
1483 * SFL - Shuffle
1484 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1485 * XOR - Logical bitwise 'exclusive or' operation
1487 * Suffixes:
1489 * E - Expand results
1490 * F - Fixed point multiplication
1491 * L - Low part result
1492 * R - Doing rounding
1493 * V - Variable instead of immediate
1494 * W - Combine above L and V
1497 * The list of MXU instructions grouped by functionality
1498 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1500 * Load/Store instructions Multiplication instructions
1501 * ----------------------- ---------------------------
1503 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1504 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1505 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1506 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1507 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1508 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1509 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1510 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1511 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1512 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1516 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1517 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1518 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1519 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1520 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1521 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1522 * S16SDI XRa, Rb, s10, eptn2
1523 * S8LDD XRa, Rb, s8, eptn3
1524 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1525 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1526 * S8SDI XRa, Rb, s8, eptn3
1527 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1528 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1529 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1530 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1531 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1532 * S32CPS XRa, XRb, XRc
1533 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1534 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1535 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1536 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1537 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1538 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1539 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1540 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1541 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1542 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1543 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1544 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1545 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1546 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1547 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1548 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1549 * Q8SLT XRa, XRb, XRc
1550 * Q8SLTU XRa, XRb, XRc
1551 * Q8MOVZ XRa, XRb, XRc Shift instructions
1552 * Q8MOVN XRa, XRb, XRc ------------------
1554 * D32SLL XRa, XRb, XRc, XRd, sft4
1555 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1556 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1557 * D32SARL XRa, XRb, XRc, sft4
1558 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1559 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1560 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1561 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1562 * Q16SLL XRa, XRb, XRc, XRd, sft4
1563 * Q16SLR XRa, XRb, XRc, XRd, sft4
1564 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1565 * ------------------------- Q16SLLV XRa, XRb, Rb
1566 * Q16SLRV XRa, XRb, Rb
1567 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1568 * S32ALN XRa, XRb, XRc, Rb
1569 * S32ALNI XRa, XRb, XRc, s3
1570 * S32LUI XRa, s8, optn3 Move instructions
1571 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1572 * S32EXTRV XRa, XRb, Rs, Rt
1573 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1574 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1577 * The opcode organization of MXU instructions
1578 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1580 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1581 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1582 * other bits up to the instruction level is as follows:
1584 * bits
1585 * 05..00
1587 * ┌─ 000000 ─ OPC_MXU_S32MADD
1588 * ├─ 000001 ─ OPC_MXU_S32MADDU
1589 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1590 * │
1591 * │ 20..18
1592 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1593 * │ ├─ 001 ─ OPC_MXU_S32MIN
1594 * │ ├─ 010 ─ OPC_MXU_D16MAX
1595 * │ ├─ 011 ─ OPC_MXU_D16MIN
1596 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1597 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1598 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1599 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1600 * ├─ 000100 ─ OPC_MXU_S32MSUB
1601 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1602 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1603 * │ ├─ 001 ─ OPC_MXU_D16SLT
1604 * │ ├─ 010 ─ OPC_MXU_D16AVG
1605 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1606 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1607 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1608 * │ └─ 111 ─ OPC_MXU_Q8ADD
1609 * │
1610 * │ 20..18
1611 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1612 * │ ├─ 010 ─ OPC_MXU_D16CPS
1613 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1614 * │ └─ 110 ─ OPC_MXU_Q16SAT
1615 * ├─ 001000 ─ OPC_MXU_D16MUL
1616 * │ 25..24
1617 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1618 * │ └─ 01 ─ OPC_MXU_D16MULE
1619 * ├─ 001010 ─ OPC_MXU_D16MAC
1620 * ├─ 001011 ─ OPC_MXU_D16MACF
1621 * ├─ 001100 ─ OPC_MXU_D16MADL
1622 * ├─ 001101 ─ OPC_MXU_S16MAD
1623 * ├─ 001110 ─ OPC_MXU_Q16ADD
1624 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1625 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1626 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1627 * │
1628 * │ 23
1629 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1630 * │ └─ 1 ─ OPC_MXU_S32STDR
1631 * │
1632 * │ 13..10
1633 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1634 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1635 * │
1636 * │ 13..10
1637 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1638 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1639 * │
1640 * │ 23
1641 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1642 * │ └─ 1 ─ OPC_MXU_S32LDIR
1643 * │
1644 * │ 23
1645 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1646 * │ └─ 1 ─ OPC_MXU_S32SDIR
1647 * │
1648 * │ 13..10
1649 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1650 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1651 * │
1652 * │ 13..10
1653 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1654 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1655 * ├─ 011000 ─ OPC_MXU_D32ADD
1656 * │ 23..22
1657 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1658 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1659 * │ └─ 10 ─ OPC_MXU_D32ASUM
1660 * ├─ 011010 ─ <not assigned>
1661 * │ 23..22
1662 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1663 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1664 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1665 * │
1666 * │ 23..22
1667 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1668 * │ ├─ 01 ─ OPC_MXU_D8SUM
1669 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1670 * ├─ 011110 ─ <not assigned>
1671 * ├─ 011111 ─ <not assigned>
1672 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1673 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1674 * ├─ 100010 ─ OPC_MXU_S8LDD
1675 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1676 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1677 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1678 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1679 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1680 * │
1681 * │ 20..18
1682 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1683 * │ ├─ 001 ─ OPC_MXU_S32ALN
1684 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1685 * │ ├─ 011 ─ OPC_MXU_S32LUI
1686 * │ ├─ 100 ─ OPC_MXU_S32NOR
1687 * │ ├─ 101 ─ OPC_MXU_S32AND
1688 * │ ├─ 110 ─ OPC_MXU_S32OR
1689 * │ └─ 111 ─ OPC_MXU_S32XOR
1690 * │
1691 * │ 7..5
1692 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1693 * │ ├─ 001 ─ OPC_MXU_LXH
1694 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1695 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1696 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1697 * ├─ 101100 ─ OPC_MXU_S16LDI
1698 * ├─ 101101 ─ OPC_MXU_S16SDI
1699 * ├─ 101110 ─ OPC_MXU_S32M2I
1700 * ├─ 101111 ─ OPC_MXU_S32I2M
1701 * ├─ 110000 ─ OPC_MXU_D32SLL
1702 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1703 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1704 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1705 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1706 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1707 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1708 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1709 * │
1710 * ├─ 110111 ─ OPC_MXU_Q16SAR
1711 * │ 23..22
1712 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1713 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1714 * │
1715 * │ 20..18
1716 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1717 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1718 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1719 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1720 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1721 * │ └─ 101 ─ OPC_MXU_S32MOVN
1722 * │
1723 * │ 23..22
1724 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1725 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1726 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1727 * ├─ 111100 ─ OPC_MXU_Q8MADL
1728 * ├─ 111101 ─ OPC_MXU_S32SFL
1729 * ├─ 111110 ─ OPC_MXU_Q8SAD
1730 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1733 * Compiled after:
1735 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1736 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1739 enum {
1740 OPC_MXU_S32MADD = 0x00,
1741 OPC_MXU_S32MADDU = 0x01,
1742 OPC__MXU_MUL = 0x02,
1743 OPC_MXU__POOL00 = 0x03,
1744 OPC_MXU_S32MSUB = 0x04,
1745 OPC_MXU_S32MSUBU = 0x05,
1746 OPC_MXU__POOL01 = 0x06,
1747 OPC_MXU__POOL02 = 0x07,
1748 OPC_MXU_D16MUL = 0x08,
1749 OPC_MXU__POOL03 = 0x09,
1750 OPC_MXU_D16MAC = 0x0A,
1751 OPC_MXU_D16MACF = 0x0B,
1752 OPC_MXU_D16MADL = 0x0C,
1753 OPC_MXU_S16MAD = 0x0D,
1754 OPC_MXU_Q16ADD = 0x0E,
1755 OPC_MXU_D16MACE = 0x0F,
1756 OPC_MXU__POOL04 = 0x10,
1757 OPC_MXU__POOL05 = 0x11,
1758 OPC_MXU__POOL06 = 0x12,
1759 OPC_MXU__POOL07 = 0x13,
1760 OPC_MXU__POOL08 = 0x14,
1761 OPC_MXU__POOL09 = 0x15,
1762 OPC_MXU__POOL10 = 0x16,
1763 OPC_MXU__POOL11 = 0x17,
1764 OPC_MXU_D32ADD = 0x18,
1765 OPC_MXU__POOL12 = 0x19,
1766 /* not assigned 0x1A */
1767 OPC_MXU__POOL13 = 0x1B,
1768 OPC_MXU__POOL14 = 0x1C,
1769 OPC_MXU_Q8ACCE = 0x1D,
1770 /* not assigned 0x1E */
1771 /* not assigned 0x1F */
1772 /* not assigned 0x20 */
1773 /* not assigned 0x21 */
1774 OPC_MXU_S8LDD = 0x22,
1775 OPC_MXU_S8STD = 0x23,
1776 OPC_MXU_S8LDI = 0x24,
1777 OPC_MXU_S8SDI = 0x25,
1778 OPC_MXU__POOL15 = 0x26,
1779 OPC_MXU__POOL16 = 0x27,
1780 OPC_MXU__POOL17 = 0x28,
1781 /* not assigned 0x29 */
1782 OPC_MXU_S16LDD = 0x2A,
1783 OPC_MXU_S16STD = 0x2B,
1784 OPC_MXU_S16LDI = 0x2C,
1785 OPC_MXU_S16SDI = 0x2D,
1786 OPC_MXU_S32M2I = 0x2E,
1787 OPC_MXU_S32I2M = 0x2F,
1788 OPC_MXU_D32SLL = 0x30,
1789 OPC_MXU_D32SLR = 0x31,
1790 OPC_MXU_D32SARL = 0x32,
1791 OPC_MXU_D32SAR = 0x33,
1792 OPC_MXU_Q16SLL = 0x34,
1793 OPC_MXU_Q16SLR = 0x35,
1794 OPC_MXU__POOL18 = 0x36,
1795 OPC_MXU_Q16SAR = 0x37,
1796 OPC_MXU__POOL19 = 0x38,
1797 OPC_MXU__POOL20 = 0x39,
1798 OPC_MXU__POOL21 = 0x3A,
1799 OPC_MXU_Q16SCOP = 0x3B,
1800 OPC_MXU_Q8MADL = 0x3C,
1801 OPC_MXU_S32SFL = 0x3D,
1802 OPC_MXU_Q8SAD = 0x3E,
1803 /* not assigned 0x3F */
1808 * MXU pool 00
1810 enum {
1811 OPC_MXU_S32MAX = 0x00,
1812 OPC_MXU_S32MIN = 0x01,
1813 OPC_MXU_D16MAX = 0x02,
1814 OPC_MXU_D16MIN = 0x03,
1815 OPC_MXU_Q8MAX = 0x04,
1816 OPC_MXU_Q8MIN = 0x05,
1817 OPC_MXU_Q8SLT = 0x06,
1818 OPC_MXU_Q8SLTU = 0x07,
1822 * MXU pool 01
1824 enum {
1825 OPC_MXU_S32SLT = 0x00,
1826 OPC_MXU_D16SLT = 0x01,
1827 OPC_MXU_D16AVG = 0x02,
1828 OPC_MXU_D16AVGR = 0x03,
1829 OPC_MXU_Q8AVG = 0x04,
1830 OPC_MXU_Q8AVGR = 0x05,
1831 OPC_MXU_Q8ADD = 0x07,
1835 * MXU pool 02
1837 enum {
1838 OPC_MXU_S32CPS = 0x00,
1839 OPC_MXU_D16CPS = 0x02,
1840 OPC_MXU_Q8ABD = 0x04,
1841 OPC_MXU_Q16SAT = 0x06,
1845 * MXU pool 03
1847 enum {
1848 OPC_MXU_D16MULF = 0x00,
1849 OPC_MXU_D16MULE = 0x01,
1853 * MXU pool 04
1855 enum {
1856 OPC_MXU_S32LDD = 0x00,
1857 OPC_MXU_S32LDDR = 0x01,
1861 * MXU pool 05
1863 enum {
1864 OPC_MXU_S32STD = 0x00,
1865 OPC_MXU_S32STDR = 0x01,
1869 * MXU pool 06
1871 enum {
1872 OPC_MXU_S32LDDV = 0x00,
1873 OPC_MXU_S32LDDVR = 0x01,
1877 * MXU pool 07
1879 enum {
1880 OPC_MXU_S32STDV = 0x00,
1881 OPC_MXU_S32STDVR = 0x01,
1885 * MXU pool 08
1887 enum {
1888 OPC_MXU_S32LDI = 0x00,
1889 OPC_MXU_S32LDIR = 0x01,
1893 * MXU pool 09
1895 enum {
1896 OPC_MXU_S32SDI = 0x00,
1897 OPC_MXU_S32SDIR = 0x01,
1901 * MXU pool 10
1903 enum {
1904 OPC_MXU_S32LDIV = 0x00,
1905 OPC_MXU_S32LDIVR = 0x01,
1909 * MXU pool 11
1911 enum {
1912 OPC_MXU_S32SDIV = 0x00,
1913 OPC_MXU_S32SDIVR = 0x01,
1917 * MXU pool 12
1919 enum {
1920 OPC_MXU_D32ACC = 0x00,
1921 OPC_MXU_D32ACCM = 0x01,
1922 OPC_MXU_D32ASUM = 0x02,
1926 * MXU pool 13
1928 enum {
1929 OPC_MXU_Q16ACC = 0x00,
1930 OPC_MXU_Q16ACCM = 0x01,
1931 OPC_MXU_Q16ASUM = 0x02,
1935 * MXU pool 14
1937 enum {
1938 OPC_MXU_Q8ADDE = 0x00,
1939 OPC_MXU_D8SUM = 0x01,
1940 OPC_MXU_D8SUMC = 0x02,
1944 * MXU pool 15
1946 enum {
1947 OPC_MXU_S32MUL = 0x00,
1948 OPC_MXU_S32MULU = 0x01,
1949 OPC_MXU_S32EXTR = 0x02,
1950 OPC_MXU_S32EXTRV = 0x03,
1954 * MXU pool 16
1956 enum {
1957 OPC_MXU_D32SARW = 0x00,
1958 OPC_MXU_S32ALN = 0x01,
1959 OPC_MXU_S32ALNI = 0x02,
1960 OPC_MXU_S32LUI = 0x03,
1961 OPC_MXU_S32NOR = 0x04,
1962 OPC_MXU_S32AND = 0x05,
1963 OPC_MXU_S32OR = 0x06,
1964 OPC_MXU_S32XOR = 0x07,
1968 * MXU pool 17
1970 enum {
1971 OPC_MXU_LXB = 0x00,
1972 OPC_MXU_LXH = 0x01,
1973 OPC_MXU_LXW = 0x03,
1974 OPC_MXU_LXBU = 0x04,
1975 OPC_MXU_LXHU = 0x05,
1979 * MXU pool 18
1981 enum {
1982 OPC_MXU_D32SLLV = 0x00,
1983 OPC_MXU_D32SLRV = 0x01,
1984 OPC_MXU_D32SARV = 0x03,
1985 OPC_MXU_Q16SLLV = 0x04,
1986 OPC_MXU_Q16SLRV = 0x05,
1987 OPC_MXU_Q16SARV = 0x07,
1991 * MXU pool 19
1993 enum {
1994 OPC_MXU_Q8MUL = 0x00,
1995 OPC_MXU_Q8MULSU = 0x01,
1999 * MXU pool 20
2001 enum {
2002 OPC_MXU_Q8MOVZ = 0x00,
2003 OPC_MXU_Q8MOVN = 0x01,
2004 OPC_MXU_D16MOVZ = 0x02,
2005 OPC_MXU_D16MOVN = 0x03,
2006 OPC_MXU_S32MOVZ = 0x04,
2007 OPC_MXU_S32MOVN = 0x05,
2011 * MXU pool 21
2013 enum {
2014 OPC_MXU_Q8MAC = 0x00,
2015 OPC_MXU_Q8MACSU = 0x01,
2019 * Overview of the TX79-specific instruction set
2020 * =============================================
2022 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2023 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2024 * instructions and certain multimedia instructions (MMIs). These MMIs
2025 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2026 * or sixteen 8-bit paths.
2028 * Reference:
2030 * The Toshiba TX System RISC TX79 Core Architecture manual,
2031 * https://wiki.qemu.org/File:C790.pdf
2033 * Three-Operand Multiply and Multiply-Add (4 instructions)
2034 * --------------------------------------------------------
2035 * MADD [rd,] rs, rt Multiply/Add
2036 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2037 * MULT [rd,] rs, rt Multiply (3-operand)
2038 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2040 * Multiply Instructions for Pipeline 1 (10 instructions)
2041 * ------------------------------------------------------
2042 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2043 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2044 * DIV1 rs, rt Divide Pipeline 1
2045 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2046 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2047 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2048 * MFHI1 rd Move From HI1 Register
2049 * MFLO1 rd Move From LO1 Register
2050 * MTHI1 rs Move To HI1 Register
2051 * MTLO1 rs Move To LO1 Register
2053 * Arithmetic (19 instructions)
2054 * ----------------------------
2055 * PADDB rd, rs, rt Parallel Add Byte
2056 * PSUBB rd, rs, rt Parallel Subtract Byte
2057 * PADDH rd, rs, rt Parallel Add Halfword
2058 * PSUBH rd, rs, rt Parallel Subtract Halfword
2059 * PADDW rd, rs, rt Parallel Add Word
2060 * PSUBW rd, rs, rt Parallel Subtract Word
2061 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2062 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2063 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2064 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2065 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2066 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2067 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2068 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2069 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2070 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2071 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2072 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2073 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2075 * Min/Max (4 instructions)
2076 * ------------------------
2077 * PMAXH rd, rs, rt Parallel Maximum Halfword
2078 * PMINH rd, rs, rt Parallel Minimum Halfword
2079 * PMAXW rd, rs, rt Parallel Maximum Word
2080 * PMINW rd, rs, rt Parallel Minimum Word
2082 * Absolute (2 instructions)
2083 * -------------------------
2084 * PABSH rd, rt Parallel Absolute Halfword
2085 * PABSW rd, rt Parallel Absolute Word
2087 * Logical (4 instructions)
2088 * ------------------------
2089 * PAND rd, rs, rt Parallel AND
2090 * POR rd, rs, rt Parallel OR
2091 * PXOR rd, rs, rt Parallel XOR
2092 * PNOR rd, rs, rt Parallel NOR
2094 * Shift (9 instructions)
2095 * ----------------------
2096 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2097 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2098 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2099 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2100 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2101 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2102 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2103 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2104 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2106 * Compare (6 instructions)
2107 * ------------------------
2108 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2109 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2110 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2111 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2112 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2113 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2115 * LZC (1 instruction)
2116 * -------------------
2117 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2119 * Quadword Load and Store (2 instructions)
2120 * ----------------------------------------
2121 * LQ rt, offset(base) Load Quadword
2122 * SQ rt, offset(base) Store Quadword
2124 * Multiply and Divide (19 instructions)
2125 * -------------------------------------
2126 * PMULTW rd, rs, rt Parallel Multiply Word
2127 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2128 * PDIVW rs, rt Parallel Divide Word
2129 * PDIVUW rs, rt Parallel Divide Unsigned Word
2130 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2131 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2132 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2133 * PMULTH rd, rs, rt Parallel Multiply Halfword
2134 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2135 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2136 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2137 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2138 * PDIVBW rs, rt Parallel Divide Broadcast Word
2139 * PMFHI rd Parallel Move From HI Register
2140 * PMFLO rd Parallel Move From LO Register
2141 * PMTHI rs Parallel Move To HI Register
2142 * PMTLO rs Parallel Move To LO Register
2143 * PMFHL rd Parallel Move From HI/LO Register
2144 * PMTHL rs Parallel Move To HI/LO Register
2146 * Pack/Extend (11 instructions)
2147 * -----------------------------
2148 * PPAC5 rd, rt Parallel Pack to 5 bits
2149 * PPACB rd, rs, rt Parallel Pack to Byte
2150 * PPACH rd, rs, rt Parallel Pack to Halfword
2151 * PPACW rd, rs, rt Parallel Pack to Word
2152 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2153 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2154 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2155 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2156 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2157 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2158 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2160 * Others (16 instructions)
2161 * ------------------------
2162 * PCPYH rd, rt Parallel Copy Halfword
2163 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2164 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2165 * PREVH rd, rt Parallel Reverse Halfword
2166 * PINTH rd, rs, rt Parallel Interleave Halfword
2167 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2168 * PEXEH rd, rt Parallel Exchange Even Halfword
2169 * PEXCH rd, rt Parallel Exchange Center Halfword
2170 * PEXEW rd, rt Parallel Exchange Even Word
2171 * PEXCW rd, rt Parallel Exchange Center Word
2172 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2173 * MFSA rd Move from Shift Amount Register
2174 * MTSA rs Move to Shift Amount Register
2175 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2176 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2177 * PROT3W rd, rt Parallel Rotate 3 Words
2179 * MMI (MultiMedia Instruction) encodings
2180 * ======================================
2182 * MMI instructions encoding table keys:
2184 * * This code is reserved for future use. An attempt to execute it
2185 * causes a Reserved Instruction exception.
2186 * % This code indicates an instruction class. The instruction word
2187 * must be further decoded by examining additional tables that show
2188 * the values for other instruction fields.
2189 * # This code is reserved for the unsupported instructions DMULT,
2190 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2191 * to execute it causes a Reserved Instruction exception.
2193 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2195 * 31 26 0
2196 * +--------+----------------------------------------+
2197 * | opcode | |
2198 * +--------+----------------------------------------+
2200 * opcode bits 28..26
2201 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2202 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2203 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2204 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2205 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2206 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2207 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2208 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2209 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2210 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2211 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2214 enum {
2215 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2216 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2217 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2221 * MMI instructions with opcode field = MMI:
2223 * 31 26 5 0
2224 * +--------+-------------------------------+--------+
2225 * | MMI | |function|
2226 * +--------+-------------------------------+--------+
2228 * function bits 2..0
2229 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2230 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2231 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2232 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2233 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2234 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2235 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2236 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2237 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2238 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2239 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2242 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2243 enum {
2244 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2245 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2246 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2249 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2250 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2251 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2252 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2253 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2254 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2255 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2256 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2257 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2268 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2272 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2274 * 31 26 10 6 5 0
2275 * +--------+----------------------+--------+--------+
2276 * | MMI | |function| MMI0 |
2277 * +--------+----------------------+--------+--------+
2279 * function bits 7..6
2280 * bits | 0 | 1 | 2 | 3
2281 * 10..8 | 00 | 01 | 10 | 11
2282 * -------+-------+-------+-------+-------
2283 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2284 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2285 * 2 010 | PADDB | PSUBB | PCGTB | *
2286 * 3 011 | * | * | * | *
2287 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2288 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2289 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2290 * 7 111 | * | * | PEXT5 | PPAC5
2293 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2294 enum {
2295 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2319 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2323 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2325 * 31 26 10 6 5 0
2326 * +--------+----------------------+--------+--------+
2327 * | MMI | |function| MMI1 |
2328 * +--------+----------------------+--------+--------+
2330 * function bits 7..6
2331 * bits | 0 | 1 | 2 | 3
2332 * 10..8 | 00 | 01 | 10 | 11
2333 * -------+-------+-------+-------+-------
2334 * 0 000 | * | PABSW | PCEQW | PMINW
2335 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2336 * 2 010 | * | * | PCEQB | *
2337 * 3 011 | * | * | * | *
2338 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2339 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2340 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2341 * 7 111 | * | * | * | *
2344 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2345 enum {
2346 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2363 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2367 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2369 * 31 26 10 6 5 0
2370 * +--------+----------------------+--------+--------+
2371 * | MMI | |function| MMI2 |
2372 * +--------+----------------------+--------+--------+
2374 * function bits 7..6
2375 * bits | 0 | 1 | 2 | 3
2376 * 10..8 | 00 | 01 | 10 | 11
2377 * -------+-------+-------+-------+-------
2378 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2379 * 1 001 | PMSUBW| * | * | *
2380 * 2 010 | PMFHI | PMFLO | PINTH | *
2381 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2382 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2383 * 5 101 | PMSUBH| PHMSBH| * | *
2384 * 6 110 | * | * | PEXEH | PREVH
2385 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2388 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2389 enum {
2390 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2411 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2415 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2417 * 31 26 10 6 5 0
2418 * +--------+----------------------+--------+--------+
2419 * | MMI | |function| MMI3 |
2420 * +--------+----------------------+--------+--------+
2422 * function bits 7..6
2423 * bits | 0 | 1 | 2 | 3
2424 * 10..8 | 00 | 01 | 10 | 11
2425 * -------+-------+-------+-------+-------
2426 * 0 000 |PMADDUW| * | * | PSRAVW
2427 * 1 001 | * | * | * | *
2428 * 2 010 | PMTHI | PMTLO | PINTEH| *
2429 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2430 * 4 100 | * | * | POR | PNOR
2431 * 5 101 | * | * | * | *
2432 * 6 110 | * | * | PEXCH | PCPYH
2433 * 7 111 | * | * | PEXCW | *
2436 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2437 enum {
2438 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2450 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2453 /* global register indices */
2454 static TCGv cpu_gpr[32], cpu_PC;
2455 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2456 static TCGv cpu_dspctrl, btarget, bcond;
2457 static TCGv cpu_lladdr, cpu_llval;
2458 static TCGv_i32 hflags;
2459 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2460 static TCGv_i64 fpu_f64[32];
2461 static TCGv_i64 msa_wr_d[64];
2463 #if defined(TARGET_MIPS64)
2464 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2465 static TCGv_i64 cpu_mmr[32];
2466 #endif
2468 #if !defined(TARGET_MIPS64)
2469 /* MXU registers */
2470 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2471 static TCGv mxu_CR;
2472 #endif
2474 #include "exec/gen-icount.h"
2476 #define gen_helper_0e0i(name, arg) do { \
2477 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2478 gen_helper_##name(cpu_env, helper_tmp); \
2479 tcg_temp_free_i32(helper_tmp); \
2480 } while (0)
2482 #define gen_helper_0e1i(name, arg1, arg2) do { \
2483 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2484 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2485 tcg_temp_free_i32(helper_tmp); \
2486 } while (0)
2488 #define gen_helper_1e0i(name, ret, arg1) do { \
2489 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2490 gen_helper_##name(ret, cpu_env, helper_tmp); \
2491 tcg_temp_free_i32(helper_tmp); \
2492 } while (0)
2494 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2495 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2496 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2497 tcg_temp_free_i32(helper_tmp); \
2498 } while (0)
2500 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2501 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2502 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2503 tcg_temp_free_i32(helper_tmp); \
2504 } while (0)
2506 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2507 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2508 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2509 tcg_temp_free_i32(helper_tmp); \
2510 } while (0)
2512 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2513 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2514 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2515 tcg_temp_free_i32(helper_tmp); \
2516 } while (0)
2518 typedef struct DisasContext {
2519 DisasContextBase base;
2520 target_ulong saved_pc;
2521 target_ulong page_start;
2522 uint32_t opcode;
2523 uint64_t insn_flags;
2524 int32_t CP0_Config1;
2525 int32_t CP0_Config2;
2526 int32_t CP0_Config3;
2527 int32_t CP0_Config5;
2528 /* Routine used to access memory */
2529 int mem_idx;
2530 MemOp default_tcg_memop_mask;
2531 uint32_t hflags, saved_hflags;
2532 target_ulong btarget;
2533 bool ulri;
2534 int kscrexist;
2535 bool rxi;
2536 int ie;
2537 bool bi;
2538 bool bp;
2539 uint64_t PAMask;
2540 bool mvh;
2541 bool eva;
2542 bool sc;
2543 int CP0_LLAddr_shift;
2544 bool ps;
2545 bool vp;
2546 bool cmgcr;
2547 bool mrp;
2548 bool nan2008;
2549 bool abs2008;
2550 bool saar;
2551 bool mi;
2552 int gi;
2553 } DisasContext;
2555 #define DISAS_STOP DISAS_TARGET_0
2556 #define DISAS_EXIT DISAS_TARGET_1
2558 static const char * const regnames[] = {
2559 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2560 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2561 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2562 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2565 static const char * const regnames_HI[] = {
2566 "HI0", "HI1", "HI2", "HI3",
2569 static const char * const regnames_LO[] = {
2570 "LO0", "LO1", "LO2", "LO3",
2573 static const char * const fregnames[] = {
2574 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2575 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2576 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2577 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2580 static const char * const msaregnames[] = {
2581 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2582 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2583 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2584 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2585 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2586 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2587 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2588 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2589 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2590 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2591 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2592 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2593 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2594 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2595 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2596 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2599 #if !defined(TARGET_MIPS64)
2600 static const char * const mxuregnames[] = {
2601 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2602 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2604 #endif
2606 #define LOG_DISAS(...) \
2607 do { \
2608 if (MIPS_DEBUG_DISAS) { \
2609 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2611 } while (0)
2613 #define MIPS_INVAL(op) \
2614 do { \
2615 if (MIPS_DEBUG_DISAS) { \
2616 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2617 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2618 ctx->base.pc_next, ctx->opcode, op, \
2619 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2620 ((ctx->opcode >> 16) & 0x1F)); \
2622 } while (0)
2624 /* General purpose registers moves. */
2625 static inline void gen_load_gpr(TCGv t, int reg)
2627 if (reg == 0) {
2628 tcg_gen_movi_tl(t, 0);
2629 } else {
2630 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2634 static inline void gen_store_gpr(TCGv t, int reg)
2636 if (reg != 0) {
2637 tcg_gen_mov_tl(cpu_gpr[reg], t);
2641 /* Moves to/from shadow registers. */
2642 static inline void gen_load_srsgpr(int from, int to)
2644 TCGv t0 = tcg_temp_new();
2646 if (from == 0) {
2647 tcg_gen_movi_tl(t0, 0);
2648 } else {
2649 TCGv_i32 t2 = tcg_temp_new_i32();
2650 TCGv_ptr addr = tcg_temp_new_ptr();
2652 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2653 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2654 tcg_gen_andi_i32(t2, t2, 0xf);
2655 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2656 tcg_gen_ext_i32_ptr(addr, t2);
2657 tcg_gen_add_ptr(addr, cpu_env, addr);
2659 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2660 tcg_temp_free_ptr(addr);
2661 tcg_temp_free_i32(t2);
2663 gen_store_gpr(t0, to);
2664 tcg_temp_free(t0);
2667 static inline void gen_store_srsgpr(int from, int to)
2669 if (to != 0) {
2670 TCGv t0 = tcg_temp_new();
2671 TCGv_i32 t2 = tcg_temp_new_i32();
2672 TCGv_ptr addr = tcg_temp_new_ptr();
2674 gen_load_gpr(t0, from);
2675 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2676 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2677 tcg_gen_andi_i32(t2, t2, 0xf);
2678 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2679 tcg_gen_ext_i32_ptr(addr, t2);
2680 tcg_gen_add_ptr(addr, cpu_env, addr);
2682 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2683 tcg_temp_free_ptr(addr);
2684 tcg_temp_free_i32(t2);
2685 tcg_temp_free(t0);
2689 #if !defined(TARGET_MIPS64)
2690 /* MXU General purpose registers moves. */
2691 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2693 if (reg == 0) {
2694 tcg_gen_movi_tl(t, 0);
2695 } else if (reg <= 15) {
2696 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2700 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2702 if (reg > 0 && reg <= 15) {
2703 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2707 /* MXU control register moves. */
2708 static inline void gen_load_mxu_cr(TCGv t)
2710 tcg_gen_mov_tl(t, mxu_CR);
2713 static inline void gen_store_mxu_cr(TCGv t)
2715 /* TODO: Add handling of RW rules for MXU_CR. */
2716 tcg_gen_mov_tl(mxu_CR, t);
2718 #endif
2721 /* Tests */
2722 static inline void gen_save_pc(target_ulong pc)
2724 tcg_gen_movi_tl(cpu_PC, pc);
2727 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2729 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2730 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2731 gen_save_pc(ctx->base.pc_next);
2732 ctx->saved_pc = ctx->base.pc_next;
2734 if (ctx->hflags != ctx->saved_hflags) {
2735 tcg_gen_movi_i32(hflags, ctx->hflags);
2736 ctx->saved_hflags = ctx->hflags;
2737 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2738 case MIPS_HFLAG_BR:
2739 break;
2740 case MIPS_HFLAG_BC:
2741 case MIPS_HFLAG_BL:
2742 case MIPS_HFLAG_B:
2743 tcg_gen_movi_tl(btarget, ctx->btarget);
2744 break;
2749 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2751 ctx->saved_hflags = ctx->hflags;
2752 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2753 case MIPS_HFLAG_BR:
2754 break;
2755 case MIPS_HFLAG_BC:
2756 case MIPS_HFLAG_BL:
2757 case MIPS_HFLAG_B:
2758 ctx->btarget = env->btarget;
2759 break;
2763 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2765 TCGv_i32 texcp = tcg_const_i32(excp);
2766 TCGv_i32 terr = tcg_const_i32(err);
2767 save_cpu_state(ctx, 1);
2768 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2769 tcg_temp_free_i32(terr);
2770 tcg_temp_free_i32(texcp);
2771 ctx->base.is_jmp = DISAS_NORETURN;
2774 static inline void generate_exception(DisasContext *ctx, int excp)
2776 gen_helper_0e0i(raise_exception, excp);
2779 static inline void generate_exception_end(DisasContext *ctx, int excp)
2781 generate_exception_err(ctx, excp, 0);
2784 /* Floating point register moves. */
2785 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2787 if (ctx->hflags & MIPS_HFLAG_FRE) {
2788 generate_exception(ctx, EXCP_RI);
2790 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2793 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2795 TCGv_i64 t64;
2796 if (ctx->hflags & MIPS_HFLAG_FRE) {
2797 generate_exception(ctx, EXCP_RI);
2799 t64 = tcg_temp_new_i64();
2800 tcg_gen_extu_i32_i64(t64, t);
2801 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2802 tcg_temp_free_i64(t64);
2805 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2807 if (ctx->hflags & MIPS_HFLAG_F64) {
2808 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2809 } else {
2810 gen_load_fpr32(ctx, t, reg | 1);
2814 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2816 if (ctx->hflags & MIPS_HFLAG_F64) {
2817 TCGv_i64 t64 = tcg_temp_new_i64();
2818 tcg_gen_extu_i32_i64(t64, t);
2819 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2820 tcg_temp_free_i64(t64);
2821 } else {
2822 gen_store_fpr32(ctx, t, reg | 1);
2826 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2828 if (ctx->hflags & MIPS_HFLAG_F64) {
2829 tcg_gen_mov_i64(t, fpu_f64[reg]);
2830 } else {
2831 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2835 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2837 if (ctx->hflags & MIPS_HFLAG_F64) {
2838 tcg_gen_mov_i64(fpu_f64[reg], t);
2839 } else {
2840 TCGv_i64 t0;
2841 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2842 t0 = tcg_temp_new_i64();
2843 tcg_gen_shri_i64(t0, t, 32);
2844 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2845 tcg_temp_free_i64(t0);
2849 static inline int get_fp_bit(int cc)
2851 if (cc) {
2852 return 24 + cc;
2853 } else {
2854 return 23;
2858 /* Addresses computation */
2859 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2860 TCGv arg1)
2862 tcg_gen_add_tl(ret, arg0, arg1);
2864 #if defined(TARGET_MIPS64)
2865 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2866 tcg_gen_ext32s_i64(ret, ret);
2868 #endif
2871 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2872 target_long ofs)
2874 tcg_gen_addi_tl(ret, base, ofs);
2876 #if defined(TARGET_MIPS64)
2877 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2878 tcg_gen_ext32s_i64(ret, ret);
2880 #endif
2883 /* Addresses computation (translation time) */
2884 static target_long addr_add(DisasContext *ctx, target_long base,
2885 target_long offset)
2887 target_long sum = base + offset;
2889 #if defined(TARGET_MIPS64)
2890 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2891 sum = (int32_t)sum;
2893 #endif
2894 return sum;
2897 /* Sign-extract the low 32-bits to a target_long. */
2898 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2900 #if defined(TARGET_MIPS64)
2901 tcg_gen_ext32s_i64(ret, arg);
2902 #else
2903 tcg_gen_extrl_i64_i32(ret, arg);
2904 #endif
2907 /* Sign-extract the high 32-bits to a target_long. */
2908 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2910 #if defined(TARGET_MIPS64)
2911 tcg_gen_sari_i64(ret, arg, 32);
2912 #else
2913 tcg_gen_extrh_i64_i32(ret, arg);
2914 #endif
2917 static inline void check_cp0_enabled(DisasContext *ctx)
2919 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2920 generate_exception_err(ctx, EXCP_CpU, 0);
2924 static inline void check_cp1_enabled(DisasContext *ctx)
2926 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2927 generate_exception_err(ctx, EXCP_CpU, 1);
2932 * Verify that the processor is running with COP1X instructions enabled.
2933 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2934 * opcode tables.
2936 static inline void check_cop1x(DisasContext *ctx)
2938 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2939 generate_exception_end(ctx, EXCP_RI);
2944 * Verify that the processor is running with 64-bit floating-point
2945 * operations enabled.
2947 static inline void check_cp1_64bitmode(DisasContext *ctx)
2949 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2950 generate_exception_end(ctx, EXCP_RI);
2955 * Verify if floating point register is valid; an operation is not defined
2956 * if bit 0 of any register specification is set and the FR bit in the
2957 * Status register equals zero, since the register numbers specify an
2958 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2959 * in the Status register equals one, both even and odd register numbers
2960 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2962 * Multiple 64 bit wide registers can be checked by calling
2963 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2965 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2967 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2968 generate_exception_end(ctx, EXCP_RI);
2973 * Verify that the processor is running with DSP instructions enabled.
2974 * This is enabled by CP0 Status register MX(24) bit.
2976 static inline void check_dsp(DisasContext *ctx)
2978 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2979 if (ctx->insn_flags & ASE_DSP) {
2980 generate_exception_end(ctx, EXCP_DSPDIS);
2981 } else {
2982 generate_exception_end(ctx, EXCP_RI);
2987 static inline void check_dsp_r2(DisasContext *ctx)
2989 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2990 if (ctx->insn_flags & ASE_DSP) {
2991 generate_exception_end(ctx, EXCP_DSPDIS);
2992 } else {
2993 generate_exception_end(ctx, EXCP_RI);
2998 static inline void check_dsp_r3(DisasContext *ctx)
3000 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
3001 if (ctx->insn_flags & ASE_DSP) {
3002 generate_exception_end(ctx, EXCP_DSPDIS);
3003 } else {
3004 generate_exception_end(ctx, EXCP_RI);
3010 * This code generates a "reserved instruction" exception if the
3011 * CPU does not support the instruction set corresponding to flags.
3013 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3015 if (unlikely(!(ctx->insn_flags & flags))) {
3016 generate_exception_end(ctx, EXCP_RI);
3021 * This code generates a "reserved instruction" exception if the
3022 * CPU has corresponding flag set which indicates that the instruction
3023 * has been removed.
3025 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3027 if (unlikely(ctx->insn_flags & flags)) {
3028 generate_exception_end(ctx, EXCP_RI);
3033 * The Linux kernel traps certain reserved instruction exceptions to
3034 * emulate the corresponding instructions. QEMU is the kernel in user
3035 * mode, so those traps are emulated by accepting the instructions.
3037 * A reserved instruction exception is generated for flagged CPUs if
3038 * QEMU runs in system mode.
3040 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3042 #ifndef CONFIG_USER_ONLY
3043 check_insn_opc_removed(ctx, flags);
3044 #endif
3048 * This code generates a "reserved instruction" exception if the
3049 * CPU does not support 64-bit paired-single (PS) floating point data type.
3051 static inline void check_ps(DisasContext *ctx)
3053 if (unlikely(!ctx->ps)) {
3054 generate_exception(ctx, EXCP_RI);
3056 check_cp1_64bitmode(ctx);
3059 #ifdef TARGET_MIPS64
3061 * This code generates a "reserved instruction" exception if 64-bit
3062 * instructions are not enabled.
3064 static inline void check_mips_64(DisasContext *ctx)
3066 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3067 generate_exception_end(ctx, EXCP_RI);
3070 #endif
3072 #ifndef CONFIG_USER_ONLY
3073 static inline void check_mvh(DisasContext *ctx)
3075 if (unlikely(!ctx->mvh)) {
3076 generate_exception(ctx, EXCP_RI);
3079 #endif
3082 * This code generates a "reserved instruction" exception if the
3083 * Config5 XNP bit is set.
3085 static inline void check_xnp(DisasContext *ctx)
3087 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3088 generate_exception_end(ctx, EXCP_RI);
3092 #ifndef CONFIG_USER_ONLY
3094 * This code generates a "reserved instruction" exception if the
3095 * Config3 PW bit is NOT set.
3097 static inline void check_pw(DisasContext *ctx)
3099 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3100 generate_exception_end(ctx, EXCP_RI);
3103 #endif
3106 * This code generates a "reserved instruction" exception if the
3107 * Config3 MT bit is NOT set.
3109 static inline void check_mt(DisasContext *ctx)
3111 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3112 generate_exception_end(ctx, EXCP_RI);
3116 #ifndef CONFIG_USER_ONLY
3118 * This code generates a "coprocessor unusable" exception if CP0 is not
3119 * available, and, if that is not the case, generates a "reserved instruction"
3120 * exception if the Config5 MT bit is NOT set. This is needed for availability
3121 * control of some of MT ASE instructions.
3123 static inline void check_cp0_mt(DisasContext *ctx)
3125 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3126 generate_exception_err(ctx, EXCP_CpU, 0);
3127 } else {
3128 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3129 generate_exception_err(ctx, EXCP_RI, 0);
3133 #endif
3136 * This code generates a "reserved instruction" exception if the
3137 * Config5 NMS bit is set.
3139 static inline void check_nms(DisasContext *ctx)
3141 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3142 generate_exception_end(ctx, EXCP_RI);
3147 * This code generates a "reserved instruction" exception if the
3148 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3149 * Config2 TL, and Config5 L2C are unset.
3151 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3153 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3154 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3155 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3156 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3157 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3158 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3159 generate_exception_end(ctx, EXCP_RI);
3164 * This code generates a "reserved instruction" exception if the
3165 * Config5 EVA bit is NOT set.
3167 static inline void check_eva(DisasContext *ctx)
3169 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3170 generate_exception_end(ctx, EXCP_RI);
3176 * Define small wrappers for gen_load_fpr* so that we have a uniform
3177 * calling interface for 32 and 64-bit FPRs. No sense in changing
3178 * all callers for gen_load_fpr32 when we need the CTX parameter for
3179 * this one use.
3181 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3182 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3183 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3184 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3185 int ft, int fs, int cc) \
3187 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3188 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3189 switch (ifmt) { \
3190 case FMT_PS: \
3191 check_ps(ctx); \
3192 break; \
3193 case FMT_D: \
3194 if (abs) { \
3195 check_cop1x(ctx); \
3197 check_cp1_registers(ctx, fs | ft); \
3198 break; \
3199 case FMT_S: \
3200 if (abs) { \
3201 check_cop1x(ctx); \
3203 break; \
3205 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3206 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3207 switch (n) { \
3208 case 0: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3210 break; \
3211 case 1: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3213 break; \
3214 case 2: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3216 break; \
3217 case 3: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3219 break; \
3220 case 4: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3222 break; \
3223 case 5: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3225 break; \
3226 case 6: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3228 break; \
3229 case 7: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3231 break; \
3232 case 8: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3234 break; \
3235 case 9: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3237 break; \
3238 case 10: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3240 break; \
3241 case 11: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3243 break; \
3244 case 12: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3246 break; \
3247 case 13: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3249 break; \
3250 case 14: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3252 break; \
3253 case 15: \
3254 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3255 break; \
3256 default: \
3257 abort(); \
3259 tcg_temp_free_i##bits(fp0); \
3260 tcg_temp_free_i##bits(fp1); \
3263 FOP_CONDS(, 0, d, FMT_D, 64)
3264 FOP_CONDS(abs, 1, d, FMT_D, 64)
3265 FOP_CONDS(, 0, s, FMT_S, 32)
3266 FOP_CONDS(abs, 1, s, FMT_S, 32)
3267 FOP_CONDS(, 0, ps, FMT_PS, 64)
3268 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3269 #undef FOP_CONDS
3271 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3272 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3273 int ft, int fs, int fd) \
3275 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3276 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3277 if (ifmt == FMT_D) { \
3278 check_cp1_registers(ctx, fs | ft | fd); \
3280 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3281 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3282 switch (n) { \
3283 case 0: \
3284 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 1: \
3287 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 2: \
3290 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 3: \
3293 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 4: \
3296 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 5: \
3299 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 6: \
3302 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 7: \
3305 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 8: \
3308 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 9: \
3311 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 10: \
3314 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 11: \
3317 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 12: \
3320 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 13: \
3323 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 14: \
3326 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 15: \
3329 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 17: \
3332 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 18: \
3335 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 19: \
3338 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 25: \
3341 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 26: \
3344 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 case 27: \
3347 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3348 break; \
3349 default: \
3350 abort(); \
3352 STORE; \
3353 tcg_temp_free_i ## bits(fp0); \
3354 tcg_temp_free_i ## bits(fp1); \
3357 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3358 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3359 #undef FOP_CONDNS
3360 #undef gen_ldcmp_fpr32
3361 #undef gen_ldcmp_fpr64
3363 /* load/store instructions. */
3364 #ifdef CONFIG_USER_ONLY
3365 #define OP_LD_ATOMIC(insn, fname) \
3366 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3367 DisasContext *ctx) \
3369 TCGv t0 = tcg_temp_new(); \
3370 tcg_gen_mov_tl(t0, arg1); \
3371 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3372 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3373 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3374 tcg_temp_free(t0); \
3376 #else
3377 #define OP_LD_ATOMIC(insn, fname) \
3378 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3379 DisasContext *ctx) \
3381 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3383 #endif
3384 OP_LD_ATOMIC(ll, ld32s);
3385 #if defined(TARGET_MIPS64)
3386 OP_LD_ATOMIC(lld, ld64);
3387 #endif
3388 #undef OP_LD_ATOMIC
3390 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3391 int base, int offset)
3393 if (base == 0) {
3394 tcg_gen_movi_tl(addr, offset);
3395 } else if (offset == 0) {
3396 gen_load_gpr(addr, base);
3397 } else {
3398 tcg_gen_movi_tl(addr, offset);
3399 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3403 static target_ulong pc_relative_pc(DisasContext *ctx)
3405 target_ulong pc = ctx->base.pc_next;
3407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3408 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3410 pc -= branch_bytes;
3413 pc &= ~(target_ulong)3;
3414 return pc;
3417 /* Load */
3418 static void gen_ld(DisasContext *ctx, uint32_t opc,
3419 int rt, int base, int offset)
3421 TCGv t0, t1, t2;
3422 int mem_idx = ctx->mem_idx;
3424 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3425 INSN_LOONGSON3A)) {
3427 * Loongson CPU uses a load to zero register for prefetch.
3428 * We emulate it as a NOP. On other CPU we must perform the
3429 * actual memory access.
3431 return;
3434 t0 = tcg_temp_new();
3435 gen_base_offset_addr(ctx, t0, base, offset);
3437 switch (opc) {
3438 #if defined(TARGET_MIPS64)
3439 case OPC_LWU:
3440 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3441 ctx->default_tcg_memop_mask);
3442 gen_store_gpr(t0, rt);
3443 break;
3444 case OPC_LD:
3445 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3446 ctx->default_tcg_memop_mask);
3447 gen_store_gpr(t0, rt);
3448 break;
3449 case OPC_LLD:
3450 case R6_OPC_LLD:
3451 op_ld_lld(t0, t0, mem_idx, ctx);
3452 gen_store_gpr(t0, rt);
3453 break;
3454 case OPC_LDL:
3455 t1 = tcg_temp_new();
3457 * Do a byte access to possibly trigger a page
3458 * fault with the unaligned address.
3460 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3461 tcg_gen_andi_tl(t1, t0, 7);
3462 #ifndef TARGET_WORDS_BIGENDIAN
3463 tcg_gen_xori_tl(t1, t1, 7);
3464 #endif
3465 tcg_gen_shli_tl(t1, t1, 3);
3466 tcg_gen_andi_tl(t0, t0, ~7);
3467 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3468 tcg_gen_shl_tl(t0, t0, t1);
3469 t2 = tcg_const_tl(-1);
3470 tcg_gen_shl_tl(t2, t2, t1);
3471 gen_load_gpr(t1, rt);
3472 tcg_gen_andc_tl(t1, t1, t2);
3473 tcg_temp_free(t2);
3474 tcg_gen_or_tl(t0, t0, t1);
3475 tcg_temp_free(t1);
3476 gen_store_gpr(t0, rt);
3477 break;
3478 case OPC_LDR:
3479 t1 = tcg_temp_new();
3481 * Do a byte access to possibly trigger a page
3482 * fault with the unaligned address.
3484 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3485 tcg_gen_andi_tl(t1, t0, 7);
3486 #ifdef TARGET_WORDS_BIGENDIAN
3487 tcg_gen_xori_tl(t1, t1, 7);
3488 #endif
3489 tcg_gen_shli_tl(t1, t1, 3);
3490 tcg_gen_andi_tl(t0, t0, ~7);
3491 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3492 tcg_gen_shr_tl(t0, t0, t1);
3493 tcg_gen_xori_tl(t1, t1, 63);
3494 t2 = tcg_const_tl(0xfffffffffffffffeull);
3495 tcg_gen_shl_tl(t2, t2, t1);
3496 gen_load_gpr(t1, rt);
3497 tcg_gen_and_tl(t1, t1, t2);
3498 tcg_temp_free(t2);
3499 tcg_gen_or_tl(t0, t0, t1);
3500 tcg_temp_free(t1);
3501 gen_store_gpr(t0, rt);
3502 break;
3503 case OPC_LDPC:
3504 t1 = tcg_const_tl(pc_relative_pc(ctx));
3505 gen_op_addr_add(ctx, t0, t0, t1);
3506 tcg_temp_free(t1);
3507 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3508 gen_store_gpr(t0, rt);
3509 break;
3510 #endif
3511 case OPC_LWPC:
3512 t1 = tcg_const_tl(pc_relative_pc(ctx));
3513 gen_op_addr_add(ctx, t0, t0, t1);
3514 tcg_temp_free(t1);
3515 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3516 gen_store_gpr(t0, rt);
3517 break;
3518 case OPC_LWE:
3519 mem_idx = MIPS_HFLAG_UM;
3520 /* fall through */
3521 case OPC_LW:
3522 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3523 ctx->default_tcg_memop_mask);
3524 gen_store_gpr(t0, rt);
3525 break;
3526 case OPC_LHE:
3527 mem_idx = MIPS_HFLAG_UM;
3528 /* fall through */
3529 case OPC_LH:
3530 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3531 ctx->default_tcg_memop_mask);
3532 gen_store_gpr(t0, rt);
3533 break;
3534 case OPC_LHUE:
3535 mem_idx = MIPS_HFLAG_UM;
3536 /* fall through */
3537 case OPC_LHU:
3538 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3539 ctx->default_tcg_memop_mask);
3540 gen_store_gpr(t0, rt);
3541 break;
3542 case OPC_LBE:
3543 mem_idx = MIPS_HFLAG_UM;
3544 /* fall through */
3545 case OPC_LB:
3546 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3547 gen_store_gpr(t0, rt);
3548 break;
3549 case OPC_LBUE:
3550 mem_idx = MIPS_HFLAG_UM;
3551 /* fall through */
3552 case OPC_LBU:
3553 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3554 gen_store_gpr(t0, rt);
3555 break;
3556 case OPC_LWLE:
3557 mem_idx = MIPS_HFLAG_UM;
3558 /* fall through */
3559 case OPC_LWL:
3560 t1 = tcg_temp_new();
3562 * Do a byte access to possibly trigger a page
3563 * fault with the unaligned address.
3565 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3566 tcg_gen_andi_tl(t1, t0, 3);
3567 #ifndef TARGET_WORDS_BIGENDIAN
3568 tcg_gen_xori_tl(t1, t1, 3);
3569 #endif
3570 tcg_gen_shli_tl(t1, t1, 3);
3571 tcg_gen_andi_tl(t0, t0, ~3);
3572 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3573 tcg_gen_shl_tl(t0, t0, t1);
3574 t2 = tcg_const_tl(-1);
3575 tcg_gen_shl_tl(t2, t2, t1);
3576 gen_load_gpr(t1, rt);
3577 tcg_gen_andc_tl(t1, t1, t2);
3578 tcg_temp_free(t2);
3579 tcg_gen_or_tl(t0, t0, t1);
3580 tcg_temp_free(t1);
3581 tcg_gen_ext32s_tl(t0, t0);
3582 gen_store_gpr(t0, rt);
3583 break;
3584 case OPC_LWRE:
3585 mem_idx = MIPS_HFLAG_UM;
3586 /* fall through */
3587 case OPC_LWR:
3588 t1 = tcg_temp_new();
3590 * Do a byte access to possibly trigger a page
3591 * fault with the unaligned address.
3593 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3594 tcg_gen_andi_tl(t1, t0, 3);
3595 #ifdef TARGET_WORDS_BIGENDIAN
3596 tcg_gen_xori_tl(t1, t1, 3);
3597 #endif
3598 tcg_gen_shli_tl(t1, t1, 3);
3599 tcg_gen_andi_tl(t0, t0, ~3);
3600 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3601 tcg_gen_shr_tl(t0, t0, t1);
3602 tcg_gen_xori_tl(t1, t1, 31);
3603 t2 = tcg_const_tl(0xfffffffeull);
3604 tcg_gen_shl_tl(t2, t2, t1);
3605 gen_load_gpr(t1, rt);
3606 tcg_gen_and_tl(t1, t1, t2);
3607 tcg_temp_free(t2);
3608 tcg_gen_or_tl(t0, t0, t1);
3609 tcg_temp_free(t1);
3610 tcg_gen_ext32s_tl(t0, t0);
3611 gen_store_gpr(t0, rt);
3612 break;
3613 case OPC_LLE:
3614 mem_idx = MIPS_HFLAG_UM;
3615 /* fall through */
3616 case OPC_LL:
3617 case R6_OPC_LL:
3618 op_ld_ll(t0, t0, mem_idx, ctx);
3619 gen_store_gpr(t0, rt);
3620 break;
3622 tcg_temp_free(t0);
3625 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3626 uint32_t reg1, uint32_t reg2)
3628 TCGv taddr = tcg_temp_new();
3629 TCGv_i64 tval = tcg_temp_new_i64();
3630 TCGv tmp1 = tcg_temp_new();
3631 TCGv tmp2 = tcg_temp_new();
3633 gen_base_offset_addr(ctx, taddr, base, offset);
3634 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3635 #ifdef TARGET_WORDS_BIGENDIAN
3636 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3637 #else
3638 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3639 #endif
3640 gen_store_gpr(tmp1, reg1);
3641 tcg_temp_free(tmp1);
3642 gen_store_gpr(tmp2, reg2);
3643 tcg_temp_free(tmp2);
3644 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3645 tcg_temp_free_i64(tval);
3646 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3647 tcg_temp_free(taddr);
3650 /* Store */
3651 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3652 int base, int offset)
3654 TCGv t0 = tcg_temp_new();
3655 TCGv t1 = tcg_temp_new();
3656 int mem_idx = ctx->mem_idx;
3658 gen_base_offset_addr(ctx, t0, base, offset);
3659 gen_load_gpr(t1, rt);
3660 switch (opc) {
3661 #if defined(TARGET_MIPS64)
3662 case OPC_SD:
3663 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3664 ctx->default_tcg_memop_mask);
3665 break;
3666 case OPC_SDL:
3667 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3668 break;
3669 case OPC_SDR:
3670 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3671 break;
3672 #endif
3673 case OPC_SWE:
3674 mem_idx = MIPS_HFLAG_UM;
3675 /* fall through */
3676 case OPC_SW:
3677 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3678 ctx->default_tcg_memop_mask);
3679 break;
3680 case OPC_SHE:
3681 mem_idx = MIPS_HFLAG_UM;
3682 /* fall through */
3683 case OPC_SH:
3684 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3685 ctx->default_tcg_memop_mask);
3686 break;
3687 case OPC_SBE:
3688 mem_idx = MIPS_HFLAG_UM;
3689 /* fall through */
3690 case OPC_SB:
3691 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3692 break;
3693 case OPC_SWLE:
3694 mem_idx = MIPS_HFLAG_UM;
3695 /* fall through */
3696 case OPC_SWL:
3697 gen_helper_0e2i(swl, t1, t0, mem_idx);
3698 break;
3699 case OPC_SWRE:
3700 mem_idx = MIPS_HFLAG_UM;
3701 /* fall through */
3702 case OPC_SWR:
3703 gen_helper_0e2i(swr, t1, t0, mem_idx);
3704 break;
3706 tcg_temp_free(t0);
3707 tcg_temp_free(t1);
3711 /* Store conditional */
3712 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3713 MemOp tcg_mo, bool eva)
3715 TCGv addr, t0, val;
3716 TCGLabel *l1 = gen_new_label();
3717 TCGLabel *done = gen_new_label();
3719 t0 = tcg_temp_new();
3720 addr = tcg_temp_new();
3721 /* compare the address against that of the preceeding LL */
3722 gen_base_offset_addr(ctx, addr, base, offset);
3723 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3724 tcg_temp_free(addr);
3725 tcg_gen_movi_tl(t0, 0);
3726 gen_store_gpr(t0, rt);
3727 tcg_gen_br(done);
3729 gen_set_label(l1);
3730 /* generate cmpxchg */
3731 val = tcg_temp_new();
3732 gen_load_gpr(val, rt);
3733 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3734 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3735 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3736 gen_store_gpr(t0, rt);
3737 tcg_temp_free(val);
3739 gen_set_label(done);
3740 tcg_temp_free(t0);
3744 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3745 uint32_t reg1, uint32_t reg2, bool eva)
3747 TCGv taddr = tcg_temp_local_new();
3748 TCGv lladdr = tcg_temp_local_new();
3749 TCGv_i64 tval = tcg_temp_new_i64();
3750 TCGv_i64 llval = tcg_temp_new_i64();
3751 TCGv_i64 val = tcg_temp_new_i64();
3752 TCGv tmp1 = tcg_temp_new();
3753 TCGv tmp2 = tcg_temp_new();
3754 TCGLabel *lab_fail = gen_new_label();
3755 TCGLabel *lab_done = gen_new_label();
3757 gen_base_offset_addr(ctx, taddr, base, offset);
3759 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3760 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3762 gen_load_gpr(tmp1, reg1);
3763 gen_load_gpr(tmp2, reg2);
3765 #ifdef TARGET_WORDS_BIGENDIAN
3766 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3767 #else
3768 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3769 #endif
3771 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3772 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3773 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3774 if (reg1 != 0) {
3775 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3777 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3779 gen_set_label(lab_fail);
3781 if (reg1 != 0) {
3782 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3784 gen_set_label(lab_done);
3785 tcg_gen_movi_tl(lladdr, -1);
3786 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3789 /* Load and store */
3790 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3791 TCGv t0)
3794 * Don't do NOP if destination is zero: we must perform the actual
3795 * memory access.
3797 switch (opc) {
3798 case OPC_LWC1:
3800 TCGv_i32 fp0 = tcg_temp_new_i32();
3801 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3802 ctx->default_tcg_memop_mask);
3803 gen_store_fpr32(ctx, fp0, ft);
3804 tcg_temp_free_i32(fp0);
3806 break;
3807 case OPC_SWC1:
3809 TCGv_i32 fp0 = tcg_temp_new_i32();
3810 gen_load_fpr32(ctx, fp0, ft);
3811 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3812 ctx->default_tcg_memop_mask);
3813 tcg_temp_free_i32(fp0);
3815 break;
3816 case OPC_LDC1:
3818 TCGv_i64 fp0 = tcg_temp_new_i64();
3819 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3820 ctx->default_tcg_memop_mask);
3821 gen_store_fpr64(ctx, fp0, ft);
3822 tcg_temp_free_i64(fp0);
3824 break;
3825 case OPC_SDC1:
3827 TCGv_i64 fp0 = tcg_temp_new_i64();
3828 gen_load_fpr64(ctx, fp0, ft);
3829 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3830 ctx->default_tcg_memop_mask);
3831 tcg_temp_free_i64(fp0);
3833 break;
3834 default:
3835 MIPS_INVAL("flt_ldst");
3836 generate_exception_end(ctx, EXCP_RI);
3837 break;
3841 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3842 int rs, int16_t imm)
3844 TCGv t0 = tcg_temp_new();
3846 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3847 check_cp1_enabled(ctx);
3848 switch (op) {
3849 case OPC_LDC1:
3850 case OPC_SDC1:
3851 check_insn(ctx, ISA_MIPS2);
3852 /* Fallthrough */
3853 default:
3854 gen_base_offset_addr(ctx, t0, rs, imm);
3855 gen_flt_ldst(ctx, op, rt, t0);
3857 } else {
3858 generate_exception_err(ctx, EXCP_CpU, 1);
3860 tcg_temp_free(t0);
3863 /* Arithmetic with immediate operand */
3864 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3865 int rt, int rs, int imm)
3867 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3869 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3871 * If no destination, treat it as a NOP.
3872 * For addi, we must generate the overflow exception when needed.
3874 return;
3876 switch (opc) {
3877 case OPC_ADDI:
3879 TCGv t0 = tcg_temp_local_new();
3880 TCGv t1 = tcg_temp_new();
3881 TCGv t2 = tcg_temp_new();
3882 TCGLabel *l1 = gen_new_label();
3884 gen_load_gpr(t1, rs);
3885 tcg_gen_addi_tl(t0, t1, uimm);
3886 tcg_gen_ext32s_tl(t0, t0);
3888 tcg_gen_xori_tl(t1, t1, ~uimm);
3889 tcg_gen_xori_tl(t2, t0, uimm);
3890 tcg_gen_and_tl(t1, t1, t2);
3891 tcg_temp_free(t2);
3892 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3893 tcg_temp_free(t1);
3894 /* operands of same sign, result different sign */
3895 generate_exception(ctx, EXCP_OVERFLOW);
3896 gen_set_label(l1);
3897 tcg_gen_ext32s_tl(t0, t0);
3898 gen_store_gpr(t0, rt);
3899 tcg_temp_free(t0);
3901 break;
3902 case OPC_ADDIU:
3903 if (rs != 0) {
3904 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3905 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3906 } else {
3907 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3909 break;
3910 #if defined(TARGET_MIPS64)
3911 case OPC_DADDI:
3913 TCGv t0 = tcg_temp_local_new();
3914 TCGv t1 = tcg_temp_new();
3915 TCGv t2 = tcg_temp_new();
3916 TCGLabel *l1 = gen_new_label();
3918 gen_load_gpr(t1, rs);
3919 tcg_gen_addi_tl(t0, t1, uimm);
3921 tcg_gen_xori_tl(t1, t1, ~uimm);
3922 tcg_gen_xori_tl(t2, t0, uimm);
3923 tcg_gen_and_tl(t1, t1, t2);
3924 tcg_temp_free(t2);
3925 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3926 tcg_temp_free(t1);
3927 /* operands of same sign, result different sign */
3928 generate_exception(ctx, EXCP_OVERFLOW);
3929 gen_set_label(l1);
3930 gen_store_gpr(t0, rt);
3931 tcg_temp_free(t0);
3933 break;
3934 case OPC_DADDIU:
3935 if (rs != 0) {
3936 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3937 } else {
3938 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3940 break;
3941 #endif
3945 /* Logic with immediate operand */
3946 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3947 int rt, int rs, int16_t imm)
3949 target_ulong uimm;
3951 if (rt == 0) {
3952 /* If no destination, treat it as a NOP. */
3953 return;
3955 uimm = (uint16_t)imm;
3956 switch (opc) {
3957 case OPC_ANDI:
3958 if (likely(rs != 0)) {
3959 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3960 } else {
3961 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3963 break;
3964 case OPC_ORI:
3965 if (rs != 0) {
3966 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3967 } else {
3968 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3970 break;
3971 case OPC_XORI:
3972 if (likely(rs != 0)) {
3973 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3974 } else {
3975 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3977 break;
3978 case OPC_LUI:
3979 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3980 /* OPC_AUI */
3981 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3982 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3983 } else {
3984 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3986 break;
3988 default:
3989 break;
3993 /* Set on less than with immediate operand */
3994 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3995 int rt, int rs, int16_t imm)
3997 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3998 TCGv t0;
4000 if (rt == 0) {
4001 /* If no destination, treat it as a NOP. */
4002 return;
4004 t0 = tcg_temp_new();
4005 gen_load_gpr(t0, rs);
4006 switch (opc) {
4007 case OPC_SLTI:
4008 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4009 break;
4010 case OPC_SLTIU:
4011 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4012 break;
4014 tcg_temp_free(t0);
4017 /* Shifts with immediate operand */
4018 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4019 int rt, int rs, int16_t imm)
4021 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4022 TCGv t0;
4024 if (rt == 0) {
4025 /* If no destination, treat it as a NOP. */
4026 return;
4029 t0 = tcg_temp_new();
4030 gen_load_gpr(t0, rs);
4031 switch (opc) {
4032 case OPC_SLL:
4033 tcg_gen_shli_tl(t0, t0, uimm);
4034 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4035 break;
4036 case OPC_SRA:
4037 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4038 break;
4039 case OPC_SRL:
4040 if (uimm != 0) {
4041 tcg_gen_ext32u_tl(t0, t0);
4042 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4043 } else {
4044 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4046 break;
4047 case OPC_ROTR:
4048 if (uimm != 0) {
4049 TCGv_i32 t1 = tcg_temp_new_i32();
4051 tcg_gen_trunc_tl_i32(t1, t0);
4052 tcg_gen_rotri_i32(t1, t1, uimm);
4053 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4054 tcg_temp_free_i32(t1);
4055 } else {
4056 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4058 break;
4059 #if defined(TARGET_MIPS64)
4060 case OPC_DSLL:
4061 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4062 break;
4063 case OPC_DSRA:
4064 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4065 break;
4066 case OPC_DSRL:
4067 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4068 break;
4069 case OPC_DROTR:
4070 if (uimm != 0) {
4071 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4072 } else {
4073 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4075 break;
4076 case OPC_DSLL32:
4077 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4078 break;
4079 case OPC_DSRA32:
4080 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4081 break;
4082 case OPC_DSRL32:
4083 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4084 break;
4085 case OPC_DROTR32:
4086 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4087 break;
4088 #endif
4090 tcg_temp_free(t0);
4093 /* Arithmetic */
4094 static void gen_arith(DisasContext *ctx, uint32_t opc,
4095 int rd, int rs, int rt)
4097 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4098 && opc != OPC_DADD && opc != OPC_DSUB) {
4100 * If no destination, treat it as a NOP.
4101 * For add & sub, we must generate the overflow exception when needed.
4103 return;
4106 switch (opc) {
4107 case OPC_ADD:
4109 TCGv t0 = tcg_temp_local_new();
4110 TCGv t1 = tcg_temp_new();
4111 TCGv t2 = tcg_temp_new();
4112 TCGLabel *l1 = gen_new_label();
4114 gen_load_gpr(t1, rs);
4115 gen_load_gpr(t2, rt);
4116 tcg_gen_add_tl(t0, t1, t2);
4117 tcg_gen_ext32s_tl(t0, t0);
4118 tcg_gen_xor_tl(t1, t1, t2);
4119 tcg_gen_xor_tl(t2, t0, t2);
4120 tcg_gen_andc_tl(t1, t2, t1);
4121 tcg_temp_free(t2);
4122 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4123 tcg_temp_free(t1);
4124 /* operands of same sign, result different sign */
4125 generate_exception(ctx, EXCP_OVERFLOW);
4126 gen_set_label(l1);
4127 gen_store_gpr(t0, rd);
4128 tcg_temp_free(t0);
4130 break;
4131 case OPC_ADDU:
4132 if (rs != 0 && rt != 0) {
4133 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4134 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4135 } else if (rs == 0 && rt != 0) {
4136 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4137 } else if (rs != 0 && rt == 0) {
4138 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4139 } else {
4140 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4142 break;
4143 case OPC_SUB:
4145 TCGv t0 = tcg_temp_local_new();
4146 TCGv t1 = tcg_temp_new();
4147 TCGv t2 = tcg_temp_new();
4148 TCGLabel *l1 = gen_new_label();
4150 gen_load_gpr(t1, rs);
4151 gen_load_gpr(t2, rt);
4152 tcg_gen_sub_tl(t0, t1, t2);
4153 tcg_gen_ext32s_tl(t0, t0);
4154 tcg_gen_xor_tl(t2, t1, t2);
4155 tcg_gen_xor_tl(t1, t0, t1);
4156 tcg_gen_and_tl(t1, t1, t2);
4157 tcg_temp_free(t2);
4158 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4159 tcg_temp_free(t1);
4161 * operands of different sign, first operand and the result
4162 * of different sign
4164 generate_exception(ctx, EXCP_OVERFLOW);
4165 gen_set_label(l1);
4166 gen_store_gpr(t0, rd);
4167 tcg_temp_free(t0);
4169 break;
4170 case OPC_SUBU:
4171 if (rs != 0 && rt != 0) {
4172 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4173 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4174 } else if (rs == 0 && rt != 0) {
4175 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4176 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4177 } else if (rs != 0 && rt == 0) {
4178 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4179 } else {
4180 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4182 break;
4183 #if defined(TARGET_MIPS64)
4184 case OPC_DADD:
4186 TCGv t0 = tcg_temp_local_new();
4187 TCGv t1 = tcg_temp_new();
4188 TCGv t2 = tcg_temp_new();
4189 TCGLabel *l1 = gen_new_label();
4191 gen_load_gpr(t1, rs);
4192 gen_load_gpr(t2, rt);
4193 tcg_gen_add_tl(t0, t1, t2);
4194 tcg_gen_xor_tl(t1, t1, t2);
4195 tcg_gen_xor_tl(t2, t0, t2);
4196 tcg_gen_andc_tl(t1, t2, t1);
4197 tcg_temp_free(t2);
4198 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4199 tcg_temp_free(t1);
4200 /* operands of same sign, result different sign */
4201 generate_exception(ctx, EXCP_OVERFLOW);
4202 gen_set_label(l1);
4203 gen_store_gpr(t0, rd);
4204 tcg_temp_free(t0);
4206 break;
4207 case OPC_DADDU:
4208 if (rs != 0 && rt != 0) {
4209 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4210 } else if (rs == 0 && rt != 0) {
4211 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4212 } else if (rs != 0 && rt == 0) {
4213 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4214 } else {
4215 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4217 break;
4218 case OPC_DSUB:
4220 TCGv t0 = tcg_temp_local_new();
4221 TCGv t1 = tcg_temp_new();
4222 TCGv t2 = tcg_temp_new();
4223 TCGLabel *l1 = gen_new_label();
4225 gen_load_gpr(t1, rs);
4226 gen_load_gpr(t2, rt);
4227 tcg_gen_sub_tl(t0, t1, t2);
4228 tcg_gen_xor_tl(t2, t1, t2);
4229 tcg_gen_xor_tl(t1, t0, t1);
4230 tcg_gen_and_tl(t1, t1, t2);
4231 tcg_temp_free(t2);
4232 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4233 tcg_temp_free(t1);
4235 * Operands of different sign, first operand and result different
4236 * sign.
4238 generate_exception(ctx, EXCP_OVERFLOW);
4239 gen_set_label(l1);
4240 gen_store_gpr(t0, rd);
4241 tcg_temp_free(t0);
4243 break;
4244 case OPC_DSUBU:
4245 if (rs != 0 && rt != 0) {
4246 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4247 } else if (rs == 0 && rt != 0) {
4248 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4249 } else if (rs != 0 && rt == 0) {
4250 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4251 } else {
4252 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4254 break;
4255 #endif
4256 case OPC_MUL:
4257 if (likely(rs != 0 && rt != 0)) {
4258 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4259 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4260 } else {
4261 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4263 break;
4267 /* Conditional move */
4268 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4269 int rd, int rs, int rt)
4271 TCGv t0, t1, t2;
4273 if (rd == 0) {
4274 /* If no destination, treat it as a NOP. */
4275 return;
4278 t0 = tcg_temp_new();
4279 gen_load_gpr(t0, rt);
4280 t1 = tcg_const_tl(0);
4281 t2 = tcg_temp_new();
4282 gen_load_gpr(t2, rs);
4283 switch (opc) {
4284 case OPC_MOVN:
4285 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4286 break;
4287 case OPC_MOVZ:
4288 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4289 break;
4290 case OPC_SELNEZ:
4291 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4292 break;
4293 case OPC_SELEQZ:
4294 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4295 break;
4297 tcg_temp_free(t2);
4298 tcg_temp_free(t1);
4299 tcg_temp_free(t0);
4302 /* Logic */
4303 static void gen_logic(DisasContext *ctx, uint32_t opc,
4304 int rd, int rs, int rt)
4306 if (rd == 0) {
4307 /* If no destination, treat it as a NOP. */
4308 return;
4311 switch (opc) {
4312 case OPC_AND:
4313 if (likely(rs != 0 && rt != 0)) {
4314 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4315 } else {
4316 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4318 break;
4319 case OPC_NOR:
4320 if (rs != 0 && rt != 0) {
4321 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4322 } else if (rs == 0 && rt != 0) {
4323 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4324 } else if (rs != 0 && rt == 0) {
4325 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4326 } else {
4327 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4329 break;
4330 case OPC_OR:
4331 if (likely(rs != 0 && rt != 0)) {
4332 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4333 } else if (rs == 0 && rt != 0) {
4334 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4335 } else if (rs != 0 && rt == 0) {
4336 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4337 } else {
4338 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4340 break;
4341 case OPC_XOR:
4342 if (likely(rs != 0 && rt != 0)) {
4343 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4344 } else if (rs == 0 && rt != 0) {
4345 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4346 } else if (rs != 0 && rt == 0) {
4347 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4348 } else {
4349 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4351 break;
4355 /* Set on lower than */
4356 static void gen_slt(DisasContext *ctx, uint32_t opc,
4357 int rd, int rs, int rt)
4359 TCGv t0, t1;
4361 if (rd == 0) {
4362 /* If no destination, treat it as a NOP. */
4363 return;
4366 t0 = tcg_temp_new();
4367 t1 = tcg_temp_new();
4368 gen_load_gpr(t0, rs);
4369 gen_load_gpr(t1, rt);
4370 switch (opc) {
4371 case OPC_SLT:
4372 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4373 break;
4374 case OPC_SLTU:
4375 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4376 break;
4378 tcg_temp_free(t0);
4379 tcg_temp_free(t1);
4382 /* Shifts */
4383 static void gen_shift(DisasContext *ctx, uint32_t opc,
4384 int rd, int rs, int rt)
4386 TCGv t0, t1;
4388 if (rd == 0) {
4390 * If no destination, treat it as a NOP.
4391 * For add & sub, we must generate the overflow exception when needed.
4393 return;
4396 t0 = tcg_temp_new();
4397 t1 = tcg_temp_new();
4398 gen_load_gpr(t0, rs);
4399 gen_load_gpr(t1, rt);
4400 switch (opc) {
4401 case OPC_SLLV:
4402 tcg_gen_andi_tl(t0, t0, 0x1f);
4403 tcg_gen_shl_tl(t0, t1, t0);
4404 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4405 break;
4406 case OPC_SRAV:
4407 tcg_gen_andi_tl(t0, t0, 0x1f);
4408 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4409 break;
4410 case OPC_SRLV:
4411 tcg_gen_ext32u_tl(t1, t1);
4412 tcg_gen_andi_tl(t0, t0, 0x1f);
4413 tcg_gen_shr_tl(t0, t1, t0);
4414 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4415 break;
4416 case OPC_ROTRV:
4418 TCGv_i32 t2 = tcg_temp_new_i32();
4419 TCGv_i32 t3 = tcg_temp_new_i32();
4421 tcg_gen_trunc_tl_i32(t2, t0);
4422 tcg_gen_trunc_tl_i32(t3, t1);
4423 tcg_gen_andi_i32(t2, t2, 0x1f);
4424 tcg_gen_rotr_i32(t2, t3, t2);
4425 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4426 tcg_temp_free_i32(t2);
4427 tcg_temp_free_i32(t3);
4429 break;
4430 #if defined(TARGET_MIPS64)
4431 case OPC_DSLLV:
4432 tcg_gen_andi_tl(t0, t0, 0x3f);
4433 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4434 break;
4435 case OPC_DSRAV:
4436 tcg_gen_andi_tl(t0, t0, 0x3f);
4437 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4438 break;
4439 case OPC_DSRLV:
4440 tcg_gen_andi_tl(t0, t0, 0x3f);
4441 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4442 break;
4443 case OPC_DROTRV:
4444 tcg_gen_andi_tl(t0, t0, 0x3f);
4445 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4446 break;
4447 #endif
4449 tcg_temp_free(t0);
4450 tcg_temp_free(t1);
4453 #if defined(TARGET_MIPS64)
4454 /* Copy GPR to and from TX79 HI1/LO1 register. */
4455 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4457 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4458 /* Treat as NOP. */
4459 return;
4462 switch (opc) {
4463 case MMI_OPC_MFHI1:
4464 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4465 break;
4466 case MMI_OPC_MFLO1:
4467 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4468 break;
4469 case MMI_OPC_MTHI1:
4470 if (reg != 0) {
4471 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4472 } else {
4473 tcg_gen_movi_tl(cpu_HI[1], 0);
4475 break;
4476 case MMI_OPC_MTLO1:
4477 if (reg != 0) {
4478 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4479 } else {
4480 tcg_gen_movi_tl(cpu_LO[1], 0);
4482 break;
4483 default:
4484 MIPS_INVAL("mfthilo1 TX79");
4485 generate_exception_end(ctx, EXCP_RI);
4486 break;
4489 #endif
4491 /* Arithmetic on HI/LO registers */
4492 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4494 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4495 /* Treat as NOP. */
4496 return;
4499 if (acc != 0) {
4500 check_dsp(ctx);
4503 switch (opc) {
4504 case OPC_MFHI:
4505 #if defined(TARGET_MIPS64)
4506 if (acc != 0) {
4507 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4508 } else
4509 #endif
4511 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4513 break;
4514 case OPC_MFLO:
4515 #if defined(TARGET_MIPS64)
4516 if (acc != 0) {
4517 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4518 } else
4519 #endif
4521 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4523 break;
4524 case OPC_MTHI:
4525 if (reg != 0) {
4526 #if defined(TARGET_MIPS64)
4527 if (acc != 0) {
4528 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4529 } else
4530 #endif
4532 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4534 } else {
4535 tcg_gen_movi_tl(cpu_HI[acc], 0);
4537 break;
4538 case OPC_MTLO:
4539 if (reg != 0) {
4540 #if defined(TARGET_MIPS64)
4541 if (acc != 0) {
4542 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4543 } else
4544 #endif
4546 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4548 } else {
4549 tcg_gen_movi_tl(cpu_LO[acc], 0);
4551 break;
4555 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4556 MemOp memop)
4558 TCGv t0 = tcg_const_tl(addr);
4559 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4560 gen_store_gpr(t0, reg);
4561 tcg_temp_free(t0);
4564 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4565 int rs)
4567 target_long offset;
4568 target_long addr;
4570 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4571 case OPC_ADDIUPC:
4572 if (rs != 0) {
4573 offset = sextract32(ctx->opcode << 2, 0, 21);
4574 addr = addr_add(ctx, pc, offset);
4575 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4577 break;
4578 case R6_OPC_LWPC:
4579 offset = sextract32(ctx->opcode << 2, 0, 21);
4580 addr = addr_add(ctx, pc, offset);
4581 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4582 break;
4583 #if defined(TARGET_MIPS64)
4584 case OPC_LWUPC:
4585 check_mips_64(ctx);
4586 offset = sextract32(ctx->opcode << 2, 0, 21);
4587 addr = addr_add(ctx, pc, offset);
4588 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4589 break;
4590 #endif
4591 default:
4592 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4593 case OPC_AUIPC:
4594 if (rs != 0) {
4595 offset = sextract32(ctx->opcode, 0, 16) << 16;
4596 addr = addr_add(ctx, pc, offset);
4597 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4599 break;
4600 case OPC_ALUIPC:
4601 if (rs != 0) {
4602 offset = sextract32(ctx->opcode, 0, 16) << 16;
4603 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4604 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4606 break;
4607 #if defined(TARGET_MIPS64)
4608 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4609 case R6_OPC_LDPC + (1 << 16):
4610 case R6_OPC_LDPC + (2 << 16):
4611 case R6_OPC_LDPC + (3 << 16):
4612 check_mips_64(ctx);
4613 offset = sextract32(ctx->opcode << 3, 0, 21);
4614 addr = addr_add(ctx, (pc & ~0x7), offset);
4615 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4616 break;
4617 #endif
4618 default:
4619 MIPS_INVAL("OPC_PCREL");
4620 generate_exception_end(ctx, EXCP_RI);
4621 break;
4623 break;
4627 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4629 TCGv t0, t1;
4631 if (rd == 0) {
4632 /* Treat as NOP. */
4633 return;
4636 t0 = tcg_temp_new();
4637 t1 = tcg_temp_new();
4639 gen_load_gpr(t0, rs);
4640 gen_load_gpr(t1, rt);
4642 switch (opc) {
4643 case R6_OPC_DIV:
4645 TCGv t2 = tcg_temp_new();
4646 TCGv t3 = tcg_temp_new();
4647 tcg_gen_ext32s_tl(t0, t0);
4648 tcg_gen_ext32s_tl(t1, t1);
4649 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4650 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4651 tcg_gen_and_tl(t2, t2, t3);
4652 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4653 tcg_gen_or_tl(t2, t2, t3);
4654 tcg_gen_movi_tl(t3, 0);
4655 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4656 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4657 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4658 tcg_temp_free(t3);
4659 tcg_temp_free(t2);
4661 break;
4662 case R6_OPC_MOD:
4664 TCGv t2 = tcg_temp_new();
4665 TCGv t3 = tcg_temp_new();
4666 tcg_gen_ext32s_tl(t0, t0);
4667 tcg_gen_ext32s_tl(t1, t1);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4669 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4670 tcg_gen_and_tl(t2, t2, t3);
4671 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4672 tcg_gen_or_tl(t2, t2, t3);
4673 tcg_gen_movi_tl(t3, 0);
4674 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4675 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4676 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4677 tcg_temp_free(t3);
4678 tcg_temp_free(t2);
4680 break;
4681 case R6_OPC_DIVU:
4683 TCGv t2 = tcg_const_tl(0);
4684 TCGv t3 = tcg_const_tl(1);
4685 tcg_gen_ext32u_tl(t0, t0);
4686 tcg_gen_ext32u_tl(t1, t1);
4687 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4688 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4689 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4690 tcg_temp_free(t3);
4691 tcg_temp_free(t2);
4693 break;
4694 case R6_OPC_MODU:
4696 TCGv t2 = tcg_const_tl(0);
4697 TCGv t3 = tcg_const_tl(1);
4698 tcg_gen_ext32u_tl(t0, t0);
4699 tcg_gen_ext32u_tl(t1, t1);
4700 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4701 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4702 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4703 tcg_temp_free(t3);
4704 tcg_temp_free(t2);
4706 break;
4707 case R6_OPC_MUL:
4709 TCGv_i32 t2 = tcg_temp_new_i32();
4710 TCGv_i32 t3 = tcg_temp_new_i32();
4711 tcg_gen_trunc_tl_i32(t2, t0);
4712 tcg_gen_trunc_tl_i32(t3, t1);
4713 tcg_gen_mul_i32(t2, t2, t3);
4714 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4715 tcg_temp_free_i32(t2);
4716 tcg_temp_free_i32(t3);
4718 break;
4719 case R6_OPC_MUH:
4721 TCGv_i32 t2 = tcg_temp_new_i32();
4722 TCGv_i32 t3 = tcg_temp_new_i32();
4723 tcg_gen_trunc_tl_i32(t2, t0);
4724 tcg_gen_trunc_tl_i32(t3, t1);
4725 tcg_gen_muls2_i32(t2, t3, t2, t3);
4726 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4727 tcg_temp_free_i32(t2);
4728 tcg_temp_free_i32(t3);
4730 break;
4731 case R6_OPC_MULU:
4733 TCGv_i32 t2 = tcg_temp_new_i32();
4734 TCGv_i32 t3 = tcg_temp_new_i32();
4735 tcg_gen_trunc_tl_i32(t2, t0);
4736 tcg_gen_trunc_tl_i32(t3, t1);
4737 tcg_gen_mul_i32(t2, t2, t3);
4738 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4739 tcg_temp_free_i32(t2);
4740 tcg_temp_free_i32(t3);
4742 break;
4743 case R6_OPC_MUHU:
4745 TCGv_i32 t2 = tcg_temp_new_i32();
4746 TCGv_i32 t3 = tcg_temp_new_i32();
4747 tcg_gen_trunc_tl_i32(t2, t0);
4748 tcg_gen_trunc_tl_i32(t3, t1);
4749 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4750 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4751 tcg_temp_free_i32(t2);
4752 tcg_temp_free_i32(t3);
4754 break;
4755 #if defined(TARGET_MIPS64)
4756 case R6_OPC_DDIV:
4758 TCGv t2 = tcg_temp_new();
4759 TCGv t3 = tcg_temp_new();
4760 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4761 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4762 tcg_gen_and_tl(t2, t2, t3);
4763 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4764 tcg_gen_or_tl(t2, t2, t3);
4765 tcg_gen_movi_tl(t3, 0);
4766 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4767 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4768 tcg_temp_free(t3);
4769 tcg_temp_free(t2);
4771 break;
4772 case R6_OPC_DMOD:
4774 TCGv t2 = tcg_temp_new();
4775 TCGv t3 = tcg_temp_new();
4776 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4777 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4778 tcg_gen_and_tl(t2, t2, t3);
4779 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4780 tcg_gen_or_tl(t2, t2, t3);
4781 tcg_gen_movi_tl(t3, 0);
4782 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4783 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4784 tcg_temp_free(t3);
4785 tcg_temp_free(t2);
4787 break;
4788 case R6_OPC_DDIVU:
4790 TCGv t2 = tcg_const_tl(0);
4791 TCGv t3 = tcg_const_tl(1);
4792 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4793 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4794 tcg_temp_free(t3);
4795 tcg_temp_free(t2);
4797 break;
4798 case R6_OPC_DMODU:
4800 TCGv t2 = tcg_const_tl(0);
4801 TCGv t3 = tcg_const_tl(1);
4802 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4803 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4804 tcg_temp_free(t3);
4805 tcg_temp_free(t2);
4807 break;
4808 case R6_OPC_DMUL:
4809 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4810 break;
4811 case R6_OPC_DMUH:
4813 TCGv t2 = tcg_temp_new();
4814 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4815 tcg_temp_free(t2);
4817 break;
4818 case R6_OPC_DMULU:
4819 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4820 break;
4821 case R6_OPC_DMUHU:
4823 TCGv t2 = tcg_temp_new();
4824 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4825 tcg_temp_free(t2);
4827 break;
4828 #endif
4829 default:
4830 MIPS_INVAL("r6 mul/div");
4831 generate_exception_end(ctx, EXCP_RI);
4832 goto out;
4834 out:
4835 tcg_temp_free(t0);
4836 tcg_temp_free(t1);
4839 #if defined(TARGET_MIPS64)
4840 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4842 TCGv t0, t1;
4844 t0 = tcg_temp_new();
4845 t1 = tcg_temp_new();
4847 gen_load_gpr(t0, rs);
4848 gen_load_gpr(t1, rt);
4850 switch (opc) {
4851 case MMI_OPC_DIV1:
4853 TCGv t2 = tcg_temp_new();
4854 TCGv t3 = tcg_temp_new();
4855 tcg_gen_ext32s_tl(t0, t0);
4856 tcg_gen_ext32s_tl(t1, t1);
4857 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4858 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4859 tcg_gen_and_tl(t2, t2, t3);
4860 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4861 tcg_gen_or_tl(t2, t2, t3);
4862 tcg_gen_movi_tl(t3, 0);
4863 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4864 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4865 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4866 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4867 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4868 tcg_temp_free(t3);
4869 tcg_temp_free(t2);
4871 break;
4872 case MMI_OPC_DIVU1:
4874 TCGv t2 = tcg_const_tl(0);
4875 TCGv t3 = tcg_const_tl(1);
4876 tcg_gen_ext32u_tl(t0, t0);
4877 tcg_gen_ext32u_tl(t1, t1);
4878 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4879 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4880 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4881 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4882 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4883 tcg_temp_free(t3);
4884 tcg_temp_free(t2);
4886 break;
4887 default:
4888 MIPS_INVAL("div1 TX79");
4889 generate_exception_end(ctx, EXCP_RI);
4890 goto out;
4892 out:
4893 tcg_temp_free(t0);
4894 tcg_temp_free(t1);
4896 #endif
4898 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4899 int acc, int rs, int rt)
4901 TCGv t0, t1;
4903 t0 = tcg_temp_new();
4904 t1 = tcg_temp_new();
4906 gen_load_gpr(t0, rs);
4907 gen_load_gpr(t1, rt);
4909 if (acc != 0) {
4910 check_dsp(ctx);
4913 switch (opc) {
4914 case OPC_DIV:
4916 TCGv t2 = tcg_temp_new();
4917 TCGv t3 = tcg_temp_new();
4918 tcg_gen_ext32s_tl(t0, t0);
4919 tcg_gen_ext32s_tl(t1, t1);
4920 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4921 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4922 tcg_gen_and_tl(t2, t2, t3);
4923 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4924 tcg_gen_or_tl(t2, t2, t3);
4925 tcg_gen_movi_tl(t3, 0);
4926 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4927 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4928 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4929 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4930 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4931 tcg_temp_free(t3);
4932 tcg_temp_free(t2);
4934 break;
4935 case OPC_DIVU:
4937 TCGv t2 = tcg_const_tl(0);
4938 TCGv t3 = tcg_const_tl(1);
4939 tcg_gen_ext32u_tl(t0, t0);
4940 tcg_gen_ext32u_tl(t1, t1);
4941 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4942 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4943 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4944 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4945 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4946 tcg_temp_free(t3);
4947 tcg_temp_free(t2);
4949 break;
4950 case OPC_MULT:
4952 TCGv_i32 t2 = tcg_temp_new_i32();
4953 TCGv_i32 t3 = tcg_temp_new_i32();
4954 tcg_gen_trunc_tl_i32(t2, t0);
4955 tcg_gen_trunc_tl_i32(t3, t1);
4956 tcg_gen_muls2_i32(t2, t3, t2, t3);
4957 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4958 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4959 tcg_temp_free_i32(t2);
4960 tcg_temp_free_i32(t3);
4962 break;
4963 case OPC_MULTU:
4965 TCGv_i32 t2 = tcg_temp_new_i32();
4966 TCGv_i32 t3 = tcg_temp_new_i32();
4967 tcg_gen_trunc_tl_i32(t2, t0);
4968 tcg_gen_trunc_tl_i32(t3, t1);
4969 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4970 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4971 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4972 tcg_temp_free_i32(t2);
4973 tcg_temp_free_i32(t3);
4975 break;
4976 #if defined(TARGET_MIPS64)
4977 case OPC_DDIV:
4979 TCGv t2 = tcg_temp_new();
4980 TCGv t3 = tcg_temp_new();
4981 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4982 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4983 tcg_gen_and_tl(t2, t2, t3);
4984 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4985 tcg_gen_or_tl(t2, t2, t3);
4986 tcg_gen_movi_tl(t3, 0);
4987 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4988 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4989 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4990 tcg_temp_free(t3);
4991 tcg_temp_free(t2);
4993 break;
4994 case OPC_DDIVU:
4996 TCGv t2 = tcg_const_tl(0);
4997 TCGv t3 = tcg_const_tl(1);
4998 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4999 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
5000 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
5001 tcg_temp_free(t3);
5002 tcg_temp_free(t2);
5004 break;
5005 case OPC_DMULT:
5006 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5007 break;
5008 case OPC_DMULTU:
5009 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5010 break;
5011 #endif
5012 case OPC_MADD:
5014 TCGv_i64 t2 = tcg_temp_new_i64();
5015 TCGv_i64 t3 = tcg_temp_new_i64();
5017 tcg_gen_ext_tl_i64(t2, t0);
5018 tcg_gen_ext_tl_i64(t3, t1);
5019 tcg_gen_mul_i64(t2, t2, t3);
5020 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5021 tcg_gen_add_i64(t2, t2, t3);
5022 tcg_temp_free_i64(t3);
5023 gen_move_low32(cpu_LO[acc], t2);
5024 gen_move_high32(cpu_HI[acc], t2);
5025 tcg_temp_free_i64(t2);
5027 break;
5028 case OPC_MADDU:
5030 TCGv_i64 t2 = tcg_temp_new_i64();
5031 TCGv_i64 t3 = tcg_temp_new_i64();
5033 tcg_gen_ext32u_tl(t0, t0);
5034 tcg_gen_ext32u_tl(t1, t1);
5035 tcg_gen_extu_tl_i64(t2, t0);
5036 tcg_gen_extu_tl_i64(t3, t1);
5037 tcg_gen_mul_i64(t2, t2, t3);
5038 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5039 tcg_gen_add_i64(t2, t2, t3);
5040 tcg_temp_free_i64(t3);
5041 gen_move_low32(cpu_LO[acc], t2);
5042 gen_move_high32(cpu_HI[acc], t2);
5043 tcg_temp_free_i64(t2);
5045 break;
5046 case OPC_MSUB:
5048 TCGv_i64 t2 = tcg_temp_new_i64();
5049 TCGv_i64 t3 = tcg_temp_new_i64();
5051 tcg_gen_ext_tl_i64(t2, t0);
5052 tcg_gen_ext_tl_i64(t3, t1);
5053 tcg_gen_mul_i64(t2, t2, t3);
5054 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5055 tcg_gen_sub_i64(t2, t3, t2);
5056 tcg_temp_free_i64(t3);
5057 gen_move_low32(cpu_LO[acc], t2);
5058 gen_move_high32(cpu_HI[acc], t2);
5059 tcg_temp_free_i64(t2);
5061 break;
5062 case OPC_MSUBU:
5064 TCGv_i64 t2 = tcg_temp_new_i64();
5065 TCGv_i64 t3 = tcg_temp_new_i64();
5067 tcg_gen_ext32u_tl(t0, t0);
5068 tcg_gen_ext32u_tl(t1, t1);
5069 tcg_gen_extu_tl_i64(t2, t0);
5070 tcg_gen_extu_tl_i64(t3, t1);
5071 tcg_gen_mul_i64(t2, t2, t3);
5072 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5073 tcg_gen_sub_i64(t2, t3, t2);
5074 tcg_temp_free_i64(t3);
5075 gen_move_low32(cpu_LO[acc], t2);
5076 gen_move_high32(cpu_HI[acc], t2);
5077 tcg_temp_free_i64(t2);
5079 break;
5080 default:
5081 MIPS_INVAL("mul/div");
5082 generate_exception_end(ctx, EXCP_RI);
5083 goto out;
5085 out:
5086 tcg_temp_free(t0);
5087 tcg_temp_free(t1);
5091 * These MULT[U] and MADD[U] instructions implemented in for example
5092 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5093 * architectures are special three-operand variants with the syntax
5095 * MULT[U][1] rd, rs, rt
5097 * such that
5099 * (rd, LO, HI) <- rs * rt
5101 * and
5103 * MADD[U][1] rd, rs, rt
5105 * such that
5107 * (rd, LO, HI) <- (LO, HI) + rs * rt
5109 * where the low-order 32-bits of the result is placed into both the
5110 * GPR rd and the special register LO. The high-order 32-bits of the
5111 * result is placed into the special register HI.
5113 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5114 * which is the zero register that always reads as 0.
5116 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5117 int rd, int rs, int rt)
5119 TCGv t0 = tcg_temp_new();
5120 TCGv t1 = tcg_temp_new();
5121 int acc = 0;
5123 gen_load_gpr(t0, rs);
5124 gen_load_gpr(t1, rt);
5126 switch (opc) {
5127 case MMI_OPC_MULT1:
5128 acc = 1;
5129 /* Fall through */
5130 case OPC_MULT:
5132 TCGv_i32 t2 = tcg_temp_new_i32();
5133 TCGv_i32 t3 = tcg_temp_new_i32();
5134 tcg_gen_trunc_tl_i32(t2, t0);
5135 tcg_gen_trunc_tl_i32(t3, t1);
5136 tcg_gen_muls2_i32(t2, t3, t2, t3);
5137 if (rd) {
5138 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5140 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5141 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5142 tcg_temp_free_i32(t2);
5143 tcg_temp_free_i32(t3);
5145 break;
5146 case MMI_OPC_MULTU1:
5147 acc = 1;
5148 /* Fall through */
5149 case OPC_MULTU:
5151 TCGv_i32 t2 = tcg_temp_new_i32();
5152 TCGv_i32 t3 = tcg_temp_new_i32();
5153 tcg_gen_trunc_tl_i32(t2, t0);
5154 tcg_gen_trunc_tl_i32(t3, t1);
5155 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5156 if (rd) {
5157 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5159 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5160 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5161 tcg_temp_free_i32(t2);
5162 tcg_temp_free_i32(t3);
5164 break;
5165 case MMI_OPC_MADD1:
5166 acc = 1;
5167 /* Fall through */
5168 case MMI_OPC_MADD:
5170 TCGv_i64 t2 = tcg_temp_new_i64();
5171 TCGv_i64 t3 = tcg_temp_new_i64();
5173 tcg_gen_ext_tl_i64(t2, t0);
5174 tcg_gen_ext_tl_i64(t3, t1);
5175 tcg_gen_mul_i64(t2, t2, t3);
5176 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5177 tcg_gen_add_i64(t2, t2, t3);
5178 tcg_temp_free_i64(t3);
5179 gen_move_low32(cpu_LO[acc], t2);
5180 gen_move_high32(cpu_HI[acc], t2);
5181 if (rd) {
5182 gen_move_low32(cpu_gpr[rd], t2);
5184 tcg_temp_free_i64(t2);
5186 break;
5187 case MMI_OPC_MADDU1:
5188 acc = 1;
5189 /* Fall through */
5190 case MMI_OPC_MADDU:
5192 TCGv_i64 t2 = tcg_temp_new_i64();
5193 TCGv_i64 t3 = tcg_temp_new_i64();
5195 tcg_gen_ext32u_tl(t0, t0);
5196 tcg_gen_ext32u_tl(t1, t1);
5197 tcg_gen_extu_tl_i64(t2, t0);
5198 tcg_gen_extu_tl_i64(t3, t1);
5199 tcg_gen_mul_i64(t2, t2, t3);
5200 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5201 tcg_gen_add_i64(t2, t2, t3);
5202 tcg_temp_free_i64(t3);
5203 gen_move_low32(cpu_LO[acc], t2);
5204 gen_move_high32(cpu_HI[acc], t2);
5205 if (rd) {
5206 gen_move_low32(cpu_gpr[rd], t2);
5208 tcg_temp_free_i64(t2);
5210 break;
5211 default:
5212 MIPS_INVAL("mul/madd TXx9");
5213 generate_exception_end(ctx, EXCP_RI);
5214 goto out;
5217 out:
5218 tcg_temp_free(t0);
5219 tcg_temp_free(t1);
5222 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5223 int rd, int rs, int rt)
5225 TCGv t0 = tcg_temp_new();
5226 TCGv t1 = tcg_temp_new();
5228 gen_load_gpr(t0, rs);
5229 gen_load_gpr(t1, rt);
5231 switch (opc) {
5232 case OPC_VR54XX_MULS:
5233 gen_helper_muls(t0, cpu_env, t0, t1);
5234 break;
5235 case OPC_VR54XX_MULSU:
5236 gen_helper_mulsu(t0, cpu_env, t0, t1);
5237 break;
5238 case OPC_VR54XX_MACC:
5239 gen_helper_macc(t0, cpu_env, t0, t1);
5240 break;
5241 case OPC_VR54XX_MACCU:
5242 gen_helper_maccu(t0, cpu_env, t0, t1);
5243 break;
5244 case OPC_VR54XX_MSAC:
5245 gen_helper_msac(t0, cpu_env, t0, t1);
5246 break;
5247 case OPC_VR54XX_MSACU:
5248 gen_helper_msacu(t0, cpu_env, t0, t1);
5249 break;
5250 case OPC_VR54XX_MULHI:
5251 gen_helper_mulhi(t0, cpu_env, t0, t1);
5252 break;
5253 case OPC_VR54XX_MULHIU:
5254 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5255 break;
5256 case OPC_VR54XX_MULSHI:
5257 gen_helper_mulshi(t0, cpu_env, t0, t1);
5258 break;
5259 case OPC_VR54XX_MULSHIU:
5260 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5261 break;
5262 case OPC_VR54XX_MACCHI:
5263 gen_helper_macchi(t0, cpu_env, t0, t1);
5264 break;
5265 case OPC_VR54XX_MACCHIU:
5266 gen_helper_macchiu(t0, cpu_env, t0, t1);
5267 break;
5268 case OPC_VR54XX_MSACHI:
5269 gen_helper_msachi(t0, cpu_env, t0, t1);
5270 break;
5271 case OPC_VR54XX_MSACHIU:
5272 gen_helper_msachiu(t0, cpu_env, t0, t1);
5273 break;
5274 default:
5275 MIPS_INVAL("mul vr54xx");
5276 generate_exception_end(ctx, EXCP_RI);
5277 goto out;
5279 gen_store_gpr(t0, rd);
5281 out:
5282 tcg_temp_free(t0);
5283 tcg_temp_free(t1);
5286 static void gen_cl(DisasContext *ctx, uint32_t opc,
5287 int rd, int rs)
5289 TCGv t0;
5291 if (rd == 0) {
5292 /* Treat as NOP. */
5293 return;
5295 t0 = cpu_gpr[rd];
5296 gen_load_gpr(t0, rs);
5298 switch (opc) {
5299 case OPC_CLO:
5300 case R6_OPC_CLO:
5301 #if defined(TARGET_MIPS64)
5302 case OPC_DCLO:
5303 case R6_OPC_DCLO:
5304 #endif
5305 tcg_gen_not_tl(t0, t0);
5306 break;
5309 switch (opc) {
5310 case OPC_CLO:
5311 case R6_OPC_CLO:
5312 case OPC_CLZ:
5313 case R6_OPC_CLZ:
5314 tcg_gen_ext32u_tl(t0, t0);
5315 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5316 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5317 break;
5318 #if defined(TARGET_MIPS64)
5319 case OPC_DCLO:
5320 case R6_OPC_DCLO:
5321 case OPC_DCLZ:
5322 case R6_OPC_DCLZ:
5323 tcg_gen_clzi_i64(t0, t0, 64);
5324 break;
5325 #endif
5329 /* Godson integer instructions */
5330 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5331 int rd, int rs, int rt)
5333 TCGv t0, t1;
5335 if (rd == 0) {
5336 /* Treat as NOP. */
5337 return;
5340 switch (opc) {
5341 case OPC_MULT_G_2E:
5342 case OPC_MULT_G_2F:
5343 case OPC_MULTU_G_2E:
5344 case OPC_MULTU_G_2F:
5345 #if defined(TARGET_MIPS64)
5346 case OPC_DMULT_G_2E:
5347 case OPC_DMULT_G_2F:
5348 case OPC_DMULTU_G_2E:
5349 case OPC_DMULTU_G_2F:
5350 #endif
5351 t0 = tcg_temp_new();
5352 t1 = tcg_temp_new();
5353 break;
5354 default:
5355 t0 = tcg_temp_local_new();
5356 t1 = tcg_temp_local_new();
5357 break;
5360 gen_load_gpr(t0, rs);
5361 gen_load_gpr(t1, rt);
5363 switch (opc) {
5364 case OPC_MULT_G_2E:
5365 case OPC_MULT_G_2F:
5366 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5367 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5368 break;
5369 case OPC_MULTU_G_2E:
5370 case OPC_MULTU_G_2F:
5371 tcg_gen_ext32u_tl(t0, t0);
5372 tcg_gen_ext32u_tl(t1, t1);
5373 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5374 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5375 break;
5376 case OPC_DIV_G_2E:
5377 case OPC_DIV_G_2F:
5379 TCGLabel *l1 = gen_new_label();
5380 TCGLabel *l2 = gen_new_label();
5381 TCGLabel *l3 = gen_new_label();
5382 tcg_gen_ext32s_tl(t0, t0);
5383 tcg_gen_ext32s_tl(t1, t1);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5385 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5386 tcg_gen_br(l3);
5387 gen_set_label(l1);
5388 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5389 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5390 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5391 tcg_gen_br(l3);
5392 gen_set_label(l2);
5393 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5394 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5395 gen_set_label(l3);
5397 break;
5398 case OPC_DIVU_G_2E:
5399 case OPC_DIVU_G_2F:
5401 TCGLabel *l1 = gen_new_label();
5402 TCGLabel *l2 = gen_new_label();
5403 tcg_gen_ext32u_tl(t0, t0);
5404 tcg_gen_ext32u_tl(t1, t1);
5405 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5406 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5407 tcg_gen_br(l2);
5408 gen_set_label(l1);
5409 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5410 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5411 gen_set_label(l2);
5413 break;
5414 case OPC_MOD_G_2E:
5415 case OPC_MOD_G_2F:
5417 TCGLabel *l1 = gen_new_label();
5418 TCGLabel *l2 = gen_new_label();
5419 TCGLabel *l3 = gen_new_label();
5420 tcg_gen_ext32u_tl(t0, t0);
5421 tcg_gen_ext32u_tl(t1, t1);
5422 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5423 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5424 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5425 gen_set_label(l1);
5426 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5427 tcg_gen_br(l3);
5428 gen_set_label(l2);
5429 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5430 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5431 gen_set_label(l3);
5433 break;
5434 case OPC_MODU_G_2E:
5435 case OPC_MODU_G_2F:
5437 TCGLabel *l1 = gen_new_label();
5438 TCGLabel *l2 = gen_new_label();
5439 tcg_gen_ext32u_tl(t0, t0);
5440 tcg_gen_ext32u_tl(t1, t1);
5441 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5442 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5443 tcg_gen_br(l2);
5444 gen_set_label(l1);
5445 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5446 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5447 gen_set_label(l2);
5449 break;
5450 #if defined(TARGET_MIPS64)
5451 case OPC_DMULT_G_2E:
5452 case OPC_DMULT_G_2F:
5453 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5454 break;
5455 case OPC_DMULTU_G_2E:
5456 case OPC_DMULTU_G_2F:
5457 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5458 break;
5459 case OPC_DDIV_G_2E:
5460 case OPC_DDIV_G_2F:
5462 TCGLabel *l1 = gen_new_label();
5463 TCGLabel *l2 = gen_new_label();
5464 TCGLabel *l3 = gen_new_label();
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5466 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5467 tcg_gen_br(l3);
5468 gen_set_label(l1);
5469 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5470 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5471 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5472 tcg_gen_br(l3);
5473 gen_set_label(l2);
5474 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5475 gen_set_label(l3);
5477 break;
5478 case OPC_DDIVU_G_2E:
5479 case OPC_DDIVU_G_2F:
5481 TCGLabel *l1 = gen_new_label();
5482 TCGLabel *l2 = gen_new_label();
5483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5484 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5485 tcg_gen_br(l2);
5486 gen_set_label(l1);
5487 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5488 gen_set_label(l2);
5490 break;
5491 case OPC_DMOD_G_2E:
5492 case OPC_DMOD_G_2F:
5494 TCGLabel *l1 = gen_new_label();
5495 TCGLabel *l2 = gen_new_label();
5496 TCGLabel *l3 = gen_new_label();
5497 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5498 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5499 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5500 gen_set_label(l1);
5501 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5502 tcg_gen_br(l3);
5503 gen_set_label(l2);
5504 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5505 gen_set_label(l3);
5507 break;
5508 case OPC_DMODU_G_2E:
5509 case OPC_DMODU_G_2F:
5511 TCGLabel *l1 = gen_new_label();
5512 TCGLabel *l2 = gen_new_label();
5513 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5514 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5515 tcg_gen_br(l2);
5516 gen_set_label(l1);
5517 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5518 gen_set_label(l2);
5520 break;
5521 #endif
5524 tcg_temp_free(t0);
5525 tcg_temp_free(t1);
5528 /* Loongson multimedia instructions */
5529 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5531 uint32_t opc, shift_max;
5532 TCGv_i64 t0, t1;
5533 TCGCond cond;
5535 opc = MASK_LMMI(ctx->opcode);
5536 switch (opc) {
5537 case OPC_ADD_CP2:
5538 case OPC_SUB_CP2:
5539 case OPC_DADD_CP2:
5540 case OPC_DSUB_CP2:
5541 t0 = tcg_temp_local_new_i64();
5542 t1 = tcg_temp_local_new_i64();
5543 break;
5544 default:
5545 t0 = tcg_temp_new_i64();
5546 t1 = tcg_temp_new_i64();
5547 break;
5550 check_cp1_enabled(ctx);
5551 gen_load_fpr64(ctx, t0, rs);
5552 gen_load_fpr64(ctx, t1, rt);
5554 switch (opc) {
5555 case OPC_PADDSH:
5556 gen_helper_paddsh(t0, t0, t1);
5557 break;
5558 case OPC_PADDUSH:
5559 gen_helper_paddush(t0, t0, t1);
5560 break;
5561 case OPC_PADDH:
5562 gen_helper_paddh(t0, t0, t1);
5563 break;
5564 case OPC_PADDW:
5565 gen_helper_paddw(t0, t0, t1);
5566 break;
5567 case OPC_PADDSB:
5568 gen_helper_paddsb(t0, t0, t1);
5569 break;
5570 case OPC_PADDUSB:
5571 gen_helper_paddusb(t0, t0, t1);
5572 break;
5573 case OPC_PADDB:
5574 gen_helper_paddb(t0, t0, t1);
5575 break;
5577 case OPC_PSUBSH:
5578 gen_helper_psubsh(t0, t0, t1);
5579 break;
5580 case OPC_PSUBUSH:
5581 gen_helper_psubush(t0, t0, t1);
5582 break;
5583 case OPC_PSUBH:
5584 gen_helper_psubh(t0, t0, t1);
5585 break;
5586 case OPC_PSUBW:
5587 gen_helper_psubw(t0, t0, t1);
5588 break;
5589 case OPC_PSUBSB:
5590 gen_helper_psubsb(t0, t0, t1);
5591 break;
5592 case OPC_PSUBUSB:
5593 gen_helper_psubusb(t0, t0, t1);
5594 break;
5595 case OPC_PSUBB:
5596 gen_helper_psubb(t0, t0, t1);
5597 break;
5599 case OPC_PSHUFH:
5600 gen_helper_pshufh(t0, t0, t1);
5601 break;
5602 case OPC_PACKSSWH:
5603 gen_helper_packsswh(t0, t0, t1);
5604 break;
5605 case OPC_PACKSSHB:
5606 gen_helper_packsshb(t0, t0, t1);
5607 break;
5608 case OPC_PACKUSHB:
5609 gen_helper_packushb(t0, t0, t1);
5610 break;
5612 case OPC_PUNPCKLHW:
5613 gen_helper_punpcklhw(t0, t0, t1);
5614 break;
5615 case OPC_PUNPCKHHW:
5616 gen_helper_punpckhhw(t0, t0, t1);
5617 break;
5618 case OPC_PUNPCKLBH:
5619 gen_helper_punpcklbh(t0, t0, t1);
5620 break;
5621 case OPC_PUNPCKHBH:
5622 gen_helper_punpckhbh(t0, t0, t1);
5623 break;
5624 case OPC_PUNPCKLWD:
5625 gen_helper_punpcklwd(t0, t0, t1);
5626 break;
5627 case OPC_PUNPCKHWD:
5628 gen_helper_punpckhwd(t0, t0, t1);
5629 break;
5631 case OPC_PAVGH:
5632 gen_helper_pavgh(t0, t0, t1);
5633 break;
5634 case OPC_PAVGB:
5635 gen_helper_pavgb(t0, t0, t1);
5636 break;
5637 case OPC_PMAXSH:
5638 gen_helper_pmaxsh(t0, t0, t1);
5639 break;
5640 case OPC_PMINSH:
5641 gen_helper_pminsh(t0, t0, t1);
5642 break;
5643 case OPC_PMAXUB:
5644 gen_helper_pmaxub(t0, t0, t1);
5645 break;
5646 case OPC_PMINUB:
5647 gen_helper_pminub(t0, t0, t1);
5648 break;
5650 case OPC_PCMPEQW:
5651 gen_helper_pcmpeqw(t0, t0, t1);
5652 break;
5653 case OPC_PCMPGTW:
5654 gen_helper_pcmpgtw(t0, t0, t1);
5655 break;
5656 case OPC_PCMPEQH:
5657 gen_helper_pcmpeqh(t0, t0, t1);
5658 break;
5659 case OPC_PCMPGTH:
5660 gen_helper_pcmpgth(t0, t0, t1);
5661 break;
5662 case OPC_PCMPEQB:
5663 gen_helper_pcmpeqb(t0, t0, t1);
5664 break;
5665 case OPC_PCMPGTB:
5666 gen_helper_pcmpgtb(t0, t0, t1);
5667 break;
5669 case OPC_PSLLW:
5670 gen_helper_psllw(t0, t0, t1);
5671 break;
5672 case OPC_PSLLH:
5673 gen_helper_psllh(t0, t0, t1);
5674 break;
5675 case OPC_PSRLW:
5676 gen_helper_psrlw(t0, t0, t1);
5677 break;
5678 case OPC_PSRLH:
5679 gen_helper_psrlh(t0, t0, t1);
5680 break;
5681 case OPC_PSRAW:
5682 gen_helper_psraw(t0, t0, t1);
5683 break;
5684 case OPC_PSRAH:
5685 gen_helper_psrah(t0, t0, t1);
5686 break;
5688 case OPC_PMULLH:
5689 gen_helper_pmullh(t0, t0, t1);
5690 break;
5691 case OPC_PMULHH:
5692 gen_helper_pmulhh(t0, t0, t1);
5693 break;
5694 case OPC_PMULHUH:
5695 gen_helper_pmulhuh(t0, t0, t1);
5696 break;
5697 case OPC_PMADDHW:
5698 gen_helper_pmaddhw(t0, t0, t1);
5699 break;
5701 case OPC_PASUBUB:
5702 gen_helper_pasubub(t0, t0, t1);
5703 break;
5704 case OPC_BIADD:
5705 gen_helper_biadd(t0, t0);
5706 break;
5707 case OPC_PMOVMSKB:
5708 gen_helper_pmovmskb(t0, t0);
5709 break;
5711 case OPC_PADDD:
5712 tcg_gen_add_i64(t0, t0, t1);
5713 break;
5714 case OPC_PSUBD:
5715 tcg_gen_sub_i64(t0, t0, t1);
5716 break;
5717 case OPC_XOR_CP2:
5718 tcg_gen_xor_i64(t0, t0, t1);
5719 break;
5720 case OPC_NOR_CP2:
5721 tcg_gen_nor_i64(t0, t0, t1);
5722 break;
5723 case OPC_AND_CP2:
5724 tcg_gen_and_i64(t0, t0, t1);
5725 break;
5726 case OPC_OR_CP2:
5727 tcg_gen_or_i64(t0, t0, t1);
5728 break;
5730 case OPC_PANDN:
5731 tcg_gen_andc_i64(t0, t1, t0);
5732 break;
5734 case OPC_PINSRH_0:
5735 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5736 break;
5737 case OPC_PINSRH_1:
5738 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5739 break;
5740 case OPC_PINSRH_2:
5741 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5742 break;
5743 case OPC_PINSRH_3:
5744 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5745 break;
5747 case OPC_PEXTRH:
5748 tcg_gen_andi_i64(t1, t1, 3);
5749 tcg_gen_shli_i64(t1, t1, 4);
5750 tcg_gen_shr_i64(t0, t0, t1);
5751 tcg_gen_ext16u_i64(t0, t0);
5752 break;
5754 case OPC_ADDU_CP2:
5755 tcg_gen_add_i64(t0, t0, t1);
5756 tcg_gen_ext32s_i64(t0, t0);
5757 break;
5758 case OPC_SUBU_CP2:
5759 tcg_gen_sub_i64(t0, t0, t1);
5760 tcg_gen_ext32s_i64(t0, t0);
5761 break;
5763 case OPC_SLL_CP2:
5764 shift_max = 32;
5765 goto do_shift;
5766 case OPC_SRL_CP2:
5767 shift_max = 32;
5768 goto do_shift;
5769 case OPC_SRA_CP2:
5770 shift_max = 32;
5771 goto do_shift;
5772 case OPC_DSLL_CP2:
5773 shift_max = 64;
5774 goto do_shift;
5775 case OPC_DSRL_CP2:
5776 shift_max = 64;
5777 goto do_shift;
5778 case OPC_DSRA_CP2:
5779 shift_max = 64;
5780 goto do_shift;
5781 do_shift:
5782 /* Make sure shift count isn't TCG undefined behaviour. */
5783 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5785 switch (opc) {
5786 case OPC_SLL_CP2:
5787 case OPC_DSLL_CP2:
5788 tcg_gen_shl_i64(t0, t0, t1);
5789 break;
5790 case OPC_SRA_CP2:
5791 case OPC_DSRA_CP2:
5793 * Since SRA is UndefinedResult without sign-extended inputs,
5794 * we can treat SRA and DSRA the same.
5796 tcg_gen_sar_i64(t0, t0, t1);
5797 break;
5798 case OPC_SRL_CP2:
5799 /* We want to shift in zeros for SRL; zero-extend first. */
5800 tcg_gen_ext32u_i64(t0, t0);
5801 /* FALLTHRU */
5802 case OPC_DSRL_CP2:
5803 tcg_gen_shr_i64(t0, t0, t1);
5804 break;
5807 if (shift_max == 32) {
5808 tcg_gen_ext32s_i64(t0, t0);
5811 /* Shifts larger than MAX produce zero. */
5812 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5813 tcg_gen_neg_i64(t1, t1);
5814 tcg_gen_and_i64(t0, t0, t1);
5815 break;
5817 case OPC_ADD_CP2:
5818 case OPC_DADD_CP2:
5820 TCGv_i64 t2 = tcg_temp_new_i64();
5821 TCGLabel *lab = gen_new_label();
5823 tcg_gen_mov_i64(t2, t0);
5824 tcg_gen_add_i64(t0, t1, t2);
5825 if (opc == OPC_ADD_CP2) {
5826 tcg_gen_ext32s_i64(t0, t0);
5828 tcg_gen_xor_i64(t1, t1, t2);
5829 tcg_gen_xor_i64(t2, t2, t0);
5830 tcg_gen_andc_i64(t1, t2, t1);
5831 tcg_temp_free_i64(t2);
5832 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5833 generate_exception(ctx, EXCP_OVERFLOW);
5834 gen_set_label(lab);
5835 break;
5838 case OPC_SUB_CP2:
5839 case OPC_DSUB_CP2:
5841 TCGv_i64 t2 = tcg_temp_new_i64();
5842 TCGLabel *lab = gen_new_label();
5844 tcg_gen_mov_i64(t2, t0);
5845 tcg_gen_sub_i64(t0, t1, t2);
5846 if (opc == OPC_SUB_CP2) {
5847 tcg_gen_ext32s_i64(t0, t0);
5849 tcg_gen_xor_i64(t1, t1, t2);
5850 tcg_gen_xor_i64(t2, t2, t0);
5851 tcg_gen_and_i64(t1, t1, t2);
5852 tcg_temp_free_i64(t2);
5853 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5854 generate_exception(ctx, EXCP_OVERFLOW);
5855 gen_set_label(lab);
5856 break;
5859 case OPC_PMULUW:
5860 tcg_gen_ext32u_i64(t0, t0);
5861 tcg_gen_ext32u_i64(t1, t1);
5862 tcg_gen_mul_i64(t0, t0, t1);
5863 break;
5865 case OPC_SEQU_CP2:
5866 case OPC_SEQ_CP2:
5867 cond = TCG_COND_EQ;
5868 goto do_cc_cond;
5869 break;
5870 case OPC_SLTU_CP2:
5871 cond = TCG_COND_LTU;
5872 goto do_cc_cond;
5873 break;
5874 case OPC_SLT_CP2:
5875 cond = TCG_COND_LT;
5876 goto do_cc_cond;
5877 break;
5878 case OPC_SLEU_CP2:
5879 cond = TCG_COND_LEU;
5880 goto do_cc_cond;
5881 break;
5882 case OPC_SLE_CP2:
5883 cond = TCG_COND_LE;
5884 do_cc_cond:
5886 int cc = (ctx->opcode >> 8) & 0x7;
5887 TCGv_i64 t64 = tcg_temp_new_i64();
5888 TCGv_i32 t32 = tcg_temp_new_i32();
5890 tcg_gen_setcond_i64(cond, t64, t0, t1);
5891 tcg_gen_extrl_i64_i32(t32, t64);
5892 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5893 get_fp_bit(cc), 1);
5895 tcg_temp_free_i32(t32);
5896 tcg_temp_free_i64(t64);
5898 goto no_rd;
5899 break;
5900 default:
5901 MIPS_INVAL("loongson_cp2");
5902 generate_exception_end(ctx, EXCP_RI);
5903 return;
5906 gen_store_fpr64(ctx, t0, rd);
5908 no_rd:
5909 tcg_temp_free_i64(t0);
5910 tcg_temp_free_i64(t1);
5913 /* Traps */
5914 static void gen_trap(DisasContext *ctx, uint32_t opc,
5915 int rs, int rt, int16_t imm)
5917 int cond;
5918 TCGv t0 = tcg_temp_new();
5919 TCGv t1 = tcg_temp_new();
5921 cond = 0;
5922 /* Load needed operands */
5923 switch (opc) {
5924 case OPC_TEQ:
5925 case OPC_TGE:
5926 case OPC_TGEU:
5927 case OPC_TLT:
5928 case OPC_TLTU:
5929 case OPC_TNE:
5930 /* Compare two registers */
5931 if (rs != rt) {
5932 gen_load_gpr(t0, rs);
5933 gen_load_gpr(t1, rt);
5934 cond = 1;
5936 break;
5937 case OPC_TEQI:
5938 case OPC_TGEI:
5939 case OPC_TGEIU:
5940 case OPC_TLTI:
5941 case OPC_TLTIU:
5942 case OPC_TNEI:
5943 /* Compare register to immediate */
5944 if (rs != 0 || imm != 0) {
5945 gen_load_gpr(t0, rs);
5946 tcg_gen_movi_tl(t1, (int32_t)imm);
5947 cond = 1;
5949 break;
5951 if (cond == 0) {
5952 switch (opc) {
5953 case OPC_TEQ: /* rs == rs */
5954 case OPC_TEQI: /* r0 == 0 */
5955 case OPC_TGE: /* rs >= rs */
5956 case OPC_TGEI: /* r0 >= 0 */
5957 case OPC_TGEU: /* rs >= rs unsigned */
5958 case OPC_TGEIU: /* r0 >= 0 unsigned */
5959 /* Always trap */
5960 generate_exception_end(ctx, EXCP_TRAP);
5961 break;
5962 case OPC_TLT: /* rs < rs */
5963 case OPC_TLTI: /* r0 < 0 */
5964 case OPC_TLTU: /* rs < rs unsigned */
5965 case OPC_TLTIU: /* r0 < 0 unsigned */
5966 case OPC_TNE: /* rs != rs */
5967 case OPC_TNEI: /* r0 != 0 */
5968 /* Never trap: treat as NOP. */
5969 break;
5971 } else {
5972 TCGLabel *l1 = gen_new_label();
5974 switch (opc) {
5975 case OPC_TEQ:
5976 case OPC_TEQI:
5977 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5978 break;
5979 case OPC_TGE:
5980 case OPC_TGEI:
5981 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5982 break;
5983 case OPC_TGEU:
5984 case OPC_TGEIU:
5985 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5986 break;
5987 case OPC_TLT:
5988 case OPC_TLTI:
5989 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5990 break;
5991 case OPC_TLTU:
5992 case OPC_TLTIU:
5993 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5994 break;
5995 case OPC_TNE:
5996 case OPC_TNEI:
5997 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5998 break;
6000 generate_exception(ctx, EXCP_TRAP);
6001 gen_set_label(l1);
6003 tcg_temp_free(t0);
6004 tcg_temp_free(t1);
6007 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6009 if (unlikely(ctx->base.singlestep_enabled)) {
6010 return false;
6013 #ifndef CONFIG_USER_ONLY
6014 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6015 #else
6016 return true;
6017 #endif
6020 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6022 if (use_goto_tb(ctx, dest)) {
6023 tcg_gen_goto_tb(n);
6024 gen_save_pc(dest);
6025 tcg_gen_exit_tb(ctx->base.tb, n);
6026 } else {
6027 gen_save_pc(dest);
6028 if (ctx->base.singlestep_enabled) {
6029 save_cpu_state(ctx, 0);
6030 gen_helper_raise_exception_debug(cpu_env);
6032 tcg_gen_lookup_and_goto_ptr();
6036 /* Branches (before delay slot) */
6037 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6038 int insn_bytes,
6039 int rs, int rt, int32_t offset,
6040 int delayslot_size)
6042 target_ulong btgt = -1;
6043 int blink = 0;
6044 int bcond_compute = 0;
6045 TCGv t0 = tcg_temp_new();
6046 TCGv t1 = tcg_temp_new();
6048 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6049 #ifdef MIPS_DEBUG_DISAS
6050 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6051 TARGET_FMT_lx "\n", ctx->base.pc_next);
6052 #endif
6053 generate_exception_end(ctx, EXCP_RI);
6054 goto out;
6057 /* Load needed operands */
6058 switch (opc) {
6059 case OPC_BEQ:
6060 case OPC_BEQL:
6061 case OPC_BNE:
6062 case OPC_BNEL:
6063 /* Compare two registers */
6064 if (rs != rt) {
6065 gen_load_gpr(t0, rs);
6066 gen_load_gpr(t1, rt);
6067 bcond_compute = 1;
6069 btgt = ctx->base.pc_next + insn_bytes + offset;
6070 break;
6071 case OPC_BGEZ:
6072 case OPC_BGEZAL:
6073 case OPC_BGEZALL:
6074 case OPC_BGEZL:
6075 case OPC_BGTZ:
6076 case OPC_BGTZL:
6077 case OPC_BLEZ:
6078 case OPC_BLEZL:
6079 case OPC_BLTZ:
6080 case OPC_BLTZAL:
6081 case OPC_BLTZALL:
6082 case OPC_BLTZL:
6083 /* Compare to zero */
6084 if (rs != 0) {
6085 gen_load_gpr(t0, rs);
6086 bcond_compute = 1;
6088 btgt = ctx->base.pc_next + insn_bytes + offset;
6089 break;
6090 case OPC_BPOSGE32:
6091 #if defined(TARGET_MIPS64)
6092 case OPC_BPOSGE64:
6093 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6094 #else
6095 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6096 #endif
6097 bcond_compute = 1;
6098 btgt = ctx->base.pc_next + insn_bytes + offset;
6099 break;
6100 case OPC_J:
6101 case OPC_JAL:
6102 case OPC_JALX:
6103 /* Jump to immediate */
6104 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6105 (uint32_t)offset;
6106 break;
6107 case OPC_JR:
6108 case OPC_JALR:
6109 /* Jump to register */
6110 if (offset != 0 && offset != 16) {
6112 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6113 * others are reserved.
6115 MIPS_INVAL("jump hint");
6116 generate_exception_end(ctx, EXCP_RI);
6117 goto out;
6119 gen_load_gpr(btarget, rs);
6120 break;
6121 default:
6122 MIPS_INVAL("branch/jump");
6123 generate_exception_end(ctx, EXCP_RI);
6124 goto out;
6126 if (bcond_compute == 0) {
6127 /* No condition to be computed */
6128 switch (opc) {
6129 case OPC_BEQ: /* rx == rx */
6130 case OPC_BEQL: /* rx == rx likely */
6131 case OPC_BGEZ: /* 0 >= 0 */
6132 case OPC_BGEZL: /* 0 >= 0 likely */
6133 case OPC_BLEZ: /* 0 <= 0 */
6134 case OPC_BLEZL: /* 0 <= 0 likely */
6135 /* Always take */
6136 ctx->hflags |= MIPS_HFLAG_B;
6137 break;
6138 case OPC_BGEZAL: /* 0 >= 0 */
6139 case OPC_BGEZALL: /* 0 >= 0 likely */
6140 /* Always take and link */
6141 blink = 31;
6142 ctx->hflags |= MIPS_HFLAG_B;
6143 break;
6144 case OPC_BNE: /* rx != rx */
6145 case OPC_BGTZ: /* 0 > 0 */
6146 case OPC_BLTZ: /* 0 < 0 */
6147 /* Treat as NOP. */
6148 goto out;
6149 case OPC_BLTZAL: /* 0 < 0 */
6151 * Handle as an unconditional branch to get correct delay
6152 * slot checking.
6154 blink = 31;
6155 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6156 ctx->hflags |= MIPS_HFLAG_B;
6157 break;
6158 case OPC_BLTZALL: /* 0 < 0 likely */
6159 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6160 /* Skip the instruction in the delay slot */
6161 ctx->base.pc_next += 4;
6162 goto out;
6163 case OPC_BNEL: /* rx != rx likely */
6164 case OPC_BGTZL: /* 0 > 0 likely */
6165 case OPC_BLTZL: /* 0 < 0 likely */
6166 /* Skip the instruction in the delay slot */
6167 ctx->base.pc_next += 4;
6168 goto out;
6169 case OPC_J:
6170 ctx->hflags |= MIPS_HFLAG_B;
6171 break;
6172 case OPC_JALX:
6173 ctx->hflags |= MIPS_HFLAG_BX;
6174 /* Fallthrough */
6175 case OPC_JAL:
6176 blink = 31;
6177 ctx->hflags |= MIPS_HFLAG_B;
6178 break;
6179 case OPC_JR:
6180 ctx->hflags |= MIPS_HFLAG_BR;
6181 break;
6182 case OPC_JALR:
6183 blink = rt;
6184 ctx->hflags |= MIPS_HFLAG_BR;
6185 break;
6186 default:
6187 MIPS_INVAL("branch/jump");
6188 generate_exception_end(ctx, EXCP_RI);
6189 goto out;
6191 } else {
6192 switch (opc) {
6193 case OPC_BEQ:
6194 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6195 goto not_likely;
6196 case OPC_BEQL:
6197 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6198 goto likely;
6199 case OPC_BNE:
6200 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6201 goto not_likely;
6202 case OPC_BNEL:
6203 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6204 goto likely;
6205 case OPC_BGEZ:
6206 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6207 goto not_likely;
6208 case OPC_BGEZL:
6209 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6210 goto likely;
6211 case OPC_BGEZAL:
6212 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6213 blink = 31;
6214 goto not_likely;
6215 case OPC_BGEZALL:
6216 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6217 blink = 31;
6218 goto likely;
6219 case OPC_BGTZ:
6220 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6221 goto not_likely;
6222 case OPC_BGTZL:
6223 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6224 goto likely;
6225 case OPC_BLEZ:
6226 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6227 goto not_likely;
6228 case OPC_BLEZL:
6229 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6230 goto likely;
6231 case OPC_BLTZ:
6232 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6233 goto not_likely;
6234 case OPC_BLTZL:
6235 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6236 goto likely;
6237 case OPC_BPOSGE32:
6238 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6239 goto not_likely;
6240 #if defined(TARGET_MIPS64)
6241 case OPC_BPOSGE64:
6242 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6243 goto not_likely;
6244 #endif
6245 case OPC_BLTZAL:
6246 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6247 blink = 31;
6248 not_likely:
6249 ctx->hflags |= MIPS_HFLAG_BC;
6250 break;
6251 case OPC_BLTZALL:
6252 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6253 blink = 31;
6254 likely:
6255 ctx->hflags |= MIPS_HFLAG_BL;
6256 break;
6257 default:
6258 MIPS_INVAL("conditional branch/jump");
6259 generate_exception_end(ctx, EXCP_RI);
6260 goto out;
6264 ctx->btarget = btgt;
6266 switch (delayslot_size) {
6267 case 2:
6268 ctx->hflags |= MIPS_HFLAG_BDS16;
6269 break;
6270 case 4:
6271 ctx->hflags |= MIPS_HFLAG_BDS32;
6272 break;
6275 if (blink > 0) {
6276 int post_delay = insn_bytes + delayslot_size;
6277 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6279 tcg_gen_movi_tl(cpu_gpr[blink],
6280 ctx->base.pc_next + post_delay + lowbit);
6283 out:
6284 if (insn_bytes == 2) {
6285 ctx->hflags |= MIPS_HFLAG_B16;
6287 tcg_temp_free(t0);
6288 tcg_temp_free(t1);
6292 /* nanoMIPS Branches */
6293 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6294 int insn_bytes,
6295 int rs, int rt, int32_t offset)
6297 target_ulong btgt = -1;
6298 int bcond_compute = 0;
6299 TCGv t0 = tcg_temp_new();
6300 TCGv t1 = tcg_temp_new();
6302 /* Load needed operands */
6303 switch (opc) {
6304 case OPC_BEQ:
6305 case OPC_BNE:
6306 /* Compare two registers */
6307 if (rs != rt) {
6308 gen_load_gpr(t0, rs);
6309 gen_load_gpr(t1, rt);
6310 bcond_compute = 1;
6312 btgt = ctx->base.pc_next + insn_bytes + offset;
6313 break;
6314 case OPC_BGEZAL:
6315 /* Compare to zero */
6316 if (rs != 0) {
6317 gen_load_gpr(t0, rs);
6318 bcond_compute = 1;
6320 btgt = ctx->base.pc_next + insn_bytes + offset;
6321 break;
6322 case OPC_BPOSGE32:
6323 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6324 bcond_compute = 1;
6325 btgt = ctx->base.pc_next + insn_bytes + offset;
6326 break;
6327 case OPC_JR:
6328 case OPC_JALR:
6329 /* Jump to register */
6330 if (offset != 0 && offset != 16) {
6332 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6333 * others are reserved.
6335 MIPS_INVAL("jump hint");
6336 generate_exception_end(ctx, EXCP_RI);
6337 goto out;
6339 gen_load_gpr(btarget, rs);
6340 break;
6341 default:
6342 MIPS_INVAL("branch/jump");
6343 generate_exception_end(ctx, EXCP_RI);
6344 goto out;
6346 if (bcond_compute == 0) {
6347 /* No condition to be computed */
6348 switch (opc) {
6349 case OPC_BEQ: /* rx == rx */
6350 /* Always take */
6351 ctx->hflags |= MIPS_HFLAG_B;
6352 break;
6353 case OPC_BGEZAL: /* 0 >= 0 */
6354 /* Always take and link */
6355 tcg_gen_movi_tl(cpu_gpr[31],
6356 ctx->base.pc_next + insn_bytes);
6357 ctx->hflags |= MIPS_HFLAG_B;
6358 break;
6359 case OPC_BNE: /* rx != rx */
6360 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6361 /* Skip the instruction in the delay slot */
6362 ctx->base.pc_next += 4;
6363 goto out;
6364 case OPC_JR:
6365 ctx->hflags |= MIPS_HFLAG_BR;
6366 break;
6367 case OPC_JALR:
6368 if (rt > 0) {
6369 tcg_gen_movi_tl(cpu_gpr[rt],
6370 ctx->base.pc_next + insn_bytes);
6372 ctx->hflags |= MIPS_HFLAG_BR;
6373 break;
6374 default:
6375 MIPS_INVAL("branch/jump");
6376 generate_exception_end(ctx, EXCP_RI);
6377 goto out;
6379 } else {
6380 switch (opc) {
6381 case OPC_BEQ:
6382 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6383 goto not_likely;
6384 case OPC_BNE:
6385 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6386 goto not_likely;
6387 case OPC_BGEZAL:
6388 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6389 tcg_gen_movi_tl(cpu_gpr[31],
6390 ctx->base.pc_next + insn_bytes);
6391 goto not_likely;
6392 case OPC_BPOSGE32:
6393 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6394 not_likely:
6395 ctx->hflags |= MIPS_HFLAG_BC;
6396 break;
6397 default:
6398 MIPS_INVAL("conditional branch/jump");
6399 generate_exception_end(ctx, EXCP_RI);
6400 goto out;
6404 ctx->btarget = btgt;
6406 out:
6407 if (insn_bytes == 2) {
6408 ctx->hflags |= MIPS_HFLAG_B16;
6410 tcg_temp_free(t0);
6411 tcg_temp_free(t1);
6415 /* special3 bitfield operations */
6416 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6417 int rs, int lsb, int msb)
6419 TCGv t0 = tcg_temp_new();
6420 TCGv t1 = tcg_temp_new();
6422 gen_load_gpr(t1, rs);
6423 switch (opc) {
6424 case OPC_EXT:
6425 if (lsb + msb > 31) {
6426 goto fail;
6428 if (msb != 31) {
6429 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6430 } else {
6432 * The two checks together imply that lsb == 0,
6433 * so this is a simple sign-extension.
6435 tcg_gen_ext32s_tl(t0, t1);
6437 break;
6438 #if defined(TARGET_MIPS64)
6439 case OPC_DEXTU:
6440 lsb += 32;
6441 goto do_dext;
6442 case OPC_DEXTM:
6443 msb += 32;
6444 goto do_dext;
6445 case OPC_DEXT:
6446 do_dext:
6447 if (lsb + msb > 63) {
6448 goto fail;
6450 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6451 break;
6452 #endif
6453 case OPC_INS:
6454 if (lsb > msb) {
6455 goto fail;
6457 gen_load_gpr(t0, rt);
6458 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6459 tcg_gen_ext32s_tl(t0, t0);
6460 break;
6461 #if defined(TARGET_MIPS64)
6462 case OPC_DINSU:
6463 lsb += 32;
6464 /* FALLTHRU */
6465 case OPC_DINSM:
6466 msb += 32;
6467 /* FALLTHRU */
6468 case OPC_DINS:
6469 if (lsb > msb) {
6470 goto fail;
6472 gen_load_gpr(t0, rt);
6473 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6474 break;
6475 #endif
6476 default:
6477 fail:
6478 MIPS_INVAL("bitops");
6479 generate_exception_end(ctx, EXCP_RI);
6480 tcg_temp_free(t0);
6481 tcg_temp_free(t1);
6482 return;
6484 gen_store_gpr(t0, rt);
6485 tcg_temp_free(t0);
6486 tcg_temp_free(t1);
6489 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6491 TCGv t0;
6493 if (rd == 0) {
6494 /* If no destination, treat it as a NOP. */
6495 return;
6498 t0 = tcg_temp_new();
6499 gen_load_gpr(t0, rt);
6500 switch (op2) {
6501 case OPC_WSBH:
6503 TCGv t1 = tcg_temp_new();
6504 TCGv t2 = tcg_const_tl(0x00FF00FF);
6506 tcg_gen_shri_tl(t1, t0, 8);
6507 tcg_gen_and_tl(t1, t1, t2);
6508 tcg_gen_and_tl(t0, t0, t2);
6509 tcg_gen_shli_tl(t0, t0, 8);
6510 tcg_gen_or_tl(t0, t0, t1);
6511 tcg_temp_free(t2);
6512 tcg_temp_free(t1);
6513 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6515 break;
6516 case OPC_SEB:
6517 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6518 break;
6519 case OPC_SEH:
6520 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6521 break;
6522 #if defined(TARGET_MIPS64)
6523 case OPC_DSBH:
6525 TCGv t1 = tcg_temp_new();
6526 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6528 tcg_gen_shri_tl(t1, t0, 8);
6529 tcg_gen_and_tl(t1, t1, t2);
6530 tcg_gen_and_tl(t0, t0, t2);
6531 tcg_gen_shli_tl(t0, t0, 8);
6532 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6533 tcg_temp_free(t2);
6534 tcg_temp_free(t1);
6536 break;
6537 case OPC_DSHD:
6539 TCGv t1 = tcg_temp_new();
6540 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6542 tcg_gen_shri_tl(t1, t0, 16);
6543 tcg_gen_and_tl(t1, t1, t2);
6544 tcg_gen_and_tl(t0, t0, t2);
6545 tcg_gen_shli_tl(t0, t0, 16);
6546 tcg_gen_or_tl(t0, t0, t1);
6547 tcg_gen_shri_tl(t1, t0, 32);
6548 tcg_gen_shli_tl(t0, t0, 32);
6549 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6550 tcg_temp_free(t2);
6551 tcg_temp_free(t1);
6553 break;
6554 #endif
6555 default:
6556 MIPS_INVAL("bsfhl");
6557 generate_exception_end(ctx, EXCP_RI);
6558 tcg_temp_free(t0);
6559 return;
6561 tcg_temp_free(t0);
6564 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6565 int imm2)
6567 TCGv t0;
6568 TCGv t1;
6569 if (rd == 0) {
6570 /* Treat as NOP. */
6571 return;
6573 t0 = tcg_temp_new();
6574 t1 = tcg_temp_new();
6575 gen_load_gpr(t0, rs);
6576 gen_load_gpr(t1, rt);
6577 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6578 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6579 if (opc == OPC_LSA) {
6580 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6583 tcg_temp_free(t1);
6584 tcg_temp_free(t0);
6586 return;
6589 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6590 int rt, int bits)
6592 TCGv t0;
6593 if (rd == 0) {
6594 /* Treat as NOP. */
6595 return;
6597 t0 = tcg_temp_new();
6598 if (bits == 0 || bits == wordsz) {
6599 if (bits == 0) {
6600 gen_load_gpr(t0, rt);
6601 } else {
6602 gen_load_gpr(t0, rs);
6604 switch (wordsz) {
6605 case 32:
6606 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6607 break;
6608 #if defined(TARGET_MIPS64)
6609 case 64:
6610 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6611 break;
6612 #endif
6614 } else {
6615 TCGv t1 = tcg_temp_new();
6616 gen_load_gpr(t0, rt);
6617 gen_load_gpr(t1, rs);
6618 switch (wordsz) {
6619 case 32:
6621 TCGv_i64 t2 = tcg_temp_new_i64();
6622 tcg_gen_concat_tl_i64(t2, t1, t0);
6623 tcg_gen_shri_i64(t2, t2, 32 - bits);
6624 gen_move_low32(cpu_gpr[rd], t2);
6625 tcg_temp_free_i64(t2);
6627 break;
6628 #if defined(TARGET_MIPS64)
6629 case 64:
6630 tcg_gen_shli_tl(t0, t0, bits);
6631 tcg_gen_shri_tl(t1, t1, 64 - bits);
6632 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6633 break;
6634 #endif
6636 tcg_temp_free(t1);
6639 tcg_temp_free(t0);
6642 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6643 int bp)
6645 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6648 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6649 int shift)
6651 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6654 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6656 TCGv t0;
6657 if (rd == 0) {
6658 /* Treat as NOP. */
6659 return;
6661 t0 = tcg_temp_new();
6662 gen_load_gpr(t0, rt);
6663 switch (opc) {
6664 case OPC_BITSWAP:
6665 gen_helper_bitswap(cpu_gpr[rd], t0);
6666 break;
6667 #if defined(TARGET_MIPS64)
6668 case OPC_DBITSWAP:
6669 gen_helper_dbitswap(cpu_gpr[rd], t0);
6670 break;
6671 #endif
6673 tcg_temp_free(t0);
6676 #ifndef CONFIG_USER_ONLY
6677 /* CP0 (MMU and control) */
6678 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6680 TCGv_i64 t0 = tcg_temp_new_i64();
6681 TCGv_i64 t1 = tcg_temp_new_i64();
6683 tcg_gen_ext_tl_i64(t0, arg);
6684 tcg_gen_ld_i64(t1, cpu_env, off);
6685 #if defined(TARGET_MIPS64)
6686 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6687 #else
6688 tcg_gen_concat32_i64(t1, t1, t0);
6689 #endif
6690 tcg_gen_st_i64(t1, cpu_env, off);
6691 tcg_temp_free_i64(t1);
6692 tcg_temp_free_i64(t0);
6695 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6697 TCGv_i64 t0 = tcg_temp_new_i64();
6698 TCGv_i64 t1 = tcg_temp_new_i64();
6700 tcg_gen_ext_tl_i64(t0, arg);
6701 tcg_gen_ld_i64(t1, cpu_env, off);
6702 tcg_gen_concat32_i64(t1, t1, t0);
6703 tcg_gen_st_i64(t1, cpu_env, off);
6704 tcg_temp_free_i64(t1);
6705 tcg_temp_free_i64(t0);
6708 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6710 TCGv_i64 t0 = tcg_temp_new_i64();
6712 tcg_gen_ld_i64(t0, cpu_env, off);
6713 #if defined(TARGET_MIPS64)
6714 tcg_gen_shri_i64(t0, t0, 30);
6715 #else
6716 tcg_gen_shri_i64(t0, t0, 32);
6717 #endif
6718 gen_move_low32(arg, t0);
6719 tcg_temp_free_i64(t0);
6722 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6724 TCGv_i64 t0 = tcg_temp_new_i64();
6726 tcg_gen_ld_i64(t0, cpu_env, off);
6727 tcg_gen_shri_i64(t0, t0, 32 + shift);
6728 gen_move_low32(arg, t0);
6729 tcg_temp_free_i64(t0);
6732 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6734 TCGv_i32 t0 = tcg_temp_new_i32();
6736 tcg_gen_ld_i32(t0, cpu_env, off);
6737 tcg_gen_ext_i32_tl(arg, t0);
6738 tcg_temp_free_i32(t0);
6741 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6743 tcg_gen_ld_tl(arg, cpu_env, off);
6744 tcg_gen_ext32s_tl(arg, arg);
6747 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6749 TCGv_i32 t0 = tcg_temp_new_i32();
6751 tcg_gen_trunc_tl_i32(t0, arg);
6752 tcg_gen_st_i32(t0, cpu_env, off);
6753 tcg_temp_free_i32(t0);
6756 #define CP0_CHECK(c) \
6757 do { \
6758 if (!(c)) { \
6759 goto cp0_unimplemented; \
6761 } while (0)
6763 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6765 const char *register_name = "invalid";
6767 switch (reg) {
6768 case CP0_REGISTER_02:
6769 switch (sel) {
6770 case 0:
6771 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6772 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6773 register_name = "EntryLo0";
6774 break;
6775 default:
6776 goto cp0_unimplemented;
6778 break;
6779 case CP0_REGISTER_03:
6780 switch (sel) {
6781 case CP0_REG03__ENTRYLO1:
6782 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6783 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6784 register_name = "EntryLo1";
6785 break;
6786 default:
6787 goto cp0_unimplemented;
6789 break;
6790 case CP0_REGISTER_09:
6791 switch (sel) {
6792 case CP0_REG09__SAAR:
6793 CP0_CHECK(ctx->saar);
6794 gen_helper_mfhc0_saar(arg, cpu_env);
6795 register_name = "SAAR";
6796 break;
6797 default:
6798 goto cp0_unimplemented;
6800 break;
6801 case CP0_REGISTER_17:
6802 switch (sel) {
6803 case CP0_REG17__LLADDR:
6804 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6805 ctx->CP0_LLAddr_shift);
6806 register_name = "LLAddr";
6807 break;
6808 case CP0_REG17__MAAR:
6809 CP0_CHECK(ctx->mrp);
6810 gen_helper_mfhc0_maar(arg, cpu_env);
6811 register_name = "MAAR";
6812 break;
6813 default:
6814 goto cp0_unimplemented;
6816 break;
6817 case CP0_REGISTER_19:
6818 switch (sel) {
6819 case CP0_REG19__WATCHHI0:
6820 case CP0_REG19__WATCHHI1:
6821 case CP0_REG19__WATCHHI2:
6822 case CP0_REG19__WATCHHI3:
6823 case CP0_REG19__WATCHHI4:
6824 case CP0_REG19__WATCHHI5:
6825 case CP0_REG19__WATCHHI6:
6826 case CP0_REG19__WATCHHI7:
6827 /* upper 32 bits are only available when Config5MI != 0 */
6828 CP0_CHECK(ctx->mi);
6829 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6830 register_name = "WatchHi";
6831 break;
6832 default:
6833 goto cp0_unimplemented;
6835 break;
6836 case CP0_REGISTER_28:
6837 switch (sel) {
6838 case 0:
6839 case 2:
6840 case 4:
6841 case 6:
6842 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6843 register_name = "TagLo";
6844 break;
6845 default:
6846 goto cp0_unimplemented;
6848 break;
6849 default:
6850 goto cp0_unimplemented;
6852 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6853 return;
6855 cp0_unimplemented:
6856 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6857 register_name, reg, sel);
6858 tcg_gen_movi_tl(arg, 0);
6861 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6863 const char *register_name = "invalid";
6864 uint64_t mask = ctx->PAMask >> 36;
6866 switch (reg) {
6867 case CP0_REGISTER_02:
6868 switch (sel) {
6869 case 0:
6870 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6871 tcg_gen_andi_tl(arg, arg, mask);
6872 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6873 register_name = "EntryLo0";
6874 break;
6875 default:
6876 goto cp0_unimplemented;
6878 break;
6879 case CP0_REGISTER_03:
6880 switch (sel) {
6881 case CP0_REG03__ENTRYLO1:
6882 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6883 tcg_gen_andi_tl(arg, arg, mask);
6884 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6885 register_name = "EntryLo1";
6886 break;
6887 default:
6888 goto cp0_unimplemented;
6890 break;
6891 case CP0_REGISTER_09:
6892 switch (sel) {
6893 case CP0_REG09__SAAR:
6894 CP0_CHECK(ctx->saar);
6895 gen_helper_mthc0_saar(cpu_env, arg);
6896 register_name = "SAAR";
6897 break;
6898 default:
6899 goto cp0_unimplemented;
6901 break;
6902 case CP0_REGISTER_17:
6903 switch (sel) {
6904 case CP0_REG17__LLADDR:
6906 * LLAddr is read-only (the only exception is bit 0 if LLB is
6907 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6908 * relevant for modern MIPS cores supporting MTHC0, therefore
6909 * treating MTHC0 to LLAddr as NOP.
6911 register_name = "LLAddr";
6912 break;
6913 case CP0_REG17__MAAR:
6914 CP0_CHECK(ctx->mrp);
6915 gen_helper_mthc0_maar(cpu_env, arg);
6916 register_name = "MAAR";
6917 break;
6918 default:
6919 goto cp0_unimplemented;
6921 break;
6922 case CP0_REGISTER_19:
6923 switch (sel) {
6924 case CP0_REG19__WATCHHI0:
6925 case CP0_REG19__WATCHHI1:
6926 case CP0_REG19__WATCHHI2:
6927 case CP0_REG19__WATCHHI3:
6928 case CP0_REG19__WATCHHI4:
6929 case CP0_REG19__WATCHHI5:
6930 case CP0_REG19__WATCHHI6:
6931 case CP0_REG19__WATCHHI7:
6932 /* upper 32 bits are only available when Config5MI != 0 */
6933 CP0_CHECK(ctx->mi);
6934 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6935 register_name = "WatchHi";
6936 break;
6937 default:
6938 goto cp0_unimplemented;
6940 break;
6941 case CP0_REGISTER_28:
6942 switch (sel) {
6943 case 0:
6944 case 2:
6945 case 4:
6946 case 6:
6947 tcg_gen_andi_tl(arg, arg, mask);
6948 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6949 register_name = "TagLo";
6950 break;
6951 default:
6952 goto cp0_unimplemented;
6954 break;
6955 default:
6956 goto cp0_unimplemented;
6958 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6960 cp0_unimplemented:
6961 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6962 register_name, reg, sel);
6965 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6967 if (ctx->insn_flags & ISA_MIPS32R6) {
6968 tcg_gen_movi_tl(arg, 0);
6969 } else {
6970 tcg_gen_movi_tl(arg, ~0);
6974 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6976 const char *register_name = "invalid";
6978 if (sel != 0) {
6979 check_insn(ctx, ISA_MIPS32);
6982 switch (reg) {
6983 case CP0_REGISTER_00:
6984 switch (sel) {
6985 case CP0_REG00__INDEX:
6986 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6987 register_name = "Index";
6988 break;
6989 case CP0_REG00__MVPCONTROL:
6990 CP0_CHECK(ctx->insn_flags & ASE_MT);
6991 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6992 register_name = "MVPControl";
6993 break;
6994 case CP0_REG00__MVPCONF0:
6995 CP0_CHECK(ctx->insn_flags & ASE_MT);
6996 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6997 register_name = "MVPConf0";
6998 break;
6999 case CP0_REG00__MVPCONF1:
7000 CP0_CHECK(ctx->insn_flags & ASE_MT);
7001 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7002 register_name = "MVPConf1";
7003 break;
7004 case CP0_REG00__VPCONTROL:
7005 CP0_CHECK(ctx->vp);
7006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7007 register_name = "VPControl";
7008 break;
7009 default:
7010 goto cp0_unimplemented;
7012 break;
7013 case CP0_REGISTER_01:
7014 switch (sel) {
7015 case CP0_REG01__RANDOM:
7016 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7017 gen_helper_mfc0_random(arg, cpu_env);
7018 register_name = "Random";
7019 break;
7020 case CP0_REG01__VPECONTROL:
7021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7023 register_name = "VPEControl";
7024 break;
7025 case CP0_REG01__VPECONF0:
7026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7027 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7028 register_name = "VPEConf0";
7029 break;
7030 case CP0_REG01__VPECONF1:
7031 CP0_CHECK(ctx->insn_flags & ASE_MT);
7032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7033 register_name = "VPEConf1";
7034 break;
7035 case CP0_REG01__YQMASK:
7036 CP0_CHECK(ctx->insn_flags & ASE_MT);
7037 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7038 register_name = "YQMask";
7039 break;
7040 case CP0_REG01__VPESCHEDULE:
7041 CP0_CHECK(ctx->insn_flags & ASE_MT);
7042 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7043 register_name = "VPESchedule";
7044 break;
7045 case CP0_REG01__VPESCHEFBACK:
7046 CP0_CHECK(ctx->insn_flags & ASE_MT);
7047 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7048 register_name = "VPEScheFBack";
7049 break;
7050 case CP0_REG01__VPEOPT:
7051 CP0_CHECK(ctx->insn_flags & ASE_MT);
7052 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7053 register_name = "VPEOpt";
7054 break;
7055 default:
7056 goto cp0_unimplemented;
7058 break;
7059 case CP0_REGISTER_02:
7060 switch (sel) {
7061 case CP0_REG02__ENTRYLO0:
7063 TCGv_i64 tmp = tcg_temp_new_i64();
7064 tcg_gen_ld_i64(tmp, cpu_env,
7065 offsetof(CPUMIPSState, CP0_EntryLo0));
7066 #if defined(TARGET_MIPS64)
7067 if (ctx->rxi) {
7068 /* Move RI/XI fields to bits 31:30 */
7069 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7070 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7072 #endif
7073 gen_move_low32(arg, tmp);
7074 tcg_temp_free_i64(tmp);
7076 register_name = "EntryLo0";
7077 break;
7078 case CP0_REG02__TCSTATUS:
7079 CP0_CHECK(ctx->insn_flags & ASE_MT);
7080 gen_helper_mfc0_tcstatus(arg, cpu_env);
7081 register_name = "TCStatus";
7082 break;
7083 case CP0_REG02__TCBIND:
7084 CP0_CHECK(ctx->insn_flags & ASE_MT);
7085 gen_helper_mfc0_tcbind(arg, cpu_env);
7086 register_name = "TCBind";
7087 break;
7088 case CP0_REG02__TCRESTART:
7089 CP0_CHECK(ctx->insn_flags & ASE_MT);
7090 gen_helper_mfc0_tcrestart(arg, cpu_env);
7091 register_name = "TCRestart";
7092 break;
7093 case CP0_REG02__TCHALT:
7094 CP0_CHECK(ctx->insn_flags & ASE_MT);
7095 gen_helper_mfc0_tchalt(arg, cpu_env);
7096 register_name = "TCHalt";
7097 break;
7098 case CP0_REG02__TCCONTEXT:
7099 CP0_CHECK(ctx->insn_flags & ASE_MT);
7100 gen_helper_mfc0_tccontext(arg, cpu_env);
7101 register_name = "TCContext";
7102 break;
7103 case CP0_REG02__TCSCHEDULE:
7104 CP0_CHECK(ctx->insn_flags & ASE_MT);
7105 gen_helper_mfc0_tcschedule(arg, cpu_env);
7106 register_name = "TCSchedule";
7107 break;
7108 case CP0_REG02__TCSCHEFBACK:
7109 CP0_CHECK(ctx->insn_flags & ASE_MT);
7110 gen_helper_mfc0_tcschefback(arg, cpu_env);
7111 register_name = "TCScheFBack";
7112 break;
7113 default:
7114 goto cp0_unimplemented;
7116 break;
7117 case CP0_REGISTER_03:
7118 switch (sel) {
7119 case CP0_REG03__ENTRYLO1:
7121 TCGv_i64 tmp = tcg_temp_new_i64();
7122 tcg_gen_ld_i64(tmp, cpu_env,
7123 offsetof(CPUMIPSState, CP0_EntryLo1));
7124 #if defined(TARGET_MIPS64)
7125 if (ctx->rxi) {
7126 /* Move RI/XI fields to bits 31:30 */
7127 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7128 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7130 #endif
7131 gen_move_low32(arg, tmp);
7132 tcg_temp_free_i64(tmp);
7134 register_name = "EntryLo1";
7135 break;
7136 case CP0_REG03__GLOBALNUM:
7137 CP0_CHECK(ctx->vp);
7138 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7139 register_name = "GlobalNumber";
7140 break;
7141 default:
7142 goto cp0_unimplemented;
7144 break;
7145 case CP0_REGISTER_04:
7146 switch (sel) {
7147 case CP0_REG04__CONTEXT:
7148 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7149 tcg_gen_ext32s_tl(arg, arg);
7150 register_name = "Context";
7151 break;
7152 case CP0_REG04__CONTEXTCONFIG:
7153 /* SmartMIPS ASE */
7154 /* gen_helper_mfc0_contextconfig(arg); */
7155 register_name = "ContextConfig";
7156 goto cp0_unimplemented;
7157 case CP0_REG04__USERLOCAL:
7158 CP0_CHECK(ctx->ulri);
7159 tcg_gen_ld_tl(arg, cpu_env,
7160 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7161 tcg_gen_ext32s_tl(arg, arg);
7162 register_name = "UserLocal";
7163 break;
7164 case CP0_REG04__MMID:
7165 CP0_CHECK(ctx->mi);
7166 gen_helper_mtc0_memorymapid(cpu_env, arg);
7167 register_name = "MMID";
7168 break;
7169 default:
7170 goto cp0_unimplemented;
7172 break;
7173 case CP0_REGISTER_05:
7174 switch (sel) {
7175 case CP0_REG05__PAGEMASK:
7176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7177 register_name = "PageMask";
7178 break;
7179 case CP0_REG05__PAGEGRAIN:
7180 check_insn(ctx, ISA_MIPS32R2);
7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7182 register_name = "PageGrain";
7183 break;
7184 case CP0_REG05__SEGCTL0:
7185 CP0_CHECK(ctx->sc);
7186 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7187 tcg_gen_ext32s_tl(arg, arg);
7188 register_name = "SegCtl0";
7189 break;
7190 case CP0_REG05__SEGCTL1:
7191 CP0_CHECK(ctx->sc);
7192 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7193 tcg_gen_ext32s_tl(arg, arg);
7194 register_name = "SegCtl1";
7195 break;
7196 case CP0_REG05__SEGCTL2:
7197 CP0_CHECK(ctx->sc);
7198 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7199 tcg_gen_ext32s_tl(arg, arg);
7200 register_name = "SegCtl2";
7201 break;
7202 case CP0_REG05__PWBASE:
7203 check_pw(ctx);
7204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7205 register_name = "PWBase";
7206 break;
7207 case CP0_REG05__PWFIELD:
7208 check_pw(ctx);
7209 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7210 register_name = "PWField";
7211 break;
7212 case CP0_REG05__PWSIZE:
7213 check_pw(ctx);
7214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7215 register_name = "PWSize";
7216 break;
7217 default:
7218 goto cp0_unimplemented;
7220 break;
7221 case CP0_REGISTER_06:
7222 switch (sel) {
7223 case CP0_REG06__WIRED:
7224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7225 register_name = "Wired";
7226 break;
7227 case CP0_REG06__SRSCONF0:
7228 check_insn(ctx, ISA_MIPS32R2);
7229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7230 register_name = "SRSConf0";
7231 break;
7232 case CP0_REG06__SRSCONF1:
7233 check_insn(ctx, ISA_MIPS32R2);
7234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7235 register_name = "SRSConf1";
7236 break;
7237 case CP0_REG06__SRSCONF2:
7238 check_insn(ctx, ISA_MIPS32R2);
7239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7240 register_name = "SRSConf2";
7241 break;
7242 case CP0_REG06__SRSCONF3:
7243 check_insn(ctx, ISA_MIPS32R2);
7244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7245 register_name = "SRSConf3";
7246 break;
7247 case CP0_REG06__SRSCONF4:
7248 check_insn(ctx, ISA_MIPS32R2);
7249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7250 register_name = "SRSConf4";
7251 break;
7252 case CP0_REG06__PWCTL:
7253 check_pw(ctx);
7254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7255 register_name = "PWCtl";
7256 break;
7257 default:
7258 goto cp0_unimplemented;
7260 break;
7261 case CP0_REGISTER_07:
7262 switch (sel) {
7263 case CP0_REG07__HWRENA:
7264 check_insn(ctx, ISA_MIPS32R2);
7265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7266 register_name = "HWREna";
7267 break;
7268 default:
7269 goto cp0_unimplemented;
7271 break;
7272 case CP0_REGISTER_08:
7273 switch (sel) {
7274 case CP0_REG08__BADVADDR:
7275 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7276 tcg_gen_ext32s_tl(arg, arg);
7277 register_name = "BadVAddr";
7278 break;
7279 case CP0_REG08__BADINSTR:
7280 CP0_CHECK(ctx->bi);
7281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7282 register_name = "BadInstr";
7283 break;
7284 case CP0_REG08__BADINSTRP:
7285 CP0_CHECK(ctx->bp);
7286 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7287 register_name = "BadInstrP";
7288 break;
7289 case CP0_REG08__BADINSTRX:
7290 CP0_CHECK(ctx->bi);
7291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7292 tcg_gen_andi_tl(arg, arg, ~0xffff);
7293 register_name = "BadInstrX";
7294 break;
7295 default:
7296 goto cp0_unimplemented;
7298 break;
7299 case CP0_REGISTER_09:
7300 switch (sel) {
7301 case CP0_REG09__COUNT:
7302 /* Mark as an IO operation because we read the time. */
7303 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7304 gen_io_start();
7306 gen_helper_mfc0_count(arg, cpu_env);
7308 * Break the TB to be able to take timer interrupts immediately
7309 * after reading count. DISAS_STOP isn't sufficient, we need to
7310 * ensure we break completely out of translated code.
7312 gen_save_pc(ctx->base.pc_next + 4);
7313 ctx->base.is_jmp = DISAS_EXIT;
7314 register_name = "Count";
7315 break;
7316 case CP0_REG09__SAARI:
7317 CP0_CHECK(ctx->saar);
7318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7319 register_name = "SAARI";
7320 break;
7321 case CP0_REG09__SAAR:
7322 CP0_CHECK(ctx->saar);
7323 gen_helper_mfc0_saar(arg, cpu_env);
7324 register_name = "SAAR";
7325 break;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case CP0_REGISTER_10:
7331 switch (sel) {
7332 case CP0_REG10__ENTRYHI:
7333 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7334 tcg_gen_ext32s_tl(arg, arg);
7335 register_name = "EntryHi";
7336 break;
7337 default:
7338 goto cp0_unimplemented;
7340 break;
7341 case CP0_REGISTER_11:
7342 switch (sel) {
7343 case CP0_REG11__COMPARE:
7344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7345 register_name = "Compare";
7346 break;
7347 /* 6,7 are implementation dependent */
7348 default:
7349 goto cp0_unimplemented;
7351 break;
7352 case CP0_REGISTER_12:
7353 switch (sel) {
7354 case CP0_REG12__STATUS:
7355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7356 register_name = "Status";
7357 break;
7358 case CP0_REG12__INTCTL:
7359 check_insn(ctx, ISA_MIPS32R2);
7360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7361 register_name = "IntCtl";
7362 break;
7363 case CP0_REG12__SRSCTL:
7364 check_insn(ctx, ISA_MIPS32R2);
7365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7366 register_name = "SRSCtl";
7367 break;
7368 case CP0_REG12__SRSMAP:
7369 check_insn(ctx, ISA_MIPS32R2);
7370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7371 register_name = "SRSMap";
7372 break;
7373 default:
7374 goto cp0_unimplemented;
7376 break;
7377 case CP0_REGISTER_13:
7378 switch (sel) {
7379 case CP0_REG13__CAUSE:
7380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7381 register_name = "Cause";
7382 break;
7383 default:
7384 goto cp0_unimplemented;
7386 break;
7387 case CP0_REGISTER_14:
7388 switch (sel) {
7389 case CP0_REG14__EPC:
7390 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7391 tcg_gen_ext32s_tl(arg, arg);
7392 register_name = "EPC";
7393 break;
7394 default:
7395 goto cp0_unimplemented;
7397 break;
7398 case CP0_REGISTER_15:
7399 switch (sel) {
7400 case CP0_REG15__PRID:
7401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7402 register_name = "PRid";
7403 break;
7404 case CP0_REG15__EBASE:
7405 check_insn(ctx, ISA_MIPS32R2);
7406 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7407 tcg_gen_ext32s_tl(arg, arg);
7408 register_name = "EBase";
7409 break;
7410 case CP0_REG15__CMGCRBASE:
7411 check_insn(ctx, ISA_MIPS32R2);
7412 CP0_CHECK(ctx->cmgcr);
7413 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7414 tcg_gen_ext32s_tl(arg, arg);
7415 register_name = "CMGCRBase";
7416 break;
7417 default:
7418 goto cp0_unimplemented;
7420 break;
7421 case CP0_REGISTER_16:
7422 switch (sel) {
7423 case CP0_REG16__CONFIG:
7424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7425 register_name = "Config";
7426 break;
7427 case CP0_REG16__CONFIG1:
7428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7429 register_name = "Config1";
7430 break;
7431 case CP0_REG16__CONFIG2:
7432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7433 register_name = "Config2";
7434 break;
7435 case CP0_REG16__CONFIG3:
7436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7437 register_name = "Config3";
7438 break;
7439 case CP0_REG16__CONFIG4:
7440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7441 register_name = "Config4";
7442 break;
7443 case CP0_REG16__CONFIG5:
7444 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7445 register_name = "Config5";
7446 break;
7447 /* 6,7 are implementation dependent */
7448 case CP0_REG16__CONFIG6:
7449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7450 register_name = "Config6";
7451 break;
7452 case CP0_REG16__CONFIG7:
7453 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7454 register_name = "Config7";
7455 break;
7456 default:
7457 goto cp0_unimplemented;
7459 break;
7460 case CP0_REGISTER_17:
7461 switch (sel) {
7462 case CP0_REG17__LLADDR:
7463 gen_helper_mfc0_lladdr(arg, cpu_env);
7464 register_name = "LLAddr";
7465 break;
7466 case CP0_REG17__MAAR:
7467 CP0_CHECK(ctx->mrp);
7468 gen_helper_mfc0_maar(arg, cpu_env);
7469 register_name = "MAAR";
7470 break;
7471 case CP0_REG17__MAARI:
7472 CP0_CHECK(ctx->mrp);
7473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7474 register_name = "MAARI";
7475 break;
7476 default:
7477 goto cp0_unimplemented;
7479 break;
7480 case CP0_REGISTER_18:
7481 switch (sel) {
7482 case CP0_REG18__WATCHLO0:
7483 case CP0_REG18__WATCHLO1:
7484 case CP0_REG18__WATCHLO2:
7485 case CP0_REG18__WATCHLO3:
7486 case CP0_REG18__WATCHLO4:
7487 case CP0_REG18__WATCHLO5:
7488 case CP0_REG18__WATCHLO6:
7489 case CP0_REG18__WATCHLO7:
7490 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7491 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7492 register_name = "WatchLo";
7493 break;
7494 default:
7495 goto cp0_unimplemented;
7497 break;
7498 case CP0_REGISTER_19:
7499 switch (sel) {
7500 case CP0_REG19__WATCHHI0:
7501 case CP0_REG19__WATCHHI1:
7502 case CP0_REG19__WATCHHI2:
7503 case CP0_REG19__WATCHHI3:
7504 case CP0_REG19__WATCHHI4:
7505 case CP0_REG19__WATCHHI5:
7506 case CP0_REG19__WATCHHI6:
7507 case CP0_REG19__WATCHHI7:
7508 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7509 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7510 register_name = "WatchHi";
7511 break;
7512 default:
7513 goto cp0_unimplemented;
7515 break;
7516 case CP0_REGISTER_20:
7517 switch (sel) {
7518 case CP0_REG20__XCONTEXT:
7519 #if defined(TARGET_MIPS64)
7520 check_insn(ctx, ISA_MIPS3);
7521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7522 tcg_gen_ext32s_tl(arg, arg);
7523 register_name = "XContext";
7524 break;
7525 #endif
7526 default:
7527 goto cp0_unimplemented;
7529 break;
7530 case CP0_REGISTER_21:
7531 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7532 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7533 switch (sel) {
7534 case 0:
7535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7536 register_name = "Framemask";
7537 break;
7538 default:
7539 goto cp0_unimplemented;
7541 break;
7542 case CP0_REGISTER_22:
7543 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7544 register_name = "'Diagnostic"; /* implementation dependent */
7545 break;
7546 case CP0_REGISTER_23:
7547 switch (sel) {
7548 case CP0_REG23__DEBUG:
7549 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7550 register_name = "Debug";
7551 break;
7552 case CP0_REG23__TRACECONTROL:
7553 /* PDtrace support */
7554 /* gen_helper_mfc0_tracecontrol(arg); */
7555 register_name = "TraceControl";
7556 goto cp0_unimplemented;
7557 case CP0_REG23__TRACECONTROL2:
7558 /* PDtrace support */
7559 /* gen_helper_mfc0_tracecontrol2(arg); */
7560 register_name = "TraceControl2";
7561 goto cp0_unimplemented;
7562 case CP0_REG23__USERTRACEDATA1:
7563 /* PDtrace support */
7564 /* gen_helper_mfc0_usertracedata1(arg);*/
7565 register_name = "UserTraceData1";
7566 goto cp0_unimplemented;
7567 case CP0_REG23__TRACEIBPC:
7568 /* PDtrace support */
7569 /* gen_helper_mfc0_traceibpc(arg); */
7570 register_name = "TraceIBPC";
7571 goto cp0_unimplemented;
7572 case CP0_REG23__TRACEDBPC:
7573 /* PDtrace support */
7574 /* gen_helper_mfc0_tracedbpc(arg); */
7575 register_name = "TraceDBPC";
7576 goto cp0_unimplemented;
7577 default:
7578 goto cp0_unimplemented;
7580 break;
7581 case CP0_REGISTER_24:
7582 switch (sel) {
7583 case CP0_REG24__DEPC:
7584 /* EJTAG support */
7585 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7586 tcg_gen_ext32s_tl(arg, arg);
7587 register_name = "DEPC";
7588 break;
7589 default:
7590 goto cp0_unimplemented;
7592 break;
7593 case CP0_REGISTER_25:
7594 switch (sel) {
7595 case CP0_REG25__PERFCTL0:
7596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7597 register_name = "Performance0";
7598 break;
7599 case CP0_REG25__PERFCNT0:
7600 /* gen_helper_mfc0_performance1(arg); */
7601 register_name = "Performance1";
7602 goto cp0_unimplemented;
7603 case CP0_REG25__PERFCTL1:
7604 /* gen_helper_mfc0_performance2(arg); */
7605 register_name = "Performance2";
7606 goto cp0_unimplemented;
7607 case CP0_REG25__PERFCNT1:
7608 /* gen_helper_mfc0_performance3(arg); */
7609 register_name = "Performance3";
7610 goto cp0_unimplemented;
7611 case CP0_REG25__PERFCTL2:
7612 /* gen_helper_mfc0_performance4(arg); */
7613 register_name = "Performance4";
7614 goto cp0_unimplemented;
7615 case CP0_REG25__PERFCNT2:
7616 /* gen_helper_mfc0_performance5(arg); */
7617 register_name = "Performance5";
7618 goto cp0_unimplemented;
7619 case CP0_REG25__PERFCTL3:
7620 /* gen_helper_mfc0_performance6(arg); */
7621 register_name = "Performance6";
7622 goto cp0_unimplemented;
7623 case CP0_REG25__PERFCNT3:
7624 /* gen_helper_mfc0_performance7(arg); */
7625 register_name = "Performance7";
7626 goto cp0_unimplemented;
7627 default:
7628 goto cp0_unimplemented;
7630 break;
7631 case CP0_REGISTER_26:
7632 switch (sel) {
7633 case CP0_REG26__ERRCTL:
7634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7635 register_name = "ErrCtl";
7636 break;
7637 default:
7638 goto cp0_unimplemented;
7640 break;
7641 case CP0_REGISTER_27:
7642 switch (sel) {
7643 case CP0_REG27__CACHERR:
7644 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7645 register_name = "CacheErr";
7646 break;
7647 default:
7648 goto cp0_unimplemented;
7650 break;
7651 case CP0_REGISTER_28:
7652 switch (sel) {
7653 case CP0_REG28__TAGLO:
7654 case CP0_REG28__TAGLO1:
7655 case CP0_REG28__TAGLO2:
7656 case CP0_REG28__TAGLO3:
7658 TCGv_i64 tmp = tcg_temp_new_i64();
7659 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7660 gen_move_low32(arg, tmp);
7661 tcg_temp_free_i64(tmp);
7663 register_name = "TagLo";
7664 break;
7665 case CP0_REG28__DATALO:
7666 case CP0_REG28__DATALO1:
7667 case CP0_REG28__DATALO2:
7668 case CP0_REG28__DATALO3:
7669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7670 register_name = "DataLo";
7671 break;
7672 default:
7673 goto cp0_unimplemented;
7675 break;
7676 case CP0_REGISTER_29:
7677 switch (sel) {
7678 case CP0_REG29__TAGHI:
7679 case CP0_REG29__TAGHI1:
7680 case CP0_REG29__TAGHI2:
7681 case CP0_REG29__TAGHI3:
7682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7683 register_name = "TagHi";
7684 break;
7685 case CP0_REG29__DATAHI:
7686 case CP0_REG29__DATAHI1:
7687 case CP0_REG29__DATAHI2:
7688 case CP0_REG29__DATAHI3:
7689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7690 register_name = "DataHi";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case CP0_REGISTER_30:
7697 switch (sel) {
7698 case CP0_REG30__ERROREPC:
7699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7700 tcg_gen_ext32s_tl(arg, arg);
7701 register_name = "ErrorEPC";
7702 break;
7703 default:
7704 goto cp0_unimplemented;
7706 break;
7707 case CP0_REGISTER_31:
7708 switch (sel) {
7709 case CP0_REG31__DESAVE:
7710 /* EJTAG support */
7711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7712 register_name = "DESAVE";
7713 break;
7714 case CP0_REG31__KSCRATCH1:
7715 case CP0_REG31__KSCRATCH2:
7716 case CP0_REG31__KSCRATCH3:
7717 case CP0_REG31__KSCRATCH4:
7718 case CP0_REG31__KSCRATCH5:
7719 case CP0_REG31__KSCRATCH6:
7720 CP0_CHECK(ctx->kscrexist & (1 << sel));
7721 tcg_gen_ld_tl(arg, cpu_env,
7722 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7723 tcg_gen_ext32s_tl(arg, arg);
7724 register_name = "KScratch";
7725 break;
7726 default:
7727 goto cp0_unimplemented;
7729 break;
7730 default:
7731 goto cp0_unimplemented;
7733 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7734 return;
7736 cp0_unimplemented:
7737 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7738 register_name, reg, sel);
7739 gen_mfc0_unimplemented(ctx, arg);
7742 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7744 const char *register_name = "invalid";
7746 if (sel != 0) {
7747 check_insn(ctx, ISA_MIPS32);
7750 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7751 gen_io_start();
7754 switch (reg) {
7755 case CP0_REGISTER_00:
7756 switch (sel) {
7757 case CP0_REG00__INDEX:
7758 gen_helper_mtc0_index(cpu_env, arg);
7759 register_name = "Index";
7760 break;
7761 case CP0_REG00__MVPCONTROL:
7762 CP0_CHECK(ctx->insn_flags & ASE_MT);
7763 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7764 register_name = "MVPControl";
7765 break;
7766 case CP0_REG00__MVPCONF0:
7767 CP0_CHECK(ctx->insn_flags & ASE_MT);
7768 /* ignored */
7769 register_name = "MVPConf0";
7770 break;
7771 case CP0_REG00__MVPCONF1:
7772 CP0_CHECK(ctx->insn_flags & ASE_MT);
7773 /* ignored */
7774 register_name = "MVPConf1";
7775 break;
7776 case CP0_REG00__VPCONTROL:
7777 CP0_CHECK(ctx->vp);
7778 /* ignored */
7779 register_name = "VPControl";
7780 break;
7781 default:
7782 goto cp0_unimplemented;
7784 break;
7785 case CP0_REGISTER_01:
7786 switch (sel) {
7787 case CP0_REG01__RANDOM:
7788 /* ignored */
7789 register_name = "Random";
7790 break;
7791 case CP0_REG01__VPECONTROL:
7792 CP0_CHECK(ctx->insn_flags & ASE_MT);
7793 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7794 register_name = "VPEControl";
7795 break;
7796 case CP0_REG01__VPECONF0:
7797 CP0_CHECK(ctx->insn_flags & ASE_MT);
7798 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7799 register_name = "VPEConf0";
7800 break;
7801 case CP0_REG01__VPECONF1:
7802 CP0_CHECK(ctx->insn_flags & ASE_MT);
7803 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7804 register_name = "VPEConf1";
7805 break;
7806 case CP0_REG01__YQMASK:
7807 CP0_CHECK(ctx->insn_flags & ASE_MT);
7808 gen_helper_mtc0_yqmask(cpu_env, arg);
7809 register_name = "YQMask";
7810 break;
7811 case CP0_REG01__VPESCHEDULE:
7812 CP0_CHECK(ctx->insn_flags & ASE_MT);
7813 tcg_gen_st_tl(arg, cpu_env,
7814 offsetof(CPUMIPSState, CP0_VPESchedule));
7815 register_name = "VPESchedule";
7816 break;
7817 case CP0_REG01__VPESCHEFBACK:
7818 CP0_CHECK(ctx->insn_flags & ASE_MT);
7819 tcg_gen_st_tl(arg, cpu_env,
7820 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7821 register_name = "VPEScheFBack";
7822 break;
7823 case CP0_REG01__VPEOPT:
7824 CP0_CHECK(ctx->insn_flags & ASE_MT);
7825 gen_helper_mtc0_vpeopt(cpu_env, arg);
7826 register_name = "VPEOpt";
7827 break;
7828 default:
7829 goto cp0_unimplemented;
7831 break;
7832 case CP0_REGISTER_02:
7833 switch (sel) {
7834 case CP0_REG02__ENTRYLO0:
7835 gen_helper_mtc0_entrylo0(cpu_env, arg);
7836 register_name = "EntryLo0";
7837 break;
7838 case CP0_REG02__TCSTATUS:
7839 CP0_CHECK(ctx->insn_flags & ASE_MT);
7840 gen_helper_mtc0_tcstatus(cpu_env, arg);
7841 register_name = "TCStatus";
7842 break;
7843 case CP0_REG02__TCBIND:
7844 CP0_CHECK(ctx->insn_flags & ASE_MT);
7845 gen_helper_mtc0_tcbind(cpu_env, arg);
7846 register_name = "TCBind";
7847 break;
7848 case CP0_REG02__TCRESTART:
7849 CP0_CHECK(ctx->insn_flags & ASE_MT);
7850 gen_helper_mtc0_tcrestart(cpu_env, arg);
7851 register_name = "TCRestart";
7852 break;
7853 case CP0_REG02__TCHALT:
7854 CP0_CHECK(ctx->insn_flags & ASE_MT);
7855 gen_helper_mtc0_tchalt(cpu_env, arg);
7856 register_name = "TCHalt";
7857 break;
7858 case CP0_REG02__TCCONTEXT:
7859 CP0_CHECK(ctx->insn_flags & ASE_MT);
7860 gen_helper_mtc0_tccontext(cpu_env, arg);
7861 register_name = "TCContext";
7862 break;
7863 case CP0_REG02__TCSCHEDULE:
7864 CP0_CHECK(ctx->insn_flags & ASE_MT);
7865 gen_helper_mtc0_tcschedule(cpu_env, arg);
7866 register_name = "TCSchedule";
7867 break;
7868 case CP0_REG02__TCSCHEFBACK:
7869 CP0_CHECK(ctx->insn_flags & ASE_MT);
7870 gen_helper_mtc0_tcschefback(cpu_env, arg);
7871 register_name = "TCScheFBack";
7872 break;
7873 default:
7874 goto cp0_unimplemented;
7876 break;
7877 case CP0_REGISTER_03:
7878 switch (sel) {
7879 case CP0_REG03__ENTRYLO1:
7880 gen_helper_mtc0_entrylo1(cpu_env, arg);
7881 register_name = "EntryLo1";
7882 break;
7883 case CP0_REG03__GLOBALNUM:
7884 CP0_CHECK(ctx->vp);
7885 /* ignored */
7886 register_name = "GlobalNumber";
7887 break;
7888 default:
7889 goto cp0_unimplemented;
7891 break;
7892 case CP0_REGISTER_04:
7893 switch (sel) {
7894 case CP0_REG04__CONTEXT:
7895 gen_helper_mtc0_context(cpu_env, arg);
7896 register_name = "Context";
7897 break;
7898 case CP0_REG04__CONTEXTCONFIG:
7899 /* SmartMIPS ASE */
7900 /* gen_helper_mtc0_contextconfig(arg); */
7901 register_name = "ContextConfig";
7902 goto cp0_unimplemented;
7903 case CP0_REG04__USERLOCAL:
7904 CP0_CHECK(ctx->ulri);
7905 tcg_gen_st_tl(arg, cpu_env,
7906 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7907 register_name = "UserLocal";
7908 break;
7909 case CP0_REG04__MMID:
7910 CP0_CHECK(ctx->mi);
7911 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7912 register_name = "MMID";
7913 break;
7914 default:
7915 goto cp0_unimplemented;
7917 break;
7918 case CP0_REGISTER_05:
7919 switch (sel) {
7920 case CP0_REG05__PAGEMASK:
7921 gen_helper_mtc0_pagemask(cpu_env, arg);
7922 register_name = "PageMask";
7923 break;
7924 case CP0_REG05__PAGEGRAIN:
7925 check_insn(ctx, ISA_MIPS32R2);
7926 gen_helper_mtc0_pagegrain(cpu_env, arg);
7927 register_name = "PageGrain";
7928 ctx->base.is_jmp = DISAS_STOP;
7929 break;
7930 case CP0_REG05__SEGCTL0:
7931 CP0_CHECK(ctx->sc);
7932 gen_helper_mtc0_segctl0(cpu_env, arg);
7933 register_name = "SegCtl0";
7934 break;
7935 case CP0_REG05__SEGCTL1:
7936 CP0_CHECK(ctx->sc);
7937 gen_helper_mtc0_segctl1(cpu_env, arg);
7938 register_name = "SegCtl1";
7939 break;
7940 case CP0_REG05__SEGCTL2:
7941 CP0_CHECK(ctx->sc);
7942 gen_helper_mtc0_segctl2(cpu_env, arg);
7943 register_name = "SegCtl2";
7944 break;
7945 case CP0_REG05__PWBASE:
7946 check_pw(ctx);
7947 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7948 register_name = "PWBase";
7949 break;
7950 case CP0_REG05__PWFIELD:
7951 check_pw(ctx);
7952 gen_helper_mtc0_pwfield(cpu_env, arg);
7953 register_name = "PWField";
7954 break;
7955 case CP0_REG05__PWSIZE:
7956 check_pw(ctx);
7957 gen_helper_mtc0_pwsize(cpu_env, arg);
7958 register_name = "PWSize";
7959 break;
7960 default:
7961 goto cp0_unimplemented;
7963 break;
7964 case CP0_REGISTER_06:
7965 switch (sel) {
7966 case CP0_REG06__WIRED:
7967 gen_helper_mtc0_wired(cpu_env, arg);
7968 register_name = "Wired";
7969 break;
7970 case CP0_REG06__SRSCONF0:
7971 check_insn(ctx, ISA_MIPS32R2);
7972 gen_helper_mtc0_srsconf0(cpu_env, arg);
7973 register_name = "SRSConf0";
7974 break;
7975 case CP0_REG06__SRSCONF1:
7976 check_insn(ctx, ISA_MIPS32R2);
7977 gen_helper_mtc0_srsconf1(cpu_env, arg);
7978 register_name = "SRSConf1";
7979 break;
7980 case CP0_REG06__SRSCONF2:
7981 check_insn(ctx, ISA_MIPS32R2);
7982 gen_helper_mtc0_srsconf2(cpu_env, arg);
7983 register_name = "SRSConf2";
7984 break;
7985 case CP0_REG06__SRSCONF3:
7986 check_insn(ctx, ISA_MIPS32R2);
7987 gen_helper_mtc0_srsconf3(cpu_env, arg);
7988 register_name = "SRSConf3";
7989 break;
7990 case CP0_REG06__SRSCONF4:
7991 check_insn(ctx, ISA_MIPS32R2);
7992 gen_helper_mtc0_srsconf4(cpu_env, arg);
7993 register_name = "SRSConf4";
7994 break;
7995 case CP0_REG06__PWCTL:
7996 check_pw(ctx);
7997 gen_helper_mtc0_pwctl(cpu_env, arg);
7998 register_name = "PWCtl";
7999 break;
8000 default:
8001 goto cp0_unimplemented;
8003 break;
8004 case CP0_REGISTER_07:
8005 switch (sel) {
8006 case CP0_REG07__HWRENA:
8007 check_insn(ctx, ISA_MIPS32R2);
8008 gen_helper_mtc0_hwrena(cpu_env, arg);
8009 ctx->base.is_jmp = DISAS_STOP;
8010 register_name = "HWREna";
8011 break;
8012 default:
8013 goto cp0_unimplemented;
8015 break;
8016 case CP0_REGISTER_08:
8017 switch (sel) {
8018 case CP0_REG08__BADVADDR:
8019 /* ignored */
8020 register_name = "BadVAddr";
8021 break;
8022 case CP0_REG08__BADINSTR:
8023 /* ignored */
8024 register_name = "BadInstr";
8025 break;
8026 case CP0_REG08__BADINSTRP:
8027 /* ignored */
8028 register_name = "BadInstrP";
8029 break;
8030 case CP0_REG08__BADINSTRX:
8031 /* ignored */
8032 register_name = "BadInstrX";
8033 break;
8034 default:
8035 goto cp0_unimplemented;
8037 break;
8038 case CP0_REGISTER_09:
8039 switch (sel) {
8040 case CP0_REG09__COUNT:
8041 gen_helper_mtc0_count(cpu_env, arg);
8042 register_name = "Count";
8043 break;
8044 case CP0_REG09__SAARI:
8045 CP0_CHECK(ctx->saar);
8046 gen_helper_mtc0_saari(cpu_env, arg);
8047 register_name = "SAARI";
8048 break;
8049 case CP0_REG09__SAAR:
8050 CP0_CHECK(ctx->saar);
8051 gen_helper_mtc0_saar(cpu_env, arg);
8052 register_name = "SAAR";
8053 break;
8054 default:
8055 goto cp0_unimplemented;
8057 break;
8058 case CP0_REGISTER_10:
8059 switch (sel) {
8060 case CP0_REG10__ENTRYHI:
8061 gen_helper_mtc0_entryhi(cpu_env, arg);
8062 register_name = "EntryHi";
8063 break;
8064 default:
8065 goto cp0_unimplemented;
8067 break;
8068 case CP0_REGISTER_11:
8069 switch (sel) {
8070 case CP0_REG11__COMPARE:
8071 gen_helper_mtc0_compare(cpu_env, arg);
8072 register_name = "Compare";
8073 break;
8074 /* 6,7 are implementation dependent */
8075 default:
8076 goto cp0_unimplemented;
8078 break;
8079 case CP0_REGISTER_12:
8080 switch (sel) {
8081 case CP0_REG12__STATUS:
8082 save_cpu_state(ctx, 1);
8083 gen_helper_mtc0_status(cpu_env, arg);
8084 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8085 gen_save_pc(ctx->base.pc_next + 4);
8086 ctx->base.is_jmp = DISAS_EXIT;
8087 register_name = "Status";
8088 break;
8089 case CP0_REG12__INTCTL:
8090 check_insn(ctx, ISA_MIPS32R2);
8091 gen_helper_mtc0_intctl(cpu_env, arg);
8092 /* Stop translation as we may have switched the execution mode */
8093 ctx->base.is_jmp = DISAS_STOP;
8094 register_name = "IntCtl";
8095 break;
8096 case CP0_REG12__SRSCTL:
8097 check_insn(ctx, ISA_MIPS32R2);
8098 gen_helper_mtc0_srsctl(cpu_env, arg);
8099 /* Stop translation as we may have switched the execution mode */
8100 ctx->base.is_jmp = DISAS_STOP;
8101 register_name = "SRSCtl";
8102 break;
8103 case CP0_REG12__SRSMAP:
8104 check_insn(ctx, ISA_MIPS32R2);
8105 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8106 /* Stop translation as we may have switched the execution mode */
8107 ctx->base.is_jmp = DISAS_STOP;
8108 register_name = "SRSMap";
8109 break;
8110 default:
8111 goto cp0_unimplemented;
8113 break;
8114 case CP0_REGISTER_13:
8115 switch (sel) {
8116 case CP0_REG13__CAUSE:
8117 save_cpu_state(ctx, 1);
8118 gen_helper_mtc0_cause(cpu_env, arg);
8120 * Stop translation as we may have triggered an interrupt.
8121 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8122 * translated code to check for pending interrupts.
8124 gen_save_pc(ctx->base.pc_next + 4);
8125 ctx->base.is_jmp = DISAS_EXIT;
8126 register_name = "Cause";
8127 break;
8128 default:
8129 goto cp0_unimplemented;
8131 break;
8132 case CP0_REGISTER_14:
8133 switch (sel) {
8134 case CP0_REG14__EPC:
8135 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8136 register_name = "EPC";
8137 break;
8138 default:
8139 goto cp0_unimplemented;
8141 break;
8142 case CP0_REGISTER_15:
8143 switch (sel) {
8144 case CP0_REG15__PRID:
8145 /* ignored */
8146 register_name = "PRid";
8147 break;
8148 case CP0_REG15__EBASE:
8149 check_insn(ctx, ISA_MIPS32R2);
8150 gen_helper_mtc0_ebase(cpu_env, arg);
8151 register_name = "EBase";
8152 break;
8153 default:
8154 goto cp0_unimplemented;
8156 break;
8157 case CP0_REGISTER_16:
8158 switch (sel) {
8159 case CP0_REG16__CONFIG:
8160 gen_helper_mtc0_config0(cpu_env, arg);
8161 register_name = "Config";
8162 /* Stop translation as we may have switched the execution mode */
8163 ctx->base.is_jmp = DISAS_STOP;
8164 break;
8165 case CP0_REG16__CONFIG1:
8166 /* ignored, read only */
8167 register_name = "Config1";
8168 break;
8169 case CP0_REG16__CONFIG2:
8170 gen_helper_mtc0_config2(cpu_env, arg);
8171 register_name = "Config2";
8172 /* Stop translation as we may have switched the execution mode */
8173 ctx->base.is_jmp = DISAS_STOP;
8174 break;
8175 case CP0_REG16__CONFIG3:
8176 gen_helper_mtc0_config3(cpu_env, arg);
8177 register_name = "Config3";
8178 /* Stop translation as we may have switched the execution mode */
8179 ctx->base.is_jmp = DISAS_STOP;
8180 break;
8181 case CP0_REG16__CONFIG4:
8182 gen_helper_mtc0_config4(cpu_env, arg);
8183 register_name = "Config4";
8184 ctx->base.is_jmp = DISAS_STOP;
8185 break;
8186 case CP0_REG16__CONFIG5:
8187 gen_helper_mtc0_config5(cpu_env, arg);
8188 register_name = "Config5";
8189 /* Stop translation as we may have switched the execution mode */
8190 ctx->base.is_jmp = DISAS_STOP;
8191 break;
8192 /* 6,7 are implementation dependent */
8193 case CP0_REG16__CONFIG6:
8194 /* ignored */
8195 register_name = "Config6";
8196 break;
8197 case CP0_REG16__CONFIG7:
8198 /* ignored */
8199 register_name = "Config7";
8200 break;
8201 default:
8202 register_name = "Invalid config selector";
8203 goto cp0_unimplemented;
8205 break;
8206 case CP0_REGISTER_17:
8207 switch (sel) {
8208 case CP0_REG17__LLADDR:
8209 gen_helper_mtc0_lladdr(cpu_env, arg);
8210 register_name = "LLAddr";
8211 break;
8212 case CP0_REG17__MAAR:
8213 CP0_CHECK(ctx->mrp);
8214 gen_helper_mtc0_maar(cpu_env, arg);
8215 register_name = "MAAR";
8216 break;
8217 case CP0_REG17__MAARI:
8218 CP0_CHECK(ctx->mrp);
8219 gen_helper_mtc0_maari(cpu_env, arg);
8220 register_name = "MAARI";
8221 break;
8222 default:
8223 goto cp0_unimplemented;
8225 break;
8226 case CP0_REGISTER_18:
8227 switch (sel) {
8228 case CP0_REG18__WATCHLO0:
8229 case CP0_REG18__WATCHLO1:
8230 case CP0_REG18__WATCHLO2:
8231 case CP0_REG18__WATCHLO3:
8232 case CP0_REG18__WATCHLO4:
8233 case CP0_REG18__WATCHLO5:
8234 case CP0_REG18__WATCHLO6:
8235 case CP0_REG18__WATCHLO7:
8236 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8237 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8238 register_name = "WatchLo";
8239 break;
8240 default:
8241 goto cp0_unimplemented;
8243 break;
8244 case CP0_REGISTER_19:
8245 switch (sel) {
8246 case CP0_REG19__WATCHHI0:
8247 case CP0_REG19__WATCHHI1:
8248 case CP0_REG19__WATCHHI2:
8249 case CP0_REG19__WATCHHI3:
8250 case CP0_REG19__WATCHHI4:
8251 case CP0_REG19__WATCHHI5:
8252 case CP0_REG19__WATCHHI6:
8253 case CP0_REG19__WATCHHI7:
8254 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8255 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8256 register_name = "WatchHi";
8257 break;
8258 default:
8259 goto cp0_unimplemented;
8261 break;
8262 case CP0_REGISTER_20:
8263 switch (sel) {
8264 case CP0_REG20__XCONTEXT:
8265 #if defined(TARGET_MIPS64)
8266 check_insn(ctx, ISA_MIPS3);
8267 gen_helper_mtc0_xcontext(cpu_env, arg);
8268 register_name = "XContext";
8269 break;
8270 #endif
8271 default:
8272 goto cp0_unimplemented;
8274 break;
8275 case CP0_REGISTER_21:
8276 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8277 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8278 switch (sel) {
8279 case 0:
8280 gen_helper_mtc0_framemask(cpu_env, arg);
8281 register_name = "Framemask";
8282 break;
8283 default:
8284 goto cp0_unimplemented;
8286 break;
8287 case CP0_REGISTER_22:
8288 /* ignored */
8289 register_name = "Diagnostic"; /* implementation dependent */
8290 break;
8291 case CP0_REGISTER_23:
8292 switch (sel) {
8293 case CP0_REG23__DEBUG:
8294 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8295 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8296 gen_save_pc(ctx->base.pc_next + 4);
8297 ctx->base.is_jmp = DISAS_EXIT;
8298 register_name = "Debug";
8299 break;
8300 case CP0_REG23__TRACECONTROL:
8301 /* PDtrace support */
8302 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8303 register_name = "TraceControl";
8304 /* Stop translation as we may have switched the execution mode */
8305 ctx->base.is_jmp = DISAS_STOP;
8306 goto cp0_unimplemented;
8307 case CP0_REG23__TRACECONTROL2:
8308 /* PDtrace support */
8309 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8310 register_name = "TraceControl2";
8311 /* Stop translation as we may have switched the execution mode */
8312 ctx->base.is_jmp = DISAS_STOP;
8313 goto cp0_unimplemented;
8314 case CP0_REG23__USERTRACEDATA1:
8315 /* Stop translation as we may have switched the execution mode */
8316 ctx->base.is_jmp = DISAS_STOP;
8317 /* PDtrace support */
8318 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8319 register_name = "UserTraceData";
8320 /* Stop translation as we may have switched the execution mode */
8321 ctx->base.is_jmp = DISAS_STOP;
8322 goto cp0_unimplemented;
8323 case CP0_REG23__TRACEIBPC:
8324 /* PDtrace support */
8325 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8326 /* Stop translation as we may have switched the execution mode */
8327 ctx->base.is_jmp = DISAS_STOP;
8328 register_name = "TraceIBPC";
8329 goto cp0_unimplemented;
8330 case CP0_REG23__TRACEDBPC:
8331 /* PDtrace support */
8332 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8333 /* Stop translation as we may have switched the execution mode */
8334 ctx->base.is_jmp = DISAS_STOP;
8335 register_name = "TraceDBPC";
8336 goto cp0_unimplemented;
8337 default:
8338 goto cp0_unimplemented;
8340 break;
8341 case CP0_REGISTER_24:
8342 switch (sel) {
8343 case CP0_REG24__DEPC:
8344 /* EJTAG support */
8345 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8346 register_name = "DEPC";
8347 break;
8348 default:
8349 goto cp0_unimplemented;
8351 break;
8352 case CP0_REGISTER_25:
8353 switch (sel) {
8354 case CP0_REG25__PERFCTL0:
8355 gen_helper_mtc0_performance0(cpu_env, arg);
8356 register_name = "Performance0";
8357 break;
8358 case CP0_REG25__PERFCNT0:
8359 /* gen_helper_mtc0_performance1(arg); */
8360 register_name = "Performance1";
8361 goto cp0_unimplemented;
8362 case CP0_REG25__PERFCTL1:
8363 /* gen_helper_mtc0_performance2(arg); */
8364 register_name = "Performance2";
8365 goto cp0_unimplemented;
8366 case CP0_REG25__PERFCNT1:
8367 /* gen_helper_mtc0_performance3(arg); */
8368 register_name = "Performance3";
8369 goto cp0_unimplemented;
8370 case CP0_REG25__PERFCTL2:
8371 /* gen_helper_mtc0_performance4(arg); */
8372 register_name = "Performance4";
8373 goto cp0_unimplemented;
8374 case CP0_REG25__PERFCNT2:
8375 /* gen_helper_mtc0_performance5(arg); */
8376 register_name = "Performance5";
8377 goto cp0_unimplemented;
8378 case CP0_REG25__PERFCTL3:
8379 /* gen_helper_mtc0_performance6(arg); */
8380 register_name = "Performance6";
8381 goto cp0_unimplemented;
8382 case CP0_REG25__PERFCNT3:
8383 /* gen_helper_mtc0_performance7(arg); */
8384 register_name = "Performance7";
8385 goto cp0_unimplemented;
8386 default:
8387 goto cp0_unimplemented;
8389 break;
8390 case CP0_REGISTER_26:
8391 switch (sel) {
8392 case CP0_REG26__ERRCTL:
8393 gen_helper_mtc0_errctl(cpu_env, arg);
8394 ctx->base.is_jmp = DISAS_STOP;
8395 register_name = "ErrCtl";
8396 break;
8397 default:
8398 goto cp0_unimplemented;
8400 break;
8401 case CP0_REGISTER_27:
8402 switch (sel) {
8403 case CP0_REG27__CACHERR:
8404 /* ignored */
8405 register_name = "CacheErr";
8406 break;
8407 default:
8408 goto cp0_unimplemented;
8410 break;
8411 case CP0_REGISTER_28:
8412 switch (sel) {
8413 case CP0_REG28__TAGLO:
8414 case CP0_REG28__TAGLO1:
8415 case CP0_REG28__TAGLO2:
8416 case CP0_REG28__TAGLO3:
8417 gen_helper_mtc0_taglo(cpu_env, arg);
8418 register_name = "TagLo";
8419 break;
8420 case CP0_REG28__DATALO:
8421 case CP0_REG28__DATALO1:
8422 case CP0_REG28__DATALO2:
8423 case CP0_REG28__DATALO3:
8424 gen_helper_mtc0_datalo(cpu_env, arg);
8425 register_name = "DataLo";
8426 break;
8427 default:
8428 goto cp0_unimplemented;
8430 break;
8431 case CP0_REGISTER_29:
8432 switch (sel) {
8433 case CP0_REG29__TAGHI:
8434 case CP0_REG29__TAGHI1:
8435 case CP0_REG29__TAGHI2:
8436 case CP0_REG29__TAGHI3:
8437 gen_helper_mtc0_taghi(cpu_env, arg);
8438 register_name = "TagHi";
8439 break;
8440 case CP0_REG29__DATAHI:
8441 case CP0_REG29__DATAHI1:
8442 case CP0_REG29__DATAHI2:
8443 case CP0_REG29__DATAHI3:
8444 gen_helper_mtc0_datahi(cpu_env, arg);
8445 register_name = "DataHi";
8446 break;
8447 default:
8448 register_name = "invalid sel";
8449 goto cp0_unimplemented;
8451 break;
8452 case CP0_REGISTER_30:
8453 switch (sel) {
8454 case CP0_REG30__ERROREPC:
8455 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8456 register_name = "ErrorEPC";
8457 break;
8458 default:
8459 goto cp0_unimplemented;
8461 break;
8462 case CP0_REGISTER_31:
8463 switch (sel) {
8464 case CP0_REG31__DESAVE:
8465 /* EJTAG support */
8466 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8467 register_name = "DESAVE";
8468 break;
8469 case CP0_REG31__KSCRATCH1:
8470 case CP0_REG31__KSCRATCH2:
8471 case CP0_REG31__KSCRATCH3:
8472 case CP0_REG31__KSCRATCH4:
8473 case CP0_REG31__KSCRATCH5:
8474 case CP0_REG31__KSCRATCH6:
8475 CP0_CHECK(ctx->kscrexist & (1 << sel));
8476 tcg_gen_st_tl(arg, cpu_env,
8477 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8478 register_name = "KScratch";
8479 break;
8480 default:
8481 goto cp0_unimplemented;
8483 break;
8484 default:
8485 goto cp0_unimplemented;
8487 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8489 /* For simplicity assume that all writes can cause interrupts. */
8490 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8492 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8493 * translated code to check for pending interrupts.
8495 gen_save_pc(ctx->base.pc_next + 4);
8496 ctx->base.is_jmp = DISAS_EXIT;
8498 return;
8500 cp0_unimplemented:
8501 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8502 register_name, reg, sel);
8505 #if defined(TARGET_MIPS64)
8506 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8508 const char *register_name = "invalid";
8510 if (sel != 0) {
8511 check_insn(ctx, ISA_MIPS64);
8514 switch (reg) {
8515 case CP0_REGISTER_00:
8516 switch (sel) {
8517 case CP0_REG00__INDEX:
8518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8519 register_name = "Index";
8520 break;
8521 case CP0_REG00__MVPCONTROL:
8522 CP0_CHECK(ctx->insn_flags & ASE_MT);
8523 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8524 register_name = "MVPControl";
8525 break;
8526 case CP0_REG00__MVPCONF0:
8527 CP0_CHECK(ctx->insn_flags & ASE_MT);
8528 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8529 register_name = "MVPConf0";
8530 break;
8531 case CP0_REG00__MVPCONF1:
8532 CP0_CHECK(ctx->insn_flags & ASE_MT);
8533 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8534 register_name = "MVPConf1";
8535 break;
8536 case CP0_REG00__VPCONTROL:
8537 CP0_CHECK(ctx->vp);
8538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8539 register_name = "VPControl";
8540 break;
8541 default:
8542 goto cp0_unimplemented;
8544 break;
8545 case CP0_REGISTER_01:
8546 switch (sel) {
8547 case CP0_REG01__RANDOM:
8548 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8549 gen_helper_mfc0_random(arg, cpu_env);
8550 register_name = "Random";
8551 break;
8552 case CP0_REG01__VPECONTROL:
8553 CP0_CHECK(ctx->insn_flags & ASE_MT);
8554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8555 register_name = "VPEControl";
8556 break;
8557 case CP0_REG01__VPECONF0:
8558 CP0_CHECK(ctx->insn_flags & ASE_MT);
8559 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8560 register_name = "VPEConf0";
8561 break;
8562 case CP0_REG01__VPECONF1:
8563 CP0_CHECK(ctx->insn_flags & ASE_MT);
8564 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8565 register_name = "VPEConf1";
8566 break;
8567 case CP0_REG01__YQMASK:
8568 CP0_CHECK(ctx->insn_flags & ASE_MT);
8569 tcg_gen_ld_tl(arg, cpu_env,
8570 offsetof(CPUMIPSState, CP0_YQMask));
8571 register_name = "YQMask";
8572 break;
8573 case CP0_REG01__VPESCHEDULE:
8574 CP0_CHECK(ctx->insn_flags & ASE_MT);
8575 tcg_gen_ld_tl(arg, cpu_env,
8576 offsetof(CPUMIPSState, CP0_VPESchedule));
8577 register_name = "VPESchedule";
8578 break;
8579 case CP0_REG01__VPESCHEFBACK:
8580 CP0_CHECK(ctx->insn_flags & ASE_MT);
8581 tcg_gen_ld_tl(arg, cpu_env,
8582 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8583 register_name = "VPEScheFBack";
8584 break;
8585 case CP0_REG01__VPEOPT:
8586 CP0_CHECK(ctx->insn_flags & ASE_MT);
8587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8588 register_name = "VPEOpt";
8589 break;
8590 default:
8591 goto cp0_unimplemented;
8593 break;
8594 case CP0_REGISTER_02:
8595 switch (sel) {
8596 case CP0_REG02__ENTRYLO0:
8597 tcg_gen_ld_tl(arg, cpu_env,
8598 offsetof(CPUMIPSState, CP0_EntryLo0));
8599 register_name = "EntryLo0";
8600 break;
8601 case CP0_REG02__TCSTATUS:
8602 CP0_CHECK(ctx->insn_flags & ASE_MT);
8603 gen_helper_mfc0_tcstatus(arg, cpu_env);
8604 register_name = "TCStatus";
8605 break;
8606 case CP0_REG02__TCBIND:
8607 CP0_CHECK(ctx->insn_flags & ASE_MT);
8608 gen_helper_mfc0_tcbind(arg, cpu_env);
8609 register_name = "TCBind";
8610 break;
8611 case CP0_REG02__TCRESTART:
8612 CP0_CHECK(ctx->insn_flags & ASE_MT);
8613 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8614 register_name = "TCRestart";
8615 break;
8616 case CP0_REG02__TCHALT:
8617 CP0_CHECK(ctx->insn_flags & ASE_MT);
8618 gen_helper_dmfc0_tchalt(arg, cpu_env);
8619 register_name = "TCHalt";
8620 break;
8621 case CP0_REG02__TCCONTEXT:
8622 CP0_CHECK(ctx->insn_flags & ASE_MT);
8623 gen_helper_dmfc0_tccontext(arg, cpu_env);
8624 register_name = "TCContext";
8625 break;
8626 case CP0_REG02__TCSCHEDULE:
8627 CP0_CHECK(ctx->insn_flags & ASE_MT);
8628 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8629 register_name = "TCSchedule";
8630 break;
8631 case CP0_REG02__TCSCHEFBACK:
8632 CP0_CHECK(ctx->insn_flags & ASE_MT);
8633 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8634 register_name = "TCScheFBack";
8635 break;
8636 default:
8637 goto cp0_unimplemented;
8639 break;
8640 case CP0_REGISTER_03:
8641 switch (sel) {
8642 case CP0_REG03__ENTRYLO1:
8643 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8644 register_name = "EntryLo1";
8645 break;
8646 case CP0_REG03__GLOBALNUM:
8647 CP0_CHECK(ctx->vp);
8648 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8649 register_name = "GlobalNumber";
8650 break;
8651 default:
8652 goto cp0_unimplemented;
8654 break;
8655 case CP0_REGISTER_04:
8656 switch (sel) {
8657 case CP0_REG04__CONTEXT:
8658 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8659 register_name = "Context";
8660 break;
8661 case CP0_REG04__CONTEXTCONFIG:
8662 /* SmartMIPS ASE */
8663 /* gen_helper_dmfc0_contextconfig(arg); */
8664 register_name = "ContextConfig";
8665 goto cp0_unimplemented;
8666 case CP0_REG04__USERLOCAL:
8667 CP0_CHECK(ctx->ulri);
8668 tcg_gen_ld_tl(arg, cpu_env,
8669 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8670 register_name = "UserLocal";
8671 break;
8672 case CP0_REG04__MMID:
8673 CP0_CHECK(ctx->mi);
8674 gen_helper_mtc0_memorymapid(cpu_env, arg);
8675 register_name = "MMID";
8676 break;
8677 default:
8678 goto cp0_unimplemented;
8680 break;
8681 case CP0_REGISTER_05:
8682 switch (sel) {
8683 case CP0_REG05__PAGEMASK:
8684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8685 register_name = "PageMask";
8686 break;
8687 case CP0_REG05__PAGEGRAIN:
8688 check_insn(ctx, ISA_MIPS32R2);
8689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8690 register_name = "PageGrain";
8691 break;
8692 case CP0_REG05__SEGCTL0:
8693 CP0_CHECK(ctx->sc);
8694 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8695 register_name = "SegCtl0";
8696 break;
8697 case CP0_REG05__SEGCTL1:
8698 CP0_CHECK(ctx->sc);
8699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8700 register_name = "SegCtl1";
8701 break;
8702 case CP0_REG05__SEGCTL2:
8703 CP0_CHECK(ctx->sc);
8704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8705 register_name = "SegCtl2";
8706 break;
8707 case CP0_REG05__PWBASE:
8708 check_pw(ctx);
8709 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8710 register_name = "PWBase";
8711 break;
8712 case CP0_REG05__PWFIELD:
8713 check_pw(ctx);
8714 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8715 register_name = "PWField";
8716 break;
8717 case CP0_REG05__PWSIZE:
8718 check_pw(ctx);
8719 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8720 register_name = "PWSize";
8721 break;
8722 default:
8723 goto cp0_unimplemented;
8725 break;
8726 case CP0_REGISTER_06:
8727 switch (sel) {
8728 case CP0_REG06__WIRED:
8729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8730 register_name = "Wired";
8731 break;
8732 case CP0_REG06__SRSCONF0:
8733 check_insn(ctx, ISA_MIPS32R2);
8734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8735 register_name = "SRSConf0";
8736 break;
8737 case CP0_REG06__SRSCONF1:
8738 check_insn(ctx, ISA_MIPS32R2);
8739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8740 register_name = "SRSConf1";
8741 break;
8742 case CP0_REG06__SRSCONF2:
8743 check_insn(ctx, ISA_MIPS32R2);
8744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8745 register_name = "SRSConf2";
8746 break;
8747 case CP0_REG06__SRSCONF3:
8748 check_insn(ctx, ISA_MIPS32R2);
8749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8750 register_name = "SRSConf3";
8751 break;
8752 case CP0_REG06__SRSCONF4:
8753 check_insn(ctx, ISA_MIPS32R2);
8754 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8755 register_name = "SRSConf4";
8756 break;
8757 case CP0_REG06__PWCTL:
8758 check_pw(ctx);
8759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8760 register_name = "PWCtl";
8761 break;
8762 default:
8763 goto cp0_unimplemented;
8765 break;
8766 case CP0_REGISTER_07:
8767 switch (sel) {
8768 case CP0_REG07__HWRENA:
8769 check_insn(ctx, ISA_MIPS32R2);
8770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8771 register_name = "HWREna";
8772 break;
8773 default:
8774 goto cp0_unimplemented;
8776 break;
8777 case CP0_REGISTER_08:
8778 switch (sel) {
8779 case CP0_REG08__BADVADDR:
8780 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8781 register_name = "BadVAddr";
8782 break;
8783 case CP0_REG08__BADINSTR:
8784 CP0_CHECK(ctx->bi);
8785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8786 register_name = "BadInstr";
8787 break;
8788 case CP0_REG08__BADINSTRP:
8789 CP0_CHECK(ctx->bp);
8790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8791 register_name = "BadInstrP";
8792 break;
8793 case CP0_REG08__BADINSTRX:
8794 CP0_CHECK(ctx->bi);
8795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8796 tcg_gen_andi_tl(arg, arg, ~0xffff);
8797 register_name = "BadInstrX";
8798 break;
8799 default:
8800 goto cp0_unimplemented;
8802 break;
8803 case CP0_REGISTER_09:
8804 switch (sel) {
8805 case CP0_REG09__COUNT:
8806 /* Mark as an IO operation because we read the time. */
8807 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8808 gen_io_start();
8810 gen_helper_mfc0_count(arg, cpu_env);
8812 * Break the TB to be able to take timer interrupts immediately
8813 * after reading count. DISAS_STOP isn't sufficient, we need to
8814 * ensure we break completely out of translated code.
8816 gen_save_pc(ctx->base.pc_next + 4);
8817 ctx->base.is_jmp = DISAS_EXIT;
8818 register_name = "Count";
8819 break;
8820 case CP0_REG09__SAARI:
8821 CP0_CHECK(ctx->saar);
8822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8823 register_name = "SAARI";
8824 break;
8825 case CP0_REG09__SAAR:
8826 CP0_CHECK(ctx->saar);
8827 gen_helper_dmfc0_saar(arg, cpu_env);
8828 register_name = "SAAR";
8829 break;
8830 default:
8831 goto cp0_unimplemented;
8833 break;
8834 case CP0_REGISTER_10:
8835 switch (sel) {
8836 case CP0_REG10__ENTRYHI:
8837 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8838 register_name = "EntryHi";
8839 break;
8840 default:
8841 goto cp0_unimplemented;
8843 break;
8844 case CP0_REGISTER_11:
8845 switch (sel) {
8846 case CP0_REG11__COMPARE:
8847 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8848 register_name = "Compare";
8849 break;
8850 /* 6,7 are implementation dependent */
8851 default:
8852 goto cp0_unimplemented;
8854 break;
8855 case CP0_REGISTER_12:
8856 switch (sel) {
8857 case CP0_REG12__STATUS:
8858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8859 register_name = "Status";
8860 break;
8861 case CP0_REG12__INTCTL:
8862 check_insn(ctx, ISA_MIPS32R2);
8863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8864 register_name = "IntCtl";
8865 break;
8866 case CP0_REG12__SRSCTL:
8867 check_insn(ctx, ISA_MIPS32R2);
8868 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8869 register_name = "SRSCtl";
8870 break;
8871 case CP0_REG12__SRSMAP:
8872 check_insn(ctx, ISA_MIPS32R2);
8873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8874 register_name = "SRSMap";
8875 break;
8876 default:
8877 goto cp0_unimplemented;
8879 break;
8880 case CP0_REGISTER_13:
8881 switch (sel) {
8882 case CP0_REG13__CAUSE:
8883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8884 register_name = "Cause";
8885 break;
8886 default:
8887 goto cp0_unimplemented;
8889 break;
8890 case CP0_REGISTER_14:
8891 switch (sel) {
8892 case CP0_REG14__EPC:
8893 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8894 register_name = "EPC";
8895 break;
8896 default:
8897 goto cp0_unimplemented;
8899 break;
8900 case CP0_REGISTER_15:
8901 switch (sel) {
8902 case CP0_REG15__PRID:
8903 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8904 register_name = "PRid";
8905 break;
8906 case CP0_REG15__EBASE:
8907 check_insn(ctx, ISA_MIPS32R2);
8908 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8909 register_name = "EBase";
8910 break;
8911 case CP0_REG15__CMGCRBASE:
8912 check_insn(ctx, ISA_MIPS32R2);
8913 CP0_CHECK(ctx->cmgcr);
8914 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8915 register_name = "CMGCRBase";
8916 break;
8917 default:
8918 goto cp0_unimplemented;
8920 break;
8921 case CP0_REGISTER_16:
8922 switch (sel) {
8923 case CP0_REG16__CONFIG:
8924 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8925 register_name = "Config";
8926 break;
8927 case CP0_REG16__CONFIG1:
8928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8929 register_name = "Config1";
8930 break;
8931 case CP0_REG16__CONFIG2:
8932 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8933 register_name = "Config2";
8934 break;
8935 case CP0_REG16__CONFIG3:
8936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8937 register_name = "Config3";
8938 break;
8939 case CP0_REG16__CONFIG4:
8940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8941 register_name = "Config4";
8942 break;
8943 case CP0_REG16__CONFIG5:
8944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8945 register_name = "Config5";
8946 break;
8947 /* 6,7 are implementation dependent */
8948 case CP0_REG16__CONFIG6:
8949 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8950 register_name = "Config6";
8951 break;
8952 case CP0_REG16__CONFIG7:
8953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8954 register_name = "Config7";
8955 break;
8956 default:
8957 goto cp0_unimplemented;
8959 break;
8960 case CP0_REGISTER_17:
8961 switch (sel) {
8962 case CP0_REG17__LLADDR:
8963 gen_helper_dmfc0_lladdr(arg, cpu_env);
8964 register_name = "LLAddr";
8965 break;
8966 case CP0_REG17__MAAR:
8967 CP0_CHECK(ctx->mrp);
8968 gen_helper_dmfc0_maar(arg, cpu_env);
8969 register_name = "MAAR";
8970 break;
8971 case CP0_REG17__MAARI:
8972 CP0_CHECK(ctx->mrp);
8973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8974 register_name = "MAARI";
8975 break;
8976 default:
8977 goto cp0_unimplemented;
8979 break;
8980 case CP0_REGISTER_18:
8981 switch (sel) {
8982 case CP0_REG18__WATCHLO0:
8983 case CP0_REG18__WATCHLO1:
8984 case CP0_REG18__WATCHLO2:
8985 case CP0_REG18__WATCHLO3:
8986 case CP0_REG18__WATCHLO4:
8987 case CP0_REG18__WATCHLO5:
8988 case CP0_REG18__WATCHLO6:
8989 case CP0_REG18__WATCHLO7:
8990 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8991 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8992 register_name = "WatchLo";
8993 break;
8994 default:
8995 goto cp0_unimplemented;
8997 break;
8998 case CP0_REGISTER_19:
8999 switch (sel) {
9000 case CP0_REG19__WATCHHI0:
9001 case CP0_REG19__WATCHHI1:
9002 case CP0_REG19__WATCHHI2:
9003 case CP0_REG19__WATCHHI3:
9004 case CP0_REG19__WATCHHI4:
9005 case CP0_REG19__WATCHHI5:
9006 case CP0_REG19__WATCHHI6:
9007 case CP0_REG19__WATCHHI7:
9008 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9009 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9010 register_name = "WatchHi";
9011 break;
9012 default:
9013 goto cp0_unimplemented;
9015 break;
9016 case CP0_REGISTER_20:
9017 switch (sel) {
9018 case CP0_REG20__XCONTEXT:
9019 check_insn(ctx, ISA_MIPS3);
9020 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9021 register_name = "XContext";
9022 break;
9023 default:
9024 goto cp0_unimplemented;
9026 break;
9027 case CP0_REGISTER_21:
9028 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9029 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9030 switch (sel) {
9031 case 0:
9032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9033 register_name = "Framemask";
9034 break;
9035 default:
9036 goto cp0_unimplemented;
9038 break;
9039 case CP0_REGISTER_22:
9040 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9041 register_name = "'Diagnostic"; /* implementation dependent */
9042 break;
9043 case CP0_REGISTER_23:
9044 switch (sel) {
9045 case CP0_REG23__DEBUG:
9046 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9047 register_name = "Debug";
9048 break;
9049 case CP0_REG23__TRACECONTROL:
9050 /* PDtrace support */
9051 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9052 register_name = "TraceControl";
9053 goto cp0_unimplemented;
9054 case CP0_REG23__TRACECONTROL2:
9055 /* PDtrace support */
9056 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9057 register_name = "TraceControl2";
9058 goto cp0_unimplemented;
9059 case CP0_REG23__USERTRACEDATA1:
9060 /* PDtrace support */
9061 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9062 register_name = "UserTraceData1";
9063 goto cp0_unimplemented;
9064 case CP0_REG23__TRACEIBPC:
9065 /* PDtrace support */
9066 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9067 register_name = "TraceIBPC";
9068 goto cp0_unimplemented;
9069 case CP0_REG23__TRACEDBPC:
9070 /* PDtrace support */
9071 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9072 register_name = "TraceDBPC";
9073 goto cp0_unimplemented;
9074 default:
9075 goto cp0_unimplemented;
9077 break;
9078 case CP0_REGISTER_24:
9079 switch (sel) {
9080 case CP0_REG24__DEPC:
9081 /* EJTAG support */
9082 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9083 register_name = "DEPC";
9084 break;
9085 default:
9086 goto cp0_unimplemented;
9088 break;
9089 case CP0_REGISTER_25:
9090 switch (sel) {
9091 case CP0_REG25__PERFCTL0:
9092 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9093 register_name = "Performance0";
9094 break;
9095 case CP0_REG25__PERFCNT0:
9096 /* gen_helper_dmfc0_performance1(arg); */
9097 register_name = "Performance1";
9098 goto cp0_unimplemented;
9099 case CP0_REG25__PERFCTL1:
9100 /* gen_helper_dmfc0_performance2(arg); */
9101 register_name = "Performance2";
9102 goto cp0_unimplemented;
9103 case CP0_REG25__PERFCNT1:
9104 /* gen_helper_dmfc0_performance3(arg); */
9105 register_name = "Performance3";
9106 goto cp0_unimplemented;
9107 case CP0_REG25__PERFCTL2:
9108 /* gen_helper_dmfc0_performance4(arg); */
9109 register_name = "Performance4";
9110 goto cp0_unimplemented;
9111 case CP0_REG25__PERFCNT2:
9112 /* gen_helper_dmfc0_performance5(arg); */
9113 register_name = "Performance5";
9114 goto cp0_unimplemented;
9115 case CP0_REG25__PERFCTL3:
9116 /* gen_helper_dmfc0_performance6(arg); */
9117 register_name = "Performance6";
9118 goto cp0_unimplemented;
9119 case CP0_REG25__PERFCNT3:
9120 /* gen_helper_dmfc0_performance7(arg); */
9121 register_name = "Performance7";
9122 goto cp0_unimplemented;
9123 default:
9124 goto cp0_unimplemented;
9126 break;
9127 case CP0_REGISTER_26:
9128 switch (sel) {
9129 case CP0_REG26__ERRCTL:
9130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9131 register_name = "ErrCtl";
9132 break;
9133 default:
9134 goto cp0_unimplemented;
9136 break;
9137 case CP0_REGISTER_27:
9138 switch (sel) {
9139 /* ignored */
9140 case CP0_REG27__CACHERR:
9141 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9142 register_name = "CacheErr";
9143 break;
9144 default:
9145 goto cp0_unimplemented;
9147 break;
9148 case CP0_REGISTER_28:
9149 switch (sel) {
9150 case CP0_REG28__TAGLO:
9151 case CP0_REG28__TAGLO1:
9152 case CP0_REG28__TAGLO2:
9153 case CP0_REG28__TAGLO3:
9154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9155 register_name = "TagLo";
9156 break;
9157 case CP0_REG28__DATALO:
9158 case CP0_REG28__DATALO1:
9159 case CP0_REG28__DATALO2:
9160 case CP0_REG28__DATALO3:
9161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9162 register_name = "DataLo";
9163 break;
9164 default:
9165 goto cp0_unimplemented;
9167 break;
9168 case CP0_REGISTER_29:
9169 switch (sel) {
9170 case CP0_REG29__TAGHI:
9171 case CP0_REG29__TAGHI1:
9172 case CP0_REG29__TAGHI2:
9173 case CP0_REG29__TAGHI3:
9174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9175 register_name = "TagHi";
9176 break;
9177 case CP0_REG29__DATAHI:
9178 case CP0_REG29__DATAHI1:
9179 case CP0_REG29__DATAHI2:
9180 case CP0_REG29__DATAHI3:
9181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9182 register_name = "DataHi";
9183 break;
9184 default:
9185 goto cp0_unimplemented;
9187 break;
9188 case CP0_REGISTER_30:
9189 switch (sel) {
9190 case CP0_REG30__ERROREPC:
9191 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9192 register_name = "ErrorEPC";
9193 break;
9194 default:
9195 goto cp0_unimplemented;
9197 break;
9198 case CP0_REGISTER_31:
9199 switch (sel) {
9200 case CP0_REG31__DESAVE:
9201 /* EJTAG support */
9202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9203 register_name = "DESAVE";
9204 break;
9205 case CP0_REG31__KSCRATCH1:
9206 case CP0_REG31__KSCRATCH2:
9207 case CP0_REG31__KSCRATCH3:
9208 case CP0_REG31__KSCRATCH4:
9209 case CP0_REG31__KSCRATCH5:
9210 case CP0_REG31__KSCRATCH6:
9211 CP0_CHECK(ctx->kscrexist & (1 << sel));
9212 tcg_gen_ld_tl(arg, cpu_env,
9213 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9214 register_name = "KScratch";
9215 break;
9216 default:
9217 goto cp0_unimplemented;
9219 break;
9220 default:
9221 goto cp0_unimplemented;
9223 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9224 return;
9226 cp0_unimplemented:
9227 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9228 register_name, reg, sel);
9229 gen_mfc0_unimplemented(ctx, arg);
9232 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9234 const char *register_name = "invalid";
9236 if (sel != 0) {
9237 check_insn(ctx, ISA_MIPS64);
9240 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9241 gen_io_start();
9244 switch (reg) {
9245 case CP0_REGISTER_00:
9246 switch (sel) {
9247 case CP0_REG00__INDEX:
9248 gen_helper_mtc0_index(cpu_env, arg);
9249 register_name = "Index";
9250 break;
9251 case CP0_REG00__MVPCONTROL:
9252 CP0_CHECK(ctx->insn_flags & ASE_MT);
9253 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9254 register_name = "MVPControl";
9255 break;
9256 case CP0_REG00__MVPCONF0:
9257 CP0_CHECK(ctx->insn_flags & ASE_MT);
9258 /* ignored */
9259 register_name = "MVPConf0";
9260 break;
9261 case CP0_REG00__MVPCONF1:
9262 CP0_CHECK(ctx->insn_flags & ASE_MT);
9263 /* ignored */
9264 register_name = "MVPConf1";
9265 break;
9266 case CP0_REG00__VPCONTROL:
9267 CP0_CHECK(ctx->vp);
9268 /* ignored */
9269 register_name = "VPControl";
9270 break;
9271 default:
9272 goto cp0_unimplemented;
9274 break;
9275 case CP0_REGISTER_01:
9276 switch (sel) {
9277 case CP0_REG01__RANDOM:
9278 /* ignored */
9279 register_name = "Random";
9280 break;
9281 case CP0_REG01__VPECONTROL:
9282 CP0_CHECK(ctx->insn_flags & ASE_MT);
9283 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9284 register_name = "VPEControl";
9285 break;
9286 case CP0_REG01__VPECONF0:
9287 CP0_CHECK(ctx->insn_flags & ASE_MT);
9288 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9289 register_name = "VPEConf0";
9290 break;
9291 case CP0_REG01__VPECONF1:
9292 CP0_CHECK(ctx->insn_flags & ASE_MT);
9293 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9294 register_name = "VPEConf1";
9295 break;
9296 case CP0_REG01__YQMASK:
9297 CP0_CHECK(ctx->insn_flags & ASE_MT);
9298 gen_helper_mtc0_yqmask(cpu_env, arg);
9299 register_name = "YQMask";
9300 break;
9301 case CP0_REG01__VPESCHEDULE:
9302 CP0_CHECK(ctx->insn_flags & ASE_MT);
9303 tcg_gen_st_tl(arg, cpu_env,
9304 offsetof(CPUMIPSState, CP0_VPESchedule));
9305 register_name = "VPESchedule";
9306 break;
9307 case CP0_REG01__VPESCHEFBACK:
9308 CP0_CHECK(ctx->insn_flags & ASE_MT);
9309 tcg_gen_st_tl(arg, cpu_env,
9310 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9311 register_name = "VPEScheFBack";
9312 break;
9313 case CP0_REG01__VPEOPT:
9314 CP0_CHECK(ctx->insn_flags & ASE_MT);
9315 gen_helper_mtc0_vpeopt(cpu_env, arg);
9316 register_name = "VPEOpt";
9317 break;
9318 default:
9319 goto cp0_unimplemented;
9321 break;
9322 case CP0_REGISTER_02:
9323 switch (sel) {
9324 case CP0_REG02__ENTRYLO0:
9325 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9326 register_name = "EntryLo0";
9327 break;
9328 case CP0_REG02__TCSTATUS:
9329 CP0_CHECK(ctx->insn_flags & ASE_MT);
9330 gen_helper_mtc0_tcstatus(cpu_env, arg);
9331 register_name = "TCStatus";
9332 break;
9333 case CP0_REG02__TCBIND:
9334 CP0_CHECK(ctx->insn_flags & ASE_MT);
9335 gen_helper_mtc0_tcbind(cpu_env, arg);
9336 register_name = "TCBind";
9337 break;
9338 case CP0_REG02__TCRESTART:
9339 CP0_CHECK(ctx->insn_flags & ASE_MT);
9340 gen_helper_mtc0_tcrestart(cpu_env, arg);
9341 register_name = "TCRestart";
9342 break;
9343 case CP0_REG02__TCHALT:
9344 CP0_CHECK(ctx->insn_flags & ASE_MT);
9345 gen_helper_mtc0_tchalt(cpu_env, arg);
9346 register_name = "TCHalt";
9347 break;
9348 case CP0_REG02__TCCONTEXT:
9349 CP0_CHECK(ctx->insn_flags & ASE_MT);
9350 gen_helper_mtc0_tccontext(cpu_env, arg);
9351 register_name = "TCContext";
9352 break;
9353 case CP0_REG02__TCSCHEDULE:
9354 CP0_CHECK(ctx->insn_flags & ASE_MT);
9355 gen_helper_mtc0_tcschedule(cpu_env, arg);
9356 register_name = "TCSchedule";
9357 break;
9358 case CP0_REG02__TCSCHEFBACK:
9359 CP0_CHECK(ctx->insn_flags & ASE_MT);
9360 gen_helper_mtc0_tcschefback(cpu_env, arg);
9361 register_name = "TCScheFBack";
9362 break;
9363 default:
9364 goto cp0_unimplemented;
9366 break;
9367 case CP0_REGISTER_03:
9368 switch (sel) {
9369 case CP0_REG03__ENTRYLO1:
9370 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9371 register_name = "EntryLo1";
9372 break;
9373 case CP0_REG03__GLOBALNUM:
9374 CP0_CHECK(ctx->vp);
9375 /* ignored */
9376 register_name = "GlobalNumber";
9377 break;
9378 default:
9379 goto cp0_unimplemented;
9381 break;
9382 case CP0_REGISTER_04:
9383 switch (sel) {
9384 case CP0_REG04__CONTEXT:
9385 gen_helper_mtc0_context(cpu_env, arg);
9386 register_name = "Context";
9387 break;
9388 case CP0_REG04__CONTEXTCONFIG:
9389 /* SmartMIPS ASE */
9390 /* gen_helper_dmtc0_contextconfig(arg); */
9391 register_name = "ContextConfig";
9392 goto cp0_unimplemented;
9393 case CP0_REG04__USERLOCAL:
9394 CP0_CHECK(ctx->ulri);
9395 tcg_gen_st_tl(arg, cpu_env,
9396 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9397 register_name = "UserLocal";
9398 break;
9399 case CP0_REG04__MMID:
9400 CP0_CHECK(ctx->mi);
9401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9402 register_name = "MMID";
9403 break;
9404 default:
9405 goto cp0_unimplemented;
9407 break;
9408 case CP0_REGISTER_05:
9409 switch (sel) {
9410 case CP0_REG05__PAGEMASK:
9411 gen_helper_mtc0_pagemask(cpu_env, arg);
9412 register_name = "PageMask";
9413 break;
9414 case CP0_REG05__PAGEGRAIN:
9415 check_insn(ctx, ISA_MIPS32R2);
9416 gen_helper_mtc0_pagegrain(cpu_env, arg);
9417 register_name = "PageGrain";
9418 break;
9419 case CP0_REG05__SEGCTL0:
9420 CP0_CHECK(ctx->sc);
9421 gen_helper_mtc0_segctl0(cpu_env, arg);
9422 register_name = "SegCtl0";
9423 break;
9424 case CP0_REG05__SEGCTL1:
9425 CP0_CHECK(ctx->sc);
9426 gen_helper_mtc0_segctl1(cpu_env, arg);
9427 register_name = "SegCtl1";
9428 break;
9429 case CP0_REG05__SEGCTL2:
9430 CP0_CHECK(ctx->sc);
9431 gen_helper_mtc0_segctl2(cpu_env, arg);
9432 register_name = "SegCtl2";
9433 break;
9434 case CP0_REG05__PWBASE:
9435 check_pw(ctx);
9436 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9437 register_name = "PWBase";
9438 break;
9439 case CP0_REG05__PWFIELD:
9440 check_pw(ctx);
9441 gen_helper_mtc0_pwfield(cpu_env, arg);
9442 register_name = "PWField";
9443 break;
9444 case CP0_REG05__PWSIZE:
9445 check_pw(ctx);
9446 gen_helper_mtc0_pwsize(cpu_env, arg);
9447 register_name = "PWSize";
9448 break;
9449 default:
9450 goto cp0_unimplemented;
9452 break;
9453 case CP0_REGISTER_06:
9454 switch (sel) {
9455 case CP0_REG06__WIRED:
9456 gen_helper_mtc0_wired(cpu_env, arg);
9457 register_name = "Wired";
9458 break;
9459 case CP0_REG06__SRSCONF0:
9460 check_insn(ctx, ISA_MIPS32R2);
9461 gen_helper_mtc0_srsconf0(cpu_env, arg);
9462 register_name = "SRSConf0";
9463 break;
9464 case CP0_REG06__SRSCONF1:
9465 check_insn(ctx, ISA_MIPS32R2);
9466 gen_helper_mtc0_srsconf1(cpu_env, arg);
9467 register_name = "SRSConf1";
9468 break;
9469 case CP0_REG06__SRSCONF2:
9470 check_insn(ctx, ISA_MIPS32R2);
9471 gen_helper_mtc0_srsconf2(cpu_env, arg);
9472 register_name = "SRSConf2";
9473 break;
9474 case CP0_REG06__SRSCONF3:
9475 check_insn(ctx, ISA_MIPS32R2);
9476 gen_helper_mtc0_srsconf3(cpu_env, arg);
9477 register_name = "SRSConf3";
9478 break;
9479 case CP0_REG06__SRSCONF4:
9480 check_insn(ctx, ISA_MIPS32R2);
9481 gen_helper_mtc0_srsconf4(cpu_env, arg);
9482 register_name = "SRSConf4";
9483 break;
9484 case CP0_REG06__PWCTL:
9485 check_pw(ctx);
9486 gen_helper_mtc0_pwctl(cpu_env, arg);
9487 register_name = "PWCtl";
9488 break;
9489 default:
9490 goto cp0_unimplemented;
9492 break;
9493 case CP0_REGISTER_07:
9494 switch (sel) {
9495 case CP0_REG07__HWRENA:
9496 check_insn(ctx, ISA_MIPS32R2);
9497 gen_helper_mtc0_hwrena(cpu_env, arg);
9498 ctx->base.is_jmp = DISAS_STOP;
9499 register_name = "HWREna";
9500 break;
9501 default:
9502 goto cp0_unimplemented;
9504 break;
9505 case CP0_REGISTER_08:
9506 switch (sel) {
9507 case CP0_REG08__BADVADDR:
9508 /* ignored */
9509 register_name = "BadVAddr";
9510 break;
9511 case CP0_REG08__BADINSTR:
9512 /* ignored */
9513 register_name = "BadInstr";
9514 break;
9515 case CP0_REG08__BADINSTRP:
9516 /* ignored */
9517 register_name = "BadInstrP";
9518 break;
9519 case CP0_REG08__BADINSTRX:
9520 /* ignored */
9521 register_name = "BadInstrX";
9522 break;
9523 default:
9524 goto cp0_unimplemented;
9526 break;
9527 case CP0_REGISTER_09:
9528 switch (sel) {
9529 case CP0_REG09__COUNT:
9530 gen_helper_mtc0_count(cpu_env, arg);
9531 register_name = "Count";
9532 break;
9533 case CP0_REG09__SAARI:
9534 CP0_CHECK(ctx->saar);
9535 gen_helper_mtc0_saari(cpu_env, arg);
9536 register_name = "SAARI";
9537 break;
9538 case CP0_REG09__SAAR:
9539 CP0_CHECK(ctx->saar);
9540 gen_helper_mtc0_saar(cpu_env, arg);
9541 register_name = "SAAR";
9542 break;
9543 default:
9544 goto cp0_unimplemented;
9546 /* Stop translation as we may have switched the execution mode */
9547 ctx->base.is_jmp = DISAS_STOP;
9548 break;
9549 case CP0_REGISTER_10:
9550 switch (sel) {
9551 case CP0_REG10__ENTRYHI:
9552 gen_helper_mtc0_entryhi(cpu_env, arg);
9553 register_name = "EntryHi";
9554 break;
9555 default:
9556 goto cp0_unimplemented;
9558 break;
9559 case CP0_REGISTER_11:
9560 switch (sel) {
9561 case CP0_REG11__COMPARE:
9562 gen_helper_mtc0_compare(cpu_env, arg);
9563 register_name = "Compare";
9564 break;
9565 /* 6,7 are implementation dependent */
9566 default:
9567 goto cp0_unimplemented;
9569 /* Stop translation as we may have switched the execution mode */
9570 ctx->base.is_jmp = DISAS_STOP;
9571 break;
9572 case CP0_REGISTER_12:
9573 switch (sel) {
9574 case CP0_REG12__STATUS:
9575 save_cpu_state(ctx, 1);
9576 gen_helper_mtc0_status(cpu_env, arg);
9577 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9578 gen_save_pc(ctx->base.pc_next + 4);
9579 ctx->base.is_jmp = DISAS_EXIT;
9580 register_name = "Status";
9581 break;
9582 case CP0_REG12__INTCTL:
9583 check_insn(ctx, ISA_MIPS32R2);
9584 gen_helper_mtc0_intctl(cpu_env, arg);
9585 /* Stop translation as we may have switched the execution mode */
9586 ctx->base.is_jmp = DISAS_STOP;
9587 register_name = "IntCtl";
9588 break;
9589 case CP0_REG12__SRSCTL:
9590 check_insn(ctx, ISA_MIPS32R2);
9591 gen_helper_mtc0_srsctl(cpu_env, arg);
9592 /* Stop translation as we may have switched the execution mode */
9593 ctx->base.is_jmp = DISAS_STOP;
9594 register_name = "SRSCtl";
9595 break;
9596 case CP0_REG12__SRSMAP:
9597 check_insn(ctx, ISA_MIPS32R2);
9598 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9599 /* Stop translation as we may have switched the execution mode */
9600 ctx->base.is_jmp = DISAS_STOP;
9601 register_name = "SRSMap";
9602 break;
9603 default:
9604 goto cp0_unimplemented;
9606 break;
9607 case CP0_REGISTER_13:
9608 switch (sel) {
9609 case CP0_REG13__CAUSE:
9610 save_cpu_state(ctx, 1);
9611 gen_helper_mtc0_cause(cpu_env, arg);
9613 * Stop translation as we may have triggered an interrupt.
9614 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9615 * translated code to check for pending interrupts.
9617 gen_save_pc(ctx->base.pc_next + 4);
9618 ctx->base.is_jmp = DISAS_EXIT;
9619 register_name = "Cause";
9620 break;
9621 default:
9622 goto cp0_unimplemented;
9624 break;
9625 case CP0_REGISTER_14:
9626 switch (sel) {
9627 case CP0_REG14__EPC:
9628 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9629 register_name = "EPC";
9630 break;
9631 default:
9632 goto cp0_unimplemented;
9634 break;
9635 case CP0_REGISTER_15:
9636 switch (sel) {
9637 case CP0_REG15__PRID:
9638 /* ignored */
9639 register_name = "PRid";
9640 break;
9641 case CP0_REG15__EBASE:
9642 check_insn(ctx, ISA_MIPS32R2);
9643 gen_helper_mtc0_ebase(cpu_env, arg);
9644 register_name = "EBase";
9645 break;
9646 default:
9647 goto cp0_unimplemented;
9649 break;
9650 case CP0_REGISTER_16:
9651 switch (sel) {
9652 case CP0_REG16__CONFIG:
9653 gen_helper_mtc0_config0(cpu_env, arg);
9654 register_name = "Config";
9655 /* Stop translation as we may have switched the execution mode */
9656 ctx->base.is_jmp = DISAS_STOP;
9657 break;
9658 case CP0_REG16__CONFIG1:
9659 /* ignored, read only */
9660 register_name = "Config1";
9661 break;
9662 case CP0_REG16__CONFIG2:
9663 gen_helper_mtc0_config2(cpu_env, arg);
9664 register_name = "Config2";
9665 /* Stop translation as we may have switched the execution mode */
9666 ctx->base.is_jmp = DISAS_STOP;
9667 break;
9668 case CP0_REG16__CONFIG3:
9669 gen_helper_mtc0_config3(cpu_env, arg);
9670 register_name = "Config3";
9671 /* Stop translation as we may have switched the execution mode */
9672 ctx->base.is_jmp = DISAS_STOP;
9673 break;
9674 case CP0_REG16__CONFIG4:
9675 /* currently ignored */
9676 register_name = "Config4";
9677 break;
9678 case CP0_REG16__CONFIG5:
9679 gen_helper_mtc0_config5(cpu_env, arg);
9680 register_name = "Config5";
9681 /* Stop translation as we may have switched the execution mode */
9682 ctx->base.is_jmp = DISAS_STOP;
9683 break;
9684 /* 6,7 are implementation dependent */
9685 default:
9686 register_name = "Invalid config selector";
9687 goto cp0_unimplemented;
9689 break;
9690 case CP0_REGISTER_17:
9691 switch (sel) {
9692 case CP0_REG17__LLADDR:
9693 gen_helper_mtc0_lladdr(cpu_env, arg);
9694 register_name = "LLAddr";
9695 break;
9696 case CP0_REG17__MAAR:
9697 CP0_CHECK(ctx->mrp);
9698 gen_helper_mtc0_maar(cpu_env, arg);
9699 register_name = "MAAR";
9700 break;
9701 case CP0_REG17__MAARI:
9702 CP0_CHECK(ctx->mrp);
9703 gen_helper_mtc0_maari(cpu_env, arg);
9704 register_name = "MAARI";
9705 break;
9706 default:
9707 goto cp0_unimplemented;
9709 break;
9710 case CP0_REGISTER_18:
9711 switch (sel) {
9712 case CP0_REG18__WATCHLO0:
9713 case CP0_REG18__WATCHLO1:
9714 case CP0_REG18__WATCHLO2:
9715 case CP0_REG18__WATCHLO3:
9716 case CP0_REG18__WATCHLO4:
9717 case CP0_REG18__WATCHLO5:
9718 case CP0_REG18__WATCHLO6:
9719 case CP0_REG18__WATCHLO7:
9720 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9721 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9722 register_name = "WatchLo";
9723 break;
9724 default:
9725 goto cp0_unimplemented;
9727 break;
9728 case CP0_REGISTER_19:
9729 switch (sel) {
9730 case CP0_REG19__WATCHHI0:
9731 case CP0_REG19__WATCHHI1:
9732 case CP0_REG19__WATCHHI2:
9733 case CP0_REG19__WATCHHI3:
9734 case CP0_REG19__WATCHHI4:
9735 case CP0_REG19__WATCHHI5:
9736 case CP0_REG19__WATCHHI6:
9737 case CP0_REG19__WATCHHI7:
9738 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9739 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9740 register_name = "WatchHi";
9741 break;
9742 default:
9743 goto cp0_unimplemented;
9745 break;
9746 case CP0_REGISTER_20:
9747 switch (sel) {
9748 case CP0_REG20__XCONTEXT:
9749 check_insn(ctx, ISA_MIPS3);
9750 gen_helper_mtc0_xcontext(cpu_env, arg);
9751 register_name = "XContext";
9752 break;
9753 default:
9754 goto cp0_unimplemented;
9756 break;
9757 case CP0_REGISTER_21:
9758 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9759 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9760 switch (sel) {
9761 case 0:
9762 gen_helper_mtc0_framemask(cpu_env, arg);
9763 register_name = "Framemask";
9764 break;
9765 default:
9766 goto cp0_unimplemented;
9768 break;
9769 case CP0_REGISTER_22:
9770 /* ignored */
9771 register_name = "Diagnostic"; /* implementation dependent */
9772 break;
9773 case CP0_REGISTER_23:
9774 switch (sel) {
9775 case CP0_REG23__DEBUG:
9776 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9777 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9778 gen_save_pc(ctx->base.pc_next + 4);
9779 ctx->base.is_jmp = DISAS_EXIT;
9780 register_name = "Debug";
9781 break;
9782 case CP0_REG23__TRACECONTROL:
9783 /* PDtrace support */
9784 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9785 /* Stop translation as we may have switched the execution mode */
9786 ctx->base.is_jmp = DISAS_STOP;
9787 register_name = "TraceControl";
9788 goto cp0_unimplemented;
9789 case CP0_REG23__TRACECONTROL2:
9790 /* PDtrace support */
9791 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9792 /* Stop translation as we may have switched the execution mode */
9793 ctx->base.is_jmp = DISAS_STOP;
9794 register_name = "TraceControl2";
9795 goto cp0_unimplemented;
9796 case CP0_REG23__USERTRACEDATA1:
9797 /* PDtrace support */
9798 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9799 /* Stop translation as we may have switched the execution mode */
9800 ctx->base.is_jmp = DISAS_STOP;
9801 register_name = "UserTraceData1";
9802 goto cp0_unimplemented;
9803 case CP0_REG23__TRACEIBPC:
9804 /* PDtrace support */
9805 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9806 /* Stop translation as we may have switched the execution mode */
9807 ctx->base.is_jmp = DISAS_STOP;
9808 register_name = "TraceIBPC";
9809 goto cp0_unimplemented;
9810 case CP0_REG23__TRACEDBPC:
9811 /* PDtrace support */
9812 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9813 /* Stop translation as we may have switched the execution mode */
9814 ctx->base.is_jmp = DISAS_STOP;
9815 register_name = "TraceDBPC";
9816 goto cp0_unimplemented;
9817 default:
9818 goto cp0_unimplemented;
9820 break;
9821 case CP0_REGISTER_24:
9822 switch (sel) {
9823 case CP0_REG24__DEPC:
9824 /* EJTAG support */
9825 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9826 register_name = "DEPC";
9827 break;
9828 default:
9829 goto cp0_unimplemented;
9831 break;
9832 case CP0_REGISTER_25:
9833 switch (sel) {
9834 case CP0_REG25__PERFCTL0:
9835 gen_helper_mtc0_performance0(cpu_env, arg);
9836 register_name = "Performance0";
9837 break;
9838 case CP0_REG25__PERFCNT0:
9839 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9840 register_name = "Performance1";
9841 goto cp0_unimplemented;
9842 case CP0_REG25__PERFCTL1:
9843 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9844 register_name = "Performance2";
9845 goto cp0_unimplemented;
9846 case CP0_REG25__PERFCNT1:
9847 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9848 register_name = "Performance3";
9849 goto cp0_unimplemented;
9850 case CP0_REG25__PERFCTL2:
9851 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9852 register_name = "Performance4";
9853 goto cp0_unimplemented;
9854 case CP0_REG25__PERFCNT2:
9855 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9856 register_name = "Performance5";
9857 goto cp0_unimplemented;
9858 case CP0_REG25__PERFCTL3:
9859 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9860 register_name = "Performance6";
9861 goto cp0_unimplemented;
9862 case CP0_REG25__PERFCNT3:
9863 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9864 register_name = "Performance7";
9865 goto cp0_unimplemented;
9866 default:
9867 goto cp0_unimplemented;
9869 break;
9870 case CP0_REGISTER_26:
9871 switch (sel) {
9872 case CP0_REG26__ERRCTL:
9873 gen_helper_mtc0_errctl(cpu_env, arg);
9874 ctx->base.is_jmp = DISAS_STOP;
9875 register_name = "ErrCtl";
9876 break;
9877 default:
9878 goto cp0_unimplemented;
9880 break;
9881 case CP0_REGISTER_27:
9882 switch (sel) {
9883 case CP0_REG27__CACHERR:
9884 /* ignored */
9885 register_name = "CacheErr";
9886 break;
9887 default:
9888 goto cp0_unimplemented;
9890 break;
9891 case CP0_REGISTER_28:
9892 switch (sel) {
9893 case CP0_REG28__TAGLO:
9894 case CP0_REG28__TAGLO1:
9895 case CP0_REG28__TAGLO2:
9896 case CP0_REG28__TAGLO3:
9897 gen_helper_mtc0_taglo(cpu_env, arg);
9898 register_name = "TagLo";
9899 break;
9900 case CP0_REG28__DATALO:
9901 case CP0_REG28__DATALO1:
9902 case CP0_REG28__DATALO2:
9903 case CP0_REG28__DATALO3:
9904 gen_helper_mtc0_datalo(cpu_env, arg);
9905 register_name = "DataLo";
9906 break;
9907 default:
9908 goto cp0_unimplemented;
9910 break;
9911 case CP0_REGISTER_29:
9912 switch (sel) {
9913 case CP0_REG29__TAGHI:
9914 case CP0_REG29__TAGHI1:
9915 case CP0_REG29__TAGHI2:
9916 case CP0_REG29__TAGHI3:
9917 gen_helper_mtc0_taghi(cpu_env, arg);
9918 register_name = "TagHi";
9919 break;
9920 case CP0_REG29__DATAHI:
9921 case CP0_REG29__DATAHI1:
9922 case CP0_REG29__DATAHI2:
9923 case CP0_REG29__DATAHI3:
9924 gen_helper_mtc0_datahi(cpu_env, arg);
9925 register_name = "DataHi";
9926 break;
9927 default:
9928 register_name = "invalid sel";
9929 goto cp0_unimplemented;
9931 break;
9932 case CP0_REGISTER_30:
9933 switch (sel) {
9934 case CP0_REG30__ERROREPC:
9935 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9936 register_name = "ErrorEPC";
9937 break;
9938 default:
9939 goto cp0_unimplemented;
9941 break;
9942 case CP0_REGISTER_31:
9943 switch (sel) {
9944 case CP0_REG31__DESAVE:
9945 /* EJTAG support */
9946 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9947 register_name = "DESAVE";
9948 break;
9949 case CP0_REG31__KSCRATCH1:
9950 case CP0_REG31__KSCRATCH2:
9951 case CP0_REG31__KSCRATCH3:
9952 case CP0_REG31__KSCRATCH4:
9953 case CP0_REG31__KSCRATCH5:
9954 case CP0_REG31__KSCRATCH6:
9955 CP0_CHECK(ctx->kscrexist & (1 << sel));
9956 tcg_gen_st_tl(arg, cpu_env,
9957 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9958 register_name = "KScratch";
9959 break;
9960 default:
9961 goto cp0_unimplemented;
9963 break;
9964 default:
9965 goto cp0_unimplemented;
9967 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9969 /* For simplicity assume that all writes can cause interrupts. */
9970 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9972 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9973 * translated code to check for pending interrupts.
9975 gen_save_pc(ctx->base.pc_next + 4);
9976 ctx->base.is_jmp = DISAS_EXIT;
9978 return;
9980 cp0_unimplemented:
9981 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9982 register_name, reg, sel);
9984 #endif /* TARGET_MIPS64 */
9986 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9987 int u, int sel, int h)
9989 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9990 TCGv t0 = tcg_temp_local_new();
9992 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9993 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9994 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9995 tcg_gen_movi_tl(t0, -1);
9996 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9997 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9998 tcg_gen_movi_tl(t0, -1);
9999 } else if (u == 0) {
10000 switch (rt) {
10001 case 1:
10002 switch (sel) {
10003 case 1:
10004 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10005 break;
10006 case 2:
10007 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10008 break;
10009 default:
10010 goto die;
10011 break;
10013 break;
10014 case 2:
10015 switch (sel) {
10016 case 1:
10017 gen_helper_mftc0_tcstatus(t0, cpu_env);
10018 break;
10019 case 2:
10020 gen_helper_mftc0_tcbind(t0, cpu_env);
10021 break;
10022 case 3:
10023 gen_helper_mftc0_tcrestart(t0, cpu_env);
10024 break;
10025 case 4:
10026 gen_helper_mftc0_tchalt(t0, cpu_env);
10027 break;
10028 case 5:
10029 gen_helper_mftc0_tccontext(t0, cpu_env);
10030 break;
10031 case 6:
10032 gen_helper_mftc0_tcschedule(t0, cpu_env);
10033 break;
10034 case 7:
10035 gen_helper_mftc0_tcschefback(t0, cpu_env);
10036 break;
10037 default:
10038 gen_mfc0(ctx, t0, rt, sel);
10039 break;
10041 break;
10042 case 10:
10043 switch (sel) {
10044 case 0:
10045 gen_helper_mftc0_entryhi(t0, cpu_env);
10046 break;
10047 default:
10048 gen_mfc0(ctx, t0, rt, sel);
10049 break;
10051 break;
10052 case 12:
10053 switch (sel) {
10054 case 0:
10055 gen_helper_mftc0_status(t0, cpu_env);
10056 break;
10057 default:
10058 gen_mfc0(ctx, t0, rt, sel);
10059 break;
10061 break;
10062 case 13:
10063 switch (sel) {
10064 case 0:
10065 gen_helper_mftc0_cause(t0, cpu_env);
10066 break;
10067 default:
10068 goto die;
10069 break;
10071 break;
10072 case 14:
10073 switch (sel) {
10074 case 0:
10075 gen_helper_mftc0_epc(t0, cpu_env);
10076 break;
10077 default:
10078 goto die;
10079 break;
10081 break;
10082 case 15:
10083 switch (sel) {
10084 case 1:
10085 gen_helper_mftc0_ebase(t0, cpu_env);
10086 break;
10087 default:
10088 goto die;
10089 break;
10091 break;
10092 case 16:
10093 switch (sel) {
10094 case 0:
10095 case 1:
10096 case 2:
10097 case 3:
10098 case 4:
10099 case 5:
10100 case 6:
10101 case 7:
10102 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10103 break;
10104 default:
10105 goto die;
10106 break;
10108 break;
10109 case 23:
10110 switch (sel) {
10111 case 0:
10112 gen_helper_mftc0_debug(t0, cpu_env);
10113 break;
10114 default:
10115 gen_mfc0(ctx, t0, rt, sel);
10116 break;
10118 break;
10119 default:
10120 gen_mfc0(ctx, t0, rt, sel);
10122 } else {
10123 switch (sel) {
10124 /* GPR registers. */
10125 case 0:
10126 gen_helper_1e0i(mftgpr, t0, rt);
10127 break;
10128 /* Auxiliary CPU registers */
10129 case 1:
10130 switch (rt) {
10131 case 0:
10132 gen_helper_1e0i(mftlo, t0, 0);
10133 break;
10134 case 1:
10135 gen_helper_1e0i(mfthi, t0, 0);
10136 break;
10137 case 2:
10138 gen_helper_1e0i(mftacx, t0, 0);
10139 break;
10140 case 4:
10141 gen_helper_1e0i(mftlo, t0, 1);
10142 break;
10143 case 5:
10144 gen_helper_1e0i(mfthi, t0, 1);
10145 break;
10146 case 6:
10147 gen_helper_1e0i(mftacx, t0, 1);
10148 break;
10149 case 8:
10150 gen_helper_1e0i(mftlo, t0, 2);
10151 break;
10152 case 9:
10153 gen_helper_1e0i(mfthi, t0, 2);
10154 break;
10155 case 10:
10156 gen_helper_1e0i(mftacx, t0, 2);
10157 break;
10158 case 12:
10159 gen_helper_1e0i(mftlo, t0, 3);
10160 break;
10161 case 13:
10162 gen_helper_1e0i(mfthi, t0, 3);
10163 break;
10164 case 14:
10165 gen_helper_1e0i(mftacx, t0, 3);
10166 break;
10167 case 16:
10168 gen_helper_mftdsp(t0, cpu_env);
10169 break;
10170 default:
10171 goto die;
10173 break;
10174 /* Floating point (COP1). */
10175 case 2:
10176 /* XXX: For now we support only a single FPU context. */
10177 if (h == 0) {
10178 TCGv_i32 fp0 = tcg_temp_new_i32();
10180 gen_load_fpr32(ctx, fp0, rt);
10181 tcg_gen_ext_i32_tl(t0, fp0);
10182 tcg_temp_free_i32(fp0);
10183 } else {
10184 TCGv_i32 fp0 = tcg_temp_new_i32();
10186 gen_load_fpr32h(ctx, fp0, rt);
10187 tcg_gen_ext_i32_tl(t0, fp0);
10188 tcg_temp_free_i32(fp0);
10190 break;
10191 case 3:
10192 /* XXX: For now we support only a single FPU context. */
10193 gen_helper_1e0i(cfc1, t0, rt);
10194 break;
10195 /* COP2: Not implemented. */
10196 case 4:
10197 case 5:
10198 /* fall through */
10199 default:
10200 goto die;
10203 trace_mips_translate_tr("mftr", rt, u, sel, h);
10204 gen_store_gpr(t0, rd);
10205 tcg_temp_free(t0);
10206 return;
10208 die:
10209 tcg_temp_free(t0);
10210 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10211 generate_exception_end(ctx, EXCP_RI);
10214 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10215 int u, int sel, int h)
10217 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10218 TCGv t0 = tcg_temp_local_new();
10220 gen_load_gpr(t0, rt);
10221 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10222 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10223 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10224 /* NOP */
10226 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10227 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10228 /* NOP */
10230 } else if (u == 0) {
10231 switch (rd) {
10232 case 1:
10233 switch (sel) {
10234 case 1:
10235 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10236 break;
10237 case 2:
10238 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10239 break;
10240 default:
10241 goto die;
10242 break;
10244 break;
10245 case 2:
10246 switch (sel) {
10247 case 1:
10248 gen_helper_mttc0_tcstatus(cpu_env, t0);
10249 break;
10250 case 2:
10251 gen_helper_mttc0_tcbind(cpu_env, t0);
10252 break;
10253 case 3:
10254 gen_helper_mttc0_tcrestart(cpu_env, t0);
10255 break;
10256 case 4:
10257 gen_helper_mttc0_tchalt(cpu_env, t0);
10258 break;
10259 case 5:
10260 gen_helper_mttc0_tccontext(cpu_env, t0);
10261 break;
10262 case 6:
10263 gen_helper_mttc0_tcschedule(cpu_env, t0);
10264 break;
10265 case 7:
10266 gen_helper_mttc0_tcschefback(cpu_env, t0);
10267 break;
10268 default:
10269 gen_mtc0(ctx, t0, rd, sel);
10270 break;
10272 break;
10273 case 10:
10274 switch (sel) {
10275 case 0:
10276 gen_helper_mttc0_entryhi(cpu_env, t0);
10277 break;
10278 default:
10279 gen_mtc0(ctx, t0, rd, sel);
10280 break;
10282 break;
10283 case 12:
10284 switch (sel) {
10285 case 0:
10286 gen_helper_mttc0_status(cpu_env, t0);
10287 break;
10288 default:
10289 gen_mtc0(ctx, t0, rd, sel);
10290 break;
10292 break;
10293 case 13:
10294 switch (sel) {
10295 case 0:
10296 gen_helper_mttc0_cause(cpu_env, t0);
10297 break;
10298 default:
10299 goto die;
10300 break;
10302 break;
10303 case 15:
10304 switch (sel) {
10305 case 1:
10306 gen_helper_mttc0_ebase(cpu_env, t0);
10307 break;
10308 default:
10309 goto die;
10310 break;
10312 break;
10313 case 23:
10314 switch (sel) {
10315 case 0:
10316 gen_helper_mttc0_debug(cpu_env, t0);
10317 break;
10318 default:
10319 gen_mtc0(ctx, t0, rd, sel);
10320 break;
10322 break;
10323 default:
10324 gen_mtc0(ctx, t0, rd, sel);
10326 } else {
10327 switch (sel) {
10328 /* GPR registers. */
10329 case 0:
10330 gen_helper_0e1i(mttgpr, t0, rd);
10331 break;
10332 /* Auxiliary CPU registers */
10333 case 1:
10334 switch (rd) {
10335 case 0:
10336 gen_helper_0e1i(mttlo, t0, 0);
10337 break;
10338 case 1:
10339 gen_helper_0e1i(mtthi, t0, 0);
10340 break;
10341 case 2:
10342 gen_helper_0e1i(mttacx, t0, 0);
10343 break;
10344 case 4:
10345 gen_helper_0e1i(mttlo, t0, 1);
10346 break;
10347 case 5:
10348 gen_helper_0e1i(mtthi, t0, 1);
10349 break;
10350 case 6:
10351 gen_helper_0e1i(mttacx, t0, 1);
10352 break;
10353 case 8:
10354 gen_helper_0e1i(mttlo, t0, 2);
10355 break;
10356 case 9:
10357 gen_helper_0e1i(mtthi, t0, 2);
10358 break;
10359 case 10:
10360 gen_helper_0e1i(mttacx, t0, 2);
10361 break;
10362 case 12:
10363 gen_helper_0e1i(mttlo, t0, 3);
10364 break;
10365 case 13:
10366 gen_helper_0e1i(mtthi, t0, 3);
10367 break;
10368 case 14:
10369 gen_helper_0e1i(mttacx, t0, 3);
10370 break;
10371 case 16:
10372 gen_helper_mttdsp(cpu_env, t0);
10373 break;
10374 default:
10375 goto die;
10377 break;
10378 /* Floating point (COP1). */
10379 case 2:
10380 /* XXX: For now we support only a single FPU context. */
10381 if (h == 0) {
10382 TCGv_i32 fp0 = tcg_temp_new_i32();
10384 tcg_gen_trunc_tl_i32(fp0, t0);
10385 gen_store_fpr32(ctx, fp0, rd);
10386 tcg_temp_free_i32(fp0);
10387 } else {
10388 TCGv_i32 fp0 = tcg_temp_new_i32();
10390 tcg_gen_trunc_tl_i32(fp0, t0);
10391 gen_store_fpr32h(ctx, fp0, rd);
10392 tcg_temp_free_i32(fp0);
10394 break;
10395 case 3:
10396 /* XXX: For now we support only a single FPU context. */
10398 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10400 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10401 tcg_temp_free_i32(fs_tmp);
10403 /* Stop translation as we may have changed hflags */
10404 ctx->base.is_jmp = DISAS_STOP;
10405 break;
10406 /* COP2: Not implemented. */
10407 case 4:
10408 case 5:
10409 /* fall through */
10410 default:
10411 goto die;
10414 trace_mips_translate_tr("mttr", rd, u, sel, h);
10415 tcg_temp_free(t0);
10416 return;
10418 die:
10419 tcg_temp_free(t0);
10420 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10421 generate_exception_end(ctx, EXCP_RI);
10424 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10425 int rt, int rd)
10427 const char *opn = "ldst";
10429 check_cp0_enabled(ctx);
10430 switch (opc) {
10431 case OPC_MFC0:
10432 if (rt == 0) {
10433 /* Treat as NOP. */
10434 return;
10436 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10437 opn = "mfc0";
10438 break;
10439 case OPC_MTC0:
10441 TCGv t0 = tcg_temp_new();
10443 gen_load_gpr(t0, rt);
10444 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10445 tcg_temp_free(t0);
10447 opn = "mtc0";
10448 break;
10449 #if defined(TARGET_MIPS64)
10450 case OPC_DMFC0:
10451 check_insn(ctx, ISA_MIPS3);
10452 if (rt == 0) {
10453 /* Treat as NOP. */
10454 return;
10456 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10457 opn = "dmfc0";
10458 break;
10459 case OPC_DMTC0:
10460 check_insn(ctx, ISA_MIPS3);
10462 TCGv t0 = tcg_temp_new();
10464 gen_load_gpr(t0, rt);
10465 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10466 tcg_temp_free(t0);
10468 opn = "dmtc0";
10469 break;
10470 #endif
10471 case OPC_MFHC0:
10472 check_mvh(ctx);
10473 if (rt == 0) {
10474 /* Treat as NOP. */
10475 return;
10477 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10478 opn = "mfhc0";
10479 break;
10480 case OPC_MTHC0:
10481 check_mvh(ctx);
10483 TCGv t0 = tcg_temp_new();
10484 gen_load_gpr(t0, rt);
10485 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10486 tcg_temp_free(t0);
10488 opn = "mthc0";
10489 break;
10490 case OPC_MFTR:
10491 check_cp0_enabled(ctx);
10492 if (rd == 0) {
10493 /* Treat as NOP. */
10494 return;
10496 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10497 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10498 opn = "mftr";
10499 break;
10500 case OPC_MTTR:
10501 check_cp0_enabled(ctx);
10502 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10503 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10504 opn = "mttr";
10505 break;
10506 case OPC_TLBWI:
10507 opn = "tlbwi";
10508 if (!env->tlb->helper_tlbwi) {
10509 goto die;
10511 gen_helper_tlbwi(cpu_env);
10512 break;
10513 case OPC_TLBINV:
10514 opn = "tlbinv";
10515 if (ctx->ie >= 2) {
10516 if (!env->tlb->helper_tlbinv) {
10517 goto die;
10519 gen_helper_tlbinv(cpu_env);
10520 } /* treat as nop if TLBINV not supported */
10521 break;
10522 case OPC_TLBINVF:
10523 opn = "tlbinvf";
10524 if (ctx->ie >= 2) {
10525 if (!env->tlb->helper_tlbinvf) {
10526 goto die;
10528 gen_helper_tlbinvf(cpu_env);
10529 } /* treat as nop if TLBINV not supported */
10530 break;
10531 case OPC_TLBWR:
10532 opn = "tlbwr";
10533 if (!env->tlb->helper_tlbwr) {
10534 goto die;
10536 gen_helper_tlbwr(cpu_env);
10537 break;
10538 case OPC_TLBP:
10539 opn = "tlbp";
10540 if (!env->tlb->helper_tlbp) {
10541 goto die;
10543 gen_helper_tlbp(cpu_env);
10544 break;
10545 case OPC_TLBR:
10546 opn = "tlbr";
10547 if (!env->tlb->helper_tlbr) {
10548 goto die;
10550 gen_helper_tlbr(cpu_env);
10551 break;
10552 case OPC_ERET: /* OPC_ERETNC */
10553 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10554 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10555 goto die;
10556 } else {
10557 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10558 if (ctx->opcode & (1 << bit_shift)) {
10559 /* OPC_ERETNC */
10560 opn = "eretnc";
10561 check_insn(ctx, ISA_MIPS32R5);
10562 gen_helper_eretnc(cpu_env);
10563 } else {
10564 /* OPC_ERET */
10565 opn = "eret";
10566 check_insn(ctx, ISA_MIPS2);
10567 gen_helper_eret(cpu_env);
10569 ctx->base.is_jmp = DISAS_EXIT;
10571 break;
10572 case OPC_DERET:
10573 opn = "deret";
10574 check_insn(ctx, ISA_MIPS32);
10575 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10576 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10577 goto die;
10579 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10580 MIPS_INVAL(opn);
10581 generate_exception_end(ctx, EXCP_RI);
10582 } else {
10583 gen_helper_deret(cpu_env);
10584 ctx->base.is_jmp = DISAS_EXIT;
10586 break;
10587 case OPC_WAIT:
10588 opn = "wait";
10589 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10590 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10591 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10592 goto die;
10594 /* If we get an exception, we want to restart at next instruction */
10595 ctx->base.pc_next += 4;
10596 save_cpu_state(ctx, 1);
10597 ctx->base.pc_next -= 4;
10598 gen_helper_wait(cpu_env);
10599 ctx->base.is_jmp = DISAS_NORETURN;
10600 break;
10601 default:
10602 die:
10603 MIPS_INVAL(opn);
10604 generate_exception_end(ctx, EXCP_RI);
10605 return;
10607 (void)opn; /* avoid a compiler warning */
10609 #endif /* !CONFIG_USER_ONLY */
10611 /* CP1 Branches (before delay slot) */
10612 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10613 int32_t cc, int32_t offset)
10615 target_ulong btarget;
10616 TCGv_i32 t0 = tcg_temp_new_i32();
10618 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10619 generate_exception_end(ctx, EXCP_RI);
10620 goto out;
10623 if (cc != 0) {
10624 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10627 btarget = ctx->base.pc_next + 4 + offset;
10629 switch (op) {
10630 case OPC_BC1F:
10631 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10632 tcg_gen_not_i32(t0, t0);
10633 tcg_gen_andi_i32(t0, t0, 1);
10634 tcg_gen_extu_i32_tl(bcond, t0);
10635 goto not_likely;
10636 case OPC_BC1FL:
10637 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10638 tcg_gen_not_i32(t0, t0);
10639 tcg_gen_andi_i32(t0, t0, 1);
10640 tcg_gen_extu_i32_tl(bcond, t0);
10641 goto likely;
10642 case OPC_BC1T:
10643 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10644 tcg_gen_andi_i32(t0, t0, 1);
10645 tcg_gen_extu_i32_tl(bcond, t0);
10646 goto not_likely;
10647 case OPC_BC1TL:
10648 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10649 tcg_gen_andi_i32(t0, t0, 1);
10650 tcg_gen_extu_i32_tl(bcond, t0);
10651 likely:
10652 ctx->hflags |= MIPS_HFLAG_BL;
10653 break;
10654 case OPC_BC1FANY2:
10656 TCGv_i32 t1 = tcg_temp_new_i32();
10657 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10658 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10659 tcg_gen_nand_i32(t0, t0, t1);
10660 tcg_temp_free_i32(t1);
10661 tcg_gen_andi_i32(t0, t0, 1);
10662 tcg_gen_extu_i32_tl(bcond, t0);
10664 goto not_likely;
10665 case OPC_BC1TANY2:
10667 TCGv_i32 t1 = tcg_temp_new_i32();
10668 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10669 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10670 tcg_gen_or_i32(t0, t0, t1);
10671 tcg_temp_free_i32(t1);
10672 tcg_gen_andi_i32(t0, t0, 1);
10673 tcg_gen_extu_i32_tl(bcond, t0);
10675 goto not_likely;
10676 case OPC_BC1FANY4:
10678 TCGv_i32 t1 = tcg_temp_new_i32();
10679 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10680 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10681 tcg_gen_and_i32(t0, t0, t1);
10682 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10683 tcg_gen_and_i32(t0, t0, t1);
10684 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10685 tcg_gen_nand_i32(t0, t0, t1);
10686 tcg_temp_free_i32(t1);
10687 tcg_gen_andi_i32(t0, t0, 1);
10688 tcg_gen_extu_i32_tl(bcond, t0);
10690 goto not_likely;
10691 case OPC_BC1TANY4:
10693 TCGv_i32 t1 = tcg_temp_new_i32();
10694 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10695 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10696 tcg_gen_or_i32(t0, t0, t1);
10697 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10698 tcg_gen_or_i32(t0, t0, t1);
10699 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10700 tcg_gen_or_i32(t0, t0, t1);
10701 tcg_temp_free_i32(t1);
10702 tcg_gen_andi_i32(t0, t0, 1);
10703 tcg_gen_extu_i32_tl(bcond, t0);
10705 not_likely:
10706 ctx->hflags |= MIPS_HFLAG_BC;
10707 break;
10708 default:
10709 MIPS_INVAL("cp1 cond branch");
10710 generate_exception_end(ctx, EXCP_RI);
10711 goto out;
10713 ctx->btarget = btarget;
10714 ctx->hflags |= MIPS_HFLAG_BDS32;
10715 out:
10716 tcg_temp_free_i32(t0);
10719 /* R6 CP1 Branches */
10720 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10721 int32_t ft, int32_t offset,
10722 int delayslot_size)
10724 target_ulong btarget;
10725 TCGv_i64 t0 = tcg_temp_new_i64();
10727 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10728 #ifdef MIPS_DEBUG_DISAS
10729 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10730 "\n", ctx->base.pc_next);
10731 #endif
10732 generate_exception_end(ctx, EXCP_RI);
10733 goto out;
10736 gen_load_fpr64(ctx, t0, ft);
10737 tcg_gen_andi_i64(t0, t0, 1);
10739 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10741 switch (op) {
10742 case OPC_BC1EQZ:
10743 tcg_gen_xori_i64(t0, t0, 1);
10744 ctx->hflags |= MIPS_HFLAG_BC;
10745 break;
10746 case OPC_BC1NEZ:
10747 /* t0 already set */
10748 ctx->hflags |= MIPS_HFLAG_BC;
10749 break;
10750 default:
10751 MIPS_INVAL("cp1 cond branch");
10752 generate_exception_end(ctx, EXCP_RI);
10753 goto out;
10756 tcg_gen_trunc_i64_tl(bcond, t0);
10758 ctx->btarget = btarget;
10760 switch (delayslot_size) {
10761 case 2:
10762 ctx->hflags |= MIPS_HFLAG_BDS16;
10763 break;
10764 case 4:
10765 ctx->hflags |= MIPS_HFLAG_BDS32;
10766 break;
10769 out:
10770 tcg_temp_free_i64(t0);
10773 /* Coprocessor 1 (FPU) */
10775 #define FOP(func, fmt) (((fmt) << 21) | (func))
10777 enum fopcode {
10778 OPC_ADD_S = FOP(0, FMT_S),
10779 OPC_SUB_S = FOP(1, FMT_S),
10780 OPC_MUL_S = FOP(2, FMT_S),
10781 OPC_DIV_S = FOP(3, FMT_S),
10782 OPC_SQRT_S = FOP(4, FMT_S),
10783 OPC_ABS_S = FOP(5, FMT_S),
10784 OPC_MOV_S = FOP(6, FMT_S),
10785 OPC_NEG_S = FOP(7, FMT_S),
10786 OPC_ROUND_L_S = FOP(8, FMT_S),
10787 OPC_TRUNC_L_S = FOP(9, FMT_S),
10788 OPC_CEIL_L_S = FOP(10, FMT_S),
10789 OPC_FLOOR_L_S = FOP(11, FMT_S),
10790 OPC_ROUND_W_S = FOP(12, FMT_S),
10791 OPC_TRUNC_W_S = FOP(13, FMT_S),
10792 OPC_CEIL_W_S = FOP(14, FMT_S),
10793 OPC_FLOOR_W_S = FOP(15, FMT_S),
10794 OPC_SEL_S = FOP(16, FMT_S),
10795 OPC_MOVCF_S = FOP(17, FMT_S),
10796 OPC_MOVZ_S = FOP(18, FMT_S),
10797 OPC_MOVN_S = FOP(19, FMT_S),
10798 OPC_SELEQZ_S = FOP(20, FMT_S),
10799 OPC_RECIP_S = FOP(21, FMT_S),
10800 OPC_RSQRT_S = FOP(22, FMT_S),
10801 OPC_SELNEZ_S = FOP(23, FMT_S),
10802 OPC_MADDF_S = FOP(24, FMT_S),
10803 OPC_MSUBF_S = FOP(25, FMT_S),
10804 OPC_RINT_S = FOP(26, FMT_S),
10805 OPC_CLASS_S = FOP(27, FMT_S),
10806 OPC_MIN_S = FOP(28, FMT_S),
10807 OPC_RECIP2_S = FOP(28, FMT_S),
10808 OPC_MINA_S = FOP(29, FMT_S),
10809 OPC_RECIP1_S = FOP(29, FMT_S),
10810 OPC_MAX_S = FOP(30, FMT_S),
10811 OPC_RSQRT1_S = FOP(30, FMT_S),
10812 OPC_MAXA_S = FOP(31, FMT_S),
10813 OPC_RSQRT2_S = FOP(31, FMT_S),
10814 OPC_CVT_D_S = FOP(33, FMT_S),
10815 OPC_CVT_W_S = FOP(36, FMT_S),
10816 OPC_CVT_L_S = FOP(37, FMT_S),
10817 OPC_CVT_PS_S = FOP(38, FMT_S),
10818 OPC_CMP_F_S = FOP(48, FMT_S),
10819 OPC_CMP_UN_S = FOP(49, FMT_S),
10820 OPC_CMP_EQ_S = FOP(50, FMT_S),
10821 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10822 OPC_CMP_OLT_S = FOP(52, FMT_S),
10823 OPC_CMP_ULT_S = FOP(53, FMT_S),
10824 OPC_CMP_OLE_S = FOP(54, FMT_S),
10825 OPC_CMP_ULE_S = FOP(55, FMT_S),
10826 OPC_CMP_SF_S = FOP(56, FMT_S),
10827 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10828 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10829 OPC_CMP_NGL_S = FOP(59, FMT_S),
10830 OPC_CMP_LT_S = FOP(60, FMT_S),
10831 OPC_CMP_NGE_S = FOP(61, FMT_S),
10832 OPC_CMP_LE_S = FOP(62, FMT_S),
10833 OPC_CMP_NGT_S = FOP(63, FMT_S),
10835 OPC_ADD_D = FOP(0, FMT_D),
10836 OPC_SUB_D = FOP(1, FMT_D),
10837 OPC_MUL_D = FOP(2, FMT_D),
10838 OPC_DIV_D = FOP(3, FMT_D),
10839 OPC_SQRT_D = FOP(4, FMT_D),
10840 OPC_ABS_D = FOP(5, FMT_D),
10841 OPC_MOV_D = FOP(6, FMT_D),
10842 OPC_NEG_D = FOP(7, FMT_D),
10843 OPC_ROUND_L_D = FOP(8, FMT_D),
10844 OPC_TRUNC_L_D = FOP(9, FMT_D),
10845 OPC_CEIL_L_D = FOP(10, FMT_D),
10846 OPC_FLOOR_L_D = FOP(11, FMT_D),
10847 OPC_ROUND_W_D = FOP(12, FMT_D),
10848 OPC_TRUNC_W_D = FOP(13, FMT_D),
10849 OPC_CEIL_W_D = FOP(14, FMT_D),
10850 OPC_FLOOR_W_D = FOP(15, FMT_D),
10851 OPC_SEL_D = FOP(16, FMT_D),
10852 OPC_MOVCF_D = FOP(17, FMT_D),
10853 OPC_MOVZ_D = FOP(18, FMT_D),
10854 OPC_MOVN_D = FOP(19, FMT_D),
10855 OPC_SELEQZ_D = FOP(20, FMT_D),
10856 OPC_RECIP_D = FOP(21, FMT_D),
10857 OPC_RSQRT_D = FOP(22, FMT_D),
10858 OPC_SELNEZ_D = FOP(23, FMT_D),
10859 OPC_MADDF_D = FOP(24, FMT_D),
10860 OPC_MSUBF_D = FOP(25, FMT_D),
10861 OPC_RINT_D = FOP(26, FMT_D),
10862 OPC_CLASS_D = FOP(27, FMT_D),
10863 OPC_MIN_D = FOP(28, FMT_D),
10864 OPC_RECIP2_D = FOP(28, FMT_D),
10865 OPC_MINA_D = FOP(29, FMT_D),
10866 OPC_RECIP1_D = FOP(29, FMT_D),
10867 OPC_MAX_D = FOP(30, FMT_D),
10868 OPC_RSQRT1_D = FOP(30, FMT_D),
10869 OPC_MAXA_D = FOP(31, FMT_D),
10870 OPC_RSQRT2_D = FOP(31, FMT_D),
10871 OPC_CVT_S_D = FOP(32, FMT_D),
10872 OPC_CVT_W_D = FOP(36, FMT_D),
10873 OPC_CVT_L_D = FOP(37, FMT_D),
10874 OPC_CMP_F_D = FOP(48, FMT_D),
10875 OPC_CMP_UN_D = FOP(49, FMT_D),
10876 OPC_CMP_EQ_D = FOP(50, FMT_D),
10877 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10878 OPC_CMP_OLT_D = FOP(52, FMT_D),
10879 OPC_CMP_ULT_D = FOP(53, FMT_D),
10880 OPC_CMP_OLE_D = FOP(54, FMT_D),
10881 OPC_CMP_ULE_D = FOP(55, FMT_D),
10882 OPC_CMP_SF_D = FOP(56, FMT_D),
10883 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10884 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10885 OPC_CMP_NGL_D = FOP(59, FMT_D),
10886 OPC_CMP_LT_D = FOP(60, FMT_D),
10887 OPC_CMP_NGE_D = FOP(61, FMT_D),
10888 OPC_CMP_LE_D = FOP(62, FMT_D),
10889 OPC_CMP_NGT_D = FOP(63, FMT_D),
10891 OPC_CVT_S_W = FOP(32, FMT_W),
10892 OPC_CVT_D_W = FOP(33, FMT_W),
10893 OPC_CVT_S_L = FOP(32, FMT_L),
10894 OPC_CVT_D_L = FOP(33, FMT_L),
10895 OPC_CVT_PS_PW = FOP(38, FMT_W),
10897 OPC_ADD_PS = FOP(0, FMT_PS),
10898 OPC_SUB_PS = FOP(1, FMT_PS),
10899 OPC_MUL_PS = FOP(2, FMT_PS),
10900 OPC_DIV_PS = FOP(3, FMT_PS),
10901 OPC_ABS_PS = FOP(5, FMT_PS),
10902 OPC_MOV_PS = FOP(6, FMT_PS),
10903 OPC_NEG_PS = FOP(7, FMT_PS),
10904 OPC_MOVCF_PS = FOP(17, FMT_PS),
10905 OPC_MOVZ_PS = FOP(18, FMT_PS),
10906 OPC_MOVN_PS = FOP(19, FMT_PS),
10907 OPC_ADDR_PS = FOP(24, FMT_PS),
10908 OPC_MULR_PS = FOP(26, FMT_PS),
10909 OPC_RECIP2_PS = FOP(28, FMT_PS),
10910 OPC_RECIP1_PS = FOP(29, FMT_PS),
10911 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10912 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10914 OPC_CVT_S_PU = FOP(32, FMT_PS),
10915 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10916 OPC_CVT_S_PL = FOP(40, FMT_PS),
10917 OPC_PLL_PS = FOP(44, FMT_PS),
10918 OPC_PLU_PS = FOP(45, FMT_PS),
10919 OPC_PUL_PS = FOP(46, FMT_PS),
10920 OPC_PUU_PS = FOP(47, FMT_PS),
10921 OPC_CMP_F_PS = FOP(48, FMT_PS),
10922 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10923 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10924 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10925 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10926 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10927 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10928 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10929 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10930 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10931 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10932 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10933 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10934 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10935 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10936 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10939 enum r6_f_cmp_op {
10940 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10941 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10942 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10943 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10944 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10945 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10946 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10947 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10948 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10949 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10950 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10951 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10952 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10953 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10954 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10955 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10956 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10957 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10958 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10959 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10960 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10961 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10963 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10964 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10965 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10966 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10967 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10968 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10969 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10970 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10971 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10972 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10973 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10974 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10975 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10976 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10977 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10978 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10979 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10980 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10981 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10982 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10983 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10984 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10987 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10989 TCGv t0 = tcg_temp_new();
10991 switch (opc) {
10992 case OPC_MFC1:
10994 TCGv_i32 fp0 = tcg_temp_new_i32();
10996 gen_load_fpr32(ctx, fp0, fs);
10997 tcg_gen_ext_i32_tl(t0, fp0);
10998 tcg_temp_free_i32(fp0);
11000 gen_store_gpr(t0, rt);
11001 break;
11002 case OPC_MTC1:
11003 gen_load_gpr(t0, rt);
11005 TCGv_i32 fp0 = tcg_temp_new_i32();
11007 tcg_gen_trunc_tl_i32(fp0, t0);
11008 gen_store_fpr32(ctx, fp0, fs);
11009 tcg_temp_free_i32(fp0);
11011 break;
11012 case OPC_CFC1:
11013 gen_helper_1e0i(cfc1, t0, fs);
11014 gen_store_gpr(t0, rt);
11015 break;
11016 case OPC_CTC1:
11017 gen_load_gpr(t0, rt);
11018 save_cpu_state(ctx, 0);
11020 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11022 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11023 tcg_temp_free_i32(fs_tmp);
11025 /* Stop translation as we may have changed hflags */
11026 ctx->base.is_jmp = DISAS_STOP;
11027 break;
11028 #if defined(TARGET_MIPS64)
11029 case OPC_DMFC1:
11030 gen_load_fpr64(ctx, t0, fs);
11031 gen_store_gpr(t0, rt);
11032 break;
11033 case OPC_DMTC1:
11034 gen_load_gpr(t0, rt);
11035 gen_store_fpr64(ctx, t0, fs);
11036 break;
11037 #endif
11038 case OPC_MFHC1:
11040 TCGv_i32 fp0 = tcg_temp_new_i32();
11042 gen_load_fpr32h(ctx, fp0, fs);
11043 tcg_gen_ext_i32_tl(t0, fp0);
11044 tcg_temp_free_i32(fp0);
11046 gen_store_gpr(t0, rt);
11047 break;
11048 case OPC_MTHC1:
11049 gen_load_gpr(t0, rt);
11051 TCGv_i32 fp0 = tcg_temp_new_i32();
11053 tcg_gen_trunc_tl_i32(fp0, t0);
11054 gen_store_fpr32h(ctx, fp0, fs);
11055 tcg_temp_free_i32(fp0);
11057 break;
11058 default:
11059 MIPS_INVAL("cp1 move");
11060 generate_exception_end(ctx, EXCP_RI);
11061 goto out;
11064 out:
11065 tcg_temp_free(t0);
11068 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11070 TCGLabel *l1;
11071 TCGCond cond;
11072 TCGv_i32 t0;
11074 if (rd == 0) {
11075 /* Treat as NOP. */
11076 return;
11079 if (tf) {
11080 cond = TCG_COND_EQ;
11081 } else {
11082 cond = TCG_COND_NE;
11085 l1 = gen_new_label();
11086 t0 = tcg_temp_new_i32();
11087 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11088 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11089 tcg_temp_free_i32(t0);
11090 if (rs == 0) {
11091 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11092 } else {
11093 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11095 gen_set_label(l1);
11098 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11099 int tf)
11101 int cond;
11102 TCGv_i32 t0 = tcg_temp_new_i32();
11103 TCGLabel *l1 = gen_new_label();
11105 if (tf) {
11106 cond = TCG_COND_EQ;
11107 } else {
11108 cond = TCG_COND_NE;
11111 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11112 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11113 gen_load_fpr32(ctx, t0, fs);
11114 gen_store_fpr32(ctx, t0, fd);
11115 gen_set_label(l1);
11116 tcg_temp_free_i32(t0);
11119 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11120 int tf)
11122 int cond;
11123 TCGv_i32 t0 = tcg_temp_new_i32();
11124 TCGv_i64 fp0;
11125 TCGLabel *l1 = gen_new_label();
11127 if (tf) {
11128 cond = TCG_COND_EQ;
11129 } else {
11130 cond = TCG_COND_NE;
11133 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11134 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11135 tcg_temp_free_i32(t0);
11136 fp0 = tcg_temp_new_i64();
11137 gen_load_fpr64(ctx, fp0, fs);
11138 gen_store_fpr64(ctx, fp0, fd);
11139 tcg_temp_free_i64(fp0);
11140 gen_set_label(l1);
11143 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11144 int cc, int tf)
11146 int cond;
11147 TCGv_i32 t0 = tcg_temp_new_i32();
11148 TCGLabel *l1 = gen_new_label();
11149 TCGLabel *l2 = gen_new_label();
11151 if (tf) {
11152 cond = TCG_COND_EQ;
11153 } else {
11154 cond = TCG_COND_NE;
11157 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11158 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11159 gen_load_fpr32(ctx, t0, fs);
11160 gen_store_fpr32(ctx, t0, fd);
11161 gen_set_label(l1);
11163 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11164 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11165 gen_load_fpr32h(ctx, t0, fs);
11166 gen_store_fpr32h(ctx, t0, fd);
11167 tcg_temp_free_i32(t0);
11168 gen_set_label(l2);
11171 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11172 int fs)
11174 TCGv_i32 t1 = tcg_const_i32(0);
11175 TCGv_i32 fp0 = tcg_temp_new_i32();
11176 TCGv_i32 fp1 = tcg_temp_new_i32();
11177 TCGv_i32 fp2 = tcg_temp_new_i32();
11178 gen_load_fpr32(ctx, fp0, fd);
11179 gen_load_fpr32(ctx, fp1, ft);
11180 gen_load_fpr32(ctx, fp2, fs);
11182 switch (op1) {
11183 case OPC_SEL_S:
11184 tcg_gen_andi_i32(fp0, fp0, 1);
11185 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11186 break;
11187 case OPC_SELEQZ_S:
11188 tcg_gen_andi_i32(fp1, fp1, 1);
11189 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11190 break;
11191 case OPC_SELNEZ_S:
11192 tcg_gen_andi_i32(fp1, fp1, 1);
11193 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11194 break;
11195 default:
11196 MIPS_INVAL("gen_sel_s");
11197 generate_exception_end(ctx, EXCP_RI);
11198 break;
11201 gen_store_fpr32(ctx, fp0, fd);
11202 tcg_temp_free_i32(fp2);
11203 tcg_temp_free_i32(fp1);
11204 tcg_temp_free_i32(fp0);
11205 tcg_temp_free_i32(t1);
11208 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11209 int fs)
11211 TCGv_i64 t1 = tcg_const_i64(0);
11212 TCGv_i64 fp0 = tcg_temp_new_i64();
11213 TCGv_i64 fp1 = tcg_temp_new_i64();
11214 TCGv_i64 fp2 = tcg_temp_new_i64();
11215 gen_load_fpr64(ctx, fp0, fd);
11216 gen_load_fpr64(ctx, fp1, ft);
11217 gen_load_fpr64(ctx, fp2, fs);
11219 switch (op1) {
11220 case OPC_SEL_D:
11221 tcg_gen_andi_i64(fp0, fp0, 1);
11222 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11223 break;
11224 case OPC_SELEQZ_D:
11225 tcg_gen_andi_i64(fp1, fp1, 1);
11226 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11227 break;
11228 case OPC_SELNEZ_D:
11229 tcg_gen_andi_i64(fp1, fp1, 1);
11230 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11231 break;
11232 default:
11233 MIPS_INVAL("gen_sel_d");
11234 generate_exception_end(ctx, EXCP_RI);
11235 break;
11238 gen_store_fpr64(ctx, fp0, fd);
11239 tcg_temp_free_i64(fp2);
11240 tcg_temp_free_i64(fp1);
11241 tcg_temp_free_i64(fp0);
11242 tcg_temp_free_i64(t1);
11245 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11246 int ft, int fs, int fd, int cc)
11248 uint32_t func = ctx->opcode & 0x3f;
11249 switch (op1) {
11250 case OPC_ADD_S:
11252 TCGv_i32 fp0 = tcg_temp_new_i32();
11253 TCGv_i32 fp1 = tcg_temp_new_i32();
11255 gen_load_fpr32(ctx, fp0, fs);
11256 gen_load_fpr32(ctx, fp1, ft);
11257 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11258 tcg_temp_free_i32(fp1);
11259 gen_store_fpr32(ctx, fp0, fd);
11260 tcg_temp_free_i32(fp0);
11262 break;
11263 case OPC_SUB_S:
11265 TCGv_i32 fp0 = tcg_temp_new_i32();
11266 TCGv_i32 fp1 = tcg_temp_new_i32();
11268 gen_load_fpr32(ctx, fp0, fs);
11269 gen_load_fpr32(ctx, fp1, ft);
11270 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11271 tcg_temp_free_i32(fp1);
11272 gen_store_fpr32(ctx, fp0, fd);
11273 tcg_temp_free_i32(fp0);
11275 break;
11276 case OPC_MUL_S:
11278 TCGv_i32 fp0 = tcg_temp_new_i32();
11279 TCGv_i32 fp1 = tcg_temp_new_i32();
11281 gen_load_fpr32(ctx, fp0, fs);
11282 gen_load_fpr32(ctx, fp1, ft);
11283 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11284 tcg_temp_free_i32(fp1);
11285 gen_store_fpr32(ctx, fp0, fd);
11286 tcg_temp_free_i32(fp0);
11288 break;
11289 case OPC_DIV_S:
11291 TCGv_i32 fp0 = tcg_temp_new_i32();
11292 TCGv_i32 fp1 = tcg_temp_new_i32();
11294 gen_load_fpr32(ctx, fp0, fs);
11295 gen_load_fpr32(ctx, fp1, ft);
11296 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11297 tcg_temp_free_i32(fp1);
11298 gen_store_fpr32(ctx, fp0, fd);
11299 tcg_temp_free_i32(fp0);
11301 break;
11302 case OPC_SQRT_S:
11304 TCGv_i32 fp0 = tcg_temp_new_i32();
11306 gen_load_fpr32(ctx, fp0, fs);
11307 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11308 gen_store_fpr32(ctx, fp0, fd);
11309 tcg_temp_free_i32(fp0);
11311 break;
11312 case OPC_ABS_S:
11314 TCGv_i32 fp0 = tcg_temp_new_i32();
11316 gen_load_fpr32(ctx, fp0, fs);
11317 if (ctx->abs2008) {
11318 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11319 } else {
11320 gen_helper_float_abs_s(fp0, fp0);
11322 gen_store_fpr32(ctx, fp0, fd);
11323 tcg_temp_free_i32(fp0);
11325 break;
11326 case OPC_MOV_S:
11328 TCGv_i32 fp0 = tcg_temp_new_i32();
11330 gen_load_fpr32(ctx, fp0, fs);
11331 gen_store_fpr32(ctx, fp0, fd);
11332 tcg_temp_free_i32(fp0);
11334 break;
11335 case OPC_NEG_S:
11337 TCGv_i32 fp0 = tcg_temp_new_i32();
11339 gen_load_fpr32(ctx, fp0, fs);
11340 if (ctx->abs2008) {
11341 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11342 } else {
11343 gen_helper_float_chs_s(fp0, fp0);
11345 gen_store_fpr32(ctx, fp0, fd);
11346 tcg_temp_free_i32(fp0);
11348 break;
11349 case OPC_ROUND_L_S:
11350 check_cp1_64bitmode(ctx);
11352 TCGv_i32 fp32 = tcg_temp_new_i32();
11353 TCGv_i64 fp64 = tcg_temp_new_i64();
11355 gen_load_fpr32(ctx, fp32, fs);
11356 if (ctx->nan2008) {
11357 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11358 } else {
11359 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11361 tcg_temp_free_i32(fp32);
11362 gen_store_fpr64(ctx, fp64, fd);
11363 tcg_temp_free_i64(fp64);
11365 break;
11366 case OPC_TRUNC_L_S:
11367 check_cp1_64bitmode(ctx);
11369 TCGv_i32 fp32 = tcg_temp_new_i32();
11370 TCGv_i64 fp64 = tcg_temp_new_i64();
11372 gen_load_fpr32(ctx, fp32, fs);
11373 if (ctx->nan2008) {
11374 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11375 } else {
11376 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11378 tcg_temp_free_i32(fp32);
11379 gen_store_fpr64(ctx, fp64, fd);
11380 tcg_temp_free_i64(fp64);
11382 break;
11383 case OPC_CEIL_L_S:
11384 check_cp1_64bitmode(ctx);
11386 TCGv_i32 fp32 = tcg_temp_new_i32();
11387 TCGv_i64 fp64 = tcg_temp_new_i64();
11389 gen_load_fpr32(ctx, fp32, fs);
11390 if (ctx->nan2008) {
11391 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11392 } else {
11393 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11395 tcg_temp_free_i32(fp32);
11396 gen_store_fpr64(ctx, fp64, fd);
11397 tcg_temp_free_i64(fp64);
11399 break;
11400 case OPC_FLOOR_L_S:
11401 check_cp1_64bitmode(ctx);
11403 TCGv_i32 fp32 = tcg_temp_new_i32();
11404 TCGv_i64 fp64 = tcg_temp_new_i64();
11406 gen_load_fpr32(ctx, fp32, fs);
11407 if (ctx->nan2008) {
11408 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11409 } else {
11410 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11412 tcg_temp_free_i32(fp32);
11413 gen_store_fpr64(ctx, fp64, fd);
11414 tcg_temp_free_i64(fp64);
11416 break;
11417 case OPC_ROUND_W_S:
11419 TCGv_i32 fp0 = tcg_temp_new_i32();
11421 gen_load_fpr32(ctx, fp0, fs);
11422 if (ctx->nan2008) {
11423 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11424 } else {
11425 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11427 gen_store_fpr32(ctx, fp0, fd);
11428 tcg_temp_free_i32(fp0);
11430 break;
11431 case OPC_TRUNC_W_S:
11433 TCGv_i32 fp0 = tcg_temp_new_i32();
11435 gen_load_fpr32(ctx, fp0, fs);
11436 if (ctx->nan2008) {
11437 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11438 } else {
11439 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11441 gen_store_fpr32(ctx, fp0, fd);
11442 tcg_temp_free_i32(fp0);
11444 break;
11445 case OPC_CEIL_W_S:
11447 TCGv_i32 fp0 = tcg_temp_new_i32();
11449 gen_load_fpr32(ctx, fp0, fs);
11450 if (ctx->nan2008) {
11451 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11452 } else {
11453 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11455 gen_store_fpr32(ctx, fp0, fd);
11456 tcg_temp_free_i32(fp0);
11458 break;
11459 case OPC_FLOOR_W_S:
11461 TCGv_i32 fp0 = tcg_temp_new_i32();
11463 gen_load_fpr32(ctx, fp0, fs);
11464 if (ctx->nan2008) {
11465 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11466 } else {
11467 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11469 gen_store_fpr32(ctx, fp0, fd);
11470 tcg_temp_free_i32(fp0);
11472 break;
11473 case OPC_SEL_S:
11474 check_insn(ctx, ISA_MIPS32R6);
11475 gen_sel_s(ctx, op1, fd, ft, fs);
11476 break;
11477 case OPC_SELEQZ_S:
11478 check_insn(ctx, ISA_MIPS32R6);
11479 gen_sel_s(ctx, op1, fd, ft, fs);
11480 break;
11481 case OPC_SELNEZ_S:
11482 check_insn(ctx, ISA_MIPS32R6);
11483 gen_sel_s(ctx, op1, fd, ft, fs);
11484 break;
11485 case OPC_MOVCF_S:
11486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11487 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11488 break;
11489 case OPC_MOVZ_S:
11490 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11492 TCGLabel *l1 = gen_new_label();
11493 TCGv_i32 fp0;
11495 if (ft != 0) {
11496 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11498 fp0 = tcg_temp_new_i32();
11499 gen_load_fpr32(ctx, fp0, fs);
11500 gen_store_fpr32(ctx, fp0, fd);
11501 tcg_temp_free_i32(fp0);
11502 gen_set_label(l1);
11504 break;
11505 case OPC_MOVN_S:
11506 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11508 TCGLabel *l1 = gen_new_label();
11509 TCGv_i32 fp0;
11511 if (ft != 0) {
11512 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11513 fp0 = tcg_temp_new_i32();
11514 gen_load_fpr32(ctx, fp0, fs);
11515 gen_store_fpr32(ctx, fp0, fd);
11516 tcg_temp_free_i32(fp0);
11517 gen_set_label(l1);
11520 break;
11521 case OPC_RECIP_S:
11523 TCGv_i32 fp0 = tcg_temp_new_i32();
11525 gen_load_fpr32(ctx, fp0, fs);
11526 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11527 gen_store_fpr32(ctx, fp0, fd);
11528 tcg_temp_free_i32(fp0);
11530 break;
11531 case OPC_RSQRT_S:
11533 TCGv_i32 fp0 = tcg_temp_new_i32();
11535 gen_load_fpr32(ctx, fp0, fs);
11536 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11537 gen_store_fpr32(ctx, fp0, fd);
11538 tcg_temp_free_i32(fp0);
11540 break;
11541 case OPC_MADDF_S:
11542 check_insn(ctx, ISA_MIPS32R6);
11544 TCGv_i32 fp0 = tcg_temp_new_i32();
11545 TCGv_i32 fp1 = tcg_temp_new_i32();
11546 TCGv_i32 fp2 = tcg_temp_new_i32();
11547 gen_load_fpr32(ctx, fp0, fs);
11548 gen_load_fpr32(ctx, fp1, ft);
11549 gen_load_fpr32(ctx, fp2, fd);
11550 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11551 gen_store_fpr32(ctx, fp2, fd);
11552 tcg_temp_free_i32(fp2);
11553 tcg_temp_free_i32(fp1);
11554 tcg_temp_free_i32(fp0);
11556 break;
11557 case OPC_MSUBF_S:
11558 check_insn(ctx, ISA_MIPS32R6);
11560 TCGv_i32 fp0 = tcg_temp_new_i32();
11561 TCGv_i32 fp1 = tcg_temp_new_i32();
11562 TCGv_i32 fp2 = tcg_temp_new_i32();
11563 gen_load_fpr32(ctx, fp0, fs);
11564 gen_load_fpr32(ctx, fp1, ft);
11565 gen_load_fpr32(ctx, fp2, fd);
11566 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11567 gen_store_fpr32(ctx, fp2, fd);
11568 tcg_temp_free_i32(fp2);
11569 tcg_temp_free_i32(fp1);
11570 tcg_temp_free_i32(fp0);
11572 break;
11573 case OPC_RINT_S:
11574 check_insn(ctx, ISA_MIPS32R6);
11576 TCGv_i32 fp0 = tcg_temp_new_i32();
11577 gen_load_fpr32(ctx, fp0, fs);
11578 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11579 gen_store_fpr32(ctx, fp0, fd);
11580 tcg_temp_free_i32(fp0);
11582 break;
11583 case OPC_CLASS_S:
11584 check_insn(ctx, ISA_MIPS32R6);
11586 TCGv_i32 fp0 = tcg_temp_new_i32();
11587 gen_load_fpr32(ctx, fp0, fs);
11588 gen_helper_float_class_s(fp0, cpu_env, fp0);
11589 gen_store_fpr32(ctx, fp0, fd);
11590 tcg_temp_free_i32(fp0);
11592 break;
11593 case OPC_MIN_S: /* OPC_RECIP2_S */
11594 if (ctx->insn_flags & ISA_MIPS32R6) {
11595 /* OPC_MIN_S */
11596 TCGv_i32 fp0 = tcg_temp_new_i32();
11597 TCGv_i32 fp1 = tcg_temp_new_i32();
11598 TCGv_i32 fp2 = tcg_temp_new_i32();
11599 gen_load_fpr32(ctx, fp0, fs);
11600 gen_load_fpr32(ctx, fp1, ft);
11601 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11602 gen_store_fpr32(ctx, fp2, fd);
11603 tcg_temp_free_i32(fp2);
11604 tcg_temp_free_i32(fp1);
11605 tcg_temp_free_i32(fp0);
11606 } else {
11607 /* OPC_RECIP2_S */
11608 check_cp1_64bitmode(ctx);
11610 TCGv_i32 fp0 = tcg_temp_new_i32();
11611 TCGv_i32 fp1 = tcg_temp_new_i32();
11613 gen_load_fpr32(ctx, fp0, fs);
11614 gen_load_fpr32(ctx, fp1, ft);
11615 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11616 tcg_temp_free_i32(fp1);
11617 gen_store_fpr32(ctx, fp0, fd);
11618 tcg_temp_free_i32(fp0);
11621 break;
11622 case OPC_MINA_S: /* OPC_RECIP1_S */
11623 if (ctx->insn_flags & ISA_MIPS32R6) {
11624 /* OPC_MINA_S */
11625 TCGv_i32 fp0 = tcg_temp_new_i32();
11626 TCGv_i32 fp1 = tcg_temp_new_i32();
11627 TCGv_i32 fp2 = tcg_temp_new_i32();
11628 gen_load_fpr32(ctx, fp0, fs);
11629 gen_load_fpr32(ctx, fp1, ft);
11630 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11631 gen_store_fpr32(ctx, fp2, fd);
11632 tcg_temp_free_i32(fp2);
11633 tcg_temp_free_i32(fp1);
11634 tcg_temp_free_i32(fp0);
11635 } else {
11636 /* OPC_RECIP1_S */
11637 check_cp1_64bitmode(ctx);
11639 TCGv_i32 fp0 = tcg_temp_new_i32();
11641 gen_load_fpr32(ctx, fp0, fs);
11642 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11643 gen_store_fpr32(ctx, fp0, fd);
11644 tcg_temp_free_i32(fp0);
11647 break;
11648 case OPC_MAX_S: /* OPC_RSQRT1_S */
11649 if (ctx->insn_flags & ISA_MIPS32R6) {
11650 /* OPC_MAX_S */
11651 TCGv_i32 fp0 = tcg_temp_new_i32();
11652 TCGv_i32 fp1 = tcg_temp_new_i32();
11653 gen_load_fpr32(ctx, fp0, fs);
11654 gen_load_fpr32(ctx, fp1, ft);
11655 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11656 gen_store_fpr32(ctx, fp1, fd);
11657 tcg_temp_free_i32(fp1);
11658 tcg_temp_free_i32(fp0);
11659 } else {
11660 /* OPC_RSQRT1_S */
11661 check_cp1_64bitmode(ctx);
11663 TCGv_i32 fp0 = tcg_temp_new_i32();
11665 gen_load_fpr32(ctx, fp0, fs);
11666 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11667 gen_store_fpr32(ctx, fp0, fd);
11668 tcg_temp_free_i32(fp0);
11671 break;
11672 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11673 if (ctx->insn_flags & ISA_MIPS32R6) {
11674 /* OPC_MAXA_S */
11675 TCGv_i32 fp0 = tcg_temp_new_i32();
11676 TCGv_i32 fp1 = tcg_temp_new_i32();
11677 gen_load_fpr32(ctx, fp0, fs);
11678 gen_load_fpr32(ctx, fp1, ft);
11679 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11680 gen_store_fpr32(ctx, fp1, fd);
11681 tcg_temp_free_i32(fp1);
11682 tcg_temp_free_i32(fp0);
11683 } else {
11684 /* OPC_RSQRT2_S */
11685 check_cp1_64bitmode(ctx);
11687 TCGv_i32 fp0 = tcg_temp_new_i32();
11688 TCGv_i32 fp1 = tcg_temp_new_i32();
11690 gen_load_fpr32(ctx, fp0, fs);
11691 gen_load_fpr32(ctx, fp1, ft);
11692 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11693 tcg_temp_free_i32(fp1);
11694 gen_store_fpr32(ctx, fp0, fd);
11695 tcg_temp_free_i32(fp0);
11698 break;
11699 case OPC_CVT_D_S:
11700 check_cp1_registers(ctx, fd);
11702 TCGv_i32 fp32 = tcg_temp_new_i32();
11703 TCGv_i64 fp64 = tcg_temp_new_i64();
11705 gen_load_fpr32(ctx, fp32, fs);
11706 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11707 tcg_temp_free_i32(fp32);
11708 gen_store_fpr64(ctx, fp64, fd);
11709 tcg_temp_free_i64(fp64);
11711 break;
11712 case OPC_CVT_W_S:
11714 TCGv_i32 fp0 = tcg_temp_new_i32();
11716 gen_load_fpr32(ctx, fp0, fs);
11717 if (ctx->nan2008) {
11718 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11719 } else {
11720 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11722 gen_store_fpr32(ctx, fp0, fd);
11723 tcg_temp_free_i32(fp0);
11725 break;
11726 case OPC_CVT_L_S:
11727 check_cp1_64bitmode(ctx);
11729 TCGv_i32 fp32 = tcg_temp_new_i32();
11730 TCGv_i64 fp64 = tcg_temp_new_i64();
11732 gen_load_fpr32(ctx, fp32, fs);
11733 if (ctx->nan2008) {
11734 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11735 } else {
11736 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11738 tcg_temp_free_i32(fp32);
11739 gen_store_fpr64(ctx, fp64, fd);
11740 tcg_temp_free_i64(fp64);
11742 break;
11743 case OPC_CVT_PS_S:
11744 check_ps(ctx);
11746 TCGv_i64 fp64 = tcg_temp_new_i64();
11747 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11748 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11750 gen_load_fpr32(ctx, fp32_0, fs);
11751 gen_load_fpr32(ctx, fp32_1, ft);
11752 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11753 tcg_temp_free_i32(fp32_1);
11754 tcg_temp_free_i32(fp32_0);
11755 gen_store_fpr64(ctx, fp64, fd);
11756 tcg_temp_free_i64(fp64);
11758 break;
11759 case OPC_CMP_F_S:
11760 case OPC_CMP_UN_S:
11761 case OPC_CMP_EQ_S:
11762 case OPC_CMP_UEQ_S:
11763 case OPC_CMP_OLT_S:
11764 case OPC_CMP_ULT_S:
11765 case OPC_CMP_OLE_S:
11766 case OPC_CMP_ULE_S:
11767 case OPC_CMP_SF_S:
11768 case OPC_CMP_NGLE_S:
11769 case OPC_CMP_SEQ_S:
11770 case OPC_CMP_NGL_S:
11771 case OPC_CMP_LT_S:
11772 case OPC_CMP_NGE_S:
11773 case OPC_CMP_LE_S:
11774 case OPC_CMP_NGT_S:
11775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11776 if (ctx->opcode & (1 << 6)) {
11777 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11778 } else {
11779 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11781 break;
11782 case OPC_ADD_D:
11783 check_cp1_registers(ctx, fs | ft | fd);
11785 TCGv_i64 fp0 = tcg_temp_new_i64();
11786 TCGv_i64 fp1 = tcg_temp_new_i64();
11788 gen_load_fpr64(ctx, fp0, fs);
11789 gen_load_fpr64(ctx, fp1, ft);
11790 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11791 tcg_temp_free_i64(fp1);
11792 gen_store_fpr64(ctx, fp0, fd);
11793 tcg_temp_free_i64(fp0);
11795 break;
11796 case OPC_SUB_D:
11797 check_cp1_registers(ctx, fs | ft | fd);
11799 TCGv_i64 fp0 = tcg_temp_new_i64();
11800 TCGv_i64 fp1 = tcg_temp_new_i64();
11802 gen_load_fpr64(ctx, fp0, fs);
11803 gen_load_fpr64(ctx, fp1, ft);
11804 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11805 tcg_temp_free_i64(fp1);
11806 gen_store_fpr64(ctx, fp0, fd);
11807 tcg_temp_free_i64(fp0);
11809 break;
11810 case OPC_MUL_D:
11811 check_cp1_registers(ctx, fs | ft | fd);
11813 TCGv_i64 fp0 = tcg_temp_new_i64();
11814 TCGv_i64 fp1 = tcg_temp_new_i64();
11816 gen_load_fpr64(ctx, fp0, fs);
11817 gen_load_fpr64(ctx, fp1, ft);
11818 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11819 tcg_temp_free_i64(fp1);
11820 gen_store_fpr64(ctx, fp0, fd);
11821 tcg_temp_free_i64(fp0);
11823 break;
11824 case OPC_DIV_D:
11825 check_cp1_registers(ctx, fs | ft | fd);
11827 TCGv_i64 fp0 = tcg_temp_new_i64();
11828 TCGv_i64 fp1 = tcg_temp_new_i64();
11830 gen_load_fpr64(ctx, fp0, fs);
11831 gen_load_fpr64(ctx, fp1, ft);
11832 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11833 tcg_temp_free_i64(fp1);
11834 gen_store_fpr64(ctx, fp0, fd);
11835 tcg_temp_free_i64(fp0);
11837 break;
11838 case OPC_SQRT_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_sqrt_d(fp0, cpu_env, fp0);
11845 gen_store_fpr64(ctx, fp0, fd);
11846 tcg_temp_free_i64(fp0);
11848 break;
11849 case OPC_ABS_D:
11850 check_cp1_registers(ctx, fs | fd);
11852 TCGv_i64 fp0 = tcg_temp_new_i64();
11854 gen_load_fpr64(ctx, fp0, fs);
11855 if (ctx->abs2008) {
11856 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11857 } else {
11858 gen_helper_float_abs_d(fp0, fp0);
11860 gen_store_fpr64(ctx, fp0, fd);
11861 tcg_temp_free_i64(fp0);
11863 break;
11864 case OPC_MOV_D:
11865 check_cp1_registers(ctx, fs | fd);
11867 TCGv_i64 fp0 = tcg_temp_new_i64();
11869 gen_load_fpr64(ctx, fp0, fs);
11870 gen_store_fpr64(ctx, fp0, fd);
11871 tcg_temp_free_i64(fp0);
11873 break;
11874 case OPC_NEG_D:
11875 check_cp1_registers(ctx, fs | fd);
11877 TCGv_i64 fp0 = tcg_temp_new_i64();
11879 gen_load_fpr64(ctx, fp0, fs);
11880 if (ctx->abs2008) {
11881 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11882 } else {
11883 gen_helper_float_chs_d(fp0, fp0);
11885 gen_store_fpr64(ctx, fp0, fd);
11886 tcg_temp_free_i64(fp0);
11888 break;
11889 case OPC_ROUND_L_D:
11890 check_cp1_64bitmode(ctx);
11892 TCGv_i64 fp0 = tcg_temp_new_i64();
11894 gen_load_fpr64(ctx, fp0, fs);
11895 if (ctx->nan2008) {
11896 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11897 } else {
11898 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11900 gen_store_fpr64(ctx, fp0, fd);
11901 tcg_temp_free_i64(fp0);
11903 break;
11904 case OPC_TRUNC_L_D:
11905 check_cp1_64bitmode(ctx);
11907 TCGv_i64 fp0 = tcg_temp_new_i64();
11909 gen_load_fpr64(ctx, fp0, fs);
11910 if (ctx->nan2008) {
11911 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11912 } else {
11913 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11915 gen_store_fpr64(ctx, fp0, fd);
11916 tcg_temp_free_i64(fp0);
11918 break;
11919 case OPC_CEIL_L_D:
11920 check_cp1_64bitmode(ctx);
11922 TCGv_i64 fp0 = tcg_temp_new_i64();
11924 gen_load_fpr64(ctx, fp0, fs);
11925 if (ctx->nan2008) {
11926 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11927 } else {
11928 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11930 gen_store_fpr64(ctx, fp0, fd);
11931 tcg_temp_free_i64(fp0);
11933 break;
11934 case OPC_FLOOR_L_D:
11935 check_cp1_64bitmode(ctx);
11937 TCGv_i64 fp0 = tcg_temp_new_i64();
11939 gen_load_fpr64(ctx, fp0, fs);
11940 if (ctx->nan2008) {
11941 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11942 } else {
11943 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11945 gen_store_fpr64(ctx, fp0, fd);
11946 tcg_temp_free_i64(fp0);
11948 break;
11949 case OPC_ROUND_W_D:
11950 check_cp1_registers(ctx, fs);
11952 TCGv_i32 fp32 = tcg_temp_new_i32();
11953 TCGv_i64 fp64 = tcg_temp_new_i64();
11955 gen_load_fpr64(ctx, fp64, fs);
11956 if (ctx->nan2008) {
11957 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11958 } else {
11959 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11961 tcg_temp_free_i64(fp64);
11962 gen_store_fpr32(ctx, fp32, fd);
11963 tcg_temp_free_i32(fp32);
11965 break;
11966 case OPC_TRUNC_W_D:
11967 check_cp1_registers(ctx, fs);
11969 TCGv_i32 fp32 = tcg_temp_new_i32();
11970 TCGv_i64 fp64 = tcg_temp_new_i64();
11972 gen_load_fpr64(ctx, fp64, fs);
11973 if (ctx->nan2008) {
11974 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11975 } else {
11976 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11978 tcg_temp_free_i64(fp64);
11979 gen_store_fpr32(ctx, fp32, fd);
11980 tcg_temp_free_i32(fp32);
11982 break;
11983 case OPC_CEIL_W_D:
11984 check_cp1_registers(ctx, fs);
11986 TCGv_i32 fp32 = tcg_temp_new_i32();
11987 TCGv_i64 fp64 = tcg_temp_new_i64();
11989 gen_load_fpr64(ctx, fp64, fs);
11990 if (ctx->nan2008) {
11991 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11992 } else {
11993 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11995 tcg_temp_free_i64(fp64);
11996 gen_store_fpr32(ctx, fp32, fd);
11997 tcg_temp_free_i32(fp32);
11999 break;
12000 case OPC_FLOOR_W_D:
12001 check_cp1_registers(ctx, fs);
12003 TCGv_i32 fp32 = tcg_temp_new_i32();
12004 TCGv_i64 fp64 = tcg_temp_new_i64();
12006 gen_load_fpr64(ctx, fp64, fs);
12007 if (ctx->nan2008) {
12008 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12009 } else {
12010 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12012 tcg_temp_free_i64(fp64);
12013 gen_store_fpr32(ctx, fp32, fd);
12014 tcg_temp_free_i32(fp32);
12016 break;
12017 case OPC_SEL_D:
12018 check_insn(ctx, ISA_MIPS32R6);
12019 gen_sel_d(ctx, op1, fd, ft, fs);
12020 break;
12021 case OPC_SELEQZ_D:
12022 check_insn(ctx, ISA_MIPS32R6);
12023 gen_sel_d(ctx, op1, fd, ft, fs);
12024 break;
12025 case OPC_SELNEZ_D:
12026 check_insn(ctx, ISA_MIPS32R6);
12027 gen_sel_d(ctx, op1, fd, ft, fs);
12028 break;
12029 case OPC_MOVCF_D:
12030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12031 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12032 break;
12033 case OPC_MOVZ_D:
12034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12036 TCGLabel *l1 = gen_new_label();
12037 TCGv_i64 fp0;
12039 if (ft != 0) {
12040 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12042 fp0 = tcg_temp_new_i64();
12043 gen_load_fpr64(ctx, fp0, fs);
12044 gen_store_fpr64(ctx, fp0, fd);
12045 tcg_temp_free_i64(fp0);
12046 gen_set_label(l1);
12048 break;
12049 case OPC_MOVN_D:
12050 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12052 TCGLabel *l1 = gen_new_label();
12053 TCGv_i64 fp0;
12055 if (ft != 0) {
12056 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12057 fp0 = tcg_temp_new_i64();
12058 gen_load_fpr64(ctx, fp0, fs);
12059 gen_store_fpr64(ctx, fp0, fd);
12060 tcg_temp_free_i64(fp0);
12061 gen_set_label(l1);
12064 break;
12065 case OPC_RECIP_D:
12066 check_cp1_registers(ctx, fs | fd);
12068 TCGv_i64 fp0 = tcg_temp_new_i64();
12070 gen_load_fpr64(ctx, fp0, fs);
12071 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12072 gen_store_fpr64(ctx, fp0, fd);
12073 tcg_temp_free_i64(fp0);
12075 break;
12076 case OPC_RSQRT_D:
12077 check_cp1_registers(ctx, fs | fd);
12079 TCGv_i64 fp0 = tcg_temp_new_i64();
12081 gen_load_fpr64(ctx, fp0, fs);
12082 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12083 gen_store_fpr64(ctx, fp0, fd);
12084 tcg_temp_free_i64(fp0);
12086 break;
12087 case OPC_MADDF_D:
12088 check_insn(ctx, ISA_MIPS32R6);
12090 TCGv_i64 fp0 = tcg_temp_new_i64();
12091 TCGv_i64 fp1 = tcg_temp_new_i64();
12092 TCGv_i64 fp2 = tcg_temp_new_i64();
12093 gen_load_fpr64(ctx, fp0, fs);
12094 gen_load_fpr64(ctx, fp1, ft);
12095 gen_load_fpr64(ctx, fp2, fd);
12096 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12097 gen_store_fpr64(ctx, fp2, fd);
12098 tcg_temp_free_i64(fp2);
12099 tcg_temp_free_i64(fp1);
12100 tcg_temp_free_i64(fp0);
12102 break;
12103 case OPC_MSUBF_D:
12104 check_insn(ctx, ISA_MIPS32R6);
12106 TCGv_i64 fp0 = tcg_temp_new_i64();
12107 TCGv_i64 fp1 = tcg_temp_new_i64();
12108 TCGv_i64 fp2 = tcg_temp_new_i64();
12109 gen_load_fpr64(ctx, fp0, fs);
12110 gen_load_fpr64(ctx, fp1, ft);
12111 gen_load_fpr64(ctx, fp2, fd);
12112 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12113 gen_store_fpr64(ctx, fp2, fd);
12114 tcg_temp_free_i64(fp2);
12115 tcg_temp_free_i64(fp1);
12116 tcg_temp_free_i64(fp0);
12118 break;
12119 case OPC_RINT_D:
12120 check_insn(ctx, ISA_MIPS32R6);
12122 TCGv_i64 fp0 = tcg_temp_new_i64();
12123 gen_load_fpr64(ctx, fp0, fs);
12124 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12125 gen_store_fpr64(ctx, fp0, fd);
12126 tcg_temp_free_i64(fp0);
12128 break;
12129 case OPC_CLASS_D:
12130 check_insn(ctx, ISA_MIPS32R6);
12132 TCGv_i64 fp0 = tcg_temp_new_i64();
12133 gen_load_fpr64(ctx, fp0, fs);
12134 gen_helper_float_class_d(fp0, cpu_env, fp0);
12135 gen_store_fpr64(ctx, fp0, fd);
12136 tcg_temp_free_i64(fp0);
12138 break;
12139 case OPC_MIN_D: /* OPC_RECIP2_D */
12140 if (ctx->insn_flags & ISA_MIPS32R6) {
12141 /* OPC_MIN_D */
12142 TCGv_i64 fp0 = tcg_temp_new_i64();
12143 TCGv_i64 fp1 = tcg_temp_new_i64();
12144 gen_load_fpr64(ctx, fp0, fs);
12145 gen_load_fpr64(ctx, fp1, ft);
12146 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12147 gen_store_fpr64(ctx, fp1, fd);
12148 tcg_temp_free_i64(fp1);
12149 tcg_temp_free_i64(fp0);
12150 } else {
12151 /* OPC_RECIP2_D */
12152 check_cp1_64bitmode(ctx);
12154 TCGv_i64 fp0 = tcg_temp_new_i64();
12155 TCGv_i64 fp1 = tcg_temp_new_i64();
12157 gen_load_fpr64(ctx, fp0, fs);
12158 gen_load_fpr64(ctx, fp1, ft);
12159 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12160 tcg_temp_free_i64(fp1);
12161 gen_store_fpr64(ctx, fp0, fd);
12162 tcg_temp_free_i64(fp0);
12165 break;
12166 case OPC_MINA_D: /* OPC_RECIP1_D */
12167 if (ctx->insn_flags & ISA_MIPS32R6) {
12168 /* OPC_MINA_D */
12169 TCGv_i64 fp0 = tcg_temp_new_i64();
12170 TCGv_i64 fp1 = tcg_temp_new_i64();
12171 gen_load_fpr64(ctx, fp0, fs);
12172 gen_load_fpr64(ctx, fp1, ft);
12173 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12174 gen_store_fpr64(ctx, fp1, fd);
12175 tcg_temp_free_i64(fp1);
12176 tcg_temp_free_i64(fp0);
12177 } else {
12178 /* OPC_RECIP1_D */
12179 check_cp1_64bitmode(ctx);
12181 TCGv_i64 fp0 = tcg_temp_new_i64();
12183 gen_load_fpr64(ctx, fp0, fs);
12184 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12185 gen_store_fpr64(ctx, fp0, fd);
12186 tcg_temp_free_i64(fp0);
12189 break;
12190 case OPC_MAX_D: /* OPC_RSQRT1_D */
12191 if (ctx->insn_flags & ISA_MIPS32R6) {
12192 /* OPC_MAX_D */
12193 TCGv_i64 fp0 = tcg_temp_new_i64();
12194 TCGv_i64 fp1 = tcg_temp_new_i64();
12195 gen_load_fpr64(ctx, fp0, fs);
12196 gen_load_fpr64(ctx, fp1, ft);
12197 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12198 gen_store_fpr64(ctx, fp1, fd);
12199 tcg_temp_free_i64(fp1);
12200 tcg_temp_free_i64(fp0);
12201 } else {
12202 /* OPC_RSQRT1_D */
12203 check_cp1_64bitmode(ctx);
12205 TCGv_i64 fp0 = tcg_temp_new_i64();
12207 gen_load_fpr64(ctx, fp0, fs);
12208 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12209 gen_store_fpr64(ctx, fp0, fd);
12210 tcg_temp_free_i64(fp0);
12213 break;
12214 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12215 if (ctx->insn_flags & ISA_MIPS32R6) {
12216 /* OPC_MAXA_D */
12217 TCGv_i64 fp0 = tcg_temp_new_i64();
12218 TCGv_i64 fp1 = tcg_temp_new_i64();
12219 gen_load_fpr64(ctx, fp0, fs);
12220 gen_load_fpr64(ctx, fp1, ft);
12221 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12222 gen_store_fpr64(ctx, fp1, fd);
12223 tcg_temp_free_i64(fp1);
12224 tcg_temp_free_i64(fp0);
12225 } else {
12226 /* OPC_RSQRT2_D */
12227 check_cp1_64bitmode(ctx);
12229 TCGv_i64 fp0 = tcg_temp_new_i64();
12230 TCGv_i64 fp1 = tcg_temp_new_i64();
12232 gen_load_fpr64(ctx, fp0, fs);
12233 gen_load_fpr64(ctx, fp1, ft);
12234 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12235 tcg_temp_free_i64(fp1);
12236 gen_store_fpr64(ctx, fp0, fd);
12237 tcg_temp_free_i64(fp0);
12240 break;
12241 case OPC_CMP_F_D:
12242 case OPC_CMP_UN_D:
12243 case OPC_CMP_EQ_D:
12244 case OPC_CMP_UEQ_D:
12245 case OPC_CMP_OLT_D:
12246 case OPC_CMP_ULT_D:
12247 case OPC_CMP_OLE_D:
12248 case OPC_CMP_ULE_D:
12249 case OPC_CMP_SF_D:
12250 case OPC_CMP_NGLE_D:
12251 case OPC_CMP_SEQ_D:
12252 case OPC_CMP_NGL_D:
12253 case OPC_CMP_LT_D:
12254 case OPC_CMP_NGE_D:
12255 case OPC_CMP_LE_D:
12256 case OPC_CMP_NGT_D:
12257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12258 if (ctx->opcode & (1 << 6)) {
12259 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12260 } else {
12261 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12263 break;
12264 case OPC_CVT_S_D:
12265 check_cp1_registers(ctx, fs);
12267 TCGv_i32 fp32 = tcg_temp_new_i32();
12268 TCGv_i64 fp64 = tcg_temp_new_i64();
12270 gen_load_fpr64(ctx, fp64, fs);
12271 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12272 tcg_temp_free_i64(fp64);
12273 gen_store_fpr32(ctx, fp32, fd);
12274 tcg_temp_free_i32(fp32);
12276 break;
12277 case OPC_CVT_W_D:
12278 check_cp1_registers(ctx, fs);
12280 TCGv_i32 fp32 = tcg_temp_new_i32();
12281 TCGv_i64 fp64 = tcg_temp_new_i64();
12283 gen_load_fpr64(ctx, fp64, fs);
12284 if (ctx->nan2008) {
12285 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12286 } else {
12287 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12289 tcg_temp_free_i64(fp64);
12290 gen_store_fpr32(ctx, fp32, fd);
12291 tcg_temp_free_i32(fp32);
12293 break;
12294 case OPC_CVT_L_D:
12295 check_cp1_64bitmode(ctx);
12297 TCGv_i64 fp0 = tcg_temp_new_i64();
12299 gen_load_fpr64(ctx, fp0, fs);
12300 if (ctx->nan2008) {
12301 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12302 } else {
12303 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12305 gen_store_fpr64(ctx, fp0, fd);
12306 tcg_temp_free_i64(fp0);
12308 break;
12309 case OPC_CVT_S_W:
12311 TCGv_i32 fp0 = tcg_temp_new_i32();
12313 gen_load_fpr32(ctx, fp0, fs);
12314 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12315 gen_store_fpr32(ctx, fp0, fd);
12316 tcg_temp_free_i32(fp0);
12318 break;
12319 case OPC_CVT_D_W:
12320 check_cp1_registers(ctx, fd);
12322 TCGv_i32 fp32 = tcg_temp_new_i32();
12323 TCGv_i64 fp64 = tcg_temp_new_i64();
12325 gen_load_fpr32(ctx, fp32, fs);
12326 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12327 tcg_temp_free_i32(fp32);
12328 gen_store_fpr64(ctx, fp64, fd);
12329 tcg_temp_free_i64(fp64);
12331 break;
12332 case OPC_CVT_S_L:
12333 check_cp1_64bitmode(ctx);
12335 TCGv_i32 fp32 = tcg_temp_new_i32();
12336 TCGv_i64 fp64 = tcg_temp_new_i64();
12338 gen_load_fpr64(ctx, fp64, fs);
12339 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12340 tcg_temp_free_i64(fp64);
12341 gen_store_fpr32(ctx, fp32, fd);
12342 tcg_temp_free_i32(fp32);
12344 break;
12345 case OPC_CVT_D_L:
12346 check_cp1_64bitmode(ctx);
12348 TCGv_i64 fp0 = tcg_temp_new_i64();
12350 gen_load_fpr64(ctx, fp0, fs);
12351 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12352 gen_store_fpr64(ctx, fp0, fd);
12353 tcg_temp_free_i64(fp0);
12355 break;
12356 case OPC_CVT_PS_PW:
12357 check_ps(ctx);
12359 TCGv_i64 fp0 = tcg_temp_new_i64();
12361 gen_load_fpr64(ctx, fp0, fs);
12362 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12363 gen_store_fpr64(ctx, fp0, fd);
12364 tcg_temp_free_i64(fp0);
12366 break;
12367 case OPC_ADD_PS:
12368 check_ps(ctx);
12370 TCGv_i64 fp0 = tcg_temp_new_i64();
12371 TCGv_i64 fp1 = tcg_temp_new_i64();
12373 gen_load_fpr64(ctx, fp0, fs);
12374 gen_load_fpr64(ctx, fp1, ft);
12375 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12376 tcg_temp_free_i64(fp1);
12377 gen_store_fpr64(ctx, fp0, fd);
12378 tcg_temp_free_i64(fp0);
12380 break;
12381 case OPC_SUB_PS:
12382 check_ps(ctx);
12384 TCGv_i64 fp0 = tcg_temp_new_i64();
12385 TCGv_i64 fp1 = tcg_temp_new_i64();
12387 gen_load_fpr64(ctx, fp0, fs);
12388 gen_load_fpr64(ctx, fp1, ft);
12389 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12390 tcg_temp_free_i64(fp1);
12391 gen_store_fpr64(ctx, fp0, fd);
12392 tcg_temp_free_i64(fp0);
12394 break;
12395 case OPC_MUL_PS:
12396 check_ps(ctx);
12398 TCGv_i64 fp0 = tcg_temp_new_i64();
12399 TCGv_i64 fp1 = tcg_temp_new_i64();
12401 gen_load_fpr64(ctx, fp0, fs);
12402 gen_load_fpr64(ctx, fp1, ft);
12403 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12404 tcg_temp_free_i64(fp1);
12405 gen_store_fpr64(ctx, fp0, fd);
12406 tcg_temp_free_i64(fp0);
12408 break;
12409 case OPC_ABS_PS:
12410 check_ps(ctx);
12412 TCGv_i64 fp0 = tcg_temp_new_i64();
12414 gen_load_fpr64(ctx, fp0, fs);
12415 gen_helper_float_abs_ps(fp0, fp0);
12416 gen_store_fpr64(ctx, fp0, fd);
12417 tcg_temp_free_i64(fp0);
12419 break;
12420 case OPC_MOV_PS:
12421 check_ps(ctx);
12423 TCGv_i64 fp0 = tcg_temp_new_i64();
12425 gen_load_fpr64(ctx, fp0, fs);
12426 gen_store_fpr64(ctx, fp0, fd);
12427 tcg_temp_free_i64(fp0);
12429 break;
12430 case OPC_NEG_PS:
12431 check_ps(ctx);
12433 TCGv_i64 fp0 = tcg_temp_new_i64();
12435 gen_load_fpr64(ctx, fp0, fs);
12436 gen_helper_float_chs_ps(fp0, fp0);
12437 gen_store_fpr64(ctx, fp0, fd);
12438 tcg_temp_free_i64(fp0);
12440 break;
12441 case OPC_MOVCF_PS:
12442 check_ps(ctx);
12443 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12444 break;
12445 case OPC_MOVZ_PS:
12446 check_ps(ctx);
12448 TCGLabel *l1 = gen_new_label();
12449 TCGv_i64 fp0;
12451 if (ft != 0) {
12452 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12454 fp0 = tcg_temp_new_i64();
12455 gen_load_fpr64(ctx, fp0, fs);
12456 gen_store_fpr64(ctx, fp0, fd);
12457 tcg_temp_free_i64(fp0);
12458 gen_set_label(l1);
12460 break;
12461 case OPC_MOVN_PS:
12462 check_ps(ctx);
12464 TCGLabel *l1 = gen_new_label();
12465 TCGv_i64 fp0;
12467 if (ft != 0) {
12468 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12469 fp0 = tcg_temp_new_i64();
12470 gen_load_fpr64(ctx, fp0, fs);
12471 gen_store_fpr64(ctx, fp0, fd);
12472 tcg_temp_free_i64(fp0);
12473 gen_set_label(l1);
12476 break;
12477 case OPC_ADDR_PS:
12478 check_ps(ctx);
12480 TCGv_i64 fp0 = tcg_temp_new_i64();
12481 TCGv_i64 fp1 = tcg_temp_new_i64();
12483 gen_load_fpr64(ctx, fp0, ft);
12484 gen_load_fpr64(ctx, fp1, fs);
12485 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12486 tcg_temp_free_i64(fp1);
12487 gen_store_fpr64(ctx, fp0, fd);
12488 tcg_temp_free_i64(fp0);
12490 break;
12491 case OPC_MULR_PS:
12492 check_ps(ctx);
12494 TCGv_i64 fp0 = tcg_temp_new_i64();
12495 TCGv_i64 fp1 = tcg_temp_new_i64();
12497 gen_load_fpr64(ctx, fp0, ft);
12498 gen_load_fpr64(ctx, fp1, fs);
12499 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12500 tcg_temp_free_i64(fp1);
12501 gen_store_fpr64(ctx, fp0, fd);
12502 tcg_temp_free_i64(fp0);
12504 break;
12505 case OPC_RECIP2_PS:
12506 check_ps(ctx);
12508 TCGv_i64 fp0 = tcg_temp_new_i64();
12509 TCGv_i64 fp1 = tcg_temp_new_i64();
12511 gen_load_fpr64(ctx, fp0, fs);
12512 gen_load_fpr64(ctx, fp1, ft);
12513 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12514 tcg_temp_free_i64(fp1);
12515 gen_store_fpr64(ctx, fp0, fd);
12516 tcg_temp_free_i64(fp0);
12518 break;
12519 case OPC_RECIP1_PS:
12520 check_ps(ctx);
12522 TCGv_i64 fp0 = tcg_temp_new_i64();
12524 gen_load_fpr64(ctx, fp0, fs);
12525 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12526 gen_store_fpr64(ctx, fp0, fd);
12527 tcg_temp_free_i64(fp0);
12529 break;
12530 case OPC_RSQRT1_PS:
12531 check_ps(ctx);
12533 TCGv_i64 fp0 = tcg_temp_new_i64();
12535 gen_load_fpr64(ctx, fp0, fs);
12536 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12537 gen_store_fpr64(ctx, fp0, fd);
12538 tcg_temp_free_i64(fp0);
12540 break;
12541 case OPC_RSQRT2_PS:
12542 check_ps(ctx);
12544 TCGv_i64 fp0 = tcg_temp_new_i64();
12545 TCGv_i64 fp1 = tcg_temp_new_i64();
12547 gen_load_fpr64(ctx, fp0, fs);
12548 gen_load_fpr64(ctx, fp1, ft);
12549 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12550 tcg_temp_free_i64(fp1);
12551 gen_store_fpr64(ctx, fp0, fd);
12552 tcg_temp_free_i64(fp0);
12554 break;
12555 case OPC_CVT_S_PU:
12556 check_cp1_64bitmode(ctx);
12558 TCGv_i32 fp0 = tcg_temp_new_i32();
12560 gen_load_fpr32h(ctx, fp0, fs);
12561 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12562 gen_store_fpr32(ctx, fp0, fd);
12563 tcg_temp_free_i32(fp0);
12565 break;
12566 case OPC_CVT_PW_PS:
12567 check_ps(ctx);
12569 TCGv_i64 fp0 = tcg_temp_new_i64();
12571 gen_load_fpr64(ctx, fp0, fs);
12572 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12573 gen_store_fpr64(ctx, fp0, fd);
12574 tcg_temp_free_i64(fp0);
12576 break;
12577 case OPC_CVT_S_PL:
12578 check_cp1_64bitmode(ctx);
12580 TCGv_i32 fp0 = tcg_temp_new_i32();
12582 gen_load_fpr32(ctx, fp0, fs);
12583 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12584 gen_store_fpr32(ctx, fp0, fd);
12585 tcg_temp_free_i32(fp0);
12587 break;
12588 case OPC_PLL_PS:
12589 check_ps(ctx);
12591 TCGv_i32 fp0 = tcg_temp_new_i32();
12592 TCGv_i32 fp1 = tcg_temp_new_i32();
12594 gen_load_fpr32(ctx, fp0, fs);
12595 gen_load_fpr32(ctx, fp1, ft);
12596 gen_store_fpr32h(ctx, fp0, fd);
12597 gen_store_fpr32(ctx, fp1, fd);
12598 tcg_temp_free_i32(fp0);
12599 tcg_temp_free_i32(fp1);
12601 break;
12602 case OPC_PLU_PS:
12603 check_ps(ctx);
12605 TCGv_i32 fp0 = tcg_temp_new_i32();
12606 TCGv_i32 fp1 = tcg_temp_new_i32();
12608 gen_load_fpr32(ctx, fp0, fs);
12609 gen_load_fpr32h(ctx, fp1, ft);
12610 gen_store_fpr32(ctx, fp1, fd);
12611 gen_store_fpr32h(ctx, fp0, fd);
12612 tcg_temp_free_i32(fp0);
12613 tcg_temp_free_i32(fp1);
12615 break;
12616 case OPC_PUL_PS:
12617 check_ps(ctx);
12619 TCGv_i32 fp0 = tcg_temp_new_i32();
12620 TCGv_i32 fp1 = tcg_temp_new_i32();
12622 gen_load_fpr32h(ctx, fp0, fs);
12623 gen_load_fpr32(ctx, fp1, ft);
12624 gen_store_fpr32(ctx, fp1, fd);
12625 gen_store_fpr32h(ctx, fp0, fd);
12626 tcg_temp_free_i32(fp0);
12627 tcg_temp_free_i32(fp1);
12629 break;
12630 case OPC_PUU_PS:
12631 check_ps(ctx);
12633 TCGv_i32 fp0 = tcg_temp_new_i32();
12634 TCGv_i32 fp1 = tcg_temp_new_i32();
12636 gen_load_fpr32h(ctx, fp0, fs);
12637 gen_load_fpr32h(ctx, fp1, ft);
12638 gen_store_fpr32(ctx, fp1, fd);
12639 gen_store_fpr32h(ctx, fp0, fd);
12640 tcg_temp_free_i32(fp0);
12641 tcg_temp_free_i32(fp1);
12643 break;
12644 case OPC_CMP_F_PS:
12645 case OPC_CMP_UN_PS:
12646 case OPC_CMP_EQ_PS:
12647 case OPC_CMP_UEQ_PS:
12648 case OPC_CMP_OLT_PS:
12649 case OPC_CMP_ULT_PS:
12650 case OPC_CMP_OLE_PS:
12651 case OPC_CMP_ULE_PS:
12652 case OPC_CMP_SF_PS:
12653 case OPC_CMP_NGLE_PS:
12654 case OPC_CMP_SEQ_PS:
12655 case OPC_CMP_NGL_PS:
12656 case OPC_CMP_LT_PS:
12657 case OPC_CMP_NGE_PS:
12658 case OPC_CMP_LE_PS:
12659 case OPC_CMP_NGT_PS:
12660 if (ctx->opcode & (1 << 6)) {
12661 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12662 } else {
12663 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12665 break;
12666 default:
12667 MIPS_INVAL("farith");
12668 generate_exception_end(ctx, EXCP_RI);
12669 return;
12673 /* Coprocessor 3 (FPU) */
12674 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12675 int fd, int fs, int base, int index)
12677 TCGv t0 = tcg_temp_new();
12679 if (base == 0) {
12680 gen_load_gpr(t0, index);
12681 } else if (index == 0) {
12682 gen_load_gpr(t0, base);
12683 } else {
12684 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12687 * Don't do NOP if destination is zero: we must perform the actual
12688 * memory access.
12690 switch (opc) {
12691 case OPC_LWXC1:
12692 check_cop1x(ctx);
12694 TCGv_i32 fp0 = tcg_temp_new_i32();
12696 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12697 tcg_gen_trunc_tl_i32(fp0, t0);
12698 gen_store_fpr32(ctx, fp0, fd);
12699 tcg_temp_free_i32(fp0);
12701 break;
12702 case OPC_LDXC1:
12703 check_cop1x(ctx);
12704 check_cp1_registers(ctx, fd);
12706 TCGv_i64 fp0 = tcg_temp_new_i64();
12707 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12708 gen_store_fpr64(ctx, fp0, fd);
12709 tcg_temp_free_i64(fp0);
12711 break;
12712 case OPC_LUXC1:
12713 check_cp1_64bitmode(ctx);
12714 tcg_gen_andi_tl(t0, t0, ~0x7);
12716 TCGv_i64 fp0 = tcg_temp_new_i64();
12718 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12719 gen_store_fpr64(ctx, fp0, fd);
12720 tcg_temp_free_i64(fp0);
12722 break;
12723 case OPC_SWXC1:
12724 check_cop1x(ctx);
12726 TCGv_i32 fp0 = tcg_temp_new_i32();
12727 gen_load_fpr32(ctx, fp0, fs);
12728 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12729 tcg_temp_free_i32(fp0);
12731 break;
12732 case OPC_SDXC1:
12733 check_cop1x(ctx);
12734 check_cp1_registers(ctx, fs);
12736 TCGv_i64 fp0 = tcg_temp_new_i64();
12737 gen_load_fpr64(ctx, fp0, fs);
12738 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12739 tcg_temp_free_i64(fp0);
12741 break;
12742 case OPC_SUXC1:
12743 check_cp1_64bitmode(ctx);
12744 tcg_gen_andi_tl(t0, t0, ~0x7);
12746 TCGv_i64 fp0 = tcg_temp_new_i64();
12747 gen_load_fpr64(ctx, fp0, fs);
12748 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12749 tcg_temp_free_i64(fp0);
12751 break;
12753 tcg_temp_free(t0);
12756 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12757 int fd, int fr, int fs, int ft)
12759 switch (opc) {
12760 case OPC_ALNV_PS:
12761 check_ps(ctx);
12763 TCGv t0 = tcg_temp_local_new();
12764 TCGv_i32 fp = tcg_temp_new_i32();
12765 TCGv_i32 fph = tcg_temp_new_i32();
12766 TCGLabel *l1 = gen_new_label();
12767 TCGLabel *l2 = gen_new_label();
12769 gen_load_gpr(t0, fr);
12770 tcg_gen_andi_tl(t0, t0, 0x7);
12772 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12773 gen_load_fpr32(ctx, fp, fs);
12774 gen_load_fpr32h(ctx, fph, fs);
12775 gen_store_fpr32(ctx, fp, fd);
12776 gen_store_fpr32h(ctx, fph, fd);
12777 tcg_gen_br(l2);
12778 gen_set_label(l1);
12779 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12780 tcg_temp_free(t0);
12781 #ifdef TARGET_WORDS_BIGENDIAN
12782 gen_load_fpr32(ctx, fp, fs);
12783 gen_load_fpr32h(ctx, fph, ft);
12784 gen_store_fpr32h(ctx, fp, fd);
12785 gen_store_fpr32(ctx, fph, fd);
12786 #else
12787 gen_load_fpr32h(ctx, fph, fs);
12788 gen_load_fpr32(ctx, fp, ft);
12789 gen_store_fpr32(ctx, fph, fd);
12790 gen_store_fpr32h(ctx, fp, fd);
12791 #endif
12792 gen_set_label(l2);
12793 tcg_temp_free_i32(fp);
12794 tcg_temp_free_i32(fph);
12796 break;
12797 case OPC_MADD_S:
12798 check_cop1x(ctx);
12800 TCGv_i32 fp0 = tcg_temp_new_i32();
12801 TCGv_i32 fp1 = tcg_temp_new_i32();
12802 TCGv_i32 fp2 = tcg_temp_new_i32();
12804 gen_load_fpr32(ctx, fp0, fs);
12805 gen_load_fpr32(ctx, fp1, ft);
12806 gen_load_fpr32(ctx, fp2, fr);
12807 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12808 tcg_temp_free_i32(fp0);
12809 tcg_temp_free_i32(fp1);
12810 gen_store_fpr32(ctx, fp2, fd);
12811 tcg_temp_free_i32(fp2);
12813 break;
12814 case OPC_MADD_D:
12815 check_cop1x(ctx);
12816 check_cp1_registers(ctx, fd | fs | ft | fr);
12818 TCGv_i64 fp0 = tcg_temp_new_i64();
12819 TCGv_i64 fp1 = tcg_temp_new_i64();
12820 TCGv_i64 fp2 = tcg_temp_new_i64();
12822 gen_load_fpr64(ctx, fp0, fs);
12823 gen_load_fpr64(ctx, fp1, ft);
12824 gen_load_fpr64(ctx, fp2, fr);
12825 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12826 tcg_temp_free_i64(fp0);
12827 tcg_temp_free_i64(fp1);
12828 gen_store_fpr64(ctx, fp2, fd);
12829 tcg_temp_free_i64(fp2);
12831 break;
12832 case OPC_MADD_PS:
12833 check_ps(ctx);
12835 TCGv_i64 fp0 = tcg_temp_new_i64();
12836 TCGv_i64 fp1 = tcg_temp_new_i64();
12837 TCGv_i64 fp2 = tcg_temp_new_i64();
12839 gen_load_fpr64(ctx, fp0, fs);
12840 gen_load_fpr64(ctx, fp1, ft);
12841 gen_load_fpr64(ctx, fp2, fr);
12842 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12843 tcg_temp_free_i64(fp0);
12844 tcg_temp_free_i64(fp1);
12845 gen_store_fpr64(ctx, fp2, fd);
12846 tcg_temp_free_i64(fp2);
12848 break;
12849 case OPC_MSUB_S:
12850 check_cop1x(ctx);
12852 TCGv_i32 fp0 = tcg_temp_new_i32();
12853 TCGv_i32 fp1 = tcg_temp_new_i32();
12854 TCGv_i32 fp2 = tcg_temp_new_i32();
12856 gen_load_fpr32(ctx, fp0, fs);
12857 gen_load_fpr32(ctx, fp1, ft);
12858 gen_load_fpr32(ctx, fp2, fr);
12859 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12860 tcg_temp_free_i32(fp0);
12861 tcg_temp_free_i32(fp1);
12862 gen_store_fpr32(ctx, fp2, fd);
12863 tcg_temp_free_i32(fp2);
12865 break;
12866 case OPC_MSUB_D:
12867 check_cop1x(ctx);
12868 check_cp1_registers(ctx, fd | fs | ft | fr);
12870 TCGv_i64 fp0 = tcg_temp_new_i64();
12871 TCGv_i64 fp1 = tcg_temp_new_i64();
12872 TCGv_i64 fp2 = tcg_temp_new_i64();
12874 gen_load_fpr64(ctx, fp0, fs);
12875 gen_load_fpr64(ctx, fp1, ft);
12876 gen_load_fpr64(ctx, fp2, fr);
12877 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12878 tcg_temp_free_i64(fp0);
12879 tcg_temp_free_i64(fp1);
12880 gen_store_fpr64(ctx, fp2, fd);
12881 tcg_temp_free_i64(fp2);
12883 break;
12884 case OPC_MSUB_PS:
12885 check_ps(ctx);
12887 TCGv_i64 fp0 = tcg_temp_new_i64();
12888 TCGv_i64 fp1 = tcg_temp_new_i64();
12889 TCGv_i64 fp2 = tcg_temp_new_i64();
12891 gen_load_fpr64(ctx, fp0, fs);
12892 gen_load_fpr64(ctx, fp1, ft);
12893 gen_load_fpr64(ctx, fp2, fr);
12894 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12895 tcg_temp_free_i64(fp0);
12896 tcg_temp_free_i64(fp1);
12897 gen_store_fpr64(ctx, fp2, fd);
12898 tcg_temp_free_i64(fp2);
12900 break;
12901 case OPC_NMADD_S:
12902 check_cop1x(ctx);
12904 TCGv_i32 fp0 = tcg_temp_new_i32();
12905 TCGv_i32 fp1 = tcg_temp_new_i32();
12906 TCGv_i32 fp2 = tcg_temp_new_i32();
12908 gen_load_fpr32(ctx, fp0, fs);
12909 gen_load_fpr32(ctx, fp1, ft);
12910 gen_load_fpr32(ctx, fp2, fr);
12911 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12912 tcg_temp_free_i32(fp0);
12913 tcg_temp_free_i32(fp1);
12914 gen_store_fpr32(ctx, fp2, fd);
12915 tcg_temp_free_i32(fp2);
12917 break;
12918 case OPC_NMADD_D:
12919 check_cop1x(ctx);
12920 check_cp1_registers(ctx, fd | fs | ft | fr);
12922 TCGv_i64 fp0 = tcg_temp_new_i64();
12923 TCGv_i64 fp1 = tcg_temp_new_i64();
12924 TCGv_i64 fp2 = tcg_temp_new_i64();
12926 gen_load_fpr64(ctx, fp0, fs);
12927 gen_load_fpr64(ctx, fp1, ft);
12928 gen_load_fpr64(ctx, fp2, fr);
12929 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12930 tcg_temp_free_i64(fp0);
12931 tcg_temp_free_i64(fp1);
12932 gen_store_fpr64(ctx, fp2, fd);
12933 tcg_temp_free_i64(fp2);
12935 break;
12936 case OPC_NMADD_PS:
12937 check_ps(ctx);
12939 TCGv_i64 fp0 = tcg_temp_new_i64();
12940 TCGv_i64 fp1 = tcg_temp_new_i64();
12941 TCGv_i64 fp2 = tcg_temp_new_i64();
12943 gen_load_fpr64(ctx, fp0, fs);
12944 gen_load_fpr64(ctx, fp1, ft);
12945 gen_load_fpr64(ctx, fp2, fr);
12946 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12947 tcg_temp_free_i64(fp0);
12948 tcg_temp_free_i64(fp1);
12949 gen_store_fpr64(ctx, fp2, fd);
12950 tcg_temp_free_i64(fp2);
12952 break;
12953 case OPC_NMSUB_S:
12954 check_cop1x(ctx);
12956 TCGv_i32 fp0 = tcg_temp_new_i32();
12957 TCGv_i32 fp1 = tcg_temp_new_i32();
12958 TCGv_i32 fp2 = tcg_temp_new_i32();
12960 gen_load_fpr32(ctx, fp0, fs);
12961 gen_load_fpr32(ctx, fp1, ft);
12962 gen_load_fpr32(ctx, fp2, fr);
12963 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12964 tcg_temp_free_i32(fp0);
12965 tcg_temp_free_i32(fp1);
12966 gen_store_fpr32(ctx, fp2, fd);
12967 tcg_temp_free_i32(fp2);
12969 break;
12970 case OPC_NMSUB_D:
12971 check_cop1x(ctx);
12972 check_cp1_registers(ctx, fd | fs | ft | fr);
12974 TCGv_i64 fp0 = tcg_temp_new_i64();
12975 TCGv_i64 fp1 = tcg_temp_new_i64();
12976 TCGv_i64 fp2 = tcg_temp_new_i64();
12978 gen_load_fpr64(ctx, fp0, fs);
12979 gen_load_fpr64(ctx, fp1, ft);
12980 gen_load_fpr64(ctx, fp2, fr);
12981 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12982 tcg_temp_free_i64(fp0);
12983 tcg_temp_free_i64(fp1);
12984 gen_store_fpr64(ctx, fp2, fd);
12985 tcg_temp_free_i64(fp2);
12987 break;
12988 case OPC_NMSUB_PS:
12989 check_ps(ctx);
12991 TCGv_i64 fp0 = tcg_temp_new_i64();
12992 TCGv_i64 fp1 = tcg_temp_new_i64();
12993 TCGv_i64 fp2 = tcg_temp_new_i64();
12995 gen_load_fpr64(ctx, fp0, fs);
12996 gen_load_fpr64(ctx, fp1, ft);
12997 gen_load_fpr64(ctx, fp2, fr);
12998 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12999 tcg_temp_free_i64(fp0);
13000 tcg_temp_free_i64(fp1);
13001 gen_store_fpr64(ctx, fp2, fd);
13002 tcg_temp_free_i64(fp2);
13004 break;
13005 default:
13006 MIPS_INVAL("flt3_arith");
13007 generate_exception_end(ctx, EXCP_RI);
13008 return;
13012 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13014 TCGv t0;
13016 #if !defined(CONFIG_USER_ONLY)
13018 * The Linux kernel will emulate rdhwr if it's not supported natively.
13019 * Therefore only check the ISA in system mode.
13021 check_insn(ctx, ISA_MIPS32R2);
13022 #endif
13023 t0 = tcg_temp_new();
13025 switch (rd) {
13026 case 0:
13027 gen_helper_rdhwr_cpunum(t0, cpu_env);
13028 gen_store_gpr(t0, rt);
13029 break;
13030 case 1:
13031 gen_helper_rdhwr_synci_step(t0, cpu_env);
13032 gen_store_gpr(t0, rt);
13033 break;
13034 case 2:
13035 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13036 gen_io_start();
13038 gen_helper_rdhwr_cc(t0, cpu_env);
13039 gen_store_gpr(t0, rt);
13041 * Break the TB to be able to take timer interrupts immediately
13042 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13043 * we break completely out of translated code.
13045 gen_save_pc(ctx->base.pc_next + 4);
13046 ctx->base.is_jmp = DISAS_EXIT;
13047 break;
13048 case 3:
13049 gen_helper_rdhwr_ccres(t0, cpu_env);
13050 gen_store_gpr(t0, rt);
13051 break;
13052 case 4:
13053 check_insn(ctx, ISA_MIPS32R6);
13054 if (sel != 0) {
13056 * Performance counter registers are not implemented other than
13057 * control register 0.
13059 generate_exception(ctx, EXCP_RI);
13061 gen_helper_rdhwr_performance(t0, cpu_env);
13062 gen_store_gpr(t0, rt);
13063 break;
13064 case 5:
13065 check_insn(ctx, ISA_MIPS32R6);
13066 gen_helper_rdhwr_xnp(t0, cpu_env);
13067 gen_store_gpr(t0, rt);
13068 break;
13069 case 29:
13070 #if defined(CONFIG_USER_ONLY)
13071 tcg_gen_ld_tl(t0, cpu_env,
13072 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13073 gen_store_gpr(t0, rt);
13074 break;
13075 #else
13076 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13077 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13078 tcg_gen_ld_tl(t0, cpu_env,
13079 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13080 gen_store_gpr(t0, rt);
13081 } else {
13082 generate_exception_end(ctx, EXCP_RI);
13084 break;
13085 #endif
13086 default: /* Invalid */
13087 MIPS_INVAL("rdhwr");
13088 generate_exception_end(ctx, EXCP_RI);
13089 break;
13091 tcg_temp_free(t0);
13094 static inline void clear_branch_hflags(DisasContext *ctx)
13096 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13097 if (ctx->base.is_jmp == DISAS_NEXT) {
13098 save_cpu_state(ctx, 0);
13099 } else {
13101 * It is not safe to save ctx->hflags as hflags may be changed
13102 * in execution time by the instruction in delay / forbidden slot.
13104 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13108 static void gen_branch(DisasContext *ctx, int insn_bytes)
13110 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13111 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13112 /* Branches completion */
13113 clear_branch_hflags(ctx);
13114 ctx->base.is_jmp = DISAS_NORETURN;
13115 /* FIXME: Need to clear can_do_io. */
13116 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13117 case MIPS_HFLAG_FBNSLOT:
13118 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13119 break;
13120 case MIPS_HFLAG_B:
13121 /* unconditional branch */
13122 if (proc_hflags & MIPS_HFLAG_BX) {
13123 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13125 gen_goto_tb(ctx, 0, ctx->btarget);
13126 break;
13127 case MIPS_HFLAG_BL:
13128 /* blikely taken case */
13129 gen_goto_tb(ctx, 0, ctx->btarget);
13130 break;
13131 case MIPS_HFLAG_BC:
13132 /* Conditional branch */
13134 TCGLabel *l1 = gen_new_label();
13136 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13137 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13138 gen_set_label(l1);
13139 gen_goto_tb(ctx, 0, ctx->btarget);
13141 break;
13142 case MIPS_HFLAG_BR:
13143 /* unconditional branch to register */
13144 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13145 TCGv t0 = tcg_temp_new();
13146 TCGv_i32 t1 = tcg_temp_new_i32();
13148 tcg_gen_andi_tl(t0, btarget, 0x1);
13149 tcg_gen_trunc_tl_i32(t1, t0);
13150 tcg_temp_free(t0);
13151 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13152 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13153 tcg_gen_or_i32(hflags, hflags, t1);
13154 tcg_temp_free_i32(t1);
13156 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13157 } else {
13158 tcg_gen_mov_tl(cpu_PC, btarget);
13160 if (ctx->base.singlestep_enabled) {
13161 save_cpu_state(ctx, 0);
13162 gen_helper_raise_exception_debug(cpu_env);
13164 tcg_gen_lookup_and_goto_ptr();
13165 break;
13166 default:
13167 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13168 abort();
13173 /* Compact Branches */
13174 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13175 int rs, int rt, int32_t offset)
13177 int bcond_compute = 0;
13178 TCGv t0 = tcg_temp_new();
13179 TCGv t1 = tcg_temp_new();
13180 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13182 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13183 #ifdef MIPS_DEBUG_DISAS
13184 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13185 "\n", ctx->base.pc_next);
13186 #endif
13187 generate_exception_end(ctx, EXCP_RI);
13188 goto out;
13191 /* Load needed operands and calculate btarget */
13192 switch (opc) {
13193 /* compact branch */
13194 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13195 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13196 gen_load_gpr(t0, rs);
13197 gen_load_gpr(t1, rt);
13198 bcond_compute = 1;
13199 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13200 if (rs <= rt && rs == 0) {
13201 /* OPC_BEQZALC, OPC_BNEZALC */
13202 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13204 break;
13205 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13206 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13207 gen_load_gpr(t0, rs);
13208 gen_load_gpr(t1, rt);
13209 bcond_compute = 1;
13210 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13211 break;
13212 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13213 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13214 if (rs == 0 || rs == rt) {
13215 /* OPC_BLEZALC, OPC_BGEZALC */
13216 /* OPC_BGTZALC, OPC_BLTZALC */
13217 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13219 gen_load_gpr(t0, rs);
13220 gen_load_gpr(t1, rt);
13221 bcond_compute = 1;
13222 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13223 break;
13224 case OPC_BC:
13225 case OPC_BALC:
13226 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13227 break;
13228 case OPC_BEQZC:
13229 case OPC_BNEZC:
13230 if (rs != 0) {
13231 /* OPC_BEQZC, OPC_BNEZC */
13232 gen_load_gpr(t0, rs);
13233 bcond_compute = 1;
13234 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13235 } else {
13236 /* OPC_JIC, OPC_JIALC */
13237 TCGv tbase = tcg_temp_new();
13238 TCGv toffset = tcg_temp_new();
13240 gen_load_gpr(tbase, rt);
13241 tcg_gen_movi_tl(toffset, offset);
13242 gen_op_addr_add(ctx, btarget, tbase, toffset);
13243 tcg_temp_free(tbase);
13244 tcg_temp_free(toffset);
13246 break;
13247 default:
13248 MIPS_INVAL("Compact branch/jump");
13249 generate_exception_end(ctx, EXCP_RI);
13250 goto out;
13253 if (bcond_compute == 0) {
13254 /* Uncoditional compact branch */
13255 switch (opc) {
13256 case OPC_JIALC:
13257 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13258 /* Fallthrough */
13259 case OPC_JIC:
13260 ctx->hflags |= MIPS_HFLAG_BR;
13261 break;
13262 case OPC_BALC:
13263 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13264 /* Fallthrough */
13265 case OPC_BC:
13266 ctx->hflags |= MIPS_HFLAG_B;
13267 break;
13268 default:
13269 MIPS_INVAL("Compact branch/jump");
13270 generate_exception_end(ctx, EXCP_RI);
13271 goto out;
13274 /* Generating branch here as compact branches don't have delay slot */
13275 gen_branch(ctx, 4);
13276 } else {
13277 /* Conditional compact branch */
13278 TCGLabel *fs = gen_new_label();
13279 save_cpu_state(ctx, 0);
13281 switch (opc) {
13282 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13283 if (rs == 0 && rt != 0) {
13284 /* OPC_BLEZALC */
13285 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13286 } else if (rs != 0 && rt != 0 && rs == rt) {
13287 /* OPC_BGEZALC */
13288 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13289 } else {
13290 /* OPC_BGEUC */
13291 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13293 break;
13294 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13295 if (rs == 0 && rt != 0) {
13296 /* OPC_BGTZALC */
13297 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13298 } else if (rs != 0 && rt != 0 && rs == rt) {
13299 /* OPC_BLTZALC */
13300 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13301 } else {
13302 /* OPC_BLTUC */
13303 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13305 break;
13306 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13307 if (rs == 0 && rt != 0) {
13308 /* OPC_BLEZC */
13309 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13310 } else if (rs != 0 && rt != 0 && rs == rt) {
13311 /* OPC_BGEZC */
13312 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13313 } else {
13314 /* OPC_BGEC */
13315 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13317 break;
13318 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13319 if (rs == 0 && rt != 0) {
13320 /* OPC_BGTZC */
13321 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13322 } else if (rs != 0 && rt != 0 && rs == rt) {
13323 /* OPC_BLTZC */
13324 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13325 } else {
13326 /* OPC_BLTC */
13327 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13329 break;
13330 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13331 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13332 if (rs >= rt) {
13333 /* OPC_BOVC, OPC_BNVC */
13334 TCGv t2 = tcg_temp_new();
13335 TCGv t3 = tcg_temp_new();
13336 TCGv t4 = tcg_temp_new();
13337 TCGv input_overflow = tcg_temp_new();
13339 gen_load_gpr(t0, rs);
13340 gen_load_gpr(t1, rt);
13341 tcg_gen_ext32s_tl(t2, t0);
13342 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13343 tcg_gen_ext32s_tl(t3, t1);
13344 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13345 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13347 tcg_gen_add_tl(t4, t2, t3);
13348 tcg_gen_ext32s_tl(t4, t4);
13349 tcg_gen_xor_tl(t2, t2, t3);
13350 tcg_gen_xor_tl(t3, t4, t3);
13351 tcg_gen_andc_tl(t2, t3, t2);
13352 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13353 tcg_gen_or_tl(t4, t4, input_overflow);
13354 if (opc == OPC_BOVC) {
13355 /* OPC_BOVC */
13356 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13357 } else {
13358 /* OPC_BNVC */
13359 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13361 tcg_temp_free(input_overflow);
13362 tcg_temp_free(t4);
13363 tcg_temp_free(t3);
13364 tcg_temp_free(t2);
13365 } else if (rs < rt && rs == 0) {
13366 /* OPC_BEQZALC, OPC_BNEZALC */
13367 if (opc == OPC_BEQZALC) {
13368 /* OPC_BEQZALC */
13369 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13370 } else {
13371 /* OPC_BNEZALC */
13372 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13374 } else {
13375 /* OPC_BEQC, OPC_BNEC */
13376 if (opc == OPC_BEQC) {
13377 /* OPC_BEQC */
13378 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13379 } else {
13380 /* OPC_BNEC */
13381 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13384 break;
13385 case OPC_BEQZC:
13386 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13387 break;
13388 case OPC_BNEZC:
13389 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13390 break;
13391 default:
13392 MIPS_INVAL("Compact conditional branch/jump");
13393 generate_exception_end(ctx, EXCP_RI);
13394 goto out;
13397 /* Generating branch here as compact branches don't have delay slot */
13398 gen_goto_tb(ctx, 1, ctx->btarget);
13399 gen_set_label(fs);
13401 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13404 out:
13405 tcg_temp_free(t0);
13406 tcg_temp_free(t1);
13409 /* ISA extensions (ASEs) */
13410 /* MIPS16 extension to MIPS32 */
13412 /* MIPS16 major opcodes */
13413 enum {
13414 M16_OPC_ADDIUSP = 0x00,
13415 M16_OPC_ADDIUPC = 0x01,
13416 M16_OPC_B = 0x02,
13417 M16_OPC_JAL = 0x03,
13418 M16_OPC_BEQZ = 0x04,
13419 M16_OPC_BNEQZ = 0x05,
13420 M16_OPC_SHIFT = 0x06,
13421 M16_OPC_LD = 0x07,
13422 M16_OPC_RRIA = 0x08,
13423 M16_OPC_ADDIU8 = 0x09,
13424 M16_OPC_SLTI = 0x0a,
13425 M16_OPC_SLTIU = 0x0b,
13426 M16_OPC_I8 = 0x0c,
13427 M16_OPC_LI = 0x0d,
13428 M16_OPC_CMPI = 0x0e,
13429 M16_OPC_SD = 0x0f,
13430 M16_OPC_LB = 0x10,
13431 M16_OPC_LH = 0x11,
13432 M16_OPC_LWSP = 0x12,
13433 M16_OPC_LW = 0x13,
13434 M16_OPC_LBU = 0x14,
13435 M16_OPC_LHU = 0x15,
13436 M16_OPC_LWPC = 0x16,
13437 M16_OPC_LWU = 0x17,
13438 M16_OPC_SB = 0x18,
13439 M16_OPC_SH = 0x19,
13440 M16_OPC_SWSP = 0x1a,
13441 M16_OPC_SW = 0x1b,
13442 M16_OPC_RRR = 0x1c,
13443 M16_OPC_RR = 0x1d,
13444 M16_OPC_EXTEND = 0x1e,
13445 M16_OPC_I64 = 0x1f
13448 /* I8 funct field */
13449 enum {
13450 I8_BTEQZ = 0x0,
13451 I8_BTNEZ = 0x1,
13452 I8_SWRASP = 0x2,
13453 I8_ADJSP = 0x3,
13454 I8_SVRS = 0x4,
13455 I8_MOV32R = 0x5,
13456 I8_MOVR32 = 0x7
13459 /* RRR f field */
13460 enum {
13461 RRR_DADDU = 0x0,
13462 RRR_ADDU = 0x1,
13463 RRR_DSUBU = 0x2,
13464 RRR_SUBU = 0x3
13467 /* RR funct field */
13468 enum {
13469 RR_JR = 0x00,
13470 RR_SDBBP = 0x01,
13471 RR_SLT = 0x02,
13472 RR_SLTU = 0x03,
13473 RR_SLLV = 0x04,
13474 RR_BREAK = 0x05,
13475 RR_SRLV = 0x06,
13476 RR_SRAV = 0x07,
13477 RR_DSRL = 0x08,
13478 RR_CMP = 0x0a,
13479 RR_NEG = 0x0b,
13480 RR_AND = 0x0c,
13481 RR_OR = 0x0d,
13482 RR_XOR = 0x0e,
13483 RR_NOT = 0x0f,
13484 RR_MFHI = 0x10,
13485 RR_CNVT = 0x11,
13486 RR_MFLO = 0x12,
13487 RR_DSRA = 0x13,
13488 RR_DSLLV = 0x14,
13489 RR_DSRLV = 0x16,
13490 RR_DSRAV = 0x17,
13491 RR_MULT = 0x18,
13492 RR_MULTU = 0x19,
13493 RR_DIV = 0x1a,
13494 RR_DIVU = 0x1b,
13495 RR_DMULT = 0x1c,
13496 RR_DMULTU = 0x1d,
13497 RR_DDIV = 0x1e,
13498 RR_DDIVU = 0x1f
13501 /* I64 funct field */
13502 enum {
13503 I64_LDSP = 0x0,
13504 I64_SDSP = 0x1,
13505 I64_SDRASP = 0x2,
13506 I64_DADJSP = 0x3,
13507 I64_LDPC = 0x4,
13508 I64_DADDIU5 = 0x5,
13509 I64_DADDIUPC = 0x6,
13510 I64_DADDIUSP = 0x7
13513 /* RR ry field for CNVT */
13514 enum {
13515 RR_RY_CNVT_ZEB = 0x0,
13516 RR_RY_CNVT_ZEH = 0x1,
13517 RR_RY_CNVT_ZEW = 0x2,
13518 RR_RY_CNVT_SEB = 0x4,
13519 RR_RY_CNVT_SEH = 0x5,
13520 RR_RY_CNVT_SEW = 0x6,
13523 static int xlat(int r)
13525 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13527 return map[r];
13530 static void gen_mips16_save(DisasContext *ctx,
13531 int xsregs, int aregs,
13532 int do_ra, int do_s0, int do_s1,
13533 int framesize)
13535 TCGv t0 = tcg_temp_new();
13536 TCGv t1 = tcg_temp_new();
13537 TCGv t2 = tcg_temp_new();
13538 int args, astatic;
13540 switch (aregs) {
13541 case 0:
13542 case 1:
13543 case 2:
13544 case 3:
13545 case 11:
13546 args = 0;
13547 break;
13548 case 4:
13549 case 5:
13550 case 6:
13551 case 7:
13552 args = 1;
13553 break;
13554 case 8:
13555 case 9:
13556 case 10:
13557 args = 2;
13558 break;
13559 case 12:
13560 case 13:
13561 args = 3;
13562 break;
13563 case 14:
13564 args = 4;
13565 break;
13566 default:
13567 generate_exception_end(ctx, EXCP_RI);
13568 return;
13571 switch (args) {
13572 case 4:
13573 gen_base_offset_addr(ctx, t0, 29, 12);
13574 gen_load_gpr(t1, 7);
13575 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13576 /* Fall through */
13577 case 3:
13578 gen_base_offset_addr(ctx, t0, 29, 8);
13579 gen_load_gpr(t1, 6);
13580 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13581 /* Fall through */
13582 case 2:
13583 gen_base_offset_addr(ctx, t0, 29, 4);
13584 gen_load_gpr(t1, 5);
13585 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13586 /* Fall through */
13587 case 1:
13588 gen_base_offset_addr(ctx, t0, 29, 0);
13589 gen_load_gpr(t1, 4);
13590 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13593 gen_load_gpr(t0, 29);
13595 #define DECR_AND_STORE(reg) do { \
13596 tcg_gen_movi_tl(t2, -4); \
13597 gen_op_addr_add(ctx, t0, t0, t2); \
13598 gen_load_gpr(t1, reg); \
13599 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13600 } while (0)
13602 if (do_ra) {
13603 DECR_AND_STORE(31);
13606 switch (xsregs) {
13607 case 7:
13608 DECR_AND_STORE(30);
13609 /* Fall through */
13610 case 6:
13611 DECR_AND_STORE(23);
13612 /* Fall through */
13613 case 5:
13614 DECR_AND_STORE(22);
13615 /* Fall through */
13616 case 4:
13617 DECR_AND_STORE(21);
13618 /* Fall through */
13619 case 3:
13620 DECR_AND_STORE(20);
13621 /* Fall through */
13622 case 2:
13623 DECR_AND_STORE(19);
13624 /* Fall through */
13625 case 1:
13626 DECR_AND_STORE(18);
13629 if (do_s1) {
13630 DECR_AND_STORE(17);
13632 if (do_s0) {
13633 DECR_AND_STORE(16);
13636 switch (aregs) {
13637 case 0:
13638 case 4:
13639 case 8:
13640 case 12:
13641 case 14:
13642 astatic = 0;
13643 break;
13644 case 1:
13645 case 5:
13646 case 9:
13647 case 13:
13648 astatic = 1;
13649 break;
13650 case 2:
13651 case 6:
13652 case 10:
13653 astatic = 2;
13654 break;
13655 case 3:
13656 case 7:
13657 astatic = 3;
13658 break;
13659 case 11:
13660 astatic = 4;
13661 break;
13662 default:
13663 generate_exception_end(ctx, EXCP_RI);
13664 return;
13667 if (astatic > 0) {
13668 DECR_AND_STORE(7);
13669 if (astatic > 1) {
13670 DECR_AND_STORE(6);
13671 if (astatic > 2) {
13672 DECR_AND_STORE(5);
13673 if (astatic > 3) {
13674 DECR_AND_STORE(4);
13679 #undef DECR_AND_STORE
13681 tcg_gen_movi_tl(t2, -framesize);
13682 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13683 tcg_temp_free(t0);
13684 tcg_temp_free(t1);
13685 tcg_temp_free(t2);
13688 static void gen_mips16_restore(DisasContext *ctx,
13689 int xsregs, int aregs,
13690 int do_ra, int do_s0, int do_s1,
13691 int framesize)
13693 int astatic;
13694 TCGv t0 = tcg_temp_new();
13695 TCGv t1 = tcg_temp_new();
13696 TCGv t2 = tcg_temp_new();
13698 tcg_gen_movi_tl(t2, framesize);
13699 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13701 #define DECR_AND_LOAD(reg) do { \
13702 tcg_gen_movi_tl(t2, -4); \
13703 gen_op_addr_add(ctx, t0, t0, t2); \
13704 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13705 gen_store_gpr(t1, reg); \
13706 } while (0)
13708 if (do_ra) {
13709 DECR_AND_LOAD(31);
13712 switch (xsregs) {
13713 case 7:
13714 DECR_AND_LOAD(30);
13715 /* Fall through */
13716 case 6:
13717 DECR_AND_LOAD(23);
13718 /* Fall through */
13719 case 5:
13720 DECR_AND_LOAD(22);
13721 /* Fall through */
13722 case 4:
13723 DECR_AND_LOAD(21);
13724 /* Fall through */
13725 case 3:
13726 DECR_AND_LOAD(20);
13727 /* Fall through */
13728 case 2:
13729 DECR_AND_LOAD(19);
13730 /* Fall through */
13731 case 1:
13732 DECR_AND_LOAD(18);
13735 if (do_s1) {
13736 DECR_AND_LOAD(17);
13738 if (do_s0) {
13739 DECR_AND_LOAD(16);
13742 switch (aregs) {
13743 case 0:
13744 case 4:
13745 case 8:
13746 case 12:
13747 case 14:
13748 astatic = 0;
13749 break;
13750 case 1:
13751 case 5:
13752 case 9:
13753 case 13:
13754 astatic = 1;
13755 break;
13756 case 2:
13757 case 6:
13758 case 10:
13759 astatic = 2;
13760 break;
13761 case 3:
13762 case 7:
13763 astatic = 3;
13764 break;
13765 case 11:
13766 astatic = 4;
13767 break;
13768 default:
13769 generate_exception_end(ctx, EXCP_RI);
13770 return;
13773 if (astatic > 0) {
13774 DECR_AND_LOAD(7);
13775 if (astatic > 1) {
13776 DECR_AND_LOAD(6);
13777 if (astatic > 2) {
13778 DECR_AND_LOAD(5);
13779 if (astatic > 3) {
13780 DECR_AND_LOAD(4);
13785 #undef DECR_AND_LOAD
13787 tcg_gen_movi_tl(t2, framesize);
13788 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13789 tcg_temp_free(t0);
13790 tcg_temp_free(t1);
13791 tcg_temp_free(t2);
13794 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13795 int is_64_bit, int extended)
13797 TCGv t0;
13799 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13800 generate_exception_end(ctx, EXCP_RI);
13801 return;
13804 t0 = tcg_temp_new();
13806 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13807 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13808 if (!is_64_bit) {
13809 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13812 tcg_temp_free(t0);
13815 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13816 int16_t offset)
13818 TCGv_i32 t0 = tcg_const_i32(op);
13819 TCGv t1 = tcg_temp_new();
13820 gen_base_offset_addr(ctx, t1, base, offset);
13821 gen_helper_cache(cpu_env, t1, t0);
13824 #if defined(TARGET_MIPS64)
13825 static void decode_i64_mips16(DisasContext *ctx,
13826 int ry, int funct, int16_t offset,
13827 int extended)
13829 switch (funct) {
13830 case I64_LDSP:
13831 check_insn(ctx, ISA_MIPS3);
13832 check_mips_64(ctx);
13833 offset = extended ? offset : offset << 3;
13834 gen_ld(ctx, OPC_LD, ry, 29, offset);
13835 break;
13836 case I64_SDSP:
13837 check_insn(ctx, ISA_MIPS3);
13838 check_mips_64(ctx);
13839 offset = extended ? offset : offset << 3;
13840 gen_st(ctx, OPC_SD, ry, 29, offset);
13841 break;
13842 case I64_SDRASP:
13843 check_insn(ctx, ISA_MIPS3);
13844 check_mips_64(ctx);
13845 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13846 gen_st(ctx, OPC_SD, 31, 29, offset);
13847 break;
13848 case I64_DADJSP:
13849 check_insn(ctx, ISA_MIPS3);
13850 check_mips_64(ctx);
13851 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13852 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13853 break;
13854 case I64_LDPC:
13855 check_insn(ctx, ISA_MIPS3);
13856 check_mips_64(ctx);
13857 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13858 generate_exception_end(ctx, EXCP_RI);
13859 } else {
13860 offset = extended ? offset : offset << 3;
13861 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13863 break;
13864 case I64_DADDIU5:
13865 check_insn(ctx, ISA_MIPS3);
13866 check_mips_64(ctx);
13867 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13868 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13869 break;
13870 case I64_DADDIUPC:
13871 check_insn(ctx, ISA_MIPS3);
13872 check_mips_64(ctx);
13873 offset = extended ? offset : offset << 2;
13874 gen_addiupc(ctx, ry, offset, 1, extended);
13875 break;
13876 case I64_DADDIUSP:
13877 check_insn(ctx, ISA_MIPS3);
13878 check_mips_64(ctx);
13879 offset = extended ? offset : offset << 2;
13880 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13881 break;
13884 #endif
13886 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13888 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13889 int op, rx, ry, funct, sa;
13890 int16_t imm, offset;
13892 ctx->opcode = (ctx->opcode << 16) | extend;
13893 op = (ctx->opcode >> 11) & 0x1f;
13894 sa = (ctx->opcode >> 22) & 0x1f;
13895 funct = (ctx->opcode >> 8) & 0x7;
13896 rx = xlat((ctx->opcode >> 8) & 0x7);
13897 ry = xlat((ctx->opcode >> 5) & 0x7);
13898 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13899 | ((ctx->opcode >> 21) & 0x3f) << 5
13900 | (ctx->opcode & 0x1f));
13903 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13904 * counterparts.
13906 switch (op) {
13907 case M16_OPC_ADDIUSP:
13908 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13909 break;
13910 case M16_OPC_ADDIUPC:
13911 gen_addiupc(ctx, rx, imm, 0, 1);
13912 break;
13913 case M16_OPC_B:
13914 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13915 /* No delay slot, so just process as a normal instruction */
13916 break;
13917 case M16_OPC_BEQZ:
13918 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13919 /* No delay slot, so just process as a normal instruction */
13920 break;
13921 case M16_OPC_BNEQZ:
13922 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13923 /* No delay slot, so just process as a normal instruction */
13924 break;
13925 case M16_OPC_SHIFT:
13926 switch (ctx->opcode & 0x3) {
13927 case 0x0:
13928 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13929 break;
13930 case 0x1:
13931 #if defined(TARGET_MIPS64)
13932 check_mips_64(ctx);
13933 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13934 #else
13935 generate_exception_end(ctx, EXCP_RI);
13936 #endif
13937 break;
13938 case 0x2:
13939 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13940 break;
13941 case 0x3:
13942 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13943 break;
13945 break;
13946 #if defined(TARGET_MIPS64)
13947 case M16_OPC_LD:
13948 check_insn(ctx, ISA_MIPS3);
13949 check_mips_64(ctx);
13950 gen_ld(ctx, OPC_LD, ry, rx, offset);
13951 break;
13952 #endif
13953 case M16_OPC_RRIA:
13954 imm = ctx->opcode & 0xf;
13955 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13956 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13957 imm = (int16_t) (imm << 1) >> 1;
13958 if ((ctx->opcode >> 4) & 0x1) {
13959 #if defined(TARGET_MIPS64)
13960 check_mips_64(ctx);
13961 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13962 #else
13963 generate_exception_end(ctx, EXCP_RI);
13964 #endif
13965 } else {
13966 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13968 break;
13969 case M16_OPC_ADDIU8:
13970 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13971 break;
13972 case M16_OPC_SLTI:
13973 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13974 break;
13975 case M16_OPC_SLTIU:
13976 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13977 break;
13978 case M16_OPC_I8:
13979 switch (funct) {
13980 case I8_BTEQZ:
13981 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13982 break;
13983 case I8_BTNEZ:
13984 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13985 break;
13986 case I8_SWRASP:
13987 gen_st(ctx, OPC_SW, 31, 29, imm);
13988 break;
13989 case I8_ADJSP:
13990 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13991 break;
13992 case I8_SVRS:
13993 check_insn(ctx, ISA_MIPS32);
13995 int xsregs = (ctx->opcode >> 24) & 0x7;
13996 int aregs = (ctx->opcode >> 16) & 0xf;
13997 int do_ra = (ctx->opcode >> 6) & 0x1;
13998 int do_s0 = (ctx->opcode >> 5) & 0x1;
13999 int do_s1 = (ctx->opcode >> 4) & 0x1;
14000 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14001 | (ctx->opcode & 0xf)) << 3;
14003 if (ctx->opcode & (1 << 7)) {
14004 gen_mips16_save(ctx, xsregs, aregs,
14005 do_ra, do_s0, do_s1,
14006 framesize);
14007 } else {
14008 gen_mips16_restore(ctx, xsregs, aregs,
14009 do_ra, do_s0, do_s1,
14010 framesize);
14013 break;
14014 default:
14015 generate_exception_end(ctx, EXCP_RI);
14016 break;
14018 break;
14019 case M16_OPC_LI:
14020 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14021 break;
14022 case M16_OPC_CMPI:
14023 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14024 break;
14025 #if defined(TARGET_MIPS64)
14026 case M16_OPC_SD:
14027 check_insn(ctx, ISA_MIPS3);
14028 check_mips_64(ctx);
14029 gen_st(ctx, OPC_SD, ry, rx, offset);
14030 break;
14031 #endif
14032 case M16_OPC_LB:
14033 gen_ld(ctx, OPC_LB, ry, rx, offset);
14034 break;
14035 case M16_OPC_LH:
14036 gen_ld(ctx, OPC_LH, ry, rx, offset);
14037 break;
14038 case M16_OPC_LWSP:
14039 gen_ld(ctx, OPC_LW, rx, 29, offset);
14040 break;
14041 case M16_OPC_LW:
14042 gen_ld(ctx, OPC_LW, ry, rx, offset);
14043 break;
14044 case M16_OPC_LBU:
14045 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14046 break;
14047 case M16_OPC_LHU:
14048 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14049 break;
14050 case M16_OPC_LWPC:
14051 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14052 break;
14053 #if defined(TARGET_MIPS64)
14054 case M16_OPC_LWU:
14055 check_insn(ctx, ISA_MIPS3);
14056 check_mips_64(ctx);
14057 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14058 break;
14059 #endif
14060 case M16_OPC_SB:
14061 gen_st(ctx, OPC_SB, ry, rx, offset);
14062 break;
14063 case M16_OPC_SH:
14064 gen_st(ctx, OPC_SH, ry, rx, offset);
14065 break;
14066 case M16_OPC_SWSP:
14067 gen_st(ctx, OPC_SW, rx, 29, offset);
14068 break;
14069 case M16_OPC_SW:
14070 gen_st(ctx, OPC_SW, ry, rx, offset);
14071 break;
14072 #if defined(TARGET_MIPS64)
14073 case M16_OPC_I64:
14074 decode_i64_mips16(ctx, ry, funct, offset, 1);
14075 break;
14076 #endif
14077 default:
14078 generate_exception_end(ctx, EXCP_RI);
14079 break;
14082 return 4;
14085 static inline bool is_uhi(int sdbbp_code)
14087 #ifdef CONFIG_USER_ONLY
14088 return false;
14089 #else
14090 return semihosting_enabled() && sdbbp_code == 1;
14091 #endif
14094 #ifdef CONFIG_USER_ONLY
14095 /* The above should dead-code away any calls to this..*/
14096 static inline void gen_helper_do_semihosting(void *env)
14098 g_assert_not_reached();
14100 #endif
14102 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14104 int rx, ry;
14105 int sa;
14106 int op, cnvt_op, op1, offset;
14107 int funct;
14108 int n_bytes;
14110 op = (ctx->opcode >> 11) & 0x1f;
14111 sa = (ctx->opcode >> 2) & 0x7;
14112 sa = sa == 0 ? 8 : sa;
14113 rx = xlat((ctx->opcode >> 8) & 0x7);
14114 cnvt_op = (ctx->opcode >> 5) & 0x7;
14115 ry = xlat((ctx->opcode >> 5) & 0x7);
14116 op1 = offset = ctx->opcode & 0x1f;
14118 n_bytes = 2;
14120 switch (op) {
14121 case M16_OPC_ADDIUSP:
14123 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14125 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14127 break;
14128 case M16_OPC_ADDIUPC:
14129 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14130 break;
14131 case M16_OPC_B:
14132 offset = (ctx->opcode & 0x7ff) << 1;
14133 offset = (int16_t)(offset << 4) >> 4;
14134 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14135 /* No delay slot, so just process as a normal instruction */
14136 break;
14137 case M16_OPC_JAL:
14138 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14139 offset = (((ctx->opcode & 0x1f) << 21)
14140 | ((ctx->opcode >> 5) & 0x1f) << 16
14141 | offset) << 2;
14142 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14143 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14144 n_bytes = 4;
14145 break;
14146 case M16_OPC_BEQZ:
14147 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14148 ((int8_t)ctx->opcode) << 1, 0);
14149 /* No delay slot, so just process as a normal instruction */
14150 break;
14151 case M16_OPC_BNEQZ:
14152 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14153 ((int8_t)ctx->opcode) << 1, 0);
14154 /* No delay slot, so just process as a normal instruction */
14155 break;
14156 case M16_OPC_SHIFT:
14157 switch (ctx->opcode & 0x3) {
14158 case 0x0:
14159 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14160 break;
14161 case 0x1:
14162 #if defined(TARGET_MIPS64)
14163 check_insn(ctx, ISA_MIPS3);
14164 check_mips_64(ctx);
14165 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14166 #else
14167 generate_exception_end(ctx, EXCP_RI);
14168 #endif
14169 break;
14170 case 0x2:
14171 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14172 break;
14173 case 0x3:
14174 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14175 break;
14177 break;
14178 #if defined(TARGET_MIPS64)
14179 case M16_OPC_LD:
14180 check_insn(ctx, ISA_MIPS3);
14181 check_mips_64(ctx);
14182 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14183 break;
14184 #endif
14185 case M16_OPC_RRIA:
14187 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14189 if ((ctx->opcode >> 4) & 1) {
14190 #if defined(TARGET_MIPS64)
14191 check_insn(ctx, ISA_MIPS3);
14192 check_mips_64(ctx);
14193 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14194 #else
14195 generate_exception_end(ctx, EXCP_RI);
14196 #endif
14197 } else {
14198 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14201 break;
14202 case M16_OPC_ADDIU8:
14204 int16_t imm = (int8_t) ctx->opcode;
14206 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14208 break;
14209 case M16_OPC_SLTI:
14211 int16_t imm = (uint8_t) ctx->opcode;
14212 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14214 break;
14215 case M16_OPC_SLTIU:
14217 int16_t imm = (uint8_t) ctx->opcode;
14218 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14220 break;
14221 case M16_OPC_I8:
14223 int reg32;
14225 funct = (ctx->opcode >> 8) & 0x7;
14226 switch (funct) {
14227 case I8_BTEQZ:
14228 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14229 ((int8_t)ctx->opcode) << 1, 0);
14230 break;
14231 case I8_BTNEZ:
14232 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14233 ((int8_t)ctx->opcode) << 1, 0);
14234 break;
14235 case I8_SWRASP:
14236 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14237 break;
14238 case I8_ADJSP:
14239 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14240 ((int8_t)ctx->opcode) << 3);
14241 break;
14242 case I8_SVRS:
14243 check_insn(ctx, ISA_MIPS32);
14245 int do_ra = ctx->opcode & (1 << 6);
14246 int do_s0 = ctx->opcode & (1 << 5);
14247 int do_s1 = ctx->opcode & (1 << 4);
14248 int framesize = ctx->opcode & 0xf;
14250 if (framesize == 0) {
14251 framesize = 128;
14252 } else {
14253 framesize = framesize << 3;
14256 if (ctx->opcode & (1 << 7)) {
14257 gen_mips16_save(ctx, 0, 0,
14258 do_ra, do_s0, do_s1, framesize);
14259 } else {
14260 gen_mips16_restore(ctx, 0, 0,
14261 do_ra, do_s0, do_s1, framesize);
14264 break;
14265 case I8_MOV32R:
14267 int rz = xlat(ctx->opcode & 0x7);
14269 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14270 ((ctx->opcode >> 5) & 0x7);
14271 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14273 break;
14274 case I8_MOVR32:
14275 reg32 = ctx->opcode & 0x1f;
14276 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14277 break;
14278 default:
14279 generate_exception_end(ctx, EXCP_RI);
14280 break;
14283 break;
14284 case M16_OPC_LI:
14286 int16_t imm = (uint8_t) ctx->opcode;
14288 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14290 break;
14291 case M16_OPC_CMPI:
14293 int16_t imm = (uint8_t) ctx->opcode;
14294 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14296 break;
14297 #if defined(TARGET_MIPS64)
14298 case M16_OPC_SD:
14299 check_insn(ctx, ISA_MIPS3);
14300 check_mips_64(ctx);
14301 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14302 break;
14303 #endif
14304 case M16_OPC_LB:
14305 gen_ld(ctx, OPC_LB, ry, rx, offset);
14306 break;
14307 case M16_OPC_LH:
14308 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14309 break;
14310 case M16_OPC_LWSP:
14311 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14312 break;
14313 case M16_OPC_LW:
14314 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14315 break;
14316 case M16_OPC_LBU:
14317 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14318 break;
14319 case M16_OPC_LHU:
14320 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14321 break;
14322 case M16_OPC_LWPC:
14323 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14324 break;
14325 #if defined(TARGET_MIPS64)
14326 case M16_OPC_LWU:
14327 check_insn(ctx, ISA_MIPS3);
14328 check_mips_64(ctx);
14329 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14330 break;
14331 #endif
14332 case M16_OPC_SB:
14333 gen_st(ctx, OPC_SB, ry, rx, offset);
14334 break;
14335 case M16_OPC_SH:
14336 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14337 break;
14338 case M16_OPC_SWSP:
14339 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14340 break;
14341 case M16_OPC_SW:
14342 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14343 break;
14344 case M16_OPC_RRR:
14346 int rz = xlat((ctx->opcode >> 2) & 0x7);
14347 int mips32_op;
14349 switch (ctx->opcode & 0x3) {
14350 case RRR_ADDU:
14351 mips32_op = OPC_ADDU;
14352 break;
14353 case RRR_SUBU:
14354 mips32_op = OPC_SUBU;
14355 break;
14356 #if defined(TARGET_MIPS64)
14357 case RRR_DADDU:
14358 mips32_op = OPC_DADDU;
14359 check_insn(ctx, ISA_MIPS3);
14360 check_mips_64(ctx);
14361 break;
14362 case RRR_DSUBU:
14363 mips32_op = OPC_DSUBU;
14364 check_insn(ctx, ISA_MIPS3);
14365 check_mips_64(ctx);
14366 break;
14367 #endif
14368 default:
14369 generate_exception_end(ctx, EXCP_RI);
14370 goto done;
14373 gen_arith(ctx, mips32_op, rz, rx, ry);
14374 done:
14377 break;
14378 case M16_OPC_RR:
14379 switch (op1) {
14380 case RR_JR:
14382 int nd = (ctx->opcode >> 7) & 0x1;
14383 int link = (ctx->opcode >> 6) & 0x1;
14384 int ra = (ctx->opcode >> 5) & 0x1;
14386 if (nd) {
14387 check_insn(ctx, ISA_MIPS32);
14390 if (link) {
14391 op = OPC_JALR;
14392 } else {
14393 op = OPC_JR;
14396 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14397 (nd ? 0 : 2));
14399 break;
14400 case RR_SDBBP:
14401 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14402 gen_helper_do_semihosting(cpu_env);
14403 } else {
14405 * XXX: not clear which exception should be raised
14406 * when in debug mode...
14408 check_insn(ctx, ISA_MIPS32);
14409 generate_exception_end(ctx, EXCP_DBp);
14411 break;
14412 case RR_SLT:
14413 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14414 break;
14415 case RR_SLTU:
14416 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14417 break;
14418 case RR_BREAK:
14419 generate_exception_end(ctx, EXCP_BREAK);
14420 break;
14421 case RR_SLLV:
14422 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14423 break;
14424 case RR_SRLV:
14425 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14426 break;
14427 case RR_SRAV:
14428 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14429 break;
14430 #if defined(TARGET_MIPS64)
14431 case RR_DSRL:
14432 check_insn(ctx, ISA_MIPS3);
14433 check_mips_64(ctx);
14434 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14435 break;
14436 #endif
14437 case RR_CMP:
14438 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14439 break;
14440 case RR_NEG:
14441 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14442 break;
14443 case RR_AND:
14444 gen_logic(ctx, OPC_AND, rx, rx, ry);
14445 break;
14446 case RR_OR:
14447 gen_logic(ctx, OPC_OR, rx, rx, ry);
14448 break;
14449 case RR_XOR:
14450 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14451 break;
14452 case RR_NOT:
14453 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14454 break;
14455 case RR_MFHI:
14456 gen_HILO(ctx, OPC_MFHI, 0, rx);
14457 break;
14458 case RR_CNVT:
14459 check_insn(ctx, ISA_MIPS32);
14460 switch (cnvt_op) {
14461 case RR_RY_CNVT_ZEB:
14462 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14463 break;
14464 case RR_RY_CNVT_ZEH:
14465 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14466 break;
14467 case RR_RY_CNVT_SEB:
14468 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14469 break;
14470 case RR_RY_CNVT_SEH:
14471 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14472 break;
14473 #if defined(TARGET_MIPS64)
14474 case RR_RY_CNVT_ZEW:
14475 check_insn(ctx, ISA_MIPS64);
14476 check_mips_64(ctx);
14477 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14478 break;
14479 case RR_RY_CNVT_SEW:
14480 check_insn(ctx, ISA_MIPS64);
14481 check_mips_64(ctx);
14482 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14483 break;
14484 #endif
14485 default:
14486 generate_exception_end(ctx, EXCP_RI);
14487 break;
14489 break;
14490 case RR_MFLO:
14491 gen_HILO(ctx, OPC_MFLO, 0, rx);
14492 break;
14493 #if defined(TARGET_MIPS64)
14494 case RR_DSRA:
14495 check_insn(ctx, ISA_MIPS3);
14496 check_mips_64(ctx);
14497 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14498 break;
14499 case RR_DSLLV:
14500 check_insn(ctx, ISA_MIPS3);
14501 check_mips_64(ctx);
14502 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14503 break;
14504 case RR_DSRLV:
14505 check_insn(ctx, ISA_MIPS3);
14506 check_mips_64(ctx);
14507 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14508 break;
14509 case RR_DSRAV:
14510 check_insn(ctx, ISA_MIPS3);
14511 check_mips_64(ctx);
14512 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14513 break;
14514 #endif
14515 case RR_MULT:
14516 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14517 break;
14518 case RR_MULTU:
14519 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14520 break;
14521 case RR_DIV:
14522 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14523 break;
14524 case RR_DIVU:
14525 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14526 break;
14527 #if defined(TARGET_MIPS64)
14528 case RR_DMULT:
14529 check_insn(ctx, ISA_MIPS3);
14530 check_mips_64(ctx);
14531 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14532 break;
14533 case RR_DMULTU:
14534 check_insn(ctx, ISA_MIPS3);
14535 check_mips_64(ctx);
14536 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14537 break;
14538 case RR_DDIV:
14539 check_insn(ctx, ISA_MIPS3);
14540 check_mips_64(ctx);
14541 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14542 break;
14543 case RR_DDIVU:
14544 check_insn(ctx, ISA_MIPS3);
14545 check_mips_64(ctx);
14546 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14547 break;
14548 #endif
14549 default:
14550 generate_exception_end(ctx, EXCP_RI);
14551 break;
14553 break;
14554 case M16_OPC_EXTEND:
14555 decode_extended_mips16_opc(env, ctx);
14556 n_bytes = 4;
14557 break;
14558 #if defined(TARGET_MIPS64)
14559 case M16_OPC_I64:
14560 funct = (ctx->opcode >> 8) & 0x7;
14561 decode_i64_mips16(ctx, ry, funct, offset, 0);
14562 break;
14563 #endif
14564 default:
14565 generate_exception_end(ctx, EXCP_RI);
14566 break;
14569 return n_bytes;
14572 /* microMIPS extension to MIPS32/MIPS64 */
14575 * microMIPS32/microMIPS64 major opcodes
14577 * 1. MIPS Architecture for Programmers Volume II-B:
14578 * The microMIPS32 Instruction Set (Revision 3.05)
14580 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14582 * 2. MIPS Architecture For Programmers Volume II-A:
14583 * The MIPS64 Instruction Set (Revision 3.51)
14586 enum {
14587 POOL32A = 0x00,
14588 POOL16A = 0x01,
14589 LBU16 = 0x02,
14590 MOVE16 = 0x03,
14591 ADDI32 = 0x04,
14592 R6_LUI = 0x04,
14593 AUI = 0x04,
14594 LBU32 = 0x05,
14595 SB32 = 0x06,
14596 LB32 = 0x07,
14598 POOL32B = 0x08,
14599 POOL16B = 0x09,
14600 LHU16 = 0x0a,
14601 ANDI16 = 0x0b,
14602 ADDIU32 = 0x0c,
14603 LHU32 = 0x0d,
14604 SH32 = 0x0e,
14605 LH32 = 0x0f,
14607 POOL32I = 0x10,
14608 POOL16C = 0x11,
14609 LWSP16 = 0x12,
14610 POOL16D = 0x13,
14611 ORI32 = 0x14,
14612 POOL32F = 0x15,
14613 POOL32S = 0x16, /* MIPS64 */
14614 DADDIU32 = 0x17, /* MIPS64 */
14616 POOL32C = 0x18,
14617 LWGP16 = 0x19,
14618 LW16 = 0x1a,
14619 POOL16E = 0x1b,
14620 XORI32 = 0x1c,
14621 JALS32 = 0x1d,
14622 BOVC = 0x1d,
14623 BEQC = 0x1d,
14624 BEQZALC = 0x1d,
14625 ADDIUPC = 0x1e,
14626 PCREL = 0x1e,
14627 BNVC = 0x1f,
14628 BNEC = 0x1f,
14629 BNEZALC = 0x1f,
14631 R6_BEQZC = 0x20,
14632 JIC = 0x20,
14633 POOL16F = 0x21,
14634 SB16 = 0x22,
14635 BEQZ16 = 0x23,
14636 BEQZC16 = 0x23,
14637 SLTI32 = 0x24,
14638 BEQ32 = 0x25,
14639 BC = 0x25,
14640 SWC132 = 0x26,
14641 LWC132 = 0x27,
14643 /* 0x29 is reserved */
14644 RES_29 = 0x29,
14645 R6_BNEZC = 0x28,
14646 JIALC = 0x28,
14647 SH16 = 0x2a,
14648 BNEZ16 = 0x2b,
14649 BNEZC16 = 0x2b,
14650 SLTIU32 = 0x2c,
14651 BNE32 = 0x2d,
14652 BALC = 0x2d,
14653 SDC132 = 0x2e,
14654 LDC132 = 0x2f,
14656 /* 0x31 is reserved */
14657 RES_31 = 0x31,
14658 BLEZALC = 0x30,
14659 BGEZALC = 0x30,
14660 BGEUC = 0x30,
14661 SWSP16 = 0x32,
14662 B16 = 0x33,
14663 BC16 = 0x33,
14664 ANDI32 = 0x34,
14665 J32 = 0x35,
14666 BGTZC = 0x35,
14667 BLTZC = 0x35,
14668 BLTC = 0x35,
14669 SD32 = 0x36, /* MIPS64 */
14670 LD32 = 0x37, /* MIPS64 */
14672 /* 0x39 is reserved */
14673 RES_39 = 0x39,
14674 BGTZALC = 0x38,
14675 BLTZALC = 0x38,
14676 BLTUC = 0x38,
14677 SW16 = 0x3a,
14678 LI16 = 0x3b,
14679 JALX32 = 0x3c,
14680 JAL32 = 0x3d,
14681 BLEZC = 0x3d,
14682 BGEZC = 0x3d,
14683 BGEC = 0x3d,
14684 SW32 = 0x3e,
14685 LW32 = 0x3f
14688 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14689 enum {
14690 ADDIUPC_00 = 0x00,
14691 ADDIUPC_01 = 0x01,
14692 ADDIUPC_02 = 0x02,
14693 ADDIUPC_03 = 0x03,
14694 ADDIUPC_04 = 0x04,
14695 ADDIUPC_05 = 0x05,
14696 ADDIUPC_06 = 0x06,
14697 ADDIUPC_07 = 0x07,
14698 AUIPC = 0x1e,
14699 ALUIPC = 0x1f,
14700 LWPC_08 = 0x08,
14701 LWPC_09 = 0x09,
14702 LWPC_0A = 0x0A,
14703 LWPC_0B = 0x0B,
14704 LWPC_0C = 0x0C,
14705 LWPC_0D = 0x0D,
14706 LWPC_0E = 0x0E,
14707 LWPC_0F = 0x0F,
14710 /* POOL32A encoding of minor opcode field */
14712 enum {
14714 * These opcodes are distinguished only by bits 9..6; those bits are
14715 * what are recorded below.
14717 SLL32 = 0x0,
14718 SRL32 = 0x1,
14719 SRA = 0x2,
14720 ROTR = 0x3,
14721 SELEQZ = 0x5,
14722 SELNEZ = 0x6,
14723 R6_RDHWR = 0x7,
14725 SLLV = 0x0,
14726 SRLV = 0x1,
14727 SRAV = 0x2,
14728 ROTRV = 0x3,
14729 ADD = 0x4,
14730 ADDU32 = 0x5,
14731 SUB = 0x6,
14732 SUBU32 = 0x7,
14733 MUL = 0x8,
14734 AND = 0x9,
14735 OR32 = 0xa,
14736 NOR = 0xb,
14737 XOR32 = 0xc,
14738 SLT = 0xd,
14739 SLTU = 0xe,
14741 MOVN = 0x0,
14742 R6_MUL = 0x0,
14743 MOVZ = 0x1,
14744 MUH = 0x1,
14745 MULU = 0x2,
14746 MUHU = 0x3,
14747 LWXS = 0x4,
14748 R6_DIV = 0x4,
14749 MOD = 0x5,
14750 R6_DIVU = 0x6,
14751 MODU = 0x7,
14753 /* The following can be distinguished by their lower 6 bits. */
14754 BREAK32 = 0x07,
14755 INS = 0x0c,
14756 LSA = 0x0f,
14757 ALIGN = 0x1f,
14758 EXT = 0x2c,
14759 POOL32AXF = 0x3c,
14760 SIGRIE = 0x3f
14763 /* POOL32AXF encoding of minor opcode field extension */
14766 * 1. MIPS Architecture for Programmers Volume II-B:
14767 * The microMIPS32 Instruction Set (Revision 3.05)
14769 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14771 * 2. MIPS Architecture for Programmers VolumeIV-e:
14772 * The MIPS DSP Application-Specific Extension
14773 * to the microMIPS32 Architecture (Revision 2.34)
14775 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14778 enum {
14779 /* bits 11..6 */
14780 TEQ = 0x00,
14781 TGE = 0x08,
14782 TGEU = 0x10,
14783 TLT = 0x20,
14784 TLTU = 0x28,
14785 TNE = 0x30,
14787 MFC0 = 0x03,
14788 MTC0 = 0x0b,
14790 /* begin of microMIPS32 DSP */
14792 /* bits 13..12 for 0x01 */
14793 MFHI_ACC = 0x0,
14794 MFLO_ACC = 0x1,
14795 MTHI_ACC = 0x2,
14796 MTLO_ACC = 0x3,
14798 /* bits 13..12 for 0x2a */
14799 MADD_ACC = 0x0,
14800 MADDU_ACC = 0x1,
14801 MSUB_ACC = 0x2,
14802 MSUBU_ACC = 0x3,
14804 /* bits 13..12 for 0x32 */
14805 MULT_ACC = 0x0,
14806 MULTU_ACC = 0x1,
14808 /* end of microMIPS32 DSP */
14810 /* bits 15..12 for 0x2c */
14811 BITSWAP = 0x0,
14812 SEB = 0x2,
14813 SEH = 0x3,
14814 CLO = 0x4,
14815 CLZ = 0x5,
14816 RDHWR = 0x6,
14817 WSBH = 0x7,
14818 MULT = 0x8,
14819 MULTU = 0x9,
14820 DIV = 0xa,
14821 DIVU = 0xb,
14822 MADD = 0xc,
14823 MADDU = 0xd,
14824 MSUB = 0xe,
14825 MSUBU = 0xf,
14827 /* bits 15..12 for 0x34 */
14828 MFC2 = 0x4,
14829 MTC2 = 0x5,
14830 MFHC2 = 0x8,
14831 MTHC2 = 0x9,
14832 CFC2 = 0xc,
14833 CTC2 = 0xd,
14835 /* bits 15..12 for 0x3c */
14836 JALR = 0x0,
14837 JR = 0x0, /* alias */
14838 JALRC = 0x0,
14839 JRC = 0x0,
14840 JALR_HB = 0x1,
14841 JALRC_HB = 0x1,
14842 JALRS = 0x4,
14843 JALRS_HB = 0x5,
14845 /* bits 15..12 for 0x05 */
14846 RDPGPR = 0xe,
14847 WRPGPR = 0xf,
14849 /* bits 15..12 for 0x0d */
14850 TLBP = 0x0,
14851 TLBR = 0x1,
14852 TLBWI = 0x2,
14853 TLBWR = 0x3,
14854 TLBINV = 0x4,
14855 TLBINVF = 0x5,
14856 WAIT = 0x9,
14857 IRET = 0xd,
14858 DERET = 0xe,
14859 ERET = 0xf,
14861 /* bits 15..12 for 0x15 */
14862 DMT = 0x0,
14863 DVPE = 0x1,
14864 EMT = 0x2,
14865 EVPE = 0x3,
14867 /* bits 15..12 for 0x1d */
14868 DI = 0x4,
14869 EI = 0x5,
14871 /* bits 15..12 for 0x2d */
14872 SYNC = 0x6,
14873 SYSCALL = 0x8,
14874 SDBBP = 0xd,
14876 /* bits 15..12 for 0x35 */
14877 MFHI32 = 0x0,
14878 MFLO32 = 0x1,
14879 MTHI32 = 0x2,
14880 MTLO32 = 0x3,
14883 /* POOL32B encoding of minor opcode field (bits 15..12) */
14885 enum {
14886 LWC2 = 0x0,
14887 LWP = 0x1,
14888 LDP = 0x4,
14889 LWM32 = 0x5,
14890 CACHE = 0x6,
14891 LDM = 0x7,
14892 SWC2 = 0x8,
14893 SWP = 0x9,
14894 SDP = 0xc,
14895 SWM32 = 0xd,
14896 SDM = 0xf
14899 /* POOL32C encoding of minor opcode field (bits 15..12) */
14901 enum {
14902 LWL = 0x0,
14903 SWL = 0x8,
14904 LWR = 0x1,
14905 SWR = 0x9,
14906 PREF = 0x2,
14907 ST_EVA = 0xa,
14908 LL = 0x3,
14909 SC = 0xb,
14910 LDL = 0x4,
14911 SDL = 0xc,
14912 LDR = 0x5,
14913 SDR = 0xd,
14914 LD_EVA = 0x6,
14915 LWU = 0xe,
14916 LLD = 0x7,
14917 SCD = 0xf
14920 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14922 enum {
14923 LBUE = 0x0,
14924 LHUE = 0x1,
14925 LWLE = 0x2,
14926 LWRE = 0x3,
14927 LBE = 0x4,
14928 LHE = 0x5,
14929 LLE = 0x6,
14930 LWE = 0x7,
14933 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14935 enum {
14936 SWLE = 0x0,
14937 SWRE = 0x1,
14938 PREFE = 0x2,
14939 CACHEE = 0x3,
14940 SBE = 0x4,
14941 SHE = 0x5,
14942 SCE = 0x6,
14943 SWE = 0x7,
14946 /* POOL32F encoding of minor opcode field (bits 5..0) */
14948 enum {
14949 /* These are the bit 7..6 values */
14950 ADD_FMT = 0x0,
14952 SUB_FMT = 0x1,
14954 MUL_FMT = 0x2,
14956 DIV_FMT = 0x3,
14958 /* These are the bit 8..6 values */
14959 MOVN_FMT = 0x0,
14960 RSQRT2_FMT = 0x0,
14961 MOVF_FMT = 0x0,
14962 RINT_FMT = 0x0,
14963 SELNEZ_FMT = 0x0,
14965 MOVZ_FMT = 0x1,
14966 LWXC1 = 0x1,
14967 MOVT_FMT = 0x1,
14968 CLASS_FMT = 0x1,
14969 SELEQZ_FMT = 0x1,
14971 PLL_PS = 0x2,
14972 SWXC1 = 0x2,
14973 SEL_FMT = 0x2,
14975 PLU_PS = 0x3,
14976 LDXC1 = 0x3,
14978 MOVN_FMT_04 = 0x4,
14979 PUL_PS = 0x4,
14980 SDXC1 = 0x4,
14981 RECIP2_FMT = 0x4,
14983 MOVZ_FMT_05 = 0x05,
14984 PUU_PS = 0x5,
14985 LUXC1 = 0x5,
14987 CVT_PS_S = 0x6,
14988 SUXC1 = 0x6,
14989 ADDR_PS = 0x6,
14990 PREFX = 0x6,
14991 MADDF_FMT = 0x6,
14993 MULR_PS = 0x7,
14994 MSUBF_FMT = 0x7,
14996 MADD_S = 0x01,
14997 MADD_D = 0x09,
14998 MADD_PS = 0x11,
14999 ALNV_PS = 0x19,
15000 MSUB_S = 0x21,
15001 MSUB_D = 0x29,
15002 MSUB_PS = 0x31,
15004 NMADD_S = 0x02,
15005 NMADD_D = 0x0a,
15006 NMADD_PS = 0x12,
15007 NMSUB_S = 0x22,
15008 NMSUB_D = 0x2a,
15009 NMSUB_PS = 0x32,
15011 MIN_FMT = 0x3,
15012 MAX_FMT = 0xb,
15013 MINA_FMT = 0x23,
15014 MAXA_FMT = 0x2b,
15015 POOL32FXF = 0x3b,
15017 CABS_COND_FMT = 0x1c, /* MIPS3D */
15018 C_COND_FMT = 0x3c,
15020 CMP_CONDN_S = 0x5,
15021 CMP_CONDN_D = 0x15
15024 /* POOL32Fxf encoding of minor opcode extension field */
15026 enum {
15027 CVT_L = 0x04,
15028 RSQRT_FMT = 0x08,
15029 FLOOR_L = 0x0c,
15030 CVT_PW_PS = 0x1c,
15031 CVT_W = 0x24,
15032 SQRT_FMT = 0x28,
15033 FLOOR_W = 0x2c,
15034 CVT_PS_PW = 0x3c,
15035 CFC1 = 0x40,
15036 RECIP_FMT = 0x48,
15037 CEIL_L = 0x4c,
15038 CTC1 = 0x60,
15039 CEIL_W = 0x6c,
15040 MFC1 = 0x80,
15041 CVT_S_PL = 0x84,
15042 TRUNC_L = 0x8c,
15043 MTC1 = 0xa0,
15044 CVT_S_PU = 0xa4,
15045 TRUNC_W = 0xac,
15046 MFHC1 = 0xc0,
15047 ROUND_L = 0xcc,
15048 MTHC1 = 0xe0,
15049 ROUND_W = 0xec,
15051 MOV_FMT = 0x01,
15052 MOVF = 0x05,
15053 ABS_FMT = 0x0d,
15054 RSQRT1_FMT = 0x1d,
15055 MOVT = 0x25,
15056 NEG_FMT = 0x2d,
15057 CVT_D = 0x4d,
15058 RECIP1_FMT = 0x5d,
15059 CVT_S = 0x6d
15062 /* POOL32I encoding of minor opcode field (bits 25..21) */
15064 enum {
15065 BLTZ = 0x00,
15066 BLTZAL = 0x01,
15067 BGEZ = 0x02,
15068 BGEZAL = 0x03,
15069 BLEZ = 0x04,
15070 BNEZC = 0x05,
15071 BGTZ = 0x06,
15072 BEQZC = 0x07,
15073 TLTI = 0x08,
15074 BC1EQZC = 0x08,
15075 TGEI = 0x09,
15076 BC1NEZC = 0x09,
15077 TLTIU = 0x0a,
15078 BC2EQZC = 0x0a,
15079 TGEIU = 0x0b,
15080 BC2NEZC = 0x0a,
15081 TNEI = 0x0c,
15082 R6_SYNCI = 0x0c,
15083 LUI = 0x0d,
15084 TEQI = 0x0e,
15085 SYNCI = 0x10,
15086 BLTZALS = 0x11,
15087 BGEZALS = 0x13,
15088 BC2F = 0x14,
15089 BC2T = 0x15,
15090 BPOSGE64 = 0x1a,
15091 BPOSGE32 = 0x1b,
15092 /* These overlap and are distinguished by bit16 of the instruction */
15093 BC1F = 0x1c,
15094 BC1T = 0x1d,
15095 BC1ANY2F = 0x1c,
15096 BC1ANY2T = 0x1d,
15097 BC1ANY4F = 0x1e,
15098 BC1ANY4T = 0x1f
15101 /* POOL16A encoding of minor opcode field */
15103 enum {
15104 ADDU16 = 0x0,
15105 SUBU16 = 0x1
15108 /* POOL16B encoding of minor opcode field */
15110 enum {
15111 SLL16 = 0x0,
15112 SRL16 = 0x1
15115 /* POOL16C encoding of minor opcode field */
15117 enum {
15118 NOT16 = 0x00,
15119 XOR16 = 0x04,
15120 AND16 = 0x08,
15121 OR16 = 0x0c,
15122 LWM16 = 0x10,
15123 SWM16 = 0x14,
15124 JR16 = 0x18,
15125 JRC16 = 0x1a,
15126 JALR16 = 0x1c,
15127 JALR16S = 0x1e,
15128 MFHI16 = 0x20,
15129 MFLO16 = 0x24,
15130 BREAK16 = 0x28,
15131 SDBBP16 = 0x2c,
15132 JRADDIUSP = 0x30
15135 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15137 enum {
15138 R6_NOT16 = 0x00,
15139 R6_AND16 = 0x01,
15140 R6_LWM16 = 0x02,
15141 R6_JRC16 = 0x03,
15142 MOVEP = 0x04,
15143 MOVEP_05 = 0x05,
15144 MOVEP_06 = 0x06,
15145 MOVEP_07 = 0x07,
15146 R6_XOR16 = 0x08,
15147 R6_OR16 = 0x09,
15148 R6_SWM16 = 0x0a,
15149 JALRC16 = 0x0b,
15150 MOVEP_0C = 0x0c,
15151 MOVEP_0D = 0x0d,
15152 MOVEP_0E = 0x0e,
15153 MOVEP_0F = 0x0f,
15154 JRCADDIUSP = 0x13,
15155 R6_BREAK16 = 0x1b,
15156 R6_SDBBP16 = 0x3b
15159 /* POOL16D encoding of minor opcode field */
15161 enum {
15162 ADDIUS5 = 0x0,
15163 ADDIUSP = 0x1
15166 /* POOL16E encoding of minor opcode field */
15168 enum {
15169 ADDIUR2 = 0x0,
15170 ADDIUR1SP = 0x1
15173 static int mmreg(int r)
15175 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15177 return map[r];
15180 /* Used for 16-bit store instructions. */
15181 static int mmreg2(int r)
15183 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15185 return map[r];
15188 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15189 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15190 #define uMIPS_RS2(op) uMIPS_RS(op)
15191 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15192 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15193 #define uMIPS_RS5(op) (op & 0x1f)
15195 /* Signed immediate */
15196 #define SIMM(op, start, width) \
15197 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15198 << (32 - width)) \
15199 >> (32 - width))
15200 /* Zero-extended immediate */
15201 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15203 static void gen_addiur1sp(DisasContext *ctx)
15205 int rd = mmreg(uMIPS_RD(ctx->opcode));
15207 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15210 static void gen_addiur2(DisasContext *ctx)
15212 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15213 int rd = mmreg(uMIPS_RD(ctx->opcode));
15214 int rs = mmreg(uMIPS_RS(ctx->opcode));
15216 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15219 static void gen_addiusp(DisasContext *ctx)
15221 int encoded = ZIMM(ctx->opcode, 1, 9);
15222 int decoded;
15224 if (encoded <= 1) {
15225 decoded = 256 + encoded;
15226 } else if (encoded <= 255) {
15227 decoded = encoded;
15228 } else if (encoded <= 509) {
15229 decoded = encoded - 512;
15230 } else {
15231 decoded = encoded - 768;
15234 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15237 static void gen_addius5(DisasContext *ctx)
15239 int imm = SIMM(ctx->opcode, 1, 4);
15240 int rd = (ctx->opcode >> 5) & 0x1f;
15242 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15245 static void gen_andi16(DisasContext *ctx)
15247 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15248 31, 32, 63, 64, 255, 32768, 65535 };
15249 int rd = mmreg(uMIPS_RD(ctx->opcode));
15250 int rs = mmreg(uMIPS_RS(ctx->opcode));
15251 int encoded = ZIMM(ctx->opcode, 0, 4);
15253 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15256 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15257 int base, int16_t offset)
15259 TCGv t0, t1;
15260 TCGv_i32 t2;
15262 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15263 generate_exception_end(ctx, EXCP_RI);
15264 return;
15267 t0 = tcg_temp_new();
15269 gen_base_offset_addr(ctx, t0, base, offset);
15271 t1 = tcg_const_tl(reglist);
15272 t2 = tcg_const_i32(ctx->mem_idx);
15274 save_cpu_state(ctx, 1);
15275 switch (opc) {
15276 case LWM32:
15277 gen_helper_lwm(cpu_env, t0, t1, t2);
15278 break;
15279 case SWM32:
15280 gen_helper_swm(cpu_env, t0, t1, t2);
15281 break;
15282 #ifdef TARGET_MIPS64
15283 case LDM:
15284 gen_helper_ldm(cpu_env, t0, t1, t2);
15285 break;
15286 case SDM:
15287 gen_helper_sdm(cpu_env, t0, t1, t2);
15288 break;
15289 #endif
15291 tcg_temp_free(t0);
15292 tcg_temp_free(t1);
15293 tcg_temp_free_i32(t2);
15297 static void gen_pool16c_insn(DisasContext *ctx)
15299 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15300 int rs = mmreg(ctx->opcode & 0x7);
15302 switch (((ctx->opcode) >> 4) & 0x3f) {
15303 case NOT16 + 0:
15304 case NOT16 + 1:
15305 case NOT16 + 2:
15306 case NOT16 + 3:
15307 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15308 break;
15309 case XOR16 + 0:
15310 case XOR16 + 1:
15311 case XOR16 + 2:
15312 case XOR16 + 3:
15313 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15314 break;
15315 case AND16 + 0:
15316 case AND16 + 1:
15317 case AND16 + 2:
15318 case AND16 + 3:
15319 gen_logic(ctx, OPC_AND, rd, rd, rs);
15320 break;
15321 case OR16 + 0:
15322 case OR16 + 1:
15323 case OR16 + 2:
15324 case OR16 + 3:
15325 gen_logic(ctx, OPC_OR, rd, rd, rs);
15326 break;
15327 case LWM16 + 0:
15328 case LWM16 + 1:
15329 case LWM16 + 2:
15330 case LWM16 + 3:
15332 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15333 int offset = ZIMM(ctx->opcode, 0, 4);
15335 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15336 29, offset << 2);
15338 break;
15339 case SWM16 + 0:
15340 case SWM16 + 1:
15341 case SWM16 + 2:
15342 case SWM16 + 3:
15344 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15345 int offset = ZIMM(ctx->opcode, 0, 4);
15347 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15348 29, offset << 2);
15350 break;
15351 case JR16 + 0:
15352 case JR16 + 1:
15354 int reg = ctx->opcode & 0x1f;
15356 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15358 break;
15359 case JRC16 + 0:
15360 case JRC16 + 1:
15362 int reg = ctx->opcode & 0x1f;
15363 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15365 * Let normal delay slot handling in our caller take us
15366 * to the branch target.
15369 break;
15370 case JALR16 + 0:
15371 case JALR16 + 1:
15372 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15373 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15374 break;
15375 case JALR16S + 0:
15376 case JALR16S + 1:
15377 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15378 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15379 break;
15380 case MFHI16 + 0:
15381 case MFHI16 + 1:
15382 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15383 break;
15384 case MFLO16 + 0:
15385 case MFLO16 + 1:
15386 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15387 break;
15388 case BREAK16:
15389 generate_exception_end(ctx, EXCP_BREAK);
15390 break;
15391 case SDBBP16:
15392 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15393 gen_helper_do_semihosting(cpu_env);
15394 } else {
15396 * XXX: not clear which exception should be raised
15397 * when in debug mode...
15399 check_insn(ctx, ISA_MIPS32);
15400 generate_exception_end(ctx, EXCP_DBp);
15402 break;
15403 case JRADDIUSP + 0:
15404 case JRADDIUSP + 1:
15406 int imm = ZIMM(ctx->opcode, 0, 5);
15407 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15408 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15410 * Let normal delay slot handling in our caller take us
15411 * to the branch target.
15414 break;
15415 default:
15416 generate_exception_end(ctx, EXCP_RI);
15417 break;
15421 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15422 int enc_rs)
15424 int rd, rs, re, rt;
15425 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15426 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15427 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15428 rd = rd_enc[enc_dest];
15429 re = re_enc[enc_dest];
15430 rs = rs_rt_enc[enc_rs];
15431 rt = rs_rt_enc[enc_rt];
15432 if (rs) {
15433 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15434 } else {
15435 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15437 if (rt) {
15438 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15439 } else {
15440 tcg_gen_movi_tl(cpu_gpr[re], 0);
15444 static void gen_pool16c_r6_insn(DisasContext *ctx)
15446 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15447 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15449 switch (ctx->opcode & 0xf) {
15450 case R6_NOT16:
15451 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15452 break;
15453 case R6_AND16:
15454 gen_logic(ctx, OPC_AND, rt, rt, rs);
15455 break;
15456 case R6_LWM16:
15458 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15459 int offset = extract32(ctx->opcode, 4, 4);
15460 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15462 break;
15463 case R6_JRC16: /* JRCADDIUSP */
15464 if ((ctx->opcode >> 4) & 1) {
15465 /* JRCADDIUSP */
15466 int imm = extract32(ctx->opcode, 5, 5);
15467 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15468 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15469 } else {
15470 /* JRC16 */
15471 rs = extract32(ctx->opcode, 5, 5);
15472 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15474 break;
15475 case MOVEP:
15476 case MOVEP_05:
15477 case MOVEP_06:
15478 case MOVEP_07:
15479 case MOVEP_0C:
15480 case MOVEP_0D:
15481 case MOVEP_0E:
15482 case MOVEP_0F:
15484 int enc_dest = uMIPS_RD(ctx->opcode);
15485 int enc_rt = uMIPS_RS2(ctx->opcode);
15486 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15487 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15489 break;
15490 case R6_XOR16:
15491 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15492 break;
15493 case R6_OR16:
15494 gen_logic(ctx, OPC_OR, rt, rt, rs);
15495 break;
15496 case R6_SWM16:
15498 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15499 int offset = extract32(ctx->opcode, 4, 4);
15500 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15502 break;
15503 case JALRC16: /* BREAK16, SDBBP16 */
15504 switch (ctx->opcode & 0x3f) {
15505 case JALRC16:
15506 case JALRC16 + 0x20:
15507 /* JALRC16 */
15508 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15509 31, 0, 0);
15510 break;
15511 case R6_BREAK16:
15512 /* BREAK16 */
15513 generate_exception(ctx, EXCP_BREAK);
15514 break;
15515 case R6_SDBBP16:
15516 /* SDBBP16 */
15517 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15518 gen_helper_do_semihosting(cpu_env);
15519 } else {
15520 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15521 generate_exception(ctx, EXCP_RI);
15522 } else {
15523 generate_exception(ctx, EXCP_DBp);
15526 break;
15528 break;
15529 default:
15530 generate_exception(ctx, EXCP_RI);
15531 break;
15535 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15537 TCGv t0 = tcg_temp_new();
15538 TCGv t1 = tcg_temp_new();
15540 gen_load_gpr(t0, base);
15542 if (index != 0) {
15543 gen_load_gpr(t1, index);
15544 tcg_gen_shli_tl(t1, t1, 2);
15545 gen_op_addr_add(ctx, t0, t1, t0);
15548 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15549 gen_store_gpr(t1, rd);
15551 tcg_temp_free(t0);
15552 tcg_temp_free(t1);
15555 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15556 int base, int16_t offset)
15558 TCGv t0, t1;
15560 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15561 generate_exception_end(ctx, EXCP_RI);
15562 return;
15565 t0 = tcg_temp_new();
15566 t1 = tcg_temp_new();
15568 gen_base_offset_addr(ctx, t0, base, offset);
15570 switch (opc) {
15571 case LWP:
15572 if (rd == base) {
15573 generate_exception_end(ctx, EXCP_RI);
15574 return;
15576 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15577 gen_store_gpr(t1, rd);
15578 tcg_gen_movi_tl(t1, 4);
15579 gen_op_addr_add(ctx, t0, t0, t1);
15580 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15581 gen_store_gpr(t1, rd + 1);
15582 break;
15583 case SWP:
15584 gen_load_gpr(t1, rd);
15585 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15586 tcg_gen_movi_tl(t1, 4);
15587 gen_op_addr_add(ctx, t0, t0, t1);
15588 gen_load_gpr(t1, rd + 1);
15589 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15590 break;
15591 #ifdef TARGET_MIPS64
15592 case LDP:
15593 if (rd == base) {
15594 generate_exception_end(ctx, EXCP_RI);
15595 return;
15597 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15598 gen_store_gpr(t1, rd);
15599 tcg_gen_movi_tl(t1, 8);
15600 gen_op_addr_add(ctx, t0, t0, t1);
15601 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15602 gen_store_gpr(t1, rd + 1);
15603 break;
15604 case SDP:
15605 gen_load_gpr(t1, rd);
15606 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15607 tcg_gen_movi_tl(t1, 8);
15608 gen_op_addr_add(ctx, t0, t0, t1);
15609 gen_load_gpr(t1, rd + 1);
15610 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15611 break;
15612 #endif
15614 tcg_temp_free(t0);
15615 tcg_temp_free(t1);
15618 static void gen_sync(int stype)
15620 TCGBar tcg_mo = TCG_BAR_SC;
15622 switch (stype) {
15623 case 0x4: /* SYNC_WMB */
15624 tcg_mo |= TCG_MO_ST_ST;
15625 break;
15626 case 0x10: /* SYNC_MB */
15627 tcg_mo |= TCG_MO_ALL;
15628 break;
15629 case 0x11: /* SYNC_ACQUIRE */
15630 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15631 break;
15632 case 0x12: /* SYNC_RELEASE */
15633 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15634 break;
15635 case 0x13: /* SYNC_RMB */
15636 tcg_mo |= TCG_MO_LD_LD;
15637 break;
15638 default:
15639 tcg_mo |= TCG_MO_ALL;
15640 break;
15643 tcg_gen_mb(tcg_mo);
15646 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15648 int extension = (ctx->opcode >> 6) & 0x3f;
15649 int minor = (ctx->opcode >> 12) & 0xf;
15650 uint32_t mips32_op;
15652 switch (extension) {
15653 case TEQ:
15654 mips32_op = OPC_TEQ;
15655 goto do_trap;
15656 case TGE:
15657 mips32_op = OPC_TGE;
15658 goto do_trap;
15659 case TGEU:
15660 mips32_op = OPC_TGEU;
15661 goto do_trap;
15662 case TLT:
15663 mips32_op = OPC_TLT;
15664 goto do_trap;
15665 case TLTU:
15666 mips32_op = OPC_TLTU;
15667 goto do_trap;
15668 case TNE:
15669 mips32_op = OPC_TNE;
15670 do_trap:
15671 gen_trap(ctx, mips32_op, rs, rt, -1);
15672 break;
15673 #ifndef CONFIG_USER_ONLY
15674 case MFC0:
15675 case MFC0 + 32:
15676 check_cp0_enabled(ctx);
15677 if (rt == 0) {
15678 /* Treat as NOP. */
15679 break;
15681 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15682 break;
15683 case MTC0:
15684 case MTC0 + 32:
15685 check_cp0_enabled(ctx);
15687 TCGv t0 = tcg_temp_new();
15689 gen_load_gpr(t0, rt);
15690 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15691 tcg_temp_free(t0);
15693 break;
15694 #endif
15695 case 0x2a:
15696 switch (minor & 3) {
15697 case MADD_ACC:
15698 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15699 break;
15700 case MADDU_ACC:
15701 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15702 break;
15703 case MSUB_ACC:
15704 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15705 break;
15706 case MSUBU_ACC:
15707 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15708 break;
15709 default:
15710 goto pool32axf_invalid;
15712 break;
15713 case 0x32:
15714 switch (minor & 3) {
15715 case MULT_ACC:
15716 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15717 break;
15718 case MULTU_ACC:
15719 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15720 break;
15721 default:
15722 goto pool32axf_invalid;
15724 break;
15725 case 0x2c:
15726 switch (minor) {
15727 case BITSWAP:
15728 check_insn(ctx, ISA_MIPS32R6);
15729 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15730 break;
15731 case SEB:
15732 gen_bshfl(ctx, OPC_SEB, rs, rt);
15733 break;
15734 case SEH:
15735 gen_bshfl(ctx, OPC_SEH, rs, rt);
15736 break;
15737 case CLO:
15738 mips32_op = OPC_CLO;
15739 goto do_cl;
15740 case CLZ:
15741 mips32_op = OPC_CLZ;
15742 do_cl:
15743 check_insn(ctx, ISA_MIPS32);
15744 gen_cl(ctx, mips32_op, rt, rs);
15745 break;
15746 case RDHWR:
15747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15748 gen_rdhwr(ctx, rt, rs, 0);
15749 break;
15750 case WSBH:
15751 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15752 break;
15753 case MULT:
15754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15755 mips32_op = OPC_MULT;
15756 goto do_mul;
15757 case MULTU:
15758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15759 mips32_op = OPC_MULTU;
15760 goto do_mul;
15761 case DIV:
15762 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15763 mips32_op = OPC_DIV;
15764 goto do_div;
15765 case DIVU:
15766 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15767 mips32_op = OPC_DIVU;
15768 goto do_div;
15769 do_div:
15770 check_insn(ctx, ISA_MIPS32);
15771 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15772 break;
15773 case MADD:
15774 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15775 mips32_op = OPC_MADD;
15776 goto do_mul;
15777 case MADDU:
15778 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15779 mips32_op = OPC_MADDU;
15780 goto do_mul;
15781 case MSUB:
15782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15783 mips32_op = OPC_MSUB;
15784 goto do_mul;
15785 case MSUBU:
15786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15787 mips32_op = OPC_MSUBU;
15788 do_mul:
15789 check_insn(ctx, ISA_MIPS32);
15790 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15791 break;
15792 default:
15793 goto pool32axf_invalid;
15795 break;
15796 case 0x34:
15797 switch (minor) {
15798 case MFC2:
15799 case MTC2:
15800 case MFHC2:
15801 case MTHC2:
15802 case CFC2:
15803 case CTC2:
15804 generate_exception_err(ctx, EXCP_CpU, 2);
15805 break;
15806 default:
15807 goto pool32axf_invalid;
15809 break;
15810 case 0x3c:
15811 switch (minor) {
15812 case JALR: /* JALRC */
15813 case JALR_HB: /* JALRC_HB */
15814 if (ctx->insn_flags & ISA_MIPS32R6) {
15815 /* JALRC, JALRC_HB */
15816 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15817 } else {
15818 /* JALR, JALR_HB */
15819 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15820 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15822 break;
15823 case JALRS:
15824 case JALRS_HB:
15825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15826 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15827 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15828 break;
15829 default:
15830 goto pool32axf_invalid;
15832 break;
15833 case 0x05:
15834 switch (minor) {
15835 case RDPGPR:
15836 check_cp0_enabled(ctx);
15837 check_insn(ctx, ISA_MIPS32R2);
15838 gen_load_srsgpr(rs, rt);
15839 break;
15840 case WRPGPR:
15841 check_cp0_enabled(ctx);
15842 check_insn(ctx, ISA_MIPS32R2);
15843 gen_store_srsgpr(rs, rt);
15844 break;
15845 default:
15846 goto pool32axf_invalid;
15848 break;
15849 #ifndef CONFIG_USER_ONLY
15850 case 0x0d:
15851 switch (minor) {
15852 case TLBP:
15853 mips32_op = OPC_TLBP;
15854 goto do_cp0;
15855 case TLBR:
15856 mips32_op = OPC_TLBR;
15857 goto do_cp0;
15858 case TLBWI:
15859 mips32_op = OPC_TLBWI;
15860 goto do_cp0;
15861 case TLBWR:
15862 mips32_op = OPC_TLBWR;
15863 goto do_cp0;
15864 case TLBINV:
15865 mips32_op = OPC_TLBINV;
15866 goto do_cp0;
15867 case TLBINVF:
15868 mips32_op = OPC_TLBINVF;
15869 goto do_cp0;
15870 case WAIT:
15871 mips32_op = OPC_WAIT;
15872 goto do_cp0;
15873 case DERET:
15874 mips32_op = OPC_DERET;
15875 goto do_cp0;
15876 case ERET:
15877 mips32_op = OPC_ERET;
15878 do_cp0:
15879 gen_cp0(env, ctx, mips32_op, rt, rs);
15880 break;
15881 default:
15882 goto pool32axf_invalid;
15884 break;
15885 case 0x1d:
15886 switch (minor) {
15887 case DI:
15888 check_cp0_enabled(ctx);
15890 TCGv t0 = tcg_temp_new();
15892 save_cpu_state(ctx, 1);
15893 gen_helper_di(t0, cpu_env);
15894 gen_store_gpr(t0, rs);
15896 * Stop translation as we may have switched the execution
15897 * mode.
15899 ctx->base.is_jmp = DISAS_STOP;
15900 tcg_temp_free(t0);
15902 break;
15903 case EI:
15904 check_cp0_enabled(ctx);
15906 TCGv t0 = tcg_temp_new();
15908 save_cpu_state(ctx, 1);
15909 gen_helper_ei(t0, cpu_env);
15910 gen_store_gpr(t0, rs);
15912 * DISAS_STOP isn't sufficient, we need to ensure we break out
15913 * of translated code to check for pending interrupts.
15915 gen_save_pc(ctx->base.pc_next + 4);
15916 ctx->base.is_jmp = DISAS_EXIT;
15917 tcg_temp_free(t0);
15919 break;
15920 default:
15921 goto pool32axf_invalid;
15923 break;
15924 #endif
15925 case 0x2d:
15926 switch (minor) {
15927 case SYNC:
15928 gen_sync(extract32(ctx->opcode, 16, 5));
15929 break;
15930 case SYSCALL:
15931 generate_exception_end(ctx, EXCP_SYSCALL);
15932 break;
15933 case SDBBP:
15934 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15935 gen_helper_do_semihosting(cpu_env);
15936 } else {
15937 check_insn(ctx, ISA_MIPS32);
15938 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15939 generate_exception_end(ctx, EXCP_RI);
15940 } else {
15941 generate_exception_end(ctx, EXCP_DBp);
15944 break;
15945 default:
15946 goto pool32axf_invalid;
15948 break;
15949 case 0x01:
15950 switch (minor & 3) {
15951 case MFHI_ACC:
15952 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15953 break;
15954 case MFLO_ACC:
15955 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15956 break;
15957 case MTHI_ACC:
15958 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15959 break;
15960 case MTLO_ACC:
15961 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15962 break;
15963 default:
15964 goto pool32axf_invalid;
15966 break;
15967 case 0x35:
15968 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15969 switch (minor) {
15970 case MFHI32:
15971 gen_HILO(ctx, OPC_MFHI, 0, rs);
15972 break;
15973 case MFLO32:
15974 gen_HILO(ctx, OPC_MFLO, 0, rs);
15975 break;
15976 case MTHI32:
15977 gen_HILO(ctx, OPC_MTHI, 0, rs);
15978 break;
15979 case MTLO32:
15980 gen_HILO(ctx, OPC_MTLO, 0, rs);
15981 break;
15982 default:
15983 goto pool32axf_invalid;
15985 break;
15986 default:
15987 pool32axf_invalid:
15988 MIPS_INVAL("pool32axf");
15989 generate_exception_end(ctx, EXCP_RI);
15990 break;
15995 * Values for microMIPS fmt field. Variable-width, depending on which
15996 * formats the instruction supports.
15998 enum {
15999 FMT_SD_S = 0,
16000 FMT_SD_D = 1,
16002 FMT_SDPS_S = 0,
16003 FMT_SDPS_D = 1,
16004 FMT_SDPS_PS = 2,
16006 FMT_SWL_S = 0,
16007 FMT_SWL_W = 1,
16008 FMT_SWL_L = 2,
16010 FMT_DWL_D = 0,
16011 FMT_DWL_W = 1,
16012 FMT_DWL_L = 2
16015 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16017 int extension = (ctx->opcode >> 6) & 0x3ff;
16018 uint32_t mips32_op;
16020 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16021 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16022 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16024 switch (extension) {
16025 case FLOAT_1BIT_FMT(CFC1, 0):
16026 mips32_op = OPC_CFC1;
16027 goto do_cp1;
16028 case FLOAT_1BIT_FMT(CTC1, 0):
16029 mips32_op = OPC_CTC1;
16030 goto do_cp1;
16031 case FLOAT_1BIT_FMT(MFC1, 0):
16032 mips32_op = OPC_MFC1;
16033 goto do_cp1;
16034 case FLOAT_1BIT_FMT(MTC1, 0):
16035 mips32_op = OPC_MTC1;
16036 goto do_cp1;
16037 case FLOAT_1BIT_FMT(MFHC1, 0):
16038 mips32_op = OPC_MFHC1;
16039 goto do_cp1;
16040 case FLOAT_1BIT_FMT(MTHC1, 0):
16041 mips32_op = OPC_MTHC1;
16042 do_cp1:
16043 gen_cp1(ctx, mips32_op, rt, rs);
16044 break;
16046 /* Reciprocal square root */
16047 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16048 mips32_op = OPC_RSQRT_S;
16049 goto do_unaryfp;
16050 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16051 mips32_op = OPC_RSQRT_D;
16052 goto do_unaryfp;
16054 /* Square root */
16055 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16056 mips32_op = OPC_SQRT_S;
16057 goto do_unaryfp;
16058 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16059 mips32_op = OPC_SQRT_D;
16060 goto do_unaryfp;
16062 /* Reciprocal */
16063 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16064 mips32_op = OPC_RECIP_S;
16065 goto do_unaryfp;
16066 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16067 mips32_op = OPC_RECIP_D;
16068 goto do_unaryfp;
16070 /* Floor */
16071 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16072 mips32_op = OPC_FLOOR_L_S;
16073 goto do_unaryfp;
16074 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16075 mips32_op = OPC_FLOOR_L_D;
16076 goto do_unaryfp;
16077 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16078 mips32_op = OPC_FLOOR_W_S;
16079 goto do_unaryfp;
16080 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16081 mips32_op = OPC_FLOOR_W_D;
16082 goto do_unaryfp;
16084 /* Ceiling */
16085 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16086 mips32_op = OPC_CEIL_L_S;
16087 goto do_unaryfp;
16088 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16089 mips32_op = OPC_CEIL_L_D;
16090 goto do_unaryfp;
16091 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16092 mips32_op = OPC_CEIL_W_S;
16093 goto do_unaryfp;
16094 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16095 mips32_op = OPC_CEIL_W_D;
16096 goto do_unaryfp;
16098 /* Truncation */
16099 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16100 mips32_op = OPC_TRUNC_L_S;
16101 goto do_unaryfp;
16102 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16103 mips32_op = OPC_TRUNC_L_D;
16104 goto do_unaryfp;
16105 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16106 mips32_op = OPC_TRUNC_W_S;
16107 goto do_unaryfp;
16108 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16109 mips32_op = OPC_TRUNC_W_D;
16110 goto do_unaryfp;
16112 /* Round */
16113 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16114 mips32_op = OPC_ROUND_L_S;
16115 goto do_unaryfp;
16116 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16117 mips32_op = OPC_ROUND_L_D;
16118 goto do_unaryfp;
16119 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16120 mips32_op = OPC_ROUND_W_S;
16121 goto do_unaryfp;
16122 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16123 mips32_op = OPC_ROUND_W_D;
16124 goto do_unaryfp;
16126 /* Integer to floating-point conversion */
16127 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16128 mips32_op = OPC_CVT_L_S;
16129 goto do_unaryfp;
16130 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16131 mips32_op = OPC_CVT_L_D;
16132 goto do_unaryfp;
16133 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16134 mips32_op = OPC_CVT_W_S;
16135 goto do_unaryfp;
16136 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16137 mips32_op = OPC_CVT_W_D;
16138 goto do_unaryfp;
16140 /* Paired-foo conversions */
16141 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16142 mips32_op = OPC_CVT_S_PL;
16143 goto do_unaryfp;
16144 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16145 mips32_op = OPC_CVT_S_PU;
16146 goto do_unaryfp;
16147 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16148 mips32_op = OPC_CVT_PW_PS;
16149 goto do_unaryfp;
16150 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16151 mips32_op = OPC_CVT_PS_PW;
16152 goto do_unaryfp;
16154 /* Floating-point moves */
16155 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16156 mips32_op = OPC_MOV_S;
16157 goto do_unaryfp;
16158 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16159 mips32_op = OPC_MOV_D;
16160 goto do_unaryfp;
16161 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16162 mips32_op = OPC_MOV_PS;
16163 goto do_unaryfp;
16165 /* Absolute value */
16166 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16167 mips32_op = OPC_ABS_S;
16168 goto do_unaryfp;
16169 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16170 mips32_op = OPC_ABS_D;
16171 goto do_unaryfp;
16172 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16173 mips32_op = OPC_ABS_PS;
16174 goto do_unaryfp;
16176 /* Negation */
16177 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16178 mips32_op = OPC_NEG_S;
16179 goto do_unaryfp;
16180 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16181 mips32_op = OPC_NEG_D;
16182 goto do_unaryfp;
16183 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16184 mips32_op = OPC_NEG_PS;
16185 goto do_unaryfp;
16187 /* Reciprocal square root step */
16188 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16189 mips32_op = OPC_RSQRT1_S;
16190 goto do_unaryfp;
16191 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16192 mips32_op = OPC_RSQRT1_D;
16193 goto do_unaryfp;
16194 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16195 mips32_op = OPC_RSQRT1_PS;
16196 goto do_unaryfp;
16198 /* Reciprocal step */
16199 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16200 mips32_op = OPC_RECIP1_S;
16201 goto do_unaryfp;
16202 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16203 mips32_op = OPC_RECIP1_S;
16204 goto do_unaryfp;
16205 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16206 mips32_op = OPC_RECIP1_PS;
16207 goto do_unaryfp;
16209 /* Conversions from double */
16210 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16211 mips32_op = OPC_CVT_D_S;
16212 goto do_unaryfp;
16213 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16214 mips32_op = OPC_CVT_D_W;
16215 goto do_unaryfp;
16216 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16217 mips32_op = OPC_CVT_D_L;
16218 goto do_unaryfp;
16220 /* Conversions from single */
16221 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16222 mips32_op = OPC_CVT_S_D;
16223 goto do_unaryfp;
16224 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16225 mips32_op = OPC_CVT_S_W;
16226 goto do_unaryfp;
16227 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16228 mips32_op = OPC_CVT_S_L;
16229 do_unaryfp:
16230 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16231 break;
16233 /* Conditional moves on floating-point codes */
16234 case COND_FLOAT_MOV(MOVT, 0):
16235 case COND_FLOAT_MOV(MOVT, 1):
16236 case COND_FLOAT_MOV(MOVT, 2):
16237 case COND_FLOAT_MOV(MOVT, 3):
16238 case COND_FLOAT_MOV(MOVT, 4):
16239 case COND_FLOAT_MOV(MOVT, 5):
16240 case COND_FLOAT_MOV(MOVT, 6):
16241 case COND_FLOAT_MOV(MOVT, 7):
16242 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16243 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16244 break;
16245 case COND_FLOAT_MOV(MOVF, 0):
16246 case COND_FLOAT_MOV(MOVF, 1):
16247 case COND_FLOAT_MOV(MOVF, 2):
16248 case COND_FLOAT_MOV(MOVF, 3):
16249 case COND_FLOAT_MOV(MOVF, 4):
16250 case COND_FLOAT_MOV(MOVF, 5):
16251 case COND_FLOAT_MOV(MOVF, 6):
16252 case COND_FLOAT_MOV(MOVF, 7):
16253 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16254 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16255 break;
16256 default:
16257 MIPS_INVAL("pool32fxf");
16258 generate_exception_end(ctx, EXCP_RI);
16259 break;
16263 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16265 int32_t offset;
16266 uint16_t insn;
16267 int rt, rs, rd, rr;
16268 int16_t imm;
16269 uint32_t op, minor, minor2, mips32_op;
16270 uint32_t cond, fmt, cc;
16272 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16273 ctx->opcode = (ctx->opcode << 16) | insn;
16275 rt = (ctx->opcode >> 21) & 0x1f;
16276 rs = (ctx->opcode >> 16) & 0x1f;
16277 rd = (ctx->opcode >> 11) & 0x1f;
16278 rr = (ctx->opcode >> 6) & 0x1f;
16279 imm = (int16_t) ctx->opcode;
16281 op = (ctx->opcode >> 26) & 0x3f;
16282 switch (op) {
16283 case POOL32A:
16284 minor = ctx->opcode & 0x3f;
16285 switch (minor) {
16286 case 0x00:
16287 minor = (ctx->opcode >> 6) & 0xf;
16288 switch (minor) {
16289 case SLL32:
16290 mips32_op = OPC_SLL;
16291 goto do_shifti;
16292 case SRA:
16293 mips32_op = OPC_SRA;
16294 goto do_shifti;
16295 case SRL32:
16296 mips32_op = OPC_SRL;
16297 goto do_shifti;
16298 case ROTR:
16299 mips32_op = OPC_ROTR;
16300 do_shifti:
16301 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16302 break;
16303 case SELEQZ:
16304 check_insn(ctx, ISA_MIPS32R6);
16305 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16306 break;
16307 case SELNEZ:
16308 check_insn(ctx, ISA_MIPS32R6);
16309 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16310 break;
16311 case R6_RDHWR:
16312 check_insn(ctx, ISA_MIPS32R6);
16313 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16314 break;
16315 default:
16316 goto pool32a_invalid;
16318 break;
16319 case 0x10:
16320 minor = (ctx->opcode >> 6) & 0xf;
16321 switch (minor) {
16322 /* Arithmetic */
16323 case ADD:
16324 mips32_op = OPC_ADD;
16325 goto do_arith;
16326 case ADDU32:
16327 mips32_op = OPC_ADDU;
16328 goto do_arith;
16329 case SUB:
16330 mips32_op = OPC_SUB;
16331 goto do_arith;
16332 case SUBU32:
16333 mips32_op = OPC_SUBU;
16334 goto do_arith;
16335 case MUL:
16336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16337 mips32_op = OPC_MUL;
16338 do_arith:
16339 gen_arith(ctx, mips32_op, rd, rs, rt);
16340 break;
16341 /* Shifts */
16342 case SLLV:
16343 mips32_op = OPC_SLLV;
16344 goto do_shift;
16345 case SRLV:
16346 mips32_op = OPC_SRLV;
16347 goto do_shift;
16348 case SRAV:
16349 mips32_op = OPC_SRAV;
16350 goto do_shift;
16351 case ROTRV:
16352 mips32_op = OPC_ROTRV;
16353 do_shift:
16354 gen_shift(ctx, mips32_op, rd, rs, rt);
16355 break;
16356 /* Logical operations */
16357 case AND:
16358 mips32_op = OPC_AND;
16359 goto do_logic;
16360 case OR32:
16361 mips32_op = OPC_OR;
16362 goto do_logic;
16363 case NOR:
16364 mips32_op = OPC_NOR;
16365 goto do_logic;
16366 case XOR32:
16367 mips32_op = OPC_XOR;
16368 do_logic:
16369 gen_logic(ctx, mips32_op, rd, rs, rt);
16370 break;
16371 /* Set less than */
16372 case SLT:
16373 mips32_op = OPC_SLT;
16374 goto do_slt;
16375 case SLTU:
16376 mips32_op = OPC_SLTU;
16377 do_slt:
16378 gen_slt(ctx, mips32_op, rd, rs, rt);
16379 break;
16380 default:
16381 goto pool32a_invalid;
16383 break;
16384 case 0x18:
16385 minor = (ctx->opcode >> 6) & 0xf;
16386 switch (minor) {
16387 /* Conditional moves */
16388 case MOVN: /* MUL */
16389 if (ctx->insn_flags & ISA_MIPS32R6) {
16390 /* MUL */
16391 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16392 } else {
16393 /* MOVN */
16394 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16396 break;
16397 case MOVZ: /* MUH */
16398 if (ctx->insn_flags & ISA_MIPS32R6) {
16399 /* MUH */
16400 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16401 } else {
16402 /* MOVZ */
16403 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16405 break;
16406 case MULU:
16407 check_insn(ctx, ISA_MIPS32R6);
16408 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16409 break;
16410 case MUHU:
16411 check_insn(ctx, ISA_MIPS32R6);
16412 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16413 break;
16414 case LWXS: /* DIV */
16415 if (ctx->insn_flags & ISA_MIPS32R6) {
16416 /* DIV */
16417 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16418 } else {
16419 /* LWXS */
16420 gen_ldxs(ctx, rs, rt, rd);
16422 break;
16423 case MOD:
16424 check_insn(ctx, ISA_MIPS32R6);
16425 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16426 break;
16427 case R6_DIVU:
16428 check_insn(ctx, ISA_MIPS32R6);
16429 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16430 break;
16431 case MODU:
16432 check_insn(ctx, ISA_MIPS32R6);
16433 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16434 break;
16435 default:
16436 goto pool32a_invalid;
16438 break;
16439 case INS:
16440 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16441 return;
16442 case LSA:
16443 check_insn(ctx, ISA_MIPS32R6);
16444 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16445 extract32(ctx->opcode, 9, 2));
16446 break;
16447 case ALIGN:
16448 check_insn(ctx, ISA_MIPS32R6);
16449 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16450 break;
16451 case EXT:
16452 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16453 return;
16454 case POOL32AXF:
16455 gen_pool32axf(env, ctx, rt, rs);
16456 break;
16457 case BREAK32:
16458 generate_exception_end(ctx, EXCP_BREAK);
16459 break;
16460 case SIGRIE:
16461 check_insn(ctx, ISA_MIPS32R6);
16462 generate_exception_end(ctx, EXCP_RI);
16463 break;
16464 default:
16465 pool32a_invalid:
16466 MIPS_INVAL("pool32a");
16467 generate_exception_end(ctx, EXCP_RI);
16468 break;
16470 break;
16471 case POOL32B:
16472 minor = (ctx->opcode >> 12) & 0xf;
16473 switch (minor) {
16474 case CACHE:
16475 check_cp0_enabled(ctx);
16476 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16477 gen_cache_operation(ctx, rt, rs, imm);
16479 break;
16480 case LWC2:
16481 case SWC2:
16482 /* COP2: Not implemented. */
16483 generate_exception_err(ctx, EXCP_CpU, 2);
16484 break;
16485 #ifdef TARGET_MIPS64
16486 case LDP:
16487 case SDP:
16488 check_insn(ctx, ISA_MIPS3);
16489 check_mips_64(ctx);
16490 #endif
16491 /* fall through */
16492 case LWP:
16493 case SWP:
16494 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16495 break;
16496 #ifdef TARGET_MIPS64
16497 case LDM:
16498 case SDM:
16499 check_insn(ctx, ISA_MIPS3);
16500 check_mips_64(ctx);
16501 #endif
16502 /* fall through */
16503 case LWM32:
16504 case SWM32:
16505 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16506 break;
16507 default:
16508 MIPS_INVAL("pool32b");
16509 generate_exception_end(ctx, EXCP_RI);
16510 break;
16512 break;
16513 case POOL32F:
16514 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16515 minor = ctx->opcode & 0x3f;
16516 check_cp1_enabled(ctx);
16517 switch (minor) {
16518 case ALNV_PS:
16519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16520 mips32_op = OPC_ALNV_PS;
16521 goto do_madd;
16522 case MADD_S:
16523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16524 mips32_op = OPC_MADD_S;
16525 goto do_madd;
16526 case MADD_D:
16527 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16528 mips32_op = OPC_MADD_D;
16529 goto do_madd;
16530 case MADD_PS:
16531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16532 mips32_op = OPC_MADD_PS;
16533 goto do_madd;
16534 case MSUB_S:
16535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16536 mips32_op = OPC_MSUB_S;
16537 goto do_madd;
16538 case MSUB_D:
16539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16540 mips32_op = OPC_MSUB_D;
16541 goto do_madd;
16542 case MSUB_PS:
16543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16544 mips32_op = OPC_MSUB_PS;
16545 goto do_madd;
16546 case NMADD_S:
16547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16548 mips32_op = OPC_NMADD_S;
16549 goto do_madd;
16550 case NMADD_D:
16551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16552 mips32_op = OPC_NMADD_D;
16553 goto do_madd;
16554 case NMADD_PS:
16555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16556 mips32_op = OPC_NMADD_PS;
16557 goto do_madd;
16558 case NMSUB_S:
16559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16560 mips32_op = OPC_NMSUB_S;
16561 goto do_madd;
16562 case NMSUB_D:
16563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16564 mips32_op = OPC_NMSUB_D;
16565 goto do_madd;
16566 case NMSUB_PS:
16567 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16568 mips32_op = OPC_NMSUB_PS;
16569 do_madd:
16570 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16571 break;
16572 case CABS_COND_FMT:
16573 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16574 cond = (ctx->opcode >> 6) & 0xf;
16575 cc = (ctx->opcode >> 13) & 0x7;
16576 fmt = (ctx->opcode >> 10) & 0x3;
16577 switch (fmt) {
16578 case 0x0:
16579 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16580 break;
16581 case 0x1:
16582 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16583 break;
16584 case 0x2:
16585 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16586 break;
16587 default:
16588 goto pool32f_invalid;
16590 break;
16591 case C_COND_FMT:
16592 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16593 cond = (ctx->opcode >> 6) & 0xf;
16594 cc = (ctx->opcode >> 13) & 0x7;
16595 fmt = (ctx->opcode >> 10) & 0x3;
16596 switch (fmt) {
16597 case 0x0:
16598 gen_cmp_s(ctx, cond, rt, rs, cc);
16599 break;
16600 case 0x1:
16601 gen_cmp_d(ctx, cond, rt, rs, cc);
16602 break;
16603 case 0x2:
16604 gen_cmp_ps(ctx, cond, rt, rs, cc);
16605 break;
16606 default:
16607 goto pool32f_invalid;
16609 break;
16610 case CMP_CONDN_S:
16611 check_insn(ctx, ISA_MIPS32R6);
16612 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16613 break;
16614 case CMP_CONDN_D:
16615 check_insn(ctx, ISA_MIPS32R6);
16616 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16617 break;
16618 case POOL32FXF:
16619 gen_pool32fxf(ctx, rt, rs);
16620 break;
16621 case 0x00:
16622 /* PLL foo */
16623 switch ((ctx->opcode >> 6) & 0x7) {
16624 case PLL_PS:
16625 mips32_op = OPC_PLL_PS;
16626 goto do_ps;
16627 case PLU_PS:
16628 mips32_op = OPC_PLU_PS;
16629 goto do_ps;
16630 case PUL_PS:
16631 mips32_op = OPC_PUL_PS;
16632 goto do_ps;
16633 case PUU_PS:
16634 mips32_op = OPC_PUU_PS;
16635 goto do_ps;
16636 case CVT_PS_S:
16637 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16638 mips32_op = OPC_CVT_PS_S;
16639 do_ps:
16640 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16641 break;
16642 default:
16643 goto pool32f_invalid;
16645 break;
16646 case MIN_FMT:
16647 check_insn(ctx, ISA_MIPS32R6);
16648 switch ((ctx->opcode >> 9) & 0x3) {
16649 case FMT_SDPS_S:
16650 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16651 break;
16652 case FMT_SDPS_D:
16653 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16654 break;
16655 default:
16656 goto pool32f_invalid;
16658 break;
16659 case 0x08:
16660 /* [LS][WDU]XC1 */
16661 switch ((ctx->opcode >> 6) & 0x7) {
16662 case LWXC1:
16663 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16664 mips32_op = OPC_LWXC1;
16665 goto do_ldst_cp1;
16666 case SWXC1:
16667 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16668 mips32_op = OPC_SWXC1;
16669 goto do_ldst_cp1;
16670 case LDXC1:
16671 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16672 mips32_op = OPC_LDXC1;
16673 goto do_ldst_cp1;
16674 case SDXC1:
16675 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16676 mips32_op = OPC_SDXC1;
16677 goto do_ldst_cp1;
16678 case LUXC1:
16679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16680 mips32_op = OPC_LUXC1;
16681 goto do_ldst_cp1;
16682 case SUXC1:
16683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16684 mips32_op = OPC_SUXC1;
16685 do_ldst_cp1:
16686 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16687 break;
16688 default:
16689 goto pool32f_invalid;
16691 break;
16692 case MAX_FMT:
16693 check_insn(ctx, ISA_MIPS32R6);
16694 switch ((ctx->opcode >> 9) & 0x3) {
16695 case FMT_SDPS_S:
16696 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16697 break;
16698 case FMT_SDPS_D:
16699 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16700 break;
16701 default:
16702 goto pool32f_invalid;
16704 break;
16705 case 0x18:
16706 /* 3D insns */
16707 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16708 fmt = (ctx->opcode >> 9) & 0x3;
16709 switch ((ctx->opcode >> 6) & 0x7) {
16710 case RSQRT2_FMT:
16711 switch (fmt) {
16712 case FMT_SDPS_S:
16713 mips32_op = OPC_RSQRT2_S;
16714 goto do_3d;
16715 case FMT_SDPS_D:
16716 mips32_op = OPC_RSQRT2_D;
16717 goto do_3d;
16718 case FMT_SDPS_PS:
16719 mips32_op = OPC_RSQRT2_PS;
16720 goto do_3d;
16721 default:
16722 goto pool32f_invalid;
16724 break;
16725 case RECIP2_FMT:
16726 switch (fmt) {
16727 case FMT_SDPS_S:
16728 mips32_op = OPC_RECIP2_S;
16729 goto do_3d;
16730 case FMT_SDPS_D:
16731 mips32_op = OPC_RECIP2_D;
16732 goto do_3d;
16733 case FMT_SDPS_PS:
16734 mips32_op = OPC_RECIP2_PS;
16735 goto do_3d;
16736 default:
16737 goto pool32f_invalid;
16739 break;
16740 case ADDR_PS:
16741 mips32_op = OPC_ADDR_PS;
16742 goto do_3d;
16743 case MULR_PS:
16744 mips32_op = OPC_MULR_PS;
16745 do_3d:
16746 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16747 break;
16748 default:
16749 goto pool32f_invalid;
16751 break;
16752 case 0x20:
16753 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16754 cc = (ctx->opcode >> 13) & 0x7;
16755 fmt = (ctx->opcode >> 9) & 0x3;
16756 switch ((ctx->opcode >> 6) & 0x7) {
16757 case MOVF_FMT: /* RINT_FMT */
16758 if (ctx->insn_flags & ISA_MIPS32R6) {
16759 /* RINT_FMT */
16760 switch (fmt) {
16761 case FMT_SDPS_S:
16762 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16763 break;
16764 case FMT_SDPS_D:
16765 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16766 break;
16767 default:
16768 goto pool32f_invalid;
16770 } else {
16771 /* MOVF_FMT */
16772 switch (fmt) {
16773 case FMT_SDPS_S:
16774 gen_movcf_s(ctx, rs, rt, cc, 0);
16775 break;
16776 case FMT_SDPS_D:
16777 gen_movcf_d(ctx, rs, rt, cc, 0);
16778 break;
16779 case FMT_SDPS_PS:
16780 check_ps(ctx);
16781 gen_movcf_ps(ctx, rs, rt, cc, 0);
16782 break;
16783 default:
16784 goto pool32f_invalid;
16787 break;
16788 case MOVT_FMT: /* CLASS_FMT */
16789 if (ctx->insn_flags & ISA_MIPS32R6) {
16790 /* CLASS_FMT */
16791 switch (fmt) {
16792 case FMT_SDPS_S:
16793 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16794 break;
16795 case FMT_SDPS_D:
16796 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16797 break;
16798 default:
16799 goto pool32f_invalid;
16801 } else {
16802 /* MOVT_FMT */
16803 switch (fmt) {
16804 case FMT_SDPS_S:
16805 gen_movcf_s(ctx, rs, rt, cc, 1);
16806 break;
16807 case FMT_SDPS_D:
16808 gen_movcf_d(ctx, rs, rt, cc, 1);
16809 break;
16810 case FMT_SDPS_PS:
16811 check_ps(ctx);
16812 gen_movcf_ps(ctx, rs, rt, cc, 1);
16813 break;
16814 default:
16815 goto pool32f_invalid;
16818 break;
16819 case PREFX:
16820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16821 break;
16822 default:
16823 goto pool32f_invalid;
16825 break;
16826 #define FINSN_3ARG_SDPS(prfx) \
16827 switch ((ctx->opcode >> 8) & 0x3) { \
16828 case FMT_SDPS_S: \
16829 mips32_op = OPC_##prfx##_S; \
16830 goto do_fpop; \
16831 case FMT_SDPS_D: \
16832 mips32_op = OPC_##prfx##_D; \
16833 goto do_fpop; \
16834 case FMT_SDPS_PS: \
16835 check_ps(ctx); \
16836 mips32_op = OPC_##prfx##_PS; \
16837 goto do_fpop; \
16838 default: \
16839 goto pool32f_invalid; \
16841 case MINA_FMT:
16842 check_insn(ctx, ISA_MIPS32R6);
16843 switch ((ctx->opcode >> 9) & 0x3) {
16844 case FMT_SDPS_S:
16845 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16846 break;
16847 case FMT_SDPS_D:
16848 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16849 break;
16850 default:
16851 goto pool32f_invalid;
16853 break;
16854 case MAXA_FMT:
16855 check_insn(ctx, ISA_MIPS32R6);
16856 switch ((ctx->opcode >> 9) & 0x3) {
16857 case FMT_SDPS_S:
16858 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16859 break;
16860 case FMT_SDPS_D:
16861 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16862 break;
16863 default:
16864 goto pool32f_invalid;
16866 break;
16867 case 0x30:
16868 /* regular FP ops */
16869 switch ((ctx->opcode >> 6) & 0x3) {
16870 case ADD_FMT:
16871 FINSN_3ARG_SDPS(ADD);
16872 break;
16873 case SUB_FMT:
16874 FINSN_3ARG_SDPS(SUB);
16875 break;
16876 case MUL_FMT:
16877 FINSN_3ARG_SDPS(MUL);
16878 break;
16879 case DIV_FMT:
16880 fmt = (ctx->opcode >> 8) & 0x3;
16881 if (fmt == 1) {
16882 mips32_op = OPC_DIV_D;
16883 } else if (fmt == 0) {
16884 mips32_op = OPC_DIV_S;
16885 } else {
16886 goto pool32f_invalid;
16888 goto do_fpop;
16889 default:
16890 goto pool32f_invalid;
16892 break;
16893 case 0x38:
16894 /* cmovs */
16895 switch ((ctx->opcode >> 6) & 0x7) {
16896 case MOVN_FMT: /* SELEQZ_FMT */
16897 if (ctx->insn_flags & ISA_MIPS32R6) {
16898 /* SELEQZ_FMT */
16899 switch ((ctx->opcode >> 9) & 0x3) {
16900 case FMT_SDPS_S:
16901 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16902 break;
16903 case FMT_SDPS_D:
16904 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16905 break;
16906 default:
16907 goto pool32f_invalid;
16909 } else {
16910 /* MOVN_FMT */
16911 FINSN_3ARG_SDPS(MOVN);
16913 break;
16914 case MOVN_FMT_04:
16915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16916 FINSN_3ARG_SDPS(MOVN);
16917 break;
16918 case MOVZ_FMT: /* SELNEZ_FMT */
16919 if (ctx->insn_flags & ISA_MIPS32R6) {
16920 /* SELNEZ_FMT */
16921 switch ((ctx->opcode >> 9) & 0x3) {
16922 case FMT_SDPS_S:
16923 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16924 break;
16925 case FMT_SDPS_D:
16926 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16927 break;
16928 default:
16929 goto pool32f_invalid;
16931 } else {
16932 /* MOVZ_FMT */
16933 FINSN_3ARG_SDPS(MOVZ);
16935 break;
16936 case MOVZ_FMT_05:
16937 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16938 FINSN_3ARG_SDPS(MOVZ);
16939 break;
16940 case SEL_FMT:
16941 check_insn(ctx, ISA_MIPS32R6);
16942 switch ((ctx->opcode >> 9) & 0x3) {
16943 case FMT_SDPS_S:
16944 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16945 break;
16946 case FMT_SDPS_D:
16947 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16948 break;
16949 default:
16950 goto pool32f_invalid;
16952 break;
16953 case MADDF_FMT:
16954 check_insn(ctx, ISA_MIPS32R6);
16955 switch ((ctx->opcode >> 9) & 0x3) {
16956 case FMT_SDPS_S:
16957 mips32_op = OPC_MADDF_S;
16958 goto do_fpop;
16959 case FMT_SDPS_D:
16960 mips32_op = OPC_MADDF_D;
16961 goto do_fpop;
16962 default:
16963 goto pool32f_invalid;
16965 break;
16966 case MSUBF_FMT:
16967 check_insn(ctx, ISA_MIPS32R6);
16968 switch ((ctx->opcode >> 9) & 0x3) {
16969 case FMT_SDPS_S:
16970 mips32_op = OPC_MSUBF_S;
16971 goto do_fpop;
16972 case FMT_SDPS_D:
16973 mips32_op = OPC_MSUBF_D;
16974 goto do_fpop;
16975 default:
16976 goto pool32f_invalid;
16978 break;
16979 default:
16980 goto pool32f_invalid;
16982 break;
16983 do_fpop:
16984 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16985 break;
16986 default:
16987 pool32f_invalid:
16988 MIPS_INVAL("pool32f");
16989 generate_exception_end(ctx, EXCP_RI);
16990 break;
16992 } else {
16993 generate_exception_err(ctx, EXCP_CpU, 1);
16995 break;
16996 case POOL32I:
16997 minor = (ctx->opcode >> 21) & 0x1f;
16998 switch (minor) {
16999 case BLTZ:
17000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17001 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17002 break;
17003 case BLTZAL:
17004 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17005 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17006 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17007 break;
17008 case BLTZALS:
17009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17010 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17011 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17012 break;
17013 case BGEZ:
17014 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17015 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17016 break;
17017 case BGEZAL:
17018 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17019 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17020 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17021 break;
17022 case BGEZALS:
17023 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17024 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17025 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17026 break;
17027 case BLEZ:
17028 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17029 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17030 break;
17031 case BGTZ:
17032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17033 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17034 break;
17036 /* Traps */
17037 case TLTI: /* BC1EQZC */
17038 if (ctx->insn_flags & ISA_MIPS32R6) {
17039 /* BC1EQZC */
17040 check_cp1_enabled(ctx);
17041 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17042 } else {
17043 /* TLTI */
17044 mips32_op = OPC_TLTI;
17045 goto do_trapi;
17047 break;
17048 case TGEI: /* BC1NEZC */
17049 if (ctx->insn_flags & ISA_MIPS32R6) {
17050 /* BC1NEZC */
17051 check_cp1_enabled(ctx);
17052 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17053 } else {
17054 /* TGEI */
17055 mips32_op = OPC_TGEI;
17056 goto do_trapi;
17058 break;
17059 case TLTIU:
17060 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17061 mips32_op = OPC_TLTIU;
17062 goto do_trapi;
17063 case TGEIU:
17064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17065 mips32_op = OPC_TGEIU;
17066 goto do_trapi;
17067 case TNEI: /* SYNCI */
17068 if (ctx->insn_flags & ISA_MIPS32R6) {
17069 /* SYNCI */
17071 * Break the TB to be able to sync copied instructions
17072 * immediately.
17074 ctx->base.is_jmp = DISAS_STOP;
17075 } else {
17076 /* TNEI */
17077 mips32_op = OPC_TNEI;
17078 goto do_trapi;
17080 break;
17081 case TEQI:
17082 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17083 mips32_op = OPC_TEQI;
17084 do_trapi:
17085 gen_trap(ctx, mips32_op, rs, -1, imm);
17086 break;
17088 case BNEZC:
17089 case BEQZC:
17090 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17091 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17092 4, rs, 0, imm << 1, 0);
17094 * Compact branches don't have a delay slot, so just let
17095 * the normal delay slot handling take us to the branch
17096 * target.
17098 break;
17099 case LUI:
17100 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17101 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17102 break;
17103 case SYNCI:
17104 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17106 * Break the TB to be able to sync copied instructions
17107 * immediately.
17109 ctx->base.is_jmp = DISAS_STOP;
17110 break;
17111 case BC2F:
17112 case BC2T:
17113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17114 /* COP2: Not implemented. */
17115 generate_exception_err(ctx, EXCP_CpU, 2);
17116 break;
17117 case BC1F:
17118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17119 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17120 goto do_cp1branch;
17121 case BC1T:
17122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17123 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17124 goto do_cp1branch;
17125 case BC1ANY4F:
17126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17127 mips32_op = OPC_BC1FANY4;
17128 goto do_cp1mips3d;
17129 case BC1ANY4T:
17130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17131 mips32_op = OPC_BC1TANY4;
17132 do_cp1mips3d:
17133 check_cop1x(ctx);
17134 check_insn(ctx, ASE_MIPS3D);
17135 /* Fall through */
17136 do_cp1branch:
17137 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17138 check_cp1_enabled(ctx);
17139 gen_compute_branch1(ctx, mips32_op,
17140 (ctx->opcode >> 18) & 0x7, imm << 1);
17141 } else {
17142 generate_exception_err(ctx, EXCP_CpU, 1);
17144 break;
17145 case BPOSGE64:
17146 case BPOSGE32:
17147 /* MIPS DSP: not implemented */
17148 /* Fall through */
17149 default:
17150 MIPS_INVAL("pool32i");
17151 generate_exception_end(ctx, EXCP_RI);
17152 break;
17154 break;
17155 case POOL32C:
17156 minor = (ctx->opcode >> 12) & 0xf;
17157 offset = sextract32(ctx->opcode, 0,
17158 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
17159 switch (minor) {
17160 case LWL:
17161 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17162 mips32_op = OPC_LWL;
17163 goto do_ld_lr;
17164 case SWL:
17165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17166 mips32_op = OPC_SWL;
17167 goto do_st_lr;
17168 case LWR:
17169 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17170 mips32_op = OPC_LWR;
17171 goto do_ld_lr;
17172 case SWR:
17173 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17174 mips32_op = OPC_SWR;
17175 goto do_st_lr;
17176 #if defined(TARGET_MIPS64)
17177 case LDL:
17178 check_insn(ctx, ISA_MIPS3);
17179 check_mips_64(ctx);
17180 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17181 mips32_op = OPC_LDL;
17182 goto do_ld_lr;
17183 case SDL:
17184 check_insn(ctx, ISA_MIPS3);
17185 check_mips_64(ctx);
17186 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17187 mips32_op = OPC_SDL;
17188 goto do_st_lr;
17189 case LDR:
17190 check_insn(ctx, ISA_MIPS3);
17191 check_mips_64(ctx);
17192 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17193 mips32_op = OPC_LDR;
17194 goto do_ld_lr;
17195 case SDR:
17196 check_insn(ctx, ISA_MIPS3);
17197 check_mips_64(ctx);
17198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17199 mips32_op = OPC_SDR;
17200 goto do_st_lr;
17201 case LWU:
17202 check_insn(ctx, ISA_MIPS3);
17203 check_mips_64(ctx);
17204 mips32_op = OPC_LWU;
17205 goto do_ld_lr;
17206 case LLD:
17207 check_insn(ctx, ISA_MIPS3);
17208 check_mips_64(ctx);
17209 mips32_op = OPC_LLD;
17210 goto do_ld_lr;
17211 #endif
17212 case LL:
17213 mips32_op = OPC_LL;
17214 goto do_ld_lr;
17215 do_ld_lr:
17216 gen_ld(ctx, mips32_op, rt, rs, offset);
17217 break;
17218 do_st_lr:
17219 gen_st(ctx, mips32_op, rt, rs, offset);
17220 break;
17221 case SC:
17222 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17223 break;
17224 #if defined(TARGET_MIPS64)
17225 case SCD:
17226 check_insn(ctx, ISA_MIPS3);
17227 check_mips_64(ctx);
17228 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17229 break;
17230 #endif
17231 case LD_EVA:
17232 if (!ctx->eva) {
17233 MIPS_INVAL("pool32c ld-eva");
17234 generate_exception_end(ctx, EXCP_RI);
17235 break;
17237 check_cp0_enabled(ctx);
17239 minor2 = (ctx->opcode >> 9) & 0x7;
17240 offset = sextract32(ctx->opcode, 0, 9);
17241 switch (minor2) {
17242 case LBUE:
17243 mips32_op = OPC_LBUE;
17244 goto do_ld_lr;
17245 case LHUE:
17246 mips32_op = OPC_LHUE;
17247 goto do_ld_lr;
17248 case LWLE:
17249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17250 mips32_op = OPC_LWLE;
17251 goto do_ld_lr;
17252 case LWRE:
17253 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17254 mips32_op = OPC_LWRE;
17255 goto do_ld_lr;
17256 case LBE:
17257 mips32_op = OPC_LBE;
17258 goto do_ld_lr;
17259 case LHE:
17260 mips32_op = OPC_LHE;
17261 goto do_ld_lr;
17262 case LLE:
17263 mips32_op = OPC_LLE;
17264 goto do_ld_lr;
17265 case LWE:
17266 mips32_op = OPC_LWE;
17267 goto do_ld_lr;
17269 break;
17270 case ST_EVA:
17271 if (!ctx->eva) {
17272 MIPS_INVAL("pool32c st-eva");
17273 generate_exception_end(ctx, EXCP_RI);
17274 break;
17276 check_cp0_enabled(ctx);
17278 minor2 = (ctx->opcode >> 9) & 0x7;
17279 offset = sextract32(ctx->opcode, 0, 9);
17280 switch (minor2) {
17281 case SWLE:
17282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17283 mips32_op = OPC_SWLE;
17284 goto do_st_lr;
17285 case SWRE:
17286 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17287 mips32_op = OPC_SWRE;
17288 goto do_st_lr;
17289 case PREFE:
17290 /* Treat as no-op */
17291 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17292 /* hint codes 24-31 are reserved and signal RI */
17293 generate_exception(ctx, EXCP_RI);
17295 break;
17296 case CACHEE:
17297 /* Treat as no-op */
17298 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17299 gen_cache_operation(ctx, rt, rs, offset);
17301 break;
17302 case SBE:
17303 mips32_op = OPC_SBE;
17304 goto do_st_lr;
17305 case SHE:
17306 mips32_op = OPC_SHE;
17307 goto do_st_lr;
17308 case SCE:
17309 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17310 break;
17311 case SWE:
17312 mips32_op = OPC_SWE;
17313 goto do_st_lr;
17315 break;
17316 case PREF:
17317 /* Treat as no-op */
17318 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17319 /* hint codes 24-31 are reserved and signal RI */
17320 generate_exception(ctx, EXCP_RI);
17322 break;
17323 default:
17324 MIPS_INVAL("pool32c");
17325 generate_exception_end(ctx, EXCP_RI);
17326 break;
17328 break;
17329 case ADDI32: /* AUI, LUI */
17330 if (ctx->insn_flags & ISA_MIPS32R6) {
17331 /* AUI, LUI */
17332 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17333 } else {
17334 /* ADDI32 */
17335 mips32_op = OPC_ADDI;
17336 goto do_addi;
17338 break;
17339 case ADDIU32:
17340 mips32_op = OPC_ADDIU;
17341 do_addi:
17342 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17343 break;
17345 /* Logical operations */
17346 case ORI32:
17347 mips32_op = OPC_ORI;
17348 goto do_logici;
17349 case XORI32:
17350 mips32_op = OPC_XORI;
17351 goto do_logici;
17352 case ANDI32:
17353 mips32_op = OPC_ANDI;
17354 do_logici:
17355 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17356 break;
17358 /* Set less than immediate */
17359 case SLTI32:
17360 mips32_op = OPC_SLTI;
17361 goto do_slti;
17362 case SLTIU32:
17363 mips32_op = OPC_SLTIU;
17364 do_slti:
17365 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17366 break;
17367 case JALX32:
17368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17369 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17370 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17371 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17372 break;
17373 case JALS32: /* BOVC, BEQC, BEQZALC */
17374 if (ctx->insn_flags & ISA_MIPS32R6) {
17375 if (rs >= rt) {
17376 /* BOVC */
17377 mips32_op = OPC_BOVC;
17378 } else if (rs < rt && rs == 0) {
17379 /* BEQZALC */
17380 mips32_op = OPC_BEQZALC;
17381 } else {
17382 /* BEQC */
17383 mips32_op = OPC_BEQC;
17385 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17386 } else {
17387 /* JALS32 */
17388 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17389 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17390 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17392 break;
17393 case BEQ32: /* BC */
17394 if (ctx->insn_flags & ISA_MIPS32R6) {
17395 /* BC */
17396 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17397 sextract32(ctx->opcode << 1, 0, 27));
17398 } else {
17399 /* BEQ32 */
17400 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17402 break;
17403 case BNE32: /* BALC */
17404 if (ctx->insn_flags & ISA_MIPS32R6) {
17405 /* BALC */
17406 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17407 sextract32(ctx->opcode << 1, 0, 27));
17408 } else {
17409 /* BNE32 */
17410 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17412 break;
17413 case J32: /* BGTZC, BLTZC, BLTC */
17414 if (ctx->insn_flags & ISA_MIPS32R6) {
17415 if (rs == 0 && rt != 0) {
17416 /* BGTZC */
17417 mips32_op = OPC_BGTZC;
17418 } else if (rs != 0 && rt != 0 && rs == rt) {
17419 /* BLTZC */
17420 mips32_op = OPC_BLTZC;
17421 } else {
17422 /* BLTC */
17423 mips32_op = OPC_BLTC;
17425 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17426 } else {
17427 /* J32 */
17428 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17429 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17431 break;
17432 case JAL32: /* BLEZC, BGEZC, BGEC */
17433 if (ctx->insn_flags & ISA_MIPS32R6) {
17434 if (rs == 0 && rt != 0) {
17435 /* BLEZC */
17436 mips32_op = OPC_BLEZC;
17437 } else if (rs != 0 && rt != 0 && rs == rt) {
17438 /* BGEZC */
17439 mips32_op = OPC_BGEZC;
17440 } else {
17441 /* BGEC */
17442 mips32_op = OPC_BGEC;
17444 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17445 } else {
17446 /* JAL32 */
17447 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17448 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17449 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17451 break;
17452 /* Floating point (COP1) */
17453 case LWC132:
17454 mips32_op = OPC_LWC1;
17455 goto do_cop1;
17456 case LDC132:
17457 mips32_op = OPC_LDC1;
17458 goto do_cop1;
17459 case SWC132:
17460 mips32_op = OPC_SWC1;
17461 goto do_cop1;
17462 case SDC132:
17463 mips32_op = OPC_SDC1;
17464 do_cop1:
17465 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17466 break;
17467 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17468 if (ctx->insn_flags & ISA_MIPS32R6) {
17469 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17470 switch ((ctx->opcode >> 16) & 0x1f) {
17471 case ADDIUPC_00:
17472 case ADDIUPC_01:
17473 case ADDIUPC_02:
17474 case ADDIUPC_03:
17475 case ADDIUPC_04:
17476 case ADDIUPC_05:
17477 case ADDIUPC_06:
17478 case ADDIUPC_07:
17479 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17480 break;
17481 case AUIPC:
17482 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17483 break;
17484 case ALUIPC:
17485 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17486 break;
17487 case LWPC_08:
17488 case LWPC_09:
17489 case LWPC_0A:
17490 case LWPC_0B:
17491 case LWPC_0C:
17492 case LWPC_0D:
17493 case LWPC_0E:
17494 case LWPC_0F:
17495 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17496 break;
17497 default:
17498 generate_exception(ctx, EXCP_RI);
17499 break;
17501 } else {
17502 /* ADDIUPC */
17503 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17504 offset = SIMM(ctx->opcode, 0, 23) << 2;
17506 gen_addiupc(ctx, reg, offset, 0, 0);
17508 break;
17509 case BNVC: /* BNEC, BNEZALC */
17510 check_insn(ctx, ISA_MIPS32R6);
17511 if (rs >= rt) {
17512 /* BNVC */
17513 mips32_op = OPC_BNVC;
17514 } else if (rs < rt && rs == 0) {
17515 /* BNEZALC */
17516 mips32_op = OPC_BNEZALC;
17517 } else {
17518 /* BNEC */
17519 mips32_op = OPC_BNEC;
17521 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17522 break;
17523 case R6_BNEZC: /* JIALC */
17524 check_insn(ctx, ISA_MIPS32R6);
17525 if (rt != 0) {
17526 /* BNEZC */
17527 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17528 sextract32(ctx->opcode << 1, 0, 22));
17529 } else {
17530 /* JIALC */
17531 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17533 break;
17534 case R6_BEQZC: /* JIC */
17535 check_insn(ctx, ISA_MIPS32R6);
17536 if (rt != 0) {
17537 /* BEQZC */
17538 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17539 sextract32(ctx->opcode << 1, 0, 22));
17540 } else {
17541 /* JIC */
17542 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17544 break;
17545 case BLEZALC: /* BGEZALC, BGEUC */
17546 check_insn(ctx, ISA_MIPS32R6);
17547 if (rs == 0 && rt != 0) {
17548 /* BLEZALC */
17549 mips32_op = OPC_BLEZALC;
17550 } else if (rs != 0 && rt != 0 && rs == rt) {
17551 /* BGEZALC */
17552 mips32_op = OPC_BGEZALC;
17553 } else {
17554 /* BGEUC */
17555 mips32_op = OPC_BGEUC;
17557 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17558 break;
17559 case BGTZALC: /* BLTZALC, BLTUC */
17560 check_insn(ctx, ISA_MIPS32R6);
17561 if (rs == 0 && rt != 0) {
17562 /* BGTZALC */
17563 mips32_op = OPC_BGTZALC;
17564 } else if (rs != 0 && rt != 0 && rs == rt) {
17565 /* BLTZALC */
17566 mips32_op = OPC_BLTZALC;
17567 } else {
17568 /* BLTUC */
17569 mips32_op = OPC_BLTUC;
17571 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17572 break;
17573 /* Loads and stores */
17574 case LB32:
17575 mips32_op = OPC_LB;
17576 goto do_ld;
17577 case LBU32:
17578 mips32_op = OPC_LBU;
17579 goto do_ld;
17580 case LH32:
17581 mips32_op = OPC_LH;
17582 goto do_ld;
17583 case LHU32:
17584 mips32_op = OPC_LHU;
17585 goto do_ld;
17586 case LW32:
17587 mips32_op = OPC_LW;
17588 goto do_ld;
17589 #ifdef TARGET_MIPS64
17590 case LD32:
17591 check_insn(ctx, ISA_MIPS3);
17592 check_mips_64(ctx);
17593 mips32_op = OPC_LD;
17594 goto do_ld;
17595 case SD32:
17596 check_insn(ctx, ISA_MIPS3);
17597 check_mips_64(ctx);
17598 mips32_op = OPC_SD;
17599 goto do_st;
17600 #endif
17601 case SB32:
17602 mips32_op = OPC_SB;
17603 goto do_st;
17604 case SH32:
17605 mips32_op = OPC_SH;
17606 goto do_st;
17607 case SW32:
17608 mips32_op = OPC_SW;
17609 goto do_st;
17610 do_ld:
17611 gen_ld(ctx, mips32_op, rt, rs, imm);
17612 break;
17613 do_st:
17614 gen_st(ctx, mips32_op, rt, rs, imm);
17615 break;
17616 default:
17617 generate_exception_end(ctx, EXCP_RI);
17618 break;
17622 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17624 uint32_t op;
17626 /* make sure instructions are on a halfword boundary */
17627 if (ctx->base.pc_next & 0x1) {
17628 env->CP0_BadVAddr = ctx->base.pc_next;
17629 generate_exception_end(ctx, EXCP_AdEL);
17630 return 2;
17633 op = (ctx->opcode >> 10) & 0x3f;
17634 /* Enforce properly-sized instructions in a delay slot */
17635 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17636 switch (op & 0x7) { /* MSB-3..MSB-5 */
17637 case 0:
17638 /* POOL32A, POOL32B, POOL32I, POOL32C */
17639 case 4:
17640 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17641 case 5:
17642 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17643 case 6:
17644 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17645 case 7:
17646 /* LB32, LH32, LWC132, LDC132, LW32 */
17647 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17648 generate_exception_end(ctx, EXCP_RI);
17649 return 2;
17651 break;
17652 case 1:
17653 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17654 case 2:
17655 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17656 case 3:
17657 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17658 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17659 generate_exception_end(ctx, EXCP_RI);
17660 return 2;
17662 break;
17666 switch (op) {
17667 case POOL16A:
17669 int rd = mmreg(uMIPS_RD(ctx->opcode));
17670 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17671 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17672 uint32_t opc = 0;
17674 switch (ctx->opcode & 0x1) {
17675 case ADDU16:
17676 opc = OPC_ADDU;
17677 break;
17678 case SUBU16:
17679 opc = OPC_SUBU;
17680 break;
17682 if (ctx->insn_flags & ISA_MIPS32R6) {
17684 * In the Release 6, the register number location in
17685 * the instruction encoding has changed.
17687 gen_arith(ctx, opc, rs1, rd, rs2);
17688 } else {
17689 gen_arith(ctx, opc, rd, rs1, rs2);
17692 break;
17693 case POOL16B:
17695 int rd = mmreg(uMIPS_RD(ctx->opcode));
17696 int rs = mmreg(uMIPS_RS(ctx->opcode));
17697 int amount = (ctx->opcode >> 1) & 0x7;
17698 uint32_t opc = 0;
17699 amount = amount == 0 ? 8 : amount;
17701 switch (ctx->opcode & 0x1) {
17702 case SLL16:
17703 opc = OPC_SLL;
17704 break;
17705 case SRL16:
17706 opc = OPC_SRL;
17707 break;
17710 gen_shift_imm(ctx, opc, rd, rs, amount);
17712 break;
17713 case POOL16C:
17714 if (ctx->insn_flags & ISA_MIPS32R6) {
17715 gen_pool16c_r6_insn(ctx);
17716 } else {
17717 gen_pool16c_insn(ctx);
17719 break;
17720 case LWGP16:
17722 int rd = mmreg(uMIPS_RD(ctx->opcode));
17723 int rb = 28; /* GP */
17724 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17726 gen_ld(ctx, OPC_LW, rd, rb, offset);
17728 break;
17729 case POOL16F:
17730 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17731 if (ctx->opcode & 1) {
17732 generate_exception_end(ctx, EXCP_RI);
17733 } else {
17734 /* MOVEP */
17735 int enc_dest = uMIPS_RD(ctx->opcode);
17736 int enc_rt = uMIPS_RS2(ctx->opcode);
17737 int enc_rs = uMIPS_RS1(ctx->opcode);
17738 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17740 break;
17741 case LBU16:
17743 int rd = mmreg(uMIPS_RD(ctx->opcode));
17744 int rb = mmreg(uMIPS_RS(ctx->opcode));
17745 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17746 offset = (offset == 0xf ? -1 : offset);
17748 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17750 break;
17751 case LHU16:
17753 int rd = mmreg(uMIPS_RD(ctx->opcode));
17754 int rb = mmreg(uMIPS_RS(ctx->opcode));
17755 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17757 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17759 break;
17760 case LWSP16:
17762 int rd = (ctx->opcode >> 5) & 0x1f;
17763 int rb = 29; /* SP */
17764 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17766 gen_ld(ctx, OPC_LW, rd, rb, offset);
17768 break;
17769 case LW16:
17771 int rd = mmreg(uMIPS_RD(ctx->opcode));
17772 int rb = mmreg(uMIPS_RS(ctx->opcode));
17773 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17775 gen_ld(ctx, OPC_LW, rd, rb, offset);
17777 break;
17778 case SB16:
17780 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17781 int rb = mmreg(uMIPS_RS(ctx->opcode));
17782 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17784 gen_st(ctx, OPC_SB, rd, rb, offset);
17786 break;
17787 case SH16:
17789 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17790 int rb = mmreg(uMIPS_RS(ctx->opcode));
17791 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17793 gen_st(ctx, OPC_SH, rd, rb, offset);
17795 break;
17796 case SWSP16:
17798 int rd = (ctx->opcode >> 5) & 0x1f;
17799 int rb = 29; /* SP */
17800 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17802 gen_st(ctx, OPC_SW, rd, rb, offset);
17804 break;
17805 case SW16:
17807 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17808 int rb = mmreg(uMIPS_RS(ctx->opcode));
17809 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17811 gen_st(ctx, OPC_SW, rd, rb, offset);
17813 break;
17814 case MOVE16:
17816 int rd = uMIPS_RD5(ctx->opcode);
17817 int rs = uMIPS_RS5(ctx->opcode);
17819 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17821 break;
17822 case ANDI16:
17823 gen_andi16(ctx);
17824 break;
17825 case POOL16D:
17826 switch (ctx->opcode & 0x1) {
17827 case ADDIUS5:
17828 gen_addius5(ctx);
17829 break;
17830 case ADDIUSP:
17831 gen_addiusp(ctx);
17832 break;
17834 break;
17835 case POOL16E:
17836 switch (ctx->opcode & 0x1) {
17837 case ADDIUR2:
17838 gen_addiur2(ctx);
17839 break;
17840 case ADDIUR1SP:
17841 gen_addiur1sp(ctx);
17842 break;
17844 break;
17845 case B16: /* BC16 */
17846 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17847 sextract32(ctx->opcode, 0, 10) << 1,
17848 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17849 break;
17850 case BNEZ16: /* BNEZC16 */
17851 case BEQZ16: /* BEQZC16 */
17852 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17853 mmreg(uMIPS_RD(ctx->opcode)),
17854 0, sextract32(ctx->opcode, 0, 7) << 1,
17855 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17857 break;
17858 case LI16:
17860 int reg = mmreg(uMIPS_RD(ctx->opcode));
17861 int imm = ZIMM(ctx->opcode, 0, 7);
17863 imm = (imm == 0x7f ? -1 : imm);
17864 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17866 break;
17867 case RES_29:
17868 case RES_31:
17869 case RES_39:
17870 generate_exception_end(ctx, EXCP_RI);
17871 break;
17872 default:
17873 decode_micromips32_opc(env, ctx);
17874 return 4;
17877 return 2;
17882 * nanoMIPS opcodes
17886 /* MAJOR, P16, and P32 pools opcodes */
17887 enum {
17888 NM_P_ADDIU = 0x00,
17889 NM_ADDIUPC = 0x01,
17890 NM_MOVE_BALC = 0x02,
17891 NM_P16_MV = 0x04,
17892 NM_LW16 = 0x05,
17893 NM_BC16 = 0x06,
17894 NM_P16_SR = 0x07,
17896 NM_POOL32A = 0x08,
17897 NM_P_BAL = 0x0a,
17898 NM_P16_SHIFT = 0x0c,
17899 NM_LWSP16 = 0x0d,
17900 NM_BALC16 = 0x0e,
17901 NM_P16_4X4 = 0x0f,
17903 NM_P_GP_W = 0x10,
17904 NM_P_GP_BH = 0x11,
17905 NM_P_J = 0x12,
17906 NM_P16C = 0x14,
17907 NM_LWGP16 = 0x15,
17908 NM_P16_LB = 0x17,
17910 NM_P48I = 0x18,
17911 NM_P16_A1 = 0x1c,
17912 NM_LW4X4 = 0x1d,
17913 NM_P16_LH = 0x1f,
17915 NM_P_U12 = 0x20,
17916 NM_P_LS_U12 = 0x21,
17917 NM_P_BR1 = 0x22,
17918 NM_P16_A2 = 0x24,
17919 NM_SW16 = 0x25,
17920 NM_BEQZC16 = 0x26,
17922 NM_POOL32F = 0x28,
17923 NM_P_LS_S9 = 0x29,
17924 NM_P_BR2 = 0x2a,
17926 NM_P16_ADDU = 0x2c,
17927 NM_SWSP16 = 0x2d,
17928 NM_BNEZC16 = 0x2e,
17929 NM_MOVEP = 0x2f,
17931 NM_POOL32S = 0x30,
17932 NM_P_BRI = 0x32,
17933 NM_LI16 = 0x34,
17934 NM_SWGP16 = 0x35,
17935 NM_P16_BR = 0x36,
17937 NM_P_LUI = 0x38,
17938 NM_ANDI16 = 0x3c,
17939 NM_SW4X4 = 0x3d,
17940 NM_MOVEPREV = 0x3f,
17943 /* POOL32A instruction pool */
17944 enum {
17945 NM_POOL32A0 = 0x00,
17946 NM_SPECIAL2 = 0x01,
17947 NM_COP2_1 = 0x02,
17948 NM_UDI = 0x03,
17949 NM_POOL32A5 = 0x05,
17950 NM_POOL32A7 = 0x07,
17953 /* P.GP.W instruction pool */
17954 enum {
17955 NM_ADDIUGP_W = 0x00,
17956 NM_LWGP = 0x02,
17957 NM_SWGP = 0x03,
17960 /* P48I instruction pool */
17961 enum {
17962 NM_LI48 = 0x00,
17963 NM_ADDIU48 = 0x01,
17964 NM_ADDIUGP48 = 0x02,
17965 NM_ADDIUPC48 = 0x03,
17966 NM_LWPC48 = 0x0b,
17967 NM_SWPC48 = 0x0f,
17970 /* P.U12 instruction pool */
17971 enum {
17972 NM_ORI = 0x00,
17973 NM_XORI = 0x01,
17974 NM_ANDI = 0x02,
17975 NM_P_SR = 0x03,
17976 NM_SLTI = 0x04,
17977 NM_SLTIU = 0x05,
17978 NM_SEQI = 0x06,
17979 NM_ADDIUNEG = 0x08,
17980 NM_P_SHIFT = 0x0c,
17981 NM_P_ROTX = 0x0d,
17982 NM_P_INS = 0x0e,
17983 NM_P_EXT = 0x0f,
17986 /* POOL32F instruction pool */
17987 enum {
17988 NM_POOL32F_0 = 0x00,
17989 NM_POOL32F_3 = 0x03,
17990 NM_POOL32F_5 = 0x05,
17993 /* POOL32S instruction pool */
17994 enum {
17995 NM_POOL32S_0 = 0x00,
17996 NM_POOL32S_4 = 0x04,
17999 /* P.LUI instruction pool */
18000 enum {
18001 NM_LUI = 0x00,
18002 NM_ALUIPC = 0x01,
18005 /* P.GP.BH instruction pool */
18006 enum {
18007 NM_LBGP = 0x00,
18008 NM_SBGP = 0x01,
18009 NM_LBUGP = 0x02,
18010 NM_ADDIUGP_B = 0x03,
18011 NM_P_GP_LH = 0x04,
18012 NM_P_GP_SH = 0x05,
18013 NM_P_GP_CP1 = 0x06,
18016 /* P.LS.U12 instruction pool */
18017 enum {
18018 NM_LB = 0x00,
18019 NM_SB = 0x01,
18020 NM_LBU = 0x02,
18021 NM_P_PREFU12 = 0x03,
18022 NM_LH = 0x04,
18023 NM_SH = 0x05,
18024 NM_LHU = 0x06,
18025 NM_LWU = 0x07,
18026 NM_LW = 0x08,
18027 NM_SW = 0x09,
18028 NM_LWC1 = 0x0a,
18029 NM_SWC1 = 0x0b,
18030 NM_LDC1 = 0x0e,
18031 NM_SDC1 = 0x0f,
18034 /* P.LS.S9 instruction pool */
18035 enum {
18036 NM_P_LS_S0 = 0x00,
18037 NM_P_LS_S1 = 0x01,
18038 NM_P_LS_E0 = 0x02,
18039 NM_P_LS_WM = 0x04,
18040 NM_P_LS_UAWM = 0x05,
18043 /* P.BAL instruction pool */
18044 enum {
18045 NM_BC = 0x00,
18046 NM_BALC = 0x01,
18049 /* P.J instruction pool */
18050 enum {
18051 NM_JALRC = 0x00,
18052 NM_JALRC_HB = 0x01,
18053 NM_P_BALRSC = 0x08,
18056 /* P.BR1 instruction pool */
18057 enum {
18058 NM_BEQC = 0x00,
18059 NM_P_BR3A = 0x01,
18060 NM_BGEC = 0x02,
18061 NM_BGEUC = 0x03,
18064 /* P.BR2 instruction pool */
18065 enum {
18066 NM_BNEC = 0x00,
18067 NM_BLTC = 0x02,
18068 NM_BLTUC = 0x03,
18071 /* P.BRI instruction pool */
18072 enum {
18073 NM_BEQIC = 0x00,
18074 NM_BBEQZC = 0x01,
18075 NM_BGEIC = 0x02,
18076 NM_BGEIUC = 0x03,
18077 NM_BNEIC = 0x04,
18078 NM_BBNEZC = 0x05,
18079 NM_BLTIC = 0x06,
18080 NM_BLTIUC = 0x07,
18083 /* P16.SHIFT instruction pool */
18084 enum {
18085 NM_SLL16 = 0x00,
18086 NM_SRL16 = 0x01,
18089 /* POOL16C instruction pool */
18090 enum {
18091 NM_POOL16C_0 = 0x00,
18092 NM_LWXS16 = 0x01,
18095 /* P16.A1 instruction pool */
18096 enum {
18097 NM_ADDIUR1SP = 0x01,
18100 /* P16.A2 instruction pool */
18101 enum {
18102 NM_ADDIUR2 = 0x00,
18103 NM_P_ADDIURS5 = 0x01,
18106 /* P16.ADDU instruction pool */
18107 enum {
18108 NM_ADDU16 = 0x00,
18109 NM_SUBU16 = 0x01,
18112 /* P16.SR instruction pool */
18113 enum {
18114 NM_SAVE16 = 0x00,
18115 NM_RESTORE_JRC16 = 0x01,
18118 /* P16.4X4 instruction pool */
18119 enum {
18120 NM_ADDU4X4 = 0x00,
18121 NM_MUL4X4 = 0x01,
18124 /* P16.LB instruction pool */
18125 enum {
18126 NM_LB16 = 0x00,
18127 NM_SB16 = 0x01,
18128 NM_LBU16 = 0x02,
18131 /* P16.LH instruction pool */
18132 enum {
18133 NM_LH16 = 0x00,
18134 NM_SH16 = 0x01,
18135 NM_LHU16 = 0x02,
18138 /* P.RI instruction pool */
18139 enum {
18140 NM_SIGRIE = 0x00,
18141 NM_P_SYSCALL = 0x01,
18142 NM_BREAK = 0x02,
18143 NM_SDBBP = 0x03,
18146 /* POOL32A0 instruction pool */
18147 enum {
18148 NM_P_TRAP = 0x00,
18149 NM_SEB = 0x01,
18150 NM_SLLV = 0x02,
18151 NM_MUL = 0x03,
18152 NM_MFC0 = 0x06,
18153 NM_MFHC0 = 0x07,
18154 NM_SEH = 0x09,
18155 NM_SRLV = 0x0a,
18156 NM_MUH = 0x0b,
18157 NM_MTC0 = 0x0e,
18158 NM_MTHC0 = 0x0f,
18159 NM_SRAV = 0x12,
18160 NM_MULU = 0x13,
18161 NM_ROTRV = 0x1a,
18162 NM_MUHU = 0x1b,
18163 NM_ADD = 0x22,
18164 NM_DIV = 0x23,
18165 NM_ADDU = 0x2a,
18166 NM_MOD = 0x2b,
18167 NM_SUB = 0x32,
18168 NM_DIVU = 0x33,
18169 NM_RDHWR = 0x38,
18170 NM_SUBU = 0x3a,
18171 NM_MODU = 0x3b,
18172 NM_P_CMOVE = 0x42,
18173 NM_FORK = 0x45,
18174 NM_MFTR = 0x46,
18175 NM_MFHTR = 0x47,
18176 NM_AND = 0x4a,
18177 NM_YIELD = 0x4d,
18178 NM_MTTR = 0x4e,
18179 NM_MTHTR = 0x4f,
18180 NM_OR = 0x52,
18181 NM_D_E_MT_VPE = 0x56,
18182 NM_NOR = 0x5a,
18183 NM_XOR = 0x62,
18184 NM_SLT = 0x6a,
18185 NM_P_SLTU = 0x72,
18186 NM_SOV = 0x7a,
18189 /* CRC32 instruction pool */
18190 enum {
18191 NM_CRC32B = 0x00,
18192 NM_CRC32H = 0x01,
18193 NM_CRC32W = 0x02,
18194 NM_CRC32CB = 0x04,
18195 NM_CRC32CH = 0x05,
18196 NM_CRC32CW = 0x06,
18199 /* POOL32A5 instruction pool */
18200 enum {
18201 NM_CMP_EQ_PH = 0x00,
18202 NM_CMP_LT_PH = 0x08,
18203 NM_CMP_LE_PH = 0x10,
18204 NM_CMPGU_EQ_QB = 0x18,
18205 NM_CMPGU_LT_QB = 0x20,
18206 NM_CMPGU_LE_QB = 0x28,
18207 NM_CMPGDU_EQ_QB = 0x30,
18208 NM_CMPGDU_LT_QB = 0x38,
18209 NM_CMPGDU_LE_QB = 0x40,
18210 NM_CMPU_EQ_QB = 0x48,
18211 NM_CMPU_LT_QB = 0x50,
18212 NM_CMPU_LE_QB = 0x58,
18213 NM_ADDQ_S_W = 0x60,
18214 NM_SUBQ_S_W = 0x68,
18215 NM_ADDSC = 0x70,
18216 NM_ADDWC = 0x78,
18218 NM_ADDQ_S_PH = 0x01,
18219 NM_ADDQH_R_PH = 0x09,
18220 NM_ADDQH_R_W = 0x11,
18221 NM_ADDU_S_QB = 0x19,
18222 NM_ADDU_S_PH = 0x21,
18223 NM_ADDUH_R_QB = 0x29,
18224 NM_SHRAV_R_PH = 0x31,
18225 NM_SHRAV_R_QB = 0x39,
18226 NM_SUBQ_S_PH = 0x41,
18227 NM_SUBQH_R_PH = 0x49,
18228 NM_SUBQH_R_W = 0x51,
18229 NM_SUBU_S_QB = 0x59,
18230 NM_SUBU_S_PH = 0x61,
18231 NM_SUBUH_R_QB = 0x69,
18232 NM_SHLLV_S_PH = 0x71,
18233 NM_PRECR_SRA_R_PH_W = 0x79,
18235 NM_MULEU_S_PH_QBL = 0x12,
18236 NM_MULEU_S_PH_QBR = 0x1a,
18237 NM_MULQ_RS_PH = 0x22,
18238 NM_MULQ_S_PH = 0x2a,
18239 NM_MULQ_RS_W = 0x32,
18240 NM_MULQ_S_W = 0x3a,
18241 NM_APPEND = 0x42,
18242 NM_MODSUB = 0x52,
18243 NM_SHRAV_R_W = 0x5a,
18244 NM_SHRLV_PH = 0x62,
18245 NM_SHRLV_QB = 0x6a,
18246 NM_SHLLV_QB = 0x72,
18247 NM_SHLLV_S_W = 0x7a,
18249 NM_SHILO = 0x03,
18251 NM_MULEQ_S_W_PHL = 0x04,
18252 NM_MULEQ_S_W_PHR = 0x0c,
18254 NM_MUL_S_PH = 0x05,
18255 NM_PRECR_QB_PH = 0x0d,
18256 NM_PRECRQ_QB_PH = 0x15,
18257 NM_PRECRQ_PH_W = 0x1d,
18258 NM_PRECRQ_RS_PH_W = 0x25,
18259 NM_PRECRQU_S_QB_PH = 0x2d,
18260 NM_PACKRL_PH = 0x35,
18261 NM_PICK_QB = 0x3d,
18262 NM_PICK_PH = 0x45,
18264 NM_SHRA_R_W = 0x5e,
18265 NM_SHRA_R_PH = 0x66,
18266 NM_SHLL_S_PH = 0x76,
18267 NM_SHLL_S_W = 0x7e,
18269 NM_REPL_PH = 0x07
18272 /* POOL32A7 instruction pool */
18273 enum {
18274 NM_P_LSX = 0x00,
18275 NM_LSA = 0x01,
18276 NM_EXTW = 0x03,
18277 NM_POOL32AXF = 0x07,
18280 /* P.SR instruction pool */
18281 enum {
18282 NM_PP_SR = 0x00,
18283 NM_P_SR_F = 0x01,
18286 /* P.SHIFT instruction pool */
18287 enum {
18288 NM_P_SLL = 0x00,
18289 NM_SRL = 0x02,
18290 NM_SRA = 0x04,
18291 NM_ROTR = 0x06,
18294 /* P.ROTX instruction pool */
18295 enum {
18296 NM_ROTX = 0x00,
18299 /* P.INS instruction pool */
18300 enum {
18301 NM_INS = 0x00,
18304 /* P.EXT instruction pool */
18305 enum {
18306 NM_EXT = 0x00,
18309 /* POOL32F_0 (fmt) instruction pool */
18310 enum {
18311 NM_RINT_S = 0x04,
18312 NM_RINT_D = 0x44,
18313 NM_ADD_S = 0x06,
18314 NM_SELEQZ_S = 0x07,
18315 NM_SELEQZ_D = 0x47,
18316 NM_CLASS_S = 0x0c,
18317 NM_CLASS_D = 0x4c,
18318 NM_SUB_S = 0x0e,
18319 NM_SELNEZ_S = 0x0f,
18320 NM_SELNEZ_D = 0x4f,
18321 NM_MUL_S = 0x16,
18322 NM_SEL_S = 0x17,
18323 NM_SEL_D = 0x57,
18324 NM_DIV_S = 0x1e,
18325 NM_ADD_D = 0x26,
18326 NM_SUB_D = 0x2e,
18327 NM_MUL_D = 0x36,
18328 NM_MADDF_S = 0x37,
18329 NM_MADDF_D = 0x77,
18330 NM_DIV_D = 0x3e,
18331 NM_MSUBF_S = 0x3f,
18332 NM_MSUBF_D = 0x7f,
18335 /* POOL32F_3 instruction pool */
18336 enum {
18337 NM_MIN_FMT = 0x00,
18338 NM_MAX_FMT = 0x01,
18339 NM_MINA_FMT = 0x04,
18340 NM_MAXA_FMT = 0x05,
18341 NM_POOL32FXF = 0x07,
18344 /* POOL32F_5 instruction pool */
18345 enum {
18346 NM_CMP_CONDN_S = 0x00,
18347 NM_CMP_CONDN_D = 0x02,
18350 /* P.GP.LH instruction pool */
18351 enum {
18352 NM_LHGP = 0x00,
18353 NM_LHUGP = 0x01,
18356 /* P.GP.SH instruction pool */
18357 enum {
18358 NM_SHGP = 0x00,
18361 /* P.GP.CP1 instruction pool */
18362 enum {
18363 NM_LWC1GP = 0x00,
18364 NM_SWC1GP = 0x01,
18365 NM_LDC1GP = 0x02,
18366 NM_SDC1GP = 0x03,
18369 /* P.LS.S0 instruction pool */
18370 enum {
18371 NM_LBS9 = 0x00,
18372 NM_LHS9 = 0x04,
18373 NM_LWS9 = 0x08,
18374 NM_LDS9 = 0x0c,
18376 NM_SBS9 = 0x01,
18377 NM_SHS9 = 0x05,
18378 NM_SWS9 = 0x09,
18379 NM_SDS9 = 0x0d,
18381 NM_LBUS9 = 0x02,
18382 NM_LHUS9 = 0x06,
18383 NM_LWC1S9 = 0x0a,
18384 NM_LDC1S9 = 0x0e,
18386 NM_P_PREFS9 = 0x03,
18387 NM_LWUS9 = 0x07,
18388 NM_SWC1S9 = 0x0b,
18389 NM_SDC1S9 = 0x0f,
18392 /* P.LS.S1 instruction pool */
18393 enum {
18394 NM_ASET_ACLR = 0x02,
18395 NM_UALH = 0x04,
18396 NM_UASH = 0x05,
18397 NM_CACHE = 0x07,
18398 NM_P_LL = 0x0a,
18399 NM_P_SC = 0x0b,
18402 /* P.LS.E0 instruction pool */
18403 enum {
18404 NM_LBE = 0x00,
18405 NM_SBE = 0x01,
18406 NM_LBUE = 0x02,
18407 NM_P_PREFE = 0x03,
18408 NM_LHE = 0x04,
18409 NM_SHE = 0x05,
18410 NM_LHUE = 0x06,
18411 NM_CACHEE = 0x07,
18412 NM_LWE = 0x08,
18413 NM_SWE = 0x09,
18414 NM_P_LLE = 0x0a,
18415 NM_P_SCE = 0x0b,
18418 /* P.PREFE instruction pool */
18419 enum {
18420 NM_SYNCIE = 0x00,
18421 NM_PREFE = 0x01,
18424 /* P.LLE instruction pool */
18425 enum {
18426 NM_LLE = 0x00,
18427 NM_LLWPE = 0x01,
18430 /* P.SCE instruction pool */
18431 enum {
18432 NM_SCE = 0x00,
18433 NM_SCWPE = 0x01,
18436 /* P.LS.WM instruction pool */
18437 enum {
18438 NM_LWM = 0x00,
18439 NM_SWM = 0x01,
18442 /* P.LS.UAWM instruction pool */
18443 enum {
18444 NM_UALWM = 0x00,
18445 NM_UASWM = 0x01,
18448 /* P.BR3A instruction pool */
18449 enum {
18450 NM_BC1EQZC = 0x00,
18451 NM_BC1NEZC = 0x01,
18452 NM_BC2EQZC = 0x02,
18453 NM_BC2NEZC = 0x03,
18454 NM_BPOSGE32C = 0x04,
18457 /* P16.RI instruction pool */
18458 enum {
18459 NM_P16_SYSCALL = 0x01,
18460 NM_BREAK16 = 0x02,
18461 NM_SDBBP16 = 0x03,
18464 /* POOL16C_0 instruction pool */
18465 enum {
18466 NM_POOL16C_00 = 0x00,
18469 /* P16.JRC instruction pool */
18470 enum {
18471 NM_JRC = 0x00,
18472 NM_JALRC16 = 0x01,
18475 /* P.SYSCALL instruction pool */
18476 enum {
18477 NM_SYSCALL = 0x00,
18478 NM_HYPCALL = 0x01,
18481 /* P.TRAP instruction pool */
18482 enum {
18483 NM_TEQ = 0x00,
18484 NM_TNE = 0x01,
18487 /* P.CMOVE instruction pool */
18488 enum {
18489 NM_MOVZ = 0x00,
18490 NM_MOVN = 0x01,
18493 /* POOL32Axf instruction pool */
18494 enum {
18495 NM_POOL32AXF_1 = 0x01,
18496 NM_POOL32AXF_2 = 0x02,
18497 NM_POOL32AXF_4 = 0x04,
18498 NM_POOL32AXF_5 = 0x05,
18499 NM_POOL32AXF_7 = 0x07,
18502 /* POOL32Axf_1 instruction pool */
18503 enum {
18504 NM_POOL32AXF_1_0 = 0x00,
18505 NM_POOL32AXF_1_1 = 0x01,
18506 NM_POOL32AXF_1_3 = 0x03,
18507 NM_POOL32AXF_1_4 = 0x04,
18508 NM_POOL32AXF_1_5 = 0x05,
18509 NM_POOL32AXF_1_7 = 0x07,
18512 /* POOL32Axf_2 instruction pool */
18513 enum {
18514 NM_POOL32AXF_2_0_7 = 0x00,
18515 NM_POOL32AXF_2_8_15 = 0x01,
18516 NM_POOL32AXF_2_16_23 = 0x02,
18517 NM_POOL32AXF_2_24_31 = 0x03,
18520 /* POOL32Axf_7 instruction pool */
18521 enum {
18522 NM_SHRA_R_QB = 0x0,
18523 NM_SHRL_PH = 0x1,
18524 NM_REPL_QB = 0x2,
18527 /* POOL32Axf_1_0 instruction pool */
18528 enum {
18529 NM_MFHI = 0x0,
18530 NM_MFLO = 0x1,
18531 NM_MTHI = 0x2,
18532 NM_MTLO = 0x3,
18535 /* POOL32Axf_1_1 instruction pool */
18536 enum {
18537 NM_MTHLIP = 0x0,
18538 NM_SHILOV = 0x1,
18541 /* POOL32Axf_1_3 instruction pool */
18542 enum {
18543 NM_RDDSP = 0x0,
18544 NM_WRDSP = 0x1,
18545 NM_EXTP = 0x2,
18546 NM_EXTPDP = 0x3,
18549 /* POOL32Axf_1_4 instruction pool */
18550 enum {
18551 NM_SHLL_QB = 0x0,
18552 NM_SHRL_QB = 0x1,
18555 /* POOL32Axf_1_5 instruction pool */
18556 enum {
18557 NM_MAQ_S_W_PHR = 0x0,
18558 NM_MAQ_S_W_PHL = 0x1,
18559 NM_MAQ_SA_W_PHR = 0x2,
18560 NM_MAQ_SA_W_PHL = 0x3,
18563 /* POOL32Axf_1_7 instruction pool */
18564 enum {
18565 NM_EXTR_W = 0x0,
18566 NM_EXTR_R_W = 0x1,
18567 NM_EXTR_RS_W = 0x2,
18568 NM_EXTR_S_H = 0x3,
18571 /* POOL32Axf_2_0_7 instruction pool */
18572 enum {
18573 NM_DPA_W_PH = 0x0,
18574 NM_DPAQ_S_W_PH = 0x1,
18575 NM_DPS_W_PH = 0x2,
18576 NM_DPSQ_S_W_PH = 0x3,
18577 NM_BALIGN = 0x4,
18578 NM_MADD = 0x5,
18579 NM_MULT = 0x6,
18580 NM_EXTRV_W = 0x7,
18583 /* POOL32Axf_2_8_15 instruction pool */
18584 enum {
18585 NM_DPAX_W_PH = 0x0,
18586 NM_DPAQ_SA_L_W = 0x1,
18587 NM_DPSX_W_PH = 0x2,
18588 NM_DPSQ_SA_L_W = 0x3,
18589 NM_MADDU = 0x5,
18590 NM_MULTU = 0x6,
18591 NM_EXTRV_R_W = 0x7,
18594 /* POOL32Axf_2_16_23 instruction pool */
18595 enum {
18596 NM_DPAU_H_QBL = 0x0,
18597 NM_DPAQX_S_W_PH = 0x1,
18598 NM_DPSU_H_QBL = 0x2,
18599 NM_DPSQX_S_W_PH = 0x3,
18600 NM_EXTPV = 0x4,
18601 NM_MSUB = 0x5,
18602 NM_MULSA_W_PH = 0x6,
18603 NM_EXTRV_RS_W = 0x7,
18606 /* POOL32Axf_2_24_31 instruction pool */
18607 enum {
18608 NM_DPAU_H_QBR = 0x0,
18609 NM_DPAQX_SA_W_PH = 0x1,
18610 NM_DPSU_H_QBR = 0x2,
18611 NM_DPSQX_SA_W_PH = 0x3,
18612 NM_EXTPDPV = 0x4,
18613 NM_MSUBU = 0x5,
18614 NM_MULSAQ_S_W_PH = 0x6,
18615 NM_EXTRV_S_H = 0x7,
18618 /* POOL32Axf_{4, 5} instruction pool */
18619 enum {
18620 NM_CLO = 0x25,
18621 NM_CLZ = 0x2d,
18623 NM_TLBP = 0x01,
18624 NM_TLBR = 0x09,
18625 NM_TLBWI = 0x11,
18626 NM_TLBWR = 0x19,
18627 NM_TLBINV = 0x03,
18628 NM_TLBINVF = 0x0b,
18629 NM_DI = 0x23,
18630 NM_EI = 0x2b,
18631 NM_RDPGPR = 0x70,
18632 NM_WRPGPR = 0x78,
18633 NM_WAIT = 0x61,
18634 NM_DERET = 0x71,
18635 NM_ERETX = 0x79,
18637 /* nanoMIPS DSP instructions */
18638 NM_ABSQ_S_QB = 0x00,
18639 NM_ABSQ_S_PH = 0x08,
18640 NM_ABSQ_S_W = 0x10,
18641 NM_PRECEQ_W_PHL = 0x28,
18642 NM_PRECEQ_W_PHR = 0x30,
18643 NM_PRECEQU_PH_QBL = 0x38,
18644 NM_PRECEQU_PH_QBR = 0x48,
18645 NM_PRECEU_PH_QBL = 0x58,
18646 NM_PRECEU_PH_QBR = 0x68,
18647 NM_PRECEQU_PH_QBLA = 0x39,
18648 NM_PRECEQU_PH_QBRA = 0x49,
18649 NM_PRECEU_PH_QBLA = 0x59,
18650 NM_PRECEU_PH_QBRA = 0x69,
18651 NM_REPLV_PH = 0x01,
18652 NM_REPLV_QB = 0x09,
18653 NM_BITREV = 0x18,
18654 NM_INSV = 0x20,
18655 NM_RADDU_W_QB = 0x78,
18657 NM_BITSWAP = 0x05,
18658 NM_WSBH = 0x3d,
18661 /* PP.SR instruction pool */
18662 enum {
18663 NM_SAVE = 0x00,
18664 NM_RESTORE = 0x02,
18665 NM_RESTORE_JRC = 0x03,
18668 /* P.SR.F instruction pool */
18669 enum {
18670 NM_SAVEF = 0x00,
18671 NM_RESTOREF = 0x01,
18674 /* P16.SYSCALL instruction pool */
18675 enum {
18676 NM_SYSCALL16 = 0x00,
18677 NM_HYPCALL16 = 0x01,
18680 /* POOL16C_00 instruction pool */
18681 enum {
18682 NM_NOT16 = 0x00,
18683 NM_XOR16 = 0x01,
18684 NM_AND16 = 0x02,
18685 NM_OR16 = 0x03,
18688 /* PP.LSX and PP.LSXS instruction pool */
18689 enum {
18690 NM_LBX = 0x00,
18691 NM_LHX = 0x04,
18692 NM_LWX = 0x08,
18693 NM_LDX = 0x0c,
18695 NM_SBX = 0x01,
18696 NM_SHX = 0x05,
18697 NM_SWX = 0x09,
18698 NM_SDX = 0x0d,
18700 NM_LBUX = 0x02,
18701 NM_LHUX = 0x06,
18702 NM_LWC1X = 0x0a,
18703 NM_LDC1X = 0x0e,
18705 NM_LWUX = 0x07,
18706 NM_SWC1X = 0x0b,
18707 NM_SDC1X = 0x0f,
18709 NM_LHXS = 0x04,
18710 NM_LWXS = 0x08,
18711 NM_LDXS = 0x0c,
18713 NM_SHXS = 0x05,
18714 NM_SWXS = 0x09,
18715 NM_SDXS = 0x0d,
18717 NM_LHUXS = 0x06,
18718 NM_LWC1XS = 0x0a,
18719 NM_LDC1XS = 0x0e,
18721 NM_LWUXS = 0x07,
18722 NM_SWC1XS = 0x0b,
18723 NM_SDC1XS = 0x0f,
18726 /* ERETx instruction pool */
18727 enum {
18728 NM_ERET = 0x00,
18729 NM_ERETNC = 0x01,
18732 /* POOL32FxF_{0, 1} insturction pool */
18733 enum {
18734 NM_CFC1 = 0x40,
18735 NM_CTC1 = 0x60,
18736 NM_MFC1 = 0x80,
18737 NM_MTC1 = 0xa0,
18738 NM_MFHC1 = 0xc0,
18739 NM_MTHC1 = 0xe0,
18741 NM_CVT_S_PL = 0x84,
18742 NM_CVT_S_PU = 0xa4,
18744 NM_CVT_L_S = 0x004,
18745 NM_CVT_L_D = 0x104,
18746 NM_CVT_W_S = 0x024,
18747 NM_CVT_W_D = 0x124,
18749 NM_RSQRT_S = 0x008,
18750 NM_RSQRT_D = 0x108,
18752 NM_SQRT_S = 0x028,
18753 NM_SQRT_D = 0x128,
18755 NM_RECIP_S = 0x048,
18756 NM_RECIP_D = 0x148,
18758 NM_FLOOR_L_S = 0x00c,
18759 NM_FLOOR_L_D = 0x10c,
18761 NM_FLOOR_W_S = 0x02c,
18762 NM_FLOOR_W_D = 0x12c,
18764 NM_CEIL_L_S = 0x04c,
18765 NM_CEIL_L_D = 0x14c,
18766 NM_CEIL_W_S = 0x06c,
18767 NM_CEIL_W_D = 0x16c,
18768 NM_TRUNC_L_S = 0x08c,
18769 NM_TRUNC_L_D = 0x18c,
18770 NM_TRUNC_W_S = 0x0ac,
18771 NM_TRUNC_W_D = 0x1ac,
18772 NM_ROUND_L_S = 0x0cc,
18773 NM_ROUND_L_D = 0x1cc,
18774 NM_ROUND_W_S = 0x0ec,
18775 NM_ROUND_W_D = 0x1ec,
18777 NM_MOV_S = 0x01,
18778 NM_MOV_D = 0x81,
18779 NM_ABS_S = 0x0d,
18780 NM_ABS_D = 0x8d,
18781 NM_NEG_S = 0x2d,
18782 NM_NEG_D = 0xad,
18783 NM_CVT_D_S = 0x04d,
18784 NM_CVT_D_W = 0x0cd,
18785 NM_CVT_D_L = 0x14d,
18786 NM_CVT_S_D = 0x06d,
18787 NM_CVT_S_W = 0x0ed,
18788 NM_CVT_S_L = 0x16d,
18791 /* P.LL instruction pool */
18792 enum {
18793 NM_LL = 0x00,
18794 NM_LLWP = 0x01,
18797 /* P.SC instruction pool */
18798 enum {
18799 NM_SC = 0x00,
18800 NM_SCWP = 0x01,
18803 /* P.DVP instruction pool */
18804 enum {
18805 NM_DVP = 0x00,
18806 NM_EVP = 0x01,
18812 * nanoMIPS decoding engine
18817 /* extraction utilities */
18819 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18820 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18821 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18822 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18823 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18825 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18826 static inline int decode_gpr_gpr3(int r)
18828 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18830 return map[r & 0x7];
18833 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18834 static inline int decode_gpr_gpr3_src_store(int r)
18836 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18838 return map[r & 0x7];
18841 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18842 static inline int decode_gpr_gpr4(int r)
18844 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18845 16, 17, 18, 19, 20, 21, 22, 23 };
18847 return map[r & 0xf];
18850 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18851 static inline int decode_gpr_gpr4_zero(int r)
18853 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18854 16, 17, 18, 19, 20, 21, 22, 23 };
18856 return map[r & 0xf];
18860 static void gen_adjust_sp(DisasContext *ctx, int u)
18862 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18865 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18866 uint8_t gp, uint16_t u)
18868 int counter = 0;
18869 TCGv va = tcg_temp_new();
18870 TCGv t0 = tcg_temp_new();
18872 while (counter != count) {
18873 bool use_gp = gp && (counter == count - 1);
18874 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18875 int this_offset = -((counter + 1) << 2);
18876 gen_base_offset_addr(ctx, va, 29, this_offset);
18877 gen_load_gpr(t0, this_rt);
18878 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18879 (MO_TEUL | ctx->default_tcg_memop_mask));
18880 counter++;
18883 /* adjust stack pointer */
18884 gen_adjust_sp(ctx, -u);
18886 tcg_temp_free(t0);
18887 tcg_temp_free(va);
18890 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18891 uint8_t gp, uint16_t u)
18893 int counter = 0;
18894 TCGv va = tcg_temp_new();
18895 TCGv t0 = tcg_temp_new();
18897 while (counter != count) {
18898 bool use_gp = gp && (counter == count - 1);
18899 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18900 int this_offset = u - ((counter + 1) << 2);
18901 gen_base_offset_addr(ctx, va, 29, this_offset);
18902 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18903 ctx->default_tcg_memop_mask);
18904 tcg_gen_ext32s_tl(t0, t0);
18905 gen_store_gpr(t0, this_rt);
18906 counter++;
18909 /* adjust stack pointer */
18910 gen_adjust_sp(ctx, u);
18912 tcg_temp_free(t0);
18913 tcg_temp_free(va);
18916 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18918 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18919 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18921 switch (extract32(ctx->opcode, 2, 2)) {
18922 case NM_NOT16:
18923 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18924 break;
18925 case NM_AND16:
18926 gen_logic(ctx, OPC_AND, rt, rt, rs);
18927 break;
18928 case NM_XOR16:
18929 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18930 break;
18931 case NM_OR16:
18932 gen_logic(ctx, OPC_OR, rt, rt, rs);
18933 break;
18937 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18939 int rt = extract32(ctx->opcode, 21, 5);
18940 int rs = extract32(ctx->opcode, 16, 5);
18941 int rd = extract32(ctx->opcode, 11, 5);
18943 switch (extract32(ctx->opcode, 3, 7)) {
18944 case NM_P_TRAP:
18945 switch (extract32(ctx->opcode, 10, 1)) {
18946 case NM_TEQ:
18947 check_nms(ctx);
18948 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18949 break;
18950 case NM_TNE:
18951 check_nms(ctx);
18952 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18953 break;
18955 break;
18956 case NM_RDHWR:
18957 check_nms(ctx);
18958 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18959 break;
18960 case NM_SEB:
18961 check_nms(ctx);
18962 gen_bshfl(ctx, OPC_SEB, rs, rt);
18963 break;
18964 case NM_SEH:
18965 gen_bshfl(ctx, OPC_SEH, rs, rt);
18966 break;
18967 case NM_SLLV:
18968 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18969 break;
18970 case NM_SRLV:
18971 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18972 break;
18973 case NM_SRAV:
18974 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18975 break;
18976 case NM_ROTRV:
18977 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18978 break;
18979 case NM_ADD:
18980 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18981 break;
18982 case NM_ADDU:
18983 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18984 break;
18985 case NM_SUB:
18986 check_nms(ctx);
18987 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18988 break;
18989 case NM_SUBU:
18990 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18991 break;
18992 case NM_P_CMOVE:
18993 switch (extract32(ctx->opcode, 10, 1)) {
18994 case NM_MOVZ:
18995 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18996 break;
18997 case NM_MOVN:
18998 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18999 break;
19001 break;
19002 case NM_AND:
19003 gen_logic(ctx, OPC_AND, rd, rs, rt);
19004 break;
19005 case NM_OR:
19006 gen_logic(ctx, OPC_OR, rd, rs, rt);
19007 break;
19008 case NM_NOR:
19009 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19010 break;
19011 case NM_XOR:
19012 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19013 break;
19014 case NM_SLT:
19015 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19016 break;
19017 case NM_P_SLTU:
19018 if (rd == 0) {
19019 /* P_DVP */
19020 #ifndef CONFIG_USER_ONLY
19021 TCGv t0 = tcg_temp_new();
19022 switch (extract32(ctx->opcode, 10, 1)) {
19023 case NM_DVP:
19024 if (ctx->vp) {
19025 check_cp0_enabled(ctx);
19026 gen_helper_dvp(t0, cpu_env);
19027 gen_store_gpr(t0, rt);
19029 break;
19030 case NM_EVP:
19031 if (ctx->vp) {
19032 check_cp0_enabled(ctx);
19033 gen_helper_evp(t0, cpu_env);
19034 gen_store_gpr(t0, rt);
19036 break;
19038 tcg_temp_free(t0);
19039 #endif
19040 } else {
19041 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19043 break;
19044 case NM_SOV:
19046 TCGv t0 = tcg_temp_new();
19047 TCGv t1 = tcg_temp_new();
19048 TCGv t2 = tcg_temp_new();
19050 gen_load_gpr(t1, rs);
19051 gen_load_gpr(t2, rt);
19052 tcg_gen_add_tl(t0, t1, t2);
19053 tcg_gen_ext32s_tl(t0, t0);
19054 tcg_gen_xor_tl(t1, t1, t2);
19055 tcg_gen_xor_tl(t2, t0, t2);
19056 tcg_gen_andc_tl(t1, t2, t1);
19058 /* operands of same sign, result different sign */
19059 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19060 gen_store_gpr(t0, rd);
19062 tcg_temp_free(t0);
19063 tcg_temp_free(t1);
19064 tcg_temp_free(t2);
19066 break;
19067 case NM_MUL:
19068 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19069 break;
19070 case NM_MUH:
19071 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19072 break;
19073 case NM_MULU:
19074 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19075 break;
19076 case NM_MUHU:
19077 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19078 break;
19079 case NM_DIV:
19080 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19081 break;
19082 case NM_MOD:
19083 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19084 break;
19085 case NM_DIVU:
19086 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19087 break;
19088 case NM_MODU:
19089 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19090 break;
19091 #ifndef CONFIG_USER_ONLY
19092 case NM_MFC0:
19093 check_cp0_enabled(ctx);
19094 if (rt == 0) {
19095 /* Treat as NOP. */
19096 break;
19098 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19099 break;
19100 case NM_MTC0:
19101 check_cp0_enabled(ctx);
19103 TCGv t0 = tcg_temp_new();
19105 gen_load_gpr(t0, rt);
19106 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19107 tcg_temp_free(t0);
19109 break;
19110 case NM_D_E_MT_VPE:
19112 uint8_t sc = extract32(ctx->opcode, 10, 1);
19113 TCGv t0 = tcg_temp_new();
19115 switch (sc) {
19116 case 0:
19117 if (rs == 1) {
19118 /* DMT */
19119 check_cp0_mt(ctx);
19120 gen_helper_dmt(t0);
19121 gen_store_gpr(t0, rt);
19122 } else if (rs == 0) {
19123 /* DVPE */
19124 check_cp0_mt(ctx);
19125 gen_helper_dvpe(t0, cpu_env);
19126 gen_store_gpr(t0, rt);
19127 } else {
19128 generate_exception_end(ctx, EXCP_RI);
19130 break;
19131 case 1:
19132 if (rs == 1) {
19133 /* EMT */
19134 check_cp0_mt(ctx);
19135 gen_helper_emt(t0);
19136 gen_store_gpr(t0, rt);
19137 } else if (rs == 0) {
19138 /* EVPE */
19139 check_cp0_mt(ctx);
19140 gen_helper_evpe(t0, cpu_env);
19141 gen_store_gpr(t0, rt);
19142 } else {
19143 generate_exception_end(ctx, EXCP_RI);
19145 break;
19148 tcg_temp_free(t0);
19150 break;
19151 case NM_FORK:
19152 check_mt(ctx);
19154 TCGv t0 = tcg_temp_new();
19155 TCGv t1 = tcg_temp_new();
19157 gen_load_gpr(t0, rt);
19158 gen_load_gpr(t1, rs);
19159 gen_helper_fork(t0, t1);
19160 tcg_temp_free(t0);
19161 tcg_temp_free(t1);
19163 break;
19164 case NM_MFTR:
19165 case NM_MFHTR:
19166 check_cp0_enabled(ctx);
19167 if (rd == 0) {
19168 /* Treat as NOP. */
19169 return;
19171 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19172 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19173 break;
19174 case NM_MTTR:
19175 case NM_MTHTR:
19176 check_cp0_enabled(ctx);
19177 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19178 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19179 break;
19180 case NM_YIELD:
19181 check_mt(ctx);
19183 TCGv t0 = tcg_temp_new();
19185 gen_load_gpr(t0, rs);
19186 gen_helper_yield(t0, cpu_env, t0);
19187 gen_store_gpr(t0, rt);
19188 tcg_temp_free(t0);
19190 break;
19191 #endif
19192 default:
19193 generate_exception_end(ctx, EXCP_RI);
19194 break;
19198 /* dsp */
19199 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19200 int ret, int v1, int v2)
19202 TCGv_i32 t0;
19203 TCGv v0_t;
19204 TCGv v1_t;
19206 t0 = tcg_temp_new_i32();
19208 v0_t = tcg_temp_new();
19209 v1_t = tcg_temp_new();
19211 tcg_gen_movi_i32(t0, v2 >> 3);
19213 gen_load_gpr(v0_t, ret);
19214 gen_load_gpr(v1_t, v1);
19216 switch (opc) {
19217 case NM_MAQ_S_W_PHR:
19218 check_dsp(ctx);
19219 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19220 break;
19221 case NM_MAQ_S_W_PHL:
19222 check_dsp(ctx);
19223 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19224 break;
19225 case NM_MAQ_SA_W_PHR:
19226 check_dsp(ctx);
19227 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19228 break;
19229 case NM_MAQ_SA_W_PHL:
19230 check_dsp(ctx);
19231 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19232 break;
19233 default:
19234 generate_exception_end(ctx, EXCP_RI);
19235 break;
19238 tcg_temp_free_i32(t0);
19240 tcg_temp_free(v0_t);
19241 tcg_temp_free(v1_t);
19245 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19246 int ret, int v1, int v2)
19248 int16_t imm;
19249 TCGv t0 = tcg_temp_new();
19250 TCGv t1 = tcg_temp_new();
19251 TCGv v0_t = tcg_temp_new();
19253 gen_load_gpr(v0_t, v1);
19255 switch (opc) {
19256 case NM_POOL32AXF_1_0:
19257 check_dsp(ctx);
19258 switch (extract32(ctx->opcode, 12, 2)) {
19259 case NM_MFHI:
19260 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19261 break;
19262 case NM_MFLO:
19263 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19264 break;
19265 case NM_MTHI:
19266 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19267 break;
19268 case NM_MTLO:
19269 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19270 break;
19272 break;
19273 case NM_POOL32AXF_1_1:
19274 check_dsp(ctx);
19275 switch (extract32(ctx->opcode, 12, 2)) {
19276 case NM_MTHLIP:
19277 tcg_gen_movi_tl(t0, v2);
19278 gen_helper_mthlip(t0, v0_t, cpu_env);
19279 break;
19280 case NM_SHILOV:
19281 tcg_gen_movi_tl(t0, v2 >> 3);
19282 gen_helper_shilo(t0, v0_t, cpu_env);
19283 break;
19284 default:
19285 generate_exception_end(ctx, EXCP_RI);
19286 break;
19288 break;
19289 case NM_POOL32AXF_1_3:
19290 check_dsp(ctx);
19291 imm = extract32(ctx->opcode, 14, 7);
19292 switch (extract32(ctx->opcode, 12, 2)) {
19293 case NM_RDDSP:
19294 tcg_gen_movi_tl(t0, imm);
19295 gen_helper_rddsp(t0, t0, cpu_env);
19296 gen_store_gpr(t0, ret);
19297 break;
19298 case NM_WRDSP:
19299 gen_load_gpr(t0, ret);
19300 tcg_gen_movi_tl(t1, imm);
19301 gen_helper_wrdsp(t0, t1, cpu_env);
19302 break;
19303 case NM_EXTP:
19304 tcg_gen_movi_tl(t0, v2 >> 3);
19305 tcg_gen_movi_tl(t1, v1);
19306 gen_helper_extp(t0, t0, t1, cpu_env);
19307 gen_store_gpr(t0, ret);
19308 break;
19309 case NM_EXTPDP:
19310 tcg_gen_movi_tl(t0, v2 >> 3);
19311 tcg_gen_movi_tl(t1, v1);
19312 gen_helper_extpdp(t0, t0, t1, cpu_env);
19313 gen_store_gpr(t0, ret);
19314 break;
19316 break;
19317 case NM_POOL32AXF_1_4:
19318 check_dsp(ctx);
19319 tcg_gen_movi_tl(t0, v2 >> 2);
19320 switch (extract32(ctx->opcode, 12, 1)) {
19321 case NM_SHLL_QB:
19322 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19323 gen_store_gpr(t0, ret);
19324 break;
19325 case NM_SHRL_QB:
19326 gen_helper_shrl_qb(t0, t0, v0_t);
19327 gen_store_gpr(t0, ret);
19328 break;
19330 break;
19331 case NM_POOL32AXF_1_5:
19332 opc = extract32(ctx->opcode, 12, 2);
19333 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19334 break;
19335 case NM_POOL32AXF_1_7:
19336 check_dsp(ctx);
19337 tcg_gen_movi_tl(t0, v2 >> 3);
19338 tcg_gen_movi_tl(t1, v1);
19339 switch (extract32(ctx->opcode, 12, 2)) {
19340 case NM_EXTR_W:
19341 gen_helper_extr_w(t0, t0, t1, cpu_env);
19342 gen_store_gpr(t0, ret);
19343 break;
19344 case NM_EXTR_R_W:
19345 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19346 gen_store_gpr(t0, ret);
19347 break;
19348 case NM_EXTR_RS_W:
19349 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19350 gen_store_gpr(t0, ret);
19351 break;
19352 case NM_EXTR_S_H:
19353 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19354 gen_store_gpr(t0, ret);
19355 break;
19357 break;
19358 default:
19359 generate_exception_end(ctx, EXCP_RI);
19360 break;
19363 tcg_temp_free(t0);
19364 tcg_temp_free(t1);
19365 tcg_temp_free(v0_t);
19368 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19369 TCGv v0, TCGv v1, int rd)
19371 TCGv_i32 t0;
19373 t0 = tcg_temp_new_i32();
19375 tcg_gen_movi_i32(t0, rd >> 3);
19377 switch (opc) {
19378 case NM_POOL32AXF_2_0_7:
19379 switch (extract32(ctx->opcode, 9, 3)) {
19380 case NM_DPA_W_PH:
19381 check_dsp_r2(ctx);
19382 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19383 break;
19384 case NM_DPAQ_S_W_PH:
19385 check_dsp(ctx);
19386 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19387 break;
19388 case NM_DPS_W_PH:
19389 check_dsp_r2(ctx);
19390 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19391 break;
19392 case NM_DPSQ_S_W_PH:
19393 check_dsp(ctx);
19394 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19395 break;
19396 default:
19397 generate_exception_end(ctx, EXCP_RI);
19398 break;
19400 break;
19401 case NM_POOL32AXF_2_8_15:
19402 switch (extract32(ctx->opcode, 9, 3)) {
19403 case NM_DPAX_W_PH:
19404 check_dsp_r2(ctx);
19405 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19406 break;
19407 case NM_DPAQ_SA_L_W:
19408 check_dsp(ctx);
19409 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19410 break;
19411 case NM_DPSX_W_PH:
19412 check_dsp_r2(ctx);
19413 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19414 break;
19415 case NM_DPSQ_SA_L_W:
19416 check_dsp(ctx);
19417 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19418 break;
19419 default:
19420 generate_exception_end(ctx, EXCP_RI);
19421 break;
19423 break;
19424 case NM_POOL32AXF_2_16_23:
19425 switch (extract32(ctx->opcode, 9, 3)) {
19426 case NM_DPAU_H_QBL:
19427 check_dsp(ctx);
19428 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19429 break;
19430 case NM_DPAQX_S_W_PH:
19431 check_dsp_r2(ctx);
19432 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19433 break;
19434 case NM_DPSU_H_QBL:
19435 check_dsp(ctx);
19436 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19437 break;
19438 case NM_DPSQX_S_W_PH:
19439 check_dsp_r2(ctx);
19440 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19441 break;
19442 case NM_MULSA_W_PH:
19443 check_dsp_r2(ctx);
19444 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19445 break;
19446 default:
19447 generate_exception_end(ctx, EXCP_RI);
19448 break;
19450 break;
19451 case NM_POOL32AXF_2_24_31:
19452 switch (extract32(ctx->opcode, 9, 3)) {
19453 case NM_DPAU_H_QBR:
19454 check_dsp(ctx);
19455 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19456 break;
19457 case NM_DPAQX_SA_W_PH:
19458 check_dsp_r2(ctx);
19459 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19460 break;
19461 case NM_DPSU_H_QBR:
19462 check_dsp(ctx);
19463 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19464 break;
19465 case NM_DPSQX_SA_W_PH:
19466 check_dsp_r2(ctx);
19467 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19468 break;
19469 case NM_MULSAQ_S_W_PH:
19470 check_dsp(ctx);
19471 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19472 break;
19473 default:
19474 generate_exception_end(ctx, EXCP_RI);
19475 break;
19477 break;
19478 default:
19479 generate_exception_end(ctx, EXCP_RI);
19480 break;
19483 tcg_temp_free_i32(t0);
19486 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19487 int rt, int rs, int rd)
19489 int ret = rt;
19490 TCGv t0 = tcg_temp_new();
19491 TCGv t1 = tcg_temp_new();
19492 TCGv v0_t = tcg_temp_new();
19493 TCGv v1_t = tcg_temp_new();
19495 gen_load_gpr(v0_t, rt);
19496 gen_load_gpr(v1_t, rs);
19498 switch (opc) {
19499 case NM_POOL32AXF_2_0_7:
19500 switch (extract32(ctx->opcode, 9, 3)) {
19501 case NM_DPA_W_PH:
19502 case NM_DPAQ_S_W_PH:
19503 case NM_DPS_W_PH:
19504 case NM_DPSQ_S_W_PH:
19505 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19506 break;
19507 case NM_BALIGN:
19508 check_dsp_r2(ctx);
19509 if (rt != 0) {
19510 gen_load_gpr(t0, rs);
19511 rd &= 3;
19512 if (rd != 0 && rd != 2) {
19513 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19514 tcg_gen_ext32u_tl(t0, t0);
19515 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19516 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19518 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19520 break;
19521 case NM_MADD:
19522 check_dsp(ctx);
19524 int acc = extract32(ctx->opcode, 14, 2);
19525 TCGv_i64 t2 = tcg_temp_new_i64();
19526 TCGv_i64 t3 = tcg_temp_new_i64();
19528 gen_load_gpr(t0, rt);
19529 gen_load_gpr(t1, rs);
19530 tcg_gen_ext_tl_i64(t2, t0);
19531 tcg_gen_ext_tl_i64(t3, t1);
19532 tcg_gen_mul_i64(t2, t2, t3);
19533 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19534 tcg_gen_add_i64(t2, t2, t3);
19535 tcg_temp_free_i64(t3);
19536 gen_move_low32(cpu_LO[acc], t2);
19537 gen_move_high32(cpu_HI[acc], t2);
19538 tcg_temp_free_i64(t2);
19540 break;
19541 case NM_MULT:
19542 check_dsp(ctx);
19544 int acc = extract32(ctx->opcode, 14, 2);
19545 TCGv_i32 t2 = tcg_temp_new_i32();
19546 TCGv_i32 t3 = tcg_temp_new_i32();
19548 gen_load_gpr(t0, rs);
19549 gen_load_gpr(t1, rt);
19550 tcg_gen_trunc_tl_i32(t2, t0);
19551 tcg_gen_trunc_tl_i32(t3, t1);
19552 tcg_gen_muls2_i32(t2, t3, t2, t3);
19553 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19554 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19555 tcg_temp_free_i32(t2);
19556 tcg_temp_free_i32(t3);
19558 break;
19559 case NM_EXTRV_W:
19560 check_dsp(ctx);
19561 gen_load_gpr(v1_t, rs);
19562 tcg_gen_movi_tl(t0, rd >> 3);
19563 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19564 gen_store_gpr(t0, ret);
19565 break;
19567 break;
19568 case NM_POOL32AXF_2_8_15:
19569 switch (extract32(ctx->opcode, 9, 3)) {
19570 case NM_DPAX_W_PH:
19571 case NM_DPAQ_SA_L_W:
19572 case NM_DPSX_W_PH:
19573 case NM_DPSQ_SA_L_W:
19574 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19575 break;
19576 case NM_MADDU:
19577 check_dsp(ctx);
19579 int acc = extract32(ctx->opcode, 14, 2);
19580 TCGv_i64 t2 = tcg_temp_new_i64();
19581 TCGv_i64 t3 = tcg_temp_new_i64();
19583 gen_load_gpr(t0, rs);
19584 gen_load_gpr(t1, rt);
19585 tcg_gen_ext32u_tl(t0, t0);
19586 tcg_gen_ext32u_tl(t1, t1);
19587 tcg_gen_extu_tl_i64(t2, t0);
19588 tcg_gen_extu_tl_i64(t3, t1);
19589 tcg_gen_mul_i64(t2, t2, t3);
19590 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19591 tcg_gen_add_i64(t2, t2, t3);
19592 tcg_temp_free_i64(t3);
19593 gen_move_low32(cpu_LO[acc], t2);
19594 gen_move_high32(cpu_HI[acc], t2);
19595 tcg_temp_free_i64(t2);
19597 break;
19598 case NM_MULTU:
19599 check_dsp(ctx);
19601 int acc = extract32(ctx->opcode, 14, 2);
19602 TCGv_i32 t2 = tcg_temp_new_i32();
19603 TCGv_i32 t3 = tcg_temp_new_i32();
19605 gen_load_gpr(t0, rs);
19606 gen_load_gpr(t1, rt);
19607 tcg_gen_trunc_tl_i32(t2, t0);
19608 tcg_gen_trunc_tl_i32(t3, t1);
19609 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19610 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19611 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19612 tcg_temp_free_i32(t2);
19613 tcg_temp_free_i32(t3);
19615 break;
19616 case NM_EXTRV_R_W:
19617 check_dsp(ctx);
19618 tcg_gen_movi_tl(t0, rd >> 3);
19619 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19620 gen_store_gpr(t0, ret);
19621 break;
19622 default:
19623 generate_exception_end(ctx, EXCP_RI);
19624 break;
19626 break;
19627 case NM_POOL32AXF_2_16_23:
19628 switch (extract32(ctx->opcode, 9, 3)) {
19629 case NM_DPAU_H_QBL:
19630 case NM_DPAQX_S_W_PH:
19631 case NM_DPSU_H_QBL:
19632 case NM_DPSQX_S_W_PH:
19633 case NM_MULSA_W_PH:
19634 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19635 break;
19636 case NM_EXTPV:
19637 check_dsp(ctx);
19638 tcg_gen_movi_tl(t0, rd >> 3);
19639 gen_helper_extp(t0, t0, v1_t, cpu_env);
19640 gen_store_gpr(t0, ret);
19641 break;
19642 case NM_MSUB:
19643 check_dsp(ctx);
19645 int acc = extract32(ctx->opcode, 14, 2);
19646 TCGv_i64 t2 = tcg_temp_new_i64();
19647 TCGv_i64 t3 = tcg_temp_new_i64();
19649 gen_load_gpr(t0, rs);
19650 gen_load_gpr(t1, rt);
19651 tcg_gen_ext_tl_i64(t2, t0);
19652 tcg_gen_ext_tl_i64(t3, t1);
19653 tcg_gen_mul_i64(t2, t2, t3);
19654 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19655 tcg_gen_sub_i64(t2, t3, t2);
19656 tcg_temp_free_i64(t3);
19657 gen_move_low32(cpu_LO[acc], t2);
19658 gen_move_high32(cpu_HI[acc], t2);
19659 tcg_temp_free_i64(t2);
19661 break;
19662 case NM_EXTRV_RS_W:
19663 check_dsp(ctx);
19664 tcg_gen_movi_tl(t0, rd >> 3);
19665 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19666 gen_store_gpr(t0, ret);
19667 break;
19669 break;
19670 case NM_POOL32AXF_2_24_31:
19671 switch (extract32(ctx->opcode, 9, 3)) {
19672 case NM_DPAU_H_QBR:
19673 case NM_DPAQX_SA_W_PH:
19674 case NM_DPSU_H_QBR:
19675 case NM_DPSQX_SA_W_PH:
19676 case NM_MULSAQ_S_W_PH:
19677 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19678 break;
19679 case NM_EXTPDPV:
19680 check_dsp(ctx);
19681 tcg_gen_movi_tl(t0, rd >> 3);
19682 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19683 gen_store_gpr(t0, ret);
19684 break;
19685 case NM_MSUBU:
19686 check_dsp(ctx);
19688 int acc = extract32(ctx->opcode, 14, 2);
19689 TCGv_i64 t2 = tcg_temp_new_i64();
19690 TCGv_i64 t3 = tcg_temp_new_i64();
19692 gen_load_gpr(t0, rs);
19693 gen_load_gpr(t1, rt);
19694 tcg_gen_ext32u_tl(t0, t0);
19695 tcg_gen_ext32u_tl(t1, t1);
19696 tcg_gen_extu_tl_i64(t2, t0);
19697 tcg_gen_extu_tl_i64(t3, t1);
19698 tcg_gen_mul_i64(t2, t2, t3);
19699 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19700 tcg_gen_sub_i64(t2, t3, t2);
19701 tcg_temp_free_i64(t3);
19702 gen_move_low32(cpu_LO[acc], t2);
19703 gen_move_high32(cpu_HI[acc], t2);
19704 tcg_temp_free_i64(t2);
19706 break;
19707 case NM_EXTRV_S_H:
19708 check_dsp(ctx);
19709 tcg_gen_movi_tl(t0, rd >> 3);
19710 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19711 gen_store_gpr(t0, ret);
19712 break;
19714 break;
19715 default:
19716 generate_exception_end(ctx, EXCP_RI);
19717 break;
19720 tcg_temp_free(t0);
19721 tcg_temp_free(t1);
19723 tcg_temp_free(v0_t);
19724 tcg_temp_free(v1_t);
19727 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19728 int rt, int rs)
19730 int ret = rt;
19731 TCGv t0 = tcg_temp_new();
19732 TCGv v0_t = tcg_temp_new();
19734 gen_load_gpr(v0_t, rs);
19736 switch (opc) {
19737 case NM_ABSQ_S_QB:
19738 check_dsp_r2(ctx);
19739 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19740 gen_store_gpr(v0_t, ret);
19741 break;
19742 case NM_ABSQ_S_PH:
19743 check_dsp(ctx);
19744 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19745 gen_store_gpr(v0_t, ret);
19746 break;
19747 case NM_ABSQ_S_W:
19748 check_dsp(ctx);
19749 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19750 gen_store_gpr(v0_t, ret);
19751 break;
19752 case NM_PRECEQ_W_PHL:
19753 check_dsp(ctx);
19754 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19755 tcg_gen_ext32s_tl(v0_t, v0_t);
19756 gen_store_gpr(v0_t, ret);
19757 break;
19758 case NM_PRECEQ_W_PHR:
19759 check_dsp(ctx);
19760 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19761 tcg_gen_shli_tl(v0_t, v0_t, 16);
19762 tcg_gen_ext32s_tl(v0_t, v0_t);
19763 gen_store_gpr(v0_t, ret);
19764 break;
19765 case NM_PRECEQU_PH_QBL:
19766 check_dsp(ctx);
19767 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19768 gen_store_gpr(v0_t, ret);
19769 break;
19770 case NM_PRECEQU_PH_QBR:
19771 check_dsp(ctx);
19772 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19773 gen_store_gpr(v0_t, ret);
19774 break;
19775 case NM_PRECEQU_PH_QBLA:
19776 check_dsp(ctx);
19777 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19778 gen_store_gpr(v0_t, ret);
19779 break;
19780 case NM_PRECEQU_PH_QBRA:
19781 check_dsp(ctx);
19782 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19783 gen_store_gpr(v0_t, ret);
19784 break;
19785 case NM_PRECEU_PH_QBL:
19786 check_dsp(ctx);
19787 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19788 gen_store_gpr(v0_t, ret);
19789 break;
19790 case NM_PRECEU_PH_QBR:
19791 check_dsp(ctx);
19792 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19793 gen_store_gpr(v0_t, ret);
19794 break;
19795 case NM_PRECEU_PH_QBLA:
19796 check_dsp(ctx);
19797 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19798 gen_store_gpr(v0_t, ret);
19799 break;
19800 case NM_PRECEU_PH_QBRA:
19801 check_dsp(ctx);
19802 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19803 gen_store_gpr(v0_t, ret);
19804 break;
19805 case NM_REPLV_PH:
19806 check_dsp(ctx);
19807 tcg_gen_ext16u_tl(v0_t, v0_t);
19808 tcg_gen_shli_tl(t0, v0_t, 16);
19809 tcg_gen_or_tl(v0_t, v0_t, t0);
19810 tcg_gen_ext32s_tl(v0_t, v0_t);
19811 gen_store_gpr(v0_t, ret);
19812 break;
19813 case NM_REPLV_QB:
19814 check_dsp(ctx);
19815 tcg_gen_ext8u_tl(v0_t, v0_t);
19816 tcg_gen_shli_tl(t0, v0_t, 8);
19817 tcg_gen_or_tl(v0_t, v0_t, t0);
19818 tcg_gen_shli_tl(t0, v0_t, 16);
19819 tcg_gen_or_tl(v0_t, v0_t, t0);
19820 tcg_gen_ext32s_tl(v0_t, v0_t);
19821 gen_store_gpr(v0_t, ret);
19822 break;
19823 case NM_BITREV:
19824 check_dsp(ctx);
19825 gen_helper_bitrev(v0_t, v0_t);
19826 gen_store_gpr(v0_t, ret);
19827 break;
19828 case NM_INSV:
19829 check_dsp(ctx);
19831 TCGv tv0 = tcg_temp_new();
19833 gen_load_gpr(tv0, rt);
19834 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19835 gen_store_gpr(v0_t, ret);
19836 tcg_temp_free(tv0);
19838 break;
19839 case NM_RADDU_W_QB:
19840 check_dsp(ctx);
19841 gen_helper_raddu_w_qb(v0_t, v0_t);
19842 gen_store_gpr(v0_t, ret);
19843 break;
19844 case NM_BITSWAP:
19845 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19846 break;
19847 case NM_CLO:
19848 check_nms(ctx);
19849 gen_cl(ctx, OPC_CLO, ret, rs);
19850 break;
19851 case NM_CLZ:
19852 check_nms(ctx);
19853 gen_cl(ctx, OPC_CLZ, ret, rs);
19854 break;
19855 case NM_WSBH:
19856 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19857 break;
19858 default:
19859 generate_exception_end(ctx, EXCP_RI);
19860 break;
19863 tcg_temp_free(v0_t);
19864 tcg_temp_free(t0);
19867 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19868 int rt, int rs, int rd)
19870 TCGv t0 = tcg_temp_new();
19871 TCGv rs_t = tcg_temp_new();
19873 gen_load_gpr(rs_t, rs);
19875 switch (opc) {
19876 case NM_SHRA_R_QB:
19877 check_dsp_r2(ctx);
19878 tcg_gen_movi_tl(t0, rd >> 2);
19879 switch (extract32(ctx->opcode, 12, 1)) {
19880 case 0:
19881 /* NM_SHRA_QB */
19882 gen_helper_shra_qb(t0, t0, rs_t);
19883 gen_store_gpr(t0, rt);
19884 break;
19885 case 1:
19886 /* NM_SHRA_R_QB */
19887 gen_helper_shra_r_qb(t0, t0, rs_t);
19888 gen_store_gpr(t0, rt);
19889 break;
19891 break;
19892 case NM_SHRL_PH:
19893 check_dsp_r2(ctx);
19894 tcg_gen_movi_tl(t0, rd >> 1);
19895 gen_helper_shrl_ph(t0, t0, rs_t);
19896 gen_store_gpr(t0, rt);
19897 break;
19898 case NM_REPL_QB:
19899 check_dsp(ctx);
19901 int16_t imm;
19902 target_long result;
19903 imm = extract32(ctx->opcode, 13, 8);
19904 result = (uint32_t)imm << 24 |
19905 (uint32_t)imm << 16 |
19906 (uint32_t)imm << 8 |
19907 (uint32_t)imm;
19908 result = (int32_t)result;
19909 tcg_gen_movi_tl(t0, result);
19910 gen_store_gpr(t0, rt);
19912 break;
19913 default:
19914 generate_exception_end(ctx, EXCP_RI);
19915 break;
19917 tcg_temp_free(t0);
19918 tcg_temp_free(rs_t);
19922 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19924 int rt = extract32(ctx->opcode, 21, 5);
19925 int rs = extract32(ctx->opcode, 16, 5);
19926 int rd = extract32(ctx->opcode, 11, 5);
19928 switch (extract32(ctx->opcode, 6, 3)) {
19929 case NM_POOL32AXF_1:
19931 int32_t op1 = extract32(ctx->opcode, 9, 3);
19932 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19934 break;
19935 case NM_POOL32AXF_2:
19937 int32_t op1 = extract32(ctx->opcode, 12, 2);
19938 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19940 break;
19941 case NM_POOL32AXF_4:
19943 int32_t op1 = extract32(ctx->opcode, 9, 7);
19944 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19946 break;
19947 case NM_POOL32AXF_5:
19948 switch (extract32(ctx->opcode, 9, 7)) {
19949 #ifndef CONFIG_USER_ONLY
19950 case NM_TLBP:
19951 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19952 break;
19953 case NM_TLBR:
19954 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19955 break;
19956 case NM_TLBWI:
19957 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19958 break;
19959 case NM_TLBWR:
19960 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19961 break;
19962 case NM_TLBINV:
19963 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19964 break;
19965 case NM_TLBINVF:
19966 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19967 break;
19968 case NM_DI:
19969 check_cp0_enabled(ctx);
19971 TCGv t0 = tcg_temp_new();
19973 save_cpu_state(ctx, 1);
19974 gen_helper_di(t0, cpu_env);
19975 gen_store_gpr(t0, rt);
19976 /* Stop translation as we may have switched the execution mode */
19977 ctx->base.is_jmp = DISAS_STOP;
19978 tcg_temp_free(t0);
19980 break;
19981 case NM_EI:
19982 check_cp0_enabled(ctx);
19984 TCGv t0 = tcg_temp_new();
19986 save_cpu_state(ctx, 1);
19987 gen_helper_ei(t0, cpu_env);
19988 gen_store_gpr(t0, rt);
19989 /* Stop translation as we may have switched the execution mode */
19990 ctx->base.is_jmp = DISAS_STOP;
19991 tcg_temp_free(t0);
19993 break;
19994 case NM_RDPGPR:
19995 gen_load_srsgpr(rs, rt);
19996 break;
19997 case NM_WRPGPR:
19998 gen_store_srsgpr(rs, rt);
19999 break;
20000 case NM_WAIT:
20001 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20002 break;
20003 case NM_DERET:
20004 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20005 break;
20006 case NM_ERETX:
20007 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20008 break;
20009 #endif
20010 default:
20011 generate_exception_end(ctx, EXCP_RI);
20012 break;
20014 break;
20015 case NM_POOL32AXF_7:
20017 int32_t op1 = extract32(ctx->opcode, 9, 3);
20018 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20020 break;
20021 default:
20022 generate_exception_end(ctx, EXCP_RI);
20023 break;
20027 /* Immediate Value Compact Branches */
20028 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20029 int rt, int32_t imm, int32_t offset)
20031 TCGCond cond = TCG_COND_ALWAYS;
20032 TCGv t0 = tcg_temp_new();
20033 TCGv t1 = tcg_temp_new();
20035 gen_load_gpr(t0, rt);
20036 tcg_gen_movi_tl(t1, imm);
20037 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20039 /* Load needed operands and calculate btarget */
20040 switch (opc) {
20041 case NM_BEQIC:
20042 if (rt == 0 && imm == 0) {
20043 /* Unconditional branch */
20044 } else if (rt == 0 && imm != 0) {
20045 /* Treat as NOP */
20046 goto out;
20047 } else {
20048 cond = TCG_COND_EQ;
20050 break;
20051 case NM_BBEQZC:
20052 case NM_BBNEZC:
20053 check_nms(ctx);
20054 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20055 generate_exception_end(ctx, EXCP_RI);
20056 goto out;
20057 } else if (rt == 0 && opc == NM_BBEQZC) {
20058 /* Unconditional branch */
20059 } else if (rt == 0 && opc == NM_BBNEZC) {
20060 /* Treat as NOP */
20061 goto out;
20062 } else {
20063 tcg_gen_shri_tl(t0, t0, imm);
20064 tcg_gen_andi_tl(t0, t0, 1);
20065 tcg_gen_movi_tl(t1, 0);
20066 if (opc == NM_BBEQZC) {
20067 cond = TCG_COND_EQ;
20068 } else {
20069 cond = TCG_COND_NE;
20072 break;
20073 case NM_BNEIC:
20074 if (rt == 0 && imm == 0) {
20075 /* Treat as NOP */
20076 goto out;
20077 } else if (rt == 0 && imm != 0) {
20078 /* Unconditional branch */
20079 } else {
20080 cond = TCG_COND_NE;
20082 break;
20083 case NM_BGEIC:
20084 if (rt == 0 && imm == 0) {
20085 /* Unconditional branch */
20086 } else {
20087 cond = TCG_COND_GE;
20089 break;
20090 case NM_BLTIC:
20091 cond = TCG_COND_LT;
20092 break;
20093 case NM_BGEIUC:
20094 if (rt == 0 && imm == 0) {
20095 /* Unconditional branch */
20096 } else {
20097 cond = TCG_COND_GEU;
20099 break;
20100 case NM_BLTIUC:
20101 cond = TCG_COND_LTU;
20102 break;
20103 default:
20104 MIPS_INVAL("Immediate Value Compact branch");
20105 generate_exception_end(ctx, EXCP_RI);
20106 goto out;
20109 /* branch completion */
20110 clear_branch_hflags(ctx);
20111 ctx->base.is_jmp = DISAS_NORETURN;
20113 if (cond == TCG_COND_ALWAYS) {
20114 /* Uncoditional compact branch */
20115 gen_goto_tb(ctx, 0, ctx->btarget);
20116 } else {
20117 /* Conditional compact branch */
20118 TCGLabel *fs = gen_new_label();
20120 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20122 gen_goto_tb(ctx, 1, ctx->btarget);
20123 gen_set_label(fs);
20125 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20128 out:
20129 tcg_temp_free(t0);
20130 tcg_temp_free(t1);
20133 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20134 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20135 int rt)
20137 TCGv t0 = tcg_temp_new();
20138 TCGv t1 = tcg_temp_new();
20140 /* load rs */
20141 gen_load_gpr(t0, rs);
20143 /* link */
20144 if (rt != 0) {
20145 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20148 /* calculate btarget */
20149 tcg_gen_shli_tl(t0, t0, 1);
20150 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20151 gen_op_addr_add(ctx, btarget, t1, t0);
20153 /* branch completion */
20154 clear_branch_hflags(ctx);
20155 ctx->base.is_jmp = DISAS_NORETURN;
20157 /* unconditional branch to register */
20158 tcg_gen_mov_tl(cpu_PC, btarget);
20159 tcg_gen_lookup_and_goto_ptr();
20161 tcg_temp_free(t0);
20162 tcg_temp_free(t1);
20165 /* nanoMIPS Branches */
20166 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20167 int rs, int rt, int32_t offset)
20169 int bcond_compute = 0;
20170 TCGv t0 = tcg_temp_new();
20171 TCGv t1 = tcg_temp_new();
20173 /* Load needed operands and calculate btarget */
20174 switch (opc) {
20175 /* compact branch */
20176 case OPC_BGEC:
20177 case OPC_BLTC:
20178 gen_load_gpr(t0, rs);
20179 gen_load_gpr(t1, rt);
20180 bcond_compute = 1;
20181 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20182 break;
20183 case OPC_BGEUC:
20184 case OPC_BLTUC:
20185 if (rs == 0 || rs == rt) {
20186 /* OPC_BLEZALC, OPC_BGEZALC */
20187 /* OPC_BGTZALC, OPC_BLTZALC */
20188 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20190 gen_load_gpr(t0, rs);
20191 gen_load_gpr(t1, rt);
20192 bcond_compute = 1;
20193 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20194 break;
20195 case OPC_BC:
20196 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20197 break;
20198 case OPC_BEQZC:
20199 if (rs != 0) {
20200 /* OPC_BEQZC, OPC_BNEZC */
20201 gen_load_gpr(t0, rs);
20202 bcond_compute = 1;
20203 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20204 } else {
20205 /* OPC_JIC, OPC_JIALC */
20206 TCGv tbase = tcg_temp_new();
20207 TCGv toffset = tcg_temp_new();
20209 gen_load_gpr(tbase, rt);
20210 tcg_gen_movi_tl(toffset, offset);
20211 gen_op_addr_add(ctx, btarget, tbase, toffset);
20212 tcg_temp_free(tbase);
20213 tcg_temp_free(toffset);
20215 break;
20216 default:
20217 MIPS_INVAL("Compact branch/jump");
20218 generate_exception_end(ctx, EXCP_RI);
20219 goto out;
20222 if (bcond_compute == 0) {
20223 /* Uncoditional compact branch */
20224 switch (opc) {
20225 case OPC_BC:
20226 gen_goto_tb(ctx, 0, ctx->btarget);
20227 break;
20228 default:
20229 MIPS_INVAL("Compact branch/jump");
20230 generate_exception_end(ctx, EXCP_RI);
20231 goto out;
20233 } else {
20234 /* Conditional compact branch */
20235 TCGLabel *fs = gen_new_label();
20237 switch (opc) {
20238 case OPC_BGEUC:
20239 if (rs == 0 && rt != 0) {
20240 /* OPC_BLEZALC */
20241 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20242 } else if (rs != 0 && rt != 0 && rs == rt) {
20243 /* OPC_BGEZALC */
20244 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20245 } else {
20246 /* OPC_BGEUC */
20247 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20249 break;
20250 case OPC_BLTUC:
20251 if (rs == 0 && rt != 0) {
20252 /* OPC_BGTZALC */
20253 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20254 } else if (rs != 0 && rt != 0 && rs == rt) {
20255 /* OPC_BLTZALC */
20256 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20257 } else {
20258 /* OPC_BLTUC */
20259 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20261 break;
20262 case OPC_BGEC:
20263 if (rs == 0 && rt != 0) {
20264 /* OPC_BLEZC */
20265 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20266 } else if (rs != 0 && rt != 0 && rs == rt) {
20267 /* OPC_BGEZC */
20268 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20269 } else {
20270 /* OPC_BGEC */
20271 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20273 break;
20274 case OPC_BLTC:
20275 if (rs == 0 && rt != 0) {
20276 /* OPC_BGTZC */
20277 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20278 } else if (rs != 0 && rt != 0 && rs == rt) {
20279 /* OPC_BLTZC */
20280 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20281 } else {
20282 /* OPC_BLTC */
20283 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20285 break;
20286 case OPC_BEQZC:
20287 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20288 break;
20289 default:
20290 MIPS_INVAL("Compact conditional branch/jump");
20291 generate_exception_end(ctx, EXCP_RI);
20292 goto out;
20295 /* branch completion */
20296 clear_branch_hflags(ctx);
20297 ctx->base.is_jmp = DISAS_NORETURN;
20299 /* Generating branch here as compact branches don't have delay slot */
20300 gen_goto_tb(ctx, 1, ctx->btarget);
20301 gen_set_label(fs);
20303 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20306 out:
20307 tcg_temp_free(t0);
20308 tcg_temp_free(t1);
20312 /* nanoMIPS CP1 Branches */
20313 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20314 int32_t ft, int32_t offset)
20316 target_ulong btarget;
20317 TCGv_i64 t0 = tcg_temp_new_i64();
20319 gen_load_fpr64(ctx, t0, ft);
20320 tcg_gen_andi_i64(t0, t0, 1);
20322 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20324 switch (op) {
20325 case NM_BC1EQZC:
20326 tcg_gen_xori_i64(t0, t0, 1);
20327 ctx->hflags |= MIPS_HFLAG_BC;
20328 break;
20329 case NM_BC1NEZC:
20330 /* t0 already set */
20331 ctx->hflags |= MIPS_HFLAG_BC;
20332 break;
20333 default:
20334 MIPS_INVAL("cp1 cond branch");
20335 generate_exception_end(ctx, EXCP_RI);
20336 goto out;
20339 tcg_gen_trunc_i64_tl(bcond, t0);
20341 ctx->btarget = btarget;
20343 out:
20344 tcg_temp_free_i64(t0);
20348 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20350 TCGv t0, t1;
20351 t0 = tcg_temp_new();
20352 t1 = tcg_temp_new();
20354 gen_load_gpr(t0, rs);
20355 gen_load_gpr(t1, rt);
20357 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20358 /* PP.LSXS instructions require shifting */
20359 switch (extract32(ctx->opcode, 7, 4)) {
20360 case NM_SHXS:
20361 check_nms(ctx);
20362 /* fall through */
20363 case NM_LHXS:
20364 case NM_LHUXS:
20365 tcg_gen_shli_tl(t0, t0, 1);
20366 break;
20367 case NM_SWXS:
20368 check_nms(ctx);
20369 /* fall through */
20370 case NM_LWXS:
20371 case NM_LWC1XS:
20372 case NM_SWC1XS:
20373 tcg_gen_shli_tl(t0, t0, 2);
20374 break;
20375 case NM_LDC1XS:
20376 case NM_SDC1XS:
20377 tcg_gen_shli_tl(t0, t0, 3);
20378 break;
20381 gen_op_addr_add(ctx, t0, t0, t1);
20383 switch (extract32(ctx->opcode, 7, 4)) {
20384 case NM_LBX:
20385 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20386 MO_SB);
20387 gen_store_gpr(t0, rd);
20388 break;
20389 case NM_LHX:
20390 /*case NM_LHXS:*/
20391 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20392 MO_TESW);
20393 gen_store_gpr(t0, rd);
20394 break;
20395 case NM_LWX:
20396 /*case NM_LWXS:*/
20397 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20398 MO_TESL);
20399 gen_store_gpr(t0, rd);
20400 break;
20401 case NM_LBUX:
20402 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20403 MO_UB);
20404 gen_store_gpr(t0, rd);
20405 break;
20406 case NM_LHUX:
20407 /*case NM_LHUXS:*/
20408 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20409 MO_TEUW);
20410 gen_store_gpr(t0, rd);
20411 break;
20412 case NM_SBX:
20413 check_nms(ctx);
20414 gen_load_gpr(t1, rd);
20415 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20416 MO_8);
20417 break;
20418 case NM_SHX:
20419 /*case NM_SHXS:*/
20420 check_nms(ctx);
20421 gen_load_gpr(t1, rd);
20422 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20423 MO_TEUW);
20424 break;
20425 case NM_SWX:
20426 /*case NM_SWXS:*/
20427 check_nms(ctx);
20428 gen_load_gpr(t1, rd);
20429 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20430 MO_TEUL);
20431 break;
20432 case NM_LWC1X:
20433 /*case NM_LWC1XS:*/
20434 case NM_LDC1X:
20435 /*case NM_LDC1XS:*/
20436 case NM_SWC1X:
20437 /*case NM_SWC1XS:*/
20438 case NM_SDC1X:
20439 /*case NM_SDC1XS:*/
20440 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20441 check_cp1_enabled(ctx);
20442 switch (extract32(ctx->opcode, 7, 4)) {
20443 case NM_LWC1X:
20444 /*case NM_LWC1XS:*/
20445 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20446 break;
20447 case NM_LDC1X:
20448 /*case NM_LDC1XS:*/
20449 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20450 break;
20451 case NM_SWC1X:
20452 /*case NM_SWC1XS:*/
20453 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20454 break;
20455 case NM_SDC1X:
20456 /*case NM_SDC1XS:*/
20457 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20458 break;
20460 } else {
20461 generate_exception_err(ctx, EXCP_CpU, 1);
20463 break;
20464 default:
20465 generate_exception_end(ctx, EXCP_RI);
20466 break;
20469 tcg_temp_free(t0);
20470 tcg_temp_free(t1);
20473 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20475 int rt, rs, rd;
20477 rt = extract32(ctx->opcode, 21, 5);
20478 rs = extract32(ctx->opcode, 16, 5);
20479 rd = extract32(ctx->opcode, 11, 5);
20481 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20482 generate_exception_end(ctx, EXCP_RI);
20483 return;
20485 check_cp1_enabled(ctx);
20486 switch (extract32(ctx->opcode, 0, 3)) {
20487 case NM_POOL32F_0:
20488 switch (extract32(ctx->opcode, 3, 7)) {
20489 case NM_RINT_S:
20490 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20491 break;
20492 case NM_RINT_D:
20493 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20494 break;
20495 case NM_CLASS_S:
20496 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20497 break;
20498 case NM_CLASS_D:
20499 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20500 break;
20501 case NM_ADD_S:
20502 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20503 break;
20504 case NM_ADD_D:
20505 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20506 break;
20507 case NM_SUB_S:
20508 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20509 break;
20510 case NM_SUB_D:
20511 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20512 break;
20513 case NM_MUL_S:
20514 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20515 break;
20516 case NM_MUL_D:
20517 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20518 break;
20519 case NM_DIV_S:
20520 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20521 break;
20522 case NM_DIV_D:
20523 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20524 break;
20525 case NM_SELEQZ_S:
20526 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20527 break;
20528 case NM_SELEQZ_D:
20529 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20530 break;
20531 case NM_SELNEZ_S:
20532 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20533 break;
20534 case NM_SELNEZ_D:
20535 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20536 break;
20537 case NM_SEL_S:
20538 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20539 break;
20540 case NM_SEL_D:
20541 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20542 break;
20543 case NM_MADDF_S:
20544 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20545 break;
20546 case NM_MADDF_D:
20547 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20548 break;
20549 case NM_MSUBF_S:
20550 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20551 break;
20552 case NM_MSUBF_D:
20553 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20554 break;
20555 default:
20556 generate_exception_end(ctx, EXCP_RI);
20557 break;
20559 break;
20560 case NM_POOL32F_3:
20561 switch (extract32(ctx->opcode, 3, 3)) {
20562 case NM_MIN_FMT:
20563 switch (extract32(ctx->opcode, 9, 1)) {
20564 case FMT_SDPS_S:
20565 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20566 break;
20567 case FMT_SDPS_D:
20568 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20569 break;
20571 break;
20572 case NM_MAX_FMT:
20573 switch (extract32(ctx->opcode, 9, 1)) {
20574 case FMT_SDPS_S:
20575 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20576 break;
20577 case FMT_SDPS_D:
20578 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20579 break;
20581 break;
20582 case NM_MINA_FMT:
20583 switch (extract32(ctx->opcode, 9, 1)) {
20584 case FMT_SDPS_S:
20585 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20586 break;
20587 case FMT_SDPS_D:
20588 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20589 break;
20591 break;
20592 case NM_MAXA_FMT:
20593 switch (extract32(ctx->opcode, 9, 1)) {
20594 case FMT_SDPS_S:
20595 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20596 break;
20597 case FMT_SDPS_D:
20598 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20599 break;
20601 break;
20602 case NM_POOL32FXF:
20603 switch (extract32(ctx->opcode, 6, 8)) {
20604 case NM_CFC1:
20605 gen_cp1(ctx, OPC_CFC1, rt, rs);
20606 break;
20607 case NM_CTC1:
20608 gen_cp1(ctx, OPC_CTC1, rt, rs);
20609 break;
20610 case NM_MFC1:
20611 gen_cp1(ctx, OPC_MFC1, rt, rs);
20612 break;
20613 case NM_MTC1:
20614 gen_cp1(ctx, OPC_MTC1, rt, rs);
20615 break;
20616 case NM_MFHC1:
20617 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20618 break;
20619 case NM_MTHC1:
20620 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20621 break;
20622 case NM_CVT_S_PL:
20623 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20624 break;
20625 case NM_CVT_S_PU:
20626 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20627 break;
20628 default:
20629 switch (extract32(ctx->opcode, 6, 9)) {
20630 case NM_CVT_L_S:
20631 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20632 break;
20633 case NM_CVT_L_D:
20634 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20635 break;
20636 case NM_CVT_W_S:
20637 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20638 break;
20639 case NM_CVT_W_D:
20640 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20641 break;
20642 case NM_RSQRT_S:
20643 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20644 break;
20645 case NM_RSQRT_D:
20646 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20647 break;
20648 case NM_SQRT_S:
20649 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20650 break;
20651 case NM_SQRT_D:
20652 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20653 break;
20654 case NM_RECIP_S:
20655 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20656 break;
20657 case NM_RECIP_D:
20658 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20659 break;
20660 case NM_FLOOR_L_S:
20661 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20662 break;
20663 case NM_FLOOR_L_D:
20664 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20665 break;
20666 case NM_FLOOR_W_S:
20667 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20668 break;
20669 case NM_FLOOR_W_D:
20670 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20671 break;
20672 case NM_CEIL_L_S:
20673 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20674 break;
20675 case NM_CEIL_L_D:
20676 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20677 break;
20678 case NM_CEIL_W_S:
20679 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20680 break;
20681 case NM_CEIL_W_D:
20682 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20683 break;
20684 case NM_TRUNC_L_S:
20685 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20686 break;
20687 case NM_TRUNC_L_D:
20688 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20689 break;
20690 case NM_TRUNC_W_S:
20691 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20692 break;
20693 case NM_TRUNC_W_D:
20694 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20695 break;
20696 case NM_ROUND_L_S:
20697 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20698 break;
20699 case NM_ROUND_L_D:
20700 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20701 break;
20702 case NM_ROUND_W_S:
20703 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20704 break;
20705 case NM_ROUND_W_D:
20706 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20707 break;
20708 case NM_MOV_S:
20709 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20710 break;
20711 case NM_MOV_D:
20712 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20713 break;
20714 case NM_ABS_S:
20715 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20716 break;
20717 case NM_ABS_D:
20718 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20719 break;
20720 case NM_NEG_S:
20721 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20722 break;
20723 case NM_NEG_D:
20724 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20725 break;
20726 case NM_CVT_D_S:
20727 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20728 break;
20729 case NM_CVT_D_W:
20730 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20731 break;
20732 case NM_CVT_D_L:
20733 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20734 break;
20735 case NM_CVT_S_D:
20736 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20737 break;
20738 case NM_CVT_S_W:
20739 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20740 break;
20741 case NM_CVT_S_L:
20742 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20743 break;
20744 default:
20745 generate_exception_end(ctx, EXCP_RI);
20746 break;
20748 break;
20750 break;
20752 break;
20753 case NM_POOL32F_5:
20754 switch (extract32(ctx->opcode, 3, 3)) {
20755 case NM_CMP_CONDN_S:
20756 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20757 break;
20758 case NM_CMP_CONDN_D:
20759 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20760 break;
20761 default:
20762 generate_exception_end(ctx, EXCP_RI);
20763 break;
20765 break;
20766 default:
20767 generate_exception_end(ctx, EXCP_RI);
20768 break;
20772 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20773 int rd, int rs, int rt)
20775 int ret = rd;
20776 TCGv t0 = tcg_temp_new();
20777 TCGv v1_t = tcg_temp_new();
20778 TCGv v2_t = tcg_temp_new();
20780 gen_load_gpr(v1_t, rs);
20781 gen_load_gpr(v2_t, rt);
20783 switch (opc) {
20784 case NM_CMP_EQ_PH:
20785 check_dsp(ctx);
20786 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20787 break;
20788 case NM_CMP_LT_PH:
20789 check_dsp(ctx);
20790 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20791 break;
20792 case NM_CMP_LE_PH:
20793 check_dsp(ctx);
20794 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20795 break;
20796 case NM_CMPU_EQ_QB:
20797 check_dsp(ctx);
20798 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20799 break;
20800 case NM_CMPU_LT_QB:
20801 check_dsp(ctx);
20802 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20803 break;
20804 case NM_CMPU_LE_QB:
20805 check_dsp(ctx);
20806 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20807 break;
20808 case NM_CMPGU_EQ_QB:
20809 check_dsp(ctx);
20810 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20811 gen_store_gpr(v1_t, ret);
20812 break;
20813 case NM_CMPGU_LT_QB:
20814 check_dsp(ctx);
20815 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20816 gen_store_gpr(v1_t, ret);
20817 break;
20818 case NM_CMPGU_LE_QB:
20819 check_dsp(ctx);
20820 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20821 gen_store_gpr(v1_t, ret);
20822 break;
20823 case NM_CMPGDU_EQ_QB:
20824 check_dsp_r2(ctx);
20825 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20826 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20827 gen_store_gpr(v1_t, ret);
20828 break;
20829 case NM_CMPGDU_LT_QB:
20830 check_dsp_r2(ctx);
20831 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20832 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20833 gen_store_gpr(v1_t, ret);
20834 break;
20835 case NM_CMPGDU_LE_QB:
20836 check_dsp_r2(ctx);
20837 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20838 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20839 gen_store_gpr(v1_t, ret);
20840 break;
20841 case NM_PACKRL_PH:
20842 check_dsp(ctx);
20843 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20844 gen_store_gpr(v1_t, ret);
20845 break;
20846 case NM_PICK_QB:
20847 check_dsp(ctx);
20848 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20849 gen_store_gpr(v1_t, ret);
20850 break;
20851 case NM_PICK_PH:
20852 check_dsp(ctx);
20853 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20854 gen_store_gpr(v1_t, ret);
20855 break;
20856 case NM_ADDQ_S_W:
20857 check_dsp(ctx);
20858 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20859 gen_store_gpr(v1_t, ret);
20860 break;
20861 case NM_SUBQ_S_W:
20862 check_dsp(ctx);
20863 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20864 gen_store_gpr(v1_t, ret);
20865 break;
20866 case NM_ADDSC:
20867 check_dsp(ctx);
20868 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20869 gen_store_gpr(v1_t, ret);
20870 break;
20871 case NM_ADDWC:
20872 check_dsp(ctx);
20873 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20874 gen_store_gpr(v1_t, ret);
20875 break;
20876 case NM_ADDQ_S_PH:
20877 check_dsp(ctx);
20878 switch (extract32(ctx->opcode, 10, 1)) {
20879 case 0:
20880 /* ADDQ_PH */
20881 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20882 gen_store_gpr(v1_t, ret);
20883 break;
20884 case 1:
20885 /* ADDQ_S_PH */
20886 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20887 gen_store_gpr(v1_t, ret);
20888 break;
20890 break;
20891 case NM_ADDQH_R_PH:
20892 check_dsp_r2(ctx);
20893 switch (extract32(ctx->opcode, 10, 1)) {
20894 case 0:
20895 /* ADDQH_PH */
20896 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20897 gen_store_gpr(v1_t, ret);
20898 break;
20899 case 1:
20900 /* ADDQH_R_PH */
20901 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20902 gen_store_gpr(v1_t, ret);
20903 break;
20905 break;
20906 case NM_ADDQH_R_W:
20907 check_dsp_r2(ctx);
20908 switch (extract32(ctx->opcode, 10, 1)) {
20909 case 0:
20910 /* ADDQH_W */
20911 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20912 gen_store_gpr(v1_t, ret);
20913 break;
20914 case 1:
20915 /* ADDQH_R_W */
20916 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20917 gen_store_gpr(v1_t, ret);
20918 break;
20920 break;
20921 case NM_ADDU_S_QB:
20922 check_dsp(ctx);
20923 switch (extract32(ctx->opcode, 10, 1)) {
20924 case 0:
20925 /* ADDU_QB */
20926 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20927 gen_store_gpr(v1_t, ret);
20928 break;
20929 case 1:
20930 /* ADDU_S_QB */
20931 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20932 gen_store_gpr(v1_t, ret);
20933 break;
20935 break;
20936 case NM_ADDU_S_PH:
20937 check_dsp_r2(ctx);
20938 switch (extract32(ctx->opcode, 10, 1)) {
20939 case 0:
20940 /* ADDU_PH */
20941 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20942 gen_store_gpr(v1_t, ret);
20943 break;
20944 case 1:
20945 /* ADDU_S_PH */
20946 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20947 gen_store_gpr(v1_t, ret);
20948 break;
20950 break;
20951 case NM_ADDUH_R_QB:
20952 check_dsp_r2(ctx);
20953 switch (extract32(ctx->opcode, 10, 1)) {
20954 case 0:
20955 /* ADDUH_QB */
20956 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20959 case 1:
20960 /* ADDUH_R_QB */
20961 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20962 gen_store_gpr(v1_t, ret);
20963 break;
20965 break;
20966 case NM_SHRAV_R_PH:
20967 check_dsp(ctx);
20968 switch (extract32(ctx->opcode, 10, 1)) {
20969 case 0:
20970 /* SHRAV_PH */
20971 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20972 gen_store_gpr(v1_t, ret);
20973 break;
20974 case 1:
20975 /* SHRAV_R_PH */
20976 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20977 gen_store_gpr(v1_t, ret);
20978 break;
20980 break;
20981 case NM_SHRAV_R_QB:
20982 check_dsp_r2(ctx);
20983 switch (extract32(ctx->opcode, 10, 1)) {
20984 case 0:
20985 /* SHRAV_QB */
20986 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20987 gen_store_gpr(v1_t, ret);
20988 break;
20989 case 1:
20990 /* SHRAV_R_QB */
20991 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20992 gen_store_gpr(v1_t, ret);
20993 break;
20995 break;
20996 case NM_SUBQ_S_PH:
20997 check_dsp(ctx);
20998 switch (extract32(ctx->opcode, 10, 1)) {
20999 case 0:
21000 /* SUBQ_PH */
21001 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21002 gen_store_gpr(v1_t, ret);
21003 break;
21004 case 1:
21005 /* SUBQ_S_PH */
21006 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21007 gen_store_gpr(v1_t, ret);
21008 break;
21010 break;
21011 case NM_SUBQH_R_PH:
21012 check_dsp_r2(ctx);
21013 switch (extract32(ctx->opcode, 10, 1)) {
21014 case 0:
21015 /* SUBQH_PH */
21016 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21017 gen_store_gpr(v1_t, ret);
21018 break;
21019 case 1:
21020 /* SUBQH_R_PH */
21021 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21022 gen_store_gpr(v1_t, ret);
21023 break;
21025 break;
21026 case NM_SUBQH_R_W:
21027 check_dsp_r2(ctx);
21028 switch (extract32(ctx->opcode, 10, 1)) {
21029 case 0:
21030 /* SUBQH_W */
21031 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21032 gen_store_gpr(v1_t, ret);
21033 break;
21034 case 1:
21035 /* SUBQH_R_W */
21036 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21037 gen_store_gpr(v1_t, ret);
21038 break;
21040 break;
21041 case NM_SUBU_S_QB:
21042 check_dsp(ctx);
21043 switch (extract32(ctx->opcode, 10, 1)) {
21044 case 0:
21045 /* SUBU_QB */
21046 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21047 gen_store_gpr(v1_t, ret);
21048 break;
21049 case 1:
21050 /* SUBU_S_QB */
21051 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21052 gen_store_gpr(v1_t, ret);
21053 break;
21055 break;
21056 case NM_SUBU_S_PH:
21057 check_dsp_r2(ctx);
21058 switch (extract32(ctx->opcode, 10, 1)) {
21059 case 0:
21060 /* SUBU_PH */
21061 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21062 gen_store_gpr(v1_t, ret);
21063 break;
21064 case 1:
21065 /* SUBU_S_PH */
21066 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21067 gen_store_gpr(v1_t, ret);
21068 break;
21070 break;
21071 case NM_SUBUH_R_QB:
21072 check_dsp_r2(ctx);
21073 switch (extract32(ctx->opcode, 10, 1)) {
21074 case 0:
21075 /* SUBUH_QB */
21076 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21077 gen_store_gpr(v1_t, ret);
21078 break;
21079 case 1:
21080 /* SUBUH_R_QB */
21081 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21082 gen_store_gpr(v1_t, ret);
21083 break;
21085 break;
21086 case NM_SHLLV_S_PH:
21087 check_dsp(ctx);
21088 switch (extract32(ctx->opcode, 10, 1)) {
21089 case 0:
21090 /* SHLLV_PH */
21091 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21092 gen_store_gpr(v1_t, ret);
21093 break;
21094 case 1:
21095 /* SHLLV_S_PH */
21096 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21097 gen_store_gpr(v1_t, ret);
21098 break;
21100 break;
21101 case NM_PRECR_SRA_R_PH_W:
21102 check_dsp_r2(ctx);
21103 switch (extract32(ctx->opcode, 10, 1)) {
21104 case 0:
21105 /* PRECR_SRA_PH_W */
21107 TCGv_i32 sa_t = tcg_const_i32(rd);
21108 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21109 cpu_gpr[rt]);
21110 gen_store_gpr(v1_t, rt);
21111 tcg_temp_free_i32(sa_t);
21113 break;
21114 case 1:
21115 /* PRECR_SRA_R_PH_W */
21117 TCGv_i32 sa_t = tcg_const_i32(rd);
21118 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21119 cpu_gpr[rt]);
21120 gen_store_gpr(v1_t, rt);
21121 tcg_temp_free_i32(sa_t);
21123 break;
21125 break;
21126 case NM_MULEU_S_PH_QBL:
21127 check_dsp(ctx);
21128 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21129 gen_store_gpr(v1_t, ret);
21130 break;
21131 case NM_MULEU_S_PH_QBR:
21132 check_dsp(ctx);
21133 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21134 gen_store_gpr(v1_t, ret);
21135 break;
21136 case NM_MULQ_RS_PH:
21137 check_dsp(ctx);
21138 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21139 gen_store_gpr(v1_t, ret);
21140 break;
21141 case NM_MULQ_S_PH:
21142 check_dsp_r2(ctx);
21143 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21144 gen_store_gpr(v1_t, ret);
21145 break;
21146 case NM_MULQ_RS_W:
21147 check_dsp_r2(ctx);
21148 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21149 gen_store_gpr(v1_t, ret);
21150 break;
21151 case NM_MULQ_S_W:
21152 check_dsp_r2(ctx);
21153 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21154 gen_store_gpr(v1_t, ret);
21155 break;
21156 case NM_APPEND:
21157 check_dsp_r2(ctx);
21158 gen_load_gpr(t0, rs);
21159 if (rd != 0) {
21160 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21162 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21163 break;
21164 case NM_MODSUB:
21165 check_dsp(ctx);
21166 gen_helper_modsub(v1_t, v1_t, v2_t);
21167 gen_store_gpr(v1_t, ret);
21168 break;
21169 case NM_SHRAV_R_W:
21170 check_dsp(ctx);
21171 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21172 gen_store_gpr(v1_t, ret);
21173 break;
21174 case NM_SHRLV_PH:
21175 check_dsp_r2(ctx);
21176 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21177 gen_store_gpr(v1_t, ret);
21178 break;
21179 case NM_SHRLV_QB:
21180 check_dsp(ctx);
21181 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21182 gen_store_gpr(v1_t, ret);
21183 break;
21184 case NM_SHLLV_QB:
21185 check_dsp(ctx);
21186 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21187 gen_store_gpr(v1_t, ret);
21188 break;
21189 case NM_SHLLV_S_W:
21190 check_dsp(ctx);
21191 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21192 gen_store_gpr(v1_t, ret);
21193 break;
21194 case NM_SHILO:
21195 check_dsp(ctx);
21197 TCGv tv0 = tcg_temp_new();
21198 TCGv tv1 = tcg_temp_new();
21199 int16_t imm = extract32(ctx->opcode, 16, 7);
21201 tcg_gen_movi_tl(tv0, rd >> 3);
21202 tcg_gen_movi_tl(tv1, imm);
21203 gen_helper_shilo(tv0, tv1, cpu_env);
21205 break;
21206 case NM_MULEQ_S_W_PHL:
21207 check_dsp(ctx);
21208 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21209 gen_store_gpr(v1_t, ret);
21210 break;
21211 case NM_MULEQ_S_W_PHR:
21212 check_dsp(ctx);
21213 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21214 gen_store_gpr(v1_t, ret);
21215 break;
21216 case NM_MUL_S_PH:
21217 check_dsp_r2(ctx);
21218 switch (extract32(ctx->opcode, 10, 1)) {
21219 case 0:
21220 /* MUL_PH */
21221 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21222 gen_store_gpr(v1_t, ret);
21223 break;
21224 case 1:
21225 /* MUL_S_PH */
21226 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21227 gen_store_gpr(v1_t, ret);
21228 break;
21230 break;
21231 case NM_PRECR_QB_PH:
21232 check_dsp_r2(ctx);
21233 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21234 gen_store_gpr(v1_t, ret);
21235 break;
21236 case NM_PRECRQ_QB_PH:
21237 check_dsp(ctx);
21238 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21239 gen_store_gpr(v1_t, ret);
21240 break;
21241 case NM_PRECRQ_PH_W:
21242 check_dsp(ctx);
21243 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21244 gen_store_gpr(v1_t, ret);
21245 break;
21246 case NM_PRECRQ_RS_PH_W:
21247 check_dsp(ctx);
21248 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21249 gen_store_gpr(v1_t, ret);
21250 break;
21251 case NM_PRECRQU_S_QB_PH:
21252 check_dsp(ctx);
21253 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21254 gen_store_gpr(v1_t, ret);
21255 break;
21256 case NM_SHRA_R_W:
21257 check_dsp(ctx);
21258 tcg_gen_movi_tl(t0, rd);
21259 gen_helper_shra_r_w(v1_t, t0, v1_t);
21260 gen_store_gpr(v1_t, rt);
21261 break;
21262 case NM_SHRA_R_PH:
21263 check_dsp(ctx);
21264 tcg_gen_movi_tl(t0, rd >> 1);
21265 switch (extract32(ctx->opcode, 10, 1)) {
21266 case 0:
21267 /* SHRA_PH */
21268 gen_helper_shra_ph(v1_t, t0, v1_t);
21269 gen_store_gpr(v1_t, rt);
21270 break;
21271 case 1:
21272 /* SHRA_R_PH */
21273 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21274 gen_store_gpr(v1_t, rt);
21275 break;
21277 break;
21278 case NM_SHLL_S_PH:
21279 check_dsp(ctx);
21280 tcg_gen_movi_tl(t0, rd >> 1);
21281 switch (extract32(ctx->opcode, 10, 2)) {
21282 case 0:
21283 /* SHLL_PH */
21284 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21285 gen_store_gpr(v1_t, rt);
21286 break;
21287 case 2:
21288 /* SHLL_S_PH */
21289 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21290 gen_store_gpr(v1_t, rt);
21291 break;
21292 default:
21293 generate_exception_end(ctx, EXCP_RI);
21294 break;
21296 break;
21297 case NM_SHLL_S_W:
21298 check_dsp(ctx);
21299 tcg_gen_movi_tl(t0, rd);
21300 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21301 gen_store_gpr(v1_t, rt);
21302 break;
21303 case NM_REPL_PH:
21304 check_dsp(ctx);
21306 int16_t imm;
21307 imm = sextract32(ctx->opcode, 11, 11);
21308 imm = (int16_t)(imm << 6) >> 6;
21309 if (rt != 0) {
21310 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21313 break;
21314 default:
21315 generate_exception_end(ctx, EXCP_RI);
21316 break;
21320 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21322 uint16_t insn;
21323 uint32_t op;
21324 int rt, rs, rd;
21325 int offset;
21326 int imm;
21328 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21329 ctx->opcode = (ctx->opcode << 16) | insn;
21331 rt = extract32(ctx->opcode, 21, 5);
21332 rs = extract32(ctx->opcode, 16, 5);
21333 rd = extract32(ctx->opcode, 11, 5);
21335 op = extract32(ctx->opcode, 26, 6);
21336 switch (op) {
21337 case NM_P_ADDIU:
21338 if (rt == 0) {
21339 /* P.RI */
21340 switch (extract32(ctx->opcode, 19, 2)) {
21341 case NM_SIGRIE:
21342 default:
21343 generate_exception_end(ctx, EXCP_RI);
21344 break;
21345 case NM_P_SYSCALL:
21346 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21347 generate_exception_end(ctx, EXCP_SYSCALL);
21348 } else {
21349 generate_exception_end(ctx, EXCP_RI);
21351 break;
21352 case NM_BREAK:
21353 generate_exception_end(ctx, EXCP_BREAK);
21354 break;
21355 case NM_SDBBP:
21356 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21357 gen_helper_do_semihosting(cpu_env);
21358 } else {
21359 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21360 generate_exception_end(ctx, EXCP_RI);
21361 } else {
21362 generate_exception_end(ctx, EXCP_DBp);
21365 break;
21367 } else {
21368 /* NM_ADDIU */
21369 imm = extract32(ctx->opcode, 0, 16);
21370 if (rs != 0) {
21371 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21372 } else {
21373 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21375 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21377 break;
21378 case NM_ADDIUPC:
21379 if (rt != 0) {
21380 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21381 extract32(ctx->opcode, 1, 20) << 1;
21382 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21383 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21385 break;
21386 case NM_POOL32A:
21387 switch (ctx->opcode & 0x07) {
21388 case NM_POOL32A0:
21389 gen_pool32a0_nanomips_insn(env, ctx);
21390 break;
21391 case NM_POOL32A5:
21393 int32_t op1 = extract32(ctx->opcode, 3, 7);
21394 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21396 break;
21397 case NM_POOL32A7:
21398 switch (extract32(ctx->opcode, 3, 3)) {
21399 case NM_P_LSX:
21400 gen_p_lsx(ctx, rd, rs, rt);
21401 break;
21402 case NM_LSA:
21404 * In nanoMIPS, the shift field directly encodes the shift
21405 * amount, meaning that the supported shift values are in
21406 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21408 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21409 extract32(ctx->opcode, 9, 2) - 1);
21410 break;
21411 case NM_EXTW:
21412 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21413 break;
21414 case NM_POOL32AXF:
21415 gen_pool32axf_nanomips_insn(env, ctx);
21416 break;
21417 default:
21418 generate_exception_end(ctx, EXCP_RI);
21419 break;
21421 break;
21422 default:
21423 generate_exception_end(ctx, EXCP_RI);
21424 break;
21426 break;
21427 case NM_P_GP_W:
21428 switch (ctx->opcode & 0x03) {
21429 case NM_ADDIUGP_W:
21430 if (rt != 0) {
21431 offset = extract32(ctx->opcode, 0, 21);
21432 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21434 break;
21435 case NM_LWGP:
21436 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21437 break;
21438 case NM_SWGP:
21439 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21440 break;
21441 default:
21442 generate_exception_end(ctx, EXCP_RI);
21443 break;
21445 break;
21446 case NM_P48I:
21448 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21449 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21450 switch (extract32(ctx->opcode, 16, 5)) {
21451 case NM_LI48:
21452 check_nms(ctx);
21453 if (rt != 0) {
21454 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21456 break;
21457 case NM_ADDIU48:
21458 check_nms(ctx);
21459 if (rt != 0) {
21460 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21461 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21463 break;
21464 case NM_ADDIUGP48:
21465 check_nms(ctx);
21466 if (rt != 0) {
21467 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21469 break;
21470 case NM_ADDIUPC48:
21471 check_nms(ctx);
21472 if (rt != 0) {
21473 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21474 addr_off);
21476 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21478 break;
21479 case NM_LWPC48:
21480 check_nms(ctx);
21481 if (rt != 0) {
21482 TCGv t0;
21483 t0 = tcg_temp_new();
21485 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21486 addr_off);
21488 tcg_gen_movi_tl(t0, addr);
21489 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21490 tcg_temp_free(t0);
21492 break;
21493 case NM_SWPC48:
21494 check_nms(ctx);
21496 TCGv t0, t1;
21497 t0 = tcg_temp_new();
21498 t1 = tcg_temp_new();
21500 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21501 addr_off);
21503 tcg_gen_movi_tl(t0, addr);
21504 gen_load_gpr(t1, rt);
21506 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21508 tcg_temp_free(t0);
21509 tcg_temp_free(t1);
21511 break;
21512 default:
21513 generate_exception_end(ctx, EXCP_RI);
21514 break;
21516 return 6;
21518 case NM_P_U12:
21519 switch (extract32(ctx->opcode, 12, 4)) {
21520 case NM_ORI:
21521 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21522 break;
21523 case NM_XORI:
21524 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21525 break;
21526 case NM_ANDI:
21527 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21528 break;
21529 case NM_P_SR:
21530 switch (extract32(ctx->opcode, 20, 1)) {
21531 case NM_PP_SR:
21532 switch (ctx->opcode & 3) {
21533 case NM_SAVE:
21534 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21535 extract32(ctx->opcode, 2, 1),
21536 extract32(ctx->opcode, 3, 9) << 3);
21537 break;
21538 case NM_RESTORE:
21539 case NM_RESTORE_JRC:
21540 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21541 extract32(ctx->opcode, 2, 1),
21542 extract32(ctx->opcode, 3, 9) << 3);
21543 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21544 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21546 break;
21547 default:
21548 generate_exception_end(ctx, EXCP_RI);
21549 break;
21551 break;
21552 case NM_P_SR_F:
21553 generate_exception_end(ctx, EXCP_RI);
21554 break;
21556 break;
21557 case NM_SLTI:
21558 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21559 break;
21560 case NM_SLTIU:
21561 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21562 break;
21563 case NM_SEQI:
21565 TCGv t0 = tcg_temp_new();
21567 imm = extract32(ctx->opcode, 0, 12);
21568 gen_load_gpr(t0, rs);
21569 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21570 gen_store_gpr(t0, rt);
21572 tcg_temp_free(t0);
21574 break;
21575 case NM_ADDIUNEG:
21576 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21577 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21578 break;
21579 case NM_P_SHIFT:
21581 int shift = extract32(ctx->opcode, 0, 5);
21582 switch (extract32(ctx->opcode, 5, 4)) {
21583 case NM_P_SLL:
21584 if (rt == 0 && shift == 0) {
21585 /* NOP */
21586 } else if (rt == 0 && shift == 3) {
21587 /* EHB - treat as NOP */
21588 } else if (rt == 0 && shift == 5) {
21589 /* PAUSE - treat as NOP */
21590 } else if (rt == 0 && shift == 6) {
21591 /* SYNC */
21592 gen_sync(extract32(ctx->opcode, 16, 5));
21593 } else {
21594 /* SLL */
21595 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21596 extract32(ctx->opcode, 0, 5));
21598 break;
21599 case NM_SRL:
21600 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21601 extract32(ctx->opcode, 0, 5));
21602 break;
21603 case NM_SRA:
21604 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21605 extract32(ctx->opcode, 0, 5));
21606 break;
21607 case NM_ROTR:
21608 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21609 extract32(ctx->opcode, 0, 5));
21610 break;
21613 break;
21614 case NM_P_ROTX:
21615 check_nms(ctx);
21616 if (rt != 0) {
21617 TCGv t0 = tcg_temp_new();
21618 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21619 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21620 << 1);
21621 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21623 gen_load_gpr(t0, rs);
21624 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21625 tcg_temp_free(t0);
21627 tcg_temp_free_i32(shift);
21628 tcg_temp_free_i32(shiftx);
21629 tcg_temp_free_i32(stripe);
21631 break;
21632 case NM_P_INS:
21633 switch (((ctx->opcode >> 10) & 2) |
21634 (extract32(ctx->opcode, 5, 1))) {
21635 case NM_INS:
21636 check_nms(ctx);
21637 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21638 extract32(ctx->opcode, 6, 5));
21639 break;
21640 default:
21641 generate_exception_end(ctx, EXCP_RI);
21642 break;
21644 break;
21645 case NM_P_EXT:
21646 switch (((ctx->opcode >> 10) & 2) |
21647 (extract32(ctx->opcode, 5, 1))) {
21648 case NM_EXT:
21649 check_nms(ctx);
21650 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21651 extract32(ctx->opcode, 6, 5));
21652 break;
21653 default:
21654 generate_exception_end(ctx, EXCP_RI);
21655 break;
21657 break;
21658 default:
21659 generate_exception_end(ctx, EXCP_RI);
21660 break;
21662 break;
21663 case NM_POOL32F:
21664 gen_pool32f_nanomips_insn(ctx);
21665 break;
21666 case NM_POOL32S:
21667 break;
21668 case NM_P_LUI:
21669 switch (extract32(ctx->opcode, 1, 1)) {
21670 case NM_LUI:
21671 if (rt != 0) {
21672 tcg_gen_movi_tl(cpu_gpr[rt],
21673 sextract32(ctx->opcode, 0, 1) << 31 |
21674 extract32(ctx->opcode, 2, 10) << 21 |
21675 extract32(ctx->opcode, 12, 9) << 12);
21677 break;
21678 case NM_ALUIPC:
21679 if (rt != 0) {
21680 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21681 extract32(ctx->opcode, 2, 10) << 21 |
21682 extract32(ctx->opcode, 12, 9) << 12;
21683 target_long addr;
21684 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21685 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21687 break;
21689 break;
21690 case NM_P_GP_BH:
21692 uint32_t u = extract32(ctx->opcode, 0, 18);
21694 switch (extract32(ctx->opcode, 18, 3)) {
21695 case NM_LBGP:
21696 gen_ld(ctx, OPC_LB, rt, 28, u);
21697 break;
21698 case NM_SBGP:
21699 gen_st(ctx, OPC_SB, rt, 28, u);
21700 break;
21701 case NM_LBUGP:
21702 gen_ld(ctx, OPC_LBU, rt, 28, u);
21703 break;
21704 case NM_ADDIUGP_B:
21705 if (rt != 0) {
21706 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21708 break;
21709 case NM_P_GP_LH:
21710 u &= ~1;
21711 switch (ctx->opcode & 1) {
21712 case NM_LHGP:
21713 gen_ld(ctx, OPC_LH, rt, 28, u);
21714 break;
21715 case NM_LHUGP:
21716 gen_ld(ctx, OPC_LHU, rt, 28, u);
21717 break;
21719 break;
21720 case NM_P_GP_SH:
21721 u &= ~1;
21722 switch (ctx->opcode & 1) {
21723 case NM_SHGP:
21724 gen_st(ctx, OPC_SH, rt, 28, u);
21725 break;
21726 default:
21727 generate_exception_end(ctx, EXCP_RI);
21728 break;
21730 break;
21731 case NM_P_GP_CP1:
21732 u &= ~0x3;
21733 switch (ctx->opcode & 0x3) {
21734 case NM_LWC1GP:
21735 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21736 break;
21737 case NM_LDC1GP:
21738 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21739 break;
21740 case NM_SWC1GP:
21741 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21742 break;
21743 case NM_SDC1GP:
21744 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21745 break;
21747 break;
21748 default:
21749 generate_exception_end(ctx, EXCP_RI);
21750 break;
21753 break;
21754 case NM_P_LS_U12:
21756 uint32_t u = extract32(ctx->opcode, 0, 12);
21758 switch (extract32(ctx->opcode, 12, 4)) {
21759 case NM_P_PREFU12:
21760 if (rt == 31) {
21761 /* SYNCI */
21763 * Break the TB to be able to sync copied instructions
21764 * immediately.
21766 ctx->base.is_jmp = DISAS_STOP;
21767 } else {
21768 /* PREF */
21769 /* Treat as NOP. */
21771 break;
21772 case NM_LB:
21773 gen_ld(ctx, OPC_LB, rt, rs, u);
21774 break;
21775 case NM_LH:
21776 gen_ld(ctx, OPC_LH, rt, rs, u);
21777 break;
21778 case NM_LW:
21779 gen_ld(ctx, OPC_LW, rt, rs, u);
21780 break;
21781 case NM_LBU:
21782 gen_ld(ctx, OPC_LBU, rt, rs, u);
21783 break;
21784 case NM_LHU:
21785 gen_ld(ctx, OPC_LHU, rt, rs, u);
21786 break;
21787 case NM_SB:
21788 gen_st(ctx, OPC_SB, rt, rs, u);
21789 break;
21790 case NM_SH:
21791 gen_st(ctx, OPC_SH, rt, rs, u);
21792 break;
21793 case NM_SW:
21794 gen_st(ctx, OPC_SW, rt, rs, u);
21795 break;
21796 case NM_LWC1:
21797 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21798 break;
21799 case NM_LDC1:
21800 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21801 break;
21802 case NM_SWC1:
21803 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21804 break;
21805 case NM_SDC1:
21806 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21807 break;
21808 default:
21809 generate_exception_end(ctx, EXCP_RI);
21810 break;
21813 break;
21814 case NM_P_LS_S9:
21816 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21817 extract32(ctx->opcode, 0, 8);
21819 switch (extract32(ctx->opcode, 8, 3)) {
21820 case NM_P_LS_S0:
21821 switch (extract32(ctx->opcode, 11, 4)) {
21822 case NM_LBS9:
21823 gen_ld(ctx, OPC_LB, rt, rs, s);
21824 break;
21825 case NM_LHS9:
21826 gen_ld(ctx, OPC_LH, rt, rs, s);
21827 break;
21828 case NM_LWS9:
21829 gen_ld(ctx, OPC_LW, rt, rs, s);
21830 break;
21831 case NM_LBUS9:
21832 gen_ld(ctx, OPC_LBU, rt, rs, s);
21833 break;
21834 case NM_LHUS9:
21835 gen_ld(ctx, OPC_LHU, rt, rs, s);
21836 break;
21837 case NM_SBS9:
21838 gen_st(ctx, OPC_SB, rt, rs, s);
21839 break;
21840 case NM_SHS9:
21841 gen_st(ctx, OPC_SH, rt, rs, s);
21842 break;
21843 case NM_SWS9:
21844 gen_st(ctx, OPC_SW, rt, rs, s);
21845 break;
21846 case NM_LWC1S9:
21847 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21848 break;
21849 case NM_LDC1S9:
21850 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21851 break;
21852 case NM_SWC1S9:
21853 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21854 break;
21855 case NM_SDC1S9:
21856 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21857 break;
21858 case NM_P_PREFS9:
21859 if (rt == 31) {
21860 /* SYNCI */
21862 * Break the TB to be able to sync copied instructions
21863 * immediately.
21865 ctx->base.is_jmp = DISAS_STOP;
21866 } else {
21867 /* PREF */
21868 /* Treat as NOP. */
21870 break;
21871 default:
21872 generate_exception_end(ctx, EXCP_RI);
21873 break;
21875 break;
21876 case NM_P_LS_S1:
21877 switch (extract32(ctx->opcode, 11, 4)) {
21878 case NM_UALH:
21879 case NM_UASH:
21880 check_nms(ctx);
21882 TCGv t0 = tcg_temp_new();
21883 TCGv t1 = tcg_temp_new();
21885 gen_base_offset_addr(ctx, t0, rs, s);
21887 switch (extract32(ctx->opcode, 11, 4)) {
21888 case NM_UALH:
21889 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21890 MO_UNALN);
21891 gen_store_gpr(t0, rt);
21892 break;
21893 case NM_UASH:
21894 gen_load_gpr(t1, rt);
21895 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21896 MO_UNALN);
21897 break;
21899 tcg_temp_free(t0);
21900 tcg_temp_free(t1);
21902 break;
21903 case NM_P_LL:
21904 switch (ctx->opcode & 0x03) {
21905 case NM_LL:
21906 gen_ld(ctx, OPC_LL, rt, rs, s);
21907 break;
21908 case NM_LLWP:
21909 check_xnp(ctx);
21910 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21911 break;
21913 break;
21914 case NM_P_SC:
21915 switch (ctx->opcode & 0x03) {
21916 case NM_SC:
21917 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21918 break;
21919 case NM_SCWP:
21920 check_xnp(ctx);
21921 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21922 false);
21923 break;
21925 break;
21926 case NM_CACHE:
21927 check_cp0_enabled(ctx);
21928 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21929 gen_cache_operation(ctx, rt, rs, s);
21931 break;
21933 break;
21934 case NM_P_LS_E0:
21935 switch (extract32(ctx->opcode, 11, 4)) {
21936 case NM_LBE:
21937 check_eva(ctx);
21938 check_cp0_enabled(ctx);
21939 gen_ld(ctx, OPC_LBE, rt, rs, s);
21940 break;
21941 case NM_SBE:
21942 check_eva(ctx);
21943 check_cp0_enabled(ctx);
21944 gen_st(ctx, OPC_SBE, rt, rs, s);
21945 break;
21946 case NM_LBUE:
21947 check_eva(ctx);
21948 check_cp0_enabled(ctx);
21949 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21950 break;
21951 case NM_P_PREFE:
21952 if (rt == 31) {
21953 /* case NM_SYNCIE */
21954 check_eva(ctx);
21955 check_cp0_enabled(ctx);
21957 * Break the TB to be able to sync copied instructions
21958 * immediately.
21960 ctx->base.is_jmp = DISAS_STOP;
21961 } else {
21962 /* case NM_PREFE */
21963 check_eva(ctx);
21964 check_cp0_enabled(ctx);
21965 /* Treat as NOP. */
21967 break;
21968 case NM_LHE:
21969 check_eva(ctx);
21970 check_cp0_enabled(ctx);
21971 gen_ld(ctx, OPC_LHE, rt, rs, s);
21972 break;
21973 case NM_SHE:
21974 check_eva(ctx);
21975 check_cp0_enabled(ctx);
21976 gen_st(ctx, OPC_SHE, rt, rs, s);
21977 break;
21978 case NM_LHUE:
21979 check_eva(ctx);
21980 check_cp0_enabled(ctx);
21981 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21982 break;
21983 case NM_CACHEE:
21984 check_nms_dl_il_sl_tl_l2c(ctx);
21985 gen_cache_operation(ctx, rt, rs, s);
21986 break;
21987 case NM_LWE:
21988 check_eva(ctx);
21989 check_cp0_enabled(ctx);
21990 gen_ld(ctx, OPC_LWE, rt, rs, s);
21991 break;
21992 case NM_SWE:
21993 check_eva(ctx);
21994 check_cp0_enabled(ctx);
21995 gen_st(ctx, OPC_SWE, rt, rs, s);
21996 break;
21997 case NM_P_LLE:
21998 switch (extract32(ctx->opcode, 2, 2)) {
21999 case NM_LLE:
22000 check_xnp(ctx);
22001 check_eva(ctx);
22002 check_cp0_enabled(ctx);
22003 gen_ld(ctx, OPC_LLE, rt, rs, s);
22004 break;
22005 case NM_LLWPE:
22006 check_xnp(ctx);
22007 check_eva(ctx);
22008 check_cp0_enabled(ctx);
22009 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22010 break;
22011 default:
22012 generate_exception_end(ctx, EXCP_RI);
22013 break;
22015 break;
22016 case NM_P_SCE:
22017 switch (extract32(ctx->opcode, 2, 2)) {
22018 case NM_SCE:
22019 check_xnp(ctx);
22020 check_eva(ctx);
22021 check_cp0_enabled(ctx);
22022 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22023 break;
22024 case NM_SCWPE:
22025 check_xnp(ctx);
22026 check_eva(ctx);
22027 check_cp0_enabled(ctx);
22028 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22029 true);
22030 break;
22031 default:
22032 generate_exception_end(ctx, EXCP_RI);
22033 break;
22035 break;
22037 break;
22038 case NM_P_LS_WM:
22039 case NM_P_LS_UAWM:
22040 check_nms(ctx);
22042 int count = extract32(ctx->opcode, 12, 3);
22043 int counter = 0;
22045 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22046 extract32(ctx->opcode, 0, 8);
22047 TCGv va = tcg_temp_new();
22048 TCGv t1 = tcg_temp_new();
22049 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22050 NM_P_LS_UAWM ? MO_UNALN : 0;
22052 count = (count == 0) ? 8 : count;
22053 while (counter != count) {
22054 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22055 int this_offset = offset + (counter << 2);
22057 gen_base_offset_addr(ctx, va, rs, this_offset);
22059 switch (extract32(ctx->opcode, 11, 1)) {
22060 case NM_LWM:
22061 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22062 memop | MO_TESL);
22063 gen_store_gpr(t1, this_rt);
22064 if ((this_rt == rs) &&
22065 (counter != (count - 1))) {
22066 /* UNPREDICTABLE */
22068 break;
22069 case NM_SWM:
22070 this_rt = (rt == 0) ? 0 : this_rt;
22071 gen_load_gpr(t1, this_rt);
22072 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22073 memop | MO_TEUL);
22074 break;
22076 counter++;
22078 tcg_temp_free(va);
22079 tcg_temp_free(t1);
22081 break;
22082 default:
22083 generate_exception_end(ctx, EXCP_RI);
22084 break;
22087 break;
22088 case NM_MOVE_BALC:
22089 check_nms(ctx);
22091 TCGv t0 = tcg_temp_new();
22092 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22093 extract32(ctx->opcode, 1, 20) << 1;
22094 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22095 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22096 extract32(ctx->opcode, 21, 3));
22097 gen_load_gpr(t0, rt);
22098 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22099 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22100 tcg_temp_free(t0);
22102 break;
22103 case NM_P_BAL:
22105 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22106 extract32(ctx->opcode, 1, 24) << 1;
22108 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22109 /* BC */
22110 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22111 } else {
22112 /* BALC */
22113 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22116 break;
22117 case NM_P_J:
22118 switch (extract32(ctx->opcode, 12, 4)) {
22119 case NM_JALRC:
22120 case NM_JALRC_HB:
22121 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22122 break;
22123 case NM_P_BALRSC:
22124 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22125 break;
22126 default:
22127 generate_exception_end(ctx, EXCP_RI);
22128 break;
22130 break;
22131 case NM_P_BR1:
22133 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22134 extract32(ctx->opcode, 1, 13) << 1;
22135 switch (extract32(ctx->opcode, 14, 2)) {
22136 case NM_BEQC:
22137 check_nms(ctx);
22138 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22139 break;
22140 case NM_P_BR3A:
22141 s = sextract32(ctx->opcode, 0, 1) << 14 |
22142 extract32(ctx->opcode, 1, 13) << 1;
22143 check_cp1_enabled(ctx);
22144 switch (extract32(ctx->opcode, 16, 5)) {
22145 case NM_BC1EQZC:
22146 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22147 break;
22148 case NM_BC1NEZC:
22149 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22150 break;
22151 case NM_BPOSGE32C:
22152 check_dsp_r3(ctx);
22154 int32_t imm = extract32(ctx->opcode, 1, 13) |
22155 extract32(ctx->opcode, 0, 1) << 13;
22157 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22158 imm);
22160 break;
22161 default:
22162 generate_exception_end(ctx, EXCP_RI);
22163 break;
22165 break;
22166 case NM_BGEC:
22167 if (rs == rt) {
22168 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22169 } else {
22170 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22172 break;
22173 case NM_BGEUC:
22174 if (rs == rt || rt == 0) {
22175 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22176 } else if (rs == 0) {
22177 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22178 } else {
22179 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22181 break;
22184 break;
22185 case NM_P_BR2:
22187 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22188 extract32(ctx->opcode, 1, 13) << 1;
22189 switch (extract32(ctx->opcode, 14, 2)) {
22190 case NM_BNEC:
22191 check_nms(ctx);
22192 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22193 break;
22194 case NM_BLTC:
22195 if (rs != 0 && rt != 0 && rs == rt) {
22196 /* NOP */
22197 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22198 } else {
22199 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22201 break;
22202 case NM_BLTUC:
22203 if (rs == 0 || rs == rt) {
22204 /* NOP */
22205 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22206 } else {
22207 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22209 break;
22210 default:
22211 generate_exception_end(ctx, EXCP_RI);
22212 break;
22215 break;
22216 case NM_P_BRI:
22218 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22219 extract32(ctx->opcode, 1, 10) << 1;
22220 uint32_t u = extract32(ctx->opcode, 11, 7);
22222 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22223 rt, u, s);
22225 break;
22226 default:
22227 generate_exception_end(ctx, EXCP_RI);
22228 break;
22230 return 4;
22233 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22235 uint32_t op;
22236 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22237 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22238 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22239 int offset;
22240 int imm;
22242 /* make sure instructions are on a halfword boundary */
22243 if (ctx->base.pc_next & 0x1) {
22244 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22245 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22246 tcg_temp_free(tmp);
22247 generate_exception_end(ctx, EXCP_AdEL);
22248 return 2;
22251 op = extract32(ctx->opcode, 10, 6);
22252 switch (op) {
22253 case NM_P16_MV:
22254 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22255 if (rt != 0) {
22256 /* MOVE */
22257 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22258 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22259 } else {
22260 /* P16.RI */
22261 switch (extract32(ctx->opcode, 3, 2)) {
22262 case NM_P16_SYSCALL:
22263 if (extract32(ctx->opcode, 2, 1) == 0) {
22264 generate_exception_end(ctx, EXCP_SYSCALL);
22265 } else {
22266 generate_exception_end(ctx, EXCP_RI);
22268 break;
22269 case NM_BREAK16:
22270 generate_exception_end(ctx, EXCP_BREAK);
22271 break;
22272 case NM_SDBBP16:
22273 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22274 gen_helper_do_semihosting(cpu_env);
22275 } else {
22276 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22277 generate_exception_end(ctx, EXCP_RI);
22278 } else {
22279 generate_exception_end(ctx, EXCP_DBp);
22282 break;
22283 default:
22284 generate_exception_end(ctx, EXCP_RI);
22285 break;
22288 break;
22289 case NM_P16_SHIFT:
22291 int shift = extract32(ctx->opcode, 0, 3);
22292 uint32_t opc = 0;
22293 shift = (shift == 0) ? 8 : shift;
22295 switch (extract32(ctx->opcode, 3, 1)) {
22296 case NM_SLL16:
22297 opc = OPC_SLL;
22298 break;
22299 case NM_SRL16:
22300 opc = OPC_SRL;
22301 break;
22303 gen_shift_imm(ctx, opc, rt, rs, shift);
22305 break;
22306 case NM_P16C:
22307 switch (ctx->opcode & 1) {
22308 case NM_POOL16C_0:
22309 gen_pool16c_nanomips_insn(ctx);
22310 break;
22311 case NM_LWXS16:
22312 gen_ldxs(ctx, rt, rs, rd);
22313 break;
22315 break;
22316 case NM_P16_A1:
22317 switch (extract32(ctx->opcode, 6, 1)) {
22318 case NM_ADDIUR1SP:
22319 imm = extract32(ctx->opcode, 0, 6) << 2;
22320 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22321 break;
22322 default:
22323 generate_exception_end(ctx, EXCP_RI);
22324 break;
22326 break;
22327 case NM_P16_A2:
22328 switch (extract32(ctx->opcode, 3, 1)) {
22329 case NM_ADDIUR2:
22330 imm = extract32(ctx->opcode, 0, 3) << 2;
22331 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22332 break;
22333 case NM_P_ADDIURS5:
22334 rt = extract32(ctx->opcode, 5, 5);
22335 if (rt != 0) {
22336 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22337 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22338 (extract32(ctx->opcode, 0, 3));
22339 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22341 break;
22343 break;
22344 case NM_P16_ADDU:
22345 switch (ctx->opcode & 0x1) {
22346 case NM_ADDU16:
22347 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22348 break;
22349 case NM_SUBU16:
22350 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22351 break;
22353 break;
22354 case NM_P16_4X4:
22355 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22356 extract32(ctx->opcode, 5, 3);
22357 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22358 extract32(ctx->opcode, 0, 3);
22359 rt = decode_gpr_gpr4(rt);
22360 rs = decode_gpr_gpr4(rs);
22361 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22362 (extract32(ctx->opcode, 3, 1))) {
22363 case NM_ADDU4X4:
22364 check_nms(ctx);
22365 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22366 break;
22367 case NM_MUL4X4:
22368 check_nms(ctx);
22369 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22370 break;
22371 default:
22372 generate_exception_end(ctx, EXCP_RI);
22373 break;
22375 break;
22376 case NM_LI16:
22378 int imm = extract32(ctx->opcode, 0, 7);
22379 imm = (imm == 0x7f ? -1 : imm);
22380 if (rt != 0) {
22381 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22384 break;
22385 case NM_ANDI16:
22387 uint32_t u = extract32(ctx->opcode, 0, 4);
22388 u = (u == 12) ? 0xff :
22389 (u == 13) ? 0xffff : u;
22390 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22392 break;
22393 case NM_P16_LB:
22394 offset = extract32(ctx->opcode, 0, 2);
22395 switch (extract32(ctx->opcode, 2, 2)) {
22396 case NM_LB16:
22397 gen_ld(ctx, OPC_LB, rt, rs, offset);
22398 break;
22399 case NM_SB16:
22400 rt = decode_gpr_gpr3_src_store(
22401 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22402 gen_st(ctx, OPC_SB, rt, rs, offset);
22403 break;
22404 case NM_LBU16:
22405 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22406 break;
22407 default:
22408 generate_exception_end(ctx, EXCP_RI);
22409 break;
22411 break;
22412 case NM_P16_LH:
22413 offset = extract32(ctx->opcode, 1, 2) << 1;
22414 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22415 case NM_LH16:
22416 gen_ld(ctx, OPC_LH, rt, rs, offset);
22417 break;
22418 case NM_SH16:
22419 rt = decode_gpr_gpr3_src_store(
22420 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22421 gen_st(ctx, OPC_SH, rt, rs, offset);
22422 break;
22423 case NM_LHU16:
22424 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22425 break;
22426 default:
22427 generate_exception_end(ctx, EXCP_RI);
22428 break;
22430 break;
22431 case NM_LW16:
22432 offset = extract32(ctx->opcode, 0, 4) << 2;
22433 gen_ld(ctx, OPC_LW, rt, rs, offset);
22434 break;
22435 case NM_LWSP16:
22436 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22437 offset = extract32(ctx->opcode, 0, 5) << 2;
22438 gen_ld(ctx, OPC_LW, rt, 29, offset);
22439 break;
22440 case NM_LW4X4:
22441 check_nms(ctx);
22442 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22443 extract32(ctx->opcode, 5, 3);
22444 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22445 extract32(ctx->opcode, 0, 3);
22446 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22447 (extract32(ctx->opcode, 8, 1) << 2);
22448 rt = decode_gpr_gpr4(rt);
22449 rs = decode_gpr_gpr4(rs);
22450 gen_ld(ctx, OPC_LW, rt, rs, offset);
22451 break;
22452 case NM_SW4X4:
22453 check_nms(ctx);
22454 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22455 extract32(ctx->opcode, 5, 3);
22456 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22457 extract32(ctx->opcode, 0, 3);
22458 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22459 (extract32(ctx->opcode, 8, 1) << 2);
22460 rt = decode_gpr_gpr4_zero(rt);
22461 rs = decode_gpr_gpr4(rs);
22462 gen_st(ctx, OPC_SW, rt, rs, offset);
22463 break;
22464 case NM_LWGP16:
22465 offset = extract32(ctx->opcode, 0, 7) << 2;
22466 gen_ld(ctx, OPC_LW, rt, 28, offset);
22467 break;
22468 case NM_SWSP16:
22469 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22470 offset = extract32(ctx->opcode, 0, 5) << 2;
22471 gen_st(ctx, OPC_SW, rt, 29, offset);
22472 break;
22473 case NM_SW16:
22474 rt = decode_gpr_gpr3_src_store(
22475 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22476 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22477 offset = extract32(ctx->opcode, 0, 4) << 2;
22478 gen_st(ctx, OPC_SW, rt, rs, offset);
22479 break;
22480 case NM_SWGP16:
22481 rt = decode_gpr_gpr3_src_store(
22482 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22483 offset = extract32(ctx->opcode, 0, 7) << 2;
22484 gen_st(ctx, OPC_SW, rt, 28, offset);
22485 break;
22486 case NM_BC16:
22487 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22488 (sextract32(ctx->opcode, 0, 1) << 10) |
22489 (extract32(ctx->opcode, 1, 9) << 1));
22490 break;
22491 case NM_BALC16:
22492 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22493 (sextract32(ctx->opcode, 0, 1) << 10) |
22494 (extract32(ctx->opcode, 1, 9) << 1));
22495 break;
22496 case NM_BEQZC16:
22497 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22498 (sextract32(ctx->opcode, 0, 1) << 7) |
22499 (extract32(ctx->opcode, 1, 6) << 1));
22500 break;
22501 case NM_BNEZC16:
22502 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22503 (sextract32(ctx->opcode, 0, 1) << 7) |
22504 (extract32(ctx->opcode, 1, 6) << 1));
22505 break;
22506 case NM_P16_BR:
22507 switch (ctx->opcode & 0xf) {
22508 case 0:
22509 /* P16.JRC */
22510 switch (extract32(ctx->opcode, 4, 1)) {
22511 case NM_JRC:
22512 gen_compute_branch_nm(ctx, OPC_JR, 2,
22513 extract32(ctx->opcode, 5, 5), 0, 0);
22514 break;
22515 case NM_JALRC16:
22516 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22517 extract32(ctx->opcode, 5, 5), 31, 0);
22518 break;
22520 break;
22521 default:
22523 /* P16.BRI */
22524 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22525 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22526 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22527 extract32(ctx->opcode, 0, 4) << 1);
22529 break;
22531 break;
22532 case NM_P16_SR:
22534 int count = extract32(ctx->opcode, 0, 4);
22535 int u = extract32(ctx->opcode, 4, 4) << 4;
22537 rt = 30 + extract32(ctx->opcode, 9, 1);
22538 switch (extract32(ctx->opcode, 8, 1)) {
22539 case NM_SAVE16:
22540 gen_save(ctx, rt, count, 0, u);
22541 break;
22542 case NM_RESTORE_JRC16:
22543 gen_restore(ctx, rt, count, 0, u);
22544 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22545 break;
22548 break;
22549 case NM_MOVEP:
22550 case NM_MOVEPREV:
22551 check_nms(ctx);
22553 static const int gpr2reg1[] = {4, 5, 6, 7};
22554 static const int gpr2reg2[] = {5, 6, 7, 8};
22555 int re;
22556 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22557 extract32(ctx->opcode, 8, 1);
22558 int r1 = gpr2reg1[rd2];
22559 int r2 = gpr2reg2[rd2];
22560 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22561 extract32(ctx->opcode, 0, 3);
22562 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22563 extract32(ctx->opcode, 5, 3);
22564 TCGv t0 = tcg_temp_new();
22565 TCGv t1 = tcg_temp_new();
22566 if (op == NM_MOVEP) {
22567 rd = r1;
22568 re = r2;
22569 rs = decode_gpr_gpr4_zero(r3);
22570 rt = decode_gpr_gpr4_zero(r4);
22571 } else {
22572 rd = decode_gpr_gpr4(r3);
22573 re = decode_gpr_gpr4(r4);
22574 rs = r1;
22575 rt = r2;
22577 gen_load_gpr(t0, rs);
22578 gen_load_gpr(t1, rt);
22579 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22580 tcg_gen_mov_tl(cpu_gpr[re], t1);
22581 tcg_temp_free(t0);
22582 tcg_temp_free(t1);
22584 break;
22585 default:
22586 return decode_nanomips_32_48_opc(env, ctx);
22589 return 2;
22593 /* SmartMIPS extension to MIPS32 */
22595 #if defined(TARGET_MIPS64)
22597 /* MDMX extension to MIPS64 */
22599 #endif
22601 /* MIPSDSP functions. */
22602 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22603 int rd, int base, int offset)
22605 TCGv t0;
22607 check_dsp(ctx);
22608 t0 = tcg_temp_new();
22610 if (base == 0) {
22611 gen_load_gpr(t0, offset);
22612 } else if (offset == 0) {
22613 gen_load_gpr(t0, base);
22614 } else {
22615 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22618 switch (opc) {
22619 case OPC_LBUX:
22620 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22621 gen_store_gpr(t0, rd);
22622 break;
22623 case OPC_LHX:
22624 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22625 gen_store_gpr(t0, rd);
22626 break;
22627 case OPC_LWX:
22628 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22629 gen_store_gpr(t0, rd);
22630 break;
22631 #if defined(TARGET_MIPS64)
22632 case OPC_LDX:
22633 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22634 gen_store_gpr(t0, rd);
22635 break;
22636 #endif
22638 tcg_temp_free(t0);
22641 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22642 int ret, int v1, int v2)
22644 TCGv v1_t;
22645 TCGv v2_t;
22647 if (ret == 0) {
22648 /* Treat as NOP. */
22649 return;
22652 v1_t = tcg_temp_new();
22653 v2_t = tcg_temp_new();
22655 gen_load_gpr(v1_t, v1);
22656 gen_load_gpr(v2_t, v2);
22658 switch (op1) {
22659 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22660 case OPC_MULT_G_2E:
22661 check_dsp_r2(ctx);
22662 switch (op2) {
22663 case OPC_ADDUH_QB:
22664 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22665 break;
22666 case OPC_ADDUH_R_QB:
22667 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22668 break;
22669 case OPC_ADDQH_PH:
22670 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22671 break;
22672 case OPC_ADDQH_R_PH:
22673 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22674 break;
22675 case OPC_ADDQH_W:
22676 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22677 break;
22678 case OPC_ADDQH_R_W:
22679 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22680 break;
22681 case OPC_SUBUH_QB:
22682 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22683 break;
22684 case OPC_SUBUH_R_QB:
22685 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22686 break;
22687 case OPC_SUBQH_PH:
22688 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22689 break;
22690 case OPC_SUBQH_R_PH:
22691 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22692 break;
22693 case OPC_SUBQH_W:
22694 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22695 break;
22696 case OPC_SUBQH_R_W:
22697 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22698 break;
22700 break;
22701 case OPC_ABSQ_S_PH_DSP:
22702 switch (op2) {
22703 case OPC_ABSQ_S_QB:
22704 check_dsp_r2(ctx);
22705 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22706 break;
22707 case OPC_ABSQ_S_PH:
22708 check_dsp(ctx);
22709 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22710 break;
22711 case OPC_ABSQ_S_W:
22712 check_dsp(ctx);
22713 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22714 break;
22715 case OPC_PRECEQ_W_PHL:
22716 check_dsp(ctx);
22717 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22718 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22719 break;
22720 case OPC_PRECEQ_W_PHR:
22721 check_dsp(ctx);
22722 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22723 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22724 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22725 break;
22726 case OPC_PRECEQU_PH_QBL:
22727 check_dsp(ctx);
22728 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22729 break;
22730 case OPC_PRECEQU_PH_QBR:
22731 check_dsp(ctx);
22732 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22733 break;
22734 case OPC_PRECEQU_PH_QBLA:
22735 check_dsp(ctx);
22736 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22737 break;
22738 case OPC_PRECEQU_PH_QBRA:
22739 check_dsp(ctx);
22740 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22741 break;
22742 case OPC_PRECEU_PH_QBL:
22743 check_dsp(ctx);
22744 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22745 break;
22746 case OPC_PRECEU_PH_QBR:
22747 check_dsp(ctx);
22748 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22749 break;
22750 case OPC_PRECEU_PH_QBLA:
22751 check_dsp(ctx);
22752 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22753 break;
22754 case OPC_PRECEU_PH_QBRA:
22755 check_dsp(ctx);
22756 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22757 break;
22759 break;
22760 case OPC_ADDU_QB_DSP:
22761 switch (op2) {
22762 case OPC_ADDQ_PH:
22763 check_dsp(ctx);
22764 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_ADDQ_S_PH:
22767 check_dsp(ctx);
22768 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22769 break;
22770 case OPC_ADDQ_S_W:
22771 check_dsp(ctx);
22772 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_ADDU_QB:
22775 check_dsp(ctx);
22776 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22777 break;
22778 case OPC_ADDU_S_QB:
22779 check_dsp(ctx);
22780 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_ADDU_PH:
22783 check_dsp_r2(ctx);
22784 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_ADDU_S_PH:
22787 check_dsp_r2(ctx);
22788 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_SUBQ_PH:
22791 check_dsp(ctx);
22792 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_SUBQ_S_PH:
22795 check_dsp(ctx);
22796 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_SUBQ_S_W:
22799 check_dsp(ctx);
22800 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_SUBU_QB:
22803 check_dsp(ctx);
22804 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_SUBU_S_QB:
22807 check_dsp(ctx);
22808 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_SUBU_PH:
22811 check_dsp_r2(ctx);
22812 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22813 break;
22814 case OPC_SUBU_S_PH:
22815 check_dsp_r2(ctx);
22816 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22817 break;
22818 case OPC_ADDSC:
22819 check_dsp(ctx);
22820 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22821 break;
22822 case OPC_ADDWC:
22823 check_dsp(ctx);
22824 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22825 break;
22826 case OPC_MODSUB:
22827 check_dsp(ctx);
22828 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22829 break;
22830 case OPC_RADDU_W_QB:
22831 check_dsp(ctx);
22832 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22833 break;
22835 break;
22836 case OPC_CMPU_EQ_QB_DSP:
22837 switch (op2) {
22838 case OPC_PRECR_QB_PH:
22839 check_dsp_r2(ctx);
22840 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22841 break;
22842 case OPC_PRECRQ_QB_PH:
22843 check_dsp(ctx);
22844 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22845 break;
22846 case OPC_PRECR_SRA_PH_W:
22847 check_dsp_r2(ctx);
22849 TCGv_i32 sa_t = tcg_const_i32(v2);
22850 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22851 cpu_gpr[ret]);
22852 tcg_temp_free_i32(sa_t);
22853 break;
22855 case OPC_PRECR_SRA_R_PH_W:
22856 check_dsp_r2(ctx);
22858 TCGv_i32 sa_t = tcg_const_i32(v2);
22859 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22860 cpu_gpr[ret]);
22861 tcg_temp_free_i32(sa_t);
22862 break;
22864 case OPC_PRECRQ_PH_W:
22865 check_dsp(ctx);
22866 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22867 break;
22868 case OPC_PRECRQ_RS_PH_W:
22869 check_dsp(ctx);
22870 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22871 break;
22872 case OPC_PRECRQU_S_QB_PH:
22873 check_dsp(ctx);
22874 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22875 break;
22877 break;
22878 #ifdef TARGET_MIPS64
22879 case OPC_ABSQ_S_QH_DSP:
22880 switch (op2) {
22881 case OPC_PRECEQ_L_PWL:
22882 check_dsp(ctx);
22883 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22884 break;
22885 case OPC_PRECEQ_L_PWR:
22886 check_dsp(ctx);
22887 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22888 break;
22889 case OPC_PRECEQ_PW_QHL:
22890 check_dsp(ctx);
22891 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22892 break;
22893 case OPC_PRECEQ_PW_QHR:
22894 check_dsp(ctx);
22895 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22896 break;
22897 case OPC_PRECEQ_PW_QHLA:
22898 check_dsp(ctx);
22899 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22900 break;
22901 case OPC_PRECEQ_PW_QHRA:
22902 check_dsp(ctx);
22903 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22904 break;
22905 case OPC_PRECEQU_QH_OBL:
22906 check_dsp(ctx);
22907 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22908 break;
22909 case OPC_PRECEQU_QH_OBR:
22910 check_dsp(ctx);
22911 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22912 break;
22913 case OPC_PRECEQU_QH_OBLA:
22914 check_dsp(ctx);
22915 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22916 break;
22917 case OPC_PRECEQU_QH_OBRA:
22918 check_dsp(ctx);
22919 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22920 break;
22921 case OPC_PRECEU_QH_OBL:
22922 check_dsp(ctx);
22923 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22924 break;
22925 case OPC_PRECEU_QH_OBR:
22926 check_dsp(ctx);
22927 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22928 break;
22929 case OPC_PRECEU_QH_OBLA:
22930 check_dsp(ctx);
22931 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22932 break;
22933 case OPC_PRECEU_QH_OBRA:
22934 check_dsp(ctx);
22935 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22936 break;
22937 case OPC_ABSQ_S_OB:
22938 check_dsp_r2(ctx);
22939 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22940 break;
22941 case OPC_ABSQ_S_PW:
22942 check_dsp(ctx);
22943 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22944 break;
22945 case OPC_ABSQ_S_QH:
22946 check_dsp(ctx);
22947 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22948 break;
22950 break;
22951 case OPC_ADDU_OB_DSP:
22952 switch (op2) {
22953 case OPC_RADDU_L_OB:
22954 check_dsp(ctx);
22955 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22956 break;
22957 case OPC_SUBQ_PW:
22958 check_dsp(ctx);
22959 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22960 break;
22961 case OPC_SUBQ_S_PW:
22962 check_dsp(ctx);
22963 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22964 break;
22965 case OPC_SUBQ_QH:
22966 check_dsp(ctx);
22967 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22968 break;
22969 case OPC_SUBQ_S_QH:
22970 check_dsp(ctx);
22971 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22972 break;
22973 case OPC_SUBU_OB:
22974 check_dsp(ctx);
22975 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22976 break;
22977 case OPC_SUBU_S_OB:
22978 check_dsp(ctx);
22979 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22980 break;
22981 case OPC_SUBU_QH:
22982 check_dsp_r2(ctx);
22983 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22984 break;
22985 case OPC_SUBU_S_QH:
22986 check_dsp_r2(ctx);
22987 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22988 break;
22989 case OPC_SUBUH_OB:
22990 check_dsp_r2(ctx);
22991 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22992 break;
22993 case OPC_SUBUH_R_OB:
22994 check_dsp_r2(ctx);
22995 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22996 break;
22997 case OPC_ADDQ_PW:
22998 check_dsp(ctx);
22999 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23000 break;
23001 case OPC_ADDQ_S_PW:
23002 check_dsp(ctx);
23003 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23004 break;
23005 case OPC_ADDQ_QH:
23006 check_dsp(ctx);
23007 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23008 break;
23009 case OPC_ADDQ_S_QH:
23010 check_dsp(ctx);
23011 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23012 break;
23013 case OPC_ADDU_OB:
23014 check_dsp(ctx);
23015 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23016 break;
23017 case OPC_ADDU_S_OB:
23018 check_dsp(ctx);
23019 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23020 break;
23021 case OPC_ADDU_QH:
23022 check_dsp_r2(ctx);
23023 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23024 break;
23025 case OPC_ADDU_S_QH:
23026 check_dsp_r2(ctx);
23027 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23028 break;
23029 case OPC_ADDUH_OB:
23030 check_dsp_r2(ctx);
23031 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23032 break;
23033 case OPC_ADDUH_R_OB:
23034 check_dsp_r2(ctx);
23035 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23036 break;
23038 break;
23039 case OPC_CMPU_EQ_OB_DSP:
23040 switch (op2) {
23041 case OPC_PRECR_OB_QH:
23042 check_dsp_r2(ctx);
23043 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23044 break;
23045 case OPC_PRECR_SRA_QH_PW:
23046 check_dsp_r2(ctx);
23048 TCGv_i32 ret_t = tcg_const_i32(ret);
23049 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23050 tcg_temp_free_i32(ret_t);
23051 break;
23053 case OPC_PRECR_SRA_R_QH_PW:
23054 check_dsp_r2(ctx);
23056 TCGv_i32 sa_v = tcg_const_i32(ret);
23057 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23058 tcg_temp_free_i32(sa_v);
23059 break;
23061 case OPC_PRECRQ_OB_QH:
23062 check_dsp(ctx);
23063 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23064 break;
23065 case OPC_PRECRQ_PW_L:
23066 check_dsp(ctx);
23067 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23068 break;
23069 case OPC_PRECRQ_QH_PW:
23070 check_dsp(ctx);
23071 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23072 break;
23073 case OPC_PRECRQ_RS_QH_PW:
23074 check_dsp(ctx);
23075 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23076 break;
23077 case OPC_PRECRQU_S_OB_QH:
23078 check_dsp(ctx);
23079 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23080 break;
23082 break;
23083 #endif
23086 tcg_temp_free(v1_t);
23087 tcg_temp_free(v2_t);
23090 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23091 int ret, int v1, int v2)
23093 uint32_t op2;
23094 TCGv t0;
23095 TCGv v1_t;
23096 TCGv v2_t;
23098 if (ret == 0) {
23099 /* Treat as NOP. */
23100 return;
23103 t0 = tcg_temp_new();
23104 v1_t = tcg_temp_new();
23105 v2_t = tcg_temp_new();
23107 tcg_gen_movi_tl(t0, v1);
23108 gen_load_gpr(v1_t, v1);
23109 gen_load_gpr(v2_t, v2);
23111 switch (opc) {
23112 case OPC_SHLL_QB_DSP:
23114 op2 = MASK_SHLL_QB(ctx->opcode);
23115 switch (op2) {
23116 case OPC_SHLL_QB:
23117 check_dsp(ctx);
23118 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23119 break;
23120 case OPC_SHLLV_QB:
23121 check_dsp(ctx);
23122 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23123 break;
23124 case OPC_SHLL_PH:
23125 check_dsp(ctx);
23126 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23127 break;
23128 case OPC_SHLLV_PH:
23129 check_dsp(ctx);
23130 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23131 break;
23132 case OPC_SHLL_S_PH:
23133 check_dsp(ctx);
23134 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23135 break;
23136 case OPC_SHLLV_S_PH:
23137 check_dsp(ctx);
23138 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23139 break;
23140 case OPC_SHLL_S_W:
23141 check_dsp(ctx);
23142 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23143 break;
23144 case OPC_SHLLV_S_W:
23145 check_dsp(ctx);
23146 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23147 break;
23148 case OPC_SHRL_QB:
23149 check_dsp(ctx);
23150 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23151 break;
23152 case OPC_SHRLV_QB:
23153 check_dsp(ctx);
23154 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23155 break;
23156 case OPC_SHRL_PH:
23157 check_dsp_r2(ctx);
23158 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23159 break;
23160 case OPC_SHRLV_PH:
23161 check_dsp_r2(ctx);
23162 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23163 break;
23164 case OPC_SHRA_QB:
23165 check_dsp_r2(ctx);
23166 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23167 break;
23168 case OPC_SHRA_R_QB:
23169 check_dsp_r2(ctx);
23170 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23171 break;
23172 case OPC_SHRAV_QB:
23173 check_dsp_r2(ctx);
23174 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23175 break;
23176 case OPC_SHRAV_R_QB:
23177 check_dsp_r2(ctx);
23178 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23179 break;
23180 case OPC_SHRA_PH:
23181 check_dsp(ctx);
23182 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23183 break;
23184 case OPC_SHRA_R_PH:
23185 check_dsp(ctx);
23186 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23187 break;
23188 case OPC_SHRAV_PH:
23189 check_dsp(ctx);
23190 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23191 break;
23192 case OPC_SHRAV_R_PH:
23193 check_dsp(ctx);
23194 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23195 break;
23196 case OPC_SHRA_R_W:
23197 check_dsp(ctx);
23198 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23199 break;
23200 case OPC_SHRAV_R_W:
23201 check_dsp(ctx);
23202 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23203 break;
23204 default: /* Invalid */
23205 MIPS_INVAL("MASK SHLL.QB");
23206 generate_exception_end(ctx, EXCP_RI);
23207 break;
23209 break;
23211 #ifdef TARGET_MIPS64
23212 case OPC_SHLL_OB_DSP:
23213 op2 = MASK_SHLL_OB(ctx->opcode);
23214 switch (op2) {
23215 case OPC_SHLL_PW:
23216 check_dsp(ctx);
23217 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23218 break;
23219 case OPC_SHLLV_PW:
23220 check_dsp(ctx);
23221 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23222 break;
23223 case OPC_SHLL_S_PW:
23224 check_dsp(ctx);
23225 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23226 break;
23227 case OPC_SHLLV_S_PW:
23228 check_dsp(ctx);
23229 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23230 break;
23231 case OPC_SHLL_OB:
23232 check_dsp(ctx);
23233 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23234 break;
23235 case OPC_SHLLV_OB:
23236 check_dsp(ctx);
23237 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23238 break;
23239 case OPC_SHLL_QH:
23240 check_dsp(ctx);
23241 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23242 break;
23243 case OPC_SHLLV_QH:
23244 check_dsp(ctx);
23245 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23246 break;
23247 case OPC_SHLL_S_QH:
23248 check_dsp(ctx);
23249 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23250 break;
23251 case OPC_SHLLV_S_QH:
23252 check_dsp(ctx);
23253 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23254 break;
23255 case OPC_SHRA_OB:
23256 check_dsp_r2(ctx);
23257 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23258 break;
23259 case OPC_SHRAV_OB:
23260 check_dsp_r2(ctx);
23261 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23262 break;
23263 case OPC_SHRA_R_OB:
23264 check_dsp_r2(ctx);
23265 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23266 break;
23267 case OPC_SHRAV_R_OB:
23268 check_dsp_r2(ctx);
23269 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23270 break;
23271 case OPC_SHRA_PW:
23272 check_dsp(ctx);
23273 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23274 break;
23275 case OPC_SHRAV_PW:
23276 check_dsp(ctx);
23277 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23278 break;
23279 case OPC_SHRA_R_PW:
23280 check_dsp(ctx);
23281 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23282 break;
23283 case OPC_SHRAV_R_PW:
23284 check_dsp(ctx);
23285 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23286 break;
23287 case OPC_SHRA_QH:
23288 check_dsp(ctx);
23289 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23290 break;
23291 case OPC_SHRAV_QH:
23292 check_dsp(ctx);
23293 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23294 break;
23295 case OPC_SHRA_R_QH:
23296 check_dsp(ctx);
23297 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23298 break;
23299 case OPC_SHRAV_R_QH:
23300 check_dsp(ctx);
23301 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23302 break;
23303 case OPC_SHRL_OB:
23304 check_dsp(ctx);
23305 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23306 break;
23307 case OPC_SHRLV_OB:
23308 check_dsp(ctx);
23309 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23310 break;
23311 case OPC_SHRL_QH:
23312 check_dsp_r2(ctx);
23313 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23314 break;
23315 case OPC_SHRLV_QH:
23316 check_dsp_r2(ctx);
23317 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23318 break;
23319 default: /* Invalid */
23320 MIPS_INVAL("MASK SHLL.OB");
23321 generate_exception_end(ctx, EXCP_RI);
23322 break;
23324 break;
23325 #endif
23328 tcg_temp_free(t0);
23329 tcg_temp_free(v1_t);
23330 tcg_temp_free(v2_t);
23333 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23334 int ret, int v1, int v2, int check_ret)
23336 TCGv_i32 t0;
23337 TCGv v1_t;
23338 TCGv v2_t;
23340 if ((ret == 0) && (check_ret == 1)) {
23341 /* Treat as NOP. */
23342 return;
23345 t0 = tcg_temp_new_i32();
23346 v1_t = tcg_temp_new();
23347 v2_t = tcg_temp_new();
23349 tcg_gen_movi_i32(t0, ret);
23350 gen_load_gpr(v1_t, v1);
23351 gen_load_gpr(v2_t, v2);
23353 switch (op1) {
23355 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23356 * the same mask and op1.
23358 case OPC_MULT_G_2E:
23359 check_dsp_r2(ctx);
23360 switch (op2) {
23361 case OPC_MUL_PH:
23362 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23363 break;
23364 case OPC_MUL_S_PH:
23365 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23366 break;
23367 case OPC_MULQ_S_W:
23368 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23369 break;
23370 case OPC_MULQ_RS_W:
23371 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23372 break;
23374 break;
23375 case OPC_DPA_W_PH_DSP:
23376 switch (op2) {
23377 case OPC_DPAU_H_QBL:
23378 check_dsp(ctx);
23379 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23380 break;
23381 case OPC_DPAU_H_QBR:
23382 check_dsp(ctx);
23383 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23384 break;
23385 case OPC_DPSU_H_QBL:
23386 check_dsp(ctx);
23387 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23388 break;
23389 case OPC_DPSU_H_QBR:
23390 check_dsp(ctx);
23391 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23392 break;
23393 case OPC_DPA_W_PH:
23394 check_dsp_r2(ctx);
23395 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23396 break;
23397 case OPC_DPAX_W_PH:
23398 check_dsp_r2(ctx);
23399 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23400 break;
23401 case OPC_DPAQ_S_W_PH:
23402 check_dsp(ctx);
23403 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23404 break;
23405 case OPC_DPAQX_S_W_PH:
23406 check_dsp_r2(ctx);
23407 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23408 break;
23409 case OPC_DPAQX_SA_W_PH:
23410 check_dsp_r2(ctx);
23411 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23412 break;
23413 case OPC_DPS_W_PH:
23414 check_dsp_r2(ctx);
23415 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23416 break;
23417 case OPC_DPSX_W_PH:
23418 check_dsp_r2(ctx);
23419 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23420 break;
23421 case OPC_DPSQ_S_W_PH:
23422 check_dsp(ctx);
23423 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23424 break;
23425 case OPC_DPSQX_S_W_PH:
23426 check_dsp_r2(ctx);
23427 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23428 break;
23429 case OPC_DPSQX_SA_W_PH:
23430 check_dsp_r2(ctx);
23431 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23432 break;
23433 case OPC_MULSAQ_S_W_PH:
23434 check_dsp(ctx);
23435 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23436 break;
23437 case OPC_DPAQ_SA_L_W:
23438 check_dsp(ctx);
23439 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23440 break;
23441 case OPC_DPSQ_SA_L_W:
23442 check_dsp(ctx);
23443 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23444 break;
23445 case OPC_MAQ_S_W_PHL:
23446 check_dsp(ctx);
23447 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23448 break;
23449 case OPC_MAQ_S_W_PHR:
23450 check_dsp(ctx);
23451 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23452 break;
23453 case OPC_MAQ_SA_W_PHL:
23454 check_dsp(ctx);
23455 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23456 break;
23457 case OPC_MAQ_SA_W_PHR:
23458 check_dsp(ctx);
23459 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23460 break;
23461 case OPC_MULSA_W_PH:
23462 check_dsp_r2(ctx);
23463 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23464 break;
23466 break;
23467 #ifdef TARGET_MIPS64
23468 case OPC_DPAQ_W_QH_DSP:
23470 int ac = ret & 0x03;
23471 tcg_gen_movi_i32(t0, ac);
23473 switch (op2) {
23474 case OPC_DMADD:
23475 check_dsp(ctx);
23476 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23477 break;
23478 case OPC_DMADDU:
23479 check_dsp(ctx);
23480 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23481 break;
23482 case OPC_DMSUB:
23483 check_dsp(ctx);
23484 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23485 break;
23486 case OPC_DMSUBU:
23487 check_dsp(ctx);
23488 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23489 break;
23490 case OPC_DPA_W_QH:
23491 check_dsp_r2(ctx);
23492 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23493 break;
23494 case OPC_DPAQ_S_W_QH:
23495 check_dsp(ctx);
23496 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23497 break;
23498 case OPC_DPAQ_SA_L_PW:
23499 check_dsp(ctx);
23500 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23501 break;
23502 case OPC_DPAU_H_OBL:
23503 check_dsp(ctx);
23504 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23505 break;
23506 case OPC_DPAU_H_OBR:
23507 check_dsp(ctx);
23508 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23509 break;
23510 case OPC_DPS_W_QH:
23511 check_dsp_r2(ctx);
23512 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23513 break;
23514 case OPC_DPSQ_S_W_QH:
23515 check_dsp(ctx);
23516 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23517 break;
23518 case OPC_DPSQ_SA_L_PW:
23519 check_dsp(ctx);
23520 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23521 break;
23522 case OPC_DPSU_H_OBL:
23523 check_dsp(ctx);
23524 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23525 break;
23526 case OPC_DPSU_H_OBR:
23527 check_dsp(ctx);
23528 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23529 break;
23530 case OPC_MAQ_S_L_PWL:
23531 check_dsp(ctx);
23532 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23533 break;
23534 case OPC_MAQ_S_L_PWR:
23535 check_dsp(ctx);
23536 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23537 break;
23538 case OPC_MAQ_S_W_QHLL:
23539 check_dsp(ctx);
23540 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23541 break;
23542 case OPC_MAQ_SA_W_QHLL:
23543 check_dsp(ctx);
23544 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23545 break;
23546 case OPC_MAQ_S_W_QHLR:
23547 check_dsp(ctx);
23548 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23549 break;
23550 case OPC_MAQ_SA_W_QHLR:
23551 check_dsp(ctx);
23552 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23553 break;
23554 case OPC_MAQ_S_W_QHRL:
23555 check_dsp(ctx);
23556 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23557 break;
23558 case OPC_MAQ_SA_W_QHRL:
23559 check_dsp(ctx);
23560 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23561 break;
23562 case OPC_MAQ_S_W_QHRR:
23563 check_dsp(ctx);
23564 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23565 break;
23566 case OPC_MAQ_SA_W_QHRR:
23567 check_dsp(ctx);
23568 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23569 break;
23570 case OPC_MULSAQ_S_L_PW:
23571 check_dsp(ctx);
23572 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23573 break;
23574 case OPC_MULSAQ_S_W_QH:
23575 check_dsp(ctx);
23576 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23577 break;
23580 break;
23581 #endif
23582 case OPC_ADDU_QB_DSP:
23583 switch (op2) {
23584 case OPC_MULEU_S_PH_QBL:
23585 check_dsp(ctx);
23586 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23587 break;
23588 case OPC_MULEU_S_PH_QBR:
23589 check_dsp(ctx);
23590 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23591 break;
23592 case OPC_MULQ_RS_PH:
23593 check_dsp(ctx);
23594 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23595 break;
23596 case OPC_MULEQ_S_W_PHL:
23597 check_dsp(ctx);
23598 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23599 break;
23600 case OPC_MULEQ_S_W_PHR:
23601 check_dsp(ctx);
23602 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23603 break;
23604 case OPC_MULQ_S_PH:
23605 check_dsp_r2(ctx);
23606 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23607 break;
23609 break;
23610 #ifdef TARGET_MIPS64
23611 case OPC_ADDU_OB_DSP:
23612 switch (op2) {
23613 case OPC_MULEQ_S_PW_QHL:
23614 check_dsp(ctx);
23615 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23616 break;
23617 case OPC_MULEQ_S_PW_QHR:
23618 check_dsp(ctx);
23619 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23620 break;
23621 case OPC_MULEU_S_QH_OBL:
23622 check_dsp(ctx);
23623 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23624 break;
23625 case OPC_MULEU_S_QH_OBR:
23626 check_dsp(ctx);
23627 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23628 break;
23629 case OPC_MULQ_RS_QH:
23630 check_dsp(ctx);
23631 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23632 break;
23634 break;
23635 #endif
23638 tcg_temp_free_i32(t0);
23639 tcg_temp_free(v1_t);
23640 tcg_temp_free(v2_t);
23643 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23644 int ret, int val)
23646 int16_t imm;
23647 TCGv t0;
23648 TCGv val_t;
23650 if (ret == 0) {
23651 /* Treat as NOP. */
23652 return;
23655 t0 = tcg_temp_new();
23656 val_t = tcg_temp_new();
23657 gen_load_gpr(val_t, val);
23659 switch (op1) {
23660 case OPC_ABSQ_S_PH_DSP:
23661 switch (op2) {
23662 case OPC_BITREV:
23663 check_dsp(ctx);
23664 gen_helper_bitrev(cpu_gpr[ret], val_t);
23665 break;
23666 case OPC_REPL_QB:
23667 check_dsp(ctx);
23669 target_long result;
23670 imm = (ctx->opcode >> 16) & 0xFF;
23671 result = (uint32_t)imm << 24 |
23672 (uint32_t)imm << 16 |
23673 (uint32_t)imm << 8 |
23674 (uint32_t)imm;
23675 result = (int32_t)result;
23676 tcg_gen_movi_tl(cpu_gpr[ret], result);
23678 break;
23679 case OPC_REPLV_QB:
23680 check_dsp(ctx);
23681 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23682 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23683 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23684 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23685 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23686 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23687 break;
23688 case OPC_REPL_PH:
23689 check_dsp(ctx);
23691 imm = (ctx->opcode >> 16) & 0x03FF;
23692 imm = (int16_t)(imm << 6) >> 6;
23693 tcg_gen_movi_tl(cpu_gpr[ret], \
23694 (target_long)((int32_t)imm << 16 | \
23695 (uint16_t)imm));
23697 break;
23698 case OPC_REPLV_PH:
23699 check_dsp(ctx);
23700 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23701 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23702 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23703 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23704 break;
23706 break;
23707 #ifdef TARGET_MIPS64
23708 case OPC_ABSQ_S_QH_DSP:
23709 switch (op2) {
23710 case OPC_REPL_OB:
23711 check_dsp(ctx);
23713 target_long temp;
23715 imm = (ctx->opcode >> 16) & 0xFF;
23716 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23717 temp = (temp << 16) | temp;
23718 temp = (temp << 32) | temp;
23719 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23720 break;
23722 case OPC_REPL_PW:
23723 check_dsp(ctx);
23725 target_long temp;
23727 imm = (ctx->opcode >> 16) & 0x03FF;
23728 imm = (int16_t)(imm << 6) >> 6;
23729 temp = ((target_long)imm << 32) \
23730 | ((target_long)imm & 0xFFFFFFFF);
23731 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23732 break;
23734 case OPC_REPL_QH:
23735 check_dsp(ctx);
23737 target_long temp;
23739 imm = (ctx->opcode >> 16) & 0x03FF;
23740 imm = (int16_t)(imm << 6) >> 6;
23742 temp = ((uint64_t)(uint16_t)imm << 48) |
23743 ((uint64_t)(uint16_t)imm << 32) |
23744 ((uint64_t)(uint16_t)imm << 16) |
23745 (uint64_t)(uint16_t)imm;
23746 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23747 break;
23749 case OPC_REPLV_OB:
23750 check_dsp(ctx);
23751 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23752 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23753 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23754 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23755 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23756 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23757 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23758 break;
23759 case OPC_REPLV_PW:
23760 check_dsp(ctx);
23761 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23762 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23763 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23764 break;
23765 case OPC_REPLV_QH:
23766 check_dsp(ctx);
23767 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23768 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23769 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23770 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23771 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23772 break;
23774 break;
23775 #endif
23777 tcg_temp_free(t0);
23778 tcg_temp_free(val_t);
23781 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23782 uint32_t op1, uint32_t op2,
23783 int ret, int v1, int v2, int check_ret)
23785 TCGv t1;
23786 TCGv v1_t;
23787 TCGv v2_t;
23789 if ((ret == 0) && (check_ret == 1)) {
23790 /* Treat as NOP. */
23791 return;
23794 t1 = tcg_temp_new();
23795 v1_t = tcg_temp_new();
23796 v2_t = tcg_temp_new();
23798 gen_load_gpr(v1_t, v1);
23799 gen_load_gpr(v2_t, v2);
23801 switch (op1) {
23802 case OPC_CMPU_EQ_QB_DSP:
23803 switch (op2) {
23804 case OPC_CMPU_EQ_QB:
23805 check_dsp(ctx);
23806 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23807 break;
23808 case OPC_CMPU_LT_QB:
23809 check_dsp(ctx);
23810 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23811 break;
23812 case OPC_CMPU_LE_QB:
23813 check_dsp(ctx);
23814 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23815 break;
23816 case OPC_CMPGU_EQ_QB:
23817 check_dsp(ctx);
23818 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23819 break;
23820 case OPC_CMPGU_LT_QB:
23821 check_dsp(ctx);
23822 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23823 break;
23824 case OPC_CMPGU_LE_QB:
23825 check_dsp(ctx);
23826 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23827 break;
23828 case OPC_CMPGDU_EQ_QB:
23829 check_dsp_r2(ctx);
23830 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23831 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23832 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23833 tcg_gen_shli_tl(t1, t1, 24);
23834 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23835 break;
23836 case OPC_CMPGDU_LT_QB:
23837 check_dsp_r2(ctx);
23838 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23839 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23840 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23841 tcg_gen_shli_tl(t1, t1, 24);
23842 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23843 break;
23844 case OPC_CMPGDU_LE_QB:
23845 check_dsp_r2(ctx);
23846 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23847 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23848 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23849 tcg_gen_shli_tl(t1, t1, 24);
23850 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23851 break;
23852 case OPC_CMP_EQ_PH:
23853 check_dsp(ctx);
23854 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23855 break;
23856 case OPC_CMP_LT_PH:
23857 check_dsp(ctx);
23858 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23859 break;
23860 case OPC_CMP_LE_PH:
23861 check_dsp(ctx);
23862 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23863 break;
23864 case OPC_PICK_QB:
23865 check_dsp(ctx);
23866 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23867 break;
23868 case OPC_PICK_PH:
23869 check_dsp(ctx);
23870 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23871 break;
23872 case OPC_PACKRL_PH:
23873 check_dsp(ctx);
23874 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23875 break;
23877 break;
23878 #ifdef TARGET_MIPS64
23879 case OPC_CMPU_EQ_OB_DSP:
23880 switch (op2) {
23881 case OPC_CMP_EQ_PW:
23882 check_dsp(ctx);
23883 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23884 break;
23885 case OPC_CMP_LT_PW:
23886 check_dsp(ctx);
23887 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23888 break;
23889 case OPC_CMP_LE_PW:
23890 check_dsp(ctx);
23891 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23892 break;
23893 case OPC_CMP_EQ_QH:
23894 check_dsp(ctx);
23895 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23896 break;
23897 case OPC_CMP_LT_QH:
23898 check_dsp(ctx);
23899 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23900 break;
23901 case OPC_CMP_LE_QH:
23902 check_dsp(ctx);
23903 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23904 break;
23905 case OPC_CMPGDU_EQ_OB:
23906 check_dsp_r2(ctx);
23907 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23908 break;
23909 case OPC_CMPGDU_LT_OB:
23910 check_dsp_r2(ctx);
23911 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23912 break;
23913 case OPC_CMPGDU_LE_OB:
23914 check_dsp_r2(ctx);
23915 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23916 break;
23917 case OPC_CMPGU_EQ_OB:
23918 check_dsp(ctx);
23919 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23920 break;
23921 case OPC_CMPGU_LT_OB:
23922 check_dsp(ctx);
23923 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23924 break;
23925 case OPC_CMPGU_LE_OB:
23926 check_dsp(ctx);
23927 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23928 break;
23929 case OPC_CMPU_EQ_OB:
23930 check_dsp(ctx);
23931 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23932 break;
23933 case OPC_CMPU_LT_OB:
23934 check_dsp(ctx);
23935 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23936 break;
23937 case OPC_CMPU_LE_OB:
23938 check_dsp(ctx);
23939 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23940 break;
23941 case OPC_PACKRL_PW:
23942 check_dsp(ctx);
23943 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23944 break;
23945 case OPC_PICK_OB:
23946 check_dsp(ctx);
23947 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23948 break;
23949 case OPC_PICK_PW:
23950 check_dsp(ctx);
23951 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23952 break;
23953 case OPC_PICK_QH:
23954 check_dsp(ctx);
23955 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23956 break;
23958 break;
23959 #endif
23962 tcg_temp_free(t1);
23963 tcg_temp_free(v1_t);
23964 tcg_temp_free(v2_t);
23967 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23968 uint32_t op1, int rt, int rs, int sa)
23970 TCGv t0;
23972 check_dsp_r2(ctx);
23974 if (rt == 0) {
23975 /* Treat as NOP. */
23976 return;
23979 t0 = tcg_temp_new();
23980 gen_load_gpr(t0, rs);
23982 switch (op1) {
23983 case OPC_APPEND_DSP:
23984 switch (MASK_APPEND(ctx->opcode)) {
23985 case OPC_APPEND:
23986 if (sa != 0) {
23987 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23989 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23990 break;
23991 case OPC_PREPEND:
23992 if (sa != 0) {
23993 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23994 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23995 tcg_gen_shli_tl(t0, t0, 32 - sa);
23996 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23998 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23999 break;
24000 case OPC_BALIGN:
24001 sa &= 3;
24002 if (sa != 0 && sa != 2) {
24003 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24004 tcg_gen_ext32u_tl(t0, t0);
24005 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24006 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24008 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24009 break;
24010 default: /* Invalid */
24011 MIPS_INVAL("MASK APPEND");
24012 generate_exception_end(ctx, EXCP_RI);
24013 break;
24015 break;
24016 #ifdef TARGET_MIPS64
24017 case OPC_DAPPEND_DSP:
24018 switch (MASK_DAPPEND(ctx->opcode)) {
24019 case OPC_DAPPEND:
24020 if (sa != 0) {
24021 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24023 break;
24024 case OPC_PREPENDD:
24025 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24026 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24027 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24028 break;
24029 case OPC_PREPENDW:
24030 if (sa != 0) {
24031 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24032 tcg_gen_shli_tl(t0, t0, 64 - sa);
24033 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24035 break;
24036 case OPC_DBALIGN:
24037 sa &= 7;
24038 if (sa != 0 && sa != 2 && sa != 4) {
24039 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24040 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24041 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24043 break;
24044 default: /* Invalid */
24045 MIPS_INVAL("MASK DAPPEND");
24046 generate_exception_end(ctx, EXCP_RI);
24047 break;
24049 break;
24050 #endif
24052 tcg_temp_free(t0);
24055 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24056 int ret, int v1, int v2, int check_ret)
24059 TCGv t0;
24060 TCGv t1;
24061 TCGv v1_t;
24062 TCGv v2_t;
24063 int16_t imm;
24065 if ((ret == 0) && (check_ret == 1)) {
24066 /* Treat as NOP. */
24067 return;
24070 t0 = tcg_temp_new();
24071 t1 = tcg_temp_new();
24072 v1_t = tcg_temp_new();
24073 v2_t = tcg_temp_new();
24075 gen_load_gpr(v1_t, v1);
24076 gen_load_gpr(v2_t, v2);
24078 switch (op1) {
24079 case OPC_EXTR_W_DSP:
24080 check_dsp(ctx);
24081 switch (op2) {
24082 case OPC_EXTR_W:
24083 tcg_gen_movi_tl(t0, v2);
24084 tcg_gen_movi_tl(t1, v1);
24085 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24086 break;
24087 case OPC_EXTR_R_W:
24088 tcg_gen_movi_tl(t0, v2);
24089 tcg_gen_movi_tl(t1, v1);
24090 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24091 break;
24092 case OPC_EXTR_RS_W:
24093 tcg_gen_movi_tl(t0, v2);
24094 tcg_gen_movi_tl(t1, v1);
24095 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24096 break;
24097 case OPC_EXTR_S_H:
24098 tcg_gen_movi_tl(t0, v2);
24099 tcg_gen_movi_tl(t1, v1);
24100 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24101 break;
24102 case OPC_EXTRV_S_H:
24103 tcg_gen_movi_tl(t0, v2);
24104 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24105 break;
24106 case OPC_EXTRV_W:
24107 tcg_gen_movi_tl(t0, v2);
24108 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24109 break;
24110 case OPC_EXTRV_R_W:
24111 tcg_gen_movi_tl(t0, v2);
24112 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24113 break;
24114 case OPC_EXTRV_RS_W:
24115 tcg_gen_movi_tl(t0, v2);
24116 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24117 break;
24118 case OPC_EXTP:
24119 tcg_gen_movi_tl(t0, v2);
24120 tcg_gen_movi_tl(t1, v1);
24121 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24122 break;
24123 case OPC_EXTPV:
24124 tcg_gen_movi_tl(t0, v2);
24125 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24126 break;
24127 case OPC_EXTPDP:
24128 tcg_gen_movi_tl(t0, v2);
24129 tcg_gen_movi_tl(t1, v1);
24130 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24131 break;
24132 case OPC_EXTPDPV:
24133 tcg_gen_movi_tl(t0, v2);
24134 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24135 break;
24136 case OPC_SHILO:
24137 imm = (ctx->opcode >> 20) & 0x3F;
24138 tcg_gen_movi_tl(t0, ret);
24139 tcg_gen_movi_tl(t1, imm);
24140 gen_helper_shilo(t0, t1, cpu_env);
24141 break;
24142 case OPC_SHILOV:
24143 tcg_gen_movi_tl(t0, ret);
24144 gen_helper_shilo(t0, v1_t, cpu_env);
24145 break;
24146 case OPC_MTHLIP:
24147 tcg_gen_movi_tl(t0, ret);
24148 gen_helper_mthlip(t0, v1_t, cpu_env);
24149 break;
24150 case OPC_WRDSP:
24151 imm = (ctx->opcode >> 11) & 0x3FF;
24152 tcg_gen_movi_tl(t0, imm);
24153 gen_helper_wrdsp(v1_t, t0, cpu_env);
24154 break;
24155 case OPC_RDDSP:
24156 imm = (ctx->opcode >> 16) & 0x03FF;
24157 tcg_gen_movi_tl(t0, imm);
24158 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24159 break;
24161 break;
24162 #ifdef TARGET_MIPS64
24163 case OPC_DEXTR_W_DSP:
24164 check_dsp(ctx);
24165 switch (op2) {
24166 case OPC_DMTHLIP:
24167 tcg_gen_movi_tl(t0, ret);
24168 gen_helper_dmthlip(v1_t, t0, cpu_env);
24169 break;
24170 case OPC_DSHILO:
24172 int shift = (ctx->opcode >> 19) & 0x7F;
24173 int ac = (ctx->opcode >> 11) & 0x03;
24174 tcg_gen_movi_tl(t0, shift);
24175 tcg_gen_movi_tl(t1, ac);
24176 gen_helper_dshilo(t0, t1, cpu_env);
24177 break;
24179 case OPC_DSHILOV:
24181 int ac = (ctx->opcode >> 11) & 0x03;
24182 tcg_gen_movi_tl(t0, ac);
24183 gen_helper_dshilo(v1_t, t0, cpu_env);
24184 break;
24186 case OPC_DEXTP:
24187 tcg_gen_movi_tl(t0, v2);
24188 tcg_gen_movi_tl(t1, v1);
24190 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24191 break;
24192 case OPC_DEXTPV:
24193 tcg_gen_movi_tl(t0, v2);
24194 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24195 break;
24196 case OPC_DEXTPDP:
24197 tcg_gen_movi_tl(t0, v2);
24198 tcg_gen_movi_tl(t1, v1);
24199 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24200 break;
24201 case OPC_DEXTPDPV:
24202 tcg_gen_movi_tl(t0, v2);
24203 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24204 break;
24205 case OPC_DEXTR_L:
24206 tcg_gen_movi_tl(t0, v2);
24207 tcg_gen_movi_tl(t1, v1);
24208 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24209 break;
24210 case OPC_DEXTR_R_L:
24211 tcg_gen_movi_tl(t0, v2);
24212 tcg_gen_movi_tl(t1, v1);
24213 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24214 break;
24215 case OPC_DEXTR_RS_L:
24216 tcg_gen_movi_tl(t0, v2);
24217 tcg_gen_movi_tl(t1, v1);
24218 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24219 break;
24220 case OPC_DEXTR_W:
24221 tcg_gen_movi_tl(t0, v2);
24222 tcg_gen_movi_tl(t1, v1);
24223 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24224 break;
24225 case OPC_DEXTR_R_W:
24226 tcg_gen_movi_tl(t0, v2);
24227 tcg_gen_movi_tl(t1, v1);
24228 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24229 break;
24230 case OPC_DEXTR_RS_W:
24231 tcg_gen_movi_tl(t0, v2);
24232 tcg_gen_movi_tl(t1, v1);
24233 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24234 break;
24235 case OPC_DEXTR_S_H:
24236 tcg_gen_movi_tl(t0, v2);
24237 tcg_gen_movi_tl(t1, v1);
24238 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24239 break;
24240 case OPC_DEXTRV_S_H:
24241 tcg_gen_movi_tl(t0, v2);
24242 tcg_gen_movi_tl(t1, v1);
24243 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24244 break;
24245 case OPC_DEXTRV_L:
24246 tcg_gen_movi_tl(t0, v2);
24247 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24248 break;
24249 case OPC_DEXTRV_R_L:
24250 tcg_gen_movi_tl(t0, v2);
24251 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24252 break;
24253 case OPC_DEXTRV_RS_L:
24254 tcg_gen_movi_tl(t0, v2);
24255 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24256 break;
24257 case OPC_DEXTRV_W:
24258 tcg_gen_movi_tl(t0, v2);
24259 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24260 break;
24261 case OPC_DEXTRV_R_W:
24262 tcg_gen_movi_tl(t0, v2);
24263 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24264 break;
24265 case OPC_DEXTRV_RS_W:
24266 tcg_gen_movi_tl(t0, v2);
24267 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24268 break;
24270 break;
24271 #endif
24274 tcg_temp_free(t0);
24275 tcg_temp_free(t1);
24276 tcg_temp_free(v1_t);
24277 tcg_temp_free(v2_t);
24280 /* End MIPSDSP functions. */
24282 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24284 int rs, rt, rd, sa;
24285 uint32_t op1, op2;
24287 rs = (ctx->opcode >> 21) & 0x1f;
24288 rt = (ctx->opcode >> 16) & 0x1f;
24289 rd = (ctx->opcode >> 11) & 0x1f;
24290 sa = (ctx->opcode >> 6) & 0x1f;
24292 op1 = MASK_SPECIAL(ctx->opcode);
24293 switch (op1) {
24294 case OPC_LSA:
24295 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24296 break;
24297 case OPC_MULT:
24298 case OPC_MULTU:
24299 case OPC_DIV:
24300 case OPC_DIVU:
24301 op2 = MASK_R6_MULDIV(ctx->opcode);
24302 switch (op2) {
24303 case R6_OPC_MUL:
24304 case R6_OPC_MUH:
24305 case R6_OPC_MULU:
24306 case R6_OPC_MUHU:
24307 case R6_OPC_DIV:
24308 case R6_OPC_MOD:
24309 case R6_OPC_DIVU:
24310 case R6_OPC_MODU:
24311 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24312 break;
24313 default:
24314 MIPS_INVAL("special_r6 muldiv");
24315 generate_exception_end(ctx, EXCP_RI);
24316 break;
24318 break;
24319 case OPC_SELEQZ:
24320 case OPC_SELNEZ:
24321 gen_cond_move(ctx, op1, rd, rs, rt);
24322 break;
24323 case R6_OPC_CLO:
24324 case R6_OPC_CLZ:
24325 if (rt == 0 && sa == 1) {
24327 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24328 * We need additionally to check other fields.
24330 gen_cl(ctx, op1, rd, rs);
24331 } else {
24332 generate_exception_end(ctx, EXCP_RI);
24334 break;
24335 case R6_OPC_SDBBP:
24336 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24337 gen_helper_do_semihosting(cpu_env);
24338 } else {
24339 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24340 generate_exception_end(ctx, EXCP_RI);
24341 } else {
24342 generate_exception_end(ctx, EXCP_DBp);
24345 break;
24346 #if defined(TARGET_MIPS64)
24347 case OPC_DLSA:
24348 check_mips_64(ctx);
24349 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24350 break;
24351 case R6_OPC_DCLO:
24352 case R6_OPC_DCLZ:
24353 if (rt == 0 && sa == 1) {
24355 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24356 * We need additionally to check other fields.
24358 check_mips_64(ctx);
24359 gen_cl(ctx, op1, rd, rs);
24360 } else {
24361 generate_exception_end(ctx, EXCP_RI);
24363 break;
24364 case OPC_DMULT:
24365 case OPC_DMULTU:
24366 case OPC_DDIV:
24367 case OPC_DDIVU:
24369 op2 = MASK_R6_MULDIV(ctx->opcode);
24370 switch (op2) {
24371 case R6_OPC_DMUL:
24372 case R6_OPC_DMUH:
24373 case R6_OPC_DMULU:
24374 case R6_OPC_DMUHU:
24375 case R6_OPC_DDIV:
24376 case R6_OPC_DMOD:
24377 case R6_OPC_DDIVU:
24378 case R6_OPC_DMODU:
24379 check_mips_64(ctx);
24380 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24381 break;
24382 default:
24383 MIPS_INVAL("special_r6 muldiv");
24384 generate_exception_end(ctx, EXCP_RI);
24385 break;
24387 break;
24388 #endif
24389 default: /* Invalid */
24390 MIPS_INVAL("special_r6");
24391 generate_exception_end(ctx, EXCP_RI);
24392 break;
24396 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24398 int rs = extract32(ctx->opcode, 21, 5);
24399 int rt = extract32(ctx->opcode, 16, 5);
24400 int rd = extract32(ctx->opcode, 11, 5);
24401 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24403 switch (op1) {
24404 case OPC_MOVN: /* Conditional move */
24405 case OPC_MOVZ:
24406 gen_cond_move(ctx, op1, rd, rs, rt);
24407 break;
24408 case OPC_MFHI: /* Move from HI/LO */
24409 case OPC_MFLO:
24410 gen_HILO(ctx, op1, 0, rd);
24411 break;
24412 case OPC_MTHI:
24413 case OPC_MTLO: /* Move to HI/LO */
24414 gen_HILO(ctx, op1, 0, rs);
24415 break;
24416 case OPC_MULT:
24417 case OPC_MULTU:
24418 gen_mul_txx9(ctx, op1, rd, rs, rt);
24419 break;
24420 case OPC_DIV:
24421 case OPC_DIVU:
24422 gen_muldiv(ctx, op1, 0, rs, rt);
24423 break;
24424 #if defined(TARGET_MIPS64)
24425 case OPC_DMULT:
24426 case OPC_DMULTU:
24427 case OPC_DDIV:
24428 case OPC_DDIVU:
24429 check_insn_opc_user_only(ctx, INSN_R5900);
24430 gen_muldiv(ctx, op1, 0, rs, rt);
24431 break;
24432 #endif
24433 case OPC_JR:
24434 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24435 break;
24436 default: /* Invalid */
24437 MIPS_INVAL("special_tx79");
24438 generate_exception_end(ctx, EXCP_RI);
24439 break;
24443 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24445 int rs, rt, rd, sa;
24446 uint32_t op1;
24448 rs = (ctx->opcode >> 21) & 0x1f;
24449 rt = (ctx->opcode >> 16) & 0x1f;
24450 rd = (ctx->opcode >> 11) & 0x1f;
24451 sa = (ctx->opcode >> 6) & 0x1f;
24453 op1 = MASK_SPECIAL(ctx->opcode);
24454 switch (op1) {
24455 case OPC_MOVN: /* Conditional move */
24456 case OPC_MOVZ:
24457 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24458 INSN_LOONGSON2E | INSN_LOONGSON2F);
24459 gen_cond_move(ctx, op1, rd, rs, rt);
24460 break;
24461 case OPC_MFHI: /* Move from HI/LO */
24462 case OPC_MFLO:
24463 gen_HILO(ctx, op1, rs & 3, rd);
24464 break;
24465 case OPC_MTHI:
24466 case OPC_MTLO: /* Move to HI/LO */
24467 gen_HILO(ctx, op1, rd & 3, rs);
24468 break;
24469 case OPC_MOVCI:
24470 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24471 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24472 check_cp1_enabled(ctx);
24473 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24474 (ctx->opcode >> 16) & 1);
24475 } else {
24476 generate_exception_err(ctx, EXCP_CpU, 1);
24478 break;
24479 case OPC_MULT:
24480 case OPC_MULTU:
24481 if (sa) {
24482 check_insn(ctx, INSN_VR54XX);
24483 op1 = MASK_MUL_VR54XX(ctx->opcode);
24484 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24485 } else {
24486 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24488 break;
24489 case OPC_DIV:
24490 case OPC_DIVU:
24491 gen_muldiv(ctx, op1, 0, rs, rt);
24492 break;
24493 #if defined(TARGET_MIPS64)
24494 case OPC_DMULT:
24495 case OPC_DMULTU:
24496 case OPC_DDIV:
24497 case OPC_DDIVU:
24498 check_insn(ctx, ISA_MIPS3);
24499 check_mips_64(ctx);
24500 gen_muldiv(ctx, op1, 0, rs, rt);
24501 break;
24502 #endif
24503 case OPC_JR:
24504 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24505 break;
24506 case OPC_SPIM:
24507 #ifdef MIPS_STRICT_STANDARD
24508 MIPS_INVAL("SPIM");
24509 generate_exception_end(ctx, EXCP_RI);
24510 #else
24511 /* Implemented as RI exception for now. */
24512 MIPS_INVAL("spim (unofficial)");
24513 generate_exception_end(ctx, EXCP_RI);
24514 #endif
24515 break;
24516 default: /* Invalid */
24517 MIPS_INVAL("special_legacy");
24518 generate_exception_end(ctx, EXCP_RI);
24519 break;
24523 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24525 int rs, rt, rd, sa;
24526 uint32_t op1;
24528 rs = (ctx->opcode >> 21) & 0x1f;
24529 rt = (ctx->opcode >> 16) & 0x1f;
24530 rd = (ctx->opcode >> 11) & 0x1f;
24531 sa = (ctx->opcode >> 6) & 0x1f;
24533 op1 = MASK_SPECIAL(ctx->opcode);
24534 switch (op1) {
24535 case OPC_SLL: /* Shift with immediate */
24536 if (sa == 5 && rd == 0 &&
24537 rs == 0 && rt == 0) { /* PAUSE */
24538 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24539 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24540 generate_exception_end(ctx, EXCP_RI);
24541 break;
24544 /* Fallthrough */
24545 case OPC_SRA:
24546 gen_shift_imm(ctx, op1, rd, rt, sa);
24547 break;
24548 case OPC_SRL:
24549 switch ((ctx->opcode >> 21) & 0x1f) {
24550 case 1:
24551 /* rotr is decoded as srl on non-R2 CPUs */
24552 if (ctx->insn_flags & ISA_MIPS32R2) {
24553 op1 = OPC_ROTR;
24555 /* Fallthrough */
24556 case 0:
24557 gen_shift_imm(ctx, op1, rd, rt, sa);
24558 break;
24559 default:
24560 generate_exception_end(ctx, EXCP_RI);
24561 break;
24563 break;
24564 case OPC_ADD:
24565 case OPC_ADDU:
24566 case OPC_SUB:
24567 case OPC_SUBU:
24568 gen_arith(ctx, op1, rd, rs, rt);
24569 break;
24570 case OPC_SLLV: /* Shifts */
24571 case OPC_SRAV:
24572 gen_shift(ctx, op1, rd, rs, rt);
24573 break;
24574 case OPC_SRLV:
24575 switch ((ctx->opcode >> 6) & 0x1f) {
24576 case 1:
24577 /* rotrv is decoded as srlv on non-R2 CPUs */
24578 if (ctx->insn_flags & ISA_MIPS32R2) {
24579 op1 = OPC_ROTRV;
24581 /* Fallthrough */
24582 case 0:
24583 gen_shift(ctx, op1, rd, rs, rt);
24584 break;
24585 default:
24586 generate_exception_end(ctx, EXCP_RI);
24587 break;
24589 break;
24590 case OPC_SLT: /* Set on less than */
24591 case OPC_SLTU:
24592 gen_slt(ctx, op1, rd, rs, rt);
24593 break;
24594 case OPC_AND: /* Logic*/
24595 case OPC_OR:
24596 case OPC_NOR:
24597 case OPC_XOR:
24598 gen_logic(ctx, op1, rd, rs, rt);
24599 break;
24600 case OPC_JALR:
24601 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24602 break;
24603 case OPC_TGE: /* Traps */
24604 case OPC_TGEU:
24605 case OPC_TLT:
24606 case OPC_TLTU:
24607 case OPC_TEQ:
24608 case OPC_TNE:
24609 check_insn(ctx, ISA_MIPS2);
24610 gen_trap(ctx, op1, rs, rt, -1);
24611 break;
24612 case OPC_LSA: /* OPC_PMON */
24613 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24614 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24615 decode_opc_special_r6(env, ctx);
24616 } else {
24617 /* Pmon entry point, also R4010 selsl */
24618 #ifdef MIPS_STRICT_STANDARD
24619 MIPS_INVAL("PMON / selsl");
24620 generate_exception_end(ctx, EXCP_RI);
24621 #else
24622 gen_helper_0e0i(pmon, sa);
24623 #endif
24625 break;
24626 case OPC_SYSCALL:
24627 generate_exception_end(ctx, EXCP_SYSCALL);
24628 break;
24629 case OPC_BREAK:
24630 generate_exception_end(ctx, EXCP_BREAK);
24631 break;
24632 case OPC_SYNC:
24633 check_insn(ctx, ISA_MIPS2);
24634 gen_sync(extract32(ctx->opcode, 6, 5));
24635 break;
24637 #if defined(TARGET_MIPS64)
24638 /* MIPS64 specific opcodes */
24639 case OPC_DSLL:
24640 case OPC_DSRA:
24641 case OPC_DSLL32:
24642 case OPC_DSRA32:
24643 check_insn(ctx, ISA_MIPS3);
24644 check_mips_64(ctx);
24645 gen_shift_imm(ctx, op1, rd, rt, sa);
24646 break;
24647 case OPC_DSRL:
24648 switch ((ctx->opcode >> 21) & 0x1f) {
24649 case 1:
24650 /* drotr is decoded as dsrl on non-R2 CPUs */
24651 if (ctx->insn_flags & ISA_MIPS32R2) {
24652 op1 = OPC_DROTR;
24654 /* Fallthrough */
24655 case 0:
24656 check_insn(ctx, ISA_MIPS3);
24657 check_mips_64(ctx);
24658 gen_shift_imm(ctx, op1, rd, rt, sa);
24659 break;
24660 default:
24661 generate_exception_end(ctx, EXCP_RI);
24662 break;
24664 break;
24665 case OPC_DSRL32:
24666 switch ((ctx->opcode >> 21) & 0x1f) {
24667 case 1:
24668 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24669 if (ctx->insn_flags & ISA_MIPS32R2) {
24670 op1 = OPC_DROTR32;
24672 /* Fallthrough */
24673 case 0:
24674 check_insn(ctx, ISA_MIPS3);
24675 check_mips_64(ctx);
24676 gen_shift_imm(ctx, op1, rd, rt, sa);
24677 break;
24678 default:
24679 generate_exception_end(ctx, EXCP_RI);
24680 break;
24682 break;
24683 case OPC_DADD:
24684 case OPC_DADDU:
24685 case OPC_DSUB:
24686 case OPC_DSUBU:
24687 check_insn(ctx, ISA_MIPS3);
24688 check_mips_64(ctx);
24689 gen_arith(ctx, op1, rd, rs, rt);
24690 break;
24691 case OPC_DSLLV:
24692 case OPC_DSRAV:
24693 check_insn(ctx, ISA_MIPS3);
24694 check_mips_64(ctx);
24695 gen_shift(ctx, op1, rd, rs, rt);
24696 break;
24697 case OPC_DSRLV:
24698 switch ((ctx->opcode >> 6) & 0x1f) {
24699 case 1:
24700 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24701 if (ctx->insn_flags & ISA_MIPS32R2) {
24702 op1 = OPC_DROTRV;
24704 /* Fallthrough */
24705 case 0:
24706 check_insn(ctx, ISA_MIPS3);
24707 check_mips_64(ctx);
24708 gen_shift(ctx, op1, rd, rs, rt);
24709 break;
24710 default:
24711 generate_exception_end(ctx, EXCP_RI);
24712 break;
24714 break;
24715 case OPC_DLSA:
24716 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24717 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24718 decode_opc_special_r6(env, ctx);
24720 break;
24721 #endif
24722 default:
24723 if (ctx->insn_flags & ISA_MIPS32R6) {
24724 decode_opc_special_r6(env, ctx);
24725 } else if (ctx->insn_flags & INSN_R5900) {
24726 decode_opc_special_tx79(env, ctx);
24727 } else {
24728 decode_opc_special_legacy(env, ctx);
24734 #if defined(TARGET_MIPS64)
24738 * MMI (MultiMedia Interface) ASE instructions
24739 * ===========================================
24743 * MMI instructions category: data communication
24744 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24746 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24747 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24748 * PCPYUD PEXEH PEXTLW PPACW
24749 * PEXEW PEXTUB
24750 * PEXTUH
24751 * PEXTUW
24755 * PCPYH rd, rt
24757 * Parallel Copy Halfword
24759 * 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
24760 * +-----------+---------+---------+---------+---------+-----------+
24761 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24762 * +-----------+---------+---------+---------+---------+-----------+
24764 static void gen_mmi_pcpyh(DisasContext *ctx)
24766 uint32_t pd, rt, rd;
24767 uint32_t opcode;
24769 opcode = ctx->opcode;
24771 pd = extract32(opcode, 21, 5);
24772 rt = extract32(opcode, 16, 5);
24773 rd = extract32(opcode, 11, 5);
24775 if (unlikely(pd != 0)) {
24776 generate_exception_end(ctx, EXCP_RI);
24777 } else if (rd == 0) {
24778 /* nop */
24779 } else if (rt == 0) {
24780 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24781 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24782 } else {
24783 TCGv_i64 t0 = tcg_temp_new();
24784 TCGv_i64 t1 = tcg_temp_new();
24785 uint64_t mask = (1ULL << 16) - 1;
24787 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24788 tcg_gen_movi_i64(t1, 0);
24789 tcg_gen_or_i64(t1, t0, t1);
24790 tcg_gen_shli_i64(t0, t0, 16);
24791 tcg_gen_or_i64(t1, t0, t1);
24792 tcg_gen_shli_i64(t0, t0, 16);
24793 tcg_gen_or_i64(t1, t0, t1);
24794 tcg_gen_shli_i64(t0, t0, 16);
24795 tcg_gen_or_i64(t1, t0, t1);
24797 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24799 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24800 tcg_gen_movi_i64(t1, 0);
24801 tcg_gen_or_i64(t1, t0, t1);
24802 tcg_gen_shli_i64(t0, t0, 16);
24803 tcg_gen_or_i64(t1, t0, t1);
24804 tcg_gen_shli_i64(t0, t0, 16);
24805 tcg_gen_or_i64(t1, t0, t1);
24806 tcg_gen_shli_i64(t0, t0, 16);
24807 tcg_gen_or_i64(t1, t0, t1);
24809 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24811 tcg_temp_free(t0);
24812 tcg_temp_free(t1);
24817 * PCPYLD rd, rs, rt
24819 * Parallel Copy Lower Doubleword
24821 * 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
24822 * +-----------+---------+---------+---------+---------+-----------+
24823 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24824 * +-----------+---------+---------+---------+---------+-----------+
24826 static void gen_mmi_pcpyld(DisasContext *ctx)
24828 uint32_t rs, rt, rd;
24829 uint32_t opcode;
24831 opcode = ctx->opcode;
24833 rs = extract32(opcode, 21, 5);
24834 rt = extract32(opcode, 16, 5);
24835 rd = extract32(opcode, 11, 5);
24837 if (rd == 0) {
24838 /* nop */
24839 } else {
24840 if (rs == 0) {
24841 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24842 } else {
24843 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24845 if (rt == 0) {
24846 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24847 } else {
24848 if (rd != rt) {
24849 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24856 * PCPYUD rd, rs, rt
24858 * Parallel Copy Upper Doubleword
24860 * 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
24861 * +-----------+---------+---------+---------+---------+-----------+
24862 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24863 * +-----------+---------+---------+---------+---------+-----------+
24865 static void gen_mmi_pcpyud(DisasContext *ctx)
24867 uint32_t rs, rt, rd;
24868 uint32_t opcode;
24870 opcode = ctx->opcode;
24872 rs = extract32(opcode, 21, 5);
24873 rt = extract32(opcode, 16, 5);
24874 rd = extract32(opcode, 11, 5);
24876 if (rd == 0) {
24877 /* nop */
24878 } else {
24879 if (rs == 0) {
24880 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24881 } else {
24882 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24884 if (rt == 0) {
24885 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24886 } else {
24887 if (rd != rt) {
24888 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24894 #endif
24897 #if !defined(TARGET_MIPS64)
24899 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24900 #define MXU_APTN1_A 0
24901 #define MXU_APTN1_S 1
24903 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24904 #define MXU_APTN2_AA 0
24905 #define MXU_APTN2_AS 1
24906 #define MXU_APTN2_SA 2
24907 #define MXU_APTN2_SS 3
24909 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24910 #define MXU_EPTN2_AA 0
24911 #define MXU_EPTN2_AS 1
24912 #define MXU_EPTN2_SA 2
24913 #define MXU_EPTN2_SS 3
24915 /* MXU operand getting pattern 'optn2' */
24916 #define MXU_OPTN2_PTN0 0
24917 #define MXU_OPTN2_PTN1 1
24918 #define MXU_OPTN2_PTN2 2
24919 #define MXU_OPTN2_PTN3 3
24920 /* alternative naming scheme for 'optn2' */
24921 #define MXU_OPTN2_WW 0
24922 #define MXU_OPTN2_LW 1
24923 #define MXU_OPTN2_HW 2
24924 #define MXU_OPTN2_XW 3
24926 /* MXU operand getting pattern 'optn3' */
24927 #define MXU_OPTN3_PTN0 0
24928 #define MXU_OPTN3_PTN1 1
24929 #define MXU_OPTN3_PTN2 2
24930 #define MXU_OPTN3_PTN3 3
24931 #define MXU_OPTN3_PTN4 4
24932 #define MXU_OPTN3_PTN5 5
24933 #define MXU_OPTN3_PTN6 6
24934 #define MXU_OPTN3_PTN7 7
24938 * S32I2M XRa, rb - Register move from GRF to XRF
24940 static void gen_mxu_s32i2m(DisasContext *ctx)
24942 TCGv t0;
24943 uint32_t XRa, Rb;
24945 t0 = tcg_temp_new();
24947 XRa = extract32(ctx->opcode, 6, 5);
24948 Rb = extract32(ctx->opcode, 16, 5);
24950 gen_load_gpr(t0, Rb);
24951 if (XRa <= 15) {
24952 gen_store_mxu_gpr(t0, XRa);
24953 } else if (XRa == 16) {
24954 gen_store_mxu_cr(t0);
24957 tcg_temp_free(t0);
24961 * S32M2I XRa, rb - Register move from XRF to GRF
24963 static void gen_mxu_s32m2i(DisasContext *ctx)
24965 TCGv t0;
24966 uint32_t XRa, Rb;
24968 t0 = tcg_temp_new();
24970 XRa = extract32(ctx->opcode, 6, 5);
24971 Rb = extract32(ctx->opcode, 16, 5);
24973 if (XRa <= 15) {
24974 gen_load_mxu_gpr(t0, XRa);
24975 } else if (XRa == 16) {
24976 gen_load_mxu_cr(t0);
24979 gen_store_gpr(t0, Rb);
24981 tcg_temp_free(t0);
24985 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24987 static void gen_mxu_s8ldd(DisasContext *ctx)
24989 TCGv t0, t1;
24990 uint32_t XRa, Rb, s8, optn3;
24992 t0 = tcg_temp_new();
24993 t1 = tcg_temp_new();
24995 XRa = extract32(ctx->opcode, 6, 4);
24996 s8 = extract32(ctx->opcode, 10, 8);
24997 optn3 = extract32(ctx->opcode, 18, 3);
24998 Rb = extract32(ctx->opcode, 21, 5);
25000 gen_load_gpr(t0, Rb);
25001 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25003 switch (optn3) {
25004 /* XRa[7:0] = tmp8 */
25005 case MXU_OPTN3_PTN0:
25006 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25007 gen_load_mxu_gpr(t0, XRa);
25008 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25009 break;
25010 /* XRa[15:8] = tmp8 */
25011 case MXU_OPTN3_PTN1:
25012 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25013 gen_load_mxu_gpr(t0, XRa);
25014 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25015 break;
25016 /* XRa[23:16] = tmp8 */
25017 case MXU_OPTN3_PTN2:
25018 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25019 gen_load_mxu_gpr(t0, XRa);
25020 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25021 break;
25022 /* XRa[31:24] = tmp8 */
25023 case MXU_OPTN3_PTN3:
25024 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25025 gen_load_mxu_gpr(t0, XRa);
25026 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25027 break;
25028 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25029 case MXU_OPTN3_PTN4:
25030 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25031 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25032 break;
25033 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25034 case MXU_OPTN3_PTN5:
25035 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25036 tcg_gen_shli_tl(t1, t1, 8);
25037 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25038 break;
25039 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25040 case MXU_OPTN3_PTN6:
25041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25042 tcg_gen_mov_tl(t0, t1);
25043 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25044 tcg_gen_shli_tl(t1, t1, 16);
25045 tcg_gen_or_tl(t0, t0, t1);
25046 break;
25047 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25048 case MXU_OPTN3_PTN7:
25049 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25050 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25051 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25052 break;
25055 gen_store_mxu_gpr(t0, XRa);
25057 tcg_temp_free(t0);
25058 tcg_temp_free(t1);
25062 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25064 static void gen_mxu_d16mul(DisasContext *ctx)
25066 TCGv t0, t1, t2, t3;
25067 uint32_t XRa, XRb, XRc, XRd, optn2;
25069 t0 = tcg_temp_new();
25070 t1 = tcg_temp_new();
25071 t2 = tcg_temp_new();
25072 t3 = tcg_temp_new();
25074 XRa = extract32(ctx->opcode, 6, 4);
25075 XRb = extract32(ctx->opcode, 10, 4);
25076 XRc = extract32(ctx->opcode, 14, 4);
25077 XRd = extract32(ctx->opcode, 18, 4);
25078 optn2 = extract32(ctx->opcode, 22, 2);
25080 gen_load_mxu_gpr(t1, XRb);
25081 tcg_gen_sextract_tl(t0, t1, 0, 16);
25082 tcg_gen_sextract_tl(t1, t1, 16, 16);
25083 gen_load_mxu_gpr(t3, XRc);
25084 tcg_gen_sextract_tl(t2, t3, 0, 16);
25085 tcg_gen_sextract_tl(t3, t3, 16, 16);
25087 switch (optn2) {
25088 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25089 tcg_gen_mul_tl(t3, t1, t3);
25090 tcg_gen_mul_tl(t2, t0, t2);
25091 break;
25092 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25093 tcg_gen_mul_tl(t3, t0, t3);
25094 tcg_gen_mul_tl(t2, t0, t2);
25095 break;
25096 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25097 tcg_gen_mul_tl(t3, t1, t3);
25098 tcg_gen_mul_tl(t2, t1, t2);
25099 break;
25100 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25101 tcg_gen_mul_tl(t3, t0, t3);
25102 tcg_gen_mul_tl(t2, t1, t2);
25103 break;
25105 gen_store_mxu_gpr(t3, XRa);
25106 gen_store_mxu_gpr(t2, XRd);
25108 tcg_temp_free(t0);
25109 tcg_temp_free(t1);
25110 tcg_temp_free(t2);
25111 tcg_temp_free(t3);
25115 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25116 * and accumulate
25118 static void gen_mxu_d16mac(DisasContext *ctx)
25120 TCGv t0, t1, t2, t3;
25121 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25123 t0 = tcg_temp_new();
25124 t1 = tcg_temp_new();
25125 t2 = tcg_temp_new();
25126 t3 = tcg_temp_new();
25128 XRa = extract32(ctx->opcode, 6, 4);
25129 XRb = extract32(ctx->opcode, 10, 4);
25130 XRc = extract32(ctx->opcode, 14, 4);
25131 XRd = extract32(ctx->opcode, 18, 4);
25132 optn2 = extract32(ctx->opcode, 22, 2);
25133 aptn2 = extract32(ctx->opcode, 24, 2);
25135 gen_load_mxu_gpr(t1, XRb);
25136 tcg_gen_sextract_tl(t0, t1, 0, 16);
25137 tcg_gen_sextract_tl(t1, t1, 16, 16);
25139 gen_load_mxu_gpr(t3, XRc);
25140 tcg_gen_sextract_tl(t2, t3, 0, 16);
25141 tcg_gen_sextract_tl(t3, t3, 16, 16);
25143 switch (optn2) {
25144 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25145 tcg_gen_mul_tl(t3, t1, t3);
25146 tcg_gen_mul_tl(t2, t0, t2);
25147 break;
25148 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25149 tcg_gen_mul_tl(t3, t0, t3);
25150 tcg_gen_mul_tl(t2, t0, t2);
25151 break;
25152 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25153 tcg_gen_mul_tl(t3, t1, t3);
25154 tcg_gen_mul_tl(t2, t1, t2);
25155 break;
25156 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25157 tcg_gen_mul_tl(t3, t0, t3);
25158 tcg_gen_mul_tl(t2, t1, t2);
25159 break;
25161 gen_load_mxu_gpr(t0, XRa);
25162 gen_load_mxu_gpr(t1, XRd);
25164 switch (aptn2) {
25165 case MXU_APTN2_AA:
25166 tcg_gen_add_tl(t3, t0, t3);
25167 tcg_gen_add_tl(t2, t1, t2);
25168 break;
25169 case MXU_APTN2_AS:
25170 tcg_gen_add_tl(t3, t0, t3);
25171 tcg_gen_sub_tl(t2, t1, t2);
25172 break;
25173 case MXU_APTN2_SA:
25174 tcg_gen_sub_tl(t3, t0, t3);
25175 tcg_gen_add_tl(t2, t1, t2);
25176 break;
25177 case MXU_APTN2_SS:
25178 tcg_gen_sub_tl(t3, t0, t3);
25179 tcg_gen_sub_tl(t2, t1, t2);
25180 break;
25182 gen_store_mxu_gpr(t3, XRa);
25183 gen_store_mxu_gpr(t2, XRd);
25185 tcg_temp_free(t0);
25186 tcg_temp_free(t1);
25187 tcg_temp_free(t2);
25188 tcg_temp_free(t3);
25192 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25193 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25195 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25197 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25198 uint32_t XRa, XRb, XRc, XRd, sel;
25200 t0 = tcg_temp_new();
25201 t1 = tcg_temp_new();
25202 t2 = tcg_temp_new();
25203 t3 = tcg_temp_new();
25204 t4 = tcg_temp_new();
25205 t5 = tcg_temp_new();
25206 t6 = tcg_temp_new();
25207 t7 = tcg_temp_new();
25209 XRa = extract32(ctx->opcode, 6, 4);
25210 XRb = extract32(ctx->opcode, 10, 4);
25211 XRc = extract32(ctx->opcode, 14, 4);
25212 XRd = extract32(ctx->opcode, 18, 4);
25213 sel = extract32(ctx->opcode, 22, 2);
25215 gen_load_mxu_gpr(t3, XRb);
25216 gen_load_mxu_gpr(t7, XRc);
25218 if (sel == 0x2) {
25219 /* Q8MULSU */
25220 tcg_gen_ext8s_tl(t0, t3);
25221 tcg_gen_shri_tl(t3, t3, 8);
25222 tcg_gen_ext8s_tl(t1, t3);
25223 tcg_gen_shri_tl(t3, t3, 8);
25224 tcg_gen_ext8s_tl(t2, t3);
25225 tcg_gen_shri_tl(t3, t3, 8);
25226 tcg_gen_ext8s_tl(t3, t3);
25227 } else {
25228 /* Q8MUL */
25229 tcg_gen_ext8u_tl(t0, t3);
25230 tcg_gen_shri_tl(t3, t3, 8);
25231 tcg_gen_ext8u_tl(t1, t3);
25232 tcg_gen_shri_tl(t3, t3, 8);
25233 tcg_gen_ext8u_tl(t2, t3);
25234 tcg_gen_shri_tl(t3, t3, 8);
25235 tcg_gen_ext8u_tl(t3, t3);
25238 tcg_gen_ext8u_tl(t4, t7);
25239 tcg_gen_shri_tl(t7, t7, 8);
25240 tcg_gen_ext8u_tl(t5, t7);
25241 tcg_gen_shri_tl(t7, t7, 8);
25242 tcg_gen_ext8u_tl(t6, t7);
25243 tcg_gen_shri_tl(t7, t7, 8);
25244 tcg_gen_ext8u_tl(t7, t7);
25246 tcg_gen_mul_tl(t0, t0, t4);
25247 tcg_gen_mul_tl(t1, t1, t5);
25248 tcg_gen_mul_tl(t2, t2, t6);
25249 tcg_gen_mul_tl(t3, t3, t7);
25251 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25252 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25253 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25254 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25256 tcg_gen_shli_tl(t1, t1, 16);
25257 tcg_gen_shli_tl(t3, t3, 16);
25259 tcg_gen_or_tl(t0, t0, t1);
25260 tcg_gen_or_tl(t1, t2, t3);
25262 gen_store_mxu_gpr(t0, XRd);
25263 gen_store_mxu_gpr(t1, XRa);
25265 tcg_temp_free(t0);
25266 tcg_temp_free(t1);
25267 tcg_temp_free(t2);
25268 tcg_temp_free(t3);
25269 tcg_temp_free(t4);
25270 tcg_temp_free(t5);
25271 tcg_temp_free(t6);
25272 tcg_temp_free(t7);
25276 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25277 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25279 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25281 TCGv t0, t1;
25282 uint32_t XRa, Rb, s12, sel;
25284 t0 = tcg_temp_new();
25285 t1 = tcg_temp_new();
25287 XRa = extract32(ctx->opcode, 6, 4);
25288 s12 = extract32(ctx->opcode, 10, 10);
25289 sel = extract32(ctx->opcode, 20, 1);
25290 Rb = extract32(ctx->opcode, 21, 5);
25292 gen_load_gpr(t0, Rb);
25294 tcg_gen_movi_tl(t1, s12);
25295 tcg_gen_shli_tl(t1, t1, 2);
25296 if (s12 & 0x200) {
25297 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25299 tcg_gen_add_tl(t1, t0, t1);
25300 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25302 if (sel == 1) {
25303 /* S32LDDR */
25304 tcg_gen_bswap32_tl(t1, t1);
25306 gen_store_mxu_gpr(t1, XRa);
25308 tcg_temp_free(t0);
25309 tcg_temp_free(t1);
25314 * MXU instruction category: logic
25315 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25317 * S32NOR S32AND S32OR S32XOR
25321 * S32NOR XRa, XRb, XRc
25322 * Update XRa with the result of logical bitwise 'nor' operation
25323 * applied to the content of XRb and XRc.
25325 * 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
25326 * +-----------+---------+-----+-------+-------+-------+-----------+
25327 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25328 * +-----------+---------+-----+-------+-------+-------+-----------+
25330 static void gen_mxu_S32NOR(DisasContext *ctx)
25332 uint32_t pad, XRc, XRb, XRa;
25334 pad = extract32(ctx->opcode, 21, 5);
25335 XRc = extract32(ctx->opcode, 14, 4);
25336 XRb = extract32(ctx->opcode, 10, 4);
25337 XRa = extract32(ctx->opcode, 6, 4);
25339 if (unlikely(pad != 0)) {
25340 /* opcode padding incorrect -> do nothing */
25341 } else if (unlikely(XRa == 0)) {
25342 /* destination is zero register -> do nothing */
25343 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25344 /* both operands zero registers -> just set destination to all 1s */
25345 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25346 } else if (unlikely(XRb == 0)) {
25347 /* XRb zero register -> just set destination to the negation of XRc */
25348 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25349 } else if (unlikely(XRc == 0)) {
25350 /* XRa zero register -> just set destination to the negation of XRb */
25351 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25352 } else if (unlikely(XRb == XRc)) {
25353 /* both operands same -> just set destination to the negation of XRb */
25354 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25355 } else {
25356 /* the most general case */
25357 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25362 * S32AND XRa, XRb, XRc
25363 * Update XRa with the result of logical bitwise 'and' operation
25364 * applied to the content of XRb and XRc.
25366 * 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
25367 * +-----------+---------+-----+-------+-------+-------+-----------+
25368 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25369 * +-----------+---------+-----+-------+-------+-------+-----------+
25371 static void gen_mxu_S32AND(DisasContext *ctx)
25373 uint32_t pad, XRc, XRb, XRa;
25375 pad = extract32(ctx->opcode, 21, 5);
25376 XRc = extract32(ctx->opcode, 14, 4);
25377 XRb = extract32(ctx->opcode, 10, 4);
25378 XRa = extract32(ctx->opcode, 6, 4);
25380 if (unlikely(pad != 0)) {
25381 /* opcode padding incorrect -> do nothing */
25382 } else if (unlikely(XRa == 0)) {
25383 /* destination is zero register -> do nothing */
25384 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25385 /* one of operands zero register -> just set destination to all 0s */
25386 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25387 } else if (unlikely(XRb == XRc)) {
25388 /* both operands same -> just set destination to one of them */
25389 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25390 } else {
25391 /* the most general case */
25392 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25397 * S32OR XRa, XRb, XRc
25398 * Update XRa with the result of logical bitwise 'or' operation
25399 * applied to the content of XRb and XRc.
25401 * 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
25402 * +-----------+---------+-----+-------+-------+-------+-----------+
25403 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25404 * +-----------+---------+-----+-------+-------+-------+-----------+
25406 static void gen_mxu_S32OR(DisasContext *ctx)
25408 uint32_t pad, XRc, XRb, XRa;
25410 pad = extract32(ctx->opcode, 21, 5);
25411 XRc = extract32(ctx->opcode, 14, 4);
25412 XRb = extract32(ctx->opcode, 10, 4);
25413 XRa = extract32(ctx->opcode, 6, 4);
25415 if (unlikely(pad != 0)) {
25416 /* opcode padding incorrect -> do nothing */
25417 } else if (unlikely(XRa == 0)) {
25418 /* destination is zero register -> do nothing */
25419 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25420 /* both operands zero registers -> just set destination to all 0s */
25421 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25422 } else if (unlikely(XRb == 0)) {
25423 /* XRb zero register -> just set destination to the content of XRc */
25424 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25425 } else if (unlikely(XRc == 0)) {
25426 /* XRc zero register -> just set destination to the content of XRb */
25427 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25428 } else if (unlikely(XRb == XRc)) {
25429 /* both operands same -> just set destination to one of them */
25430 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25431 } else {
25432 /* the most general case */
25433 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25438 * S32XOR XRa, XRb, XRc
25439 * Update XRa with the result of logical bitwise 'xor' operation
25440 * applied to the content of XRb and XRc.
25442 * 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
25443 * +-----------+---------+-----+-------+-------+-------+-----------+
25444 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25445 * +-----------+---------+-----+-------+-------+-------+-----------+
25447 static void gen_mxu_S32XOR(DisasContext *ctx)
25449 uint32_t pad, XRc, XRb, XRa;
25451 pad = extract32(ctx->opcode, 21, 5);
25452 XRc = extract32(ctx->opcode, 14, 4);
25453 XRb = extract32(ctx->opcode, 10, 4);
25454 XRa = extract32(ctx->opcode, 6, 4);
25456 if (unlikely(pad != 0)) {
25457 /* opcode padding incorrect -> do nothing */
25458 } else if (unlikely(XRa == 0)) {
25459 /* destination is zero register -> do nothing */
25460 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25461 /* both operands zero registers -> just set destination to all 0s */
25462 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25463 } else if (unlikely(XRb == 0)) {
25464 /* XRb zero register -> just set destination to the content of XRc */
25465 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25466 } else if (unlikely(XRc == 0)) {
25467 /* XRc zero register -> just set destination to the content of XRb */
25468 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25469 } else if (unlikely(XRb == XRc)) {
25470 /* both operands same -> just set destination to all 0s */
25471 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25472 } else {
25473 /* the most general case */
25474 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25480 * MXU instruction category max/min
25481 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25483 * S32MAX D16MAX Q8MAX
25484 * S32MIN D16MIN Q8MIN
25488 * S32MAX XRa, XRb, XRc
25489 * Update XRa with the maximum of signed 32-bit integers contained
25490 * in XRb and XRc.
25492 * S32MIN XRa, XRb, XRc
25493 * Update XRa with the minimum of signed 32-bit integers contained
25494 * in XRb and XRc.
25496 * 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
25497 * +-----------+---------+-----+-------+-------+-------+-----------+
25498 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25499 * +-----------+---------+-----+-------+-------+-------+-----------+
25501 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25503 uint32_t pad, opc, XRc, XRb, XRa;
25505 pad = extract32(ctx->opcode, 21, 5);
25506 opc = extract32(ctx->opcode, 18, 3);
25507 XRc = extract32(ctx->opcode, 14, 4);
25508 XRb = extract32(ctx->opcode, 10, 4);
25509 XRa = extract32(ctx->opcode, 6, 4);
25511 if (unlikely(pad != 0)) {
25512 /* opcode padding incorrect -> do nothing */
25513 } else if (unlikely(XRa == 0)) {
25514 /* destination is zero register -> do nothing */
25515 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25516 /* both operands zero registers -> just set destination to zero */
25517 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25518 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25519 /* exactly one operand is zero register - find which one is not...*/
25520 uint32_t XRx = XRb ? XRb : XRc;
25521 /* ...and do max/min operation with one operand 0 */
25522 if (opc == OPC_MXU_S32MAX) {
25523 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25524 } else {
25525 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25527 } else if (unlikely(XRb == XRc)) {
25528 /* both operands same -> just set destination to one of them */
25529 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25530 } else {
25531 /* the most general case */
25532 if (opc == OPC_MXU_S32MAX) {
25533 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25534 mxu_gpr[XRc - 1]);
25535 } else {
25536 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25537 mxu_gpr[XRc - 1]);
25543 * D16MAX
25544 * Update XRa with the 16-bit-wise maximums of signed integers
25545 * contained in XRb and XRc.
25547 * D16MIN
25548 * Update XRa with the 16-bit-wise minimums of signed integers
25549 * contained in XRb and XRc.
25551 * 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
25552 * +-----------+---------+-----+-------+-------+-------+-----------+
25553 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25554 * +-----------+---------+-----+-------+-------+-------+-----------+
25556 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25558 uint32_t pad, opc, XRc, XRb, XRa;
25560 pad = extract32(ctx->opcode, 21, 5);
25561 opc = extract32(ctx->opcode, 18, 3);
25562 XRc = extract32(ctx->opcode, 14, 4);
25563 XRb = extract32(ctx->opcode, 10, 4);
25564 XRa = extract32(ctx->opcode, 6, 4);
25566 if (unlikely(pad != 0)) {
25567 /* opcode padding incorrect -> do nothing */
25568 } else if (unlikely(XRc == 0)) {
25569 /* destination is zero register -> do nothing */
25570 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25571 /* both operands zero registers -> just set destination to zero */
25572 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25573 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25574 /* exactly one operand is zero register - find which one is not...*/
25575 uint32_t XRx = XRb ? XRb : XRc;
25576 /* ...and do half-word-wise max/min with one operand 0 */
25577 TCGv_i32 t0 = tcg_temp_new();
25578 TCGv_i32 t1 = tcg_const_i32(0);
25580 /* the left half-word first */
25581 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25582 if (opc == OPC_MXU_D16MAX) {
25583 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25584 } else {
25585 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25588 /* the right half-word */
25589 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25590 /* move half-words to the leftmost position */
25591 tcg_gen_shli_i32(t0, t0, 16);
25592 /* t0 will be max/min of t0 and t1 */
25593 if (opc == OPC_MXU_D16MAX) {
25594 tcg_gen_smax_i32(t0, t0, t1);
25595 } else {
25596 tcg_gen_smin_i32(t0, t0, t1);
25598 /* return resulting half-words to its original position */
25599 tcg_gen_shri_i32(t0, t0, 16);
25600 /* finaly update the destination */
25601 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25603 tcg_temp_free(t1);
25604 tcg_temp_free(t0);
25605 } else if (unlikely(XRb == XRc)) {
25606 /* both operands same -> just set destination to one of them */
25607 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25608 } else {
25609 /* the most general case */
25610 TCGv_i32 t0 = tcg_temp_new();
25611 TCGv_i32 t1 = tcg_temp_new();
25613 /* the left half-word first */
25614 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25615 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25616 if (opc == OPC_MXU_D16MAX) {
25617 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25618 } else {
25619 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25622 /* the right half-word */
25623 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25624 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25625 /* move half-words to the leftmost position */
25626 tcg_gen_shli_i32(t0, t0, 16);
25627 tcg_gen_shli_i32(t1, t1, 16);
25628 /* t0 will be max/min of t0 and t1 */
25629 if (opc == OPC_MXU_D16MAX) {
25630 tcg_gen_smax_i32(t0, t0, t1);
25631 } else {
25632 tcg_gen_smin_i32(t0, t0, t1);
25634 /* return resulting half-words to its original position */
25635 tcg_gen_shri_i32(t0, t0, 16);
25636 /* finaly update the destination */
25637 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25639 tcg_temp_free(t1);
25640 tcg_temp_free(t0);
25645 * Q8MAX
25646 * Update XRa with the 8-bit-wise maximums of signed integers
25647 * contained in XRb and XRc.
25649 * Q8MIN
25650 * Update XRa with the 8-bit-wise minimums of signed integers
25651 * contained in XRb and XRc.
25653 * 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
25654 * +-----------+---------+-----+-------+-------+-------+-----------+
25655 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25656 * +-----------+---------+-----+-------+-------+-------+-----------+
25658 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25660 uint32_t pad, opc, XRc, XRb, XRa;
25662 pad = extract32(ctx->opcode, 21, 5);
25663 opc = extract32(ctx->opcode, 18, 3);
25664 XRc = extract32(ctx->opcode, 14, 4);
25665 XRb = extract32(ctx->opcode, 10, 4);
25666 XRa = extract32(ctx->opcode, 6, 4);
25668 if (unlikely(pad != 0)) {
25669 /* opcode padding incorrect -> do nothing */
25670 } else if (unlikely(XRa == 0)) {
25671 /* destination is zero register -> do nothing */
25672 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25673 /* both operands zero registers -> just set destination to zero */
25674 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25675 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25676 /* exactly one operand is zero register - make it be the first...*/
25677 uint32_t XRx = XRb ? XRb : XRc;
25678 /* ...and do byte-wise max/min with one operand 0 */
25679 TCGv_i32 t0 = tcg_temp_new();
25680 TCGv_i32 t1 = tcg_const_i32(0);
25681 int32_t i;
25683 /* the leftmost byte (byte 3) first */
25684 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25685 if (opc == OPC_MXU_Q8MAX) {
25686 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25687 } else {
25688 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25691 /* bytes 2, 1, 0 */
25692 for (i = 2; i >= 0; i--) {
25693 /* extract the byte */
25694 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25695 /* move the byte to the leftmost position */
25696 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25697 /* t0 will be max/min of t0 and t1 */
25698 if (opc == OPC_MXU_Q8MAX) {
25699 tcg_gen_smax_i32(t0, t0, t1);
25700 } else {
25701 tcg_gen_smin_i32(t0, t0, t1);
25703 /* return resulting byte to its original position */
25704 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25705 /* finaly update the destination */
25706 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25709 tcg_temp_free(t1);
25710 tcg_temp_free(t0);
25711 } else if (unlikely(XRb == XRc)) {
25712 /* both operands same -> just set destination to one of them */
25713 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25714 } else {
25715 /* the most general case */
25716 TCGv_i32 t0 = tcg_temp_new();
25717 TCGv_i32 t1 = tcg_temp_new();
25718 int32_t i;
25720 /* the leftmost bytes (bytes 3) first */
25721 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25722 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25723 if (opc == OPC_MXU_Q8MAX) {
25724 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25725 } else {
25726 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25729 /* bytes 2, 1, 0 */
25730 for (i = 2; i >= 0; i--) {
25731 /* extract corresponding bytes */
25732 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25733 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25734 /* move the bytes to the leftmost position */
25735 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25736 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25737 /* t0 will be max/min of t0 and t1 */
25738 if (opc == OPC_MXU_Q8MAX) {
25739 tcg_gen_smax_i32(t0, t0, t1);
25740 } else {
25741 tcg_gen_smin_i32(t0, t0, t1);
25743 /* return resulting byte to its original position */
25744 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25745 /* finaly update the destination */
25746 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25749 tcg_temp_free(t1);
25750 tcg_temp_free(t0);
25756 * MXU instruction category: align
25757 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25759 * S32ALN S32ALNI
25763 * S32ALNI XRc, XRb, XRa, optn3
25764 * Arrange bytes from XRb and XRc according to one of five sets of
25765 * rules determined by optn3, and place the result in XRa.
25767 * 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
25768 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25769 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25770 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25773 static void gen_mxu_S32ALNI(DisasContext *ctx)
25775 uint32_t optn3, pad, XRc, XRb, XRa;
25777 optn3 = extract32(ctx->opcode, 23, 3);
25778 pad = extract32(ctx->opcode, 21, 2);
25779 XRc = extract32(ctx->opcode, 14, 4);
25780 XRb = extract32(ctx->opcode, 10, 4);
25781 XRa = extract32(ctx->opcode, 6, 4);
25783 if (unlikely(pad != 0)) {
25784 /* opcode padding incorrect -> do nothing */
25785 } else if (unlikely(XRa == 0)) {
25786 /* destination is zero register -> do nothing */
25787 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25788 /* both operands zero registers -> just set destination to all 0s */
25789 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25790 } else if (unlikely(XRb == 0)) {
25791 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25792 switch (optn3) {
25793 case MXU_OPTN3_PTN0:
25794 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25795 break;
25796 case MXU_OPTN3_PTN1:
25797 case MXU_OPTN3_PTN2:
25798 case MXU_OPTN3_PTN3:
25799 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25800 8 * (4 - optn3));
25801 break;
25802 case MXU_OPTN3_PTN4:
25803 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25804 break;
25806 } else if (unlikely(XRc == 0)) {
25807 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25808 switch (optn3) {
25809 case MXU_OPTN3_PTN0:
25810 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25811 break;
25812 case MXU_OPTN3_PTN1:
25813 case MXU_OPTN3_PTN2:
25814 case MXU_OPTN3_PTN3:
25815 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25816 break;
25817 case MXU_OPTN3_PTN4:
25818 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25819 break;
25821 } else if (unlikely(XRb == XRc)) {
25822 /* both operands same -> just rotation or moving from any of them */
25823 switch (optn3) {
25824 case MXU_OPTN3_PTN0:
25825 case MXU_OPTN3_PTN4:
25826 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25827 break;
25828 case MXU_OPTN3_PTN1:
25829 case MXU_OPTN3_PTN2:
25830 case MXU_OPTN3_PTN3:
25831 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25832 break;
25834 } else {
25835 /* the most general case */
25836 switch (optn3) {
25837 case MXU_OPTN3_PTN0:
25839 /* */
25840 /* XRb XRc */
25841 /* +---------------+ */
25842 /* | A B C D | E F G H */
25843 /* +-------+-------+ */
25844 /* | */
25845 /* XRa */
25846 /* */
25848 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25850 break;
25851 case MXU_OPTN3_PTN1:
25853 /* */
25854 /* XRb XRc */
25855 /* +-------------------+ */
25856 /* A | B C D E | F G H */
25857 /* +---------+---------+ */
25858 /* | */
25859 /* XRa */
25860 /* */
25862 TCGv_i32 t0 = tcg_temp_new();
25863 TCGv_i32 t1 = tcg_temp_new();
25865 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25866 tcg_gen_shli_i32(t0, t0, 8);
25868 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25869 tcg_gen_shri_i32(t1, t1, 24);
25871 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25873 tcg_temp_free(t1);
25874 tcg_temp_free(t0);
25876 break;
25877 case MXU_OPTN3_PTN2:
25879 /* */
25880 /* XRb XRc */
25881 /* +-------------------+ */
25882 /* A B | C D E F | G H */
25883 /* +---------+---------+ */
25884 /* | */
25885 /* XRa */
25886 /* */
25888 TCGv_i32 t0 = tcg_temp_new();
25889 TCGv_i32 t1 = tcg_temp_new();
25891 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25892 tcg_gen_shli_i32(t0, t0, 16);
25894 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25895 tcg_gen_shri_i32(t1, t1, 16);
25897 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25899 tcg_temp_free(t1);
25900 tcg_temp_free(t0);
25902 break;
25903 case MXU_OPTN3_PTN3:
25905 /* */
25906 /* XRb XRc */
25907 /* +-------------------+ */
25908 /* A B C | D E F G | H */
25909 /* +---------+---------+ */
25910 /* | */
25911 /* XRa */
25912 /* */
25914 TCGv_i32 t0 = tcg_temp_new();
25915 TCGv_i32 t1 = tcg_temp_new();
25917 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25918 tcg_gen_shli_i32(t0, t0, 24);
25920 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25921 tcg_gen_shri_i32(t1, t1, 8);
25923 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25925 tcg_temp_free(t1);
25926 tcg_temp_free(t0);
25928 break;
25929 case MXU_OPTN3_PTN4:
25931 /* */
25932 /* XRb XRc */
25933 /* +---------------+ */
25934 /* A B C D | E F G H | */
25935 /* +-------+-------+ */
25936 /* | */
25937 /* XRa */
25938 /* */
25940 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25942 break;
25949 * Decoding engine for MXU
25950 * =======================
25955 * Decode MXU pool00
25957 * 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
25958 * +-----------+---------+-----+-------+-------+-------+-----------+
25959 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25960 * +-----------+---------+-----+-------+-------+-------+-----------+
25963 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25965 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25967 switch (opcode) {
25968 case OPC_MXU_S32MAX:
25969 case OPC_MXU_S32MIN:
25970 gen_mxu_S32MAX_S32MIN(ctx);
25971 break;
25972 case OPC_MXU_D16MAX:
25973 case OPC_MXU_D16MIN:
25974 gen_mxu_D16MAX_D16MIN(ctx);
25975 break;
25976 case OPC_MXU_Q8MAX:
25977 case OPC_MXU_Q8MIN:
25978 gen_mxu_Q8MAX_Q8MIN(ctx);
25979 break;
25980 case OPC_MXU_Q8SLT:
25981 /* TODO: Implement emulation of Q8SLT instruction. */
25982 MIPS_INVAL("OPC_MXU_Q8SLT");
25983 generate_exception_end(ctx, EXCP_RI);
25984 break;
25985 case OPC_MXU_Q8SLTU:
25986 /* TODO: Implement emulation of Q8SLTU instruction. */
25987 MIPS_INVAL("OPC_MXU_Q8SLTU");
25988 generate_exception_end(ctx, EXCP_RI);
25989 break;
25990 default:
25991 MIPS_INVAL("decode_opc_mxu");
25992 generate_exception_end(ctx, EXCP_RI);
25993 break;
25999 * Decode MXU pool01
26001 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26002 * 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
26003 * +-----------+---------+-----+-------+-------+-------+-----------+
26004 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26005 * +-----------+---------+-----+-------+-------+-------+-----------+
26007 * Q8ADD:
26008 * 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
26009 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26010 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26011 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26014 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26016 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26018 switch (opcode) {
26019 case OPC_MXU_S32SLT:
26020 /* TODO: Implement emulation of S32SLT instruction. */
26021 MIPS_INVAL("OPC_MXU_S32SLT");
26022 generate_exception_end(ctx, EXCP_RI);
26023 break;
26024 case OPC_MXU_D16SLT:
26025 /* TODO: Implement emulation of D16SLT instruction. */
26026 MIPS_INVAL("OPC_MXU_D16SLT");
26027 generate_exception_end(ctx, EXCP_RI);
26028 break;
26029 case OPC_MXU_D16AVG:
26030 /* TODO: Implement emulation of D16AVG instruction. */
26031 MIPS_INVAL("OPC_MXU_D16AVG");
26032 generate_exception_end(ctx, EXCP_RI);
26033 break;
26034 case OPC_MXU_D16AVGR:
26035 /* TODO: Implement emulation of D16AVGR instruction. */
26036 MIPS_INVAL("OPC_MXU_D16AVGR");
26037 generate_exception_end(ctx, EXCP_RI);
26038 break;
26039 case OPC_MXU_Q8AVG:
26040 /* TODO: Implement emulation of Q8AVG instruction. */
26041 MIPS_INVAL("OPC_MXU_Q8AVG");
26042 generate_exception_end(ctx, EXCP_RI);
26043 break;
26044 case OPC_MXU_Q8AVGR:
26045 /* TODO: Implement emulation of Q8AVGR instruction. */
26046 MIPS_INVAL("OPC_MXU_Q8AVGR");
26047 generate_exception_end(ctx, EXCP_RI);
26048 break;
26049 case OPC_MXU_Q8ADD:
26050 /* TODO: Implement emulation of Q8ADD instruction. */
26051 MIPS_INVAL("OPC_MXU_Q8ADD");
26052 generate_exception_end(ctx, EXCP_RI);
26053 break;
26054 default:
26055 MIPS_INVAL("decode_opc_mxu");
26056 generate_exception_end(ctx, EXCP_RI);
26057 break;
26063 * Decode MXU pool02
26065 * 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
26066 * +-----------+---------+-----+-------+-------+-------+-----------+
26067 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26068 * +-----------+---------+-----+-------+-------+-------+-----------+
26071 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26073 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26075 switch (opcode) {
26076 case OPC_MXU_S32CPS:
26077 /* TODO: Implement emulation of S32CPS instruction. */
26078 MIPS_INVAL("OPC_MXU_S32CPS");
26079 generate_exception_end(ctx, EXCP_RI);
26080 break;
26081 case OPC_MXU_D16CPS:
26082 /* TODO: Implement emulation of D16CPS instruction. */
26083 MIPS_INVAL("OPC_MXU_D16CPS");
26084 generate_exception_end(ctx, EXCP_RI);
26085 break;
26086 case OPC_MXU_Q8ABD:
26087 /* TODO: Implement emulation of Q8ABD instruction. */
26088 MIPS_INVAL("OPC_MXU_Q8ABD");
26089 generate_exception_end(ctx, EXCP_RI);
26090 break;
26091 case OPC_MXU_Q16SAT:
26092 /* TODO: Implement emulation of Q16SAT instruction. */
26093 MIPS_INVAL("OPC_MXU_Q16SAT");
26094 generate_exception_end(ctx, EXCP_RI);
26095 break;
26096 default:
26097 MIPS_INVAL("decode_opc_mxu");
26098 generate_exception_end(ctx, EXCP_RI);
26099 break;
26105 * Decode MXU pool03
26107 * D16MULF:
26108 * 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
26109 * +-----------+---+---+-------+-------+-------+-------+-----------+
26110 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26111 * +-----------+---+---+-------+-------+-------+-------+-----------+
26113 * D16MULE:
26114 * 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
26115 * +-----------+---+---+-------+-------+-------+-------+-----------+
26116 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26117 * +-----------+---+---+-------+-------+-------+-------+-----------+
26120 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26122 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26124 switch (opcode) {
26125 case OPC_MXU_D16MULF:
26126 /* TODO: Implement emulation of D16MULF instruction. */
26127 MIPS_INVAL("OPC_MXU_D16MULF");
26128 generate_exception_end(ctx, EXCP_RI);
26129 break;
26130 case OPC_MXU_D16MULE:
26131 /* TODO: Implement emulation of D16MULE instruction. */
26132 MIPS_INVAL("OPC_MXU_D16MULE");
26133 generate_exception_end(ctx, EXCP_RI);
26134 break;
26135 default:
26136 MIPS_INVAL("decode_opc_mxu");
26137 generate_exception_end(ctx, EXCP_RI);
26138 break;
26144 * Decode MXU pool04
26146 * 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
26147 * +-----------+---------+-+-------------------+-------+-----------+
26148 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26149 * +-----------+---------+-+-------------------+-------+-----------+
26152 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26154 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26156 switch (opcode) {
26157 case OPC_MXU_S32LDD:
26158 case OPC_MXU_S32LDDR:
26159 gen_mxu_s32ldd_s32lddr(ctx);
26160 break;
26161 default:
26162 MIPS_INVAL("decode_opc_mxu");
26163 generate_exception_end(ctx, EXCP_RI);
26164 break;
26170 * Decode MXU pool05
26172 * 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
26173 * +-----------+---------+-+-------------------+-------+-----------+
26174 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26175 * +-----------+---------+-+-------------------+-------+-----------+
26178 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26180 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26182 switch (opcode) {
26183 case OPC_MXU_S32STD:
26184 /* TODO: Implement emulation of S32STD instruction. */
26185 MIPS_INVAL("OPC_MXU_S32STD");
26186 generate_exception_end(ctx, EXCP_RI);
26187 break;
26188 case OPC_MXU_S32STDR:
26189 /* TODO: Implement emulation of S32STDR instruction. */
26190 MIPS_INVAL("OPC_MXU_S32STDR");
26191 generate_exception_end(ctx, EXCP_RI);
26192 break;
26193 default:
26194 MIPS_INVAL("decode_opc_mxu");
26195 generate_exception_end(ctx, EXCP_RI);
26196 break;
26202 * Decode MXU pool06
26204 * 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
26205 * +-----------+---------+---------+---+-------+-------+-----------+
26206 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26207 * +-----------+---------+---------+---+-------+-------+-----------+
26210 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26212 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26214 switch (opcode) {
26215 case OPC_MXU_S32LDDV:
26216 /* TODO: Implement emulation of S32LDDV instruction. */
26217 MIPS_INVAL("OPC_MXU_S32LDDV");
26218 generate_exception_end(ctx, EXCP_RI);
26219 break;
26220 case OPC_MXU_S32LDDVR:
26221 /* TODO: Implement emulation of S32LDDVR instruction. */
26222 MIPS_INVAL("OPC_MXU_S32LDDVR");
26223 generate_exception_end(ctx, EXCP_RI);
26224 break;
26225 default:
26226 MIPS_INVAL("decode_opc_mxu");
26227 generate_exception_end(ctx, EXCP_RI);
26228 break;
26234 * Decode MXU pool07
26236 * 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
26237 * +-----------+---------+---------+---+-------+-------+-----------+
26238 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26239 * +-----------+---------+---------+---+-------+-------+-----------+
26242 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26244 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26246 switch (opcode) {
26247 case OPC_MXU_S32STDV:
26248 /* TODO: Implement emulation of S32TDV instruction. */
26249 MIPS_INVAL("OPC_MXU_S32TDV");
26250 generate_exception_end(ctx, EXCP_RI);
26251 break;
26252 case OPC_MXU_S32STDVR:
26253 /* TODO: Implement emulation of S32TDVR instruction. */
26254 MIPS_INVAL("OPC_MXU_S32TDVR");
26255 generate_exception_end(ctx, EXCP_RI);
26256 break;
26257 default:
26258 MIPS_INVAL("decode_opc_mxu");
26259 generate_exception_end(ctx, EXCP_RI);
26260 break;
26266 * Decode MXU pool08
26268 * 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
26269 * +-----------+---------+-+-------------------+-------+-----------+
26270 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26271 * +-----------+---------+-+-------------------+-------+-----------+
26274 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26276 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26278 switch (opcode) {
26279 case OPC_MXU_S32LDI:
26280 /* TODO: Implement emulation of S32LDI instruction. */
26281 MIPS_INVAL("OPC_MXU_S32LDI");
26282 generate_exception_end(ctx, EXCP_RI);
26283 break;
26284 case OPC_MXU_S32LDIR:
26285 /* TODO: Implement emulation of S32LDIR instruction. */
26286 MIPS_INVAL("OPC_MXU_S32LDIR");
26287 generate_exception_end(ctx, EXCP_RI);
26288 break;
26289 default:
26290 MIPS_INVAL("decode_opc_mxu");
26291 generate_exception_end(ctx, EXCP_RI);
26292 break;
26298 * Decode MXU pool09
26300 * 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
26301 * +-----------+---------+-+-------------------+-------+-----------+
26302 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26303 * +-----------+---------+-+-------------------+-------+-----------+
26306 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26308 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26310 switch (opcode) {
26311 case OPC_MXU_S32SDI:
26312 /* TODO: Implement emulation of S32SDI instruction. */
26313 MIPS_INVAL("OPC_MXU_S32SDI");
26314 generate_exception_end(ctx, EXCP_RI);
26315 break;
26316 case OPC_MXU_S32SDIR:
26317 /* TODO: Implement emulation of S32SDIR instruction. */
26318 MIPS_INVAL("OPC_MXU_S32SDIR");
26319 generate_exception_end(ctx, EXCP_RI);
26320 break;
26321 default:
26322 MIPS_INVAL("decode_opc_mxu");
26323 generate_exception_end(ctx, EXCP_RI);
26324 break;
26330 * Decode MXU pool10
26332 * 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
26333 * +-----------+---------+---------+---+-------+-------+-----------+
26334 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26335 * +-----------+---------+---------+---+-------+-------+-----------+
26338 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26340 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26342 switch (opcode) {
26343 case OPC_MXU_S32LDIV:
26344 /* TODO: Implement emulation of S32LDIV instruction. */
26345 MIPS_INVAL("OPC_MXU_S32LDIV");
26346 generate_exception_end(ctx, EXCP_RI);
26347 break;
26348 case OPC_MXU_S32LDIVR:
26349 /* TODO: Implement emulation of S32LDIVR instruction. */
26350 MIPS_INVAL("OPC_MXU_S32LDIVR");
26351 generate_exception_end(ctx, EXCP_RI);
26352 break;
26353 default:
26354 MIPS_INVAL("decode_opc_mxu");
26355 generate_exception_end(ctx, EXCP_RI);
26356 break;
26362 * Decode MXU pool11
26364 * 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
26365 * +-----------+---------+---------+---+-------+-------+-----------+
26366 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26367 * +-----------+---------+---------+---+-------+-------+-----------+
26370 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26372 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26374 switch (opcode) {
26375 case OPC_MXU_S32SDIV:
26376 /* TODO: Implement emulation of S32SDIV instruction. */
26377 MIPS_INVAL("OPC_MXU_S32SDIV");
26378 generate_exception_end(ctx, EXCP_RI);
26379 break;
26380 case OPC_MXU_S32SDIVR:
26381 /* TODO: Implement emulation of S32SDIVR instruction. */
26382 MIPS_INVAL("OPC_MXU_S32SDIVR");
26383 generate_exception_end(ctx, EXCP_RI);
26384 break;
26385 default:
26386 MIPS_INVAL("decode_opc_mxu");
26387 generate_exception_end(ctx, EXCP_RI);
26388 break;
26394 * Decode MXU pool12
26396 * 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
26397 * +-----------+---+---+-------+-------+-------+-------+-----------+
26398 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26399 * +-----------+---+---+-------+-------+-------+-------+-----------+
26402 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26404 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26406 switch (opcode) {
26407 case OPC_MXU_D32ACC:
26408 /* TODO: Implement emulation of D32ACC instruction. */
26409 MIPS_INVAL("OPC_MXU_D32ACC");
26410 generate_exception_end(ctx, EXCP_RI);
26411 break;
26412 case OPC_MXU_D32ACCM:
26413 /* TODO: Implement emulation of D32ACCM instruction. */
26414 MIPS_INVAL("OPC_MXU_D32ACCM");
26415 generate_exception_end(ctx, EXCP_RI);
26416 break;
26417 case OPC_MXU_D32ASUM:
26418 /* TODO: Implement emulation of D32ASUM instruction. */
26419 MIPS_INVAL("OPC_MXU_D32ASUM");
26420 generate_exception_end(ctx, EXCP_RI);
26421 break;
26422 default:
26423 MIPS_INVAL("decode_opc_mxu");
26424 generate_exception_end(ctx, EXCP_RI);
26425 break;
26431 * Decode MXU pool13
26433 * 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
26434 * +-----------+---+---+-------+-------+-------+-------+-----------+
26435 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26436 * +-----------+---+---+-------+-------+-------+-------+-----------+
26439 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26441 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26443 switch (opcode) {
26444 case OPC_MXU_Q16ACC:
26445 /* TODO: Implement emulation of Q16ACC instruction. */
26446 MIPS_INVAL("OPC_MXU_Q16ACC");
26447 generate_exception_end(ctx, EXCP_RI);
26448 break;
26449 case OPC_MXU_Q16ACCM:
26450 /* TODO: Implement emulation of Q16ACCM instruction. */
26451 MIPS_INVAL("OPC_MXU_Q16ACCM");
26452 generate_exception_end(ctx, EXCP_RI);
26453 break;
26454 case OPC_MXU_Q16ASUM:
26455 /* TODO: Implement emulation of Q16ASUM instruction. */
26456 MIPS_INVAL("OPC_MXU_Q16ASUM");
26457 generate_exception_end(ctx, EXCP_RI);
26458 break;
26459 default:
26460 MIPS_INVAL("decode_opc_mxu");
26461 generate_exception_end(ctx, EXCP_RI);
26462 break;
26468 * Decode MXU pool14
26470 * Q8ADDE, Q8ACCE:
26471 * 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
26472 * +-----------+---+---+-------+-------+-------+-------+-----------+
26473 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26474 * +-----------+---+---+-------+-------+-------+-------+-----------+
26476 * D8SUM, D8SUMC:
26477 * 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
26478 * +-----------+---+---+-------+-------+-------+-------+-----------+
26479 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26480 * +-----------+---+---+-------+-------+-------+-------+-----------+
26483 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26485 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26487 switch (opcode) {
26488 case OPC_MXU_Q8ADDE:
26489 /* TODO: Implement emulation of Q8ADDE instruction. */
26490 MIPS_INVAL("OPC_MXU_Q8ADDE");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26493 case OPC_MXU_D8SUM:
26494 /* TODO: Implement emulation of D8SUM instruction. */
26495 MIPS_INVAL("OPC_MXU_D8SUM");
26496 generate_exception_end(ctx, EXCP_RI);
26497 break;
26498 case OPC_MXU_D8SUMC:
26499 /* TODO: Implement emulation of D8SUMC instruction. */
26500 MIPS_INVAL("OPC_MXU_D8SUMC");
26501 generate_exception_end(ctx, EXCP_RI);
26502 break;
26503 default:
26504 MIPS_INVAL("decode_opc_mxu");
26505 generate_exception_end(ctx, EXCP_RI);
26506 break;
26512 * Decode MXU pool15
26514 * S32MUL, S32MULU, S32EXTRV:
26515 * 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
26516 * +-----------+---------+---------+---+-------+-------+-----------+
26517 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26518 * +-----------+---------+---------+---+-------+-------+-----------+
26520 * S32EXTR:
26521 * 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
26522 * +-----------+---------+---------+---+-------+-------+-----------+
26523 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26524 * +-----------+---------+---------+---+-------+-------+-----------+
26527 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26529 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26531 switch (opcode) {
26532 case OPC_MXU_S32MUL:
26533 /* TODO: Implement emulation of S32MUL instruction. */
26534 MIPS_INVAL("OPC_MXU_S32MUL");
26535 generate_exception_end(ctx, EXCP_RI);
26536 break;
26537 case OPC_MXU_S32MULU:
26538 /* TODO: Implement emulation of S32MULU instruction. */
26539 MIPS_INVAL("OPC_MXU_S32MULU");
26540 generate_exception_end(ctx, EXCP_RI);
26541 break;
26542 case OPC_MXU_S32EXTR:
26543 /* TODO: Implement emulation of S32EXTR instruction. */
26544 MIPS_INVAL("OPC_MXU_S32EXTR");
26545 generate_exception_end(ctx, EXCP_RI);
26546 break;
26547 case OPC_MXU_S32EXTRV:
26548 /* TODO: Implement emulation of S32EXTRV instruction. */
26549 MIPS_INVAL("OPC_MXU_S32EXTRV");
26550 generate_exception_end(ctx, EXCP_RI);
26551 break;
26552 default:
26553 MIPS_INVAL("decode_opc_mxu");
26554 generate_exception_end(ctx, EXCP_RI);
26555 break;
26561 * Decode MXU pool16
26563 * D32SARW:
26564 * 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
26565 * +-----------+---------+-----+-------+-------+-------+-----------+
26566 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26567 * +-----------+---------+-----+-------+-------+-------+-----------+
26569 * S32ALN:
26570 * 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
26571 * +-----------+---------+-----+-------+-------+-------+-----------+
26572 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26573 * +-----------+---------+-----+-------+-------+-------+-----------+
26575 * S32ALNI:
26576 * 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
26577 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26578 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26579 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26581 * S32LUI:
26582 * 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
26583 * +-----------+-----+---+-----+-------+---------------+-----------+
26584 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26585 * +-----------+-----+---+-----+-------+---------------+-----------+
26587 * S32NOR, S32AND, S32OR, S32XOR:
26588 * 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
26589 * +-----------+---------+-----+-------+-------+-------+-----------+
26590 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26591 * +-----------+---------+-----+-------+-------+-------+-----------+
26594 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26596 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26598 switch (opcode) {
26599 case OPC_MXU_D32SARW:
26600 /* TODO: Implement emulation of D32SARW instruction. */
26601 MIPS_INVAL("OPC_MXU_D32SARW");
26602 generate_exception_end(ctx, EXCP_RI);
26603 break;
26604 case OPC_MXU_S32ALN:
26605 /* TODO: Implement emulation of S32ALN instruction. */
26606 MIPS_INVAL("OPC_MXU_S32ALN");
26607 generate_exception_end(ctx, EXCP_RI);
26608 break;
26609 case OPC_MXU_S32ALNI:
26610 gen_mxu_S32ALNI(ctx);
26611 break;
26612 case OPC_MXU_S32LUI:
26613 /* TODO: Implement emulation of S32LUI instruction. */
26614 MIPS_INVAL("OPC_MXU_S32LUI");
26615 generate_exception_end(ctx, EXCP_RI);
26616 break;
26617 case OPC_MXU_S32NOR:
26618 gen_mxu_S32NOR(ctx);
26619 break;
26620 case OPC_MXU_S32AND:
26621 gen_mxu_S32AND(ctx);
26622 break;
26623 case OPC_MXU_S32OR:
26624 gen_mxu_S32OR(ctx);
26625 break;
26626 case OPC_MXU_S32XOR:
26627 gen_mxu_S32XOR(ctx);
26628 break;
26629 default:
26630 MIPS_INVAL("decode_opc_mxu");
26631 generate_exception_end(ctx, EXCP_RI);
26632 break;
26638 * Decode MXU pool17
26640 * 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
26641 * +-----------+---------+---------+---+---------+-----+-----------+
26642 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26643 * +-----------+---------+---------+---+---------+-----+-----------+
26646 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26648 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26650 switch (opcode) {
26651 case OPC_MXU_LXW:
26652 /* TODO: Implement emulation of LXW instruction. */
26653 MIPS_INVAL("OPC_MXU_LXW");
26654 generate_exception_end(ctx, EXCP_RI);
26655 break;
26656 case OPC_MXU_LXH:
26657 /* TODO: Implement emulation of LXH instruction. */
26658 MIPS_INVAL("OPC_MXU_LXH");
26659 generate_exception_end(ctx, EXCP_RI);
26660 break;
26661 case OPC_MXU_LXHU:
26662 /* TODO: Implement emulation of LXHU instruction. */
26663 MIPS_INVAL("OPC_MXU_LXHU");
26664 generate_exception_end(ctx, EXCP_RI);
26665 break;
26666 case OPC_MXU_LXB:
26667 /* TODO: Implement emulation of LXB instruction. */
26668 MIPS_INVAL("OPC_MXU_LXB");
26669 generate_exception_end(ctx, EXCP_RI);
26670 break;
26671 case OPC_MXU_LXBU:
26672 /* TODO: Implement emulation of LXBU instruction. */
26673 MIPS_INVAL("OPC_MXU_LXBU");
26674 generate_exception_end(ctx, EXCP_RI);
26675 break;
26676 default:
26677 MIPS_INVAL("decode_opc_mxu");
26678 generate_exception_end(ctx, EXCP_RI);
26679 break;
26684 * Decode MXU pool18
26686 * 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
26687 * +-----------+---------+-----+-------+-------+-------+-----------+
26688 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26689 * +-----------+---------+-----+-------+-------+-------+-----------+
26692 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26694 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26696 switch (opcode) {
26697 case OPC_MXU_D32SLLV:
26698 /* TODO: Implement emulation of D32SLLV instruction. */
26699 MIPS_INVAL("OPC_MXU_D32SLLV");
26700 generate_exception_end(ctx, EXCP_RI);
26701 break;
26702 case OPC_MXU_D32SLRV:
26703 /* TODO: Implement emulation of D32SLRV instruction. */
26704 MIPS_INVAL("OPC_MXU_D32SLRV");
26705 generate_exception_end(ctx, EXCP_RI);
26706 break;
26707 case OPC_MXU_D32SARV:
26708 /* TODO: Implement emulation of D32SARV instruction. */
26709 MIPS_INVAL("OPC_MXU_D32SARV");
26710 generate_exception_end(ctx, EXCP_RI);
26711 break;
26712 case OPC_MXU_Q16SLLV:
26713 /* TODO: Implement emulation of Q16SLLV instruction. */
26714 MIPS_INVAL("OPC_MXU_Q16SLLV");
26715 generate_exception_end(ctx, EXCP_RI);
26716 break;
26717 case OPC_MXU_Q16SLRV:
26718 /* TODO: Implement emulation of Q16SLRV instruction. */
26719 MIPS_INVAL("OPC_MXU_Q16SLRV");
26720 generate_exception_end(ctx, EXCP_RI);
26721 break;
26722 case OPC_MXU_Q16SARV:
26723 /* TODO: Implement emulation of Q16SARV instruction. */
26724 MIPS_INVAL("OPC_MXU_Q16SARV");
26725 generate_exception_end(ctx, EXCP_RI);
26726 break;
26727 default:
26728 MIPS_INVAL("decode_opc_mxu");
26729 generate_exception_end(ctx, EXCP_RI);
26730 break;
26736 * Decode MXU pool19
26738 * 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
26739 * +-----------+---+---+-------+-------+-------+-------+-----------+
26740 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26741 * +-----------+---+---+-------+-------+-------+-------+-----------+
26744 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26746 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26748 switch (opcode) {
26749 case OPC_MXU_Q8MUL:
26750 case OPC_MXU_Q8MULSU:
26751 gen_mxu_q8mul_q8mulsu(ctx);
26752 break;
26753 default:
26754 MIPS_INVAL("decode_opc_mxu");
26755 generate_exception_end(ctx, EXCP_RI);
26756 break;
26762 * Decode MXU pool20
26764 * 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
26765 * +-----------+---------+-----+-------+-------+-------+-----------+
26766 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26767 * +-----------+---------+-----+-------+-------+-------+-----------+
26770 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26772 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26774 switch (opcode) {
26775 case OPC_MXU_Q8MOVZ:
26776 /* TODO: Implement emulation of Q8MOVZ instruction. */
26777 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26778 generate_exception_end(ctx, EXCP_RI);
26779 break;
26780 case OPC_MXU_Q8MOVN:
26781 /* TODO: Implement emulation of Q8MOVN instruction. */
26782 MIPS_INVAL("OPC_MXU_Q8MOVN");
26783 generate_exception_end(ctx, EXCP_RI);
26784 break;
26785 case OPC_MXU_D16MOVZ:
26786 /* TODO: Implement emulation of D16MOVZ instruction. */
26787 MIPS_INVAL("OPC_MXU_D16MOVZ");
26788 generate_exception_end(ctx, EXCP_RI);
26789 break;
26790 case OPC_MXU_D16MOVN:
26791 /* TODO: Implement emulation of D16MOVN instruction. */
26792 MIPS_INVAL("OPC_MXU_D16MOVN");
26793 generate_exception_end(ctx, EXCP_RI);
26794 break;
26795 case OPC_MXU_S32MOVZ:
26796 /* TODO: Implement emulation of S32MOVZ instruction. */
26797 MIPS_INVAL("OPC_MXU_S32MOVZ");
26798 generate_exception_end(ctx, EXCP_RI);
26799 break;
26800 case OPC_MXU_S32MOVN:
26801 /* TODO: Implement emulation of S32MOVN instruction. */
26802 MIPS_INVAL("OPC_MXU_S32MOVN");
26803 generate_exception_end(ctx, EXCP_RI);
26804 break;
26805 default:
26806 MIPS_INVAL("decode_opc_mxu");
26807 generate_exception_end(ctx, EXCP_RI);
26808 break;
26814 * Decode MXU pool21
26816 * 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
26817 * +-----------+---+---+-------+-------+-------+-------+-----------+
26818 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26819 * +-----------+---+---+-------+-------+-------+-------+-----------+
26822 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26824 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26826 switch (opcode) {
26827 case OPC_MXU_Q8MAC:
26828 /* TODO: Implement emulation of Q8MAC instruction. */
26829 MIPS_INVAL("OPC_MXU_Q8MAC");
26830 generate_exception_end(ctx, EXCP_RI);
26831 break;
26832 case OPC_MXU_Q8MACSU:
26833 /* TODO: Implement emulation of Q8MACSU instruction. */
26834 MIPS_INVAL("OPC_MXU_Q8MACSU");
26835 generate_exception_end(ctx, EXCP_RI);
26836 break;
26837 default:
26838 MIPS_INVAL("decode_opc_mxu");
26839 generate_exception_end(ctx, EXCP_RI);
26840 break;
26846 * Main MXU decoding function
26848 * 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
26849 * +-----------+---------------------------------------+-----------+
26850 * | SPECIAL2 | |x x x x x x|
26851 * +-----------+---------------------------------------+-----------+
26854 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26857 * TODO: Investigate necessity of including handling of
26858 * CLZ, CLO, SDBB in this function, as they belong to
26859 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26861 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26863 if (opcode == OPC__MXU_MUL) {
26864 uint32_t rs, rt, rd, op1;
26866 rs = extract32(ctx->opcode, 21, 5);
26867 rt = extract32(ctx->opcode, 16, 5);
26868 rd = extract32(ctx->opcode, 11, 5);
26869 op1 = MASK_SPECIAL2(ctx->opcode);
26871 gen_arith(ctx, op1, rd, rs, rt);
26873 return;
26876 if (opcode == OPC_MXU_S32M2I) {
26877 gen_mxu_s32m2i(ctx);
26878 return;
26881 if (opcode == OPC_MXU_S32I2M) {
26882 gen_mxu_s32i2m(ctx);
26883 return;
26887 TCGv t_mxu_cr = tcg_temp_new();
26888 TCGLabel *l_exit = gen_new_label();
26890 gen_load_mxu_cr(t_mxu_cr);
26891 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26892 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26894 switch (opcode) {
26895 case OPC_MXU_S32MADD:
26896 /* TODO: Implement emulation of S32MADD instruction. */
26897 MIPS_INVAL("OPC_MXU_S32MADD");
26898 generate_exception_end(ctx, EXCP_RI);
26899 break;
26900 case OPC_MXU_S32MADDU:
26901 /* TODO: Implement emulation of S32MADDU instruction. */
26902 MIPS_INVAL("OPC_MXU_S32MADDU");
26903 generate_exception_end(ctx, EXCP_RI);
26904 break;
26905 case OPC_MXU__POOL00:
26906 decode_opc_mxu__pool00(env, ctx);
26907 break;
26908 case OPC_MXU_S32MSUB:
26909 /* TODO: Implement emulation of S32MSUB instruction. */
26910 MIPS_INVAL("OPC_MXU_S32MSUB");
26911 generate_exception_end(ctx, EXCP_RI);
26912 break;
26913 case OPC_MXU_S32MSUBU:
26914 /* TODO: Implement emulation of S32MSUBU instruction. */
26915 MIPS_INVAL("OPC_MXU_S32MSUBU");
26916 generate_exception_end(ctx, EXCP_RI);
26917 break;
26918 case OPC_MXU__POOL01:
26919 decode_opc_mxu__pool01(env, ctx);
26920 break;
26921 case OPC_MXU__POOL02:
26922 decode_opc_mxu__pool02(env, ctx);
26923 break;
26924 case OPC_MXU_D16MUL:
26925 gen_mxu_d16mul(ctx);
26926 break;
26927 case OPC_MXU__POOL03:
26928 decode_opc_mxu__pool03(env, ctx);
26929 break;
26930 case OPC_MXU_D16MAC:
26931 gen_mxu_d16mac(ctx);
26932 break;
26933 case OPC_MXU_D16MACF:
26934 /* TODO: Implement emulation of D16MACF instruction. */
26935 MIPS_INVAL("OPC_MXU_D16MACF");
26936 generate_exception_end(ctx, EXCP_RI);
26937 break;
26938 case OPC_MXU_D16MADL:
26939 /* TODO: Implement emulation of D16MADL instruction. */
26940 MIPS_INVAL("OPC_MXU_D16MADL");
26941 generate_exception_end(ctx, EXCP_RI);
26942 break;
26943 case OPC_MXU_S16MAD:
26944 /* TODO: Implement emulation of S16MAD instruction. */
26945 MIPS_INVAL("OPC_MXU_S16MAD");
26946 generate_exception_end(ctx, EXCP_RI);
26947 break;
26948 case OPC_MXU_Q16ADD:
26949 /* TODO: Implement emulation of Q16ADD instruction. */
26950 MIPS_INVAL("OPC_MXU_Q16ADD");
26951 generate_exception_end(ctx, EXCP_RI);
26952 break;
26953 case OPC_MXU_D16MACE:
26954 /* TODO: Implement emulation of D16MACE instruction. */
26955 MIPS_INVAL("OPC_MXU_D16MACE");
26956 generate_exception_end(ctx, EXCP_RI);
26957 break;
26958 case OPC_MXU__POOL04:
26959 decode_opc_mxu__pool04(env, ctx);
26960 break;
26961 case OPC_MXU__POOL05:
26962 decode_opc_mxu__pool05(env, ctx);
26963 break;
26964 case OPC_MXU__POOL06:
26965 decode_opc_mxu__pool06(env, ctx);
26966 break;
26967 case OPC_MXU__POOL07:
26968 decode_opc_mxu__pool07(env, ctx);
26969 break;
26970 case OPC_MXU__POOL08:
26971 decode_opc_mxu__pool08(env, ctx);
26972 break;
26973 case OPC_MXU__POOL09:
26974 decode_opc_mxu__pool09(env, ctx);
26975 break;
26976 case OPC_MXU__POOL10:
26977 decode_opc_mxu__pool10(env, ctx);
26978 break;
26979 case OPC_MXU__POOL11:
26980 decode_opc_mxu__pool11(env, ctx);
26981 break;
26982 case OPC_MXU_D32ADD:
26983 /* TODO: Implement emulation of D32ADD instruction. */
26984 MIPS_INVAL("OPC_MXU_D32ADD");
26985 generate_exception_end(ctx, EXCP_RI);
26986 break;
26987 case OPC_MXU__POOL12:
26988 decode_opc_mxu__pool12(env, ctx);
26989 break;
26990 case OPC_MXU__POOL13:
26991 decode_opc_mxu__pool13(env, ctx);
26992 break;
26993 case OPC_MXU__POOL14:
26994 decode_opc_mxu__pool14(env, ctx);
26995 break;
26996 case OPC_MXU_Q8ACCE:
26997 /* TODO: Implement emulation of Q8ACCE instruction. */
26998 MIPS_INVAL("OPC_MXU_Q8ACCE");
26999 generate_exception_end(ctx, EXCP_RI);
27000 break;
27001 case OPC_MXU_S8LDD:
27002 gen_mxu_s8ldd(ctx);
27003 break;
27004 case OPC_MXU_S8STD:
27005 /* TODO: Implement emulation of S8STD instruction. */
27006 MIPS_INVAL("OPC_MXU_S8STD");
27007 generate_exception_end(ctx, EXCP_RI);
27008 break;
27009 case OPC_MXU_S8LDI:
27010 /* TODO: Implement emulation of S8LDI instruction. */
27011 MIPS_INVAL("OPC_MXU_S8LDI");
27012 generate_exception_end(ctx, EXCP_RI);
27013 break;
27014 case OPC_MXU_S8SDI:
27015 /* TODO: Implement emulation of S8SDI instruction. */
27016 MIPS_INVAL("OPC_MXU_S8SDI");
27017 generate_exception_end(ctx, EXCP_RI);
27018 break;
27019 case OPC_MXU__POOL15:
27020 decode_opc_mxu__pool15(env, ctx);
27021 break;
27022 case OPC_MXU__POOL16:
27023 decode_opc_mxu__pool16(env, ctx);
27024 break;
27025 case OPC_MXU__POOL17:
27026 decode_opc_mxu__pool17(env, ctx);
27027 break;
27028 case OPC_MXU_S16LDD:
27029 /* TODO: Implement emulation of S16LDD instruction. */
27030 MIPS_INVAL("OPC_MXU_S16LDD");
27031 generate_exception_end(ctx, EXCP_RI);
27032 break;
27033 case OPC_MXU_S16STD:
27034 /* TODO: Implement emulation of S16STD instruction. */
27035 MIPS_INVAL("OPC_MXU_S16STD");
27036 generate_exception_end(ctx, EXCP_RI);
27037 break;
27038 case OPC_MXU_S16LDI:
27039 /* TODO: Implement emulation of S16LDI instruction. */
27040 MIPS_INVAL("OPC_MXU_S16LDI");
27041 generate_exception_end(ctx, EXCP_RI);
27042 break;
27043 case OPC_MXU_S16SDI:
27044 /* TODO: Implement emulation of S16SDI instruction. */
27045 MIPS_INVAL("OPC_MXU_S16SDI");
27046 generate_exception_end(ctx, EXCP_RI);
27047 break;
27048 case OPC_MXU_D32SLL:
27049 /* TODO: Implement emulation of D32SLL instruction. */
27050 MIPS_INVAL("OPC_MXU_D32SLL");
27051 generate_exception_end(ctx, EXCP_RI);
27052 break;
27053 case OPC_MXU_D32SLR:
27054 /* TODO: Implement emulation of D32SLR instruction. */
27055 MIPS_INVAL("OPC_MXU_D32SLR");
27056 generate_exception_end(ctx, EXCP_RI);
27057 break;
27058 case OPC_MXU_D32SARL:
27059 /* TODO: Implement emulation of D32SARL instruction. */
27060 MIPS_INVAL("OPC_MXU_D32SARL");
27061 generate_exception_end(ctx, EXCP_RI);
27062 break;
27063 case OPC_MXU_D32SAR:
27064 /* TODO: Implement emulation of D32SAR instruction. */
27065 MIPS_INVAL("OPC_MXU_D32SAR");
27066 generate_exception_end(ctx, EXCP_RI);
27067 break;
27068 case OPC_MXU_Q16SLL:
27069 /* TODO: Implement emulation of Q16SLL instruction. */
27070 MIPS_INVAL("OPC_MXU_Q16SLL");
27071 generate_exception_end(ctx, EXCP_RI);
27072 break;
27073 case OPC_MXU_Q16SLR:
27074 /* TODO: Implement emulation of Q16SLR instruction. */
27075 MIPS_INVAL("OPC_MXU_Q16SLR");
27076 generate_exception_end(ctx, EXCP_RI);
27077 break;
27078 case OPC_MXU__POOL18:
27079 decode_opc_mxu__pool18(env, ctx);
27080 break;
27081 case OPC_MXU_Q16SAR:
27082 /* TODO: Implement emulation of Q16SAR instruction. */
27083 MIPS_INVAL("OPC_MXU_Q16SAR");
27084 generate_exception_end(ctx, EXCP_RI);
27085 break;
27086 case OPC_MXU__POOL19:
27087 decode_opc_mxu__pool19(env, ctx);
27088 break;
27089 case OPC_MXU__POOL20:
27090 decode_opc_mxu__pool20(env, ctx);
27091 break;
27092 case OPC_MXU__POOL21:
27093 decode_opc_mxu__pool21(env, ctx);
27094 break;
27095 case OPC_MXU_Q16SCOP:
27096 /* TODO: Implement emulation of Q16SCOP instruction. */
27097 MIPS_INVAL("OPC_MXU_Q16SCOP");
27098 generate_exception_end(ctx, EXCP_RI);
27099 break;
27100 case OPC_MXU_Q8MADL:
27101 /* TODO: Implement emulation of Q8MADL instruction. */
27102 MIPS_INVAL("OPC_MXU_Q8MADL");
27103 generate_exception_end(ctx, EXCP_RI);
27104 break;
27105 case OPC_MXU_S32SFL:
27106 /* TODO: Implement emulation of S32SFL instruction. */
27107 MIPS_INVAL("OPC_MXU_S32SFL");
27108 generate_exception_end(ctx, EXCP_RI);
27109 break;
27110 case OPC_MXU_Q8SAD:
27111 /* TODO: Implement emulation of Q8SAD instruction. */
27112 MIPS_INVAL("OPC_MXU_Q8SAD");
27113 generate_exception_end(ctx, EXCP_RI);
27114 break;
27115 default:
27116 MIPS_INVAL("decode_opc_mxu");
27117 generate_exception_end(ctx, EXCP_RI);
27120 gen_set_label(l_exit);
27121 tcg_temp_free(t_mxu_cr);
27125 #endif /* !defined(TARGET_MIPS64) */
27128 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27130 int rs, rt, rd;
27131 uint32_t op1;
27133 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27135 rs = (ctx->opcode >> 21) & 0x1f;
27136 rt = (ctx->opcode >> 16) & 0x1f;
27137 rd = (ctx->opcode >> 11) & 0x1f;
27139 op1 = MASK_SPECIAL2(ctx->opcode);
27140 switch (op1) {
27141 case OPC_MADD: /* Multiply and add/sub */
27142 case OPC_MADDU:
27143 case OPC_MSUB:
27144 case OPC_MSUBU:
27145 check_insn(ctx, ISA_MIPS32);
27146 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27147 break;
27148 case OPC_MUL:
27149 gen_arith(ctx, op1, rd, rs, rt);
27150 break;
27151 case OPC_DIV_G_2F:
27152 case OPC_DIVU_G_2F:
27153 case OPC_MULT_G_2F:
27154 case OPC_MULTU_G_2F:
27155 case OPC_MOD_G_2F:
27156 case OPC_MODU_G_2F:
27157 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27158 gen_loongson_integer(ctx, op1, rd, rs, rt);
27159 break;
27160 case OPC_CLO:
27161 case OPC_CLZ:
27162 check_insn(ctx, ISA_MIPS32);
27163 gen_cl(ctx, op1, rd, rs);
27164 break;
27165 case OPC_SDBBP:
27166 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27167 gen_helper_do_semihosting(cpu_env);
27168 } else {
27170 * XXX: not clear which exception should be raised
27171 * when in debug mode...
27173 check_insn(ctx, ISA_MIPS32);
27174 generate_exception_end(ctx, EXCP_DBp);
27176 break;
27177 #if defined(TARGET_MIPS64)
27178 case OPC_DCLO:
27179 case OPC_DCLZ:
27180 check_insn(ctx, ISA_MIPS64);
27181 check_mips_64(ctx);
27182 gen_cl(ctx, op1, rd, rs);
27183 break;
27184 case OPC_DMULT_G_2F:
27185 case OPC_DMULTU_G_2F:
27186 case OPC_DDIV_G_2F:
27187 case OPC_DDIVU_G_2F:
27188 case OPC_DMOD_G_2F:
27189 case OPC_DMODU_G_2F:
27190 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27191 gen_loongson_integer(ctx, op1, rd, rs, rt);
27192 break;
27193 #endif
27194 default: /* Invalid */
27195 MIPS_INVAL("special2_legacy");
27196 generate_exception_end(ctx, EXCP_RI);
27197 break;
27201 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27203 int rs, rt, rd, sa;
27204 uint32_t op1, op2;
27205 int16_t imm;
27207 rs = (ctx->opcode >> 21) & 0x1f;
27208 rt = (ctx->opcode >> 16) & 0x1f;
27209 rd = (ctx->opcode >> 11) & 0x1f;
27210 sa = (ctx->opcode >> 6) & 0x1f;
27211 imm = (int16_t)ctx->opcode >> 7;
27213 op1 = MASK_SPECIAL3(ctx->opcode);
27214 switch (op1) {
27215 case R6_OPC_PREF:
27216 if (rt >= 24) {
27217 /* hint codes 24-31 are reserved and signal RI */
27218 generate_exception_end(ctx, EXCP_RI);
27220 /* Treat as NOP. */
27221 break;
27222 case R6_OPC_CACHE:
27223 check_cp0_enabled(ctx);
27224 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27225 gen_cache_operation(ctx, rt, rs, imm);
27227 break;
27228 case R6_OPC_SC:
27229 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27230 break;
27231 case R6_OPC_LL:
27232 gen_ld(ctx, op1, rt, rs, imm);
27233 break;
27234 case OPC_BSHFL:
27236 if (rd == 0) {
27237 /* Treat as NOP. */
27238 break;
27240 op2 = MASK_BSHFL(ctx->opcode);
27241 switch (op2) {
27242 case OPC_ALIGN:
27243 case OPC_ALIGN_1:
27244 case OPC_ALIGN_2:
27245 case OPC_ALIGN_3:
27246 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27247 break;
27248 case OPC_BITSWAP:
27249 gen_bitswap(ctx, op2, rd, rt);
27250 break;
27253 break;
27254 #ifndef CONFIG_USER_ONLY
27255 case OPC_GINV:
27256 if (unlikely(ctx->gi <= 1)) {
27257 generate_exception_end(ctx, EXCP_RI);
27259 check_cp0_enabled(ctx);
27260 switch ((ctx->opcode >> 6) & 3) {
27261 case 0: /* GINVI */
27262 /* Treat as NOP. */
27263 break;
27264 case 2: /* GINVT */
27265 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27266 break;
27267 default:
27268 generate_exception_end(ctx, EXCP_RI);
27269 break;
27271 break;
27272 #endif
27273 #if defined(TARGET_MIPS64)
27274 case R6_OPC_SCD:
27275 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27276 break;
27277 case R6_OPC_LLD:
27278 gen_ld(ctx, op1, rt, rs, imm);
27279 break;
27280 case OPC_DBSHFL:
27281 check_mips_64(ctx);
27283 if (rd == 0) {
27284 /* Treat as NOP. */
27285 break;
27287 op2 = MASK_DBSHFL(ctx->opcode);
27288 switch (op2) {
27289 case OPC_DALIGN:
27290 case OPC_DALIGN_1:
27291 case OPC_DALIGN_2:
27292 case OPC_DALIGN_3:
27293 case OPC_DALIGN_4:
27294 case OPC_DALIGN_5:
27295 case OPC_DALIGN_6:
27296 case OPC_DALIGN_7:
27297 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27298 break;
27299 case OPC_DBITSWAP:
27300 gen_bitswap(ctx, op2, rd, rt);
27301 break;
27305 break;
27306 #endif
27307 default: /* Invalid */
27308 MIPS_INVAL("special3_r6");
27309 generate_exception_end(ctx, EXCP_RI);
27310 break;
27314 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27316 int rs, rt, rd;
27317 uint32_t op1, op2;
27319 rs = (ctx->opcode >> 21) & 0x1f;
27320 rt = (ctx->opcode >> 16) & 0x1f;
27321 rd = (ctx->opcode >> 11) & 0x1f;
27323 op1 = MASK_SPECIAL3(ctx->opcode);
27324 switch (op1) {
27325 case OPC_DIV_G_2E:
27326 case OPC_DIVU_G_2E:
27327 case OPC_MOD_G_2E:
27328 case OPC_MODU_G_2E:
27329 case OPC_MULT_G_2E:
27330 case OPC_MULTU_G_2E:
27332 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27333 * the same mask and op1.
27335 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27336 op2 = MASK_ADDUH_QB(ctx->opcode);
27337 switch (op2) {
27338 case OPC_ADDUH_QB:
27339 case OPC_ADDUH_R_QB:
27340 case OPC_ADDQH_PH:
27341 case OPC_ADDQH_R_PH:
27342 case OPC_ADDQH_W:
27343 case OPC_ADDQH_R_W:
27344 case OPC_SUBUH_QB:
27345 case OPC_SUBUH_R_QB:
27346 case OPC_SUBQH_PH:
27347 case OPC_SUBQH_R_PH:
27348 case OPC_SUBQH_W:
27349 case OPC_SUBQH_R_W:
27350 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27351 break;
27352 case OPC_MUL_PH:
27353 case OPC_MUL_S_PH:
27354 case OPC_MULQ_S_W:
27355 case OPC_MULQ_RS_W:
27356 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27357 break;
27358 default:
27359 MIPS_INVAL("MASK ADDUH.QB");
27360 generate_exception_end(ctx, EXCP_RI);
27361 break;
27363 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27364 gen_loongson_integer(ctx, op1, rd, rs, rt);
27365 } else {
27366 generate_exception_end(ctx, EXCP_RI);
27368 break;
27369 case OPC_LX_DSP:
27370 op2 = MASK_LX(ctx->opcode);
27371 switch (op2) {
27372 #if defined(TARGET_MIPS64)
27373 case OPC_LDX:
27374 #endif
27375 case OPC_LBUX:
27376 case OPC_LHX:
27377 case OPC_LWX:
27378 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27379 break;
27380 default: /* Invalid */
27381 MIPS_INVAL("MASK LX");
27382 generate_exception_end(ctx, EXCP_RI);
27383 break;
27385 break;
27386 case OPC_ABSQ_S_PH_DSP:
27387 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27388 switch (op2) {
27389 case OPC_ABSQ_S_QB:
27390 case OPC_ABSQ_S_PH:
27391 case OPC_ABSQ_S_W:
27392 case OPC_PRECEQ_W_PHL:
27393 case OPC_PRECEQ_W_PHR:
27394 case OPC_PRECEQU_PH_QBL:
27395 case OPC_PRECEQU_PH_QBR:
27396 case OPC_PRECEQU_PH_QBLA:
27397 case OPC_PRECEQU_PH_QBRA:
27398 case OPC_PRECEU_PH_QBL:
27399 case OPC_PRECEU_PH_QBR:
27400 case OPC_PRECEU_PH_QBLA:
27401 case OPC_PRECEU_PH_QBRA:
27402 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27403 break;
27404 case OPC_BITREV:
27405 case OPC_REPL_QB:
27406 case OPC_REPLV_QB:
27407 case OPC_REPL_PH:
27408 case OPC_REPLV_PH:
27409 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27410 break;
27411 default:
27412 MIPS_INVAL("MASK ABSQ_S.PH");
27413 generate_exception_end(ctx, EXCP_RI);
27414 break;
27416 break;
27417 case OPC_ADDU_QB_DSP:
27418 op2 = MASK_ADDU_QB(ctx->opcode);
27419 switch (op2) {
27420 case OPC_ADDQ_PH:
27421 case OPC_ADDQ_S_PH:
27422 case OPC_ADDQ_S_W:
27423 case OPC_ADDU_QB:
27424 case OPC_ADDU_S_QB:
27425 case OPC_ADDU_PH:
27426 case OPC_ADDU_S_PH:
27427 case OPC_SUBQ_PH:
27428 case OPC_SUBQ_S_PH:
27429 case OPC_SUBQ_S_W:
27430 case OPC_SUBU_QB:
27431 case OPC_SUBU_S_QB:
27432 case OPC_SUBU_PH:
27433 case OPC_SUBU_S_PH:
27434 case OPC_ADDSC:
27435 case OPC_ADDWC:
27436 case OPC_MODSUB:
27437 case OPC_RADDU_W_QB:
27438 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27439 break;
27440 case OPC_MULEU_S_PH_QBL:
27441 case OPC_MULEU_S_PH_QBR:
27442 case OPC_MULQ_RS_PH:
27443 case OPC_MULEQ_S_W_PHL:
27444 case OPC_MULEQ_S_W_PHR:
27445 case OPC_MULQ_S_PH:
27446 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27447 break;
27448 default: /* Invalid */
27449 MIPS_INVAL("MASK ADDU.QB");
27450 generate_exception_end(ctx, EXCP_RI);
27451 break;
27454 break;
27455 case OPC_CMPU_EQ_QB_DSP:
27456 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27457 switch (op2) {
27458 case OPC_PRECR_SRA_PH_W:
27459 case OPC_PRECR_SRA_R_PH_W:
27460 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27461 break;
27462 case OPC_PRECR_QB_PH:
27463 case OPC_PRECRQ_QB_PH:
27464 case OPC_PRECRQ_PH_W:
27465 case OPC_PRECRQ_RS_PH_W:
27466 case OPC_PRECRQU_S_QB_PH:
27467 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27468 break;
27469 case OPC_CMPU_EQ_QB:
27470 case OPC_CMPU_LT_QB:
27471 case OPC_CMPU_LE_QB:
27472 case OPC_CMP_EQ_PH:
27473 case OPC_CMP_LT_PH:
27474 case OPC_CMP_LE_PH:
27475 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27476 break;
27477 case OPC_CMPGU_EQ_QB:
27478 case OPC_CMPGU_LT_QB:
27479 case OPC_CMPGU_LE_QB:
27480 case OPC_CMPGDU_EQ_QB:
27481 case OPC_CMPGDU_LT_QB:
27482 case OPC_CMPGDU_LE_QB:
27483 case OPC_PICK_QB:
27484 case OPC_PICK_PH:
27485 case OPC_PACKRL_PH:
27486 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27487 break;
27488 default: /* Invalid */
27489 MIPS_INVAL("MASK CMPU.EQ.QB");
27490 generate_exception_end(ctx, EXCP_RI);
27491 break;
27493 break;
27494 case OPC_SHLL_QB_DSP:
27495 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27496 break;
27497 case OPC_DPA_W_PH_DSP:
27498 op2 = MASK_DPA_W_PH(ctx->opcode);
27499 switch (op2) {
27500 case OPC_DPAU_H_QBL:
27501 case OPC_DPAU_H_QBR:
27502 case OPC_DPSU_H_QBL:
27503 case OPC_DPSU_H_QBR:
27504 case OPC_DPA_W_PH:
27505 case OPC_DPAX_W_PH:
27506 case OPC_DPAQ_S_W_PH:
27507 case OPC_DPAQX_S_W_PH:
27508 case OPC_DPAQX_SA_W_PH:
27509 case OPC_DPS_W_PH:
27510 case OPC_DPSX_W_PH:
27511 case OPC_DPSQ_S_W_PH:
27512 case OPC_DPSQX_S_W_PH:
27513 case OPC_DPSQX_SA_W_PH:
27514 case OPC_MULSAQ_S_W_PH:
27515 case OPC_DPAQ_SA_L_W:
27516 case OPC_DPSQ_SA_L_W:
27517 case OPC_MAQ_S_W_PHL:
27518 case OPC_MAQ_S_W_PHR:
27519 case OPC_MAQ_SA_W_PHL:
27520 case OPC_MAQ_SA_W_PHR:
27521 case OPC_MULSA_W_PH:
27522 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27523 break;
27524 default: /* Invalid */
27525 MIPS_INVAL("MASK DPAW.PH");
27526 generate_exception_end(ctx, EXCP_RI);
27527 break;
27529 break;
27530 case OPC_INSV_DSP:
27531 op2 = MASK_INSV(ctx->opcode);
27532 switch (op2) {
27533 case OPC_INSV:
27534 check_dsp(ctx);
27536 TCGv t0, t1;
27538 if (rt == 0) {
27539 break;
27542 t0 = tcg_temp_new();
27543 t1 = tcg_temp_new();
27545 gen_load_gpr(t0, rt);
27546 gen_load_gpr(t1, rs);
27548 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27550 tcg_temp_free(t0);
27551 tcg_temp_free(t1);
27552 break;
27554 default: /* Invalid */
27555 MIPS_INVAL("MASK INSV");
27556 generate_exception_end(ctx, EXCP_RI);
27557 break;
27559 break;
27560 case OPC_APPEND_DSP:
27561 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27562 break;
27563 case OPC_EXTR_W_DSP:
27564 op2 = MASK_EXTR_W(ctx->opcode);
27565 switch (op2) {
27566 case OPC_EXTR_W:
27567 case OPC_EXTR_R_W:
27568 case OPC_EXTR_RS_W:
27569 case OPC_EXTR_S_H:
27570 case OPC_EXTRV_S_H:
27571 case OPC_EXTRV_W:
27572 case OPC_EXTRV_R_W:
27573 case OPC_EXTRV_RS_W:
27574 case OPC_EXTP:
27575 case OPC_EXTPV:
27576 case OPC_EXTPDP:
27577 case OPC_EXTPDPV:
27578 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27579 break;
27580 case OPC_RDDSP:
27581 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27582 break;
27583 case OPC_SHILO:
27584 case OPC_SHILOV:
27585 case OPC_MTHLIP:
27586 case OPC_WRDSP:
27587 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27588 break;
27589 default: /* Invalid */
27590 MIPS_INVAL("MASK EXTR.W");
27591 generate_exception_end(ctx, EXCP_RI);
27592 break;
27594 break;
27595 #if defined(TARGET_MIPS64)
27596 case OPC_DDIV_G_2E:
27597 case OPC_DDIVU_G_2E:
27598 case OPC_DMULT_G_2E:
27599 case OPC_DMULTU_G_2E:
27600 case OPC_DMOD_G_2E:
27601 case OPC_DMODU_G_2E:
27602 check_insn(ctx, INSN_LOONGSON2E);
27603 gen_loongson_integer(ctx, op1, rd, rs, rt);
27604 break;
27605 case OPC_ABSQ_S_QH_DSP:
27606 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27607 switch (op2) {
27608 case OPC_PRECEQ_L_PWL:
27609 case OPC_PRECEQ_L_PWR:
27610 case OPC_PRECEQ_PW_QHL:
27611 case OPC_PRECEQ_PW_QHR:
27612 case OPC_PRECEQ_PW_QHLA:
27613 case OPC_PRECEQ_PW_QHRA:
27614 case OPC_PRECEQU_QH_OBL:
27615 case OPC_PRECEQU_QH_OBR:
27616 case OPC_PRECEQU_QH_OBLA:
27617 case OPC_PRECEQU_QH_OBRA:
27618 case OPC_PRECEU_QH_OBL:
27619 case OPC_PRECEU_QH_OBR:
27620 case OPC_PRECEU_QH_OBLA:
27621 case OPC_PRECEU_QH_OBRA:
27622 case OPC_ABSQ_S_OB:
27623 case OPC_ABSQ_S_PW:
27624 case OPC_ABSQ_S_QH:
27625 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27626 break;
27627 case OPC_REPL_OB:
27628 case OPC_REPL_PW:
27629 case OPC_REPL_QH:
27630 case OPC_REPLV_OB:
27631 case OPC_REPLV_PW:
27632 case OPC_REPLV_QH:
27633 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27634 break;
27635 default: /* Invalid */
27636 MIPS_INVAL("MASK ABSQ_S.QH");
27637 generate_exception_end(ctx, EXCP_RI);
27638 break;
27640 break;
27641 case OPC_ADDU_OB_DSP:
27642 op2 = MASK_ADDU_OB(ctx->opcode);
27643 switch (op2) {
27644 case OPC_RADDU_L_OB:
27645 case OPC_SUBQ_PW:
27646 case OPC_SUBQ_S_PW:
27647 case OPC_SUBQ_QH:
27648 case OPC_SUBQ_S_QH:
27649 case OPC_SUBU_OB:
27650 case OPC_SUBU_S_OB:
27651 case OPC_SUBU_QH:
27652 case OPC_SUBU_S_QH:
27653 case OPC_SUBUH_OB:
27654 case OPC_SUBUH_R_OB:
27655 case OPC_ADDQ_PW:
27656 case OPC_ADDQ_S_PW:
27657 case OPC_ADDQ_QH:
27658 case OPC_ADDQ_S_QH:
27659 case OPC_ADDU_OB:
27660 case OPC_ADDU_S_OB:
27661 case OPC_ADDU_QH:
27662 case OPC_ADDU_S_QH:
27663 case OPC_ADDUH_OB:
27664 case OPC_ADDUH_R_OB:
27665 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27666 break;
27667 case OPC_MULEQ_S_PW_QHL:
27668 case OPC_MULEQ_S_PW_QHR:
27669 case OPC_MULEU_S_QH_OBL:
27670 case OPC_MULEU_S_QH_OBR:
27671 case OPC_MULQ_RS_QH:
27672 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27673 break;
27674 default: /* Invalid */
27675 MIPS_INVAL("MASK ADDU.OB");
27676 generate_exception_end(ctx, EXCP_RI);
27677 break;
27679 break;
27680 case OPC_CMPU_EQ_OB_DSP:
27681 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27682 switch (op2) {
27683 case OPC_PRECR_SRA_QH_PW:
27684 case OPC_PRECR_SRA_R_QH_PW:
27685 /* Return value is rt. */
27686 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27687 break;
27688 case OPC_PRECR_OB_QH:
27689 case OPC_PRECRQ_OB_QH:
27690 case OPC_PRECRQ_PW_L:
27691 case OPC_PRECRQ_QH_PW:
27692 case OPC_PRECRQ_RS_QH_PW:
27693 case OPC_PRECRQU_S_OB_QH:
27694 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27695 break;
27696 case OPC_CMPU_EQ_OB:
27697 case OPC_CMPU_LT_OB:
27698 case OPC_CMPU_LE_OB:
27699 case OPC_CMP_EQ_QH:
27700 case OPC_CMP_LT_QH:
27701 case OPC_CMP_LE_QH:
27702 case OPC_CMP_EQ_PW:
27703 case OPC_CMP_LT_PW:
27704 case OPC_CMP_LE_PW:
27705 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27706 break;
27707 case OPC_CMPGDU_EQ_OB:
27708 case OPC_CMPGDU_LT_OB:
27709 case OPC_CMPGDU_LE_OB:
27710 case OPC_CMPGU_EQ_OB:
27711 case OPC_CMPGU_LT_OB:
27712 case OPC_CMPGU_LE_OB:
27713 case OPC_PACKRL_PW:
27714 case OPC_PICK_OB:
27715 case OPC_PICK_PW:
27716 case OPC_PICK_QH:
27717 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27718 break;
27719 default: /* Invalid */
27720 MIPS_INVAL("MASK CMPU_EQ.OB");
27721 generate_exception_end(ctx, EXCP_RI);
27722 break;
27724 break;
27725 case OPC_DAPPEND_DSP:
27726 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27727 break;
27728 case OPC_DEXTR_W_DSP:
27729 op2 = MASK_DEXTR_W(ctx->opcode);
27730 switch (op2) {
27731 case OPC_DEXTP:
27732 case OPC_DEXTPDP:
27733 case OPC_DEXTPDPV:
27734 case OPC_DEXTPV:
27735 case OPC_DEXTR_L:
27736 case OPC_DEXTR_R_L:
27737 case OPC_DEXTR_RS_L:
27738 case OPC_DEXTR_W:
27739 case OPC_DEXTR_R_W:
27740 case OPC_DEXTR_RS_W:
27741 case OPC_DEXTR_S_H:
27742 case OPC_DEXTRV_L:
27743 case OPC_DEXTRV_R_L:
27744 case OPC_DEXTRV_RS_L:
27745 case OPC_DEXTRV_S_H:
27746 case OPC_DEXTRV_W:
27747 case OPC_DEXTRV_R_W:
27748 case OPC_DEXTRV_RS_W:
27749 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27750 break;
27751 case OPC_DMTHLIP:
27752 case OPC_DSHILO:
27753 case OPC_DSHILOV:
27754 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27755 break;
27756 default: /* Invalid */
27757 MIPS_INVAL("MASK EXTR.W");
27758 generate_exception_end(ctx, EXCP_RI);
27759 break;
27761 break;
27762 case OPC_DPAQ_W_QH_DSP:
27763 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27764 switch (op2) {
27765 case OPC_DPAU_H_OBL:
27766 case OPC_DPAU_H_OBR:
27767 case OPC_DPSU_H_OBL:
27768 case OPC_DPSU_H_OBR:
27769 case OPC_DPA_W_QH:
27770 case OPC_DPAQ_S_W_QH:
27771 case OPC_DPS_W_QH:
27772 case OPC_DPSQ_S_W_QH:
27773 case OPC_MULSAQ_S_W_QH:
27774 case OPC_DPAQ_SA_L_PW:
27775 case OPC_DPSQ_SA_L_PW:
27776 case OPC_MULSAQ_S_L_PW:
27777 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27778 break;
27779 case OPC_MAQ_S_W_QHLL:
27780 case OPC_MAQ_S_W_QHLR:
27781 case OPC_MAQ_S_W_QHRL:
27782 case OPC_MAQ_S_W_QHRR:
27783 case OPC_MAQ_SA_W_QHLL:
27784 case OPC_MAQ_SA_W_QHLR:
27785 case OPC_MAQ_SA_W_QHRL:
27786 case OPC_MAQ_SA_W_QHRR:
27787 case OPC_MAQ_S_L_PWL:
27788 case OPC_MAQ_S_L_PWR:
27789 case OPC_DMADD:
27790 case OPC_DMADDU:
27791 case OPC_DMSUB:
27792 case OPC_DMSUBU:
27793 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27794 break;
27795 default: /* Invalid */
27796 MIPS_INVAL("MASK DPAQ.W.QH");
27797 generate_exception_end(ctx, EXCP_RI);
27798 break;
27800 break;
27801 case OPC_DINSV_DSP:
27802 op2 = MASK_INSV(ctx->opcode);
27803 switch (op2) {
27804 case OPC_DINSV:
27806 TCGv t0, t1;
27808 if (rt == 0) {
27809 break;
27811 check_dsp(ctx);
27813 t0 = tcg_temp_new();
27814 t1 = tcg_temp_new();
27816 gen_load_gpr(t0, rt);
27817 gen_load_gpr(t1, rs);
27819 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27821 tcg_temp_free(t0);
27822 tcg_temp_free(t1);
27823 break;
27825 default: /* Invalid */
27826 MIPS_INVAL("MASK DINSV");
27827 generate_exception_end(ctx, EXCP_RI);
27828 break;
27830 break;
27831 case OPC_SHLL_OB_DSP:
27832 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27833 break;
27834 #endif
27835 default: /* Invalid */
27836 MIPS_INVAL("special3_legacy");
27837 generate_exception_end(ctx, EXCP_RI);
27838 break;
27843 #if defined(TARGET_MIPS64)
27845 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27847 uint32_t opc = MASK_MMI0(ctx->opcode);
27849 switch (opc) {
27850 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27851 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27852 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27853 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27854 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27855 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27856 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27857 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27858 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27859 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27860 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27861 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27862 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27863 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27864 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27865 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27866 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27867 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27868 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27869 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27870 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27871 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27872 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27873 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27874 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27875 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27876 break;
27877 default:
27878 MIPS_INVAL("TX79 MMI class MMI0");
27879 generate_exception_end(ctx, EXCP_RI);
27880 break;
27884 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27886 uint32_t opc = MASK_MMI1(ctx->opcode);
27888 switch (opc) {
27889 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27890 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27891 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27892 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27893 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27894 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27895 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27896 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27897 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27898 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27899 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27900 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27901 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27902 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27903 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27904 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27905 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27906 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27907 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27908 break;
27909 default:
27910 MIPS_INVAL("TX79 MMI class MMI1");
27911 generate_exception_end(ctx, EXCP_RI);
27912 break;
27916 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27918 uint32_t opc = MASK_MMI2(ctx->opcode);
27920 switch (opc) {
27921 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27922 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27923 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27924 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27925 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27926 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27927 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27928 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27929 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27930 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27931 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27932 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27933 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27934 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27935 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27936 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27937 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27938 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27939 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27940 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27941 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27942 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27943 break;
27944 case MMI_OPC_2_PCPYLD:
27945 gen_mmi_pcpyld(ctx);
27946 break;
27947 default:
27948 MIPS_INVAL("TX79 MMI class MMI2");
27949 generate_exception_end(ctx, EXCP_RI);
27950 break;
27954 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27956 uint32_t opc = MASK_MMI3(ctx->opcode);
27958 switch (opc) {
27959 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27960 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27961 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27962 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27963 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27964 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27965 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27966 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27967 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27968 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27969 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27970 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27971 break;
27972 case MMI_OPC_3_PCPYH:
27973 gen_mmi_pcpyh(ctx);
27974 break;
27975 case MMI_OPC_3_PCPYUD:
27976 gen_mmi_pcpyud(ctx);
27977 break;
27978 default:
27979 MIPS_INVAL("TX79 MMI class MMI3");
27980 generate_exception_end(ctx, EXCP_RI);
27981 break;
27985 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27987 uint32_t opc = MASK_MMI(ctx->opcode);
27988 int rs = extract32(ctx->opcode, 21, 5);
27989 int rt = extract32(ctx->opcode, 16, 5);
27990 int rd = extract32(ctx->opcode, 11, 5);
27992 switch (opc) {
27993 case MMI_OPC_CLASS_MMI0:
27994 decode_mmi0(env, ctx);
27995 break;
27996 case MMI_OPC_CLASS_MMI1:
27997 decode_mmi1(env, ctx);
27998 break;
27999 case MMI_OPC_CLASS_MMI2:
28000 decode_mmi2(env, ctx);
28001 break;
28002 case MMI_OPC_CLASS_MMI3:
28003 decode_mmi3(env, ctx);
28004 break;
28005 case MMI_OPC_MULT1:
28006 case MMI_OPC_MULTU1:
28007 case MMI_OPC_MADD:
28008 case MMI_OPC_MADDU:
28009 case MMI_OPC_MADD1:
28010 case MMI_OPC_MADDU1:
28011 gen_mul_txx9(ctx, opc, rd, rs, rt);
28012 break;
28013 case MMI_OPC_DIV1:
28014 case MMI_OPC_DIVU1:
28015 gen_div1_tx79(ctx, opc, rs, rt);
28016 break;
28017 case MMI_OPC_MTLO1:
28018 case MMI_OPC_MTHI1:
28019 gen_HILO1_tx79(ctx, opc, rs);
28020 break;
28021 case MMI_OPC_MFLO1:
28022 case MMI_OPC_MFHI1:
28023 gen_HILO1_tx79(ctx, opc, rd);
28024 break;
28025 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28026 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28027 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28028 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28029 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28030 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28031 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28032 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28033 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28034 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
28035 break;
28036 default:
28037 MIPS_INVAL("TX79 MMI class");
28038 generate_exception_end(ctx, EXCP_RI);
28039 break;
28043 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28045 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
28048 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28050 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
28054 * The TX79-specific instruction Store Quadword
28056 * +--------+-------+-------+------------------------+
28057 * | 011111 | base | rt | offset | SQ
28058 * +--------+-------+-------+------------------------+
28059 * 6 5 5 16
28061 * has the same opcode as the Read Hardware Register instruction
28063 * +--------+-------+-------+-------+-------+--------+
28064 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28065 * +--------+-------+-------+-------+-------+--------+
28066 * 6 5 5 5 5 6
28068 * that is required, trapped and emulated by the Linux kernel. However, all
28069 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28070 * offset is odd. Therefore all valid SQ instructions can execute normally.
28071 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28072 * between SQ and RDHWR, as the Linux kernel does.
28074 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28076 int base = extract32(ctx->opcode, 21, 5);
28077 int rt = extract32(ctx->opcode, 16, 5);
28078 int offset = extract32(ctx->opcode, 0, 16);
28080 #ifdef CONFIG_USER_ONLY
28081 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28082 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28084 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28085 int rd = extract32(ctx->opcode, 11, 5);
28087 gen_rdhwr(ctx, rt, rd, 0);
28088 return;
28090 #endif
28092 gen_mmi_sq(ctx, base, rt, offset);
28095 #endif
28097 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28099 int rs, rt, rd, sa;
28100 uint32_t op1, op2;
28101 int16_t imm;
28103 rs = (ctx->opcode >> 21) & 0x1f;
28104 rt = (ctx->opcode >> 16) & 0x1f;
28105 rd = (ctx->opcode >> 11) & 0x1f;
28106 sa = (ctx->opcode >> 6) & 0x1f;
28107 imm = sextract32(ctx->opcode, 7, 9);
28109 op1 = MASK_SPECIAL3(ctx->opcode);
28112 * EVA loads and stores overlap Loongson 2E instructions decoded by
28113 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28114 * EVA is absent.
28116 if (ctx->eva) {
28117 switch (op1) {
28118 case OPC_LWLE:
28119 case OPC_LWRE:
28120 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28121 /* fall through */
28122 case OPC_LBUE:
28123 case OPC_LHUE:
28124 case OPC_LBE:
28125 case OPC_LHE:
28126 case OPC_LLE:
28127 case OPC_LWE:
28128 check_cp0_enabled(ctx);
28129 gen_ld(ctx, op1, rt, rs, imm);
28130 return;
28131 case OPC_SWLE:
28132 case OPC_SWRE:
28133 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28134 /* fall through */
28135 case OPC_SBE:
28136 case OPC_SHE:
28137 case OPC_SWE:
28138 check_cp0_enabled(ctx);
28139 gen_st(ctx, op1, rt, rs, imm);
28140 return;
28141 case OPC_SCE:
28142 check_cp0_enabled(ctx);
28143 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28144 return;
28145 case OPC_CACHEE:
28146 check_cp0_enabled(ctx);
28147 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28148 gen_cache_operation(ctx, rt, rs, imm);
28150 /* Treat as NOP. */
28151 return;
28152 case OPC_PREFE:
28153 check_cp0_enabled(ctx);
28154 /* Treat as NOP. */
28155 return;
28159 switch (op1) {
28160 case OPC_EXT:
28161 case OPC_INS:
28162 check_insn(ctx, ISA_MIPS32R2);
28163 gen_bitops(ctx, op1, rt, rs, sa, rd);
28164 break;
28165 case OPC_BSHFL:
28166 op2 = MASK_BSHFL(ctx->opcode);
28167 switch (op2) {
28168 case OPC_ALIGN:
28169 case OPC_ALIGN_1:
28170 case OPC_ALIGN_2:
28171 case OPC_ALIGN_3:
28172 case OPC_BITSWAP:
28173 check_insn(ctx, ISA_MIPS32R6);
28174 decode_opc_special3_r6(env, ctx);
28175 break;
28176 default:
28177 check_insn(ctx, ISA_MIPS32R2);
28178 gen_bshfl(ctx, op2, rt, rd);
28179 break;
28181 break;
28182 #if defined(TARGET_MIPS64)
28183 case OPC_DEXTM:
28184 case OPC_DEXTU:
28185 case OPC_DEXT:
28186 case OPC_DINSM:
28187 case OPC_DINSU:
28188 case OPC_DINS:
28189 check_insn(ctx, ISA_MIPS64R2);
28190 check_mips_64(ctx);
28191 gen_bitops(ctx, op1, rt, rs, sa, rd);
28192 break;
28193 case OPC_DBSHFL:
28194 op2 = MASK_DBSHFL(ctx->opcode);
28195 switch (op2) {
28196 case OPC_DALIGN:
28197 case OPC_DALIGN_1:
28198 case OPC_DALIGN_2:
28199 case OPC_DALIGN_3:
28200 case OPC_DALIGN_4:
28201 case OPC_DALIGN_5:
28202 case OPC_DALIGN_6:
28203 case OPC_DALIGN_7:
28204 case OPC_DBITSWAP:
28205 check_insn(ctx, ISA_MIPS32R6);
28206 decode_opc_special3_r6(env, ctx);
28207 break;
28208 default:
28209 check_insn(ctx, ISA_MIPS64R2);
28210 check_mips_64(ctx);
28211 op2 = MASK_DBSHFL(ctx->opcode);
28212 gen_bshfl(ctx, op2, rt, rd);
28213 break;
28215 break;
28216 #endif
28217 case OPC_RDHWR:
28218 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28219 break;
28220 case OPC_FORK:
28221 check_mt(ctx);
28223 TCGv t0 = tcg_temp_new();
28224 TCGv t1 = tcg_temp_new();
28226 gen_load_gpr(t0, rt);
28227 gen_load_gpr(t1, rs);
28228 gen_helper_fork(t0, t1);
28229 tcg_temp_free(t0);
28230 tcg_temp_free(t1);
28232 break;
28233 case OPC_YIELD:
28234 check_mt(ctx);
28236 TCGv t0 = tcg_temp_new();
28238 gen_load_gpr(t0, rs);
28239 gen_helper_yield(t0, cpu_env, t0);
28240 gen_store_gpr(t0, rd);
28241 tcg_temp_free(t0);
28243 break;
28244 default:
28245 if (ctx->insn_flags & ISA_MIPS32R6) {
28246 decode_opc_special3_r6(env, ctx);
28247 } else {
28248 decode_opc_special3_legacy(env, ctx);
28253 /* MIPS SIMD Architecture (MSA) */
28254 static inline int check_msa_access(DisasContext *ctx)
28256 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28257 !(ctx->hflags & MIPS_HFLAG_F64))) {
28258 generate_exception_end(ctx, EXCP_RI);
28259 return 0;
28262 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28263 if (ctx->insn_flags & ASE_MSA) {
28264 generate_exception_end(ctx, EXCP_MSADIS);
28265 return 0;
28266 } else {
28267 generate_exception_end(ctx, EXCP_RI);
28268 return 0;
28271 return 1;
28274 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28276 /* generates tcg ops to check if any element is 0 */
28277 /* Note this function only works with MSA_WRLEN = 128 */
28278 uint64_t eval_zero_or_big = 0;
28279 uint64_t eval_big = 0;
28280 TCGv_i64 t0 = tcg_temp_new_i64();
28281 TCGv_i64 t1 = tcg_temp_new_i64();
28282 switch (df) {
28283 case DF_BYTE:
28284 eval_zero_or_big = 0x0101010101010101ULL;
28285 eval_big = 0x8080808080808080ULL;
28286 break;
28287 case DF_HALF:
28288 eval_zero_or_big = 0x0001000100010001ULL;
28289 eval_big = 0x8000800080008000ULL;
28290 break;
28291 case DF_WORD:
28292 eval_zero_or_big = 0x0000000100000001ULL;
28293 eval_big = 0x8000000080000000ULL;
28294 break;
28295 case DF_DOUBLE:
28296 eval_zero_or_big = 0x0000000000000001ULL;
28297 eval_big = 0x8000000000000000ULL;
28298 break;
28300 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28301 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28302 tcg_gen_andi_i64(t0, t0, eval_big);
28303 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28304 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28305 tcg_gen_andi_i64(t1, t1, eval_big);
28306 tcg_gen_or_i64(t0, t0, t1);
28307 /* if all bits are zero then all elements are not zero */
28308 /* if some bit is non-zero then some element is zero */
28309 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28310 tcg_gen_trunc_i64_tl(tresult, t0);
28311 tcg_temp_free_i64(t0);
28312 tcg_temp_free_i64(t1);
28315 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28317 uint8_t df = (ctx->opcode >> 21) & 0x3;
28318 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28319 int64_t s16 = (int16_t)ctx->opcode;
28321 check_msa_access(ctx);
28323 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28324 generate_exception_end(ctx, EXCP_RI);
28325 return;
28327 switch (op1) {
28328 case OPC_BZ_V:
28329 case OPC_BNZ_V:
28331 TCGv_i64 t0 = tcg_temp_new_i64();
28332 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28333 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28334 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28335 tcg_gen_trunc_i64_tl(bcond, t0);
28336 tcg_temp_free_i64(t0);
28338 break;
28339 case OPC_BZ_B:
28340 case OPC_BZ_H:
28341 case OPC_BZ_W:
28342 case OPC_BZ_D:
28343 gen_check_zero_element(bcond, df, wt);
28344 break;
28345 case OPC_BNZ_B:
28346 case OPC_BNZ_H:
28347 case OPC_BNZ_W:
28348 case OPC_BNZ_D:
28349 gen_check_zero_element(bcond, df, wt);
28350 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28351 break;
28354 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28356 ctx->hflags |= MIPS_HFLAG_BC;
28357 ctx->hflags |= MIPS_HFLAG_BDS32;
28360 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28362 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28363 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28364 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28365 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28367 TCGv_i32 twd = tcg_const_i32(wd);
28368 TCGv_i32 tws = tcg_const_i32(ws);
28369 TCGv_i32 ti8 = tcg_const_i32(i8);
28371 switch (MASK_MSA_I8(ctx->opcode)) {
28372 case OPC_ANDI_B:
28373 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28374 break;
28375 case OPC_ORI_B:
28376 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28377 break;
28378 case OPC_NORI_B:
28379 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28380 break;
28381 case OPC_XORI_B:
28382 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28383 break;
28384 case OPC_BMNZI_B:
28385 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28386 break;
28387 case OPC_BMZI_B:
28388 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28389 break;
28390 case OPC_BSELI_B:
28391 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28392 break;
28393 case OPC_SHF_B:
28394 case OPC_SHF_H:
28395 case OPC_SHF_W:
28397 uint8_t df = (ctx->opcode >> 24) & 0x3;
28398 if (df == DF_DOUBLE) {
28399 generate_exception_end(ctx, EXCP_RI);
28400 } else {
28401 TCGv_i32 tdf = tcg_const_i32(df);
28402 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28403 tcg_temp_free_i32(tdf);
28406 break;
28407 default:
28408 MIPS_INVAL("MSA instruction");
28409 generate_exception_end(ctx, EXCP_RI);
28410 break;
28413 tcg_temp_free_i32(twd);
28414 tcg_temp_free_i32(tws);
28415 tcg_temp_free_i32(ti8);
28418 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28420 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28421 uint8_t df = (ctx->opcode >> 21) & 0x3;
28422 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28423 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28424 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28425 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28427 TCGv_i32 tdf = tcg_const_i32(df);
28428 TCGv_i32 twd = tcg_const_i32(wd);
28429 TCGv_i32 tws = tcg_const_i32(ws);
28430 TCGv_i32 timm = tcg_temp_new_i32();
28431 tcg_gen_movi_i32(timm, u5);
28433 switch (MASK_MSA_I5(ctx->opcode)) {
28434 case OPC_ADDVI_df:
28435 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28436 break;
28437 case OPC_SUBVI_df:
28438 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28439 break;
28440 case OPC_MAXI_S_df:
28441 tcg_gen_movi_i32(timm, s5);
28442 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28443 break;
28444 case OPC_MAXI_U_df:
28445 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28446 break;
28447 case OPC_MINI_S_df:
28448 tcg_gen_movi_i32(timm, s5);
28449 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28450 break;
28451 case OPC_MINI_U_df:
28452 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28453 break;
28454 case OPC_CEQI_df:
28455 tcg_gen_movi_i32(timm, s5);
28456 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28457 break;
28458 case OPC_CLTI_S_df:
28459 tcg_gen_movi_i32(timm, s5);
28460 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28461 break;
28462 case OPC_CLTI_U_df:
28463 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28464 break;
28465 case OPC_CLEI_S_df:
28466 tcg_gen_movi_i32(timm, s5);
28467 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28468 break;
28469 case OPC_CLEI_U_df:
28470 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28471 break;
28472 case OPC_LDI_df:
28474 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28475 tcg_gen_movi_i32(timm, s10);
28476 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28478 break;
28479 default:
28480 MIPS_INVAL("MSA instruction");
28481 generate_exception_end(ctx, EXCP_RI);
28482 break;
28485 tcg_temp_free_i32(tdf);
28486 tcg_temp_free_i32(twd);
28487 tcg_temp_free_i32(tws);
28488 tcg_temp_free_i32(timm);
28491 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28493 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28494 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28495 uint32_t df = 0, m = 0;
28496 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28497 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28499 TCGv_i32 tdf;
28500 TCGv_i32 tm;
28501 TCGv_i32 twd;
28502 TCGv_i32 tws;
28504 if ((dfm & 0x40) == 0x00) {
28505 m = dfm & 0x3f;
28506 df = DF_DOUBLE;
28507 } else if ((dfm & 0x60) == 0x40) {
28508 m = dfm & 0x1f;
28509 df = DF_WORD;
28510 } else if ((dfm & 0x70) == 0x60) {
28511 m = dfm & 0x0f;
28512 df = DF_HALF;
28513 } else if ((dfm & 0x78) == 0x70) {
28514 m = dfm & 0x7;
28515 df = DF_BYTE;
28516 } else {
28517 generate_exception_end(ctx, EXCP_RI);
28518 return;
28521 tdf = tcg_const_i32(df);
28522 tm = tcg_const_i32(m);
28523 twd = tcg_const_i32(wd);
28524 tws = tcg_const_i32(ws);
28526 switch (MASK_MSA_BIT(ctx->opcode)) {
28527 case OPC_SLLI_df:
28528 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28529 break;
28530 case OPC_SRAI_df:
28531 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28532 break;
28533 case OPC_SRLI_df:
28534 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28535 break;
28536 case OPC_BCLRI_df:
28537 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28538 break;
28539 case OPC_BSETI_df:
28540 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28541 break;
28542 case OPC_BNEGI_df:
28543 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28544 break;
28545 case OPC_BINSLI_df:
28546 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28547 break;
28548 case OPC_BINSRI_df:
28549 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28550 break;
28551 case OPC_SAT_S_df:
28552 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28553 break;
28554 case OPC_SAT_U_df:
28555 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28556 break;
28557 case OPC_SRARI_df:
28558 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28559 break;
28560 case OPC_SRLRI_df:
28561 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28562 break;
28563 default:
28564 MIPS_INVAL("MSA instruction");
28565 generate_exception_end(ctx, EXCP_RI);
28566 break;
28569 tcg_temp_free_i32(tdf);
28570 tcg_temp_free_i32(tm);
28571 tcg_temp_free_i32(twd);
28572 tcg_temp_free_i32(tws);
28575 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28577 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28578 uint8_t df = (ctx->opcode >> 21) & 0x3;
28579 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28580 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28581 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28583 TCGv_i32 tdf = tcg_const_i32(df);
28584 TCGv_i32 twd = tcg_const_i32(wd);
28585 TCGv_i32 tws = tcg_const_i32(ws);
28586 TCGv_i32 twt = tcg_const_i32(wt);
28588 switch (MASK_MSA_3R(ctx->opcode)) {
28589 case OPC_BINSL_df:
28590 switch (df) {
28591 case DF_BYTE:
28592 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28593 break;
28594 case DF_HALF:
28595 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28596 break;
28597 case DF_WORD:
28598 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28599 break;
28600 case DF_DOUBLE:
28601 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28602 break;
28604 break;
28605 case OPC_BINSR_df:
28606 switch (df) {
28607 case DF_BYTE:
28608 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28609 break;
28610 case DF_HALF:
28611 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28612 break;
28613 case DF_WORD:
28614 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28615 break;
28616 case DF_DOUBLE:
28617 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28618 break;
28620 break;
28621 case OPC_BCLR_df:
28622 switch (df) {
28623 case DF_BYTE:
28624 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28625 break;
28626 case DF_HALF:
28627 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28628 break;
28629 case DF_WORD:
28630 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28631 break;
28632 case DF_DOUBLE:
28633 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28634 break;
28636 break;
28637 case OPC_BNEG_df:
28638 switch (df) {
28639 case DF_BYTE:
28640 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28641 break;
28642 case DF_HALF:
28643 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28644 break;
28645 case DF_WORD:
28646 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28647 break;
28648 case DF_DOUBLE:
28649 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28650 break;
28652 break;
28653 case OPC_BSET_df:
28654 switch (df) {
28655 case DF_BYTE:
28656 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28657 break;
28658 case DF_HALF:
28659 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28660 break;
28661 case DF_WORD:
28662 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28663 break;
28664 case DF_DOUBLE:
28665 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28666 break;
28668 break;
28669 case OPC_ADD_A_df:
28670 switch (df) {
28671 case DF_BYTE:
28672 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28673 break;
28674 case DF_HALF:
28675 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28676 break;
28677 case DF_WORD:
28678 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28679 break;
28680 case DF_DOUBLE:
28681 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28682 break;
28684 break;
28685 case OPC_ADDS_A_df:
28686 switch (df) {
28687 case DF_BYTE:
28688 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28689 break;
28690 case DF_HALF:
28691 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28692 break;
28693 case DF_WORD:
28694 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
28695 break;
28696 case DF_DOUBLE:
28697 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
28698 break;
28700 break;
28701 case OPC_ADDS_S_df:
28702 switch (df) {
28703 case DF_BYTE:
28704 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
28705 break;
28706 case DF_HALF:
28707 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
28708 break;
28709 case DF_WORD:
28710 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
28711 break;
28712 case DF_DOUBLE:
28713 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
28714 break;
28716 break;
28717 case OPC_ADDS_U_df:
28718 switch (df) {
28719 case DF_BYTE:
28720 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
28721 break;
28722 case DF_HALF:
28723 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
28724 break;
28725 case DF_WORD:
28726 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
28727 break;
28728 case DF_DOUBLE:
28729 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
28730 break;
28732 break;
28733 case OPC_ADDV_df:
28734 switch (df) {
28735 case DF_BYTE:
28736 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
28737 break;
28738 case DF_HALF:
28739 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
28740 break;
28741 case DF_WORD:
28742 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
28743 break;
28744 case DF_DOUBLE:
28745 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
28746 break;
28748 break;
28749 case OPC_AVE_S_df:
28750 switch (df) {
28751 case DF_BYTE:
28752 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
28753 break;
28754 case DF_HALF:
28755 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
28756 break;
28757 case DF_WORD:
28758 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
28759 break;
28760 case DF_DOUBLE:
28761 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
28762 break;
28764 break;
28765 case OPC_AVE_U_df:
28766 switch (df) {
28767 case DF_BYTE:
28768 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
28769 break;
28770 case DF_HALF:
28771 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
28772 break;
28773 case DF_WORD:
28774 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
28775 break;
28776 case DF_DOUBLE:
28777 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
28778 break;
28780 break;
28781 case OPC_AVER_S_df:
28782 switch (df) {
28783 case DF_BYTE:
28784 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
28785 break;
28786 case DF_HALF:
28787 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
28788 break;
28789 case DF_WORD:
28790 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
28791 break;
28792 case DF_DOUBLE:
28793 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
28794 break;
28796 break;
28797 case OPC_AVER_U_df:
28798 switch (df) {
28799 case DF_BYTE:
28800 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
28801 break;
28802 case DF_HALF:
28803 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
28804 break;
28805 case DF_WORD:
28806 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
28807 break;
28808 case DF_DOUBLE:
28809 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
28810 break;
28812 break;
28813 case OPC_CEQ_df:
28814 switch (df) {
28815 case DF_BYTE:
28816 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
28817 break;
28818 case DF_HALF:
28819 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
28820 break;
28821 case DF_WORD:
28822 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
28823 break;
28824 case DF_DOUBLE:
28825 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
28826 break;
28828 break;
28829 case OPC_CLE_S_df:
28830 switch (df) {
28831 case DF_BYTE:
28832 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
28833 break;
28834 case DF_HALF:
28835 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
28836 break;
28837 case DF_WORD:
28838 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
28839 break;
28840 case DF_DOUBLE:
28841 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
28842 break;
28844 break;
28845 case OPC_CLE_U_df:
28846 switch (df) {
28847 case DF_BYTE:
28848 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
28849 break;
28850 case DF_HALF:
28851 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
28852 break;
28853 case DF_WORD:
28854 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
28855 break;
28856 case DF_DOUBLE:
28857 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
28858 break;
28860 break;
28861 case OPC_CLT_S_df:
28862 switch (df) {
28863 case DF_BYTE:
28864 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
28865 break;
28866 case DF_HALF:
28867 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
28868 break;
28869 case DF_WORD:
28870 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
28871 break;
28872 case DF_DOUBLE:
28873 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
28874 break;
28876 break;
28877 case OPC_CLT_U_df:
28878 switch (df) {
28879 case DF_BYTE:
28880 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
28881 break;
28882 case DF_HALF:
28883 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
28884 break;
28885 case DF_WORD:
28886 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
28887 break;
28888 case DF_DOUBLE:
28889 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
28890 break;
28892 break;
28893 case OPC_DIV_S_df:
28894 switch (df) {
28895 case DF_BYTE:
28896 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
28897 break;
28898 case DF_HALF:
28899 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
28900 break;
28901 case DF_WORD:
28902 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
28903 break;
28904 case DF_DOUBLE:
28905 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
28906 break;
28908 break;
28909 case OPC_DIV_U_df:
28910 switch (df) {
28911 case DF_BYTE:
28912 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
28913 break;
28914 case DF_HALF:
28915 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
28916 break;
28917 case DF_WORD:
28918 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
28919 break;
28920 case DF_DOUBLE:
28921 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
28922 break;
28924 break;
28925 case OPC_MAX_A_df:
28926 switch (df) {
28927 case DF_BYTE:
28928 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
28929 break;
28930 case DF_HALF:
28931 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
28932 break;
28933 case DF_WORD:
28934 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
28935 break;
28936 case DF_DOUBLE:
28937 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
28938 break;
28940 break;
28941 case OPC_MAX_S_df:
28942 switch (df) {
28943 case DF_BYTE:
28944 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
28945 break;
28946 case DF_HALF:
28947 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
28948 break;
28949 case DF_WORD:
28950 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
28951 break;
28952 case DF_DOUBLE:
28953 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
28954 break;
28956 break;
28957 case OPC_MAX_U_df:
28958 switch (df) {
28959 case DF_BYTE:
28960 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
28961 break;
28962 case DF_HALF:
28963 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
28964 break;
28965 case DF_WORD:
28966 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
28967 break;
28968 case DF_DOUBLE:
28969 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
28970 break;
28972 break;
28973 case OPC_MIN_A_df:
28974 switch (df) {
28975 case DF_BYTE:
28976 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
28977 break;
28978 case DF_HALF:
28979 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
28980 break;
28981 case DF_WORD:
28982 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
28983 break;
28984 case DF_DOUBLE:
28985 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
28986 break;
28988 break;
28989 case OPC_MIN_S_df:
28990 switch (df) {
28991 case DF_BYTE:
28992 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
28993 break;
28994 case DF_HALF:
28995 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
28996 break;
28997 case DF_WORD:
28998 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
28999 break;
29000 case DF_DOUBLE:
29001 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29002 break;
29004 break;
29005 case OPC_MIN_U_df:
29006 switch (df) {
29007 case DF_BYTE:
29008 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29009 break;
29010 case DF_HALF:
29011 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29012 break;
29013 case DF_WORD:
29014 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29015 break;
29016 case DF_DOUBLE:
29017 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29018 break;
29020 break;
29021 case OPC_MOD_S_df:
29022 switch (df) {
29023 case DF_BYTE:
29024 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29025 break;
29026 case DF_HALF:
29027 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29028 break;
29029 case DF_WORD:
29030 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29031 break;
29032 case DF_DOUBLE:
29033 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29034 break;
29036 break;
29037 case OPC_MOD_U_df:
29038 switch (df) {
29039 case DF_BYTE:
29040 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29041 break;
29042 case DF_HALF:
29043 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29044 break;
29045 case DF_WORD:
29046 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29047 break;
29048 case DF_DOUBLE:
29049 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29050 break;
29052 break;
29053 case OPC_MADDV_df:
29054 switch (df) {
29055 case DF_BYTE:
29056 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29057 break;
29058 case DF_HALF:
29059 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29060 break;
29061 case DF_WORD:
29062 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29063 break;
29064 case DF_DOUBLE:
29065 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29066 break;
29068 break;
29069 case OPC_MSUBV_df:
29070 switch (df) {
29071 case DF_BYTE:
29072 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29073 break;
29074 case DF_HALF:
29075 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29076 break;
29077 case DF_WORD:
29078 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29079 break;
29080 case DF_DOUBLE:
29081 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29082 break;
29084 break;
29085 case OPC_ASUB_S_df:
29086 switch (df) {
29087 case DF_BYTE:
29088 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29089 break;
29090 case DF_HALF:
29091 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29092 break;
29093 case DF_WORD:
29094 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29095 break;
29096 case DF_DOUBLE:
29097 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29098 break;
29100 break;
29101 case OPC_ASUB_U_df:
29102 switch (df) {
29103 case DF_BYTE:
29104 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29105 break;
29106 case DF_HALF:
29107 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29108 break;
29109 case DF_WORD:
29110 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29111 break;
29112 case DF_DOUBLE:
29113 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29114 break;
29116 break;
29117 case OPC_ILVEV_df:
29118 switch (df) {
29119 case DF_BYTE:
29120 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29121 break;
29122 case DF_HALF:
29123 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29124 break;
29125 case DF_WORD:
29126 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29127 break;
29128 case DF_DOUBLE:
29129 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29130 break;
29132 break;
29133 case OPC_ILVOD_df:
29134 switch (df) {
29135 case DF_BYTE:
29136 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29137 break;
29138 case DF_HALF:
29139 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29140 break;
29141 case DF_WORD:
29142 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29143 break;
29144 case DF_DOUBLE:
29145 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29146 break;
29148 break;
29149 case OPC_ILVL_df:
29150 switch (df) {
29151 case DF_BYTE:
29152 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29153 break;
29154 case DF_HALF:
29155 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29156 break;
29157 case DF_WORD:
29158 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29159 break;
29160 case DF_DOUBLE:
29161 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29162 break;
29164 break;
29165 case OPC_ILVR_df:
29166 switch (df) {
29167 case DF_BYTE:
29168 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29169 break;
29170 case DF_HALF:
29171 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29172 break;
29173 case DF_WORD:
29174 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29175 break;
29176 case DF_DOUBLE:
29177 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29178 break;
29180 break;
29181 case OPC_PCKEV_df:
29182 switch (df) {
29183 case DF_BYTE:
29184 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29185 break;
29186 case DF_HALF:
29187 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29188 break;
29189 case DF_WORD:
29190 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29191 break;
29192 case DF_DOUBLE:
29193 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29194 break;
29196 break;
29197 case OPC_PCKOD_df:
29198 switch (df) {
29199 case DF_BYTE:
29200 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29201 break;
29202 case DF_HALF:
29203 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29204 break;
29205 case DF_WORD:
29206 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29207 break;
29208 case DF_DOUBLE:
29209 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29210 break;
29212 break;
29213 case OPC_SLL_df:
29214 switch (df) {
29215 case DF_BYTE:
29216 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29217 break;
29218 case DF_HALF:
29219 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29220 break;
29221 case DF_WORD:
29222 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29223 break;
29224 case DF_DOUBLE:
29225 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29226 break;
29228 break;
29229 case OPC_SRA_df:
29230 switch (df) {
29231 case DF_BYTE:
29232 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29233 break;
29234 case DF_HALF:
29235 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29236 break;
29237 case DF_WORD:
29238 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29239 break;
29240 case DF_DOUBLE:
29241 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29242 break;
29244 break;
29245 case OPC_SRAR_df:
29246 switch (df) {
29247 case DF_BYTE:
29248 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29249 break;
29250 case DF_HALF:
29251 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29252 break;
29253 case DF_WORD:
29254 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29255 break;
29256 case DF_DOUBLE:
29257 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29258 break;
29260 break;
29261 case OPC_SRL_df:
29262 switch (df) {
29263 case DF_BYTE:
29264 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29265 break;
29266 case DF_HALF:
29267 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29268 break;
29269 case DF_WORD:
29270 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29271 break;
29272 case DF_DOUBLE:
29273 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29274 break;
29276 break;
29277 case OPC_SRLR_df:
29278 switch (df) {
29279 case DF_BYTE:
29280 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29281 break;
29282 case DF_HALF:
29283 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29284 break;
29285 case DF_WORD:
29286 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29287 break;
29288 case DF_DOUBLE:
29289 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29290 break;
29292 break;
29293 case OPC_SUBS_S_df:
29294 switch (df) {
29295 case DF_BYTE:
29296 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29297 break;
29298 case DF_HALF:
29299 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29300 break;
29301 case DF_WORD:
29302 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29303 break;
29304 case DF_DOUBLE:
29305 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29306 break;
29308 break;
29309 case OPC_MULV_df:
29310 switch (df) {
29311 case DF_BYTE:
29312 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29313 break;
29314 case DF_HALF:
29315 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29316 break;
29317 case DF_WORD:
29318 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29319 break;
29320 case DF_DOUBLE:
29321 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29322 break;
29324 break;
29325 case OPC_SLD_df:
29326 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29327 break;
29328 case OPC_VSHF_df:
29329 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29330 break;
29331 case OPC_SUBV_df:
29332 switch (df) {
29333 case DF_BYTE:
29334 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29335 break;
29336 case DF_HALF:
29337 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29338 break;
29339 case DF_WORD:
29340 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29341 break;
29342 case DF_DOUBLE:
29343 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29344 break;
29346 break;
29347 case OPC_SUBS_U_df:
29348 switch (df) {
29349 case DF_BYTE:
29350 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29351 break;
29352 case DF_HALF:
29353 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29354 break;
29355 case DF_WORD:
29356 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29357 break;
29358 case DF_DOUBLE:
29359 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29360 break;
29362 break;
29363 case OPC_SPLAT_df:
29364 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29365 break;
29366 case OPC_SUBSUS_U_df:
29367 switch (df) {
29368 case DF_BYTE:
29369 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29370 break;
29371 case DF_HALF:
29372 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29373 break;
29374 case DF_WORD:
29375 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29376 break;
29377 case DF_DOUBLE:
29378 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29379 break;
29381 break;
29382 case OPC_SUBSUU_S_df:
29383 switch (df) {
29384 case DF_BYTE:
29385 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29386 break;
29387 case DF_HALF:
29388 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29389 break;
29390 case DF_WORD:
29391 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29392 break;
29393 case DF_DOUBLE:
29394 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29395 break;
29397 break;
29399 case OPC_DOTP_S_df:
29400 case OPC_DOTP_U_df:
29401 case OPC_DPADD_S_df:
29402 case OPC_DPADD_U_df:
29403 case OPC_DPSUB_S_df:
29404 case OPC_HADD_S_df:
29405 case OPC_DPSUB_U_df:
29406 case OPC_HADD_U_df:
29407 case OPC_HSUB_S_df:
29408 case OPC_HSUB_U_df:
29409 if (df == DF_BYTE) {
29410 generate_exception_end(ctx, EXCP_RI);
29411 break;
29413 switch (MASK_MSA_3R(ctx->opcode)) {
29414 case OPC_HADD_S_df:
29415 switch (df) {
29416 case DF_HALF:
29417 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29418 break;
29419 case DF_WORD:
29420 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29421 break;
29422 case DF_DOUBLE:
29423 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29424 break;
29426 break;
29427 case OPC_HADD_U_df:
29428 switch (df) {
29429 case DF_HALF:
29430 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29431 break;
29432 case DF_WORD:
29433 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29434 break;
29435 case DF_DOUBLE:
29436 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29437 break;
29439 break;
29440 case OPC_HSUB_S_df:
29441 switch (df) {
29442 case DF_HALF:
29443 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29444 break;
29445 case DF_WORD:
29446 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29447 break;
29448 case DF_DOUBLE:
29449 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29450 break;
29452 break;
29453 case OPC_HSUB_U_df:
29454 switch (df) {
29455 case DF_HALF:
29456 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29457 break;
29458 case DF_WORD:
29459 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29460 break;
29461 case DF_DOUBLE:
29462 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29463 break;
29465 break;
29466 case OPC_DOTP_S_df:
29467 switch (df) {
29468 case DF_HALF:
29469 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29470 break;
29471 case DF_WORD:
29472 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29473 break;
29474 case DF_DOUBLE:
29475 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29476 break;
29478 break;
29479 case OPC_DOTP_U_df:
29480 switch (df) {
29481 case DF_HALF:
29482 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29483 break;
29484 case DF_WORD:
29485 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29486 break;
29487 case DF_DOUBLE:
29488 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29489 break;
29491 break;
29492 case OPC_DPADD_S_df:
29493 switch (df) {
29494 case DF_HALF:
29495 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29496 break;
29497 case DF_WORD:
29498 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29499 break;
29500 case DF_DOUBLE:
29501 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29502 break;
29504 break;
29505 case OPC_DPADD_U_df:
29506 switch (df) {
29507 case DF_HALF:
29508 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29509 break;
29510 case DF_WORD:
29511 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29512 break;
29513 case DF_DOUBLE:
29514 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29515 break;
29517 break;
29518 case OPC_DPSUB_S_df:
29519 switch (df) {
29520 case DF_HALF:
29521 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29522 break;
29523 case DF_WORD:
29524 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29525 break;
29526 case DF_DOUBLE:
29527 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29528 break;
29530 break;
29531 case OPC_DPSUB_U_df:
29532 switch (df) {
29533 case DF_HALF:
29534 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29535 break;
29536 case DF_WORD:
29537 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29538 break;
29539 case DF_DOUBLE:
29540 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29541 break;
29543 break;
29545 break;
29546 default:
29547 MIPS_INVAL("MSA instruction");
29548 generate_exception_end(ctx, EXCP_RI);
29549 break;
29551 tcg_temp_free_i32(twd);
29552 tcg_temp_free_i32(tws);
29553 tcg_temp_free_i32(twt);
29554 tcg_temp_free_i32(tdf);
29557 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29559 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29560 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29561 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29562 TCGv telm = tcg_temp_new();
29563 TCGv_i32 tsr = tcg_const_i32(source);
29564 TCGv_i32 tdt = tcg_const_i32(dest);
29566 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29567 case OPC_CTCMSA:
29568 gen_load_gpr(telm, source);
29569 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29570 break;
29571 case OPC_CFCMSA:
29572 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29573 gen_store_gpr(telm, dest);
29574 break;
29575 case OPC_MOVE_V:
29576 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29577 break;
29578 default:
29579 MIPS_INVAL("MSA instruction");
29580 generate_exception_end(ctx, EXCP_RI);
29581 break;
29584 tcg_temp_free(telm);
29585 tcg_temp_free_i32(tdt);
29586 tcg_temp_free_i32(tsr);
29589 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29590 uint32_t n)
29592 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29593 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29594 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29596 TCGv_i32 tws = tcg_const_i32(ws);
29597 TCGv_i32 twd = tcg_const_i32(wd);
29598 TCGv_i32 tn = tcg_const_i32(n);
29599 TCGv_i32 tdf = tcg_const_i32(df);
29601 switch (MASK_MSA_ELM(ctx->opcode)) {
29602 case OPC_SLDI_df:
29603 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29604 break;
29605 case OPC_SPLATI_df:
29606 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29607 break;
29608 case OPC_INSVE_df:
29609 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29610 break;
29611 case OPC_COPY_S_df:
29612 case OPC_COPY_U_df:
29613 case OPC_INSERT_df:
29614 #if !defined(TARGET_MIPS64)
29615 /* Double format valid only for MIPS64 */
29616 if (df == DF_DOUBLE) {
29617 generate_exception_end(ctx, EXCP_RI);
29618 break;
29620 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29621 (df == DF_WORD)) {
29622 generate_exception_end(ctx, EXCP_RI);
29623 break;
29625 #endif
29626 switch (MASK_MSA_ELM(ctx->opcode)) {
29627 case OPC_COPY_S_df:
29628 if (likely(wd != 0)) {
29629 switch (df) {
29630 case DF_BYTE:
29631 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29632 break;
29633 case DF_HALF:
29634 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29635 break;
29636 case DF_WORD:
29637 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29638 break;
29639 #if defined(TARGET_MIPS64)
29640 case DF_DOUBLE:
29641 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29642 break;
29643 #endif
29644 default:
29645 assert(0);
29648 break;
29649 case OPC_COPY_U_df:
29650 if (likely(wd != 0)) {
29651 switch (df) {
29652 case DF_BYTE:
29653 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29654 break;
29655 case DF_HALF:
29656 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29657 break;
29658 #if defined(TARGET_MIPS64)
29659 case DF_WORD:
29660 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29661 break;
29662 #endif
29663 default:
29664 assert(0);
29667 break;
29668 case OPC_INSERT_df:
29669 switch (df) {
29670 case DF_BYTE:
29671 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29672 break;
29673 case DF_HALF:
29674 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29675 break;
29676 case DF_WORD:
29677 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29678 break;
29679 #if defined(TARGET_MIPS64)
29680 case DF_DOUBLE:
29681 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29682 break;
29683 #endif
29684 default:
29685 assert(0);
29687 break;
29689 break;
29690 default:
29691 MIPS_INVAL("MSA instruction");
29692 generate_exception_end(ctx, EXCP_RI);
29694 tcg_temp_free_i32(twd);
29695 tcg_temp_free_i32(tws);
29696 tcg_temp_free_i32(tn);
29697 tcg_temp_free_i32(tdf);
29700 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
29702 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
29703 uint32_t df = 0, n = 0;
29705 if ((dfn & 0x30) == 0x00) {
29706 n = dfn & 0x0f;
29707 df = DF_BYTE;
29708 } else if ((dfn & 0x38) == 0x20) {
29709 n = dfn & 0x07;
29710 df = DF_HALF;
29711 } else if ((dfn & 0x3c) == 0x30) {
29712 n = dfn & 0x03;
29713 df = DF_WORD;
29714 } else if ((dfn & 0x3e) == 0x38) {
29715 n = dfn & 0x01;
29716 df = DF_DOUBLE;
29717 } else if (dfn == 0x3E) {
29718 /* CTCMSA, CFCMSA, MOVE.V */
29719 gen_msa_elm_3e(env, ctx);
29720 return;
29721 } else {
29722 generate_exception_end(ctx, EXCP_RI);
29723 return;
29726 gen_msa_elm_df(env, ctx, df, n);
29729 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
29731 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29732 uint8_t df = (ctx->opcode >> 21) & 0x1;
29733 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29734 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29735 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29737 TCGv_i32 twd = tcg_const_i32(wd);
29738 TCGv_i32 tws = tcg_const_i32(ws);
29739 TCGv_i32 twt = tcg_const_i32(wt);
29740 TCGv_i32 tdf = tcg_temp_new_i32();
29742 /* adjust df value for floating-point instruction */
29743 tcg_gen_movi_i32(tdf, df + 2);
29745 switch (MASK_MSA_3RF(ctx->opcode)) {
29746 case OPC_FCAF_df:
29747 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
29748 break;
29749 case OPC_FADD_df:
29750 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
29751 break;
29752 case OPC_FCUN_df:
29753 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
29754 break;
29755 case OPC_FSUB_df:
29756 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
29757 break;
29758 case OPC_FCOR_df:
29759 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
29760 break;
29761 case OPC_FCEQ_df:
29762 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
29763 break;
29764 case OPC_FMUL_df:
29765 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
29766 break;
29767 case OPC_FCUNE_df:
29768 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
29769 break;
29770 case OPC_FCUEQ_df:
29771 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
29772 break;
29773 case OPC_FDIV_df:
29774 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
29775 break;
29776 case OPC_FCNE_df:
29777 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
29778 break;
29779 case OPC_FCLT_df:
29780 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
29781 break;
29782 case OPC_FMADD_df:
29783 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
29784 break;
29785 case OPC_MUL_Q_df:
29786 tcg_gen_movi_i32(tdf, df + 1);
29787 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
29788 break;
29789 case OPC_FCULT_df:
29790 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
29791 break;
29792 case OPC_FMSUB_df:
29793 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
29794 break;
29795 case OPC_MADD_Q_df:
29796 tcg_gen_movi_i32(tdf, df + 1);
29797 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
29798 break;
29799 case OPC_FCLE_df:
29800 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
29801 break;
29802 case OPC_MSUB_Q_df:
29803 tcg_gen_movi_i32(tdf, df + 1);
29804 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
29805 break;
29806 case OPC_FCULE_df:
29807 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
29808 break;
29809 case OPC_FEXP2_df:
29810 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
29811 break;
29812 case OPC_FSAF_df:
29813 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
29814 break;
29815 case OPC_FEXDO_df:
29816 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
29817 break;
29818 case OPC_FSUN_df:
29819 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
29820 break;
29821 case OPC_FSOR_df:
29822 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
29823 break;
29824 case OPC_FSEQ_df:
29825 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
29826 break;
29827 case OPC_FTQ_df:
29828 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
29829 break;
29830 case OPC_FSUNE_df:
29831 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
29832 break;
29833 case OPC_FSUEQ_df:
29834 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
29835 break;
29836 case OPC_FSNE_df:
29837 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
29838 break;
29839 case OPC_FSLT_df:
29840 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
29841 break;
29842 case OPC_FMIN_df:
29843 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
29844 break;
29845 case OPC_MULR_Q_df:
29846 tcg_gen_movi_i32(tdf, df + 1);
29847 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
29848 break;
29849 case OPC_FSULT_df:
29850 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
29851 break;
29852 case OPC_FMIN_A_df:
29853 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
29854 break;
29855 case OPC_MADDR_Q_df:
29856 tcg_gen_movi_i32(tdf, df + 1);
29857 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
29858 break;
29859 case OPC_FSLE_df:
29860 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
29861 break;
29862 case OPC_FMAX_df:
29863 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
29864 break;
29865 case OPC_MSUBR_Q_df:
29866 tcg_gen_movi_i32(tdf, df + 1);
29867 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
29868 break;
29869 case OPC_FSULE_df:
29870 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
29871 break;
29872 case OPC_FMAX_A_df:
29873 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
29874 break;
29875 default:
29876 MIPS_INVAL("MSA instruction");
29877 generate_exception_end(ctx, EXCP_RI);
29878 break;
29881 tcg_temp_free_i32(twd);
29882 tcg_temp_free_i32(tws);
29883 tcg_temp_free_i32(twt);
29884 tcg_temp_free_i32(tdf);
29887 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
29889 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29890 (op & (0x7 << 18)))
29891 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29892 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29893 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29894 uint8_t df = (ctx->opcode >> 16) & 0x3;
29895 TCGv_i32 twd = tcg_const_i32(wd);
29896 TCGv_i32 tws = tcg_const_i32(ws);
29897 TCGv_i32 twt = tcg_const_i32(wt);
29898 TCGv_i32 tdf = tcg_const_i32(df);
29900 switch (MASK_MSA_2R(ctx->opcode)) {
29901 case OPC_FILL_df:
29902 #if !defined(TARGET_MIPS64)
29903 /* Double format valid only for MIPS64 */
29904 if (df == DF_DOUBLE) {
29905 generate_exception_end(ctx, EXCP_RI);
29906 break;
29908 #endif
29909 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
29910 break;
29911 case OPC_NLOC_df:
29912 switch (df) {
29913 case DF_BYTE:
29914 gen_helper_msa_nloc_b(cpu_env, twd, tws);
29915 break;
29916 case DF_HALF:
29917 gen_helper_msa_nloc_h(cpu_env, twd, tws);
29918 break;
29919 case DF_WORD:
29920 gen_helper_msa_nloc_w(cpu_env, twd, tws);
29921 break;
29922 case DF_DOUBLE:
29923 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29924 break;
29926 break;
29927 case OPC_NLZC_df:
29928 switch (df) {
29929 case DF_BYTE:
29930 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29931 break;
29932 case DF_HALF:
29933 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29934 break;
29935 case DF_WORD:
29936 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29937 break;
29938 case DF_DOUBLE:
29939 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29940 break;
29942 break;
29943 case OPC_PCNT_df:
29944 switch (df) {
29945 case DF_BYTE:
29946 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29947 break;
29948 case DF_HALF:
29949 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29950 break;
29951 case DF_WORD:
29952 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29953 break;
29954 case DF_DOUBLE:
29955 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29956 break;
29958 break;
29959 default:
29960 MIPS_INVAL("MSA instruction");
29961 generate_exception_end(ctx, EXCP_RI);
29962 break;
29965 tcg_temp_free_i32(twd);
29966 tcg_temp_free_i32(tws);
29967 tcg_temp_free_i32(twt);
29968 tcg_temp_free_i32(tdf);
29971 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29973 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29974 (op & (0xf << 17)))
29975 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29976 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29977 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29978 uint8_t df = (ctx->opcode >> 16) & 0x1;
29979 TCGv_i32 twd = tcg_const_i32(wd);
29980 TCGv_i32 tws = tcg_const_i32(ws);
29981 TCGv_i32 twt = tcg_const_i32(wt);
29982 /* adjust df value for floating-point instruction */
29983 TCGv_i32 tdf = tcg_const_i32(df + 2);
29985 switch (MASK_MSA_2RF(ctx->opcode)) {
29986 case OPC_FCLASS_df:
29987 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29988 break;
29989 case OPC_FTRUNC_S_df:
29990 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29991 break;
29992 case OPC_FTRUNC_U_df:
29993 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
29994 break;
29995 case OPC_FSQRT_df:
29996 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29997 break;
29998 case OPC_FRSQRT_df:
29999 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30000 break;
30001 case OPC_FRCP_df:
30002 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30003 break;
30004 case OPC_FRINT_df:
30005 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30006 break;
30007 case OPC_FLOG2_df:
30008 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30009 break;
30010 case OPC_FEXUPL_df:
30011 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30012 break;
30013 case OPC_FEXUPR_df:
30014 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30015 break;
30016 case OPC_FFQL_df:
30017 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30018 break;
30019 case OPC_FFQR_df:
30020 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30021 break;
30022 case OPC_FTINT_S_df:
30023 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30024 break;
30025 case OPC_FTINT_U_df:
30026 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30027 break;
30028 case OPC_FFINT_S_df:
30029 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30030 break;
30031 case OPC_FFINT_U_df:
30032 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30033 break;
30036 tcg_temp_free_i32(twd);
30037 tcg_temp_free_i32(tws);
30038 tcg_temp_free_i32(twt);
30039 tcg_temp_free_i32(tdf);
30042 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30044 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30045 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30046 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30047 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30048 TCGv_i32 twd = tcg_const_i32(wd);
30049 TCGv_i32 tws = tcg_const_i32(ws);
30050 TCGv_i32 twt = tcg_const_i32(wt);
30052 switch (MASK_MSA_VEC(ctx->opcode)) {
30053 case OPC_AND_V:
30054 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30055 break;
30056 case OPC_OR_V:
30057 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30058 break;
30059 case OPC_NOR_V:
30060 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30061 break;
30062 case OPC_XOR_V:
30063 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30064 break;
30065 case OPC_BMNZ_V:
30066 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30067 break;
30068 case OPC_BMZ_V:
30069 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30070 break;
30071 case OPC_BSEL_V:
30072 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30073 break;
30074 default:
30075 MIPS_INVAL("MSA instruction");
30076 generate_exception_end(ctx, EXCP_RI);
30077 break;
30080 tcg_temp_free_i32(twd);
30081 tcg_temp_free_i32(tws);
30082 tcg_temp_free_i32(twt);
30085 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30087 switch (MASK_MSA_VEC(ctx->opcode)) {
30088 case OPC_AND_V:
30089 case OPC_OR_V:
30090 case OPC_NOR_V:
30091 case OPC_XOR_V:
30092 case OPC_BMNZ_V:
30093 case OPC_BMZ_V:
30094 case OPC_BSEL_V:
30095 gen_msa_vec_v(env, ctx);
30096 break;
30097 case OPC_MSA_2R:
30098 gen_msa_2r(env, ctx);
30099 break;
30100 case OPC_MSA_2RF:
30101 gen_msa_2rf(env, ctx);
30102 break;
30103 default:
30104 MIPS_INVAL("MSA instruction");
30105 generate_exception_end(ctx, EXCP_RI);
30106 break;
30110 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30112 uint32_t opcode = ctx->opcode;
30113 check_insn(ctx, ASE_MSA);
30114 check_msa_access(ctx);
30116 switch (MASK_MSA_MINOR(opcode)) {
30117 case OPC_MSA_I8_00:
30118 case OPC_MSA_I8_01:
30119 case OPC_MSA_I8_02:
30120 gen_msa_i8(env, ctx);
30121 break;
30122 case OPC_MSA_I5_06:
30123 case OPC_MSA_I5_07:
30124 gen_msa_i5(env, ctx);
30125 break;
30126 case OPC_MSA_BIT_09:
30127 case OPC_MSA_BIT_0A:
30128 gen_msa_bit(env, ctx);
30129 break;
30130 case OPC_MSA_3R_0D:
30131 case OPC_MSA_3R_0E:
30132 case OPC_MSA_3R_0F:
30133 case OPC_MSA_3R_10:
30134 case OPC_MSA_3R_11:
30135 case OPC_MSA_3R_12:
30136 case OPC_MSA_3R_13:
30137 case OPC_MSA_3R_14:
30138 case OPC_MSA_3R_15:
30139 gen_msa_3r(env, ctx);
30140 break;
30141 case OPC_MSA_ELM:
30142 gen_msa_elm(env, ctx);
30143 break;
30144 case OPC_MSA_3RF_1A:
30145 case OPC_MSA_3RF_1B:
30146 case OPC_MSA_3RF_1C:
30147 gen_msa_3rf(env, ctx);
30148 break;
30149 case OPC_MSA_VEC:
30150 gen_msa_vec(env, ctx);
30151 break;
30152 case OPC_LD_B:
30153 case OPC_LD_H:
30154 case OPC_LD_W:
30155 case OPC_LD_D:
30156 case OPC_ST_B:
30157 case OPC_ST_H:
30158 case OPC_ST_W:
30159 case OPC_ST_D:
30161 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30162 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30163 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30164 uint8_t df = (ctx->opcode >> 0) & 0x3;
30166 TCGv_i32 twd = tcg_const_i32(wd);
30167 TCGv taddr = tcg_temp_new();
30168 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30170 switch (MASK_MSA_MINOR(opcode)) {
30171 case OPC_LD_B:
30172 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30173 break;
30174 case OPC_LD_H:
30175 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30176 break;
30177 case OPC_LD_W:
30178 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30179 break;
30180 case OPC_LD_D:
30181 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30182 break;
30183 case OPC_ST_B:
30184 gen_helper_msa_st_b(cpu_env, twd, taddr);
30185 break;
30186 case OPC_ST_H:
30187 gen_helper_msa_st_h(cpu_env, twd, taddr);
30188 break;
30189 case OPC_ST_W:
30190 gen_helper_msa_st_w(cpu_env, twd, taddr);
30191 break;
30192 case OPC_ST_D:
30193 gen_helper_msa_st_d(cpu_env, twd, taddr);
30194 break;
30197 tcg_temp_free_i32(twd);
30198 tcg_temp_free(taddr);
30200 break;
30201 default:
30202 MIPS_INVAL("MSA instruction");
30203 generate_exception_end(ctx, EXCP_RI);
30204 break;
30209 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30211 int32_t offset;
30212 int rs, rt, rd, sa;
30213 uint32_t op, op1;
30214 int16_t imm;
30216 /* make sure instructions are on a word boundary */
30217 if (ctx->base.pc_next & 0x3) {
30218 env->CP0_BadVAddr = ctx->base.pc_next;
30219 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30220 return;
30223 /* Handle blikely not taken case */
30224 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30225 TCGLabel *l1 = gen_new_label();
30227 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30228 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30229 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30230 gen_set_label(l1);
30233 op = MASK_OP_MAJOR(ctx->opcode);
30234 rs = (ctx->opcode >> 21) & 0x1f;
30235 rt = (ctx->opcode >> 16) & 0x1f;
30236 rd = (ctx->opcode >> 11) & 0x1f;
30237 sa = (ctx->opcode >> 6) & 0x1f;
30238 imm = (int16_t)ctx->opcode;
30239 switch (op) {
30240 case OPC_SPECIAL:
30241 decode_opc_special(env, ctx);
30242 break;
30243 case OPC_SPECIAL2:
30244 #if defined(TARGET_MIPS64)
30245 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30246 decode_mmi(env, ctx);
30247 #else
30248 if (ctx->insn_flags & ASE_MXU) {
30249 decode_opc_mxu(env, ctx);
30250 #endif
30251 } else {
30252 decode_opc_special2_legacy(env, ctx);
30254 break;
30255 case OPC_SPECIAL3:
30256 #if defined(TARGET_MIPS64)
30257 if (ctx->insn_flags & INSN_R5900) {
30258 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30259 } else {
30260 decode_opc_special3(env, ctx);
30262 #else
30263 decode_opc_special3(env, ctx);
30264 #endif
30265 break;
30266 case OPC_REGIMM:
30267 op1 = MASK_REGIMM(ctx->opcode);
30268 switch (op1) {
30269 case OPC_BLTZL: /* REGIMM branches */
30270 case OPC_BGEZL:
30271 case OPC_BLTZALL:
30272 case OPC_BGEZALL:
30273 check_insn(ctx, ISA_MIPS2);
30274 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30275 /* Fallthrough */
30276 case OPC_BLTZ:
30277 case OPC_BGEZ:
30278 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30279 break;
30280 case OPC_BLTZAL:
30281 case OPC_BGEZAL:
30282 if (ctx->insn_flags & ISA_MIPS32R6) {
30283 if (rs == 0) {
30284 /* OPC_NAL, OPC_BAL */
30285 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30286 } else {
30287 generate_exception_end(ctx, EXCP_RI);
30289 } else {
30290 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30292 break;
30293 case OPC_TGEI: /* REGIMM traps */
30294 case OPC_TGEIU:
30295 case OPC_TLTI:
30296 case OPC_TLTIU:
30297 case OPC_TEQI:
30299 case OPC_TNEI:
30300 check_insn(ctx, ISA_MIPS2);
30301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30302 gen_trap(ctx, op1, rs, -1, imm);
30303 break;
30304 case OPC_SIGRIE:
30305 check_insn(ctx, ISA_MIPS32R6);
30306 generate_exception_end(ctx, EXCP_RI);
30307 break;
30308 case OPC_SYNCI:
30309 check_insn(ctx, ISA_MIPS32R2);
30311 * Break the TB to be able to sync copied instructions
30312 * immediately.
30314 ctx->base.is_jmp = DISAS_STOP;
30315 break;
30316 case OPC_BPOSGE32: /* MIPS DSP branch */
30317 #if defined(TARGET_MIPS64)
30318 case OPC_BPOSGE64:
30319 #endif
30320 check_dsp(ctx);
30321 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30322 break;
30323 #if defined(TARGET_MIPS64)
30324 case OPC_DAHI:
30325 check_insn(ctx, ISA_MIPS32R6);
30326 check_mips_64(ctx);
30327 if (rs != 0) {
30328 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30330 break;
30331 case OPC_DATI:
30332 check_insn(ctx, ISA_MIPS32R6);
30333 check_mips_64(ctx);
30334 if (rs != 0) {
30335 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30337 break;
30338 #endif
30339 default: /* Invalid */
30340 MIPS_INVAL("regimm");
30341 generate_exception_end(ctx, EXCP_RI);
30342 break;
30344 break;
30345 case OPC_CP0:
30346 check_cp0_enabled(ctx);
30347 op1 = MASK_CP0(ctx->opcode);
30348 switch (op1) {
30349 case OPC_MFC0:
30350 case OPC_MTC0:
30351 case OPC_MFTR:
30352 case OPC_MTTR:
30353 case OPC_MFHC0:
30354 case OPC_MTHC0:
30355 #if defined(TARGET_MIPS64)
30356 case OPC_DMFC0:
30357 case OPC_DMTC0:
30358 #endif
30359 #ifndef CONFIG_USER_ONLY
30360 gen_cp0(env, ctx, op1, rt, rd);
30361 #endif /* !CONFIG_USER_ONLY */
30362 break;
30363 case OPC_C0:
30364 case OPC_C0_1:
30365 case OPC_C0_2:
30366 case OPC_C0_3:
30367 case OPC_C0_4:
30368 case OPC_C0_5:
30369 case OPC_C0_6:
30370 case OPC_C0_7:
30371 case OPC_C0_8:
30372 case OPC_C0_9:
30373 case OPC_C0_A:
30374 case OPC_C0_B:
30375 case OPC_C0_C:
30376 case OPC_C0_D:
30377 case OPC_C0_E:
30378 case OPC_C0_F:
30379 #ifndef CONFIG_USER_ONLY
30380 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30381 #endif /* !CONFIG_USER_ONLY */
30382 break;
30383 case OPC_MFMC0:
30384 #ifndef CONFIG_USER_ONLY
30386 uint32_t op2;
30387 TCGv t0 = tcg_temp_new();
30389 op2 = MASK_MFMC0(ctx->opcode);
30390 switch (op2) {
30391 case OPC_DMT:
30392 check_cp0_mt(ctx);
30393 gen_helper_dmt(t0);
30394 gen_store_gpr(t0, rt);
30395 break;
30396 case OPC_EMT:
30397 check_cp0_mt(ctx);
30398 gen_helper_emt(t0);
30399 gen_store_gpr(t0, rt);
30400 break;
30401 case OPC_DVPE:
30402 check_cp0_mt(ctx);
30403 gen_helper_dvpe(t0, cpu_env);
30404 gen_store_gpr(t0, rt);
30405 break;
30406 case OPC_EVPE:
30407 check_cp0_mt(ctx);
30408 gen_helper_evpe(t0, cpu_env);
30409 gen_store_gpr(t0, rt);
30410 break;
30411 case OPC_DVP:
30412 check_insn(ctx, ISA_MIPS32R6);
30413 if (ctx->vp) {
30414 gen_helper_dvp(t0, cpu_env);
30415 gen_store_gpr(t0, rt);
30417 break;
30418 case OPC_EVP:
30419 check_insn(ctx, ISA_MIPS32R6);
30420 if (ctx->vp) {
30421 gen_helper_evp(t0, cpu_env);
30422 gen_store_gpr(t0, rt);
30424 break;
30425 case OPC_DI:
30426 check_insn(ctx, ISA_MIPS32R2);
30427 save_cpu_state(ctx, 1);
30428 gen_helper_di(t0, cpu_env);
30429 gen_store_gpr(t0, rt);
30431 * Stop translation as we may have switched
30432 * the execution mode.
30434 ctx->base.is_jmp = DISAS_STOP;
30435 break;
30436 case OPC_EI:
30437 check_insn(ctx, ISA_MIPS32R2);
30438 save_cpu_state(ctx, 1);
30439 gen_helper_ei(t0, cpu_env);
30440 gen_store_gpr(t0, rt);
30442 * DISAS_STOP isn't sufficient, we need to ensure we break
30443 * out of translated code to check for pending interrupts.
30445 gen_save_pc(ctx->base.pc_next + 4);
30446 ctx->base.is_jmp = DISAS_EXIT;
30447 break;
30448 default: /* Invalid */
30449 MIPS_INVAL("mfmc0");
30450 generate_exception_end(ctx, EXCP_RI);
30451 break;
30453 tcg_temp_free(t0);
30455 #endif /* !CONFIG_USER_ONLY */
30456 break;
30457 case OPC_RDPGPR:
30458 check_insn(ctx, ISA_MIPS32R2);
30459 gen_load_srsgpr(rt, rd);
30460 break;
30461 case OPC_WRPGPR:
30462 check_insn(ctx, ISA_MIPS32R2);
30463 gen_store_srsgpr(rt, rd);
30464 break;
30465 default:
30466 MIPS_INVAL("cp0");
30467 generate_exception_end(ctx, EXCP_RI);
30468 break;
30470 break;
30471 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30472 if (ctx->insn_flags & ISA_MIPS32R6) {
30473 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30474 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30475 } else {
30476 /* OPC_ADDI */
30477 /* Arithmetic with immediate opcode */
30478 gen_arith_imm(ctx, op, rt, rs, imm);
30480 break;
30481 case OPC_ADDIU:
30482 gen_arith_imm(ctx, op, rt, rs, imm);
30483 break;
30484 case OPC_SLTI: /* Set on less than with immediate opcode */
30485 case OPC_SLTIU:
30486 gen_slt_imm(ctx, op, rt, rs, imm);
30487 break;
30488 case OPC_ANDI: /* Arithmetic with immediate opcode */
30489 case OPC_LUI: /* OPC_AUI */
30490 case OPC_ORI:
30491 case OPC_XORI:
30492 gen_logic_imm(ctx, op, rt, rs, imm);
30493 break;
30494 case OPC_J: /* Jump */
30495 case OPC_JAL:
30496 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30497 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30498 break;
30499 /* Branch */
30500 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30501 if (ctx->insn_flags & ISA_MIPS32R6) {
30502 if (rt == 0) {
30503 generate_exception_end(ctx, EXCP_RI);
30504 break;
30506 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30507 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30508 } else {
30509 /* OPC_BLEZL */
30510 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30512 break;
30513 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30514 if (ctx->insn_flags & ISA_MIPS32R6) {
30515 if (rt == 0) {
30516 generate_exception_end(ctx, EXCP_RI);
30517 break;
30519 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30520 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30521 } else {
30522 /* OPC_BGTZL */
30523 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30525 break;
30526 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30527 if (rt == 0) {
30528 /* OPC_BLEZ */
30529 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30530 } else {
30531 check_insn(ctx, ISA_MIPS32R6);
30532 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30533 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30535 break;
30536 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30537 if (rt == 0) {
30538 /* OPC_BGTZ */
30539 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30540 } else {
30541 check_insn(ctx, ISA_MIPS32R6);
30542 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30543 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30545 break;
30546 case OPC_BEQL:
30547 case OPC_BNEL:
30548 check_insn(ctx, ISA_MIPS2);
30549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30550 /* Fallthrough */
30551 case OPC_BEQ:
30552 case OPC_BNE:
30553 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30554 break;
30555 case OPC_LL: /* Load and stores */
30556 check_insn(ctx, ISA_MIPS2);
30557 if (ctx->insn_flags & INSN_R5900) {
30558 check_insn_opc_user_only(ctx, INSN_R5900);
30560 /* Fallthrough */
30561 case OPC_LWL:
30562 case OPC_LWR:
30563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30564 /* Fallthrough */
30565 case OPC_LB:
30566 case OPC_LH:
30567 case OPC_LW:
30568 case OPC_LWPC:
30569 case OPC_LBU:
30570 case OPC_LHU:
30571 gen_ld(ctx, op, rt, rs, imm);
30572 break;
30573 case OPC_SWL:
30574 case OPC_SWR:
30575 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30576 /* fall through */
30577 case OPC_SB:
30578 case OPC_SH:
30579 case OPC_SW:
30580 gen_st(ctx, op, rt, rs, imm);
30581 break;
30582 case OPC_SC:
30583 check_insn(ctx, ISA_MIPS2);
30584 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30585 if (ctx->insn_flags & INSN_R5900) {
30586 check_insn_opc_user_only(ctx, INSN_R5900);
30588 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30589 break;
30590 case OPC_CACHE:
30591 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30592 check_cp0_enabled(ctx);
30593 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
30594 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30595 gen_cache_operation(ctx, rt, rs, imm);
30597 /* Treat as NOP. */
30598 break;
30599 case OPC_PREF:
30600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30601 if (ctx->insn_flags & INSN_R5900) {
30602 /* Treat as NOP. */
30603 } else {
30604 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
30605 /* Treat as NOP. */
30607 break;
30609 /* Floating point (COP1). */
30610 case OPC_LWC1:
30611 case OPC_LDC1:
30612 case OPC_SWC1:
30613 case OPC_SDC1:
30614 gen_cop1_ldst(ctx, op, rt, rs, imm);
30615 break;
30617 case OPC_CP1:
30618 op1 = MASK_CP1(ctx->opcode);
30620 switch (op1) {
30621 case OPC_MFHC1:
30622 case OPC_MTHC1:
30623 check_cp1_enabled(ctx);
30624 check_insn(ctx, ISA_MIPS32R2);
30625 /* fall through */
30626 case OPC_MFC1:
30627 case OPC_CFC1:
30628 case OPC_MTC1:
30629 case OPC_CTC1:
30630 check_cp1_enabled(ctx);
30631 gen_cp1(ctx, op1, rt, rd);
30632 break;
30633 #if defined(TARGET_MIPS64)
30634 case OPC_DMFC1:
30635 case OPC_DMTC1:
30636 check_cp1_enabled(ctx);
30637 check_insn(ctx, ISA_MIPS3);
30638 check_mips_64(ctx);
30639 gen_cp1(ctx, op1, rt, rd);
30640 break;
30641 #endif
30642 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30643 check_cp1_enabled(ctx);
30644 if (ctx->insn_flags & ISA_MIPS32R6) {
30645 /* OPC_BC1EQZ */
30646 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30647 rt, imm << 2, 4);
30648 } else {
30649 /* OPC_BC1ANY2 */
30650 check_cop1x(ctx);
30651 check_insn(ctx, ASE_MIPS3D);
30652 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30653 (rt >> 2) & 0x7, imm << 2);
30655 break;
30656 case OPC_BC1NEZ:
30657 check_cp1_enabled(ctx);
30658 check_insn(ctx, ISA_MIPS32R6);
30659 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30660 rt, imm << 2, 4);
30661 break;
30662 case OPC_BC1ANY4:
30663 check_cp1_enabled(ctx);
30664 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30665 check_cop1x(ctx);
30666 check_insn(ctx, ASE_MIPS3D);
30667 /* fall through */
30668 case OPC_BC1:
30669 check_cp1_enabled(ctx);
30670 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30671 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30672 (rt >> 2) & 0x7, imm << 2);
30673 break;
30674 case OPC_PS_FMT:
30675 check_ps(ctx);
30676 /* fall through */
30677 case OPC_S_FMT:
30678 case OPC_D_FMT:
30679 check_cp1_enabled(ctx);
30680 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30681 (imm >> 8) & 0x7);
30682 break;
30683 case OPC_W_FMT:
30684 case OPC_L_FMT:
30686 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30687 check_cp1_enabled(ctx);
30688 if (ctx->insn_flags & ISA_MIPS32R6) {
30689 switch (r6_op) {
30690 case R6_OPC_CMP_AF_S:
30691 case R6_OPC_CMP_UN_S:
30692 case R6_OPC_CMP_EQ_S:
30693 case R6_OPC_CMP_UEQ_S:
30694 case R6_OPC_CMP_LT_S:
30695 case R6_OPC_CMP_ULT_S:
30696 case R6_OPC_CMP_LE_S:
30697 case R6_OPC_CMP_ULE_S:
30698 case R6_OPC_CMP_SAF_S:
30699 case R6_OPC_CMP_SUN_S:
30700 case R6_OPC_CMP_SEQ_S:
30701 case R6_OPC_CMP_SEUQ_S:
30702 case R6_OPC_CMP_SLT_S:
30703 case R6_OPC_CMP_SULT_S:
30704 case R6_OPC_CMP_SLE_S:
30705 case R6_OPC_CMP_SULE_S:
30706 case R6_OPC_CMP_OR_S:
30707 case R6_OPC_CMP_UNE_S:
30708 case R6_OPC_CMP_NE_S:
30709 case R6_OPC_CMP_SOR_S:
30710 case R6_OPC_CMP_SUNE_S:
30711 case R6_OPC_CMP_SNE_S:
30712 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30713 break;
30714 case R6_OPC_CMP_AF_D:
30715 case R6_OPC_CMP_UN_D:
30716 case R6_OPC_CMP_EQ_D:
30717 case R6_OPC_CMP_UEQ_D:
30718 case R6_OPC_CMP_LT_D:
30719 case R6_OPC_CMP_ULT_D:
30720 case R6_OPC_CMP_LE_D:
30721 case R6_OPC_CMP_ULE_D:
30722 case R6_OPC_CMP_SAF_D:
30723 case R6_OPC_CMP_SUN_D:
30724 case R6_OPC_CMP_SEQ_D:
30725 case R6_OPC_CMP_SEUQ_D:
30726 case R6_OPC_CMP_SLT_D:
30727 case R6_OPC_CMP_SULT_D:
30728 case R6_OPC_CMP_SLE_D:
30729 case R6_OPC_CMP_SULE_D:
30730 case R6_OPC_CMP_OR_D:
30731 case R6_OPC_CMP_UNE_D:
30732 case R6_OPC_CMP_NE_D:
30733 case R6_OPC_CMP_SOR_D:
30734 case R6_OPC_CMP_SUNE_D:
30735 case R6_OPC_CMP_SNE_D:
30736 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30737 break;
30738 default:
30739 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
30740 rt, rd, sa, (imm >> 8) & 0x7);
30742 break;
30744 } else {
30745 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30746 (imm >> 8) & 0x7);
30748 break;
30750 case OPC_BZ_V:
30751 case OPC_BNZ_V:
30752 case OPC_BZ_B:
30753 case OPC_BZ_H:
30754 case OPC_BZ_W:
30755 case OPC_BZ_D:
30756 case OPC_BNZ_B:
30757 case OPC_BNZ_H:
30758 case OPC_BNZ_W:
30759 case OPC_BNZ_D:
30760 check_insn(ctx, ASE_MSA);
30761 gen_msa_branch(env, ctx, op1);
30762 break;
30763 default:
30764 MIPS_INVAL("cp1");
30765 generate_exception_end(ctx, EXCP_RI);
30766 break;
30768 break;
30770 /* Compact branches [R6] and COP2 [non-R6] */
30771 case OPC_BC: /* OPC_LWC2 */
30772 case OPC_BALC: /* OPC_SWC2 */
30773 if (ctx->insn_flags & ISA_MIPS32R6) {
30774 /* OPC_BC, OPC_BALC */
30775 gen_compute_compact_branch(ctx, op, 0, 0,
30776 sextract32(ctx->opcode << 2, 0, 28));
30777 } else {
30778 /* OPC_LWC2, OPC_SWC2 */
30779 /* COP2: Not implemented. */
30780 generate_exception_err(ctx, EXCP_CpU, 2);
30782 break;
30783 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
30784 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
30785 if (ctx->insn_flags & ISA_MIPS32R6) {
30786 if (rs != 0) {
30787 /* OPC_BEQZC, OPC_BNEZC */
30788 gen_compute_compact_branch(ctx, op, rs, 0,
30789 sextract32(ctx->opcode << 2, 0, 23));
30790 } else {
30791 /* OPC_JIC, OPC_JIALC */
30792 gen_compute_compact_branch(ctx, op, 0, rt, imm);
30794 } else {
30795 /* OPC_LWC2, OPC_SWC2 */
30796 /* COP2: Not implemented. */
30797 generate_exception_err(ctx, EXCP_CpU, 2);
30799 break;
30800 case OPC_CP2:
30801 check_insn(ctx, ASE_LMMI);
30802 /* Note that these instructions use different fields. */
30803 gen_loongson_multimedia(ctx, sa, rd, rt);
30804 break;
30806 case OPC_CP3:
30807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30808 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
30809 check_cp1_enabled(ctx);
30810 op1 = MASK_CP3(ctx->opcode);
30811 switch (op1) {
30812 case OPC_LUXC1:
30813 case OPC_SUXC1:
30814 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30815 /* Fallthrough */
30816 case OPC_LWXC1:
30817 case OPC_LDXC1:
30818 case OPC_SWXC1:
30819 case OPC_SDXC1:
30820 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30821 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
30822 break;
30823 case OPC_PREFX:
30824 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30825 /* Treat as NOP. */
30826 break;
30827 case OPC_ALNV_PS:
30828 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30829 /* Fallthrough */
30830 case OPC_MADD_S:
30831 case OPC_MADD_D:
30832 case OPC_MADD_PS:
30833 case OPC_MSUB_S:
30834 case OPC_MSUB_D:
30835 case OPC_MSUB_PS:
30836 case OPC_NMADD_S:
30837 case OPC_NMADD_D:
30838 case OPC_NMADD_PS:
30839 case OPC_NMSUB_S:
30840 case OPC_NMSUB_D:
30841 case OPC_NMSUB_PS:
30842 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30843 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
30844 break;
30845 default:
30846 MIPS_INVAL("cp3");
30847 generate_exception_end(ctx, EXCP_RI);
30848 break;
30850 } else {
30851 generate_exception_err(ctx, EXCP_CpU, 1);
30853 break;
30855 #if defined(TARGET_MIPS64)
30856 /* MIPS64 opcodes */
30857 case OPC_LLD:
30858 if (ctx->insn_flags & INSN_R5900) {
30859 check_insn_opc_user_only(ctx, INSN_R5900);
30861 /* fall through */
30862 case OPC_LDL:
30863 case OPC_LDR:
30864 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30865 /* fall through */
30866 case OPC_LWU:
30867 case OPC_LD:
30868 check_insn(ctx, ISA_MIPS3);
30869 check_mips_64(ctx);
30870 gen_ld(ctx, op, rt, rs, imm);
30871 break;
30872 case OPC_SDL:
30873 case OPC_SDR:
30874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30875 /* fall through */
30876 case OPC_SD:
30877 check_insn(ctx, ISA_MIPS3);
30878 check_mips_64(ctx);
30879 gen_st(ctx, op, rt, rs, imm);
30880 break;
30881 case OPC_SCD:
30882 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30883 check_insn(ctx, ISA_MIPS3);
30884 if (ctx->insn_flags & INSN_R5900) {
30885 check_insn_opc_user_only(ctx, INSN_R5900);
30887 check_mips_64(ctx);
30888 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
30889 break;
30890 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
30891 if (ctx->insn_flags & ISA_MIPS32R6) {
30892 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
30893 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30894 } else {
30895 /* OPC_DADDI */
30896 check_insn(ctx, ISA_MIPS3);
30897 check_mips_64(ctx);
30898 gen_arith_imm(ctx, op, rt, rs, imm);
30900 break;
30901 case OPC_DADDIU:
30902 check_insn(ctx, ISA_MIPS3);
30903 check_mips_64(ctx);
30904 gen_arith_imm(ctx, op, rt, rs, imm);
30905 break;
30906 #else
30907 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
30908 if (ctx->insn_flags & ISA_MIPS32R6) {
30909 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30910 } else {
30911 MIPS_INVAL("major opcode");
30912 generate_exception_end(ctx, EXCP_RI);
30914 break;
30915 #endif
30916 case OPC_DAUI: /* OPC_JALX */
30917 if (ctx->insn_flags & ISA_MIPS32R6) {
30918 #if defined(TARGET_MIPS64)
30919 /* OPC_DAUI */
30920 check_mips_64(ctx);
30921 if (rs == 0) {
30922 generate_exception(ctx, EXCP_RI);
30923 } else if (rt != 0) {
30924 TCGv t0 = tcg_temp_new();
30925 gen_load_gpr(t0, rs);
30926 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30927 tcg_temp_free(t0);
30929 #else
30930 generate_exception_end(ctx, EXCP_RI);
30931 MIPS_INVAL("major opcode");
30932 #endif
30933 } else {
30934 /* OPC_JALX */
30935 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30936 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30937 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30939 break;
30940 case OPC_MSA: /* OPC_MDMX */
30941 if (ctx->insn_flags & INSN_R5900) {
30942 #if defined(TARGET_MIPS64)
30943 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
30944 #endif
30945 } else {
30946 /* MDMX: Not implemented. */
30947 gen_msa(env, ctx);
30949 break;
30950 case OPC_PCREL:
30951 check_insn(ctx, ISA_MIPS32R6);
30952 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
30953 break;
30954 default: /* Invalid */
30955 MIPS_INVAL("major opcode");
30956 generate_exception_end(ctx, EXCP_RI);
30957 break;
30961 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
30963 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30964 CPUMIPSState *env = cs->env_ptr;
30966 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
30967 ctx->saved_pc = -1;
30968 ctx->insn_flags = env->insn_flags;
30969 ctx->CP0_Config1 = env->CP0_Config1;
30970 ctx->CP0_Config2 = env->CP0_Config2;
30971 ctx->CP0_Config3 = env->CP0_Config3;
30972 ctx->CP0_Config5 = env->CP0_Config5;
30973 ctx->btarget = 0;
30974 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30975 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30976 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30977 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30978 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30979 ctx->PAMask = env->PAMask;
30980 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30981 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30982 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30983 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30984 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
30985 /* Restore delay slot state from the tb context. */
30986 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30987 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30988 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
30989 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
30990 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30991 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
30992 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
30993 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
30994 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
30995 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
30996 restore_cpu_state(env, ctx);
30997 #ifdef CONFIG_USER_ONLY
30998 ctx->mem_idx = MIPS_HFLAG_UM;
30999 #else
31000 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
31001 #endif
31002 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
31003 MO_UNALN : MO_ALIGN;
31005 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31006 ctx->hflags);
31009 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31013 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31015 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31017 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31018 ctx->btarget);
31021 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31022 const CPUBreakpoint *bp)
31024 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31026 save_cpu_state(ctx, 1);
31027 ctx->base.is_jmp = DISAS_NORETURN;
31028 gen_helper_raise_exception_debug(cpu_env);
31030 * The address covered by the breakpoint must be included in
31031 * [tb->pc, tb->pc + tb->size) in order to for it to be
31032 * properly cleared -- thus we increment the PC here so that
31033 * the logic setting tb->size below does the right thing.
31035 ctx->base.pc_next += 4;
31036 return true;
31039 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31041 CPUMIPSState *env = cs->env_ptr;
31042 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31043 int insn_bytes;
31044 int is_slot;
31046 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
31047 if (ctx->insn_flags & ISA_NANOMIPS32) {
31048 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31049 insn_bytes = decode_nanomips_opc(env, ctx);
31050 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
31051 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31052 insn_bytes = 4;
31053 decode_opc(env, ctx);
31054 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31055 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31056 insn_bytes = decode_micromips_opc(env, ctx);
31057 } else if (ctx->insn_flags & ASE_MIPS16) {
31058 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31059 insn_bytes = decode_mips16_opc(env, ctx);
31060 } else {
31061 generate_exception_end(ctx, EXCP_RI);
31062 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31063 return;
31066 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31067 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31068 MIPS_HFLAG_FBNSLOT))) {
31070 * Force to generate branch as there is neither delay nor
31071 * forbidden slot.
31073 is_slot = 1;
31075 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31076 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
31078 * Force to generate branch as microMIPS R6 doesn't restrict
31079 * branches in the forbidden slot.
31081 is_slot = 1;
31084 if (is_slot) {
31085 gen_branch(ctx, insn_bytes);
31087 ctx->base.pc_next += insn_bytes;
31089 if (ctx->base.is_jmp != DISAS_NEXT) {
31090 return;
31093 * Execute a branch and its delay slot as a single instruction.
31094 * This is what GDB expects and is consistent with what the
31095 * hardware does (e.g. if a delay slot instruction faults, the
31096 * reported PC is the PC of the branch).
31098 if (ctx->base.singlestep_enabled &&
31099 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31100 ctx->base.is_jmp = DISAS_TOO_MANY;
31102 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31103 ctx->base.is_jmp = DISAS_TOO_MANY;
31107 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31109 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31111 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31112 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
31113 gen_helper_raise_exception_debug(cpu_env);
31114 } else {
31115 switch (ctx->base.is_jmp) {
31116 case DISAS_STOP:
31117 gen_save_pc(ctx->base.pc_next);
31118 tcg_gen_lookup_and_goto_ptr();
31119 break;
31120 case DISAS_NEXT:
31121 case DISAS_TOO_MANY:
31122 save_cpu_state(ctx, 0);
31123 gen_goto_tb(ctx, 0, ctx->base.pc_next);
31124 break;
31125 case DISAS_EXIT:
31126 tcg_gen_exit_tb(NULL, 0);
31127 break;
31128 case DISAS_NORETURN:
31129 break;
31130 default:
31131 g_assert_not_reached();
31136 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31138 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31139 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31142 static const TranslatorOps mips_tr_ops = {
31143 .init_disas_context = mips_tr_init_disas_context,
31144 .tb_start = mips_tr_tb_start,
31145 .insn_start = mips_tr_insn_start,
31146 .breakpoint_check = mips_tr_breakpoint_check,
31147 .translate_insn = mips_tr_translate_insn,
31148 .tb_stop = mips_tr_tb_stop,
31149 .disas_log = mips_tr_disas_log,
31152 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31154 DisasContext ctx;
31156 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31159 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31161 int i;
31162 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31164 #define printfpr(fp) \
31165 do { \
31166 if (is_fpu64) \
31167 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31168 " fd:%13g fs:%13g psu: %13g\n", \
31169 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31170 (double)(fp)->fd, \
31171 (double)(fp)->fs[FP_ENDIAN_IDX], \
31172 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31173 else { \
31174 fpr_t tmp; \
31175 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31176 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31177 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31178 " fd:%13g fs:%13g psu:%13g\n", \
31179 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31180 (double)tmp.fd, \
31181 (double)tmp.fs[FP_ENDIAN_IDX], \
31182 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31184 } while (0)
31187 qemu_fprintf(f,
31188 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31189 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31190 get_float_exception_flags(&env->active_fpu.fp_status));
31191 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31192 qemu_fprintf(f, "%3s: ", fregnames[i]);
31193 printfpr(&env->active_fpu.fpr[i]);
31196 #undef printfpr
31199 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31201 MIPSCPU *cpu = MIPS_CPU(cs);
31202 CPUMIPSState *env = &cpu->env;
31203 int i;
31205 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31206 " LO=0x" TARGET_FMT_lx " ds %04x "
31207 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31208 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31209 env->hflags, env->btarget, env->bcond);
31210 for (i = 0; i < 32; i++) {
31211 if ((i & 3) == 0) {
31212 qemu_fprintf(f, "GPR%02d:", i);
31214 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31215 regnames[i], env->active_tc.gpr[i]);
31216 if ((i & 3) == 3) {
31217 qemu_fprintf(f, "\n");
31221 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31222 TARGET_FMT_lx "\n",
31223 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31224 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31225 PRIx64 "\n",
31226 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31227 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31228 env->CP0_Config2, env->CP0_Config3);
31229 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31230 env->CP0_Config4, env->CP0_Config5);
31231 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31232 fpu_dump_state(env, f, flags);
31236 void mips_tcg_init(void)
31238 int i;
31240 cpu_gpr[0] = NULL;
31241 for (i = 1; i < 32; i++)
31242 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31243 offsetof(CPUMIPSState,
31244 active_tc.gpr[i]),
31245 regnames[i]);
31247 for (i = 0; i < 32; i++) {
31248 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31249 msa_wr_d[i * 2] =
31250 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31252 * The scalar floating-point unit (FPU) registers are mapped on
31253 * the MSA vector registers.
31255 fpu_f64[i] = msa_wr_d[i * 2];
31256 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31257 msa_wr_d[i * 2 + 1] =
31258 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31261 cpu_PC = tcg_global_mem_new(cpu_env,
31262 offsetof(CPUMIPSState, active_tc.PC), "PC");
31263 for (i = 0; i < MIPS_DSP_ACC; i++) {
31264 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31265 offsetof(CPUMIPSState, active_tc.HI[i]),
31266 regnames_HI[i]);
31267 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31268 offsetof(CPUMIPSState, active_tc.LO[i]),
31269 regnames_LO[i]);
31271 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31272 offsetof(CPUMIPSState,
31273 active_tc.DSPControl),
31274 "DSPControl");
31275 bcond = tcg_global_mem_new(cpu_env,
31276 offsetof(CPUMIPSState, bcond), "bcond");
31277 btarget = tcg_global_mem_new(cpu_env,
31278 offsetof(CPUMIPSState, btarget), "btarget");
31279 hflags = tcg_global_mem_new_i32(cpu_env,
31280 offsetof(CPUMIPSState, hflags), "hflags");
31282 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31283 offsetof(CPUMIPSState, active_fpu.fcr0),
31284 "fcr0");
31285 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31286 offsetof(CPUMIPSState, active_fpu.fcr31),
31287 "fcr31");
31288 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31289 "lladdr");
31290 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31291 "llval");
31293 #if defined(TARGET_MIPS64)
31294 cpu_mmr[0] = NULL;
31295 for (i = 1; i < 32; i++) {
31296 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31297 offsetof(CPUMIPSState,
31298 active_tc.mmr[i]),
31299 regnames[i]);
31301 #endif
31303 #if !defined(TARGET_MIPS64)
31304 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31305 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31306 offsetof(CPUMIPSState,
31307 active_tc.mxu_gpr[i]),
31308 mxuregnames[i]);
31311 mxu_CR = tcg_global_mem_new(cpu_env,
31312 offsetof(CPUMIPSState, active_tc.mxu_cr),
31313 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31314 #endif
31317 #include "translate_init.c.inc"
31319 void cpu_mips_realize_env(CPUMIPSState *env)
31321 env->exception_base = (int32_t)0xBFC00000;
31323 #ifndef CONFIG_USER_ONLY
31324 mmu_init(env, env->cpu_model);
31325 #endif
31326 fpu_init(env, env->cpu_model);
31327 mvp_init(env, env->cpu_model);
31330 bool cpu_supports_cps_smp(const char *cpu_type)
31332 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31333 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
31336 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
31338 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31339 return (mcc->cpu_def->insn_flags & isa) != 0;
31342 void cpu_set_exception_base(int vp_index, target_ulong address)
31344 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31345 vp->env.exception_base = address;
31348 void cpu_state_reset(CPUMIPSState *env)
31350 CPUState *cs = env_cpu(env);
31352 /* Reset registers to their default values */
31353 env->CP0_PRid = env->cpu_model->CP0_PRid;
31354 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31355 #ifdef TARGET_WORDS_BIGENDIAN
31356 env->CP0_Config0 |= (1 << CP0C0_BE);
31357 #endif
31358 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31359 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31360 env->CP0_Config3 = env->cpu_model->CP0_Config3;
31361 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31362 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
31363 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31364 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
31365 env->CP0_Config6 = env->cpu_model->CP0_Config6;
31366 env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
31367 env->CP0_Config7 = env->cpu_model->CP0_Config7;
31368 env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
31369 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31370 << env->cpu_model->CP0_LLAddr_shift;
31371 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
31372 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31373 env->CCRes = env->cpu_model->CCRes;
31374 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31375 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31376 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31377 env->current_tc = 0;
31378 env->SEGBITS = env->cpu_model->SEGBITS;
31379 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31380 #if defined(TARGET_MIPS64)
31381 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31382 env->SEGMask |= 3ULL << 62;
31384 #endif
31385 env->PABITS = env->cpu_model->PABITS;
31386 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31387 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31388 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31389 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31390 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31391 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31392 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31393 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31394 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31395 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
31396 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31397 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
31398 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
31399 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
31400 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
31401 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
31402 env->msair = env->cpu_model->MSAIR;
31403 env->insn_flags = env->cpu_model->insn_flags;
31405 #if defined(CONFIG_USER_ONLY)
31406 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
31407 # ifdef TARGET_MIPS64
31408 /* Enable 64-bit register mode. */
31409 env->CP0_Status |= (1 << CP0St_PX);
31410 # endif
31411 # ifdef TARGET_ABI_MIPSN64
31412 /* Enable 64-bit address mode. */
31413 env->CP0_Status |= (1 << CP0St_UX);
31414 # endif
31416 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31417 * hardware registers.
31419 env->CP0_HWREna |= 0x0000000F;
31420 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
31421 env->CP0_Status |= (1 << CP0St_CU1);
31423 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31424 env->CP0_Status |= (1 << CP0St_MX);
31426 # if defined(TARGET_MIPS64)
31427 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31428 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31429 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
31430 env->CP0_Status |= (1 << CP0St_FR);
31432 # endif
31433 #else
31434 if (env->hflags & MIPS_HFLAG_BMASK) {
31436 * If the exception was raised from a delay slot,
31437 * come back to the jump.
31439 env->CP0_ErrorEPC = (env->active_tc.PC
31440 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
31441 } else {
31442 env->CP0_ErrorEPC = env->active_tc.PC;
31444 env->active_tc.PC = env->exception_base;
31445 env->CP0_Random = env->tlb->nb_tlb - 1;
31446 env->tlb->tlb_in_use = env->tlb->nb_tlb;
31447 env->CP0_Wired = 0;
31448 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
31449 env->CP0_EBase = (cs->cpu_index & 0x3FF);
31450 if (mips_um_ksegs_enabled()) {
31451 env->CP0_EBase |= 0x40000000;
31452 } else {
31453 env->CP0_EBase |= (int32_t)0x80000000;
31455 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31456 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31458 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
31459 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
31460 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
31462 * Vectored interrupts not implemented, timer on int 7,
31463 * no performance counters.
31465 env->CP0_IntCtl = 0xe0000000;
31467 int i;
31469 for (i = 0; i < 7; i++) {
31470 env->CP0_WatchLo[i] = 0;
31471 env->CP0_WatchHi[i] = 0x80000000;
31473 env->CP0_WatchLo[7] = 0;
31474 env->CP0_WatchHi[7] = 0;
31476 /* Count register increments in debug mode, EJTAG version 1 */
31477 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
31479 cpu_mips_store_count(env, 1);
31481 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31482 int i;
31484 /* Only TC0 on VPE 0 starts as active. */
31485 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
31486 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
31487 env->tcs[i].CP0_TCHalt = 1;
31489 env->active_tc.CP0_TCHalt = 1;
31490 cs->halted = 1;
31492 if (cs->cpu_index == 0) {
31493 /* VPE0 starts up enabled. */
31494 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31495 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31497 /* TC0 starts up unhalted. */
31498 cs->halted = 0;
31499 env->active_tc.CP0_TCHalt = 0;
31500 env->tcs[0].CP0_TCHalt = 0;
31501 /* With thread 0 active. */
31502 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31503 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31508 * Configure default legacy segmentation control. We use this regardless of
31509 * whether segmentation control is presented to the guest.
31511 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31512 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31513 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31514 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31515 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31516 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31517 (2 << CP0SC_C);
31518 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31519 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31520 (3 << CP0SC_C)) << 16;
31521 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31522 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31523 (1 << CP0SC_EU) | (2 << CP0SC_C);
31524 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31525 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31526 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31527 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31528 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
31529 #endif
31530 if ((env->insn_flags & ISA_MIPS32R6) &&
31531 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31532 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31533 env->CP0_Status |= (1 << CP0St_FR);
31536 if (env->insn_flags & ISA_MIPS32R6) {
31537 /* PTW = 1 */
31538 env->CP0_PWSize = 0x40;
31539 /* GDI = 12 */
31540 /* UDI = 12 */
31541 /* MDI = 12 */
31542 /* PRI = 12 */
31543 /* PTEI = 2 */
31544 env->CP0_PWField = 0x0C30C302;
31545 } else {
31546 /* GDI = 0 */
31547 /* UDI = 0 */
31548 /* MDI = 0 */
31549 /* PRI = 0 */
31550 /* PTEI = 2 */
31551 env->CP0_PWField = 0x02;
31554 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31555 /* microMIPS on reset when Config3.ISA is 3 */
31556 env->hflags |= MIPS_HFLAG_M16;
31559 /* MSA */
31560 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
31561 msa_reset(env);
31564 compute_hflags(env);
31565 restore_fp_status(env);
31566 restore_pamask(env);
31567 cs->exception_index = EXCP_NONE;
31569 if (semihosting_get_argc()) {
31570 /* UHI interface can be used to obtain argc and argv */
31571 env->active_tc.gpr[4] = -1;
31575 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31576 target_ulong *data)
31578 env->active_tc.PC = data[0];
31579 env->hflags &= ~MIPS_HFLAG_BMASK;
31580 env->hflags |= data[1];
31581 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31582 case MIPS_HFLAG_BR:
31583 break;
31584 case MIPS_HFLAG_BC:
31585 case MIPS_HFLAG_BL:
31586 case MIPS_HFLAG_B:
31587 env->btarget = data[2];
31588 break;