target/mips: Replace gen_exception_end(EXCP_RI) by gen_rsvd_instruction
[qemu.git] / target / mips / translate.c
blobd7767215050a71cc0010edf21f2d2f7fc07ed86e
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.1 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 "tcg/tcg-op.h"
28 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "hw/semihosting/semihost.h"
33 #include "target/mips/trace.h"
34 #include "trace-tcg.h"
35 #include "exec/translator.h"
36 #include "exec/log.h"
37 #include "qemu/qemu-print.h"
38 #include "fpu_helper.h"
39 #include "translate.h"
41 enum {
42 /* indirect opcode tables */
43 OPC_SPECIAL = (0x00 << 26),
44 OPC_REGIMM = (0x01 << 26),
45 OPC_CP0 = (0x10 << 26),
46 OPC_CP1 = (0x11 << 26),
47 OPC_CP2 = (0x12 << 26),
48 OPC_CP3 = (0x13 << 26),
49 OPC_SPECIAL2 = (0x1C << 26),
50 OPC_SPECIAL3 = (0x1F << 26),
51 /* arithmetic with immediate */
52 OPC_ADDI = (0x08 << 26),
53 OPC_ADDIU = (0x09 << 26),
54 OPC_SLTI = (0x0A << 26),
55 OPC_SLTIU = (0x0B << 26),
56 /* logic with immediate */
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
61 /* arithmetic with immediate */
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26),
76 OPC_DAUI = (0x1D << 26),
77 /* Load and stores */
78 OPC_LDL = (0x1A << 26),
79 OPC_LDR = (0x1B << 26),
80 OPC_LB = (0x20 << 26),
81 OPC_LH = (0x21 << 26),
82 OPC_LWL = (0x22 << 26),
83 OPC_LW = (0x23 << 26),
84 OPC_LWPC = OPC_LW | 0x5,
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_LDPC = OPC_LD | 0x5,
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* Compact Branches */
113 OPC_BLEZALC = (0x06 << 26),
114 OPC_BGEZALC = (0x06 << 26),
115 OPC_BGEUC = (0x06 << 26),
116 OPC_BGTZALC = (0x07 << 26),
117 OPC_BLTZALC = (0x07 << 26),
118 OPC_BLTUC = (0x07 << 26),
119 OPC_BOVC = (0x08 << 26),
120 OPC_BEQZALC = (0x08 << 26),
121 OPC_BEQC = (0x08 << 26),
122 OPC_BLEZC = (0x16 << 26),
123 OPC_BGEZC = (0x16 << 26),
124 OPC_BGEC = (0x16 << 26),
125 OPC_BGTZC = (0x17 << 26),
126 OPC_BLTZC = (0x17 << 26),
127 OPC_BLTC = (0x17 << 26),
128 OPC_BNVC = (0x18 << 26),
129 OPC_BNEZALC = (0x18 << 26),
130 OPC_BNEC = (0x18 << 26),
131 OPC_BC = (0x32 << 26),
132 OPC_BEQZC = (0x36 << 26),
133 OPC_JIC = (0x36 << 26),
134 OPC_BALC = (0x3A << 26),
135 OPC_BNEZC = (0x3E << 26),
136 OPC_JIALC = (0x3E << 26),
137 /* MDMX ASE specific */
138 OPC_MDMX = (0x1E << 26),
139 /* MSA ASE, same as MDMX */
140 OPC_MSA = OPC_MDMX,
141 /* Cache and prefetch */
142 OPC_CACHE = (0x2F << 26),
143 OPC_PREF = (0x33 << 26),
144 /* PC-relative address computation / loads */
145 OPC_PCREL = (0x3B << 26),
148 /* PC-relative address computation / loads */
149 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
150 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
151 enum {
152 /* Instructions determined by bits 19 and 20 */
153 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
154 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
155 OPC_LWUPC = OPC_PCREL | (2 << 19),
157 /* Instructions determined by bits 16 ... 20 */
158 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
159 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
161 /* Other */
162 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
165 /* MIPS special opcodes */
166 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
168 enum {
169 /* Shifts */
170 OPC_SLL = 0x00 | OPC_SPECIAL,
171 /* NOP is SLL r0, r0, 0 */
172 /* SSNOP is SLL r0, r0, 1 */
173 /* EHB is SLL r0, r0, 3 */
174 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
175 OPC_ROTR = OPC_SRL | (1 << 21),
176 OPC_SRA = 0x03 | OPC_SPECIAL,
177 OPC_SLLV = 0x04 | OPC_SPECIAL,
178 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
179 OPC_ROTRV = OPC_SRLV | (1 << 6),
180 OPC_SRAV = 0x07 | OPC_SPECIAL,
181 OPC_DSLLV = 0x14 | OPC_SPECIAL,
182 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
183 OPC_DROTRV = OPC_DSRLV | (1 << 6),
184 OPC_DSRAV = 0x17 | OPC_SPECIAL,
185 OPC_DSLL = 0x38 | OPC_SPECIAL,
186 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
187 OPC_DROTR = OPC_DSRL | (1 << 21),
188 OPC_DSRA = 0x3B | OPC_SPECIAL,
189 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
190 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
191 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
192 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
193 /* Multiplication / division */
194 OPC_MULT = 0x18 | OPC_SPECIAL,
195 OPC_MULTU = 0x19 | OPC_SPECIAL,
196 OPC_DIV = 0x1A | OPC_SPECIAL,
197 OPC_DIVU = 0x1B | OPC_SPECIAL,
198 OPC_DMULT = 0x1C | OPC_SPECIAL,
199 OPC_DMULTU = 0x1D | OPC_SPECIAL,
200 OPC_DDIV = 0x1E | OPC_SPECIAL,
201 OPC_DDIVU = 0x1F | OPC_SPECIAL,
203 /* 2 registers arithmetic / logic */
204 OPC_ADD = 0x20 | OPC_SPECIAL,
205 OPC_ADDU = 0x21 | OPC_SPECIAL,
206 OPC_SUB = 0x22 | OPC_SPECIAL,
207 OPC_SUBU = 0x23 | OPC_SPECIAL,
208 OPC_AND = 0x24 | OPC_SPECIAL,
209 OPC_OR = 0x25 | OPC_SPECIAL,
210 OPC_XOR = 0x26 | OPC_SPECIAL,
211 OPC_NOR = 0x27 | OPC_SPECIAL,
212 OPC_SLT = 0x2A | OPC_SPECIAL,
213 OPC_SLTU = 0x2B | OPC_SPECIAL,
214 OPC_DADD = 0x2C | OPC_SPECIAL,
215 OPC_DADDU = 0x2D | OPC_SPECIAL,
216 OPC_DSUB = 0x2E | OPC_SPECIAL,
217 OPC_DSUBU = 0x2F | OPC_SPECIAL,
218 /* Jumps */
219 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
220 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
221 /* Traps */
222 OPC_TGE = 0x30 | OPC_SPECIAL,
223 OPC_TGEU = 0x31 | OPC_SPECIAL,
224 OPC_TLT = 0x32 | OPC_SPECIAL,
225 OPC_TLTU = 0x33 | OPC_SPECIAL,
226 OPC_TEQ = 0x34 | OPC_SPECIAL,
227 OPC_TNE = 0x36 | OPC_SPECIAL,
228 /* HI / LO registers load & stores */
229 OPC_MFHI = 0x10 | OPC_SPECIAL,
230 OPC_MTHI = 0x11 | OPC_SPECIAL,
231 OPC_MFLO = 0x12 | OPC_SPECIAL,
232 OPC_MTLO = 0x13 | OPC_SPECIAL,
233 /* Conditional moves */
234 OPC_MOVZ = 0x0A | OPC_SPECIAL,
235 OPC_MOVN = 0x0B | OPC_SPECIAL,
237 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
238 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
240 OPC_MOVCI = 0x01 | OPC_SPECIAL,
242 /* Special */
243 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
244 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
245 OPC_BREAK = 0x0D | OPC_SPECIAL,
246 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
247 OPC_SYNC = 0x0F | OPC_SPECIAL,
249 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
250 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
251 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
252 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
256 * R6 Multiply and Divide instructions have the same opcode
257 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
259 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
261 enum {
262 R6_OPC_MUL = OPC_MULT | (2 << 6),
263 R6_OPC_MUH = OPC_MULT | (3 << 6),
264 R6_OPC_MULU = OPC_MULTU | (2 << 6),
265 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
266 R6_OPC_DIV = OPC_DIV | (2 << 6),
267 R6_OPC_MOD = OPC_DIV | (3 << 6),
268 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
269 R6_OPC_MODU = OPC_DIVU | (3 << 6),
271 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
272 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
273 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
274 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
275 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
276 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
277 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
278 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
280 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
281 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
282 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
283 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
284 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
286 OPC_LSA = 0x05 | OPC_SPECIAL,
287 OPC_DLSA = 0x15 | OPC_SPECIAL,
290 /* Multiplication variants of the vr54xx. */
291 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
293 enum {
294 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
295 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
296 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
297 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
298 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
299 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
300 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
301 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
302 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
303 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
304 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
305 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
306 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
307 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
310 /* REGIMM (rt field) opcodes */
311 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
313 enum {
314 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
315 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
316 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
317 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
318 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
319 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
320 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
321 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
322 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
323 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
324 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
325 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
326 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
327 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
328 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
329 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
331 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
332 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
335 /* Special2 opcodes */
336 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
338 enum {
339 /* Multiply & xxx operations */
340 OPC_MADD = 0x00 | OPC_SPECIAL2,
341 OPC_MADDU = 0x01 | OPC_SPECIAL2,
342 OPC_MUL = 0x02 | OPC_SPECIAL2,
343 OPC_MSUB = 0x04 | OPC_SPECIAL2,
344 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
345 /* Loongson 2F */
346 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
347 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
348 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
349 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
350 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
351 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
352 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
353 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
354 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
355 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
356 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
357 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
358 /* Misc */
359 OPC_CLZ = 0x20 | OPC_SPECIAL2,
360 OPC_CLO = 0x21 | OPC_SPECIAL2,
361 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
362 OPC_DCLO = 0x25 | OPC_SPECIAL2,
363 /* Special */
364 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
367 /* Special3 opcodes */
368 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
370 enum {
371 OPC_EXT = 0x00 | OPC_SPECIAL3,
372 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
373 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
374 OPC_DEXT = 0x03 | OPC_SPECIAL3,
375 OPC_INS = 0x04 | OPC_SPECIAL3,
376 OPC_DINSM = 0x05 | OPC_SPECIAL3,
377 OPC_DINSU = 0x06 | OPC_SPECIAL3,
378 OPC_DINS = 0x07 | OPC_SPECIAL3,
379 OPC_FORK = 0x08 | OPC_SPECIAL3,
380 OPC_YIELD = 0x09 | OPC_SPECIAL3,
381 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
382 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
383 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
384 OPC_GINV = 0x3D | OPC_SPECIAL3,
386 /* Loongson 2E */
387 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
388 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
389 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
390 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
391 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
392 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
393 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
394 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
395 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
396 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
397 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
398 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
400 /* MIPS DSP Load */
401 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
402 /* MIPS DSP Arithmetic */
403 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
404 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
405 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
406 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
407 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
408 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
409 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
410 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
411 /* MIPS DSP GPR-Based Shift Sub-class */
412 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
413 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
414 /* MIPS DSP Multiply Sub-class insns */
415 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
416 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
417 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
418 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
419 /* DSP Bit/Manipulation Sub-class */
420 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
421 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
422 /* MIPS DSP Append Sub-class */
423 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
424 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
425 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
426 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
427 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
429 /* EVA */
430 OPC_LWLE = 0x19 | OPC_SPECIAL3,
431 OPC_LWRE = 0x1A | OPC_SPECIAL3,
432 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
433 OPC_SBE = 0x1C | OPC_SPECIAL3,
434 OPC_SHE = 0x1D | OPC_SPECIAL3,
435 OPC_SCE = 0x1E | OPC_SPECIAL3,
436 OPC_SWE = 0x1F | OPC_SPECIAL3,
437 OPC_SWLE = 0x21 | OPC_SPECIAL3,
438 OPC_SWRE = 0x22 | OPC_SPECIAL3,
439 OPC_PREFE = 0x23 | OPC_SPECIAL3,
440 OPC_LBUE = 0x28 | OPC_SPECIAL3,
441 OPC_LHUE = 0x29 | OPC_SPECIAL3,
442 OPC_LBE = 0x2C | OPC_SPECIAL3,
443 OPC_LHE = 0x2D | OPC_SPECIAL3,
444 OPC_LLE = 0x2E | OPC_SPECIAL3,
445 OPC_LWE = 0x2F | OPC_SPECIAL3,
447 /* R6 */
448 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
449 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
450 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
451 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
452 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
453 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
456 /* Loongson EXT load/store quad word opcodes */
457 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
458 enum {
459 OPC_GSLQ = 0x0020 | OPC_LWC2,
460 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
461 OPC_GSSHFL = OPC_LWC2,
462 OPC_GSSQ = 0x0020 | OPC_SWC2,
463 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
464 OPC_GSSHFS = OPC_SWC2,
467 /* Loongson EXT shifted load/store opcodes */
468 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
469 enum {
470 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
471 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
472 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
473 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
474 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
475 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
476 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
477 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
480 /* Loongson EXT LDC2/SDC2 opcodes */
481 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
483 enum {
484 OPC_GSLBX = 0x0 | OPC_LDC2,
485 OPC_GSLHX = 0x1 | OPC_LDC2,
486 OPC_GSLWX = 0x2 | OPC_LDC2,
487 OPC_GSLDX = 0x3 | OPC_LDC2,
488 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
489 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
490 OPC_GSSBX = 0x0 | OPC_SDC2,
491 OPC_GSSHX = 0x1 | OPC_SDC2,
492 OPC_GSSWX = 0x2 | OPC_SDC2,
493 OPC_GSSDX = 0x3 | OPC_SDC2,
494 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
495 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
498 /* BSHFL opcodes */
499 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
501 enum {
502 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
503 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
504 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
505 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
506 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
507 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
508 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
509 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
512 /* DBSHFL opcodes */
513 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
515 enum {
516 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
517 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
518 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
519 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
520 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
521 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
522 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
523 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
524 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
525 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
526 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
529 /* MIPS DSP REGIMM opcodes */
530 enum {
531 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
532 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
535 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
536 /* MIPS DSP Load */
537 enum {
538 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
539 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
540 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
541 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
544 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
545 enum {
546 /* MIPS DSP Arithmetic Sub-class */
547 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
549 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
550 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
551 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
552 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
553 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
556 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
557 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
558 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
559 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
560 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
561 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
562 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
563 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
564 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
565 /* MIPS DSP Multiply Sub-class insns */
566 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
567 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
568 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
569 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
570 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
571 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
574 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
575 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
576 enum {
577 /* MIPS DSP Arithmetic Sub-class */
578 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
582 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
583 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
585 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
588 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
590 /* MIPS DSP Multiply Sub-class insns */
591 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
592 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
593 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
594 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
597 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
598 enum {
599 /* MIPS DSP Arithmetic Sub-class */
600 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
613 /* DSP Bit/Manipulation Sub-class */
614 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
621 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
622 enum {
623 /* MIPS DSP Arithmetic Sub-class */
624 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
626 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
627 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
631 /* DSP Compare-Pick Sub-class */
632 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
649 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
650 enum {
651 /* MIPS DSP GPR-Based Shift Sub-class */
652 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
676 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
677 enum {
678 /* MIPS DSP Multiply Sub-class insns */
679 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
693 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
696 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
700 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
703 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
704 enum {
705 /* DSP Bit/Manipulation Sub-class */
706 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
709 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
710 enum {
711 /* MIPS DSP Append Sub-class */
712 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
713 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
714 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
717 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
718 enum {
719 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
720 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
727 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
732 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
733 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
734 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
735 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
736 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
739 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
740 enum {
741 /* MIPS DSP Arithmetic Sub-class */
742 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
759 /* DSP Bit/Manipulation Sub-class */
760 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
768 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
769 enum {
770 /* MIPS DSP Multiply Sub-class insns */
771 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
772 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
773 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
774 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
775 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
776 /* MIPS DSP Arithmetic Sub-class */
777 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
783 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
784 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
793 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
794 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
800 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
801 enum {
802 /* DSP Compare-Pick Sub-class */
803 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
822 /* MIPS DSP Arithmetic Sub-class */
823 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
830 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
833 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
834 enum {
835 /* DSP Append Sub-class */
836 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
837 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
838 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
839 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
842 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
843 enum {
844 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
845 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
846 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
865 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
868 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
869 enum {
870 /* DSP Bit/Manipulation Sub-class */
871 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
874 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
875 enum {
876 /* MIPS DSP Multiply Sub-class insns */
877 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
905 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
906 enum {
907 /* MIPS DSP GPR-Based Shift Sub-class */
908 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
936 /* Coprocessor 0 (rs field) */
937 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
939 enum {
940 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
941 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
942 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
943 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
944 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
945 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
946 OPC_MFTR = (0x08 << 21) | OPC_CP0,
947 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
948 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
949 OPC_MTTR = (0x0C << 21) | OPC_CP0,
950 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
951 OPC_C0 = (0x10 << 21) | OPC_CP0,
952 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
953 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
954 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
955 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
956 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
957 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
958 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
959 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
960 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
961 OPC_C0_A = (0x1A << 21) | OPC_CP0,
962 OPC_C0_B = (0x1B << 21) | OPC_CP0,
963 OPC_C0_C = (0x1C << 21) | OPC_CP0,
964 OPC_C0_D = (0x1D << 21) | OPC_CP0,
965 OPC_C0_E = (0x1E << 21) | OPC_CP0,
966 OPC_C0_F = (0x1F << 21) | OPC_CP0,
969 /* MFMC0 opcodes */
970 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
972 enum {
973 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
974 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
975 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
976 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
977 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
978 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
979 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
980 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
983 /* Coprocessor 0 (with rs == C0) */
984 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
986 enum {
987 OPC_TLBR = 0x01 | OPC_C0,
988 OPC_TLBWI = 0x02 | OPC_C0,
989 OPC_TLBINV = 0x03 | OPC_C0,
990 OPC_TLBINVF = 0x04 | OPC_C0,
991 OPC_TLBWR = 0x06 | OPC_C0,
992 OPC_TLBP = 0x08 | OPC_C0,
993 OPC_RFE = 0x10 | OPC_C0,
994 OPC_ERET = 0x18 | OPC_C0,
995 OPC_DERET = 0x1F | OPC_C0,
996 OPC_WAIT = 0x20 | OPC_C0,
999 /* Coprocessor 1 (rs field) */
1000 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1002 /* Values for the fmt field in FP instructions */
1003 enum {
1004 /* 0 - 15 are reserved */
1005 FMT_S = 16, /* single fp */
1006 FMT_D = 17, /* double fp */
1007 FMT_E = 18, /* extended fp */
1008 FMT_Q = 19, /* quad fp */
1009 FMT_W = 20, /* 32-bit fixed */
1010 FMT_L = 21, /* 64-bit fixed */
1011 FMT_PS = 22, /* paired single fp */
1012 /* 23 - 31 are reserved */
1015 enum {
1016 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
1017 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
1018 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1019 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1020 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
1021 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
1022 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1023 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1024 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1025 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
1026 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1027 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
1028 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
1029 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
1030 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
1031 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
1032 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
1033 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
1034 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1035 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1036 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1037 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1038 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1039 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1040 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1041 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1042 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1043 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1044 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1045 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1048 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1049 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1051 enum {
1052 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1053 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1054 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1055 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1058 enum {
1059 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1060 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1063 enum {
1064 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1065 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1068 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1070 enum {
1071 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1072 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1073 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1074 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1075 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1076 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1077 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1078 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1079 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1080 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1081 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1084 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1086 enum {
1087 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1088 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1089 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1090 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1091 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1092 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1093 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1094 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1096 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1097 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1098 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1099 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1100 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1101 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1102 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1103 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1105 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1106 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1107 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1108 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1109 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1110 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1111 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1112 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1114 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1115 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1116 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1117 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1118 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1119 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1120 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1121 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1123 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1124 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1125 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1126 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1127 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1128 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1130 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1131 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1132 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1133 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1134 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1135 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1137 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1138 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1139 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1140 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1141 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1142 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1144 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1145 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1146 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1147 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1148 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1149 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1151 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1152 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1153 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1154 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1155 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1156 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1158 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1159 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1160 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1161 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1162 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1163 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1165 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1166 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1167 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1168 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1169 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1170 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1172 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1173 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1174 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1175 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1176 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1177 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1181 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1183 enum {
1184 OPC_LWXC1 = 0x00 | OPC_CP3,
1185 OPC_LDXC1 = 0x01 | OPC_CP3,
1186 OPC_LUXC1 = 0x05 | OPC_CP3,
1187 OPC_SWXC1 = 0x08 | OPC_CP3,
1188 OPC_SDXC1 = 0x09 | OPC_CP3,
1189 OPC_SUXC1 = 0x0D | OPC_CP3,
1190 OPC_PREFX = 0x0F | OPC_CP3,
1191 OPC_ALNV_PS = 0x1E | OPC_CP3,
1192 OPC_MADD_S = 0x20 | OPC_CP3,
1193 OPC_MADD_D = 0x21 | OPC_CP3,
1194 OPC_MADD_PS = 0x26 | OPC_CP3,
1195 OPC_MSUB_S = 0x28 | OPC_CP3,
1196 OPC_MSUB_D = 0x29 | OPC_CP3,
1197 OPC_MSUB_PS = 0x2E | OPC_CP3,
1198 OPC_NMADD_S = 0x30 | OPC_CP3,
1199 OPC_NMADD_D = 0x31 | OPC_CP3,
1200 OPC_NMADD_PS = 0x36 | OPC_CP3,
1201 OPC_NMSUB_S = 0x38 | OPC_CP3,
1202 OPC_NMSUB_D = 0x39 | OPC_CP3,
1203 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1206 /* MSA Opcodes */
1207 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1208 enum {
1209 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1210 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1211 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1212 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1213 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1214 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1215 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1216 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1217 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1218 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1219 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1220 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1221 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1222 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1223 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1224 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1225 OPC_MSA_ELM = 0x19 | OPC_MSA,
1226 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1227 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1228 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1229 OPC_MSA_VEC = 0x1E | OPC_MSA,
1231 /* MI10 instruction */
1232 OPC_LD_B = (0x20) | OPC_MSA,
1233 OPC_LD_H = (0x21) | OPC_MSA,
1234 OPC_LD_W = (0x22) | OPC_MSA,
1235 OPC_LD_D = (0x23) | OPC_MSA,
1236 OPC_ST_B = (0x24) | OPC_MSA,
1237 OPC_ST_H = (0x25) | OPC_MSA,
1238 OPC_ST_W = (0x26) | OPC_MSA,
1239 OPC_ST_D = (0x27) | OPC_MSA,
1242 enum {
1243 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1244 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1245 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1246 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1247 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1248 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1249 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1250 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1251 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1252 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1253 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1254 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1255 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1257 /* I8 instruction */
1258 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1259 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1260 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1261 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1262 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1263 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1264 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1265 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1266 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1267 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1269 /* VEC/2R/2RF instruction */
1270 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1271 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1272 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1273 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1274 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1275 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1276 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1278 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1279 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1281 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1282 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1283 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1284 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1285 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1287 /* 2RF instruction df(bit 16) = _w, _d */
1288 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1289 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1290 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1291 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1292 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1293 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1294 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1295 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1296 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1297 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1298 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1299 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1300 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1301 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1302 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1303 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1305 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1306 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1307 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1308 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1309 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1310 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1311 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1312 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1313 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1314 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1315 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1316 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1317 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1318 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1319 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1320 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1321 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1322 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1323 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1324 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1325 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1326 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1327 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1328 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1329 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1330 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1331 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1332 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1333 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1334 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1335 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1336 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1337 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1338 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1339 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1340 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1341 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1342 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1343 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1344 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1345 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1346 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1347 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1348 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1349 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1350 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1351 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1352 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1353 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1354 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1355 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1356 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1357 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1358 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1359 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1360 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1361 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1362 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1363 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1364 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1365 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1366 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1367 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1368 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1370 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1371 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1372 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1373 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1374 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1375 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1376 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1377 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1378 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1379 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1381 /* 3RF instruction _df(bit 21) = _w, _d */
1382 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1383 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1384 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1385 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1386 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1387 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1388 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1389 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1390 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1391 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1392 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1393 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1394 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1395 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1396 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1397 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1398 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1399 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1400 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1401 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1402 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1403 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1404 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1405 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1406 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1407 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1408 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1409 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1410 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1411 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1412 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1413 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1414 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1415 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1416 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1417 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1418 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1419 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1420 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1421 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1422 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1424 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1425 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1426 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1427 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1428 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1429 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1430 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1431 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1432 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1433 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1434 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1435 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1436 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1442 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1443 * ============================================
1446 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1447 * instructions set. It is designed to fit the needs of signal, graphical and
1448 * video processing applications. MXU instruction set is used in Xburst family
1449 * of microprocessors by Ingenic.
1451 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1452 * the control register.
1455 * The notation used in MXU assembler mnemonics
1456 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1458 * Register operands:
1460 * XRa, XRb, XRc, XRd - MXU registers
1461 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1463 * Non-register operands:
1465 * aptn1 - 1-bit accumulate add/subtract pattern
1466 * aptn2 - 2-bit accumulate add/subtract pattern
1467 * eptn2 - 2-bit execute add/subtract pattern
1468 * optn2 - 2-bit operand pattern
1469 * optn3 - 3-bit operand pattern
1470 * sft4 - 4-bit shift amount
1471 * strd2 - 2-bit stride amount
1473 * Prefixes:
1475 * Level of parallelism: Operand size:
1476 * S - single operation at a time 32 - word
1477 * D - two operations in parallel 16 - half word
1478 * Q - four operations in parallel 8 - byte
1480 * Operations:
1482 * ADD - Add or subtract
1483 * ADDC - Add with carry-in
1484 * ACC - Accumulate
1485 * ASUM - Sum together then accumulate (add or subtract)
1486 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1487 * AVG - Average between 2 operands
1488 * ABD - Absolute difference
1489 * ALN - Align data
1490 * AND - Logical bitwise 'and' operation
1491 * CPS - Copy sign
1492 * EXTR - Extract bits
1493 * I2M - Move from GPR register to MXU register
1494 * LDD - Load data from memory to XRF
1495 * LDI - Load data from memory to XRF (and increase the address base)
1496 * LUI - Load unsigned immediate
1497 * MUL - Multiply
1498 * MULU - Unsigned multiply
1499 * MADD - 64-bit operand add 32x32 product
1500 * MSUB - 64-bit operand subtract 32x32 product
1501 * MAC - Multiply and accumulate (add or subtract)
1502 * MAD - Multiply and add or subtract
1503 * MAX - Maximum between 2 operands
1504 * MIN - Minimum between 2 operands
1505 * M2I - Move from MXU register to GPR register
1506 * MOVZ - Move if zero
1507 * MOVN - Move if non-zero
1508 * NOR - Logical bitwise 'nor' operation
1509 * OR - Logical bitwise 'or' operation
1510 * STD - Store data from XRF to memory
1511 * SDI - Store data from XRF to memory (and increase the address base)
1512 * SLT - Set of less than comparison
1513 * SAD - Sum of absolute differences
1514 * SLL - Logical shift left
1515 * SLR - Logical shift right
1516 * SAR - Arithmetic shift right
1517 * SAT - Saturation
1518 * SFL - Shuffle
1519 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1520 * XOR - Logical bitwise 'exclusive or' operation
1522 * Suffixes:
1524 * E - Expand results
1525 * F - Fixed point multiplication
1526 * L - Low part result
1527 * R - Doing rounding
1528 * V - Variable instead of immediate
1529 * W - Combine above L and V
1532 * The list of MXU instructions grouped by functionality
1533 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1535 * Load/Store instructions Multiplication instructions
1536 * ----------------------- ---------------------------
1538 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1539 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1540 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1541 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1542 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1543 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1544 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1545 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1546 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1547 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1548 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1549 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1550 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1551 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1552 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1553 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1554 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1555 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1556 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1557 * S16SDI XRa, Rb, s10, eptn2
1558 * S8LDD XRa, Rb, s8, eptn3
1559 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1560 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1561 * S8SDI XRa, Rb, s8, eptn3
1562 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1563 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1564 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1565 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1566 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1567 * S32CPS XRa, XRb, XRc
1568 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1569 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1570 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1571 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1572 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1573 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1574 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1575 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1576 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1577 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1578 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1579 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1580 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1581 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1582 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1583 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1584 * Q8SLT XRa, XRb, XRc
1585 * Q8SLTU XRa, XRb, XRc
1586 * Q8MOVZ XRa, XRb, XRc Shift instructions
1587 * Q8MOVN XRa, XRb, XRc ------------------
1589 * D32SLL XRa, XRb, XRc, XRd, sft4
1590 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1591 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1592 * D32SARL XRa, XRb, XRc, sft4
1593 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1594 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1595 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1596 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1597 * Q16SLL XRa, XRb, XRc, XRd, sft4
1598 * Q16SLR XRa, XRb, XRc, XRd, sft4
1599 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1600 * ------------------------- Q16SLLV XRa, XRb, Rb
1601 * Q16SLRV XRa, XRb, Rb
1602 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1603 * S32ALN XRa, XRb, XRc, Rb
1604 * S32ALNI XRa, XRb, XRc, s3
1605 * S32LUI XRa, s8, optn3 Move instructions
1606 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1607 * S32EXTRV XRa, XRb, Rs, Rt
1608 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1609 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1612 * The opcode organization of MXU instructions
1613 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1615 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1616 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1617 * other bits up to the instruction level is as follows:
1619 * bits
1620 * 05..00
1622 * ┌─ 000000 ─ OPC_MXU_S32MADD
1623 * ├─ 000001 ─ OPC_MXU_S32MADDU
1624 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1625 * │
1626 * │ 20..18
1627 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1628 * │ ├─ 001 ─ OPC_MXU_S32MIN
1629 * │ ├─ 010 ─ OPC_MXU_D16MAX
1630 * │ ├─ 011 ─ OPC_MXU_D16MIN
1631 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1632 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1633 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1634 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1635 * ├─ 000100 ─ OPC_MXU_S32MSUB
1636 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1637 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1638 * │ ├─ 001 ─ OPC_MXU_D16SLT
1639 * │ ├─ 010 ─ OPC_MXU_D16AVG
1640 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1641 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1642 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1643 * │ └─ 111 ─ OPC_MXU_Q8ADD
1644 * │
1645 * │ 20..18
1646 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1647 * │ ├─ 010 ─ OPC_MXU_D16CPS
1648 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1649 * │ └─ 110 ─ OPC_MXU_Q16SAT
1650 * ├─ 001000 ─ OPC_MXU_D16MUL
1651 * │ 25..24
1652 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1653 * │ └─ 01 ─ OPC_MXU_D16MULE
1654 * ├─ 001010 ─ OPC_MXU_D16MAC
1655 * ├─ 001011 ─ OPC_MXU_D16MACF
1656 * ├─ 001100 ─ OPC_MXU_D16MADL
1657 * ├─ 001101 ─ OPC_MXU_S16MAD
1658 * ├─ 001110 ─ OPC_MXU_Q16ADD
1659 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1660 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1661 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1662 * │
1663 * │ 23
1664 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1665 * │ └─ 1 ─ OPC_MXU_S32STDR
1666 * │
1667 * │ 13..10
1668 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1669 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1670 * │
1671 * │ 13..10
1672 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1673 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1674 * │
1675 * │ 23
1676 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1677 * │ └─ 1 ─ OPC_MXU_S32LDIR
1678 * │
1679 * │ 23
1680 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1681 * │ └─ 1 ─ OPC_MXU_S32SDIR
1682 * │
1683 * │ 13..10
1684 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1685 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1686 * │
1687 * │ 13..10
1688 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1689 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1690 * ├─ 011000 ─ OPC_MXU_D32ADD
1691 * │ 23..22
1692 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1693 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1694 * │ └─ 10 ─ OPC_MXU_D32ASUM
1695 * ├─ 011010 ─ <not assigned>
1696 * │ 23..22
1697 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1698 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1699 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1700 * │
1701 * │ 23..22
1702 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1703 * │ ├─ 01 ─ OPC_MXU_D8SUM
1704 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1705 * ├─ 011110 ─ <not assigned>
1706 * ├─ 011111 ─ <not assigned>
1707 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1708 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1709 * ├─ 100010 ─ OPC_MXU_S8LDD
1710 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1711 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1712 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1713 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1714 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1715 * │
1716 * │ 20..18
1717 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1718 * │ ├─ 001 ─ OPC_MXU_S32ALN
1719 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1720 * │ ├─ 011 ─ OPC_MXU_S32LUI
1721 * │ ├─ 100 ─ OPC_MXU_S32NOR
1722 * │ ├─ 101 ─ OPC_MXU_S32AND
1723 * │ ├─ 110 ─ OPC_MXU_S32OR
1724 * │ └─ 111 ─ OPC_MXU_S32XOR
1725 * │
1726 * │ 7..5
1727 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1728 * │ ├─ 001 ─ OPC_MXU_LXH
1729 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1730 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1731 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1732 * ├─ 101100 ─ OPC_MXU_S16LDI
1733 * ├─ 101101 ─ OPC_MXU_S16SDI
1734 * ├─ 101110 ─ OPC_MXU_S32M2I
1735 * ├─ 101111 ─ OPC_MXU_S32I2M
1736 * ├─ 110000 ─ OPC_MXU_D32SLL
1737 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1738 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1739 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1740 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1741 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1742 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1743 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1744 * │
1745 * ├─ 110111 ─ OPC_MXU_Q16SAR
1746 * │ 23..22
1747 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1748 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1749 * │
1750 * │ 20..18
1751 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1752 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1753 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1754 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1755 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1756 * │ └─ 101 ─ OPC_MXU_S32MOVN
1757 * │
1758 * │ 23..22
1759 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1760 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1761 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1762 * ├─ 111100 ─ OPC_MXU_Q8MADL
1763 * ├─ 111101 ─ OPC_MXU_S32SFL
1764 * ├─ 111110 ─ OPC_MXU_Q8SAD
1765 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1768 * Compiled after:
1770 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1771 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1774 enum {
1775 OPC_MXU_S32MADD = 0x00,
1776 OPC_MXU_S32MADDU = 0x01,
1777 OPC__MXU_MUL = 0x02,
1778 OPC_MXU__POOL00 = 0x03,
1779 OPC_MXU_S32MSUB = 0x04,
1780 OPC_MXU_S32MSUBU = 0x05,
1781 OPC_MXU__POOL01 = 0x06,
1782 OPC_MXU__POOL02 = 0x07,
1783 OPC_MXU_D16MUL = 0x08,
1784 OPC_MXU__POOL03 = 0x09,
1785 OPC_MXU_D16MAC = 0x0A,
1786 OPC_MXU_D16MACF = 0x0B,
1787 OPC_MXU_D16MADL = 0x0C,
1788 OPC_MXU_S16MAD = 0x0D,
1789 OPC_MXU_Q16ADD = 0x0E,
1790 OPC_MXU_D16MACE = 0x0F,
1791 OPC_MXU__POOL04 = 0x10,
1792 OPC_MXU__POOL05 = 0x11,
1793 OPC_MXU__POOL06 = 0x12,
1794 OPC_MXU__POOL07 = 0x13,
1795 OPC_MXU__POOL08 = 0x14,
1796 OPC_MXU__POOL09 = 0x15,
1797 OPC_MXU__POOL10 = 0x16,
1798 OPC_MXU__POOL11 = 0x17,
1799 OPC_MXU_D32ADD = 0x18,
1800 OPC_MXU__POOL12 = 0x19,
1801 /* not assigned 0x1A */
1802 OPC_MXU__POOL13 = 0x1B,
1803 OPC_MXU__POOL14 = 0x1C,
1804 OPC_MXU_Q8ACCE = 0x1D,
1805 /* not assigned 0x1E */
1806 /* not assigned 0x1F */
1807 /* not assigned 0x20 */
1808 /* not assigned 0x21 */
1809 OPC_MXU_S8LDD = 0x22,
1810 OPC_MXU_S8STD = 0x23,
1811 OPC_MXU_S8LDI = 0x24,
1812 OPC_MXU_S8SDI = 0x25,
1813 OPC_MXU__POOL15 = 0x26,
1814 OPC_MXU__POOL16 = 0x27,
1815 OPC_MXU__POOL17 = 0x28,
1816 /* not assigned 0x29 */
1817 OPC_MXU_S16LDD = 0x2A,
1818 OPC_MXU_S16STD = 0x2B,
1819 OPC_MXU_S16LDI = 0x2C,
1820 OPC_MXU_S16SDI = 0x2D,
1821 OPC_MXU_S32M2I = 0x2E,
1822 OPC_MXU_S32I2M = 0x2F,
1823 OPC_MXU_D32SLL = 0x30,
1824 OPC_MXU_D32SLR = 0x31,
1825 OPC_MXU_D32SARL = 0x32,
1826 OPC_MXU_D32SAR = 0x33,
1827 OPC_MXU_Q16SLL = 0x34,
1828 OPC_MXU_Q16SLR = 0x35,
1829 OPC_MXU__POOL18 = 0x36,
1830 OPC_MXU_Q16SAR = 0x37,
1831 OPC_MXU__POOL19 = 0x38,
1832 OPC_MXU__POOL20 = 0x39,
1833 OPC_MXU__POOL21 = 0x3A,
1834 OPC_MXU_Q16SCOP = 0x3B,
1835 OPC_MXU_Q8MADL = 0x3C,
1836 OPC_MXU_S32SFL = 0x3D,
1837 OPC_MXU_Q8SAD = 0x3E,
1838 /* not assigned 0x3F */
1843 * MXU pool 00
1845 enum {
1846 OPC_MXU_S32MAX = 0x00,
1847 OPC_MXU_S32MIN = 0x01,
1848 OPC_MXU_D16MAX = 0x02,
1849 OPC_MXU_D16MIN = 0x03,
1850 OPC_MXU_Q8MAX = 0x04,
1851 OPC_MXU_Q8MIN = 0x05,
1852 OPC_MXU_Q8SLT = 0x06,
1853 OPC_MXU_Q8SLTU = 0x07,
1857 * MXU pool 01
1859 enum {
1860 OPC_MXU_S32SLT = 0x00,
1861 OPC_MXU_D16SLT = 0x01,
1862 OPC_MXU_D16AVG = 0x02,
1863 OPC_MXU_D16AVGR = 0x03,
1864 OPC_MXU_Q8AVG = 0x04,
1865 OPC_MXU_Q8AVGR = 0x05,
1866 OPC_MXU_Q8ADD = 0x07,
1870 * MXU pool 02
1872 enum {
1873 OPC_MXU_S32CPS = 0x00,
1874 OPC_MXU_D16CPS = 0x02,
1875 OPC_MXU_Q8ABD = 0x04,
1876 OPC_MXU_Q16SAT = 0x06,
1880 * MXU pool 03
1882 enum {
1883 OPC_MXU_D16MULF = 0x00,
1884 OPC_MXU_D16MULE = 0x01,
1888 * MXU pool 04
1890 enum {
1891 OPC_MXU_S32LDD = 0x00,
1892 OPC_MXU_S32LDDR = 0x01,
1896 * MXU pool 05
1898 enum {
1899 OPC_MXU_S32STD = 0x00,
1900 OPC_MXU_S32STDR = 0x01,
1904 * MXU pool 06
1906 enum {
1907 OPC_MXU_S32LDDV = 0x00,
1908 OPC_MXU_S32LDDVR = 0x01,
1912 * MXU pool 07
1914 enum {
1915 OPC_MXU_S32STDV = 0x00,
1916 OPC_MXU_S32STDVR = 0x01,
1920 * MXU pool 08
1922 enum {
1923 OPC_MXU_S32LDI = 0x00,
1924 OPC_MXU_S32LDIR = 0x01,
1928 * MXU pool 09
1930 enum {
1931 OPC_MXU_S32SDI = 0x00,
1932 OPC_MXU_S32SDIR = 0x01,
1936 * MXU pool 10
1938 enum {
1939 OPC_MXU_S32LDIV = 0x00,
1940 OPC_MXU_S32LDIVR = 0x01,
1944 * MXU pool 11
1946 enum {
1947 OPC_MXU_S32SDIV = 0x00,
1948 OPC_MXU_S32SDIVR = 0x01,
1952 * MXU pool 12
1954 enum {
1955 OPC_MXU_D32ACC = 0x00,
1956 OPC_MXU_D32ACCM = 0x01,
1957 OPC_MXU_D32ASUM = 0x02,
1961 * MXU pool 13
1963 enum {
1964 OPC_MXU_Q16ACC = 0x00,
1965 OPC_MXU_Q16ACCM = 0x01,
1966 OPC_MXU_Q16ASUM = 0x02,
1970 * MXU pool 14
1972 enum {
1973 OPC_MXU_Q8ADDE = 0x00,
1974 OPC_MXU_D8SUM = 0x01,
1975 OPC_MXU_D8SUMC = 0x02,
1979 * MXU pool 15
1981 enum {
1982 OPC_MXU_S32MUL = 0x00,
1983 OPC_MXU_S32MULU = 0x01,
1984 OPC_MXU_S32EXTR = 0x02,
1985 OPC_MXU_S32EXTRV = 0x03,
1989 * MXU pool 16
1991 enum {
1992 OPC_MXU_D32SARW = 0x00,
1993 OPC_MXU_S32ALN = 0x01,
1994 OPC_MXU_S32ALNI = 0x02,
1995 OPC_MXU_S32LUI = 0x03,
1996 OPC_MXU_S32NOR = 0x04,
1997 OPC_MXU_S32AND = 0x05,
1998 OPC_MXU_S32OR = 0x06,
1999 OPC_MXU_S32XOR = 0x07,
2003 * MXU pool 17
2005 enum {
2006 OPC_MXU_LXB = 0x00,
2007 OPC_MXU_LXH = 0x01,
2008 OPC_MXU_LXW = 0x03,
2009 OPC_MXU_LXBU = 0x04,
2010 OPC_MXU_LXHU = 0x05,
2014 * MXU pool 18
2016 enum {
2017 OPC_MXU_D32SLLV = 0x00,
2018 OPC_MXU_D32SLRV = 0x01,
2019 OPC_MXU_D32SARV = 0x03,
2020 OPC_MXU_Q16SLLV = 0x04,
2021 OPC_MXU_Q16SLRV = 0x05,
2022 OPC_MXU_Q16SARV = 0x07,
2026 * MXU pool 19
2028 enum {
2029 OPC_MXU_Q8MUL = 0x00,
2030 OPC_MXU_Q8MULSU = 0x01,
2034 * MXU pool 20
2036 enum {
2037 OPC_MXU_Q8MOVZ = 0x00,
2038 OPC_MXU_Q8MOVN = 0x01,
2039 OPC_MXU_D16MOVZ = 0x02,
2040 OPC_MXU_D16MOVN = 0x03,
2041 OPC_MXU_S32MOVZ = 0x04,
2042 OPC_MXU_S32MOVN = 0x05,
2046 * MXU pool 21
2048 enum {
2049 OPC_MXU_Q8MAC = 0x00,
2050 OPC_MXU_Q8MACSU = 0x01,
2054 * Overview of the TX79-specific instruction set
2055 * =============================================
2057 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2058 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2059 * instructions and certain multimedia instructions (MMIs). These MMIs
2060 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2061 * or sixteen 8-bit paths.
2063 * Reference:
2065 * The Toshiba TX System RISC TX79 Core Architecture manual,
2066 * https://wiki.qemu.org/File:C790.pdf
2068 * Three-Operand Multiply and Multiply-Add (4 instructions)
2069 * --------------------------------------------------------
2070 * MADD [rd,] rs, rt Multiply/Add
2071 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2072 * MULT [rd,] rs, rt Multiply (3-operand)
2073 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2075 * Multiply Instructions for Pipeline 1 (10 instructions)
2076 * ------------------------------------------------------
2077 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2078 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2079 * DIV1 rs, rt Divide Pipeline 1
2080 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2081 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2082 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2083 * MFHI1 rd Move From HI1 Register
2084 * MFLO1 rd Move From LO1 Register
2085 * MTHI1 rs Move To HI1 Register
2086 * MTLO1 rs Move To LO1 Register
2088 * Arithmetic (19 instructions)
2089 * ----------------------------
2090 * PADDB rd, rs, rt Parallel Add Byte
2091 * PSUBB rd, rs, rt Parallel Subtract Byte
2092 * PADDH rd, rs, rt Parallel Add Halfword
2093 * PSUBH rd, rs, rt Parallel Subtract Halfword
2094 * PADDW rd, rs, rt Parallel Add Word
2095 * PSUBW rd, rs, rt Parallel Subtract Word
2096 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2097 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2098 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2099 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2100 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2101 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2102 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2103 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2104 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2105 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2106 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2107 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2108 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2110 * Min/Max (4 instructions)
2111 * ------------------------
2112 * PMAXH rd, rs, rt Parallel Maximum Halfword
2113 * PMINH rd, rs, rt Parallel Minimum Halfword
2114 * PMAXW rd, rs, rt Parallel Maximum Word
2115 * PMINW rd, rs, rt Parallel Minimum Word
2117 * Absolute (2 instructions)
2118 * -------------------------
2119 * PABSH rd, rt Parallel Absolute Halfword
2120 * PABSW rd, rt Parallel Absolute Word
2122 * Logical (4 instructions)
2123 * ------------------------
2124 * PAND rd, rs, rt Parallel AND
2125 * POR rd, rs, rt Parallel OR
2126 * PXOR rd, rs, rt Parallel XOR
2127 * PNOR rd, rs, rt Parallel NOR
2129 * Shift (9 instructions)
2130 * ----------------------
2131 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2132 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2133 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2134 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2135 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2136 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2137 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2138 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2139 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2141 * Compare (6 instructions)
2142 * ------------------------
2143 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2144 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2145 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2146 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2147 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2148 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2150 * LZC (1 instruction)
2151 * -------------------
2152 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2154 * Quadword Load and Store (2 instructions)
2155 * ----------------------------------------
2156 * LQ rt, offset(base) Load Quadword
2157 * SQ rt, offset(base) Store Quadword
2159 * Multiply and Divide (19 instructions)
2160 * -------------------------------------
2161 * PMULTW rd, rs, rt Parallel Multiply Word
2162 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2163 * PDIVW rs, rt Parallel Divide Word
2164 * PDIVUW rs, rt Parallel Divide Unsigned Word
2165 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2166 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2167 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2168 * PMULTH rd, rs, rt Parallel Multiply Halfword
2169 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2170 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2171 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2172 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2173 * PDIVBW rs, rt Parallel Divide Broadcast Word
2174 * PMFHI rd Parallel Move From HI Register
2175 * PMFLO rd Parallel Move From LO Register
2176 * PMTHI rs Parallel Move To HI Register
2177 * PMTLO rs Parallel Move To LO Register
2178 * PMFHL rd Parallel Move From HI/LO Register
2179 * PMTHL rs Parallel Move To HI/LO Register
2181 * Pack/Extend (11 instructions)
2182 * -----------------------------
2183 * PPAC5 rd, rt Parallel Pack to 5 bits
2184 * PPACB rd, rs, rt Parallel Pack to Byte
2185 * PPACH rd, rs, rt Parallel Pack to Halfword
2186 * PPACW rd, rs, rt Parallel Pack to Word
2187 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2188 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2189 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2190 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2191 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2192 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2193 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2195 * Others (16 instructions)
2196 * ------------------------
2197 * PCPYH rd, rt Parallel Copy Halfword
2198 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2199 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2200 * PREVH rd, rt Parallel Reverse Halfword
2201 * PINTH rd, rs, rt Parallel Interleave Halfword
2202 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2203 * PEXEH rd, rt Parallel Exchange Even Halfword
2204 * PEXCH rd, rt Parallel Exchange Center Halfword
2205 * PEXEW rd, rt Parallel Exchange Even Word
2206 * PEXCW rd, rt Parallel Exchange Center Word
2207 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2208 * MFSA rd Move from Shift Amount Register
2209 * MTSA rs Move to Shift Amount Register
2210 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2211 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2212 * PROT3W rd, rt Parallel Rotate 3 Words
2214 * MMI (MultiMedia Instruction) encodings
2215 * ======================================
2217 * MMI instructions encoding table keys:
2219 * * This code is reserved for future use. An attempt to execute it
2220 * causes a Reserved Instruction exception.
2221 * % This code indicates an instruction class. The instruction word
2222 * must be further decoded by examining additional tables that show
2223 * the values for other instruction fields.
2224 * # This code is reserved for the unsupported instructions DMULT,
2225 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2226 * to execute it causes a Reserved Instruction exception.
2228 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2230 * 31 26 0
2231 * +--------+----------------------------------------+
2232 * | opcode | |
2233 * +--------+----------------------------------------+
2235 * opcode bits 28..26
2236 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2237 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2238 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2239 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2240 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2241 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2242 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2243 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2244 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2245 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2246 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2249 enum {
2250 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2251 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2252 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2256 * MMI instructions with opcode field = MMI:
2258 * 31 26 5 0
2259 * +--------+-------------------------------+--------+
2260 * | MMI | |function|
2261 * +--------+-------------------------------+--------+
2263 * function bits 2..0
2264 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2265 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2266 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2267 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2268 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2269 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2270 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2271 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2272 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2273 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2274 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2277 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2278 enum {
2279 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2280 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2281 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2282 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2283 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2284 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2285 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2286 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2287 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2288 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2289 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2290 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2291 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2292 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2293 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2294 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2295 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2296 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2297 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2298 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2299 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2300 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2301 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2302 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2303 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2307 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2309 * 31 26 10 6 5 0
2310 * +--------+----------------------+--------+--------+
2311 * | MMI | |function| MMI0 |
2312 * +--------+----------------------+--------+--------+
2314 * function bits 7..6
2315 * bits | 0 | 1 | 2 | 3
2316 * 10..8 | 00 | 01 | 10 | 11
2317 * -------+-------+-------+-------+-------
2318 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2319 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2320 * 2 010 | PADDB | PSUBB | PCGTB | *
2321 * 3 011 | * | * | * | *
2322 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2323 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2324 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2325 * 7 111 | * | * | PEXT5 | PPAC5
2328 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2329 enum {
2330 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2331 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2332 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2333 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2334 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2335 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2336 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2337 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2338 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2339 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2340 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2341 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2342 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2343 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2344 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2345 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2346 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2347 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2348 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2349 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2350 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2351 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2352 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2353 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2354 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2358 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2360 * 31 26 10 6 5 0
2361 * +--------+----------------------+--------+--------+
2362 * | MMI | |function| MMI1 |
2363 * +--------+----------------------+--------+--------+
2365 * function bits 7..6
2366 * bits | 0 | 1 | 2 | 3
2367 * 10..8 | 00 | 01 | 10 | 11
2368 * -------+-------+-------+-------+-------
2369 * 0 000 | * | PABSW | PCEQW | PMINW
2370 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2371 * 2 010 | * | * | PCEQB | *
2372 * 3 011 | * | * | * | *
2373 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2374 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2375 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2376 * 7 111 | * | * | * | *
2379 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2380 enum {
2381 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2382 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2383 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2384 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2385 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2386 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2387 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2388 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2389 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2390 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2391 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2392 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2393 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2394 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2395 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2396 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2397 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2398 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2402 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2404 * 31 26 10 6 5 0
2405 * +--------+----------------------+--------+--------+
2406 * | MMI | |function| MMI2 |
2407 * +--------+----------------------+--------+--------+
2409 * function bits 7..6
2410 * bits | 0 | 1 | 2 | 3
2411 * 10..8 | 00 | 01 | 10 | 11
2412 * -------+-------+-------+-------+-------
2413 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2414 * 1 001 | PMSUBW| * | * | *
2415 * 2 010 | PMFHI | PMFLO | PINTH | *
2416 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2417 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2418 * 5 101 | PMSUBH| PHMSBH| * | *
2419 * 6 110 | * | * | PEXEH | PREVH
2420 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2423 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2424 enum {
2425 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2426 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2427 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2428 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2429 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2430 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2431 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2432 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2433 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2434 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2435 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2436 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2437 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2438 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2439 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2440 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2441 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2442 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2443 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2444 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2445 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2446 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2450 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2452 * 31 26 10 6 5 0
2453 * +--------+----------------------+--------+--------+
2454 * | MMI | |function| MMI3 |
2455 * +--------+----------------------+--------+--------+
2457 * function bits 7..6
2458 * bits | 0 | 1 | 2 | 3
2459 * 10..8 | 00 | 01 | 10 | 11
2460 * -------+-------+-------+-------+-------
2461 * 0 000 |PMADDUW| * | * | PSRAVW
2462 * 1 001 | * | * | * | *
2463 * 2 010 | PMTHI | PMTLO | PINTEH| *
2464 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2465 * 4 100 | * | * | POR | PNOR
2466 * 5 101 | * | * | * | *
2467 * 6 110 | * | * | PEXCH | PCPYH
2468 * 7 111 | * | * | PEXCW | *
2471 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2472 enum {
2473 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2474 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2475 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2476 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2477 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2478 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2479 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2480 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2481 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2482 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2483 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2484 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2485 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2488 /* global register indices */
2489 TCGv cpu_gpr[32], cpu_PC;
2490 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2491 static TCGv cpu_dspctrl, btarget;
2492 TCGv bcond;
2493 static TCGv cpu_lladdr, cpu_llval;
2494 static TCGv_i32 hflags;
2495 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2496 static TCGv_i64 fpu_f64[32];
2497 static TCGv_i64 msa_wr_d[64];
2499 #if defined(TARGET_MIPS64)
2500 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2501 static TCGv_i64 cpu_mmr[32];
2502 #endif
2504 #if !defined(TARGET_MIPS64)
2505 /* MXU registers */
2506 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2507 static TCGv mxu_CR;
2508 #endif
2510 #include "exec/gen-icount.h"
2512 #define gen_helper_0e0i(name, arg) do { \
2513 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2514 gen_helper_##name(cpu_env, helper_tmp); \
2515 tcg_temp_free_i32(helper_tmp); \
2516 } while (0)
2518 #define gen_helper_0e1i(name, arg1, arg2) do { \
2519 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2520 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2521 tcg_temp_free_i32(helper_tmp); \
2522 } while (0)
2524 #define gen_helper_1e0i(name, ret, arg1) do { \
2525 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2526 gen_helper_##name(ret, cpu_env, helper_tmp); \
2527 tcg_temp_free_i32(helper_tmp); \
2528 } while (0)
2530 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2531 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2532 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2533 tcg_temp_free_i32(helper_tmp); \
2534 } while (0)
2536 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2537 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2538 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2539 tcg_temp_free_i32(helper_tmp); \
2540 } while (0)
2542 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2543 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2544 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2545 tcg_temp_free_i32(helper_tmp); \
2546 } while (0)
2548 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2549 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2550 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2551 tcg_temp_free_i32(helper_tmp); \
2552 } while (0)
2554 #define DISAS_STOP DISAS_TARGET_0
2555 #define DISAS_EXIT DISAS_TARGET_1
2557 static const char * const regnames[] = {
2558 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2559 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2560 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2561 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2564 static const char * const regnames_HI[] = {
2565 "HI0", "HI1", "HI2", "HI3",
2568 static const char * const regnames_LO[] = {
2569 "LO0", "LO1", "LO2", "LO3",
2572 static const char * const fregnames[] = {
2573 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2574 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2575 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2576 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2579 static const char * const msaregnames[] = {
2580 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2581 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2582 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2583 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2584 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2585 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2586 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2587 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2588 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2589 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2590 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2591 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2592 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2593 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2594 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2595 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2598 #if !defined(TARGET_MIPS64)
2599 static const char * const mxuregnames[] = {
2600 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2601 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2603 #endif
2605 /* General purpose registers moves. */
2606 void gen_load_gpr(TCGv t, int reg)
2608 if (reg == 0) {
2609 tcg_gen_movi_tl(t, 0);
2610 } else {
2611 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2615 void gen_store_gpr(TCGv t, int reg)
2617 if (reg != 0) {
2618 tcg_gen_mov_tl(cpu_gpr[reg], t);
2622 /* Moves to/from shadow registers. */
2623 static inline void gen_load_srsgpr(int from, int to)
2625 TCGv t0 = tcg_temp_new();
2627 if (from == 0) {
2628 tcg_gen_movi_tl(t0, 0);
2629 } else {
2630 TCGv_i32 t2 = tcg_temp_new_i32();
2631 TCGv_ptr addr = tcg_temp_new_ptr();
2633 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2634 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2635 tcg_gen_andi_i32(t2, t2, 0xf);
2636 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2637 tcg_gen_ext_i32_ptr(addr, t2);
2638 tcg_gen_add_ptr(addr, cpu_env, addr);
2640 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2641 tcg_temp_free_ptr(addr);
2642 tcg_temp_free_i32(t2);
2644 gen_store_gpr(t0, to);
2645 tcg_temp_free(t0);
2648 static inline void gen_store_srsgpr(int from, int to)
2650 if (to != 0) {
2651 TCGv t0 = tcg_temp_new();
2652 TCGv_i32 t2 = tcg_temp_new_i32();
2653 TCGv_ptr addr = tcg_temp_new_ptr();
2655 gen_load_gpr(t0, from);
2656 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2657 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2658 tcg_gen_andi_i32(t2, t2, 0xf);
2659 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2660 tcg_gen_ext_i32_ptr(addr, t2);
2661 tcg_gen_add_ptr(addr, cpu_env, addr);
2663 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2664 tcg_temp_free_ptr(addr);
2665 tcg_temp_free_i32(t2);
2666 tcg_temp_free(t0);
2670 #if !defined(TARGET_MIPS64)
2671 /* MXU General purpose registers moves. */
2672 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2674 if (reg == 0) {
2675 tcg_gen_movi_tl(t, 0);
2676 } else if (reg <= 15) {
2677 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2681 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2683 if (reg > 0 && reg <= 15) {
2684 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2688 /* MXU control register moves. */
2689 static inline void gen_load_mxu_cr(TCGv t)
2691 tcg_gen_mov_tl(t, mxu_CR);
2694 static inline void gen_store_mxu_cr(TCGv t)
2696 /* TODO: Add handling of RW rules for MXU_CR. */
2697 tcg_gen_mov_tl(mxu_CR, t);
2699 #endif
2702 /* Tests */
2703 static inline void gen_save_pc(target_ulong pc)
2705 tcg_gen_movi_tl(cpu_PC, pc);
2708 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2710 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2711 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2712 gen_save_pc(ctx->base.pc_next);
2713 ctx->saved_pc = ctx->base.pc_next;
2715 if (ctx->hflags != ctx->saved_hflags) {
2716 tcg_gen_movi_i32(hflags, ctx->hflags);
2717 ctx->saved_hflags = ctx->hflags;
2718 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2719 case MIPS_HFLAG_BR:
2720 break;
2721 case MIPS_HFLAG_BC:
2722 case MIPS_HFLAG_BL:
2723 case MIPS_HFLAG_B:
2724 tcg_gen_movi_tl(btarget, ctx->btarget);
2725 break;
2730 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2732 ctx->saved_hflags = ctx->hflags;
2733 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2734 case MIPS_HFLAG_BR:
2735 break;
2736 case MIPS_HFLAG_BC:
2737 case MIPS_HFLAG_BL:
2738 case MIPS_HFLAG_B:
2739 ctx->btarget = env->btarget;
2740 break;
2744 void generate_exception_err(DisasContext *ctx, int excp, int err)
2746 TCGv_i32 texcp = tcg_const_i32(excp);
2747 TCGv_i32 terr = tcg_const_i32(err);
2748 save_cpu_state(ctx, 1);
2749 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2750 tcg_temp_free_i32(terr);
2751 tcg_temp_free_i32(texcp);
2752 ctx->base.is_jmp = DISAS_NORETURN;
2755 void generate_exception(DisasContext *ctx, int excp)
2757 gen_helper_0e0i(raise_exception, excp);
2760 void generate_exception_end(DisasContext *ctx, int excp)
2762 generate_exception_err(ctx, excp, 0);
2765 void gen_reserved_instruction(DisasContext *ctx)
2767 generate_exception_end(ctx, EXCP_RI);
2770 /* Floating point register moves. */
2771 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2773 if (ctx->hflags & MIPS_HFLAG_FRE) {
2774 generate_exception(ctx, EXCP_RI);
2776 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2779 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2781 TCGv_i64 t64;
2782 if (ctx->hflags & MIPS_HFLAG_FRE) {
2783 generate_exception(ctx, EXCP_RI);
2785 t64 = tcg_temp_new_i64();
2786 tcg_gen_extu_i32_i64(t64, t);
2787 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2788 tcg_temp_free_i64(t64);
2791 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2793 if (ctx->hflags & MIPS_HFLAG_F64) {
2794 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2795 } else {
2796 gen_load_fpr32(ctx, t, reg | 1);
2800 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2802 if (ctx->hflags & MIPS_HFLAG_F64) {
2803 TCGv_i64 t64 = tcg_temp_new_i64();
2804 tcg_gen_extu_i32_i64(t64, t);
2805 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2806 tcg_temp_free_i64(t64);
2807 } else {
2808 gen_store_fpr32(ctx, t, reg | 1);
2812 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2814 if (ctx->hflags & MIPS_HFLAG_F64) {
2815 tcg_gen_mov_i64(t, fpu_f64[reg]);
2816 } else {
2817 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2821 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2823 if (ctx->hflags & MIPS_HFLAG_F64) {
2824 tcg_gen_mov_i64(fpu_f64[reg], t);
2825 } else {
2826 TCGv_i64 t0;
2827 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2828 t0 = tcg_temp_new_i64();
2829 tcg_gen_shri_i64(t0, t, 32);
2830 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2831 tcg_temp_free_i64(t0);
2835 static inline int get_fp_bit(int cc)
2837 if (cc) {
2838 return 24 + cc;
2839 } else {
2840 return 23;
2844 /* Addresses computation */
2845 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2847 tcg_gen_add_tl(ret, arg0, arg1);
2849 #if defined(TARGET_MIPS64)
2850 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2851 tcg_gen_ext32s_i64(ret, ret);
2853 #endif
2856 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2857 target_long ofs)
2859 tcg_gen_addi_tl(ret, base, ofs);
2861 #if defined(TARGET_MIPS64)
2862 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2863 tcg_gen_ext32s_i64(ret, ret);
2865 #endif
2868 /* Addresses computation (translation time) */
2869 static target_long addr_add(DisasContext *ctx, target_long base,
2870 target_long offset)
2872 target_long sum = base + offset;
2874 #if defined(TARGET_MIPS64)
2875 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2876 sum = (int32_t)sum;
2878 #endif
2879 return sum;
2882 /* Sign-extract the low 32-bits to a target_long. */
2883 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2885 #if defined(TARGET_MIPS64)
2886 tcg_gen_ext32s_i64(ret, arg);
2887 #else
2888 tcg_gen_extrl_i64_i32(ret, arg);
2889 #endif
2892 /* Sign-extract the high 32-bits to a target_long. */
2893 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2895 #if defined(TARGET_MIPS64)
2896 tcg_gen_sari_i64(ret, arg, 32);
2897 #else
2898 tcg_gen_extrh_i64_i32(ret, arg);
2899 #endif
2902 static inline void check_cp0_enabled(DisasContext *ctx)
2904 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2905 generate_exception_end(ctx, EXCP_CpU);
2909 static inline void check_cp1_enabled(DisasContext *ctx)
2911 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2912 generate_exception_err(ctx, EXCP_CpU, 1);
2917 * Verify that the processor is running with COP1X instructions enabled.
2918 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2919 * opcode tables.
2921 static inline void check_cop1x(DisasContext *ctx)
2923 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2924 gen_reserved_instruction(ctx);
2929 * Verify that the processor is running with 64-bit floating-point
2930 * operations enabled.
2932 static inline void check_cp1_64bitmode(DisasContext *ctx)
2934 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2935 gen_reserved_instruction(ctx);
2940 * Verify if floating point register is valid; an operation is not defined
2941 * if bit 0 of any register specification is set and the FR bit in the
2942 * Status register equals zero, since the register numbers specify an
2943 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2944 * in the Status register equals one, both even and odd register numbers
2945 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2947 * Multiple 64 bit wide registers can be checked by calling
2948 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2950 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2952 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2953 gen_reserved_instruction(ctx);
2958 * Verify that the processor is running with DSP instructions enabled.
2959 * This is enabled by CP0 Status register MX(24) bit.
2961 static inline void check_dsp(DisasContext *ctx)
2963 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2964 if (ctx->insn_flags & ASE_DSP) {
2965 generate_exception_end(ctx, EXCP_DSPDIS);
2966 } else {
2967 gen_reserved_instruction(ctx);
2972 static inline void check_dsp_r2(DisasContext *ctx)
2974 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2975 if (ctx->insn_flags & ASE_DSP) {
2976 generate_exception_end(ctx, EXCP_DSPDIS);
2977 } else {
2978 gen_reserved_instruction(ctx);
2983 static inline void check_dsp_r3(DisasContext *ctx)
2985 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2986 if (ctx->insn_flags & ASE_DSP) {
2987 generate_exception_end(ctx, EXCP_DSPDIS);
2988 } else {
2989 gen_reserved_instruction(ctx);
2995 * This code generates a "reserved instruction" exception if the
2996 * CPU does not support the instruction set corresponding to flags.
2998 void check_insn(DisasContext *ctx, uint64_t flags)
3000 if (unlikely(!(ctx->insn_flags & flags))) {
3001 gen_reserved_instruction(ctx);
3006 * This code generates a "reserved instruction" exception if the
3007 * CPU has corresponding flag set which indicates that the instruction
3008 * has been removed.
3010 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3012 if (unlikely(ctx->insn_flags & flags)) {
3013 gen_reserved_instruction(ctx);
3018 * The Linux kernel traps certain reserved instruction exceptions to
3019 * emulate the corresponding instructions. QEMU is the kernel in user
3020 * mode, so those traps are emulated by accepting the instructions.
3022 * A reserved instruction exception is generated for flagged CPUs if
3023 * QEMU runs in system mode.
3025 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3027 #ifndef CONFIG_USER_ONLY
3028 check_insn_opc_removed(ctx, flags);
3029 #endif
3033 * This code generates a "reserved instruction" exception if the
3034 * CPU does not support 64-bit paired-single (PS) floating point data type.
3036 static inline void check_ps(DisasContext *ctx)
3038 if (unlikely(!ctx->ps)) {
3039 generate_exception(ctx, EXCP_RI);
3041 check_cp1_64bitmode(ctx);
3044 #ifdef TARGET_MIPS64
3046 * This code generates a "reserved instruction" exception if 64-bit
3047 * instructions are not enabled.
3049 void check_mips_64(DisasContext *ctx)
3051 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3052 gen_reserved_instruction(ctx);
3055 #endif
3057 #ifndef CONFIG_USER_ONLY
3058 static inline void check_mvh(DisasContext *ctx)
3060 if (unlikely(!ctx->mvh)) {
3061 generate_exception(ctx, EXCP_RI);
3064 #endif
3067 * This code generates a "reserved instruction" exception if the
3068 * Config5 XNP bit is set.
3070 static inline void check_xnp(DisasContext *ctx)
3072 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3073 gen_reserved_instruction(ctx);
3077 #ifndef CONFIG_USER_ONLY
3079 * This code generates a "reserved instruction" exception if the
3080 * Config3 PW bit is NOT set.
3082 static inline void check_pw(DisasContext *ctx)
3084 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3085 gen_reserved_instruction(ctx);
3088 #endif
3091 * This code generates a "reserved instruction" exception if the
3092 * Config3 MT bit is NOT set.
3094 static inline void check_mt(DisasContext *ctx)
3096 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3097 gen_reserved_instruction(ctx);
3101 #ifndef CONFIG_USER_ONLY
3103 * This code generates a "coprocessor unusable" exception if CP0 is not
3104 * available, and, if that is not the case, generates a "reserved instruction"
3105 * exception if the Config5 MT bit is NOT set. This is needed for availability
3106 * control of some of MT ASE instructions.
3108 static inline void check_cp0_mt(DisasContext *ctx)
3110 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3111 generate_exception_end(ctx, EXCP_CpU);
3112 } else {
3113 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3114 gen_reserved_instruction(ctx);
3118 #endif
3121 * This code generates a "reserved instruction" exception if the
3122 * Config5 NMS bit is set.
3124 static inline void check_nms(DisasContext *ctx)
3126 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3127 gen_reserved_instruction(ctx);
3132 * This code generates a "reserved instruction" exception if the
3133 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3134 * Config2 TL, and Config5 L2C are unset.
3136 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3138 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3139 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3140 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3141 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3142 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3143 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3144 gen_reserved_instruction(ctx);
3149 * This code generates a "reserved instruction" exception if the
3150 * Config5 EVA bit is NOT set.
3152 static inline void check_eva(DisasContext *ctx)
3154 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3155 gen_reserved_instruction(ctx);
3161 * Define small wrappers for gen_load_fpr* so that we have a uniform
3162 * calling interface for 32 and 64-bit FPRs. No sense in changing
3163 * all callers for gen_load_fpr32 when we need the CTX parameter for
3164 * this one use.
3166 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3167 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3168 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3169 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3170 int ft, int fs, int cc) \
3172 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3173 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3174 switch (ifmt) { \
3175 case FMT_PS: \
3176 check_ps(ctx); \
3177 break; \
3178 case FMT_D: \
3179 if (abs) { \
3180 check_cop1x(ctx); \
3182 check_cp1_registers(ctx, fs | ft); \
3183 break; \
3184 case FMT_S: \
3185 if (abs) { \
3186 check_cop1x(ctx); \
3188 break; \
3190 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3191 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3192 switch (n) { \
3193 case 0: \
3194 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3195 break; \
3196 case 1: \
3197 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3198 break; \
3199 case 2: \
3200 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3201 break; \
3202 case 3: \
3203 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3204 break; \
3205 case 4: \
3206 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3207 break; \
3208 case 5: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3210 break; \
3211 case 6: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3213 break; \
3214 case 7: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3216 break; \
3217 case 8: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3219 break; \
3220 case 9: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3222 break; \
3223 case 10: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3225 break; \
3226 case 11: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3228 break; \
3229 case 12: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3231 break; \
3232 case 13: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3234 break; \
3235 case 14: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3237 break; \
3238 case 15: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3240 break; \
3241 default: \
3242 abort(); \
3244 tcg_temp_free_i##bits(fp0); \
3245 tcg_temp_free_i##bits(fp1); \
3248 FOP_CONDS(, 0, d, FMT_D, 64)
3249 FOP_CONDS(abs, 1, d, FMT_D, 64)
3250 FOP_CONDS(, 0, s, FMT_S, 32)
3251 FOP_CONDS(abs, 1, s, FMT_S, 32)
3252 FOP_CONDS(, 0, ps, FMT_PS, 64)
3253 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3254 #undef FOP_CONDS
3256 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3257 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3258 int ft, int fs, int fd) \
3260 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3261 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3262 if (ifmt == FMT_D) { \
3263 check_cp1_registers(ctx, fs | ft | fd); \
3265 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3266 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3267 switch (n) { \
3268 case 0: \
3269 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3270 break; \
3271 case 1: \
3272 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3273 break; \
3274 case 2: \
3275 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3276 break; \
3277 case 3: \
3278 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3279 break; \
3280 case 4: \
3281 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3282 break; \
3283 case 5: \
3284 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 6: \
3287 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 7: \
3290 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 8: \
3293 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 9: \
3296 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 10: \
3299 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 11: \
3302 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 12: \
3305 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 13: \
3308 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 14: \
3311 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 15: \
3314 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 17: \
3317 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 18: \
3320 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 19: \
3323 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 25: \
3326 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 26: \
3329 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 27: \
3332 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 default: \
3335 abort(); \
3337 STORE; \
3338 tcg_temp_free_i ## bits(fp0); \
3339 tcg_temp_free_i ## bits(fp1); \
3342 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3343 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3344 #undef FOP_CONDNS
3345 #undef gen_ldcmp_fpr32
3346 #undef gen_ldcmp_fpr64
3348 /* load/store instructions. */
3349 #ifdef CONFIG_USER_ONLY
3350 #define OP_LD_ATOMIC(insn, fname) \
3351 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3352 DisasContext *ctx) \
3354 TCGv t0 = tcg_temp_new(); \
3355 tcg_gen_mov_tl(t0, arg1); \
3356 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3357 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3358 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3359 tcg_temp_free(t0); \
3361 #else
3362 #define OP_LD_ATOMIC(insn, fname) \
3363 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3364 DisasContext *ctx) \
3366 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3368 #endif
3369 OP_LD_ATOMIC(ll, ld32s);
3370 #if defined(TARGET_MIPS64)
3371 OP_LD_ATOMIC(lld, ld64);
3372 #endif
3373 #undef OP_LD_ATOMIC
3375 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
3377 if (base == 0) {
3378 tcg_gen_movi_tl(addr, offset);
3379 } else if (offset == 0) {
3380 gen_load_gpr(addr, base);
3381 } else {
3382 tcg_gen_movi_tl(addr, offset);
3383 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3387 static target_ulong pc_relative_pc(DisasContext *ctx)
3389 target_ulong pc = ctx->base.pc_next;
3391 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3392 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3394 pc -= branch_bytes;
3397 pc &= ~(target_ulong)3;
3398 return pc;
3401 /* Load */
3402 static void gen_ld(DisasContext *ctx, uint32_t opc,
3403 int rt, int base, int offset)
3405 TCGv t0, t1, t2;
3406 int mem_idx = ctx->mem_idx;
3408 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3409 INSN_LOONGSON3A)) {
3411 * Loongson CPU uses a load to zero register for prefetch.
3412 * We emulate it as a NOP. On other CPU we must perform the
3413 * actual memory access.
3415 return;
3418 t0 = tcg_temp_new();
3419 gen_base_offset_addr(ctx, t0, base, offset);
3421 switch (opc) {
3422 #if defined(TARGET_MIPS64)
3423 case OPC_LWU:
3424 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3425 ctx->default_tcg_memop_mask);
3426 gen_store_gpr(t0, rt);
3427 break;
3428 case OPC_LD:
3429 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3430 ctx->default_tcg_memop_mask);
3431 gen_store_gpr(t0, rt);
3432 break;
3433 case OPC_LLD:
3434 case R6_OPC_LLD:
3435 op_ld_lld(t0, t0, mem_idx, ctx);
3436 gen_store_gpr(t0, rt);
3437 break;
3438 case OPC_LDL:
3439 t1 = tcg_temp_new();
3441 * Do a byte access to possibly trigger a page
3442 * fault with the unaligned address.
3444 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3445 tcg_gen_andi_tl(t1, t0, 7);
3446 #ifndef TARGET_WORDS_BIGENDIAN
3447 tcg_gen_xori_tl(t1, t1, 7);
3448 #endif
3449 tcg_gen_shli_tl(t1, t1, 3);
3450 tcg_gen_andi_tl(t0, t0, ~7);
3451 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3452 tcg_gen_shl_tl(t0, t0, t1);
3453 t2 = tcg_const_tl(-1);
3454 tcg_gen_shl_tl(t2, t2, t1);
3455 gen_load_gpr(t1, rt);
3456 tcg_gen_andc_tl(t1, t1, t2);
3457 tcg_temp_free(t2);
3458 tcg_gen_or_tl(t0, t0, t1);
3459 tcg_temp_free(t1);
3460 gen_store_gpr(t0, rt);
3461 break;
3462 case OPC_LDR:
3463 t1 = tcg_temp_new();
3465 * Do a byte access to possibly trigger a page
3466 * fault with the unaligned address.
3468 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3469 tcg_gen_andi_tl(t1, t0, 7);
3470 #ifdef TARGET_WORDS_BIGENDIAN
3471 tcg_gen_xori_tl(t1, t1, 7);
3472 #endif
3473 tcg_gen_shli_tl(t1, t1, 3);
3474 tcg_gen_andi_tl(t0, t0, ~7);
3475 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3476 tcg_gen_shr_tl(t0, t0, t1);
3477 tcg_gen_xori_tl(t1, t1, 63);
3478 t2 = tcg_const_tl(0xfffffffffffffffeull);
3479 tcg_gen_shl_tl(t2, t2, t1);
3480 gen_load_gpr(t1, rt);
3481 tcg_gen_and_tl(t1, t1, t2);
3482 tcg_temp_free(t2);
3483 tcg_gen_or_tl(t0, t0, t1);
3484 tcg_temp_free(t1);
3485 gen_store_gpr(t0, rt);
3486 break;
3487 case OPC_LDPC:
3488 t1 = tcg_const_tl(pc_relative_pc(ctx));
3489 gen_op_addr_add(ctx, t0, t0, t1);
3490 tcg_temp_free(t1);
3491 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3492 gen_store_gpr(t0, rt);
3493 break;
3494 #endif
3495 case OPC_LWPC:
3496 t1 = tcg_const_tl(pc_relative_pc(ctx));
3497 gen_op_addr_add(ctx, t0, t0, t1);
3498 tcg_temp_free(t1);
3499 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3500 gen_store_gpr(t0, rt);
3501 break;
3502 case OPC_LWE:
3503 mem_idx = MIPS_HFLAG_UM;
3504 /* fall through */
3505 case OPC_LW:
3506 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3507 ctx->default_tcg_memop_mask);
3508 gen_store_gpr(t0, rt);
3509 break;
3510 case OPC_LHE:
3511 mem_idx = MIPS_HFLAG_UM;
3512 /* fall through */
3513 case OPC_LH:
3514 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3515 ctx->default_tcg_memop_mask);
3516 gen_store_gpr(t0, rt);
3517 break;
3518 case OPC_LHUE:
3519 mem_idx = MIPS_HFLAG_UM;
3520 /* fall through */
3521 case OPC_LHU:
3522 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3523 ctx->default_tcg_memop_mask);
3524 gen_store_gpr(t0, rt);
3525 break;
3526 case OPC_LBE:
3527 mem_idx = MIPS_HFLAG_UM;
3528 /* fall through */
3529 case OPC_LB:
3530 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3531 gen_store_gpr(t0, rt);
3532 break;
3533 case OPC_LBUE:
3534 mem_idx = MIPS_HFLAG_UM;
3535 /* fall through */
3536 case OPC_LBU:
3537 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3538 gen_store_gpr(t0, rt);
3539 break;
3540 case OPC_LWLE:
3541 mem_idx = MIPS_HFLAG_UM;
3542 /* fall through */
3543 case OPC_LWL:
3544 t1 = tcg_temp_new();
3546 * Do a byte access to possibly trigger a page
3547 * fault with the unaligned address.
3549 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3550 tcg_gen_andi_tl(t1, t0, 3);
3551 #ifndef TARGET_WORDS_BIGENDIAN
3552 tcg_gen_xori_tl(t1, t1, 3);
3553 #endif
3554 tcg_gen_shli_tl(t1, t1, 3);
3555 tcg_gen_andi_tl(t0, t0, ~3);
3556 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3557 tcg_gen_shl_tl(t0, t0, t1);
3558 t2 = tcg_const_tl(-1);
3559 tcg_gen_shl_tl(t2, t2, t1);
3560 gen_load_gpr(t1, rt);
3561 tcg_gen_andc_tl(t1, t1, t2);
3562 tcg_temp_free(t2);
3563 tcg_gen_or_tl(t0, t0, t1);
3564 tcg_temp_free(t1);
3565 tcg_gen_ext32s_tl(t0, t0);
3566 gen_store_gpr(t0, rt);
3567 break;
3568 case OPC_LWRE:
3569 mem_idx = MIPS_HFLAG_UM;
3570 /* fall through */
3571 case OPC_LWR:
3572 t1 = tcg_temp_new();
3574 * Do a byte access to possibly trigger a page
3575 * fault with the unaligned address.
3577 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3578 tcg_gen_andi_tl(t1, t0, 3);
3579 #ifdef TARGET_WORDS_BIGENDIAN
3580 tcg_gen_xori_tl(t1, t1, 3);
3581 #endif
3582 tcg_gen_shli_tl(t1, t1, 3);
3583 tcg_gen_andi_tl(t0, t0, ~3);
3584 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3585 tcg_gen_shr_tl(t0, t0, t1);
3586 tcg_gen_xori_tl(t1, t1, 31);
3587 t2 = tcg_const_tl(0xfffffffeull);
3588 tcg_gen_shl_tl(t2, t2, t1);
3589 gen_load_gpr(t1, rt);
3590 tcg_gen_and_tl(t1, t1, t2);
3591 tcg_temp_free(t2);
3592 tcg_gen_or_tl(t0, t0, t1);
3593 tcg_temp_free(t1);
3594 tcg_gen_ext32s_tl(t0, t0);
3595 gen_store_gpr(t0, rt);
3596 break;
3597 case OPC_LLE:
3598 mem_idx = MIPS_HFLAG_UM;
3599 /* fall through */
3600 case OPC_LL:
3601 case R6_OPC_LL:
3602 op_ld_ll(t0, t0, mem_idx, ctx);
3603 gen_store_gpr(t0, rt);
3604 break;
3606 tcg_temp_free(t0);
3609 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3610 uint32_t reg1, uint32_t reg2)
3612 TCGv taddr = tcg_temp_new();
3613 TCGv_i64 tval = tcg_temp_new_i64();
3614 TCGv tmp1 = tcg_temp_new();
3615 TCGv tmp2 = tcg_temp_new();
3617 gen_base_offset_addr(ctx, taddr, base, offset);
3618 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3619 #ifdef TARGET_WORDS_BIGENDIAN
3620 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3621 #else
3622 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3623 #endif
3624 gen_store_gpr(tmp1, reg1);
3625 tcg_temp_free(tmp1);
3626 gen_store_gpr(tmp2, reg2);
3627 tcg_temp_free(tmp2);
3628 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3629 tcg_temp_free_i64(tval);
3630 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3631 tcg_temp_free(taddr);
3634 /* Store */
3635 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3636 int base, int offset)
3638 TCGv t0 = tcg_temp_new();
3639 TCGv t1 = tcg_temp_new();
3640 int mem_idx = ctx->mem_idx;
3642 gen_base_offset_addr(ctx, t0, base, offset);
3643 gen_load_gpr(t1, rt);
3644 switch (opc) {
3645 #if defined(TARGET_MIPS64)
3646 case OPC_SD:
3647 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3648 ctx->default_tcg_memop_mask);
3649 break;
3650 case OPC_SDL:
3651 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3652 break;
3653 case OPC_SDR:
3654 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3655 break;
3656 #endif
3657 case OPC_SWE:
3658 mem_idx = MIPS_HFLAG_UM;
3659 /* fall through */
3660 case OPC_SW:
3661 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3662 ctx->default_tcg_memop_mask);
3663 break;
3664 case OPC_SHE:
3665 mem_idx = MIPS_HFLAG_UM;
3666 /* fall through */
3667 case OPC_SH:
3668 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3669 ctx->default_tcg_memop_mask);
3670 break;
3671 case OPC_SBE:
3672 mem_idx = MIPS_HFLAG_UM;
3673 /* fall through */
3674 case OPC_SB:
3675 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3676 break;
3677 case OPC_SWLE:
3678 mem_idx = MIPS_HFLAG_UM;
3679 /* fall through */
3680 case OPC_SWL:
3681 gen_helper_0e2i(swl, t1, t0, mem_idx);
3682 break;
3683 case OPC_SWRE:
3684 mem_idx = MIPS_HFLAG_UM;
3685 /* fall through */
3686 case OPC_SWR:
3687 gen_helper_0e2i(swr, t1, t0, mem_idx);
3688 break;
3690 tcg_temp_free(t0);
3691 tcg_temp_free(t1);
3695 /* Store conditional */
3696 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3697 MemOp tcg_mo, bool eva)
3699 TCGv addr, t0, val;
3700 TCGLabel *l1 = gen_new_label();
3701 TCGLabel *done = gen_new_label();
3703 t0 = tcg_temp_new();
3704 addr = tcg_temp_new();
3705 /* compare the address against that of the preceding LL */
3706 gen_base_offset_addr(ctx, addr, base, offset);
3707 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3708 tcg_temp_free(addr);
3709 tcg_gen_movi_tl(t0, 0);
3710 gen_store_gpr(t0, rt);
3711 tcg_gen_br(done);
3713 gen_set_label(l1);
3714 /* generate cmpxchg */
3715 val = tcg_temp_new();
3716 gen_load_gpr(val, rt);
3717 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3718 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3719 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3720 gen_store_gpr(t0, rt);
3721 tcg_temp_free(val);
3723 gen_set_label(done);
3724 tcg_temp_free(t0);
3728 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3729 uint32_t reg1, uint32_t reg2, bool eva)
3731 TCGv taddr = tcg_temp_local_new();
3732 TCGv lladdr = tcg_temp_local_new();
3733 TCGv_i64 tval = tcg_temp_new_i64();
3734 TCGv_i64 llval = tcg_temp_new_i64();
3735 TCGv_i64 val = tcg_temp_new_i64();
3736 TCGv tmp1 = tcg_temp_new();
3737 TCGv tmp2 = tcg_temp_new();
3738 TCGLabel *lab_fail = gen_new_label();
3739 TCGLabel *lab_done = gen_new_label();
3741 gen_base_offset_addr(ctx, taddr, base, offset);
3743 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3744 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3746 gen_load_gpr(tmp1, reg1);
3747 gen_load_gpr(tmp2, reg2);
3749 #ifdef TARGET_WORDS_BIGENDIAN
3750 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3751 #else
3752 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3753 #endif
3755 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3756 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3757 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3758 if (reg1 != 0) {
3759 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3761 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3763 gen_set_label(lab_fail);
3765 if (reg1 != 0) {
3766 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3768 gen_set_label(lab_done);
3769 tcg_gen_movi_tl(lladdr, -1);
3770 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3773 /* Load and store */
3774 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3775 TCGv t0)
3778 * Don't do NOP if destination is zero: we must perform the actual
3779 * memory access.
3781 switch (opc) {
3782 case OPC_LWC1:
3784 TCGv_i32 fp0 = tcg_temp_new_i32();
3785 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3786 ctx->default_tcg_memop_mask);
3787 gen_store_fpr32(ctx, fp0, ft);
3788 tcg_temp_free_i32(fp0);
3790 break;
3791 case OPC_SWC1:
3793 TCGv_i32 fp0 = tcg_temp_new_i32();
3794 gen_load_fpr32(ctx, fp0, ft);
3795 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3796 ctx->default_tcg_memop_mask);
3797 tcg_temp_free_i32(fp0);
3799 break;
3800 case OPC_LDC1:
3802 TCGv_i64 fp0 = tcg_temp_new_i64();
3803 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3804 ctx->default_tcg_memop_mask);
3805 gen_store_fpr64(ctx, fp0, ft);
3806 tcg_temp_free_i64(fp0);
3808 break;
3809 case OPC_SDC1:
3811 TCGv_i64 fp0 = tcg_temp_new_i64();
3812 gen_load_fpr64(ctx, fp0, ft);
3813 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3814 ctx->default_tcg_memop_mask);
3815 tcg_temp_free_i64(fp0);
3817 break;
3818 default:
3819 MIPS_INVAL("flt_ldst");
3820 gen_reserved_instruction(ctx);
3821 break;
3825 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3826 int rs, int16_t imm)
3828 TCGv t0 = tcg_temp_new();
3830 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3831 check_cp1_enabled(ctx);
3832 switch (op) {
3833 case OPC_LDC1:
3834 case OPC_SDC1:
3835 check_insn(ctx, ISA_MIPS2);
3836 /* Fallthrough */
3837 default:
3838 gen_base_offset_addr(ctx, t0, rs, imm);
3839 gen_flt_ldst(ctx, op, rt, t0);
3841 } else {
3842 generate_exception_err(ctx, EXCP_CpU, 1);
3844 tcg_temp_free(t0);
3847 /* Arithmetic with immediate operand */
3848 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3849 int rt, int rs, int imm)
3851 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3853 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3855 * If no destination, treat it as a NOP.
3856 * For addi, we must generate the overflow exception when needed.
3858 return;
3860 switch (opc) {
3861 case OPC_ADDI:
3863 TCGv t0 = tcg_temp_local_new();
3864 TCGv t1 = tcg_temp_new();
3865 TCGv t2 = tcg_temp_new();
3866 TCGLabel *l1 = gen_new_label();
3868 gen_load_gpr(t1, rs);
3869 tcg_gen_addi_tl(t0, t1, uimm);
3870 tcg_gen_ext32s_tl(t0, t0);
3872 tcg_gen_xori_tl(t1, t1, ~uimm);
3873 tcg_gen_xori_tl(t2, t0, uimm);
3874 tcg_gen_and_tl(t1, t1, t2);
3875 tcg_temp_free(t2);
3876 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3877 tcg_temp_free(t1);
3878 /* operands of same sign, result different sign */
3879 generate_exception(ctx, EXCP_OVERFLOW);
3880 gen_set_label(l1);
3881 tcg_gen_ext32s_tl(t0, t0);
3882 gen_store_gpr(t0, rt);
3883 tcg_temp_free(t0);
3885 break;
3886 case OPC_ADDIU:
3887 if (rs != 0) {
3888 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3889 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3890 } else {
3891 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3893 break;
3894 #if defined(TARGET_MIPS64)
3895 case OPC_DADDI:
3897 TCGv t0 = tcg_temp_local_new();
3898 TCGv t1 = tcg_temp_new();
3899 TCGv t2 = tcg_temp_new();
3900 TCGLabel *l1 = gen_new_label();
3902 gen_load_gpr(t1, rs);
3903 tcg_gen_addi_tl(t0, t1, uimm);
3905 tcg_gen_xori_tl(t1, t1, ~uimm);
3906 tcg_gen_xori_tl(t2, t0, uimm);
3907 tcg_gen_and_tl(t1, t1, t2);
3908 tcg_temp_free(t2);
3909 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3910 tcg_temp_free(t1);
3911 /* operands of same sign, result different sign */
3912 generate_exception(ctx, EXCP_OVERFLOW);
3913 gen_set_label(l1);
3914 gen_store_gpr(t0, rt);
3915 tcg_temp_free(t0);
3917 break;
3918 case OPC_DADDIU:
3919 if (rs != 0) {
3920 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3921 } else {
3922 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3924 break;
3925 #endif
3929 /* Logic with immediate operand */
3930 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3931 int rt, int rs, int16_t imm)
3933 target_ulong uimm;
3935 if (rt == 0) {
3936 /* If no destination, treat it as a NOP. */
3937 return;
3939 uimm = (uint16_t)imm;
3940 switch (opc) {
3941 case OPC_ANDI:
3942 if (likely(rs != 0)) {
3943 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3944 } else {
3945 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3947 break;
3948 case OPC_ORI:
3949 if (rs != 0) {
3950 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3951 } else {
3952 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3954 break;
3955 case OPC_XORI:
3956 if (likely(rs != 0)) {
3957 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3958 } else {
3959 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3961 break;
3962 case OPC_LUI:
3963 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3964 /* OPC_AUI */
3965 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3966 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3967 } else {
3968 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3970 break;
3972 default:
3973 break;
3977 /* Set on less than with immediate operand */
3978 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3979 int rt, int rs, int16_t imm)
3981 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3982 TCGv t0;
3984 if (rt == 0) {
3985 /* If no destination, treat it as a NOP. */
3986 return;
3988 t0 = tcg_temp_new();
3989 gen_load_gpr(t0, rs);
3990 switch (opc) {
3991 case OPC_SLTI:
3992 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3993 break;
3994 case OPC_SLTIU:
3995 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3996 break;
3998 tcg_temp_free(t0);
4001 /* Shifts with immediate operand */
4002 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4003 int rt, int rs, int16_t imm)
4005 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4006 TCGv t0;
4008 if (rt == 0) {
4009 /* If no destination, treat it as a NOP. */
4010 return;
4013 t0 = tcg_temp_new();
4014 gen_load_gpr(t0, rs);
4015 switch (opc) {
4016 case OPC_SLL:
4017 tcg_gen_shli_tl(t0, t0, uimm);
4018 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4019 break;
4020 case OPC_SRA:
4021 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4022 break;
4023 case OPC_SRL:
4024 if (uimm != 0) {
4025 tcg_gen_ext32u_tl(t0, t0);
4026 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4027 } else {
4028 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4030 break;
4031 case OPC_ROTR:
4032 if (uimm != 0) {
4033 TCGv_i32 t1 = tcg_temp_new_i32();
4035 tcg_gen_trunc_tl_i32(t1, t0);
4036 tcg_gen_rotri_i32(t1, t1, uimm);
4037 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4038 tcg_temp_free_i32(t1);
4039 } else {
4040 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4042 break;
4043 #if defined(TARGET_MIPS64)
4044 case OPC_DSLL:
4045 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4046 break;
4047 case OPC_DSRA:
4048 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4049 break;
4050 case OPC_DSRL:
4051 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4052 break;
4053 case OPC_DROTR:
4054 if (uimm != 0) {
4055 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4056 } else {
4057 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4059 break;
4060 case OPC_DSLL32:
4061 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4062 break;
4063 case OPC_DSRA32:
4064 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4065 break;
4066 case OPC_DSRL32:
4067 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4068 break;
4069 case OPC_DROTR32:
4070 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4071 break;
4072 #endif
4074 tcg_temp_free(t0);
4077 /* Arithmetic */
4078 static void gen_arith(DisasContext *ctx, uint32_t opc,
4079 int rd, int rs, int rt)
4081 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4082 && opc != OPC_DADD && opc != OPC_DSUB) {
4084 * If no destination, treat it as a NOP.
4085 * For add & sub, we must generate the overflow exception when needed.
4087 return;
4090 switch (opc) {
4091 case OPC_ADD:
4093 TCGv t0 = tcg_temp_local_new();
4094 TCGv t1 = tcg_temp_new();
4095 TCGv t2 = tcg_temp_new();
4096 TCGLabel *l1 = gen_new_label();
4098 gen_load_gpr(t1, rs);
4099 gen_load_gpr(t2, rt);
4100 tcg_gen_add_tl(t0, t1, t2);
4101 tcg_gen_ext32s_tl(t0, t0);
4102 tcg_gen_xor_tl(t1, t1, t2);
4103 tcg_gen_xor_tl(t2, t0, t2);
4104 tcg_gen_andc_tl(t1, t2, t1);
4105 tcg_temp_free(t2);
4106 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4107 tcg_temp_free(t1);
4108 /* operands of same sign, result different sign */
4109 generate_exception(ctx, EXCP_OVERFLOW);
4110 gen_set_label(l1);
4111 gen_store_gpr(t0, rd);
4112 tcg_temp_free(t0);
4114 break;
4115 case OPC_ADDU:
4116 if (rs != 0 && rt != 0) {
4117 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4118 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4119 } else if (rs == 0 && rt != 0) {
4120 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4121 } else if (rs != 0 && rt == 0) {
4122 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4123 } else {
4124 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4126 break;
4127 case OPC_SUB:
4129 TCGv t0 = tcg_temp_local_new();
4130 TCGv t1 = tcg_temp_new();
4131 TCGv t2 = tcg_temp_new();
4132 TCGLabel *l1 = gen_new_label();
4134 gen_load_gpr(t1, rs);
4135 gen_load_gpr(t2, rt);
4136 tcg_gen_sub_tl(t0, t1, t2);
4137 tcg_gen_ext32s_tl(t0, t0);
4138 tcg_gen_xor_tl(t2, t1, t2);
4139 tcg_gen_xor_tl(t1, t0, t1);
4140 tcg_gen_and_tl(t1, t1, t2);
4141 tcg_temp_free(t2);
4142 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4143 tcg_temp_free(t1);
4145 * operands of different sign, first operand and the result
4146 * of different sign
4148 generate_exception(ctx, EXCP_OVERFLOW);
4149 gen_set_label(l1);
4150 gen_store_gpr(t0, rd);
4151 tcg_temp_free(t0);
4153 break;
4154 case OPC_SUBU:
4155 if (rs != 0 && rt != 0) {
4156 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4157 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4158 } else if (rs == 0 && rt != 0) {
4159 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4160 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4161 } else if (rs != 0 && rt == 0) {
4162 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4163 } else {
4164 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4166 break;
4167 #if defined(TARGET_MIPS64)
4168 case OPC_DADD:
4170 TCGv t0 = tcg_temp_local_new();
4171 TCGv t1 = tcg_temp_new();
4172 TCGv t2 = tcg_temp_new();
4173 TCGLabel *l1 = gen_new_label();
4175 gen_load_gpr(t1, rs);
4176 gen_load_gpr(t2, rt);
4177 tcg_gen_add_tl(t0, t1, t2);
4178 tcg_gen_xor_tl(t1, t1, t2);
4179 tcg_gen_xor_tl(t2, t0, t2);
4180 tcg_gen_andc_tl(t1, t2, t1);
4181 tcg_temp_free(t2);
4182 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4183 tcg_temp_free(t1);
4184 /* operands of same sign, result different sign */
4185 generate_exception(ctx, EXCP_OVERFLOW);
4186 gen_set_label(l1);
4187 gen_store_gpr(t0, rd);
4188 tcg_temp_free(t0);
4190 break;
4191 case OPC_DADDU:
4192 if (rs != 0 && rt != 0) {
4193 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4194 } else if (rs == 0 && rt != 0) {
4195 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4196 } else if (rs != 0 && rt == 0) {
4197 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4198 } else {
4199 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4201 break;
4202 case OPC_DSUB:
4204 TCGv t0 = tcg_temp_local_new();
4205 TCGv t1 = tcg_temp_new();
4206 TCGv t2 = tcg_temp_new();
4207 TCGLabel *l1 = gen_new_label();
4209 gen_load_gpr(t1, rs);
4210 gen_load_gpr(t2, rt);
4211 tcg_gen_sub_tl(t0, t1, t2);
4212 tcg_gen_xor_tl(t2, t1, t2);
4213 tcg_gen_xor_tl(t1, t0, t1);
4214 tcg_gen_and_tl(t1, t1, t2);
4215 tcg_temp_free(t2);
4216 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4217 tcg_temp_free(t1);
4219 * Operands of different sign, first operand and result different
4220 * sign.
4222 generate_exception(ctx, EXCP_OVERFLOW);
4223 gen_set_label(l1);
4224 gen_store_gpr(t0, rd);
4225 tcg_temp_free(t0);
4227 break;
4228 case OPC_DSUBU:
4229 if (rs != 0 && rt != 0) {
4230 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4231 } else if (rs == 0 && rt != 0) {
4232 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4233 } else if (rs != 0 && rt == 0) {
4234 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4235 } else {
4236 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4238 break;
4239 #endif
4240 case OPC_MUL:
4241 if (likely(rs != 0 && rt != 0)) {
4242 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4243 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4244 } else {
4245 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4247 break;
4251 /* Conditional move */
4252 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4253 int rd, int rs, int rt)
4255 TCGv t0, t1, t2;
4257 if (rd == 0) {
4258 /* If no destination, treat it as a NOP. */
4259 return;
4262 t0 = tcg_temp_new();
4263 gen_load_gpr(t0, rt);
4264 t1 = tcg_const_tl(0);
4265 t2 = tcg_temp_new();
4266 gen_load_gpr(t2, rs);
4267 switch (opc) {
4268 case OPC_MOVN:
4269 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4270 break;
4271 case OPC_MOVZ:
4272 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4273 break;
4274 case OPC_SELNEZ:
4275 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4276 break;
4277 case OPC_SELEQZ:
4278 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4279 break;
4281 tcg_temp_free(t2);
4282 tcg_temp_free(t1);
4283 tcg_temp_free(t0);
4286 /* Logic */
4287 static void gen_logic(DisasContext *ctx, uint32_t opc,
4288 int rd, int rs, int rt)
4290 if (rd == 0) {
4291 /* If no destination, treat it as a NOP. */
4292 return;
4295 switch (opc) {
4296 case OPC_AND:
4297 if (likely(rs != 0 && rt != 0)) {
4298 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4299 } else {
4300 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4302 break;
4303 case OPC_NOR:
4304 if (rs != 0 && rt != 0) {
4305 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4306 } else if (rs == 0 && rt != 0) {
4307 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4308 } else if (rs != 0 && rt == 0) {
4309 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4310 } else {
4311 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4313 break;
4314 case OPC_OR:
4315 if (likely(rs != 0 && rt != 0)) {
4316 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4317 } else if (rs == 0 && rt != 0) {
4318 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4319 } else if (rs != 0 && rt == 0) {
4320 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4321 } else {
4322 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4324 break;
4325 case OPC_XOR:
4326 if (likely(rs != 0 && rt != 0)) {
4327 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4328 } else if (rs == 0 && rt != 0) {
4329 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4330 } else if (rs != 0 && rt == 0) {
4331 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4332 } else {
4333 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4335 break;
4339 /* Set on lower than */
4340 static void gen_slt(DisasContext *ctx, uint32_t opc,
4341 int rd, int rs, int rt)
4343 TCGv t0, t1;
4345 if (rd == 0) {
4346 /* If no destination, treat it as a NOP. */
4347 return;
4350 t0 = tcg_temp_new();
4351 t1 = tcg_temp_new();
4352 gen_load_gpr(t0, rs);
4353 gen_load_gpr(t1, rt);
4354 switch (opc) {
4355 case OPC_SLT:
4356 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4357 break;
4358 case OPC_SLTU:
4359 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4360 break;
4362 tcg_temp_free(t0);
4363 tcg_temp_free(t1);
4366 /* Shifts */
4367 static void gen_shift(DisasContext *ctx, uint32_t opc,
4368 int rd, int rs, int rt)
4370 TCGv t0, t1;
4372 if (rd == 0) {
4374 * If no destination, treat it as a NOP.
4375 * For add & sub, we must generate the overflow exception when needed.
4377 return;
4380 t0 = tcg_temp_new();
4381 t1 = tcg_temp_new();
4382 gen_load_gpr(t0, rs);
4383 gen_load_gpr(t1, rt);
4384 switch (opc) {
4385 case OPC_SLLV:
4386 tcg_gen_andi_tl(t0, t0, 0x1f);
4387 tcg_gen_shl_tl(t0, t1, t0);
4388 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4389 break;
4390 case OPC_SRAV:
4391 tcg_gen_andi_tl(t0, t0, 0x1f);
4392 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4393 break;
4394 case OPC_SRLV:
4395 tcg_gen_ext32u_tl(t1, t1);
4396 tcg_gen_andi_tl(t0, t0, 0x1f);
4397 tcg_gen_shr_tl(t0, t1, t0);
4398 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4399 break;
4400 case OPC_ROTRV:
4402 TCGv_i32 t2 = tcg_temp_new_i32();
4403 TCGv_i32 t3 = tcg_temp_new_i32();
4405 tcg_gen_trunc_tl_i32(t2, t0);
4406 tcg_gen_trunc_tl_i32(t3, t1);
4407 tcg_gen_andi_i32(t2, t2, 0x1f);
4408 tcg_gen_rotr_i32(t2, t3, t2);
4409 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4410 tcg_temp_free_i32(t2);
4411 tcg_temp_free_i32(t3);
4413 break;
4414 #if defined(TARGET_MIPS64)
4415 case OPC_DSLLV:
4416 tcg_gen_andi_tl(t0, t0, 0x3f);
4417 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4418 break;
4419 case OPC_DSRAV:
4420 tcg_gen_andi_tl(t0, t0, 0x3f);
4421 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4422 break;
4423 case OPC_DSRLV:
4424 tcg_gen_andi_tl(t0, t0, 0x3f);
4425 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4426 break;
4427 case OPC_DROTRV:
4428 tcg_gen_andi_tl(t0, t0, 0x3f);
4429 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4430 break;
4431 #endif
4433 tcg_temp_free(t0);
4434 tcg_temp_free(t1);
4437 #if defined(TARGET_MIPS64)
4438 /* Copy GPR to and from TX79 HI1/LO1 register. */
4439 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4441 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4442 /* Treat as NOP. */
4443 return;
4446 switch (opc) {
4447 case MMI_OPC_MFHI1:
4448 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4449 break;
4450 case MMI_OPC_MFLO1:
4451 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4452 break;
4453 case MMI_OPC_MTHI1:
4454 if (reg != 0) {
4455 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4456 } else {
4457 tcg_gen_movi_tl(cpu_HI[1], 0);
4459 break;
4460 case MMI_OPC_MTLO1:
4461 if (reg != 0) {
4462 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4463 } else {
4464 tcg_gen_movi_tl(cpu_LO[1], 0);
4466 break;
4467 default:
4468 MIPS_INVAL("mfthilo1 TX79");
4469 gen_reserved_instruction(ctx);
4470 break;
4473 #endif
4475 /* Arithmetic on HI/LO registers */
4476 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4478 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4479 /* Treat as NOP. */
4480 return;
4483 if (acc != 0) {
4484 check_dsp(ctx);
4487 switch (opc) {
4488 case OPC_MFHI:
4489 #if defined(TARGET_MIPS64)
4490 if (acc != 0) {
4491 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4492 } else
4493 #endif
4495 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4497 break;
4498 case OPC_MFLO:
4499 #if defined(TARGET_MIPS64)
4500 if (acc != 0) {
4501 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4502 } else
4503 #endif
4505 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4507 break;
4508 case OPC_MTHI:
4509 if (reg != 0) {
4510 #if defined(TARGET_MIPS64)
4511 if (acc != 0) {
4512 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4513 } else
4514 #endif
4516 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4518 } else {
4519 tcg_gen_movi_tl(cpu_HI[acc], 0);
4521 break;
4522 case OPC_MTLO:
4523 if (reg != 0) {
4524 #if defined(TARGET_MIPS64)
4525 if (acc != 0) {
4526 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4527 } else
4528 #endif
4530 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4532 } else {
4533 tcg_gen_movi_tl(cpu_LO[acc], 0);
4535 break;
4539 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4540 MemOp memop)
4542 TCGv t0 = tcg_const_tl(addr);
4543 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4544 gen_store_gpr(t0, reg);
4545 tcg_temp_free(t0);
4548 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4549 int rs)
4551 target_long offset;
4552 target_long addr;
4554 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4555 case OPC_ADDIUPC:
4556 if (rs != 0) {
4557 offset = sextract32(ctx->opcode << 2, 0, 21);
4558 addr = addr_add(ctx, pc, offset);
4559 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4561 break;
4562 case R6_OPC_LWPC:
4563 offset = sextract32(ctx->opcode << 2, 0, 21);
4564 addr = addr_add(ctx, pc, offset);
4565 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4566 break;
4567 #if defined(TARGET_MIPS64)
4568 case OPC_LWUPC:
4569 check_mips_64(ctx);
4570 offset = sextract32(ctx->opcode << 2, 0, 21);
4571 addr = addr_add(ctx, pc, offset);
4572 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4573 break;
4574 #endif
4575 default:
4576 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4577 case OPC_AUIPC:
4578 if (rs != 0) {
4579 offset = sextract32(ctx->opcode, 0, 16) << 16;
4580 addr = addr_add(ctx, pc, offset);
4581 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4583 break;
4584 case OPC_ALUIPC:
4585 if (rs != 0) {
4586 offset = sextract32(ctx->opcode, 0, 16) << 16;
4587 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4588 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4590 break;
4591 #if defined(TARGET_MIPS64)
4592 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4593 case R6_OPC_LDPC + (1 << 16):
4594 case R6_OPC_LDPC + (2 << 16):
4595 case R6_OPC_LDPC + (3 << 16):
4596 check_mips_64(ctx);
4597 offset = sextract32(ctx->opcode << 3, 0, 21);
4598 addr = addr_add(ctx, (pc & ~0x7), offset);
4599 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4600 break;
4601 #endif
4602 default:
4603 MIPS_INVAL("OPC_PCREL");
4604 gen_reserved_instruction(ctx);
4605 break;
4607 break;
4611 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4613 TCGv t0, t1;
4615 if (rd == 0) {
4616 /* Treat as NOP. */
4617 return;
4620 t0 = tcg_temp_new();
4621 t1 = tcg_temp_new();
4623 gen_load_gpr(t0, rs);
4624 gen_load_gpr(t1, rt);
4626 switch (opc) {
4627 case R6_OPC_DIV:
4629 TCGv t2 = tcg_temp_new();
4630 TCGv t3 = tcg_temp_new();
4631 tcg_gen_ext32s_tl(t0, t0);
4632 tcg_gen_ext32s_tl(t1, t1);
4633 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4634 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4635 tcg_gen_and_tl(t2, t2, t3);
4636 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4637 tcg_gen_or_tl(t2, t2, t3);
4638 tcg_gen_movi_tl(t3, 0);
4639 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4640 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4641 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4642 tcg_temp_free(t3);
4643 tcg_temp_free(t2);
4645 break;
4646 case R6_OPC_MOD:
4648 TCGv t2 = tcg_temp_new();
4649 TCGv t3 = tcg_temp_new();
4650 tcg_gen_ext32s_tl(t0, t0);
4651 tcg_gen_ext32s_tl(t1, t1);
4652 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4653 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4654 tcg_gen_and_tl(t2, t2, t3);
4655 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4656 tcg_gen_or_tl(t2, t2, t3);
4657 tcg_gen_movi_tl(t3, 0);
4658 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4659 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4660 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4661 tcg_temp_free(t3);
4662 tcg_temp_free(t2);
4664 break;
4665 case R6_OPC_DIVU:
4667 TCGv t2 = tcg_const_tl(0);
4668 TCGv t3 = tcg_const_tl(1);
4669 tcg_gen_ext32u_tl(t0, t0);
4670 tcg_gen_ext32u_tl(t1, t1);
4671 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4672 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4673 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4674 tcg_temp_free(t3);
4675 tcg_temp_free(t2);
4677 break;
4678 case R6_OPC_MODU:
4680 TCGv t2 = tcg_const_tl(0);
4681 TCGv t3 = tcg_const_tl(1);
4682 tcg_gen_ext32u_tl(t0, t0);
4683 tcg_gen_ext32u_tl(t1, t1);
4684 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4685 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4686 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4687 tcg_temp_free(t3);
4688 tcg_temp_free(t2);
4690 break;
4691 case R6_OPC_MUL:
4693 TCGv_i32 t2 = tcg_temp_new_i32();
4694 TCGv_i32 t3 = tcg_temp_new_i32();
4695 tcg_gen_trunc_tl_i32(t2, t0);
4696 tcg_gen_trunc_tl_i32(t3, t1);
4697 tcg_gen_mul_i32(t2, t2, t3);
4698 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4699 tcg_temp_free_i32(t2);
4700 tcg_temp_free_i32(t3);
4702 break;
4703 case R6_OPC_MUH:
4705 TCGv_i32 t2 = tcg_temp_new_i32();
4706 TCGv_i32 t3 = tcg_temp_new_i32();
4707 tcg_gen_trunc_tl_i32(t2, t0);
4708 tcg_gen_trunc_tl_i32(t3, t1);
4709 tcg_gen_muls2_i32(t2, t3, t2, t3);
4710 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4711 tcg_temp_free_i32(t2);
4712 tcg_temp_free_i32(t3);
4714 break;
4715 case R6_OPC_MULU:
4717 TCGv_i32 t2 = tcg_temp_new_i32();
4718 TCGv_i32 t3 = tcg_temp_new_i32();
4719 tcg_gen_trunc_tl_i32(t2, t0);
4720 tcg_gen_trunc_tl_i32(t3, t1);
4721 tcg_gen_mul_i32(t2, t2, t3);
4722 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4723 tcg_temp_free_i32(t2);
4724 tcg_temp_free_i32(t3);
4726 break;
4727 case R6_OPC_MUHU:
4729 TCGv_i32 t2 = tcg_temp_new_i32();
4730 TCGv_i32 t3 = tcg_temp_new_i32();
4731 tcg_gen_trunc_tl_i32(t2, t0);
4732 tcg_gen_trunc_tl_i32(t3, t1);
4733 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4734 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4735 tcg_temp_free_i32(t2);
4736 tcg_temp_free_i32(t3);
4738 break;
4739 #if defined(TARGET_MIPS64)
4740 case R6_OPC_DDIV:
4742 TCGv t2 = tcg_temp_new();
4743 TCGv t3 = tcg_temp_new();
4744 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4745 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4746 tcg_gen_and_tl(t2, t2, t3);
4747 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4748 tcg_gen_or_tl(t2, t2, t3);
4749 tcg_gen_movi_tl(t3, 0);
4750 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4751 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4752 tcg_temp_free(t3);
4753 tcg_temp_free(t2);
4755 break;
4756 case R6_OPC_DMOD:
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_rem_tl(cpu_gpr[rd], t0, t1);
4768 tcg_temp_free(t3);
4769 tcg_temp_free(t2);
4771 break;
4772 case R6_OPC_DDIVU:
4774 TCGv t2 = tcg_const_tl(0);
4775 TCGv t3 = tcg_const_tl(1);
4776 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4777 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4778 tcg_temp_free(t3);
4779 tcg_temp_free(t2);
4781 break;
4782 case R6_OPC_DMODU:
4784 TCGv t2 = tcg_const_tl(0);
4785 TCGv t3 = tcg_const_tl(1);
4786 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4787 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4788 tcg_temp_free(t3);
4789 tcg_temp_free(t2);
4791 break;
4792 case R6_OPC_DMUL:
4793 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4794 break;
4795 case R6_OPC_DMUH:
4797 TCGv t2 = tcg_temp_new();
4798 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4799 tcg_temp_free(t2);
4801 break;
4802 case R6_OPC_DMULU:
4803 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4804 break;
4805 case R6_OPC_DMUHU:
4807 TCGv t2 = tcg_temp_new();
4808 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4809 tcg_temp_free(t2);
4811 break;
4812 #endif
4813 default:
4814 MIPS_INVAL("r6 mul/div");
4815 gen_reserved_instruction(ctx);
4816 goto out;
4818 out:
4819 tcg_temp_free(t0);
4820 tcg_temp_free(t1);
4823 #if defined(TARGET_MIPS64)
4824 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4826 TCGv t0, t1;
4828 t0 = tcg_temp_new();
4829 t1 = tcg_temp_new();
4831 gen_load_gpr(t0, rs);
4832 gen_load_gpr(t1, rt);
4834 switch (opc) {
4835 case MMI_OPC_DIV1:
4837 TCGv t2 = tcg_temp_new();
4838 TCGv t3 = tcg_temp_new();
4839 tcg_gen_ext32s_tl(t0, t0);
4840 tcg_gen_ext32s_tl(t1, t1);
4841 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4842 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4843 tcg_gen_and_tl(t2, t2, t3);
4844 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4845 tcg_gen_or_tl(t2, t2, t3);
4846 tcg_gen_movi_tl(t3, 0);
4847 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4848 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4849 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4850 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4851 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4852 tcg_temp_free(t3);
4853 tcg_temp_free(t2);
4855 break;
4856 case MMI_OPC_DIVU1:
4858 TCGv t2 = tcg_const_tl(0);
4859 TCGv t3 = tcg_const_tl(1);
4860 tcg_gen_ext32u_tl(t0, t0);
4861 tcg_gen_ext32u_tl(t1, t1);
4862 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4863 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4864 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4865 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4866 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4867 tcg_temp_free(t3);
4868 tcg_temp_free(t2);
4870 break;
4871 default:
4872 MIPS_INVAL("div1 TX79");
4873 gen_reserved_instruction(ctx);
4874 goto out;
4876 out:
4877 tcg_temp_free(t0);
4878 tcg_temp_free(t1);
4880 #endif
4882 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4883 int acc, int rs, int rt)
4885 TCGv t0, t1;
4887 t0 = tcg_temp_new();
4888 t1 = tcg_temp_new();
4890 gen_load_gpr(t0, rs);
4891 gen_load_gpr(t1, rt);
4893 if (acc != 0) {
4894 check_dsp(ctx);
4897 switch (opc) {
4898 case OPC_DIV:
4900 TCGv t2 = tcg_temp_new();
4901 TCGv t3 = tcg_temp_new();
4902 tcg_gen_ext32s_tl(t0, t0);
4903 tcg_gen_ext32s_tl(t1, t1);
4904 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4905 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4906 tcg_gen_and_tl(t2, t2, t3);
4907 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4908 tcg_gen_or_tl(t2, t2, t3);
4909 tcg_gen_movi_tl(t3, 0);
4910 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4911 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4912 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4913 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4914 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4915 tcg_temp_free(t3);
4916 tcg_temp_free(t2);
4918 break;
4919 case OPC_DIVU:
4921 TCGv t2 = tcg_const_tl(0);
4922 TCGv t3 = tcg_const_tl(1);
4923 tcg_gen_ext32u_tl(t0, t0);
4924 tcg_gen_ext32u_tl(t1, t1);
4925 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4926 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4927 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4928 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4929 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4930 tcg_temp_free(t3);
4931 tcg_temp_free(t2);
4933 break;
4934 case OPC_MULT:
4936 TCGv_i32 t2 = tcg_temp_new_i32();
4937 TCGv_i32 t3 = tcg_temp_new_i32();
4938 tcg_gen_trunc_tl_i32(t2, t0);
4939 tcg_gen_trunc_tl_i32(t3, t1);
4940 tcg_gen_muls2_i32(t2, t3, t2, t3);
4941 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4942 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4943 tcg_temp_free_i32(t2);
4944 tcg_temp_free_i32(t3);
4946 break;
4947 case OPC_MULTU:
4949 TCGv_i32 t2 = tcg_temp_new_i32();
4950 TCGv_i32 t3 = tcg_temp_new_i32();
4951 tcg_gen_trunc_tl_i32(t2, t0);
4952 tcg_gen_trunc_tl_i32(t3, t1);
4953 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4954 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4955 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4956 tcg_temp_free_i32(t2);
4957 tcg_temp_free_i32(t3);
4959 break;
4960 #if defined(TARGET_MIPS64)
4961 case OPC_DDIV:
4963 TCGv t2 = tcg_temp_new();
4964 TCGv t3 = tcg_temp_new();
4965 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4966 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4967 tcg_gen_and_tl(t2, t2, t3);
4968 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4969 tcg_gen_or_tl(t2, t2, t3);
4970 tcg_gen_movi_tl(t3, 0);
4971 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4972 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4973 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4974 tcg_temp_free(t3);
4975 tcg_temp_free(t2);
4977 break;
4978 case OPC_DDIVU:
4980 TCGv t2 = tcg_const_tl(0);
4981 TCGv t3 = tcg_const_tl(1);
4982 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4983 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4984 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4985 tcg_temp_free(t3);
4986 tcg_temp_free(t2);
4988 break;
4989 case OPC_DMULT:
4990 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4991 break;
4992 case OPC_DMULTU:
4993 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4994 break;
4995 #endif
4996 case OPC_MADD:
4998 TCGv_i64 t2 = tcg_temp_new_i64();
4999 TCGv_i64 t3 = tcg_temp_new_i64();
5001 tcg_gen_ext_tl_i64(t2, t0);
5002 tcg_gen_ext_tl_i64(t3, t1);
5003 tcg_gen_mul_i64(t2, t2, t3);
5004 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5005 tcg_gen_add_i64(t2, t2, t3);
5006 tcg_temp_free_i64(t3);
5007 gen_move_low32(cpu_LO[acc], t2);
5008 gen_move_high32(cpu_HI[acc], t2);
5009 tcg_temp_free_i64(t2);
5011 break;
5012 case OPC_MADDU:
5014 TCGv_i64 t2 = tcg_temp_new_i64();
5015 TCGv_i64 t3 = tcg_temp_new_i64();
5017 tcg_gen_ext32u_tl(t0, t0);
5018 tcg_gen_ext32u_tl(t1, t1);
5019 tcg_gen_extu_tl_i64(t2, t0);
5020 tcg_gen_extu_tl_i64(t3, t1);
5021 tcg_gen_mul_i64(t2, t2, t3);
5022 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5023 tcg_gen_add_i64(t2, t2, t3);
5024 tcg_temp_free_i64(t3);
5025 gen_move_low32(cpu_LO[acc], t2);
5026 gen_move_high32(cpu_HI[acc], t2);
5027 tcg_temp_free_i64(t2);
5029 break;
5030 case OPC_MSUB:
5032 TCGv_i64 t2 = tcg_temp_new_i64();
5033 TCGv_i64 t3 = tcg_temp_new_i64();
5035 tcg_gen_ext_tl_i64(t2, t0);
5036 tcg_gen_ext_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_sub_i64(t2, t3, t2);
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_MSUBU:
5048 TCGv_i64 t2 = tcg_temp_new_i64();
5049 TCGv_i64 t3 = tcg_temp_new_i64();
5051 tcg_gen_ext32u_tl(t0, t0);
5052 tcg_gen_ext32u_tl(t1, t1);
5053 tcg_gen_extu_tl_i64(t2, t0);
5054 tcg_gen_extu_tl_i64(t3, t1);
5055 tcg_gen_mul_i64(t2, t2, t3);
5056 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5057 tcg_gen_sub_i64(t2, t3, t2);
5058 tcg_temp_free_i64(t3);
5059 gen_move_low32(cpu_LO[acc], t2);
5060 gen_move_high32(cpu_HI[acc], t2);
5061 tcg_temp_free_i64(t2);
5063 break;
5064 default:
5065 MIPS_INVAL("mul/div");
5066 gen_reserved_instruction(ctx);
5067 goto out;
5069 out:
5070 tcg_temp_free(t0);
5071 tcg_temp_free(t1);
5075 * These MULT[U] and MADD[U] instructions implemented in for example
5076 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5077 * architectures are special three-operand variants with the syntax
5079 * MULT[U][1] rd, rs, rt
5081 * such that
5083 * (rd, LO, HI) <- rs * rt
5085 * and
5087 * MADD[U][1] rd, rs, rt
5089 * such that
5091 * (rd, LO, HI) <- (LO, HI) + rs * rt
5093 * where the low-order 32-bits of the result is placed into both the
5094 * GPR rd and the special register LO. The high-order 32-bits of the
5095 * result is placed into the special register HI.
5097 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5098 * which is the zero register that always reads as 0.
5100 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5101 int rd, int rs, int rt)
5103 TCGv t0 = tcg_temp_new();
5104 TCGv t1 = tcg_temp_new();
5105 int acc = 0;
5107 gen_load_gpr(t0, rs);
5108 gen_load_gpr(t1, rt);
5110 switch (opc) {
5111 case MMI_OPC_MULT1:
5112 acc = 1;
5113 /* Fall through */
5114 case OPC_MULT:
5116 TCGv_i32 t2 = tcg_temp_new_i32();
5117 TCGv_i32 t3 = tcg_temp_new_i32();
5118 tcg_gen_trunc_tl_i32(t2, t0);
5119 tcg_gen_trunc_tl_i32(t3, t1);
5120 tcg_gen_muls2_i32(t2, t3, t2, t3);
5121 if (rd) {
5122 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5124 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5125 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5126 tcg_temp_free_i32(t2);
5127 tcg_temp_free_i32(t3);
5129 break;
5130 case MMI_OPC_MULTU1:
5131 acc = 1;
5132 /* Fall through */
5133 case OPC_MULTU:
5135 TCGv_i32 t2 = tcg_temp_new_i32();
5136 TCGv_i32 t3 = tcg_temp_new_i32();
5137 tcg_gen_trunc_tl_i32(t2, t0);
5138 tcg_gen_trunc_tl_i32(t3, t1);
5139 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5140 if (rd) {
5141 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5143 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5144 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5145 tcg_temp_free_i32(t2);
5146 tcg_temp_free_i32(t3);
5148 break;
5149 case MMI_OPC_MADD1:
5150 acc = 1;
5151 /* Fall through */
5152 case MMI_OPC_MADD:
5154 TCGv_i64 t2 = tcg_temp_new_i64();
5155 TCGv_i64 t3 = tcg_temp_new_i64();
5157 tcg_gen_ext_tl_i64(t2, t0);
5158 tcg_gen_ext_tl_i64(t3, t1);
5159 tcg_gen_mul_i64(t2, t2, t3);
5160 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5161 tcg_gen_add_i64(t2, t2, t3);
5162 tcg_temp_free_i64(t3);
5163 gen_move_low32(cpu_LO[acc], t2);
5164 gen_move_high32(cpu_HI[acc], t2);
5165 if (rd) {
5166 gen_move_low32(cpu_gpr[rd], t2);
5168 tcg_temp_free_i64(t2);
5170 break;
5171 case MMI_OPC_MADDU1:
5172 acc = 1;
5173 /* Fall through */
5174 case MMI_OPC_MADDU:
5176 TCGv_i64 t2 = tcg_temp_new_i64();
5177 TCGv_i64 t3 = tcg_temp_new_i64();
5179 tcg_gen_ext32u_tl(t0, t0);
5180 tcg_gen_ext32u_tl(t1, t1);
5181 tcg_gen_extu_tl_i64(t2, t0);
5182 tcg_gen_extu_tl_i64(t3, t1);
5183 tcg_gen_mul_i64(t2, t2, t3);
5184 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5185 tcg_gen_add_i64(t2, t2, t3);
5186 tcg_temp_free_i64(t3);
5187 gen_move_low32(cpu_LO[acc], t2);
5188 gen_move_high32(cpu_HI[acc], t2);
5189 if (rd) {
5190 gen_move_low32(cpu_gpr[rd], t2);
5192 tcg_temp_free_i64(t2);
5194 break;
5195 default:
5196 MIPS_INVAL("mul/madd TXx9");
5197 gen_reserved_instruction(ctx);
5198 goto out;
5201 out:
5202 tcg_temp_free(t0);
5203 tcg_temp_free(t1);
5206 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5207 int rd, int rs, int rt)
5209 TCGv t0 = tcg_temp_new();
5210 TCGv t1 = tcg_temp_new();
5212 gen_load_gpr(t0, rs);
5213 gen_load_gpr(t1, rt);
5215 switch (opc) {
5216 case OPC_VR54XX_MULS:
5217 gen_helper_muls(t0, cpu_env, t0, t1);
5218 break;
5219 case OPC_VR54XX_MULSU:
5220 gen_helper_mulsu(t0, cpu_env, t0, t1);
5221 break;
5222 case OPC_VR54XX_MACC:
5223 gen_helper_macc(t0, cpu_env, t0, t1);
5224 break;
5225 case OPC_VR54XX_MACCU:
5226 gen_helper_maccu(t0, cpu_env, t0, t1);
5227 break;
5228 case OPC_VR54XX_MSAC:
5229 gen_helper_msac(t0, cpu_env, t0, t1);
5230 break;
5231 case OPC_VR54XX_MSACU:
5232 gen_helper_msacu(t0, cpu_env, t0, t1);
5233 break;
5234 case OPC_VR54XX_MULHI:
5235 gen_helper_mulhi(t0, cpu_env, t0, t1);
5236 break;
5237 case OPC_VR54XX_MULHIU:
5238 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5239 break;
5240 case OPC_VR54XX_MULSHI:
5241 gen_helper_mulshi(t0, cpu_env, t0, t1);
5242 break;
5243 case OPC_VR54XX_MULSHIU:
5244 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5245 break;
5246 case OPC_VR54XX_MACCHI:
5247 gen_helper_macchi(t0, cpu_env, t0, t1);
5248 break;
5249 case OPC_VR54XX_MACCHIU:
5250 gen_helper_macchiu(t0, cpu_env, t0, t1);
5251 break;
5252 case OPC_VR54XX_MSACHI:
5253 gen_helper_msachi(t0, cpu_env, t0, t1);
5254 break;
5255 case OPC_VR54XX_MSACHIU:
5256 gen_helper_msachiu(t0, cpu_env, t0, t1);
5257 break;
5258 default:
5259 MIPS_INVAL("mul vr54xx");
5260 gen_reserved_instruction(ctx);
5261 goto out;
5263 gen_store_gpr(t0, rd);
5265 out:
5266 tcg_temp_free(t0);
5267 tcg_temp_free(t1);
5270 static void gen_cl(DisasContext *ctx, uint32_t opc,
5271 int rd, int rs)
5273 TCGv t0;
5275 if (rd == 0) {
5276 /* Treat as NOP. */
5277 return;
5279 t0 = cpu_gpr[rd];
5280 gen_load_gpr(t0, rs);
5282 switch (opc) {
5283 case OPC_CLO:
5284 case R6_OPC_CLO:
5285 #if defined(TARGET_MIPS64)
5286 case OPC_DCLO:
5287 case R6_OPC_DCLO:
5288 #endif
5289 tcg_gen_not_tl(t0, t0);
5290 break;
5293 switch (opc) {
5294 case OPC_CLO:
5295 case R6_OPC_CLO:
5296 case OPC_CLZ:
5297 case R6_OPC_CLZ:
5298 tcg_gen_ext32u_tl(t0, t0);
5299 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5300 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5301 break;
5302 #if defined(TARGET_MIPS64)
5303 case OPC_DCLO:
5304 case R6_OPC_DCLO:
5305 case OPC_DCLZ:
5306 case R6_OPC_DCLZ:
5307 tcg_gen_clzi_i64(t0, t0, 64);
5308 break;
5309 #endif
5313 /* Godson integer instructions */
5314 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5315 int rd, int rs, int rt)
5317 TCGv t0, t1;
5319 if (rd == 0) {
5320 /* Treat as NOP. */
5321 return;
5324 switch (opc) {
5325 case OPC_MULT_G_2E:
5326 case OPC_MULT_G_2F:
5327 case OPC_MULTU_G_2E:
5328 case OPC_MULTU_G_2F:
5329 #if defined(TARGET_MIPS64)
5330 case OPC_DMULT_G_2E:
5331 case OPC_DMULT_G_2F:
5332 case OPC_DMULTU_G_2E:
5333 case OPC_DMULTU_G_2F:
5334 #endif
5335 t0 = tcg_temp_new();
5336 t1 = tcg_temp_new();
5337 break;
5338 default:
5339 t0 = tcg_temp_local_new();
5340 t1 = tcg_temp_local_new();
5341 break;
5344 gen_load_gpr(t0, rs);
5345 gen_load_gpr(t1, rt);
5347 switch (opc) {
5348 case OPC_MULT_G_2E:
5349 case OPC_MULT_G_2F:
5350 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5351 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5352 break;
5353 case OPC_MULTU_G_2E:
5354 case OPC_MULTU_G_2F:
5355 tcg_gen_ext32u_tl(t0, t0);
5356 tcg_gen_ext32u_tl(t1, t1);
5357 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5358 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5359 break;
5360 case OPC_DIV_G_2E:
5361 case OPC_DIV_G_2F:
5363 TCGLabel *l1 = gen_new_label();
5364 TCGLabel *l2 = gen_new_label();
5365 TCGLabel *l3 = gen_new_label();
5366 tcg_gen_ext32s_tl(t0, t0);
5367 tcg_gen_ext32s_tl(t1, t1);
5368 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5369 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5370 tcg_gen_br(l3);
5371 gen_set_label(l1);
5372 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5373 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5374 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5375 tcg_gen_br(l3);
5376 gen_set_label(l2);
5377 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5378 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5379 gen_set_label(l3);
5381 break;
5382 case OPC_DIVU_G_2E:
5383 case OPC_DIVU_G_2F:
5385 TCGLabel *l1 = gen_new_label();
5386 TCGLabel *l2 = gen_new_label();
5387 tcg_gen_ext32u_tl(t0, t0);
5388 tcg_gen_ext32u_tl(t1, t1);
5389 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5390 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5391 tcg_gen_br(l2);
5392 gen_set_label(l1);
5393 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5394 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5395 gen_set_label(l2);
5397 break;
5398 case OPC_MOD_G_2E:
5399 case OPC_MOD_G_2F:
5401 TCGLabel *l1 = gen_new_label();
5402 TCGLabel *l2 = gen_new_label();
5403 TCGLabel *l3 = gen_new_label();
5404 tcg_gen_ext32u_tl(t0, t0);
5405 tcg_gen_ext32u_tl(t1, t1);
5406 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5407 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5408 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5409 gen_set_label(l1);
5410 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5411 tcg_gen_br(l3);
5412 gen_set_label(l2);
5413 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5414 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5415 gen_set_label(l3);
5417 break;
5418 case OPC_MODU_G_2E:
5419 case OPC_MODU_G_2F:
5421 TCGLabel *l1 = gen_new_label();
5422 TCGLabel *l2 = gen_new_label();
5423 tcg_gen_ext32u_tl(t0, t0);
5424 tcg_gen_ext32u_tl(t1, t1);
5425 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5426 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5427 tcg_gen_br(l2);
5428 gen_set_label(l1);
5429 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5430 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5431 gen_set_label(l2);
5433 break;
5434 #if defined(TARGET_MIPS64)
5435 case OPC_DMULT_G_2E:
5436 case OPC_DMULT_G_2F:
5437 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5438 break;
5439 case OPC_DMULTU_G_2E:
5440 case OPC_DMULTU_G_2F:
5441 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5442 break;
5443 case OPC_DDIV_G_2E:
5444 case OPC_DDIV_G_2F:
5446 TCGLabel *l1 = gen_new_label();
5447 TCGLabel *l2 = gen_new_label();
5448 TCGLabel *l3 = gen_new_label();
5449 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5450 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5451 tcg_gen_br(l3);
5452 gen_set_label(l1);
5453 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5454 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5455 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5456 tcg_gen_br(l3);
5457 gen_set_label(l2);
5458 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5459 gen_set_label(l3);
5461 break;
5462 case OPC_DDIVU_G_2E:
5463 case OPC_DDIVU_G_2F:
5465 TCGLabel *l1 = gen_new_label();
5466 TCGLabel *l2 = gen_new_label();
5467 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5468 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5469 tcg_gen_br(l2);
5470 gen_set_label(l1);
5471 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5472 gen_set_label(l2);
5474 break;
5475 case OPC_DMOD_G_2E:
5476 case OPC_DMOD_G_2F:
5478 TCGLabel *l1 = gen_new_label();
5479 TCGLabel *l2 = gen_new_label();
5480 TCGLabel *l3 = gen_new_label();
5481 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5482 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5484 gen_set_label(l1);
5485 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5486 tcg_gen_br(l3);
5487 gen_set_label(l2);
5488 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5489 gen_set_label(l3);
5491 break;
5492 case OPC_DMODU_G_2E:
5493 case OPC_DMODU_G_2F:
5495 TCGLabel *l1 = gen_new_label();
5496 TCGLabel *l2 = gen_new_label();
5497 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5498 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5499 tcg_gen_br(l2);
5500 gen_set_label(l1);
5501 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5502 gen_set_label(l2);
5504 break;
5505 #endif
5508 tcg_temp_free(t0);
5509 tcg_temp_free(t1);
5512 /* Loongson multimedia instructions */
5513 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5515 uint32_t opc, shift_max;
5516 TCGv_i64 t0, t1;
5517 TCGCond cond;
5519 opc = MASK_LMMI(ctx->opcode);
5520 switch (opc) {
5521 case OPC_ADD_CP2:
5522 case OPC_SUB_CP2:
5523 case OPC_DADD_CP2:
5524 case OPC_DSUB_CP2:
5525 t0 = tcg_temp_local_new_i64();
5526 t1 = tcg_temp_local_new_i64();
5527 break;
5528 default:
5529 t0 = tcg_temp_new_i64();
5530 t1 = tcg_temp_new_i64();
5531 break;
5534 check_cp1_enabled(ctx);
5535 gen_load_fpr64(ctx, t0, rs);
5536 gen_load_fpr64(ctx, t1, rt);
5538 switch (opc) {
5539 case OPC_PADDSH:
5540 gen_helper_paddsh(t0, t0, t1);
5541 break;
5542 case OPC_PADDUSH:
5543 gen_helper_paddush(t0, t0, t1);
5544 break;
5545 case OPC_PADDH:
5546 gen_helper_paddh(t0, t0, t1);
5547 break;
5548 case OPC_PADDW:
5549 gen_helper_paddw(t0, t0, t1);
5550 break;
5551 case OPC_PADDSB:
5552 gen_helper_paddsb(t0, t0, t1);
5553 break;
5554 case OPC_PADDUSB:
5555 gen_helper_paddusb(t0, t0, t1);
5556 break;
5557 case OPC_PADDB:
5558 gen_helper_paddb(t0, t0, t1);
5559 break;
5561 case OPC_PSUBSH:
5562 gen_helper_psubsh(t0, t0, t1);
5563 break;
5564 case OPC_PSUBUSH:
5565 gen_helper_psubush(t0, t0, t1);
5566 break;
5567 case OPC_PSUBH:
5568 gen_helper_psubh(t0, t0, t1);
5569 break;
5570 case OPC_PSUBW:
5571 gen_helper_psubw(t0, t0, t1);
5572 break;
5573 case OPC_PSUBSB:
5574 gen_helper_psubsb(t0, t0, t1);
5575 break;
5576 case OPC_PSUBUSB:
5577 gen_helper_psubusb(t0, t0, t1);
5578 break;
5579 case OPC_PSUBB:
5580 gen_helper_psubb(t0, t0, t1);
5581 break;
5583 case OPC_PSHUFH:
5584 gen_helper_pshufh(t0, t0, t1);
5585 break;
5586 case OPC_PACKSSWH:
5587 gen_helper_packsswh(t0, t0, t1);
5588 break;
5589 case OPC_PACKSSHB:
5590 gen_helper_packsshb(t0, t0, t1);
5591 break;
5592 case OPC_PACKUSHB:
5593 gen_helper_packushb(t0, t0, t1);
5594 break;
5596 case OPC_PUNPCKLHW:
5597 gen_helper_punpcklhw(t0, t0, t1);
5598 break;
5599 case OPC_PUNPCKHHW:
5600 gen_helper_punpckhhw(t0, t0, t1);
5601 break;
5602 case OPC_PUNPCKLBH:
5603 gen_helper_punpcklbh(t0, t0, t1);
5604 break;
5605 case OPC_PUNPCKHBH:
5606 gen_helper_punpckhbh(t0, t0, t1);
5607 break;
5608 case OPC_PUNPCKLWD:
5609 gen_helper_punpcklwd(t0, t0, t1);
5610 break;
5611 case OPC_PUNPCKHWD:
5612 gen_helper_punpckhwd(t0, t0, t1);
5613 break;
5615 case OPC_PAVGH:
5616 gen_helper_pavgh(t0, t0, t1);
5617 break;
5618 case OPC_PAVGB:
5619 gen_helper_pavgb(t0, t0, t1);
5620 break;
5621 case OPC_PMAXSH:
5622 gen_helper_pmaxsh(t0, t0, t1);
5623 break;
5624 case OPC_PMINSH:
5625 gen_helper_pminsh(t0, t0, t1);
5626 break;
5627 case OPC_PMAXUB:
5628 gen_helper_pmaxub(t0, t0, t1);
5629 break;
5630 case OPC_PMINUB:
5631 gen_helper_pminub(t0, t0, t1);
5632 break;
5634 case OPC_PCMPEQW:
5635 gen_helper_pcmpeqw(t0, t0, t1);
5636 break;
5637 case OPC_PCMPGTW:
5638 gen_helper_pcmpgtw(t0, t0, t1);
5639 break;
5640 case OPC_PCMPEQH:
5641 gen_helper_pcmpeqh(t0, t0, t1);
5642 break;
5643 case OPC_PCMPGTH:
5644 gen_helper_pcmpgth(t0, t0, t1);
5645 break;
5646 case OPC_PCMPEQB:
5647 gen_helper_pcmpeqb(t0, t0, t1);
5648 break;
5649 case OPC_PCMPGTB:
5650 gen_helper_pcmpgtb(t0, t0, t1);
5651 break;
5653 case OPC_PSLLW:
5654 gen_helper_psllw(t0, t0, t1);
5655 break;
5656 case OPC_PSLLH:
5657 gen_helper_psllh(t0, t0, t1);
5658 break;
5659 case OPC_PSRLW:
5660 gen_helper_psrlw(t0, t0, t1);
5661 break;
5662 case OPC_PSRLH:
5663 gen_helper_psrlh(t0, t0, t1);
5664 break;
5665 case OPC_PSRAW:
5666 gen_helper_psraw(t0, t0, t1);
5667 break;
5668 case OPC_PSRAH:
5669 gen_helper_psrah(t0, t0, t1);
5670 break;
5672 case OPC_PMULLH:
5673 gen_helper_pmullh(t0, t0, t1);
5674 break;
5675 case OPC_PMULHH:
5676 gen_helper_pmulhh(t0, t0, t1);
5677 break;
5678 case OPC_PMULHUH:
5679 gen_helper_pmulhuh(t0, t0, t1);
5680 break;
5681 case OPC_PMADDHW:
5682 gen_helper_pmaddhw(t0, t0, t1);
5683 break;
5685 case OPC_PASUBUB:
5686 gen_helper_pasubub(t0, t0, t1);
5687 break;
5688 case OPC_BIADD:
5689 gen_helper_biadd(t0, t0);
5690 break;
5691 case OPC_PMOVMSKB:
5692 gen_helper_pmovmskb(t0, t0);
5693 break;
5695 case OPC_PADDD:
5696 tcg_gen_add_i64(t0, t0, t1);
5697 break;
5698 case OPC_PSUBD:
5699 tcg_gen_sub_i64(t0, t0, t1);
5700 break;
5701 case OPC_XOR_CP2:
5702 tcg_gen_xor_i64(t0, t0, t1);
5703 break;
5704 case OPC_NOR_CP2:
5705 tcg_gen_nor_i64(t0, t0, t1);
5706 break;
5707 case OPC_AND_CP2:
5708 tcg_gen_and_i64(t0, t0, t1);
5709 break;
5710 case OPC_OR_CP2:
5711 tcg_gen_or_i64(t0, t0, t1);
5712 break;
5714 case OPC_PANDN:
5715 tcg_gen_andc_i64(t0, t1, t0);
5716 break;
5718 case OPC_PINSRH_0:
5719 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5720 break;
5721 case OPC_PINSRH_1:
5722 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5723 break;
5724 case OPC_PINSRH_2:
5725 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5726 break;
5727 case OPC_PINSRH_3:
5728 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5729 break;
5731 case OPC_PEXTRH:
5732 tcg_gen_andi_i64(t1, t1, 3);
5733 tcg_gen_shli_i64(t1, t1, 4);
5734 tcg_gen_shr_i64(t0, t0, t1);
5735 tcg_gen_ext16u_i64(t0, t0);
5736 break;
5738 case OPC_ADDU_CP2:
5739 tcg_gen_add_i64(t0, t0, t1);
5740 tcg_gen_ext32s_i64(t0, t0);
5741 break;
5742 case OPC_SUBU_CP2:
5743 tcg_gen_sub_i64(t0, t0, t1);
5744 tcg_gen_ext32s_i64(t0, t0);
5745 break;
5747 case OPC_SLL_CP2:
5748 shift_max = 32;
5749 goto do_shift;
5750 case OPC_SRL_CP2:
5751 shift_max = 32;
5752 goto do_shift;
5753 case OPC_SRA_CP2:
5754 shift_max = 32;
5755 goto do_shift;
5756 case OPC_DSLL_CP2:
5757 shift_max = 64;
5758 goto do_shift;
5759 case OPC_DSRL_CP2:
5760 shift_max = 64;
5761 goto do_shift;
5762 case OPC_DSRA_CP2:
5763 shift_max = 64;
5764 goto do_shift;
5765 do_shift:
5766 /* Make sure shift count isn't TCG undefined behaviour. */
5767 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5769 switch (opc) {
5770 case OPC_SLL_CP2:
5771 case OPC_DSLL_CP2:
5772 tcg_gen_shl_i64(t0, t0, t1);
5773 break;
5774 case OPC_SRA_CP2:
5775 case OPC_DSRA_CP2:
5777 * Since SRA is UndefinedResult without sign-extended inputs,
5778 * we can treat SRA and DSRA the same.
5780 tcg_gen_sar_i64(t0, t0, t1);
5781 break;
5782 case OPC_SRL_CP2:
5783 /* We want to shift in zeros for SRL; zero-extend first. */
5784 tcg_gen_ext32u_i64(t0, t0);
5785 /* FALLTHRU */
5786 case OPC_DSRL_CP2:
5787 tcg_gen_shr_i64(t0, t0, t1);
5788 break;
5791 if (shift_max == 32) {
5792 tcg_gen_ext32s_i64(t0, t0);
5795 /* Shifts larger than MAX produce zero. */
5796 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5797 tcg_gen_neg_i64(t1, t1);
5798 tcg_gen_and_i64(t0, t0, t1);
5799 break;
5801 case OPC_ADD_CP2:
5802 case OPC_DADD_CP2:
5804 TCGv_i64 t2 = tcg_temp_new_i64();
5805 TCGLabel *lab = gen_new_label();
5807 tcg_gen_mov_i64(t2, t0);
5808 tcg_gen_add_i64(t0, t1, t2);
5809 if (opc == OPC_ADD_CP2) {
5810 tcg_gen_ext32s_i64(t0, t0);
5812 tcg_gen_xor_i64(t1, t1, t2);
5813 tcg_gen_xor_i64(t2, t2, t0);
5814 tcg_gen_andc_i64(t1, t2, t1);
5815 tcg_temp_free_i64(t2);
5816 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5817 generate_exception(ctx, EXCP_OVERFLOW);
5818 gen_set_label(lab);
5819 break;
5822 case OPC_SUB_CP2:
5823 case OPC_DSUB_CP2:
5825 TCGv_i64 t2 = tcg_temp_new_i64();
5826 TCGLabel *lab = gen_new_label();
5828 tcg_gen_mov_i64(t2, t0);
5829 tcg_gen_sub_i64(t0, t1, t2);
5830 if (opc == OPC_SUB_CP2) {
5831 tcg_gen_ext32s_i64(t0, t0);
5833 tcg_gen_xor_i64(t1, t1, t2);
5834 tcg_gen_xor_i64(t2, t2, t0);
5835 tcg_gen_and_i64(t1, t1, t2);
5836 tcg_temp_free_i64(t2);
5837 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5838 generate_exception(ctx, EXCP_OVERFLOW);
5839 gen_set_label(lab);
5840 break;
5843 case OPC_PMULUW:
5844 tcg_gen_ext32u_i64(t0, t0);
5845 tcg_gen_ext32u_i64(t1, t1);
5846 tcg_gen_mul_i64(t0, t0, t1);
5847 break;
5849 case OPC_SEQU_CP2:
5850 case OPC_SEQ_CP2:
5851 cond = TCG_COND_EQ;
5852 goto do_cc_cond;
5853 break;
5854 case OPC_SLTU_CP2:
5855 cond = TCG_COND_LTU;
5856 goto do_cc_cond;
5857 break;
5858 case OPC_SLT_CP2:
5859 cond = TCG_COND_LT;
5860 goto do_cc_cond;
5861 break;
5862 case OPC_SLEU_CP2:
5863 cond = TCG_COND_LEU;
5864 goto do_cc_cond;
5865 break;
5866 case OPC_SLE_CP2:
5867 cond = TCG_COND_LE;
5868 do_cc_cond:
5870 int cc = (ctx->opcode >> 8) & 0x7;
5871 TCGv_i64 t64 = tcg_temp_new_i64();
5872 TCGv_i32 t32 = tcg_temp_new_i32();
5874 tcg_gen_setcond_i64(cond, t64, t0, t1);
5875 tcg_gen_extrl_i64_i32(t32, t64);
5876 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5877 get_fp_bit(cc), 1);
5879 tcg_temp_free_i32(t32);
5880 tcg_temp_free_i64(t64);
5882 goto no_rd;
5883 break;
5884 default:
5885 MIPS_INVAL("loongson_cp2");
5886 gen_reserved_instruction(ctx);
5887 return;
5890 gen_store_fpr64(ctx, t0, rd);
5892 no_rd:
5893 tcg_temp_free_i64(t0);
5894 tcg_temp_free_i64(t1);
5897 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5898 int rs, int rd)
5900 TCGv t0, t1, t2;
5901 TCGv_i32 fp0;
5902 #if defined(TARGET_MIPS64)
5903 int lsq_rt1 = ctx->opcode & 0x1f;
5904 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5905 #endif
5906 int shf_offset = sextract32(ctx->opcode, 6, 8);
5908 t0 = tcg_temp_new();
5910 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5911 #if defined(TARGET_MIPS64)
5912 case OPC_GSLQ:
5913 t1 = tcg_temp_new();
5914 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5915 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5916 ctx->default_tcg_memop_mask);
5917 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5918 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5919 ctx->default_tcg_memop_mask);
5920 gen_store_gpr(t1, rt);
5921 gen_store_gpr(t0, lsq_rt1);
5922 tcg_temp_free(t1);
5923 break;
5924 case OPC_GSLQC1:
5925 check_cp1_enabled(ctx);
5926 t1 = tcg_temp_new();
5927 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5928 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5929 ctx->default_tcg_memop_mask);
5930 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5931 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5932 ctx->default_tcg_memop_mask);
5933 gen_store_fpr64(ctx, t1, rt);
5934 gen_store_fpr64(ctx, t0, lsq_rt1);
5935 tcg_temp_free(t1);
5936 break;
5937 case OPC_GSSQ:
5938 t1 = tcg_temp_new();
5939 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5940 gen_load_gpr(t1, rt);
5941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5942 ctx->default_tcg_memop_mask);
5943 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5944 gen_load_gpr(t1, lsq_rt1);
5945 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5946 ctx->default_tcg_memop_mask);
5947 tcg_temp_free(t1);
5948 break;
5949 case OPC_GSSQC1:
5950 check_cp1_enabled(ctx);
5951 t1 = tcg_temp_new();
5952 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5953 gen_load_fpr64(ctx, t1, rt);
5954 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5955 ctx->default_tcg_memop_mask);
5956 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5957 gen_load_fpr64(ctx, t1, lsq_rt1);
5958 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5959 ctx->default_tcg_memop_mask);
5960 tcg_temp_free(t1);
5961 break;
5962 #endif
5963 case OPC_GSSHFL:
5964 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5965 case OPC_GSLWLC1:
5966 check_cp1_enabled(ctx);
5967 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5968 t1 = tcg_temp_new();
5969 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5970 tcg_gen_andi_tl(t1, t0, 3);
5971 #ifndef TARGET_WORDS_BIGENDIAN
5972 tcg_gen_xori_tl(t1, t1, 3);
5973 #endif
5974 tcg_gen_shli_tl(t1, t1, 3);
5975 tcg_gen_andi_tl(t0, t0, ~3);
5976 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5977 tcg_gen_shl_tl(t0, t0, t1);
5978 t2 = tcg_const_tl(-1);
5979 tcg_gen_shl_tl(t2, t2, t1);
5980 fp0 = tcg_temp_new_i32();
5981 gen_load_fpr32(ctx, fp0, rt);
5982 tcg_gen_ext_i32_tl(t1, fp0);
5983 tcg_gen_andc_tl(t1, t1, t2);
5984 tcg_temp_free(t2);
5985 tcg_gen_or_tl(t0, t0, t1);
5986 tcg_temp_free(t1);
5987 #if defined(TARGET_MIPS64)
5988 tcg_gen_extrl_i64_i32(fp0, t0);
5989 #else
5990 tcg_gen_ext32s_tl(fp0, t0);
5991 #endif
5992 gen_store_fpr32(ctx, fp0, rt);
5993 tcg_temp_free_i32(fp0);
5994 break;
5995 case OPC_GSLWRC1:
5996 check_cp1_enabled(ctx);
5997 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5998 t1 = tcg_temp_new();
5999 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6000 tcg_gen_andi_tl(t1, t0, 3);
6001 #ifdef TARGET_WORDS_BIGENDIAN
6002 tcg_gen_xori_tl(t1, t1, 3);
6003 #endif
6004 tcg_gen_shli_tl(t1, t1, 3);
6005 tcg_gen_andi_tl(t0, t0, ~3);
6006 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6007 tcg_gen_shr_tl(t0, t0, t1);
6008 tcg_gen_xori_tl(t1, t1, 31);
6009 t2 = tcg_const_tl(0xfffffffeull);
6010 tcg_gen_shl_tl(t2, t2, t1);
6011 fp0 = tcg_temp_new_i32();
6012 gen_load_fpr32(ctx, fp0, rt);
6013 tcg_gen_ext_i32_tl(t1, fp0);
6014 tcg_gen_and_tl(t1, t1, t2);
6015 tcg_temp_free(t2);
6016 tcg_gen_or_tl(t0, t0, t1);
6017 tcg_temp_free(t1);
6018 #if defined(TARGET_MIPS64)
6019 tcg_gen_extrl_i64_i32(fp0, t0);
6020 #else
6021 tcg_gen_ext32s_tl(fp0, t0);
6022 #endif
6023 gen_store_fpr32(ctx, fp0, rt);
6024 tcg_temp_free_i32(fp0);
6025 break;
6026 #if defined(TARGET_MIPS64)
6027 case OPC_GSLDLC1:
6028 check_cp1_enabled(ctx);
6029 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6030 t1 = tcg_temp_new();
6031 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6032 tcg_gen_andi_tl(t1, t0, 7);
6033 #ifndef TARGET_WORDS_BIGENDIAN
6034 tcg_gen_xori_tl(t1, t1, 7);
6035 #endif
6036 tcg_gen_shli_tl(t1, t1, 3);
6037 tcg_gen_andi_tl(t0, t0, ~7);
6038 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6039 tcg_gen_shl_tl(t0, t0, t1);
6040 t2 = tcg_const_tl(-1);
6041 tcg_gen_shl_tl(t2, t2, t1);
6042 gen_load_fpr64(ctx, t1, rt);
6043 tcg_gen_andc_tl(t1, t1, t2);
6044 tcg_temp_free(t2);
6045 tcg_gen_or_tl(t0, t0, t1);
6046 tcg_temp_free(t1);
6047 gen_store_fpr64(ctx, t0, rt);
6048 break;
6049 case OPC_GSLDRC1:
6050 check_cp1_enabled(ctx);
6051 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6052 t1 = tcg_temp_new();
6053 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6054 tcg_gen_andi_tl(t1, t0, 7);
6055 #ifdef TARGET_WORDS_BIGENDIAN
6056 tcg_gen_xori_tl(t1, t1, 7);
6057 #endif
6058 tcg_gen_shli_tl(t1, t1, 3);
6059 tcg_gen_andi_tl(t0, t0, ~7);
6060 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6061 tcg_gen_shr_tl(t0, t0, t1);
6062 tcg_gen_xori_tl(t1, t1, 63);
6063 t2 = tcg_const_tl(0xfffffffffffffffeull);
6064 tcg_gen_shl_tl(t2, t2, t1);
6065 gen_load_fpr64(ctx, t1, rt);
6066 tcg_gen_and_tl(t1, t1, t2);
6067 tcg_temp_free(t2);
6068 tcg_gen_or_tl(t0, t0, t1);
6069 tcg_temp_free(t1);
6070 gen_store_fpr64(ctx, t0, rt);
6071 break;
6072 #endif
6073 default:
6074 MIPS_INVAL("loongson_gsshfl");
6075 gen_reserved_instruction(ctx);
6076 break;
6078 break;
6079 case OPC_GSSHFS:
6080 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6081 case OPC_GSSWLC1:
6082 check_cp1_enabled(ctx);
6083 t1 = tcg_temp_new();
6084 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6085 fp0 = tcg_temp_new_i32();
6086 gen_load_fpr32(ctx, fp0, rt);
6087 tcg_gen_ext_i32_tl(t1, fp0);
6088 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
6089 tcg_temp_free_i32(fp0);
6090 tcg_temp_free(t1);
6091 break;
6092 case OPC_GSSWRC1:
6093 check_cp1_enabled(ctx);
6094 t1 = tcg_temp_new();
6095 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6096 fp0 = tcg_temp_new_i32();
6097 gen_load_fpr32(ctx, fp0, rt);
6098 tcg_gen_ext_i32_tl(t1, fp0);
6099 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
6100 tcg_temp_free_i32(fp0);
6101 tcg_temp_free(t1);
6102 break;
6103 #if defined(TARGET_MIPS64)
6104 case OPC_GSSDLC1:
6105 check_cp1_enabled(ctx);
6106 t1 = tcg_temp_new();
6107 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6108 gen_load_fpr64(ctx, t1, rt);
6109 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
6110 tcg_temp_free(t1);
6111 break;
6112 case OPC_GSSDRC1:
6113 check_cp1_enabled(ctx);
6114 t1 = tcg_temp_new();
6115 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6116 gen_load_fpr64(ctx, t1, rt);
6117 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
6118 tcg_temp_free(t1);
6119 break;
6120 #endif
6121 default:
6122 MIPS_INVAL("loongson_gsshfs");
6123 gen_reserved_instruction(ctx);
6124 break;
6126 break;
6127 default:
6128 MIPS_INVAL("loongson_gslsq");
6129 gen_reserved_instruction(ctx);
6130 break;
6132 tcg_temp_free(t0);
6135 /* Loongson EXT LDC2/SDC2 */
6136 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
6137 int rs, int rd)
6139 int offset = sextract32(ctx->opcode, 3, 8);
6140 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
6141 TCGv t0, t1;
6142 TCGv_i32 fp0;
6144 /* Pre-conditions */
6145 switch (opc) {
6146 case OPC_GSLBX:
6147 case OPC_GSLHX:
6148 case OPC_GSLWX:
6149 case OPC_GSLDX:
6150 /* prefetch, implement as NOP */
6151 if (rt == 0) {
6152 return;
6154 break;
6155 case OPC_GSSBX:
6156 case OPC_GSSHX:
6157 case OPC_GSSWX:
6158 case OPC_GSSDX:
6159 break;
6160 case OPC_GSLWXC1:
6161 #if defined(TARGET_MIPS64)
6162 case OPC_GSLDXC1:
6163 #endif
6164 check_cp1_enabled(ctx);
6165 /* prefetch, implement as NOP */
6166 if (rt == 0) {
6167 return;
6169 break;
6170 case OPC_GSSWXC1:
6171 #if defined(TARGET_MIPS64)
6172 case OPC_GSSDXC1:
6173 #endif
6174 check_cp1_enabled(ctx);
6175 break;
6176 default:
6177 MIPS_INVAL("loongson_lsdc2");
6178 gen_reserved_instruction(ctx);
6179 return;
6180 break;
6183 t0 = tcg_temp_new();
6185 gen_base_offset_addr(ctx, t0, rs, offset);
6186 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6188 switch (opc) {
6189 case OPC_GSLBX:
6190 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
6191 gen_store_gpr(t0, rt);
6192 break;
6193 case OPC_GSLHX:
6194 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
6195 ctx->default_tcg_memop_mask);
6196 gen_store_gpr(t0, rt);
6197 break;
6198 case OPC_GSLWX:
6199 gen_base_offset_addr(ctx, t0, rs, offset);
6200 if (rd) {
6201 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6203 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
6204 ctx->default_tcg_memop_mask);
6205 gen_store_gpr(t0, rt);
6206 break;
6207 #if defined(TARGET_MIPS64)
6208 case OPC_GSLDX:
6209 gen_base_offset_addr(ctx, t0, rs, offset);
6210 if (rd) {
6211 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6213 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6214 ctx->default_tcg_memop_mask);
6215 gen_store_gpr(t0, rt);
6216 break;
6217 #endif
6218 case OPC_GSLWXC1:
6219 check_cp1_enabled(ctx);
6220 gen_base_offset_addr(ctx, t0, rs, offset);
6221 if (rd) {
6222 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6224 fp0 = tcg_temp_new_i32();
6225 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
6226 ctx->default_tcg_memop_mask);
6227 gen_store_fpr32(ctx, fp0, rt);
6228 tcg_temp_free_i32(fp0);
6229 break;
6230 #if defined(TARGET_MIPS64)
6231 case OPC_GSLDXC1:
6232 check_cp1_enabled(ctx);
6233 gen_base_offset_addr(ctx, t0, rs, offset);
6234 if (rd) {
6235 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6237 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6238 ctx->default_tcg_memop_mask);
6239 gen_store_fpr64(ctx, t0, rt);
6240 break;
6241 #endif
6242 case OPC_GSSBX:
6243 t1 = tcg_temp_new();
6244 gen_load_gpr(t1, rt);
6245 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
6246 tcg_temp_free(t1);
6247 break;
6248 case OPC_GSSHX:
6249 t1 = tcg_temp_new();
6250 gen_load_gpr(t1, rt);
6251 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
6252 ctx->default_tcg_memop_mask);
6253 tcg_temp_free(t1);
6254 break;
6255 case OPC_GSSWX:
6256 t1 = tcg_temp_new();
6257 gen_load_gpr(t1, rt);
6258 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
6259 ctx->default_tcg_memop_mask);
6260 tcg_temp_free(t1);
6261 break;
6262 #if defined(TARGET_MIPS64)
6263 case OPC_GSSDX:
6264 t1 = tcg_temp_new();
6265 gen_load_gpr(t1, rt);
6266 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6267 ctx->default_tcg_memop_mask);
6268 tcg_temp_free(t1);
6269 break;
6270 #endif
6271 case OPC_GSSWXC1:
6272 fp0 = tcg_temp_new_i32();
6273 gen_load_fpr32(ctx, fp0, rt);
6274 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
6275 ctx->default_tcg_memop_mask);
6276 tcg_temp_free_i32(fp0);
6277 break;
6278 #if defined(TARGET_MIPS64)
6279 case OPC_GSSDXC1:
6280 t1 = tcg_temp_new();
6281 gen_load_fpr64(ctx, t1, rt);
6282 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
6283 ctx->default_tcg_memop_mask);
6284 tcg_temp_free(t1);
6285 break;
6286 #endif
6287 default:
6288 break;
6291 tcg_temp_free(t0);
6294 /* Traps */
6295 static void gen_trap(DisasContext *ctx, uint32_t opc,
6296 int rs, int rt, int16_t imm)
6298 int cond;
6299 TCGv t0 = tcg_temp_new();
6300 TCGv t1 = tcg_temp_new();
6302 cond = 0;
6303 /* Load needed operands */
6304 switch (opc) {
6305 case OPC_TEQ:
6306 case OPC_TGE:
6307 case OPC_TGEU:
6308 case OPC_TLT:
6309 case OPC_TLTU:
6310 case OPC_TNE:
6311 /* Compare two registers */
6312 if (rs != rt) {
6313 gen_load_gpr(t0, rs);
6314 gen_load_gpr(t1, rt);
6315 cond = 1;
6317 break;
6318 case OPC_TEQI:
6319 case OPC_TGEI:
6320 case OPC_TGEIU:
6321 case OPC_TLTI:
6322 case OPC_TLTIU:
6323 case OPC_TNEI:
6324 /* Compare register to immediate */
6325 if (rs != 0 || imm != 0) {
6326 gen_load_gpr(t0, rs);
6327 tcg_gen_movi_tl(t1, (int32_t)imm);
6328 cond = 1;
6330 break;
6332 if (cond == 0) {
6333 switch (opc) {
6334 case OPC_TEQ: /* rs == rs */
6335 case OPC_TEQI: /* r0 == 0 */
6336 case OPC_TGE: /* rs >= rs */
6337 case OPC_TGEI: /* r0 >= 0 */
6338 case OPC_TGEU: /* rs >= rs unsigned */
6339 case OPC_TGEIU: /* r0 >= 0 unsigned */
6340 /* Always trap */
6341 generate_exception_end(ctx, EXCP_TRAP);
6342 break;
6343 case OPC_TLT: /* rs < rs */
6344 case OPC_TLTI: /* r0 < 0 */
6345 case OPC_TLTU: /* rs < rs unsigned */
6346 case OPC_TLTIU: /* r0 < 0 unsigned */
6347 case OPC_TNE: /* rs != rs */
6348 case OPC_TNEI: /* r0 != 0 */
6349 /* Never trap: treat as NOP. */
6350 break;
6352 } else {
6353 TCGLabel *l1 = gen_new_label();
6355 switch (opc) {
6356 case OPC_TEQ:
6357 case OPC_TEQI:
6358 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6359 break;
6360 case OPC_TGE:
6361 case OPC_TGEI:
6362 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6363 break;
6364 case OPC_TGEU:
6365 case OPC_TGEIU:
6366 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6367 break;
6368 case OPC_TLT:
6369 case OPC_TLTI:
6370 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6371 break;
6372 case OPC_TLTU:
6373 case OPC_TLTIU:
6374 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6375 break;
6376 case OPC_TNE:
6377 case OPC_TNEI:
6378 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6379 break;
6381 generate_exception(ctx, EXCP_TRAP);
6382 gen_set_label(l1);
6384 tcg_temp_free(t0);
6385 tcg_temp_free(t1);
6388 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6390 if (unlikely(ctx->base.singlestep_enabled)) {
6391 return false;
6394 #ifndef CONFIG_USER_ONLY
6395 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6396 #else
6397 return true;
6398 #endif
6401 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6403 if (use_goto_tb(ctx, dest)) {
6404 tcg_gen_goto_tb(n);
6405 gen_save_pc(dest);
6406 tcg_gen_exit_tb(ctx->base.tb, n);
6407 } else {
6408 gen_save_pc(dest);
6409 if (ctx->base.singlestep_enabled) {
6410 save_cpu_state(ctx, 0);
6411 gen_helper_raise_exception_debug(cpu_env);
6413 tcg_gen_lookup_and_goto_ptr();
6417 /* Branches (before delay slot) */
6418 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6419 int insn_bytes,
6420 int rs, int rt, int32_t offset,
6421 int delayslot_size)
6423 target_ulong btgt = -1;
6424 int blink = 0;
6425 int bcond_compute = 0;
6426 TCGv t0 = tcg_temp_new();
6427 TCGv t1 = tcg_temp_new();
6429 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6430 #ifdef MIPS_DEBUG_DISAS
6431 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6432 TARGET_FMT_lx "\n", ctx->base.pc_next);
6433 #endif
6434 gen_reserved_instruction(ctx);
6435 goto out;
6438 /* Load needed operands */
6439 switch (opc) {
6440 case OPC_BEQ:
6441 case OPC_BEQL:
6442 case OPC_BNE:
6443 case OPC_BNEL:
6444 /* Compare two registers */
6445 if (rs != rt) {
6446 gen_load_gpr(t0, rs);
6447 gen_load_gpr(t1, rt);
6448 bcond_compute = 1;
6450 btgt = ctx->base.pc_next + insn_bytes + offset;
6451 break;
6452 case OPC_BGEZ:
6453 case OPC_BGEZAL:
6454 case OPC_BGEZALL:
6455 case OPC_BGEZL:
6456 case OPC_BGTZ:
6457 case OPC_BGTZL:
6458 case OPC_BLEZ:
6459 case OPC_BLEZL:
6460 case OPC_BLTZ:
6461 case OPC_BLTZAL:
6462 case OPC_BLTZALL:
6463 case OPC_BLTZL:
6464 /* Compare to zero */
6465 if (rs != 0) {
6466 gen_load_gpr(t0, rs);
6467 bcond_compute = 1;
6469 btgt = ctx->base.pc_next + insn_bytes + offset;
6470 break;
6471 case OPC_BPOSGE32:
6472 #if defined(TARGET_MIPS64)
6473 case OPC_BPOSGE64:
6474 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6475 #else
6476 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6477 #endif
6478 bcond_compute = 1;
6479 btgt = ctx->base.pc_next + insn_bytes + offset;
6480 break;
6481 case OPC_J:
6482 case OPC_JAL:
6483 case OPC_JALX:
6484 /* Jump to immediate */
6485 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6486 (uint32_t)offset;
6487 break;
6488 case OPC_JR:
6489 case OPC_JALR:
6490 /* Jump to register */
6491 if (offset != 0 && offset != 16) {
6493 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6494 * others are reserved.
6496 MIPS_INVAL("jump hint");
6497 gen_reserved_instruction(ctx);
6498 goto out;
6500 gen_load_gpr(btarget, rs);
6501 break;
6502 default:
6503 MIPS_INVAL("branch/jump");
6504 gen_reserved_instruction(ctx);
6505 goto out;
6507 if (bcond_compute == 0) {
6508 /* No condition to be computed */
6509 switch (opc) {
6510 case OPC_BEQ: /* rx == rx */
6511 case OPC_BEQL: /* rx == rx likely */
6512 case OPC_BGEZ: /* 0 >= 0 */
6513 case OPC_BGEZL: /* 0 >= 0 likely */
6514 case OPC_BLEZ: /* 0 <= 0 */
6515 case OPC_BLEZL: /* 0 <= 0 likely */
6516 /* Always take */
6517 ctx->hflags |= MIPS_HFLAG_B;
6518 break;
6519 case OPC_BGEZAL: /* 0 >= 0 */
6520 case OPC_BGEZALL: /* 0 >= 0 likely */
6521 /* Always take and link */
6522 blink = 31;
6523 ctx->hflags |= MIPS_HFLAG_B;
6524 break;
6525 case OPC_BNE: /* rx != rx */
6526 case OPC_BGTZ: /* 0 > 0 */
6527 case OPC_BLTZ: /* 0 < 0 */
6528 /* Treat as NOP. */
6529 goto out;
6530 case OPC_BLTZAL: /* 0 < 0 */
6532 * Handle as an unconditional branch to get correct delay
6533 * slot checking.
6535 blink = 31;
6536 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6537 ctx->hflags |= MIPS_HFLAG_B;
6538 break;
6539 case OPC_BLTZALL: /* 0 < 0 likely */
6540 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6541 /* Skip the instruction in the delay slot */
6542 ctx->base.pc_next += 4;
6543 goto out;
6544 case OPC_BNEL: /* rx != rx likely */
6545 case OPC_BGTZL: /* 0 > 0 likely */
6546 case OPC_BLTZL: /* 0 < 0 likely */
6547 /* Skip the instruction in the delay slot */
6548 ctx->base.pc_next += 4;
6549 goto out;
6550 case OPC_J:
6551 ctx->hflags |= MIPS_HFLAG_B;
6552 break;
6553 case OPC_JALX:
6554 ctx->hflags |= MIPS_HFLAG_BX;
6555 /* Fallthrough */
6556 case OPC_JAL:
6557 blink = 31;
6558 ctx->hflags |= MIPS_HFLAG_B;
6559 break;
6560 case OPC_JR:
6561 ctx->hflags |= MIPS_HFLAG_BR;
6562 break;
6563 case OPC_JALR:
6564 blink = rt;
6565 ctx->hflags |= MIPS_HFLAG_BR;
6566 break;
6567 default:
6568 MIPS_INVAL("branch/jump");
6569 gen_reserved_instruction(ctx);
6570 goto out;
6572 } else {
6573 switch (opc) {
6574 case OPC_BEQ:
6575 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6576 goto not_likely;
6577 case OPC_BEQL:
6578 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6579 goto likely;
6580 case OPC_BNE:
6581 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6582 goto not_likely;
6583 case OPC_BNEL:
6584 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6585 goto likely;
6586 case OPC_BGEZ:
6587 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6588 goto not_likely;
6589 case OPC_BGEZL:
6590 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6591 goto likely;
6592 case OPC_BGEZAL:
6593 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6594 blink = 31;
6595 goto not_likely;
6596 case OPC_BGEZALL:
6597 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6598 blink = 31;
6599 goto likely;
6600 case OPC_BGTZ:
6601 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6602 goto not_likely;
6603 case OPC_BGTZL:
6604 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6605 goto likely;
6606 case OPC_BLEZ:
6607 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6608 goto not_likely;
6609 case OPC_BLEZL:
6610 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6611 goto likely;
6612 case OPC_BLTZ:
6613 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6614 goto not_likely;
6615 case OPC_BLTZL:
6616 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6617 goto likely;
6618 case OPC_BPOSGE32:
6619 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6620 goto not_likely;
6621 #if defined(TARGET_MIPS64)
6622 case OPC_BPOSGE64:
6623 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6624 goto not_likely;
6625 #endif
6626 case OPC_BLTZAL:
6627 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6628 blink = 31;
6629 not_likely:
6630 ctx->hflags |= MIPS_HFLAG_BC;
6631 break;
6632 case OPC_BLTZALL:
6633 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6634 blink = 31;
6635 likely:
6636 ctx->hflags |= MIPS_HFLAG_BL;
6637 break;
6638 default:
6639 MIPS_INVAL("conditional branch/jump");
6640 gen_reserved_instruction(ctx);
6641 goto out;
6645 ctx->btarget = btgt;
6647 switch (delayslot_size) {
6648 case 2:
6649 ctx->hflags |= MIPS_HFLAG_BDS16;
6650 break;
6651 case 4:
6652 ctx->hflags |= MIPS_HFLAG_BDS32;
6653 break;
6656 if (blink > 0) {
6657 int post_delay = insn_bytes + delayslot_size;
6658 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6660 tcg_gen_movi_tl(cpu_gpr[blink],
6661 ctx->base.pc_next + post_delay + lowbit);
6664 out:
6665 if (insn_bytes == 2) {
6666 ctx->hflags |= MIPS_HFLAG_B16;
6668 tcg_temp_free(t0);
6669 tcg_temp_free(t1);
6673 /* nanoMIPS Branches */
6674 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6675 int insn_bytes,
6676 int rs, int rt, int32_t offset)
6678 target_ulong btgt = -1;
6679 int bcond_compute = 0;
6680 TCGv t0 = tcg_temp_new();
6681 TCGv t1 = tcg_temp_new();
6683 /* Load needed operands */
6684 switch (opc) {
6685 case OPC_BEQ:
6686 case OPC_BNE:
6687 /* Compare two registers */
6688 if (rs != rt) {
6689 gen_load_gpr(t0, rs);
6690 gen_load_gpr(t1, rt);
6691 bcond_compute = 1;
6693 btgt = ctx->base.pc_next + insn_bytes + offset;
6694 break;
6695 case OPC_BGEZAL:
6696 /* Compare to zero */
6697 if (rs != 0) {
6698 gen_load_gpr(t0, rs);
6699 bcond_compute = 1;
6701 btgt = ctx->base.pc_next + insn_bytes + offset;
6702 break;
6703 case OPC_BPOSGE32:
6704 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6705 bcond_compute = 1;
6706 btgt = ctx->base.pc_next + insn_bytes + offset;
6707 break;
6708 case OPC_JR:
6709 case OPC_JALR:
6710 /* Jump to register */
6711 if (offset != 0 && offset != 16) {
6713 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6714 * others are reserved.
6716 MIPS_INVAL("jump hint");
6717 gen_reserved_instruction(ctx);
6718 goto out;
6720 gen_load_gpr(btarget, rs);
6721 break;
6722 default:
6723 MIPS_INVAL("branch/jump");
6724 gen_reserved_instruction(ctx);
6725 goto out;
6727 if (bcond_compute == 0) {
6728 /* No condition to be computed */
6729 switch (opc) {
6730 case OPC_BEQ: /* rx == rx */
6731 /* Always take */
6732 ctx->hflags |= MIPS_HFLAG_B;
6733 break;
6734 case OPC_BGEZAL: /* 0 >= 0 */
6735 /* Always take and link */
6736 tcg_gen_movi_tl(cpu_gpr[31],
6737 ctx->base.pc_next + insn_bytes);
6738 ctx->hflags |= MIPS_HFLAG_B;
6739 break;
6740 case OPC_BNE: /* rx != rx */
6741 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6742 /* Skip the instruction in the delay slot */
6743 ctx->base.pc_next += 4;
6744 goto out;
6745 case OPC_JR:
6746 ctx->hflags |= MIPS_HFLAG_BR;
6747 break;
6748 case OPC_JALR:
6749 if (rt > 0) {
6750 tcg_gen_movi_tl(cpu_gpr[rt],
6751 ctx->base.pc_next + insn_bytes);
6753 ctx->hflags |= MIPS_HFLAG_BR;
6754 break;
6755 default:
6756 MIPS_INVAL("branch/jump");
6757 gen_reserved_instruction(ctx);
6758 goto out;
6760 } else {
6761 switch (opc) {
6762 case OPC_BEQ:
6763 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6764 goto not_likely;
6765 case OPC_BNE:
6766 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6767 goto not_likely;
6768 case OPC_BGEZAL:
6769 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6770 tcg_gen_movi_tl(cpu_gpr[31],
6771 ctx->base.pc_next + insn_bytes);
6772 goto not_likely;
6773 case OPC_BPOSGE32:
6774 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6775 not_likely:
6776 ctx->hflags |= MIPS_HFLAG_BC;
6777 break;
6778 default:
6779 MIPS_INVAL("conditional branch/jump");
6780 gen_reserved_instruction(ctx);
6781 goto out;
6785 ctx->btarget = btgt;
6787 out:
6788 if (insn_bytes == 2) {
6789 ctx->hflags |= MIPS_HFLAG_B16;
6791 tcg_temp_free(t0);
6792 tcg_temp_free(t1);
6796 /* special3 bitfield operations */
6797 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6798 int rs, int lsb, int msb)
6800 TCGv t0 = tcg_temp_new();
6801 TCGv t1 = tcg_temp_new();
6803 gen_load_gpr(t1, rs);
6804 switch (opc) {
6805 case OPC_EXT:
6806 if (lsb + msb > 31) {
6807 goto fail;
6809 if (msb != 31) {
6810 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6811 } else {
6813 * The two checks together imply that lsb == 0,
6814 * so this is a simple sign-extension.
6816 tcg_gen_ext32s_tl(t0, t1);
6818 break;
6819 #if defined(TARGET_MIPS64)
6820 case OPC_DEXTU:
6821 lsb += 32;
6822 goto do_dext;
6823 case OPC_DEXTM:
6824 msb += 32;
6825 goto do_dext;
6826 case OPC_DEXT:
6827 do_dext:
6828 if (lsb + msb > 63) {
6829 goto fail;
6831 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6832 break;
6833 #endif
6834 case OPC_INS:
6835 if (lsb > msb) {
6836 goto fail;
6838 gen_load_gpr(t0, rt);
6839 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6840 tcg_gen_ext32s_tl(t0, t0);
6841 break;
6842 #if defined(TARGET_MIPS64)
6843 case OPC_DINSU:
6844 lsb += 32;
6845 /* FALLTHRU */
6846 case OPC_DINSM:
6847 msb += 32;
6848 /* FALLTHRU */
6849 case OPC_DINS:
6850 if (lsb > msb) {
6851 goto fail;
6853 gen_load_gpr(t0, rt);
6854 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6855 break;
6856 #endif
6857 default:
6858 fail:
6859 MIPS_INVAL("bitops");
6860 gen_reserved_instruction(ctx);
6861 tcg_temp_free(t0);
6862 tcg_temp_free(t1);
6863 return;
6865 gen_store_gpr(t0, rt);
6866 tcg_temp_free(t0);
6867 tcg_temp_free(t1);
6870 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6872 TCGv t0;
6874 if (rd == 0) {
6875 /* If no destination, treat it as a NOP. */
6876 return;
6879 t0 = tcg_temp_new();
6880 gen_load_gpr(t0, rt);
6881 switch (op2) {
6882 case OPC_WSBH:
6884 TCGv t1 = tcg_temp_new();
6885 TCGv t2 = tcg_const_tl(0x00FF00FF);
6887 tcg_gen_shri_tl(t1, t0, 8);
6888 tcg_gen_and_tl(t1, t1, t2);
6889 tcg_gen_and_tl(t0, t0, t2);
6890 tcg_gen_shli_tl(t0, t0, 8);
6891 tcg_gen_or_tl(t0, t0, t1);
6892 tcg_temp_free(t2);
6893 tcg_temp_free(t1);
6894 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6896 break;
6897 case OPC_SEB:
6898 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6899 break;
6900 case OPC_SEH:
6901 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6902 break;
6903 #if defined(TARGET_MIPS64)
6904 case OPC_DSBH:
6906 TCGv t1 = tcg_temp_new();
6907 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6909 tcg_gen_shri_tl(t1, t0, 8);
6910 tcg_gen_and_tl(t1, t1, t2);
6911 tcg_gen_and_tl(t0, t0, t2);
6912 tcg_gen_shli_tl(t0, t0, 8);
6913 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6914 tcg_temp_free(t2);
6915 tcg_temp_free(t1);
6917 break;
6918 case OPC_DSHD:
6920 TCGv t1 = tcg_temp_new();
6921 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6923 tcg_gen_shri_tl(t1, t0, 16);
6924 tcg_gen_and_tl(t1, t1, t2);
6925 tcg_gen_and_tl(t0, t0, t2);
6926 tcg_gen_shli_tl(t0, t0, 16);
6927 tcg_gen_or_tl(t0, t0, t1);
6928 tcg_gen_shri_tl(t1, t0, 32);
6929 tcg_gen_shli_tl(t0, t0, 32);
6930 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6931 tcg_temp_free(t2);
6932 tcg_temp_free(t1);
6934 break;
6935 #endif
6936 default:
6937 MIPS_INVAL("bsfhl");
6938 gen_reserved_instruction(ctx);
6939 tcg_temp_free(t0);
6940 return;
6942 tcg_temp_free(t0);
6945 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6946 int imm2)
6948 TCGv t0;
6949 TCGv t1;
6950 if (rd == 0) {
6951 /* Treat as NOP. */
6952 return;
6954 t0 = tcg_temp_new();
6955 t1 = tcg_temp_new();
6956 gen_load_gpr(t0, rs);
6957 gen_load_gpr(t1, rt);
6958 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6959 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6960 if (opc == OPC_LSA) {
6961 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6964 tcg_temp_free(t1);
6965 tcg_temp_free(t0);
6967 return;
6970 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6971 int rt, int bits)
6973 TCGv t0;
6974 if (rd == 0) {
6975 /* Treat as NOP. */
6976 return;
6978 t0 = tcg_temp_new();
6979 if (bits == 0 || bits == wordsz) {
6980 if (bits == 0) {
6981 gen_load_gpr(t0, rt);
6982 } else {
6983 gen_load_gpr(t0, rs);
6985 switch (wordsz) {
6986 case 32:
6987 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6988 break;
6989 #if defined(TARGET_MIPS64)
6990 case 64:
6991 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6992 break;
6993 #endif
6995 } else {
6996 TCGv t1 = tcg_temp_new();
6997 gen_load_gpr(t0, rt);
6998 gen_load_gpr(t1, rs);
6999 switch (wordsz) {
7000 case 32:
7002 TCGv_i64 t2 = tcg_temp_new_i64();
7003 tcg_gen_concat_tl_i64(t2, t1, t0);
7004 tcg_gen_shri_i64(t2, t2, 32 - bits);
7005 gen_move_low32(cpu_gpr[rd], t2);
7006 tcg_temp_free_i64(t2);
7008 break;
7009 #if defined(TARGET_MIPS64)
7010 case 64:
7011 tcg_gen_shli_tl(t0, t0, bits);
7012 tcg_gen_shri_tl(t1, t1, 64 - bits);
7013 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
7014 break;
7015 #endif
7017 tcg_temp_free(t1);
7020 tcg_temp_free(t0);
7023 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7024 int bp)
7026 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
7029 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7030 int shift)
7032 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
7035 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
7037 TCGv t0;
7038 if (rd == 0) {
7039 /* Treat as NOP. */
7040 return;
7042 t0 = tcg_temp_new();
7043 gen_load_gpr(t0, rt);
7044 switch (opc) {
7045 case OPC_BITSWAP:
7046 gen_helper_bitswap(cpu_gpr[rd], t0);
7047 break;
7048 #if defined(TARGET_MIPS64)
7049 case OPC_DBITSWAP:
7050 gen_helper_dbitswap(cpu_gpr[rd], t0);
7051 break;
7052 #endif
7054 tcg_temp_free(t0);
7057 #ifndef CONFIG_USER_ONLY
7058 /* CP0 (MMU and control) */
7059 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
7061 TCGv_i64 t0 = tcg_temp_new_i64();
7062 TCGv_i64 t1 = tcg_temp_new_i64();
7064 tcg_gen_ext_tl_i64(t0, arg);
7065 tcg_gen_ld_i64(t1, cpu_env, off);
7066 #if defined(TARGET_MIPS64)
7067 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
7068 #else
7069 tcg_gen_concat32_i64(t1, t1, t0);
7070 #endif
7071 tcg_gen_st_i64(t1, cpu_env, off);
7072 tcg_temp_free_i64(t1);
7073 tcg_temp_free_i64(t0);
7076 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
7078 TCGv_i64 t0 = tcg_temp_new_i64();
7079 TCGv_i64 t1 = tcg_temp_new_i64();
7081 tcg_gen_ext_tl_i64(t0, arg);
7082 tcg_gen_ld_i64(t1, cpu_env, off);
7083 tcg_gen_concat32_i64(t1, t1, t0);
7084 tcg_gen_st_i64(t1, cpu_env, off);
7085 tcg_temp_free_i64(t1);
7086 tcg_temp_free_i64(t0);
7089 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
7091 TCGv_i64 t0 = tcg_temp_new_i64();
7093 tcg_gen_ld_i64(t0, cpu_env, off);
7094 #if defined(TARGET_MIPS64)
7095 tcg_gen_shri_i64(t0, t0, 30);
7096 #else
7097 tcg_gen_shri_i64(t0, t0, 32);
7098 #endif
7099 gen_move_low32(arg, t0);
7100 tcg_temp_free_i64(t0);
7103 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
7105 TCGv_i64 t0 = tcg_temp_new_i64();
7107 tcg_gen_ld_i64(t0, cpu_env, off);
7108 tcg_gen_shri_i64(t0, t0, 32 + shift);
7109 gen_move_low32(arg, t0);
7110 tcg_temp_free_i64(t0);
7113 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
7115 TCGv_i32 t0 = tcg_temp_new_i32();
7117 tcg_gen_ld_i32(t0, cpu_env, off);
7118 tcg_gen_ext_i32_tl(arg, t0);
7119 tcg_temp_free_i32(t0);
7122 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
7124 tcg_gen_ld_tl(arg, cpu_env, off);
7125 tcg_gen_ext32s_tl(arg, arg);
7128 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
7130 TCGv_i32 t0 = tcg_temp_new_i32();
7132 tcg_gen_trunc_tl_i32(t0, arg);
7133 tcg_gen_st_i32(t0, cpu_env, off);
7134 tcg_temp_free_i32(t0);
7137 #define CP0_CHECK(c) \
7138 do { \
7139 if (!(c)) { \
7140 goto cp0_unimplemented; \
7142 } while (0)
7144 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7146 const char *register_name = "invalid";
7148 switch (reg) {
7149 case CP0_REGISTER_02:
7150 switch (sel) {
7151 case 0:
7152 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7153 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7154 register_name = "EntryLo0";
7155 break;
7156 default:
7157 goto cp0_unimplemented;
7159 break;
7160 case CP0_REGISTER_03:
7161 switch (sel) {
7162 case CP0_REG03__ENTRYLO1:
7163 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7164 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7165 register_name = "EntryLo1";
7166 break;
7167 default:
7168 goto cp0_unimplemented;
7170 break;
7171 case CP0_REGISTER_09:
7172 switch (sel) {
7173 case CP0_REG09__SAAR:
7174 CP0_CHECK(ctx->saar);
7175 gen_helper_mfhc0_saar(arg, cpu_env);
7176 register_name = "SAAR";
7177 break;
7178 default:
7179 goto cp0_unimplemented;
7181 break;
7182 case CP0_REGISTER_17:
7183 switch (sel) {
7184 case CP0_REG17__LLADDR:
7185 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
7186 ctx->CP0_LLAddr_shift);
7187 register_name = "LLAddr";
7188 break;
7189 case CP0_REG17__MAAR:
7190 CP0_CHECK(ctx->mrp);
7191 gen_helper_mfhc0_maar(arg, cpu_env);
7192 register_name = "MAAR";
7193 break;
7194 default:
7195 goto cp0_unimplemented;
7197 break;
7198 case CP0_REGISTER_19:
7199 switch (sel) {
7200 case CP0_REG19__WATCHHI0:
7201 case CP0_REG19__WATCHHI1:
7202 case CP0_REG19__WATCHHI2:
7203 case CP0_REG19__WATCHHI3:
7204 case CP0_REG19__WATCHHI4:
7205 case CP0_REG19__WATCHHI5:
7206 case CP0_REG19__WATCHHI6:
7207 case CP0_REG19__WATCHHI7:
7208 /* upper 32 bits are only available when Config5MI != 0 */
7209 CP0_CHECK(ctx->mi);
7210 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
7211 register_name = "WatchHi";
7212 break;
7213 default:
7214 goto cp0_unimplemented;
7216 break;
7217 case CP0_REGISTER_28:
7218 switch (sel) {
7219 case 0:
7220 case 2:
7221 case 4:
7222 case 6:
7223 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
7224 register_name = "TagLo";
7225 break;
7226 default:
7227 goto cp0_unimplemented;
7229 break;
7230 default:
7231 goto cp0_unimplemented;
7233 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
7234 return;
7236 cp0_unimplemented:
7237 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
7238 register_name, reg, sel);
7239 tcg_gen_movi_tl(arg, 0);
7242 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7244 const char *register_name = "invalid";
7245 uint64_t mask = ctx->PAMask >> 36;
7247 switch (reg) {
7248 case CP0_REGISTER_02:
7249 switch (sel) {
7250 case 0:
7251 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7252 tcg_gen_andi_tl(arg, arg, mask);
7253 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7254 register_name = "EntryLo0";
7255 break;
7256 default:
7257 goto cp0_unimplemented;
7259 break;
7260 case CP0_REGISTER_03:
7261 switch (sel) {
7262 case CP0_REG03__ENTRYLO1:
7263 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7264 tcg_gen_andi_tl(arg, arg, mask);
7265 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7266 register_name = "EntryLo1";
7267 break;
7268 default:
7269 goto cp0_unimplemented;
7271 break;
7272 case CP0_REGISTER_09:
7273 switch (sel) {
7274 case CP0_REG09__SAAR:
7275 CP0_CHECK(ctx->saar);
7276 gen_helper_mthc0_saar(cpu_env, arg);
7277 register_name = "SAAR";
7278 break;
7279 default:
7280 goto cp0_unimplemented;
7282 break;
7283 case CP0_REGISTER_17:
7284 switch (sel) {
7285 case CP0_REG17__LLADDR:
7287 * LLAddr is read-only (the only exception is bit 0 if LLB is
7288 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
7289 * relevant for modern MIPS cores supporting MTHC0, therefore
7290 * treating MTHC0 to LLAddr as NOP.
7292 register_name = "LLAddr";
7293 break;
7294 case CP0_REG17__MAAR:
7295 CP0_CHECK(ctx->mrp);
7296 gen_helper_mthc0_maar(cpu_env, arg);
7297 register_name = "MAAR";
7298 break;
7299 default:
7300 goto cp0_unimplemented;
7302 break;
7303 case CP0_REGISTER_19:
7304 switch (sel) {
7305 case CP0_REG19__WATCHHI0:
7306 case CP0_REG19__WATCHHI1:
7307 case CP0_REG19__WATCHHI2:
7308 case CP0_REG19__WATCHHI3:
7309 case CP0_REG19__WATCHHI4:
7310 case CP0_REG19__WATCHHI5:
7311 case CP0_REG19__WATCHHI6:
7312 case CP0_REG19__WATCHHI7:
7313 /* upper 32 bits are only available when Config5MI != 0 */
7314 CP0_CHECK(ctx->mi);
7315 gen_helper_0e1i(mthc0_watchhi, arg, sel);
7316 register_name = "WatchHi";
7317 break;
7318 default:
7319 goto cp0_unimplemented;
7321 break;
7322 case CP0_REGISTER_28:
7323 switch (sel) {
7324 case 0:
7325 case 2:
7326 case 4:
7327 case 6:
7328 tcg_gen_andi_tl(arg, arg, mask);
7329 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
7330 register_name = "TagLo";
7331 break;
7332 default:
7333 goto cp0_unimplemented;
7335 break;
7336 default:
7337 goto cp0_unimplemented;
7339 trace_mips_translate_c0("mthc0", register_name, reg, sel);
7341 cp0_unimplemented:
7342 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
7343 register_name, reg, sel);
7346 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
7348 if (ctx->insn_flags & ISA_MIPS_R6) {
7349 tcg_gen_movi_tl(arg, 0);
7350 } else {
7351 tcg_gen_movi_tl(arg, ~0);
7355 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7357 const char *register_name = "invalid";
7359 if (sel != 0) {
7360 check_insn(ctx, ISA_MIPS_R1);
7363 switch (reg) {
7364 case CP0_REGISTER_00:
7365 switch (sel) {
7366 case CP0_REG00__INDEX:
7367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7368 register_name = "Index";
7369 break;
7370 case CP0_REG00__MVPCONTROL:
7371 CP0_CHECK(ctx->insn_flags & ASE_MT);
7372 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7373 register_name = "MVPControl";
7374 break;
7375 case CP0_REG00__MVPCONF0:
7376 CP0_CHECK(ctx->insn_flags & ASE_MT);
7377 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7378 register_name = "MVPConf0";
7379 break;
7380 case CP0_REG00__MVPCONF1:
7381 CP0_CHECK(ctx->insn_flags & ASE_MT);
7382 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7383 register_name = "MVPConf1";
7384 break;
7385 case CP0_REG00__VPCONTROL:
7386 CP0_CHECK(ctx->vp);
7387 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7388 register_name = "VPControl";
7389 break;
7390 default:
7391 goto cp0_unimplemented;
7393 break;
7394 case CP0_REGISTER_01:
7395 switch (sel) {
7396 case CP0_REG01__RANDOM:
7397 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7398 gen_helper_mfc0_random(arg, cpu_env);
7399 register_name = "Random";
7400 break;
7401 case CP0_REG01__VPECONTROL:
7402 CP0_CHECK(ctx->insn_flags & ASE_MT);
7403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7404 register_name = "VPEControl";
7405 break;
7406 case CP0_REG01__VPECONF0:
7407 CP0_CHECK(ctx->insn_flags & ASE_MT);
7408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7409 register_name = "VPEConf0";
7410 break;
7411 case CP0_REG01__VPECONF1:
7412 CP0_CHECK(ctx->insn_flags & ASE_MT);
7413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7414 register_name = "VPEConf1";
7415 break;
7416 case CP0_REG01__YQMASK:
7417 CP0_CHECK(ctx->insn_flags & ASE_MT);
7418 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7419 register_name = "YQMask";
7420 break;
7421 case CP0_REG01__VPESCHEDULE:
7422 CP0_CHECK(ctx->insn_flags & ASE_MT);
7423 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7424 register_name = "VPESchedule";
7425 break;
7426 case CP0_REG01__VPESCHEFBACK:
7427 CP0_CHECK(ctx->insn_flags & ASE_MT);
7428 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7429 register_name = "VPEScheFBack";
7430 break;
7431 case CP0_REG01__VPEOPT:
7432 CP0_CHECK(ctx->insn_flags & ASE_MT);
7433 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7434 register_name = "VPEOpt";
7435 break;
7436 default:
7437 goto cp0_unimplemented;
7439 break;
7440 case CP0_REGISTER_02:
7441 switch (sel) {
7442 case CP0_REG02__ENTRYLO0:
7444 TCGv_i64 tmp = tcg_temp_new_i64();
7445 tcg_gen_ld_i64(tmp, cpu_env,
7446 offsetof(CPUMIPSState, CP0_EntryLo0));
7447 #if defined(TARGET_MIPS64)
7448 if (ctx->rxi) {
7449 /* Move RI/XI fields to bits 31:30 */
7450 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7451 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7453 #endif
7454 gen_move_low32(arg, tmp);
7455 tcg_temp_free_i64(tmp);
7457 register_name = "EntryLo0";
7458 break;
7459 case CP0_REG02__TCSTATUS:
7460 CP0_CHECK(ctx->insn_flags & ASE_MT);
7461 gen_helper_mfc0_tcstatus(arg, cpu_env);
7462 register_name = "TCStatus";
7463 break;
7464 case CP0_REG02__TCBIND:
7465 CP0_CHECK(ctx->insn_flags & ASE_MT);
7466 gen_helper_mfc0_tcbind(arg, cpu_env);
7467 register_name = "TCBind";
7468 break;
7469 case CP0_REG02__TCRESTART:
7470 CP0_CHECK(ctx->insn_flags & ASE_MT);
7471 gen_helper_mfc0_tcrestart(arg, cpu_env);
7472 register_name = "TCRestart";
7473 break;
7474 case CP0_REG02__TCHALT:
7475 CP0_CHECK(ctx->insn_flags & ASE_MT);
7476 gen_helper_mfc0_tchalt(arg, cpu_env);
7477 register_name = "TCHalt";
7478 break;
7479 case CP0_REG02__TCCONTEXT:
7480 CP0_CHECK(ctx->insn_flags & ASE_MT);
7481 gen_helper_mfc0_tccontext(arg, cpu_env);
7482 register_name = "TCContext";
7483 break;
7484 case CP0_REG02__TCSCHEDULE:
7485 CP0_CHECK(ctx->insn_flags & ASE_MT);
7486 gen_helper_mfc0_tcschedule(arg, cpu_env);
7487 register_name = "TCSchedule";
7488 break;
7489 case CP0_REG02__TCSCHEFBACK:
7490 CP0_CHECK(ctx->insn_flags & ASE_MT);
7491 gen_helper_mfc0_tcschefback(arg, cpu_env);
7492 register_name = "TCScheFBack";
7493 break;
7494 default:
7495 goto cp0_unimplemented;
7497 break;
7498 case CP0_REGISTER_03:
7499 switch (sel) {
7500 case CP0_REG03__ENTRYLO1:
7502 TCGv_i64 tmp = tcg_temp_new_i64();
7503 tcg_gen_ld_i64(tmp, cpu_env,
7504 offsetof(CPUMIPSState, CP0_EntryLo1));
7505 #if defined(TARGET_MIPS64)
7506 if (ctx->rxi) {
7507 /* Move RI/XI fields to bits 31:30 */
7508 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7509 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7511 #endif
7512 gen_move_low32(arg, tmp);
7513 tcg_temp_free_i64(tmp);
7515 register_name = "EntryLo1";
7516 break;
7517 case CP0_REG03__GLOBALNUM:
7518 CP0_CHECK(ctx->vp);
7519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7520 register_name = "GlobalNumber";
7521 break;
7522 default:
7523 goto cp0_unimplemented;
7525 break;
7526 case CP0_REGISTER_04:
7527 switch (sel) {
7528 case CP0_REG04__CONTEXT:
7529 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7530 tcg_gen_ext32s_tl(arg, arg);
7531 register_name = "Context";
7532 break;
7533 case CP0_REG04__CONTEXTCONFIG:
7534 /* SmartMIPS ASE */
7535 /* gen_helper_mfc0_contextconfig(arg); */
7536 register_name = "ContextConfig";
7537 goto cp0_unimplemented;
7538 case CP0_REG04__USERLOCAL:
7539 CP0_CHECK(ctx->ulri);
7540 tcg_gen_ld_tl(arg, cpu_env,
7541 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7542 tcg_gen_ext32s_tl(arg, arg);
7543 register_name = "UserLocal";
7544 break;
7545 case CP0_REG04__MMID:
7546 CP0_CHECK(ctx->mi);
7547 gen_helper_mtc0_memorymapid(cpu_env, arg);
7548 register_name = "MMID";
7549 break;
7550 default:
7551 goto cp0_unimplemented;
7553 break;
7554 case CP0_REGISTER_05:
7555 switch (sel) {
7556 case CP0_REG05__PAGEMASK:
7557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7558 register_name = "PageMask";
7559 break;
7560 case CP0_REG05__PAGEGRAIN:
7561 check_insn(ctx, ISA_MIPS_R2);
7562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7563 register_name = "PageGrain";
7564 break;
7565 case CP0_REG05__SEGCTL0:
7566 CP0_CHECK(ctx->sc);
7567 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7568 tcg_gen_ext32s_tl(arg, arg);
7569 register_name = "SegCtl0";
7570 break;
7571 case CP0_REG05__SEGCTL1:
7572 CP0_CHECK(ctx->sc);
7573 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7574 tcg_gen_ext32s_tl(arg, arg);
7575 register_name = "SegCtl1";
7576 break;
7577 case CP0_REG05__SEGCTL2:
7578 CP0_CHECK(ctx->sc);
7579 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7580 tcg_gen_ext32s_tl(arg, arg);
7581 register_name = "SegCtl2";
7582 break;
7583 case CP0_REG05__PWBASE:
7584 check_pw(ctx);
7585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7586 register_name = "PWBase";
7587 break;
7588 case CP0_REG05__PWFIELD:
7589 check_pw(ctx);
7590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7591 register_name = "PWField";
7592 break;
7593 case CP0_REG05__PWSIZE:
7594 check_pw(ctx);
7595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7596 register_name = "PWSize";
7597 break;
7598 default:
7599 goto cp0_unimplemented;
7601 break;
7602 case CP0_REGISTER_06:
7603 switch (sel) {
7604 case CP0_REG06__WIRED:
7605 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7606 register_name = "Wired";
7607 break;
7608 case CP0_REG06__SRSCONF0:
7609 check_insn(ctx, ISA_MIPS_R2);
7610 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7611 register_name = "SRSConf0";
7612 break;
7613 case CP0_REG06__SRSCONF1:
7614 check_insn(ctx, ISA_MIPS_R2);
7615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7616 register_name = "SRSConf1";
7617 break;
7618 case CP0_REG06__SRSCONF2:
7619 check_insn(ctx, ISA_MIPS_R2);
7620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7621 register_name = "SRSConf2";
7622 break;
7623 case CP0_REG06__SRSCONF3:
7624 check_insn(ctx, ISA_MIPS_R2);
7625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7626 register_name = "SRSConf3";
7627 break;
7628 case CP0_REG06__SRSCONF4:
7629 check_insn(ctx, ISA_MIPS_R2);
7630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7631 register_name = "SRSConf4";
7632 break;
7633 case CP0_REG06__PWCTL:
7634 check_pw(ctx);
7635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7636 register_name = "PWCtl";
7637 break;
7638 default:
7639 goto cp0_unimplemented;
7641 break;
7642 case CP0_REGISTER_07:
7643 switch (sel) {
7644 case CP0_REG07__HWRENA:
7645 check_insn(ctx, ISA_MIPS_R2);
7646 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7647 register_name = "HWREna";
7648 break;
7649 default:
7650 goto cp0_unimplemented;
7652 break;
7653 case CP0_REGISTER_08:
7654 switch (sel) {
7655 case CP0_REG08__BADVADDR:
7656 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7657 tcg_gen_ext32s_tl(arg, arg);
7658 register_name = "BadVAddr";
7659 break;
7660 case CP0_REG08__BADINSTR:
7661 CP0_CHECK(ctx->bi);
7662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7663 register_name = "BadInstr";
7664 break;
7665 case CP0_REG08__BADINSTRP:
7666 CP0_CHECK(ctx->bp);
7667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7668 register_name = "BadInstrP";
7669 break;
7670 case CP0_REG08__BADINSTRX:
7671 CP0_CHECK(ctx->bi);
7672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7673 tcg_gen_andi_tl(arg, arg, ~0xffff);
7674 register_name = "BadInstrX";
7675 break;
7676 default:
7677 goto cp0_unimplemented;
7679 break;
7680 case CP0_REGISTER_09:
7681 switch (sel) {
7682 case CP0_REG09__COUNT:
7683 /* Mark as an IO operation because we read the time. */
7684 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7685 gen_io_start();
7687 gen_helper_mfc0_count(arg, cpu_env);
7689 * Break the TB to be able to take timer interrupts immediately
7690 * after reading count. DISAS_STOP isn't sufficient, we need to
7691 * ensure we break completely out of translated code.
7693 gen_save_pc(ctx->base.pc_next + 4);
7694 ctx->base.is_jmp = DISAS_EXIT;
7695 register_name = "Count";
7696 break;
7697 case CP0_REG09__SAARI:
7698 CP0_CHECK(ctx->saar);
7699 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7700 register_name = "SAARI";
7701 break;
7702 case CP0_REG09__SAAR:
7703 CP0_CHECK(ctx->saar);
7704 gen_helper_mfc0_saar(arg, cpu_env);
7705 register_name = "SAAR";
7706 break;
7707 default:
7708 goto cp0_unimplemented;
7710 break;
7711 case CP0_REGISTER_10:
7712 switch (sel) {
7713 case CP0_REG10__ENTRYHI:
7714 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7715 tcg_gen_ext32s_tl(arg, arg);
7716 register_name = "EntryHi";
7717 break;
7718 default:
7719 goto cp0_unimplemented;
7721 break;
7722 case CP0_REGISTER_11:
7723 switch (sel) {
7724 case CP0_REG11__COMPARE:
7725 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7726 register_name = "Compare";
7727 break;
7728 /* 6,7 are implementation dependent */
7729 default:
7730 goto cp0_unimplemented;
7732 break;
7733 case CP0_REGISTER_12:
7734 switch (sel) {
7735 case CP0_REG12__STATUS:
7736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7737 register_name = "Status";
7738 break;
7739 case CP0_REG12__INTCTL:
7740 check_insn(ctx, ISA_MIPS_R2);
7741 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7742 register_name = "IntCtl";
7743 break;
7744 case CP0_REG12__SRSCTL:
7745 check_insn(ctx, ISA_MIPS_R2);
7746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7747 register_name = "SRSCtl";
7748 break;
7749 case CP0_REG12__SRSMAP:
7750 check_insn(ctx, ISA_MIPS_R2);
7751 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7752 register_name = "SRSMap";
7753 break;
7754 default:
7755 goto cp0_unimplemented;
7757 break;
7758 case CP0_REGISTER_13:
7759 switch (sel) {
7760 case CP0_REG13__CAUSE:
7761 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7762 register_name = "Cause";
7763 break;
7764 default:
7765 goto cp0_unimplemented;
7767 break;
7768 case CP0_REGISTER_14:
7769 switch (sel) {
7770 case CP0_REG14__EPC:
7771 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7772 tcg_gen_ext32s_tl(arg, arg);
7773 register_name = "EPC";
7774 break;
7775 default:
7776 goto cp0_unimplemented;
7778 break;
7779 case CP0_REGISTER_15:
7780 switch (sel) {
7781 case CP0_REG15__PRID:
7782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7783 register_name = "PRid";
7784 break;
7785 case CP0_REG15__EBASE:
7786 check_insn(ctx, ISA_MIPS_R2);
7787 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7788 tcg_gen_ext32s_tl(arg, arg);
7789 register_name = "EBase";
7790 break;
7791 case CP0_REG15__CMGCRBASE:
7792 check_insn(ctx, ISA_MIPS_R2);
7793 CP0_CHECK(ctx->cmgcr);
7794 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7795 tcg_gen_ext32s_tl(arg, arg);
7796 register_name = "CMGCRBase";
7797 break;
7798 default:
7799 goto cp0_unimplemented;
7801 break;
7802 case CP0_REGISTER_16:
7803 switch (sel) {
7804 case CP0_REG16__CONFIG:
7805 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7806 register_name = "Config";
7807 break;
7808 case CP0_REG16__CONFIG1:
7809 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7810 register_name = "Config1";
7811 break;
7812 case CP0_REG16__CONFIG2:
7813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7814 register_name = "Config2";
7815 break;
7816 case CP0_REG16__CONFIG3:
7817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7818 register_name = "Config3";
7819 break;
7820 case CP0_REG16__CONFIG4:
7821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7822 register_name = "Config4";
7823 break;
7824 case CP0_REG16__CONFIG5:
7825 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7826 register_name = "Config5";
7827 break;
7828 /* 6,7 are implementation dependent */
7829 case CP0_REG16__CONFIG6:
7830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7831 register_name = "Config6";
7832 break;
7833 case CP0_REG16__CONFIG7:
7834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7835 register_name = "Config7";
7836 break;
7837 default:
7838 goto cp0_unimplemented;
7840 break;
7841 case CP0_REGISTER_17:
7842 switch (sel) {
7843 case CP0_REG17__LLADDR:
7844 gen_helper_mfc0_lladdr(arg, cpu_env);
7845 register_name = "LLAddr";
7846 break;
7847 case CP0_REG17__MAAR:
7848 CP0_CHECK(ctx->mrp);
7849 gen_helper_mfc0_maar(arg, cpu_env);
7850 register_name = "MAAR";
7851 break;
7852 case CP0_REG17__MAARI:
7853 CP0_CHECK(ctx->mrp);
7854 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7855 register_name = "MAARI";
7856 break;
7857 default:
7858 goto cp0_unimplemented;
7860 break;
7861 case CP0_REGISTER_18:
7862 switch (sel) {
7863 case CP0_REG18__WATCHLO0:
7864 case CP0_REG18__WATCHLO1:
7865 case CP0_REG18__WATCHLO2:
7866 case CP0_REG18__WATCHLO3:
7867 case CP0_REG18__WATCHLO4:
7868 case CP0_REG18__WATCHLO5:
7869 case CP0_REG18__WATCHLO6:
7870 case CP0_REG18__WATCHLO7:
7871 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7872 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7873 register_name = "WatchLo";
7874 break;
7875 default:
7876 goto cp0_unimplemented;
7878 break;
7879 case CP0_REGISTER_19:
7880 switch (sel) {
7881 case CP0_REG19__WATCHHI0:
7882 case CP0_REG19__WATCHHI1:
7883 case CP0_REG19__WATCHHI2:
7884 case CP0_REG19__WATCHHI3:
7885 case CP0_REG19__WATCHHI4:
7886 case CP0_REG19__WATCHHI5:
7887 case CP0_REG19__WATCHHI6:
7888 case CP0_REG19__WATCHHI7:
7889 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7890 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7891 register_name = "WatchHi";
7892 break;
7893 default:
7894 goto cp0_unimplemented;
7896 break;
7897 case CP0_REGISTER_20:
7898 switch (sel) {
7899 case CP0_REG20__XCONTEXT:
7900 #if defined(TARGET_MIPS64)
7901 check_insn(ctx, ISA_MIPS3);
7902 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7903 tcg_gen_ext32s_tl(arg, arg);
7904 register_name = "XContext";
7905 break;
7906 #endif
7907 default:
7908 goto cp0_unimplemented;
7910 break;
7911 case CP0_REGISTER_21:
7912 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7913 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7914 switch (sel) {
7915 case 0:
7916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7917 register_name = "Framemask";
7918 break;
7919 default:
7920 goto cp0_unimplemented;
7922 break;
7923 case CP0_REGISTER_22:
7924 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7925 register_name = "'Diagnostic"; /* implementation dependent */
7926 break;
7927 case CP0_REGISTER_23:
7928 switch (sel) {
7929 case CP0_REG23__DEBUG:
7930 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7931 register_name = "Debug";
7932 break;
7933 case CP0_REG23__TRACECONTROL:
7934 /* PDtrace support */
7935 /* gen_helper_mfc0_tracecontrol(arg); */
7936 register_name = "TraceControl";
7937 goto cp0_unimplemented;
7938 case CP0_REG23__TRACECONTROL2:
7939 /* PDtrace support */
7940 /* gen_helper_mfc0_tracecontrol2(arg); */
7941 register_name = "TraceControl2";
7942 goto cp0_unimplemented;
7943 case CP0_REG23__USERTRACEDATA1:
7944 /* PDtrace support */
7945 /* gen_helper_mfc0_usertracedata1(arg);*/
7946 register_name = "UserTraceData1";
7947 goto cp0_unimplemented;
7948 case CP0_REG23__TRACEIBPC:
7949 /* PDtrace support */
7950 /* gen_helper_mfc0_traceibpc(arg); */
7951 register_name = "TraceIBPC";
7952 goto cp0_unimplemented;
7953 case CP0_REG23__TRACEDBPC:
7954 /* PDtrace support */
7955 /* gen_helper_mfc0_tracedbpc(arg); */
7956 register_name = "TraceDBPC";
7957 goto cp0_unimplemented;
7958 default:
7959 goto cp0_unimplemented;
7961 break;
7962 case CP0_REGISTER_24:
7963 switch (sel) {
7964 case CP0_REG24__DEPC:
7965 /* EJTAG support */
7966 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7967 tcg_gen_ext32s_tl(arg, arg);
7968 register_name = "DEPC";
7969 break;
7970 default:
7971 goto cp0_unimplemented;
7973 break;
7974 case CP0_REGISTER_25:
7975 switch (sel) {
7976 case CP0_REG25__PERFCTL0:
7977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7978 register_name = "Performance0";
7979 break;
7980 case CP0_REG25__PERFCNT0:
7981 /* gen_helper_mfc0_performance1(arg); */
7982 register_name = "Performance1";
7983 goto cp0_unimplemented;
7984 case CP0_REG25__PERFCTL1:
7985 /* gen_helper_mfc0_performance2(arg); */
7986 register_name = "Performance2";
7987 goto cp0_unimplemented;
7988 case CP0_REG25__PERFCNT1:
7989 /* gen_helper_mfc0_performance3(arg); */
7990 register_name = "Performance3";
7991 goto cp0_unimplemented;
7992 case CP0_REG25__PERFCTL2:
7993 /* gen_helper_mfc0_performance4(arg); */
7994 register_name = "Performance4";
7995 goto cp0_unimplemented;
7996 case CP0_REG25__PERFCNT2:
7997 /* gen_helper_mfc0_performance5(arg); */
7998 register_name = "Performance5";
7999 goto cp0_unimplemented;
8000 case CP0_REG25__PERFCTL3:
8001 /* gen_helper_mfc0_performance6(arg); */
8002 register_name = "Performance6";
8003 goto cp0_unimplemented;
8004 case CP0_REG25__PERFCNT3:
8005 /* gen_helper_mfc0_performance7(arg); */
8006 register_name = "Performance7";
8007 goto cp0_unimplemented;
8008 default:
8009 goto cp0_unimplemented;
8011 break;
8012 case CP0_REGISTER_26:
8013 switch (sel) {
8014 case CP0_REG26__ERRCTL:
8015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8016 register_name = "ErrCtl";
8017 break;
8018 default:
8019 goto cp0_unimplemented;
8021 break;
8022 case CP0_REGISTER_27:
8023 switch (sel) {
8024 case CP0_REG27__CACHERR:
8025 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8026 register_name = "CacheErr";
8027 break;
8028 default:
8029 goto cp0_unimplemented;
8031 break;
8032 case CP0_REGISTER_28:
8033 switch (sel) {
8034 case CP0_REG28__TAGLO:
8035 case CP0_REG28__TAGLO1:
8036 case CP0_REG28__TAGLO2:
8037 case CP0_REG28__TAGLO3:
8039 TCGv_i64 tmp = tcg_temp_new_i64();
8040 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
8041 gen_move_low32(arg, tmp);
8042 tcg_temp_free_i64(tmp);
8044 register_name = "TagLo";
8045 break;
8046 case CP0_REG28__DATALO:
8047 case CP0_REG28__DATALO1:
8048 case CP0_REG28__DATALO2:
8049 case CP0_REG28__DATALO3:
8050 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8051 register_name = "DataLo";
8052 break;
8053 default:
8054 goto cp0_unimplemented;
8056 break;
8057 case CP0_REGISTER_29:
8058 switch (sel) {
8059 case CP0_REG29__TAGHI:
8060 case CP0_REG29__TAGHI1:
8061 case CP0_REG29__TAGHI2:
8062 case CP0_REG29__TAGHI3:
8063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8064 register_name = "TagHi";
8065 break;
8066 case CP0_REG29__DATAHI:
8067 case CP0_REG29__DATAHI1:
8068 case CP0_REG29__DATAHI2:
8069 case CP0_REG29__DATAHI3:
8070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8071 register_name = "DataHi";
8072 break;
8073 default:
8074 goto cp0_unimplemented;
8076 break;
8077 case CP0_REGISTER_30:
8078 switch (sel) {
8079 case CP0_REG30__ERROREPC:
8080 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8081 tcg_gen_ext32s_tl(arg, arg);
8082 register_name = "ErrorEPC";
8083 break;
8084 default:
8085 goto cp0_unimplemented;
8087 break;
8088 case CP0_REGISTER_31:
8089 switch (sel) {
8090 case CP0_REG31__DESAVE:
8091 /* EJTAG support */
8092 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8093 register_name = "DESAVE";
8094 break;
8095 case CP0_REG31__KSCRATCH1:
8096 case CP0_REG31__KSCRATCH2:
8097 case CP0_REG31__KSCRATCH3:
8098 case CP0_REG31__KSCRATCH4:
8099 case CP0_REG31__KSCRATCH5:
8100 case CP0_REG31__KSCRATCH6:
8101 CP0_CHECK(ctx->kscrexist & (1 << sel));
8102 tcg_gen_ld_tl(arg, cpu_env,
8103 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8104 tcg_gen_ext32s_tl(arg, arg);
8105 register_name = "KScratch";
8106 break;
8107 default:
8108 goto cp0_unimplemented;
8110 break;
8111 default:
8112 goto cp0_unimplemented;
8114 trace_mips_translate_c0("mfc0", register_name, reg, sel);
8115 return;
8117 cp0_unimplemented:
8118 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
8119 register_name, reg, sel);
8120 gen_mfc0_unimplemented(ctx, arg);
8123 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8125 const char *register_name = "invalid";
8127 if (sel != 0) {
8128 check_insn(ctx, ISA_MIPS_R1);
8131 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8132 gen_io_start();
8135 switch (reg) {
8136 case CP0_REGISTER_00:
8137 switch (sel) {
8138 case CP0_REG00__INDEX:
8139 gen_helper_mtc0_index(cpu_env, arg);
8140 register_name = "Index";
8141 break;
8142 case CP0_REG00__MVPCONTROL:
8143 CP0_CHECK(ctx->insn_flags & ASE_MT);
8144 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8145 register_name = "MVPControl";
8146 break;
8147 case CP0_REG00__MVPCONF0:
8148 CP0_CHECK(ctx->insn_flags & ASE_MT);
8149 /* ignored */
8150 register_name = "MVPConf0";
8151 break;
8152 case CP0_REG00__MVPCONF1:
8153 CP0_CHECK(ctx->insn_flags & ASE_MT);
8154 /* ignored */
8155 register_name = "MVPConf1";
8156 break;
8157 case CP0_REG00__VPCONTROL:
8158 CP0_CHECK(ctx->vp);
8159 /* ignored */
8160 register_name = "VPControl";
8161 break;
8162 default:
8163 goto cp0_unimplemented;
8165 break;
8166 case CP0_REGISTER_01:
8167 switch (sel) {
8168 case CP0_REG01__RANDOM:
8169 /* ignored */
8170 register_name = "Random";
8171 break;
8172 case CP0_REG01__VPECONTROL:
8173 CP0_CHECK(ctx->insn_flags & ASE_MT);
8174 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8175 register_name = "VPEControl";
8176 break;
8177 case CP0_REG01__VPECONF0:
8178 CP0_CHECK(ctx->insn_flags & ASE_MT);
8179 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8180 register_name = "VPEConf0";
8181 break;
8182 case CP0_REG01__VPECONF1:
8183 CP0_CHECK(ctx->insn_flags & ASE_MT);
8184 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8185 register_name = "VPEConf1";
8186 break;
8187 case CP0_REG01__YQMASK:
8188 CP0_CHECK(ctx->insn_flags & ASE_MT);
8189 gen_helper_mtc0_yqmask(cpu_env, arg);
8190 register_name = "YQMask";
8191 break;
8192 case CP0_REG01__VPESCHEDULE:
8193 CP0_CHECK(ctx->insn_flags & ASE_MT);
8194 tcg_gen_st_tl(arg, cpu_env,
8195 offsetof(CPUMIPSState, CP0_VPESchedule));
8196 register_name = "VPESchedule";
8197 break;
8198 case CP0_REG01__VPESCHEFBACK:
8199 CP0_CHECK(ctx->insn_flags & ASE_MT);
8200 tcg_gen_st_tl(arg, cpu_env,
8201 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8202 register_name = "VPEScheFBack";
8203 break;
8204 case CP0_REG01__VPEOPT:
8205 CP0_CHECK(ctx->insn_flags & ASE_MT);
8206 gen_helper_mtc0_vpeopt(cpu_env, arg);
8207 register_name = "VPEOpt";
8208 break;
8209 default:
8210 goto cp0_unimplemented;
8212 break;
8213 case CP0_REGISTER_02:
8214 switch (sel) {
8215 case CP0_REG02__ENTRYLO0:
8216 gen_helper_mtc0_entrylo0(cpu_env, arg);
8217 register_name = "EntryLo0";
8218 break;
8219 case CP0_REG02__TCSTATUS:
8220 CP0_CHECK(ctx->insn_flags & ASE_MT);
8221 gen_helper_mtc0_tcstatus(cpu_env, arg);
8222 register_name = "TCStatus";
8223 break;
8224 case CP0_REG02__TCBIND:
8225 CP0_CHECK(ctx->insn_flags & ASE_MT);
8226 gen_helper_mtc0_tcbind(cpu_env, arg);
8227 register_name = "TCBind";
8228 break;
8229 case CP0_REG02__TCRESTART:
8230 CP0_CHECK(ctx->insn_flags & ASE_MT);
8231 gen_helper_mtc0_tcrestart(cpu_env, arg);
8232 register_name = "TCRestart";
8233 break;
8234 case CP0_REG02__TCHALT:
8235 CP0_CHECK(ctx->insn_flags & ASE_MT);
8236 gen_helper_mtc0_tchalt(cpu_env, arg);
8237 register_name = "TCHalt";
8238 break;
8239 case CP0_REG02__TCCONTEXT:
8240 CP0_CHECK(ctx->insn_flags & ASE_MT);
8241 gen_helper_mtc0_tccontext(cpu_env, arg);
8242 register_name = "TCContext";
8243 break;
8244 case CP0_REG02__TCSCHEDULE:
8245 CP0_CHECK(ctx->insn_flags & ASE_MT);
8246 gen_helper_mtc0_tcschedule(cpu_env, arg);
8247 register_name = "TCSchedule";
8248 break;
8249 case CP0_REG02__TCSCHEFBACK:
8250 CP0_CHECK(ctx->insn_flags & ASE_MT);
8251 gen_helper_mtc0_tcschefback(cpu_env, arg);
8252 register_name = "TCScheFBack";
8253 break;
8254 default:
8255 goto cp0_unimplemented;
8257 break;
8258 case CP0_REGISTER_03:
8259 switch (sel) {
8260 case CP0_REG03__ENTRYLO1:
8261 gen_helper_mtc0_entrylo1(cpu_env, arg);
8262 register_name = "EntryLo1";
8263 break;
8264 case CP0_REG03__GLOBALNUM:
8265 CP0_CHECK(ctx->vp);
8266 /* ignored */
8267 register_name = "GlobalNumber";
8268 break;
8269 default:
8270 goto cp0_unimplemented;
8272 break;
8273 case CP0_REGISTER_04:
8274 switch (sel) {
8275 case CP0_REG04__CONTEXT:
8276 gen_helper_mtc0_context(cpu_env, arg);
8277 register_name = "Context";
8278 break;
8279 case CP0_REG04__CONTEXTCONFIG:
8280 /* SmartMIPS ASE */
8281 /* gen_helper_mtc0_contextconfig(arg); */
8282 register_name = "ContextConfig";
8283 goto cp0_unimplemented;
8284 case CP0_REG04__USERLOCAL:
8285 CP0_CHECK(ctx->ulri);
8286 tcg_gen_st_tl(arg, cpu_env,
8287 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8288 register_name = "UserLocal";
8289 break;
8290 case CP0_REG04__MMID:
8291 CP0_CHECK(ctx->mi);
8292 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8293 register_name = "MMID";
8294 break;
8295 default:
8296 goto cp0_unimplemented;
8298 break;
8299 case CP0_REGISTER_05:
8300 switch (sel) {
8301 case CP0_REG05__PAGEMASK:
8302 gen_helper_mtc0_pagemask(cpu_env, arg);
8303 register_name = "PageMask";
8304 break;
8305 case CP0_REG05__PAGEGRAIN:
8306 check_insn(ctx, ISA_MIPS_R2);
8307 gen_helper_mtc0_pagegrain(cpu_env, arg);
8308 register_name = "PageGrain";
8309 ctx->base.is_jmp = DISAS_STOP;
8310 break;
8311 case CP0_REG05__SEGCTL0:
8312 CP0_CHECK(ctx->sc);
8313 gen_helper_mtc0_segctl0(cpu_env, arg);
8314 register_name = "SegCtl0";
8315 break;
8316 case CP0_REG05__SEGCTL1:
8317 CP0_CHECK(ctx->sc);
8318 gen_helper_mtc0_segctl1(cpu_env, arg);
8319 register_name = "SegCtl1";
8320 break;
8321 case CP0_REG05__SEGCTL2:
8322 CP0_CHECK(ctx->sc);
8323 gen_helper_mtc0_segctl2(cpu_env, arg);
8324 register_name = "SegCtl2";
8325 break;
8326 case CP0_REG05__PWBASE:
8327 check_pw(ctx);
8328 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
8329 register_name = "PWBase";
8330 break;
8331 case CP0_REG05__PWFIELD:
8332 check_pw(ctx);
8333 gen_helper_mtc0_pwfield(cpu_env, arg);
8334 register_name = "PWField";
8335 break;
8336 case CP0_REG05__PWSIZE:
8337 check_pw(ctx);
8338 gen_helper_mtc0_pwsize(cpu_env, arg);
8339 register_name = "PWSize";
8340 break;
8341 default:
8342 goto cp0_unimplemented;
8344 break;
8345 case CP0_REGISTER_06:
8346 switch (sel) {
8347 case CP0_REG06__WIRED:
8348 gen_helper_mtc0_wired(cpu_env, arg);
8349 register_name = "Wired";
8350 break;
8351 case CP0_REG06__SRSCONF0:
8352 check_insn(ctx, ISA_MIPS_R2);
8353 gen_helper_mtc0_srsconf0(cpu_env, arg);
8354 register_name = "SRSConf0";
8355 break;
8356 case CP0_REG06__SRSCONF1:
8357 check_insn(ctx, ISA_MIPS_R2);
8358 gen_helper_mtc0_srsconf1(cpu_env, arg);
8359 register_name = "SRSConf1";
8360 break;
8361 case CP0_REG06__SRSCONF2:
8362 check_insn(ctx, ISA_MIPS_R2);
8363 gen_helper_mtc0_srsconf2(cpu_env, arg);
8364 register_name = "SRSConf2";
8365 break;
8366 case CP0_REG06__SRSCONF3:
8367 check_insn(ctx, ISA_MIPS_R2);
8368 gen_helper_mtc0_srsconf3(cpu_env, arg);
8369 register_name = "SRSConf3";
8370 break;
8371 case CP0_REG06__SRSCONF4:
8372 check_insn(ctx, ISA_MIPS_R2);
8373 gen_helper_mtc0_srsconf4(cpu_env, arg);
8374 register_name = "SRSConf4";
8375 break;
8376 case CP0_REG06__PWCTL:
8377 check_pw(ctx);
8378 gen_helper_mtc0_pwctl(cpu_env, arg);
8379 register_name = "PWCtl";
8380 break;
8381 default:
8382 goto cp0_unimplemented;
8384 break;
8385 case CP0_REGISTER_07:
8386 switch (sel) {
8387 case CP0_REG07__HWRENA:
8388 check_insn(ctx, ISA_MIPS_R2);
8389 gen_helper_mtc0_hwrena(cpu_env, arg);
8390 ctx->base.is_jmp = DISAS_STOP;
8391 register_name = "HWREna";
8392 break;
8393 default:
8394 goto cp0_unimplemented;
8396 break;
8397 case CP0_REGISTER_08:
8398 switch (sel) {
8399 case CP0_REG08__BADVADDR:
8400 /* ignored */
8401 register_name = "BadVAddr";
8402 break;
8403 case CP0_REG08__BADINSTR:
8404 /* ignored */
8405 register_name = "BadInstr";
8406 break;
8407 case CP0_REG08__BADINSTRP:
8408 /* ignored */
8409 register_name = "BadInstrP";
8410 break;
8411 case CP0_REG08__BADINSTRX:
8412 /* ignored */
8413 register_name = "BadInstrX";
8414 break;
8415 default:
8416 goto cp0_unimplemented;
8418 break;
8419 case CP0_REGISTER_09:
8420 switch (sel) {
8421 case CP0_REG09__COUNT:
8422 gen_helper_mtc0_count(cpu_env, arg);
8423 register_name = "Count";
8424 break;
8425 case CP0_REG09__SAARI:
8426 CP0_CHECK(ctx->saar);
8427 gen_helper_mtc0_saari(cpu_env, arg);
8428 register_name = "SAARI";
8429 break;
8430 case CP0_REG09__SAAR:
8431 CP0_CHECK(ctx->saar);
8432 gen_helper_mtc0_saar(cpu_env, arg);
8433 register_name = "SAAR";
8434 break;
8435 default:
8436 goto cp0_unimplemented;
8438 break;
8439 case CP0_REGISTER_10:
8440 switch (sel) {
8441 case CP0_REG10__ENTRYHI:
8442 gen_helper_mtc0_entryhi(cpu_env, arg);
8443 register_name = "EntryHi";
8444 break;
8445 default:
8446 goto cp0_unimplemented;
8448 break;
8449 case CP0_REGISTER_11:
8450 switch (sel) {
8451 case CP0_REG11__COMPARE:
8452 gen_helper_mtc0_compare(cpu_env, arg);
8453 register_name = "Compare";
8454 break;
8455 /* 6,7 are implementation dependent */
8456 default:
8457 goto cp0_unimplemented;
8459 break;
8460 case CP0_REGISTER_12:
8461 switch (sel) {
8462 case CP0_REG12__STATUS:
8463 save_cpu_state(ctx, 1);
8464 gen_helper_mtc0_status(cpu_env, arg);
8465 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8466 gen_save_pc(ctx->base.pc_next + 4);
8467 ctx->base.is_jmp = DISAS_EXIT;
8468 register_name = "Status";
8469 break;
8470 case CP0_REG12__INTCTL:
8471 check_insn(ctx, ISA_MIPS_R2);
8472 gen_helper_mtc0_intctl(cpu_env, arg);
8473 /* Stop translation as we may have switched the execution mode */
8474 ctx->base.is_jmp = DISAS_STOP;
8475 register_name = "IntCtl";
8476 break;
8477 case CP0_REG12__SRSCTL:
8478 check_insn(ctx, ISA_MIPS_R2);
8479 gen_helper_mtc0_srsctl(cpu_env, arg);
8480 /* Stop translation as we may have switched the execution mode */
8481 ctx->base.is_jmp = DISAS_STOP;
8482 register_name = "SRSCtl";
8483 break;
8484 case CP0_REG12__SRSMAP:
8485 check_insn(ctx, ISA_MIPS_R2);
8486 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487 /* Stop translation as we may have switched the execution mode */
8488 ctx->base.is_jmp = DISAS_STOP;
8489 register_name = "SRSMap";
8490 break;
8491 default:
8492 goto cp0_unimplemented;
8494 break;
8495 case CP0_REGISTER_13:
8496 switch (sel) {
8497 case CP0_REG13__CAUSE:
8498 save_cpu_state(ctx, 1);
8499 gen_helper_mtc0_cause(cpu_env, arg);
8501 * Stop translation as we may have triggered an interrupt.
8502 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8503 * translated code to check for pending interrupts.
8505 gen_save_pc(ctx->base.pc_next + 4);
8506 ctx->base.is_jmp = DISAS_EXIT;
8507 register_name = "Cause";
8508 break;
8509 default:
8510 goto cp0_unimplemented;
8512 break;
8513 case CP0_REGISTER_14:
8514 switch (sel) {
8515 case CP0_REG14__EPC:
8516 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8517 register_name = "EPC";
8518 break;
8519 default:
8520 goto cp0_unimplemented;
8522 break;
8523 case CP0_REGISTER_15:
8524 switch (sel) {
8525 case CP0_REG15__PRID:
8526 /* ignored */
8527 register_name = "PRid";
8528 break;
8529 case CP0_REG15__EBASE:
8530 check_insn(ctx, ISA_MIPS_R2);
8531 gen_helper_mtc0_ebase(cpu_env, arg);
8532 register_name = "EBase";
8533 break;
8534 default:
8535 goto cp0_unimplemented;
8537 break;
8538 case CP0_REGISTER_16:
8539 switch (sel) {
8540 case CP0_REG16__CONFIG:
8541 gen_helper_mtc0_config0(cpu_env, arg);
8542 register_name = "Config";
8543 /* Stop translation as we may have switched the execution mode */
8544 ctx->base.is_jmp = DISAS_STOP;
8545 break;
8546 case CP0_REG16__CONFIG1:
8547 /* ignored, read only */
8548 register_name = "Config1";
8549 break;
8550 case CP0_REG16__CONFIG2:
8551 gen_helper_mtc0_config2(cpu_env, arg);
8552 register_name = "Config2";
8553 /* Stop translation as we may have switched the execution mode */
8554 ctx->base.is_jmp = DISAS_STOP;
8555 break;
8556 case CP0_REG16__CONFIG3:
8557 gen_helper_mtc0_config3(cpu_env, arg);
8558 register_name = "Config3";
8559 /* Stop translation as we may have switched the execution mode */
8560 ctx->base.is_jmp = DISAS_STOP;
8561 break;
8562 case CP0_REG16__CONFIG4:
8563 gen_helper_mtc0_config4(cpu_env, arg);
8564 register_name = "Config4";
8565 ctx->base.is_jmp = DISAS_STOP;
8566 break;
8567 case CP0_REG16__CONFIG5:
8568 gen_helper_mtc0_config5(cpu_env, arg);
8569 register_name = "Config5";
8570 /* Stop translation as we may have switched the execution mode */
8571 ctx->base.is_jmp = DISAS_STOP;
8572 break;
8573 /* 6,7 are implementation dependent */
8574 case CP0_REG16__CONFIG6:
8575 /* ignored */
8576 register_name = "Config6";
8577 break;
8578 case CP0_REG16__CONFIG7:
8579 /* ignored */
8580 register_name = "Config7";
8581 break;
8582 default:
8583 register_name = "Invalid config selector";
8584 goto cp0_unimplemented;
8586 break;
8587 case CP0_REGISTER_17:
8588 switch (sel) {
8589 case CP0_REG17__LLADDR:
8590 gen_helper_mtc0_lladdr(cpu_env, arg);
8591 register_name = "LLAddr";
8592 break;
8593 case CP0_REG17__MAAR:
8594 CP0_CHECK(ctx->mrp);
8595 gen_helper_mtc0_maar(cpu_env, arg);
8596 register_name = "MAAR";
8597 break;
8598 case CP0_REG17__MAARI:
8599 CP0_CHECK(ctx->mrp);
8600 gen_helper_mtc0_maari(cpu_env, arg);
8601 register_name = "MAARI";
8602 break;
8603 default:
8604 goto cp0_unimplemented;
8606 break;
8607 case CP0_REGISTER_18:
8608 switch (sel) {
8609 case CP0_REG18__WATCHLO0:
8610 case CP0_REG18__WATCHLO1:
8611 case CP0_REG18__WATCHLO2:
8612 case CP0_REG18__WATCHLO3:
8613 case CP0_REG18__WATCHLO4:
8614 case CP0_REG18__WATCHLO5:
8615 case CP0_REG18__WATCHLO6:
8616 case CP0_REG18__WATCHLO7:
8617 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8618 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8619 register_name = "WatchLo";
8620 break;
8621 default:
8622 goto cp0_unimplemented;
8624 break;
8625 case CP0_REGISTER_19:
8626 switch (sel) {
8627 case CP0_REG19__WATCHHI0:
8628 case CP0_REG19__WATCHHI1:
8629 case CP0_REG19__WATCHHI2:
8630 case CP0_REG19__WATCHHI3:
8631 case CP0_REG19__WATCHHI4:
8632 case CP0_REG19__WATCHHI5:
8633 case CP0_REG19__WATCHHI6:
8634 case CP0_REG19__WATCHHI7:
8635 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8636 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8637 register_name = "WatchHi";
8638 break;
8639 default:
8640 goto cp0_unimplemented;
8642 break;
8643 case CP0_REGISTER_20:
8644 switch (sel) {
8645 case CP0_REG20__XCONTEXT:
8646 #if defined(TARGET_MIPS64)
8647 check_insn(ctx, ISA_MIPS3);
8648 gen_helper_mtc0_xcontext(cpu_env, arg);
8649 register_name = "XContext";
8650 break;
8651 #endif
8652 default:
8653 goto cp0_unimplemented;
8655 break;
8656 case CP0_REGISTER_21:
8657 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8658 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8659 switch (sel) {
8660 case 0:
8661 gen_helper_mtc0_framemask(cpu_env, arg);
8662 register_name = "Framemask";
8663 break;
8664 default:
8665 goto cp0_unimplemented;
8667 break;
8668 case CP0_REGISTER_22:
8669 /* ignored */
8670 register_name = "Diagnostic"; /* implementation dependent */
8671 break;
8672 case CP0_REGISTER_23:
8673 switch (sel) {
8674 case CP0_REG23__DEBUG:
8675 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8676 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8677 gen_save_pc(ctx->base.pc_next + 4);
8678 ctx->base.is_jmp = DISAS_EXIT;
8679 register_name = "Debug";
8680 break;
8681 case CP0_REG23__TRACECONTROL:
8682 /* PDtrace support */
8683 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8684 register_name = "TraceControl";
8685 /* Stop translation as we may have switched the execution mode */
8686 ctx->base.is_jmp = DISAS_STOP;
8687 goto cp0_unimplemented;
8688 case CP0_REG23__TRACECONTROL2:
8689 /* PDtrace support */
8690 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8691 register_name = "TraceControl2";
8692 /* Stop translation as we may have switched the execution mode */
8693 ctx->base.is_jmp = DISAS_STOP;
8694 goto cp0_unimplemented;
8695 case CP0_REG23__USERTRACEDATA1:
8696 /* Stop translation as we may have switched the execution mode */
8697 ctx->base.is_jmp = DISAS_STOP;
8698 /* PDtrace support */
8699 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8700 register_name = "UserTraceData";
8701 /* Stop translation as we may have switched the execution mode */
8702 ctx->base.is_jmp = DISAS_STOP;
8703 goto cp0_unimplemented;
8704 case CP0_REG23__TRACEIBPC:
8705 /* PDtrace support */
8706 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8707 /* Stop translation as we may have switched the execution mode */
8708 ctx->base.is_jmp = DISAS_STOP;
8709 register_name = "TraceIBPC";
8710 goto cp0_unimplemented;
8711 case CP0_REG23__TRACEDBPC:
8712 /* PDtrace support */
8713 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8714 /* Stop translation as we may have switched the execution mode */
8715 ctx->base.is_jmp = DISAS_STOP;
8716 register_name = "TraceDBPC";
8717 goto cp0_unimplemented;
8718 default:
8719 goto cp0_unimplemented;
8721 break;
8722 case CP0_REGISTER_24:
8723 switch (sel) {
8724 case CP0_REG24__DEPC:
8725 /* EJTAG support */
8726 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8727 register_name = "DEPC";
8728 break;
8729 default:
8730 goto cp0_unimplemented;
8732 break;
8733 case CP0_REGISTER_25:
8734 switch (sel) {
8735 case CP0_REG25__PERFCTL0:
8736 gen_helper_mtc0_performance0(cpu_env, arg);
8737 register_name = "Performance0";
8738 break;
8739 case CP0_REG25__PERFCNT0:
8740 /* gen_helper_mtc0_performance1(arg); */
8741 register_name = "Performance1";
8742 goto cp0_unimplemented;
8743 case CP0_REG25__PERFCTL1:
8744 /* gen_helper_mtc0_performance2(arg); */
8745 register_name = "Performance2";
8746 goto cp0_unimplemented;
8747 case CP0_REG25__PERFCNT1:
8748 /* gen_helper_mtc0_performance3(arg); */
8749 register_name = "Performance3";
8750 goto cp0_unimplemented;
8751 case CP0_REG25__PERFCTL2:
8752 /* gen_helper_mtc0_performance4(arg); */
8753 register_name = "Performance4";
8754 goto cp0_unimplemented;
8755 case CP0_REG25__PERFCNT2:
8756 /* gen_helper_mtc0_performance5(arg); */
8757 register_name = "Performance5";
8758 goto cp0_unimplemented;
8759 case CP0_REG25__PERFCTL3:
8760 /* gen_helper_mtc0_performance6(arg); */
8761 register_name = "Performance6";
8762 goto cp0_unimplemented;
8763 case CP0_REG25__PERFCNT3:
8764 /* gen_helper_mtc0_performance7(arg); */
8765 register_name = "Performance7";
8766 goto cp0_unimplemented;
8767 default:
8768 goto cp0_unimplemented;
8770 break;
8771 case CP0_REGISTER_26:
8772 switch (sel) {
8773 case CP0_REG26__ERRCTL:
8774 gen_helper_mtc0_errctl(cpu_env, arg);
8775 ctx->base.is_jmp = DISAS_STOP;
8776 register_name = "ErrCtl";
8777 break;
8778 default:
8779 goto cp0_unimplemented;
8781 break;
8782 case CP0_REGISTER_27:
8783 switch (sel) {
8784 case CP0_REG27__CACHERR:
8785 /* ignored */
8786 register_name = "CacheErr";
8787 break;
8788 default:
8789 goto cp0_unimplemented;
8791 break;
8792 case CP0_REGISTER_28:
8793 switch (sel) {
8794 case CP0_REG28__TAGLO:
8795 case CP0_REG28__TAGLO1:
8796 case CP0_REG28__TAGLO2:
8797 case CP0_REG28__TAGLO3:
8798 gen_helper_mtc0_taglo(cpu_env, arg);
8799 register_name = "TagLo";
8800 break;
8801 case CP0_REG28__DATALO:
8802 case CP0_REG28__DATALO1:
8803 case CP0_REG28__DATALO2:
8804 case CP0_REG28__DATALO3:
8805 gen_helper_mtc0_datalo(cpu_env, arg);
8806 register_name = "DataLo";
8807 break;
8808 default:
8809 goto cp0_unimplemented;
8811 break;
8812 case CP0_REGISTER_29:
8813 switch (sel) {
8814 case CP0_REG29__TAGHI:
8815 case CP0_REG29__TAGHI1:
8816 case CP0_REG29__TAGHI2:
8817 case CP0_REG29__TAGHI3:
8818 gen_helper_mtc0_taghi(cpu_env, arg);
8819 register_name = "TagHi";
8820 break;
8821 case CP0_REG29__DATAHI:
8822 case CP0_REG29__DATAHI1:
8823 case CP0_REG29__DATAHI2:
8824 case CP0_REG29__DATAHI3:
8825 gen_helper_mtc0_datahi(cpu_env, arg);
8826 register_name = "DataHi";
8827 break;
8828 default:
8829 register_name = "invalid sel";
8830 goto cp0_unimplemented;
8832 break;
8833 case CP0_REGISTER_30:
8834 switch (sel) {
8835 case CP0_REG30__ERROREPC:
8836 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8837 register_name = "ErrorEPC";
8838 break;
8839 default:
8840 goto cp0_unimplemented;
8842 break;
8843 case CP0_REGISTER_31:
8844 switch (sel) {
8845 case CP0_REG31__DESAVE:
8846 /* EJTAG support */
8847 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8848 register_name = "DESAVE";
8849 break;
8850 case CP0_REG31__KSCRATCH1:
8851 case CP0_REG31__KSCRATCH2:
8852 case CP0_REG31__KSCRATCH3:
8853 case CP0_REG31__KSCRATCH4:
8854 case CP0_REG31__KSCRATCH5:
8855 case CP0_REG31__KSCRATCH6:
8856 CP0_CHECK(ctx->kscrexist & (1 << sel));
8857 tcg_gen_st_tl(arg, cpu_env,
8858 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8859 register_name = "KScratch";
8860 break;
8861 default:
8862 goto cp0_unimplemented;
8864 break;
8865 default:
8866 goto cp0_unimplemented;
8868 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8870 /* For simplicity assume that all writes can cause interrupts. */
8871 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8873 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8874 * translated code to check for pending interrupts.
8876 gen_save_pc(ctx->base.pc_next + 4);
8877 ctx->base.is_jmp = DISAS_EXIT;
8879 return;
8881 cp0_unimplemented:
8882 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8883 register_name, reg, sel);
8886 #if defined(TARGET_MIPS64)
8887 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8889 const char *register_name = "invalid";
8891 if (sel != 0) {
8892 check_insn(ctx, ISA_MIPS_R1);
8895 switch (reg) {
8896 case CP0_REGISTER_00:
8897 switch (sel) {
8898 case CP0_REG00__INDEX:
8899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8900 register_name = "Index";
8901 break;
8902 case CP0_REG00__MVPCONTROL:
8903 CP0_CHECK(ctx->insn_flags & ASE_MT);
8904 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8905 register_name = "MVPControl";
8906 break;
8907 case CP0_REG00__MVPCONF0:
8908 CP0_CHECK(ctx->insn_flags & ASE_MT);
8909 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8910 register_name = "MVPConf0";
8911 break;
8912 case CP0_REG00__MVPCONF1:
8913 CP0_CHECK(ctx->insn_flags & ASE_MT);
8914 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8915 register_name = "MVPConf1";
8916 break;
8917 case CP0_REG00__VPCONTROL:
8918 CP0_CHECK(ctx->vp);
8919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8920 register_name = "VPControl";
8921 break;
8922 default:
8923 goto cp0_unimplemented;
8925 break;
8926 case CP0_REGISTER_01:
8927 switch (sel) {
8928 case CP0_REG01__RANDOM:
8929 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8930 gen_helper_mfc0_random(arg, cpu_env);
8931 register_name = "Random";
8932 break;
8933 case CP0_REG01__VPECONTROL:
8934 CP0_CHECK(ctx->insn_flags & ASE_MT);
8935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8936 register_name = "VPEControl";
8937 break;
8938 case CP0_REG01__VPECONF0:
8939 CP0_CHECK(ctx->insn_flags & ASE_MT);
8940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8941 register_name = "VPEConf0";
8942 break;
8943 case CP0_REG01__VPECONF1:
8944 CP0_CHECK(ctx->insn_flags & ASE_MT);
8945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8946 register_name = "VPEConf1";
8947 break;
8948 case CP0_REG01__YQMASK:
8949 CP0_CHECK(ctx->insn_flags & ASE_MT);
8950 tcg_gen_ld_tl(arg, cpu_env,
8951 offsetof(CPUMIPSState, CP0_YQMask));
8952 register_name = "YQMask";
8953 break;
8954 case CP0_REG01__VPESCHEDULE:
8955 CP0_CHECK(ctx->insn_flags & ASE_MT);
8956 tcg_gen_ld_tl(arg, cpu_env,
8957 offsetof(CPUMIPSState, CP0_VPESchedule));
8958 register_name = "VPESchedule";
8959 break;
8960 case CP0_REG01__VPESCHEFBACK:
8961 CP0_CHECK(ctx->insn_flags & ASE_MT);
8962 tcg_gen_ld_tl(arg, cpu_env,
8963 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8964 register_name = "VPEScheFBack";
8965 break;
8966 case CP0_REG01__VPEOPT:
8967 CP0_CHECK(ctx->insn_flags & ASE_MT);
8968 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8969 register_name = "VPEOpt";
8970 break;
8971 default:
8972 goto cp0_unimplemented;
8974 break;
8975 case CP0_REGISTER_02:
8976 switch (sel) {
8977 case CP0_REG02__ENTRYLO0:
8978 tcg_gen_ld_tl(arg, cpu_env,
8979 offsetof(CPUMIPSState, CP0_EntryLo0));
8980 register_name = "EntryLo0";
8981 break;
8982 case CP0_REG02__TCSTATUS:
8983 CP0_CHECK(ctx->insn_flags & ASE_MT);
8984 gen_helper_mfc0_tcstatus(arg, cpu_env);
8985 register_name = "TCStatus";
8986 break;
8987 case CP0_REG02__TCBIND:
8988 CP0_CHECK(ctx->insn_flags & ASE_MT);
8989 gen_helper_mfc0_tcbind(arg, cpu_env);
8990 register_name = "TCBind";
8991 break;
8992 case CP0_REG02__TCRESTART:
8993 CP0_CHECK(ctx->insn_flags & ASE_MT);
8994 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8995 register_name = "TCRestart";
8996 break;
8997 case CP0_REG02__TCHALT:
8998 CP0_CHECK(ctx->insn_flags & ASE_MT);
8999 gen_helper_dmfc0_tchalt(arg, cpu_env);
9000 register_name = "TCHalt";
9001 break;
9002 case CP0_REG02__TCCONTEXT:
9003 CP0_CHECK(ctx->insn_flags & ASE_MT);
9004 gen_helper_dmfc0_tccontext(arg, cpu_env);
9005 register_name = "TCContext";
9006 break;
9007 case CP0_REG02__TCSCHEDULE:
9008 CP0_CHECK(ctx->insn_flags & ASE_MT);
9009 gen_helper_dmfc0_tcschedule(arg, cpu_env);
9010 register_name = "TCSchedule";
9011 break;
9012 case CP0_REG02__TCSCHEFBACK:
9013 CP0_CHECK(ctx->insn_flags & ASE_MT);
9014 gen_helper_dmfc0_tcschefback(arg, cpu_env);
9015 register_name = "TCScheFBack";
9016 break;
9017 default:
9018 goto cp0_unimplemented;
9020 break;
9021 case CP0_REGISTER_03:
9022 switch (sel) {
9023 case CP0_REG03__ENTRYLO1:
9024 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
9025 register_name = "EntryLo1";
9026 break;
9027 case CP0_REG03__GLOBALNUM:
9028 CP0_CHECK(ctx->vp);
9029 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
9030 register_name = "GlobalNumber";
9031 break;
9032 default:
9033 goto cp0_unimplemented;
9035 break;
9036 case CP0_REGISTER_04:
9037 switch (sel) {
9038 case CP0_REG04__CONTEXT:
9039 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
9040 register_name = "Context";
9041 break;
9042 case CP0_REG04__CONTEXTCONFIG:
9043 /* SmartMIPS ASE */
9044 /* gen_helper_dmfc0_contextconfig(arg); */
9045 register_name = "ContextConfig";
9046 goto cp0_unimplemented;
9047 case CP0_REG04__USERLOCAL:
9048 CP0_CHECK(ctx->ulri);
9049 tcg_gen_ld_tl(arg, cpu_env,
9050 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9051 register_name = "UserLocal";
9052 break;
9053 case CP0_REG04__MMID:
9054 CP0_CHECK(ctx->mi);
9055 gen_helper_mtc0_memorymapid(cpu_env, arg);
9056 register_name = "MMID";
9057 break;
9058 default:
9059 goto cp0_unimplemented;
9061 break;
9062 case CP0_REGISTER_05:
9063 switch (sel) {
9064 case CP0_REG05__PAGEMASK:
9065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
9066 register_name = "PageMask";
9067 break;
9068 case CP0_REG05__PAGEGRAIN:
9069 check_insn(ctx, ISA_MIPS_R2);
9070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
9071 register_name = "PageGrain";
9072 break;
9073 case CP0_REG05__SEGCTL0:
9074 CP0_CHECK(ctx->sc);
9075 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
9076 register_name = "SegCtl0";
9077 break;
9078 case CP0_REG05__SEGCTL1:
9079 CP0_CHECK(ctx->sc);
9080 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
9081 register_name = "SegCtl1";
9082 break;
9083 case CP0_REG05__SEGCTL2:
9084 CP0_CHECK(ctx->sc);
9085 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
9086 register_name = "SegCtl2";
9087 break;
9088 case CP0_REG05__PWBASE:
9089 check_pw(ctx);
9090 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9091 register_name = "PWBase";
9092 break;
9093 case CP0_REG05__PWFIELD:
9094 check_pw(ctx);
9095 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
9096 register_name = "PWField";
9097 break;
9098 case CP0_REG05__PWSIZE:
9099 check_pw(ctx);
9100 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
9101 register_name = "PWSize";
9102 break;
9103 default:
9104 goto cp0_unimplemented;
9106 break;
9107 case CP0_REGISTER_06:
9108 switch (sel) {
9109 case CP0_REG06__WIRED:
9110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
9111 register_name = "Wired";
9112 break;
9113 case CP0_REG06__SRSCONF0:
9114 check_insn(ctx, ISA_MIPS_R2);
9115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
9116 register_name = "SRSConf0";
9117 break;
9118 case CP0_REG06__SRSCONF1:
9119 check_insn(ctx, ISA_MIPS_R2);
9120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
9121 register_name = "SRSConf1";
9122 break;
9123 case CP0_REG06__SRSCONF2:
9124 check_insn(ctx, ISA_MIPS_R2);
9125 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
9126 register_name = "SRSConf2";
9127 break;
9128 case CP0_REG06__SRSCONF3:
9129 check_insn(ctx, ISA_MIPS_R2);
9130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
9131 register_name = "SRSConf3";
9132 break;
9133 case CP0_REG06__SRSCONF4:
9134 check_insn(ctx, ISA_MIPS_R2);
9135 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
9136 register_name = "SRSConf4";
9137 break;
9138 case CP0_REG06__PWCTL:
9139 check_pw(ctx);
9140 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
9141 register_name = "PWCtl";
9142 break;
9143 default:
9144 goto cp0_unimplemented;
9146 break;
9147 case CP0_REGISTER_07:
9148 switch (sel) {
9149 case CP0_REG07__HWRENA:
9150 check_insn(ctx, ISA_MIPS_R2);
9151 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
9152 register_name = "HWREna";
9153 break;
9154 default:
9155 goto cp0_unimplemented;
9157 break;
9158 case CP0_REGISTER_08:
9159 switch (sel) {
9160 case CP0_REG08__BADVADDR:
9161 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
9162 register_name = "BadVAddr";
9163 break;
9164 case CP0_REG08__BADINSTR:
9165 CP0_CHECK(ctx->bi);
9166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
9167 register_name = "BadInstr";
9168 break;
9169 case CP0_REG08__BADINSTRP:
9170 CP0_CHECK(ctx->bp);
9171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
9172 register_name = "BadInstrP";
9173 break;
9174 case CP0_REG08__BADINSTRX:
9175 CP0_CHECK(ctx->bi);
9176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
9177 tcg_gen_andi_tl(arg, arg, ~0xffff);
9178 register_name = "BadInstrX";
9179 break;
9180 default:
9181 goto cp0_unimplemented;
9183 break;
9184 case CP0_REGISTER_09:
9185 switch (sel) {
9186 case CP0_REG09__COUNT:
9187 /* Mark as an IO operation because we read the time. */
9188 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9189 gen_io_start();
9191 gen_helper_mfc0_count(arg, cpu_env);
9193 * Break the TB to be able to take timer interrupts immediately
9194 * after reading count. DISAS_STOP isn't sufficient, we need to
9195 * ensure we break completely out of translated code.
9197 gen_save_pc(ctx->base.pc_next + 4);
9198 ctx->base.is_jmp = DISAS_EXIT;
9199 register_name = "Count";
9200 break;
9201 case CP0_REG09__SAARI:
9202 CP0_CHECK(ctx->saar);
9203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
9204 register_name = "SAARI";
9205 break;
9206 case CP0_REG09__SAAR:
9207 CP0_CHECK(ctx->saar);
9208 gen_helper_dmfc0_saar(arg, cpu_env);
9209 register_name = "SAAR";
9210 break;
9211 default:
9212 goto cp0_unimplemented;
9214 break;
9215 case CP0_REGISTER_10:
9216 switch (sel) {
9217 case CP0_REG10__ENTRYHI:
9218 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
9219 register_name = "EntryHi";
9220 break;
9221 default:
9222 goto cp0_unimplemented;
9224 break;
9225 case CP0_REGISTER_11:
9226 switch (sel) {
9227 case CP0_REG11__COMPARE:
9228 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
9229 register_name = "Compare";
9230 break;
9231 /* 6,7 are implementation dependent */
9232 default:
9233 goto cp0_unimplemented;
9235 break;
9236 case CP0_REGISTER_12:
9237 switch (sel) {
9238 case CP0_REG12__STATUS:
9239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
9240 register_name = "Status";
9241 break;
9242 case CP0_REG12__INTCTL:
9243 check_insn(ctx, ISA_MIPS_R2);
9244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
9245 register_name = "IntCtl";
9246 break;
9247 case CP0_REG12__SRSCTL:
9248 check_insn(ctx, ISA_MIPS_R2);
9249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
9250 register_name = "SRSCtl";
9251 break;
9252 case CP0_REG12__SRSMAP:
9253 check_insn(ctx, ISA_MIPS_R2);
9254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9255 register_name = "SRSMap";
9256 break;
9257 default:
9258 goto cp0_unimplemented;
9260 break;
9261 case CP0_REGISTER_13:
9262 switch (sel) {
9263 case CP0_REG13__CAUSE:
9264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
9265 register_name = "Cause";
9266 break;
9267 default:
9268 goto cp0_unimplemented;
9270 break;
9271 case CP0_REGISTER_14:
9272 switch (sel) {
9273 case CP0_REG14__EPC:
9274 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9275 register_name = "EPC";
9276 break;
9277 default:
9278 goto cp0_unimplemented;
9280 break;
9281 case CP0_REGISTER_15:
9282 switch (sel) {
9283 case CP0_REG15__PRID:
9284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
9285 register_name = "PRid";
9286 break;
9287 case CP0_REG15__EBASE:
9288 check_insn(ctx, ISA_MIPS_R2);
9289 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
9290 register_name = "EBase";
9291 break;
9292 case CP0_REG15__CMGCRBASE:
9293 check_insn(ctx, ISA_MIPS_R2);
9294 CP0_CHECK(ctx->cmgcr);
9295 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
9296 register_name = "CMGCRBase";
9297 break;
9298 default:
9299 goto cp0_unimplemented;
9301 break;
9302 case CP0_REGISTER_16:
9303 switch (sel) {
9304 case CP0_REG16__CONFIG:
9305 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9306 register_name = "Config";
9307 break;
9308 case CP0_REG16__CONFIG1:
9309 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9310 register_name = "Config1";
9311 break;
9312 case CP0_REG16__CONFIG2:
9313 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9314 register_name = "Config2";
9315 break;
9316 case CP0_REG16__CONFIG3:
9317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9318 register_name = "Config3";
9319 break;
9320 case CP0_REG16__CONFIG4:
9321 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
9322 register_name = "Config4";
9323 break;
9324 case CP0_REG16__CONFIG5:
9325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
9326 register_name = "Config5";
9327 break;
9328 /* 6,7 are implementation dependent */
9329 case CP0_REG16__CONFIG6:
9330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
9331 register_name = "Config6";
9332 break;
9333 case CP0_REG16__CONFIG7:
9334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
9335 register_name = "Config7";
9336 break;
9337 default:
9338 goto cp0_unimplemented;
9340 break;
9341 case CP0_REGISTER_17:
9342 switch (sel) {
9343 case CP0_REG17__LLADDR:
9344 gen_helper_dmfc0_lladdr(arg, cpu_env);
9345 register_name = "LLAddr";
9346 break;
9347 case CP0_REG17__MAAR:
9348 CP0_CHECK(ctx->mrp);
9349 gen_helper_dmfc0_maar(arg, cpu_env);
9350 register_name = "MAAR";
9351 break;
9352 case CP0_REG17__MAARI:
9353 CP0_CHECK(ctx->mrp);
9354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9355 register_name = "MAARI";
9356 break;
9357 default:
9358 goto cp0_unimplemented;
9360 break;
9361 case CP0_REGISTER_18:
9362 switch (sel) {
9363 case CP0_REG18__WATCHLO0:
9364 case CP0_REG18__WATCHLO1:
9365 case CP0_REG18__WATCHLO2:
9366 case CP0_REG18__WATCHLO3:
9367 case CP0_REG18__WATCHLO4:
9368 case CP0_REG18__WATCHLO5:
9369 case CP0_REG18__WATCHLO6:
9370 case CP0_REG18__WATCHLO7:
9371 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9372 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9373 register_name = "WatchLo";
9374 break;
9375 default:
9376 goto cp0_unimplemented;
9378 break;
9379 case CP0_REGISTER_19:
9380 switch (sel) {
9381 case CP0_REG19__WATCHHI0:
9382 case CP0_REG19__WATCHHI1:
9383 case CP0_REG19__WATCHHI2:
9384 case CP0_REG19__WATCHHI3:
9385 case CP0_REG19__WATCHHI4:
9386 case CP0_REG19__WATCHHI5:
9387 case CP0_REG19__WATCHHI6:
9388 case CP0_REG19__WATCHHI7:
9389 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9390 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9391 register_name = "WatchHi";
9392 break;
9393 default:
9394 goto cp0_unimplemented;
9396 break;
9397 case CP0_REGISTER_20:
9398 switch (sel) {
9399 case CP0_REG20__XCONTEXT:
9400 check_insn(ctx, ISA_MIPS3);
9401 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9402 register_name = "XContext";
9403 break;
9404 default:
9405 goto cp0_unimplemented;
9407 break;
9408 case CP0_REGISTER_21:
9409 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9410 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9411 switch (sel) {
9412 case 0:
9413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9414 register_name = "Framemask";
9415 break;
9416 default:
9417 goto cp0_unimplemented;
9419 break;
9420 case CP0_REGISTER_22:
9421 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9422 register_name = "'Diagnostic"; /* implementation dependent */
9423 break;
9424 case CP0_REGISTER_23:
9425 switch (sel) {
9426 case CP0_REG23__DEBUG:
9427 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9428 register_name = "Debug";
9429 break;
9430 case CP0_REG23__TRACECONTROL:
9431 /* PDtrace support */
9432 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9433 register_name = "TraceControl";
9434 goto cp0_unimplemented;
9435 case CP0_REG23__TRACECONTROL2:
9436 /* PDtrace support */
9437 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9438 register_name = "TraceControl2";
9439 goto cp0_unimplemented;
9440 case CP0_REG23__USERTRACEDATA1:
9441 /* PDtrace support */
9442 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9443 register_name = "UserTraceData1";
9444 goto cp0_unimplemented;
9445 case CP0_REG23__TRACEIBPC:
9446 /* PDtrace support */
9447 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9448 register_name = "TraceIBPC";
9449 goto cp0_unimplemented;
9450 case CP0_REG23__TRACEDBPC:
9451 /* PDtrace support */
9452 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9453 register_name = "TraceDBPC";
9454 goto cp0_unimplemented;
9455 default:
9456 goto cp0_unimplemented;
9458 break;
9459 case CP0_REGISTER_24:
9460 switch (sel) {
9461 case CP0_REG24__DEPC:
9462 /* EJTAG support */
9463 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9464 register_name = "DEPC";
9465 break;
9466 default:
9467 goto cp0_unimplemented;
9469 break;
9470 case CP0_REGISTER_25:
9471 switch (sel) {
9472 case CP0_REG25__PERFCTL0:
9473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9474 register_name = "Performance0";
9475 break;
9476 case CP0_REG25__PERFCNT0:
9477 /* gen_helper_dmfc0_performance1(arg); */
9478 register_name = "Performance1";
9479 goto cp0_unimplemented;
9480 case CP0_REG25__PERFCTL1:
9481 /* gen_helper_dmfc0_performance2(arg); */
9482 register_name = "Performance2";
9483 goto cp0_unimplemented;
9484 case CP0_REG25__PERFCNT1:
9485 /* gen_helper_dmfc0_performance3(arg); */
9486 register_name = "Performance3";
9487 goto cp0_unimplemented;
9488 case CP0_REG25__PERFCTL2:
9489 /* gen_helper_dmfc0_performance4(arg); */
9490 register_name = "Performance4";
9491 goto cp0_unimplemented;
9492 case CP0_REG25__PERFCNT2:
9493 /* gen_helper_dmfc0_performance5(arg); */
9494 register_name = "Performance5";
9495 goto cp0_unimplemented;
9496 case CP0_REG25__PERFCTL3:
9497 /* gen_helper_dmfc0_performance6(arg); */
9498 register_name = "Performance6";
9499 goto cp0_unimplemented;
9500 case CP0_REG25__PERFCNT3:
9501 /* gen_helper_dmfc0_performance7(arg); */
9502 register_name = "Performance7";
9503 goto cp0_unimplemented;
9504 default:
9505 goto cp0_unimplemented;
9507 break;
9508 case CP0_REGISTER_26:
9509 switch (sel) {
9510 case CP0_REG26__ERRCTL:
9511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9512 register_name = "ErrCtl";
9513 break;
9514 default:
9515 goto cp0_unimplemented;
9517 break;
9518 case CP0_REGISTER_27:
9519 switch (sel) {
9520 /* ignored */
9521 case CP0_REG27__CACHERR:
9522 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9523 register_name = "CacheErr";
9524 break;
9525 default:
9526 goto cp0_unimplemented;
9528 break;
9529 case CP0_REGISTER_28:
9530 switch (sel) {
9531 case CP0_REG28__TAGLO:
9532 case CP0_REG28__TAGLO1:
9533 case CP0_REG28__TAGLO2:
9534 case CP0_REG28__TAGLO3:
9535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9536 register_name = "TagLo";
9537 break;
9538 case CP0_REG28__DATALO:
9539 case CP0_REG28__DATALO1:
9540 case CP0_REG28__DATALO2:
9541 case CP0_REG28__DATALO3:
9542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9543 register_name = "DataLo";
9544 break;
9545 default:
9546 goto cp0_unimplemented;
9548 break;
9549 case CP0_REGISTER_29:
9550 switch (sel) {
9551 case CP0_REG29__TAGHI:
9552 case CP0_REG29__TAGHI1:
9553 case CP0_REG29__TAGHI2:
9554 case CP0_REG29__TAGHI3:
9555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9556 register_name = "TagHi";
9557 break;
9558 case CP0_REG29__DATAHI:
9559 case CP0_REG29__DATAHI1:
9560 case CP0_REG29__DATAHI2:
9561 case CP0_REG29__DATAHI3:
9562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9563 register_name = "DataHi";
9564 break;
9565 default:
9566 goto cp0_unimplemented;
9568 break;
9569 case CP0_REGISTER_30:
9570 switch (sel) {
9571 case CP0_REG30__ERROREPC:
9572 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9573 register_name = "ErrorEPC";
9574 break;
9575 default:
9576 goto cp0_unimplemented;
9578 break;
9579 case CP0_REGISTER_31:
9580 switch (sel) {
9581 case CP0_REG31__DESAVE:
9582 /* EJTAG support */
9583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9584 register_name = "DESAVE";
9585 break;
9586 case CP0_REG31__KSCRATCH1:
9587 case CP0_REG31__KSCRATCH2:
9588 case CP0_REG31__KSCRATCH3:
9589 case CP0_REG31__KSCRATCH4:
9590 case CP0_REG31__KSCRATCH5:
9591 case CP0_REG31__KSCRATCH6:
9592 CP0_CHECK(ctx->kscrexist & (1 << sel));
9593 tcg_gen_ld_tl(arg, cpu_env,
9594 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9595 register_name = "KScratch";
9596 break;
9597 default:
9598 goto cp0_unimplemented;
9600 break;
9601 default:
9602 goto cp0_unimplemented;
9604 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9605 return;
9607 cp0_unimplemented:
9608 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9609 register_name, reg, sel);
9610 gen_mfc0_unimplemented(ctx, arg);
9613 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9615 const char *register_name = "invalid";
9617 if (sel != 0) {
9618 check_insn(ctx, ISA_MIPS_R1);
9621 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9622 gen_io_start();
9625 switch (reg) {
9626 case CP0_REGISTER_00:
9627 switch (sel) {
9628 case CP0_REG00__INDEX:
9629 gen_helper_mtc0_index(cpu_env, arg);
9630 register_name = "Index";
9631 break;
9632 case CP0_REG00__MVPCONTROL:
9633 CP0_CHECK(ctx->insn_flags & ASE_MT);
9634 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9635 register_name = "MVPControl";
9636 break;
9637 case CP0_REG00__MVPCONF0:
9638 CP0_CHECK(ctx->insn_flags & ASE_MT);
9639 /* ignored */
9640 register_name = "MVPConf0";
9641 break;
9642 case CP0_REG00__MVPCONF1:
9643 CP0_CHECK(ctx->insn_flags & ASE_MT);
9644 /* ignored */
9645 register_name = "MVPConf1";
9646 break;
9647 case CP0_REG00__VPCONTROL:
9648 CP0_CHECK(ctx->vp);
9649 /* ignored */
9650 register_name = "VPControl";
9651 break;
9652 default:
9653 goto cp0_unimplemented;
9655 break;
9656 case CP0_REGISTER_01:
9657 switch (sel) {
9658 case CP0_REG01__RANDOM:
9659 /* ignored */
9660 register_name = "Random";
9661 break;
9662 case CP0_REG01__VPECONTROL:
9663 CP0_CHECK(ctx->insn_flags & ASE_MT);
9664 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9665 register_name = "VPEControl";
9666 break;
9667 case CP0_REG01__VPECONF0:
9668 CP0_CHECK(ctx->insn_flags & ASE_MT);
9669 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9670 register_name = "VPEConf0";
9671 break;
9672 case CP0_REG01__VPECONF1:
9673 CP0_CHECK(ctx->insn_flags & ASE_MT);
9674 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9675 register_name = "VPEConf1";
9676 break;
9677 case CP0_REG01__YQMASK:
9678 CP0_CHECK(ctx->insn_flags & ASE_MT);
9679 gen_helper_mtc0_yqmask(cpu_env, arg);
9680 register_name = "YQMask";
9681 break;
9682 case CP0_REG01__VPESCHEDULE:
9683 CP0_CHECK(ctx->insn_flags & ASE_MT);
9684 tcg_gen_st_tl(arg, cpu_env,
9685 offsetof(CPUMIPSState, CP0_VPESchedule));
9686 register_name = "VPESchedule";
9687 break;
9688 case CP0_REG01__VPESCHEFBACK:
9689 CP0_CHECK(ctx->insn_flags & ASE_MT);
9690 tcg_gen_st_tl(arg, cpu_env,
9691 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9692 register_name = "VPEScheFBack";
9693 break;
9694 case CP0_REG01__VPEOPT:
9695 CP0_CHECK(ctx->insn_flags & ASE_MT);
9696 gen_helper_mtc0_vpeopt(cpu_env, arg);
9697 register_name = "VPEOpt";
9698 break;
9699 default:
9700 goto cp0_unimplemented;
9702 break;
9703 case CP0_REGISTER_02:
9704 switch (sel) {
9705 case CP0_REG02__ENTRYLO0:
9706 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9707 register_name = "EntryLo0";
9708 break;
9709 case CP0_REG02__TCSTATUS:
9710 CP0_CHECK(ctx->insn_flags & ASE_MT);
9711 gen_helper_mtc0_tcstatus(cpu_env, arg);
9712 register_name = "TCStatus";
9713 break;
9714 case CP0_REG02__TCBIND:
9715 CP0_CHECK(ctx->insn_flags & ASE_MT);
9716 gen_helper_mtc0_tcbind(cpu_env, arg);
9717 register_name = "TCBind";
9718 break;
9719 case CP0_REG02__TCRESTART:
9720 CP0_CHECK(ctx->insn_flags & ASE_MT);
9721 gen_helper_mtc0_tcrestart(cpu_env, arg);
9722 register_name = "TCRestart";
9723 break;
9724 case CP0_REG02__TCHALT:
9725 CP0_CHECK(ctx->insn_flags & ASE_MT);
9726 gen_helper_mtc0_tchalt(cpu_env, arg);
9727 register_name = "TCHalt";
9728 break;
9729 case CP0_REG02__TCCONTEXT:
9730 CP0_CHECK(ctx->insn_flags & ASE_MT);
9731 gen_helper_mtc0_tccontext(cpu_env, arg);
9732 register_name = "TCContext";
9733 break;
9734 case CP0_REG02__TCSCHEDULE:
9735 CP0_CHECK(ctx->insn_flags & ASE_MT);
9736 gen_helper_mtc0_tcschedule(cpu_env, arg);
9737 register_name = "TCSchedule";
9738 break;
9739 case CP0_REG02__TCSCHEFBACK:
9740 CP0_CHECK(ctx->insn_flags & ASE_MT);
9741 gen_helper_mtc0_tcschefback(cpu_env, arg);
9742 register_name = "TCScheFBack";
9743 break;
9744 default:
9745 goto cp0_unimplemented;
9747 break;
9748 case CP0_REGISTER_03:
9749 switch (sel) {
9750 case CP0_REG03__ENTRYLO1:
9751 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9752 register_name = "EntryLo1";
9753 break;
9754 case CP0_REG03__GLOBALNUM:
9755 CP0_CHECK(ctx->vp);
9756 /* ignored */
9757 register_name = "GlobalNumber";
9758 break;
9759 default:
9760 goto cp0_unimplemented;
9762 break;
9763 case CP0_REGISTER_04:
9764 switch (sel) {
9765 case CP0_REG04__CONTEXT:
9766 gen_helper_mtc0_context(cpu_env, arg);
9767 register_name = "Context";
9768 break;
9769 case CP0_REG04__CONTEXTCONFIG:
9770 /* SmartMIPS ASE */
9771 /* gen_helper_dmtc0_contextconfig(arg); */
9772 register_name = "ContextConfig";
9773 goto cp0_unimplemented;
9774 case CP0_REG04__USERLOCAL:
9775 CP0_CHECK(ctx->ulri);
9776 tcg_gen_st_tl(arg, cpu_env,
9777 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9778 register_name = "UserLocal";
9779 break;
9780 case CP0_REG04__MMID:
9781 CP0_CHECK(ctx->mi);
9782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9783 register_name = "MMID";
9784 break;
9785 default:
9786 goto cp0_unimplemented;
9788 break;
9789 case CP0_REGISTER_05:
9790 switch (sel) {
9791 case CP0_REG05__PAGEMASK:
9792 gen_helper_mtc0_pagemask(cpu_env, arg);
9793 register_name = "PageMask";
9794 break;
9795 case CP0_REG05__PAGEGRAIN:
9796 check_insn(ctx, ISA_MIPS_R2);
9797 gen_helper_mtc0_pagegrain(cpu_env, arg);
9798 register_name = "PageGrain";
9799 break;
9800 case CP0_REG05__SEGCTL0:
9801 CP0_CHECK(ctx->sc);
9802 gen_helper_mtc0_segctl0(cpu_env, arg);
9803 register_name = "SegCtl0";
9804 break;
9805 case CP0_REG05__SEGCTL1:
9806 CP0_CHECK(ctx->sc);
9807 gen_helper_mtc0_segctl1(cpu_env, arg);
9808 register_name = "SegCtl1";
9809 break;
9810 case CP0_REG05__SEGCTL2:
9811 CP0_CHECK(ctx->sc);
9812 gen_helper_mtc0_segctl2(cpu_env, arg);
9813 register_name = "SegCtl2";
9814 break;
9815 case CP0_REG05__PWBASE:
9816 check_pw(ctx);
9817 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9818 register_name = "PWBase";
9819 break;
9820 case CP0_REG05__PWFIELD:
9821 check_pw(ctx);
9822 gen_helper_mtc0_pwfield(cpu_env, arg);
9823 register_name = "PWField";
9824 break;
9825 case CP0_REG05__PWSIZE:
9826 check_pw(ctx);
9827 gen_helper_mtc0_pwsize(cpu_env, arg);
9828 register_name = "PWSize";
9829 break;
9830 default:
9831 goto cp0_unimplemented;
9833 break;
9834 case CP0_REGISTER_06:
9835 switch (sel) {
9836 case CP0_REG06__WIRED:
9837 gen_helper_mtc0_wired(cpu_env, arg);
9838 register_name = "Wired";
9839 break;
9840 case CP0_REG06__SRSCONF0:
9841 check_insn(ctx, ISA_MIPS_R2);
9842 gen_helper_mtc0_srsconf0(cpu_env, arg);
9843 register_name = "SRSConf0";
9844 break;
9845 case CP0_REG06__SRSCONF1:
9846 check_insn(ctx, ISA_MIPS_R2);
9847 gen_helper_mtc0_srsconf1(cpu_env, arg);
9848 register_name = "SRSConf1";
9849 break;
9850 case CP0_REG06__SRSCONF2:
9851 check_insn(ctx, ISA_MIPS_R2);
9852 gen_helper_mtc0_srsconf2(cpu_env, arg);
9853 register_name = "SRSConf2";
9854 break;
9855 case CP0_REG06__SRSCONF3:
9856 check_insn(ctx, ISA_MIPS_R2);
9857 gen_helper_mtc0_srsconf3(cpu_env, arg);
9858 register_name = "SRSConf3";
9859 break;
9860 case CP0_REG06__SRSCONF4:
9861 check_insn(ctx, ISA_MIPS_R2);
9862 gen_helper_mtc0_srsconf4(cpu_env, arg);
9863 register_name = "SRSConf4";
9864 break;
9865 case CP0_REG06__PWCTL:
9866 check_pw(ctx);
9867 gen_helper_mtc0_pwctl(cpu_env, arg);
9868 register_name = "PWCtl";
9869 break;
9870 default:
9871 goto cp0_unimplemented;
9873 break;
9874 case CP0_REGISTER_07:
9875 switch (sel) {
9876 case CP0_REG07__HWRENA:
9877 check_insn(ctx, ISA_MIPS_R2);
9878 gen_helper_mtc0_hwrena(cpu_env, arg);
9879 ctx->base.is_jmp = DISAS_STOP;
9880 register_name = "HWREna";
9881 break;
9882 default:
9883 goto cp0_unimplemented;
9885 break;
9886 case CP0_REGISTER_08:
9887 switch (sel) {
9888 case CP0_REG08__BADVADDR:
9889 /* ignored */
9890 register_name = "BadVAddr";
9891 break;
9892 case CP0_REG08__BADINSTR:
9893 /* ignored */
9894 register_name = "BadInstr";
9895 break;
9896 case CP0_REG08__BADINSTRP:
9897 /* ignored */
9898 register_name = "BadInstrP";
9899 break;
9900 case CP0_REG08__BADINSTRX:
9901 /* ignored */
9902 register_name = "BadInstrX";
9903 break;
9904 default:
9905 goto cp0_unimplemented;
9907 break;
9908 case CP0_REGISTER_09:
9909 switch (sel) {
9910 case CP0_REG09__COUNT:
9911 gen_helper_mtc0_count(cpu_env, arg);
9912 register_name = "Count";
9913 break;
9914 case CP0_REG09__SAARI:
9915 CP0_CHECK(ctx->saar);
9916 gen_helper_mtc0_saari(cpu_env, arg);
9917 register_name = "SAARI";
9918 break;
9919 case CP0_REG09__SAAR:
9920 CP0_CHECK(ctx->saar);
9921 gen_helper_mtc0_saar(cpu_env, arg);
9922 register_name = "SAAR";
9923 break;
9924 default:
9925 goto cp0_unimplemented;
9927 /* Stop translation as we may have switched the execution mode */
9928 ctx->base.is_jmp = DISAS_STOP;
9929 break;
9930 case CP0_REGISTER_10:
9931 switch (sel) {
9932 case CP0_REG10__ENTRYHI:
9933 gen_helper_mtc0_entryhi(cpu_env, arg);
9934 register_name = "EntryHi";
9935 break;
9936 default:
9937 goto cp0_unimplemented;
9939 break;
9940 case CP0_REGISTER_11:
9941 switch (sel) {
9942 case CP0_REG11__COMPARE:
9943 gen_helper_mtc0_compare(cpu_env, arg);
9944 register_name = "Compare";
9945 break;
9946 /* 6,7 are implementation dependent */
9947 default:
9948 goto cp0_unimplemented;
9950 /* Stop translation as we may have switched the execution mode */
9951 ctx->base.is_jmp = DISAS_STOP;
9952 break;
9953 case CP0_REGISTER_12:
9954 switch (sel) {
9955 case CP0_REG12__STATUS:
9956 save_cpu_state(ctx, 1);
9957 gen_helper_mtc0_status(cpu_env, arg);
9958 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9959 gen_save_pc(ctx->base.pc_next + 4);
9960 ctx->base.is_jmp = DISAS_EXIT;
9961 register_name = "Status";
9962 break;
9963 case CP0_REG12__INTCTL:
9964 check_insn(ctx, ISA_MIPS_R2);
9965 gen_helper_mtc0_intctl(cpu_env, arg);
9966 /* Stop translation as we may have switched the execution mode */
9967 ctx->base.is_jmp = DISAS_STOP;
9968 register_name = "IntCtl";
9969 break;
9970 case CP0_REG12__SRSCTL:
9971 check_insn(ctx, ISA_MIPS_R2);
9972 gen_helper_mtc0_srsctl(cpu_env, arg);
9973 /* Stop translation as we may have switched the execution mode */
9974 ctx->base.is_jmp = DISAS_STOP;
9975 register_name = "SRSCtl";
9976 break;
9977 case CP0_REG12__SRSMAP:
9978 check_insn(ctx, ISA_MIPS_R2);
9979 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9980 /* Stop translation as we may have switched the execution mode */
9981 ctx->base.is_jmp = DISAS_STOP;
9982 register_name = "SRSMap";
9983 break;
9984 default:
9985 goto cp0_unimplemented;
9987 break;
9988 case CP0_REGISTER_13:
9989 switch (sel) {
9990 case CP0_REG13__CAUSE:
9991 save_cpu_state(ctx, 1);
9992 gen_helper_mtc0_cause(cpu_env, arg);
9994 * Stop translation as we may have triggered an interrupt.
9995 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9996 * translated code to check for pending interrupts.
9998 gen_save_pc(ctx->base.pc_next + 4);
9999 ctx->base.is_jmp = DISAS_EXIT;
10000 register_name = "Cause";
10001 break;
10002 default:
10003 goto cp0_unimplemented;
10005 break;
10006 case CP0_REGISTER_14:
10007 switch (sel) {
10008 case CP0_REG14__EPC:
10009 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
10010 register_name = "EPC";
10011 break;
10012 default:
10013 goto cp0_unimplemented;
10015 break;
10016 case CP0_REGISTER_15:
10017 switch (sel) {
10018 case CP0_REG15__PRID:
10019 /* ignored */
10020 register_name = "PRid";
10021 break;
10022 case CP0_REG15__EBASE:
10023 check_insn(ctx, ISA_MIPS_R2);
10024 gen_helper_mtc0_ebase(cpu_env, arg);
10025 register_name = "EBase";
10026 break;
10027 default:
10028 goto cp0_unimplemented;
10030 break;
10031 case CP0_REGISTER_16:
10032 switch (sel) {
10033 case CP0_REG16__CONFIG:
10034 gen_helper_mtc0_config0(cpu_env, arg);
10035 register_name = "Config";
10036 /* Stop translation as we may have switched the execution mode */
10037 ctx->base.is_jmp = DISAS_STOP;
10038 break;
10039 case CP0_REG16__CONFIG1:
10040 /* ignored, read only */
10041 register_name = "Config1";
10042 break;
10043 case CP0_REG16__CONFIG2:
10044 gen_helper_mtc0_config2(cpu_env, arg);
10045 register_name = "Config2";
10046 /* Stop translation as we may have switched the execution mode */
10047 ctx->base.is_jmp = DISAS_STOP;
10048 break;
10049 case CP0_REG16__CONFIG3:
10050 gen_helper_mtc0_config3(cpu_env, arg);
10051 register_name = "Config3";
10052 /* Stop translation as we may have switched the execution mode */
10053 ctx->base.is_jmp = DISAS_STOP;
10054 break;
10055 case CP0_REG16__CONFIG4:
10056 /* currently ignored */
10057 register_name = "Config4";
10058 break;
10059 case CP0_REG16__CONFIG5:
10060 gen_helper_mtc0_config5(cpu_env, arg);
10061 register_name = "Config5";
10062 /* Stop translation as we may have switched the execution mode */
10063 ctx->base.is_jmp = DISAS_STOP;
10064 break;
10065 /* 6,7 are implementation dependent */
10066 default:
10067 register_name = "Invalid config selector";
10068 goto cp0_unimplemented;
10070 break;
10071 case CP0_REGISTER_17:
10072 switch (sel) {
10073 case CP0_REG17__LLADDR:
10074 gen_helper_mtc0_lladdr(cpu_env, arg);
10075 register_name = "LLAddr";
10076 break;
10077 case CP0_REG17__MAAR:
10078 CP0_CHECK(ctx->mrp);
10079 gen_helper_mtc0_maar(cpu_env, arg);
10080 register_name = "MAAR";
10081 break;
10082 case CP0_REG17__MAARI:
10083 CP0_CHECK(ctx->mrp);
10084 gen_helper_mtc0_maari(cpu_env, arg);
10085 register_name = "MAARI";
10086 break;
10087 default:
10088 goto cp0_unimplemented;
10090 break;
10091 case CP0_REGISTER_18:
10092 switch (sel) {
10093 case CP0_REG18__WATCHLO0:
10094 case CP0_REG18__WATCHLO1:
10095 case CP0_REG18__WATCHLO2:
10096 case CP0_REG18__WATCHLO3:
10097 case CP0_REG18__WATCHLO4:
10098 case CP0_REG18__WATCHLO5:
10099 case CP0_REG18__WATCHLO6:
10100 case CP0_REG18__WATCHLO7:
10101 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10102 gen_helper_0e1i(mtc0_watchlo, arg, sel);
10103 register_name = "WatchLo";
10104 break;
10105 default:
10106 goto cp0_unimplemented;
10108 break;
10109 case CP0_REGISTER_19:
10110 switch (sel) {
10111 case CP0_REG19__WATCHHI0:
10112 case CP0_REG19__WATCHHI1:
10113 case CP0_REG19__WATCHHI2:
10114 case CP0_REG19__WATCHHI3:
10115 case CP0_REG19__WATCHHI4:
10116 case CP0_REG19__WATCHHI5:
10117 case CP0_REG19__WATCHHI6:
10118 case CP0_REG19__WATCHHI7:
10119 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10120 gen_helper_0e1i(mtc0_watchhi, arg, sel);
10121 register_name = "WatchHi";
10122 break;
10123 default:
10124 goto cp0_unimplemented;
10126 break;
10127 case CP0_REGISTER_20:
10128 switch (sel) {
10129 case CP0_REG20__XCONTEXT:
10130 check_insn(ctx, ISA_MIPS3);
10131 gen_helper_mtc0_xcontext(cpu_env, arg);
10132 register_name = "XContext";
10133 break;
10134 default:
10135 goto cp0_unimplemented;
10137 break;
10138 case CP0_REGISTER_21:
10139 /* Officially reserved, but sel 0 is used for R1x000 framemask */
10140 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
10141 switch (sel) {
10142 case 0:
10143 gen_helper_mtc0_framemask(cpu_env, arg);
10144 register_name = "Framemask";
10145 break;
10146 default:
10147 goto cp0_unimplemented;
10149 break;
10150 case CP0_REGISTER_22:
10151 /* ignored */
10152 register_name = "Diagnostic"; /* implementation dependent */
10153 break;
10154 case CP0_REGISTER_23:
10155 switch (sel) {
10156 case CP0_REG23__DEBUG:
10157 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
10158 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10159 gen_save_pc(ctx->base.pc_next + 4);
10160 ctx->base.is_jmp = DISAS_EXIT;
10161 register_name = "Debug";
10162 break;
10163 case CP0_REG23__TRACECONTROL:
10164 /* PDtrace support */
10165 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
10166 /* Stop translation as we may have switched the execution mode */
10167 ctx->base.is_jmp = DISAS_STOP;
10168 register_name = "TraceControl";
10169 goto cp0_unimplemented;
10170 case CP0_REG23__TRACECONTROL2:
10171 /* PDtrace support */
10172 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
10173 /* Stop translation as we may have switched the execution mode */
10174 ctx->base.is_jmp = DISAS_STOP;
10175 register_name = "TraceControl2";
10176 goto cp0_unimplemented;
10177 case CP0_REG23__USERTRACEDATA1:
10178 /* PDtrace support */
10179 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
10180 /* Stop translation as we may have switched the execution mode */
10181 ctx->base.is_jmp = DISAS_STOP;
10182 register_name = "UserTraceData1";
10183 goto cp0_unimplemented;
10184 case CP0_REG23__TRACEIBPC:
10185 /* PDtrace support */
10186 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
10187 /* Stop translation as we may have switched the execution mode */
10188 ctx->base.is_jmp = DISAS_STOP;
10189 register_name = "TraceIBPC";
10190 goto cp0_unimplemented;
10191 case CP0_REG23__TRACEDBPC:
10192 /* PDtrace support */
10193 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
10194 /* Stop translation as we may have switched the execution mode */
10195 ctx->base.is_jmp = DISAS_STOP;
10196 register_name = "TraceDBPC";
10197 goto cp0_unimplemented;
10198 default:
10199 goto cp0_unimplemented;
10201 break;
10202 case CP0_REGISTER_24:
10203 switch (sel) {
10204 case CP0_REG24__DEPC:
10205 /* EJTAG support */
10206 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
10207 register_name = "DEPC";
10208 break;
10209 default:
10210 goto cp0_unimplemented;
10212 break;
10213 case CP0_REGISTER_25:
10214 switch (sel) {
10215 case CP0_REG25__PERFCTL0:
10216 gen_helper_mtc0_performance0(cpu_env, arg);
10217 register_name = "Performance0";
10218 break;
10219 case CP0_REG25__PERFCNT0:
10220 /* gen_helper_mtc0_performance1(cpu_env, arg); */
10221 register_name = "Performance1";
10222 goto cp0_unimplemented;
10223 case CP0_REG25__PERFCTL1:
10224 /* gen_helper_mtc0_performance2(cpu_env, arg); */
10225 register_name = "Performance2";
10226 goto cp0_unimplemented;
10227 case CP0_REG25__PERFCNT1:
10228 /* gen_helper_mtc0_performance3(cpu_env, arg); */
10229 register_name = "Performance3";
10230 goto cp0_unimplemented;
10231 case CP0_REG25__PERFCTL2:
10232 /* gen_helper_mtc0_performance4(cpu_env, arg); */
10233 register_name = "Performance4";
10234 goto cp0_unimplemented;
10235 case CP0_REG25__PERFCNT2:
10236 /* gen_helper_mtc0_performance5(cpu_env, arg); */
10237 register_name = "Performance5";
10238 goto cp0_unimplemented;
10239 case CP0_REG25__PERFCTL3:
10240 /* gen_helper_mtc0_performance6(cpu_env, arg); */
10241 register_name = "Performance6";
10242 goto cp0_unimplemented;
10243 case CP0_REG25__PERFCNT3:
10244 /* gen_helper_mtc0_performance7(cpu_env, arg); */
10245 register_name = "Performance7";
10246 goto cp0_unimplemented;
10247 default:
10248 goto cp0_unimplemented;
10250 break;
10251 case CP0_REGISTER_26:
10252 switch (sel) {
10253 case CP0_REG26__ERRCTL:
10254 gen_helper_mtc0_errctl(cpu_env, arg);
10255 ctx->base.is_jmp = DISAS_STOP;
10256 register_name = "ErrCtl";
10257 break;
10258 default:
10259 goto cp0_unimplemented;
10261 break;
10262 case CP0_REGISTER_27:
10263 switch (sel) {
10264 case CP0_REG27__CACHERR:
10265 /* ignored */
10266 register_name = "CacheErr";
10267 break;
10268 default:
10269 goto cp0_unimplemented;
10271 break;
10272 case CP0_REGISTER_28:
10273 switch (sel) {
10274 case CP0_REG28__TAGLO:
10275 case CP0_REG28__TAGLO1:
10276 case CP0_REG28__TAGLO2:
10277 case CP0_REG28__TAGLO3:
10278 gen_helper_mtc0_taglo(cpu_env, arg);
10279 register_name = "TagLo";
10280 break;
10281 case CP0_REG28__DATALO:
10282 case CP0_REG28__DATALO1:
10283 case CP0_REG28__DATALO2:
10284 case CP0_REG28__DATALO3:
10285 gen_helper_mtc0_datalo(cpu_env, arg);
10286 register_name = "DataLo";
10287 break;
10288 default:
10289 goto cp0_unimplemented;
10291 break;
10292 case CP0_REGISTER_29:
10293 switch (sel) {
10294 case CP0_REG29__TAGHI:
10295 case CP0_REG29__TAGHI1:
10296 case CP0_REG29__TAGHI2:
10297 case CP0_REG29__TAGHI3:
10298 gen_helper_mtc0_taghi(cpu_env, arg);
10299 register_name = "TagHi";
10300 break;
10301 case CP0_REG29__DATAHI:
10302 case CP0_REG29__DATAHI1:
10303 case CP0_REG29__DATAHI2:
10304 case CP0_REG29__DATAHI3:
10305 gen_helper_mtc0_datahi(cpu_env, arg);
10306 register_name = "DataHi";
10307 break;
10308 default:
10309 register_name = "invalid sel";
10310 goto cp0_unimplemented;
10312 break;
10313 case CP0_REGISTER_30:
10314 switch (sel) {
10315 case CP0_REG30__ERROREPC:
10316 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
10317 register_name = "ErrorEPC";
10318 break;
10319 default:
10320 goto cp0_unimplemented;
10322 break;
10323 case CP0_REGISTER_31:
10324 switch (sel) {
10325 case CP0_REG31__DESAVE:
10326 /* EJTAG support */
10327 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
10328 register_name = "DESAVE";
10329 break;
10330 case CP0_REG31__KSCRATCH1:
10331 case CP0_REG31__KSCRATCH2:
10332 case CP0_REG31__KSCRATCH3:
10333 case CP0_REG31__KSCRATCH4:
10334 case CP0_REG31__KSCRATCH5:
10335 case CP0_REG31__KSCRATCH6:
10336 CP0_CHECK(ctx->kscrexist & (1 << sel));
10337 tcg_gen_st_tl(arg, cpu_env,
10338 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
10339 register_name = "KScratch";
10340 break;
10341 default:
10342 goto cp0_unimplemented;
10344 break;
10345 default:
10346 goto cp0_unimplemented;
10348 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
10350 /* For simplicity assume that all writes can cause interrupts. */
10351 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
10353 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10354 * translated code to check for pending interrupts.
10356 gen_save_pc(ctx->base.pc_next + 4);
10357 ctx->base.is_jmp = DISAS_EXIT;
10359 return;
10361 cp0_unimplemented:
10362 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10363 register_name, reg, sel);
10365 #endif /* TARGET_MIPS64 */
10367 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10368 int u, int sel, int h)
10370 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10371 TCGv t0 = tcg_temp_local_new();
10373 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10374 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10375 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10376 tcg_gen_movi_tl(t0, -1);
10377 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10378 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10379 tcg_gen_movi_tl(t0, -1);
10380 } else if (u == 0) {
10381 switch (rt) {
10382 case 1:
10383 switch (sel) {
10384 case 1:
10385 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10386 break;
10387 case 2:
10388 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10389 break;
10390 default:
10391 goto die;
10392 break;
10394 break;
10395 case 2:
10396 switch (sel) {
10397 case 1:
10398 gen_helper_mftc0_tcstatus(t0, cpu_env);
10399 break;
10400 case 2:
10401 gen_helper_mftc0_tcbind(t0, cpu_env);
10402 break;
10403 case 3:
10404 gen_helper_mftc0_tcrestart(t0, cpu_env);
10405 break;
10406 case 4:
10407 gen_helper_mftc0_tchalt(t0, cpu_env);
10408 break;
10409 case 5:
10410 gen_helper_mftc0_tccontext(t0, cpu_env);
10411 break;
10412 case 6:
10413 gen_helper_mftc0_tcschedule(t0, cpu_env);
10414 break;
10415 case 7:
10416 gen_helper_mftc0_tcschefback(t0, cpu_env);
10417 break;
10418 default:
10419 gen_mfc0(ctx, t0, rt, sel);
10420 break;
10422 break;
10423 case 10:
10424 switch (sel) {
10425 case 0:
10426 gen_helper_mftc0_entryhi(t0, cpu_env);
10427 break;
10428 default:
10429 gen_mfc0(ctx, t0, rt, sel);
10430 break;
10432 break;
10433 case 12:
10434 switch (sel) {
10435 case 0:
10436 gen_helper_mftc0_status(t0, cpu_env);
10437 break;
10438 default:
10439 gen_mfc0(ctx, t0, rt, sel);
10440 break;
10442 break;
10443 case 13:
10444 switch (sel) {
10445 case 0:
10446 gen_helper_mftc0_cause(t0, cpu_env);
10447 break;
10448 default:
10449 goto die;
10450 break;
10452 break;
10453 case 14:
10454 switch (sel) {
10455 case 0:
10456 gen_helper_mftc0_epc(t0, cpu_env);
10457 break;
10458 default:
10459 goto die;
10460 break;
10462 break;
10463 case 15:
10464 switch (sel) {
10465 case 1:
10466 gen_helper_mftc0_ebase(t0, cpu_env);
10467 break;
10468 default:
10469 goto die;
10470 break;
10472 break;
10473 case 16:
10474 switch (sel) {
10475 case 0:
10476 case 1:
10477 case 2:
10478 case 3:
10479 case 4:
10480 case 5:
10481 case 6:
10482 case 7:
10483 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10484 break;
10485 default:
10486 goto die;
10487 break;
10489 break;
10490 case 23:
10491 switch (sel) {
10492 case 0:
10493 gen_helper_mftc0_debug(t0, cpu_env);
10494 break;
10495 default:
10496 gen_mfc0(ctx, t0, rt, sel);
10497 break;
10499 break;
10500 default:
10501 gen_mfc0(ctx, t0, rt, sel);
10503 } else {
10504 switch (sel) {
10505 /* GPR registers. */
10506 case 0:
10507 gen_helper_1e0i(mftgpr, t0, rt);
10508 break;
10509 /* Auxiliary CPU registers */
10510 case 1:
10511 switch (rt) {
10512 case 0:
10513 gen_helper_1e0i(mftlo, t0, 0);
10514 break;
10515 case 1:
10516 gen_helper_1e0i(mfthi, t0, 0);
10517 break;
10518 case 2:
10519 gen_helper_1e0i(mftacx, t0, 0);
10520 break;
10521 case 4:
10522 gen_helper_1e0i(mftlo, t0, 1);
10523 break;
10524 case 5:
10525 gen_helper_1e0i(mfthi, t0, 1);
10526 break;
10527 case 6:
10528 gen_helper_1e0i(mftacx, t0, 1);
10529 break;
10530 case 8:
10531 gen_helper_1e0i(mftlo, t0, 2);
10532 break;
10533 case 9:
10534 gen_helper_1e0i(mfthi, t0, 2);
10535 break;
10536 case 10:
10537 gen_helper_1e0i(mftacx, t0, 2);
10538 break;
10539 case 12:
10540 gen_helper_1e0i(mftlo, t0, 3);
10541 break;
10542 case 13:
10543 gen_helper_1e0i(mfthi, t0, 3);
10544 break;
10545 case 14:
10546 gen_helper_1e0i(mftacx, t0, 3);
10547 break;
10548 case 16:
10549 gen_helper_mftdsp(t0, cpu_env);
10550 break;
10551 default:
10552 goto die;
10554 break;
10555 /* Floating point (COP1). */
10556 case 2:
10557 /* XXX: For now we support only a single FPU context. */
10558 if (h == 0) {
10559 TCGv_i32 fp0 = tcg_temp_new_i32();
10561 gen_load_fpr32(ctx, fp0, rt);
10562 tcg_gen_ext_i32_tl(t0, fp0);
10563 tcg_temp_free_i32(fp0);
10564 } else {
10565 TCGv_i32 fp0 = tcg_temp_new_i32();
10567 gen_load_fpr32h(ctx, fp0, rt);
10568 tcg_gen_ext_i32_tl(t0, fp0);
10569 tcg_temp_free_i32(fp0);
10571 break;
10572 case 3:
10573 /* XXX: For now we support only a single FPU context. */
10574 gen_helper_1e0i(cfc1, t0, rt);
10575 break;
10576 /* COP2: Not implemented. */
10577 case 4:
10578 case 5:
10579 /* fall through */
10580 default:
10581 goto die;
10584 trace_mips_translate_tr("mftr", rt, u, sel, h);
10585 gen_store_gpr(t0, rd);
10586 tcg_temp_free(t0);
10587 return;
10589 die:
10590 tcg_temp_free(t0);
10591 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10592 gen_reserved_instruction(ctx);
10595 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10596 int u, int sel, int h)
10598 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10599 TCGv t0 = tcg_temp_local_new();
10601 gen_load_gpr(t0, rt);
10602 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10603 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10604 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10605 /* NOP */
10607 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10608 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10609 /* NOP */
10611 } else if (u == 0) {
10612 switch (rd) {
10613 case 1:
10614 switch (sel) {
10615 case 1:
10616 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10617 break;
10618 case 2:
10619 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10620 break;
10621 default:
10622 goto die;
10623 break;
10625 break;
10626 case 2:
10627 switch (sel) {
10628 case 1:
10629 gen_helper_mttc0_tcstatus(cpu_env, t0);
10630 break;
10631 case 2:
10632 gen_helper_mttc0_tcbind(cpu_env, t0);
10633 break;
10634 case 3:
10635 gen_helper_mttc0_tcrestart(cpu_env, t0);
10636 break;
10637 case 4:
10638 gen_helper_mttc0_tchalt(cpu_env, t0);
10639 break;
10640 case 5:
10641 gen_helper_mttc0_tccontext(cpu_env, t0);
10642 break;
10643 case 6:
10644 gen_helper_mttc0_tcschedule(cpu_env, t0);
10645 break;
10646 case 7:
10647 gen_helper_mttc0_tcschefback(cpu_env, t0);
10648 break;
10649 default:
10650 gen_mtc0(ctx, t0, rd, sel);
10651 break;
10653 break;
10654 case 10:
10655 switch (sel) {
10656 case 0:
10657 gen_helper_mttc0_entryhi(cpu_env, t0);
10658 break;
10659 default:
10660 gen_mtc0(ctx, t0, rd, sel);
10661 break;
10663 break;
10664 case 12:
10665 switch (sel) {
10666 case 0:
10667 gen_helper_mttc0_status(cpu_env, t0);
10668 break;
10669 default:
10670 gen_mtc0(ctx, t0, rd, sel);
10671 break;
10673 break;
10674 case 13:
10675 switch (sel) {
10676 case 0:
10677 gen_helper_mttc0_cause(cpu_env, t0);
10678 break;
10679 default:
10680 goto die;
10681 break;
10683 break;
10684 case 15:
10685 switch (sel) {
10686 case 1:
10687 gen_helper_mttc0_ebase(cpu_env, t0);
10688 break;
10689 default:
10690 goto die;
10691 break;
10693 break;
10694 case 23:
10695 switch (sel) {
10696 case 0:
10697 gen_helper_mttc0_debug(cpu_env, t0);
10698 break;
10699 default:
10700 gen_mtc0(ctx, t0, rd, sel);
10701 break;
10703 break;
10704 default:
10705 gen_mtc0(ctx, t0, rd, sel);
10707 } else {
10708 switch (sel) {
10709 /* GPR registers. */
10710 case 0:
10711 gen_helper_0e1i(mttgpr, t0, rd);
10712 break;
10713 /* Auxiliary CPU registers */
10714 case 1:
10715 switch (rd) {
10716 case 0:
10717 gen_helper_0e1i(mttlo, t0, 0);
10718 break;
10719 case 1:
10720 gen_helper_0e1i(mtthi, t0, 0);
10721 break;
10722 case 2:
10723 gen_helper_0e1i(mttacx, t0, 0);
10724 break;
10725 case 4:
10726 gen_helper_0e1i(mttlo, t0, 1);
10727 break;
10728 case 5:
10729 gen_helper_0e1i(mtthi, t0, 1);
10730 break;
10731 case 6:
10732 gen_helper_0e1i(mttacx, t0, 1);
10733 break;
10734 case 8:
10735 gen_helper_0e1i(mttlo, t0, 2);
10736 break;
10737 case 9:
10738 gen_helper_0e1i(mtthi, t0, 2);
10739 break;
10740 case 10:
10741 gen_helper_0e1i(mttacx, t0, 2);
10742 break;
10743 case 12:
10744 gen_helper_0e1i(mttlo, t0, 3);
10745 break;
10746 case 13:
10747 gen_helper_0e1i(mtthi, t0, 3);
10748 break;
10749 case 14:
10750 gen_helper_0e1i(mttacx, t0, 3);
10751 break;
10752 case 16:
10753 gen_helper_mttdsp(cpu_env, t0);
10754 break;
10755 default:
10756 goto die;
10758 break;
10759 /* Floating point (COP1). */
10760 case 2:
10761 /* XXX: For now we support only a single FPU context. */
10762 if (h == 0) {
10763 TCGv_i32 fp0 = tcg_temp_new_i32();
10765 tcg_gen_trunc_tl_i32(fp0, t0);
10766 gen_store_fpr32(ctx, fp0, rd);
10767 tcg_temp_free_i32(fp0);
10768 } else {
10769 TCGv_i32 fp0 = tcg_temp_new_i32();
10771 tcg_gen_trunc_tl_i32(fp0, t0);
10772 gen_store_fpr32h(ctx, fp0, rd);
10773 tcg_temp_free_i32(fp0);
10775 break;
10776 case 3:
10777 /* XXX: For now we support only a single FPU context. */
10779 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10781 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10782 tcg_temp_free_i32(fs_tmp);
10784 /* Stop translation as we may have changed hflags */
10785 ctx->base.is_jmp = DISAS_STOP;
10786 break;
10787 /* COP2: Not implemented. */
10788 case 4:
10789 case 5:
10790 /* fall through */
10791 default:
10792 goto die;
10795 trace_mips_translate_tr("mttr", rd, u, sel, h);
10796 tcg_temp_free(t0);
10797 return;
10799 die:
10800 tcg_temp_free(t0);
10801 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10802 gen_reserved_instruction(ctx);
10805 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10806 int rt, int rd)
10808 const char *opn = "ldst";
10810 check_cp0_enabled(ctx);
10811 switch (opc) {
10812 case OPC_MFC0:
10813 if (rt == 0) {
10814 /* Treat as NOP. */
10815 return;
10817 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10818 opn = "mfc0";
10819 break;
10820 case OPC_MTC0:
10822 TCGv t0 = tcg_temp_new();
10824 gen_load_gpr(t0, rt);
10825 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10826 tcg_temp_free(t0);
10828 opn = "mtc0";
10829 break;
10830 #if defined(TARGET_MIPS64)
10831 case OPC_DMFC0:
10832 check_insn(ctx, ISA_MIPS3);
10833 if (rt == 0) {
10834 /* Treat as NOP. */
10835 return;
10837 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10838 opn = "dmfc0";
10839 break;
10840 case OPC_DMTC0:
10841 check_insn(ctx, ISA_MIPS3);
10843 TCGv t0 = tcg_temp_new();
10845 gen_load_gpr(t0, rt);
10846 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10847 tcg_temp_free(t0);
10849 opn = "dmtc0";
10850 break;
10851 #endif
10852 case OPC_MFHC0:
10853 check_mvh(ctx);
10854 if (rt == 0) {
10855 /* Treat as NOP. */
10856 return;
10858 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10859 opn = "mfhc0";
10860 break;
10861 case OPC_MTHC0:
10862 check_mvh(ctx);
10864 TCGv t0 = tcg_temp_new();
10865 gen_load_gpr(t0, rt);
10866 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10867 tcg_temp_free(t0);
10869 opn = "mthc0";
10870 break;
10871 case OPC_MFTR:
10872 check_cp0_enabled(ctx);
10873 if (rd == 0) {
10874 /* Treat as NOP. */
10875 return;
10877 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10878 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10879 opn = "mftr";
10880 break;
10881 case OPC_MTTR:
10882 check_cp0_enabled(ctx);
10883 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10884 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10885 opn = "mttr";
10886 break;
10887 case OPC_TLBWI:
10888 opn = "tlbwi";
10889 if (!env->tlb->helper_tlbwi) {
10890 goto die;
10892 gen_helper_tlbwi(cpu_env);
10893 break;
10894 case OPC_TLBINV:
10895 opn = "tlbinv";
10896 if (ctx->ie >= 2) {
10897 if (!env->tlb->helper_tlbinv) {
10898 goto die;
10900 gen_helper_tlbinv(cpu_env);
10901 } /* treat as nop if TLBINV not supported */
10902 break;
10903 case OPC_TLBINVF:
10904 opn = "tlbinvf";
10905 if (ctx->ie >= 2) {
10906 if (!env->tlb->helper_tlbinvf) {
10907 goto die;
10909 gen_helper_tlbinvf(cpu_env);
10910 } /* treat as nop if TLBINV not supported */
10911 break;
10912 case OPC_TLBWR:
10913 opn = "tlbwr";
10914 if (!env->tlb->helper_tlbwr) {
10915 goto die;
10917 gen_helper_tlbwr(cpu_env);
10918 break;
10919 case OPC_TLBP:
10920 opn = "tlbp";
10921 if (!env->tlb->helper_tlbp) {
10922 goto die;
10924 gen_helper_tlbp(cpu_env);
10925 break;
10926 case OPC_TLBR:
10927 opn = "tlbr";
10928 if (!env->tlb->helper_tlbr) {
10929 goto die;
10931 gen_helper_tlbr(cpu_env);
10932 break;
10933 case OPC_ERET: /* OPC_ERETNC */
10934 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10935 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10936 goto die;
10937 } else {
10938 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10939 if (ctx->opcode & (1 << bit_shift)) {
10940 /* OPC_ERETNC */
10941 opn = "eretnc";
10942 check_insn(ctx, ISA_MIPS_R5);
10943 gen_helper_eretnc(cpu_env);
10944 } else {
10945 /* OPC_ERET */
10946 opn = "eret";
10947 check_insn(ctx, ISA_MIPS2);
10948 gen_helper_eret(cpu_env);
10950 ctx->base.is_jmp = DISAS_EXIT;
10952 break;
10953 case OPC_DERET:
10954 opn = "deret";
10955 check_insn(ctx, ISA_MIPS_R1);
10956 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10957 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10958 goto die;
10960 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10961 MIPS_INVAL(opn);
10962 gen_reserved_instruction(ctx);
10963 } else {
10964 gen_helper_deret(cpu_env);
10965 ctx->base.is_jmp = DISAS_EXIT;
10967 break;
10968 case OPC_WAIT:
10969 opn = "wait";
10970 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10971 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10972 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10973 goto die;
10975 /* If we get an exception, we want to restart at next instruction */
10976 ctx->base.pc_next += 4;
10977 save_cpu_state(ctx, 1);
10978 ctx->base.pc_next -= 4;
10979 gen_helper_wait(cpu_env);
10980 ctx->base.is_jmp = DISAS_NORETURN;
10981 break;
10982 default:
10983 die:
10984 MIPS_INVAL(opn);
10985 gen_reserved_instruction(ctx);
10986 return;
10988 (void)opn; /* avoid a compiler warning */
10990 #endif /* !CONFIG_USER_ONLY */
10992 /* CP1 Branches (before delay slot) */
10993 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10994 int32_t cc, int32_t offset)
10996 target_ulong btarget;
10997 TCGv_i32 t0 = tcg_temp_new_i32();
10999 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11000 gen_reserved_instruction(ctx);
11001 goto out;
11004 if (cc != 0) {
11005 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
11008 btarget = ctx->base.pc_next + 4 + offset;
11010 switch (op) {
11011 case OPC_BC1F:
11012 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11013 tcg_gen_not_i32(t0, t0);
11014 tcg_gen_andi_i32(t0, t0, 1);
11015 tcg_gen_extu_i32_tl(bcond, t0);
11016 goto not_likely;
11017 case OPC_BC1FL:
11018 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11019 tcg_gen_not_i32(t0, t0);
11020 tcg_gen_andi_i32(t0, t0, 1);
11021 tcg_gen_extu_i32_tl(bcond, t0);
11022 goto likely;
11023 case OPC_BC1T:
11024 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11025 tcg_gen_andi_i32(t0, t0, 1);
11026 tcg_gen_extu_i32_tl(bcond, t0);
11027 goto not_likely;
11028 case OPC_BC1TL:
11029 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11030 tcg_gen_andi_i32(t0, t0, 1);
11031 tcg_gen_extu_i32_tl(bcond, t0);
11032 likely:
11033 ctx->hflags |= MIPS_HFLAG_BL;
11034 break;
11035 case OPC_BC1FANY2:
11037 TCGv_i32 t1 = tcg_temp_new_i32();
11038 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11039 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11040 tcg_gen_nand_i32(t0, t0, t1);
11041 tcg_temp_free_i32(t1);
11042 tcg_gen_andi_i32(t0, t0, 1);
11043 tcg_gen_extu_i32_tl(bcond, t0);
11045 goto not_likely;
11046 case OPC_BC1TANY2:
11048 TCGv_i32 t1 = tcg_temp_new_i32();
11049 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11050 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11051 tcg_gen_or_i32(t0, t0, t1);
11052 tcg_temp_free_i32(t1);
11053 tcg_gen_andi_i32(t0, t0, 1);
11054 tcg_gen_extu_i32_tl(bcond, t0);
11056 goto not_likely;
11057 case OPC_BC1FANY4:
11059 TCGv_i32 t1 = tcg_temp_new_i32();
11060 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11061 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11062 tcg_gen_and_i32(t0, t0, t1);
11063 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11064 tcg_gen_and_i32(t0, t0, t1);
11065 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11066 tcg_gen_nand_i32(t0, t0, t1);
11067 tcg_temp_free_i32(t1);
11068 tcg_gen_andi_i32(t0, t0, 1);
11069 tcg_gen_extu_i32_tl(bcond, t0);
11071 goto not_likely;
11072 case OPC_BC1TANY4:
11074 TCGv_i32 t1 = tcg_temp_new_i32();
11075 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11076 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11077 tcg_gen_or_i32(t0, t0, t1);
11078 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11079 tcg_gen_or_i32(t0, t0, t1);
11080 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11081 tcg_gen_or_i32(t0, t0, t1);
11082 tcg_temp_free_i32(t1);
11083 tcg_gen_andi_i32(t0, t0, 1);
11084 tcg_gen_extu_i32_tl(bcond, t0);
11086 not_likely:
11087 ctx->hflags |= MIPS_HFLAG_BC;
11088 break;
11089 default:
11090 MIPS_INVAL("cp1 cond branch");
11091 gen_reserved_instruction(ctx);
11092 goto out;
11094 ctx->btarget = btarget;
11095 ctx->hflags |= MIPS_HFLAG_BDS32;
11096 out:
11097 tcg_temp_free_i32(t0);
11100 /* R6 CP1 Branches */
11101 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
11102 int32_t ft, int32_t offset,
11103 int delayslot_size)
11105 target_ulong btarget;
11106 TCGv_i64 t0 = tcg_temp_new_i64();
11108 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11109 #ifdef MIPS_DEBUG_DISAS
11110 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11111 "\n", ctx->base.pc_next);
11112 #endif
11113 gen_reserved_instruction(ctx);
11114 goto out;
11117 gen_load_fpr64(ctx, t0, ft);
11118 tcg_gen_andi_i64(t0, t0, 1);
11120 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11122 switch (op) {
11123 case OPC_BC1EQZ:
11124 tcg_gen_xori_i64(t0, t0, 1);
11125 ctx->hflags |= MIPS_HFLAG_BC;
11126 break;
11127 case OPC_BC1NEZ:
11128 /* t0 already set */
11129 ctx->hflags |= MIPS_HFLAG_BC;
11130 break;
11131 default:
11132 MIPS_INVAL("cp1 cond branch");
11133 gen_reserved_instruction(ctx);
11134 goto out;
11137 tcg_gen_trunc_i64_tl(bcond, t0);
11139 ctx->btarget = btarget;
11141 switch (delayslot_size) {
11142 case 2:
11143 ctx->hflags |= MIPS_HFLAG_BDS16;
11144 break;
11145 case 4:
11146 ctx->hflags |= MIPS_HFLAG_BDS32;
11147 break;
11150 out:
11151 tcg_temp_free_i64(t0);
11154 /* Coprocessor 1 (FPU) */
11156 #define FOP(func, fmt) (((fmt) << 21) | (func))
11158 enum fopcode {
11159 OPC_ADD_S = FOP(0, FMT_S),
11160 OPC_SUB_S = FOP(1, FMT_S),
11161 OPC_MUL_S = FOP(2, FMT_S),
11162 OPC_DIV_S = FOP(3, FMT_S),
11163 OPC_SQRT_S = FOP(4, FMT_S),
11164 OPC_ABS_S = FOP(5, FMT_S),
11165 OPC_MOV_S = FOP(6, FMT_S),
11166 OPC_NEG_S = FOP(7, FMT_S),
11167 OPC_ROUND_L_S = FOP(8, FMT_S),
11168 OPC_TRUNC_L_S = FOP(9, FMT_S),
11169 OPC_CEIL_L_S = FOP(10, FMT_S),
11170 OPC_FLOOR_L_S = FOP(11, FMT_S),
11171 OPC_ROUND_W_S = FOP(12, FMT_S),
11172 OPC_TRUNC_W_S = FOP(13, FMT_S),
11173 OPC_CEIL_W_S = FOP(14, FMT_S),
11174 OPC_FLOOR_W_S = FOP(15, FMT_S),
11175 OPC_SEL_S = FOP(16, FMT_S),
11176 OPC_MOVCF_S = FOP(17, FMT_S),
11177 OPC_MOVZ_S = FOP(18, FMT_S),
11178 OPC_MOVN_S = FOP(19, FMT_S),
11179 OPC_SELEQZ_S = FOP(20, FMT_S),
11180 OPC_RECIP_S = FOP(21, FMT_S),
11181 OPC_RSQRT_S = FOP(22, FMT_S),
11182 OPC_SELNEZ_S = FOP(23, FMT_S),
11183 OPC_MADDF_S = FOP(24, FMT_S),
11184 OPC_MSUBF_S = FOP(25, FMT_S),
11185 OPC_RINT_S = FOP(26, FMT_S),
11186 OPC_CLASS_S = FOP(27, FMT_S),
11187 OPC_MIN_S = FOP(28, FMT_S),
11188 OPC_RECIP2_S = FOP(28, FMT_S),
11189 OPC_MINA_S = FOP(29, FMT_S),
11190 OPC_RECIP1_S = FOP(29, FMT_S),
11191 OPC_MAX_S = FOP(30, FMT_S),
11192 OPC_RSQRT1_S = FOP(30, FMT_S),
11193 OPC_MAXA_S = FOP(31, FMT_S),
11194 OPC_RSQRT2_S = FOP(31, FMT_S),
11195 OPC_CVT_D_S = FOP(33, FMT_S),
11196 OPC_CVT_W_S = FOP(36, FMT_S),
11197 OPC_CVT_L_S = FOP(37, FMT_S),
11198 OPC_CVT_PS_S = FOP(38, FMT_S),
11199 OPC_CMP_F_S = FOP(48, FMT_S),
11200 OPC_CMP_UN_S = FOP(49, FMT_S),
11201 OPC_CMP_EQ_S = FOP(50, FMT_S),
11202 OPC_CMP_UEQ_S = FOP(51, FMT_S),
11203 OPC_CMP_OLT_S = FOP(52, FMT_S),
11204 OPC_CMP_ULT_S = FOP(53, FMT_S),
11205 OPC_CMP_OLE_S = FOP(54, FMT_S),
11206 OPC_CMP_ULE_S = FOP(55, FMT_S),
11207 OPC_CMP_SF_S = FOP(56, FMT_S),
11208 OPC_CMP_NGLE_S = FOP(57, FMT_S),
11209 OPC_CMP_SEQ_S = FOP(58, FMT_S),
11210 OPC_CMP_NGL_S = FOP(59, FMT_S),
11211 OPC_CMP_LT_S = FOP(60, FMT_S),
11212 OPC_CMP_NGE_S = FOP(61, FMT_S),
11213 OPC_CMP_LE_S = FOP(62, FMT_S),
11214 OPC_CMP_NGT_S = FOP(63, FMT_S),
11216 OPC_ADD_D = FOP(0, FMT_D),
11217 OPC_SUB_D = FOP(1, FMT_D),
11218 OPC_MUL_D = FOP(2, FMT_D),
11219 OPC_DIV_D = FOP(3, FMT_D),
11220 OPC_SQRT_D = FOP(4, FMT_D),
11221 OPC_ABS_D = FOP(5, FMT_D),
11222 OPC_MOV_D = FOP(6, FMT_D),
11223 OPC_NEG_D = FOP(7, FMT_D),
11224 OPC_ROUND_L_D = FOP(8, FMT_D),
11225 OPC_TRUNC_L_D = FOP(9, FMT_D),
11226 OPC_CEIL_L_D = FOP(10, FMT_D),
11227 OPC_FLOOR_L_D = FOP(11, FMT_D),
11228 OPC_ROUND_W_D = FOP(12, FMT_D),
11229 OPC_TRUNC_W_D = FOP(13, FMT_D),
11230 OPC_CEIL_W_D = FOP(14, FMT_D),
11231 OPC_FLOOR_W_D = FOP(15, FMT_D),
11232 OPC_SEL_D = FOP(16, FMT_D),
11233 OPC_MOVCF_D = FOP(17, FMT_D),
11234 OPC_MOVZ_D = FOP(18, FMT_D),
11235 OPC_MOVN_D = FOP(19, FMT_D),
11236 OPC_SELEQZ_D = FOP(20, FMT_D),
11237 OPC_RECIP_D = FOP(21, FMT_D),
11238 OPC_RSQRT_D = FOP(22, FMT_D),
11239 OPC_SELNEZ_D = FOP(23, FMT_D),
11240 OPC_MADDF_D = FOP(24, FMT_D),
11241 OPC_MSUBF_D = FOP(25, FMT_D),
11242 OPC_RINT_D = FOP(26, FMT_D),
11243 OPC_CLASS_D = FOP(27, FMT_D),
11244 OPC_MIN_D = FOP(28, FMT_D),
11245 OPC_RECIP2_D = FOP(28, FMT_D),
11246 OPC_MINA_D = FOP(29, FMT_D),
11247 OPC_RECIP1_D = FOP(29, FMT_D),
11248 OPC_MAX_D = FOP(30, FMT_D),
11249 OPC_RSQRT1_D = FOP(30, FMT_D),
11250 OPC_MAXA_D = FOP(31, FMT_D),
11251 OPC_RSQRT2_D = FOP(31, FMT_D),
11252 OPC_CVT_S_D = FOP(32, FMT_D),
11253 OPC_CVT_W_D = FOP(36, FMT_D),
11254 OPC_CVT_L_D = FOP(37, FMT_D),
11255 OPC_CMP_F_D = FOP(48, FMT_D),
11256 OPC_CMP_UN_D = FOP(49, FMT_D),
11257 OPC_CMP_EQ_D = FOP(50, FMT_D),
11258 OPC_CMP_UEQ_D = FOP(51, FMT_D),
11259 OPC_CMP_OLT_D = FOP(52, FMT_D),
11260 OPC_CMP_ULT_D = FOP(53, FMT_D),
11261 OPC_CMP_OLE_D = FOP(54, FMT_D),
11262 OPC_CMP_ULE_D = FOP(55, FMT_D),
11263 OPC_CMP_SF_D = FOP(56, FMT_D),
11264 OPC_CMP_NGLE_D = FOP(57, FMT_D),
11265 OPC_CMP_SEQ_D = FOP(58, FMT_D),
11266 OPC_CMP_NGL_D = FOP(59, FMT_D),
11267 OPC_CMP_LT_D = FOP(60, FMT_D),
11268 OPC_CMP_NGE_D = FOP(61, FMT_D),
11269 OPC_CMP_LE_D = FOP(62, FMT_D),
11270 OPC_CMP_NGT_D = FOP(63, FMT_D),
11272 OPC_CVT_S_W = FOP(32, FMT_W),
11273 OPC_CVT_D_W = FOP(33, FMT_W),
11274 OPC_CVT_S_L = FOP(32, FMT_L),
11275 OPC_CVT_D_L = FOP(33, FMT_L),
11276 OPC_CVT_PS_PW = FOP(38, FMT_W),
11278 OPC_ADD_PS = FOP(0, FMT_PS),
11279 OPC_SUB_PS = FOP(1, FMT_PS),
11280 OPC_MUL_PS = FOP(2, FMT_PS),
11281 OPC_DIV_PS = FOP(3, FMT_PS),
11282 OPC_ABS_PS = FOP(5, FMT_PS),
11283 OPC_MOV_PS = FOP(6, FMT_PS),
11284 OPC_NEG_PS = FOP(7, FMT_PS),
11285 OPC_MOVCF_PS = FOP(17, FMT_PS),
11286 OPC_MOVZ_PS = FOP(18, FMT_PS),
11287 OPC_MOVN_PS = FOP(19, FMT_PS),
11288 OPC_ADDR_PS = FOP(24, FMT_PS),
11289 OPC_MULR_PS = FOP(26, FMT_PS),
11290 OPC_RECIP2_PS = FOP(28, FMT_PS),
11291 OPC_RECIP1_PS = FOP(29, FMT_PS),
11292 OPC_RSQRT1_PS = FOP(30, FMT_PS),
11293 OPC_RSQRT2_PS = FOP(31, FMT_PS),
11295 OPC_CVT_S_PU = FOP(32, FMT_PS),
11296 OPC_CVT_PW_PS = FOP(36, FMT_PS),
11297 OPC_CVT_S_PL = FOP(40, FMT_PS),
11298 OPC_PLL_PS = FOP(44, FMT_PS),
11299 OPC_PLU_PS = FOP(45, FMT_PS),
11300 OPC_PUL_PS = FOP(46, FMT_PS),
11301 OPC_PUU_PS = FOP(47, FMT_PS),
11302 OPC_CMP_F_PS = FOP(48, FMT_PS),
11303 OPC_CMP_UN_PS = FOP(49, FMT_PS),
11304 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
11305 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
11306 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
11307 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
11308 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
11309 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
11310 OPC_CMP_SF_PS = FOP(56, FMT_PS),
11311 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
11312 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
11313 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
11314 OPC_CMP_LT_PS = FOP(60, FMT_PS),
11315 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
11316 OPC_CMP_LE_PS = FOP(62, FMT_PS),
11317 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
11320 enum r6_f_cmp_op {
11321 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
11322 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
11323 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
11324 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
11325 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
11326 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
11327 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
11328 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
11329 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
11330 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
11331 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
11332 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
11333 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
11334 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
11335 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
11336 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
11337 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
11338 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
11339 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
11340 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
11341 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
11342 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
11344 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
11345 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
11346 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
11347 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
11348 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
11349 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11350 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11351 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11352 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11353 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11354 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11355 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11356 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11357 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11358 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11359 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11360 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11361 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11362 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11363 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11364 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11365 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11368 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11370 TCGv t0 = tcg_temp_new();
11372 switch (opc) {
11373 case OPC_MFC1:
11375 TCGv_i32 fp0 = tcg_temp_new_i32();
11377 gen_load_fpr32(ctx, fp0, fs);
11378 tcg_gen_ext_i32_tl(t0, fp0);
11379 tcg_temp_free_i32(fp0);
11381 gen_store_gpr(t0, rt);
11382 break;
11383 case OPC_MTC1:
11384 gen_load_gpr(t0, rt);
11386 TCGv_i32 fp0 = tcg_temp_new_i32();
11388 tcg_gen_trunc_tl_i32(fp0, t0);
11389 gen_store_fpr32(ctx, fp0, fs);
11390 tcg_temp_free_i32(fp0);
11392 break;
11393 case OPC_CFC1:
11394 gen_helper_1e0i(cfc1, t0, fs);
11395 gen_store_gpr(t0, rt);
11396 break;
11397 case OPC_CTC1:
11398 gen_load_gpr(t0, rt);
11399 save_cpu_state(ctx, 0);
11401 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11403 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11404 tcg_temp_free_i32(fs_tmp);
11406 /* Stop translation as we may have changed hflags */
11407 ctx->base.is_jmp = DISAS_STOP;
11408 break;
11409 #if defined(TARGET_MIPS64)
11410 case OPC_DMFC1:
11411 gen_load_fpr64(ctx, t0, fs);
11412 gen_store_gpr(t0, rt);
11413 break;
11414 case OPC_DMTC1:
11415 gen_load_gpr(t0, rt);
11416 gen_store_fpr64(ctx, t0, fs);
11417 break;
11418 #endif
11419 case OPC_MFHC1:
11421 TCGv_i32 fp0 = tcg_temp_new_i32();
11423 gen_load_fpr32h(ctx, fp0, fs);
11424 tcg_gen_ext_i32_tl(t0, fp0);
11425 tcg_temp_free_i32(fp0);
11427 gen_store_gpr(t0, rt);
11428 break;
11429 case OPC_MTHC1:
11430 gen_load_gpr(t0, rt);
11432 TCGv_i32 fp0 = tcg_temp_new_i32();
11434 tcg_gen_trunc_tl_i32(fp0, t0);
11435 gen_store_fpr32h(ctx, fp0, fs);
11436 tcg_temp_free_i32(fp0);
11438 break;
11439 default:
11440 MIPS_INVAL("cp1 move");
11441 gen_reserved_instruction(ctx);
11442 goto out;
11445 out:
11446 tcg_temp_free(t0);
11449 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11451 TCGLabel *l1;
11452 TCGCond cond;
11453 TCGv_i32 t0;
11455 if (rd == 0) {
11456 /* Treat as NOP. */
11457 return;
11460 if (tf) {
11461 cond = TCG_COND_EQ;
11462 } else {
11463 cond = TCG_COND_NE;
11466 l1 = gen_new_label();
11467 t0 = tcg_temp_new_i32();
11468 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11469 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11470 tcg_temp_free_i32(t0);
11471 if (rs == 0) {
11472 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11473 } else {
11474 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11476 gen_set_label(l1);
11479 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11480 int tf)
11482 int cond;
11483 TCGv_i32 t0 = tcg_temp_new_i32();
11484 TCGLabel *l1 = gen_new_label();
11486 if (tf) {
11487 cond = TCG_COND_EQ;
11488 } else {
11489 cond = TCG_COND_NE;
11492 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11493 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11494 gen_load_fpr32(ctx, t0, fs);
11495 gen_store_fpr32(ctx, t0, fd);
11496 gen_set_label(l1);
11497 tcg_temp_free_i32(t0);
11500 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11501 int tf)
11503 int cond;
11504 TCGv_i32 t0 = tcg_temp_new_i32();
11505 TCGv_i64 fp0;
11506 TCGLabel *l1 = gen_new_label();
11508 if (tf) {
11509 cond = TCG_COND_EQ;
11510 } else {
11511 cond = TCG_COND_NE;
11514 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11515 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11516 tcg_temp_free_i32(t0);
11517 fp0 = tcg_temp_new_i64();
11518 gen_load_fpr64(ctx, fp0, fs);
11519 gen_store_fpr64(ctx, fp0, fd);
11520 tcg_temp_free_i64(fp0);
11521 gen_set_label(l1);
11524 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11525 int cc, int tf)
11527 int cond;
11528 TCGv_i32 t0 = tcg_temp_new_i32();
11529 TCGLabel *l1 = gen_new_label();
11530 TCGLabel *l2 = gen_new_label();
11532 if (tf) {
11533 cond = TCG_COND_EQ;
11534 } else {
11535 cond = TCG_COND_NE;
11538 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11539 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11540 gen_load_fpr32(ctx, t0, fs);
11541 gen_store_fpr32(ctx, t0, fd);
11542 gen_set_label(l1);
11544 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11545 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11546 gen_load_fpr32h(ctx, t0, fs);
11547 gen_store_fpr32h(ctx, t0, fd);
11548 tcg_temp_free_i32(t0);
11549 gen_set_label(l2);
11552 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11553 int fs)
11555 TCGv_i32 t1 = tcg_const_i32(0);
11556 TCGv_i32 fp0 = tcg_temp_new_i32();
11557 TCGv_i32 fp1 = tcg_temp_new_i32();
11558 TCGv_i32 fp2 = tcg_temp_new_i32();
11559 gen_load_fpr32(ctx, fp0, fd);
11560 gen_load_fpr32(ctx, fp1, ft);
11561 gen_load_fpr32(ctx, fp2, fs);
11563 switch (op1) {
11564 case OPC_SEL_S:
11565 tcg_gen_andi_i32(fp0, fp0, 1);
11566 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11567 break;
11568 case OPC_SELEQZ_S:
11569 tcg_gen_andi_i32(fp1, fp1, 1);
11570 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11571 break;
11572 case OPC_SELNEZ_S:
11573 tcg_gen_andi_i32(fp1, fp1, 1);
11574 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11575 break;
11576 default:
11577 MIPS_INVAL("gen_sel_s");
11578 gen_reserved_instruction(ctx);
11579 break;
11582 gen_store_fpr32(ctx, fp0, fd);
11583 tcg_temp_free_i32(fp2);
11584 tcg_temp_free_i32(fp1);
11585 tcg_temp_free_i32(fp0);
11586 tcg_temp_free_i32(t1);
11589 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11590 int fs)
11592 TCGv_i64 t1 = tcg_const_i64(0);
11593 TCGv_i64 fp0 = tcg_temp_new_i64();
11594 TCGv_i64 fp1 = tcg_temp_new_i64();
11595 TCGv_i64 fp2 = tcg_temp_new_i64();
11596 gen_load_fpr64(ctx, fp0, fd);
11597 gen_load_fpr64(ctx, fp1, ft);
11598 gen_load_fpr64(ctx, fp2, fs);
11600 switch (op1) {
11601 case OPC_SEL_D:
11602 tcg_gen_andi_i64(fp0, fp0, 1);
11603 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11604 break;
11605 case OPC_SELEQZ_D:
11606 tcg_gen_andi_i64(fp1, fp1, 1);
11607 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11608 break;
11609 case OPC_SELNEZ_D:
11610 tcg_gen_andi_i64(fp1, fp1, 1);
11611 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11612 break;
11613 default:
11614 MIPS_INVAL("gen_sel_d");
11615 gen_reserved_instruction(ctx);
11616 break;
11619 gen_store_fpr64(ctx, fp0, fd);
11620 tcg_temp_free_i64(fp2);
11621 tcg_temp_free_i64(fp1);
11622 tcg_temp_free_i64(fp0);
11623 tcg_temp_free_i64(t1);
11626 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11627 int ft, int fs, int fd, int cc)
11629 uint32_t func = ctx->opcode & 0x3f;
11630 switch (op1) {
11631 case OPC_ADD_S:
11633 TCGv_i32 fp0 = tcg_temp_new_i32();
11634 TCGv_i32 fp1 = tcg_temp_new_i32();
11636 gen_load_fpr32(ctx, fp0, fs);
11637 gen_load_fpr32(ctx, fp1, ft);
11638 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11639 tcg_temp_free_i32(fp1);
11640 gen_store_fpr32(ctx, fp0, fd);
11641 tcg_temp_free_i32(fp0);
11643 break;
11644 case OPC_SUB_S:
11646 TCGv_i32 fp0 = tcg_temp_new_i32();
11647 TCGv_i32 fp1 = tcg_temp_new_i32();
11649 gen_load_fpr32(ctx, fp0, fs);
11650 gen_load_fpr32(ctx, fp1, ft);
11651 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11652 tcg_temp_free_i32(fp1);
11653 gen_store_fpr32(ctx, fp0, fd);
11654 tcg_temp_free_i32(fp0);
11656 break;
11657 case OPC_MUL_S:
11659 TCGv_i32 fp0 = tcg_temp_new_i32();
11660 TCGv_i32 fp1 = tcg_temp_new_i32();
11662 gen_load_fpr32(ctx, fp0, fs);
11663 gen_load_fpr32(ctx, fp1, ft);
11664 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11665 tcg_temp_free_i32(fp1);
11666 gen_store_fpr32(ctx, fp0, fd);
11667 tcg_temp_free_i32(fp0);
11669 break;
11670 case OPC_DIV_S:
11672 TCGv_i32 fp0 = tcg_temp_new_i32();
11673 TCGv_i32 fp1 = tcg_temp_new_i32();
11675 gen_load_fpr32(ctx, fp0, fs);
11676 gen_load_fpr32(ctx, fp1, ft);
11677 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11678 tcg_temp_free_i32(fp1);
11679 gen_store_fpr32(ctx, fp0, fd);
11680 tcg_temp_free_i32(fp0);
11682 break;
11683 case OPC_SQRT_S:
11685 TCGv_i32 fp0 = tcg_temp_new_i32();
11687 gen_load_fpr32(ctx, fp0, fs);
11688 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11689 gen_store_fpr32(ctx, fp0, fd);
11690 tcg_temp_free_i32(fp0);
11692 break;
11693 case OPC_ABS_S:
11695 TCGv_i32 fp0 = tcg_temp_new_i32();
11697 gen_load_fpr32(ctx, fp0, fs);
11698 if (ctx->abs2008) {
11699 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11700 } else {
11701 gen_helper_float_abs_s(fp0, fp0);
11703 gen_store_fpr32(ctx, fp0, fd);
11704 tcg_temp_free_i32(fp0);
11706 break;
11707 case OPC_MOV_S:
11709 TCGv_i32 fp0 = tcg_temp_new_i32();
11711 gen_load_fpr32(ctx, fp0, fs);
11712 gen_store_fpr32(ctx, fp0, fd);
11713 tcg_temp_free_i32(fp0);
11715 break;
11716 case OPC_NEG_S:
11718 TCGv_i32 fp0 = tcg_temp_new_i32();
11720 gen_load_fpr32(ctx, fp0, fs);
11721 if (ctx->abs2008) {
11722 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11723 } else {
11724 gen_helper_float_chs_s(fp0, fp0);
11726 gen_store_fpr32(ctx, fp0, fd);
11727 tcg_temp_free_i32(fp0);
11729 break;
11730 case OPC_ROUND_L_S:
11731 check_cp1_64bitmode(ctx);
11733 TCGv_i32 fp32 = tcg_temp_new_i32();
11734 TCGv_i64 fp64 = tcg_temp_new_i64();
11736 gen_load_fpr32(ctx, fp32, fs);
11737 if (ctx->nan2008) {
11738 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11739 } else {
11740 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11742 tcg_temp_free_i32(fp32);
11743 gen_store_fpr64(ctx, fp64, fd);
11744 tcg_temp_free_i64(fp64);
11746 break;
11747 case OPC_TRUNC_L_S:
11748 check_cp1_64bitmode(ctx);
11750 TCGv_i32 fp32 = tcg_temp_new_i32();
11751 TCGv_i64 fp64 = tcg_temp_new_i64();
11753 gen_load_fpr32(ctx, fp32, fs);
11754 if (ctx->nan2008) {
11755 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11756 } else {
11757 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11759 tcg_temp_free_i32(fp32);
11760 gen_store_fpr64(ctx, fp64, fd);
11761 tcg_temp_free_i64(fp64);
11763 break;
11764 case OPC_CEIL_L_S:
11765 check_cp1_64bitmode(ctx);
11767 TCGv_i32 fp32 = tcg_temp_new_i32();
11768 TCGv_i64 fp64 = tcg_temp_new_i64();
11770 gen_load_fpr32(ctx, fp32, fs);
11771 if (ctx->nan2008) {
11772 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11773 } else {
11774 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11776 tcg_temp_free_i32(fp32);
11777 gen_store_fpr64(ctx, fp64, fd);
11778 tcg_temp_free_i64(fp64);
11780 break;
11781 case OPC_FLOOR_L_S:
11782 check_cp1_64bitmode(ctx);
11784 TCGv_i32 fp32 = tcg_temp_new_i32();
11785 TCGv_i64 fp64 = tcg_temp_new_i64();
11787 gen_load_fpr32(ctx, fp32, fs);
11788 if (ctx->nan2008) {
11789 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11790 } else {
11791 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11793 tcg_temp_free_i32(fp32);
11794 gen_store_fpr64(ctx, fp64, fd);
11795 tcg_temp_free_i64(fp64);
11797 break;
11798 case OPC_ROUND_W_S:
11800 TCGv_i32 fp0 = tcg_temp_new_i32();
11802 gen_load_fpr32(ctx, fp0, fs);
11803 if (ctx->nan2008) {
11804 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11805 } else {
11806 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11808 gen_store_fpr32(ctx, fp0, fd);
11809 tcg_temp_free_i32(fp0);
11811 break;
11812 case OPC_TRUNC_W_S:
11814 TCGv_i32 fp0 = tcg_temp_new_i32();
11816 gen_load_fpr32(ctx, fp0, fs);
11817 if (ctx->nan2008) {
11818 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11819 } else {
11820 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11822 gen_store_fpr32(ctx, fp0, fd);
11823 tcg_temp_free_i32(fp0);
11825 break;
11826 case OPC_CEIL_W_S:
11828 TCGv_i32 fp0 = tcg_temp_new_i32();
11830 gen_load_fpr32(ctx, fp0, fs);
11831 if (ctx->nan2008) {
11832 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11833 } else {
11834 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11836 gen_store_fpr32(ctx, fp0, fd);
11837 tcg_temp_free_i32(fp0);
11839 break;
11840 case OPC_FLOOR_W_S:
11842 TCGv_i32 fp0 = tcg_temp_new_i32();
11844 gen_load_fpr32(ctx, fp0, fs);
11845 if (ctx->nan2008) {
11846 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11847 } else {
11848 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11850 gen_store_fpr32(ctx, fp0, fd);
11851 tcg_temp_free_i32(fp0);
11853 break;
11854 case OPC_SEL_S:
11855 check_insn(ctx, ISA_MIPS_R6);
11856 gen_sel_s(ctx, op1, fd, ft, fs);
11857 break;
11858 case OPC_SELEQZ_S:
11859 check_insn(ctx, ISA_MIPS_R6);
11860 gen_sel_s(ctx, op1, fd, ft, fs);
11861 break;
11862 case OPC_SELNEZ_S:
11863 check_insn(ctx, ISA_MIPS_R6);
11864 gen_sel_s(ctx, op1, fd, ft, fs);
11865 break;
11866 case OPC_MOVCF_S:
11867 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11868 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11869 break;
11870 case OPC_MOVZ_S:
11871 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11873 TCGLabel *l1 = gen_new_label();
11874 TCGv_i32 fp0;
11876 if (ft != 0) {
11877 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11879 fp0 = tcg_temp_new_i32();
11880 gen_load_fpr32(ctx, fp0, fs);
11881 gen_store_fpr32(ctx, fp0, fd);
11882 tcg_temp_free_i32(fp0);
11883 gen_set_label(l1);
11885 break;
11886 case OPC_MOVN_S:
11887 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11889 TCGLabel *l1 = gen_new_label();
11890 TCGv_i32 fp0;
11892 if (ft != 0) {
11893 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11894 fp0 = tcg_temp_new_i32();
11895 gen_load_fpr32(ctx, fp0, fs);
11896 gen_store_fpr32(ctx, fp0, fd);
11897 tcg_temp_free_i32(fp0);
11898 gen_set_label(l1);
11901 break;
11902 case OPC_RECIP_S:
11904 TCGv_i32 fp0 = tcg_temp_new_i32();
11906 gen_load_fpr32(ctx, fp0, fs);
11907 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11908 gen_store_fpr32(ctx, fp0, fd);
11909 tcg_temp_free_i32(fp0);
11911 break;
11912 case OPC_RSQRT_S:
11914 TCGv_i32 fp0 = tcg_temp_new_i32();
11916 gen_load_fpr32(ctx, fp0, fs);
11917 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11918 gen_store_fpr32(ctx, fp0, fd);
11919 tcg_temp_free_i32(fp0);
11921 break;
11922 case OPC_MADDF_S:
11923 check_insn(ctx, ISA_MIPS_R6);
11925 TCGv_i32 fp0 = tcg_temp_new_i32();
11926 TCGv_i32 fp1 = tcg_temp_new_i32();
11927 TCGv_i32 fp2 = tcg_temp_new_i32();
11928 gen_load_fpr32(ctx, fp0, fs);
11929 gen_load_fpr32(ctx, fp1, ft);
11930 gen_load_fpr32(ctx, fp2, fd);
11931 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11932 gen_store_fpr32(ctx, fp2, fd);
11933 tcg_temp_free_i32(fp2);
11934 tcg_temp_free_i32(fp1);
11935 tcg_temp_free_i32(fp0);
11937 break;
11938 case OPC_MSUBF_S:
11939 check_insn(ctx, ISA_MIPS_R6);
11941 TCGv_i32 fp0 = tcg_temp_new_i32();
11942 TCGv_i32 fp1 = tcg_temp_new_i32();
11943 TCGv_i32 fp2 = tcg_temp_new_i32();
11944 gen_load_fpr32(ctx, fp0, fs);
11945 gen_load_fpr32(ctx, fp1, ft);
11946 gen_load_fpr32(ctx, fp2, fd);
11947 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11948 gen_store_fpr32(ctx, fp2, fd);
11949 tcg_temp_free_i32(fp2);
11950 tcg_temp_free_i32(fp1);
11951 tcg_temp_free_i32(fp0);
11953 break;
11954 case OPC_RINT_S:
11955 check_insn(ctx, ISA_MIPS_R6);
11957 TCGv_i32 fp0 = tcg_temp_new_i32();
11958 gen_load_fpr32(ctx, fp0, fs);
11959 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11960 gen_store_fpr32(ctx, fp0, fd);
11961 tcg_temp_free_i32(fp0);
11963 break;
11964 case OPC_CLASS_S:
11965 check_insn(ctx, ISA_MIPS_R6);
11967 TCGv_i32 fp0 = tcg_temp_new_i32();
11968 gen_load_fpr32(ctx, fp0, fs);
11969 gen_helper_float_class_s(fp0, cpu_env, fp0);
11970 gen_store_fpr32(ctx, fp0, fd);
11971 tcg_temp_free_i32(fp0);
11973 break;
11974 case OPC_MIN_S: /* OPC_RECIP2_S */
11975 if (ctx->insn_flags & ISA_MIPS_R6) {
11976 /* OPC_MIN_S */
11977 TCGv_i32 fp0 = tcg_temp_new_i32();
11978 TCGv_i32 fp1 = tcg_temp_new_i32();
11979 TCGv_i32 fp2 = tcg_temp_new_i32();
11980 gen_load_fpr32(ctx, fp0, fs);
11981 gen_load_fpr32(ctx, fp1, ft);
11982 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11983 gen_store_fpr32(ctx, fp2, fd);
11984 tcg_temp_free_i32(fp2);
11985 tcg_temp_free_i32(fp1);
11986 tcg_temp_free_i32(fp0);
11987 } else {
11988 /* OPC_RECIP2_S */
11989 check_cp1_64bitmode(ctx);
11991 TCGv_i32 fp0 = tcg_temp_new_i32();
11992 TCGv_i32 fp1 = tcg_temp_new_i32();
11994 gen_load_fpr32(ctx, fp0, fs);
11995 gen_load_fpr32(ctx, fp1, ft);
11996 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11997 tcg_temp_free_i32(fp1);
11998 gen_store_fpr32(ctx, fp0, fd);
11999 tcg_temp_free_i32(fp0);
12002 break;
12003 case OPC_MINA_S: /* OPC_RECIP1_S */
12004 if (ctx->insn_flags & ISA_MIPS_R6) {
12005 /* OPC_MINA_S */
12006 TCGv_i32 fp0 = tcg_temp_new_i32();
12007 TCGv_i32 fp1 = tcg_temp_new_i32();
12008 TCGv_i32 fp2 = tcg_temp_new_i32();
12009 gen_load_fpr32(ctx, fp0, fs);
12010 gen_load_fpr32(ctx, fp1, ft);
12011 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
12012 gen_store_fpr32(ctx, fp2, fd);
12013 tcg_temp_free_i32(fp2);
12014 tcg_temp_free_i32(fp1);
12015 tcg_temp_free_i32(fp0);
12016 } else {
12017 /* OPC_RECIP1_S */
12018 check_cp1_64bitmode(ctx);
12020 TCGv_i32 fp0 = tcg_temp_new_i32();
12022 gen_load_fpr32(ctx, fp0, fs);
12023 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
12024 gen_store_fpr32(ctx, fp0, fd);
12025 tcg_temp_free_i32(fp0);
12028 break;
12029 case OPC_MAX_S: /* OPC_RSQRT1_S */
12030 if (ctx->insn_flags & ISA_MIPS_R6) {
12031 /* OPC_MAX_S */
12032 TCGv_i32 fp0 = tcg_temp_new_i32();
12033 TCGv_i32 fp1 = tcg_temp_new_i32();
12034 gen_load_fpr32(ctx, fp0, fs);
12035 gen_load_fpr32(ctx, fp1, ft);
12036 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
12037 gen_store_fpr32(ctx, fp1, fd);
12038 tcg_temp_free_i32(fp1);
12039 tcg_temp_free_i32(fp0);
12040 } else {
12041 /* OPC_RSQRT1_S */
12042 check_cp1_64bitmode(ctx);
12044 TCGv_i32 fp0 = tcg_temp_new_i32();
12046 gen_load_fpr32(ctx, fp0, fs);
12047 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
12048 gen_store_fpr32(ctx, fp0, fd);
12049 tcg_temp_free_i32(fp0);
12052 break;
12053 case OPC_MAXA_S: /* OPC_RSQRT2_S */
12054 if (ctx->insn_flags & ISA_MIPS_R6) {
12055 /* OPC_MAXA_S */
12056 TCGv_i32 fp0 = tcg_temp_new_i32();
12057 TCGv_i32 fp1 = tcg_temp_new_i32();
12058 gen_load_fpr32(ctx, fp0, fs);
12059 gen_load_fpr32(ctx, fp1, ft);
12060 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
12061 gen_store_fpr32(ctx, fp1, fd);
12062 tcg_temp_free_i32(fp1);
12063 tcg_temp_free_i32(fp0);
12064 } else {
12065 /* OPC_RSQRT2_S */
12066 check_cp1_64bitmode(ctx);
12068 TCGv_i32 fp0 = tcg_temp_new_i32();
12069 TCGv_i32 fp1 = tcg_temp_new_i32();
12071 gen_load_fpr32(ctx, fp0, fs);
12072 gen_load_fpr32(ctx, fp1, ft);
12073 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
12074 tcg_temp_free_i32(fp1);
12075 gen_store_fpr32(ctx, fp0, fd);
12076 tcg_temp_free_i32(fp0);
12079 break;
12080 case OPC_CVT_D_S:
12081 check_cp1_registers(ctx, fd);
12083 TCGv_i32 fp32 = tcg_temp_new_i32();
12084 TCGv_i64 fp64 = tcg_temp_new_i64();
12086 gen_load_fpr32(ctx, fp32, fs);
12087 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
12088 tcg_temp_free_i32(fp32);
12089 gen_store_fpr64(ctx, fp64, fd);
12090 tcg_temp_free_i64(fp64);
12092 break;
12093 case OPC_CVT_W_S:
12095 TCGv_i32 fp0 = tcg_temp_new_i32();
12097 gen_load_fpr32(ctx, fp0, fs);
12098 if (ctx->nan2008) {
12099 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
12100 } else {
12101 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
12103 gen_store_fpr32(ctx, fp0, fd);
12104 tcg_temp_free_i32(fp0);
12106 break;
12107 case OPC_CVT_L_S:
12108 check_cp1_64bitmode(ctx);
12110 TCGv_i32 fp32 = tcg_temp_new_i32();
12111 TCGv_i64 fp64 = tcg_temp_new_i64();
12113 gen_load_fpr32(ctx, fp32, fs);
12114 if (ctx->nan2008) {
12115 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
12116 } else {
12117 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
12119 tcg_temp_free_i32(fp32);
12120 gen_store_fpr64(ctx, fp64, fd);
12121 tcg_temp_free_i64(fp64);
12123 break;
12124 case OPC_CVT_PS_S:
12125 check_ps(ctx);
12127 TCGv_i64 fp64 = tcg_temp_new_i64();
12128 TCGv_i32 fp32_0 = tcg_temp_new_i32();
12129 TCGv_i32 fp32_1 = tcg_temp_new_i32();
12131 gen_load_fpr32(ctx, fp32_0, fs);
12132 gen_load_fpr32(ctx, fp32_1, ft);
12133 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
12134 tcg_temp_free_i32(fp32_1);
12135 tcg_temp_free_i32(fp32_0);
12136 gen_store_fpr64(ctx, fp64, fd);
12137 tcg_temp_free_i64(fp64);
12139 break;
12140 case OPC_CMP_F_S:
12141 case OPC_CMP_UN_S:
12142 case OPC_CMP_EQ_S:
12143 case OPC_CMP_UEQ_S:
12144 case OPC_CMP_OLT_S:
12145 case OPC_CMP_ULT_S:
12146 case OPC_CMP_OLE_S:
12147 case OPC_CMP_ULE_S:
12148 case OPC_CMP_SF_S:
12149 case OPC_CMP_NGLE_S:
12150 case OPC_CMP_SEQ_S:
12151 case OPC_CMP_NGL_S:
12152 case OPC_CMP_LT_S:
12153 case OPC_CMP_NGE_S:
12154 case OPC_CMP_LE_S:
12155 case OPC_CMP_NGT_S:
12156 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12157 if (ctx->opcode & (1 << 6)) {
12158 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
12159 } else {
12160 gen_cmp_s(ctx, func - 48, ft, fs, cc);
12162 break;
12163 case OPC_ADD_D:
12164 check_cp1_registers(ctx, fs | ft | fd);
12166 TCGv_i64 fp0 = tcg_temp_new_i64();
12167 TCGv_i64 fp1 = tcg_temp_new_i64();
12169 gen_load_fpr64(ctx, fp0, fs);
12170 gen_load_fpr64(ctx, fp1, ft);
12171 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
12172 tcg_temp_free_i64(fp1);
12173 gen_store_fpr64(ctx, fp0, fd);
12174 tcg_temp_free_i64(fp0);
12176 break;
12177 case OPC_SUB_D:
12178 check_cp1_registers(ctx, fs | ft | fd);
12180 TCGv_i64 fp0 = tcg_temp_new_i64();
12181 TCGv_i64 fp1 = tcg_temp_new_i64();
12183 gen_load_fpr64(ctx, fp0, fs);
12184 gen_load_fpr64(ctx, fp1, ft);
12185 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
12186 tcg_temp_free_i64(fp1);
12187 gen_store_fpr64(ctx, fp0, fd);
12188 tcg_temp_free_i64(fp0);
12190 break;
12191 case OPC_MUL_D:
12192 check_cp1_registers(ctx, fs | ft | fd);
12194 TCGv_i64 fp0 = tcg_temp_new_i64();
12195 TCGv_i64 fp1 = tcg_temp_new_i64();
12197 gen_load_fpr64(ctx, fp0, fs);
12198 gen_load_fpr64(ctx, fp1, ft);
12199 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
12200 tcg_temp_free_i64(fp1);
12201 gen_store_fpr64(ctx, fp0, fd);
12202 tcg_temp_free_i64(fp0);
12204 break;
12205 case OPC_DIV_D:
12206 check_cp1_registers(ctx, fs | ft | fd);
12208 TCGv_i64 fp0 = tcg_temp_new_i64();
12209 TCGv_i64 fp1 = tcg_temp_new_i64();
12211 gen_load_fpr64(ctx, fp0, fs);
12212 gen_load_fpr64(ctx, fp1, ft);
12213 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
12214 tcg_temp_free_i64(fp1);
12215 gen_store_fpr64(ctx, fp0, fd);
12216 tcg_temp_free_i64(fp0);
12218 break;
12219 case OPC_SQRT_D:
12220 check_cp1_registers(ctx, fs | fd);
12222 TCGv_i64 fp0 = tcg_temp_new_i64();
12224 gen_load_fpr64(ctx, fp0, fs);
12225 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
12226 gen_store_fpr64(ctx, fp0, fd);
12227 tcg_temp_free_i64(fp0);
12229 break;
12230 case OPC_ABS_D:
12231 check_cp1_registers(ctx, fs | fd);
12233 TCGv_i64 fp0 = tcg_temp_new_i64();
12235 gen_load_fpr64(ctx, fp0, fs);
12236 if (ctx->abs2008) {
12237 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
12238 } else {
12239 gen_helper_float_abs_d(fp0, fp0);
12241 gen_store_fpr64(ctx, fp0, fd);
12242 tcg_temp_free_i64(fp0);
12244 break;
12245 case OPC_MOV_D:
12246 check_cp1_registers(ctx, fs | fd);
12248 TCGv_i64 fp0 = tcg_temp_new_i64();
12250 gen_load_fpr64(ctx, fp0, fs);
12251 gen_store_fpr64(ctx, fp0, fd);
12252 tcg_temp_free_i64(fp0);
12254 break;
12255 case OPC_NEG_D:
12256 check_cp1_registers(ctx, fs | fd);
12258 TCGv_i64 fp0 = tcg_temp_new_i64();
12260 gen_load_fpr64(ctx, fp0, fs);
12261 if (ctx->abs2008) {
12262 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
12263 } else {
12264 gen_helper_float_chs_d(fp0, fp0);
12266 gen_store_fpr64(ctx, fp0, fd);
12267 tcg_temp_free_i64(fp0);
12269 break;
12270 case OPC_ROUND_L_D:
12271 check_cp1_64bitmode(ctx);
12273 TCGv_i64 fp0 = tcg_temp_new_i64();
12275 gen_load_fpr64(ctx, fp0, fs);
12276 if (ctx->nan2008) {
12277 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
12278 } else {
12279 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
12281 gen_store_fpr64(ctx, fp0, fd);
12282 tcg_temp_free_i64(fp0);
12284 break;
12285 case OPC_TRUNC_L_D:
12286 check_cp1_64bitmode(ctx);
12288 TCGv_i64 fp0 = tcg_temp_new_i64();
12290 gen_load_fpr64(ctx, fp0, fs);
12291 if (ctx->nan2008) {
12292 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
12293 } else {
12294 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
12296 gen_store_fpr64(ctx, fp0, fd);
12297 tcg_temp_free_i64(fp0);
12299 break;
12300 case OPC_CEIL_L_D:
12301 check_cp1_64bitmode(ctx);
12303 TCGv_i64 fp0 = tcg_temp_new_i64();
12305 gen_load_fpr64(ctx, fp0, fs);
12306 if (ctx->nan2008) {
12307 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
12308 } else {
12309 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
12311 gen_store_fpr64(ctx, fp0, fd);
12312 tcg_temp_free_i64(fp0);
12314 break;
12315 case OPC_FLOOR_L_D:
12316 check_cp1_64bitmode(ctx);
12318 TCGv_i64 fp0 = tcg_temp_new_i64();
12320 gen_load_fpr64(ctx, fp0, fs);
12321 if (ctx->nan2008) {
12322 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
12323 } else {
12324 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
12326 gen_store_fpr64(ctx, fp0, fd);
12327 tcg_temp_free_i64(fp0);
12329 break;
12330 case OPC_ROUND_W_D:
12331 check_cp1_registers(ctx, fs);
12333 TCGv_i32 fp32 = tcg_temp_new_i32();
12334 TCGv_i64 fp64 = tcg_temp_new_i64();
12336 gen_load_fpr64(ctx, fp64, fs);
12337 if (ctx->nan2008) {
12338 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
12339 } else {
12340 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
12342 tcg_temp_free_i64(fp64);
12343 gen_store_fpr32(ctx, fp32, fd);
12344 tcg_temp_free_i32(fp32);
12346 break;
12347 case OPC_TRUNC_W_D:
12348 check_cp1_registers(ctx, fs);
12350 TCGv_i32 fp32 = tcg_temp_new_i32();
12351 TCGv_i64 fp64 = tcg_temp_new_i64();
12353 gen_load_fpr64(ctx, fp64, fs);
12354 if (ctx->nan2008) {
12355 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12356 } else {
12357 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12359 tcg_temp_free_i64(fp64);
12360 gen_store_fpr32(ctx, fp32, fd);
12361 tcg_temp_free_i32(fp32);
12363 break;
12364 case OPC_CEIL_W_D:
12365 check_cp1_registers(ctx, fs);
12367 TCGv_i32 fp32 = tcg_temp_new_i32();
12368 TCGv_i64 fp64 = tcg_temp_new_i64();
12370 gen_load_fpr64(ctx, fp64, fs);
12371 if (ctx->nan2008) {
12372 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12373 } else {
12374 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12376 tcg_temp_free_i64(fp64);
12377 gen_store_fpr32(ctx, fp32, fd);
12378 tcg_temp_free_i32(fp32);
12380 break;
12381 case OPC_FLOOR_W_D:
12382 check_cp1_registers(ctx, fs);
12384 TCGv_i32 fp32 = tcg_temp_new_i32();
12385 TCGv_i64 fp64 = tcg_temp_new_i64();
12387 gen_load_fpr64(ctx, fp64, fs);
12388 if (ctx->nan2008) {
12389 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12390 } else {
12391 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12393 tcg_temp_free_i64(fp64);
12394 gen_store_fpr32(ctx, fp32, fd);
12395 tcg_temp_free_i32(fp32);
12397 break;
12398 case OPC_SEL_D:
12399 check_insn(ctx, ISA_MIPS_R6);
12400 gen_sel_d(ctx, op1, fd, ft, fs);
12401 break;
12402 case OPC_SELEQZ_D:
12403 check_insn(ctx, ISA_MIPS_R6);
12404 gen_sel_d(ctx, op1, fd, ft, fs);
12405 break;
12406 case OPC_SELNEZ_D:
12407 check_insn(ctx, ISA_MIPS_R6);
12408 gen_sel_d(ctx, op1, fd, ft, fs);
12409 break;
12410 case OPC_MOVCF_D:
12411 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12412 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12413 break;
12414 case OPC_MOVZ_D:
12415 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12417 TCGLabel *l1 = gen_new_label();
12418 TCGv_i64 fp0;
12420 if (ft != 0) {
12421 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12423 fp0 = tcg_temp_new_i64();
12424 gen_load_fpr64(ctx, fp0, fs);
12425 gen_store_fpr64(ctx, fp0, fd);
12426 tcg_temp_free_i64(fp0);
12427 gen_set_label(l1);
12429 break;
12430 case OPC_MOVN_D:
12431 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12433 TCGLabel *l1 = gen_new_label();
12434 TCGv_i64 fp0;
12436 if (ft != 0) {
12437 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12438 fp0 = tcg_temp_new_i64();
12439 gen_load_fpr64(ctx, fp0, fs);
12440 gen_store_fpr64(ctx, fp0, fd);
12441 tcg_temp_free_i64(fp0);
12442 gen_set_label(l1);
12445 break;
12446 case OPC_RECIP_D:
12447 check_cp1_registers(ctx, fs | fd);
12449 TCGv_i64 fp0 = tcg_temp_new_i64();
12451 gen_load_fpr64(ctx, fp0, fs);
12452 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12453 gen_store_fpr64(ctx, fp0, fd);
12454 tcg_temp_free_i64(fp0);
12456 break;
12457 case OPC_RSQRT_D:
12458 check_cp1_registers(ctx, fs | fd);
12460 TCGv_i64 fp0 = tcg_temp_new_i64();
12462 gen_load_fpr64(ctx, fp0, fs);
12463 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12464 gen_store_fpr64(ctx, fp0, fd);
12465 tcg_temp_free_i64(fp0);
12467 break;
12468 case OPC_MADDF_D:
12469 check_insn(ctx, ISA_MIPS_R6);
12471 TCGv_i64 fp0 = tcg_temp_new_i64();
12472 TCGv_i64 fp1 = tcg_temp_new_i64();
12473 TCGv_i64 fp2 = tcg_temp_new_i64();
12474 gen_load_fpr64(ctx, fp0, fs);
12475 gen_load_fpr64(ctx, fp1, ft);
12476 gen_load_fpr64(ctx, fp2, fd);
12477 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12478 gen_store_fpr64(ctx, fp2, fd);
12479 tcg_temp_free_i64(fp2);
12480 tcg_temp_free_i64(fp1);
12481 tcg_temp_free_i64(fp0);
12483 break;
12484 case OPC_MSUBF_D:
12485 check_insn(ctx, ISA_MIPS_R6);
12487 TCGv_i64 fp0 = tcg_temp_new_i64();
12488 TCGv_i64 fp1 = tcg_temp_new_i64();
12489 TCGv_i64 fp2 = tcg_temp_new_i64();
12490 gen_load_fpr64(ctx, fp0, fs);
12491 gen_load_fpr64(ctx, fp1, ft);
12492 gen_load_fpr64(ctx, fp2, fd);
12493 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12494 gen_store_fpr64(ctx, fp2, fd);
12495 tcg_temp_free_i64(fp2);
12496 tcg_temp_free_i64(fp1);
12497 tcg_temp_free_i64(fp0);
12499 break;
12500 case OPC_RINT_D:
12501 check_insn(ctx, ISA_MIPS_R6);
12503 TCGv_i64 fp0 = tcg_temp_new_i64();
12504 gen_load_fpr64(ctx, fp0, fs);
12505 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12506 gen_store_fpr64(ctx, fp0, fd);
12507 tcg_temp_free_i64(fp0);
12509 break;
12510 case OPC_CLASS_D:
12511 check_insn(ctx, ISA_MIPS_R6);
12513 TCGv_i64 fp0 = tcg_temp_new_i64();
12514 gen_load_fpr64(ctx, fp0, fs);
12515 gen_helper_float_class_d(fp0, cpu_env, fp0);
12516 gen_store_fpr64(ctx, fp0, fd);
12517 tcg_temp_free_i64(fp0);
12519 break;
12520 case OPC_MIN_D: /* OPC_RECIP2_D */
12521 if (ctx->insn_flags & ISA_MIPS_R6) {
12522 /* OPC_MIN_D */
12523 TCGv_i64 fp0 = tcg_temp_new_i64();
12524 TCGv_i64 fp1 = tcg_temp_new_i64();
12525 gen_load_fpr64(ctx, fp0, fs);
12526 gen_load_fpr64(ctx, fp1, ft);
12527 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12528 gen_store_fpr64(ctx, fp1, fd);
12529 tcg_temp_free_i64(fp1);
12530 tcg_temp_free_i64(fp0);
12531 } else {
12532 /* OPC_RECIP2_D */
12533 check_cp1_64bitmode(ctx);
12535 TCGv_i64 fp0 = tcg_temp_new_i64();
12536 TCGv_i64 fp1 = tcg_temp_new_i64();
12538 gen_load_fpr64(ctx, fp0, fs);
12539 gen_load_fpr64(ctx, fp1, ft);
12540 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12541 tcg_temp_free_i64(fp1);
12542 gen_store_fpr64(ctx, fp0, fd);
12543 tcg_temp_free_i64(fp0);
12546 break;
12547 case OPC_MINA_D: /* OPC_RECIP1_D */
12548 if (ctx->insn_flags & ISA_MIPS_R6) {
12549 /* OPC_MINA_D */
12550 TCGv_i64 fp0 = tcg_temp_new_i64();
12551 TCGv_i64 fp1 = tcg_temp_new_i64();
12552 gen_load_fpr64(ctx, fp0, fs);
12553 gen_load_fpr64(ctx, fp1, ft);
12554 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12555 gen_store_fpr64(ctx, fp1, fd);
12556 tcg_temp_free_i64(fp1);
12557 tcg_temp_free_i64(fp0);
12558 } else {
12559 /* OPC_RECIP1_D */
12560 check_cp1_64bitmode(ctx);
12562 TCGv_i64 fp0 = tcg_temp_new_i64();
12564 gen_load_fpr64(ctx, fp0, fs);
12565 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12566 gen_store_fpr64(ctx, fp0, fd);
12567 tcg_temp_free_i64(fp0);
12570 break;
12571 case OPC_MAX_D: /* OPC_RSQRT1_D */
12572 if (ctx->insn_flags & ISA_MIPS_R6) {
12573 /* OPC_MAX_D */
12574 TCGv_i64 fp0 = tcg_temp_new_i64();
12575 TCGv_i64 fp1 = tcg_temp_new_i64();
12576 gen_load_fpr64(ctx, fp0, fs);
12577 gen_load_fpr64(ctx, fp1, ft);
12578 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12579 gen_store_fpr64(ctx, fp1, fd);
12580 tcg_temp_free_i64(fp1);
12581 tcg_temp_free_i64(fp0);
12582 } else {
12583 /* OPC_RSQRT1_D */
12584 check_cp1_64bitmode(ctx);
12586 TCGv_i64 fp0 = tcg_temp_new_i64();
12588 gen_load_fpr64(ctx, fp0, fs);
12589 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12590 gen_store_fpr64(ctx, fp0, fd);
12591 tcg_temp_free_i64(fp0);
12594 break;
12595 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12596 if (ctx->insn_flags & ISA_MIPS_R6) {
12597 /* OPC_MAXA_D */
12598 TCGv_i64 fp0 = tcg_temp_new_i64();
12599 TCGv_i64 fp1 = tcg_temp_new_i64();
12600 gen_load_fpr64(ctx, fp0, fs);
12601 gen_load_fpr64(ctx, fp1, ft);
12602 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12603 gen_store_fpr64(ctx, fp1, fd);
12604 tcg_temp_free_i64(fp1);
12605 tcg_temp_free_i64(fp0);
12606 } else {
12607 /* OPC_RSQRT2_D */
12608 check_cp1_64bitmode(ctx);
12610 TCGv_i64 fp0 = tcg_temp_new_i64();
12611 TCGv_i64 fp1 = tcg_temp_new_i64();
12613 gen_load_fpr64(ctx, fp0, fs);
12614 gen_load_fpr64(ctx, fp1, ft);
12615 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12616 tcg_temp_free_i64(fp1);
12617 gen_store_fpr64(ctx, fp0, fd);
12618 tcg_temp_free_i64(fp0);
12621 break;
12622 case OPC_CMP_F_D:
12623 case OPC_CMP_UN_D:
12624 case OPC_CMP_EQ_D:
12625 case OPC_CMP_UEQ_D:
12626 case OPC_CMP_OLT_D:
12627 case OPC_CMP_ULT_D:
12628 case OPC_CMP_OLE_D:
12629 case OPC_CMP_ULE_D:
12630 case OPC_CMP_SF_D:
12631 case OPC_CMP_NGLE_D:
12632 case OPC_CMP_SEQ_D:
12633 case OPC_CMP_NGL_D:
12634 case OPC_CMP_LT_D:
12635 case OPC_CMP_NGE_D:
12636 case OPC_CMP_LE_D:
12637 case OPC_CMP_NGT_D:
12638 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12639 if (ctx->opcode & (1 << 6)) {
12640 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12641 } else {
12642 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12644 break;
12645 case OPC_CVT_S_D:
12646 check_cp1_registers(ctx, fs);
12648 TCGv_i32 fp32 = tcg_temp_new_i32();
12649 TCGv_i64 fp64 = tcg_temp_new_i64();
12651 gen_load_fpr64(ctx, fp64, fs);
12652 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12653 tcg_temp_free_i64(fp64);
12654 gen_store_fpr32(ctx, fp32, fd);
12655 tcg_temp_free_i32(fp32);
12657 break;
12658 case OPC_CVT_W_D:
12659 check_cp1_registers(ctx, fs);
12661 TCGv_i32 fp32 = tcg_temp_new_i32();
12662 TCGv_i64 fp64 = tcg_temp_new_i64();
12664 gen_load_fpr64(ctx, fp64, fs);
12665 if (ctx->nan2008) {
12666 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12667 } else {
12668 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12670 tcg_temp_free_i64(fp64);
12671 gen_store_fpr32(ctx, fp32, fd);
12672 tcg_temp_free_i32(fp32);
12674 break;
12675 case OPC_CVT_L_D:
12676 check_cp1_64bitmode(ctx);
12678 TCGv_i64 fp0 = tcg_temp_new_i64();
12680 gen_load_fpr64(ctx, fp0, fs);
12681 if (ctx->nan2008) {
12682 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12683 } else {
12684 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12686 gen_store_fpr64(ctx, fp0, fd);
12687 tcg_temp_free_i64(fp0);
12689 break;
12690 case OPC_CVT_S_W:
12692 TCGv_i32 fp0 = tcg_temp_new_i32();
12694 gen_load_fpr32(ctx, fp0, fs);
12695 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12696 gen_store_fpr32(ctx, fp0, fd);
12697 tcg_temp_free_i32(fp0);
12699 break;
12700 case OPC_CVT_D_W:
12701 check_cp1_registers(ctx, fd);
12703 TCGv_i32 fp32 = tcg_temp_new_i32();
12704 TCGv_i64 fp64 = tcg_temp_new_i64();
12706 gen_load_fpr32(ctx, fp32, fs);
12707 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12708 tcg_temp_free_i32(fp32);
12709 gen_store_fpr64(ctx, fp64, fd);
12710 tcg_temp_free_i64(fp64);
12712 break;
12713 case OPC_CVT_S_L:
12714 check_cp1_64bitmode(ctx);
12716 TCGv_i32 fp32 = tcg_temp_new_i32();
12717 TCGv_i64 fp64 = tcg_temp_new_i64();
12719 gen_load_fpr64(ctx, fp64, fs);
12720 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12721 tcg_temp_free_i64(fp64);
12722 gen_store_fpr32(ctx, fp32, fd);
12723 tcg_temp_free_i32(fp32);
12725 break;
12726 case OPC_CVT_D_L:
12727 check_cp1_64bitmode(ctx);
12729 TCGv_i64 fp0 = tcg_temp_new_i64();
12731 gen_load_fpr64(ctx, fp0, fs);
12732 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12733 gen_store_fpr64(ctx, fp0, fd);
12734 tcg_temp_free_i64(fp0);
12736 break;
12737 case OPC_CVT_PS_PW:
12738 check_ps(ctx);
12740 TCGv_i64 fp0 = tcg_temp_new_i64();
12742 gen_load_fpr64(ctx, fp0, fs);
12743 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12744 gen_store_fpr64(ctx, fp0, fd);
12745 tcg_temp_free_i64(fp0);
12747 break;
12748 case OPC_ADD_PS:
12749 check_ps(ctx);
12751 TCGv_i64 fp0 = tcg_temp_new_i64();
12752 TCGv_i64 fp1 = tcg_temp_new_i64();
12754 gen_load_fpr64(ctx, fp0, fs);
12755 gen_load_fpr64(ctx, fp1, ft);
12756 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12757 tcg_temp_free_i64(fp1);
12758 gen_store_fpr64(ctx, fp0, fd);
12759 tcg_temp_free_i64(fp0);
12761 break;
12762 case OPC_SUB_PS:
12763 check_ps(ctx);
12765 TCGv_i64 fp0 = tcg_temp_new_i64();
12766 TCGv_i64 fp1 = tcg_temp_new_i64();
12768 gen_load_fpr64(ctx, fp0, fs);
12769 gen_load_fpr64(ctx, fp1, ft);
12770 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12771 tcg_temp_free_i64(fp1);
12772 gen_store_fpr64(ctx, fp0, fd);
12773 tcg_temp_free_i64(fp0);
12775 break;
12776 case OPC_MUL_PS:
12777 check_ps(ctx);
12779 TCGv_i64 fp0 = tcg_temp_new_i64();
12780 TCGv_i64 fp1 = tcg_temp_new_i64();
12782 gen_load_fpr64(ctx, fp0, fs);
12783 gen_load_fpr64(ctx, fp1, ft);
12784 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12785 tcg_temp_free_i64(fp1);
12786 gen_store_fpr64(ctx, fp0, fd);
12787 tcg_temp_free_i64(fp0);
12789 break;
12790 case OPC_ABS_PS:
12791 check_ps(ctx);
12793 TCGv_i64 fp0 = tcg_temp_new_i64();
12795 gen_load_fpr64(ctx, fp0, fs);
12796 gen_helper_float_abs_ps(fp0, fp0);
12797 gen_store_fpr64(ctx, fp0, fd);
12798 tcg_temp_free_i64(fp0);
12800 break;
12801 case OPC_MOV_PS:
12802 check_ps(ctx);
12804 TCGv_i64 fp0 = tcg_temp_new_i64();
12806 gen_load_fpr64(ctx, fp0, fs);
12807 gen_store_fpr64(ctx, fp0, fd);
12808 tcg_temp_free_i64(fp0);
12810 break;
12811 case OPC_NEG_PS:
12812 check_ps(ctx);
12814 TCGv_i64 fp0 = tcg_temp_new_i64();
12816 gen_load_fpr64(ctx, fp0, fs);
12817 gen_helper_float_chs_ps(fp0, fp0);
12818 gen_store_fpr64(ctx, fp0, fd);
12819 tcg_temp_free_i64(fp0);
12821 break;
12822 case OPC_MOVCF_PS:
12823 check_ps(ctx);
12824 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12825 break;
12826 case OPC_MOVZ_PS:
12827 check_ps(ctx);
12829 TCGLabel *l1 = gen_new_label();
12830 TCGv_i64 fp0;
12832 if (ft != 0) {
12833 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12835 fp0 = tcg_temp_new_i64();
12836 gen_load_fpr64(ctx, fp0, fs);
12837 gen_store_fpr64(ctx, fp0, fd);
12838 tcg_temp_free_i64(fp0);
12839 gen_set_label(l1);
12841 break;
12842 case OPC_MOVN_PS:
12843 check_ps(ctx);
12845 TCGLabel *l1 = gen_new_label();
12846 TCGv_i64 fp0;
12848 if (ft != 0) {
12849 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12850 fp0 = tcg_temp_new_i64();
12851 gen_load_fpr64(ctx, fp0, fs);
12852 gen_store_fpr64(ctx, fp0, fd);
12853 tcg_temp_free_i64(fp0);
12854 gen_set_label(l1);
12857 break;
12858 case OPC_ADDR_PS:
12859 check_ps(ctx);
12861 TCGv_i64 fp0 = tcg_temp_new_i64();
12862 TCGv_i64 fp1 = tcg_temp_new_i64();
12864 gen_load_fpr64(ctx, fp0, ft);
12865 gen_load_fpr64(ctx, fp1, fs);
12866 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12867 tcg_temp_free_i64(fp1);
12868 gen_store_fpr64(ctx, fp0, fd);
12869 tcg_temp_free_i64(fp0);
12871 break;
12872 case OPC_MULR_PS:
12873 check_ps(ctx);
12875 TCGv_i64 fp0 = tcg_temp_new_i64();
12876 TCGv_i64 fp1 = tcg_temp_new_i64();
12878 gen_load_fpr64(ctx, fp0, ft);
12879 gen_load_fpr64(ctx, fp1, fs);
12880 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12881 tcg_temp_free_i64(fp1);
12882 gen_store_fpr64(ctx, fp0, fd);
12883 tcg_temp_free_i64(fp0);
12885 break;
12886 case OPC_RECIP2_PS:
12887 check_ps(ctx);
12889 TCGv_i64 fp0 = tcg_temp_new_i64();
12890 TCGv_i64 fp1 = tcg_temp_new_i64();
12892 gen_load_fpr64(ctx, fp0, fs);
12893 gen_load_fpr64(ctx, fp1, ft);
12894 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12895 tcg_temp_free_i64(fp1);
12896 gen_store_fpr64(ctx, fp0, fd);
12897 tcg_temp_free_i64(fp0);
12899 break;
12900 case OPC_RECIP1_PS:
12901 check_ps(ctx);
12903 TCGv_i64 fp0 = tcg_temp_new_i64();
12905 gen_load_fpr64(ctx, fp0, fs);
12906 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12907 gen_store_fpr64(ctx, fp0, fd);
12908 tcg_temp_free_i64(fp0);
12910 break;
12911 case OPC_RSQRT1_PS:
12912 check_ps(ctx);
12914 TCGv_i64 fp0 = tcg_temp_new_i64();
12916 gen_load_fpr64(ctx, fp0, fs);
12917 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12918 gen_store_fpr64(ctx, fp0, fd);
12919 tcg_temp_free_i64(fp0);
12921 break;
12922 case OPC_RSQRT2_PS:
12923 check_ps(ctx);
12925 TCGv_i64 fp0 = tcg_temp_new_i64();
12926 TCGv_i64 fp1 = tcg_temp_new_i64();
12928 gen_load_fpr64(ctx, fp0, fs);
12929 gen_load_fpr64(ctx, fp1, ft);
12930 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12931 tcg_temp_free_i64(fp1);
12932 gen_store_fpr64(ctx, fp0, fd);
12933 tcg_temp_free_i64(fp0);
12935 break;
12936 case OPC_CVT_S_PU:
12937 check_cp1_64bitmode(ctx);
12939 TCGv_i32 fp0 = tcg_temp_new_i32();
12941 gen_load_fpr32h(ctx, fp0, fs);
12942 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12943 gen_store_fpr32(ctx, fp0, fd);
12944 tcg_temp_free_i32(fp0);
12946 break;
12947 case OPC_CVT_PW_PS:
12948 check_ps(ctx);
12950 TCGv_i64 fp0 = tcg_temp_new_i64();
12952 gen_load_fpr64(ctx, fp0, fs);
12953 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12954 gen_store_fpr64(ctx, fp0, fd);
12955 tcg_temp_free_i64(fp0);
12957 break;
12958 case OPC_CVT_S_PL:
12959 check_cp1_64bitmode(ctx);
12961 TCGv_i32 fp0 = tcg_temp_new_i32();
12963 gen_load_fpr32(ctx, fp0, fs);
12964 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12965 gen_store_fpr32(ctx, fp0, fd);
12966 tcg_temp_free_i32(fp0);
12968 break;
12969 case OPC_PLL_PS:
12970 check_ps(ctx);
12972 TCGv_i32 fp0 = tcg_temp_new_i32();
12973 TCGv_i32 fp1 = tcg_temp_new_i32();
12975 gen_load_fpr32(ctx, fp0, fs);
12976 gen_load_fpr32(ctx, fp1, ft);
12977 gen_store_fpr32h(ctx, fp0, fd);
12978 gen_store_fpr32(ctx, fp1, fd);
12979 tcg_temp_free_i32(fp0);
12980 tcg_temp_free_i32(fp1);
12982 break;
12983 case OPC_PLU_PS:
12984 check_ps(ctx);
12986 TCGv_i32 fp0 = tcg_temp_new_i32();
12987 TCGv_i32 fp1 = tcg_temp_new_i32();
12989 gen_load_fpr32(ctx, fp0, fs);
12990 gen_load_fpr32h(ctx, fp1, ft);
12991 gen_store_fpr32(ctx, fp1, fd);
12992 gen_store_fpr32h(ctx, fp0, fd);
12993 tcg_temp_free_i32(fp0);
12994 tcg_temp_free_i32(fp1);
12996 break;
12997 case OPC_PUL_PS:
12998 check_ps(ctx);
13000 TCGv_i32 fp0 = tcg_temp_new_i32();
13001 TCGv_i32 fp1 = tcg_temp_new_i32();
13003 gen_load_fpr32h(ctx, fp0, fs);
13004 gen_load_fpr32(ctx, fp1, ft);
13005 gen_store_fpr32(ctx, fp1, fd);
13006 gen_store_fpr32h(ctx, fp0, fd);
13007 tcg_temp_free_i32(fp0);
13008 tcg_temp_free_i32(fp1);
13010 break;
13011 case OPC_PUU_PS:
13012 check_ps(ctx);
13014 TCGv_i32 fp0 = tcg_temp_new_i32();
13015 TCGv_i32 fp1 = tcg_temp_new_i32();
13017 gen_load_fpr32h(ctx, fp0, fs);
13018 gen_load_fpr32h(ctx, fp1, ft);
13019 gen_store_fpr32(ctx, fp1, fd);
13020 gen_store_fpr32h(ctx, fp0, fd);
13021 tcg_temp_free_i32(fp0);
13022 tcg_temp_free_i32(fp1);
13024 break;
13025 case OPC_CMP_F_PS:
13026 case OPC_CMP_UN_PS:
13027 case OPC_CMP_EQ_PS:
13028 case OPC_CMP_UEQ_PS:
13029 case OPC_CMP_OLT_PS:
13030 case OPC_CMP_ULT_PS:
13031 case OPC_CMP_OLE_PS:
13032 case OPC_CMP_ULE_PS:
13033 case OPC_CMP_SF_PS:
13034 case OPC_CMP_NGLE_PS:
13035 case OPC_CMP_SEQ_PS:
13036 case OPC_CMP_NGL_PS:
13037 case OPC_CMP_LT_PS:
13038 case OPC_CMP_NGE_PS:
13039 case OPC_CMP_LE_PS:
13040 case OPC_CMP_NGT_PS:
13041 if (ctx->opcode & (1 << 6)) {
13042 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
13043 } else {
13044 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
13046 break;
13047 default:
13048 MIPS_INVAL("farith");
13049 gen_reserved_instruction(ctx);
13050 return;
13054 /* Coprocessor 3 (FPU) */
13055 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
13056 int fd, int fs, int base, int index)
13058 TCGv t0 = tcg_temp_new();
13060 if (base == 0) {
13061 gen_load_gpr(t0, index);
13062 } else if (index == 0) {
13063 gen_load_gpr(t0, base);
13064 } else {
13065 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
13068 * Don't do NOP if destination is zero: we must perform the actual
13069 * memory access.
13071 switch (opc) {
13072 case OPC_LWXC1:
13073 check_cop1x(ctx);
13075 TCGv_i32 fp0 = tcg_temp_new_i32();
13077 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13078 tcg_gen_trunc_tl_i32(fp0, t0);
13079 gen_store_fpr32(ctx, fp0, fd);
13080 tcg_temp_free_i32(fp0);
13082 break;
13083 case OPC_LDXC1:
13084 check_cop1x(ctx);
13085 check_cp1_registers(ctx, fd);
13087 TCGv_i64 fp0 = tcg_temp_new_i64();
13088 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13089 gen_store_fpr64(ctx, fp0, fd);
13090 tcg_temp_free_i64(fp0);
13092 break;
13093 case OPC_LUXC1:
13094 check_cp1_64bitmode(ctx);
13095 tcg_gen_andi_tl(t0, t0, ~0x7);
13097 TCGv_i64 fp0 = tcg_temp_new_i64();
13099 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13100 gen_store_fpr64(ctx, fp0, fd);
13101 tcg_temp_free_i64(fp0);
13103 break;
13104 case OPC_SWXC1:
13105 check_cop1x(ctx);
13107 TCGv_i32 fp0 = tcg_temp_new_i32();
13108 gen_load_fpr32(ctx, fp0, fs);
13109 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
13110 tcg_temp_free_i32(fp0);
13112 break;
13113 case OPC_SDXC1:
13114 check_cop1x(ctx);
13115 check_cp1_registers(ctx, fs);
13117 TCGv_i64 fp0 = tcg_temp_new_i64();
13118 gen_load_fpr64(ctx, fp0, fs);
13119 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13120 tcg_temp_free_i64(fp0);
13122 break;
13123 case OPC_SUXC1:
13124 check_cp1_64bitmode(ctx);
13125 tcg_gen_andi_tl(t0, t0, ~0x7);
13127 TCGv_i64 fp0 = tcg_temp_new_i64();
13128 gen_load_fpr64(ctx, fp0, fs);
13129 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13130 tcg_temp_free_i64(fp0);
13132 break;
13134 tcg_temp_free(t0);
13137 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
13138 int fd, int fr, int fs, int ft)
13140 switch (opc) {
13141 case OPC_ALNV_PS:
13142 check_ps(ctx);
13144 TCGv t0 = tcg_temp_local_new();
13145 TCGv_i32 fp = tcg_temp_new_i32();
13146 TCGv_i32 fph = tcg_temp_new_i32();
13147 TCGLabel *l1 = gen_new_label();
13148 TCGLabel *l2 = gen_new_label();
13150 gen_load_gpr(t0, fr);
13151 tcg_gen_andi_tl(t0, t0, 0x7);
13153 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
13154 gen_load_fpr32(ctx, fp, fs);
13155 gen_load_fpr32h(ctx, fph, fs);
13156 gen_store_fpr32(ctx, fp, fd);
13157 gen_store_fpr32h(ctx, fph, fd);
13158 tcg_gen_br(l2);
13159 gen_set_label(l1);
13160 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
13161 tcg_temp_free(t0);
13162 #ifdef TARGET_WORDS_BIGENDIAN
13163 gen_load_fpr32(ctx, fp, fs);
13164 gen_load_fpr32h(ctx, fph, ft);
13165 gen_store_fpr32h(ctx, fp, fd);
13166 gen_store_fpr32(ctx, fph, fd);
13167 #else
13168 gen_load_fpr32h(ctx, fph, fs);
13169 gen_load_fpr32(ctx, fp, ft);
13170 gen_store_fpr32(ctx, fph, fd);
13171 gen_store_fpr32h(ctx, fp, fd);
13172 #endif
13173 gen_set_label(l2);
13174 tcg_temp_free_i32(fp);
13175 tcg_temp_free_i32(fph);
13177 break;
13178 case OPC_MADD_S:
13179 check_cop1x(ctx);
13181 TCGv_i32 fp0 = tcg_temp_new_i32();
13182 TCGv_i32 fp1 = tcg_temp_new_i32();
13183 TCGv_i32 fp2 = tcg_temp_new_i32();
13185 gen_load_fpr32(ctx, fp0, fs);
13186 gen_load_fpr32(ctx, fp1, ft);
13187 gen_load_fpr32(ctx, fp2, fr);
13188 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
13189 tcg_temp_free_i32(fp0);
13190 tcg_temp_free_i32(fp1);
13191 gen_store_fpr32(ctx, fp2, fd);
13192 tcg_temp_free_i32(fp2);
13194 break;
13195 case OPC_MADD_D:
13196 check_cop1x(ctx);
13197 check_cp1_registers(ctx, fd | fs | ft | fr);
13199 TCGv_i64 fp0 = tcg_temp_new_i64();
13200 TCGv_i64 fp1 = tcg_temp_new_i64();
13201 TCGv_i64 fp2 = tcg_temp_new_i64();
13203 gen_load_fpr64(ctx, fp0, fs);
13204 gen_load_fpr64(ctx, fp1, ft);
13205 gen_load_fpr64(ctx, fp2, fr);
13206 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
13207 tcg_temp_free_i64(fp0);
13208 tcg_temp_free_i64(fp1);
13209 gen_store_fpr64(ctx, fp2, fd);
13210 tcg_temp_free_i64(fp2);
13212 break;
13213 case OPC_MADD_PS:
13214 check_ps(ctx);
13216 TCGv_i64 fp0 = tcg_temp_new_i64();
13217 TCGv_i64 fp1 = tcg_temp_new_i64();
13218 TCGv_i64 fp2 = tcg_temp_new_i64();
13220 gen_load_fpr64(ctx, fp0, fs);
13221 gen_load_fpr64(ctx, fp1, ft);
13222 gen_load_fpr64(ctx, fp2, fr);
13223 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
13224 tcg_temp_free_i64(fp0);
13225 tcg_temp_free_i64(fp1);
13226 gen_store_fpr64(ctx, fp2, fd);
13227 tcg_temp_free_i64(fp2);
13229 break;
13230 case OPC_MSUB_S:
13231 check_cop1x(ctx);
13233 TCGv_i32 fp0 = tcg_temp_new_i32();
13234 TCGv_i32 fp1 = tcg_temp_new_i32();
13235 TCGv_i32 fp2 = tcg_temp_new_i32();
13237 gen_load_fpr32(ctx, fp0, fs);
13238 gen_load_fpr32(ctx, fp1, ft);
13239 gen_load_fpr32(ctx, fp2, fr);
13240 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
13241 tcg_temp_free_i32(fp0);
13242 tcg_temp_free_i32(fp1);
13243 gen_store_fpr32(ctx, fp2, fd);
13244 tcg_temp_free_i32(fp2);
13246 break;
13247 case OPC_MSUB_D:
13248 check_cop1x(ctx);
13249 check_cp1_registers(ctx, fd | fs | ft | fr);
13251 TCGv_i64 fp0 = tcg_temp_new_i64();
13252 TCGv_i64 fp1 = tcg_temp_new_i64();
13253 TCGv_i64 fp2 = tcg_temp_new_i64();
13255 gen_load_fpr64(ctx, fp0, fs);
13256 gen_load_fpr64(ctx, fp1, ft);
13257 gen_load_fpr64(ctx, fp2, fr);
13258 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
13259 tcg_temp_free_i64(fp0);
13260 tcg_temp_free_i64(fp1);
13261 gen_store_fpr64(ctx, fp2, fd);
13262 tcg_temp_free_i64(fp2);
13264 break;
13265 case OPC_MSUB_PS:
13266 check_ps(ctx);
13268 TCGv_i64 fp0 = tcg_temp_new_i64();
13269 TCGv_i64 fp1 = tcg_temp_new_i64();
13270 TCGv_i64 fp2 = tcg_temp_new_i64();
13272 gen_load_fpr64(ctx, fp0, fs);
13273 gen_load_fpr64(ctx, fp1, ft);
13274 gen_load_fpr64(ctx, fp2, fr);
13275 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
13276 tcg_temp_free_i64(fp0);
13277 tcg_temp_free_i64(fp1);
13278 gen_store_fpr64(ctx, fp2, fd);
13279 tcg_temp_free_i64(fp2);
13281 break;
13282 case OPC_NMADD_S:
13283 check_cop1x(ctx);
13285 TCGv_i32 fp0 = tcg_temp_new_i32();
13286 TCGv_i32 fp1 = tcg_temp_new_i32();
13287 TCGv_i32 fp2 = tcg_temp_new_i32();
13289 gen_load_fpr32(ctx, fp0, fs);
13290 gen_load_fpr32(ctx, fp1, ft);
13291 gen_load_fpr32(ctx, fp2, fr);
13292 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
13293 tcg_temp_free_i32(fp0);
13294 tcg_temp_free_i32(fp1);
13295 gen_store_fpr32(ctx, fp2, fd);
13296 tcg_temp_free_i32(fp2);
13298 break;
13299 case OPC_NMADD_D:
13300 check_cop1x(ctx);
13301 check_cp1_registers(ctx, fd | fs | ft | fr);
13303 TCGv_i64 fp0 = tcg_temp_new_i64();
13304 TCGv_i64 fp1 = tcg_temp_new_i64();
13305 TCGv_i64 fp2 = tcg_temp_new_i64();
13307 gen_load_fpr64(ctx, fp0, fs);
13308 gen_load_fpr64(ctx, fp1, ft);
13309 gen_load_fpr64(ctx, fp2, fr);
13310 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
13311 tcg_temp_free_i64(fp0);
13312 tcg_temp_free_i64(fp1);
13313 gen_store_fpr64(ctx, fp2, fd);
13314 tcg_temp_free_i64(fp2);
13316 break;
13317 case OPC_NMADD_PS:
13318 check_ps(ctx);
13320 TCGv_i64 fp0 = tcg_temp_new_i64();
13321 TCGv_i64 fp1 = tcg_temp_new_i64();
13322 TCGv_i64 fp2 = tcg_temp_new_i64();
13324 gen_load_fpr64(ctx, fp0, fs);
13325 gen_load_fpr64(ctx, fp1, ft);
13326 gen_load_fpr64(ctx, fp2, fr);
13327 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
13328 tcg_temp_free_i64(fp0);
13329 tcg_temp_free_i64(fp1);
13330 gen_store_fpr64(ctx, fp2, fd);
13331 tcg_temp_free_i64(fp2);
13333 break;
13334 case OPC_NMSUB_S:
13335 check_cop1x(ctx);
13337 TCGv_i32 fp0 = tcg_temp_new_i32();
13338 TCGv_i32 fp1 = tcg_temp_new_i32();
13339 TCGv_i32 fp2 = tcg_temp_new_i32();
13341 gen_load_fpr32(ctx, fp0, fs);
13342 gen_load_fpr32(ctx, fp1, ft);
13343 gen_load_fpr32(ctx, fp2, fr);
13344 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
13345 tcg_temp_free_i32(fp0);
13346 tcg_temp_free_i32(fp1);
13347 gen_store_fpr32(ctx, fp2, fd);
13348 tcg_temp_free_i32(fp2);
13350 break;
13351 case OPC_NMSUB_D:
13352 check_cop1x(ctx);
13353 check_cp1_registers(ctx, fd | fs | ft | fr);
13355 TCGv_i64 fp0 = tcg_temp_new_i64();
13356 TCGv_i64 fp1 = tcg_temp_new_i64();
13357 TCGv_i64 fp2 = tcg_temp_new_i64();
13359 gen_load_fpr64(ctx, fp0, fs);
13360 gen_load_fpr64(ctx, fp1, ft);
13361 gen_load_fpr64(ctx, fp2, fr);
13362 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13363 tcg_temp_free_i64(fp0);
13364 tcg_temp_free_i64(fp1);
13365 gen_store_fpr64(ctx, fp2, fd);
13366 tcg_temp_free_i64(fp2);
13368 break;
13369 case OPC_NMSUB_PS:
13370 check_ps(ctx);
13372 TCGv_i64 fp0 = tcg_temp_new_i64();
13373 TCGv_i64 fp1 = tcg_temp_new_i64();
13374 TCGv_i64 fp2 = tcg_temp_new_i64();
13376 gen_load_fpr64(ctx, fp0, fs);
13377 gen_load_fpr64(ctx, fp1, ft);
13378 gen_load_fpr64(ctx, fp2, fr);
13379 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13380 tcg_temp_free_i64(fp0);
13381 tcg_temp_free_i64(fp1);
13382 gen_store_fpr64(ctx, fp2, fd);
13383 tcg_temp_free_i64(fp2);
13385 break;
13386 default:
13387 MIPS_INVAL("flt3_arith");
13388 gen_reserved_instruction(ctx);
13389 return;
13393 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13395 TCGv t0;
13397 #if !defined(CONFIG_USER_ONLY)
13399 * The Linux kernel will emulate rdhwr if it's not supported natively.
13400 * Therefore only check the ISA in system mode.
13402 check_insn(ctx, ISA_MIPS_R2);
13403 #endif
13404 t0 = tcg_temp_new();
13406 switch (rd) {
13407 case 0:
13408 gen_helper_rdhwr_cpunum(t0, cpu_env);
13409 gen_store_gpr(t0, rt);
13410 break;
13411 case 1:
13412 gen_helper_rdhwr_synci_step(t0, cpu_env);
13413 gen_store_gpr(t0, rt);
13414 break;
13415 case 2:
13416 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13417 gen_io_start();
13419 gen_helper_rdhwr_cc(t0, cpu_env);
13420 gen_store_gpr(t0, rt);
13422 * Break the TB to be able to take timer interrupts immediately
13423 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13424 * we break completely out of translated code.
13426 gen_save_pc(ctx->base.pc_next + 4);
13427 ctx->base.is_jmp = DISAS_EXIT;
13428 break;
13429 case 3:
13430 gen_helper_rdhwr_ccres(t0, cpu_env);
13431 gen_store_gpr(t0, rt);
13432 break;
13433 case 4:
13434 check_insn(ctx, ISA_MIPS_R6);
13435 if (sel != 0) {
13437 * Performance counter registers are not implemented other than
13438 * control register 0.
13440 generate_exception(ctx, EXCP_RI);
13442 gen_helper_rdhwr_performance(t0, cpu_env);
13443 gen_store_gpr(t0, rt);
13444 break;
13445 case 5:
13446 check_insn(ctx, ISA_MIPS_R6);
13447 gen_helper_rdhwr_xnp(t0, cpu_env);
13448 gen_store_gpr(t0, rt);
13449 break;
13450 case 29:
13451 #if defined(CONFIG_USER_ONLY)
13452 tcg_gen_ld_tl(t0, cpu_env,
13453 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13454 gen_store_gpr(t0, rt);
13455 break;
13456 #else
13457 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13458 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13459 tcg_gen_ld_tl(t0, cpu_env,
13460 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13461 gen_store_gpr(t0, rt);
13462 } else {
13463 gen_reserved_instruction(ctx);
13465 break;
13466 #endif
13467 default: /* Invalid */
13468 MIPS_INVAL("rdhwr");
13469 gen_reserved_instruction(ctx);
13470 break;
13472 tcg_temp_free(t0);
13475 static inline void clear_branch_hflags(DisasContext *ctx)
13477 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13478 if (ctx->base.is_jmp == DISAS_NEXT) {
13479 save_cpu_state(ctx, 0);
13480 } else {
13482 * It is not safe to save ctx->hflags as hflags may be changed
13483 * in execution time by the instruction in delay / forbidden slot.
13485 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13489 static void gen_branch(DisasContext *ctx, int insn_bytes)
13491 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13492 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13493 /* Branches completion */
13494 clear_branch_hflags(ctx);
13495 ctx->base.is_jmp = DISAS_NORETURN;
13496 /* FIXME: Need to clear can_do_io. */
13497 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13498 case MIPS_HFLAG_FBNSLOT:
13499 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13500 break;
13501 case MIPS_HFLAG_B:
13502 /* unconditional branch */
13503 if (proc_hflags & MIPS_HFLAG_BX) {
13504 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13506 gen_goto_tb(ctx, 0, ctx->btarget);
13507 break;
13508 case MIPS_HFLAG_BL:
13509 /* blikely taken case */
13510 gen_goto_tb(ctx, 0, ctx->btarget);
13511 break;
13512 case MIPS_HFLAG_BC:
13513 /* Conditional branch */
13515 TCGLabel *l1 = gen_new_label();
13517 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13518 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13519 gen_set_label(l1);
13520 gen_goto_tb(ctx, 0, ctx->btarget);
13522 break;
13523 case MIPS_HFLAG_BR:
13524 /* unconditional branch to register */
13525 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13526 TCGv t0 = tcg_temp_new();
13527 TCGv_i32 t1 = tcg_temp_new_i32();
13529 tcg_gen_andi_tl(t0, btarget, 0x1);
13530 tcg_gen_trunc_tl_i32(t1, t0);
13531 tcg_temp_free(t0);
13532 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13533 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13534 tcg_gen_or_i32(hflags, hflags, t1);
13535 tcg_temp_free_i32(t1);
13537 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13538 } else {
13539 tcg_gen_mov_tl(cpu_PC, btarget);
13541 if (ctx->base.singlestep_enabled) {
13542 save_cpu_state(ctx, 0);
13543 gen_helper_raise_exception_debug(cpu_env);
13545 tcg_gen_lookup_and_goto_ptr();
13546 break;
13547 default:
13548 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13549 abort();
13554 /* Compact Branches */
13555 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13556 int rs, int rt, int32_t offset)
13558 int bcond_compute = 0;
13559 TCGv t0 = tcg_temp_new();
13560 TCGv t1 = tcg_temp_new();
13561 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13563 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13564 #ifdef MIPS_DEBUG_DISAS
13565 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13566 "\n", ctx->base.pc_next);
13567 #endif
13568 gen_reserved_instruction(ctx);
13569 goto out;
13572 /* Load needed operands and calculate btarget */
13573 switch (opc) {
13574 /* compact branch */
13575 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13576 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13577 gen_load_gpr(t0, rs);
13578 gen_load_gpr(t1, rt);
13579 bcond_compute = 1;
13580 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13581 if (rs <= rt && rs == 0) {
13582 /* OPC_BEQZALC, OPC_BNEZALC */
13583 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13585 break;
13586 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13587 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13588 gen_load_gpr(t0, rs);
13589 gen_load_gpr(t1, rt);
13590 bcond_compute = 1;
13591 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13592 break;
13593 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13594 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13595 if (rs == 0 || rs == rt) {
13596 /* OPC_BLEZALC, OPC_BGEZALC */
13597 /* OPC_BGTZALC, OPC_BLTZALC */
13598 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13600 gen_load_gpr(t0, rs);
13601 gen_load_gpr(t1, rt);
13602 bcond_compute = 1;
13603 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13604 break;
13605 case OPC_BC:
13606 case OPC_BALC:
13607 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13608 break;
13609 case OPC_BEQZC:
13610 case OPC_BNEZC:
13611 if (rs != 0) {
13612 /* OPC_BEQZC, OPC_BNEZC */
13613 gen_load_gpr(t0, rs);
13614 bcond_compute = 1;
13615 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13616 } else {
13617 /* OPC_JIC, OPC_JIALC */
13618 TCGv tbase = tcg_temp_new();
13619 TCGv toffset = tcg_temp_new();
13621 gen_load_gpr(tbase, rt);
13622 tcg_gen_movi_tl(toffset, offset);
13623 gen_op_addr_add(ctx, btarget, tbase, toffset);
13624 tcg_temp_free(tbase);
13625 tcg_temp_free(toffset);
13627 break;
13628 default:
13629 MIPS_INVAL("Compact branch/jump");
13630 gen_reserved_instruction(ctx);
13631 goto out;
13634 if (bcond_compute == 0) {
13635 /* Uncoditional compact branch */
13636 switch (opc) {
13637 case OPC_JIALC:
13638 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13639 /* Fallthrough */
13640 case OPC_JIC:
13641 ctx->hflags |= MIPS_HFLAG_BR;
13642 break;
13643 case OPC_BALC:
13644 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13645 /* Fallthrough */
13646 case OPC_BC:
13647 ctx->hflags |= MIPS_HFLAG_B;
13648 break;
13649 default:
13650 MIPS_INVAL("Compact branch/jump");
13651 gen_reserved_instruction(ctx);
13652 goto out;
13655 /* Generating branch here as compact branches don't have delay slot */
13656 gen_branch(ctx, 4);
13657 } else {
13658 /* Conditional compact branch */
13659 TCGLabel *fs = gen_new_label();
13660 save_cpu_state(ctx, 0);
13662 switch (opc) {
13663 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13664 if (rs == 0 && rt != 0) {
13665 /* OPC_BLEZALC */
13666 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13667 } else if (rs != 0 && rt != 0 && rs == rt) {
13668 /* OPC_BGEZALC */
13669 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13670 } else {
13671 /* OPC_BGEUC */
13672 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13674 break;
13675 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13676 if (rs == 0 && rt != 0) {
13677 /* OPC_BGTZALC */
13678 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13679 } else if (rs != 0 && rt != 0 && rs == rt) {
13680 /* OPC_BLTZALC */
13681 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13682 } else {
13683 /* OPC_BLTUC */
13684 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13686 break;
13687 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13688 if (rs == 0 && rt != 0) {
13689 /* OPC_BLEZC */
13690 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13691 } else if (rs != 0 && rt != 0 && rs == rt) {
13692 /* OPC_BGEZC */
13693 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13694 } else {
13695 /* OPC_BGEC */
13696 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13698 break;
13699 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13700 if (rs == 0 && rt != 0) {
13701 /* OPC_BGTZC */
13702 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13703 } else if (rs != 0 && rt != 0 && rs == rt) {
13704 /* OPC_BLTZC */
13705 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13706 } else {
13707 /* OPC_BLTC */
13708 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13710 break;
13711 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13712 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13713 if (rs >= rt) {
13714 /* OPC_BOVC, OPC_BNVC */
13715 TCGv t2 = tcg_temp_new();
13716 TCGv t3 = tcg_temp_new();
13717 TCGv t4 = tcg_temp_new();
13718 TCGv input_overflow = tcg_temp_new();
13720 gen_load_gpr(t0, rs);
13721 gen_load_gpr(t1, rt);
13722 tcg_gen_ext32s_tl(t2, t0);
13723 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13724 tcg_gen_ext32s_tl(t3, t1);
13725 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13726 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13728 tcg_gen_add_tl(t4, t2, t3);
13729 tcg_gen_ext32s_tl(t4, t4);
13730 tcg_gen_xor_tl(t2, t2, t3);
13731 tcg_gen_xor_tl(t3, t4, t3);
13732 tcg_gen_andc_tl(t2, t3, t2);
13733 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13734 tcg_gen_or_tl(t4, t4, input_overflow);
13735 if (opc == OPC_BOVC) {
13736 /* OPC_BOVC */
13737 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13738 } else {
13739 /* OPC_BNVC */
13740 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13742 tcg_temp_free(input_overflow);
13743 tcg_temp_free(t4);
13744 tcg_temp_free(t3);
13745 tcg_temp_free(t2);
13746 } else if (rs < rt && rs == 0) {
13747 /* OPC_BEQZALC, OPC_BNEZALC */
13748 if (opc == OPC_BEQZALC) {
13749 /* OPC_BEQZALC */
13750 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13751 } else {
13752 /* OPC_BNEZALC */
13753 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13755 } else {
13756 /* OPC_BEQC, OPC_BNEC */
13757 if (opc == OPC_BEQC) {
13758 /* OPC_BEQC */
13759 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13760 } else {
13761 /* OPC_BNEC */
13762 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13765 break;
13766 case OPC_BEQZC:
13767 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13768 break;
13769 case OPC_BNEZC:
13770 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13771 break;
13772 default:
13773 MIPS_INVAL("Compact conditional branch/jump");
13774 gen_reserved_instruction(ctx);
13775 goto out;
13778 /* Generating branch here as compact branches don't have delay slot */
13779 gen_goto_tb(ctx, 1, ctx->btarget);
13780 gen_set_label(fs);
13782 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13785 out:
13786 tcg_temp_free(t0);
13787 tcg_temp_free(t1);
13790 /* ISA extensions (ASEs) */
13791 /* MIPS16 extension to MIPS32 */
13793 /* MIPS16 major opcodes */
13794 enum {
13795 M16_OPC_ADDIUSP = 0x00,
13796 M16_OPC_ADDIUPC = 0x01,
13797 M16_OPC_B = 0x02,
13798 M16_OPC_JAL = 0x03,
13799 M16_OPC_BEQZ = 0x04,
13800 M16_OPC_BNEQZ = 0x05,
13801 M16_OPC_SHIFT = 0x06,
13802 M16_OPC_LD = 0x07,
13803 M16_OPC_RRIA = 0x08,
13804 M16_OPC_ADDIU8 = 0x09,
13805 M16_OPC_SLTI = 0x0a,
13806 M16_OPC_SLTIU = 0x0b,
13807 M16_OPC_I8 = 0x0c,
13808 M16_OPC_LI = 0x0d,
13809 M16_OPC_CMPI = 0x0e,
13810 M16_OPC_SD = 0x0f,
13811 M16_OPC_LB = 0x10,
13812 M16_OPC_LH = 0x11,
13813 M16_OPC_LWSP = 0x12,
13814 M16_OPC_LW = 0x13,
13815 M16_OPC_LBU = 0x14,
13816 M16_OPC_LHU = 0x15,
13817 M16_OPC_LWPC = 0x16,
13818 M16_OPC_LWU = 0x17,
13819 M16_OPC_SB = 0x18,
13820 M16_OPC_SH = 0x19,
13821 M16_OPC_SWSP = 0x1a,
13822 M16_OPC_SW = 0x1b,
13823 M16_OPC_RRR = 0x1c,
13824 M16_OPC_RR = 0x1d,
13825 M16_OPC_EXTEND = 0x1e,
13826 M16_OPC_I64 = 0x1f
13829 /* I8 funct field */
13830 enum {
13831 I8_BTEQZ = 0x0,
13832 I8_BTNEZ = 0x1,
13833 I8_SWRASP = 0x2,
13834 I8_ADJSP = 0x3,
13835 I8_SVRS = 0x4,
13836 I8_MOV32R = 0x5,
13837 I8_MOVR32 = 0x7
13840 /* RRR f field */
13841 enum {
13842 RRR_DADDU = 0x0,
13843 RRR_ADDU = 0x1,
13844 RRR_DSUBU = 0x2,
13845 RRR_SUBU = 0x3
13848 /* RR funct field */
13849 enum {
13850 RR_JR = 0x00,
13851 RR_SDBBP = 0x01,
13852 RR_SLT = 0x02,
13853 RR_SLTU = 0x03,
13854 RR_SLLV = 0x04,
13855 RR_BREAK = 0x05,
13856 RR_SRLV = 0x06,
13857 RR_SRAV = 0x07,
13858 RR_DSRL = 0x08,
13859 RR_CMP = 0x0a,
13860 RR_NEG = 0x0b,
13861 RR_AND = 0x0c,
13862 RR_OR = 0x0d,
13863 RR_XOR = 0x0e,
13864 RR_NOT = 0x0f,
13865 RR_MFHI = 0x10,
13866 RR_CNVT = 0x11,
13867 RR_MFLO = 0x12,
13868 RR_DSRA = 0x13,
13869 RR_DSLLV = 0x14,
13870 RR_DSRLV = 0x16,
13871 RR_DSRAV = 0x17,
13872 RR_MULT = 0x18,
13873 RR_MULTU = 0x19,
13874 RR_DIV = 0x1a,
13875 RR_DIVU = 0x1b,
13876 RR_DMULT = 0x1c,
13877 RR_DMULTU = 0x1d,
13878 RR_DDIV = 0x1e,
13879 RR_DDIVU = 0x1f
13882 /* I64 funct field */
13883 enum {
13884 I64_LDSP = 0x0,
13885 I64_SDSP = 0x1,
13886 I64_SDRASP = 0x2,
13887 I64_DADJSP = 0x3,
13888 I64_LDPC = 0x4,
13889 I64_DADDIU5 = 0x5,
13890 I64_DADDIUPC = 0x6,
13891 I64_DADDIUSP = 0x7
13894 /* RR ry field for CNVT */
13895 enum {
13896 RR_RY_CNVT_ZEB = 0x0,
13897 RR_RY_CNVT_ZEH = 0x1,
13898 RR_RY_CNVT_ZEW = 0x2,
13899 RR_RY_CNVT_SEB = 0x4,
13900 RR_RY_CNVT_SEH = 0x5,
13901 RR_RY_CNVT_SEW = 0x6,
13904 static int xlat(int r)
13906 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13908 return map[r];
13911 static void gen_mips16_save(DisasContext *ctx,
13912 int xsregs, int aregs,
13913 int do_ra, int do_s0, int do_s1,
13914 int framesize)
13916 TCGv t0 = tcg_temp_new();
13917 TCGv t1 = tcg_temp_new();
13918 TCGv t2 = tcg_temp_new();
13919 int args, astatic;
13921 switch (aregs) {
13922 case 0:
13923 case 1:
13924 case 2:
13925 case 3:
13926 case 11:
13927 args = 0;
13928 break;
13929 case 4:
13930 case 5:
13931 case 6:
13932 case 7:
13933 args = 1;
13934 break;
13935 case 8:
13936 case 9:
13937 case 10:
13938 args = 2;
13939 break;
13940 case 12:
13941 case 13:
13942 args = 3;
13943 break;
13944 case 14:
13945 args = 4;
13946 break;
13947 default:
13948 gen_reserved_instruction(ctx);
13949 return;
13952 switch (args) {
13953 case 4:
13954 gen_base_offset_addr(ctx, t0, 29, 12);
13955 gen_load_gpr(t1, 7);
13956 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13957 /* Fall through */
13958 case 3:
13959 gen_base_offset_addr(ctx, t0, 29, 8);
13960 gen_load_gpr(t1, 6);
13961 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13962 /* Fall through */
13963 case 2:
13964 gen_base_offset_addr(ctx, t0, 29, 4);
13965 gen_load_gpr(t1, 5);
13966 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13967 /* Fall through */
13968 case 1:
13969 gen_base_offset_addr(ctx, t0, 29, 0);
13970 gen_load_gpr(t1, 4);
13971 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13974 gen_load_gpr(t0, 29);
13976 #define DECR_AND_STORE(reg) do { \
13977 tcg_gen_movi_tl(t2, -4); \
13978 gen_op_addr_add(ctx, t0, t0, t2); \
13979 gen_load_gpr(t1, reg); \
13980 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13981 } while (0)
13983 if (do_ra) {
13984 DECR_AND_STORE(31);
13987 switch (xsregs) {
13988 case 7:
13989 DECR_AND_STORE(30);
13990 /* Fall through */
13991 case 6:
13992 DECR_AND_STORE(23);
13993 /* Fall through */
13994 case 5:
13995 DECR_AND_STORE(22);
13996 /* Fall through */
13997 case 4:
13998 DECR_AND_STORE(21);
13999 /* Fall through */
14000 case 3:
14001 DECR_AND_STORE(20);
14002 /* Fall through */
14003 case 2:
14004 DECR_AND_STORE(19);
14005 /* Fall through */
14006 case 1:
14007 DECR_AND_STORE(18);
14010 if (do_s1) {
14011 DECR_AND_STORE(17);
14013 if (do_s0) {
14014 DECR_AND_STORE(16);
14017 switch (aregs) {
14018 case 0:
14019 case 4:
14020 case 8:
14021 case 12:
14022 case 14:
14023 astatic = 0;
14024 break;
14025 case 1:
14026 case 5:
14027 case 9:
14028 case 13:
14029 astatic = 1;
14030 break;
14031 case 2:
14032 case 6:
14033 case 10:
14034 astatic = 2;
14035 break;
14036 case 3:
14037 case 7:
14038 astatic = 3;
14039 break;
14040 case 11:
14041 astatic = 4;
14042 break;
14043 default:
14044 gen_reserved_instruction(ctx);
14045 return;
14048 if (astatic > 0) {
14049 DECR_AND_STORE(7);
14050 if (astatic > 1) {
14051 DECR_AND_STORE(6);
14052 if (astatic > 2) {
14053 DECR_AND_STORE(5);
14054 if (astatic > 3) {
14055 DECR_AND_STORE(4);
14060 #undef DECR_AND_STORE
14062 tcg_gen_movi_tl(t2, -framesize);
14063 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14064 tcg_temp_free(t0);
14065 tcg_temp_free(t1);
14066 tcg_temp_free(t2);
14069 static void gen_mips16_restore(DisasContext *ctx,
14070 int xsregs, int aregs,
14071 int do_ra, int do_s0, int do_s1,
14072 int framesize)
14074 int astatic;
14075 TCGv t0 = tcg_temp_new();
14076 TCGv t1 = tcg_temp_new();
14077 TCGv t2 = tcg_temp_new();
14079 tcg_gen_movi_tl(t2, framesize);
14080 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
14082 #define DECR_AND_LOAD(reg) do { \
14083 tcg_gen_movi_tl(t2, -4); \
14084 gen_op_addr_add(ctx, t0, t0, t2); \
14085 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
14086 gen_store_gpr(t1, reg); \
14087 } while (0)
14089 if (do_ra) {
14090 DECR_AND_LOAD(31);
14093 switch (xsregs) {
14094 case 7:
14095 DECR_AND_LOAD(30);
14096 /* Fall through */
14097 case 6:
14098 DECR_AND_LOAD(23);
14099 /* Fall through */
14100 case 5:
14101 DECR_AND_LOAD(22);
14102 /* Fall through */
14103 case 4:
14104 DECR_AND_LOAD(21);
14105 /* Fall through */
14106 case 3:
14107 DECR_AND_LOAD(20);
14108 /* Fall through */
14109 case 2:
14110 DECR_AND_LOAD(19);
14111 /* Fall through */
14112 case 1:
14113 DECR_AND_LOAD(18);
14116 if (do_s1) {
14117 DECR_AND_LOAD(17);
14119 if (do_s0) {
14120 DECR_AND_LOAD(16);
14123 switch (aregs) {
14124 case 0:
14125 case 4:
14126 case 8:
14127 case 12:
14128 case 14:
14129 astatic = 0;
14130 break;
14131 case 1:
14132 case 5:
14133 case 9:
14134 case 13:
14135 astatic = 1;
14136 break;
14137 case 2:
14138 case 6:
14139 case 10:
14140 astatic = 2;
14141 break;
14142 case 3:
14143 case 7:
14144 astatic = 3;
14145 break;
14146 case 11:
14147 astatic = 4;
14148 break;
14149 default:
14150 gen_reserved_instruction(ctx);
14151 return;
14154 if (astatic > 0) {
14155 DECR_AND_LOAD(7);
14156 if (astatic > 1) {
14157 DECR_AND_LOAD(6);
14158 if (astatic > 2) {
14159 DECR_AND_LOAD(5);
14160 if (astatic > 3) {
14161 DECR_AND_LOAD(4);
14166 #undef DECR_AND_LOAD
14168 tcg_gen_movi_tl(t2, framesize);
14169 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14170 tcg_temp_free(t0);
14171 tcg_temp_free(t1);
14172 tcg_temp_free(t2);
14175 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
14176 int is_64_bit, int extended)
14178 TCGv t0;
14180 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14181 gen_reserved_instruction(ctx);
14182 return;
14185 t0 = tcg_temp_new();
14187 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
14188 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
14189 if (!is_64_bit) {
14190 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14193 tcg_temp_free(t0);
14196 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
14197 int16_t offset)
14199 TCGv_i32 t0 = tcg_const_i32(op);
14200 TCGv t1 = tcg_temp_new();
14201 gen_base_offset_addr(ctx, t1, base, offset);
14202 gen_helper_cache(cpu_env, t1, t0);
14205 #if defined(TARGET_MIPS64)
14206 static void decode_i64_mips16(DisasContext *ctx,
14207 int ry, int funct, int16_t offset,
14208 int extended)
14210 switch (funct) {
14211 case I64_LDSP:
14212 check_insn(ctx, ISA_MIPS3);
14213 check_mips_64(ctx);
14214 offset = extended ? offset : offset << 3;
14215 gen_ld(ctx, OPC_LD, ry, 29, offset);
14216 break;
14217 case I64_SDSP:
14218 check_insn(ctx, ISA_MIPS3);
14219 check_mips_64(ctx);
14220 offset = extended ? offset : offset << 3;
14221 gen_st(ctx, OPC_SD, ry, 29, offset);
14222 break;
14223 case I64_SDRASP:
14224 check_insn(ctx, ISA_MIPS3);
14225 check_mips_64(ctx);
14226 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
14227 gen_st(ctx, OPC_SD, 31, 29, offset);
14228 break;
14229 case I64_DADJSP:
14230 check_insn(ctx, ISA_MIPS3);
14231 check_mips_64(ctx);
14232 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
14233 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
14234 break;
14235 case I64_LDPC:
14236 check_insn(ctx, ISA_MIPS3);
14237 check_mips_64(ctx);
14238 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14239 gen_reserved_instruction(ctx);
14240 } else {
14241 offset = extended ? offset : offset << 3;
14242 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
14244 break;
14245 case I64_DADDIU5:
14246 check_insn(ctx, ISA_MIPS3);
14247 check_mips_64(ctx);
14248 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
14249 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
14250 break;
14251 case I64_DADDIUPC:
14252 check_insn(ctx, ISA_MIPS3);
14253 check_mips_64(ctx);
14254 offset = extended ? offset : offset << 2;
14255 gen_addiupc(ctx, ry, offset, 1, extended);
14256 break;
14257 case I64_DADDIUSP:
14258 check_insn(ctx, ISA_MIPS3);
14259 check_mips_64(ctx);
14260 offset = extended ? offset : offset << 2;
14261 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
14262 break;
14265 #endif
14267 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14269 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
14270 int op, rx, ry, funct, sa;
14271 int16_t imm, offset;
14273 ctx->opcode = (ctx->opcode << 16) | extend;
14274 op = (ctx->opcode >> 11) & 0x1f;
14275 sa = (ctx->opcode >> 22) & 0x1f;
14276 funct = (ctx->opcode >> 8) & 0x7;
14277 rx = xlat((ctx->opcode >> 8) & 0x7);
14278 ry = xlat((ctx->opcode >> 5) & 0x7);
14279 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
14280 | ((ctx->opcode >> 21) & 0x3f) << 5
14281 | (ctx->opcode & 0x1f));
14284 * The extended opcodes cleverly reuse the opcodes from their 16-bit
14285 * counterparts.
14287 switch (op) {
14288 case M16_OPC_ADDIUSP:
14289 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14290 break;
14291 case M16_OPC_ADDIUPC:
14292 gen_addiupc(ctx, rx, imm, 0, 1);
14293 break;
14294 case M16_OPC_B:
14295 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
14296 /* No delay slot, so just process as a normal instruction */
14297 break;
14298 case M16_OPC_BEQZ:
14299 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
14300 /* No delay slot, so just process as a normal instruction */
14301 break;
14302 case M16_OPC_BNEQZ:
14303 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
14304 /* No delay slot, so just process as a normal instruction */
14305 break;
14306 case M16_OPC_SHIFT:
14307 switch (ctx->opcode & 0x3) {
14308 case 0x0:
14309 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14310 break;
14311 case 0x1:
14312 #if defined(TARGET_MIPS64)
14313 check_mips_64(ctx);
14314 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14315 #else
14316 gen_reserved_instruction(ctx);
14317 #endif
14318 break;
14319 case 0x2:
14320 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14321 break;
14322 case 0x3:
14323 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14324 break;
14326 break;
14327 #if defined(TARGET_MIPS64)
14328 case M16_OPC_LD:
14329 check_insn(ctx, ISA_MIPS3);
14330 check_mips_64(ctx);
14331 gen_ld(ctx, OPC_LD, ry, rx, offset);
14332 break;
14333 #endif
14334 case M16_OPC_RRIA:
14335 imm = ctx->opcode & 0xf;
14336 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
14337 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
14338 imm = (int16_t) (imm << 1) >> 1;
14339 if ((ctx->opcode >> 4) & 0x1) {
14340 #if defined(TARGET_MIPS64)
14341 check_mips_64(ctx);
14342 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14343 #else
14344 gen_reserved_instruction(ctx);
14345 #endif
14346 } else {
14347 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14349 break;
14350 case M16_OPC_ADDIU8:
14351 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14352 break;
14353 case M16_OPC_SLTI:
14354 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14355 break;
14356 case M16_OPC_SLTIU:
14357 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14358 break;
14359 case M16_OPC_I8:
14360 switch (funct) {
14361 case I8_BTEQZ:
14362 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14363 break;
14364 case I8_BTNEZ:
14365 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14366 break;
14367 case I8_SWRASP:
14368 gen_st(ctx, OPC_SW, 31, 29, imm);
14369 break;
14370 case I8_ADJSP:
14371 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14372 break;
14373 case I8_SVRS:
14374 check_insn(ctx, ISA_MIPS_R1);
14376 int xsregs = (ctx->opcode >> 24) & 0x7;
14377 int aregs = (ctx->opcode >> 16) & 0xf;
14378 int do_ra = (ctx->opcode >> 6) & 0x1;
14379 int do_s0 = (ctx->opcode >> 5) & 0x1;
14380 int do_s1 = (ctx->opcode >> 4) & 0x1;
14381 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14382 | (ctx->opcode & 0xf)) << 3;
14384 if (ctx->opcode & (1 << 7)) {
14385 gen_mips16_save(ctx, xsregs, aregs,
14386 do_ra, do_s0, do_s1,
14387 framesize);
14388 } else {
14389 gen_mips16_restore(ctx, xsregs, aregs,
14390 do_ra, do_s0, do_s1,
14391 framesize);
14394 break;
14395 default:
14396 gen_reserved_instruction(ctx);
14397 break;
14399 break;
14400 case M16_OPC_LI:
14401 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14402 break;
14403 case M16_OPC_CMPI:
14404 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14405 break;
14406 #if defined(TARGET_MIPS64)
14407 case M16_OPC_SD:
14408 check_insn(ctx, ISA_MIPS3);
14409 check_mips_64(ctx);
14410 gen_st(ctx, OPC_SD, ry, rx, offset);
14411 break;
14412 #endif
14413 case M16_OPC_LB:
14414 gen_ld(ctx, OPC_LB, ry, rx, offset);
14415 break;
14416 case M16_OPC_LH:
14417 gen_ld(ctx, OPC_LH, ry, rx, offset);
14418 break;
14419 case M16_OPC_LWSP:
14420 gen_ld(ctx, OPC_LW, rx, 29, offset);
14421 break;
14422 case M16_OPC_LW:
14423 gen_ld(ctx, OPC_LW, ry, rx, offset);
14424 break;
14425 case M16_OPC_LBU:
14426 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14427 break;
14428 case M16_OPC_LHU:
14429 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14430 break;
14431 case M16_OPC_LWPC:
14432 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14433 break;
14434 #if defined(TARGET_MIPS64)
14435 case M16_OPC_LWU:
14436 check_insn(ctx, ISA_MIPS3);
14437 check_mips_64(ctx);
14438 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14439 break;
14440 #endif
14441 case M16_OPC_SB:
14442 gen_st(ctx, OPC_SB, ry, rx, offset);
14443 break;
14444 case M16_OPC_SH:
14445 gen_st(ctx, OPC_SH, ry, rx, offset);
14446 break;
14447 case M16_OPC_SWSP:
14448 gen_st(ctx, OPC_SW, rx, 29, offset);
14449 break;
14450 case M16_OPC_SW:
14451 gen_st(ctx, OPC_SW, ry, rx, offset);
14452 break;
14453 #if defined(TARGET_MIPS64)
14454 case M16_OPC_I64:
14455 decode_i64_mips16(ctx, ry, funct, offset, 1);
14456 break;
14457 #endif
14458 default:
14459 gen_reserved_instruction(ctx);
14460 break;
14463 return 4;
14466 static inline bool is_uhi(int sdbbp_code)
14468 #ifdef CONFIG_USER_ONLY
14469 return false;
14470 #else
14471 return semihosting_enabled() && sdbbp_code == 1;
14472 #endif
14475 #ifdef CONFIG_USER_ONLY
14476 /* The above should dead-code away any calls to this..*/
14477 static inline void gen_helper_do_semihosting(void *env)
14479 g_assert_not_reached();
14481 #endif
14483 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14485 int rx, ry;
14486 int sa;
14487 int op, cnvt_op, op1, offset;
14488 int funct;
14489 int n_bytes;
14491 op = (ctx->opcode >> 11) & 0x1f;
14492 sa = (ctx->opcode >> 2) & 0x7;
14493 sa = sa == 0 ? 8 : sa;
14494 rx = xlat((ctx->opcode >> 8) & 0x7);
14495 cnvt_op = (ctx->opcode >> 5) & 0x7;
14496 ry = xlat((ctx->opcode >> 5) & 0x7);
14497 op1 = offset = ctx->opcode & 0x1f;
14499 n_bytes = 2;
14501 switch (op) {
14502 case M16_OPC_ADDIUSP:
14504 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14506 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14508 break;
14509 case M16_OPC_ADDIUPC:
14510 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14511 break;
14512 case M16_OPC_B:
14513 offset = (ctx->opcode & 0x7ff) << 1;
14514 offset = (int16_t)(offset << 4) >> 4;
14515 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14516 /* No delay slot, so just process as a normal instruction */
14517 break;
14518 case M16_OPC_JAL:
14519 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14520 offset = (((ctx->opcode & 0x1f) << 21)
14521 | ((ctx->opcode >> 5) & 0x1f) << 16
14522 | offset) << 2;
14523 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14524 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14525 n_bytes = 4;
14526 break;
14527 case M16_OPC_BEQZ:
14528 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14529 ((int8_t)ctx->opcode) << 1, 0);
14530 /* No delay slot, so just process as a normal instruction */
14531 break;
14532 case M16_OPC_BNEQZ:
14533 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14534 ((int8_t)ctx->opcode) << 1, 0);
14535 /* No delay slot, so just process as a normal instruction */
14536 break;
14537 case M16_OPC_SHIFT:
14538 switch (ctx->opcode & 0x3) {
14539 case 0x0:
14540 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14541 break;
14542 case 0x1:
14543 #if defined(TARGET_MIPS64)
14544 check_insn(ctx, ISA_MIPS3);
14545 check_mips_64(ctx);
14546 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14547 #else
14548 gen_reserved_instruction(ctx);
14549 #endif
14550 break;
14551 case 0x2:
14552 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14553 break;
14554 case 0x3:
14555 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14556 break;
14558 break;
14559 #if defined(TARGET_MIPS64)
14560 case M16_OPC_LD:
14561 check_insn(ctx, ISA_MIPS3);
14562 check_mips_64(ctx);
14563 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14564 break;
14565 #endif
14566 case M16_OPC_RRIA:
14568 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14570 if ((ctx->opcode >> 4) & 1) {
14571 #if defined(TARGET_MIPS64)
14572 check_insn(ctx, ISA_MIPS3);
14573 check_mips_64(ctx);
14574 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14575 #else
14576 gen_reserved_instruction(ctx);
14577 #endif
14578 } else {
14579 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14582 break;
14583 case M16_OPC_ADDIU8:
14585 int16_t imm = (int8_t) ctx->opcode;
14587 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14589 break;
14590 case M16_OPC_SLTI:
14592 int16_t imm = (uint8_t) ctx->opcode;
14593 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14595 break;
14596 case M16_OPC_SLTIU:
14598 int16_t imm = (uint8_t) ctx->opcode;
14599 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14601 break;
14602 case M16_OPC_I8:
14604 int reg32;
14606 funct = (ctx->opcode >> 8) & 0x7;
14607 switch (funct) {
14608 case I8_BTEQZ:
14609 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14610 ((int8_t)ctx->opcode) << 1, 0);
14611 break;
14612 case I8_BTNEZ:
14613 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14614 ((int8_t)ctx->opcode) << 1, 0);
14615 break;
14616 case I8_SWRASP:
14617 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14618 break;
14619 case I8_ADJSP:
14620 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14621 ((int8_t)ctx->opcode) << 3);
14622 break;
14623 case I8_SVRS:
14624 check_insn(ctx, ISA_MIPS_R1);
14626 int do_ra = ctx->opcode & (1 << 6);
14627 int do_s0 = ctx->opcode & (1 << 5);
14628 int do_s1 = ctx->opcode & (1 << 4);
14629 int framesize = ctx->opcode & 0xf;
14631 if (framesize == 0) {
14632 framesize = 128;
14633 } else {
14634 framesize = framesize << 3;
14637 if (ctx->opcode & (1 << 7)) {
14638 gen_mips16_save(ctx, 0, 0,
14639 do_ra, do_s0, do_s1, framesize);
14640 } else {
14641 gen_mips16_restore(ctx, 0, 0,
14642 do_ra, do_s0, do_s1, framesize);
14645 break;
14646 case I8_MOV32R:
14648 int rz = xlat(ctx->opcode & 0x7);
14650 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14651 ((ctx->opcode >> 5) & 0x7);
14652 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14654 break;
14655 case I8_MOVR32:
14656 reg32 = ctx->opcode & 0x1f;
14657 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14658 break;
14659 default:
14660 gen_reserved_instruction(ctx);
14661 break;
14664 break;
14665 case M16_OPC_LI:
14667 int16_t imm = (uint8_t) ctx->opcode;
14669 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14671 break;
14672 case M16_OPC_CMPI:
14674 int16_t imm = (uint8_t) ctx->opcode;
14675 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14677 break;
14678 #if defined(TARGET_MIPS64)
14679 case M16_OPC_SD:
14680 check_insn(ctx, ISA_MIPS3);
14681 check_mips_64(ctx);
14682 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14683 break;
14684 #endif
14685 case M16_OPC_LB:
14686 gen_ld(ctx, OPC_LB, ry, rx, offset);
14687 break;
14688 case M16_OPC_LH:
14689 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14690 break;
14691 case M16_OPC_LWSP:
14692 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14693 break;
14694 case M16_OPC_LW:
14695 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14696 break;
14697 case M16_OPC_LBU:
14698 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14699 break;
14700 case M16_OPC_LHU:
14701 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14702 break;
14703 case M16_OPC_LWPC:
14704 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14705 break;
14706 #if defined(TARGET_MIPS64)
14707 case M16_OPC_LWU:
14708 check_insn(ctx, ISA_MIPS3);
14709 check_mips_64(ctx);
14710 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14711 break;
14712 #endif
14713 case M16_OPC_SB:
14714 gen_st(ctx, OPC_SB, ry, rx, offset);
14715 break;
14716 case M16_OPC_SH:
14717 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14718 break;
14719 case M16_OPC_SWSP:
14720 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14721 break;
14722 case M16_OPC_SW:
14723 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14724 break;
14725 case M16_OPC_RRR:
14727 int rz = xlat((ctx->opcode >> 2) & 0x7);
14728 int mips32_op;
14730 switch (ctx->opcode & 0x3) {
14731 case RRR_ADDU:
14732 mips32_op = OPC_ADDU;
14733 break;
14734 case RRR_SUBU:
14735 mips32_op = OPC_SUBU;
14736 break;
14737 #if defined(TARGET_MIPS64)
14738 case RRR_DADDU:
14739 mips32_op = OPC_DADDU;
14740 check_insn(ctx, ISA_MIPS3);
14741 check_mips_64(ctx);
14742 break;
14743 case RRR_DSUBU:
14744 mips32_op = OPC_DSUBU;
14745 check_insn(ctx, ISA_MIPS3);
14746 check_mips_64(ctx);
14747 break;
14748 #endif
14749 default:
14750 gen_reserved_instruction(ctx);
14751 goto done;
14754 gen_arith(ctx, mips32_op, rz, rx, ry);
14755 done:
14758 break;
14759 case M16_OPC_RR:
14760 switch (op1) {
14761 case RR_JR:
14763 int nd = (ctx->opcode >> 7) & 0x1;
14764 int link = (ctx->opcode >> 6) & 0x1;
14765 int ra = (ctx->opcode >> 5) & 0x1;
14767 if (nd) {
14768 check_insn(ctx, ISA_MIPS_R1);
14771 if (link) {
14772 op = OPC_JALR;
14773 } else {
14774 op = OPC_JR;
14777 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14778 (nd ? 0 : 2));
14780 break;
14781 case RR_SDBBP:
14782 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14783 gen_helper_do_semihosting(cpu_env);
14784 } else {
14786 * XXX: not clear which exception should be raised
14787 * when in debug mode...
14789 check_insn(ctx, ISA_MIPS_R1);
14790 generate_exception_end(ctx, EXCP_DBp);
14792 break;
14793 case RR_SLT:
14794 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14795 break;
14796 case RR_SLTU:
14797 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14798 break;
14799 case RR_BREAK:
14800 generate_exception_end(ctx, EXCP_BREAK);
14801 break;
14802 case RR_SLLV:
14803 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14804 break;
14805 case RR_SRLV:
14806 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14807 break;
14808 case RR_SRAV:
14809 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14810 break;
14811 #if defined(TARGET_MIPS64)
14812 case RR_DSRL:
14813 check_insn(ctx, ISA_MIPS3);
14814 check_mips_64(ctx);
14815 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14816 break;
14817 #endif
14818 case RR_CMP:
14819 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14820 break;
14821 case RR_NEG:
14822 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14823 break;
14824 case RR_AND:
14825 gen_logic(ctx, OPC_AND, rx, rx, ry);
14826 break;
14827 case RR_OR:
14828 gen_logic(ctx, OPC_OR, rx, rx, ry);
14829 break;
14830 case RR_XOR:
14831 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14832 break;
14833 case RR_NOT:
14834 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14835 break;
14836 case RR_MFHI:
14837 gen_HILO(ctx, OPC_MFHI, 0, rx);
14838 break;
14839 case RR_CNVT:
14840 check_insn(ctx, ISA_MIPS_R1);
14841 switch (cnvt_op) {
14842 case RR_RY_CNVT_ZEB:
14843 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14844 break;
14845 case RR_RY_CNVT_ZEH:
14846 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14847 break;
14848 case RR_RY_CNVT_SEB:
14849 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14850 break;
14851 case RR_RY_CNVT_SEH:
14852 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14853 break;
14854 #if defined(TARGET_MIPS64)
14855 case RR_RY_CNVT_ZEW:
14856 check_insn(ctx, ISA_MIPS_R1);
14857 check_mips_64(ctx);
14858 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14859 break;
14860 case RR_RY_CNVT_SEW:
14861 check_insn(ctx, ISA_MIPS_R1);
14862 check_mips_64(ctx);
14863 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14864 break;
14865 #endif
14866 default:
14867 gen_reserved_instruction(ctx);
14868 break;
14870 break;
14871 case RR_MFLO:
14872 gen_HILO(ctx, OPC_MFLO, 0, rx);
14873 break;
14874 #if defined(TARGET_MIPS64)
14875 case RR_DSRA:
14876 check_insn(ctx, ISA_MIPS3);
14877 check_mips_64(ctx);
14878 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14879 break;
14880 case RR_DSLLV:
14881 check_insn(ctx, ISA_MIPS3);
14882 check_mips_64(ctx);
14883 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14884 break;
14885 case RR_DSRLV:
14886 check_insn(ctx, ISA_MIPS3);
14887 check_mips_64(ctx);
14888 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14889 break;
14890 case RR_DSRAV:
14891 check_insn(ctx, ISA_MIPS3);
14892 check_mips_64(ctx);
14893 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14894 break;
14895 #endif
14896 case RR_MULT:
14897 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14898 break;
14899 case RR_MULTU:
14900 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14901 break;
14902 case RR_DIV:
14903 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14904 break;
14905 case RR_DIVU:
14906 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14907 break;
14908 #if defined(TARGET_MIPS64)
14909 case RR_DMULT:
14910 check_insn(ctx, ISA_MIPS3);
14911 check_mips_64(ctx);
14912 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14913 break;
14914 case RR_DMULTU:
14915 check_insn(ctx, ISA_MIPS3);
14916 check_mips_64(ctx);
14917 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14918 break;
14919 case RR_DDIV:
14920 check_insn(ctx, ISA_MIPS3);
14921 check_mips_64(ctx);
14922 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14923 break;
14924 case RR_DDIVU:
14925 check_insn(ctx, ISA_MIPS3);
14926 check_mips_64(ctx);
14927 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14928 break;
14929 #endif
14930 default:
14931 gen_reserved_instruction(ctx);
14932 break;
14934 break;
14935 case M16_OPC_EXTEND:
14936 decode_extended_mips16_opc(env, ctx);
14937 n_bytes = 4;
14938 break;
14939 #if defined(TARGET_MIPS64)
14940 case M16_OPC_I64:
14941 funct = (ctx->opcode >> 8) & 0x7;
14942 decode_i64_mips16(ctx, ry, funct, offset, 0);
14943 break;
14944 #endif
14945 default:
14946 gen_reserved_instruction(ctx);
14947 break;
14950 return n_bytes;
14953 /* microMIPS extension to MIPS32/MIPS64 */
14956 * microMIPS32/microMIPS64 major opcodes
14958 * 1. MIPS Architecture for Programmers Volume II-B:
14959 * The microMIPS32 Instruction Set (Revision 3.05)
14961 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14963 * 2. MIPS Architecture For Programmers Volume II-A:
14964 * The MIPS64 Instruction Set (Revision 3.51)
14967 enum {
14968 POOL32A = 0x00,
14969 POOL16A = 0x01,
14970 LBU16 = 0x02,
14971 MOVE16 = 0x03,
14972 ADDI32 = 0x04,
14973 R6_LUI = 0x04,
14974 AUI = 0x04,
14975 LBU32 = 0x05,
14976 SB32 = 0x06,
14977 LB32 = 0x07,
14979 POOL32B = 0x08,
14980 POOL16B = 0x09,
14981 LHU16 = 0x0a,
14982 ANDI16 = 0x0b,
14983 ADDIU32 = 0x0c,
14984 LHU32 = 0x0d,
14985 SH32 = 0x0e,
14986 LH32 = 0x0f,
14988 POOL32I = 0x10,
14989 POOL16C = 0x11,
14990 LWSP16 = 0x12,
14991 POOL16D = 0x13,
14992 ORI32 = 0x14,
14993 POOL32F = 0x15,
14994 POOL32S = 0x16, /* MIPS64 */
14995 DADDIU32 = 0x17, /* MIPS64 */
14997 POOL32C = 0x18,
14998 LWGP16 = 0x19,
14999 LW16 = 0x1a,
15000 POOL16E = 0x1b,
15001 XORI32 = 0x1c,
15002 JALS32 = 0x1d,
15003 BOVC = 0x1d,
15004 BEQC = 0x1d,
15005 BEQZALC = 0x1d,
15006 ADDIUPC = 0x1e,
15007 PCREL = 0x1e,
15008 BNVC = 0x1f,
15009 BNEC = 0x1f,
15010 BNEZALC = 0x1f,
15012 R6_BEQZC = 0x20,
15013 JIC = 0x20,
15014 POOL16F = 0x21,
15015 SB16 = 0x22,
15016 BEQZ16 = 0x23,
15017 BEQZC16 = 0x23,
15018 SLTI32 = 0x24,
15019 BEQ32 = 0x25,
15020 BC = 0x25,
15021 SWC132 = 0x26,
15022 LWC132 = 0x27,
15024 /* 0x29 is reserved */
15025 RES_29 = 0x29,
15026 R6_BNEZC = 0x28,
15027 JIALC = 0x28,
15028 SH16 = 0x2a,
15029 BNEZ16 = 0x2b,
15030 BNEZC16 = 0x2b,
15031 SLTIU32 = 0x2c,
15032 BNE32 = 0x2d,
15033 BALC = 0x2d,
15034 SDC132 = 0x2e,
15035 LDC132 = 0x2f,
15037 /* 0x31 is reserved */
15038 RES_31 = 0x31,
15039 BLEZALC = 0x30,
15040 BGEZALC = 0x30,
15041 BGEUC = 0x30,
15042 SWSP16 = 0x32,
15043 B16 = 0x33,
15044 BC16 = 0x33,
15045 ANDI32 = 0x34,
15046 J32 = 0x35,
15047 BGTZC = 0x35,
15048 BLTZC = 0x35,
15049 BLTC = 0x35,
15050 SD32 = 0x36, /* MIPS64 */
15051 LD32 = 0x37, /* MIPS64 */
15053 /* 0x39 is reserved */
15054 RES_39 = 0x39,
15055 BGTZALC = 0x38,
15056 BLTZALC = 0x38,
15057 BLTUC = 0x38,
15058 SW16 = 0x3a,
15059 LI16 = 0x3b,
15060 JALX32 = 0x3c,
15061 JAL32 = 0x3d,
15062 BLEZC = 0x3d,
15063 BGEZC = 0x3d,
15064 BGEC = 0x3d,
15065 SW32 = 0x3e,
15066 LW32 = 0x3f
15069 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
15070 enum {
15071 ADDIUPC_00 = 0x00,
15072 ADDIUPC_01 = 0x01,
15073 ADDIUPC_02 = 0x02,
15074 ADDIUPC_03 = 0x03,
15075 ADDIUPC_04 = 0x04,
15076 ADDIUPC_05 = 0x05,
15077 ADDIUPC_06 = 0x06,
15078 ADDIUPC_07 = 0x07,
15079 AUIPC = 0x1e,
15080 ALUIPC = 0x1f,
15081 LWPC_08 = 0x08,
15082 LWPC_09 = 0x09,
15083 LWPC_0A = 0x0A,
15084 LWPC_0B = 0x0B,
15085 LWPC_0C = 0x0C,
15086 LWPC_0D = 0x0D,
15087 LWPC_0E = 0x0E,
15088 LWPC_0F = 0x0F,
15091 /* POOL32A encoding of minor opcode field */
15093 enum {
15095 * These opcodes are distinguished only by bits 9..6; those bits are
15096 * what are recorded below.
15098 SLL32 = 0x0,
15099 SRL32 = 0x1,
15100 SRA = 0x2,
15101 ROTR = 0x3,
15102 SELEQZ = 0x5,
15103 SELNEZ = 0x6,
15104 R6_RDHWR = 0x7,
15106 SLLV = 0x0,
15107 SRLV = 0x1,
15108 SRAV = 0x2,
15109 ROTRV = 0x3,
15110 ADD = 0x4,
15111 ADDU32 = 0x5,
15112 SUB = 0x6,
15113 SUBU32 = 0x7,
15114 MUL = 0x8,
15115 AND = 0x9,
15116 OR32 = 0xa,
15117 NOR = 0xb,
15118 XOR32 = 0xc,
15119 SLT = 0xd,
15120 SLTU = 0xe,
15122 MOVN = 0x0,
15123 R6_MUL = 0x0,
15124 MOVZ = 0x1,
15125 MUH = 0x1,
15126 MULU = 0x2,
15127 MUHU = 0x3,
15128 LWXS = 0x4,
15129 R6_DIV = 0x4,
15130 MOD = 0x5,
15131 R6_DIVU = 0x6,
15132 MODU = 0x7,
15134 /* The following can be distinguished by their lower 6 bits. */
15135 BREAK32 = 0x07,
15136 INS = 0x0c,
15137 LSA = 0x0f,
15138 ALIGN = 0x1f,
15139 EXT = 0x2c,
15140 POOL32AXF = 0x3c,
15141 SIGRIE = 0x3f
15144 /* POOL32AXF encoding of minor opcode field extension */
15147 * 1. MIPS Architecture for Programmers Volume II-B:
15148 * The microMIPS32 Instruction Set (Revision 3.05)
15150 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
15152 * 2. MIPS Architecture for Programmers VolumeIV-e:
15153 * The MIPS DSP Application-Specific Extension
15154 * to the microMIPS32 Architecture (Revision 2.34)
15156 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
15159 enum {
15160 /* bits 11..6 */
15161 TEQ = 0x00,
15162 TGE = 0x08,
15163 TGEU = 0x10,
15164 TLT = 0x20,
15165 TLTU = 0x28,
15166 TNE = 0x30,
15168 MFC0 = 0x03,
15169 MTC0 = 0x0b,
15171 /* begin of microMIPS32 DSP */
15173 /* bits 13..12 for 0x01 */
15174 MFHI_ACC = 0x0,
15175 MFLO_ACC = 0x1,
15176 MTHI_ACC = 0x2,
15177 MTLO_ACC = 0x3,
15179 /* bits 13..12 for 0x2a */
15180 MADD_ACC = 0x0,
15181 MADDU_ACC = 0x1,
15182 MSUB_ACC = 0x2,
15183 MSUBU_ACC = 0x3,
15185 /* bits 13..12 for 0x32 */
15186 MULT_ACC = 0x0,
15187 MULTU_ACC = 0x1,
15189 /* end of microMIPS32 DSP */
15191 /* bits 15..12 for 0x2c */
15192 BITSWAP = 0x0,
15193 SEB = 0x2,
15194 SEH = 0x3,
15195 CLO = 0x4,
15196 CLZ = 0x5,
15197 RDHWR = 0x6,
15198 WSBH = 0x7,
15199 MULT = 0x8,
15200 MULTU = 0x9,
15201 DIV = 0xa,
15202 DIVU = 0xb,
15203 MADD = 0xc,
15204 MADDU = 0xd,
15205 MSUB = 0xe,
15206 MSUBU = 0xf,
15208 /* bits 15..12 for 0x34 */
15209 MFC2 = 0x4,
15210 MTC2 = 0x5,
15211 MFHC2 = 0x8,
15212 MTHC2 = 0x9,
15213 CFC2 = 0xc,
15214 CTC2 = 0xd,
15216 /* bits 15..12 for 0x3c */
15217 JALR = 0x0,
15218 JR = 0x0, /* alias */
15219 JALRC = 0x0,
15220 JRC = 0x0,
15221 JALR_HB = 0x1,
15222 JALRC_HB = 0x1,
15223 JALRS = 0x4,
15224 JALRS_HB = 0x5,
15226 /* bits 15..12 for 0x05 */
15227 RDPGPR = 0xe,
15228 WRPGPR = 0xf,
15230 /* bits 15..12 for 0x0d */
15231 TLBP = 0x0,
15232 TLBR = 0x1,
15233 TLBWI = 0x2,
15234 TLBWR = 0x3,
15235 TLBINV = 0x4,
15236 TLBINVF = 0x5,
15237 WAIT = 0x9,
15238 IRET = 0xd,
15239 DERET = 0xe,
15240 ERET = 0xf,
15242 /* bits 15..12 for 0x15 */
15243 DMT = 0x0,
15244 DVPE = 0x1,
15245 EMT = 0x2,
15246 EVPE = 0x3,
15248 /* bits 15..12 for 0x1d */
15249 DI = 0x4,
15250 EI = 0x5,
15252 /* bits 15..12 for 0x2d */
15253 SYNC = 0x6,
15254 SYSCALL = 0x8,
15255 SDBBP = 0xd,
15257 /* bits 15..12 for 0x35 */
15258 MFHI32 = 0x0,
15259 MFLO32 = 0x1,
15260 MTHI32 = 0x2,
15261 MTLO32 = 0x3,
15264 /* POOL32B encoding of minor opcode field (bits 15..12) */
15266 enum {
15267 LWC2 = 0x0,
15268 LWP = 0x1,
15269 LDP = 0x4,
15270 LWM32 = 0x5,
15271 CACHE = 0x6,
15272 LDM = 0x7,
15273 SWC2 = 0x8,
15274 SWP = 0x9,
15275 SDP = 0xc,
15276 SWM32 = 0xd,
15277 SDM = 0xf
15280 /* POOL32C encoding of minor opcode field (bits 15..12) */
15282 enum {
15283 LWL = 0x0,
15284 SWL = 0x8,
15285 LWR = 0x1,
15286 SWR = 0x9,
15287 PREF = 0x2,
15288 ST_EVA = 0xa,
15289 LL = 0x3,
15290 SC = 0xb,
15291 LDL = 0x4,
15292 SDL = 0xc,
15293 LDR = 0x5,
15294 SDR = 0xd,
15295 LD_EVA = 0x6,
15296 LWU = 0xe,
15297 LLD = 0x7,
15298 SCD = 0xf
15301 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
15303 enum {
15304 LBUE = 0x0,
15305 LHUE = 0x1,
15306 LWLE = 0x2,
15307 LWRE = 0x3,
15308 LBE = 0x4,
15309 LHE = 0x5,
15310 LLE = 0x6,
15311 LWE = 0x7,
15314 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
15316 enum {
15317 SWLE = 0x0,
15318 SWRE = 0x1,
15319 PREFE = 0x2,
15320 CACHEE = 0x3,
15321 SBE = 0x4,
15322 SHE = 0x5,
15323 SCE = 0x6,
15324 SWE = 0x7,
15327 /* POOL32F encoding of minor opcode field (bits 5..0) */
15329 enum {
15330 /* These are the bit 7..6 values */
15331 ADD_FMT = 0x0,
15333 SUB_FMT = 0x1,
15335 MUL_FMT = 0x2,
15337 DIV_FMT = 0x3,
15339 /* These are the bit 8..6 values */
15340 MOVN_FMT = 0x0,
15341 RSQRT2_FMT = 0x0,
15342 MOVF_FMT = 0x0,
15343 RINT_FMT = 0x0,
15344 SELNEZ_FMT = 0x0,
15346 MOVZ_FMT = 0x1,
15347 LWXC1 = 0x1,
15348 MOVT_FMT = 0x1,
15349 CLASS_FMT = 0x1,
15350 SELEQZ_FMT = 0x1,
15352 PLL_PS = 0x2,
15353 SWXC1 = 0x2,
15354 SEL_FMT = 0x2,
15356 PLU_PS = 0x3,
15357 LDXC1 = 0x3,
15359 MOVN_FMT_04 = 0x4,
15360 PUL_PS = 0x4,
15361 SDXC1 = 0x4,
15362 RECIP2_FMT = 0x4,
15364 MOVZ_FMT_05 = 0x05,
15365 PUU_PS = 0x5,
15366 LUXC1 = 0x5,
15368 CVT_PS_S = 0x6,
15369 SUXC1 = 0x6,
15370 ADDR_PS = 0x6,
15371 PREFX = 0x6,
15372 MADDF_FMT = 0x6,
15374 MULR_PS = 0x7,
15375 MSUBF_FMT = 0x7,
15377 MADD_S = 0x01,
15378 MADD_D = 0x09,
15379 MADD_PS = 0x11,
15380 ALNV_PS = 0x19,
15381 MSUB_S = 0x21,
15382 MSUB_D = 0x29,
15383 MSUB_PS = 0x31,
15385 NMADD_S = 0x02,
15386 NMADD_D = 0x0a,
15387 NMADD_PS = 0x12,
15388 NMSUB_S = 0x22,
15389 NMSUB_D = 0x2a,
15390 NMSUB_PS = 0x32,
15392 MIN_FMT = 0x3,
15393 MAX_FMT = 0xb,
15394 MINA_FMT = 0x23,
15395 MAXA_FMT = 0x2b,
15396 POOL32FXF = 0x3b,
15398 CABS_COND_FMT = 0x1c, /* MIPS3D */
15399 C_COND_FMT = 0x3c,
15401 CMP_CONDN_S = 0x5,
15402 CMP_CONDN_D = 0x15
15405 /* POOL32Fxf encoding of minor opcode extension field */
15407 enum {
15408 CVT_L = 0x04,
15409 RSQRT_FMT = 0x08,
15410 FLOOR_L = 0x0c,
15411 CVT_PW_PS = 0x1c,
15412 CVT_W = 0x24,
15413 SQRT_FMT = 0x28,
15414 FLOOR_W = 0x2c,
15415 CVT_PS_PW = 0x3c,
15416 CFC1 = 0x40,
15417 RECIP_FMT = 0x48,
15418 CEIL_L = 0x4c,
15419 CTC1 = 0x60,
15420 CEIL_W = 0x6c,
15421 MFC1 = 0x80,
15422 CVT_S_PL = 0x84,
15423 TRUNC_L = 0x8c,
15424 MTC1 = 0xa0,
15425 CVT_S_PU = 0xa4,
15426 TRUNC_W = 0xac,
15427 MFHC1 = 0xc0,
15428 ROUND_L = 0xcc,
15429 MTHC1 = 0xe0,
15430 ROUND_W = 0xec,
15432 MOV_FMT = 0x01,
15433 MOVF = 0x05,
15434 ABS_FMT = 0x0d,
15435 RSQRT1_FMT = 0x1d,
15436 MOVT = 0x25,
15437 NEG_FMT = 0x2d,
15438 CVT_D = 0x4d,
15439 RECIP1_FMT = 0x5d,
15440 CVT_S = 0x6d
15443 /* POOL32I encoding of minor opcode field (bits 25..21) */
15445 enum {
15446 BLTZ = 0x00,
15447 BLTZAL = 0x01,
15448 BGEZ = 0x02,
15449 BGEZAL = 0x03,
15450 BLEZ = 0x04,
15451 BNEZC = 0x05,
15452 BGTZ = 0x06,
15453 BEQZC = 0x07,
15454 TLTI = 0x08,
15455 BC1EQZC = 0x08,
15456 TGEI = 0x09,
15457 BC1NEZC = 0x09,
15458 TLTIU = 0x0a,
15459 BC2EQZC = 0x0a,
15460 TGEIU = 0x0b,
15461 BC2NEZC = 0x0a,
15462 TNEI = 0x0c,
15463 R6_SYNCI = 0x0c,
15464 LUI = 0x0d,
15465 TEQI = 0x0e,
15466 SYNCI = 0x10,
15467 BLTZALS = 0x11,
15468 BGEZALS = 0x13,
15469 BC2F = 0x14,
15470 BC2T = 0x15,
15471 BPOSGE64 = 0x1a,
15472 BPOSGE32 = 0x1b,
15473 /* These overlap and are distinguished by bit16 of the instruction */
15474 BC1F = 0x1c,
15475 BC1T = 0x1d,
15476 BC1ANY2F = 0x1c,
15477 BC1ANY2T = 0x1d,
15478 BC1ANY4F = 0x1e,
15479 BC1ANY4T = 0x1f
15482 /* POOL16A encoding of minor opcode field */
15484 enum {
15485 ADDU16 = 0x0,
15486 SUBU16 = 0x1
15489 /* POOL16B encoding of minor opcode field */
15491 enum {
15492 SLL16 = 0x0,
15493 SRL16 = 0x1
15496 /* POOL16C encoding of minor opcode field */
15498 enum {
15499 NOT16 = 0x00,
15500 XOR16 = 0x04,
15501 AND16 = 0x08,
15502 OR16 = 0x0c,
15503 LWM16 = 0x10,
15504 SWM16 = 0x14,
15505 JR16 = 0x18,
15506 JRC16 = 0x1a,
15507 JALR16 = 0x1c,
15508 JALR16S = 0x1e,
15509 MFHI16 = 0x20,
15510 MFLO16 = 0x24,
15511 BREAK16 = 0x28,
15512 SDBBP16 = 0x2c,
15513 JRADDIUSP = 0x30
15516 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15518 enum {
15519 R6_NOT16 = 0x00,
15520 R6_AND16 = 0x01,
15521 R6_LWM16 = 0x02,
15522 R6_JRC16 = 0x03,
15523 MOVEP = 0x04,
15524 MOVEP_05 = 0x05,
15525 MOVEP_06 = 0x06,
15526 MOVEP_07 = 0x07,
15527 R6_XOR16 = 0x08,
15528 R6_OR16 = 0x09,
15529 R6_SWM16 = 0x0a,
15530 JALRC16 = 0x0b,
15531 MOVEP_0C = 0x0c,
15532 MOVEP_0D = 0x0d,
15533 MOVEP_0E = 0x0e,
15534 MOVEP_0F = 0x0f,
15535 JRCADDIUSP = 0x13,
15536 R6_BREAK16 = 0x1b,
15537 R6_SDBBP16 = 0x3b
15540 /* POOL16D encoding of minor opcode field */
15542 enum {
15543 ADDIUS5 = 0x0,
15544 ADDIUSP = 0x1
15547 /* POOL16E encoding of minor opcode field */
15549 enum {
15550 ADDIUR2 = 0x0,
15551 ADDIUR1SP = 0x1
15554 static int mmreg(int r)
15556 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15558 return map[r];
15561 /* Used for 16-bit store instructions. */
15562 static int mmreg2(int r)
15564 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15566 return map[r];
15569 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15570 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15571 #define uMIPS_RS2(op) uMIPS_RS(op)
15572 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15573 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15574 #define uMIPS_RS5(op) (op & 0x1f)
15576 /* Signed immediate */
15577 #define SIMM(op, start, width) \
15578 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15579 << (32 - width)) \
15580 >> (32 - width))
15581 /* Zero-extended immediate */
15582 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15584 static void gen_addiur1sp(DisasContext *ctx)
15586 int rd = mmreg(uMIPS_RD(ctx->opcode));
15588 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15591 static void gen_addiur2(DisasContext *ctx)
15593 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15594 int rd = mmreg(uMIPS_RD(ctx->opcode));
15595 int rs = mmreg(uMIPS_RS(ctx->opcode));
15597 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15600 static void gen_addiusp(DisasContext *ctx)
15602 int encoded = ZIMM(ctx->opcode, 1, 9);
15603 int decoded;
15605 if (encoded <= 1) {
15606 decoded = 256 + encoded;
15607 } else if (encoded <= 255) {
15608 decoded = encoded;
15609 } else if (encoded <= 509) {
15610 decoded = encoded - 512;
15611 } else {
15612 decoded = encoded - 768;
15615 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15618 static void gen_addius5(DisasContext *ctx)
15620 int imm = SIMM(ctx->opcode, 1, 4);
15621 int rd = (ctx->opcode >> 5) & 0x1f;
15623 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15626 static void gen_andi16(DisasContext *ctx)
15628 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15629 31, 32, 63, 64, 255, 32768, 65535 };
15630 int rd = mmreg(uMIPS_RD(ctx->opcode));
15631 int rs = mmreg(uMIPS_RS(ctx->opcode));
15632 int encoded = ZIMM(ctx->opcode, 0, 4);
15634 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15637 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15638 int base, int16_t offset)
15640 TCGv t0, t1;
15641 TCGv_i32 t2;
15643 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15644 gen_reserved_instruction(ctx);
15645 return;
15648 t0 = tcg_temp_new();
15650 gen_base_offset_addr(ctx, t0, base, offset);
15652 t1 = tcg_const_tl(reglist);
15653 t2 = tcg_const_i32(ctx->mem_idx);
15655 save_cpu_state(ctx, 1);
15656 switch (opc) {
15657 case LWM32:
15658 gen_helper_lwm(cpu_env, t0, t1, t2);
15659 break;
15660 case SWM32:
15661 gen_helper_swm(cpu_env, t0, t1, t2);
15662 break;
15663 #ifdef TARGET_MIPS64
15664 case LDM:
15665 gen_helper_ldm(cpu_env, t0, t1, t2);
15666 break;
15667 case SDM:
15668 gen_helper_sdm(cpu_env, t0, t1, t2);
15669 break;
15670 #endif
15672 tcg_temp_free(t0);
15673 tcg_temp_free(t1);
15674 tcg_temp_free_i32(t2);
15678 static void gen_pool16c_insn(DisasContext *ctx)
15680 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15681 int rs = mmreg(ctx->opcode & 0x7);
15683 switch (((ctx->opcode) >> 4) & 0x3f) {
15684 case NOT16 + 0:
15685 case NOT16 + 1:
15686 case NOT16 + 2:
15687 case NOT16 + 3:
15688 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15689 break;
15690 case XOR16 + 0:
15691 case XOR16 + 1:
15692 case XOR16 + 2:
15693 case XOR16 + 3:
15694 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15695 break;
15696 case AND16 + 0:
15697 case AND16 + 1:
15698 case AND16 + 2:
15699 case AND16 + 3:
15700 gen_logic(ctx, OPC_AND, rd, rd, rs);
15701 break;
15702 case OR16 + 0:
15703 case OR16 + 1:
15704 case OR16 + 2:
15705 case OR16 + 3:
15706 gen_logic(ctx, OPC_OR, rd, rd, rs);
15707 break;
15708 case LWM16 + 0:
15709 case LWM16 + 1:
15710 case LWM16 + 2:
15711 case LWM16 + 3:
15713 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15714 int offset = ZIMM(ctx->opcode, 0, 4);
15716 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15717 29, offset << 2);
15719 break;
15720 case SWM16 + 0:
15721 case SWM16 + 1:
15722 case SWM16 + 2:
15723 case SWM16 + 3:
15725 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15726 int offset = ZIMM(ctx->opcode, 0, 4);
15728 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15729 29, offset << 2);
15731 break;
15732 case JR16 + 0:
15733 case JR16 + 1:
15735 int reg = ctx->opcode & 0x1f;
15737 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15739 break;
15740 case JRC16 + 0:
15741 case JRC16 + 1:
15743 int reg = ctx->opcode & 0x1f;
15744 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15746 * Let normal delay slot handling in our caller take us
15747 * to the branch target.
15750 break;
15751 case JALR16 + 0:
15752 case JALR16 + 1:
15753 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15754 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15755 break;
15756 case JALR16S + 0:
15757 case JALR16S + 1:
15758 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15759 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15760 break;
15761 case MFHI16 + 0:
15762 case MFHI16 + 1:
15763 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15764 break;
15765 case MFLO16 + 0:
15766 case MFLO16 + 1:
15767 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15768 break;
15769 case BREAK16:
15770 generate_exception_end(ctx, EXCP_BREAK);
15771 break;
15772 case SDBBP16:
15773 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15774 gen_helper_do_semihosting(cpu_env);
15775 } else {
15777 * XXX: not clear which exception should be raised
15778 * when in debug mode...
15780 check_insn(ctx, ISA_MIPS_R1);
15781 generate_exception_end(ctx, EXCP_DBp);
15783 break;
15784 case JRADDIUSP + 0:
15785 case JRADDIUSP + 1:
15787 int imm = ZIMM(ctx->opcode, 0, 5);
15788 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15789 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15791 * Let normal delay slot handling in our caller take us
15792 * to the branch target.
15795 break;
15796 default:
15797 gen_reserved_instruction(ctx);
15798 break;
15802 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15803 int enc_rs)
15805 int rd, rs, re, rt;
15806 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15807 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15808 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15809 rd = rd_enc[enc_dest];
15810 re = re_enc[enc_dest];
15811 rs = rs_rt_enc[enc_rs];
15812 rt = rs_rt_enc[enc_rt];
15813 if (rs) {
15814 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15815 } else {
15816 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15818 if (rt) {
15819 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15820 } else {
15821 tcg_gen_movi_tl(cpu_gpr[re], 0);
15825 static void gen_pool16c_r6_insn(DisasContext *ctx)
15827 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15828 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15830 switch (ctx->opcode & 0xf) {
15831 case R6_NOT16:
15832 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15833 break;
15834 case R6_AND16:
15835 gen_logic(ctx, OPC_AND, rt, rt, rs);
15836 break;
15837 case R6_LWM16:
15839 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15840 int offset = extract32(ctx->opcode, 4, 4);
15841 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15843 break;
15844 case R6_JRC16: /* JRCADDIUSP */
15845 if ((ctx->opcode >> 4) & 1) {
15846 /* JRCADDIUSP */
15847 int imm = extract32(ctx->opcode, 5, 5);
15848 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15849 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15850 } else {
15851 /* JRC16 */
15852 rs = extract32(ctx->opcode, 5, 5);
15853 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15855 break;
15856 case MOVEP:
15857 case MOVEP_05:
15858 case MOVEP_06:
15859 case MOVEP_07:
15860 case MOVEP_0C:
15861 case MOVEP_0D:
15862 case MOVEP_0E:
15863 case MOVEP_0F:
15865 int enc_dest = uMIPS_RD(ctx->opcode);
15866 int enc_rt = uMIPS_RS2(ctx->opcode);
15867 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15868 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15870 break;
15871 case R6_XOR16:
15872 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15873 break;
15874 case R6_OR16:
15875 gen_logic(ctx, OPC_OR, rt, rt, rs);
15876 break;
15877 case R6_SWM16:
15879 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15880 int offset = extract32(ctx->opcode, 4, 4);
15881 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15883 break;
15884 case JALRC16: /* BREAK16, SDBBP16 */
15885 switch (ctx->opcode & 0x3f) {
15886 case JALRC16:
15887 case JALRC16 + 0x20:
15888 /* JALRC16 */
15889 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15890 31, 0, 0);
15891 break;
15892 case R6_BREAK16:
15893 /* BREAK16 */
15894 generate_exception(ctx, EXCP_BREAK);
15895 break;
15896 case R6_SDBBP16:
15897 /* SDBBP16 */
15898 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15899 gen_helper_do_semihosting(cpu_env);
15900 } else {
15901 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15902 generate_exception(ctx, EXCP_RI);
15903 } else {
15904 generate_exception(ctx, EXCP_DBp);
15907 break;
15909 break;
15910 default:
15911 generate_exception(ctx, EXCP_RI);
15912 break;
15916 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15918 TCGv t0 = tcg_temp_new();
15919 TCGv t1 = tcg_temp_new();
15921 gen_load_gpr(t0, base);
15923 if (index != 0) {
15924 gen_load_gpr(t1, index);
15925 tcg_gen_shli_tl(t1, t1, 2);
15926 gen_op_addr_add(ctx, t0, t1, t0);
15929 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15930 gen_store_gpr(t1, rd);
15932 tcg_temp_free(t0);
15933 tcg_temp_free(t1);
15936 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15937 int base, int16_t offset)
15939 TCGv t0, t1;
15941 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15942 gen_reserved_instruction(ctx);
15943 return;
15946 t0 = tcg_temp_new();
15947 t1 = tcg_temp_new();
15949 gen_base_offset_addr(ctx, t0, base, offset);
15951 switch (opc) {
15952 case LWP:
15953 if (rd == base) {
15954 gen_reserved_instruction(ctx);
15955 return;
15957 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15958 gen_store_gpr(t1, rd);
15959 tcg_gen_movi_tl(t1, 4);
15960 gen_op_addr_add(ctx, t0, t0, t1);
15961 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15962 gen_store_gpr(t1, rd + 1);
15963 break;
15964 case SWP:
15965 gen_load_gpr(t1, rd);
15966 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15967 tcg_gen_movi_tl(t1, 4);
15968 gen_op_addr_add(ctx, t0, t0, t1);
15969 gen_load_gpr(t1, rd + 1);
15970 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15971 break;
15972 #ifdef TARGET_MIPS64
15973 case LDP:
15974 if (rd == base) {
15975 gen_reserved_instruction(ctx);
15976 return;
15978 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15979 gen_store_gpr(t1, rd);
15980 tcg_gen_movi_tl(t1, 8);
15981 gen_op_addr_add(ctx, t0, t0, t1);
15982 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15983 gen_store_gpr(t1, rd + 1);
15984 break;
15985 case SDP:
15986 gen_load_gpr(t1, rd);
15987 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15988 tcg_gen_movi_tl(t1, 8);
15989 gen_op_addr_add(ctx, t0, t0, t1);
15990 gen_load_gpr(t1, rd + 1);
15991 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15992 break;
15993 #endif
15995 tcg_temp_free(t0);
15996 tcg_temp_free(t1);
15999 static void gen_sync(int stype)
16001 TCGBar tcg_mo = TCG_BAR_SC;
16003 switch (stype) {
16004 case 0x4: /* SYNC_WMB */
16005 tcg_mo |= TCG_MO_ST_ST;
16006 break;
16007 case 0x10: /* SYNC_MB */
16008 tcg_mo |= TCG_MO_ALL;
16009 break;
16010 case 0x11: /* SYNC_ACQUIRE */
16011 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
16012 break;
16013 case 0x12: /* SYNC_RELEASE */
16014 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
16015 break;
16016 case 0x13: /* SYNC_RMB */
16017 tcg_mo |= TCG_MO_LD_LD;
16018 break;
16019 default:
16020 tcg_mo |= TCG_MO_ALL;
16021 break;
16024 tcg_gen_mb(tcg_mo);
16027 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
16029 int extension = (ctx->opcode >> 6) & 0x3f;
16030 int minor = (ctx->opcode >> 12) & 0xf;
16031 uint32_t mips32_op;
16033 switch (extension) {
16034 case TEQ:
16035 mips32_op = OPC_TEQ;
16036 goto do_trap;
16037 case TGE:
16038 mips32_op = OPC_TGE;
16039 goto do_trap;
16040 case TGEU:
16041 mips32_op = OPC_TGEU;
16042 goto do_trap;
16043 case TLT:
16044 mips32_op = OPC_TLT;
16045 goto do_trap;
16046 case TLTU:
16047 mips32_op = OPC_TLTU;
16048 goto do_trap;
16049 case TNE:
16050 mips32_op = OPC_TNE;
16051 do_trap:
16052 gen_trap(ctx, mips32_op, rs, rt, -1);
16053 break;
16054 #ifndef CONFIG_USER_ONLY
16055 case MFC0:
16056 case MFC0 + 32:
16057 check_cp0_enabled(ctx);
16058 if (rt == 0) {
16059 /* Treat as NOP. */
16060 break;
16062 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
16063 break;
16064 case MTC0:
16065 case MTC0 + 32:
16066 check_cp0_enabled(ctx);
16068 TCGv t0 = tcg_temp_new();
16070 gen_load_gpr(t0, rt);
16071 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
16072 tcg_temp_free(t0);
16074 break;
16075 #endif
16076 case 0x2a:
16077 switch (minor & 3) {
16078 case MADD_ACC:
16079 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
16080 break;
16081 case MADDU_ACC:
16082 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
16083 break;
16084 case MSUB_ACC:
16085 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
16086 break;
16087 case MSUBU_ACC:
16088 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
16089 break;
16090 default:
16091 goto pool32axf_invalid;
16093 break;
16094 case 0x32:
16095 switch (minor & 3) {
16096 case MULT_ACC:
16097 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
16098 break;
16099 case MULTU_ACC:
16100 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
16101 break;
16102 default:
16103 goto pool32axf_invalid;
16105 break;
16106 case 0x2c:
16107 switch (minor) {
16108 case BITSWAP:
16109 check_insn(ctx, ISA_MIPS_R6);
16110 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
16111 break;
16112 case SEB:
16113 gen_bshfl(ctx, OPC_SEB, rs, rt);
16114 break;
16115 case SEH:
16116 gen_bshfl(ctx, OPC_SEH, rs, rt);
16117 break;
16118 case CLO:
16119 mips32_op = OPC_CLO;
16120 goto do_cl;
16121 case CLZ:
16122 mips32_op = OPC_CLZ;
16123 do_cl:
16124 check_insn(ctx, ISA_MIPS_R1);
16125 gen_cl(ctx, mips32_op, rt, rs);
16126 break;
16127 case RDHWR:
16128 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16129 gen_rdhwr(ctx, rt, rs, 0);
16130 break;
16131 case WSBH:
16132 gen_bshfl(ctx, OPC_WSBH, rs, rt);
16133 break;
16134 case MULT:
16135 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16136 mips32_op = OPC_MULT;
16137 goto do_mul;
16138 case MULTU:
16139 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16140 mips32_op = OPC_MULTU;
16141 goto do_mul;
16142 case DIV:
16143 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16144 mips32_op = OPC_DIV;
16145 goto do_div;
16146 case DIVU:
16147 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16148 mips32_op = OPC_DIVU;
16149 goto do_div;
16150 do_div:
16151 check_insn(ctx, ISA_MIPS_R1);
16152 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16153 break;
16154 case MADD:
16155 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16156 mips32_op = OPC_MADD;
16157 goto do_mul;
16158 case MADDU:
16159 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16160 mips32_op = OPC_MADDU;
16161 goto do_mul;
16162 case MSUB:
16163 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16164 mips32_op = OPC_MSUB;
16165 goto do_mul;
16166 case MSUBU:
16167 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16168 mips32_op = OPC_MSUBU;
16169 do_mul:
16170 check_insn(ctx, ISA_MIPS_R1);
16171 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16172 break;
16173 default:
16174 goto pool32axf_invalid;
16176 break;
16177 case 0x34:
16178 switch (minor) {
16179 case MFC2:
16180 case MTC2:
16181 case MFHC2:
16182 case MTHC2:
16183 case CFC2:
16184 case CTC2:
16185 generate_exception_err(ctx, EXCP_CpU, 2);
16186 break;
16187 default:
16188 goto pool32axf_invalid;
16190 break;
16191 case 0x3c:
16192 switch (minor) {
16193 case JALR: /* JALRC */
16194 case JALR_HB: /* JALRC_HB */
16195 if (ctx->insn_flags & ISA_MIPS_R6) {
16196 /* JALRC, JALRC_HB */
16197 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
16198 } else {
16199 /* JALR, JALR_HB */
16200 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
16201 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16203 break;
16204 case JALRS:
16205 case JALRS_HB:
16206 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16207 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
16208 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16209 break;
16210 default:
16211 goto pool32axf_invalid;
16213 break;
16214 case 0x05:
16215 switch (minor) {
16216 case RDPGPR:
16217 check_cp0_enabled(ctx);
16218 check_insn(ctx, ISA_MIPS_R2);
16219 gen_load_srsgpr(rs, rt);
16220 break;
16221 case WRPGPR:
16222 check_cp0_enabled(ctx);
16223 check_insn(ctx, ISA_MIPS_R2);
16224 gen_store_srsgpr(rs, rt);
16225 break;
16226 default:
16227 goto pool32axf_invalid;
16229 break;
16230 #ifndef CONFIG_USER_ONLY
16231 case 0x0d:
16232 switch (minor) {
16233 case TLBP:
16234 mips32_op = OPC_TLBP;
16235 goto do_cp0;
16236 case TLBR:
16237 mips32_op = OPC_TLBR;
16238 goto do_cp0;
16239 case TLBWI:
16240 mips32_op = OPC_TLBWI;
16241 goto do_cp0;
16242 case TLBWR:
16243 mips32_op = OPC_TLBWR;
16244 goto do_cp0;
16245 case TLBINV:
16246 mips32_op = OPC_TLBINV;
16247 goto do_cp0;
16248 case TLBINVF:
16249 mips32_op = OPC_TLBINVF;
16250 goto do_cp0;
16251 case WAIT:
16252 mips32_op = OPC_WAIT;
16253 goto do_cp0;
16254 case DERET:
16255 mips32_op = OPC_DERET;
16256 goto do_cp0;
16257 case ERET:
16258 mips32_op = OPC_ERET;
16259 do_cp0:
16260 gen_cp0(env, ctx, mips32_op, rt, rs);
16261 break;
16262 default:
16263 goto pool32axf_invalid;
16265 break;
16266 case 0x1d:
16267 switch (minor) {
16268 case DI:
16269 check_cp0_enabled(ctx);
16271 TCGv t0 = tcg_temp_new();
16273 save_cpu_state(ctx, 1);
16274 gen_helper_di(t0, cpu_env);
16275 gen_store_gpr(t0, rs);
16277 * Stop translation as we may have switched the execution
16278 * mode.
16280 ctx->base.is_jmp = DISAS_STOP;
16281 tcg_temp_free(t0);
16283 break;
16284 case EI:
16285 check_cp0_enabled(ctx);
16287 TCGv t0 = tcg_temp_new();
16289 save_cpu_state(ctx, 1);
16290 gen_helper_ei(t0, cpu_env);
16291 gen_store_gpr(t0, rs);
16293 * DISAS_STOP isn't sufficient, we need to ensure we break out
16294 * of translated code to check for pending interrupts.
16296 gen_save_pc(ctx->base.pc_next + 4);
16297 ctx->base.is_jmp = DISAS_EXIT;
16298 tcg_temp_free(t0);
16300 break;
16301 default:
16302 goto pool32axf_invalid;
16304 break;
16305 #endif
16306 case 0x2d:
16307 switch (minor) {
16308 case SYNC:
16309 gen_sync(extract32(ctx->opcode, 16, 5));
16310 break;
16311 case SYSCALL:
16312 generate_exception_end(ctx, EXCP_SYSCALL);
16313 break;
16314 case SDBBP:
16315 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
16316 gen_helper_do_semihosting(cpu_env);
16317 } else {
16318 check_insn(ctx, ISA_MIPS_R1);
16319 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16320 gen_reserved_instruction(ctx);
16321 } else {
16322 generate_exception_end(ctx, EXCP_DBp);
16325 break;
16326 default:
16327 goto pool32axf_invalid;
16329 break;
16330 case 0x01:
16331 switch (minor & 3) {
16332 case MFHI_ACC:
16333 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
16334 break;
16335 case MFLO_ACC:
16336 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
16337 break;
16338 case MTHI_ACC:
16339 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
16340 break;
16341 case MTLO_ACC:
16342 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
16343 break;
16344 default:
16345 goto pool32axf_invalid;
16347 break;
16348 case 0x35:
16349 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16350 switch (minor) {
16351 case MFHI32:
16352 gen_HILO(ctx, OPC_MFHI, 0, rs);
16353 break;
16354 case MFLO32:
16355 gen_HILO(ctx, OPC_MFLO, 0, rs);
16356 break;
16357 case MTHI32:
16358 gen_HILO(ctx, OPC_MTHI, 0, rs);
16359 break;
16360 case MTLO32:
16361 gen_HILO(ctx, OPC_MTLO, 0, rs);
16362 break;
16363 default:
16364 goto pool32axf_invalid;
16366 break;
16367 default:
16368 pool32axf_invalid:
16369 MIPS_INVAL("pool32axf");
16370 gen_reserved_instruction(ctx);
16371 break;
16376 * Values for microMIPS fmt field. Variable-width, depending on which
16377 * formats the instruction supports.
16379 enum {
16380 FMT_SD_S = 0,
16381 FMT_SD_D = 1,
16383 FMT_SDPS_S = 0,
16384 FMT_SDPS_D = 1,
16385 FMT_SDPS_PS = 2,
16387 FMT_SWL_S = 0,
16388 FMT_SWL_W = 1,
16389 FMT_SWL_L = 2,
16391 FMT_DWL_D = 0,
16392 FMT_DWL_W = 1,
16393 FMT_DWL_L = 2
16396 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16398 int extension = (ctx->opcode >> 6) & 0x3ff;
16399 uint32_t mips32_op;
16401 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16402 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16403 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16405 switch (extension) {
16406 case FLOAT_1BIT_FMT(CFC1, 0):
16407 mips32_op = OPC_CFC1;
16408 goto do_cp1;
16409 case FLOAT_1BIT_FMT(CTC1, 0):
16410 mips32_op = OPC_CTC1;
16411 goto do_cp1;
16412 case FLOAT_1BIT_FMT(MFC1, 0):
16413 mips32_op = OPC_MFC1;
16414 goto do_cp1;
16415 case FLOAT_1BIT_FMT(MTC1, 0):
16416 mips32_op = OPC_MTC1;
16417 goto do_cp1;
16418 case FLOAT_1BIT_FMT(MFHC1, 0):
16419 mips32_op = OPC_MFHC1;
16420 goto do_cp1;
16421 case FLOAT_1BIT_FMT(MTHC1, 0):
16422 mips32_op = OPC_MTHC1;
16423 do_cp1:
16424 gen_cp1(ctx, mips32_op, rt, rs);
16425 break;
16427 /* Reciprocal square root */
16428 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16429 mips32_op = OPC_RSQRT_S;
16430 goto do_unaryfp;
16431 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16432 mips32_op = OPC_RSQRT_D;
16433 goto do_unaryfp;
16435 /* Square root */
16436 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16437 mips32_op = OPC_SQRT_S;
16438 goto do_unaryfp;
16439 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16440 mips32_op = OPC_SQRT_D;
16441 goto do_unaryfp;
16443 /* Reciprocal */
16444 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16445 mips32_op = OPC_RECIP_S;
16446 goto do_unaryfp;
16447 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16448 mips32_op = OPC_RECIP_D;
16449 goto do_unaryfp;
16451 /* Floor */
16452 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16453 mips32_op = OPC_FLOOR_L_S;
16454 goto do_unaryfp;
16455 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16456 mips32_op = OPC_FLOOR_L_D;
16457 goto do_unaryfp;
16458 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16459 mips32_op = OPC_FLOOR_W_S;
16460 goto do_unaryfp;
16461 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16462 mips32_op = OPC_FLOOR_W_D;
16463 goto do_unaryfp;
16465 /* Ceiling */
16466 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16467 mips32_op = OPC_CEIL_L_S;
16468 goto do_unaryfp;
16469 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16470 mips32_op = OPC_CEIL_L_D;
16471 goto do_unaryfp;
16472 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16473 mips32_op = OPC_CEIL_W_S;
16474 goto do_unaryfp;
16475 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16476 mips32_op = OPC_CEIL_W_D;
16477 goto do_unaryfp;
16479 /* Truncation */
16480 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16481 mips32_op = OPC_TRUNC_L_S;
16482 goto do_unaryfp;
16483 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16484 mips32_op = OPC_TRUNC_L_D;
16485 goto do_unaryfp;
16486 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16487 mips32_op = OPC_TRUNC_W_S;
16488 goto do_unaryfp;
16489 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16490 mips32_op = OPC_TRUNC_W_D;
16491 goto do_unaryfp;
16493 /* Round */
16494 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16495 mips32_op = OPC_ROUND_L_S;
16496 goto do_unaryfp;
16497 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16498 mips32_op = OPC_ROUND_L_D;
16499 goto do_unaryfp;
16500 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16501 mips32_op = OPC_ROUND_W_S;
16502 goto do_unaryfp;
16503 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16504 mips32_op = OPC_ROUND_W_D;
16505 goto do_unaryfp;
16507 /* Integer to floating-point conversion */
16508 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16509 mips32_op = OPC_CVT_L_S;
16510 goto do_unaryfp;
16511 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16512 mips32_op = OPC_CVT_L_D;
16513 goto do_unaryfp;
16514 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16515 mips32_op = OPC_CVT_W_S;
16516 goto do_unaryfp;
16517 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16518 mips32_op = OPC_CVT_W_D;
16519 goto do_unaryfp;
16521 /* Paired-foo conversions */
16522 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16523 mips32_op = OPC_CVT_S_PL;
16524 goto do_unaryfp;
16525 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16526 mips32_op = OPC_CVT_S_PU;
16527 goto do_unaryfp;
16528 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16529 mips32_op = OPC_CVT_PW_PS;
16530 goto do_unaryfp;
16531 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16532 mips32_op = OPC_CVT_PS_PW;
16533 goto do_unaryfp;
16535 /* Floating-point moves */
16536 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16537 mips32_op = OPC_MOV_S;
16538 goto do_unaryfp;
16539 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16540 mips32_op = OPC_MOV_D;
16541 goto do_unaryfp;
16542 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16543 mips32_op = OPC_MOV_PS;
16544 goto do_unaryfp;
16546 /* Absolute value */
16547 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16548 mips32_op = OPC_ABS_S;
16549 goto do_unaryfp;
16550 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16551 mips32_op = OPC_ABS_D;
16552 goto do_unaryfp;
16553 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16554 mips32_op = OPC_ABS_PS;
16555 goto do_unaryfp;
16557 /* Negation */
16558 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16559 mips32_op = OPC_NEG_S;
16560 goto do_unaryfp;
16561 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16562 mips32_op = OPC_NEG_D;
16563 goto do_unaryfp;
16564 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16565 mips32_op = OPC_NEG_PS;
16566 goto do_unaryfp;
16568 /* Reciprocal square root step */
16569 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16570 mips32_op = OPC_RSQRT1_S;
16571 goto do_unaryfp;
16572 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16573 mips32_op = OPC_RSQRT1_D;
16574 goto do_unaryfp;
16575 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16576 mips32_op = OPC_RSQRT1_PS;
16577 goto do_unaryfp;
16579 /* Reciprocal step */
16580 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16581 mips32_op = OPC_RECIP1_S;
16582 goto do_unaryfp;
16583 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16584 mips32_op = OPC_RECIP1_S;
16585 goto do_unaryfp;
16586 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16587 mips32_op = OPC_RECIP1_PS;
16588 goto do_unaryfp;
16590 /* Conversions from double */
16591 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16592 mips32_op = OPC_CVT_D_S;
16593 goto do_unaryfp;
16594 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16595 mips32_op = OPC_CVT_D_W;
16596 goto do_unaryfp;
16597 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16598 mips32_op = OPC_CVT_D_L;
16599 goto do_unaryfp;
16601 /* Conversions from single */
16602 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16603 mips32_op = OPC_CVT_S_D;
16604 goto do_unaryfp;
16605 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16606 mips32_op = OPC_CVT_S_W;
16607 goto do_unaryfp;
16608 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16609 mips32_op = OPC_CVT_S_L;
16610 do_unaryfp:
16611 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16612 break;
16614 /* Conditional moves on floating-point codes */
16615 case COND_FLOAT_MOV(MOVT, 0):
16616 case COND_FLOAT_MOV(MOVT, 1):
16617 case COND_FLOAT_MOV(MOVT, 2):
16618 case COND_FLOAT_MOV(MOVT, 3):
16619 case COND_FLOAT_MOV(MOVT, 4):
16620 case COND_FLOAT_MOV(MOVT, 5):
16621 case COND_FLOAT_MOV(MOVT, 6):
16622 case COND_FLOAT_MOV(MOVT, 7):
16623 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16624 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16625 break;
16626 case COND_FLOAT_MOV(MOVF, 0):
16627 case COND_FLOAT_MOV(MOVF, 1):
16628 case COND_FLOAT_MOV(MOVF, 2):
16629 case COND_FLOAT_MOV(MOVF, 3):
16630 case COND_FLOAT_MOV(MOVF, 4):
16631 case COND_FLOAT_MOV(MOVF, 5):
16632 case COND_FLOAT_MOV(MOVF, 6):
16633 case COND_FLOAT_MOV(MOVF, 7):
16634 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16635 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16636 break;
16637 default:
16638 MIPS_INVAL("pool32fxf");
16639 gen_reserved_instruction(ctx);
16640 break;
16644 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16646 int32_t offset;
16647 uint16_t insn;
16648 int rt, rs, rd, rr;
16649 int16_t imm;
16650 uint32_t op, minor, minor2, mips32_op;
16651 uint32_t cond, fmt, cc;
16653 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16654 ctx->opcode = (ctx->opcode << 16) | insn;
16656 rt = (ctx->opcode >> 21) & 0x1f;
16657 rs = (ctx->opcode >> 16) & 0x1f;
16658 rd = (ctx->opcode >> 11) & 0x1f;
16659 rr = (ctx->opcode >> 6) & 0x1f;
16660 imm = (int16_t) ctx->opcode;
16662 op = (ctx->opcode >> 26) & 0x3f;
16663 switch (op) {
16664 case POOL32A:
16665 minor = ctx->opcode & 0x3f;
16666 switch (minor) {
16667 case 0x00:
16668 minor = (ctx->opcode >> 6) & 0xf;
16669 switch (minor) {
16670 case SLL32:
16671 mips32_op = OPC_SLL;
16672 goto do_shifti;
16673 case SRA:
16674 mips32_op = OPC_SRA;
16675 goto do_shifti;
16676 case SRL32:
16677 mips32_op = OPC_SRL;
16678 goto do_shifti;
16679 case ROTR:
16680 mips32_op = OPC_ROTR;
16681 do_shifti:
16682 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16683 break;
16684 case SELEQZ:
16685 check_insn(ctx, ISA_MIPS_R6);
16686 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16687 break;
16688 case SELNEZ:
16689 check_insn(ctx, ISA_MIPS_R6);
16690 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16691 break;
16692 case R6_RDHWR:
16693 check_insn(ctx, ISA_MIPS_R6);
16694 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16695 break;
16696 default:
16697 goto pool32a_invalid;
16699 break;
16700 case 0x10:
16701 minor = (ctx->opcode >> 6) & 0xf;
16702 switch (minor) {
16703 /* Arithmetic */
16704 case ADD:
16705 mips32_op = OPC_ADD;
16706 goto do_arith;
16707 case ADDU32:
16708 mips32_op = OPC_ADDU;
16709 goto do_arith;
16710 case SUB:
16711 mips32_op = OPC_SUB;
16712 goto do_arith;
16713 case SUBU32:
16714 mips32_op = OPC_SUBU;
16715 goto do_arith;
16716 case MUL:
16717 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16718 mips32_op = OPC_MUL;
16719 do_arith:
16720 gen_arith(ctx, mips32_op, rd, rs, rt);
16721 break;
16722 /* Shifts */
16723 case SLLV:
16724 mips32_op = OPC_SLLV;
16725 goto do_shift;
16726 case SRLV:
16727 mips32_op = OPC_SRLV;
16728 goto do_shift;
16729 case SRAV:
16730 mips32_op = OPC_SRAV;
16731 goto do_shift;
16732 case ROTRV:
16733 mips32_op = OPC_ROTRV;
16734 do_shift:
16735 gen_shift(ctx, mips32_op, rd, rs, rt);
16736 break;
16737 /* Logical operations */
16738 case AND:
16739 mips32_op = OPC_AND;
16740 goto do_logic;
16741 case OR32:
16742 mips32_op = OPC_OR;
16743 goto do_logic;
16744 case NOR:
16745 mips32_op = OPC_NOR;
16746 goto do_logic;
16747 case XOR32:
16748 mips32_op = OPC_XOR;
16749 do_logic:
16750 gen_logic(ctx, mips32_op, rd, rs, rt);
16751 break;
16752 /* Set less than */
16753 case SLT:
16754 mips32_op = OPC_SLT;
16755 goto do_slt;
16756 case SLTU:
16757 mips32_op = OPC_SLTU;
16758 do_slt:
16759 gen_slt(ctx, mips32_op, rd, rs, rt);
16760 break;
16761 default:
16762 goto pool32a_invalid;
16764 break;
16765 case 0x18:
16766 minor = (ctx->opcode >> 6) & 0xf;
16767 switch (minor) {
16768 /* Conditional moves */
16769 case MOVN: /* MUL */
16770 if (ctx->insn_flags & ISA_MIPS_R6) {
16771 /* MUL */
16772 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16773 } else {
16774 /* MOVN */
16775 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16777 break;
16778 case MOVZ: /* MUH */
16779 if (ctx->insn_flags & ISA_MIPS_R6) {
16780 /* MUH */
16781 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16782 } else {
16783 /* MOVZ */
16784 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16786 break;
16787 case MULU:
16788 check_insn(ctx, ISA_MIPS_R6);
16789 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16790 break;
16791 case MUHU:
16792 check_insn(ctx, ISA_MIPS_R6);
16793 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16794 break;
16795 case LWXS: /* DIV */
16796 if (ctx->insn_flags & ISA_MIPS_R6) {
16797 /* DIV */
16798 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16799 } else {
16800 /* LWXS */
16801 gen_ldxs(ctx, rs, rt, rd);
16803 break;
16804 case MOD:
16805 check_insn(ctx, ISA_MIPS_R6);
16806 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16807 break;
16808 case R6_DIVU:
16809 check_insn(ctx, ISA_MIPS_R6);
16810 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16811 break;
16812 case MODU:
16813 check_insn(ctx, ISA_MIPS_R6);
16814 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16815 break;
16816 default:
16817 goto pool32a_invalid;
16819 break;
16820 case INS:
16821 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16822 return;
16823 case LSA:
16824 check_insn(ctx, ISA_MIPS_R6);
16825 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16826 extract32(ctx->opcode, 9, 2));
16827 break;
16828 case ALIGN:
16829 check_insn(ctx, ISA_MIPS_R6);
16830 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16831 break;
16832 case EXT:
16833 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16834 return;
16835 case POOL32AXF:
16836 gen_pool32axf(env, ctx, rt, rs);
16837 break;
16838 case BREAK32:
16839 generate_exception_end(ctx, EXCP_BREAK);
16840 break;
16841 case SIGRIE:
16842 check_insn(ctx, ISA_MIPS_R6);
16843 gen_reserved_instruction(ctx);
16844 break;
16845 default:
16846 pool32a_invalid:
16847 MIPS_INVAL("pool32a");
16848 gen_reserved_instruction(ctx);
16849 break;
16851 break;
16852 case POOL32B:
16853 minor = (ctx->opcode >> 12) & 0xf;
16854 switch (minor) {
16855 case CACHE:
16856 check_cp0_enabled(ctx);
16857 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16858 gen_cache_operation(ctx, rt, rs, imm);
16860 break;
16861 case LWC2:
16862 case SWC2:
16863 /* COP2: Not implemented. */
16864 generate_exception_err(ctx, EXCP_CpU, 2);
16865 break;
16866 #ifdef TARGET_MIPS64
16867 case LDP:
16868 case SDP:
16869 check_insn(ctx, ISA_MIPS3);
16870 check_mips_64(ctx);
16871 #endif
16872 /* fall through */
16873 case LWP:
16874 case SWP:
16875 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16876 break;
16877 #ifdef TARGET_MIPS64
16878 case LDM:
16879 case SDM:
16880 check_insn(ctx, ISA_MIPS3);
16881 check_mips_64(ctx);
16882 #endif
16883 /* fall through */
16884 case LWM32:
16885 case SWM32:
16886 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16887 break;
16888 default:
16889 MIPS_INVAL("pool32b");
16890 gen_reserved_instruction(ctx);
16891 break;
16893 break;
16894 case POOL32F:
16895 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16896 minor = ctx->opcode & 0x3f;
16897 check_cp1_enabled(ctx);
16898 switch (minor) {
16899 case ALNV_PS:
16900 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16901 mips32_op = OPC_ALNV_PS;
16902 goto do_madd;
16903 case MADD_S:
16904 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16905 mips32_op = OPC_MADD_S;
16906 goto do_madd;
16907 case MADD_D:
16908 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16909 mips32_op = OPC_MADD_D;
16910 goto do_madd;
16911 case MADD_PS:
16912 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16913 mips32_op = OPC_MADD_PS;
16914 goto do_madd;
16915 case MSUB_S:
16916 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16917 mips32_op = OPC_MSUB_S;
16918 goto do_madd;
16919 case MSUB_D:
16920 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16921 mips32_op = OPC_MSUB_D;
16922 goto do_madd;
16923 case MSUB_PS:
16924 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16925 mips32_op = OPC_MSUB_PS;
16926 goto do_madd;
16927 case NMADD_S:
16928 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16929 mips32_op = OPC_NMADD_S;
16930 goto do_madd;
16931 case NMADD_D:
16932 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16933 mips32_op = OPC_NMADD_D;
16934 goto do_madd;
16935 case NMADD_PS:
16936 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16937 mips32_op = OPC_NMADD_PS;
16938 goto do_madd;
16939 case NMSUB_S:
16940 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16941 mips32_op = OPC_NMSUB_S;
16942 goto do_madd;
16943 case NMSUB_D:
16944 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16945 mips32_op = OPC_NMSUB_D;
16946 goto do_madd;
16947 case NMSUB_PS:
16948 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16949 mips32_op = OPC_NMSUB_PS;
16950 do_madd:
16951 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16952 break;
16953 case CABS_COND_FMT:
16954 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16955 cond = (ctx->opcode >> 6) & 0xf;
16956 cc = (ctx->opcode >> 13) & 0x7;
16957 fmt = (ctx->opcode >> 10) & 0x3;
16958 switch (fmt) {
16959 case 0x0:
16960 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16961 break;
16962 case 0x1:
16963 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16964 break;
16965 case 0x2:
16966 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16967 break;
16968 default:
16969 goto pool32f_invalid;
16971 break;
16972 case C_COND_FMT:
16973 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16974 cond = (ctx->opcode >> 6) & 0xf;
16975 cc = (ctx->opcode >> 13) & 0x7;
16976 fmt = (ctx->opcode >> 10) & 0x3;
16977 switch (fmt) {
16978 case 0x0:
16979 gen_cmp_s(ctx, cond, rt, rs, cc);
16980 break;
16981 case 0x1:
16982 gen_cmp_d(ctx, cond, rt, rs, cc);
16983 break;
16984 case 0x2:
16985 gen_cmp_ps(ctx, cond, rt, rs, cc);
16986 break;
16987 default:
16988 goto pool32f_invalid;
16990 break;
16991 case CMP_CONDN_S:
16992 check_insn(ctx, ISA_MIPS_R6);
16993 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16994 break;
16995 case CMP_CONDN_D:
16996 check_insn(ctx, ISA_MIPS_R6);
16997 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16998 break;
16999 case POOL32FXF:
17000 gen_pool32fxf(ctx, rt, rs);
17001 break;
17002 case 0x00:
17003 /* PLL foo */
17004 switch ((ctx->opcode >> 6) & 0x7) {
17005 case PLL_PS:
17006 mips32_op = OPC_PLL_PS;
17007 goto do_ps;
17008 case PLU_PS:
17009 mips32_op = OPC_PLU_PS;
17010 goto do_ps;
17011 case PUL_PS:
17012 mips32_op = OPC_PUL_PS;
17013 goto do_ps;
17014 case PUU_PS:
17015 mips32_op = OPC_PUU_PS;
17016 goto do_ps;
17017 case CVT_PS_S:
17018 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17019 mips32_op = OPC_CVT_PS_S;
17020 do_ps:
17021 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17022 break;
17023 default:
17024 goto pool32f_invalid;
17026 break;
17027 case MIN_FMT:
17028 check_insn(ctx, ISA_MIPS_R6);
17029 switch ((ctx->opcode >> 9) & 0x3) {
17030 case FMT_SDPS_S:
17031 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
17032 break;
17033 case FMT_SDPS_D:
17034 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
17035 break;
17036 default:
17037 goto pool32f_invalid;
17039 break;
17040 case 0x08:
17041 /* [LS][WDU]XC1 */
17042 switch ((ctx->opcode >> 6) & 0x7) {
17043 case LWXC1:
17044 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17045 mips32_op = OPC_LWXC1;
17046 goto do_ldst_cp1;
17047 case SWXC1:
17048 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17049 mips32_op = OPC_SWXC1;
17050 goto do_ldst_cp1;
17051 case LDXC1:
17052 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17053 mips32_op = OPC_LDXC1;
17054 goto do_ldst_cp1;
17055 case SDXC1:
17056 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17057 mips32_op = OPC_SDXC1;
17058 goto do_ldst_cp1;
17059 case LUXC1:
17060 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17061 mips32_op = OPC_LUXC1;
17062 goto do_ldst_cp1;
17063 case SUXC1:
17064 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17065 mips32_op = OPC_SUXC1;
17066 do_ldst_cp1:
17067 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
17068 break;
17069 default:
17070 goto pool32f_invalid;
17072 break;
17073 case MAX_FMT:
17074 check_insn(ctx, ISA_MIPS_R6);
17075 switch ((ctx->opcode >> 9) & 0x3) {
17076 case FMT_SDPS_S:
17077 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17078 break;
17079 case FMT_SDPS_D:
17080 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17081 break;
17082 default:
17083 goto pool32f_invalid;
17085 break;
17086 case 0x18:
17087 /* 3D insns */
17088 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17089 fmt = (ctx->opcode >> 9) & 0x3;
17090 switch ((ctx->opcode >> 6) & 0x7) {
17091 case RSQRT2_FMT:
17092 switch (fmt) {
17093 case FMT_SDPS_S:
17094 mips32_op = OPC_RSQRT2_S;
17095 goto do_3d;
17096 case FMT_SDPS_D:
17097 mips32_op = OPC_RSQRT2_D;
17098 goto do_3d;
17099 case FMT_SDPS_PS:
17100 mips32_op = OPC_RSQRT2_PS;
17101 goto do_3d;
17102 default:
17103 goto pool32f_invalid;
17105 break;
17106 case RECIP2_FMT:
17107 switch (fmt) {
17108 case FMT_SDPS_S:
17109 mips32_op = OPC_RECIP2_S;
17110 goto do_3d;
17111 case FMT_SDPS_D:
17112 mips32_op = OPC_RECIP2_D;
17113 goto do_3d;
17114 case FMT_SDPS_PS:
17115 mips32_op = OPC_RECIP2_PS;
17116 goto do_3d;
17117 default:
17118 goto pool32f_invalid;
17120 break;
17121 case ADDR_PS:
17122 mips32_op = OPC_ADDR_PS;
17123 goto do_3d;
17124 case MULR_PS:
17125 mips32_op = OPC_MULR_PS;
17126 do_3d:
17127 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17128 break;
17129 default:
17130 goto pool32f_invalid;
17132 break;
17133 case 0x20:
17134 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
17135 cc = (ctx->opcode >> 13) & 0x7;
17136 fmt = (ctx->opcode >> 9) & 0x3;
17137 switch ((ctx->opcode >> 6) & 0x7) {
17138 case MOVF_FMT: /* RINT_FMT */
17139 if (ctx->insn_flags & ISA_MIPS_R6) {
17140 /* RINT_FMT */
17141 switch (fmt) {
17142 case FMT_SDPS_S:
17143 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17144 break;
17145 case FMT_SDPS_D:
17146 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17147 break;
17148 default:
17149 goto pool32f_invalid;
17151 } else {
17152 /* MOVF_FMT */
17153 switch (fmt) {
17154 case FMT_SDPS_S:
17155 gen_movcf_s(ctx, rs, rt, cc, 0);
17156 break;
17157 case FMT_SDPS_D:
17158 gen_movcf_d(ctx, rs, rt, cc, 0);
17159 break;
17160 case FMT_SDPS_PS:
17161 check_ps(ctx);
17162 gen_movcf_ps(ctx, rs, rt, cc, 0);
17163 break;
17164 default:
17165 goto pool32f_invalid;
17168 break;
17169 case MOVT_FMT: /* CLASS_FMT */
17170 if (ctx->insn_flags & ISA_MIPS_R6) {
17171 /* CLASS_FMT */
17172 switch (fmt) {
17173 case FMT_SDPS_S:
17174 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17175 break;
17176 case FMT_SDPS_D:
17177 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17178 break;
17179 default:
17180 goto pool32f_invalid;
17182 } else {
17183 /* MOVT_FMT */
17184 switch (fmt) {
17185 case FMT_SDPS_S:
17186 gen_movcf_s(ctx, rs, rt, cc, 1);
17187 break;
17188 case FMT_SDPS_D:
17189 gen_movcf_d(ctx, rs, rt, cc, 1);
17190 break;
17191 case FMT_SDPS_PS:
17192 check_ps(ctx);
17193 gen_movcf_ps(ctx, rs, rt, cc, 1);
17194 break;
17195 default:
17196 goto pool32f_invalid;
17199 break;
17200 case PREFX:
17201 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17202 break;
17203 default:
17204 goto pool32f_invalid;
17206 break;
17207 #define FINSN_3ARG_SDPS(prfx) \
17208 switch ((ctx->opcode >> 8) & 0x3) { \
17209 case FMT_SDPS_S: \
17210 mips32_op = OPC_##prfx##_S; \
17211 goto do_fpop; \
17212 case FMT_SDPS_D: \
17213 mips32_op = OPC_##prfx##_D; \
17214 goto do_fpop; \
17215 case FMT_SDPS_PS: \
17216 check_ps(ctx); \
17217 mips32_op = OPC_##prfx##_PS; \
17218 goto do_fpop; \
17219 default: \
17220 goto pool32f_invalid; \
17222 case MINA_FMT:
17223 check_insn(ctx, ISA_MIPS_R6);
17224 switch ((ctx->opcode >> 9) & 0x3) {
17225 case FMT_SDPS_S:
17226 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17227 break;
17228 case FMT_SDPS_D:
17229 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17230 break;
17231 default:
17232 goto pool32f_invalid;
17234 break;
17235 case MAXA_FMT:
17236 check_insn(ctx, ISA_MIPS_R6);
17237 switch ((ctx->opcode >> 9) & 0x3) {
17238 case FMT_SDPS_S:
17239 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17240 break;
17241 case FMT_SDPS_D:
17242 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17243 break;
17244 default:
17245 goto pool32f_invalid;
17247 break;
17248 case 0x30:
17249 /* regular FP ops */
17250 switch ((ctx->opcode >> 6) & 0x3) {
17251 case ADD_FMT:
17252 FINSN_3ARG_SDPS(ADD);
17253 break;
17254 case SUB_FMT:
17255 FINSN_3ARG_SDPS(SUB);
17256 break;
17257 case MUL_FMT:
17258 FINSN_3ARG_SDPS(MUL);
17259 break;
17260 case DIV_FMT:
17261 fmt = (ctx->opcode >> 8) & 0x3;
17262 if (fmt == 1) {
17263 mips32_op = OPC_DIV_D;
17264 } else if (fmt == 0) {
17265 mips32_op = OPC_DIV_S;
17266 } else {
17267 goto pool32f_invalid;
17269 goto do_fpop;
17270 default:
17271 goto pool32f_invalid;
17273 break;
17274 case 0x38:
17275 /* cmovs */
17276 switch ((ctx->opcode >> 6) & 0x7) {
17277 case MOVN_FMT: /* SELEQZ_FMT */
17278 if (ctx->insn_flags & ISA_MIPS_R6) {
17279 /* SELEQZ_FMT */
17280 switch ((ctx->opcode >> 9) & 0x3) {
17281 case FMT_SDPS_S:
17282 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
17283 break;
17284 case FMT_SDPS_D:
17285 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
17286 break;
17287 default:
17288 goto pool32f_invalid;
17290 } else {
17291 /* MOVN_FMT */
17292 FINSN_3ARG_SDPS(MOVN);
17294 break;
17295 case MOVN_FMT_04:
17296 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17297 FINSN_3ARG_SDPS(MOVN);
17298 break;
17299 case MOVZ_FMT: /* SELNEZ_FMT */
17300 if (ctx->insn_flags & ISA_MIPS_R6) {
17301 /* SELNEZ_FMT */
17302 switch ((ctx->opcode >> 9) & 0x3) {
17303 case FMT_SDPS_S:
17304 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
17305 break;
17306 case FMT_SDPS_D:
17307 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
17308 break;
17309 default:
17310 goto pool32f_invalid;
17312 } else {
17313 /* MOVZ_FMT */
17314 FINSN_3ARG_SDPS(MOVZ);
17316 break;
17317 case MOVZ_FMT_05:
17318 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17319 FINSN_3ARG_SDPS(MOVZ);
17320 break;
17321 case SEL_FMT:
17322 check_insn(ctx, ISA_MIPS_R6);
17323 switch ((ctx->opcode >> 9) & 0x3) {
17324 case FMT_SDPS_S:
17325 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17326 break;
17327 case FMT_SDPS_D:
17328 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17329 break;
17330 default:
17331 goto pool32f_invalid;
17333 break;
17334 case MADDF_FMT:
17335 check_insn(ctx, ISA_MIPS_R6);
17336 switch ((ctx->opcode >> 9) & 0x3) {
17337 case FMT_SDPS_S:
17338 mips32_op = OPC_MADDF_S;
17339 goto do_fpop;
17340 case FMT_SDPS_D:
17341 mips32_op = OPC_MADDF_D;
17342 goto do_fpop;
17343 default:
17344 goto pool32f_invalid;
17346 break;
17347 case MSUBF_FMT:
17348 check_insn(ctx, ISA_MIPS_R6);
17349 switch ((ctx->opcode >> 9) & 0x3) {
17350 case FMT_SDPS_S:
17351 mips32_op = OPC_MSUBF_S;
17352 goto do_fpop;
17353 case FMT_SDPS_D:
17354 mips32_op = OPC_MSUBF_D;
17355 goto do_fpop;
17356 default:
17357 goto pool32f_invalid;
17359 break;
17360 default:
17361 goto pool32f_invalid;
17363 break;
17364 do_fpop:
17365 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17366 break;
17367 default:
17368 pool32f_invalid:
17369 MIPS_INVAL("pool32f");
17370 gen_reserved_instruction(ctx);
17371 break;
17373 } else {
17374 generate_exception_err(ctx, EXCP_CpU, 1);
17376 break;
17377 case POOL32I:
17378 minor = (ctx->opcode >> 21) & 0x1f;
17379 switch (minor) {
17380 case BLTZ:
17381 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17382 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17383 break;
17384 case BLTZAL:
17385 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17386 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17387 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17388 break;
17389 case BLTZALS:
17390 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17391 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17392 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17393 break;
17394 case BGEZ:
17395 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17396 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17397 break;
17398 case BGEZAL:
17399 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17400 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17401 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17402 break;
17403 case BGEZALS:
17404 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17405 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17406 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17407 break;
17408 case BLEZ:
17409 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17410 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17411 break;
17412 case BGTZ:
17413 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17414 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17415 break;
17417 /* Traps */
17418 case TLTI: /* BC1EQZC */
17419 if (ctx->insn_flags & ISA_MIPS_R6) {
17420 /* BC1EQZC */
17421 check_cp1_enabled(ctx);
17422 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17423 } else {
17424 /* TLTI */
17425 mips32_op = OPC_TLTI;
17426 goto do_trapi;
17428 break;
17429 case TGEI: /* BC1NEZC */
17430 if (ctx->insn_flags & ISA_MIPS_R6) {
17431 /* BC1NEZC */
17432 check_cp1_enabled(ctx);
17433 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17434 } else {
17435 /* TGEI */
17436 mips32_op = OPC_TGEI;
17437 goto do_trapi;
17439 break;
17440 case TLTIU:
17441 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17442 mips32_op = OPC_TLTIU;
17443 goto do_trapi;
17444 case TGEIU:
17445 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17446 mips32_op = OPC_TGEIU;
17447 goto do_trapi;
17448 case TNEI: /* SYNCI */
17449 if (ctx->insn_flags & ISA_MIPS_R6) {
17450 /* SYNCI */
17452 * Break the TB to be able to sync copied instructions
17453 * immediately.
17455 ctx->base.is_jmp = DISAS_STOP;
17456 } else {
17457 /* TNEI */
17458 mips32_op = OPC_TNEI;
17459 goto do_trapi;
17461 break;
17462 case TEQI:
17463 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17464 mips32_op = OPC_TEQI;
17465 do_trapi:
17466 gen_trap(ctx, mips32_op, rs, -1, imm);
17467 break;
17469 case BNEZC:
17470 case BEQZC:
17471 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17472 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17473 4, rs, 0, imm << 1, 0);
17475 * Compact branches don't have a delay slot, so just let
17476 * the normal delay slot handling take us to the branch
17477 * target.
17479 break;
17480 case LUI:
17481 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17482 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17483 break;
17484 case SYNCI:
17485 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17487 * Break the TB to be able to sync copied instructions
17488 * immediately.
17490 ctx->base.is_jmp = DISAS_STOP;
17491 break;
17492 case BC2F:
17493 case BC2T:
17494 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17495 /* COP2: Not implemented. */
17496 generate_exception_err(ctx, EXCP_CpU, 2);
17497 break;
17498 case BC1F:
17499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17500 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17501 goto do_cp1branch;
17502 case BC1T:
17503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17504 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17505 goto do_cp1branch;
17506 case BC1ANY4F:
17507 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17508 mips32_op = OPC_BC1FANY4;
17509 goto do_cp1mips3d;
17510 case BC1ANY4T:
17511 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17512 mips32_op = OPC_BC1TANY4;
17513 do_cp1mips3d:
17514 check_cop1x(ctx);
17515 check_insn(ctx, ASE_MIPS3D);
17516 /* Fall through */
17517 do_cp1branch:
17518 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17519 check_cp1_enabled(ctx);
17520 gen_compute_branch1(ctx, mips32_op,
17521 (ctx->opcode >> 18) & 0x7, imm << 1);
17522 } else {
17523 generate_exception_err(ctx, EXCP_CpU, 1);
17525 break;
17526 case BPOSGE64:
17527 case BPOSGE32:
17528 /* MIPS DSP: not implemented */
17529 /* Fall through */
17530 default:
17531 MIPS_INVAL("pool32i");
17532 gen_reserved_instruction(ctx);
17533 break;
17535 break;
17536 case POOL32C:
17537 minor = (ctx->opcode >> 12) & 0xf;
17538 offset = sextract32(ctx->opcode, 0,
17539 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
17540 switch (minor) {
17541 case LWL:
17542 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17543 mips32_op = OPC_LWL;
17544 goto do_ld_lr;
17545 case SWL:
17546 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17547 mips32_op = OPC_SWL;
17548 goto do_st_lr;
17549 case LWR:
17550 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17551 mips32_op = OPC_LWR;
17552 goto do_ld_lr;
17553 case SWR:
17554 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17555 mips32_op = OPC_SWR;
17556 goto do_st_lr;
17557 #if defined(TARGET_MIPS64)
17558 case LDL:
17559 check_insn(ctx, ISA_MIPS3);
17560 check_mips_64(ctx);
17561 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17562 mips32_op = OPC_LDL;
17563 goto do_ld_lr;
17564 case SDL:
17565 check_insn(ctx, ISA_MIPS3);
17566 check_mips_64(ctx);
17567 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17568 mips32_op = OPC_SDL;
17569 goto do_st_lr;
17570 case LDR:
17571 check_insn(ctx, ISA_MIPS3);
17572 check_mips_64(ctx);
17573 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17574 mips32_op = OPC_LDR;
17575 goto do_ld_lr;
17576 case SDR:
17577 check_insn(ctx, ISA_MIPS3);
17578 check_mips_64(ctx);
17579 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17580 mips32_op = OPC_SDR;
17581 goto do_st_lr;
17582 case LWU:
17583 check_insn(ctx, ISA_MIPS3);
17584 check_mips_64(ctx);
17585 mips32_op = OPC_LWU;
17586 goto do_ld_lr;
17587 case LLD:
17588 check_insn(ctx, ISA_MIPS3);
17589 check_mips_64(ctx);
17590 mips32_op = OPC_LLD;
17591 goto do_ld_lr;
17592 #endif
17593 case LL:
17594 mips32_op = OPC_LL;
17595 goto do_ld_lr;
17596 do_ld_lr:
17597 gen_ld(ctx, mips32_op, rt, rs, offset);
17598 break;
17599 do_st_lr:
17600 gen_st(ctx, mips32_op, rt, rs, offset);
17601 break;
17602 case SC:
17603 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17604 break;
17605 #if defined(TARGET_MIPS64)
17606 case SCD:
17607 check_insn(ctx, ISA_MIPS3);
17608 check_mips_64(ctx);
17609 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17610 break;
17611 #endif
17612 case LD_EVA:
17613 if (!ctx->eva) {
17614 MIPS_INVAL("pool32c ld-eva");
17615 gen_reserved_instruction(ctx);
17616 break;
17618 check_cp0_enabled(ctx);
17620 minor2 = (ctx->opcode >> 9) & 0x7;
17621 offset = sextract32(ctx->opcode, 0, 9);
17622 switch (minor2) {
17623 case LBUE:
17624 mips32_op = OPC_LBUE;
17625 goto do_ld_lr;
17626 case LHUE:
17627 mips32_op = OPC_LHUE;
17628 goto do_ld_lr;
17629 case LWLE:
17630 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17631 mips32_op = OPC_LWLE;
17632 goto do_ld_lr;
17633 case LWRE:
17634 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17635 mips32_op = OPC_LWRE;
17636 goto do_ld_lr;
17637 case LBE:
17638 mips32_op = OPC_LBE;
17639 goto do_ld_lr;
17640 case LHE:
17641 mips32_op = OPC_LHE;
17642 goto do_ld_lr;
17643 case LLE:
17644 mips32_op = OPC_LLE;
17645 goto do_ld_lr;
17646 case LWE:
17647 mips32_op = OPC_LWE;
17648 goto do_ld_lr;
17650 break;
17651 case ST_EVA:
17652 if (!ctx->eva) {
17653 MIPS_INVAL("pool32c st-eva");
17654 gen_reserved_instruction(ctx);
17655 break;
17657 check_cp0_enabled(ctx);
17659 minor2 = (ctx->opcode >> 9) & 0x7;
17660 offset = sextract32(ctx->opcode, 0, 9);
17661 switch (minor2) {
17662 case SWLE:
17663 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17664 mips32_op = OPC_SWLE;
17665 goto do_st_lr;
17666 case SWRE:
17667 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17668 mips32_op = OPC_SWRE;
17669 goto do_st_lr;
17670 case PREFE:
17671 /* Treat as no-op */
17672 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17673 /* hint codes 24-31 are reserved and signal RI */
17674 generate_exception(ctx, EXCP_RI);
17676 break;
17677 case CACHEE:
17678 /* Treat as no-op */
17679 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17680 gen_cache_operation(ctx, rt, rs, offset);
17682 break;
17683 case SBE:
17684 mips32_op = OPC_SBE;
17685 goto do_st_lr;
17686 case SHE:
17687 mips32_op = OPC_SHE;
17688 goto do_st_lr;
17689 case SCE:
17690 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17691 break;
17692 case SWE:
17693 mips32_op = OPC_SWE;
17694 goto do_st_lr;
17696 break;
17697 case PREF:
17698 /* Treat as no-op */
17699 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17700 /* hint codes 24-31 are reserved and signal RI */
17701 generate_exception(ctx, EXCP_RI);
17703 break;
17704 default:
17705 MIPS_INVAL("pool32c");
17706 gen_reserved_instruction(ctx);
17707 break;
17709 break;
17710 case ADDI32: /* AUI, LUI */
17711 if (ctx->insn_flags & ISA_MIPS_R6) {
17712 /* AUI, LUI */
17713 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17714 } else {
17715 /* ADDI32 */
17716 mips32_op = OPC_ADDI;
17717 goto do_addi;
17719 break;
17720 case ADDIU32:
17721 mips32_op = OPC_ADDIU;
17722 do_addi:
17723 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17724 break;
17726 /* Logical operations */
17727 case ORI32:
17728 mips32_op = OPC_ORI;
17729 goto do_logici;
17730 case XORI32:
17731 mips32_op = OPC_XORI;
17732 goto do_logici;
17733 case ANDI32:
17734 mips32_op = OPC_ANDI;
17735 do_logici:
17736 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17737 break;
17739 /* Set less than immediate */
17740 case SLTI32:
17741 mips32_op = OPC_SLTI;
17742 goto do_slti;
17743 case SLTIU32:
17744 mips32_op = OPC_SLTIU;
17745 do_slti:
17746 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17747 break;
17748 case JALX32:
17749 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17750 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17751 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17752 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17753 break;
17754 case JALS32: /* BOVC, BEQC, BEQZALC */
17755 if (ctx->insn_flags & ISA_MIPS_R6) {
17756 if (rs >= rt) {
17757 /* BOVC */
17758 mips32_op = OPC_BOVC;
17759 } else if (rs < rt && rs == 0) {
17760 /* BEQZALC */
17761 mips32_op = OPC_BEQZALC;
17762 } else {
17763 /* BEQC */
17764 mips32_op = OPC_BEQC;
17766 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17767 } else {
17768 /* JALS32 */
17769 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17770 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17771 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17773 break;
17774 case BEQ32: /* BC */
17775 if (ctx->insn_flags & ISA_MIPS_R6) {
17776 /* BC */
17777 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17778 sextract32(ctx->opcode << 1, 0, 27));
17779 } else {
17780 /* BEQ32 */
17781 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17783 break;
17784 case BNE32: /* BALC */
17785 if (ctx->insn_flags & ISA_MIPS_R6) {
17786 /* BALC */
17787 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17788 sextract32(ctx->opcode << 1, 0, 27));
17789 } else {
17790 /* BNE32 */
17791 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17793 break;
17794 case J32: /* BGTZC, BLTZC, BLTC */
17795 if (ctx->insn_flags & ISA_MIPS_R6) {
17796 if (rs == 0 && rt != 0) {
17797 /* BGTZC */
17798 mips32_op = OPC_BGTZC;
17799 } else if (rs != 0 && rt != 0 && rs == rt) {
17800 /* BLTZC */
17801 mips32_op = OPC_BLTZC;
17802 } else {
17803 /* BLTC */
17804 mips32_op = OPC_BLTC;
17806 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17807 } else {
17808 /* J32 */
17809 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17810 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17812 break;
17813 case JAL32: /* BLEZC, BGEZC, BGEC */
17814 if (ctx->insn_flags & ISA_MIPS_R6) {
17815 if (rs == 0 && rt != 0) {
17816 /* BLEZC */
17817 mips32_op = OPC_BLEZC;
17818 } else if (rs != 0 && rt != 0 && rs == rt) {
17819 /* BGEZC */
17820 mips32_op = OPC_BGEZC;
17821 } else {
17822 /* BGEC */
17823 mips32_op = OPC_BGEC;
17825 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17826 } else {
17827 /* JAL32 */
17828 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17829 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17830 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17832 break;
17833 /* Floating point (COP1) */
17834 case LWC132:
17835 mips32_op = OPC_LWC1;
17836 goto do_cop1;
17837 case LDC132:
17838 mips32_op = OPC_LDC1;
17839 goto do_cop1;
17840 case SWC132:
17841 mips32_op = OPC_SWC1;
17842 goto do_cop1;
17843 case SDC132:
17844 mips32_op = OPC_SDC1;
17845 do_cop1:
17846 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17847 break;
17848 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17849 if (ctx->insn_flags & ISA_MIPS_R6) {
17850 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17851 switch ((ctx->opcode >> 16) & 0x1f) {
17852 case ADDIUPC_00:
17853 case ADDIUPC_01:
17854 case ADDIUPC_02:
17855 case ADDIUPC_03:
17856 case ADDIUPC_04:
17857 case ADDIUPC_05:
17858 case ADDIUPC_06:
17859 case ADDIUPC_07:
17860 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17861 break;
17862 case AUIPC:
17863 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17864 break;
17865 case ALUIPC:
17866 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17867 break;
17868 case LWPC_08:
17869 case LWPC_09:
17870 case LWPC_0A:
17871 case LWPC_0B:
17872 case LWPC_0C:
17873 case LWPC_0D:
17874 case LWPC_0E:
17875 case LWPC_0F:
17876 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17877 break;
17878 default:
17879 generate_exception(ctx, EXCP_RI);
17880 break;
17882 } else {
17883 /* ADDIUPC */
17884 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17885 offset = SIMM(ctx->opcode, 0, 23) << 2;
17887 gen_addiupc(ctx, reg, offset, 0, 0);
17889 break;
17890 case BNVC: /* BNEC, BNEZALC */
17891 check_insn(ctx, ISA_MIPS_R6);
17892 if (rs >= rt) {
17893 /* BNVC */
17894 mips32_op = OPC_BNVC;
17895 } else if (rs < rt && rs == 0) {
17896 /* BNEZALC */
17897 mips32_op = OPC_BNEZALC;
17898 } else {
17899 /* BNEC */
17900 mips32_op = OPC_BNEC;
17902 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17903 break;
17904 case R6_BNEZC: /* JIALC */
17905 check_insn(ctx, ISA_MIPS_R6);
17906 if (rt != 0) {
17907 /* BNEZC */
17908 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17909 sextract32(ctx->opcode << 1, 0, 22));
17910 } else {
17911 /* JIALC */
17912 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17914 break;
17915 case R6_BEQZC: /* JIC */
17916 check_insn(ctx, ISA_MIPS_R6);
17917 if (rt != 0) {
17918 /* BEQZC */
17919 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17920 sextract32(ctx->opcode << 1, 0, 22));
17921 } else {
17922 /* JIC */
17923 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17925 break;
17926 case BLEZALC: /* BGEZALC, BGEUC */
17927 check_insn(ctx, ISA_MIPS_R6);
17928 if (rs == 0 && rt != 0) {
17929 /* BLEZALC */
17930 mips32_op = OPC_BLEZALC;
17931 } else if (rs != 0 && rt != 0 && rs == rt) {
17932 /* BGEZALC */
17933 mips32_op = OPC_BGEZALC;
17934 } else {
17935 /* BGEUC */
17936 mips32_op = OPC_BGEUC;
17938 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17939 break;
17940 case BGTZALC: /* BLTZALC, BLTUC */
17941 check_insn(ctx, ISA_MIPS_R6);
17942 if (rs == 0 && rt != 0) {
17943 /* BGTZALC */
17944 mips32_op = OPC_BGTZALC;
17945 } else if (rs != 0 && rt != 0 && rs == rt) {
17946 /* BLTZALC */
17947 mips32_op = OPC_BLTZALC;
17948 } else {
17949 /* BLTUC */
17950 mips32_op = OPC_BLTUC;
17952 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17953 break;
17954 /* Loads and stores */
17955 case LB32:
17956 mips32_op = OPC_LB;
17957 goto do_ld;
17958 case LBU32:
17959 mips32_op = OPC_LBU;
17960 goto do_ld;
17961 case LH32:
17962 mips32_op = OPC_LH;
17963 goto do_ld;
17964 case LHU32:
17965 mips32_op = OPC_LHU;
17966 goto do_ld;
17967 case LW32:
17968 mips32_op = OPC_LW;
17969 goto do_ld;
17970 #ifdef TARGET_MIPS64
17971 case LD32:
17972 check_insn(ctx, ISA_MIPS3);
17973 check_mips_64(ctx);
17974 mips32_op = OPC_LD;
17975 goto do_ld;
17976 case SD32:
17977 check_insn(ctx, ISA_MIPS3);
17978 check_mips_64(ctx);
17979 mips32_op = OPC_SD;
17980 goto do_st;
17981 #endif
17982 case SB32:
17983 mips32_op = OPC_SB;
17984 goto do_st;
17985 case SH32:
17986 mips32_op = OPC_SH;
17987 goto do_st;
17988 case SW32:
17989 mips32_op = OPC_SW;
17990 goto do_st;
17991 do_ld:
17992 gen_ld(ctx, mips32_op, rt, rs, imm);
17993 break;
17994 do_st:
17995 gen_st(ctx, mips32_op, rt, rs, imm);
17996 break;
17997 default:
17998 gen_reserved_instruction(ctx);
17999 break;
18003 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
18005 uint32_t op;
18007 /* make sure instructions are on a halfword boundary */
18008 if (ctx->base.pc_next & 0x1) {
18009 env->CP0_BadVAddr = ctx->base.pc_next;
18010 generate_exception_end(ctx, EXCP_AdEL);
18011 return 2;
18014 op = (ctx->opcode >> 10) & 0x3f;
18015 /* Enforce properly-sized instructions in a delay slot */
18016 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
18017 switch (op & 0x7) { /* MSB-3..MSB-5 */
18018 case 0:
18019 /* POOL32A, POOL32B, POOL32I, POOL32C */
18020 case 4:
18021 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
18022 case 5:
18023 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
18024 case 6:
18025 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
18026 case 7:
18027 /* LB32, LH32, LWC132, LDC132, LW32 */
18028 if (ctx->hflags & MIPS_HFLAG_BDS16) {
18029 gen_reserved_instruction(ctx);
18030 return 2;
18032 break;
18033 case 1:
18034 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
18035 case 2:
18036 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
18037 case 3:
18038 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
18039 if (ctx->hflags & MIPS_HFLAG_BDS32) {
18040 gen_reserved_instruction(ctx);
18041 return 2;
18043 break;
18047 switch (op) {
18048 case POOL16A:
18050 int rd = mmreg(uMIPS_RD(ctx->opcode));
18051 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
18052 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
18053 uint32_t opc = 0;
18055 switch (ctx->opcode & 0x1) {
18056 case ADDU16:
18057 opc = OPC_ADDU;
18058 break;
18059 case SUBU16:
18060 opc = OPC_SUBU;
18061 break;
18063 if (ctx->insn_flags & ISA_MIPS_R6) {
18065 * In the Release 6, the register number location in
18066 * the instruction encoding has changed.
18068 gen_arith(ctx, opc, rs1, rd, rs2);
18069 } else {
18070 gen_arith(ctx, opc, rd, rs1, rs2);
18073 break;
18074 case POOL16B:
18076 int rd = mmreg(uMIPS_RD(ctx->opcode));
18077 int rs = mmreg(uMIPS_RS(ctx->opcode));
18078 int amount = (ctx->opcode >> 1) & 0x7;
18079 uint32_t opc = 0;
18080 amount = amount == 0 ? 8 : amount;
18082 switch (ctx->opcode & 0x1) {
18083 case SLL16:
18084 opc = OPC_SLL;
18085 break;
18086 case SRL16:
18087 opc = OPC_SRL;
18088 break;
18091 gen_shift_imm(ctx, opc, rd, rs, amount);
18093 break;
18094 case POOL16C:
18095 if (ctx->insn_flags & ISA_MIPS_R6) {
18096 gen_pool16c_r6_insn(ctx);
18097 } else {
18098 gen_pool16c_insn(ctx);
18100 break;
18101 case LWGP16:
18103 int rd = mmreg(uMIPS_RD(ctx->opcode));
18104 int rb = 28; /* GP */
18105 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
18107 gen_ld(ctx, OPC_LW, rd, rb, offset);
18109 break;
18110 case POOL16F:
18111 check_insn_opc_removed(ctx, ISA_MIPS_R6);
18112 if (ctx->opcode & 1) {
18113 gen_reserved_instruction(ctx);
18114 } else {
18115 /* MOVEP */
18116 int enc_dest = uMIPS_RD(ctx->opcode);
18117 int enc_rt = uMIPS_RS2(ctx->opcode);
18118 int enc_rs = uMIPS_RS1(ctx->opcode);
18119 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
18121 break;
18122 case LBU16:
18124 int rd = mmreg(uMIPS_RD(ctx->opcode));
18125 int rb = mmreg(uMIPS_RS(ctx->opcode));
18126 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18127 offset = (offset == 0xf ? -1 : offset);
18129 gen_ld(ctx, OPC_LBU, rd, rb, offset);
18131 break;
18132 case LHU16:
18134 int rd = mmreg(uMIPS_RD(ctx->opcode));
18135 int rb = mmreg(uMIPS_RS(ctx->opcode));
18136 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18138 gen_ld(ctx, OPC_LHU, rd, rb, offset);
18140 break;
18141 case LWSP16:
18143 int rd = (ctx->opcode >> 5) & 0x1f;
18144 int rb = 29; /* SP */
18145 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18147 gen_ld(ctx, OPC_LW, rd, rb, offset);
18149 break;
18150 case LW16:
18152 int rd = mmreg(uMIPS_RD(ctx->opcode));
18153 int rb = mmreg(uMIPS_RS(ctx->opcode));
18154 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18156 gen_ld(ctx, OPC_LW, rd, rb, offset);
18158 break;
18159 case SB16:
18161 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18162 int rb = mmreg(uMIPS_RS(ctx->opcode));
18163 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18165 gen_st(ctx, OPC_SB, rd, rb, offset);
18167 break;
18168 case SH16:
18170 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18171 int rb = mmreg(uMIPS_RS(ctx->opcode));
18172 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18174 gen_st(ctx, OPC_SH, rd, rb, offset);
18176 break;
18177 case SWSP16:
18179 int rd = (ctx->opcode >> 5) & 0x1f;
18180 int rb = 29; /* SP */
18181 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18183 gen_st(ctx, OPC_SW, rd, rb, offset);
18185 break;
18186 case SW16:
18188 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18189 int rb = mmreg(uMIPS_RS(ctx->opcode));
18190 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18192 gen_st(ctx, OPC_SW, rd, rb, offset);
18194 break;
18195 case MOVE16:
18197 int rd = uMIPS_RD5(ctx->opcode);
18198 int rs = uMIPS_RS5(ctx->opcode);
18200 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
18202 break;
18203 case ANDI16:
18204 gen_andi16(ctx);
18205 break;
18206 case POOL16D:
18207 switch (ctx->opcode & 0x1) {
18208 case ADDIUS5:
18209 gen_addius5(ctx);
18210 break;
18211 case ADDIUSP:
18212 gen_addiusp(ctx);
18213 break;
18215 break;
18216 case POOL16E:
18217 switch (ctx->opcode & 0x1) {
18218 case ADDIUR2:
18219 gen_addiur2(ctx);
18220 break;
18221 case ADDIUR1SP:
18222 gen_addiur1sp(ctx);
18223 break;
18225 break;
18226 case B16: /* BC16 */
18227 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
18228 sextract32(ctx->opcode, 0, 10) << 1,
18229 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
18230 break;
18231 case BNEZ16: /* BNEZC16 */
18232 case BEQZ16: /* BEQZC16 */
18233 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
18234 mmreg(uMIPS_RD(ctx->opcode)),
18235 0, sextract32(ctx->opcode, 0, 7) << 1,
18236 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
18238 break;
18239 case LI16:
18241 int reg = mmreg(uMIPS_RD(ctx->opcode));
18242 int imm = ZIMM(ctx->opcode, 0, 7);
18244 imm = (imm == 0x7f ? -1 : imm);
18245 tcg_gen_movi_tl(cpu_gpr[reg], imm);
18247 break;
18248 case RES_29:
18249 case RES_31:
18250 case RES_39:
18251 gen_reserved_instruction(ctx);
18252 break;
18253 default:
18254 decode_micromips32_opc(env, ctx);
18255 return 4;
18258 return 2;
18263 * nanoMIPS opcodes
18267 /* MAJOR, P16, and P32 pools opcodes */
18268 enum {
18269 NM_P_ADDIU = 0x00,
18270 NM_ADDIUPC = 0x01,
18271 NM_MOVE_BALC = 0x02,
18272 NM_P16_MV = 0x04,
18273 NM_LW16 = 0x05,
18274 NM_BC16 = 0x06,
18275 NM_P16_SR = 0x07,
18277 NM_POOL32A = 0x08,
18278 NM_P_BAL = 0x0a,
18279 NM_P16_SHIFT = 0x0c,
18280 NM_LWSP16 = 0x0d,
18281 NM_BALC16 = 0x0e,
18282 NM_P16_4X4 = 0x0f,
18284 NM_P_GP_W = 0x10,
18285 NM_P_GP_BH = 0x11,
18286 NM_P_J = 0x12,
18287 NM_P16C = 0x14,
18288 NM_LWGP16 = 0x15,
18289 NM_P16_LB = 0x17,
18291 NM_P48I = 0x18,
18292 NM_P16_A1 = 0x1c,
18293 NM_LW4X4 = 0x1d,
18294 NM_P16_LH = 0x1f,
18296 NM_P_U12 = 0x20,
18297 NM_P_LS_U12 = 0x21,
18298 NM_P_BR1 = 0x22,
18299 NM_P16_A2 = 0x24,
18300 NM_SW16 = 0x25,
18301 NM_BEQZC16 = 0x26,
18303 NM_POOL32F = 0x28,
18304 NM_P_LS_S9 = 0x29,
18305 NM_P_BR2 = 0x2a,
18307 NM_P16_ADDU = 0x2c,
18308 NM_SWSP16 = 0x2d,
18309 NM_BNEZC16 = 0x2e,
18310 NM_MOVEP = 0x2f,
18312 NM_POOL32S = 0x30,
18313 NM_P_BRI = 0x32,
18314 NM_LI16 = 0x34,
18315 NM_SWGP16 = 0x35,
18316 NM_P16_BR = 0x36,
18318 NM_P_LUI = 0x38,
18319 NM_ANDI16 = 0x3c,
18320 NM_SW4X4 = 0x3d,
18321 NM_MOVEPREV = 0x3f,
18324 /* POOL32A instruction pool */
18325 enum {
18326 NM_POOL32A0 = 0x00,
18327 NM_SPECIAL2 = 0x01,
18328 NM_COP2_1 = 0x02,
18329 NM_UDI = 0x03,
18330 NM_POOL32A5 = 0x05,
18331 NM_POOL32A7 = 0x07,
18334 /* P.GP.W instruction pool */
18335 enum {
18336 NM_ADDIUGP_W = 0x00,
18337 NM_LWGP = 0x02,
18338 NM_SWGP = 0x03,
18341 /* P48I instruction pool */
18342 enum {
18343 NM_LI48 = 0x00,
18344 NM_ADDIU48 = 0x01,
18345 NM_ADDIUGP48 = 0x02,
18346 NM_ADDIUPC48 = 0x03,
18347 NM_LWPC48 = 0x0b,
18348 NM_SWPC48 = 0x0f,
18351 /* P.U12 instruction pool */
18352 enum {
18353 NM_ORI = 0x00,
18354 NM_XORI = 0x01,
18355 NM_ANDI = 0x02,
18356 NM_P_SR = 0x03,
18357 NM_SLTI = 0x04,
18358 NM_SLTIU = 0x05,
18359 NM_SEQI = 0x06,
18360 NM_ADDIUNEG = 0x08,
18361 NM_P_SHIFT = 0x0c,
18362 NM_P_ROTX = 0x0d,
18363 NM_P_INS = 0x0e,
18364 NM_P_EXT = 0x0f,
18367 /* POOL32F instruction pool */
18368 enum {
18369 NM_POOL32F_0 = 0x00,
18370 NM_POOL32F_3 = 0x03,
18371 NM_POOL32F_5 = 0x05,
18374 /* POOL32S instruction pool */
18375 enum {
18376 NM_POOL32S_0 = 0x00,
18377 NM_POOL32S_4 = 0x04,
18380 /* P.LUI instruction pool */
18381 enum {
18382 NM_LUI = 0x00,
18383 NM_ALUIPC = 0x01,
18386 /* P.GP.BH instruction pool */
18387 enum {
18388 NM_LBGP = 0x00,
18389 NM_SBGP = 0x01,
18390 NM_LBUGP = 0x02,
18391 NM_ADDIUGP_B = 0x03,
18392 NM_P_GP_LH = 0x04,
18393 NM_P_GP_SH = 0x05,
18394 NM_P_GP_CP1 = 0x06,
18397 /* P.LS.U12 instruction pool */
18398 enum {
18399 NM_LB = 0x00,
18400 NM_SB = 0x01,
18401 NM_LBU = 0x02,
18402 NM_P_PREFU12 = 0x03,
18403 NM_LH = 0x04,
18404 NM_SH = 0x05,
18405 NM_LHU = 0x06,
18406 NM_LWU = 0x07,
18407 NM_LW = 0x08,
18408 NM_SW = 0x09,
18409 NM_LWC1 = 0x0a,
18410 NM_SWC1 = 0x0b,
18411 NM_LDC1 = 0x0e,
18412 NM_SDC1 = 0x0f,
18415 /* P.LS.S9 instruction pool */
18416 enum {
18417 NM_P_LS_S0 = 0x00,
18418 NM_P_LS_S1 = 0x01,
18419 NM_P_LS_E0 = 0x02,
18420 NM_P_LS_WM = 0x04,
18421 NM_P_LS_UAWM = 0x05,
18424 /* P.BAL instruction pool */
18425 enum {
18426 NM_BC = 0x00,
18427 NM_BALC = 0x01,
18430 /* P.J instruction pool */
18431 enum {
18432 NM_JALRC = 0x00,
18433 NM_JALRC_HB = 0x01,
18434 NM_P_BALRSC = 0x08,
18437 /* P.BR1 instruction pool */
18438 enum {
18439 NM_BEQC = 0x00,
18440 NM_P_BR3A = 0x01,
18441 NM_BGEC = 0x02,
18442 NM_BGEUC = 0x03,
18445 /* P.BR2 instruction pool */
18446 enum {
18447 NM_BNEC = 0x00,
18448 NM_BLTC = 0x02,
18449 NM_BLTUC = 0x03,
18452 /* P.BRI instruction pool */
18453 enum {
18454 NM_BEQIC = 0x00,
18455 NM_BBEQZC = 0x01,
18456 NM_BGEIC = 0x02,
18457 NM_BGEIUC = 0x03,
18458 NM_BNEIC = 0x04,
18459 NM_BBNEZC = 0x05,
18460 NM_BLTIC = 0x06,
18461 NM_BLTIUC = 0x07,
18464 /* P16.SHIFT instruction pool */
18465 enum {
18466 NM_SLL16 = 0x00,
18467 NM_SRL16 = 0x01,
18470 /* POOL16C instruction pool */
18471 enum {
18472 NM_POOL16C_0 = 0x00,
18473 NM_LWXS16 = 0x01,
18476 /* P16.A1 instruction pool */
18477 enum {
18478 NM_ADDIUR1SP = 0x01,
18481 /* P16.A2 instruction pool */
18482 enum {
18483 NM_ADDIUR2 = 0x00,
18484 NM_P_ADDIURS5 = 0x01,
18487 /* P16.ADDU instruction pool */
18488 enum {
18489 NM_ADDU16 = 0x00,
18490 NM_SUBU16 = 0x01,
18493 /* P16.SR instruction pool */
18494 enum {
18495 NM_SAVE16 = 0x00,
18496 NM_RESTORE_JRC16 = 0x01,
18499 /* P16.4X4 instruction pool */
18500 enum {
18501 NM_ADDU4X4 = 0x00,
18502 NM_MUL4X4 = 0x01,
18505 /* P16.LB instruction pool */
18506 enum {
18507 NM_LB16 = 0x00,
18508 NM_SB16 = 0x01,
18509 NM_LBU16 = 0x02,
18512 /* P16.LH instruction pool */
18513 enum {
18514 NM_LH16 = 0x00,
18515 NM_SH16 = 0x01,
18516 NM_LHU16 = 0x02,
18519 /* P.RI instruction pool */
18520 enum {
18521 NM_SIGRIE = 0x00,
18522 NM_P_SYSCALL = 0x01,
18523 NM_BREAK = 0x02,
18524 NM_SDBBP = 0x03,
18527 /* POOL32A0 instruction pool */
18528 enum {
18529 NM_P_TRAP = 0x00,
18530 NM_SEB = 0x01,
18531 NM_SLLV = 0x02,
18532 NM_MUL = 0x03,
18533 NM_MFC0 = 0x06,
18534 NM_MFHC0 = 0x07,
18535 NM_SEH = 0x09,
18536 NM_SRLV = 0x0a,
18537 NM_MUH = 0x0b,
18538 NM_MTC0 = 0x0e,
18539 NM_MTHC0 = 0x0f,
18540 NM_SRAV = 0x12,
18541 NM_MULU = 0x13,
18542 NM_ROTRV = 0x1a,
18543 NM_MUHU = 0x1b,
18544 NM_ADD = 0x22,
18545 NM_DIV = 0x23,
18546 NM_ADDU = 0x2a,
18547 NM_MOD = 0x2b,
18548 NM_SUB = 0x32,
18549 NM_DIVU = 0x33,
18550 NM_RDHWR = 0x38,
18551 NM_SUBU = 0x3a,
18552 NM_MODU = 0x3b,
18553 NM_P_CMOVE = 0x42,
18554 NM_FORK = 0x45,
18555 NM_MFTR = 0x46,
18556 NM_MFHTR = 0x47,
18557 NM_AND = 0x4a,
18558 NM_YIELD = 0x4d,
18559 NM_MTTR = 0x4e,
18560 NM_MTHTR = 0x4f,
18561 NM_OR = 0x52,
18562 NM_D_E_MT_VPE = 0x56,
18563 NM_NOR = 0x5a,
18564 NM_XOR = 0x62,
18565 NM_SLT = 0x6a,
18566 NM_P_SLTU = 0x72,
18567 NM_SOV = 0x7a,
18570 /* CRC32 instruction pool */
18571 enum {
18572 NM_CRC32B = 0x00,
18573 NM_CRC32H = 0x01,
18574 NM_CRC32W = 0x02,
18575 NM_CRC32CB = 0x04,
18576 NM_CRC32CH = 0x05,
18577 NM_CRC32CW = 0x06,
18580 /* POOL32A5 instruction pool */
18581 enum {
18582 NM_CMP_EQ_PH = 0x00,
18583 NM_CMP_LT_PH = 0x08,
18584 NM_CMP_LE_PH = 0x10,
18585 NM_CMPGU_EQ_QB = 0x18,
18586 NM_CMPGU_LT_QB = 0x20,
18587 NM_CMPGU_LE_QB = 0x28,
18588 NM_CMPGDU_EQ_QB = 0x30,
18589 NM_CMPGDU_LT_QB = 0x38,
18590 NM_CMPGDU_LE_QB = 0x40,
18591 NM_CMPU_EQ_QB = 0x48,
18592 NM_CMPU_LT_QB = 0x50,
18593 NM_CMPU_LE_QB = 0x58,
18594 NM_ADDQ_S_W = 0x60,
18595 NM_SUBQ_S_W = 0x68,
18596 NM_ADDSC = 0x70,
18597 NM_ADDWC = 0x78,
18599 NM_ADDQ_S_PH = 0x01,
18600 NM_ADDQH_R_PH = 0x09,
18601 NM_ADDQH_R_W = 0x11,
18602 NM_ADDU_S_QB = 0x19,
18603 NM_ADDU_S_PH = 0x21,
18604 NM_ADDUH_R_QB = 0x29,
18605 NM_SHRAV_R_PH = 0x31,
18606 NM_SHRAV_R_QB = 0x39,
18607 NM_SUBQ_S_PH = 0x41,
18608 NM_SUBQH_R_PH = 0x49,
18609 NM_SUBQH_R_W = 0x51,
18610 NM_SUBU_S_QB = 0x59,
18611 NM_SUBU_S_PH = 0x61,
18612 NM_SUBUH_R_QB = 0x69,
18613 NM_SHLLV_S_PH = 0x71,
18614 NM_PRECR_SRA_R_PH_W = 0x79,
18616 NM_MULEU_S_PH_QBL = 0x12,
18617 NM_MULEU_S_PH_QBR = 0x1a,
18618 NM_MULQ_RS_PH = 0x22,
18619 NM_MULQ_S_PH = 0x2a,
18620 NM_MULQ_RS_W = 0x32,
18621 NM_MULQ_S_W = 0x3a,
18622 NM_APPEND = 0x42,
18623 NM_MODSUB = 0x52,
18624 NM_SHRAV_R_W = 0x5a,
18625 NM_SHRLV_PH = 0x62,
18626 NM_SHRLV_QB = 0x6a,
18627 NM_SHLLV_QB = 0x72,
18628 NM_SHLLV_S_W = 0x7a,
18630 NM_SHILO = 0x03,
18632 NM_MULEQ_S_W_PHL = 0x04,
18633 NM_MULEQ_S_W_PHR = 0x0c,
18635 NM_MUL_S_PH = 0x05,
18636 NM_PRECR_QB_PH = 0x0d,
18637 NM_PRECRQ_QB_PH = 0x15,
18638 NM_PRECRQ_PH_W = 0x1d,
18639 NM_PRECRQ_RS_PH_W = 0x25,
18640 NM_PRECRQU_S_QB_PH = 0x2d,
18641 NM_PACKRL_PH = 0x35,
18642 NM_PICK_QB = 0x3d,
18643 NM_PICK_PH = 0x45,
18645 NM_SHRA_R_W = 0x5e,
18646 NM_SHRA_R_PH = 0x66,
18647 NM_SHLL_S_PH = 0x76,
18648 NM_SHLL_S_W = 0x7e,
18650 NM_REPL_PH = 0x07
18653 /* POOL32A7 instruction pool */
18654 enum {
18655 NM_P_LSX = 0x00,
18656 NM_LSA = 0x01,
18657 NM_EXTW = 0x03,
18658 NM_POOL32AXF = 0x07,
18661 /* P.SR instruction pool */
18662 enum {
18663 NM_PP_SR = 0x00,
18664 NM_P_SR_F = 0x01,
18667 /* P.SHIFT instruction pool */
18668 enum {
18669 NM_P_SLL = 0x00,
18670 NM_SRL = 0x02,
18671 NM_SRA = 0x04,
18672 NM_ROTR = 0x06,
18675 /* P.ROTX instruction pool */
18676 enum {
18677 NM_ROTX = 0x00,
18680 /* P.INS instruction pool */
18681 enum {
18682 NM_INS = 0x00,
18685 /* P.EXT instruction pool */
18686 enum {
18687 NM_EXT = 0x00,
18690 /* POOL32F_0 (fmt) instruction pool */
18691 enum {
18692 NM_RINT_S = 0x04,
18693 NM_RINT_D = 0x44,
18694 NM_ADD_S = 0x06,
18695 NM_SELEQZ_S = 0x07,
18696 NM_SELEQZ_D = 0x47,
18697 NM_CLASS_S = 0x0c,
18698 NM_CLASS_D = 0x4c,
18699 NM_SUB_S = 0x0e,
18700 NM_SELNEZ_S = 0x0f,
18701 NM_SELNEZ_D = 0x4f,
18702 NM_MUL_S = 0x16,
18703 NM_SEL_S = 0x17,
18704 NM_SEL_D = 0x57,
18705 NM_DIV_S = 0x1e,
18706 NM_ADD_D = 0x26,
18707 NM_SUB_D = 0x2e,
18708 NM_MUL_D = 0x36,
18709 NM_MADDF_S = 0x37,
18710 NM_MADDF_D = 0x77,
18711 NM_DIV_D = 0x3e,
18712 NM_MSUBF_S = 0x3f,
18713 NM_MSUBF_D = 0x7f,
18716 /* POOL32F_3 instruction pool */
18717 enum {
18718 NM_MIN_FMT = 0x00,
18719 NM_MAX_FMT = 0x01,
18720 NM_MINA_FMT = 0x04,
18721 NM_MAXA_FMT = 0x05,
18722 NM_POOL32FXF = 0x07,
18725 /* POOL32F_5 instruction pool */
18726 enum {
18727 NM_CMP_CONDN_S = 0x00,
18728 NM_CMP_CONDN_D = 0x02,
18731 /* P.GP.LH instruction pool */
18732 enum {
18733 NM_LHGP = 0x00,
18734 NM_LHUGP = 0x01,
18737 /* P.GP.SH instruction pool */
18738 enum {
18739 NM_SHGP = 0x00,
18742 /* P.GP.CP1 instruction pool */
18743 enum {
18744 NM_LWC1GP = 0x00,
18745 NM_SWC1GP = 0x01,
18746 NM_LDC1GP = 0x02,
18747 NM_SDC1GP = 0x03,
18750 /* P.LS.S0 instruction pool */
18751 enum {
18752 NM_LBS9 = 0x00,
18753 NM_LHS9 = 0x04,
18754 NM_LWS9 = 0x08,
18755 NM_LDS9 = 0x0c,
18757 NM_SBS9 = 0x01,
18758 NM_SHS9 = 0x05,
18759 NM_SWS9 = 0x09,
18760 NM_SDS9 = 0x0d,
18762 NM_LBUS9 = 0x02,
18763 NM_LHUS9 = 0x06,
18764 NM_LWC1S9 = 0x0a,
18765 NM_LDC1S9 = 0x0e,
18767 NM_P_PREFS9 = 0x03,
18768 NM_LWUS9 = 0x07,
18769 NM_SWC1S9 = 0x0b,
18770 NM_SDC1S9 = 0x0f,
18773 /* P.LS.S1 instruction pool */
18774 enum {
18775 NM_ASET_ACLR = 0x02,
18776 NM_UALH = 0x04,
18777 NM_UASH = 0x05,
18778 NM_CACHE = 0x07,
18779 NM_P_LL = 0x0a,
18780 NM_P_SC = 0x0b,
18783 /* P.LS.E0 instruction pool */
18784 enum {
18785 NM_LBE = 0x00,
18786 NM_SBE = 0x01,
18787 NM_LBUE = 0x02,
18788 NM_P_PREFE = 0x03,
18789 NM_LHE = 0x04,
18790 NM_SHE = 0x05,
18791 NM_LHUE = 0x06,
18792 NM_CACHEE = 0x07,
18793 NM_LWE = 0x08,
18794 NM_SWE = 0x09,
18795 NM_P_LLE = 0x0a,
18796 NM_P_SCE = 0x0b,
18799 /* P.PREFE instruction pool */
18800 enum {
18801 NM_SYNCIE = 0x00,
18802 NM_PREFE = 0x01,
18805 /* P.LLE instruction pool */
18806 enum {
18807 NM_LLE = 0x00,
18808 NM_LLWPE = 0x01,
18811 /* P.SCE instruction pool */
18812 enum {
18813 NM_SCE = 0x00,
18814 NM_SCWPE = 0x01,
18817 /* P.LS.WM instruction pool */
18818 enum {
18819 NM_LWM = 0x00,
18820 NM_SWM = 0x01,
18823 /* P.LS.UAWM instruction pool */
18824 enum {
18825 NM_UALWM = 0x00,
18826 NM_UASWM = 0x01,
18829 /* P.BR3A instruction pool */
18830 enum {
18831 NM_BC1EQZC = 0x00,
18832 NM_BC1NEZC = 0x01,
18833 NM_BC2EQZC = 0x02,
18834 NM_BC2NEZC = 0x03,
18835 NM_BPOSGE32C = 0x04,
18838 /* P16.RI instruction pool */
18839 enum {
18840 NM_P16_SYSCALL = 0x01,
18841 NM_BREAK16 = 0x02,
18842 NM_SDBBP16 = 0x03,
18845 /* POOL16C_0 instruction pool */
18846 enum {
18847 NM_POOL16C_00 = 0x00,
18850 /* P16.JRC instruction pool */
18851 enum {
18852 NM_JRC = 0x00,
18853 NM_JALRC16 = 0x01,
18856 /* P.SYSCALL instruction pool */
18857 enum {
18858 NM_SYSCALL = 0x00,
18859 NM_HYPCALL = 0x01,
18862 /* P.TRAP instruction pool */
18863 enum {
18864 NM_TEQ = 0x00,
18865 NM_TNE = 0x01,
18868 /* P.CMOVE instruction pool */
18869 enum {
18870 NM_MOVZ = 0x00,
18871 NM_MOVN = 0x01,
18874 /* POOL32Axf instruction pool */
18875 enum {
18876 NM_POOL32AXF_1 = 0x01,
18877 NM_POOL32AXF_2 = 0x02,
18878 NM_POOL32AXF_4 = 0x04,
18879 NM_POOL32AXF_5 = 0x05,
18880 NM_POOL32AXF_7 = 0x07,
18883 /* POOL32Axf_1 instruction pool */
18884 enum {
18885 NM_POOL32AXF_1_0 = 0x00,
18886 NM_POOL32AXF_1_1 = 0x01,
18887 NM_POOL32AXF_1_3 = 0x03,
18888 NM_POOL32AXF_1_4 = 0x04,
18889 NM_POOL32AXF_1_5 = 0x05,
18890 NM_POOL32AXF_1_7 = 0x07,
18893 /* POOL32Axf_2 instruction pool */
18894 enum {
18895 NM_POOL32AXF_2_0_7 = 0x00,
18896 NM_POOL32AXF_2_8_15 = 0x01,
18897 NM_POOL32AXF_2_16_23 = 0x02,
18898 NM_POOL32AXF_2_24_31 = 0x03,
18901 /* POOL32Axf_7 instruction pool */
18902 enum {
18903 NM_SHRA_R_QB = 0x0,
18904 NM_SHRL_PH = 0x1,
18905 NM_REPL_QB = 0x2,
18908 /* POOL32Axf_1_0 instruction pool */
18909 enum {
18910 NM_MFHI = 0x0,
18911 NM_MFLO = 0x1,
18912 NM_MTHI = 0x2,
18913 NM_MTLO = 0x3,
18916 /* POOL32Axf_1_1 instruction pool */
18917 enum {
18918 NM_MTHLIP = 0x0,
18919 NM_SHILOV = 0x1,
18922 /* POOL32Axf_1_3 instruction pool */
18923 enum {
18924 NM_RDDSP = 0x0,
18925 NM_WRDSP = 0x1,
18926 NM_EXTP = 0x2,
18927 NM_EXTPDP = 0x3,
18930 /* POOL32Axf_1_4 instruction pool */
18931 enum {
18932 NM_SHLL_QB = 0x0,
18933 NM_SHRL_QB = 0x1,
18936 /* POOL32Axf_1_5 instruction pool */
18937 enum {
18938 NM_MAQ_S_W_PHR = 0x0,
18939 NM_MAQ_S_W_PHL = 0x1,
18940 NM_MAQ_SA_W_PHR = 0x2,
18941 NM_MAQ_SA_W_PHL = 0x3,
18944 /* POOL32Axf_1_7 instruction pool */
18945 enum {
18946 NM_EXTR_W = 0x0,
18947 NM_EXTR_R_W = 0x1,
18948 NM_EXTR_RS_W = 0x2,
18949 NM_EXTR_S_H = 0x3,
18952 /* POOL32Axf_2_0_7 instruction pool */
18953 enum {
18954 NM_DPA_W_PH = 0x0,
18955 NM_DPAQ_S_W_PH = 0x1,
18956 NM_DPS_W_PH = 0x2,
18957 NM_DPSQ_S_W_PH = 0x3,
18958 NM_BALIGN = 0x4,
18959 NM_MADD = 0x5,
18960 NM_MULT = 0x6,
18961 NM_EXTRV_W = 0x7,
18964 /* POOL32Axf_2_8_15 instruction pool */
18965 enum {
18966 NM_DPAX_W_PH = 0x0,
18967 NM_DPAQ_SA_L_W = 0x1,
18968 NM_DPSX_W_PH = 0x2,
18969 NM_DPSQ_SA_L_W = 0x3,
18970 NM_MADDU = 0x5,
18971 NM_MULTU = 0x6,
18972 NM_EXTRV_R_W = 0x7,
18975 /* POOL32Axf_2_16_23 instruction pool */
18976 enum {
18977 NM_DPAU_H_QBL = 0x0,
18978 NM_DPAQX_S_W_PH = 0x1,
18979 NM_DPSU_H_QBL = 0x2,
18980 NM_DPSQX_S_W_PH = 0x3,
18981 NM_EXTPV = 0x4,
18982 NM_MSUB = 0x5,
18983 NM_MULSA_W_PH = 0x6,
18984 NM_EXTRV_RS_W = 0x7,
18987 /* POOL32Axf_2_24_31 instruction pool */
18988 enum {
18989 NM_DPAU_H_QBR = 0x0,
18990 NM_DPAQX_SA_W_PH = 0x1,
18991 NM_DPSU_H_QBR = 0x2,
18992 NM_DPSQX_SA_W_PH = 0x3,
18993 NM_EXTPDPV = 0x4,
18994 NM_MSUBU = 0x5,
18995 NM_MULSAQ_S_W_PH = 0x6,
18996 NM_EXTRV_S_H = 0x7,
18999 /* POOL32Axf_{4, 5} instruction pool */
19000 enum {
19001 NM_CLO = 0x25,
19002 NM_CLZ = 0x2d,
19004 NM_TLBP = 0x01,
19005 NM_TLBR = 0x09,
19006 NM_TLBWI = 0x11,
19007 NM_TLBWR = 0x19,
19008 NM_TLBINV = 0x03,
19009 NM_TLBINVF = 0x0b,
19010 NM_DI = 0x23,
19011 NM_EI = 0x2b,
19012 NM_RDPGPR = 0x70,
19013 NM_WRPGPR = 0x78,
19014 NM_WAIT = 0x61,
19015 NM_DERET = 0x71,
19016 NM_ERETX = 0x79,
19018 /* nanoMIPS DSP instructions */
19019 NM_ABSQ_S_QB = 0x00,
19020 NM_ABSQ_S_PH = 0x08,
19021 NM_ABSQ_S_W = 0x10,
19022 NM_PRECEQ_W_PHL = 0x28,
19023 NM_PRECEQ_W_PHR = 0x30,
19024 NM_PRECEQU_PH_QBL = 0x38,
19025 NM_PRECEQU_PH_QBR = 0x48,
19026 NM_PRECEU_PH_QBL = 0x58,
19027 NM_PRECEU_PH_QBR = 0x68,
19028 NM_PRECEQU_PH_QBLA = 0x39,
19029 NM_PRECEQU_PH_QBRA = 0x49,
19030 NM_PRECEU_PH_QBLA = 0x59,
19031 NM_PRECEU_PH_QBRA = 0x69,
19032 NM_REPLV_PH = 0x01,
19033 NM_REPLV_QB = 0x09,
19034 NM_BITREV = 0x18,
19035 NM_INSV = 0x20,
19036 NM_RADDU_W_QB = 0x78,
19038 NM_BITSWAP = 0x05,
19039 NM_WSBH = 0x3d,
19042 /* PP.SR instruction pool */
19043 enum {
19044 NM_SAVE = 0x00,
19045 NM_RESTORE = 0x02,
19046 NM_RESTORE_JRC = 0x03,
19049 /* P.SR.F instruction pool */
19050 enum {
19051 NM_SAVEF = 0x00,
19052 NM_RESTOREF = 0x01,
19055 /* P16.SYSCALL instruction pool */
19056 enum {
19057 NM_SYSCALL16 = 0x00,
19058 NM_HYPCALL16 = 0x01,
19061 /* POOL16C_00 instruction pool */
19062 enum {
19063 NM_NOT16 = 0x00,
19064 NM_XOR16 = 0x01,
19065 NM_AND16 = 0x02,
19066 NM_OR16 = 0x03,
19069 /* PP.LSX and PP.LSXS instruction pool */
19070 enum {
19071 NM_LBX = 0x00,
19072 NM_LHX = 0x04,
19073 NM_LWX = 0x08,
19074 NM_LDX = 0x0c,
19076 NM_SBX = 0x01,
19077 NM_SHX = 0x05,
19078 NM_SWX = 0x09,
19079 NM_SDX = 0x0d,
19081 NM_LBUX = 0x02,
19082 NM_LHUX = 0x06,
19083 NM_LWC1X = 0x0a,
19084 NM_LDC1X = 0x0e,
19086 NM_LWUX = 0x07,
19087 NM_SWC1X = 0x0b,
19088 NM_SDC1X = 0x0f,
19090 NM_LHXS = 0x04,
19091 NM_LWXS = 0x08,
19092 NM_LDXS = 0x0c,
19094 NM_SHXS = 0x05,
19095 NM_SWXS = 0x09,
19096 NM_SDXS = 0x0d,
19098 NM_LHUXS = 0x06,
19099 NM_LWC1XS = 0x0a,
19100 NM_LDC1XS = 0x0e,
19102 NM_LWUXS = 0x07,
19103 NM_SWC1XS = 0x0b,
19104 NM_SDC1XS = 0x0f,
19107 /* ERETx instruction pool */
19108 enum {
19109 NM_ERET = 0x00,
19110 NM_ERETNC = 0x01,
19113 /* POOL32FxF_{0, 1} insturction pool */
19114 enum {
19115 NM_CFC1 = 0x40,
19116 NM_CTC1 = 0x60,
19117 NM_MFC1 = 0x80,
19118 NM_MTC1 = 0xa0,
19119 NM_MFHC1 = 0xc0,
19120 NM_MTHC1 = 0xe0,
19122 NM_CVT_S_PL = 0x84,
19123 NM_CVT_S_PU = 0xa4,
19125 NM_CVT_L_S = 0x004,
19126 NM_CVT_L_D = 0x104,
19127 NM_CVT_W_S = 0x024,
19128 NM_CVT_W_D = 0x124,
19130 NM_RSQRT_S = 0x008,
19131 NM_RSQRT_D = 0x108,
19133 NM_SQRT_S = 0x028,
19134 NM_SQRT_D = 0x128,
19136 NM_RECIP_S = 0x048,
19137 NM_RECIP_D = 0x148,
19139 NM_FLOOR_L_S = 0x00c,
19140 NM_FLOOR_L_D = 0x10c,
19142 NM_FLOOR_W_S = 0x02c,
19143 NM_FLOOR_W_D = 0x12c,
19145 NM_CEIL_L_S = 0x04c,
19146 NM_CEIL_L_D = 0x14c,
19147 NM_CEIL_W_S = 0x06c,
19148 NM_CEIL_W_D = 0x16c,
19149 NM_TRUNC_L_S = 0x08c,
19150 NM_TRUNC_L_D = 0x18c,
19151 NM_TRUNC_W_S = 0x0ac,
19152 NM_TRUNC_W_D = 0x1ac,
19153 NM_ROUND_L_S = 0x0cc,
19154 NM_ROUND_L_D = 0x1cc,
19155 NM_ROUND_W_S = 0x0ec,
19156 NM_ROUND_W_D = 0x1ec,
19158 NM_MOV_S = 0x01,
19159 NM_MOV_D = 0x81,
19160 NM_ABS_S = 0x0d,
19161 NM_ABS_D = 0x8d,
19162 NM_NEG_S = 0x2d,
19163 NM_NEG_D = 0xad,
19164 NM_CVT_D_S = 0x04d,
19165 NM_CVT_D_W = 0x0cd,
19166 NM_CVT_D_L = 0x14d,
19167 NM_CVT_S_D = 0x06d,
19168 NM_CVT_S_W = 0x0ed,
19169 NM_CVT_S_L = 0x16d,
19172 /* P.LL instruction pool */
19173 enum {
19174 NM_LL = 0x00,
19175 NM_LLWP = 0x01,
19178 /* P.SC instruction pool */
19179 enum {
19180 NM_SC = 0x00,
19181 NM_SCWP = 0x01,
19184 /* P.DVP instruction pool */
19185 enum {
19186 NM_DVP = 0x00,
19187 NM_EVP = 0x01,
19193 * nanoMIPS decoding engine
19198 /* extraction utilities */
19200 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
19201 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
19202 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
19203 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
19204 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
19206 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
19207 static inline int decode_gpr_gpr3(int r)
19209 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
19211 return map[r & 0x7];
19214 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
19215 static inline int decode_gpr_gpr3_src_store(int r)
19217 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
19219 return map[r & 0x7];
19222 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
19223 static inline int decode_gpr_gpr4(int r)
19225 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
19226 16, 17, 18, 19, 20, 21, 22, 23 };
19228 return map[r & 0xf];
19231 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
19232 static inline int decode_gpr_gpr4_zero(int r)
19234 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
19235 16, 17, 18, 19, 20, 21, 22, 23 };
19237 return map[r & 0xf];
19241 static void gen_adjust_sp(DisasContext *ctx, int u)
19243 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
19246 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
19247 uint8_t gp, uint16_t u)
19249 int counter = 0;
19250 TCGv va = tcg_temp_new();
19251 TCGv t0 = tcg_temp_new();
19253 while (counter != count) {
19254 bool use_gp = gp && (counter == count - 1);
19255 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19256 int this_offset = -((counter + 1) << 2);
19257 gen_base_offset_addr(ctx, va, 29, this_offset);
19258 gen_load_gpr(t0, this_rt);
19259 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
19260 (MO_TEUL | ctx->default_tcg_memop_mask));
19261 counter++;
19264 /* adjust stack pointer */
19265 gen_adjust_sp(ctx, -u);
19267 tcg_temp_free(t0);
19268 tcg_temp_free(va);
19271 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
19272 uint8_t gp, uint16_t u)
19274 int counter = 0;
19275 TCGv va = tcg_temp_new();
19276 TCGv t0 = tcg_temp_new();
19278 while (counter != count) {
19279 bool use_gp = gp && (counter == count - 1);
19280 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19281 int this_offset = u - ((counter + 1) << 2);
19282 gen_base_offset_addr(ctx, va, 29, this_offset);
19283 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
19284 ctx->default_tcg_memop_mask);
19285 tcg_gen_ext32s_tl(t0, t0);
19286 gen_store_gpr(t0, this_rt);
19287 counter++;
19290 /* adjust stack pointer */
19291 gen_adjust_sp(ctx, u);
19293 tcg_temp_free(t0);
19294 tcg_temp_free(va);
19297 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
19299 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
19300 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
19302 switch (extract32(ctx->opcode, 2, 2)) {
19303 case NM_NOT16:
19304 gen_logic(ctx, OPC_NOR, rt, rs, 0);
19305 break;
19306 case NM_AND16:
19307 gen_logic(ctx, OPC_AND, rt, rt, rs);
19308 break;
19309 case NM_XOR16:
19310 gen_logic(ctx, OPC_XOR, rt, rt, rs);
19311 break;
19312 case NM_OR16:
19313 gen_logic(ctx, OPC_OR, rt, rt, rs);
19314 break;
19318 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19320 int rt = extract32(ctx->opcode, 21, 5);
19321 int rs = extract32(ctx->opcode, 16, 5);
19322 int rd = extract32(ctx->opcode, 11, 5);
19324 switch (extract32(ctx->opcode, 3, 7)) {
19325 case NM_P_TRAP:
19326 switch (extract32(ctx->opcode, 10, 1)) {
19327 case NM_TEQ:
19328 check_nms(ctx);
19329 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
19330 break;
19331 case NM_TNE:
19332 check_nms(ctx);
19333 gen_trap(ctx, OPC_TNE, rs, rt, -1);
19334 break;
19336 break;
19337 case NM_RDHWR:
19338 check_nms(ctx);
19339 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
19340 break;
19341 case NM_SEB:
19342 check_nms(ctx);
19343 gen_bshfl(ctx, OPC_SEB, rs, rt);
19344 break;
19345 case NM_SEH:
19346 gen_bshfl(ctx, OPC_SEH, rs, rt);
19347 break;
19348 case NM_SLLV:
19349 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
19350 break;
19351 case NM_SRLV:
19352 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19353 break;
19354 case NM_SRAV:
19355 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19356 break;
19357 case NM_ROTRV:
19358 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19359 break;
19360 case NM_ADD:
19361 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19362 break;
19363 case NM_ADDU:
19364 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19365 break;
19366 case NM_SUB:
19367 check_nms(ctx);
19368 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19369 break;
19370 case NM_SUBU:
19371 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19372 break;
19373 case NM_P_CMOVE:
19374 switch (extract32(ctx->opcode, 10, 1)) {
19375 case NM_MOVZ:
19376 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19377 break;
19378 case NM_MOVN:
19379 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19380 break;
19382 break;
19383 case NM_AND:
19384 gen_logic(ctx, OPC_AND, rd, rs, rt);
19385 break;
19386 case NM_OR:
19387 gen_logic(ctx, OPC_OR, rd, rs, rt);
19388 break;
19389 case NM_NOR:
19390 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19391 break;
19392 case NM_XOR:
19393 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19394 break;
19395 case NM_SLT:
19396 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19397 break;
19398 case NM_P_SLTU:
19399 if (rd == 0) {
19400 /* P_DVP */
19401 #ifndef CONFIG_USER_ONLY
19402 TCGv t0 = tcg_temp_new();
19403 switch (extract32(ctx->opcode, 10, 1)) {
19404 case NM_DVP:
19405 if (ctx->vp) {
19406 check_cp0_enabled(ctx);
19407 gen_helper_dvp(t0, cpu_env);
19408 gen_store_gpr(t0, rt);
19410 break;
19411 case NM_EVP:
19412 if (ctx->vp) {
19413 check_cp0_enabled(ctx);
19414 gen_helper_evp(t0, cpu_env);
19415 gen_store_gpr(t0, rt);
19417 break;
19419 tcg_temp_free(t0);
19420 #endif
19421 } else {
19422 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19424 break;
19425 case NM_SOV:
19427 TCGv t0 = tcg_temp_new();
19428 TCGv t1 = tcg_temp_new();
19429 TCGv t2 = tcg_temp_new();
19431 gen_load_gpr(t1, rs);
19432 gen_load_gpr(t2, rt);
19433 tcg_gen_add_tl(t0, t1, t2);
19434 tcg_gen_ext32s_tl(t0, t0);
19435 tcg_gen_xor_tl(t1, t1, t2);
19436 tcg_gen_xor_tl(t2, t0, t2);
19437 tcg_gen_andc_tl(t1, t2, t1);
19439 /* operands of same sign, result different sign */
19440 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19441 gen_store_gpr(t0, rd);
19443 tcg_temp_free(t0);
19444 tcg_temp_free(t1);
19445 tcg_temp_free(t2);
19447 break;
19448 case NM_MUL:
19449 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19450 break;
19451 case NM_MUH:
19452 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19453 break;
19454 case NM_MULU:
19455 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19456 break;
19457 case NM_MUHU:
19458 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19459 break;
19460 case NM_DIV:
19461 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19462 break;
19463 case NM_MOD:
19464 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19465 break;
19466 case NM_DIVU:
19467 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19468 break;
19469 case NM_MODU:
19470 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19471 break;
19472 #ifndef CONFIG_USER_ONLY
19473 case NM_MFC0:
19474 check_cp0_enabled(ctx);
19475 if (rt == 0) {
19476 /* Treat as NOP. */
19477 break;
19479 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19480 break;
19481 case NM_MTC0:
19482 check_cp0_enabled(ctx);
19484 TCGv t0 = tcg_temp_new();
19486 gen_load_gpr(t0, rt);
19487 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19488 tcg_temp_free(t0);
19490 break;
19491 case NM_D_E_MT_VPE:
19493 uint8_t sc = extract32(ctx->opcode, 10, 1);
19494 TCGv t0 = tcg_temp_new();
19496 switch (sc) {
19497 case 0:
19498 if (rs == 1) {
19499 /* DMT */
19500 check_cp0_mt(ctx);
19501 gen_helper_dmt(t0);
19502 gen_store_gpr(t0, rt);
19503 } else if (rs == 0) {
19504 /* DVPE */
19505 check_cp0_mt(ctx);
19506 gen_helper_dvpe(t0, cpu_env);
19507 gen_store_gpr(t0, rt);
19508 } else {
19509 gen_reserved_instruction(ctx);
19511 break;
19512 case 1:
19513 if (rs == 1) {
19514 /* EMT */
19515 check_cp0_mt(ctx);
19516 gen_helper_emt(t0);
19517 gen_store_gpr(t0, rt);
19518 } else if (rs == 0) {
19519 /* EVPE */
19520 check_cp0_mt(ctx);
19521 gen_helper_evpe(t0, cpu_env);
19522 gen_store_gpr(t0, rt);
19523 } else {
19524 gen_reserved_instruction(ctx);
19526 break;
19529 tcg_temp_free(t0);
19531 break;
19532 case NM_FORK:
19533 check_mt(ctx);
19535 TCGv t0 = tcg_temp_new();
19536 TCGv t1 = tcg_temp_new();
19538 gen_load_gpr(t0, rt);
19539 gen_load_gpr(t1, rs);
19540 gen_helper_fork(t0, t1);
19541 tcg_temp_free(t0);
19542 tcg_temp_free(t1);
19544 break;
19545 case NM_MFTR:
19546 case NM_MFHTR:
19547 check_cp0_enabled(ctx);
19548 if (rd == 0) {
19549 /* Treat as NOP. */
19550 return;
19552 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19553 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19554 break;
19555 case NM_MTTR:
19556 case NM_MTHTR:
19557 check_cp0_enabled(ctx);
19558 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19559 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19560 break;
19561 case NM_YIELD:
19562 check_mt(ctx);
19564 TCGv t0 = tcg_temp_new();
19566 gen_load_gpr(t0, rs);
19567 gen_helper_yield(t0, cpu_env, t0);
19568 gen_store_gpr(t0, rt);
19569 tcg_temp_free(t0);
19571 break;
19572 #endif
19573 default:
19574 gen_reserved_instruction(ctx);
19575 break;
19579 /* dsp */
19580 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19581 int ret, int v1, int v2)
19583 TCGv_i32 t0;
19584 TCGv v0_t;
19585 TCGv v1_t;
19587 t0 = tcg_temp_new_i32();
19589 v0_t = tcg_temp_new();
19590 v1_t = tcg_temp_new();
19592 tcg_gen_movi_i32(t0, v2 >> 3);
19594 gen_load_gpr(v0_t, ret);
19595 gen_load_gpr(v1_t, v1);
19597 switch (opc) {
19598 case NM_MAQ_S_W_PHR:
19599 check_dsp(ctx);
19600 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19601 break;
19602 case NM_MAQ_S_W_PHL:
19603 check_dsp(ctx);
19604 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19605 break;
19606 case NM_MAQ_SA_W_PHR:
19607 check_dsp(ctx);
19608 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19609 break;
19610 case NM_MAQ_SA_W_PHL:
19611 check_dsp(ctx);
19612 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19613 break;
19614 default:
19615 gen_reserved_instruction(ctx);
19616 break;
19619 tcg_temp_free_i32(t0);
19621 tcg_temp_free(v0_t);
19622 tcg_temp_free(v1_t);
19626 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19627 int ret, int v1, int v2)
19629 int16_t imm;
19630 TCGv t0 = tcg_temp_new();
19631 TCGv t1 = tcg_temp_new();
19632 TCGv v0_t = tcg_temp_new();
19634 gen_load_gpr(v0_t, v1);
19636 switch (opc) {
19637 case NM_POOL32AXF_1_0:
19638 check_dsp(ctx);
19639 switch (extract32(ctx->opcode, 12, 2)) {
19640 case NM_MFHI:
19641 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19642 break;
19643 case NM_MFLO:
19644 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19645 break;
19646 case NM_MTHI:
19647 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19648 break;
19649 case NM_MTLO:
19650 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19651 break;
19653 break;
19654 case NM_POOL32AXF_1_1:
19655 check_dsp(ctx);
19656 switch (extract32(ctx->opcode, 12, 2)) {
19657 case NM_MTHLIP:
19658 tcg_gen_movi_tl(t0, v2);
19659 gen_helper_mthlip(t0, v0_t, cpu_env);
19660 break;
19661 case NM_SHILOV:
19662 tcg_gen_movi_tl(t0, v2 >> 3);
19663 gen_helper_shilo(t0, v0_t, cpu_env);
19664 break;
19665 default:
19666 gen_reserved_instruction(ctx);
19667 break;
19669 break;
19670 case NM_POOL32AXF_1_3:
19671 check_dsp(ctx);
19672 imm = extract32(ctx->opcode, 14, 7);
19673 switch (extract32(ctx->opcode, 12, 2)) {
19674 case NM_RDDSP:
19675 tcg_gen_movi_tl(t0, imm);
19676 gen_helper_rddsp(t0, t0, cpu_env);
19677 gen_store_gpr(t0, ret);
19678 break;
19679 case NM_WRDSP:
19680 gen_load_gpr(t0, ret);
19681 tcg_gen_movi_tl(t1, imm);
19682 gen_helper_wrdsp(t0, t1, cpu_env);
19683 break;
19684 case NM_EXTP:
19685 tcg_gen_movi_tl(t0, v2 >> 3);
19686 tcg_gen_movi_tl(t1, v1);
19687 gen_helper_extp(t0, t0, t1, cpu_env);
19688 gen_store_gpr(t0, ret);
19689 break;
19690 case NM_EXTPDP:
19691 tcg_gen_movi_tl(t0, v2 >> 3);
19692 tcg_gen_movi_tl(t1, v1);
19693 gen_helper_extpdp(t0, t0, t1, cpu_env);
19694 gen_store_gpr(t0, ret);
19695 break;
19697 break;
19698 case NM_POOL32AXF_1_4:
19699 check_dsp(ctx);
19700 tcg_gen_movi_tl(t0, v2 >> 2);
19701 switch (extract32(ctx->opcode, 12, 1)) {
19702 case NM_SHLL_QB:
19703 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19704 gen_store_gpr(t0, ret);
19705 break;
19706 case NM_SHRL_QB:
19707 gen_helper_shrl_qb(t0, t0, v0_t);
19708 gen_store_gpr(t0, ret);
19709 break;
19711 break;
19712 case NM_POOL32AXF_1_5:
19713 opc = extract32(ctx->opcode, 12, 2);
19714 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19715 break;
19716 case NM_POOL32AXF_1_7:
19717 check_dsp(ctx);
19718 tcg_gen_movi_tl(t0, v2 >> 3);
19719 tcg_gen_movi_tl(t1, v1);
19720 switch (extract32(ctx->opcode, 12, 2)) {
19721 case NM_EXTR_W:
19722 gen_helper_extr_w(t0, t0, t1, cpu_env);
19723 gen_store_gpr(t0, ret);
19724 break;
19725 case NM_EXTR_R_W:
19726 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19727 gen_store_gpr(t0, ret);
19728 break;
19729 case NM_EXTR_RS_W:
19730 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19731 gen_store_gpr(t0, ret);
19732 break;
19733 case NM_EXTR_S_H:
19734 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19735 gen_store_gpr(t0, ret);
19736 break;
19738 break;
19739 default:
19740 gen_reserved_instruction(ctx);
19741 break;
19744 tcg_temp_free(t0);
19745 tcg_temp_free(t1);
19746 tcg_temp_free(v0_t);
19749 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19750 TCGv v0, TCGv v1, int rd)
19752 TCGv_i32 t0;
19754 t0 = tcg_temp_new_i32();
19756 tcg_gen_movi_i32(t0, rd >> 3);
19758 switch (opc) {
19759 case NM_POOL32AXF_2_0_7:
19760 switch (extract32(ctx->opcode, 9, 3)) {
19761 case NM_DPA_W_PH:
19762 check_dsp_r2(ctx);
19763 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19764 break;
19765 case NM_DPAQ_S_W_PH:
19766 check_dsp(ctx);
19767 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19768 break;
19769 case NM_DPS_W_PH:
19770 check_dsp_r2(ctx);
19771 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19772 break;
19773 case NM_DPSQ_S_W_PH:
19774 check_dsp(ctx);
19775 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19776 break;
19777 default:
19778 gen_reserved_instruction(ctx);
19779 break;
19781 break;
19782 case NM_POOL32AXF_2_8_15:
19783 switch (extract32(ctx->opcode, 9, 3)) {
19784 case NM_DPAX_W_PH:
19785 check_dsp_r2(ctx);
19786 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19787 break;
19788 case NM_DPAQ_SA_L_W:
19789 check_dsp(ctx);
19790 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19791 break;
19792 case NM_DPSX_W_PH:
19793 check_dsp_r2(ctx);
19794 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19795 break;
19796 case NM_DPSQ_SA_L_W:
19797 check_dsp(ctx);
19798 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19799 break;
19800 default:
19801 gen_reserved_instruction(ctx);
19802 break;
19804 break;
19805 case NM_POOL32AXF_2_16_23:
19806 switch (extract32(ctx->opcode, 9, 3)) {
19807 case NM_DPAU_H_QBL:
19808 check_dsp(ctx);
19809 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19810 break;
19811 case NM_DPAQX_S_W_PH:
19812 check_dsp_r2(ctx);
19813 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19814 break;
19815 case NM_DPSU_H_QBL:
19816 check_dsp(ctx);
19817 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19818 break;
19819 case NM_DPSQX_S_W_PH:
19820 check_dsp_r2(ctx);
19821 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19822 break;
19823 case NM_MULSA_W_PH:
19824 check_dsp_r2(ctx);
19825 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19826 break;
19827 default:
19828 gen_reserved_instruction(ctx);
19829 break;
19831 break;
19832 case NM_POOL32AXF_2_24_31:
19833 switch (extract32(ctx->opcode, 9, 3)) {
19834 case NM_DPAU_H_QBR:
19835 check_dsp(ctx);
19836 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19837 break;
19838 case NM_DPAQX_SA_W_PH:
19839 check_dsp_r2(ctx);
19840 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19841 break;
19842 case NM_DPSU_H_QBR:
19843 check_dsp(ctx);
19844 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19845 break;
19846 case NM_DPSQX_SA_W_PH:
19847 check_dsp_r2(ctx);
19848 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19849 break;
19850 case NM_MULSAQ_S_W_PH:
19851 check_dsp(ctx);
19852 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19853 break;
19854 default:
19855 gen_reserved_instruction(ctx);
19856 break;
19858 break;
19859 default:
19860 gen_reserved_instruction(ctx);
19861 break;
19864 tcg_temp_free_i32(t0);
19867 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19868 int rt, int rs, int rd)
19870 int ret = rt;
19871 TCGv t0 = tcg_temp_new();
19872 TCGv t1 = tcg_temp_new();
19873 TCGv v0_t = tcg_temp_new();
19874 TCGv v1_t = tcg_temp_new();
19876 gen_load_gpr(v0_t, rt);
19877 gen_load_gpr(v1_t, rs);
19879 switch (opc) {
19880 case NM_POOL32AXF_2_0_7:
19881 switch (extract32(ctx->opcode, 9, 3)) {
19882 case NM_DPA_W_PH:
19883 case NM_DPAQ_S_W_PH:
19884 case NM_DPS_W_PH:
19885 case NM_DPSQ_S_W_PH:
19886 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19887 break;
19888 case NM_BALIGN:
19889 check_dsp_r2(ctx);
19890 if (rt != 0) {
19891 gen_load_gpr(t0, rs);
19892 rd &= 3;
19893 if (rd != 0 && rd != 2) {
19894 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19895 tcg_gen_ext32u_tl(t0, t0);
19896 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19897 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19899 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19901 break;
19902 case NM_MADD:
19903 check_dsp(ctx);
19905 int acc = extract32(ctx->opcode, 14, 2);
19906 TCGv_i64 t2 = tcg_temp_new_i64();
19907 TCGv_i64 t3 = tcg_temp_new_i64();
19909 gen_load_gpr(t0, rt);
19910 gen_load_gpr(t1, rs);
19911 tcg_gen_ext_tl_i64(t2, t0);
19912 tcg_gen_ext_tl_i64(t3, t1);
19913 tcg_gen_mul_i64(t2, t2, t3);
19914 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19915 tcg_gen_add_i64(t2, t2, t3);
19916 tcg_temp_free_i64(t3);
19917 gen_move_low32(cpu_LO[acc], t2);
19918 gen_move_high32(cpu_HI[acc], t2);
19919 tcg_temp_free_i64(t2);
19921 break;
19922 case NM_MULT:
19923 check_dsp(ctx);
19925 int acc = extract32(ctx->opcode, 14, 2);
19926 TCGv_i32 t2 = tcg_temp_new_i32();
19927 TCGv_i32 t3 = tcg_temp_new_i32();
19929 gen_load_gpr(t0, rs);
19930 gen_load_gpr(t1, rt);
19931 tcg_gen_trunc_tl_i32(t2, t0);
19932 tcg_gen_trunc_tl_i32(t3, t1);
19933 tcg_gen_muls2_i32(t2, t3, t2, t3);
19934 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19935 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19936 tcg_temp_free_i32(t2);
19937 tcg_temp_free_i32(t3);
19939 break;
19940 case NM_EXTRV_W:
19941 check_dsp(ctx);
19942 gen_load_gpr(v1_t, rs);
19943 tcg_gen_movi_tl(t0, rd >> 3);
19944 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19945 gen_store_gpr(t0, ret);
19946 break;
19948 break;
19949 case NM_POOL32AXF_2_8_15:
19950 switch (extract32(ctx->opcode, 9, 3)) {
19951 case NM_DPAX_W_PH:
19952 case NM_DPAQ_SA_L_W:
19953 case NM_DPSX_W_PH:
19954 case NM_DPSQ_SA_L_W:
19955 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19956 break;
19957 case NM_MADDU:
19958 check_dsp(ctx);
19960 int acc = extract32(ctx->opcode, 14, 2);
19961 TCGv_i64 t2 = tcg_temp_new_i64();
19962 TCGv_i64 t3 = tcg_temp_new_i64();
19964 gen_load_gpr(t0, rs);
19965 gen_load_gpr(t1, rt);
19966 tcg_gen_ext32u_tl(t0, t0);
19967 tcg_gen_ext32u_tl(t1, t1);
19968 tcg_gen_extu_tl_i64(t2, t0);
19969 tcg_gen_extu_tl_i64(t3, t1);
19970 tcg_gen_mul_i64(t2, t2, t3);
19971 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19972 tcg_gen_add_i64(t2, t2, t3);
19973 tcg_temp_free_i64(t3);
19974 gen_move_low32(cpu_LO[acc], t2);
19975 gen_move_high32(cpu_HI[acc], t2);
19976 tcg_temp_free_i64(t2);
19978 break;
19979 case NM_MULTU:
19980 check_dsp(ctx);
19982 int acc = extract32(ctx->opcode, 14, 2);
19983 TCGv_i32 t2 = tcg_temp_new_i32();
19984 TCGv_i32 t3 = tcg_temp_new_i32();
19986 gen_load_gpr(t0, rs);
19987 gen_load_gpr(t1, rt);
19988 tcg_gen_trunc_tl_i32(t2, t0);
19989 tcg_gen_trunc_tl_i32(t3, t1);
19990 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19991 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19992 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19993 tcg_temp_free_i32(t2);
19994 tcg_temp_free_i32(t3);
19996 break;
19997 case NM_EXTRV_R_W:
19998 check_dsp(ctx);
19999 tcg_gen_movi_tl(t0, rd >> 3);
20000 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
20001 gen_store_gpr(t0, ret);
20002 break;
20003 default:
20004 gen_reserved_instruction(ctx);
20005 break;
20007 break;
20008 case NM_POOL32AXF_2_16_23:
20009 switch (extract32(ctx->opcode, 9, 3)) {
20010 case NM_DPAU_H_QBL:
20011 case NM_DPAQX_S_W_PH:
20012 case NM_DPSU_H_QBL:
20013 case NM_DPSQX_S_W_PH:
20014 case NM_MULSA_W_PH:
20015 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20016 break;
20017 case NM_EXTPV:
20018 check_dsp(ctx);
20019 tcg_gen_movi_tl(t0, rd >> 3);
20020 gen_helper_extp(t0, t0, v1_t, cpu_env);
20021 gen_store_gpr(t0, ret);
20022 break;
20023 case NM_MSUB:
20024 check_dsp(ctx);
20026 int acc = extract32(ctx->opcode, 14, 2);
20027 TCGv_i64 t2 = tcg_temp_new_i64();
20028 TCGv_i64 t3 = tcg_temp_new_i64();
20030 gen_load_gpr(t0, rs);
20031 gen_load_gpr(t1, rt);
20032 tcg_gen_ext_tl_i64(t2, t0);
20033 tcg_gen_ext_tl_i64(t3, t1);
20034 tcg_gen_mul_i64(t2, t2, t3);
20035 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20036 tcg_gen_sub_i64(t2, t3, t2);
20037 tcg_temp_free_i64(t3);
20038 gen_move_low32(cpu_LO[acc], t2);
20039 gen_move_high32(cpu_HI[acc], t2);
20040 tcg_temp_free_i64(t2);
20042 break;
20043 case NM_EXTRV_RS_W:
20044 check_dsp(ctx);
20045 tcg_gen_movi_tl(t0, rd >> 3);
20046 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
20047 gen_store_gpr(t0, ret);
20048 break;
20050 break;
20051 case NM_POOL32AXF_2_24_31:
20052 switch (extract32(ctx->opcode, 9, 3)) {
20053 case NM_DPAU_H_QBR:
20054 case NM_DPAQX_SA_W_PH:
20055 case NM_DPSU_H_QBR:
20056 case NM_DPSQX_SA_W_PH:
20057 case NM_MULSAQ_S_W_PH:
20058 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20059 break;
20060 case NM_EXTPDPV:
20061 check_dsp(ctx);
20062 tcg_gen_movi_tl(t0, rd >> 3);
20063 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
20064 gen_store_gpr(t0, ret);
20065 break;
20066 case NM_MSUBU:
20067 check_dsp(ctx);
20069 int acc = extract32(ctx->opcode, 14, 2);
20070 TCGv_i64 t2 = tcg_temp_new_i64();
20071 TCGv_i64 t3 = tcg_temp_new_i64();
20073 gen_load_gpr(t0, rs);
20074 gen_load_gpr(t1, rt);
20075 tcg_gen_ext32u_tl(t0, t0);
20076 tcg_gen_ext32u_tl(t1, t1);
20077 tcg_gen_extu_tl_i64(t2, t0);
20078 tcg_gen_extu_tl_i64(t3, t1);
20079 tcg_gen_mul_i64(t2, t2, t3);
20080 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20081 tcg_gen_sub_i64(t2, t3, t2);
20082 tcg_temp_free_i64(t3);
20083 gen_move_low32(cpu_LO[acc], t2);
20084 gen_move_high32(cpu_HI[acc], t2);
20085 tcg_temp_free_i64(t2);
20087 break;
20088 case NM_EXTRV_S_H:
20089 check_dsp(ctx);
20090 tcg_gen_movi_tl(t0, rd >> 3);
20091 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
20092 gen_store_gpr(t0, ret);
20093 break;
20095 break;
20096 default:
20097 gen_reserved_instruction(ctx);
20098 break;
20101 tcg_temp_free(t0);
20102 tcg_temp_free(t1);
20104 tcg_temp_free(v0_t);
20105 tcg_temp_free(v1_t);
20108 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
20109 int rt, int rs)
20111 int ret = rt;
20112 TCGv t0 = tcg_temp_new();
20113 TCGv v0_t = tcg_temp_new();
20115 gen_load_gpr(v0_t, rs);
20117 switch (opc) {
20118 case NM_ABSQ_S_QB:
20119 check_dsp_r2(ctx);
20120 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
20121 gen_store_gpr(v0_t, ret);
20122 break;
20123 case NM_ABSQ_S_PH:
20124 check_dsp(ctx);
20125 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
20126 gen_store_gpr(v0_t, ret);
20127 break;
20128 case NM_ABSQ_S_W:
20129 check_dsp(ctx);
20130 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
20131 gen_store_gpr(v0_t, ret);
20132 break;
20133 case NM_PRECEQ_W_PHL:
20134 check_dsp(ctx);
20135 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
20136 tcg_gen_ext32s_tl(v0_t, v0_t);
20137 gen_store_gpr(v0_t, ret);
20138 break;
20139 case NM_PRECEQ_W_PHR:
20140 check_dsp(ctx);
20141 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
20142 tcg_gen_shli_tl(v0_t, v0_t, 16);
20143 tcg_gen_ext32s_tl(v0_t, v0_t);
20144 gen_store_gpr(v0_t, ret);
20145 break;
20146 case NM_PRECEQU_PH_QBL:
20147 check_dsp(ctx);
20148 gen_helper_precequ_ph_qbl(v0_t, v0_t);
20149 gen_store_gpr(v0_t, ret);
20150 break;
20151 case NM_PRECEQU_PH_QBR:
20152 check_dsp(ctx);
20153 gen_helper_precequ_ph_qbr(v0_t, v0_t);
20154 gen_store_gpr(v0_t, ret);
20155 break;
20156 case NM_PRECEQU_PH_QBLA:
20157 check_dsp(ctx);
20158 gen_helper_precequ_ph_qbla(v0_t, v0_t);
20159 gen_store_gpr(v0_t, ret);
20160 break;
20161 case NM_PRECEQU_PH_QBRA:
20162 check_dsp(ctx);
20163 gen_helper_precequ_ph_qbra(v0_t, v0_t);
20164 gen_store_gpr(v0_t, ret);
20165 break;
20166 case NM_PRECEU_PH_QBL:
20167 check_dsp(ctx);
20168 gen_helper_preceu_ph_qbl(v0_t, v0_t);
20169 gen_store_gpr(v0_t, ret);
20170 break;
20171 case NM_PRECEU_PH_QBR:
20172 check_dsp(ctx);
20173 gen_helper_preceu_ph_qbr(v0_t, v0_t);
20174 gen_store_gpr(v0_t, ret);
20175 break;
20176 case NM_PRECEU_PH_QBLA:
20177 check_dsp(ctx);
20178 gen_helper_preceu_ph_qbla(v0_t, v0_t);
20179 gen_store_gpr(v0_t, ret);
20180 break;
20181 case NM_PRECEU_PH_QBRA:
20182 check_dsp(ctx);
20183 gen_helper_preceu_ph_qbra(v0_t, v0_t);
20184 gen_store_gpr(v0_t, ret);
20185 break;
20186 case NM_REPLV_PH:
20187 check_dsp(ctx);
20188 tcg_gen_ext16u_tl(v0_t, v0_t);
20189 tcg_gen_shli_tl(t0, v0_t, 16);
20190 tcg_gen_or_tl(v0_t, v0_t, t0);
20191 tcg_gen_ext32s_tl(v0_t, v0_t);
20192 gen_store_gpr(v0_t, ret);
20193 break;
20194 case NM_REPLV_QB:
20195 check_dsp(ctx);
20196 tcg_gen_ext8u_tl(v0_t, v0_t);
20197 tcg_gen_shli_tl(t0, v0_t, 8);
20198 tcg_gen_or_tl(v0_t, v0_t, t0);
20199 tcg_gen_shli_tl(t0, v0_t, 16);
20200 tcg_gen_or_tl(v0_t, v0_t, t0);
20201 tcg_gen_ext32s_tl(v0_t, v0_t);
20202 gen_store_gpr(v0_t, ret);
20203 break;
20204 case NM_BITREV:
20205 check_dsp(ctx);
20206 gen_helper_bitrev(v0_t, v0_t);
20207 gen_store_gpr(v0_t, ret);
20208 break;
20209 case NM_INSV:
20210 check_dsp(ctx);
20212 TCGv tv0 = tcg_temp_new();
20214 gen_load_gpr(tv0, rt);
20215 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
20216 gen_store_gpr(v0_t, ret);
20217 tcg_temp_free(tv0);
20219 break;
20220 case NM_RADDU_W_QB:
20221 check_dsp(ctx);
20222 gen_helper_raddu_w_qb(v0_t, v0_t);
20223 gen_store_gpr(v0_t, ret);
20224 break;
20225 case NM_BITSWAP:
20226 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
20227 break;
20228 case NM_CLO:
20229 check_nms(ctx);
20230 gen_cl(ctx, OPC_CLO, ret, rs);
20231 break;
20232 case NM_CLZ:
20233 check_nms(ctx);
20234 gen_cl(ctx, OPC_CLZ, ret, rs);
20235 break;
20236 case NM_WSBH:
20237 gen_bshfl(ctx, OPC_WSBH, ret, rs);
20238 break;
20239 default:
20240 gen_reserved_instruction(ctx);
20241 break;
20244 tcg_temp_free(v0_t);
20245 tcg_temp_free(t0);
20248 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
20249 int rt, int rs, int rd)
20251 TCGv t0 = tcg_temp_new();
20252 TCGv rs_t = tcg_temp_new();
20254 gen_load_gpr(rs_t, rs);
20256 switch (opc) {
20257 case NM_SHRA_R_QB:
20258 check_dsp_r2(ctx);
20259 tcg_gen_movi_tl(t0, rd >> 2);
20260 switch (extract32(ctx->opcode, 12, 1)) {
20261 case 0:
20262 /* NM_SHRA_QB */
20263 gen_helper_shra_qb(t0, t0, rs_t);
20264 gen_store_gpr(t0, rt);
20265 break;
20266 case 1:
20267 /* NM_SHRA_R_QB */
20268 gen_helper_shra_r_qb(t0, t0, rs_t);
20269 gen_store_gpr(t0, rt);
20270 break;
20272 break;
20273 case NM_SHRL_PH:
20274 check_dsp_r2(ctx);
20275 tcg_gen_movi_tl(t0, rd >> 1);
20276 gen_helper_shrl_ph(t0, t0, rs_t);
20277 gen_store_gpr(t0, rt);
20278 break;
20279 case NM_REPL_QB:
20280 check_dsp(ctx);
20282 int16_t imm;
20283 target_long result;
20284 imm = extract32(ctx->opcode, 13, 8);
20285 result = (uint32_t)imm << 24 |
20286 (uint32_t)imm << 16 |
20287 (uint32_t)imm << 8 |
20288 (uint32_t)imm;
20289 result = (int32_t)result;
20290 tcg_gen_movi_tl(t0, result);
20291 gen_store_gpr(t0, rt);
20293 break;
20294 default:
20295 gen_reserved_instruction(ctx);
20296 break;
20298 tcg_temp_free(t0);
20299 tcg_temp_free(rs_t);
20303 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
20305 int rt = extract32(ctx->opcode, 21, 5);
20306 int rs = extract32(ctx->opcode, 16, 5);
20307 int rd = extract32(ctx->opcode, 11, 5);
20309 switch (extract32(ctx->opcode, 6, 3)) {
20310 case NM_POOL32AXF_1:
20312 int32_t op1 = extract32(ctx->opcode, 9, 3);
20313 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
20315 break;
20316 case NM_POOL32AXF_2:
20318 int32_t op1 = extract32(ctx->opcode, 12, 2);
20319 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
20321 break;
20322 case NM_POOL32AXF_4:
20324 int32_t op1 = extract32(ctx->opcode, 9, 7);
20325 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
20327 break;
20328 case NM_POOL32AXF_5:
20329 switch (extract32(ctx->opcode, 9, 7)) {
20330 #ifndef CONFIG_USER_ONLY
20331 case NM_TLBP:
20332 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
20333 break;
20334 case NM_TLBR:
20335 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
20336 break;
20337 case NM_TLBWI:
20338 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
20339 break;
20340 case NM_TLBWR:
20341 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
20342 break;
20343 case NM_TLBINV:
20344 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
20345 break;
20346 case NM_TLBINVF:
20347 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
20348 break;
20349 case NM_DI:
20350 check_cp0_enabled(ctx);
20352 TCGv t0 = tcg_temp_new();
20354 save_cpu_state(ctx, 1);
20355 gen_helper_di(t0, cpu_env);
20356 gen_store_gpr(t0, rt);
20357 /* Stop translation as we may have switched the execution mode */
20358 ctx->base.is_jmp = DISAS_STOP;
20359 tcg_temp_free(t0);
20361 break;
20362 case NM_EI:
20363 check_cp0_enabled(ctx);
20365 TCGv t0 = tcg_temp_new();
20367 save_cpu_state(ctx, 1);
20368 gen_helper_ei(t0, cpu_env);
20369 gen_store_gpr(t0, rt);
20370 /* Stop translation as we may have switched the execution mode */
20371 ctx->base.is_jmp = DISAS_STOP;
20372 tcg_temp_free(t0);
20374 break;
20375 case NM_RDPGPR:
20376 gen_load_srsgpr(rs, rt);
20377 break;
20378 case NM_WRPGPR:
20379 gen_store_srsgpr(rs, rt);
20380 break;
20381 case NM_WAIT:
20382 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20383 break;
20384 case NM_DERET:
20385 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20386 break;
20387 case NM_ERETX:
20388 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20389 break;
20390 #endif
20391 default:
20392 gen_reserved_instruction(ctx);
20393 break;
20395 break;
20396 case NM_POOL32AXF_7:
20398 int32_t op1 = extract32(ctx->opcode, 9, 3);
20399 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20401 break;
20402 default:
20403 gen_reserved_instruction(ctx);
20404 break;
20408 /* Immediate Value Compact Branches */
20409 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20410 int rt, int32_t imm, int32_t offset)
20412 TCGCond cond = TCG_COND_ALWAYS;
20413 TCGv t0 = tcg_temp_new();
20414 TCGv t1 = tcg_temp_new();
20416 gen_load_gpr(t0, rt);
20417 tcg_gen_movi_tl(t1, imm);
20418 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20420 /* Load needed operands and calculate btarget */
20421 switch (opc) {
20422 case NM_BEQIC:
20423 if (rt == 0 && imm == 0) {
20424 /* Unconditional branch */
20425 } else if (rt == 0 && imm != 0) {
20426 /* Treat as NOP */
20427 goto out;
20428 } else {
20429 cond = TCG_COND_EQ;
20431 break;
20432 case NM_BBEQZC:
20433 case NM_BBNEZC:
20434 check_nms(ctx);
20435 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20436 gen_reserved_instruction(ctx);
20437 goto out;
20438 } else if (rt == 0 && opc == NM_BBEQZC) {
20439 /* Unconditional branch */
20440 } else if (rt == 0 && opc == NM_BBNEZC) {
20441 /* Treat as NOP */
20442 goto out;
20443 } else {
20444 tcg_gen_shri_tl(t0, t0, imm);
20445 tcg_gen_andi_tl(t0, t0, 1);
20446 tcg_gen_movi_tl(t1, 0);
20447 if (opc == NM_BBEQZC) {
20448 cond = TCG_COND_EQ;
20449 } else {
20450 cond = TCG_COND_NE;
20453 break;
20454 case NM_BNEIC:
20455 if (rt == 0 && imm == 0) {
20456 /* Treat as NOP */
20457 goto out;
20458 } else if (rt == 0 && imm != 0) {
20459 /* Unconditional branch */
20460 } else {
20461 cond = TCG_COND_NE;
20463 break;
20464 case NM_BGEIC:
20465 if (rt == 0 && imm == 0) {
20466 /* Unconditional branch */
20467 } else {
20468 cond = TCG_COND_GE;
20470 break;
20471 case NM_BLTIC:
20472 cond = TCG_COND_LT;
20473 break;
20474 case NM_BGEIUC:
20475 if (rt == 0 && imm == 0) {
20476 /* Unconditional branch */
20477 } else {
20478 cond = TCG_COND_GEU;
20480 break;
20481 case NM_BLTIUC:
20482 cond = TCG_COND_LTU;
20483 break;
20484 default:
20485 MIPS_INVAL("Immediate Value Compact branch");
20486 gen_reserved_instruction(ctx);
20487 goto out;
20490 /* branch completion */
20491 clear_branch_hflags(ctx);
20492 ctx->base.is_jmp = DISAS_NORETURN;
20494 if (cond == TCG_COND_ALWAYS) {
20495 /* Uncoditional compact branch */
20496 gen_goto_tb(ctx, 0, ctx->btarget);
20497 } else {
20498 /* Conditional compact branch */
20499 TCGLabel *fs = gen_new_label();
20501 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20503 gen_goto_tb(ctx, 1, ctx->btarget);
20504 gen_set_label(fs);
20506 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20509 out:
20510 tcg_temp_free(t0);
20511 tcg_temp_free(t1);
20514 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20515 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20516 int rt)
20518 TCGv t0 = tcg_temp_new();
20519 TCGv t1 = tcg_temp_new();
20521 /* load rs */
20522 gen_load_gpr(t0, rs);
20524 /* link */
20525 if (rt != 0) {
20526 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20529 /* calculate btarget */
20530 tcg_gen_shli_tl(t0, t0, 1);
20531 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20532 gen_op_addr_add(ctx, btarget, t1, t0);
20534 /* branch completion */
20535 clear_branch_hflags(ctx);
20536 ctx->base.is_jmp = DISAS_NORETURN;
20538 /* unconditional branch to register */
20539 tcg_gen_mov_tl(cpu_PC, btarget);
20540 tcg_gen_lookup_and_goto_ptr();
20542 tcg_temp_free(t0);
20543 tcg_temp_free(t1);
20546 /* nanoMIPS Branches */
20547 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20548 int rs, int rt, int32_t offset)
20550 int bcond_compute = 0;
20551 TCGv t0 = tcg_temp_new();
20552 TCGv t1 = tcg_temp_new();
20554 /* Load needed operands and calculate btarget */
20555 switch (opc) {
20556 /* compact branch */
20557 case OPC_BGEC:
20558 case OPC_BLTC:
20559 gen_load_gpr(t0, rs);
20560 gen_load_gpr(t1, rt);
20561 bcond_compute = 1;
20562 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20563 break;
20564 case OPC_BGEUC:
20565 case OPC_BLTUC:
20566 if (rs == 0 || rs == rt) {
20567 /* OPC_BLEZALC, OPC_BGEZALC */
20568 /* OPC_BGTZALC, OPC_BLTZALC */
20569 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20571 gen_load_gpr(t0, rs);
20572 gen_load_gpr(t1, rt);
20573 bcond_compute = 1;
20574 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20575 break;
20576 case OPC_BC:
20577 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20578 break;
20579 case OPC_BEQZC:
20580 if (rs != 0) {
20581 /* OPC_BEQZC, OPC_BNEZC */
20582 gen_load_gpr(t0, rs);
20583 bcond_compute = 1;
20584 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20585 } else {
20586 /* OPC_JIC, OPC_JIALC */
20587 TCGv tbase = tcg_temp_new();
20588 TCGv toffset = tcg_temp_new();
20590 gen_load_gpr(tbase, rt);
20591 tcg_gen_movi_tl(toffset, offset);
20592 gen_op_addr_add(ctx, btarget, tbase, toffset);
20593 tcg_temp_free(tbase);
20594 tcg_temp_free(toffset);
20596 break;
20597 default:
20598 MIPS_INVAL("Compact branch/jump");
20599 gen_reserved_instruction(ctx);
20600 goto out;
20603 if (bcond_compute == 0) {
20604 /* Uncoditional compact branch */
20605 switch (opc) {
20606 case OPC_BC:
20607 gen_goto_tb(ctx, 0, ctx->btarget);
20608 break;
20609 default:
20610 MIPS_INVAL("Compact branch/jump");
20611 gen_reserved_instruction(ctx);
20612 goto out;
20614 } else {
20615 /* Conditional compact branch */
20616 TCGLabel *fs = gen_new_label();
20618 switch (opc) {
20619 case OPC_BGEUC:
20620 if (rs == 0 && rt != 0) {
20621 /* OPC_BLEZALC */
20622 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20623 } else if (rs != 0 && rt != 0 && rs == rt) {
20624 /* OPC_BGEZALC */
20625 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20626 } else {
20627 /* OPC_BGEUC */
20628 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20630 break;
20631 case OPC_BLTUC:
20632 if (rs == 0 && rt != 0) {
20633 /* OPC_BGTZALC */
20634 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20635 } else if (rs != 0 && rt != 0 && rs == rt) {
20636 /* OPC_BLTZALC */
20637 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20638 } else {
20639 /* OPC_BLTUC */
20640 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20642 break;
20643 case OPC_BGEC:
20644 if (rs == 0 && rt != 0) {
20645 /* OPC_BLEZC */
20646 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20647 } else if (rs != 0 && rt != 0 && rs == rt) {
20648 /* OPC_BGEZC */
20649 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20650 } else {
20651 /* OPC_BGEC */
20652 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20654 break;
20655 case OPC_BLTC:
20656 if (rs == 0 && rt != 0) {
20657 /* OPC_BGTZC */
20658 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20659 } else if (rs != 0 && rt != 0 && rs == rt) {
20660 /* OPC_BLTZC */
20661 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20662 } else {
20663 /* OPC_BLTC */
20664 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20666 break;
20667 case OPC_BEQZC:
20668 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20669 break;
20670 default:
20671 MIPS_INVAL("Compact conditional branch/jump");
20672 gen_reserved_instruction(ctx);
20673 goto out;
20676 /* branch completion */
20677 clear_branch_hflags(ctx);
20678 ctx->base.is_jmp = DISAS_NORETURN;
20680 /* Generating branch here as compact branches don't have delay slot */
20681 gen_goto_tb(ctx, 1, ctx->btarget);
20682 gen_set_label(fs);
20684 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20687 out:
20688 tcg_temp_free(t0);
20689 tcg_temp_free(t1);
20693 /* nanoMIPS CP1 Branches */
20694 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20695 int32_t ft, int32_t offset)
20697 target_ulong btarget;
20698 TCGv_i64 t0 = tcg_temp_new_i64();
20700 gen_load_fpr64(ctx, t0, ft);
20701 tcg_gen_andi_i64(t0, t0, 1);
20703 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20705 switch (op) {
20706 case NM_BC1EQZC:
20707 tcg_gen_xori_i64(t0, t0, 1);
20708 ctx->hflags |= MIPS_HFLAG_BC;
20709 break;
20710 case NM_BC1NEZC:
20711 /* t0 already set */
20712 ctx->hflags |= MIPS_HFLAG_BC;
20713 break;
20714 default:
20715 MIPS_INVAL("cp1 cond branch");
20716 gen_reserved_instruction(ctx);
20717 goto out;
20720 tcg_gen_trunc_i64_tl(bcond, t0);
20722 ctx->btarget = btarget;
20724 out:
20725 tcg_temp_free_i64(t0);
20729 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20731 TCGv t0, t1;
20732 t0 = tcg_temp_new();
20733 t1 = tcg_temp_new();
20735 gen_load_gpr(t0, rs);
20736 gen_load_gpr(t1, rt);
20738 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20739 /* PP.LSXS instructions require shifting */
20740 switch (extract32(ctx->opcode, 7, 4)) {
20741 case NM_SHXS:
20742 check_nms(ctx);
20743 /* fall through */
20744 case NM_LHXS:
20745 case NM_LHUXS:
20746 tcg_gen_shli_tl(t0, t0, 1);
20747 break;
20748 case NM_SWXS:
20749 check_nms(ctx);
20750 /* fall through */
20751 case NM_LWXS:
20752 case NM_LWC1XS:
20753 case NM_SWC1XS:
20754 tcg_gen_shli_tl(t0, t0, 2);
20755 break;
20756 case NM_LDC1XS:
20757 case NM_SDC1XS:
20758 tcg_gen_shli_tl(t0, t0, 3);
20759 break;
20762 gen_op_addr_add(ctx, t0, t0, t1);
20764 switch (extract32(ctx->opcode, 7, 4)) {
20765 case NM_LBX:
20766 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20767 MO_SB);
20768 gen_store_gpr(t0, rd);
20769 break;
20770 case NM_LHX:
20771 /*case NM_LHXS:*/
20772 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20773 MO_TESW);
20774 gen_store_gpr(t0, rd);
20775 break;
20776 case NM_LWX:
20777 /*case NM_LWXS:*/
20778 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20779 MO_TESL);
20780 gen_store_gpr(t0, rd);
20781 break;
20782 case NM_LBUX:
20783 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20784 MO_UB);
20785 gen_store_gpr(t0, rd);
20786 break;
20787 case NM_LHUX:
20788 /*case NM_LHUXS:*/
20789 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20790 MO_TEUW);
20791 gen_store_gpr(t0, rd);
20792 break;
20793 case NM_SBX:
20794 check_nms(ctx);
20795 gen_load_gpr(t1, rd);
20796 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20797 MO_8);
20798 break;
20799 case NM_SHX:
20800 /*case NM_SHXS:*/
20801 check_nms(ctx);
20802 gen_load_gpr(t1, rd);
20803 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20804 MO_TEUW);
20805 break;
20806 case NM_SWX:
20807 /*case NM_SWXS:*/
20808 check_nms(ctx);
20809 gen_load_gpr(t1, rd);
20810 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20811 MO_TEUL);
20812 break;
20813 case NM_LWC1X:
20814 /*case NM_LWC1XS:*/
20815 case NM_LDC1X:
20816 /*case NM_LDC1XS:*/
20817 case NM_SWC1X:
20818 /*case NM_SWC1XS:*/
20819 case NM_SDC1X:
20820 /*case NM_SDC1XS:*/
20821 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20822 check_cp1_enabled(ctx);
20823 switch (extract32(ctx->opcode, 7, 4)) {
20824 case NM_LWC1X:
20825 /*case NM_LWC1XS:*/
20826 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20827 break;
20828 case NM_LDC1X:
20829 /*case NM_LDC1XS:*/
20830 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20831 break;
20832 case NM_SWC1X:
20833 /*case NM_SWC1XS:*/
20834 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20835 break;
20836 case NM_SDC1X:
20837 /*case NM_SDC1XS:*/
20838 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20839 break;
20841 } else {
20842 generate_exception_err(ctx, EXCP_CpU, 1);
20844 break;
20845 default:
20846 gen_reserved_instruction(ctx);
20847 break;
20850 tcg_temp_free(t0);
20851 tcg_temp_free(t1);
20854 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20856 int rt, rs, rd;
20858 rt = extract32(ctx->opcode, 21, 5);
20859 rs = extract32(ctx->opcode, 16, 5);
20860 rd = extract32(ctx->opcode, 11, 5);
20862 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20863 gen_reserved_instruction(ctx);
20864 return;
20866 check_cp1_enabled(ctx);
20867 switch (extract32(ctx->opcode, 0, 3)) {
20868 case NM_POOL32F_0:
20869 switch (extract32(ctx->opcode, 3, 7)) {
20870 case NM_RINT_S:
20871 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20872 break;
20873 case NM_RINT_D:
20874 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20875 break;
20876 case NM_CLASS_S:
20877 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20878 break;
20879 case NM_CLASS_D:
20880 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20881 break;
20882 case NM_ADD_S:
20883 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20884 break;
20885 case NM_ADD_D:
20886 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20887 break;
20888 case NM_SUB_S:
20889 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20890 break;
20891 case NM_SUB_D:
20892 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20893 break;
20894 case NM_MUL_S:
20895 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20896 break;
20897 case NM_MUL_D:
20898 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20899 break;
20900 case NM_DIV_S:
20901 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20902 break;
20903 case NM_DIV_D:
20904 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20905 break;
20906 case NM_SELEQZ_S:
20907 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20908 break;
20909 case NM_SELEQZ_D:
20910 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20911 break;
20912 case NM_SELNEZ_S:
20913 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20914 break;
20915 case NM_SELNEZ_D:
20916 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20917 break;
20918 case NM_SEL_S:
20919 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20920 break;
20921 case NM_SEL_D:
20922 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20923 break;
20924 case NM_MADDF_S:
20925 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20926 break;
20927 case NM_MADDF_D:
20928 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20929 break;
20930 case NM_MSUBF_S:
20931 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20932 break;
20933 case NM_MSUBF_D:
20934 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20935 break;
20936 default:
20937 gen_reserved_instruction(ctx);
20938 break;
20940 break;
20941 case NM_POOL32F_3:
20942 switch (extract32(ctx->opcode, 3, 3)) {
20943 case NM_MIN_FMT:
20944 switch (extract32(ctx->opcode, 9, 1)) {
20945 case FMT_SDPS_S:
20946 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20947 break;
20948 case FMT_SDPS_D:
20949 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20950 break;
20952 break;
20953 case NM_MAX_FMT:
20954 switch (extract32(ctx->opcode, 9, 1)) {
20955 case FMT_SDPS_S:
20956 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20957 break;
20958 case FMT_SDPS_D:
20959 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20960 break;
20962 break;
20963 case NM_MINA_FMT:
20964 switch (extract32(ctx->opcode, 9, 1)) {
20965 case FMT_SDPS_S:
20966 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20967 break;
20968 case FMT_SDPS_D:
20969 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20970 break;
20972 break;
20973 case NM_MAXA_FMT:
20974 switch (extract32(ctx->opcode, 9, 1)) {
20975 case FMT_SDPS_S:
20976 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20977 break;
20978 case FMT_SDPS_D:
20979 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20980 break;
20982 break;
20983 case NM_POOL32FXF:
20984 switch (extract32(ctx->opcode, 6, 8)) {
20985 case NM_CFC1:
20986 gen_cp1(ctx, OPC_CFC1, rt, rs);
20987 break;
20988 case NM_CTC1:
20989 gen_cp1(ctx, OPC_CTC1, rt, rs);
20990 break;
20991 case NM_MFC1:
20992 gen_cp1(ctx, OPC_MFC1, rt, rs);
20993 break;
20994 case NM_MTC1:
20995 gen_cp1(ctx, OPC_MTC1, rt, rs);
20996 break;
20997 case NM_MFHC1:
20998 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20999 break;
21000 case NM_MTHC1:
21001 gen_cp1(ctx, OPC_MTHC1, rt, rs);
21002 break;
21003 case NM_CVT_S_PL:
21004 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
21005 break;
21006 case NM_CVT_S_PU:
21007 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
21008 break;
21009 default:
21010 switch (extract32(ctx->opcode, 6, 9)) {
21011 case NM_CVT_L_S:
21012 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
21013 break;
21014 case NM_CVT_L_D:
21015 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
21016 break;
21017 case NM_CVT_W_S:
21018 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
21019 break;
21020 case NM_CVT_W_D:
21021 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
21022 break;
21023 case NM_RSQRT_S:
21024 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
21025 break;
21026 case NM_RSQRT_D:
21027 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
21028 break;
21029 case NM_SQRT_S:
21030 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
21031 break;
21032 case NM_SQRT_D:
21033 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
21034 break;
21035 case NM_RECIP_S:
21036 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
21037 break;
21038 case NM_RECIP_D:
21039 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
21040 break;
21041 case NM_FLOOR_L_S:
21042 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
21043 break;
21044 case NM_FLOOR_L_D:
21045 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
21046 break;
21047 case NM_FLOOR_W_S:
21048 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
21049 break;
21050 case NM_FLOOR_W_D:
21051 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
21052 break;
21053 case NM_CEIL_L_S:
21054 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
21055 break;
21056 case NM_CEIL_L_D:
21057 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
21058 break;
21059 case NM_CEIL_W_S:
21060 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
21061 break;
21062 case NM_CEIL_W_D:
21063 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
21064 break;
21065 case NM_TRUNC_L_S:
21066 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
21067 break;
21068 case NM_TRUNC_L_D:
21069 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
21070 break;
21071 case NM_TRUNC_W_S:
21072 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
21073 break;
21074 case NM_TRUNC_W_D:
21075 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
21076 break;
21077 case NM_ROUND_L_S:
21078 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
21079 break;
21080 case NM_ROUND_L_D:
21081 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
21082 break;
21083 case NM_ROUND_W_S:
21084 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
21085 break;
21086 case NM_ROUND_W_D:
21087 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
21088 break;
21089 case NM_MOV_S:
21090 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
21091 break;
21092 case NM_MOV_D:
21093 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
21094 break;
21095 case NM_ABS_S:
21096 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
21097 break;
21098 case NM_ABS_D:
21099 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
21100 break;
21101 case NM_NEG_S:
21102 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
21103 break;
21104 case NM_NEG_D:
21105 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
21106 break;
21107 case NM_CVT_D_S:
21108 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
21109 break;
21110 case NM_CVT_D_W:
21111 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
21112 break;
21113 case NM_CVT_D_L:
21114 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
21115 break;
21116 case NM_CVT_S_D:
21117 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
21118 break;
21119 case NM_CVT_S_W:
21120 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
21121 break;
21122 case NM_CVT_S_L:
21123 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
21124 break;
21125 default:
21126 gen_reserved_instruction(ctx);
21127 break;
21129 break;
21131 break;
21133 break;
21134 case NM_POOL32F_5:
21135 switch (extract32(ctx->opcode, 3, 3)) {
21136 case NM_CMP_CONDN_S:
21137 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21138 break;
21139 case NM_CMP_CONDN_D:
21140 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21141 break;
21142 default:
21143 gen_reserved_instruction(ctx);
21144 break;
21146 break;
21147 default:
21148 gen_reserved_instruction(ctx);
21149 break;
21153 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
21154 int rd, int rs, int rt)
21156 int ret = rd;
21157 TCGv t0 = tcg_temp_new();
21158 TCGv v1_t = tcg_temp_new();
21159 TCGv v2_t = tcg_temp_new();
21161 gen_load_gpr(v1_t, rs);
21162 gen_load_gpr(v2_t, rt);
21164 switch (opc) {
21165 case NM_CMP_EQ_PH:
21166 check_dsp(ctx);
21167 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21168 break;
21169 case NM_CMP_LT_PH:
21170 check_dsp(ctx);
21171 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21172 break;
21173 case NM_CMP_LE_PH:
21174 check_dsp(ctx);
21175 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21176 break;
21177 case NM_CMPU_EQ_QB:
21178 check_dsp(ctx);
21179 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21180 break;
21181 case NM_CMPU_LT_QB:
21182 check_dsp(ctx);
21183 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21184 break;
21185 case NM_CMPU_LE_QB:
21186 check_dsp(ctx);
21187 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21188 break;
21189 case NM_CMPGU_EQ_QB:
21190 check_dsp(ctx);
21191 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21192 gen_store_gpr(v1_t, ret);
21193 break;
21194 case NM_CMPGU_LT_QB:
21195 check_dsp(ctx);
21196 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21197 gen_store_gpr(v1_t, ret);
21198 break;
21199 case NM_CMPGU_LE_QB:
21200 check_dsp(ctx);
21201 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21202 gen_store_gpr(v1_t, ret);
21203 break;
21204 case NM_CMPGDU_EQ_QB:
21205 check_dsp_r2(ctx);
21206 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21207 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21208 gen_store_gpr(v1_t, ret);
21209 break;
21210 case NM_CMPGDU_LT_QB:
21211 check_dsp_r2(ctx);
21212 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21213 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21214 gen_store_gpr(v1_t, ret);
21215 break;
21216 case NM_CMPGDU_LE_QB:
21217 check_dsp_r2(ctx);
21218 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21219 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21220 gen_store_gpr(v1_t, ret);
21221 break;
21222 case NM_PACKRL_PH:
21223 check_dsp(ctx);
21224 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
21225 gen_store_gpr(v1_t, ret);
21226 break;
21227 case NM_PICK_QB:
21228 check_dsp(ctx);
21229 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
21230 gen_store_gpr(v1_t, ret);
21231 break;
21232 case NM_PICK_PH:
21233 check_dsp(ctx);
21234 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
21235 gen_store_gpr(v1_t, ret);
21236 break;
21237 case NM_ADDQ_S_W:
21238 check_dsp(ctx);
21239 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
21240 gen_store_gpr(v1_t, ret);
21241 break;
21242 case NM_SUBQ_S_W:
21243 check_dsp(ctx);
21244 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
21245 gen_store_gpr(v1_t, ret);
21246 break;
21247 case NM_ADDSC:
21248 check_dsp(ctx);
21249 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
21250 gen_store_gpr(v1_t, ret);
21251 break;
21252 case NM_ADDWC:
21253 check_dsp(ctx);
21254 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
21255 gen_store_gpr(v1_t, ret);
21256 break;
21257 case NM_ADDQ_S_PH:
21258 check_dsp(ctx);
21259 switch (extract32(ctx->opcode, 10, 1)) {
21260 case 0:
21261 /* ADDQ_PH */
21262 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
21263 gen_store_gpr(v1_t, ret);
21264 break;
21265 case 1:
21266 /* ADDQ_S_PH */
21267 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21268 gen_store_gpr(v1_t, ret);
21269 break;
21271 break;
21272 case NM_ADDQH_R_PH:
21273 check_dsp_r2(ctx);
21274 switch (extract32(ctx->opcode, 10, 1)) {
21275 case 0:
21276 /* ADDQH_PH */
21277 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
21278 gen_store_gpr(v1_t, ret);
21279 break;
21280 case 1:
21281 /* ADDQH_R_PH */
21282 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
21283 gen_store_gpr(v1_t, ret);
21284 break;
21286 break;
21287 case NM_ADDQH_R_W:
21288 check_dsp_r2(ctx);
21289 switch (extract32(ctx->opcode, 10, 1)) {
21290 case 0:
21291 /* ADDQH_W */
21292 gen_helper_addqh_w(v1_t, v1_t, v2_t);
21293 gen_store_gpr(v1_t, ret);
21294 break;
21295 case 1:
21296 /* ADDQH_R_W */
21297 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
21298 gen_store_gpr(v1_t, ret);
21299 break;
21301 break;
21302 case NM_ADDU_S_QB:
21303 check_dsp(ctx);
21304 switch (extract32(ctx->opcode, 10, 1)) {
21305 case 0:
21306 /* ADDU_QB */
21307 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
21308 gen_store_gpr(v1_t, ret);
21309 break;
21310 case 1:
21311 /* ADDU_S_QB */
21312 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21313 gen_store_gpr(v1_t, ret);
21314 break;
21316 break;
21317 case NM_ADDU_S_PH:
21318 check_dsp_r2(ctx);
21319 switch (extract32(ctx->opcode, 10, 1)) {
21320 case 0:
21321 /* ADDU_PH */
21322 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
21323 gen_store_gpr(v1_t, ret);
21324 break;
21325 case 1:
21326 /* ADDU_S_PH */
21327 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21328 gen_store_gpr(v1_t, ret);
21329 break;
21331 break;
21332 case NM_ADDUH_R_QB:
21333 check_dsp_r2(ctx);
21334 switch (extract32(ctx->opcode, 10, 1)) {
21335 case 0:
21336 /* ADDUH_QB */
21337 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
21338 gen_store_gpr(v1_t, ret);
21339 break;
21340 case 1:
21341 /* ADDUH_R_QB */
21342 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
21343 gen_store_gpr(v1_t, ret);
21344 break;
21346 break;
21347 case NM_SHRAV_R_PH:
21348 check_dsp(ctx);
21349 switch (extract32(ctx->opcode, 10, 1)) {
21350 case 0:
21351 /* SHRAV_PH */
21352 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21353 gen_store_gpr(v1_t, ret);
21354 break;
21355 case 1:
21356 /* SHRAV_R_PH */
21357 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21358 gen_store_gpr(v1_t, ret);
21359 break;
21361 break;
21362 case NM_SHRAV_R_QB:
21363 check_dsp_r2(ctx);
21364 switch (extract32(ctx->opcode, 10, 1)) {
21365 case 0:
21366 /* SHRAV_QB */
21367 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21368 gen_store_gpr(v1_t, ret);
21369 break;
21370 case 1:
21371 /* SHRAV_R_QB */
21372 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21373 gen_store_gpr(v1_t, ret);
21374 break;
21376 break;
21377 case NM_SUBQ_S_PH:
21378 check_dsp(ctx);
21379 switch (extract32(ctx->opcode, 10, 1)) {
21380 case 0:
21381 /* SUBQ_PH */
21382 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21383 gen_store_gpr(v1_t, ret);
21384 break;
21385 case 1:
21386 /* SUBQ_S_PH */
21387 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21388 gen_store_gpr(v1_t, ret);
21389 break;
21391 break;
21392 case NM_SUBQH_R_PH:
21393 check_dsp_r2(ctx);
21394 switch (extract32(ctx->opcode, 10, 1)) {
21395 case 0:
21396 /* SUBQH_PH */
21397 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21398 gen_store_gpr(v1_t, ret);
21399 break;
21400 case 1:
21401 /* SUBQH_R_PH */
21402 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21403 gen_store_gpr(v1_t, ret);
21404 break;
21406 break;
21407 case NM_SUBQH_R_W:
21408 check_dsp_r2(ctx);
21409 switch (extract32(ctx->opcode, 10, 1)) {
21410 case 0:
21411 /* SUBQH_W */
21412 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21413 gen_store_gpr(v1_t, ret);
21414 break;
21415 case 1:
21416 /* SUBQH_R_W */
21417 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21418 gen_store_gpr(v1_t, ret);
21419 break;
21421 break;
21422 case NM_SUBU_S_QB:
21423 check_dsp(ctx);
21424 switch (extract32(ctx->opcode, 10, 1)) {
21425 case 0:
21426 /* SUBU_QB */
21427 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21428 gen_store_gpr(v1_t, ret);
21429 break;
21430 case 1:
21431 /* SUBU_S_QB */
21432 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21433 gen_store_gpr(v1_t, ret);
21434 break;
21436 break;
21437 case NM_SUBU_S_PH:
21438 check_dsp_r2(ctx);
21439 switch (extract32(ctx->opcode, 10, 1)) {
21440 case 0:
21441 /* SUBU_PH */
21442 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21443 gen_store_gpr(v1_t, ret);
21444 break;
21445 case 1:
21446 /* SUBU_S_PH */
21447 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21448 gen_store_gpr(v1_t, ret);
21449 break;
21451 break;
21452 case NM_SUBUH_R_QB:
21453 check_dsp_r2(ctx);
21454 switch (extract32(ctx->opcode, 10, 1)) {
21455 case 0:
21456 /* SUBUH_QB */
21457 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21458 gen_store_gpr(v1_t, ret);
21459 break;
21460 case 1:
21461 /* SUBUH_R_QB */
21462 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21463 gen_store_gpr(v1_t, ret);
21464 break;
21466 break;
21467 case NM_SHLLV_S_PH:
21468 check_dsp(ctx);
21469 switch (extract32(ctx->opcode, 10, 1)) {
21470 case 0:
21471 /* SHLLV_PH */
21472 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21473 gen_store_gpr(v1_t, ret);
21474 break;
21475 case 1:
21476 /* SHLLV_S_PH */
21477 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21478 gen_store_gpr(v1_t, ret);
21479 break;
21481 break;
21482 case NM_PRECR_SRA_R_PH_W:
21483 check_dsp_r2(ctx);
21484 switch (extract32(ctx->opcode, 10, 1)) {
21485 case 0:
21486 /* PRECR_SRA_PH_W */
21488 TCGv_i32 sa_t = tcg_const_i32(rd);
21489 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21490 cpu_gpr[rt]);
21491 gen_store_gpr(v1_t, rt);
21492 tcg_temp_free_i32(sa_t);
21494 break;
21495 case 1:
21496 /* PRECR_SRA_R_PH_W */
21498 TCGv_i32 sa_t = tcg_const_i32(rd);
21499 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21500 cpu_gpr[rt]);
21501 gen_store_gpr(v1_t, rt);
21502 tcg_temp_free_i32(sa_t);
21504 break;
21506 break;
21507 case NM_MULEU_S_PH_QBL:
21508 check_dsp(ctx);
21509 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21510 gen_store_gpr(v1_t, ret);
21511 break;
21512 case NM_MULEU_S_PH_QBR:
21513 check_dsp(ctx);
21514 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21515 gen_store_gpr(v1_t, ret);
21516 break;
21517 case NM_MULQ_RS_PH:
21518 check_dsp(ctx);
21519 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21520 gen_store_gpr(v1_t, ret);
21521 break;
21522 case NM_MULQ_S_PH:
21523 check_dsp_r2(ctx);
21524 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21525 gen_store_gpr(v1_t, ret);
21526 break;
21527 case NM_MULQ_RS_W:
21528 check_dsp_r2(ctx);
21529 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21530 gen_store_gpr(v1_t, ret);
21531 break;
21532 case NM_MULQ_S_W:
21533 check_dsp_r2(ctx);
21534 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21535 gen_store_gpr(v1_t, ret);
21536 break;
21537 case NM_APPEND:
21538 check_dsp_r2(ctx);
21539 gen_load_gpr(t0, rs);
21540 if (rd != 0) {
21541 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21543 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21544 break;
21545 case NM_MODSUB:
21546 check_dsp(ctx);
21547 gen_helper_modsub(v1_t, v1_t, v2_t);
21548 gen_store_gpr(v1_t, ret);
21549 break;
21550 case NM_SHRAV_R_W:
21551 check_dsp(ctx);
21552 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21553 gen_store_gpr(v1_t, ret);
21554 break;
21555 case NM_SHRLV_PH:
21556 check_dsp_r2(ctx);
21557 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21558 gen_store_gpr(v1_t, ret);
21559 break;
21560 case NM_SHRLV_QB:
21561 check_dsp(ctx);
21562 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21563 gen_store_gpr(v1_t, ret);
21564 break;
21565 case NM_SHLLV_QB:
21566 check_dsp(ctx);
21567 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21568 gen_store_gpr(v1_t, ret);
21569 break;
21570 case NM_SHLLV_S_W:
21571 check_dsp(ctx);
21572 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21573 gen_store_gpr(v1_t, ret);
21574 break;
21575 case NM_SHILO:
21576 check_dsp(ctx);
21578 TCGv tv0 = tcg_temp_new();
21579 TCGv tv1 = tcg_temp_new();
21580 int16_t imm = extract32(ctx->opcode, 16, 7);
21582 tcg_gen_movi_tl(tv0, rd >> 3);
21583 tcg_gen_movi_tl(tv1, imm);
21584 gen_helper_shilo(tv0, tv1, cpu_env);
21586 break;
21587 case NM_MULEQ_S_W_PHL:
21588 check_dsp(ctx);
21589 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21590 gen_store_gpr(v1_t, ret);
21591 break;
21592 case NM_MULEQ_S_W_PHR:
21593 check_dsp(ctx);
21594 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21595 gen_store_gpr(v1_t, ret);
21596 break;
21597 case NM_MUL_S_PH:
21598 check_dsp_r2(ctx);
21599 switch (extract32(ctx->opcode, 10, 1)) {
21600 case 0:
21601 /* MUL_PH */
21602 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21603 gen_store_gpr(v1_t, ret);
21604 break;
21605 case 1:
21606 /* MUL_S_PH */
21607 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21608 gen_store_gpr(v1_t, ret);
21609 break;
21611 break;
21612 case NM_PRECR_QB_PH:
21613 check_dsp_r2(ctx);
21614 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21615 gen_store_gpr(v1_t, ret);
21616 break;
21617 case NM_PRECRQ_QB_PH:
21618 check_dsp(ctx);
21619 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21620 gen_store_gpr(v1_t, ret);
21621 break;
21622 case NM_PRECRQ_PH_W:
21623 check_dsp(ctx);
21624 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21625 gen_store_gpr(v1_t, ret);
21626 break;
21627 case NM_PRECRQ_RS_PH_W:
21628 check_dsp(ctx);
21629 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21630 gen_store_gpr(v1_t, ret);
21631 break;
21632 case NM_PRECRQU_S_QB_PH:
21633 check_dsp(ctx);
21634 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21635 gen_store_gpr(v1_t, ret);
21636 break;
21637 case NM_SHRA_R_W:
21638 check_dsp(ctx);
21639 tcg_gen_movi_tl(t0, rd);
21640 gen_helper_shra_r_w(v1_t, t0, v1_t);
21641 gen_store_gpr(v1_t, rt);
21642 break;
21643 case NM_SHRA_R_PH:
21644 check_dsp(ctx);
21645 tcg_gen_movi_tl(t0, rd >> 1);
21646 switch (extract32(ctx->opcode, 10, 1)) {
21647 case 0:
21648 /* SHRA_PH */
21649 gen_helper_shra_ph(v1_t, t0, v1_t);
21650 gen_store_gpr(v1_t, rt);
21651 break;
21652 case 1:
21653 /* SHRA_R_PH */
21654 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21655 gen_store_gpr(v1_t, rt);
21656 break;
21658 break;
21659 case NM_SHLL_S_PH:
21660 check_dsp(ctx);
21661 tcg_gen_movi_tl(t0, rd >> 1);
21662 switch (extract32(ctx->opcode, 10, 2)) {
21663 case 0:
21664 /* SHLL_PH */
21665 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21666 gen_store_gpr(v1_t, rt);
21667 break;
21668 case 2:
21669 /* SHLL_S_PH */
21670 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21671 gen_store_gpr(v1_t, rt);
21672 break;
21673 default:
21674 gen_reserved_instruction(ctx);
21675 break;
21677 break;
21678 case NM_SHLL_S_W:
21679 check_dsp(ctx);
21680 tcg_gen_movi_tl(t0, rd);
21681 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21682 gen_store_gpr(v1_t, rt);
21683 break;
21684 case NM_REPL_PH:
21685 check_dsp(ctx);
21687 int16_t imm;
21688 imm = sextract32(ctx->opcode, 11, 11);
21689 imm = (int16_t)(imm << 6) >> 6;
21690 if (rt != 0) {
21691 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21694 break;
21695 default:
21696 gen_reserved_instruction(ctx);
21697 break;
21701 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21703 uint16_t insn;
21704 uint32_t op;
21705 int rt, rs, rd;
21706 int offset;
21707 int imm;
21709 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21710 ctx->opcode = (ctx->opcode << 16) | insn;
21712 rt = extract32(ctx->opcode, 21, 5);
21713 rs = extract32(ctx->opcode, 16, 5);
21714 rd = extract32(ctx->opcode, 11, 5);
21716 op = extract32(ctx->opcode, 26, 6);
21717 switch (op) {
21718 case NM_P_ADDIU:
21719 if (rt == 0) {
21720 /* P.RI */
21721 switch (extract32(ctx->opcode, 19, 2)) {
21722 case NM_SIGRIE:
21723 default:
21724 gen_reserved_instruction(ctx);
21725 break;
21726 case NM_P_SYSCALL:
21727 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21728 generate_exception_end(ctx, EXCP_SYSCALL);
21729 } else {
21730 gen_reserved_instruction(ctx);
21732 break;
21733 case NM_BREAK:
21734 generate_exception_end(ctx, EXCP_BREAK);
21735 break;
21736 case NM_SDBBP:
21737 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21738 gen_helper_do_semihosting(cpu_env);
21739 } else {
21740 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21741 gen_reserved_instruction(ctx);
21742 } else {
21743 generate_exception_end(ctx, EXCP_DBp);
21746 break;
21748 } else {
21749 /* NM_ADDIU */
21750 imm = extract32(ctx->opcode, 0, 16);
21751 if (rs != 0) {
21752 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21753 } else {
21754 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21756 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21758 break;
21759 case NM_ADDIUPC:
21760 if (rt != 0) {
21761 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21762 extract32(ctx->opcode, 1, 20) << 1;
21763 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21764 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21766 break;
21767 case NM_POOL32A:
21768 switch (ctx->opcode & 0x07) {
21769 case NM_POOL32A0:
21770 gen_pool32a0_nanomips_insn(env, ctx);
21771 break;
21772 case NM_POOL32A5:
21774 int32_t op1 = extract32(ctx->opcode, 3, 7);
21775 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21777 break;
21778 case NM_POOL32A7:
21779 switch (extract32(ctx->opcode, 3, 3)) {
21780 case NM_P_LSX:
21781 gen_p_lsx(ctx, rd, rs, rt);
21782 break;
21783 case NM_LSA:
21785 * In nanoMIPS, the shift field directly encodes the shift
21786 * amount, meaning that the supported shift values are in
21787 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21789 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21790 extract32(ctx->opcode, 9, 2) - 1);
21791 break;
21792 case NM_EXTW:
21793 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21794 break;
21795 case NM_POOL32AXF:
21796 gen_pool32axf_nanomips_insn(env, ctx);
21797 break;
21798 default:
21799 gen_reserved_instruction(ctx);
21800 break;
21802 break;
21803 default:
21804 gen_reserved_instruction(ctx);
21805 break;
21807 break;
21808 case NM_P_GP_W:
21809 switch (ctx->opcode & 0x03) {
21810 case NM_ADDIUGP_W:
21811 if (rt != 0) {
21812 offset = extract32(ctx->opcode, 0, 21);
21813 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21815 break;
21816 case NM_LWGP:
21817 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21818 break;
21819 case NM_SWGP:
21820 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21821 break;
21822 default:
21823 gen_reserved_instruction(ctx);
21824 break;
21826 break;
21827 case NM_P48I:
21829 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21830 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21831 switch (extract32(ctx->opcode, 16, 5)) {
21832 case NM_LI48:
21833 check_nms(ctx);
21834 if (rt != 0) {
21835 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21837 break;
21838 case NM_ADDIU48:
21839 check_nms(ctx);
21840 if (rt != 0) {
21841 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21842 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21844 break;
21845 case NM_ADDIUGP48:
21846 check_nms(ctx);
21847 if (rt != 0) {
21848 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21850 break;
21851 case NM_ADDIUPC48:
21852 check_nms(ctx);
21853 if (rt != 0) {
21854 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21855 addr_off);
21857 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21859 break;
21860 case NM_LWPC48:
21861 check_nms(ctx);
21862 if (rt != 0) {
21863 TCGv t0;
21864 t0 = tcg_temp_new();
21866 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21867 addr_off);
21869 tcg_gen_movi_tl(t0, addr);
21870 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21871 tcg_temp_free(t0);
21873 break;
21874 case NM_SWPC48:
21875 check_nms(ctx);
21877 TCGv t0, t1;
21878 t0 = tcg_temp_new();
21879 t1 = tcg_temp_new();
21881 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21882 addr_off);
21884 tcg_gen_movi_tl(t0, addr);
21885 gen_load_gpr(t1, rt);
21887 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21889 tcg_temp_free(t0);
21890 tcg_temp_free(t1);
21892 break;
21893 default:
21894 gen_reserved_instruction(ctx);
21895 break;
21897 return 6;
21899 case NM_P_U12:
21900 switch (extract32(ctx->opcode, 12, 4)) {
21901 case NM_ORI:
21902 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21903 break;
21904 case NM_XORI:
21905 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21906 break;
21907 case NM_ANDI:
21908 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21909 break;
21910 case NM_P_SR:
21911 switch (extract32(ctx->opcode, 20, 1)) {
21912 case NM_PP_SR:
21913 switch (ctx->opcode & 3) {
21914 case NM_SAVE:
21915 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21916 extract32(ctx->opcode, 2, 1),
21917 extract32(ctx->opcode, 3, 9) << 3);
21918 break;
21919 case NM_RESTORE:
21920 case NM_RESTORE_JRC:
21921 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21922 extract32(ctx->opcode, 2, 1),
21923 extract32(ctx->opcode, 3, 9) << 3);
21924 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21925 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21927 break;
21928 default:
21929 gen_reserved_instruction(ctx);
21930 break;
21932 break;
21933 case NM_P_SR_F:
21934 gen_reserved_instruction(ctx);
21935 break;
21937 break;
21938 case NM_SLTI:
21939 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21940 break;
21941 case NM_SLTIU:
21942 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21943 break;
21944 case NM_SEQI:
21946 TCGv t0 = tcg_temp_new();
21948 imm = extract32(ctx->opcode, 0, 12);
21949 gen_load_gpr(t0, rs);
21950 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21951 gen_store_gpr(t0, rt);
21953 tcg_temp_free(t0);
21955 break;
21956 case NM_ADDIUNEG:
21957 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21958 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21959 break;
21960 case NM_P_SHIFT:
21962 int shift = extract32(ctx->opcode, 0, 5);
21963 switch (extract32(ctx->opcode, 5, 4)) {
21964 case NM_P_SLL:
21965 if (rt == 0 && shift == 0) {
21966 /* NOP */
21967 } else if (rt == 0 && shift == 3) {
21968 /* EHB - treat as NOP */
21969 } else if (rt == 0 && shift == 5) {
21970 /* PAUSE - treat as NOP */
21971 } else if (rt == 0 && shift == 6) {
21972 /* SYNC */
21973 gen_sync(extract32(ctx->opcode, 16, 5));
21974 } else {
21975 /* SLL */
21976 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21977 extract32(ctx->opcode, 0, 5));
21979 break;
21980 case NM_SRL:
21981 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21982 extract32(ctx->opcode, 0, 5));
21983 break;
21984 case NM_SRA:
21985 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21986 extract32(ctx->opcode, 0, 5));
21987 break;
21988 case NM_ROTR:
21989 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21990 extract32(ctx->opcode, 0, 5));
21991 break;
21994 break;
21995 case NM_P_ROTX:
21996 check_nms(ctx);
21997 if (rt != 0) {
21998 TCGv t0 = tcg_temp_new();
21999 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
22000 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
22001 << 1);
22002 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
22004 gen_load_gpr(t0, rs);
22005 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
22006 tcg_temp_free(t0);
22008 tcg_temp_free_i32(shift);
22009 tcg_temp_free_i32(shiftx);
22010 tcg_temp_free_i32(stripe);
22012 break;
22013 case NM_P_INS:
22014 switch (((ctx->opcode >> 10) & 2) |
22015 (extract32(ctx->opcode, 5, 1))) {
22016 case NM_INS:
22017 check_nms(ctx);
22018 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
22019 extract32(ctx->opcode, 6, 5));
22020 break;
22021 default:
22022 gen_reserved_instruction(ctx);
22023 break;
22025 break;
22026 case NM_P_EXT:
22027 switch (((ctx->opcode >> 10) & 2) |
22028 (extract32(ctx->opcode, 5, 1))) {
22029 case NM_EXT:
22030 check_nms(ctx);
22031 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
22032 extract32(ctx->opcode, 6, 5));
22033 break;
22034 default:
22035 gen_reserved_instruction(ctx);
22036 break;
22038 break;
22039 default:
22040 gen_reserved_instruction(ctx);
22041 break;
22043 break;
22044 case NM_POOL32F:
22045 gen_pool32f_nanomips_insn(ctx);
22046 break;
22047 case NM_POOL32S:
22048 break;
22049 case NM_P_LUI:
22050 switch (extract32(ctx->opcode, 1, 1)) {
22051 case NM_LUI:
22052 if (rt != 0) {
22053 tcg_gen_movi_tl(cpu_gpr[rt],
22054 sextract32(ctx->opcode, 0, 1) << 31 |
22055 extract32(ctx->opcode, 2, 10) << 21 |
22056 extract32(ctx->opcode, 12, 9) << 12);
22058 break;
22059 case NM_ALUIPC:
22060 if (rt != 0) {
22061 offset = sextract32(ctx->opcode, 0, 1) << 31 |
22062 extract32(ctx->opcode, 2, 10) << 21 |
22063 extract32(ctx->opcode, 12, 9) << 12;
22064 target_long addr;
22065 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
22066 tcg_gen_movi_tl(cpu_gpr[rt], addr);
22068 break;
22070 break;
22071 case NM_P_GP_BH:
22073 uint32_t u = extract32(ctx->opcode, 0, 18);
22075 switch (extract32(ctx->opcode, 18, 3)) {
22076 case NM_LBGP:
22077 gen_ld(ctx, OPC_LB, rt, 28, u);
22078 break;
22079 case NM_SBGP:
22080 gen_st(ctx, OPC_SB, rt, 28, u);
22081 break;
22082 case NM_LBUGP:
22083 gen_ld(ctx, OPC_LBU, rt, 28, u);
22084 break;
22085 case NM_ADDIUGP_B:
22086 if (rt != 0) {
22087 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
22089 break;
22090 case NM_P_GP_LH:
22091 u &= ~1;
22092 switch (ctx->opcode & 1) {
22093 case NM_LHGP:
22094 gen_ld(ctx, OPC_LH, rt, 28, u);
22095 break;
22096 case NM_LHUGP:
22097 gen_ld(ctx, OPC_LHU, rt, 28, u);
22098 break;
22100 break;
22101 case NM_P_GP_SH:
22102 u &= ~1;
22103 switch (ctx->opcode & 1) {
22104 case NM_SHGP:
22105 gen_st(ctx, OPC_SH, rt, 28, u);
22106 break;
22107 default:
22108 gen_reserved_instruction(ctx);
22109 break;
22111 break;
22112 case NM_P_GP_CP1:
22113 u &= ~0x3;
22114 switch (ctx->opcode & 0x3) {
22115 case NM_LWC1GP:
22116 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
22117 break;
22118 case NM_LDC1GP:
22119 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
22120 break;
22121 case NM_SWC1GP:
22122 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
22123 break;
22124 case NM_SDC1GP:
22125 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
22126 break;
22128 break;
22129 default:
22130 gen_reserved_instruction(ctx);
22131 break;
22134 break;
22135 case NM_P_LS_U12:
22137 uint32_t u = extract32(ctx->opcode, 0, 12);
22139 switch (extract32(ctx->opcode, 12, 4)) {
22140 case NM_P_PREFU12:
22141 if (rt == 31) {
22142 /* SYNCI */
22144 * Break the TB to be able to sync copied instructions
22145 * immediately.
22147 ctx->base.is_jmp = DISAS_STOP;
22148 } else {
22149 /* PREF */
22150 /* Treat as NOP. */
22152 break;
22153 case NM_LB:
22154 gen_ld(ctx, OPC_LB, rt, rs, u);
22155 break;
22156 case NM_LH:
22157 gen_ld(ctx, OPC_LH, rt, rs, u);
22158 break;
22159 case NM_LW:
22160 gen_ld(ctx, OPC_LW, rt, rs, u);
22161 break;
22162 case NM_LBU:
22163 gen_ld(ctx, OPC_LBU, rt, rs, u);
22164 break;
22165 case NM_LHU:
22166 gen_ld(ctx, OPC_LHU, rt, rs, u);
22167 break;
22168 case NM_SB:
22169 gen_st(ctx, OPC_SB, rt, rs, u);
22170 break;
22171 case NM_SH:
22172 gen_st(ctx, OPC_SH, rt, rs, u);
22173 break;
22174 case NM_SW:
22175 gen_st(ctx, OPC_SW, rt, rs, u);
22176 break;
22177 case NM_LWC1:
22178 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
22179 break;
22180 case NM_LDC1:
22181 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
22182 break;
22183 case NM_SWC1:
22184 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
22185 break;
22186 case NM_SDC1:
22187 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
22188 break;
22189 default:
22190 gen_reserved_instruction(ctx);
22191 break;
22194 break;
22195 case NM_P_LS_S9:
22197 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
22198 extract32(ctx->opcode, 0, 8);
22200 switch (extract32(ctx->opcode, 8, 3)) {
22201 case NM_P_LS_S0:
22202 switch (extract32(ctx->opcode, 11, 4)) {
22203 case NM_LBS9:
22204 gen_ld(ctx, OPC_LB, rt, rs, s);
22205 break;
22206 case NM_LHS9:
22207 gen_ld(ctx, OPC_LH, rt, rs, s);
22208 break;
22209 case NM_LWS9:
22210 gen_ld(ctx, OPC_LW, rt, rs, s);
22211 break;
22212 case NM_LBUS9:
22213 gen_ld(ctx, OPC_LBU, rt, rs, s);
22214 break;
22215 case NM_LHUS9:
22216 gen_ld(ctx, OPC_LHU, rt, rs, s);
22217 break;
22218 case NM_SBS9:
22219 gen_st(ctx, OPC_SB, rt, rs, s);
22220 break;
22221 case NM_SHS9:
22222 gen_st(ctx, OPC_SH, rt, rs, s);
22223 break;
22224 case NM_SWS9:
22225 gen_st(ctx, OPC_SW, rt, rs, s);
22226 break;
22227 case NM_LWC1S9:
22228 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
22229 break;
22230 case NM_LDC1S9:
22231 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
22232 break;
22233 case NM_SWC1S9:
22234 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
22235 break;
22236 case NM_SDC1S9:
22237 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
22238 break;
22239 case NM_P_PREFS9:
22240 if (rt == 31) {
22241 /* SYNCI */
22243 * Break the TB to be able to sync copied instructions
22244 * immediately.
22246 ctx->base.is_jmp = DISAS_STOP;
22247 } else {
22248 /* PREF */
22249 /* Treat as NOP. */
22251 break;
22252 default:
22253 gen_reserved_instruction(ctx);
22254 break;
22256 break;
22257 case NM_P_LS_S1:
22258 switch (extract32(ctx->opcode, 11, 4)) {
22259 case NM_UALH:
22260 case NM_UASH:
22261 check_nms(ctx);
22263 TCGv t0 = tcg_temp_new();
22264 TCGv t1 = tcg_temp_new();
22266 gen_base_offset_addr(ctx, t0, rs, s);
22268 switch (extract32(ctx->opcode, 11, 4)) {
22269 case NM_UALH:
22270 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
22271 MO_UNALN);
22272 gen_store_gpr(t0, rt);
22273 break;
22274 case NM_UASH:
22275 gen_load_gpr(t1, rt);
22276 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
22277 MO_UNALN);
22278 break;
22280 tcg_temp_free(t0);
22281 tcg_temp_free(t1);
22283 break;
22284 case NM_P_LL:
22285 switch (ctx->opcode & 0x03) {
22286 case NM_LL:
22287 gen_ld(ctx, OPC_LL, rt, rs, s);
22288 break;
22289 case NM_LLWP:
22290 check_xnp(ctx);
22291 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22292 break;
22294 break;
22295 case NM_P_SC:
22296 switch (ctx->opcode & 0x03) {
22297 case NM_SC:
22298 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
22299 break;
22300 case NM_SCWP:
22301 check_xnp(ctx);
22302 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22303 false);
22304 break;
22306 break;
22307 case NM_CACHE:
22308 check_cp0_enabled(ctx);
22309 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22310 gen_cache_operation(ctx, rt, rs, s);
22312 break;
22314 break;
22315 case NM_P_LS_E0:
22316 switch (extract32(ctx->opcode, 11, 4)) {
22317 case NM_LBE:
22318 check_eva(ctx);
22319 check_cp0_enabled(ctx);
22320 gen_ld(ctx, OPC_LBE, rt, rs, s);
22321 break;
22322 case NM_SBE:
22323 check_eva(ctx);
22324 check_cp0_enabled(ctx);
22325 gen_st(ctx, OPC_SBE, rt, rs, s);
22326 break;
22327 case NM_LBUE:
22328 check_eva(ctx);
22329 check_cp0_enabled(ctx);
22330 gen_ld(ctx, OPC_LBUE, rt, rs, s);
22331 break;
22332 case NM_P_PREFE:
22333 if (rt == 31) {
22334 /* case NM_SYNCIE */
22335 check_eva(ctx);
22336 check_cp0_enabled(ctx);
22338 * Break the TB to be able to sync copied instructions
22339 * immediately.
22341 ctx->base.is_jmp = DISAS_STOP;
22342 } else {
22343 /* case NM_PREFE */
22344 check_eva(ctx);
22345 check_cp0_enabled(ctx);
22346 /* Treat as NOP. */
22348 break;
22349 case NM_LHE:
22350 check_eva(ctx);
22351 check_cp0_enabled(ctx);
22352 gen_ld(ctx, OPC_LHE, rt, rs, s);
22353 break;
22354 case NM_SHE:
22355 check_eva(ctx);
22356 check_cp0_enabled(ctx);
22357 gen_st(ctx, OPC_SHE, rt, rs, s);
22358 break;
22359 case NM_LHUE:
22360 check_eva(ctx);
22361 check_cp0_enabled(ctx);
22362 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22363 break;
22364 case NM_CACHEE:
22365 check_nms_dl_il_sl_tl_l2c(ctx);
22366 gen_cache_operation(ctx, rt, rs, s);
22367 break;
22368 case NM_LWE:
22369 check_eva(ctx);
22370 check_cp0_enabled(ctx);
22371 gen_ld(ctx, OPC_LWE, rt, rs, s);
22372 break;
22373 case NM_SWE:
22374 check_eva(ctx);
22375 check_cp0_enabled(ctx);
22376 gen_st(ctx, OPC_SWE, rt, rs, s);
22377 break;
22378 case NM_P_LLE:
22379 switch (extract32(ctx->opcode, 2, 2)) {
22380 case NM_LLE:
22381 check_xnp(ctx);
22382 check_eva(ctx);
22383 check_cp0_enabled(ctx);
22384 gen_ld(ctx, OPC_LLE, rt, rs, s);
22385 break;
22386 case NM_LLWPE:
22387 check_xnp(ctx);
22388 check_eva(ctx);
22389 check_cp0_enabled(ctx);
22390 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22391 break;
22392 default:
22393 gen_reserved_instruction(ctx);
22394 break;
22396 break;
22397 case NM_P_SCE:
22398 switch (extract32(ctx->opcode, 2, 2)) {
22399 case NM_SCE:
22400 check_xnp(ctx);
22401 check_eva(ctx);
22402 check_cp0_enabled(ctx);
22403 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22404 break;
22405 case NM_SCWPE:
22406 check_xnp(ctx);
22407 check_eva(ctx);
22408 check_cp0_enabled(ctx);
22409 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22410 true);
22411 break;
22412 default:
22413 gen_reserved_instruction(ctx);
22414 break;
22416 break;
22418 break;
22419 case NM_P_LS_WM:
22420 case NM_P_LS_UAWM:
22421 check_nms(ctx);
22423 int count = extract32(ctx->opcode, 12, 3);
22424 int counter = 0;
22426 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22427 extract32(ctx->opcode, 0, 8);
22428 TCGv va = tcg_temp_new();
22429 TCGv t1 = tcg_temp_new();
22430 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22431 NM_P_LS_UAWM ? MO_UNALN : 0;
22433 count = (count == 0) ? 8 : count;
22434 while (counter != count) {
22435 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22436 int this_offset = offset + (counter << 2);
22438 gen_base_offset_addr(ctx, va, rs, this_offset);
22440 switch (extract32(ctx->opcode, 11, 1)) {
22441 case NM_LWM:
22442 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22443 memop | MO_TESL);
22444 gen_store_gpr(t1, this_rt);
22445 if ((this_rt == rs) &&
22446 (counter != (count - 1))) {
22447 /* UNPREDICTABLE */
22449 break;
22450 case NM_SWM:
22451 this_rt = (rt == 0) ? 0 : this_rt;
22452 gen_load_gpr(t1, this_rt);
22453 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22454 memop | MO_TEUL);
22455 break;
22457 counter++;
22459 tcg_temp_free(va);
22460 tcg_temp_free(t1);
22462 break;
22463 default:
22464 gen_reserved_instruction(ctx);
22465 break;
22468 break;
22469 case NM_MOVE_BALC:
22470 check_nms(ctx);
22472 TCGv t0 = tcg_temp_new();
22473 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22474 extract32(ctx->opcode, 1, 20) << 1;
22475 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22476 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22477 extract32(ctx->opcode, 21, 3));
22478 gen_load_gpr(t0, rt);
22479 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22480 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22481 tcg_temp_free(t0);
22483 break;
22484 case NM_P_BAL:
22486 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22487 extract32(ctx->opcode, 1, 24) << 1;
22489 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22490 /* BC */
22491 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22492 } else {
22493 /* BALC */
22494 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22497 break;
22498 case NM_P_J:
22499 switch (extract32(ctx->opcode, 12, 4)) {
22500 case NM_JALRC:
22501 case NM_JALRC_HB:
22502 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22503 break;
22504 case NM_P_BALRSC:
22505 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22506 break;
22507 default:
22508 gen_reserved_instruction(ctx);
22509 break;
22511 break;
22512 case NM_P_BR1:
22514 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22515 extract32(ctx->opcode, 1, 13) << 1;
22516 switch (extract32(ctx->opcode, 14, 2)) {
22517 case NM_BEQC:
22518 check_nms(ctx);
22519 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22520 break;
22521 case NM_P_BR3A:
22522 s = sextract32(ctx->opcode, 0, 1) << 14 |
22523 extract32(ctx->opcode, 1, 13) << 1;
22524 check_cp1_enabled(ctx);
22525 switch (extract32(ctx->opcode, 16, 5)) {
22526 case NM_BC1EQZC:
22527 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22528 break;
22529 case NM_BC1NEZC:
22530 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22531 break;
22532 case NM_BPOSGE32C:
22533 check_dsp_r3(ctx);
22535 int32_t imm = extract32(ctx->opcode, 1, 13) |
22536 extract32(ctx->opcode, 0, 1) << 13;
22538 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22539 imm);
22541 break;
22542 default:
22543 gen_reserved_instruction(ctx);
22544 break;
22546 break;
22547 case NM_BGEC:
22548 if (rs == rt) {
22549 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22550 } else {
22551 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22553 break;
22554 case NM_BGEUC:
22555 if (rs == rt || rt == 0) {
22556 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22557 } else if (rs == 0) {
22558 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22559 } else {
22560 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22562 break;
22565 break;
22566 case NM_P_BR2:
22568 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22569 extract32(ctx->opcode, 1, 13) << 1;
22570 switch (extract32(ctx->opcode, 14, 2)) {
22571 case NM_BNEC:
22572 check_nms(ctx);
22573 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22574 break;
22575 case NM_BLTC:
22576 if (rs != 0 && rt != 0 && rs == rt) {
22577 /* NOP */
22578 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22579 } else {
22580 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22582 break;
22583 case NM_BLTUC:
22584 if (rs == 0 || rs == rt) {
22585 /* NOP */
22586 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22587 } else {
22588 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22590 break;
22591 default:
22592 gen_reserved_instruction(ctx);
22593 break;
22596 break;
22597 case NM_P_BRI:
22599 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22600 extract32(ctx->opcode, 1, 10) << 1;
22601 uint32_t u = extract32(ctx->opcode, 11, 7);
22603 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22604 rt, u, s);
22606 break;
22607 default:
22608 gen_reserved_instruction(ctx);
22609 break;
22611 return 4;
22614 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22616 uint32_t op;
22617 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22618 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22619 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22620 int offset;
22621 int imm;
22623 /* make sure instructions are on a halfword boundary */
22624 if (ctx->base.pc_next & 0x1) {
22625 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22626 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22627 tcg_temp_free(tmp);
22628 generate_exception_end(ctx, EXCP_AdEL);
22629 return 2;
22632 op = extract32(ctx->opcode, 10, 6);
22633 switch (op) {
22634 case NM_P16_MV:
22635 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22636 if (rt != 0) {
22637 /* MOVE */
22638 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22639 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22640 } else {
22641 /* P16.RI */
22642 switch (extract32(ctx->opcode, 3, 2)) {
22643 case NM_P16_SYSCALL:
22644 if (extract32(ctx->opcode, 2, 1) == 0) {
22645 generate_exception_end(ctx, EXCP_SYSCALL);
22646 } else {
22647 gen_reserved_instruction(ctx);
22649 break;
22650 case NM_BREAK16:
22651 generate_exception_end(ctx, EXCP_BREAK);
22652 break;
22653 case NM_SDBBP16:
22654 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22655 gen_helper_do_semihosting(cpu_env);
22656 } else {
22657 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22658 gen_reserved_instruction(ctx);
22659 } else {
22660 generate_exception_end(ctx, EXCP_DBp);
22663 break;
22664 default:
22665 gen_reserved_instruction(ctx);
22666 break;
22669 break;
22670 case NM_P16_SHIFT:
22672 int shift = extract32(ctx->opcode, 0, 3);
22673 uint32_t opc = 0;
22674 shift = (shift == 0) ? 8 : shift;
22676 switch (extract32(ctx->opcode, 3, 1)) {
22677 case NM_SLL16:
22678 opc = OPC_SLL;
22679 break;
22680 case NM_SRL16:
22681 opc = OPC_SRL;
22682 break;
22684 gen_shift_imm(ctx, opc, rt, rs, shift);
22686 break;
22687 case NM_P16C:
22688 switch (ctx->opcode & 1) {
22689 case NM_POOL16C_0:
22690 gen_pool16c_nanomips_insn(ctx);
22691 break;
22692 case NM_LWXS16:
22693 gen_ldxs(ctx, rt, rs, rd);
22694 break;
22696 break;
22697 case NM_P16_A1:
22698 switch (extract32(ctx->opcode, 6, 1)) {
22699 case NM_ADDIUR1SP:
22700 imm = extract32(ctx->opcode, 0, 6) << 2;
22701 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22702 break;
22703 default:
22704 gen_reserved_instruction(ctx);
22705 break;
22707 break;
22708 case NM_P16_A2:
22709 switch (extract32(ctx->opcode, 3, 1)) {
22710 case NM_ADDIUR2:
22711 imm = extract32(ctx->opcode, 0, 3) << 2;
22712 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22713 break;
22714 case NM_P_ADDIURS5:
22715 rt = extract32(ctx->opcode, 5, 5);
22716 if (rt != 0) {
22717 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22718 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22719 (extract32(ctx->opcode, 0, 3));
22720 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22722 break;
22724 break;
22725 case NM_P16_ADDU:
22726 switch (ctx->opcode & 0x1) {
22727 case NM_ADDU16:
22728 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22729 break;
22730 case NM_SUBU16:
22731 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22732 break;
22734 break;
22735 case NM_P16_4X4:
22736 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22737 extract32(ctx->opcode, 5, 3);
22738 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22739 extract32(ctx->opcode, 0, 3);
22740 rt = decode_gpr_gpr4(rt);
22741 rs = decode_gpr_gpr4(rs);
22742 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22743 (extract32(ctx->opcode, 3, 1))) {
22744 case NM_ADDU4X4:
22745 check_nms(ctx);
22746 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22747 break;
22748 case NM_MUL4X4:
22749 check_nms(ctx);
22750 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22751 break;
22752 default:
22753 gen_reserved_instruction(ctx);
22754 break;
22756 break;
22757 case NM_LI16:
22759 int imm = extract32(ctx->opcode, 0, 7);
22760 imm = (imm == 0x7f ? -1 : imm);
22761 if (rt != 0) {
22762 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22765 break;
22766 case NM_ANDI16:
22768 uint32_t u = extract32(ctx->opcode, 0, 4);
22769 u = (u == 12) ? 0xff :
22770 (u == 13) ? 0xffff : u;
22771 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22773 break;
22774 case NM_P16_LB:
22775 offset = extract32(ctx->opcode, 0, 2);
22776 switch (extract32(ctx->opcode, 2, 2)) {
22777 case NM_LB16:
22778 gen_ld(ctx, OPC_LB, rt, rs, offset);
22779 break;
22780 case NM_SB16:
22781 rt = decode_gpr_gpr3_src_store(
22782 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22783 gen_st(ctx, OPC_SB, rt, rs, offset);
22784 break;
22785 case NM_LBU16:
22786 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22787 break;
22788 default:
22789 gen_reserved_instruction(ctx);
22790 break;
22792 break;
22793 case NM_P16_LH:
22794 offset = extract32(ctx->opcode, 1, 2) << 1;
22795 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22796 case NM_LH16:
22797 gen_ld(ctx, OPC_LH, rt, rs, offset);
22798 break;
22799 case NM_SH16:
22800 rt = decode_gpr_gpr3_src_store(
22801 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22802 gen_st(ctx, OPC_SH, rt, rs, offset);
22803 break;
22804 case NM_LHU16:
22805 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22806 break;
22807 default:
22808 gen_reserved_instruction(ctx);
22809 break;
22811 break;
22812 case NM_LW16:
22813 offset = extract32(ctx->opcode, 0, 4) << 2;
22814 gen_ld(ctx, OPC_LW, rt, rs, offset);
22815 break;
22816 case NM_LWSP16:
22817 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22818 offset = extract32(ctx->opcode, 0, 5) << 2;
22819 gen_ld(ctx, OPC_LW, rt, 29, offset);
22820 break;
22821 case NM_LW4X4:
22822 check_nms(ctx);
22823 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22824 extract32(ctx->opcode, 5, 3);
22825 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22826 extract32(ctx->opcode, 0, 3);
22827 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22828 (extract32(ctx->opcode, 8, 1) << 2);
22829 rt = decode_gpr_gpr4(rt);
22830 rs = decode_gpr_gpr4(rs);
22831 gen_ld(ctx, OPC_LW, rt, rs, offset);
22832 break;
22833 case NM_SW4X4:
22834 check_nms(ctx);
22835 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22836 extract32(ctx->opcode, 5, 3);
22837 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22838 extract32(ctx->opcode, 0, 3);
22839 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22840 (extract32(ctx->opcode, 8, 1) << 2);
22841 rt = decode_gpr_gpr4_zero(rt);
22842 rs = decode_gpr_gpr4(rs);
22843 gen_st(ctx, OPC_SW, rt, rs, offset);
22844 break;
22845 case NM_LWGP16:
22846 offset = extract32(ctx->opcode, 0, 7) << 2;
22847 gen_ld(ctx, OPC_LW, rt, 28, offset);
22848 break;
22849 case NM_SWSP16:
22850 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22851 offset = extract32(ctx->opcode, 0, 5) << 2;
22852 gen_st(ctx, OPC_SW, rt, 29, offset);
22853 break;
22854 case NM_SW16:
22855 rt = decode_gpr_gpr3_src_store(
22856 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22857 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22858 offset = extract32(ctx->opcode, 0, 4) << 2;
22859 gen_st(ctx, OPC_SW, rt, rs, offset);
22860 break;
22861 case NM_SWGP16:
22862 rt = decode_gpr_gpr3_src_store(
22863 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22864 offset = extract32(ctx->opcode, 0, 7) << 2;
22865 gen_st(ctx, OPC_SW, rt, 28, offset);
22866 break;
22867 case NM_BC16:
22868 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22869 (sextract32(ctx->opcode, 0, 1) << 10) |
22870 (extract32(ctx->opcode, 1, 9) << 1));
22871 break;
22872 case NM_BALC16:
22873 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22874 (sextract32(ctx->opcode, 0, 1) << 10) |
22875 (extract32(ctx->opcode, 1, 9) << 1));
22876 break;
22877 case NM_BEQZC16:
22878 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22879 (sextract32(ctx->opcode, 0, 1) << 7) |
22880 (extract32(ctx->opcode, 1, 6) << 1));
22881 break;
22882 case NM_BNEZC16:
22883 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22884 (sextract32(ctx->opcode, 0, 1) << 7) |
22885 (extract32(ctx->opcode, 1, 6) << 1));
22886 break;
22887 case NM_P16_BR:
22888 switch (ctx->opcode & 0xf) {
22889 case 0:
22890 /* P16.JRC */
22891 switch (extract32(ctx->opcode, 4, 1)) {
22892 case NM_JRC:
22893 gen_compute_branch_nm(ctx, OPC_JR, 2,
22894 extract32(ctx->opcode, 5, 5), 0, 0);
22895 break;
22896 case NM_JALRC16:
22897 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22898 extract32(ctx->opcode, 5, 5), 31, 0);
22899 break;
22901 break;
22902 default:
22904 /* P16.BRI */
22905 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22906 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22907 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22908 extract32(ctx->opcode, 0, 4) << 1);
22910 break;
22912 break;
22913 case NM_P16_SR:
22915 int count = extract32(ctx->opcode, 0, 4);
22916 int u = extract32(ctx->opcode, 4, 4) << 4;
22918 rt = 30 + extract32(ctx->opcode, 9, 1);
22919 switch (extract32(ctx->opcode, 8, 1)) {
22920 case NM_SAVE16:
22921 gen_save(ctx, rt, count, 0, u);
22922 break;
22923 case NM_RESTORE_JRC16:
22924 gen_restore(ctx, rt, count, 0, u);
22925 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22926 break;
22929 break;
22930 case NM_MOVEP:
22931 case NM_MOVEPREV:
22932 check_nms(ctx);
22934 static const int gpr2reg1[] = {4, 5, 6, 7};
22935 static const int gpr2reg2[] = {5, 6, 7, 8};
22936 int re;
22937 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22938 extract32(ctx->opcode, 8, 1);
22939 int r1 = gpr2reg1[rd2];
22940 int r2 = gpr2reg2[rd2];
22941 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22942 extract32(ctx->opcode, 0, 3);
22943 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22944 extract32(ctx->opcode, 5, 3);
22945 TCGv t0 = tcg_temp_new();
22946 TCGv t1 = tcg_temp_new();
22947 if (op == NM_MOVEP) {
22948 rd = r1;
22949 re = r2;
22950 rs = decode_gpr_gpr4_zero(r3);
22951 rt = decode_gpr_gpr4_zero(r4);
22952 } else {
22953 rd = decode_gpr_gpr4(r3);
22954 re = decode_gpr_gpr4(r4);
22955 rs = r1;
22956 rt = r2;
22958 gen_load_gpr(t0, rs);
22959 gen_load_gpr(t1, rt);
22960 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22961 tcg_gen_mov_tl(cpu_gpr[re], t1);
22962 tcg_temp_free(t0);
22963 tcg_temp_free(t1);
22965 break;
22966 default:
22967 return decode_nanomips_32_48_opc(env, ctx);
22970 return 2;
22974 /* SmartMIPS extension to MIPS32 */
22976 #if defined(TARGET_MIPS64)
22978 /* MDMX extension to MIPS64 */
22980 #endif
22982 /* MIPSDSP functions. */
22983 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22984 int rd, int base, int offset)
22986 TCGv t0;
22988 check_dsp(ctx);
22989 t0 = tcg_temp_new();
22991 if (base == 0) {
22992 gen_load_gpr(t0, offset);
22993 } else if (offset == 0) {
22994 gen_load_gpr(t0, base);
22995 } else {
22996 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22999 switch (opc) {
23000 case OPC_LBUX:
23001 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
23002 gen_store_gpr(t0, rd);
23003 break;
23004 case OPC_LHX:
23005 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
23006 gen_store_gpr(t0, rd);
23007 break;
23008 case OPC_LWX:
23009 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
23010 gen_store_gpr(t0, rd);
23011 break;
23012 #if defined(TARGET_MIPS64)
23013 case OPC_LDX:
23014 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
23015 gen_store_gpr(t0, rd);
23016 break;
23017 #endif
23019 tcg_temp_free(t0);
23022 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
23023 int ret, int v1, int v2)
23025 TCGv v1_t;
23026 TCGv v2_t;
23028 if (ret == 0) {
23029 /* Treat as NOP. */
23030 return;
23033 v1_t = tcg_temp_new();
23034 v2_t = tcg_temp_new();
23036 gen_load_gpr(v1_t, v1);
23037 gen_load_gpr(v2_t, v2);
23039 switch (op1) {
23040 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
23041 case OPC_MULT_G_2E:
23042 check_dsp_r2(ctx);
23043 switch (op2) {
23044 case OPC_ADDUH_QB:
23045 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
23046 break;
23047 case OPC_ADDUH_R_QB:
23048 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23049 break;
23050 case OPC_ADDQH_PH:
23051 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
23052 break;
23053 case OPC_ADDQH_R_PH:
23054 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23055 break;
23056 case OPC_ADDQH_W:
23057 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
23058 break;
23059 case OPC_ADDQH_R_W:
23060 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23061 break;
23062 case OPC_SUBUH_QB:
23063 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
23064 break;
23065 case OPC_SUBUH_R_QB:
23066 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23067 break;
23068 case OPC_SUBQH_PH:
23069 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
23070 break;
23071 case OPC_SUBQH_R_PH:
23072 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23073 break;
23074 case OPC_SUBQH_W:
23075 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
23076 break;
23077 case OPC_SUBQH_R_W:
23078 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23079 break;
23081 break;
23082 case OPC_ABSQ_S_PH_DSP:
23083 switch (op2) {
23084 case OPC_ABSQ_S_QB:
23085 check_dsp_r2(ctx);
23086 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
23087 break;
23088 case OPC_ABSQ_S_PH:
23089 check_dsp(ctx);
23090 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
23091 break;
23092 case OPC_ABSQ_S_W:
23093 check_dsp(ctx);
23094 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
23095 break;
23096 case OPC_PRECEQ_W_PHL:
23097 check_dsp(ctx);
23098 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
23099 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23100 break;
23101 case OPC_PRECEQ_W_PHR:
23102 check_dsp(ctx);
23103 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
23104 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
23105 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23106 break;
23107 case OPC_PRECEQU_PH_QBL:
23108 check_dsp(ctx);
23109 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
23110 break;
23111 case OPC_PRECEQU_PH_QBR:
23112 check_dsp(ctx);
23113 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
23114 break;
23115 case OPC_PRECEQU_PH_QBLA:
23116 check_dsp(ctx);
23117 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
23118 break;
23119 case OPC_PRECEQU_PH_QBRA:
23120 check_dsp(ctx);
23121 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
23122 break;
23123 case OPC_PRECEU_PH_QBL:
23124 check_dsp(ctx);
23125 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
23126 break;
23127 case OPC_PRECEU_PH_QBR:
23128 check_dsp(ctx);
23129 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
23130 break;
23131 case OPC_PRECEU_PH_QBLA:
23132 check_dsp(ctx);
23133 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
23134 break;
23135 case OPC_PRECEU_PH_QBRA:
23136 check_dsp(ctx);
23137 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
23138 break;
23140 break;
23141 case OPC_ADDU_QB_DSP:
23142 switch (op2) {
23143 case OPC_ADDQ_PH:
23144 check_dsp(ctx);
23145 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23146 break;
23147 case OPC_ADDQ_S_PH:
23148 check_dsp(ctx);
23149 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23150 break;
23151 case OPC_ADDQ_S_W:
23152 check_dsp(ctx);
23153 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23154 break;
23155 case OPC_ADDU_QB:
23156 check_dsp(ctx);
23157 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23158 break;
23159 case OPC_ADDU_S_QB:
23160 check_dsp(ctx);
23161 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23162 break;
23163 case OPC_ADDU_PH:
23164 check_dsp_r2(ctx);
23165 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23166 break;
23167 case OPC_ADDU_S_PH:
23168 check_dsp_r2(ctx);
23169 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23170 break;
23171 case OPC_SUBQ_PH:
23172 check_dsp(ctx);
23173 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23174 break;
23175 case OPC_SUBQ_S_PH:
23176 check_dsp(ctx);
23177 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23178 break;
23179 case OPC_SUBQ_S_W:
23180 check_dsp(ctx);
23181 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_SUBU_QB:
23184 check_dsp(ctx);
23185 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23186 break;
23187 case OPC_SUBU_S_QB:
23188 check_dsp(ctx);
23189 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23190 break;
23191 case OPC_SUBU_PH:
23192 check_dsp_r2(ctx);
23193 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23194 break;
23195 case OPC_SUBU_S_PH:
23196 check_dsp_r2(ctx);
23197 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23198 break;
23199 case OPC_ADDSC:
23200 check_dsp(ctx);
23201 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23202 break;
23203 case OPC_ADDWC:
23204 check_dsp(ctx);
23205 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23206 break;
23207 case OPC_MODSUB:
23208 check_dsp(ctx);
23209 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
23210 break;
23211 case OPC_RADDU_W_QB:
23212 check_dsp(ctx);
23213 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
23214 break;
23216 break;
23217 case OPC_CMPU_EQ_QB_DSP:
23218 switch (op2) {
23219 case OPC_PRECR_QB_PH:
23220 check_dsp_r2(ctx);
23221 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23222 break;
23223 case OPC_PRECRQ_QB_PH:
23224 check_dsp(ctx);
23225 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23226 break;
23227 case OPC_PRECR_SRA_PH_W:
23228 check_dsp_r2(ctx);
23230 TCGv_i32 sa_t = tcg_const_i32(v2);
23231 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
23232 cpu_gpr[ret]);
23233 tcg_temp_free_i32(sa_t);
23234 break;
23236 case OPC_PRECR_SRA_R_PH_W:
23237 check_dsp_r2(ctx);
23239 TCGv_i32 sa_t = tcg_const_i32(v2);
23240 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
23241 cpu_gpr[ret]);
23242 tcg_temp_free_i32(sa_t);
23243 break;
23245 case OPC_PRECRQ_PH_W:
23246 check_dsp(ctx);
23247 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
23248 break;
23249 case OPC_PRECRQ_RS_PH_W:
23250 check_dsp(ctx);
23251 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23252 break;
23253 case OPC_PRECRQU_S_QB_PH:
23254 check_dsp(ctx);
23255 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23256 break;
23258 break;
23259 #ifdef TARGET_MIPS64
23260 case OPC_ABSQ_S_QH_DSP:
23261 switch (op2) {
23262 case OPC_PRECEQ_L_PWL:
23263 check_dsp(ctx);
23264 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
23265 break;
23266 case OPC_PRECEQ_L_PWR:
23267 check_dsp(ctx);
23268 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
23269 break;
23270 case OPC_PRECEQ_PW_QHL:
23271 check_dsp(ctx);
23272 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
23273 break;
23274 case OPC_PRECEQ_PW_QHR:
23275 check_dsp(ctx);
23276 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
23277 break;
23278 case OPC_PRECEQ_PW_QHLA:
23279 check_dsp(ctx);
23280 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
23281 break;
23282 case OPC_PRECEQ_PW_QHRA:
23283 check_dsp(ctx);
23284 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
23285 break;
23286 case OPC_PRECEQU_QH_OBL:
23287 check_dsp(ctx);
23288 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
23289 break;
23290 case OPC_PRECEQU_QH_OBR:
23291 check_dsp(ctx);
23292 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
23293 break;
23294 case OPC_PRECEQU_QH_OBLA:
23295 check_dsp(ctx);
23296 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
23297 break;
23298 case OPC_PRECEQU_QH_OBRA:
23299 check_dsp(ctx);
23300 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
23301 break;
23302 case OPC_PRECEU_QH_OBL:
23303 check_dsp(ctx);
23304 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
23305 break;
23306 case OPC_PRECEU_QH_OBR:
23307 check_dsp(ctx);
23308 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
23309 break;
23310 case OPC_PRECEU_QH_OBLA:
23311 check_dsp(ctx);
23312 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
23313 break;
23314 case OPC_PRECEU_QH_OBRA:
23315 check_dsp(ctx);
23316 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
23317 break;
23318 case OPC_ABSQ_S_OB:
23319 check_dsp_r2(ctx);
23320 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
23321 break;
23322 case OPC_ABSQ_S_PW:
23323 check_dsp(ctx);
23324 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
23325 break;
23326 case OPC_ABSQ_S_QH:
23327 check_dsp(ctx);
23328 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
23329 break;
23331 break;
23332 case OPC_ADDU_OB_DSP:
23333 switch (op2) {
23334 case OPC_RADDU_L_OB:
23335 check_dsp(ctx);
23336 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
23337 break;
23338 case OPC_SUBQ_PW:
23339 check_dsp(ctx);
23340 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23341 break;
23342 case OPC_SUBQ_S_PW:
23343 check_dsp(ctx);
23344 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23345 break;
23346 case OPC_SUBQ_QH:
23347 check_dsp(ctx);
23348 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23349 break;
23350 case OPC_SUBQ_S_QH:
23351 check_dsp(ctx);
23352 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23353 break;
23354 case OPC_SUBU_OB:
23355 check_dsp(ctx);
23356 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23357 break;
23358 case OPC_SUBU_S_OB:
23359 check_dsp(ctx);
23360 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23361 break;
23362 case OPC_SUBU_QH:
23363 check_dsp_r2(ctx);
23364 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23365 break;
23366 case OPC_SUBU_S_QH:
23367 check_dsp_r2(ctx);
23368 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23369 break;
23370 case OPC_SUBUH_OB:
23371 check_dsp_r2(ctx);
23372 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23373 break;
23374 case OPC_SUBUH_R_OB:
23375 check_dsp_r2(ctx);
23376 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23377 break;
23378 case OPC_ADDQ_PW:
23379 check_dsp(ctx);
23380 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23381 break;
23382 case OPC_ADDQ_S_PW:
23383 check_dsp(ctx);
23384 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23385 break;
23386 case OPC_ADDQ_QH:
23387 check_dsp(ctx);
23388 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23389 break;
23390 case OPC_ADDQ_S_QH:
23391 check_dsp(ctx);
23392 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23393 break;
23394 case OPC_ADDU_OB:
23395 check_dsp(ctx);
23396 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23397 break;
23398 case OPC_ADDU_S_OB:
23399 check_dsp(ctx);
23400 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23401 break;
23402 case OPC_ADDU_QH:
23403 check_dsp_r2(ctx);
23404 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23405 break;
23406 case OPC_ADDU_S_QH:
23407 check_dsp_r2(ctx);
23408 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23409 break;
23410 case OPC_ADDUH_OB:
23411 check_dsp_r2(ctx);
23412 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23413 break;
23414 case OPC_ADDUH_R_OB:
23415 check_dsp_r2(ctx);
23416 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23417 break;
23419 break;
23420 case OPC_CMPU_EQ_OB_DSP:
23421 switch (op2) {
23422 case OPC_PRECR_OB_QH:
23423 check_dsp_r2(ctx);
23424 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23425 break;
23426 case OPC_PRECR_SRA_QH_PW:
23427 check_dsp_r2(ctx);
23429 TCGv_i32 ret_t = tcg_const_i32(ret);
23430 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23431 tcg_temp_free_i32(ret_t);
23432 break;
23434 case OPC_PRECR_SRA_R_QH_PW:
23435 check_dsp_r2(ctx);
23437 TCGv_i32 sa_v = tcg_const_i32(ret);
23438 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23439 tcg_temp_free_i32(sa_v);
23440 break;
23442 case OPC_PRECRQ_OB_QH:
23443 check_dsp(ctx);
23444 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23445 break;
23446 case OPC_PRECRQ_PW_L:
23447 check_dsp(ctx);
23448 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23449 break;
23450 case OPC_PRECRQ_QH_PW:
23451 check_dsp(ctx);
23452 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23453 break;
23454 case OPC_PRECRQ_RS_QH_PW:
23455 check_dsp(ctx);
23456 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23457 break;
23458 case OPC_PRECRQU_S_OB_QH:
23459 check_dsp(ctx);
23460 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23461 break;
23463 break;
23464 #endif
23467 tcg_temp_free(v1_t);
23468 tcg_temp_free(v2_t);
23471 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23472 int ret, int v1, int v2)
23474 uint32_t op2;
23475 TCGv t0;
23476 TCGv v1_t;
23477 TCGv v2_t;
23479 if (ret == 0) {
23480 /* Treat as NOP. */
23481 return;
23484 t0 = tcg_temp_new();
23485 v1_t = tcg_temp_new();
23486 v2_t = tcg_temp_new();
23488 tcg_gen_movi_tl(t0, v1);
23489 gen_load_gpr(v1_t, v1);
23490 gen_load_gpr(v2_t, v2);
23492 switch (opc) {
23493 case OPC_SHLL_QB_DSP:
23495 op2 = MASK_SHLL_QB(ctx->opcode);
23496 switch (op2) {
23497 case OPC_SHLL_QB:
23498 check_dsp(ctx);
23499 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23500 break;
23501 case OPC_SHLLV_QB:
23502 check_dsp(ctx);
23503 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23504 break;
23505 case OPC_SHLL_PH:
23506 check_dsp(ctx);
23507 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23508 break;
23509 case OPC_SHLLV_PH:
23510 check_dsp(ctx);
23511 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23512 break;
23513 case OPC_SHLL_S_PH:
23514 check_dsp(ctx);
23515 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23516 break;
23517 case OPC_SHLLV_S_PH:
23518 check_dsp(ctx);
23519 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23520 break;
23521 case OPC_SHLL_S_W:
23522 check_dsp(ctx);
23523 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23524 break;
23525 case OPC_SHLLV_S_W:
23526 check_dsp(ctx);
23527 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23528 break;
23529 case OPC_SHRL_QB:
23530 check_dsp(ctx);
23531 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23532 break;
23533 case OPC_SHRLV_QB:
23534 check_dsp(ctx);
23535 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23536 break;
23537 case OPC_SHRL_PH:
23538 check_dsp_r2(ctx);
23539 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23540 break;
23541 case OPC_SHRLV_PH:
23542 check_dsp_r2(ctx);
23543 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23544 break;
23545 case OPC_SHRA_QB:
23546 check_dsp_r2(ctx);
23547 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23548 break;
23549 case OPC_SHRA_R_QB:
23550 check_dsp_r2(ctx);
23551 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23552 break;
23553 case OPC_SHRAV_QB:
23554 check_dsp_r2(ctx);
23555 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23556 break;
23557 case OPC_SHRAV_R_QB:
23558 check_dsp_r2(ctx);
23559 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23560 break;
23561 case OPC_SHRA_PH:
23562 check_dsp(ctx);
23563 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23564 break;
23565 case OPC_SHRA_R_PH:
23566 check_dsp(ctx);
23567 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23568 break;
23569 case OPC_SHRAV_PH:
23570 check_dsp(ctx);
23571 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23572 break;
23573 case OPC_SHRAV_R_PH:
23574 check_dsp(ctx);
23575 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23576 break;
23577 case OPC_SHRA_R_W:
23578 check_dsp(ctx);
23579 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23580 break;
23581 case OPC_SHRAV_R_W:
23582 check_dsp(ctx);
23583 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23584 break;
23585 default: /* Invalid */
23586 MIPS_INVAL("MASK SHLL.QB");
23587 gen_reserved_instruction(ctx);
23588 break;
23590 break;
23592 #ifdef TARGET_MIPS64
23593 case OPC_SHLL_OB_DSP:
23594 op2 = MASK_SHLL_OB(ctx->opcode);
23595 switch (op2) {
23596 case OPC_SHLL_PW:
23597 check_dsp(ctx);
23598 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23599 break;
23600 case OPC_SHLLV_PW:
23601 check_dsp(ctx);
23602 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23603 break;
23604 case OPC_SHLL_S_PW:
23605 check_dsp(ctx);
23606 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23607 break;
23608 case OPC_SHLLV_S_PW:
23609 check_dsp(ctx);
23610 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23611 break;
23612 case OPC_SHLL_OB:
23613 check_dsp(ctx);
23614 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23615 break;
23616 case OPC_SHLLV_OB:
23617 check_dsp(ctx);
23618 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23619 break;
23620 case OPC_SHLL_QH:
23621 check_dsp(ctx);
23622 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23623 break;
23624 case OPC_SHLLV_QH:
23625 check_dsp(ctx);
23626 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23627 break;
23628 case OPC_SHLL_S_QH:
23629 check_dsp(ctx);
23630 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23631 break;
23632 case OPC_SHLLV_S_QH:
23633 check_dsp(ctx);
23634 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23635 break;
23636 case OPC_SHRA_OB:
23637 check_dsp_r2(ctx);
23638 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23639 break;
23640 case OPC_SHRAV_OB:
23641 check_dsp_r2(ctx);
23642 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23643 break;
23644 case OPC_SHRA_R_OB:
23645 check_dsp_r2(ctx);
23646 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23647 break;
23648 case OPC_SHRAV_R_OB:
23649 check_dsp_r2(ctx);
23650 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23651 break;
23652 case OPC_SHRA_PW:
23653 check_dsp(ctx);
23654 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23655 break;
23656 case OPC_SHRAV_PW:
23657 check_dsp(ctx);
23658 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23659 break;
23660 case OPC_SHRA_R_PW:
23661 check_dsp(ctx);
23662 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23663 break;
23664 case OPC_SHRAV_R_PW:
23665 check_dsp(ctx);
23666 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23667 break;
23668 case OPC_SHRA_QH:
23669 check_dsp(ctx);
23670 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23671 break;
23672 case OPC_SHRAV_QH:
23673 check_dsp(ctx);
23674 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23675 break;
23676 case OPC_SHRA_R_QH:
23677 check_dsp(ctx);
23678 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23679 break;
23680 case OPC_SHRAV_R_QH:
23681 check_dsp(ctx);
23682 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23683 break;
23684 case OPC_SHRL_OB:
23685 check_dsp(ctx);
23686 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23687 break;
23688 case OPC_SHRLV_OB:
23689 check_dsp(ctx);
23690 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23691 break;
23692 case OPC_SHRL_QH:
23693 check_dsp_r2(ctx);
23694 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23695 break;
23696 case OPC_SHRLV_QH:
23697 check_dsp_r2(ctx);
23698 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23699 break;
23700 default: /* Invalid */
23701 MIPS_INVAL("MASK SHLL.OB");
23702 gen_reserved_instruction(ctx);
23703 break;
23705 break;
23706 #endif
23709 tcg_temp_free(t0);
23710 tcg_temp_free(v1_t);
23711 tcg_temp_free(v2_t);
23714 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23715 int ret, int v1, int v2, int check_ret)
23717 TCGv_i32 t0;
23718 TCGv v1_t;
23719 TCGv v2_t;
23721 if ((ret == 0) && (check_ret == 1)) {
23722 /* Treat as NOP. */
23723 return;
23726 t0 = tcg_temp_new_i32();
23727 v1_t = tcg_temp_new();
23728 v2_t = tcg_temp_new();
23730 tcg_gen_movi_i32(t0, ret);
23731 gen_load_gpr(v1_t, v1);
23732 gen_load_gpr(v2_t, v2);
23734 switch (op1) {
23736 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23737 * the same mask and op1.
23739 case OPC_MULT_G_2E:
23740 check_dsp_r2(ctx);
23741 switch (op2) {
23742 case OPC_MUL_PH:
23743 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23744 break;
23745 case OPC_MUL_S_PH:
23746 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23747 break;
23748 case OPC_MULQ_S_W:
23749 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23750 break;
23751 case OPC_MULQ_RS_W:
23752 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23753 break;
23755 break;
23756 case OPC_DPA_W_PH_DSP:
23757 switch (op2) {
23758 case OPC_DPAU_H_QBL:
23759 check_dsp(ctx);
23760 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23761 break;
23762 case OPC_DPAU_H_QBR:
23763 check_dsp(ctx);
23764 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23765 break;
23766 case OPC_DPSU_H_QBL:
23767 check_dsp(ctx);
23768 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23769 break;
23770 case OPC_DPSU_H_QBR:
23771 check_dsp(ctx);
23772 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23773 break;
23774 case OPC_DPA_W_PH:
23775 check_dsp_r2(ctx);
23776 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23777 break;
23778 case OPC_DPAX_W_PH:
23779 check_dsp_r2(ctx);
23780 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23781 break;
23782 case OPC_DPAQ_S_W_PH:
23783 check_dsp(ctx);
23784 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23785 break;
23786 case OPC_DPAQX_S_W_PH:
23787 check_dsp_r2(ctx);
23788 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23789 break;
23790 case OPC_DPAQX_SA_W_PH:
23791 check_dsp_r2(ctx);
23792 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23793 break;
23794 case OPC_DPS_W_PH:
23795 check_dsp_r2(ctx);
23796 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23797 break;
23798 case OPC_DPSX_W_PH:
23799 check_dsp_r2(ctx);
23800 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23801 break;
23802 case OPC_DPSQ_S_W_PH:
23803 check_dsp(ctx);
23804 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23805 break;
23806 case OPC_DPSQX_S_W_PH:
23807 check_dsp_r2(ctx);
23808 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23809 break;
23810 case OPC_DPSQX_SA_W_PH:
23811 check_dsp_r2(ctx);
23812 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23813 break;
23814 case OPC_MULSAQ_S_W_PH:
23815 check_dsp(ctx);
23816 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23817 break;
23818 case OPC_DPAQ_SA_L_W:
23819 check_dsp(ctx);
23820 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23821 break;
23822 case OPC_DPSQ_SA_L_W:
23823 check_dsp(ctx);
23824 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23825 break;
23826 case OPC_MAQ_S_W_PHL:
23827 check_dsp(ctx);
23828 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23829 break;
23830 case OPC_MAQ_S_W_PHR:
23831 check_dsp(ctx);
23832 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23833 break;
23834 case OPC_MAQ_SA_W_PHL:
23835 check_dsp(ctx);
23836 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23837 break;
23838 case OPC_MAQ_SA_W_PHR:
23839 check_dsp(ctx);
23840 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23841 break;
23842 case OPC_MULSA_W_PH:
23843 check_dsp_r2(ctx);
23844 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23845 break;
23847 break;
23848 #ifdef TARGET_MIPS64
23849 case OPC_DPAQ_W_QH_DSP:
23851 int ac = ret & 0x03;
23852 tcg_gen_movi_i32(t0, ac);
23854 switch (op2) {
23855 case OPC_DMADD:
23856 check_dsp(ctx);
23857 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23858 break;
23859 case OPC_DMADDU:
23860 check_dsp(ctx);
23861 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23862 break;
23863 case OPC_DMSUB:
23864 check_dsp(ctx);
23865 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23866 break;
23867 case OPC_DMSUBU:
23868 check_dsp(ctx);
23869 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23870 break;
23871 case OPC_DPA_W_QH:
23872 check_dsp_r2(ctx);
23873 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23874 break;
23875 case OPC_DPAQ_S_W_QH:
23876 check_dsp(ctx);
23877 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23878 break;
23879 case OPC_DPAQ_SA_L_PW:
23880 check_dsp(ctx);
23881 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23882 break;
23883 case OPC_DPAU_H_OBL:
23884 check_dsp(ctx);
23885 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23886 break;
23887 case OPC_DPAU_H_OBR:
23888 check_dsp(ctx);
23889 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23890 break;
23891 case OPC_DPS_W_QH:
23892 check_dsp_r2(ctx);
23893 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23894 break;
23895 case OPC_DPSQ_S_W_QH:
23896 check_dsp(ctx);
23897 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23898 break;
23899 case OPC_DPSQ_SA_L_PW:
23900 check_dsp(ctx);
23901 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23902 break;
23903 case OPC_DPSU_H_OBL:
23904 check_dsp(ctx);
23905 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23906 break;
23907 case OPC_DPSU_H_OBR:
23908 check_dsp(ctx);
23909 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23910 break;
23911 case OPC_MAQ_S_L_PWL:
23912 check_dsp(ctx);
23913 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23914 break;
23915 case OPC_MAQ_S_L_PWR:
23916 check_dsp(ctx);
23917 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23918 break;
23919 case OPC_MAQ_S_W_QHLL:
23920 check_dsp(ctx);
23921 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23922 break;
23923 case OPC_MAQ_SA_W_QHLL:
23924 check_dsp(ctx);
23925 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23926 break;
23927 case OPC_MAQ_S_W_QHLR:
23928 check_dsp(ctx);
23929 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23930 break;
23931 case OPC_MAQ_SA_W_QHLR:
23932 check_dsp(ctx);
23933 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23934 break;
23935 case OPC_MAQ_S_W_QHRL:
23936 check_dsp(ctx);
23937 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23938 break;
23939 case OPC_MAQ_SA_W_QHRL:
23940 check_dsp(ctx);
23941 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23942 break;
23943 case OPC_MAQ_S_W_QHRR:
23944 check_dsp(ctx);
23945 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23946 break;
23947 case OPC_MAQ_SA_W_QHRR:
23948 check_dsp(ctx);
23949 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23950 break;
23951 case OPC_MULSAQ_S_L_PW:
23952 check_dsp(ctx);
23953 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23954 break;
23955 case OPC_MULSAQ_S_W_QH:
23956 check_dsp(ctx);
23957 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23958 break;
23961 break;
23962 #endif
23963 case OPC_ADDU_QB_DSP:
23964 switch (op2) {
23965 case OPC_MULEU_S_PH_QBL:
23966 check_dsp(ctx);
23967 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23968 break;
23969 case OPC_MULEU_S_PH_QBR:
23970 check_dsp(ctx);
23971 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23972 break;
23973 case OPC_MULQ_RS_PH:
23974 check_dsp(ctx);
23975 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23976 break;
23977 case OPC_MULEQ_S_W_PHL:
23978 check_dsp(ctx);
23979 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23980 break;
23981 case OPC_MULEQ_S_W_PHR:
23982 check_dsp(ctx);
23983 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23984 break;
23985 case OPC_MULQ_S_PH:
23986 check_dsp_r2(ctx);
23987 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23988 break;
23990 break;
23991 #ifdef TARGET_MIPS64
23992 case OPC_ADDU_OB_DSP:
23993 switch (op2) {
23994 case OPC_MULEQ_S_PW_QHL:
23995 check_dsp(ctx);
23996 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23997 break;
23998 case OPC_MULEQ_S_PW_QHR:
23999 check_dsp(ctx);
24000 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24001 break;
24002 case OPC_MULEU_S_QH_OBL:
24003 check_dsp(ctx);
24004 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24005 break;
24006 case OPC_MULEU_S_QH_OBR:
24007 check_dsp(ctx);
24008 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24009 break;
24010 case OPC_MULQ_RS_QH:
24011 check_dsp(ctx);
24012 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24013 break;
24015 break;
24016 #endif
24019 tcg_temp_free_i32(t0);
24020 tcg_temp_free(v1_t);
24021 tcg_temp_free(v2_t);
24024 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24025 int ret, int val)
24027 int16_t imm;
24028 TCGv t0;
24029 TCGv val_t;
24031 if (ret == 0) {
24032 /* Treat as NOP. */
24033 return;
24036 t0 = tcg_temp_new();
24037 val_t = tcg_temp_new();
24038 gen_load_gpr(val_t, val);
24040 switch (op1) {
24041 case OPC_ABSQ_S_PH_DSP:
24042 switch (op2) {
24043 case OPC_BITREV:
24044 check_dsp(ctx);
24045 gen_helper_bitrev(cpu_gpr[ret], val_t);
24046 break;
24047 case OPC_REPL_QB:
24048 check_dsp(ctx);
24050 target_long result;
24051 imm = (ctx->opcode >> 16) & 0xFF;
24052 result = (uint32_t)imm << 24 |
24053 (uint32_t)imm << 16 |
24054 (uint32_t)imm << 8 |
24055 (uint32_t)imm;
24056 result = (int32_t)result;
24057 tcg_gen_movi_tl(cpu_gpr[ret], result);
24059 break;
24060 case OPC_REPLV_QB:
24061 check_dsp(ctx);
24062 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24063 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24064 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24065 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24066 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24067 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24068 break;
24069 case OPC_REPL_PH:
24070 check_dsp(ctx);
24072 imm = (ctx->opcode >> 16) & 0x03FF;
24073 imm = (int16_t)(imm << 6) >> 6;
24074 tcg_gen_movi_tl(cpu_gpr[ret], \
24075 (target_long)((int32_t)imm << 16 | \
24076 (uint16_t)imm));
24078 break;
24079 case OPC_REPLV_PH:
24080 check_dsp(ctx);
24081 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24082 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24083 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24084 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24085 break;
24087 break;
24088 #ifdef TARGET_MIPS64
24089 case OPC_ABSQ_S_QH_DSP:
24090 switch (op2) {
24091 case OPC_REPL_OB:
24092 check_dsp(ctx);
24094 target_long temp;
24096 imm = (ctx->opcode >> 16) & 0xFF;
24097 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
24098 temp = (temp << 16) | temp;
24099 temp = (temp << 32) | temp;
24100 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24101 break;
24103 case OPC_REPL_PW:
24104 check_dsp(ctx);
24106 target_long temp;
24108 imm = (ctx->opcode >> 16) & 0x03FF;
24109 imm = (int16_t)(imm << 6) >> 6;
24110 temp = ((target_long)imm << 32) \
24111 | ((target_long)imm & 0xFFFFFFFF);
24112 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24113 break;
24115 case OPC_REPL_QH:
24116 check_dsp(ctx);
24118 target_long temp;
24120 imm = (ctx->opcode >> 16) & 0x03FF;
24121 imm = (int16_t)(imm << 6) >> 6;
24123 temp = ((uint64_t)(uint16_t)imm << 48) |
24124 ((uint64_t)(uint16_t)imm << 32) |
24125 ((uint64_t)(uint16_t)imm << 16) |
24126 (uint64_t)(uint16_t)imm;
24127 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24128 break;
24130 case OPC_REPLV_OB:
24131 check_dsp(ctx);
24132 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24133 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24134 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24135 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24136 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24137 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24138 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24139 break;
24140 case OPC_REPLV_PW:
24141 check_dsp(ctx);
24142 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
24143 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24144 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24145 break;
24146 case OPC_REPLV_QH:
24147 check_dsp(ctx);
24148 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24149 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24150 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24151 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24152 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24153 break;
24155 break;
24156 #endif
24158 tcg_temp_free(t0);
24159 tcg_temp_free(val_t);
24162 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
24163 uint32_t op1, uint32_t op2,
24164 int ret, int v1, int v2, int check_ret)
24166 TCGv t1;
24167 TCGv v1_t;
24168 TCGv v2_t;
24170 if ((ret == 0) && (check_ret == 1)) {
24171 /* Treat as NOP. */
24172 return;
24175 t1 = tcg_temp_new();
24176 v1_t = tcg_temp_new();
24177 v2_t = tcg_temp_new();
24179 gen_load_gpr(v1_t, v1);
24180 gen_load_gpr(v2_t, v2);
24182 switch (op1) {
24183 case OPC_CMPU_EQ_QB_DSP:
24184 switch (op2) {
24185 case OPC_CMPU_EQ_QB:
24186 check_dsp(ctx);
24187 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
24188 break;
24189 case OPC_CMPU_LT_QB:
24190 check_dsp(ctx);
24191 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
24192 break;
24193 case OPC_CMPU_LE_QB:
24194 check_dsp(ctx);
24195 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
24196 break;
24197 case OPC_CMPGU_EQ_QB:
24198 check_dsp(ctx);
24199 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
24200 break;
24201 case OPC_CMPGU_LT_QB:
24202 check_dsp(ctx);
24203 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
24204 break;
24205 case OPC_CMPGU_LE_QB:
24206 check_dsp(ctx);
24207 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
24208 break;
24209 case OPC_CMPGDU_EQ_QB:
24210 check_dsp_r2(ctx);
24211 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
24212 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24213 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24214 tcg_gen_shli_tl(t1, t1, 24);
24215 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24216 break;
24217 case OPC_CMPGDU_LT_QB:
24218 check_dsp_r2(ctx);
24219 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
24220 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24221 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24222 tcg_gen_shli_tl(t1, t1, 24);
24223 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24224 break;
24225 case OPC_CMPGDU_LE_QB:
24226 check_dsp_r2(ctx);
24227 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
24228 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24229 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24230 tcg_gen_shli_tl(t1, t1, 24);
24231 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24232 break;
24233 case OPC_CMP_EQ_PH:
24234 check_dsp(ctx);
24235 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
24236 break;
24237 case OPC_CMP_LT_PH:
24238 check_dsp(ctx);
24239 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
24240 break;
24241 case OPC_CMP_LE_PH:
24242 check_dsp(ctx);
24243 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
24244 break;
24245 case OPC_PICK_QB:
24246 check_dsp(ctx);
24247 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24248 break;
24249 case OPC_PICK_PH:
24250 check_dsp(ctx);
24251 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24252 break;
24253 case OPC_PACKRL_PH:
24254 check_dsp(ctx);
24255 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
24256 break;
24258 break;
24259 #ifdef TARGET_MIPS64
24260 case OPC_CMPU_EQ_OB_DSP:
24261 switch (op2) {
24262 case OPC_CMP_EQ_PW:
24263 check_dsp(ctx);
24264 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
24265 break;
24266 case OPC_CMP_LT_PW:
24267 check_dsp(ctx);
24268 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
24269 break;
24270 case OPC_CMP_LE_PW:
24271 check_dsp(ctx);
24272 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
24273 break;
24274 case OPC_CMP_EQ_QH:
24275 check_dsp(ctx);
24276 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
24277 break;
24278 case OPC_CMP_LT_QH:
24279 check_dsp(ctx);
24280 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
24281 break;
24282 case OPC_CMP_LE_QH:
24283 check_dsp(ctx);
24284 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
24285 break;
24286 case OPC_CMPGDU_EQ_OB:
24287 check_dsp_r2(ctx);
24288 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24289 break;
24290 case OPC_CMPGDU_LT_OB:
24291 check_dsp_r2(ctx);
24292 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24293 break;
24294 case OPC_CMPGDU_LE_OB:
24295 check_dsp_r2(ctx);
24296 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24297 break;
24298 case OPC_CMPGU_EQ_OB:
24299 check_dsp(ctx);
24300 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
24301 break;
24302 case OPC_CMPGU_LT_OB:
24303 check_dsp(ctx);
24304 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
24305 break;
24306 case OPC_CMPGU_LE_OB:
24307 check_dsp(ctx);
24308 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
24309 break;
24310 case OPC_CMPU_EQ_OB:
24311 check_dsp(ctx);
24312 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
24313 break;
24314 case OPC_CMPU_LT_OB:
24315 check_dsp(ctx);
24316 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
24317 break;
24318 case OPC_CMPU_LE_OB:
24319 check_dsp(ctx);
24320 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
24321 break;
24322 case OPC_PACKRL_PW:
24323 check_dsp(ctx);
24324 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
24325 break;
24326 case OPC_PICK_OB:
24327 check_dsp(ctx);
24328 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24329 break;
24330 case OPC_PICK_PW:
24331 check_dsp(ctx);
24332 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24333 break;
24334 case OPC_PICK_QH:
24335 check_dsp(ctx);
24336 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24337 break;
24339 break;
24340 #endif
24343 tcg_temp_free(t1);
24344 tcg_temp_free(v1_t);
24345 tcg_temp_free(v2_t);
24348 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
24349 uint32_t op1, int rt, int rs, int sa)
24351 TCGv t0;
24353 check_dsp_r2(ctx);
24355 if (rt == 0) {
24356 /* Treat as NOP. */
24357 return;
24360 t0 = tcg_temp_new();
24361 gen_load_gpr(t0, rs);
24363 switch (op1) {
24364 case OPC_APPEND_DSP:
24365 switch (MASK_APPEND(ctx->opcode)) {
24366 case OPC_APPEND:
24367 if (sa != 0) {
24368 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24370 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24371 break;
24372 case OPC_PREPEND:
24373 if (sa != 0) {
24374 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24375 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24376 tcg_gen_shli_tl(t0, t0, 32 - sa);
24377 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24379 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24380 break;
24381 case OPC_BALIGN:
24382 sa &= 3;
24383 if (sa != 0 && sa != 2) {
24384 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24385 tcg_gen_ext32u_tl(t0, t0);
24386 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24387 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24389 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24390 break;
24391 default: /* Invalid */
24392 MIPS_INVAL("MASK APPEND");
24393 gen_reserved_instruction(ctx);
24394 break;
24396 break;
24397 #ifdef TARGET_MIPS64
24398 case OPC_DAPPEND_DSP:
24399 switch (MASK_DAPPEND(ctx->opcode)) {
24400 case OPC_DAPPEND:
24401 if (sa != 0) {
24402 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24404 break;
24405 case OPC_PREPENDD:
24406 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24407 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24408 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24409 break;
24410 case OPC_PREPENDW:
24411 if (sa != 0) {
24412 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24413 tcg_gen_shli_tl(t0, t0, 64 - sa);
24414 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24416 break;
24417 case OPC_DBALIGN:
24418 sa &= 7;
24419 if (sa != 0 && sa != 2 && sa != 4) {
24420 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24421 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24422 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24424 break;
24425 default: /* Invalid */
24426 MIPS_INVAL("MASK DAPPEND");
24427 gen_reserved_instruction(ctx);
24428 break;
24430 break;
24431 #endif
24433 tcg_temp_free(t0);
24436 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24437 int ret, int v1, int v2, int check_ret)
24440 TCGv t0;
24441 TCGv t1;
24442 TCGv v1_t;
24443 TCGv v2_t;
24444 int16_t imm;
24446 if ((ret == 0) && (check_ret == 1)) {
24447 /* Treat as NOP. */
24448 return;
24451 t0 = tcg_temp_new();
24452 t1 = tcg_temp_new();
24453 v1_t = tcg_temp_new();
24454 v2_t = tcg_temp_new();
24456 gen_load_gpr(v1_t, v1);
24457 gen_load_gpr(v2_t, v2);
24459 switch (op1) {
24460 case OPC_EXTR_W_DSP:
24461 check_dsp(ctx);
24462 switch (op2) {
24463 case OPC_EXTR_W:
24464 tcg_gen_movi_tl(t0, v2);
24465 tcg_gen_movi_tl(t1, v1);
24466 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24467 break;
24468 case OPC_EXTR_R_W:
24469 tcg_gen_movi_tl(t0, v2);
24470 tcg_gen_movi_tl(t1, v1);
24471 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24472 break;
24473 case OPC_EXTR_RS_W:
24474 tcg_gen_movi_tl(t0, v2);
24475 tcg_gen_movi_tl(t1, v1);
24476 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24477 break;
24478 case OPC_EXTR_S_H:
24479 tcg_gen_movi_tl(t0, v2);
24480 tcg_gen_movi_tl(t1, v1);
24481 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24482 break;
24483 case OPC_EXTRV_S_H:
24484 tcg_gen_movi_tl(t0, v2);
24485 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24486 break;
24487 case OPC_EXTRV_W:
24488 tcg_gen_movi_tl(t0, v2);
24489 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24490 break;
24491 case OPC_EXTRV_R_W:
24492 tcg_gen_movi_tl(t0, v2);
24493 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24494 break;
24495 case OPC_EXTRV_RS_W:
24496 tcg_gen_movi_tl(t0, v2);
24497 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24498 break;
24499 case OPC_EXTP:
24500 tcg_gen_movi_tl(t0, v2);
24501 tcg_gen_movi_tl(t1, v1);
24502 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24503 break;
24504 case OPC_EXTPV:
24505 tcg_gen_movi_tl(t0, v2);
24506 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24507 break;
24508 case OPC_EXTPDP:
24509 tcg_gen_movi_tl(t0, v2);
24510 tcg_gen_movi_tl(t1, v1);
24511 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24512 break;
24513 case OPC_EXTPDPV:
24514 tcg_gen_movi_tl(t0, v2);
24515 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24516 break;
24517 case OPC_SHILO:
24518 imm = (ctx->opcode >> 20) & 0x3F;
24519 tcg_gen_movi_tl(t0, ret);
24520 tcg_gen_movi_tl(t1, imm);
24521 gen_helper_shilo(t0, t1, cpu_env);
24522 break;
24523 case OPC_SHILOV:
24524 tcg_gen_movi_tl(t0, ret);
24525 gen_helper_shilo(t0, v1_t, cpu_env);
24526 break;
24527 case OPC_MTHLIP:
24528 tcg_gen_movi_tl(t0, ret);
24529 gen_helper_mthlip(t0, v1_t, cpu_env);
24530 break;
24531 case OPC_WRDSP:
24532 imm = (ctx->opcode >> 11) & 0x3FF;
24533 tcg_gen_movi_tl(t0, imm);
24534 gen_helper_wrdsp(v1_t, t0, cpu_env);
24535 break;
24536 case OPC_RDDSP:
24537 imm = (ctx->opcode >> 16) & 0x03FF;
24538 tcg_gen_movi_tl(t0, imm);
24539 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24540 break;
24542 break;
24543 #ifdef TARGET_MIPS64
24544 case OPC_DEXTR_W_DSP:
24545 check_dsp(ctx);
24546 switch (op2) {
24547 case OPC_DMTHLIP:
24548 tcg_gen_movi_tl(t0, ret);
24549 gen_helper_dmthlip(v1_t, t0, cpu_env);
24550 break;
24551 case OPC_DSHILO:
24553 int shift = (ctx->opcode >> 19) & 0x7F;
24554 int ac = (ctx->opcode >> 11) & 0x03;
24555 tcg_gen_movi_tl(t0, shift);
24556 tcg_gen_movi_tl(t1, ac);
24557 gen_helper_dshilo(t0, t1, cpu_env);
24558 break;
24560 case OPC_DSHILOV:
24562 int ac = (ctx->opcode >> 11) & 0x03;
24563 tcg_gen_movi_tl(t0, ac);
24564 gen_helper_dshilo(v1_t, t0, cpu_env);
24565 break;
24567 case OPC_DEXTP:
24568 tcg_gen_movi_tl(t0, v2);
24569 tcg_gen_movi_tl(t1, v1);
24571 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24572 break;
24573 case OPC_DEXTPV:
24574 tcg_gen_movi_tl(t0, v2);
24575 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24576 break;
24577 case OPC_DEXTPDP:
24578 tcg_gen_movi_tl(t0, v2);
24579 tcg_gen_movi_tl(t1, v1);
24580 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24581 break;
24582 case OPC_DEXTPDPV:
24583 tcg_gen_movi_tl(t0, v2);
24584 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24585 break;
24586 case OPC_DEXTR_L:
24587 tcg_gen_movi_tl(t0, v2);
24588 tcg_gen_movi_tl(t1, v1);
24589 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24590 break;
24591 case OPC_DEXTR_R_L:
24592 tcg_gen_movi_tl(t0, v2);
24593 tcg_gen_movi_tl(t1, v1);
24594 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24595 break;
24596 case OPC_DEXTR_RS_L:
24597 tcg_gen_movi_tl(t0, v2);
24598 tcg_gen_movi_tl(t1, v1);
24599 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24600 break;
24601 case OPC_DEXTR_W:
24602 tcg_gen_movi_tl(t0, v2);
24603 tcg_gen_movi_tl(t1, v1);
24604 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24605 break;
24606 case OPC_DEXTR_R_W:
24607 tcg_gen_movi_tl(t0, v2);
24608 tcg_gen_movi_tl(t1, v1);
24609 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24610 break;
24611 case OPC_DEXTR_RS_W:
24612 tcg_gen_movi_tl(t0, v2);
24613 tcg_gen_movi_tl(t1, v1);
24614 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24615 break;
24616 case OPC_DEXTR_S_H:
24617 tcg_gen_movi_tl(t0, v2);
24618 tcg_gen_movi_tl(t1, v1);
24619 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24620 break;
24621 case OPC_DEXTRV_S_H:
24622 tcg_gen_movi_tl(t0, v2);
24623 tcg_gen_movi_tl(t1, v1);
24624 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24625 break;
24626 case OPC_DEXTRV_L:
24627 tcg_gen_movi_tl(t0, v2);
24628 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24629 break;
24630 case OPC_DEXTRV_R_L:
24631 tcg_gen_movi_tl(t0, v2);
24632 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24633 break;
24634 case OPC_DEXTRV_RS_L:
24635 tcg_gen_movi_tl(t0, v2);
24636 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24637 break;
24638 case OPC_DEXTRV_W:
24639 tcg_gen_movi_tl(t0, v2);
24640 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24641 break;
24642 case OPC_DEXTRV_R_W:
24643 tcg_gen_movi_tl(t0, v2);
24644 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24645 break;
24646 case OPC_DEXTRV_RS_W:
24647 tcg_gen_movi_tl(t0, v2);
24648 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24649 break;
24651 break;
24652 #endif
24655 tcg_temp_free(t0);
24656 tcg_temp_free(t1);
24657 tcg_temp_free(v1_t);
24658 tcg_temp_free(v2_t);
24661 /* End MIPSDSP functions. */
24663 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24665 int rs, rt, rd, sa;
24666 uint32_t op1, op2;
24668 rs = (ctx->opcode >> 21) & 0x1f;
24669 rt = (ctx->opcode >> 16) & 0x1f;
24670 rd = (ctx->opcode >> 11) & 0x1f;
24671 sa = (ctx->opcode >> 6) & 0x1f;
24673 op1 = MASK_SPECIAL(ctx->opcode);
24674 switch (op1) {
24675 case OPC_LSA:
24676 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24677 break;
24678 case OPC_MULT:
24679 case OPC_MULTU:
24680 case OPC_DIV:
24681 case OPC_DIVU:
24682 op2 = MASK_R6_MULDIV(ctx->opcode);
24683 switch (op2) {
24684 case R6_OPC_MUL:
24685 case R6_OPC_MUH:
24686 case R6_OPC_MULU:
24687 case R6_OPC_MUHU:
24688 case R6_OPC_DIV:
24689 case R6_OPC_MOD:
24690 case R6_OPC_DIVU:
24691 case R6_OPC_MODU:
24692 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24693 break;
24694 default:
24695 MIPS_INVAL("special_r6 muldiv");
24696 gen_reserved_instruction(ctx);
24697 break;
24699 break;
24700 case OPC_SELEQZ:
24701 case OPC_SELNEZ:
24702 gen_cond_move(ctx, op1, rd, rs, rt);
24703 break;
24704 case R6_OPC_CLO:
24705 case R6_OPC_CLZ:
24706 if (rt == 0 && sa == 1) {
24708 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24709 * We need additionally to check other fields.
24711 gen_cl(ctx, op1, rd, rs);
24712 } else {
24713 gen_reserved_instruction(ctx);
24715 break;
24716 case R6_OPC_SDBBP:
24717 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24718 gen_helper_do_semihosting(cpu_env);
24719 } else {
24720 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24721 gen_reserved_instruction(ctx);
24722 } else {
24723 generate_exception_end(ctx, EXCP_DBp);
24726 break;
24727 #if defined(TARGET_MIPS64)
24728 case OPC_DLSA:
24729 check_mips_64(ctx);
24730 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24731 break;
24732 case R6_OPC_DCLO:
24733 case R6_OPC_DCLZ:
24734 if (rt == 0 && sa == 1) {
24736 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24737 * We need additionally to check other fields.
24739 check_mips_64(ctx);
24740 gen_cl(ctx, op1, rd, rs);
24741 } else {
24742 gen_reserved_instruction(ctx);
24744 break;
24745 case OPC_DMULT:
24746 case OPC_DMULTU:
24747 case OPC_DDIV:
24748 case OPC_DDIVU:
24750 op2 = MASK_R6_MULDIV(ctx->opcode);
24751 switch (op2) {
24752 case R6_OPC_DMUL:
24753 case R6_OPC_DMUH:
24754 case R6_OPC_DMULU:
24755 case R6_OPC_DMUHU:
24756 case R6_OPC_DDIV:
24757 case R6_OPC_DMOD:
24758 case R6_OPC_DDIVU:
24759 case R6_OPC_DMODU:
24760 check_mips_64(ctx);
24761 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24762 break;
24763 default:
24764 MIPS_INVAL("special_r6 muldiv");
24765 gen_reserved_instruction(ctx);
24766 break;
24768 break;
24769 #endif
24770 default: /* Invalid */
24771 MIPS_INVAL("special_r6");
24772 gen_reserved_instruction(ctx);
24773 break;
24777 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24779 int rs = extract32(ctx->opcode, 21, 5);
24780 int rt = extract32(ctx->opcode, 16, 5);
24781 int rd = extract32(ctx->opcode, 11, 5);
24782 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24784 switch (op1) {
24785 case OPC_MOVN: /* Conditional move */
24786 case OPC_MOVZ:
24787 gen_cond_move(ctx, op1, rd, rs, rt);
24788 break;
24789 case OPC_MFHI: /* Move from HI/LO */
24790 case OPC_MFLO:
24791 gen_HILO(ctx, op1, 0, rd);
24792 break;
24793 case OPC_MTHI:
24794 case OPC_MTLO: /* Move to HI/LO */
24795 gen_HILO(ctx, op1, 0, rs);
24796 break;
24797 case OPC_MULT:
24798 case OPC_MULTU:
24799 gen_mul_txx9(ctx, op1, rd, rs, rt);
24800 break;
24801 case OPC_DIV:
24802 case OPC_DIVU:
24803 gen_muldiv(ctx, op1, 0, rs, rt);
24804 break;
24805 #if defined(TARGET_MIPS64)
24806 case OPC_DMULT:
24807 case OPC_DMULTU:
24808 case OPC_DDIV:
24809 case OPC_DDIVU:
24810 check_insn_opc_user_only(ctx, INSN_R5900);
24811 gen_muldiv(ctx, op1, 0, rs, rt);
24812 break;
24813 #endif
24814 case OPC_JR:
24815 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24816 break;
24817 default: /* Invalid */
24818 MIPS_INVAL("special_tx79");
24819 gen_reserved_instruction(ctx);
24820 break;
24824 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24826 int rs, rt, rd, sa;
24827 uint32_t op1;
24829 rs = (ctx->opcode >> 21) & 0x1f;
24830 rt = (ctx->opcode >> 16) & 0x1f;
24831 rd = (ctx->opcode >> 11) & 0x1f;
24832 sa = (ctx->opcode >> 6) & 0x1f;
24834 op1 = MASK_SPECIAL(ctx->opcode);
24835 switch (op1) {
24836 case OPC_MOVN: /* Conditional move */
24837 case OPC_MOVZ:
24838 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24839 INSN_LOONGSON2E | INSN_LOONGSON2F);
24840 gen_cond_move(ctx, op1, rd, rs, rt);
24841 break;
24842 case OPC_MFHI: /* Move from HI/LO */
24843 case OPC_MFLO:
24844 gen_HILO(ctx, op1, rs & 3, rd);
24845 break;
24846 case OPC_MTHI:
24847 case OPC_MTLO: /* Move to HI/LO */
24848 gen_HILO(ctx, op1, rd & 3, rs);
24849 break;
24850 case OPC_MOVCI:
24851 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24852 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24853 check_cp1_enabled(ctx);
24854 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24855 (ctx->opcode >> 16) & 1);
24856 } else {
24857 generate_exception_err(ctx, EXCP_CpU, 1);
24859 break;
24860 case OPC_MULT:
24861 case OPC_MULTU:
24862 if (sa) {
24863 check_insn(ctx, INSN_VR54XX);
24864 op1 = MASK_MUL_VR54XX(ctx->opcode);
24865 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24866 } else {
24867 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24869 break;
24870 case OPC_DIV:
24871 case OPC_DIVU:
24872 gen_muldiv(ctx, op1, 0, rs, rt);
24873 break;
24874 #if defined(TARGET_MIPS64)
24875 case OPC_DMULT:
24876 case OPC_DMULTU:
24877 case OPC_DDIV:
24878 case OPC_DDIVU:
24879 check_insn(ctx, ISA_MIPS3);
24880 check_mips_64(ctx);
24881 gen_muldiv(ctx, op1, 0, rs, rt);
24882 break;
24883 #endif
24884 case OPC_JR:
24885 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24886 break;
24887 case OPC_SPIM:
24888 #ifdef MIPS_STRICT_STANDARD
24889 MIPS_INVAL("SPIM");
24890 gen_reserved_instruction(ctx);
24891 #else
24892 /* Implemented as RI exception for now. */
24893 MIPS_INVAL("spim (unofficial)");
24894 gen_reserved_instruction(ctx);
24895 #endif
24896 break;
24897 default: /* Invalid */
24898 MIPS_INVAL("special_legacy");
24899 gen_reserved_instruction(ctx);
24900 break;
24904 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24906 int rs, rt, rd, sa;
24907 uint32_t op1;
24909 rs = (ctx->opcode >> 21) & 0x1f;
24910 rt = (ctx->opcode >> 16) & 0x1f;
24911 rd = (ctx->opcode >> 11) & 0x1f;
24912 sa = (ctx->opcode >> 6) & 0x1f;
24914 op1 = MASK_SPECIAL(ctx->opcode);
24915 switch (op1) {
24916 case OPC_SLL: /* Shift with immediate */
24917 if (sa == 5 && rd == 0 &&
24918 rs == 0 && rt == 0) { /* PAUSE */
24919 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24920 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24921 gen_reserved_instruction(ctx);
24922 break;
24925 /* Fallthrough */
24926 case OPC_SRA:
24927 gen_shift_imm(ctx, op1, rd, rt, sa);
24928 break;
24929 case OPC_SRL:
24930 switch ((ctx->opcode >> 21) & 0x1f) {
24931 case 1:
24932 /* rotr is decoded as srl on non-R2 CPUs */
24933 if (ctx->insn_flags & ISA_MIPS_R2) {
24934 op1 = OPC_ROTR;
24936 /* Fallthrough */
24937 case 0:
24938 gen_shift_imm(ctx, op1, rd, rt, sa);
24939 break;
24940 default:
24941 gen_reserved_instruction(ctx);
24942 break;
24944 break;
24945 case OPC_ADD:
24946 case OPC_ADDU:
24947 case OPC_SUB:
24948 case OPC_SUBU:
24949 gen_arith(ctx, op1, rd, rs, rt);
24950 break;
24951 case OPC_SLLV: /* Shifts */
24952 case OPC_SRAV:
24953 gen_shift(ctx, op1, rd, rs, rt);
24954 break;
24955 case OPC_SRLV:
24956 switch ((ctx->opcode >> 6) & 0x1f) {
24957 case 1:
24958 /* rotrv is decoded as srlv on non-R2 CPUs */
24959 if (ctx->insn_flags & ISA_MIPS_R2) {
24960 op1 = OPC_ROTRV;
24962 /* Fallthrough */
24963 case 0:
24964 gen_shift(ctx, op1, rd, rs, rt);
24965 break;
24966 default:
24967 gen_reserved_instruction(ctx);
24968 break;
24970 break;
24971 case OPC_SLT: /* Set on less than */
24972 case OPC_SLTU:
24973 gen_slt(ctx, op1, rd, rs, rt);
24974 break;
24975 case OPC_AND: /* Logic*/
24976 case OPC_OR:
24977 case OPC_NOR:
24978 case OPC_XOR:
24979 gen_logic(ctx, op1, rd, rs, rt);
24980 break;
24981 case OPC_JALR:
24982 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24983 break;
24984 case OPC_TGE: /* Traps */
24985 case OPC_TGEU:
24986 case OPC_TLT:
24987 case OPC_TLTU:
24988 case OPC_TEQ:
24989 case OPC_TNE:
24990 check_insn(ctx, ISA_MIPS2);
24991 gen_trap(ctx, op1, rs, rt, -1);
24992 break;
24993 case OPC_LSA: /* OPC_PMON */
24994 if ((ctx->insn_flags & ISA_MIPS_R6) ||
24995 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24996 decode_opc_special_r6(env, ctx);
24997 } else {
24998 /* Pmon entry point, also R4010 selsl */
24999 #ifdef MIPS_STRICT_STANDARD
25000 MIPS_INVAL("PMON / selsl");
25001 gen_reserved_instruction(ctx);
25002 #else
25003 gen_helper_0e0i(pmon, sa);
25004 #endif
25006 break;
25007 case OPC_SYSCALL:
25008 generate_exception_end(ctx, EXCP_SYSCALL);
25009 break;
25010 case OPC_BREAK:
25011 generate_exception_end(ctx, EXCP_BREAK);
25012 break;
25013 case OPC_SYNC:
25014 check_insn(ctx, ISA_MIPS2);
25015 gen_sync(extract32(ctx->opcode, 6, 5));
25016 break;
25018 #if defined(TARGET_MIPS64)
25019 /* MIPS64 specific opcodes */
25020 case OPC_DSLL:
25021 case OPC_DSRA:
25022 case OPC_DSLL32:
25023 case OPC_DSRA32:
25024 check_insn(ctx, ISA_MIPS3);
25025 check_mips_64(ctx);
25026 gen_shift_imm(ctx, op1, rd, rt, sa);
25027 break;
25028 case OPC_DSRL:
25029 switch ((ctx->opcode >> 21) & 0x1f) {
25030 case 1:
25031 /* drotr is decoded as dsrl on non-R2 CPUs */
25032 if (ctx->insn_flags & ISA_MIPS_R2) {
25033 op1 = OPC_DROTR;
25035 /* Fallthrough */
25036 case 0:
25037 check_insn(ctx, ISA_MIPS3);
25038 check_mips_64(ctx);
25039 gen_shift_imm(ctx, op1, rd, rt, sa);
25040 break;
25041 default:
25042 gen_reserved_instruction(ctx);
25043 break;
25045 break;
25046 case OPC_DSRL32:
25047 switch ((ctx->opcode >> 21) & 0x1f) {
25048 case 1:
25049 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
25050 if (ctx->insn_flags & ISA_MIPS_R2) {
25051 op1 = OPC_DROTR32;
25053 /* Fallthrough */
25054 case 0:
25055 check_insn(ctx, ISA_MIPS3);
25056 check_mips_64(ctx);
25057 gen_shift_imm(ctx, op1, rd, rt, sa);
25058 break;
25059 default:
25060 gen_reserved_instruction(ctx);
25061 break;
25063 break;
25064 case OPC_DADD:
25065 case OPC_DADDU:
25066 case OPC_DSUB:
25067 case OPC_DSUBU:
25068 check_insn(ctx, ISA_MIPS3);
25069 check_mips_64(ctx);
25070 gen_arith(ctx, op1, rd, rs, rt);
25071 break;
25072 case OPC_DSLLV:
25073 case OPC_DSRAV:
25074 check_insn(ctx, ISA_MIPS3);
25075 check_mips_64(ctx);
25076 gen_shift(ctx, op1, rd, rs, rt);
25077 break;
25078 case OPC_DSRLV:
25079 switch ((ctx->opcode >> 6) & 0x1f) {
25080 case 1:
25081 /* drotrv is decoded as dsrlv on non-R2 CPUs */
25082 if (ctx->insn_flags & ISA_MIPS_R2) {
25083 op1 = OPC_DROTRV;
25085 /* Fallthrough */
25086 case 0:
25087 check_insn(ctx, ISA_MIPS3);
25088 check_mips_64(ctx);
25089 gen_shift(ctx, op1, rd, rs, rt);
25090 break;
25091 default:
25092 gen_reserved_instruction(ctx);
25093 break;
25095 break;
25096 case OPC_DLSA:
25097 if ((ctx->insn_flags & ISA_MIPS_R6) ||
25098 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25099 decode_opc_special_r6(env, ctx);
25101 break;
25102 #endif
25103 default:
25104 if (ctx->insn_flags & ISA_MIPS_R6) {
25105 decode_opc_special_r6(env, ctx);
25106 } else if (ctx->insn_flags & INSN_R5900) {
25107 decode_opc_special_tx79(env, ctx);
25108 } else {
25109 decode_opc_special_legacy(env, ctx);
25115 #if defined(TARGET_MIPS64)
25119 * MMI (MultiMedia Interface) ASE instructions
25120 * ===========================================
25124 * MMI instructions category: data communication
25125 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25127 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
25128 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
25129 * PCPYUD PEXEH PEXTLW PPACW
25130 * PEXEW PEXTUB
25131 * PEXTUH
25132 * PEXTUW
25136 * PCPYH rd, rt
25138 * Parallel Copy Halfword
25140 * 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
25141 * +-----------+---------+---------+---------+---------+-----------+
25142 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
25143 * +-----------+---------+---------+---------+---------+-----------+
25145 static void gen_mmi_pcpyh(DisasContext *ctx)
25147 uint32_t pd, rt, rd;
25148 uint32_t opcode;
25150 opcode = ctx->opcode;
25152 pd = extract32(opcode, 21, 5);
25153 rt = extract32(opcode, 16, 5);
25154 rd = extract32(opcode, 11, 5);
25156 if (unlikely(pd != 0)) {
25157 gen_reserved_instruction(ctx);
25158 } else if (rd == 0) {
25159 /* nop */
25160 } else if (rt == 0) {
25161 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25162 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25163 } else {
25164 TCGv_i64 t0 = tcg_temp_new();
25165 TCGv_i64 t1 = tcg_temp_new();
25166 uint64_t mask = (1ULL << 16) - 1;
25168 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
25169 tcg_gen_movi_i64(t1, 0);
25170 tcg_gen_or_i64(t1, t0, t1);
25171 tcg_gen_shli_i64(t0, t0, 16);
25172 tcg_gen_or_i64(t1, t0, t1);
25173 tcg_gen_shli_i64(t0, t0, 16);
25174 tcg_gen_or_i64(t1, t0, t1);
25175 tcg_gen_shli_i64(t0, t0, 16);
25176 tcg_gen_or_i64(t1, t0, t1);
25178 tcg_gen_mov_i64(cpu_gpr[rd], t1);
25180 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
25181 tcg_gen_movi_i64(t1, 0);
25182 tcg_gen_or_i64(t1, t0, t1);
25183 tcg_gen_shli_i64(t0, t0, 16);
25184 tcg_gen_or_i64(t1, t0, t1);
25185 tcg_gen_shli_i64(t0, t0, 16);
25186 tcg_gen_or_i64(t1, t0, t1);
25187 tcg_gen_shli_i64(t0, t0, 16);
25188 tcg_gen_or_i64(t1, t0, t1);
25190 tcg_gen_mov_i64(cpu_mmr[rd], t1);
25192 tcg_temp_free(t0);
25193 tcg_temp_free(t1);
25198 * PCPYLD rd, rs, rt
25200 * Parallel Copy Lower Doubleword
25202 * 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
25203 * +-----------+---------+---------+---------+---------+-----------+
25204 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
25205 * +-----------+---------+---------+---------+---------+-----------+
25207 static void gen_mmi_pcpyld(DisasContext *ctx)
25209 uint32_t rs, rt, rd;
25210 uint32_t opcode;
25212 opcode = ctx->opcode;
25214 rs = extract32(opcode, 21, 5);
25215 rt = extract32(opcode, 16, 5);
25216 rd = extract32(opcode, 11, 5);
25218 if (rd == 0) {
25219 /* nop */
25220 } else {
25221 if (rs == 0) {
25222 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25223 } else {
25224 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
25226 if (rt == 0) {
25227 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25228 } else {
25229 if (rd != rt) {
25230 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
25237 * PCPYUD rd, rs, rt
25239 * Parallel Copy Upper Doubleword
25241 * 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
25242 * +-----------+---------+---------+---------+---------+-----------+
25243 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
25244 * +-----------+---------+---------+---------+---------+-----------+
25246 static void gen_mmi_pcpyud(DisasContext *ctx)
25248 uint32_t rs, rt, rd;
25249 uint32_t opcode;
25251 opcode = ctx->opcode;
25253 rs = extract32(opcode, 21, 5);
25254 rt = extract32(opcode, 16, 5);
25255 rd = extract32(opcode, 11, 5);
25257 if (rd == 0) {
25258 /* nop */
25259 } else {
25260 if (rs == 0) {
25261 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25262 } else {
25263 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
25265 if (rt == 0) {
25266 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25267 } else {
25268 if (rd != rt) {
25269 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
25275 #endif
25278 #if !defined(TARGET_MIPS64)
25280 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
25281 #define MXU_APTN1_A 0
25282 #define MXU_APTN1_S 1
25284 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
25285 #define MXU_APTN2_AA 0
25286 #define MXU_APTN2_AS 1
25287 #define MXU_APTN2_SA 2
25288 #define MXU_APTN2_SS 3
25290 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
25291 #define MXU_EPTN2_AA 0
25292 #define MXU_EPTN2_AS 1
25293 #define MXU_EPTN2_SA 2
25294 #define MXU_EPTN2_SS 3
25296 /* MXU operand getting pattern 'optn2' */
25297 #define MXU_OPTN2_PTN0 0
25298 #define MXU_OPTN2_PTN1 1
25299 #define MXU_OPTN2_PTN2 2
25300 #define MXU_OPTN2_PTN3 3
25301 /* alternative naming scheme for 'optn2' */
25302 #define MXU_OPTN2_WW 0
25303 #define MXU_OPTN2_LW 1
25304 #define MXU_OPTN2_HW 2
25305 #define MXU_OPTN2_XW 3
25307 /* MXU operand getting pattern 'optn3' */
25308 #define MXU_OPTN3_PTN0 0
25309 #define MXU_OPTN3_PTN1 1
25310 #define MXU_OPTN3_PTN2 2
25311 #define MXU_OPTN3_PTN3 3
25312 #define MXU_OPTN3_PTN4 4
25313 #define MXU_OPTN3_PTN5 5
25314 #define MXU_OPTN3_PTN6 6
25315 #define MXU_OPTN3_PTN7 7
25319 * S32I2M XRa, rb - Register move from GRF to XRF
25321 static void gen_mxu_s32i2m(DisasContext *ctx)
25323 TCGv t0;
25324 uint32_t XRa, Rb;
25326 t0 = tcg_temp_new();
25328 XRa = extract32(ctx->opcode, 6, 5);
25329 Rb = extract32(ctx->opcode, 16, 5);
25331 gen_load_gpr(t0, Rb);
25332 if (XRa <= 15) {
25333 gen_store_mxu_gpr(t0, XRa);
25334 } else if (XRa == 16) {
25335 gen_store_mxu_cr(t0);
25338 tcg_temp_free(t0);
25342 * S32M2I XRa, rb - Register move from XRF to GRF
25344 static void gen_mxu_s32m2i(DisasContext *ctx)
25346 TCGv t0;
25347 uint32_t XRa, Rb;
25349 t0 = tcg_temp_new();
25351 XRa = extract32(ctx->opcode, 6, 5);
25352 Rb = extract32(ctx->opcode, 16, 5);
25354 if (XRa <= 15) {
25355 gen_load_mxu_gpr(t0, XRa);
25356 } else if (XRa == 16) {
25357 gen_load_mxu_cr(t0);
25360 gen_store_gpr(t0, Rb);
25362 tcg_temp_free(t0);
25366 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
25368 static void gen_mxu_s8ldd(DisasContext *ctx)
25370 TCGv t0, t1;
25371 uint32_t XRa, Rb, s8, optn3;
25373 t0 = tcg_temp_new();
25374 t1 = tcg_temp_new();
25376 XRa = extract32(ctx->opcode, 6, 4);
25377 s8 = extract32(ctx->opcode, 10, 8);
25378 optn3 = extract32(ctx->opcode, 18, 3);
25379 Rb = extract32(ctx->opcode, 21, 5);
25381 gen_load_gpr(t0, Rb);
25382 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25384 switch (optn3) {
25385 /* XRa[7:0] = tmp8 */
25386 case MXU_OPTN3_PTN0:
25387 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25388 gen_load_mxu_gpr(t0, XRa);
25389 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25390 break;
25391 /* XRa[15:8] = tmp8 */
25392 case MXU_OPTN3_PTN1:
25393 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25394 gen_load_mxu_gpr(t0, XRa);
25395 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25396 break;
25397 /* XRa[23:16] = tmp8 */
25398 case MXU_OPTN3_PTN2:
25399 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25400 gen_load_mxu_gpr(t0, XRa);
25401 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25402 break;
25403 /* XRa[31:24] = tmp8 */
25404 case MXU_OPTN3_PTN3:
25405 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25406 gen_load_mxu_gpr(t0, XRa);
25407 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25408 break;
25409 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25410 case MXU_OPTN3_PTN4:
25411 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25412 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25413 break;
25414 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25415 case MXU_OPTN3_PTN5:
25416 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25417 tcg_gen_shli_tl(t1, t1, 8);
25418 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25419 break;
25420 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25421 case MXU_OPTN3_PTN6:
25422 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25423 tcg_gen_mov_tl(t0, t1);
25424 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25425 tcg_gen_shli_tl(t1, t1, 16);
25426 tcg_gen_or_tl(t0, t0, t1);
25427 break;
25428 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25429 case MXU_OPTN3_PTN7:
25430 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25431 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25432 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25433 break;
25436 gen_store_mxu_gpr(t0, XRa);
25438 tcg_temp_free(t0);
25439 tcg_temp_free(t1);
25443 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25445 static void gen_mxu_d16mul(DisasContext *ctx)
25447 TCGv t0, t1, t2, t3;
25448 uint32_t XRa, XRb, XRc, XRd, optn2;
25450 t0 = tcg_temp_new();
25451 t1 = tcg_temp_new();
25452 t2 = tcg_temp_new();
25453 t3 = tcg_temp_new();
25455 XRa = extract32(ctx->opcode, 6, 4);
25456 XRb = extract32(ctx->opcode, 10, 4);
25457 XRc = extract32(ctx->opcode, 14, 4);
25458 XRd = extract32(ctx->opcode, 18, 4);
25459 optn2 = extract32(ctx->opcode, 22, 2);
25461 gen_load_mxu_gpr(t1, XRb);
25462 tcg_gen_sextract_tl(t0, t1, 0, 16);
25463 tcg_gen_sextract_tl(t1, t1, 16, 16);
25464 gen_load_mxu_gpr(t3, XRc);
25465 tcg_gen_sextract_tl(t2, t3, 0, 16);
25466 tcg_gen_sextract_tl(t3, t3, 16, 16);
25468 switch (optn2) {
25469 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25470 tcg_gen_mul_tl(t3, t1, t3);
25471 tcg_gen_mul_tl(t2, t0, t2);
25472 break;
25473 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25474 tcg_gen_mul_tl(t3, t0, t3);
25475 tcg_gen_mul_tl(t2, t0, t2);
25476 break;
25477 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25478 tcg_gen_mul_tl(t3, t1, t3);
25479 tcg_gen_mul_tl(t2, t1, t2);
25480 break;
25481 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25482 tcg_gen_mul_tl(t3, t0, t3);
25483 tcg_gen_mul_tl(t2, t1, t2);
25484 break;
25486 gen_store_mxu_gpr(t3, XRa);
25487 gen_store_mxu_gpr(t2, XRd);
25489 tcg_temp_free(t0);
25490 tcg_temp_free(t1);
25491 tcg_temp_free(t2);
25492 tcg_temp_free(t3);
25496 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25497 * and accumulate
25499 static void gen_mxu_d16mac(DisasContext *ctx)
25501 TCGv t0, t1, t2, t3;
25502 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25504 t0 = tcg_temp_new();
25505 t1 = tcg_temp_new();
25506 t2 = tcg_temp_new();
25507 t3 = tcg_temp_new();
25509 XRa = extract32(ctx->opcode, 6, 4);
25510 XRb = extract32(ctx->opcode, 10, 4);
25511 XRc = extract32(ctx->opcode, 14, 4);
25512 XRd = extract32(ctx->opcode, 18, 4);
25513 optn2 = extract32(ctx->opcode, 22, 2);
25514 aptn2 = extract32(ctx->opcode, 24, 2);
25516 gen_load_mxu_gpr(t1, XRb);
25517 tcg_gen_sextract_tl(t0, t1, 0, 16);
25518 tcg_gen_sextract_tl(t1, t1, 16, 16);
25520 gen_load_mxu_gpr(t3, XRc);
25521 tcg_gen_sextract_tl(t2, t3, 0, 16);
25522 tcg_gen_sextract_tl(t3, t3, 16, 16);
25524 switch (optn2) {
25525 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25526 tcg_gen_mul_tl(t3, t1, t3);
25527 tcg_gen_mul_tl(t2, t0, t2);
25528 break;
25529 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25530 tcg_gen_mul_tl(t3, t0, t3);
25531 tcg_gen_mul_tl(t2, t0, t2);
25532 break;
25533 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25534 tcg_gen_mul_tl(t3, t1, t3);
25535 tcg_gen_mul_tl(t2, t1, t2);
25536 break;
25537 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25538 tcg_gen_mul_tl(t3, t0, t3);
25539 tcg_gen_mul_tl(t2, t1, t2);
25540 break;
25542 gen_load_mxu_gpr(t0, XRa);
25543 gen_load_mxu_gpr(t1, XRd);
25545 switch (aptn2) {
25546 case MXU_APTN2_AA:
25547 tcg_gen_add_tl(t3, t0, t3);
25548 tcg_gen_add_tl(t2, t1, t2);
25549 break;
25550 case MXU_APTN2_AS:
25551 tcg_gen_add_tl(t3, t0, t3);
25552 tcg_gen_sub_tl(t2, t1, t2);
25553 break;
25554 case MXU_APTN2_SA:
25555 tcg_gen_sub_tl(t3, t0, t3);
25556 tcg_gen_add_tl(t2, t1, t2);
25557 break;
25558 case MXU_APTN2_SS:
25559 tcg_gen_sub_tl(t3, t0, t3);
25560 tcg_gen_sub_tl(t2, t1, t2);
25561 break;
25563 gen_store_mxu_gpr(t3, XRa);
25564 gen_store_mxu_gpr(t2, XRd);
25566 tcg_temp_free(t0);
25567 tcg_temp_free(t1);
25568 tcg_temp_free(t2);
25569 tcg_temp_free(t3);
25573 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25574 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25576 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25578 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25579 uint32_t XRa, XRb, XRc, XRd, sel;
25581 t0 = tcg_temp_new();
25582 t1 = tcg_temp_new();
25583 t2 = tcg_temp_new();
25584 t3 = tcg_temp_new();
25585 t4 = tcg_temp_new();
25586 t5 = tcg_temp_new();
25587 t6 = tcg_temp_new();
25588 t7 = tcg_temp_new();
25590 XRa = extract32(ctx->opcode, 6, 4);
25591 XRb = extract32(ctx->opcode, 10, 4);
25592 XRc = extract32(ctx->opcode, 14, 4);
25593 XRd = extract32(ctx->opcode, 18, 4);
25594 sel = extract32(ctx->opcode, 22, 2);
25596 gen_load_mxu_gpr(t3, XRb);
25597 gen_load_mxu_gpr(t7, XRc);
25599 if (sel == 0x2) {
25600 /* Q8MULSU */
25601 tcg_gen_ext8s_tl(t0, t3);
25602 tcg_gen_shri_tl(t3, t3, 8);
25603 tcg_gen_ext8s_tl(t1, t3);
25604 tcg_gen_shri_tl(t3, t3, 8);
25605 tcg_gen_ext8s_tl(t2, t3);
25606 tcg_gen_shri_tl(t3, t3, 8);
25607 tcg_gen_ext8s_tl(t3, t3);
25608 } else {
25609 /* Q8MUL */
25610 tcg_gen_ext8u_tl(t0, t3);
25611 tcg_gen_shri_tl(t3, t3, 8);
25612 tcg_gen_ext8u_tl(t1, t3);
25613 tcg_gen_shri_tl(t3, t3, 8);
25614 tcg_gen_ext8u_tl(t2, t3);
25615 tcg_gen_shri_tl(t3, t3, 8);
25616 tcg_gen_ext8u_tl(t3, t3);
25619 tcg_gen_ext8u_tl(t4, t7);
25620 tcg_gen_shri_tl(t7, t7, 8);
25621 tcg_gen_ext8u_tl(t5, t7);
25622 tcg_gen_shri_tl(t7, t7, 8);
25623 tcg_gen_ext8u_tl(t6, t7);
25624 tcg_gen_shri_tl(t7, t7, 8);
25625 tcg_gen_ext8u_tl(t7, t7);
25627 tcg_gen_mul_tl(t0, t0, t4);
25628 tcg_gen_mul_tl(t1, t1, t5);
25629 tcg_gen_mul_tl(t2, t2, t6);
25630 tcg_gen_mul_tl(t3, t3, t7);
25632 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25633 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25634 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25635 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25637 tcg_gen_shli_tl(t1, t1, 16);
25638 tcg_gen_shli_tl(t3, t3, 16);
25640 tcg_gen_or_tl(t0, t0, t1);
25641 tcg_gen_or_tl(t1, t2, t3);
25643 gen_store_mxu_gpr(t0, XRd);
25644 gen_store_mxu_gpr(t1, XRa);
25646 tcg_temp_free(t0);
25647 tcg_temp_free(t1);
25648 tcg_temp_free(t2);
25649 tcg_temp_free(t3);
25650 tcg_temp_free(t4);
25651 tcg_temp_free(t5);
25652 tcg_temp_free(t6);
25653 tcg_temp_free(t7);
25657 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25658 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25660 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25662 TCGv t0, t1;
25663 uint32_t XRa, Rb, s12, sel;
25665 t0 = tcg_temp_new();
25666 t1 = tcg_temp_new();
25668 XRa = extract32(ctx->opcode, 6, 4);
25669 s12 = extract32(ctx->opcode, 10, 10);
25670 sel = extract32(ctx->opcode, 20, 1);
25671 Rb = extract32(ctx->opcode, 21, 5);
25673 gen_load_gpr(t0, Rb);
25675 tcg_gen_movi_tl(t1, s12);
25676 tcg_gen_shli_tl(t1, t1, 2);
25677 if (s12 & 0x200) {
25678 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25680 tcg_gen_add_tl(t1, t0, t1);
25681 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25683 if (sel == 1) {
25684 /* S32LDDR */
25685 tcg_gen_bswap32_tl(t1, t1);
25687 gen_store_mxu_gpr(t1, XRa);
25689 tcg_temp_free(t0);
25690 tcg_temp_free(t1);
25695 * MXU instruction category: logic
25696 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25698 * S32NOR S32AND S32OR S32XOR
25702 * S32NOR XRa, XRb, XRc
25703 * Update XRa with the result of logical bitwise 'nor' operation
25704 * applied to the content of XRb and XRc.
25706 * 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
25707 * +-----------+---------+-----+-------+-------+-------+-----------+
25708 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25709 * +-----------+---------+-----+-------+-------+-------+-----------+
25711 static void gen_mxu_S32NOR(DisasContext *ctx)
25713 uint32_t pad, XRc, XRb, XRa;
25715 pad = extract32(ctx->opcode, 21, 5);
25716 XRc = extract32(ctx->opcode, 14, 4);
25717 XRb = extract32(ctx->opcode, 10, 4);
25718 XRa = extract32(ctx->opcode, 6, 4);
25720 if (unlikely(pad != 0)) {
25721 /* opcode padding incorrect -> do nothing */
25722 } else if (unlikely(XRa == 0)) {
25723 /* destination is zero register -> do nothing */
25724 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25725 /* both operands zero registers -> just set destination to all 1s */
25726 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25727 } else if (unlikely(XRb == 0)) {
25728 /* XRb zero register -> just set destination to the negation of XRc */
25729 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25730 } else if (unlikely(XRc == 0)) {
25731 /* XRa zero register -> just set destination to the negation of XRb */
25732 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25733 } else if (unlikely(XRb == XRc)) {
25734 /* both operands same -> just set destination to the negation of XRb */
25735 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25736 } else {
25737 /* the most general case */
25738 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25743 * S32AND XRa, XRb, XRc
25744 * Update XRa with the result of logical bitwise 'and' operation
25745 * applied to the content of XRb and XRc.
25747 * 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
25748 * +-----------+---------+-----+-------+-------+-------+-----------+
25749 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25750 * +-----------+---------+-----+-------+-------+-------+-----------+
25752 static void gen_mxu_S32AND(DisasContext *ctx)
25754 uint32_t pad, XRc, XRb, XRa;
25756 pad = extract32(ctx->opcode, 21, 5);
25757 XRc = extract32(ctx->opcode, 14, 4);
25758 XRb = extract32(ctx->opcode, 10, 4);
25759 XRa = extract32(ctx->opcode, 6, 4);
25761 if (unlikely(pad != 0)) {
25762 /* opcode padding incorrect -> do nothing */
25763 } else if (unlikely(XRa == 0)) {
25764 /* destination is zero register -> do nothing */
25765 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25766 /* one of operands zero register -> just set destination to all 0s */
25767 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25768 } else if (unlikely(XRb == XRc)) {
25769 /* both operands same -> just set destination to one of them */
25770 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25771 } else {
25772 /* the most general case */
25773 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25778 * S32OR XRa, XRb, XRc
25779 * Update XRa with the result of logical bitwise 'or' operation
25780 * applied to the content of XRb and XRc.
25782 * 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
25783 * +-----------+---------+-----+-------+-------+-------+-----------+
25784 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25785 * +-----------+---------+-----+-------+-------+-------+-----------+
25787 static void gen_mxu_S32OR(DisasContext *ctx)
25789 uint32_t pad, XRc, XRb, XRa;
25791 pad = extract32(ctx->opcode, 21, 5);
25792 XRc = extract32(ctx->opcode, 14, 4);
25793 XRb = extract32(ctx->opcode, 10, 4);
25794 XRa = extract32(ctx->opcode, 6, 4);
25796 if (unlikely(pad != 0)) {
25797 /* opcode padding incorrect -> do nothing */
25798 } else if (unlikely(XRa == 0)) {
25799 /* destination is zero register -> do nothing */
25800 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25801 /* both operands zero registers -> just set destination to all 0s */
25802 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25803 } else if (unlikely(XRb == 0)) {
25804 /* XRb zero register -> just set destination to the content of XRc */
25805 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25806 } else if (unlikely(XRc == 0)) {
25807 /* XRc zero register -> just set destination to the content of XRb */
25808 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25809 } else if (unlikely(XRb == XRc)) {
25810 /* both operands same -> just set destination to one of them */
25811 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25812 } else {
25813 /* the most general case */
25814 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25819 * S32XOR XRa, XRb, XRc
25820 * Update XRa with the result of logical bitwise 'xor' operation
25821 * applied to the content of XRb and XRc.
25823 * 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
25824 * +-----------+---------+-----+-------+-------+-------+-----------+
25825 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25826 * +-----------+---------+-----+-------+-------+-------+-----------+
25828 static void gen_mxu_S32XOR(DisasContext *ctx)
25830 uint32_t pad, XRc, XRb, XRa;
25832 pad = extract32(ctx->opcode, 21, 5);
25833 XRc = extract32(ctx->opcode, 14, 4);
25834 XRb = extract32(ctx->opcode, 10, 4);
25835 XRa = extract32(ctx->opcode, 6, 4);
25837 if (unlikely(pad != 0)) {
25838 /* opcode padding incorrect -> do nothing */
25839 } else if (unlikely(XRa == 0)) {
25840 /* destination is zero register -> do nothing */
25841 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25842 /* both operands zero registers -> just set destination to all 0s */
25843 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25844 } else if (unlikely(XRb == 0)) {
25845 /* XRb zero register -> just set destination to the content of XRc */
25846 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25847 } else if (unlikely(XRc == 0)) {
25848 /* XRc zero register -> just set destination to the content of XRb */
25849 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25850 } else if (unlikely(XRb == XRc)) {
25851 /* both operands same -> just set destination to all 0s */
25852 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25853 } else {
25854 /* the most general case */
25855 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25861 * MXU instruction category max/min
25862 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25864 * S32MAX D16MAX Q8MAX
25865 * S32MIN D16MIN Q8MIN
25869 * S32MAX XRa, XRb, XRc
25870 * Update XRa with the maximum of signed 32-bit integers contained
25871 * in XRb and XRc.
25873 * S32MIN XRa, XRb, XRc
25874 * Update XRa with the minimum of signed 32-bit integers contained
25875 * in XRb and XRc.
25877 * 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
25878 * +-----------+---------+-----+-------+-------+-------+-----------+
25879 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25880 * +-----------+---------+-----+-------+-------+-------+-----------+
25882 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25884 uint32_t pad, opc, XRc, XRb, XRa;
25886 pad = extract32(ctx->opcode, 21, 5);
25887 opc = extract32(ctx->opcode, 18, 3);
25888 XRc = extract32(ctx->opcode, 14, 4);
25889 XRb = extract32(ctx->opcode, 10, 4);
25890 XRa = extract32(ctx->opcode, 6, 4);
25892 if (unlikely(pad != 0)) {
25893 /* opcode padding incorrect -> do nothing */
25894 } else if (unlikely(XRa == 0)) {
25895 /* destination is zero register -> do nothing */
25896 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25897 /* both operands zero registers -> just set destination to zero */
25898 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25899 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25900 /* exactly one operand is zero register - find which one is not...*/
25901 uint32_t XRx = XRb ? XRb : XRc;
25902 /* ...and do max/min operation with one operand 0 */
25903 if (opc == OPC_MXU_S32MAX) {
25904 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25905 } else {
25906 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25908 } else if (unlikely(XRb == XRc)) {
25909 /* both operands same -> just set destination to one of them */
25910 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25911 } else {
25912 /* the most general case */
25913 if (opc == OPC_MXU_S32MAX) {
25914 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25915 mxu_gpr[XRc - 1]);
25916 } else {
25917 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25918 mxu_gpr[XRc - 1]);
25924 * D16MAX
25925 * Update XRa with the 16-bit-wise maximums of signed integers
25926 * contained in XRb and XRc.
25928 * D16MIN
25929 * Update XRa with the 16-bit-wise minimums of signed integers
25930 * contained in XRb and XRc.
25932 * 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
25933 * +-----------+---------+-----+-------+-------+-------+-----------+
25934 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25935 * +-----------+---------+-----+-------+-------+-------+-----------+
25937 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25939 uint32_t pad, opc, XRc, XRb, XRa;
25941 pad = extract32(ctx->opcode, 21, 5);
25942 opc = extract32(ctx->opcode, 18, 3);
25943 XRc = extract32(ctx->opcode, 14, 4);
25944 XRb = extract32(ctx->opcode, 10, 4);
25945 XRa = extract32(ctx->opcode, 6, 4);
25947 if (unlikely(pad != 0)) {
25948 /* opcode padding incorrect -> do nothing */
25949 } else if (unlikely(XRc == 0)) {
25950 /* destination is zero register -> do nothing */
25951 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25952 /* both operands zero registers -> just set destination to zero */
25953 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25954 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25955 /* exactly one operand is zero register - find which one is not...*/
25956 uint32_t XRx = XRb ? XRb : XRc;
25957 /* ...and do half-word-wise max/min with one operand 0 */
25958 TCGv_i32 t0 = tcg_temp_new();
25959 TCGv_i32 t1 = tcg_const_i32(0);
25961 /* the left half-word first */
25962 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25963 if (opc == OPC_MXU_D16MAX) {
25964 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25965 } else {
25966 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25969 /* the right half-word */
25970 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25971 /* move half-words to the leftmost position */
25972 tcg_gen_shli_i32(t0, t0, 16);
25973 /* t0 will be max/min of t0 and t1 */
25974 if (opc == OPC_MXU_D16MAX) {
25975 tcg_gen_smax_i32(t0, t0, t1);
25976 } else {
25977 tcg_gen_smin_i32(t0, t0, t1);
25979 /* return resulting half-words to its original position */
25980 tcg_gen_shri_i32(t0, t0, 16);
25981 /* finally update the destination */
25982 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25984 tcg_temp_free(t1);
25985 tcg_temp_free(t0);
25986 } else if (unlikely(XRb == XRc)) {
25987 /* both operands same -> just set destination to one of them */
25988 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25989 } else {
25990 /* the most general case */
25991 TCGv_i32 t0 = tcg_temp_new();
25992 TCGv_i32 t1 = tcg_temp_new();
25994 /* the left half-word first */
25995 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25996 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25997 if (opc == OPC_MXU_D16MAX) {
25998 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25999 } else {
26000 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26003 /* the right half-word */
26004 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26005 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
26006 /* move half-words to the leftmost position */
26007 tcg_gen_shli_i32(t0, t0, 16);
26008 tcg_gen_shli_i32(t1, t1, 16);
26009 /* t0 will be max/min of t0 and t1 */
26010 if (opc == OPC_MXU_D16MAX) {
26011 tcg_gen_smax_i32(t0, t0, t1);
26012 } else {
26013 tcg_gen_smin_i32(t0, t0, t1);
26015 /* return resulting half-words to its original position */
26016 tcg_gen_shri_i32(t0, t0, 16);
26017 /* finally update the destination */
26018 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26020 tcg_temp_free(t1);
26021 tcg_temp_free(t0);
26026 * Q8MAX
26027 * Update XRa with the 8-bit-wise maximums of signed integers
26028 * contained in XRb and XRc.
26030 * Q8MIN
26031 * Update XRa with the 8-bit-wise minimums of signed integers
26032 * contained in XRb and XRc.
26034 * 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
26035 * +-----------+---------+-----+-------+-------+-------+-----------+
26036 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
26037 * +-----------+---------+-----+-------+-------+-------+-----------+
26039 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
26041 uint32_t pad, opc, XRc, XRb, XRa;
26043 pad = extract32(ctx->opcode, 21, 5);
26044 opc = extract32(ctx->opcode, 18, 3);
26045 XRc = extract32(ctx->opcode, 14, 4);
26046 XRb = extract32(ctx->opcode, 10, 4);
26047 XRa = extract32(ctx->opcode, 6, 4);
26049 if (unlikely(pad != 0)) {
26050 /* opcode padding incorrect -> do nothing */
26051 } else if (unlikely(XRa == 0)) {
26052 /* destination is zero register -> do nothing */
26053 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26054 /* both operands zero registers -> just set destination to zero */
26055 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26056 } else if (unlikely((XRb == 0) || (XRc == 0))) {
26057 /* exactly one operand is zero register - make it be the first...*/
26058 uint32_t XRx = XRb ? XRb : XRc;
26059 /* ...and do byte-wise max/min with one operand 0 */
26060 TCGv_i32 t0 = tcg_temp_new();
26061 TCGv_i32 t1 = tcg_const_i32(0);
26062 int32_t i;
26064 /* the leftmost byte (byte 3) first */
26065 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
26066 if (opc == OPC_MXU_Q8MAX) {
26067 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26068 } else {
26069 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26072 /* bytes 2, 1, 0 */
26073 for (i = 2; i >= 0; i--) {
26074 /* extract the byte */
26075 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
26076 /* move the byte to the leftmost position */
26077 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26078 /* t0 will be max/min of t0 and t1 */
26079 if (opc == OPC_MXU_Q8MAX) {
26080 tcg_gen_smax_i32(t0, t0, t1);
26081 } else {
26082 tcg_gen_smin_i32(t0, t0, t1);
26084 /* return resulting byte to its original position */
26085 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26086 /* finally update the destination */
26087 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26090 tcg_temp_free(t1);
26091 tcg_temp_free(t0);
26092 } else if (unlikely(XRb == XRc)) {
26093 /* both operands same -> just set destination to one of them */
26094 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26095 } else {
26096 /* the most general case */
26097 TCGv_i32 t0 = tcg_temp_new();
26098 TCGv_i32 t1 = tcg_temp_new();
26099 int32_t i;
26101 /* the leftmost bytes (bytes 3) first */
26102 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
26103 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26104 if (opc == OPC_MXU_Q8MAX) {
26105 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26106 } else {
26107 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26110 /* bytes 2, 1, 0 */
26111 for (i = 2; i >= 0; i--) {
26112 /* extract corresponding bytes */
26113 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
26114 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
26115 /* move the bytes to the leftmost position */
26116 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26117 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
26118 /* t0 will be max/min of t0 and t1 */
26119 if (opc == OPC_MXU_Q8MAX) {
26120 tcg_gen_smax_i32(t0, t0, t1);
26121 } else {
26122 tcg_gen_smin_i32(t0, t0, t1);
26124 /* return resulting byte to its original position */
26125 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26126 /* finally update the destination */
26127 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26130 tcg_temp_free(t1);
26131 tcg_temp_free(t0);
26137 * MXU instruction category: align
26138 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26140 * S32ALN S32ALNI
26144 * S32ALNI XRc, XRb, XRa, optn3
26145 * Arrange bytes from XRb and XRc according to one of five sets of
26146 * rules determined by optn3, and place the result in XRa.
26148 * 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
26149 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26150 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26151 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26154 static void gen_mxu_S32ALNI(DisasContext *ctx)
26156 uint32_t optn3, pad, XRc, XRb, XRa;
26158 optn3 = extract32(ctx->opcode, 23, 3);
26159 pad = extract32(ctx->opcode, 21, 2);
26160 XRc = extract32(ctx->opcode, 14, 4);
26161 XRb = extract32(ctx->opcode, 10, 4);
26162 XRa = extract32(ctx->opcode, 6, 4);
26164 if (unlikely(pad != 0)) {
26165 /* opcode padding incorrect -> do nothing */
26166 } else if (unlikely(XRa == 0)) {
26167 /* destination is zero register -> do nothing */
26168 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26169 /* both operands zero registers -> just set destination to all 0s */
26170 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26171 } else if (unlikely(XRb == 0)) {
26172 /* XRb zero register -> just appropriatelly shift XRc into XRa */
26173 switch (optn3) {
26174 case MXU_OPTN3_PTN0:
26175 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26176 break;
26177 case MXU_OPTN3_PTN1:
26178 case MXU_OPTN3_PTN2:
26179 case MXU_OPTN3_PTN3:
26180 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
26181 8 * (4 - optn3));
26182 break;
26183 case MXU_OPTN3_PTN4:
26184 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26185 break;
26187 } else if (unlikely(XRc == 0)) {
26188 /* XRc zero register -> just appropriatelly shift XRb into XRa */
26189 switch (optn3) {
26190 case MXU_OPTN3_PTN0:
26191 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26192 break;
26193 case MXU_OPTN3_PTN1:
26194 case MXU_OPTN3_PTN2:
26195 case MXU_OPTN3_PTN3:
26196 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26197 break;
26198 case MXU_OPTN3_PTN4:
26199 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26200 break;
26202 } else if (unlikely(XRb == XRc)) {
26203 /* both operands same -> just rotation or moving from any of them */
26204 switch (optn3) {
26205 case MXU_OPTN3_PTN0:
26206 case MXU_OPTN3_PTN4:
26207 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26208 break;
26209 case MXU_OPTN3_PTN1:
26210 case MXU_OPTN3_PTN2:
26211 case MXU_OPTN3_PTN3:
26212 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26213 break;
26215 } else {
26216 /* the most general case */
26217 switch (optn3) {
26218 case MXU_OPTN3_PTN0:
26220 /* */
26221 /* XRb XRc */
26222 /* +---------------+ */
26223 /* | A B C D | E F G H */
26224 /* +-------+-------+ */
26225 /* | */
26226 /* XRa */
26227 /* */
26229 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26231 break;
26232 case MXU_OPTN3_PTN1:
26234 /* */
26235 /* XRb XRc */
26236 /* +-------------------+ */
26237 /* A | B C D E | F G H */
26238 /* +---------+---------+ */
26239 /* | */
26240 /* XRa */
26241 /* */
26243 TCGv_i32 t0 = tcg_temp_new();
26244 TCGv_i32 t1 = tcg_temp_new();
26246 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
26247 tcg_gen_shli_i32(t0, t0, 8);
26249 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26250 tcg_gen_shri_i32(t1, t1, 24);
26252 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26254 tcg_temp_free(t1);
26255 tcg_temp_free(t0);
26257 break;
26258 case MXU_OPTN3_PTN2:
26260 /* */
26261 /* XRb XRc */
26262 /* +-------------------+ */
26263 /* A B | C D E F | G H */
26264 /* +---------+---------+ */
26265 /* | */
26266 /* XRa */
26267 /* */
26269 TCGv_i32 t0 = tcg_temp_new();
26270 TCGv_i32 t1 = tcg_temp_new();
26272 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26273 tcg_gen_shli_i32(t0, t0, 16);
26275 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26276 tcg_gen_shri_i32(t1, t1, 16);
26278 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26280 tcg_temp_free(t1);
26281 tcg_temp_free(t0);
26283 break;
26284 case MXU_OPTN3_PTN3:
26286 /* */
26287 /* XRb XRc */
26288 /* +-------------------+ */
26289 /* A B C | D E F G | H */
26290 /* +---------+---------+ */
26291 /* | */
26292 /* XRa */
26293 /* */
26295 TCGv_i32 t0 = tcg_temp_new();
26296 TCGv_i32 t1 = tcg_temp_new();
26298 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
26299 tcg_gen_shli_i32(t0, t0, 24);
26301 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
26302 tcg_gen_shri_i32(t1, t1, 8);
26304 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26306 tcg_temp_free(t1);
26307 tcg_temp_free(t0);
26309 break;
26310 case MXU_OPTN3_PTN4:
26312 /* */
26313 /* XRb XRc */
26314 /* +---------------+ */
26315 /* A B C D | E F G H | */
26316 /* +-------+-------+ */
26317 /* | */
26318 /* XRa */
26319 /* */
26321 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26323 break;
26330 * Decoding engine for MXU
26331 * =======================
26336 * Decode MXU pool00
26338 * 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
26339 * +-----------+---------+-----+-------+-------+-------+-----------+
26340 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
26341 * +-----------+---------+-----+-------+-------+-------+-----------+
26344 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
26346 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26348 switch (opcode) {
26349 case OPC_MXU_S32MAX:
26350 case OPC_MXU_S32MIN:
26351 gen_mxu_S32MAX_S32MIN(ctx);
26352 break;
26353 case OPC_MXU_D16MAX:
26354 case OPC_MXU_D16MIN:
26355 gen_mxu_D16MAX_D16MIN(ctx);
26356 break;
26357 case OPC_MXU_Q8MAX:
26358 case OPC_MXU_Q8MIN:
26359 gen_mxu_Q8MAX_Q8MIN(ctx);
26360 break;
26361 case OPC_MXU_Q8SLT:
26362 /* TODO: Implement emulation of Q8SLT instruction. */
26363 MIPS_INVAL("OPC_MXU_Q8SLT");
26364 gen_reserved_instruction(ctx);
26365 break;
26366 case OPC_MXU_Q8SLTU:
26367 /* TODO: Implement emulation of Q8SLTU instruction. */
26368 MIPS_INVAL("OPC_MXU_Q8SLTU");
26369 gen_reserved_instruction(ctx);
26370 break;
26371 default:
26372 MIPS_INVAL("decode_opc_mxu");
26373 gen_reserved_instruction(ctx);
26374 break;
26380 * Decode MXU pool01
26382 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26383 * 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
26384 * +-----------+---------+-----+-------+-------+-------+-----------+
26385 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26386 * +-----------+---------+-----+-------+-------+-------+-----------+
26388 * Q8ADD:
26389 * 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
26390 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26391 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26392 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26395 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26397 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26399 switch (opcode) {
26400 case OPC_MXU_S32SLT:
26401 /* TODO: Implement emulation of S32SLT instruction. */
26402 MIPS_INVAL("OPC_MXU_S32SLT");
26403 gen_reserved_instruction(ctx);
26404 break;
26405 case OPC_MXU_D16SLT:
26406 /* TODO: Implement emulation of D16SLT instruction. */
26407 MIPS_INVAL("OPC_MXU_D16SLT");
26408 gen_reserved_instruction(ctx);
26409 break;
26410 case OPC_MXU_D16AVG:
26411 /* TODO: Implement emulation of D16AVG instruction. */
26412 MIPS_INVAL("OPC_MXU_D16AVG");
26413 gen_reserved_instruction(ctx);
26414 break;
26415 case OPC_MXU_D16AVGR:
26416 /* TODO: Implement emulation of D16AVGR instruction. */
26417 MIPS_INVAL("OPC_MXU_D16AVGR");
26418 gen_reserved_instruction(ctx);
26419 break;
26420 case OPC_MXU_Q8AVG:
26421 /* TODO: Implement emulation of Q8AVG instruction. */
26422 MIPS_INVAL("OPC_MXU_Q8AVG");
26423 gen_reserved_instruction(ctx);
26424 break;
26425 case OPC_MXU_Q8AVGR:
26426 /* TODO: Implement emulation of Q8AVGR instruction. */
26427 MIPS_INVAL("OPC_MXU_Q8AVGR");
26428 gen_reserved_instruction(ctx);
26429 break;
26430 case OPC_MXU_Q8ADD:
26431 /* TODO: Implement emulation of Q8ADD instruction. */
26432 MIPS_INVAL("OPC_MXU_Q8ADD");
26433 gen_reserved_instruction(ctx);
26434 break;
26435 default:
26436 MIPS_INVAL("decode_opc_mxu");
26437 gen_reserved_instruction(ctx);
26438 break;
26444 * Decode MXU pool02
26446 * 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
26447 * +-----------+---------+-----+-------+-------+-------+-----------+
26448 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26449 * +-----------+---------+-----+-------+-------+-------+-----------+
26452 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26454 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26456 switch (opcode) {
26457 case OPC_MXU_S32CPS:
26458 /* TODO: Implement emulation of S32CPS instruction. */
26459 MIPS_INVAL("OPC_MXU_S32CPS");
26460 gen_reserved_instruction(ctx);
26461 break;
26462 case OPC_MXU_D16CPS:
26463 /* TODO: Implement emulation of D16CPS instruction. */
26464 MIPS_INVAL("OPC_MXU_D16CPS");
26465 gen_reserved_instruction(ctx);
26466 break;
26467 case OPC_MXU_Q8ABD:
26468 /* TODO: Implement emulation of Q8ABD instruction. */
26469 MIPS_INVAL("OPC_MXU_Q8ABD");
26470 gen_reserved_instruction(ctx);
26471 break;
26472 case OPC_MXU_Q16SAT:
26473 /* TODO: Implement emulation of Q16SAT instruction. */
26474 MIPS_INVAL("OPC_MXU_Q16SAT");
26475 gen_reserved_instruction(ctx);
26476 break;
26477 default:
26478 MIPS_INVAL("decode_opc_mxu");
26479 gen_reserved_instruction(ctx);
26480 break;
26486 * Decode MXU pool03
26488 * D16MULF:
26489 * 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
26490 * +-----------+---+---+-------+-------+-------+-------+-----------+
26491 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26492 * +-----------+---+---+-------+-------+-------+-------+-----------+
26494 * D16MULE:
26495 * 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
26496 * +-----------+---+---+-------+-------+-------+-------+-----------+
26497 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26498 * +-----------+---+---+-------+-------+-------+-------+-----------+
26501 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26503 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26505 switch (opcode) {
26506 case OPC_MXU_D16MULF:
26507 /* TODO: Implement emulation of D16MULF instruction. */
26508 MIPS_INVAL("OPC_MXU_D16MULF");
26509 gen_reserved_instruction(ctx);
26510 break;
26511 case OPC_MXU_D16MULE:
26512 /* TODO: Implement emulation of D16MULE instruction. */
26513 MIPS_INVAL("OPC_MXU_D16MULE");
26514 gen_reserved_instruction(ctx);
26515 break;
26516 default:
26517 MIPS_INVAL("decode_opc_mxu");
26518 gen_reserved_instruction(ctx);
26519 break;
26525 * Decode MXU pool04
26527 * 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
26528 * +-----------+---------+-+-------------------+-------+-----------+
26529 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26530 * +-----------+---------+-+-------------------+-------+-----------+
26533 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26535 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26537 switch (opcode) {
26538 case OPC_MXU_S32LDD:
26539 case OPC_MXU_S32LDDR:
26540 gen_mxu_s32ldd_s32lddr(ctx);
26541 break;
26542 default:
26543 MIPS_INVAL("decode_opc_mxu");
26544 gen_reserved_instruction(ctx);
26545 break;
26551 * Decode MXU pool05
26553 * 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
26554 * +-----------+---------+-+-------------------+-------+-----------+
26555 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26556 * +-----------+---------+-+-------------------+-------+-----------+
26559 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26561 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26563 switch (opcode) {
26564 case OPC_MXU_S32STD:
26565 /* TODO: Implement emulation of S32STD instruction. */
26566 MIPS_INVAL("OPC_MXU_S32STD");
26567 gen_reserved_instruction(ctx);
26568 break;
26569 case OPC_MXU_S32STDR:
26570 /* TODO: Implement emulation of S32STDR instruction. */
26571 MIPS_INVAL("OPC_MXU_S32STDR");
26572 gen_reserved_instruction(ctx);
26573 break;
26574 default:
26575 MIPS_INVAL("decode_opc_mxu");
26576 gen_reserved_instruction(ctx);
26577 break;
26583 * Decode MXU pool06
26585 * 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
26586 * +-----------+---------+---------+---+-------+-------+-----------+
26587 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26588 * +-----------+---------+---------+---+-------+-------+-----------+
26591 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26593 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26595 switch (opcode) {
26596 case OPC_MXU_S32LDDV:
26597 /* TODO: Implement emulation of S32LDDV instruction. */
26598 MIPS_INVAL("OPC_MXU_S32LDDV");
26599 gen_reserved_instruction(ctx);
26600 break;
26601 case OPC_MXU_S32LDDVR:
26602 /* TODO: Implement emulation of S32LDDVR instruction. */
26603 MIPS_INVAL("OPC_MXU_S32LDDVR");
26604 gen_reserved_instruction(ctx);
26605 break;
26606 default:
26607 MIPS_INVAL("decode_opc_mxu");
26608 gen_reserved_instruction(ctx);
26609 break;
26615 * Decode MXU pool07
26617 * 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
26618 * +-----------+---------+---------+---+-------+-------+-----------+
26619 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26620 * +-----------+---------+---------+---+-------+-------+-----------+
26623 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26625 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26627 switch (opcode) {
26628 case OPC_MXU_S32STDV:
26629 /* TODO: Implement emulation of S32TDV instruction. */
26630 MIPS_INVAL("OPC_MXU_S32TDV");
26631 gen_reserved_instruction(ctx);
26632 break;
26633 case OPC_MXU_S32STDVR:
26634 /* TODO: Implement emulation of S32TDVR instruction. */
26635 MIPS_INVAL("OPC_MXU_S32TDVR");
26636 gen_reserved_instruction(ctx);
26637 break;
26638 default:
26639 MIPS_INVAL("decode_opc_mxu");
26640 gen_reserved_instruction(ctx);
26641 break;
26647 * Decode MXU pool08
26649 * 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
26650 * +-----------+---------+-+-------------------+-------+-----------+
26651 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26652 * +-----------+---------+-+-------------------+-------+-----------+
26655 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26657 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26659 switch (opcode) {
26660 case OPC_MXU_S32LDI:
26661 /* TODO: Implement emulation of S32LDI instruction. */
26662 MIPS_INVAL("OPC_MXU_S32LDI");
26663 gen_reserved_instruction(ctx);
26664 break;
26665 case OPC_MXU_S32LDIR:
26666 /* TODO: Implement emulation of S32LDIR instruction. */
26667 MIPS_INVAL("OPC_MXU_S32LDIR");
26668 gen_reserved_instruction(ctx);
26669 break;
26670 default:
26671 MIPS_INVAL("decode_opc_mxu");
26672 gen_reserved_instruction(ctx);
26673 break;
26679 * Decode MXU pool09
26681 * 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
26682 * +-----------+---------+-+-------------------+-------+-----------+
26683 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26684 * +-----------+---------+-+-------------------+-------+-----------+
26687 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26689 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26691 switch (opcode) {
26692 case OPC_MXU_S32SDI:
26693 /* TODO: Implement emulation of S32SDI instruction. */
26694 MIPS_INVAL("OPC_MXU_S32SDI");
26695 gen_reserved_instruction(ctx);
26696 break;
26697 case OPC_MXU_S32SDIR:
26698 /* TODO: Implement emulation of S32SDIR instruction. */
26699 MIPS_INVAL("OPC_MXU_S32SDIR");
26700 gen_reserved_instruction(ctx);
26701 break;
26702 default:
26703 MIPS_INVAL("decode_opc_mxu");
26704 gen_reserved_instruction(ctx);
26705 break;
26711 * Decode MXU pool10
26713 * 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
26714 * +-----------+---------+---------+---+-------+-------+-----------+
26715 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26716 * +-----------+---------+---------+---+-------+-------+-----------+
26719 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26721 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26723 switch (opcode) {
26724 case OPC_MXU_S32LDIV:
26725 /* TODO: Implement emulation of S32LDIV instruction. */
26726 MIPS_INVAL("OPC_MXU_S32LDIV");
26727 gen_reserved_instruction(ctx);
26728 break;
26729 case OPC_MXU_S32LDIVR:
26730 /* TODO: Implement emulation of S32LDIVR instruction. */
26731 MIPS_INVAL("OPC_MXU_S32LDIVR");
26732 gen_reserved_instruction(ctx);
26733 break;
26734 default:
26735 MIPS_INVAL("decode_opc_mxu");
26736 gen_reserved_instruction(ctx);
26737 break;
26743 * Decode MXU pool11
26745 * 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
26746 * +-----------+---------+---------+---+-------+-------+-----------+
26747 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26748 * +-----------+---------+---------+---+-------+-------+-----------+
26751 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26753 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26755 switch (opcode) {
26756 case OPC_MXU_S32SDIV:
26757 /* TODO: Implement emulation of S32SDIV instruction. */
26758 MIPS_INVAL("OPC_MXU_S32SDIV");
26759 gen_reserved_instruction(ctx);
26760 break;
26761 case OPC_MXU_S32SDIVR:
26762 /* TODO: Implement emulation of S32SDIVR instruction. */
26763 MIPS_INVAL("OPC_MXU_S32SDIVR");
26764 gen_reserved_instruction(ctx);
26765 break;
26766 default:
26767 MIPS_INVAL("decode_opc_mxu");
26768 gen_reserved_instruction(ctx);
26769 break;
26775 * Decode MXU pool12
26777 * 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
26778 * +-----------+---+---+-------+-------+-------+-------+-----------+
26779 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26780 * +-----------+---+---+-------+-------+-------+-------+-----------+
26783 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26785 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26787 switch (opcode) {
26788 case OPC_MXU_D32ACC:
26789 /* TODO: Implement emulation of D32ACC instruction. */
26790 MIPS_INVAL("OPC_MXU_D32ACC");
26791 gen_reserved_instruction(ctx);
26792 break;
26793 case OPC_MXU_D32ACCM:
26794 /* TODO: Implement emulation of D32ACCM instruction. */
26795 MIPS_INVAL("OPC_MXU_D32ACCM");
26796 gen_reserved_instruction(ctx);
26797 break;
26798 case OPC_MXU_D32ASUM:
26799 /* TODO: Implement emulation of D32ASUM instruction. */
26800 MIPS_INVAL("OPC_MXU_D32ASUM");
26801 gen_reserved_instruction(ctx);
26802 break;
26803 default:
26804 MIPS_INVAL("decode_opc_mxu");
26805 gen_reserved_instruction(ctx);
26806 break;
26812 * Decode MXU pool13
26814 * 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
26815 * +-----------+---+---+-------+-------+-------+-------+-----------+
26816 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26817 * +-----------+---+---+-------+-------+-------+-------+-----------+
26820 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26822 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26824 switch (opcode) {
26825 case OPC_MXU_Q16ACC:
26826 /* TODO: Implement emulation of Q16ACC instruction. */
26827 MIPS_INVAL("OPC_MXU_Q16ACC");
26828 gen_reserved_instruction(ctx);
26829 break;
26830 case OPC_MXU_Q16ACCM:
26831 /* TODO: Implement emulation of Q16ACCM instruction. */
26832 MIPS_INVAL("OPC_MXU_Q16ACCM");
26833 gen_reserved_instruction(ctx);
26834 break;
26835 case OPC_MXU_Q16ASUM:
26836 /* TODO: Implement emulation of Q16ASUM instruction. */
26837 MIPS_INVAL("OPC_MXU_Q16ASUM");
26838 gen_reserved_instruction(ctx);
26839 break;
26840 default:
26841 MIPS_INVAL("decode_opc_mxu");
26842 gen_reserved_instruction(ctx);
26843 break;
26849 * Decode MXU pool14
26851 * Q8ADDE, Q8ACCE:
26852 * 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
26853 * +-----------+---+---+-------+-------+-------+-------+-----------+
26854 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26855 * +-----------+---+---+-------+-------+-------+-------+-----------+
26857 * D8SUM, D8SUMC:
26858 * 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
26859 * +-----------+---+---+-------+-------+-------+-------+-----------+
26860 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26861 * +-----------+---+---+-------+-------+-------+-------+-----------+
26864 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26866 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26868 switch (opcode) {
26869 case OPC_MXU_Q8ADDE:
26870 /* TODO: Implement emulation of Q8ADDE instruction. */
26871 MIPS_INVAL("OPC_MXU_Q8ADDE");
26872 gen_reserved_instruction(ctx);
26873 break;
26874 case OPC_MXU_D8SUM:
26875 /* TODO: Implement emulation of D8SUM instruction. */
26876 MIPS_INVAL("OPC_MXU_D8SUM");
26877 gen_reserved_instruction(ctx);
26878 break;
26879 case OPC_MXU_D8SUMC:
26880 /* TODO: Implement emulation of D8SUMC instruction. */
26881 MIPS_INVAL("OPC_MXU_D8SUMC");
26882 gen_reserved_instruction(ctx);
26883 break;
26884 default:
26885 MIPS_INVAL("decode_opc_mxu");
26886 gen_reserved_instruction(ctx);
26887 break;
26893 * Decode MXU pool15
26895 * S32MUL, S32MULU, S32EXTRV:
26896 * 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
26897 * +-----------+---------+---------+---+-------+-------+-----------+
26898 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26899 * +-----------+---------+---------+---+-------+-------+-----------+
26901 * S32EXTR:
26902 * 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
26903 * +-----------+---------+---------+---+-------+-------+-----------+
26904 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26905 * +-----------+---------+---------+---+-------+-------+-----------+
26908 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26910 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26912 switch (opcode) {
26913 case OPC_MXU_S32MUL:
26914 /* TODO: Implement emulation of S32MUL instruction. */
26915 MIPS_INVAL("OPC_MXU_S32MUL");
26916 gen_reserved_instruction(ctx);
26917 break;
26918 case OPC_MXU_S32MULU:
26919 /* TODO: Implement emulation of S32MULU instruction. */
26920 MIPS_INVAL("OPC_MXU_S32MULU");
26921 gen_reserved_instruction(ctx);
26922 break;
26923 case OPC_MXU_S32EXTR:
26924 /* TODO: Implement emulation of S32EXTR instruction. */
26925 MIPS_INVAL("OPC_MXU_S32EXTR");
26926 gen_reserved_instruction(ctx);
26927 break;
26928 case OPC_MXU_S32EXTRV:
26929 /* TODO: Implement emulation of S32EXTRV instruction. */
26930 MIPS_INVAL("OPC_MXU_S32EXTRV");
26931 gen_reserved_instruction(ctx);
26932 break;
26933 default:
26934 MIPS_INVAL("decode_opc_mxu");
26935 gen_reserved_instruction(ctx);
26936 break;
26942 * Decode MXU pool16
26944 * D32SARW:
26945 * 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
26946 * +-----------+---------+-----+-------+-------+-------+-----------+
26947 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26948 * +-----------+---------+-----+-------+-------+-------+-----------+
26950 * S32ALN:
26951 * 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
26952 * +-----------+---------+-----+-------+-------+-------+-----------+
26953 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26954 * +-----------+---------+-----+-------+-------+-------+-----------+
26956 * S32ALNI:
26957 * 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
26958 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26959 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26960 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26962 * S32LUI:
26963 * 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
26964 * +-----------+-----+---+-----+-------+---------------+-----------+
26965 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26966 * +-----------+-----+---+-----+-------+---------------+-----------+
26968 * S32NOR, S32AND, S32OR, S32XOR:
26969 * 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
26970 * +-----------+---------+-----+-------+-------+-------+-----------+
26971 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26972 * +-----------+---------+-----+-------+-------+-------+-----------+
26975 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26977 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26979 switch (opcode) {
26980 case OPC_MXU_D32SARW:
26981 /* TODO: Implement emulation of D32SARW instruction. */
26982 MIPS_INVAL("OPC_MXU_D32SARW");
26983 gen_reserved_instruction(ctx);
26984 break;
26985 case OPC_MXU_S32ALN:
26986 /* TODO: Implement emulation of S32ALN instruction. */
26987 MIPS_INVAL("OPC_MXU_S32ALN");
26988 gen_reserved_instruction(ctx);
26989 break;
26990 case OPC_MXU_S32ALNI:
26991 gen_mxu_S32ALNI(ctx);
26992 break;
26993 case OPC_MXU_S32LUI:
26994 /* TODO: Implement emulation of S32LUI instruction. */
26995 MIPS_INVAL("OPC_MXU_S32LUI");
26996 gen_reserved_instruction(ctx);
26997 break;
26998 case OPC_MXU_S32NOR:
26999 gen_mxu_S32NOR(ctx);
27000 break;
27001 case OPC_MXU_S32AND:
27002 gen_mxu_S32AND(ctx);
27003 break;
27004 case OPC_MXU_S32OR:
27005 gen_mxu_S32OR(ctx);
27006 break;
27007 case OPC_MXU_S32XOR:
27008 gen_mxu_S32XOR(ctx);
27009 break;
27010 default:
27011 MIPS_INVAL("decode_opc_mxu");
27012 gen_reserved_instruction(ctx);
27013 break;
27019 * Decode MXU pool17
27021 * 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
27022 * +-----------+---------+---------+---+---------+-----+-----------+
27023 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
27024 * +-----------+---------+---------+---+---------+-----+-----------+
27027 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
27029 uint32_t opcode = extract32(ctx->opcode, 6, 2);
27031 switch (opcode) {
27032 case OPC_MXU_LXW:
27033 /* TODO: Implement emulation of LXW instruction. */
27034 MIPS_INVAL("OPC_MXU_LXW");
27035 gen_reserved_instruction(ctx);
27036 break;
27037 case OPC_MXU_LXH:
27038 /* TODO: Implement emulation of LXH instruction. */
27039 MIPS_INVAL("OPC_MXU_LXH");
27040 gen_reserved_instruction(ctx);
27041 break;
27042 case OPC_MXU_LXHU:
27043 /* TODO: Implement emulation of LXHU instruction. */
27044 MIPS_INVAL("OPC_MXU_LXHU");
27045 gen_reserved_instruction(ctx);
27046 break;
27047 case OPC_MXU_LXB:
27048 /* TODO: Implement emulation of LXB instruction. */
27049 MIPS_INVAL("OPC_MXU_LXB");
27050 gen_reserved_instruction(ctx);
27051 break;
27052 case OPC_MXU_LXBU:
27053 /* TODO: Implement emulation of LXBU instruction. */
27054 MIPS_INVAL("OPC_MXU_LXBU");
27055 gen_reserved_instruction(ctx);
27056 break;
27057 default:
27058 MIPS_INVAL("decode_opc_mxu");
27059 gen_reserved_instruction(ctx);
27060 break;
27065 * Decode MXU pool18
27067 * 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
27068 * +-----------+---------+-----+-------+-------+-------+-----------+
27069 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
27070 * +-----------+---------+-----+-------+-------+-------+-----------+
27073 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
27075 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27077 switch (opcode) {
27078 case OPC_MXU_D32SLLV:
27079 /* TODO: Implement emulation of D32SLLV instruction. */
27080 MIPS_INVAL("OPC_MXU_D32SLLV");
27081 gen_reserved_instruction(ctx);
27082 break;
27083 case OPC_MXU_D32SLRV:
27084 /* TODO: Implement emulation of D32SLRV instruction. */
27085 MIPS_INVAL("OPC_MXU_D32SLRV");
27086 gen_reserved_instruction(ctx);
27087 break;
27088 case OPC_MXU_D32SARV:
27089 /* TODO: Implement emulation of D32SARV instruction. */
27090 MIPS_INVAL("OPC_MXU_D32SARV");
27091 gen_reserved_instruction(ctx);
27092 break;
27093 case OPC_MXU_Q16SLLV:
27094 /* TODO: Implement emulation of Q16SLLV instruction. */
27095 MIPS_INVAL("OPC_MXU_Q16SLLV");
27096 gen_reserved_instruction(ctx);
27097 break;
27098 case OPC_MXU_Q16SLRV:
27099 /* TODO: Implement emulation of Q16SLRV instruction. */
27100 MIPS_INVAL("OPC_MXU_Q16SLRV");
27101 gen_reserved_instruction(ctx);
27102 break;
27103 case OPC_MXU_Q16SARV:
27104 /* TODO: Implement emulation of Q16SARV instruction. */
27105 MIPS_INVAL("OPC_MXU_Q16SARV");
27106 gen_reserved_instruction(ctx);
27107 break;
27108 default:
27109 MIPS_INVAL("decode_opc_mxu");
27110 gen_reserved_instruction(ctx);
27111 break;
27117 * Decode MXU pool19
27119 * 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
27120 * +-----------+---+---+-------+-------+-------+-------+-----------+
27121 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
27122 * +-----------+---+---+-------+-------+-------+-------+-----------+
27125 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
27127 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27129 switch (opcode) {
27130 case OPC_MXU_Q8MUL:
27131 case OPC_MXU_Q8MULSU:
27132 gen_mxu_q8mul_q8mulsu(ctx);
27133 break;
27134 default:
27135 MIPS_INVAL("decode_opc_mxu");
27136 gen_reserved_instruction(ctx);
27137 break;
27143 * Decode MXU pool20
27145 * 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
27146 * +-----------+---------+-----+-------+-------+-------+-----------+
27147 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
27148 * +-----------+---------+-----+-------+-------+-------+-----------+
27151 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
27153 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27155 switch (opcode) {
27156 case OPC_MXU_Q8MOVZ:
27157 /* TODO: Implement emulation of Q8MOVZ instruction. */
27158 MIPS_INVAL("OPC_MXU_Q8MOVZ");
27159 gen_reserved_instruction(ctx);
27160 break;
27161 case OPC_MXU_Q8MOVN:
27162 /* TODO: Implement emulation of Q8MOVN instruction. */
27163 MIPS_INVAL("OPC_MXU_Q8MOVN");
27164 gen_reserved_instruction(ctx);
27165 break;
27166 case OPC_MXU_D16MOVZ:
27167 /* TODO: Implement emulation of D16MOVZ instruction. */
27168 MIPS_INVAL("OPC_MXU_D16MOVZ");
27169 gen_reserved_instruction(ctx);
27170 break;
27171 case OPC_MXU_D16MOVN:
27172 /* TODO: Implement emulation of D16MOVN instruction. */
27173 MIPS_INVAL("OPC_MXU_D16MOVN");
27174 gen_reserved_instruction(ctx);
27175 break;
27176 case OPC_MXU_S32MOVZ:
27177 /* TODO: Implement emulation of S32MOVZ instruction. */
27178 MIPS_INVAL("OPC_MXU_S32MOVZ");
27179 gen_reserved_instruction(ctx);
27180 break;
27181 case OPC_MXU_S32MOVN:
27182 /* TODO: Implement emulation of S32MOVN instruction. */
27183 MIPS_INVAL("OPC_MXU_S32MOVN");
27184 gen_reserved_instruction(ctx);
27185 break;
27186 default:
27187 MIPS_INVAL("decode_opc_mxu");
27188 gen_reserved_instruction(ctx);
27189 break;
27195 * Decode MXU pool21
27197 * 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
27198 * +-----------+---+---+-------+-------+-------+-------+-----------+
27199 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
27200 * +-----------+---+---+-------+-------+-------+-------+-----------+
27203 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
27205 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27207 switch (opcode) {
27208 case OPC_MXU_Q8MAC:
27209 /* TODO: Implement emulation of Q8MAC instruction. */
27210 MIPS_INVAL("OPC_MXU_Q8MAC");
27211 gen_reserved_instruction(ctx);
27212 break;
27213 case OPC_MXU_Q8MACSU:
27214 /* TODO: Implement emulation of Q8MACSU instruction. */
27215 MIPS_INVAL("OPC_MXU_Q8MACSU");
27216 gen_reserved_instruction(ctx);
27217 break;
27218 default:
27219 MIPS_INVAL("decode_opc_mxu");
27220 gen_reserved_instruction(ctx);
27221 break;
27227 * Main MXU decoding function
27229 * 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
27230 * +-----------+---------------------------------------+-----------+
27231 * | SPECIAL2 | |x x x x x x|
27232 * +-----------+---------------------------------------+-----------+
27235 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
27238 * TODO: Investigate necessity of including handling of
27239 * CLZ, CLO, SDBB in this function, as they belong to
27240 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
27242 uint32_t opcode = extract32(ctx->opcode, 0, 6);
27244 if (opcode == OPC__MXU_MUL) {
27245 uint32_t rs, rt, rd, op1;
27247 rs = extract32(ctx->opcode, 21, 5);
27248 rt = extract32(ctx->opcode, 16, 5);
27249 rd = extract32(ctx->opcode, 11, 5);
27250 op1 = MASK_SPECIAL2(ctx->opcode);
27252 gen_arith(ctx, op1, rd, rs, rt);
27254 return;
27257 if (opcode == OPC_MXU_S32M2I) {
27258 gen_mxu_s32m2i(ctx);
27259 return;
27262 if (opcode == OPC_MXU_S32I2M) {
27263 gen_mxu_s32i2m(ctx);
27264 return;
27268 TCGv t_mxu_cr = tcg_temp_new();
27269 TCGLabel *l_exit = gen_new_label();
27271 gen_load_mxu_cr(t_mxu_cr);
27272 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
27273 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
27275 switch (opcode) {
27276 case OPC_MXU_S32MADD:
27277 /* TODO: Implement emulation of S32MADD instruction. */
27278 MIPS_INVAL("OPC_MXU_S32MADD");
27279 gen_reserved_instruction(ctx);
27280 break;
27281 case OPC_MXU_S32MADDU:
27282 /* TODO: Implement emulation of S32MADDU instruction. */
27283 MIPS_INVAL("OPC_MXU_S32MADDU");
27284 gen_reserved_instruction(ctx);
27285 break;
27286 case OPC_MXU__POOL00:
27287 decode_opc_mxu__pool00(env, ctx);
27288 break;
27289 case OPC_MXU_S32MSUB:
27290 /* TODO: Implement emulation of S32MSUB instruction. */
27291 MIPS_INVAL("OPC_MXU_S32MSUB");
27292 gen_reserved_instruction(ctx);
27293 break;
27294 case OPC_MXU_S32MSUBU:
27295 /* TODO: Implement emulation of S32MSUBU instruction. */
27296 MIPS_INVAL("OPC_MXU_S32MSUBU");
27297 gen_reserved_instruction(ctx);
27298 break;
27299 case OPC_MXU__POOL01:
27300 decode_opc_mxu__pool01(env, ctx);
27301 break;
27302 case OPC_MXU__POOL02:
27303 decode_opc_mxu__pool02(env, ctx);
27304 break;
27305 case OPC_MXU_D16MUL:
27306 gen_mxu_d16mul(ctx);
27307 break;
27308 case OPC_MXU__POOL03:
27309 decode_opc_mxu__pool03(env, ctx);
27310 break;
27311 case OPC_MXU_D16MAC:
27312 gen_mxu_d16mac(ctx);
27313 break;
27314 case OPC_MXU_D16MACF:
27315 /* TODO: Implement emulation of D16MACF instruction. */
27316 MIPS_INVAL("OPC_MXU_D16MACF");
27317 gen_reserved_instruction(ctx);
27318 break;
27319 case OPC_MXU_D16MADL:
27320 /* TODO: Implement emulation of D16MADL instruction. */
27321 MIPS_INVAL("OPC_MXU_D16MADL");
27322 gen_reserved_instruction(ctx);
27323 break;
27324 case OPC_MXU_S16MAD:
27325 /* TODO: Implement emulation of S16MAD instruction. */
27326 MIPS_INVAL("OPC_MXU_S16MAD");
27327 gen_reserved_instruction(ctx);
27328 break;
27329 case OPC_MXU_Q16ADD:
27330 /* TODO: Implement emulation of Q16ADD instruction. */
27331 MIPS_INVAL("OPC_MXU_Q16ADD");
27332 gen_reserved_instruction(ctx);
27333 break;
27334 case OPC_MXU_D16MACE:
27335 /* TODO: Implement emulation of D16MACE instruction. */
27336 MIPS_INVAL("OPC_MXU_D16MACE");
27337 gen_reserved_instruction(ctx);
27338 break;
27339 case OPC_MXU__POOL04:
27340 decode_opc_mxu__pool04(env, ctx);
27341 break;
27342 case OPC_MXU__POOL05:
27343 decode_opc_mxu__pool05(env, ctx);
27344 break;
27345 case OPC_MXU__POOL06:
27346 decode_opc_mxu__pool06(env, ctx);
27347 break;
27348 case OPC_MXU__POOL07:
27349 decode_opc_mxu__pool07(env, ctx);
27350 break;
27351 case OPC_MXU__POOL08:
27352 decode_opc_mxu__pool08(env, ctx);
27353 break;
27354 case OPC_MXU__POOL09:
27355 decode_opc_mxu__pool09(env, ctx);
27356 break;
27357 case OPC_MXU__POOL10:
27358 decode_opc_mxu__pool10(env, ctx);
27359 break;
27360 case OPC_MXU__POOL11:
27361 decode_opc_mxu__pool11(env, ctx);
27362 break;
27363 case OPC_MXU_D32ADD:
27364 /* TODO: Implement emulation of D32ADD instruction. */
27365 MIPS_INVAL("OPC_MXU_D32ADD");
27366 gen_reserved_instruction(ctx);
27367 break;
27368 case OPC_MXU__POOL12:
27369 decode_opc_mxu__pool12(env, ctx);
27370 break;
27371 case OPC_MXU__POOL13:
27372 decode_opc_mxu__pool13(env, ctx);
27373 break;
27374 case OPC_MXU__POOL14:
27375 decode_opc_mxu__pool14(env, ctx);
27376 break;
27377 case OPC_MXU_Q8ACCE:
27378 /* TODO: Implement emulation of Q8ACCE instruction. */
27379 MIPS_INVAL("OPC_MXU_Q8ACCE");
27380 gen_reserved_instruction(ctx);
27381 break;
27382 case OPC_MXU_S8LDD:
27383 gen_mxu_s8ldd(ctx);
27384 break;
27385 case OPC_MXU_S8STD:
27386 /* TODO: Implement emulation of S8STD instruction. */
27387 MIPS_INVAL("OPC_MXU_S8STD");
27388 gen_reserved_instruction(ctx);
27389 break;
27390 case OPC_MXU_S8LDI:
27391 /* TODO: Implement emulation of S8LDI instruction. */
27392 MIPS_INVAL("OPC_MXU_S8LDI");
27393 gen_reserved_instruction(ctx);
27394 break;
27395 case OPC_MXU_S8SDI:
27396 /* TODO: Implement emulation of S8SDI instruction. */
27397 MIPS_INVAL("OPC_MXU_S8SDI");
27398 gen_reserved_instruction(ctx);
27399 break;
27400 case OPC_MXU__POOL15:
27401 decode_opc_mxu__pool15(env, ctx);
27402 break;
27403 case OPC_MXU__POOL16:
27404 decode_opc_mxu__pool16(env, ctx);
27405 break;
27406 case OPC_MXU__POOL17:
27407 decode_opc_mxu__pool17(env, ctx);
27408 break;
27409 case OPC_MXU_S16LDD:
27410 /* TODO: Implement emulation of S16LDD instruction. */
27411 MIPS_INVAL("OPC_MXU_S16LDD");
27412 gen_reserved_instruction(ctx);
27413 break;
27414 case OPC_MXU_S16STD:
27415 /* TODO: Implement emulation of S16STD instruction. */
27416 MIPS_INVAL("OPC_MXU_S16STD");
27417 gen_reserved_instruction(ctx);
27418 break;
27419 case OPC_MXU_S16LDI:
27420 /* TODO: Implement emulation of S16LDI instruction. */
27421 MIPS_INVAL("OPC_MXU_S16LDI");
27422 gen_reserved_instruction(ctx);
27423 break;
27424 case OPC_MXU_S16SDI:
27425 /* TODO: Implement emulation of S16SDI instruction. */
27426 MIPS_INVAL("OPC_MXU_S16SDI");
27427 gen_reserved_instruction(ctx);
27428 break;
27429 case OPC_MXU_D32SLL:
27430 /* TODO: Implement emulation of D32SLL instruction. */
27431 MIPS_INVAL("OPC_MXU_D32SLL");
27432 gen_reserved_instruction(ctx);
27433 break;
27434 case OPC_MXU_D32SLR:
27435 /* TODO: Implement emulation of D32SLR instruction. */
27436 MIPS_INVAL("OPC_MXU_D32SLR");
27437 gen_reserved_instruction(ctx);
27438 break;
27439 case OPC_MXU_D32SARL:
27440 /* TODO: Implement emulation of D32SARL instruction. */
27441 MIPS_INVAL("OPC_MXU_D32SARL");
27442 gen_reserved_instruction(ctx);
27443 break;
27444 case OPC_MXU_D32SAR:
27445 /* TODO: Implement emulation of D32SAR instruction. */
27446 MIPS_INVAL("OPC_MXU_D32SAR");
27447 gen_reserved_instruction(ctx);
27448 break;
27449 case OPC_MXU_Q16SLL:
27450 /* TODO: Implement emulation of Q16SLL instruction. */
27451 MIPS_INVAL("OPC_MXU_Q16SLL");
27452 gen_reserved_instruction(ctx);
27453 break;
27454 case OPC_MXU_Q16SLR:
27455 /* TODO: Implement emulation of Q16SLR instruction. */
27456 MIPS_INVAL("OPC_MXU_Q16SLR");
27457 gen_reserved_instruction(ctx);
27458 break;
27459 case OPC_MXU__POOL18:
27460 decode_opc_mxu__pool18(env, ctx);
27461 break;
27462 case OPC_MXU_Q16SAR:
27463 /* TODO: Implement emulation of Q16SAR instruction. */
27464 MIPS_INVAL("OPC_MXU_Q16SAR");
27465 gen_reserved_instruction(ctx);
27466 break;
27467 case OPC_MXU__POOL19:
27468 decode_opc_mxu__pool19(env, ctx);
27469 break;
27470 case OPC_MXU__POOL20:
27471 decode_opc_mxu__pool20(env, ctx);
27472 break;
27473 case OPC_MXU__POOL21:
27474 decode_opc_mxu__pool21(env, ctx);
27475 break;
27476 case OPC_MXU_Q16SCOP:
27477 /* TODO: Implement emulation of Q16SCOP instruction. */
27478 MIPS_INVAL("OPC_MXU_Q16SCOP");
27479 gen_reserved_instruction(ctx);
27480 break;
27481 case OPC_MXU_Q8MADL:
27482 /* TODO: Implement emulation of Q8MADL instruction. */
27483 MIPS_INVAL("OPC_MXU_Q8MADL");
27484 gen_reserved_instruction(ctx);
27485 break;
27486 case OPC_MXU_S32SFL:
27487 /* TODO: Implement emulation of S32SFL instruction. */
27488 MIPS_INVAL("OPC_MXU_S32SFL");
27489 gen_reserved_instruction(ctx);
27490 break;
27491 case OPC_MXU_Q8SAD:
27492 /* TODO: Implement emulation of Q8SAD instruction. */
27493 MIPS_INVAL("OPC_MXU_Q8SAD");
27494 gen_reserved_instruction(ctx);
27495 break;
27496 default:
27497 MIPS_INVAL("decode_opc_mxu");
27498 gen_reserved_instruction(ctx);
27501 gen_set_label(l_exit);
27502 tcg_temp_free(t_mxu_cr);
27506 #endif /* !defined(TARGET_MIPS64) */
27509 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27511 int rs, rt, rd;
27512 uint32_t op1;
27514 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27516 rs = (ctx->opcode >> 21) & 0x1f;
27517 rt = (ctx->opcode >> 16) & 0x1f;
27518 rd = (ctx->opcode >> 11) & 0x1f;
27520 op1 = MASK_SPECIAL2(ctx->opcode);
27521 switch (op1) {
27522 case OPC_MADD: /* Multiply and add/sub */
27523 case OPC_MADDU:
27524 case OPC_MSUB:
27525 case OPC_MSUBU:
27526 check_insn(ctx, ISA_MIPS_R1);
27527 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27528 break;
27529 case OPC_MUL:
27530 gen_arith(ctx, op1, rd, rs, rt);
27531 break;
27532 case OPC_DIV_G_2F:
27533 case OPC_DIVU_G_2F:
27534 case OPC_MULT_G_2F:
27535 case OPC_MULTU_G_2F:
27536 case OPC_MOD_G_2F:
27537 case OPC_MODU_G_2F:
27538 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27539 gen_loongson_integer(ctx, op1, rd, rs, rt);
27540 break;
27541 case OPC_CLO:
27542 case OPC_CLZ:
27543 check_insn(ctx, ISA_MIPS_R1);
27544 gen_cl(ctx, op1, rd, rs);
27545 break;
27546 case OPC_SDBBP:
27547 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27548 gen_helper_do_semihosting(cpu_env);
27549 } else {
27551 * XXX: not clear which exception should be raised
27552 * when in debug mode...
27554 check_insn(ctx, ISA_MIPS_R1);
27555 generate_exception_end(ctx, EXCP_DBp);
27557 break;
27558 #if defined(TARGET_MIPS64)
27559 case OPC_DCLO:
27560 case OPC_DCLZ:
27561 check_insn(ctx, ISA_MIPS_R1);
27562 check_mips_64(ctx);
27563 gen_cl(ctx, op1, rd, rs);
27564 break;
27565 case OPC_DMULT_G_2F:
27566 case OPC_DMULTU_G_2F:
27567 case OPC_DDIV_G_2F:
27568 case OPC_DDIVU_G_2F:
27569 case OPC_DMOD_G_2F:
27570 case OPC_DMODU_G_2F:
27571 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27572 gen_loongson_integer(ctx, op1, rd, rs, rt);
27573 break;
27574 #endif
27575 default: /* Invalid */
27576 MIPS_INVAL("special2_legacy");
27577 gen_reserved_instruction(ctx);
27578 break;
27582 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27584 int rs, rt, rd, sa;
27585 uint32_t op1, op2;
27586 int16_t imm;
27588 rs = (ctx->opcode >> 21) & 0x1f;
27589 rt = (ctx->opcode >> 16) & 0x1f;
27590 rd = (ctx->opcode >> 11) & 0x1f;
27591 sa = (ctx->opcode >> 6) & 0x1f;
27592 imm = (int16_t)ctx->opcode >> 7;
27594 op1 = MASK_SPECIAL3(ctx->opcode);
27595 switch (op1) {
27596 case R6_OPC_PREF:
27597 if (rt >= 24) {
27598 /* hint codes 24-31 are reserved and signal RI */
27599 gen_reserved_instruction(ctx);
27601 /* Treat as NOP. */
27602 break;
27603 case R6_OPC_CACHE:
27604 check_cp0_enabled(ctx);
27605 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27606 gen_cache_operation(ctx, rt, rs, imm);
27608 break;
27609 case R6_OPC_SC:
27610 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27611 break;
27612 case R6_OPC_LL:
27613 gen_ld(ctx, op1, rt, rs, imm);
27614 break;
27615 case OPC_BSHFL:
27617 if (rd == 0) {
27618 /* Treat as NOP. */
27619 break;
27621 op2 = MASK_BSHFL(ctx->opcode);
27622 switch (op2) {
27623 case OPC_ALIGN:
27624 case OPC_ALIGN_1:
27625 case OPC_ALIGN_2:
27626 case OPC_ALIGN_3:
27627 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27628 break;
27629 case OPC_BITSWAP:
27630 gen_bitswap(ctx, op2, rd, rt);
27631 break;
27634 break;
27635 #ifndef CONFIG_USER_ONLY
27636 case OPC_GINV:
27637 if (unlikely(ctx->gi <= 1)) {
27638 gen_reserved_instruction(ctx);
27640 check_cp0_enabled(ctx);
27641 switch ((ctx->opcode >> 6) & 3) {
27642 case 0: /* GINVI */
27643 /* Treat as NOP. */
27644 break;
27645 case 2: /* GINVT */
27646 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27647 break;
27648 default:
27649 gen_reserved_instruction(ctx);
27650 break;
27652 break;
27653 #endif
27654 #if defined(TARGET_MIPS64)
27655 case R6_OPC_SCD:
27656 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27657 break;
27658 case R6_OPC_LLD:
27659 gen_ld(ctx, op1, rt, rs, imm);
27660 break;
27661 case OPC_DBSHFL:
27662 check_mips_64(ctx);
27664 if (rd == 0) {
27665 /* Treat as NOP. */
27666 break;
27668 op2 = MASK_DBSHFL(ctx->opcode);
27669 switch (op2) {
27670 case OPC_DALIGN:
27671 case OPC_DALIGN_1:
27672 case OPC_DALIGN_2:
27673 case OPC_DALIGN_3:
27674 case OPC_DALIGN_4:
27675 case OPC_DALIGN_5:
27676 case OPC_DALIGN_6:
27677 case OPC_DALIGN_7:
27678 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27679 break;
27680 case OPC_DBITSWAP:
27681 gen_bitswap(ctx, op2, rd, rt);
27682 break;
27686 break;
27687 #endif
27688 default: /* Invalid */
27689 MIPS_INVAL("special3_r6");
27690 gen_reserved_instruction(ctx);
27691 break;
27695 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27697 int rs, rt, rd;
27698 uint32_t op1, op2;
27700 rs = (ctx->opcode >> 21) & 0x1f;
27701 rt = (ctx->opcode >> 16) & 0x1f;
27702 rd = (ctx->opcode >> 11) & 0x1f;
27704 op1 = MASK_SPECIAL3(ctx->opcode);
27705 switch (op1) {
27706 case OPC_DIV_G_2E:
27707 case OPC_DIVU_G_2E:
27708 case OPC_MOD_G_2E:
27709 case OPC_MODU_G_2E:
27710 case OPC_MULT_G_2E:
27711 case OPC_MULTU_G_2E:
27713 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27714 * the same mask and op1.
27716 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27717 op2 = MASK_ADDUH_QB(ctx->opcode);
27718 switch (op2) {
27719 case OPC_ADDUH_QB:
27720 case OPC_ADDUH_R_QB:
27721 case OPC_ADDQH_PH:
27722 case OPC_ADDQH_R_PH:
27723 case OPC_ADDQH_W:
27724 case OPC_ADDQH_R_W:
27725 case OPC_SUBUH_QB:
27726 case OPC_SUBUH_R_QB:
27727 case OPC_SUBQH_PH:
27728 case OPC_SUBQH_R_PH:
27729 case OPC_SUBQH_W:
27730 case OPC_SUBQH_R_W:
27731 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27732 break;
27733 case OPC_MUL_PH:
27734 case OPC_MUL_S_PH:
27735 case OPC_MULQ_S_W:
27736 case OPC_MULQ_RS_W:
27737 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27738 break;
27739 default:
27740 MIPS_INVAL("MASK ADDUH.QB");
27741 gen_reserved_instruction(ctx);
27742 break;
27744 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27745 gen_loongson_integer(ctx, op1, rd, rs, rt);
27746 } else {
27747 gen_reserved_instruction(ctx);
27749 break;
27750 case OPC_LX_DSP:
27751 op2 = MASK_LX(ctx->opcode);
27752 switch (op2) {
27753 #if defined(TARGET_MIPS64)
27754 case OPC_LDX:
27755 #endif
27756 case OPC_LBUX:
27757 case OPC_LHX:
27758 case OPC_LWX:
27759 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27760 break;
27761 default: /* Invalid */
27762 MIPS_INVAL("MASK LX");
27763 gen_reserved_instruction(ctx);
27764 break;
27766 break;
27767 case OPC_ABSQ_S_PH_DSP:
27768 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27769 switch (op2) {
27770 case OPC_ABSQ_S_QB:
27771 case OPC_ABSQ_S_PH:
27772 case OPC_ABSQ_S_W:
27773 case OPC_PRECEQ_W_PHL:
27774 case OPC_PRECEQ_W_PHR:
27775 case OPC_PRECEQU_PH_QBL:
27776 case OPC_PRECEQU_PH_QBR:
27777 case OPC_PRECEQU_PH_QBLA:
27778 case OPC_PRECEQU_PH_QBRA:
27779 case OPC_PRECEU_PH_QBL:
27780 case OPC_PRECEU_PH_QBR:
27781 case OPC_PRECEU_PH_QBLA:
27782 case OPC_PRECEU_PH_QBRA:
27783 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27784 break;
27785 case OPC_BITREV:
27786 case OPC_REPL_QB:
27787 case OPC_REPLV_QB:
27788 case OPC_REPL_PH:
27789 case OPC_REPLV_PH:
27790 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27791 break;
27792 default:
27793 MIPS_INVAL("MASK ABSQ_S.PH");
27794 gen_reserved_instruction(ctx);
27795 break;
27797 break;
27798 case OPC_ADDU_QB_DSP:
27799 op2 = MASK_ADDU_QB(ctx->opcode);
27800 switch (op2) {
27801 case OPC_ADDQ_PH:
27802 case OPC_ADDQ_S_PH:
27803 case OPC_ADDQ_S_W:
27804 case OPC_ADDU_QB:
27805 case OPC_ADDU_S_QB:
27806 case OPC_ADDU_PH:
27807 case OPC_ADDU_S_PH:
27808 case OPC_SUBQ_PH:
27809 case OPC_SUBQ_S_PH:
27810 case OPC_SUBQ_S_W:
27811 case OPC_SUBU_QB:
27812 case OPC_SUBU_S_QB:
27813 case OPC_SUBU_PH:
27814 case OPC_SUBU_S_PH:
27815 case OPC_ADDSC:
27816 case OPC_ADDWC:
27817 case OPC_MODSUB:
27818 case OPC_RADDU_W_QB:
27819 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27820 break;
27821 case OPC_MULEU_S_PH_QBL:
27822 case OPC_MULEU_S_PH_QBR:
27823 case OPC_MULQ_RS_PH:
27824 case OPC_MULEQ_S_W_PHL:
27825 case OPC_MULEQ_S_W_PHR:
27826 case OPC_MULQ_S_PH:
27827 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27828 break;
27829 default: /* Invalid */
27830 MIPS_INVAL("MASK ADDU.QB");
27831 gen_reserved_instruction(ctx);
27832 break;
27835 break;
27836 case OPC_CMPU_EQ_QB_DSP:
27837 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27838 switch (op2) {
27839 case OPC_PRECR_SRA_PH_W:
27840 case OPC_PRECR_SRA_R_PH_W:
27841 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27842 break;
27843 case OPC_PRECR_QB_PH:
27844 case OPC_PRECRQ_QB_PH:
27845 case OPC_PRECRQ_PH_W:
27846 case OPC_PRECRQ_RS_PH_W:
27847 case OPC_PRECRQU_S_QB_PH:
27848 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27849 break;
27850 case OPC_CMPU_EQ_QB:
27851 case OPC_CMPU_LT_QB:
27852 case OPC_CMPU_LE_QB:
27853 case OPC_CMP_EQ_PH:
27854 case OPC_CMP_LT_PH:
27855 case OPC_CMP_LE_PH:
27856 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27857 break;
27858 case OPC_CMPGU_EQ_QB:
27859 case OPC_CMPGU_LT_QB:
27860 case OPC_CMPGU_LE_QB:
27861 case OPC_CMPGDU_EQ_QB:
27862 case OPC_CMPGDU_LT_QB:
27863 case OPC_CMPGDU_LE_QB:
27864 case OPC_PICK_QB:
27865 case OPC_PICK_PH:
27866 case OPC_PACKRL_PH:
27867 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27868 break;
27869 default: /* Invalid */
27870 MIPS_INVAL("MASK CMPU.EQ.QB");
27871 gen_reserved_instruction(ctx);
27872 break;
27874 break;
27875 case OPC_SHLL_QB_DSP:
27876 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27877 break;
27878 case OPC_DPA_W_PH_DSP:
27879 op2 = MASK_DPA_W_PH(ctx->opcode);
27880 switch (op2) {
27881 case OPC_DPAU_H_QBL:
27882 case OPC_DPAU_H_QBR:
27883 case OPC_DPSU_H_QBL:
27884 case OPC_DPSU_H_QBR:
27885 case OPC_DPA_W_PH:
27886 case OPC_DPAX_W_PH:
27887 case OPC_DPAQ_S_W_PH:
27888 case OPC_DPAQX_S_W_PH:
27889 case OPC_DPAQX_SA_W_PH:
27890 case OPC_DPS_W_PH:
27891 case OPC_DPSX_W_PH:
27892 case OPC_DPSQ_S_W_PH:
27893 case OPC_DPSQX_S_W_PH:
27894 case OPC_DPSQX_SA_W_PH:
27895 case OPC_MULSAQ_S_W_PH:
27896 case OPC_DPAQ_SA_L_W:
27897 case OPC_DPSQ_SA_L_W:
27898 case OPC_MAQ_S_W_PHL:
27899 case OPC_MAQ_S_W_PHR:
27900 case OPC_MAQ_SA_W_PHL:
27901 case OPC_MAQ_SA_W_PHR:
27902 case OPC_MULSA_W_PH:
27903 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27904 break;
27905 default: /* Invalid */
27906 MIPS_INVAL("MASK DPAW.PH");
27907 gen_reserved_instruction(ctx);
27908 break;
27910 break;
27911 case OPC_INSV_DSP:
27912 op2 = MASK_INSV(ctx->opcode);
27913 switch (op2) {
27914 case OPC_INSV:
27915 check_dsp(ctx);
27917 TCGv t0, t1;
27919 if (rt == 0) {
27920 break;
27923 t0 = tcg_temp_new();
27924 t1 = tcg_temp_new();
27926 gen_load_gpr(t0, rt);
27927 gen_load_gpr(t1, rs);
27929 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27931 tcg_temp_free(t0);
27932 tcg_temp_free(t1);
27933 break;
27935 default: /* Invalid */
27936 MIPS_INVAL("MASK INSV");
27937 gen_reserved_instruction(ctx);
27938 break;
27940 break;
27941 case OPC_APPEND_DSP:
27942 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27943 break;
27944 case OPC_EXTR_W_DSP:
27945 op2 = MASK_EXTR_W(ctx->opcode);
27946 switch (op2) {
27947 case OPC_EXTR_W:
27948 case OPC_EXTR_R_W:
27949 case OPC_EXTR_RS_W:
27950 case OPC_EXTR_S_H:
27951 case OPC_EXTRV_S_H:
27952 case OPC_EXTRV_W:
27953 case OPC_EXTRV_R_W:
27954 case OPC_EXTRV_RS_W:
27955 case OPC_EXTP:
27956 case OPC_EXTPV:
27957 case OPC_EXTPDP:
27958 case OPC_EXTPDPV:
27959 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27960 break;
27961 case OPC_RDDSP:
27962 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27963 break;
27964 case OPC_SHILO:
27965 case OPC_SHILOV:
27966 case OPC_MTHLIP:
27967 case OPC_WRDSP:
27968 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27969 break;
27970 default: /* Invalid */
27971 MIPS_INVAL("MASK EXTR.W");
27972 gen_reserved_instruction(ctx);
27973 break;
27975 break;
27976 #if defined(TARGET_MIPS64)
27977 case OPC_DDIV_G_2E:
27978 case OPC_DDIVU_G_2E:
27979 case OPC_DMULT_G_2E:
27980 case OPC_DMULTU_G_2E:
27981 case OPC_DMOD_G_2E:
27982 case OPC_DMODU_G_2E:
27983 check_insn(ctx, INSN_LOONGSON2E);
27984 gen_loongson_integer(ctx, op1, rd, rs, rt);
27985 break;
27986 case OPC_ABSQ_S_QH_DSP:
27987 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27988 switch (op2) {
27989 case OPC_PRECEQ_L_PWL:
27990 case OPC_PRECEQ_L_PWR:
27991 case OPC_PRECEQ_PW_QHL:
27992 case OPC_PRECEQ_PW_QHR:
27993 case OPC_PRECEQ_PW_QHLA:
27994 case OPC_PRECEQ_PW_QHRA:
27995 case OPC_PRECEQU_QH_OBL:
27996 case OPC_PRECEQU_QH_OBR:
27997 case OPC_PRECEQU_QH_OBLA:
27998 case OPC_PRECEQU_QH_OBRA:
27999 case OPC_PRECEU_QH_OBL:
28000 case OPC_PRECEU_QH_OBR:
28001 case OPC_PRECEU_QH_OBLA:
28002 case OPC_PRECEU_QH_OBRA:
28003 case OPC_ABSQ_S_OB:
28004 case OPC_ABSQ_S_PW:
28005 case OPC_ABSQ_S_QH:
28006 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28007 break;
28008 case OPC_REPL_OB:
28009 case OPC_REPL_PW:
28010 case OPC_REPL_QH:
28011 case OPC_REPLV_OB:
28012 case OPC_REPLV_PW:
28013 case OPC_REPLV_QH:
28014 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
28015 break;
28016 default: /* Invalid */
28017 MIPS_INVAL("MASK ABSQ_S.QH");
28018 gen_reserved_instruction(ctx);
28019 break;
28021 break;
28022 case OPC_ADDU_OB_DSP:
28023 op2 = MASK_ADDU_OB(ctx->opcode);
28024 switch (op2) {
28025 case OPC_RADDU_L_OB:
28026 case OPC_SUBQ_PW:
28027 case OPC_SUBQ_S_PW:
28028 case OPC_SUBQ_QH:
28029 case OPC_SUBQ_S_QH:
28030 case OPC_SUBU_OB:
28031 case OPC_SUBU_S_OB:
28032 case OPC_SUBU_QH:
28033 case OPC_SUBU_S_QH:
28034 case OPC_SUBUH_OB:
28035 case OPC_SUBUH_R_OB:
28036 case OPC_ADDQ_PW:
28037 case OPC_ADDQ_S_PW:
28038 case OPC_ADDQ_QH:
28039 case OPC_ADDQ_S_QH:
28040 case OPC_ADDU_OB:
28041 case OPC_ADDU_S_OB:
28042 case OPC_ADDU_QH:
28043 case OPC_ADDU_S_QH:
28044 case OPC_ADDUH_OB:
28045 case OPC_ADDUH_R_OB:
28046 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28047 break;
28048 case OPC_MULEQ_S_PW_QHL:
28049 case OPC_MULEQ_S_PW_QHR:
28050 case OPC_MULEU_S_QH_OBL:
28051 case OPC_MULEU_S_QH_OBR:
28052 case OPC_MULQ_RS_QH:
28053 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
28054 break;
28055 default: /* Invalid */
28056 MIPS_INVAL("MASK ADDU.OB");
28057 gen_reserved_instruction(ctx);
28058 break;
28060 break;
28061 case OPC_CMPU_EQ_OB_DSP:
28062 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
28063 switch (op2) {
28064 case OPC_PRECR_SRA_QH_PW:
28065 case OPC_PRECR_SRA_R_QH_PW:
28066 /* Return value is rt. */
28067 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
28068 break;
28069 case OPC_PRECR_OB_QH:
28070 case OPC_PRECRQ_OB_QH:
28071 case OPC_PRECRQ_PW_L:
28072 case OPC_PRECRQ_QH_PW:
28073 case OPC_PRECRQ_RS_QH_PW:
28074 case OPC_PRECRQU_S_OB_QH:
28075 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28076 break;
28077 case OPC_CMPU_EQ_OB:
28078 case OPC_CMPU_LT_OB:
28079 case OPC_CMPU_LE_OB:
28080 case OPC_CMP_EQ_QH:
28081 case OPC_CMP_LT_QH:
28082 case OPC_CMP_LE_QH:
28083 case OPC_CMP_EQ_PW:
28084 case OPC_CMP_LT_PW:
28085 case OPC_CMP_LE_PW:
28086 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
28087 break;
28088 case OPC_CMPGDU_EQ_OB:
28089 case OPC_CMPGDU_LT_OB:
28090 case OPC_CMPGDU_LE_OB:
28091 case OPC_CMPGU_EQ_OB:
28092 case OPC_CMPGU_LT_OB:
28093 case OPC_CMPGU_LE_OB:
28094 case OPC_PACKRL_PW:
28095 case OPC_PICK_OB:
28096 case OPC_PICK_PW:
28097 case OPC_PICK_QH:
28098 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
28099 break;
28100 default: /* Invalid */
28101 MIPS_INVAL("MASK CMPU_EQ.OB");
28102 gen_reserved_instruction(ctx);
28103 break;
28105 break;
28106 case OPC_DAPPEND_DSP:
28107 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28108 break;
28109 case OPC_DEXTR_W_DSP:
28110 op2 = MASK_DEXTR_W(ctx->opcode);
28111 switch (op2) {
28112 case OPC_DEXTP:
28113 case OPC_DEXTPDP:
28114 case OPC_DEXTPDPV:
28115 case OPC_DEXTPV:
28116 case OPC_DEXTR_L:
28117 case OPC_DEXTR_R_L:
28118 case OPC_DEXTR_RS_L:
28119 case OPC_DEXTR_W:
28120 case OPC_DEXTR_R_W:
28121 case OPC_DEXTR_RS_W:
28122 case OPC_DEXTR_S_H:
28123 case OPC_DEXTRV_L:
28124 case OPC_DEXTRV_R_L:
28125 case OPC_DEXTRV_RS_L:
28126 case OPC_DEXTRV_S_H:
28127 case OPC_DEXTRV_W:
28128 case OPC_DEXTRV_R_W:
28129 case OPC_DEXTRV_RS_W:
28130 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28131 break;
28132 case OPC_DMTHLIP:
28133 case OPC_DSHILO:
28134 case OPC_DSHILOV:
28135 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28136 break;
28137 default: /* Invalid */
28138 MIPS_INVAL("MASK EXTR.W");
28139 gen_reserved_instruction(ctx);
28140 break;
28142 break;
28143 case OPC_DPAQ_W_QH_DSP:
28144 op2 = MASK_DPAQ_W_QH(ctx->opcode);
28145 switch (op2) {
28146 case OPC_DPAU_H_OBL:
28147 case OPC_DPAU_H_OBR:
28148 case OPC_DPSU_H_OBL:
28149 case OPC_DPSU_H_OBR:
28150 case OPC_DPA_W_QH:
28151 case OPC_DPAQ_S_W_QH:
28152 case OPC_DPS_W_QH:
28153 case OPC_DPSQ_S_W_QH:
28154 case OPC_MULSAQ_S_W_QH:
28155 case OPC_DPAQ_SA_L_PW:
28156 case OPC_DPSQ_SA_L_PW:
28157 case OPC_MULSAQ_S_L_PW:
28158 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28159 break;
28160 case OPC_MAQ_S_W_QHLL:
28161 case OPC_MAQ_S_W_QHLR:
28162 case OPC_MAQ_S_W_QHRL:
28163 case OPC_MAQ_S_W_QHRR:
28164 case OPC_MAQ_SA_W_QHLL:
28165 case OPC_MAQ_SA_W_QHLR:
28166 case OPC_MAQ_SA_W_QHRL:
28167 case OPC_MAQ_SA_W_QHRR:
28168 case OPC_MAQ_S_L_PWL:
28169 case OPC_MAQ_S_L_PWR:
28170 case OPC_DMADD:
28171 case OPC_DMADDU:
28172 case OPC_DMSUB:
28173 case OPC_DMSUBU:
28174 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28175 break;
28176 default: /* Invalid */
28177 MIPS_INVAL("MASK DPAQ.W.QH");
28178 gen_reserved_instruction(ctx);
28179 break;
28181 break;
28182 case OPC_DINSV_DSP:
28183 op2 = MASK_INSV(ctx->opcode);
28184 switch (op2) {
28185 case OPC_DINSV:
28187 TCGv t0, t1;
28189 if (rt == 0) {
28190 break;
28192 check_dsp(ctx);
28194 t0 = tcg_temp_new();
28195 t1 = tcg_temp_new();
28197 gen_load_gpr(t0, rt);
28198 gen_load_gpr(t1, rs);
28200 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
28202 tcg_temp_free(t0);
28203 tcg_temp_free(t1);
28204 break;
28206 default: /* Invalid */
28207 MIPS_INVAL("MASK DINSV");
28208 gen_reserved_instruction(ctx);
28209 break;
28211 break;
28212 case OPC_SHLL_OB_DSP:
28213 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
28214 break;
28215 #endif
28216 default: /* Invalid */
28217 MIPS_INVAL("special3_legacy");
28218 gen_reserved_instruction(ctx);
28219 break;
28224 #if defined(TARGET_MIPS64)
28226 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
28228 uint32_t opc = MASK_MMI0(ctx->opcode);
28230 switch (opc) {
28231 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
28232 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
28233 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
28234 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
28235 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
28236 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
28237 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
28238 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
28239 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
28240 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
28241 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
28242 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
28243 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
28244 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
28245 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
28246 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
28247 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
28248 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
28249 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
28250 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
28251 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
28252 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
28253 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
28254 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
28255 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
28256 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
28257 break;
28258 default:
28259 MIPS_INVAL("TX79 MMI class MMI0");
28260 gen_reserved_instruction(ctx);
28261 break;
28265 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
28267 uint32_t opc = MASK_MMI1(ctx->opcode);
28269 switch (opc) {
28270 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
28271 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
28272 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
28273 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
28274 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
28275 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
28276 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
28277 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
28278 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
28279 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
28280 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
28281 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
28282 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
28283 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
28284 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
28285 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
28286 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
28287 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
28288 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
28289 break;
28290 default:
28291 MIPS_INVAL("TX79 MMI class MMI1");
28292 gen_reserved_instruction(ctx);
28293 break;
28297 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
28299 uint32_t opc = MASK_MMI2(ctx->opcode);
28301 switch (opc) {
28302 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
28303 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
28304 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
28305 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
28306 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
28307 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
28308 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
28309 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
28310 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
28311 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
28312 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
28313 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
28314 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
28315 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
28316 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
28317 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
28318 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
28319 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
28320 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
28321 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
28322 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
28323 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
28324 break;
28325 case MMI_OPC_2_PCPYLD:
28326 gen_mmi_pcpyld(ctx);
28327 break;
28328 default:
28329 MIPS_INVAL("TX79 MMI class MMI2");
28330 gen_reserved_instruction(ctx);
28331 break;
28335 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
28337 uint32_t opc = MASK_MMI3(ctx->opcode);
28339 switch (opc) {
28340 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
28341 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
28342 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
28343 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
28344 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
28345 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
28346 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
28347 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
28348 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
28349 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
28350 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
28351 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
28352 break;
28353 case MMI_OPC_3_PCPYH:
28354 gen_mmi_pcpyh(ctx);
28355 break;
28356 case MMI_OPC_3_PCPYUD:
28357 gen_mmi_pcpyud(ctx);
28358 break;
28359 default:
28360 MIPS_INVAL("TX79 MMI class MMI3");
28361 gen_reserved_instruction(ctx);
28362 break;
28366 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
28368 uint32_t opc = MASK_MMI(ctx->opcode);
28369 int rs = extract32(ctx->opcode, 21, 5);
28370 int rt = extract32(ctx->opcode, 16, 5);
28371 int rd = extract32(ctx->opcode, 11, 5);
28373 switch (opc) {
28374 case MMI_OPC_CLASS_MMI0:
28375 decode_mmi0(env, ctx);
28376 break;
28377 case MMI_OPC_CLASS_MMI1:
28378 decode_mmi1(env, ctx);
28379 break;
28380 case MMI_OPC_CLASS_MMI2:
28381 decode_mmi2(env, ctx);
28382 break;
28383 case MMI_OPC_CLASS_MMI3:
28384 decode_mmi3(env, ctx);
28385 break;
28386 case MMI_OPC_MULT1:
28387 case MMI_OPC_MULTU1:
28388 case MMI_OPC_MADD:
28389 case MMI_OPC_MADDU:
28390 case MMI_OPC_MADD1:
28391 case MMI_OPC_MADDU1:
28392 gen_mul_txx9(ctx, opc, rd, rs, rt);
28393 break;
28394 case MMI_OPC_DIV1:
28395 case MMI_OPC_DIVU1:
28396 gen_div1_tx79(ctx, opc, rs, rt);
28397 break;
28398 case MMI_OPC_MTLO1:
28399 case MMI_OPC_MTHI1:
28400 gen_HILO1_tx79(ctx, opc, rs);
28401 break;
28402 case MMI_OPC_MFLO1:
28403 case MMI_OPC_MFHI1:
28404 gen_HILO1_tx79(ctx, opc, rd);
28405 break;
28406 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28407 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28408 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28409 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28410 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28411 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28412 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28413 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28414 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28415 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
28416 break;
28417 default:
28418 MIPS_INVAL("TX79 MMI class");
28419 gen_reserved_instruction(ctx);
28420 break;
28424 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28426 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
28429 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28431 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
28435 * The TX79-specific instruction Store Quadword
28437 * +--------+-------+-------+------------------------+
28438 * | 011111 | base | rt | offset | SQ
28439 * +--------+-------+-------+------------------------+
28440 * 6 5 5 16
28442 * has the same opcode as the Read Hardware Register instruction
28444 * +--------+-------+-------+-------+-------+--------+
28445 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28446 * +--------+-------+-------+-------+-------+--------+
28447 * 6 5 5 5 5 6
28449 * that is required, trapped and emulated by the Linux kernel. However, all
28450 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28451 * offset is odd. Therefore all valid SQ instructions can execute normally.
28452 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28453 * between SQ and RDHWR, as the Linux kernel does.
28455 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28457 int base = extract32(ctx->opcode, 21, 5);
28458 int rt = extract32(ctx->opcode, 16, 5);
28459 int offset = extract32(ctx->opcode, 0, 16);
28461 #ifdef CONFIG_USER_ONLY
28462 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28463 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28465 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28466 int rd = extract32(ctx->opcode, 11, 5);
28468 gen_rdhwr(ctx, rt, rd, 0);
28469 return;
28471 #endif
28473 gen_mmi_sq(ctx, base, rt, offset);
28476 #endif
28478 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28480 int rs, rt, rd, sa;
28481 uint32_t op1, op2;
28482 int16_t imm;
28484 rs = (ctx->opcode >> 21) & 0x1f;
28485 rt = (ctx->opcode >> 16) & 0x1f;
28486 rd = (ctx->opcode >> 11) & 0x1f;
28487 sa = (ctx->opcode >> 6) & 0x1f;
28488 imm = sextract32(ctx->opcode, 7, 9);
28490 op1 = MASK_SPECIAL3(ctx->opcode);
28493 * EVA loads and stores overlap Loongson 2E instructions decoded by
28494 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28495 * EVA is absent.
28497 if (ctx->eva) {
28498 switch (op1) {
28499 case OPC_LWLE:
28500 case OPC_LWRE:
28501 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28502 /* fall through */
28503 case OPC_LBUE:
28504 case OPC_LHUE:
28505 case OPC_LBE:
28506 case OPC_LHE:
28507 case OPC_LLE:
28508 case OPC_LWE:
28509 check_cp0_enabled(ctx);
28510 gen_ld(ctx, op1, rt, rs, imm);
28511 return;
28512 case OPC_SWLE:
28513 case OPC_SWRE:
28514 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28515 /* fall through */
28516 case OPC_SBE:
28517 case OPC_SHE:
28518 case OPC_SWE:
28519 check_cp0_enabled(ctx);
28520 gen_st(ctx, op1, rt, rs, imm);
28521 return;
28522 case OPC_SCE:
28523 check_cp0_enabled(ctx);
28524 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28525 return;
28526 case OPC_CACHEE:
28527 check_cp0_enabled(ctx);
28528 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28529 gen_cache_operation(ctx, rt, rs, imm);
28531 /* Treat as NOP. */
28532 return;
28533 case OPC_PREFE:
28534 check_cp0_enabled(ctx);
28535 /* Treat as NOP. */
28536 return;
28540 switch (op1) {
28541 case OPC_EXT:
28542 case OPC_INS:
28543 check_insn(ctx, ISA_MIPS_R2);
28544 gen_bitops(ctx, op1, rt, rs, sa, rd);
28545 break;
28546 case OPC_BSHFL:
28547 op2 = MASK_BSHFL(ctx->opcode);
28548 switch (op2) {
28549 case OPC_ALIGN:
28550 case OPC_ALIGN_1:
28551 case OPC_ALIGN_2:
28552 case OPC_ALIGN_3:
28553 case OPC_BITSWAP:
28554 check_insn(ctx, ISA_MIPS_R6);
28555 decode_opc_special3_r6(env, ctx);
28556 break;
28557 default:
28558 check_insn(ctx, ISA_MIPS_R2);
28559 gen_bshfl(ctx, op2, rt, rd);
28560 break;
28562 break;
28563 #if defined(TARGET_MIPS64)
28564 case OPC_DEXTM:
28565 case OPC_DEXTU:
28566 case OPC_DEXT:
28567 case OPC_DINSM:
28568 case OPC_DINSU:
28569 case OPC_DINS:
28570 check_insn(ctx, ISA_MIPS_R2);
28571 check_mips_64(ctx);
28572 gen_bitops(ctx, op1, rt, rs, sa, rd);
28573 break;
28574 case OPC_DBSHFL:
28575 op2 = MASK_DBSHFL(ctx->opcode);
28576 switch (op2) {
28577 case OPC_DALIGN:
28578 case OPC_DALIGN_1:
28579 case OPC_DALIGN_2:
28580 case OPC_DALIGN_3:
28581 case OPC_DALIGN_4:
28582 case OPC_DALIGN_5:
28583 case OPC_DALIGN_6:
28584 case OPC_DALIGN_7:
28585 case OPC_DBITSWAP:
28586 check_insn(ctx, ISA_MIPS_R6);
28587 decode_opc_special3_r6(env, ctx);
28588 break;
28589 default:
28590 check_insn(ctx, ISA_MIPS_R2);
28591 check_mips_64(ctx);
28592 op2 = MASK_DBSHFL(ctx->opcode);
28593 gen_bshfl(ctx, op2, rt, rd);
28594 break;
28596 break;
28597 #endif
28598 case OPC_RDHWR:
28599 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28600 break;
28601 case OPC_FORK:
28602 check_mt(ctx);
28604 TCGv t0 = tcg_temp_new();
28605 TCGv t1 = tcg_temp_new();
28607 gen_load_gpr(t0, rt);
28608 gen_load_gpr(t1, rs);
28609 gen_helper_fork(t0, t1);
28610 tcg_temp_free(t0);
28611 tcg_temp_free(t1);
28613 break;
28614 case OPC_YIELD:
28615 check_mt(ctx);
28617 TCGv t0 = tcg_temp_new();
28619 gen_load_gpr(t0, rs);
28620 gen_helper_yield(t0, cpu_env, t0);
28621 gen_store_gpr(t0, rd);
28622 tcg_temp_free(t0);
28624 break;
28625 default:
28626 if (ctx->insn_flags & ISA_MIPS_R6) {
28627 decode_opc_special3_r6(env, ctx);
28628 } else {
28629 decode_opc_special3_legacy(env, ctx);
28634 /* MIPS SIMD Architecture (MSA) */
28635 static inline int check_msa_access(DisasContext *ctx)
28637 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28638 !(ctx->hflags & MIPS_HFLAG_F64))) {
28639 gen_reserved_instruction(ctx);
28640 return 0;
28643 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28644 if (ctx->insn_flags & ASE_MSA) {
28645 generate_exception_end(ctx, EXCP_MSADIS);
28646 return 0;
28647 } else {
28648 gen_reserved_instruction(ctx);
28649 return 0;
28652 return 1;
28655 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28657 /* generates tcg ops to check if any element is 0 */
28658 /* Note this function only works with MSA_WRLEN = 128 */
28659 uint64_t eval_zero_or_big = 0;
28660 uint64_t eval_big = 0;
28661 TCGv_i64 t0 = tcg_temp_new_i64();
28662 TCGv_i64 t1 = tcg_temp_new_i64();
28663 switch (df) {
28664 case DF_BYTE:
28665 eval_zero_or_big = 0x0101010101010101ULL;
28666 eval_big = 0x8080808080808080ULL;
28667 break;
28668 case DF_HALF:
28669 eval_zero_or_big = 0x0001000100010001ULL;
28670 eval_big = 0x8000800080008000ULL;
28671 break;
28672 case DF_WORD:
28673 eval_zero_or_big = 0x0000000100000001ULL;
28674 eval_big = 0x8000000080000000ULL;
28675 break;
28676 case DF_DOUBLE:
28677 eval_zero_or_big = 0x0000000000000001ULL;
28678 eval_big = 0x8000000000000000ULL;
28679 break;
28681 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28682 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28683 tcg_gen_andi_i64(t0, t0, eval_big);
28684 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28685 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28686 tcg_gen_andi_i64(t1, t1, eval_big);
28687 tcg_gen_or_i64(t0, t0, t1);
28688 /* if all bits are zero then all elements are not zero */
28689 /* if some bit is non-zero then some element is zero */
28690 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28691 tcg_gen_trunc_i64_tl(tresult, t0);
28692 tcg_temp_free_i64(t0);
28693 tcg_temp_free_i64(t1);
28696 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28698 uint8_t df = (ctx->opcode >> 21) & 0x3;
28699 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28700 int64_t s16 = (int16_t)ctx->opcode;
28702 check_msa_access(ctx);
28704 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28705 gen_reserved_instruction(ctx);
28706 return;
28708 switch (op1) {
28709 case OPC_BZ_V:
28710 case OPC_BNZ_V:
28712 TCGv_i64 t0 = tcg_temp_new_i64();
28713 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28714 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28715 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28716 tcg_gen_trunc_i64_tl(bcond, t0);
28717 tcg_temp_free_i64(t0);
28719 break;
28720 case OPC_BZ_B:
28721 case OPC_BZ_H:
28722 case OPC_BZ_W:
28723 case OPC_BZ_D:
28724 gen_check_zero_element(bcond, df, wt);
28725 break;
28726 case OPC_BNZ_B:
28727 case OPC_BNZ_H:
28728 case OPC_BNZ_W:
28729 case OPC_BNZ_D:
28730 gen_check_zero_element(bcond, df, wt);
28731 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28732 break;
28735 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28737 ctx->hflags |= MIPS_HFLAG_BC;
28738 ctx->hflags |= MIPS_HFLAG_BDS32;
28741 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28743 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28744 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28745 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28746 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28748 TCGv_i32 twd = tcg_const_i32(wd);
28749 TCGv_i32 tws = tcg_const_i32(ws);
28750 TCGv_i32 ti8 = tcg_const_i32(i8);
28752 switch (MASK_MSA_I8(ctx->opcode)) {
28753 case OPC_ANDI_B:
28754 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28755 break;
28756 case OPC_ORI_B:
28757 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28758 break;
28759 case OPC_NORI_B:
28760 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28761 break;
28762 case OPC_XORI_B:
28763 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28764 break;
28765 case OPC_BMNZI_B:
28766 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28767 break;
28768 case OPC_BMZI_B:
28769 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28770 break;
28771 case OPC_BSELI_B:
28772 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28773 break;
28774 case OPC_SHF_B:
28775 case OPC_SHF_H:
28776 case OPC_SHF_W:
28778 uint8_t df = (ctx->opcode >> 24) & 0x3;
28779 if (df == DF_DOUBLE) {
28780 gen_reserved_instruction(ctx);
28781 } else {
28782 TCGv_i32 tdf = tcg_const_i32(df);
28783 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28784 tcg_temp_free_i32(tdf);
28787 break;
28788 default:
28789 MIPS_INVAL("MSA instruction");
28790 gen_reserved_instruction(ctx);
28791 break;
28794 tcg_temp_free_i32(twd);
28795 tcg_temp_free_i32(tws);
28796 tcg_temp_free_i32(ti8);
28799 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28801 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28802 uint8_t df = (ctx->opcode >> 21) & 0x3;
28803 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28804 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28805 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28806 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28808 TCGv_i32 tdf = tcg_const_i32(df);
28809 TCGv_i32 twd = tcg_const_i32(wd);
28810 TCGv_i32 tws = tcg_const_i32(ws);
28811 TCGv_i32 timm = tcg_temp_new_i32();
28812 tcg_gen_movi_i32(timm, u5);
28814 switch (MASK_MSA_I5(ctx->opcode)) {
28815 case OPC_ADDVI_df:
28816 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28817 break;
28818 case OPC_SUBVI_df:
28819 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28820 break;
28821 case OPC_MAXI_S_df:
28822 tcg_gen_movi_i32(timm, s5);
28823 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28824 break;
28825 case OPC_MAXI_U_df:
28826 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28827 break;
28828 case OPC_MINI_S_df:
28829 tcg_gen_movi_i32(timm, s5);
28830 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28831 break;
28832 case OPC_MINI_U_df:
28833 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28834 break;
28835 case OPC_CEQI_df:
28836 tcg_gen_movi_i32(timm, s5);
28837 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28838 break;
28839 case OPC_CLTI_S_df:
28840 tcg_gen_movi_i32(timm, s5);
28841 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28842 break;
28843 case OPC_CLTI_U_df:
28844 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28845 break;
28846 case OPC_CLEI_S_df:
28847 tcg_gen_movi_i32(timm, s5);
28848 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28849 break;
28850 case OPC_CLEI_U_df:
28851 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28852 break;
28853 case OPC_LDI_df:
28855 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28856 tcg_gen_movi_i32(timm, s10);
28857 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28859 break;
28860 default:
28861 MIPS_INVAL("MSA instruction");
28862 gen_reserved_instruction(ctx);
28863 break;
28866 tcg_temp_free_i32(tdf);
28867 tcg_temp_free_i32(twd);
28868 tcg_temp_free_i32(tws);
28869 tcg_temp_free_i32(timm);
28872 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28874 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28875 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28876 uint32_t df = 0, m = 0;
28877 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28878 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28880 TCGv_i32 tdf;
28881 TCGv_i32 tm;
28882 TCGv_i32 twd;
28883 TCGv_i32 tws;
28885 if ((dfm & 0x40) == 0x00) {
28886 m = dfm & 0x3f;
28887 df = DF_DOUBLE;
28888 } else if ((dfm & 0x60) == 0x40) {
28889 m = dfm & 0x1f;
28890 df = DF_WORD;
28891 } else if ((dfm & 0x70) == 0x60) {
28892 m = dfm & 0x0f;
28893 df = DF_HALF;
28894 } else if ((dfm & 0x78) == 0x70) {
28895 m = dfm & 0x7;
28896 df = DF_BYTE;
28897 } else {
28898 gen_reserved_instruction(ctx);
28899 return;
28902 tdf = tcg_const_i32(df);
28903 tm = tcg_const_i32(m);
28904 twd = tcg_const_i32(wd);
28905 tws = tcg_const_i32(ws);
28907 switch (MASK_MSA_BIT(ctx->opcode)) {
28908 case OPC_SLLI_df:
28909 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28910 break;
28911 case OPC_SRAI_df:
28912 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28913 break;
28914 case OPC_SRLI_df:
28915 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28916 break;
28917 case OPC_BCLRI_df:
28918 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28919 break;
28920 case OPC_BSETI_df:
28921 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28922 break;
28923 case OPC_BNEGI_df:
28924 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28925 break;
28926 case OPC_BINSLI_df:
28927 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28928 break;
28929 case OPC_BINSRI_df:
28930 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28931 break;
28932 case OPC_SAT_S_df:
28933 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28934 break;
28935 case OPC_SAT_U_df:
28936 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28937 break;
28938 case OPC_SRARI_df:
28939 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28940 break;
28941 case OPC_SRLRI_df:
28942 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28943 break;
28944 default:
28945 MIPS_INVAL("MSA instruction");
28946 gen_reserved_instruction(ctx);
28947 break;
28950 tcg_temp_free_i32(tdf);
28951 tcg_temp_free_i32(tm);
28952 tcg_temp_free_i32(twd);
28953 tcg_temp_free_i32(tws);
28956 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28958 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28959 uint8_t df = (ctx->opcode >> 21) & 0x3;
28960 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28961 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28962 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28964 TCGv_i32 tdf = tcg_const_i32(df);
28965 TCGv_i32 twd = tcg_const_i32(wd);
28966 TCGv_i32 tws = tcg_const_i32(ws);
28967 TCGv_i32 twt = tcg_const_i32(wt);
28969 switch (MASK_MSA_3R(ctx->opcode)) {
28970 case OPC_BINSL_df:
28971 switch (df) {
28972 case DF_BYTE:
28973 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28974 break;
28975 case DF_HALF:
28976 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28977 break;
28978 case DF_WORD:
28979 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28980 break;
28981 case DF_DOUBLE:
28982 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28983 break;
28985 break;
28986 case OPC_BINSR_df:
28987 switch (df) {
28988 case DF_BYTE:
28989 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28990 break;
28991 case DF_HALF:
28992 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28993 break;
28994 case DF_WORD:
28995 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28996 break;
28997 case DF_DOUBLE:
28998 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28999 break;
29001 break;
29002 case OPC_BCLR_df:
29003 switch (df) {
29004 case DF_BYTE:
29005 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
29006 break;
29007 case DF_HALF:
29008 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
29009 break;
29010 case DF_WORD:
29011 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
29012 break;
29013 case DF_DOUBLE:
29014 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
29015 break;
29017 break;
29018 case OPC_BNEG_df:
29019 switch (df) {
29020 case DF_BYTE:
29021 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
29022 break;
29023 case DF_HALF:
29024 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
29025 break;
29026 case DF_WORD:
29027 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
29028 break;
29029 case DF_DOUBLE:
29030 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
29031 break;
29033 break;
29034 case OPC_BSET_df:
29035 switch (df) {
29036 case DF_BYTE:
29037 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
29038 break;
29039 case DF_HALF:
29040 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
29041 break;
29042 case DF_WORD:
29043 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
29044 break;
29045 case DF_DOUBLE:
29046 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
29047 break;
29049 break;
29050 case OPC_ADD_A_df:
29051 switch (df) {
29052 case DF_BYTE:
29053 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
29054 break;
29055 case DF_HALF:
29056 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
29057 break;
29058 case DF_WORD:
29059 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
29060 break;
29061 case DF_DOUBLE:
29062 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
29063 break;
29065 break;
29066 case OPC_ADDS_A_df:
29067 switch (df) {
29068 case DF_BYTE:
29069 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
29070 break;
29071 case DF_HALF:
29072 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
29073 break;
29074 case DF_WORD:
29075 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
29076 break;
29077 case DF_DOUBLE:
29078 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
29079 break;
29081 break;
29082 case OPC_ADDS_S_df:
29083 switch (df) {
29084 case DF_BYTE:
29085 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
29086 break;
29087 case DF_HALF:
29088 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
29089 break;
29090 case DF_WORD:
29091 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
29092 break;
29093 case DF_DOUBLE:
29094 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
29095 break;
29097 break;
29098 case OPC_ADDS_U_df:
29099 switch (df) {
29100 case DF_BYTE:
29101 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
29102 break;
29103 case DF_HALF:
29104 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
29105 break;
29106 case DF_WORD:
29107 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
29108 break;
29109 case DF_DOUBLE:
29110 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
29111 break;
29113 break;
29114 case OPC_ADDV_df:
29115 switch (df) {
29116 case DF_BYTE:
29117 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
29118 break;
29119 case DF_HALF:
29120 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
29121 break;
29122 case DF_WORD:
29123 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
29124 break;
29125 case DF_DOUBLE:
29126 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
29127 break;
29129 break;
29130 case OPC_AVE_S_df:
29131 switch (df) {
29132 case DF_BYTE:
29133 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
29134 break;
29135 case DF_HALF:
29136 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
29137 break;
29138 case DF_WORD:
29139 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
29140 break;
29141 case DF_DOUBLE:
29142 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
29143 break;
29145 break;
29146 case OPC_AVE_U_df:
29147 switch (df) {
29148 case DF_BYTE:
29149 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
29150 break;
29151 case DF_HALF:
29152 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
29153 break;
29154 case DF_WORD:
29155 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
29156 break;
29157 case DF_DOUBLE:
29158 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
29159 break;
29161 break;
29162 case OPC_AVER_S_df:
29163 switch (df) {
29164 case DF_BYTE:
29165 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
29166 break;
29167 case DF_HALF:
29168 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
29169 break;
29170 case DF_WORD:
29171 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
29172 break;
29173 case DF_DOUBLE:
29174 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
29175 break;
29177 break;
29178 case OPC_AVER_U_df:
29179 switch (df) {
29180 case DF_BYTE:
29181 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
29182 break;
29183 case DF_HALF:
29184 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
29185 break;
29186 case DF_WORD:
29187 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
29188 break;
29189 case DF_DOUBLE:
29190 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
29191 break;
29193 break;
29194 case OPC_CEQ_df:
29195 switch (df) {
29196 case DF_BYTE:
29197 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
29198 break;
29199 case DF_HALF:
29200 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
29201 break;
29202 case DF_WORD:
29203 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
29204 break;
29205 case DF_DOUBLE:
29206 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
29207 break;
29209 break;
29210 case OPC_CLE_S_df:
29211 switch (df) {
29212 case DF_BYTE:
29213 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
29214 break;
29215 case DF_HALF:
29216 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
29217 break;
29218 case DF_WORD:
29219 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
29220 break;
29221 case DF_DOUBLE:
29222 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
29223 break;
29225 break;
29226 case OPC_CLE_U_df:
29227 switch (df) {
29228 case DF_BYTE:
29229 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
29230 break;
29231 case DF_HALF:
29232 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
29233 break;
29234 case DF_WORD:
29235 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
29236 break;
29237 case DF_DOUBLE:
29238 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
29239 break;
29241 break;
29242 case OPC_CLT_S_df:
29243 switch (df) {
29244 case DF_BYTE:
29245 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
29246 break;
29247 case DF_HALF:
29248 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
29249 break;
29250 case DF_WORD:
29251 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
29252 break;
29253 case DF_DOUBLE:
29254 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
29255 break;
29257 break;
29258 case OPC_CLT_U_df:
29259 switch (df) {
29260 case DF_BYTE:
29261 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
29262 break;
29263 case DF_HALF:
29264 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
29265 break;
29266 case DF_WORD:
29267 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
29268 break;
29269 case DF_DOUBLE:
29270 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
29271 break;
29273 break;
29274 case OPC_DIV_S_df:
29275 switch (df) {
29276 case DF_BYTE:
29277 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
29278 break;
29279 case DF_HALF:
29280 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
29281 break;
29282 case DF_WORD:
29283 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
29284 break;
29285 case DF_DOUBLE:
29286 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
29287 break;
29289 break;
29290 case OPC_DIV_U_df:
29291 switch (df) {
29292 case DF_BYTE:
29293 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
29294 break;
29295 case DF_HALF:
29296 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
29297 break;
29298 case DF_WORD:
29299 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
29300 break;
29301 case DF_DOUBLE:
29302 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
29303 break;
29305 break;
29306 case OPC_MAX_A_df:
29307 switch (df) {
29308 case DF_BYTE:
29309 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
29310 break;
29311 case DF_HALF:
29312 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
29313 break;
29314 case DF_WORD:
29315 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
29316 break;
29317 case DF_DOUBLE:
29318 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
29319 break;
29321 break;
29322 case OPC_MAX_S_df:
29323 switch (df) {
29324 case DF_BYTE:
29325 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
29326 break;
29327 case DF_HALF:
29328 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
29329 break;
29330 case DF_WORD:
29331 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
29332 break;
29333 case DF_DOUBLE:
29334 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
29335 break;
29337 break;
29338 case OPC_MAX_U_df:
29339 switch (df) {
29340 case DF_BYTE:
29341 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
29342 break;
29343 case DF_HALF:
29344 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
29345 break;
29346 case DF_WORD:
29347 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
29348 break;
29349 case DF_DOUBLE:
29350 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
29351 break;
29353 break;
29354 case OPC_MIN_A_df:
29355 switch (df) {
29356 case DF_BYTE:
29357 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
29358 break;
29359 case DF_HALF:
29360 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
29361 break;
29362 case DF_WORD:
29363 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
29364 break;
29365 case DF_DOUBLE:
29366 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
29367 break;
29369 break;
29370 case OPC_MIN_S_df:
29371 switch (df) {
29372 case DF_BYTE:
29373 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29374 break;
29375 case DF_HALF:
29376 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29377 break;
29378 case DF_WORD:
29379 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29380 break;
29381 case DF_DOUBLE:
29382 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29383 break;
29385 break;
29386 case OPC_MIN_U_df:
29387 switch (df) {
29388 case DF_BYTE:
29389 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29390 break;
29391 case DF_HALF:
29392 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29393 break;
29394 case DF_WORD:
29395 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29396 break;
29397 case DF_DOUBLE:
29398 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29399 break;
29401 break;
29402 case OPC_MOD_S_df:
29403 switch (df) {
29404 case DF_BYTE:
29405 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29406 break;
29407 case DF_HALF:
29408 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29409 break;
29410 case DF_WORD:
29411 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29412 break;
29413 case DF_DOUBLE:
29414 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29415 break;
29417 break;
29418 case OPC_MOD_U_df:
29419 switch (df) {
29420 case DF_BYTE:
29421 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29422 break;
29423 case DF_HALF:
29424 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29425 break;
29426 case DF_WORD:
29427 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29428 break;
29429 case DF_DOUBLE:
29430 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29431 break;
29433 break;
29434 case OPC_MADDV_df:
29435 switch (df) {
29436 case DF_BYTE:
29437 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29438 break;
29439 case DF_HALF:
29440 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29441 break;
29442 case DF_WORD:
29443 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29444 break;
29445 case DF_DOUBLE:
29446 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29447 break;
29449 break;
29450 case OPC_MSUBV_df:
29451 switch (df) {
29452 case DF_BYTE:
29453 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29454 break;
29455 case DF_HALF:
29456 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29457 break;
29458 case DF_WORD:
29459 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29460 break;
29461 case DF_DOUBLE:
29462 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29463 break;
29465 break;
29466 case OPC_ASUB_S_df:
29467 switch (df) {
29468 case DF_BYTE:
29469 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29470 break;
29471 case DF_HALF:
29472 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29473 break;
29474 case DF_WORD:
29475 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29476 break;
29477 case DF_DOUBLE:
29478 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29479 break;
29481 break;
29482 case OPC_ASUB_U_df:
29483 switch (df) {
29484 case DF_BYTE:
29485 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29486 break;
29487 case DF_HALF:
29488 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29489 break;
29490 case DF_WORD:
29491 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29492 break;
29493 case DF_DOUBLE:
29494 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29495 break;
29497 break;
29498 case OPC_ILVEV_df:
29499 switch (df) {
29500 case DF_BYTE:
29501 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29502 break;
29503 case DF_HALF:
29504 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29505 break;
29506 case DF_WORD:
29507 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29508 break;
29509 case DF_DOUBLE:
29510 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29511 break;
29513 break;
29514 case OPC_ILVOD_df:
29515 switch (df) {
29516 case DF_BYTE:
29517 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29518 break;
29519 case DF_HALF:
29520 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29521 break;
29522 case DF_WORD:
29523 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29524 break;
29525 case DF_DOUBLE:
29526 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29527 break;
29529 break;
29530 case OPC_ILVL_df:
29531 switch (df) {
29532 case DF_BYTE:
29533 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29534 break;
29535 case DF_HALF:
29536 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29537 break;
29538 case DF_WORD:
29539 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29540 break;
29541 case DF_DOUBLE:
29542 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29543 break;
29545 break;
29546 case OPC_ILVR_df:
29547 switch (df) {
29548 case DF_BYTE:
29549 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29550 break;
29551 case DF_HALF:
29552 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29553 break;
29554 case DF_WORD:
29555 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29556 break;
29557 case DF_DOUBLE:
29558 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29559 break;
29561 break;
29562 case OPC_PCKEV_df:
29563 switch (df) {
29564 case DF_BYTE:
29565 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29566 break;
29567 case DF_HALF:
29568 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29569 break;
29570 case DF_WORD:
29571 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29572 break;
29573 case DF_DOUBLE:
29574 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29575 break;
29577 break;
29578 case OPC_PCKOD_df:
29579 switch (df) {
29580 case DF_BYTE:
29581 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29582 break;
29583 case DF_HALF:
29584 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29585 break;
29586 case DF_WORD:
29587 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29588 break;
29589 case DF_DOUBLE:
29590 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29591 break;
29593 break;
29594 case OPC_SLL_df:
29595 switch (df) {
29596 case DF_BYTE:
29597 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29598 break;
29599 case DF_HALF:
29600 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29601 break;
29602 case DF_WORD:
29603 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29604 break;
29605 case DF_DOUBLE:
29606 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29607 break;
29609 break;
29610 case OPC_SRA_df:
29611 switch (df) {
29612 case DF_BYTE:
29613 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29614 break;
29615 case DF_HALF:
29616 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29617 break;
29618 case DF_WORD:
29619 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29620 break;
29621 case DF_DOUBLE:
29622 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29623 break;
29625 break;
29626 case OPC_SRAR_df:
29627 switch (df) {
29628 case DF_BYTE:
29629 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29630 break;
29631 case DF_HALF:
29632 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29633 break;
29634 case DF_WORD:
29635 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29636 break;
29637 case DF_DOUBLE:
29638 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29639 break;
29641 break;
29642 case OPC_SRL_df:
29643 switch (df) {
29644 case DF_BYTE:
29645 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29646 break;
29647 case DF_HALF:
29648 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29649 break;
29650 case DF_WORD:
29651 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29652 break;
29653 case DF_DOUBLE:
29654 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29655 break;
29657 break;
29658 case OPC_SRLR_df:
29659 switch (df) {
29660 case DF_BYTE:
29661 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29662 break;
29663 case DF_HALF:
29664 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29665 break;
29666 case DF_WORD:
29667 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29668 break;
29669 case DF_DOUBLE:
29670 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29671 break;
29673 break;
29674 case OPC_SUBS_S_df:
29675 switch (df) {
29676 case DF_BYTE:
29677 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29678 break;
29679 case DF_HALF:
29680 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29681 break;
29682 case DF_WORD:
29683 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29684 break;
29685 case DF_DOUBLE:
29686 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29687 break;
29689 break;
29690 case OPC_MULV_df:
29691 switch (df) {
29692 case DF_BYTE:
29693 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29694 break;
29695 case DF_HALF:
29696 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29697 break;
29698 case DF_WORD:
29699 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29700 break;
29701 case DF_DOUBLE:
29702 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29703 break;
29705 break;
29706 case OPC_SLD_df:
29707 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29708 break;
29709 case OPC_VSHF_df:
29710 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29711 break;
29712 case OPC_SUBV_df:
29713 switch (df) {
29714 case DF_BYTE:
29715 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29716 break;
29717 case DF_HALF:
29718 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29719 break;
29720 case DF_WORD:
29721 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29722 break;
29723 case DF_DOUBLE:
29724 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29725 break;
29727 break;
29728 case OPC_SUBS_U_df:
29729 switch (df) {
29730 case DF_BYTE:
29731 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29732 break;
29733 case DF_HALF:
29734 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29735 break;
29736 case DF_WORD:
29737 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29738 break;
29739 case DF_DOUBLE:
29740 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29741 break;
29743 break;
29744 case OPC_SPLAT_df:
29745 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29746 break;
29747 case OPC_SUBSUS_U_df:
29748 switch (df) {
29749 case DF_BYTE:
29750 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29751 break;
29752 case DF_HALF:
29753 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29754 break;
29755 case DF_WORD:
29756 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29757 break;
29758 case DF_DOUBLE:
29759 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29760 break;
29762 break;
29763 case OPC_SUBSUU_S_df:
29764 switch (df) {
29765 case DF_BYTE:
29766 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29767 break;
29768 case DF_HALF:
29769 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29770 break;
29771 case DF_WORD:
29772 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29773 break;
29774 case DF_DOUBLE:
29775 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29776 break;
29778 break;
29780 case OPC_DOTP_S_df:
29781 case OPC_DOTP_U_df:
29782 case OPC_DPADD_S_df:
29783 case OPC_DPADD_U_df:
29784 case OPC_DPSUB_S_df:
29785 case OPC_HADD_S_df:
29786 case OPC_DPSUB_U_df:
29787 case OPC_HADD_U_df:
29788 case OPC_HSUB_S_df:
29789 case OPC_HSUB_U_df:
29790 if (df == DF_BYTE) {
29791 gen_reserved_instruction(ctx);
29792 break;
29794 switch (MASK_MSA_3R(ctx->opcode)) {
29795 case OPC_HADD_S_df:
29796 switch (df) {
29797 case DF_HALF:
29798 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29799 break;
29800 case DF_WORD:
29801 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29802 break;
29803 case DF_DOUBLE:
29804 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29805 break;
29807 break;
29808 case OPC_HADD_U_df:
29809 switch (df) {
29810 case DF_HALF:
29811 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29812 break;
29813 case DF_WORD:
29814 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29815 break;
29816 case DF_DOUBLE:
29817 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29818 break;
29820 break;
29821 case OPC_HSUB_S_df:
29822 switch (df) {
29823 case DF_HALF:
29824 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29825 break;
29826 case DF_WORD:
29827 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29828 break;
29829 case DF_DOUBLE:
29830 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29831 break;
29833 break;
29834 case OPC_HSUB_U_df:
29835 switch (df) {
29836 case DF_HALF:
29837 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29838 break;
29839 case DF_WORD:
29840 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29841 break;
29842 case DF_DOUBLE:
29843 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29844 break;
29846 break;
29847 case OPC_DOTP_S_df:
29848 switch (df) {
29849 case DF_HALF:
29850 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29851 break;
29852 case DF_WORD:
29853 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29854 break;
29855 case DF_DOUBLE:
29856 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29857 break;
29859 break;
29860 case OPC_DOTP_U_df:
29861 switch (df) {
29862 case DF_HALF:
29863 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29864 break;
29865 case DF_WORD:
29866 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29867 break;
29868 case DF_DOUBLE:
29869 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29870 break;
29872 break;
29873 case OPC_DPADD_S_df:
29874 switch (df) {
29875 case DF_HALF:
29876 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29877 break;
29878 case DF_WORD:
29879 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29880 break;
29881 case DF_DOUBLE:
29882 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29883 break;
29885 break;
29886 case OPC_DPADD_U_df:
29887 switch (df) {
29888 case DF_HALF:
29889 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29890 break;
29891 case DF_WORD:
29892 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29893 break;
29894 case DF_DOUBLE:
29895 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29896 break;
29898 break;
29899 case OPC_DPSUB_S_df:
29900 switch (df) {
29901 case DF_HALF:
29902 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29903 break;
29904 case DF_WORD:
29905 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29906 break;
29907 case DF_DOUBLE:
29908 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29909 break;
29911 break;
29912 case OPC_DPSUB_U_df:
29913 switch (df) {
29914 case DF_HALF:
29915 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29916 break;
29917 case DF_WORD:
29918 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29919 break;
29920 case DF_DOUBLE:
29921 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29922 break;
29924 break;
29926 break;
29927 default:
29928 MIPS_INVAL("MSA instruction");
29929 gen_reserved_instruction(ctx);
29930 break;
29932 tcg_temp_free_i32(twd);
29933 tcg_temp_free_i32(tws);
29934 tcg_temp_free_i32(twt);
29935 tcg_temp_free_i32(tdf);
29938 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29940 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29941 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29942 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29943 TCGv telm = tcg_temp_new();
29944 TCGv_i32 tsr = tcg_const_i32(source);
29945 TCGv_i32 tdt = tcg_const_i32(dest);
29947 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29948 case OPC_CTCMSA:
29949 gen_load_gpr(telm, source);
29950 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29951 break;
29952 case OPC_CFCMSA:
29953 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29954 gen_store_gpr(telm, dest);
29955 break;
29956 case OPC_MOVE_V:
29957 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29958 break;
29959 default:
29960 MIPS_INVAL("MSA instruction");
29961 gen_reserved_instruction(ctx);
29962 break;
29965 tcg_temp_free(telm);
29966 tcg_temp_free_i32(tdt);
29967 tcg_temp_free_i32(tsr);
29970 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29971 uint32_t n)
29973 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29974 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29975 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29977 TCGv_i32 tws = tcg_const_i32(ws);
29978 TCGv_i32 twd = tcg_const_i32(wd);
29979 TCGv_i32 tn = tcg_const_i32(n);
29980 TCGv_i32 tdf = tcg_const_i32(df);
29982 switch (MASK_MSA_ELM(ctx->opcode)) {
29983 case OPC_SLDI_df:
29984 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29985 break;
29986 case OPC_SPLATI_df:
29987 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29988 break;
29989 case OPC_INSVE_df:
29990 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29991 break;
29992 case OPC_COPY_S_df:
29993 case OPC_COPY_U_df:
29994 case OPC_INSERT_df:
29995 #if !defined(TARGET_MIPS64)
29996 /* Double format valid only for MIPS64 */
29997 if (df == DF_DOUBLE) {
29998 gen_reserved_instruction(ctx);
29999 break;
30001 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
30002 (df == DF_WORD)) {
30003 gen_reserved_instruction(ctx);
30004 break;
30006 #endif
30007 switch (MASK_MSA_ELM(ctx->opcode)) {
30008 case OPC_COPY_S_df:
30009 if (likely(wd != 0)) {
30010 switch (df) {
30011 case DF_BYTE:
30012 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
30013 break;
30014 case DF_HALF:
30015 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
30016 break;
30017 case DF_WORD:
30018 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
30019 break;
30020 #if defined(TARGET_MIPS64)
30021 case DF_DOUBLE:
30022 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
30023 break;
30024 #endif
30025 default:
30026 assert(0);
30029 break;
30030 case OPC_COPY_U_df:
30031 if (likely(wd != 0)) {
30032 switch (df) {
30033 case DF_BYTE:
30034 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
30035 break;
30036 case DF_HALF:
30037 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
30038 break;
30039 #if defined(TARGET_MIPS64)
30040 case DF_WORD:
30041 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
30042 break;
30043 #endif
30044 default:
30045 assert(0);
30048 break;
30049 case OPC_INSERT_df:
30050 switch (df) {
30051 case DF_BYTE:
30052 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
30053 break;
30054 case DF_HALF:
30055 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
30056 break;
30057 case DF_WORD:
30058 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
30059 break;
30060 #if defined(TARGET_MIPS64)
30061 case DF_DOUBLE:
30062 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
30063 break;
30064 #endif
30065 default:
30066 assert(0);
30068 break;
30070 break;
30071 default:
30072 MIPS_INVAL("MSA instruction");
30073 gen_reserved_instruction(ctx);
30075 tcg_temp_free_i32(twd);
30076 tcg_temp_free_i32(tws);
30077 tcg_temp_free_i32(tn);
30078 tcg_temp_free_i32(tdf);
30081 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
30083 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
30084 uint32_t df = 0, n = 0;
30086 if ((dfn & 0x30) == 0x00) {
30087 n = dfn & 0x0f;
30088 df = DF_BYTE;
30089 } else if ((dfn & 0x38) == 0x20) {
30090 n = dfn & 0x07;
30091 df = DF_HALF;
30092 } else if ((dfn & 0x3c) == 0x30) {
30093 n = dfn & 0x03;
30094 df = DF_WORD;
30095 } else if ((dfn & 0x3e) == 0x38) {
30096 n = dfn & 0x01;
30097 df = DF_DOUBLE;
30098 } else if (dfn == 0x3E) {
30099 /* CTCMSA, CFCMSA, MOVE.V */
30100 gen_msa_elm_3e(env, ctx);
30101 return;
30102 } else {
30103 gen_reserved_instruction(ctx);
30104 return;
30107 gen_msa_elm_df(env, ctx, df, n);
30110 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
30112 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30113 uint8_t df = (ctx->opcode >> 21) & 0x1;
30114 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30115 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30116 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30118 TCGv_i32 twd = tcg_const_i32(wd);
30119 TCGv_i32 tws = tcg_const_i32(ws);
30120 TCGv_i32 twt = tcg_const_i32(wt);
30121 TCGv_i32 tdf = tcg_temp_new_i32();
30123 /* adjust df value for floating-point instruction */
30124 tcg_gen_movi_i32(tdf, df + 2);
30126 switch (MASK_MSA_3RF(ctx->opcode)) {
30127 case OPC_FCAF_df:
30128 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
30129 break;
30130 case OPC_FADD_df:
30131 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
30132 break;
30133 case OPC_FCUN_df:
30134 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
30135 break;
30136 case OPC_FSUB_df:
30137 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
30138 break;
30139 case OPC_FCOR_df:
30140 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
30141 break;
30142 case OPC_FCEQ_df:
30143 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
30144 break;
30145 case OPC_FMUL_df:
30146 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
30147 break;
30148 case OPC_FCUNE_df:
30149 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
30150 break;
30151 case OPC_FCUEQ_df:
30152 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
30153 break;
30154 case OPC_FDIV_df:
30155 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
30156 break;
30157 case OPC_FCNE_df:
30158 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
30159 break;
30160 case OPC_FCLT_df:
30161 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
30162 break;
30163 case OPC_FMADD_df:
30164 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
30165 break;
30166 case OPC_MUL_Q_df:
30167 tcg_gen_movi_i32(tdf, df + 1);
30168 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
30169 break;
30170 case OPC_FCULT_df:
30171 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
30172 break;
30173 case OPC_FMSUB_df:
30174 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
30175 break;
30176 case OPC_MADD_Q_df:
30177 tcg_gen_movi_i32(tdf, df + 1);
30178 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
30179 break;
30180 case OPC_FCLE_df:
30181 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
30182 break;
30183 case OPC_MSUB_Q_df:
30184 tcg_gen_movi_i32(tdf, df + 1);
30185 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
30186 break;
30187 case OPC_FCULE_df:
30188 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
30189 break;
30190 case OPC_FEXP2_df:
30191 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
30192 break;
30193 case OPC_FSAF_df:
30194 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
30195 break;
30196 case OPC_FEXDO_df:
30197 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
30198 break;
30199 case OPC_FSUN_df:
30200 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
30201 break;
30202 case OPC_FSOR_df:
30203 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
30204 break;
30205 case OPC_FSEQ_df:
30206 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
30207 break;
30208 case OPC_FTQ_df:
30209 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
30210 break;
30211 case OPC_FSUNE_df:
30212 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
30213 break;
30214 case OPC_FSUEQ_df:
30215 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
30216 break;
30217 case OPC_FSNE_df:
30218 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
30219 break;
30220 case OPC_FSLT_df:
30221 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
30222 break;
30223 case OPC_FMIN_df:
30224 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
30225 break;
30226 case OPC_MULR_Q_df:
30227 tcg_gen_movi_i32(tdf, df + 1);
30228 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
30229 break;
30230 case OPC_FSULT_df:
30231 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
30232 break;
30233 case OPC_FMIN_A_df:
30234 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
30235 break;
30236 case OPC_MADDR_Q_df:
30237 tcg_gen_movi_i32(tdf, df + 1);
30238 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
30239 break;
30240 case OPC_FSLE_df:
30241 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
30242 break;
30243 case OPC_FMAX_df:
30244 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
30245 break;
30246 case OPC_MSUBR_Q_df:
30247 tcg_gen_movi_i32(tdf, df + 1);
30248 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
30249 break;
30250 case OPC_FSULE_df:
30251 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
30252 break;
30253 case OPC_FMAX_A_df:
30254 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
30255 break;
30256 default:
30257 MIPS_INVAL("MSA instruction");
30258 gen_reserved_instruction(ctx);
30259 break;
30262 tcg_temp_free_i32(twd);
30263 tcg_temp_free_i32(tws);
30264 tcg_temp_free_i32(twt);
30265 tcg_temp_free_i32(tdf);
30268 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
30270 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30271 (op & (0x7 << 18)))
30272 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30273 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30274 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30275 uint8_t df = (ctx->opcode >> 16) & 0x3;
30276 TCGv_i32 twd = tcg_const_i32(wd);
30277 TCGv_i32 tws = tcg_const_i32(ws);
30278 TCGv_i32 twt = tcg_const_i32(wt);
30279 TCGv_i32 tdf = tcg_const_i32(df);
30281 switch (MASK_MSA_2R(ctx->opcode)) {
30282 case OPC_FILL_df:
30283 #if !defined(TARGET_MIPS64)
30284 /* Double format valid only for MIPS64 */
30285 if (df == DF_DOUBLE) {
30286 gen_reserved_instruction(ctx);
30287 break;
30289 #endif
30290 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
30291 break;
30292 case OPC_NLOC_df:
30293 switch (df) {
30294 case DF_BYTE:
30295 gen_helper_msa_nloc_b(cpu_env, twd, tws);
30296 break;
30297 case DF_HALF:
30298 gen_helper_msa_nloc_h(cpu_env, twd, tws);
30299 break;
30300 case DF_WORD:
30301 gen_helper_msa_nloc_w(cpu_env, twd, tws);
30302 break;
30303 case DF_DOUBLE:
30304 gen_helper_msa_nloc_d(cpu_env, twd, tws);
30305 break;
30307 break;
30308 case OPC_NLZC_df:
30309 switch (df) {
30310 case DF_BYTE:
30311 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
30312 break;
30313 case DF_HALF:
30314 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
30315 break;
30316 case DF_WORD:
30317 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
30318 break;
30319 case DF_DOUBLE:
30320 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
30321 break;
30323 break;
30324 case OPC_PCNT_df:
30325 switch (df) {
30326 case DF_BYTE:
30327 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
30328 break;
30329 case DF_HALF:
30330 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
30331 break;
30332 case DF_WORD:
30333 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
30334 break;
30335 case DF_DOUBLE:
30336 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
30337 break;
30339 break;
30340 default:
30341 MIPS_INVAL("MSA instruction");
30342 gen_reserved_instruction(ctx);
30343 break;
30346 tcg_temp_free_i32(twd);
30347 tcg_temp_free_i32(tws);
30348 tcg_temp_free_i32(twt);
30349 tcg_temp_free_i32(tdf);
30352 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
30354 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30355 (op & (0xf << 17)))
30356 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30357 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30358 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30359 uint8_t df = (ctx->opcode >> 16) & 0x1;
30360 TCGv_i32 twd = tcg_const_i32(wd);
30361 TCGv_i32 tws = tcg_const_i32(ws);
30362 TCGv_i32 twt = tcg_const_i32(wt);
30363 /* adjust df value for floating-point instruction */
30364 TCGv_i32 tdf = tcg_const_i32(df + 2);
30366 switch (MASK_MSA_2RF(ctx->opcode)) {
30367 case OPC_FCLASS_df:
30368 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
30369 break;
30370 case OPC_FTRUNC_S_df:
30371 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
30372 break;
30373 case OPC_FTRUNC_U_df:
30374 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30375 break;
30376 case OPC_FSQRT_df:
30377 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30378 break;
30379 case OPC_FRSQRT_df:
30380 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30381 break;
30382 case OPC_FRCP_df:
30383 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30384 break;
30385 case OPC_FRINT_df:
30386 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30387 break;
30388 case OPC_FLOG2_df:
30389 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30390 break;
30391 case OPC_FEXUPL_df:
30392 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30393 break;
30394 case OPC_FEXUPR_df:
30395 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30396 break;
30397 case OPC_FFQL_df:
30398 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30399 break;
30400 case OPC_FFQR_df:
30401 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30402 break;
30403 case OPC_FTINT_S_df:
30404 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30405 break;
30406 case OPC_FTINT_U_df:
30407 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30408 break;
30409 case OPC_FFINT_S_df:
30410 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30411 break;
30412 case OPC_FFINT_U_df:
30413 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30414 break;
30417 tcg_temp_free_i32(twd);
30418 tcg_temp_free_i32(tws);
30419 tcg_temp_free_i32(twt);
30420 tcg_temp_free_i32(tdf);
30423 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30425 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30426 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30427 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30428 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30429 TCGv_i32 twd = tcg_const_i32(wd);
30430 TCGv_i32 tws = tcg_const_i32(ws);
30431 TCGv_i32 twt = tcg_const_i32(wt);
30433 switch (MASK_MSA_VEC(ctx->opcode)) {
30434 case OPC_AND_V:
30435 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30436 break;
30437 case OPC_OR_V:
30438 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30439 break;
30440 case OPC_NOR_V:
30441 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30442 break;
30443 case OPC_XOR_V:
30444 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30445 break;
30446 case OPC_BMNZ_V:
30447 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30448 break;
30449 case OPC_BMZ_V:
30450 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30451 break;
30452 case OPC_BSEL_V:
30453 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30454 break;
30455 default:
30456 MIPS_INVAL("MSA instruction");
30457 gen_reserved_instruction(ctx);
30458 break;
30461 tcg_temp_free_i32(twd);
30462 tcg_temp_free_i32(tws);
30463 tcg_temp_free_i32(twt);
30466 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30468 switch (MASK_MSA_VEC(ctx->opcode)) {
30469 case OPC_AND_V:
30470 case OPC_OR_V:
30471 case OPC_NOR_V:
30472 case OPC_XOR_V:
30473 case OPC_BMNZ_V:
30474 case OPC_BMZ_V:
30475 case OPC_BSEL_V:
30476 gen_msa_vec_v(env, ctx);
30477 break;
30478 case OPC_MSA_2R:
30479 gen_msa_2r(env, ctx);
30480 break;
30481 case OPC_MSA_2RF:
30482 gen_msa_2rf(env, ctx);
30483 break;
30484 default:
30485 MIPS_INVAL("MSA instruction");
30486 gen_reserved_instruction(ctx);
30487 break;
30491 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30493 uint32_t opcode = ctx->opcode;
30494 check_insn(ctx, ASE_MSA);
30495 check_msa_access(ctx);
30497 switch (MASK_MSA_MINOR(opcode)) {
30498 case OPC_MSA_I8_00:
30499 case OPC_MSA_I8_01:
30500 case OPC_MSA_I8_02:
30501 gen_msa_i8(env, ctx);
30502 break;
30503 case OPC_MSA_I5_06:
30504 case OPC_MSA_I5_07:
30505 gen_msa_i5(env, ctx);
30506 break;
30507 case OPC_MSA_BIT_09:
30508 case OPC_MSA_BIT_0A:
30509 gen_msa_bit(env, ctx);
30510 break;
30511 case OPC_MSA_3R_0D:
30512 case OPC_MSA_3R_0E:
30513 case OPC_MSA_3R_0F:
30514 case OPC_MSA_3R_10:
30515 case OPC_MSA_3R_11:
30516 case OPC_MSA_3R_12:
30517 case OPC_MSA_3R_13:
30518 case OPC_MSA_3R_14:
30519 case OPC_MSA_3R_15:
30520 gen_msa_3r(env, ctx);
30521 break;
30522 case OPC_MSA_ELM:
30523 gen_msa_elm(env, ctx);
30524 break;
30525 case OPC_MSA_3RF_1A:
30526 case OPC_MSA_3RF_1B:
30527 case OPC_MSA_3RF_1C:
30528 gen_msa_3rf(env, ctx);
30529 break;
30530 case OPC_MSA_VEC:
30531 gen_msa_vec(env, ctx);
30532 break;
30533 case OPC_LD_B:
30534 case OPC_LD_H:
30535 case OPC_LD_W:
30536 case OPC_LD_D:
30537 case OPC_ST_B:
30538 case OPC_ST_H:
30539 case OPC_ST_W:
30540 case OPC_ST_D:
30542 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30543 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30544 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30545 uint8_t df = (ctx->opcode >> 0) & 0x3;
30547 TCGv_i32 twd = tcg_const_i32(wd);
30548 TCGv taddr = tcg_temp_new();
30549 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30551 switch (MASK_MSA_MINOR(opcode)) {
30552 case OPC_LD_B:
30553 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30554 break;
30555 case OPC_LD_H:
30556 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30557 break;
30558 case OPC_LD_W:
30559 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30560 break;
30561 case OPC_LD_D:
30562 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30563 break;
30564 case OPC_ST_B:
30565 gen_helper_msa_st_b(cpu_env, twd, taddr);
30566 break;
30567 case OPC_ST_H:
30568 gen_helper_msa_st_h(cpu_env, twd, taddr);
30569 break;
30570 case OPC_ST_W:
30571 gen_helper_msa_st_w(cpu_env, twd, taddr);
30572 break;
30573 case OPC_ST_D:
30574 gen_helper_msa_st_d(cpu_env, twd, taddr);
30575 break;
30578 tcg_temp_free_i32(twd);
30579 tcg_temp_free(taddr);
30581 break;
30582 default:
30583 MIPS_INVAL("MSA instruction");
30584 gen_reserved_instruction(ctx);
30585 break;
30590 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30592 int32_t offset;
30593 int rs, rt, rd, sa;
30594 uint32_t op, op1;
30595 int16_t imm;
30597 /* make sure instructions are on a word boundary */
30598 if (ctx->base.pc_next & 0x3) {
30599 env->CP0_BadVAddr = ctx->base.pc_next;
30600 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30601 return;
30604 /* Handle blikely not taken case */
30605 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30606 TCGLabel *l1 = gen_new_label();
30608 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30609 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30610 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30611 gen_set_label(l1);
30614 op = MASK_OP_MAJOR(ctx->opcode);
30615 rs = (ctx->opcode >> 21) & 0x1f;
30616 rt = (ctx->opcode >> 16) & 0x1f;
30617 rd = (ctx->opcode >> 11) & 0x1f;
30618 sa = (ctx->opcode >> 6) & 0x1f;
30619 imm = (int16_t)ctx->opcode;
30620 switch (op) {
30621 case OPC_SPECIAL:
30622 decode_opc_special(env, ctx);
30623 break;
30624 case OPC_SPECIAL2:
30625 #if defined(TARGET_MIPS64)
30626 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30627 decode_mmi(env, ctx);
30628 #else
30629 if (ctx->insn_flags & ASE_MXU) {
30630 decode_opc_mxu(env, ctx);
30631 #endif
30632 } else {
30633 decode_opc_special2_legacy(env, ctx);
30635 break;
30636 case OPC_SPECIAL3:
30637 #if defined(TARGET_MIPS64)
30638 if (ctx->insn_flags & INSN_R5900) {
30639 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30640 } else {
30641 decode_opc_special3(env, ctx);
30643 #else
30644 decode_opc_special3(env, ctx);
30645 #endif
30646 break;
30647 case OPC_REGIMM:
30648 op1 = MASK_REGIMM(ctx->opcode);
30649 switch (op1) {
30650 case OPC_BLTZL: /* REGIMM branches */
30651 case OPC_BGEZL:
30652 case OPC_BLTZALL:
30653 case OPC_BGEZALL:
30654 check_insn(ctx, ISA_MIPS2);
30655 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30656 /* Fallthrough */
30657 case OPC_BLTZ:
30658 case OPC_BGEZ:
30659 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30660 break;
30661 case OPC_BLTZAL:
30662 case OPC_BGEZAL:
30663 if (ctx->insn_flags & ISA_MIPS_R6) {
30664 if (rs == 0) {
30665 /* OPC_NAL, OPC_BAL */
30666 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30667 } else {
30668 gen_reserved_instruction(ctx);
30670 } else {
30671 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30673 break;
30674 case OPC_TGEI: /* REGIMM traps */
30675 case OPC_TGEIU:
30676 case OPC_TLTI:
30677 case OPC_TLTIU:
30678 case OPC_TEQI:
30680 case OPC_TNEI:
30681 check_insn(ctx, ISA_MIPS2);
30682 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30683 gen_trap(ctx, op1, rs, -1, imm);
30684 break;
30685 case OPC_SIGRIE:
30686 check_insn(ctx, ISA_MIPS_R6);
30687 gen_reserved_instruction(ctx);
30688 break;
30689 case OPC_SYNCI:
30690 check_insn(ctx, ISA_MIPS_R2);
30692 * Break the TB to be able to sync copied instructions
30693 * immediately.
30695 ctx->base.is_jmp = DISAS_STOP;
30696 break;
30697 case OPC_BPOSGE32: /* MIPS DSP branch */
30698 #if defined(TARGET_MIPS64)
30699 case OPC_BPOSGE64:
30700 #endif
30701 check_dsp(ctx);
30702 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30703 break;
30704 #if defined(TARGET_MIPS64)
30705 case OPC_DAHI:
30706 check_insn(ctx, ISA_MIPS_R6);
30707 check_mips_64(ctx);
30708 if (rs != 0) {
30709 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30711 break;
30712 case OPC_DATI:
30713 check_insn(ctx, ISA_MIPS_R6);
30714 check_mips_64(ctx);
30715 if (rs != 0) {
30716 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30718 break;
30719 #endif
30720 default: /* Invalid */
30721 MIPS_INVAL("regimm");
30722 gen_reserved_instruction(ctx);
30723 break;
30725 break;
30726 case OPC_CP0:
30727 check_cp0_enabled(ctx);
30728 op1 = MASK_CP0(ctx->opcode);
30729 switch (op1) {
30730 case OPC_MFC0:
30731 case OPC_MTC0:
30732 case OPC_MFTR:
30733 case OPC_MTTR:
30734 case OPC_MFHC0:
30735 case OPC_MTHC0:
30736 #if defined(TARGET_MIPS64)
30737 case OPC_DMFC0:
30738 case OPC_DMTC0:
30739 #endif
30740 #ifndef CONFIG_USER_ONLY
30741 gen_cp0(env, ctx, op1, rt, rd);
30742 #endif /* !CONFIG_USER_ONLY */
30743 break;
30744 case OPC_C0:
30745 case OPC_C0_1:
30746 case OPC_C0_2:
30747 case OPC_C0_3:
30748 case OPC_C0_4:
30749 case OPC_C0_5:
30750 case OPC_C0_6:
30751 case OPC_C0_7:
30752 case OPC_C0_8:
30753 case OPC_C0_9:
30754 case OPC_C0_A:
30755 case OPC_C0_B:
30756 case OPC_C0_C:
30757 case OPC_C0_D:
30758 case OPC_C0_E:
30759 case OPC_C0_F:
30760 #ifndef CONFIG_USER_ONLY
30761 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30762 #endif /* !CONFIG_USER_ONLY */
30763 break;
30764 case OPC_MFMC0:
30765 #ifndef CONFIG_USER_ONLY
30767 uint32_t op2;
30768 TCGv t0 = tcg_temp_new();
30770 op2 = MASK_MFMC0(ctx->opcode);
30771 switch (op2) {
30772 case OPC_DMT:
30773 check_cp0_mt(ctx);
30774 gen_helper_dmt(t0);
30775 gen_store_gpr(t0, rt);
30776 break;
30777 case OPC_EMT:
30778 check_cp0_mt(ctx);
30779 gen_helper_emt(t0);
30780 gen_store_gpr(t0, rt);
30781 break;
30782 case OPC_DVPE:
30783 check_cp0_mt(ctx);
30784 gen_helper_dvpe(t0, cpu_env);
30785 gen_store_gpr(t0, rt);
30786 break;
30787 case OPC_EVPE:
30788 check_cp0_mt(ctx);
30789 gen_helper_evpe(t0, cpu_env);
30790 gen_store_gpr(t0, rt);
30791 break;
30792 case OPC_DVP:
30793 check_insn(ctx, ISA_MIPS_R6);
30794 if (ctx->vp) {
30795 gen_helper_dvp(t0, cpu_env);
30796 gen_store_gpr(t0, rt);
30798 break;
30799 case OPC_EVP:
30800 check_insn(ctx, ISA_MIPS_R6);
30801 if (ctx->vp) {
30802 gen_helper_evp(t0, cpu_env);
30803 gen_store_gpr(t0, rt);
30805 break;
30806 case OPC_DI:
30807 check_insn(ctx, ISA_MIPS_R2);
30808 save_cpu_state(ctx, 1);
30809 gen_helper_di(t0, cpu_env);
30810 gen_store_gpr(t0, rt);
30812 * Stop translation as we may have switched
30813 * the execution mode.
30815 ctx->base.is_jmp = DISAS_STOP;
30816 break;
30817 case OPC_EI:
30818 check_insn(ctx, ISA_MIPS_R2);
30819 save_cpu_state(ctx, 1);
30820 gen_helper_ei(t0, cpu_env);
30821 gen_store_gpr(t0, rt);
30823 * DISAS_STOP isn't sufficient, we need to ensure we break
30824 * out of translated code to check for pending interrupts.
30826 gen_save_pc(ctx->base.pc_next + 4);
30827 ctx->base.is_jmp = DISAS_EXIT;
30828 break;
30829 default: /* Invalid */
30830 MIPS_INVAL("mfmc0");
30831 gen_reserved_instruction(ctx);
30832 break;
30834 tcg_temp_free(t0);
30836 #endif /* !CONFIG_USER_ONLY */
30837 break;
30838 case OPC_RDPGPR:
30839 check_insn(ctx, ISA_MIPS_R2);
30840 gen_load_srsgpr(rt, rd);
30841 break;
30842 case OPC_WRPGPR:
30843 check_insn(ctx, ISA_MIPS_R2);
30844 gen_store_srsgpr(rt, rd);
30845 break;
30846 default:
30847 MIPS_INVAL("cp0");
30848 gen_reserved_instruction(ctx);
30849 break;
30851 break;
30852 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30853 if (ctx->insn_flags & ISA_MIPS_R6) {
30854 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30855 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30856 } else {
30857 /* OPC_ADDI */
30858 /* Arithmetic with immediate opcode */
30859 gen_arith_imm(ctx, op, rt, rs, imm);
30861 break;
30862 case OPC_ADDIU:
30863 gen_arith_imm(ctx, op, rt, rs, imm);
30864 break;
30865 case OPC_SLTI: /* Set on less than with immediate opcode */
30866 case OPC_SLTIU:
30867 gen_slt_imm(ctx, op, rt, rs, imm);
30868 break;
30869 case OPC_ANDI: /* Arithmetic with immediate opcode */
30870 case OPC_LUI: /* OPC_AUI */
30871 case OPC_ORI:
30872 case OPC_XORI:
30873 gen_logic_imm(ctx, op, rt, rs, imm);
30874 break;
30875 case OPC_J: /* Jump */
30876 case OPC_JAL:
30877 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30878 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30879 break;
30880 /* Branch */
30881 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30882 if (ctx->insn_flags & ISA_MIPS_R6) {
30883 if (rt == 0) {
30884 gen_reserved_instruction(ctx);
30885 break;
30887 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30888 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30889 } else {
30890 /* OPC_BLEZL */
30891 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30893 break;
30894 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30895 if (ctx->insn_flags & ISA_MIPS_R6) {
30896 if (rt == 0) {
30897 gen_reserved_instruction(ctx);
30898 break;
30900 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30901 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30902 } else {
30903 /* OPC_BGTZL */
30904 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30906 break;
30907 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30908 if (rt == 0) {
30909 /* OPC_BLEZ */
30910 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30911 } else {
30912 check_insn(ctx, ISA_MIPS_R6);
30913 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30914 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30916 break;
30917 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30918 if (rt == 0) {
30919 /* OPC_BGTZ */
30920 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30921 } else {
30922 check_insn(ctx, ISA_MIPS_R6);
30923 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30924 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30926 break;
30927 case OPC_BEQL:
30928 case OPC_BNEL:
30929 check_insn(ctx, ISA_MIPS2);
30930 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30931 /* Fallthrough */
30932 case OPC_BEQ:
30933 case OPC_BNE:
30934 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30935 break;
30936 case OPC_LL: /* Load and stores */
30937 check_insn(ctx, ISA_MIPS2);
30938 if (ctx->insn_flags & INSN_R5900) {
30939 check_insn_opc_user_only(ctx, INSN_R5900);
30941 /* Fallthrough */
30942 case OPC_LWL:
30943 case OPC_LWR:
30944 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30945 /* Fallthrough */
30946 case OPC_LB:
30947 case OPC_LH:
30948 case OPC_LW:
30949 case OPC_LWPC:
30950 case OPC_LBU:
30951 case OPC_LHU:
30952 gen_ld(ctx, op, rt, rs, imm);
30953 break;
30954 case OPC_SWL:
30955 case OPC_SWR:
30956 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30957 /* fall through */
30958 case OPC_SB:
30959 case OPC_SH:
30960 case OPC_SW:
30961 gen_st(ctx, op, rt, rs, imm);
30962 break;
30963 case OPC_SC:
30964 check_insn(ctx, ISA_MIPS2);
30965 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30966 if (ctx->insn_flags & INSN_R5900) {
30967 check_insn_opc_user_only(ctx, INSN_R5900);
30969 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30970 break;
30971 case OPC_CACHE:
30972 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30973 check_cp0_enabled(ctx);
30974 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
30975 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30976 gen_cache_operation(ctx, rt, rs, imm);
30978 /* Treat as NOP. */
30979 break;
30980 case OPC_PREF:
30981 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30982 if (ctx->insn_flags & INSN_R5900) {
30983 /* Treat as NOP. */
30984 } else {
30985 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
30986 /* Treat as NOP. */
30988 break;
30990 /* Floating point (COP1). */
30991 case OPC_LWC1:
30992 case OPC_LDC1:
30993 case OPC_SWC1:
30994 case OPC_SDC1:
30995 gen_cop1_ldst(ctx, op, rt, rs, imm);
30996 break;
30998 case OPC_CP1:
30999 op1 = MASK_CP1(ctx->opcode);
31001 switch (op1) {
31002 case OPC_MFHC1:
31003 case OPC_MTHC1:
31004 check_cp1_enabled(ctx);
31005 check_insn(ctx, ISA_MIPS_R2);
31006 /* fall through */
31007 case OPC_MFC1:
31008 case OPC_CFC1:
31009 case OPC_MTC1:
31010 case OPC_CTC1:
31011 check_cp1_enabled(ctx);
31012 gen_cp1(ctx, op1, rt, rd);
31013 break;
31014 #if defined(TARGET_MIPS64)
31015 case OPC_DMFC1:
31016 case OPC_DMTC1:
31017 check_cp1_enabled(ctx);
31018 check_insn(ctx, ISA_MIPS3);
31019 check_mips_64(ctx);
31020 gen_cp1(ctx, op1, rt, rd);
31021 break;
31022 #endif
31023 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
31024 check_cp1_enabled(ctx);
31025 if (ctx->insn_flags & ISA_MIPS_R6) {
31026 /* OPC_BC1EQZ */
31027 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
31028 rt, imm << 2, 4);
31029 } else {
31030 /* OPC_BC1ANY2 */
31031 check_cop1x(ctx);
31032 check_insn(ctx, ASE_MIPS3D);
31033 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31034 (rt >> 2) & 0x7, imm << 2);
31036 break;
31037 case OPC_BC1NEZ:
31038 check_cp1_enabled(ctx);
31039 check_insn(ctx, ISA_MIPS_R6);
31040 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
31041 rt, imm << 2, 4);
31042 break;
31043 case OPC_BC1ANY4:
31044 check_cp1_enabled(ctx);
31045 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31046 check_cop1x(ctx);
31047 check_insn(ctx, ASE_MIPS3D);
31048 /* fall through */
31049 case OPC_BC1:
31050 check_cp1_enabled(ctx);
31051 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31052 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31053 (rt >> 2) & 0x7, imm << 2);
31054 break;
31055 case OPC_PS_FMT:
31056 check_ps(ctx);
31057 /* fall through */
31058 case OPC_S_FMT:
31059 case OPC_D_FMT:
31060 check_cp1_enabled(ctx);
31061 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31062 (imm >> 8) & 0x7);
31063 break;
31064 case OPC_W_FMT:
31065 case OPC_L_FMT:
31067 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
31068 check_cp1_enabled(ctx);
31069 if (ctx->insn_flags & ISA_MIPS_R6) {
31070 switch (r6_op) {
31071 case R6_OPC_CMP_AF_S:
31072 case R6_OPC_CMP_UN_S:
31073 case R6_OPC_CMP_EQ_S:
31074 case R6_OPC_CMP_UEQ_S:
31075 case R6_OPC_CMP_LT_S:
31076 case R6_OPC_CMP_ULT_S:
31077 case R6_OPC_CMP_LE_S:
31078 case R6_OPC_CMP_ULE_S:
31079 case R6_OPC_CMP_SAF_S:
31080 case R6_OPC_CMP_SUN_S:
31081 case R6_OPC_CMP_SEQ_S:
31082 case R6_OPC_CMP_SEUQ_S:
31083 case R6_OPC_CMP_SLT_S:
31084 case R6_OPC_CMP_SULT_S:
31085 case R6_OPC_CMP_SLE_S:
31086 case R6_OPC_CMP_SULE_S:
31087 case R6_OPC_CMP_OR_S:
31088 case R6_OPC_CMP_UNE_S:
31089 case R6_OPC_CMP_NE_S:
31090 case R6_OPC_CMP_SOR_S:
31091 case R6_OPC_CMP_SUNE_S:
31092 case R6_OPC_CMP_SNE_S:
31093 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31094 break;
31095 case R6_OPC_CMP_AF_D:
31096 case R6_OPC_CMP_UN_D:
31097 case R6_OPC_CMP_EQ_D:
31098 case R6_OPC_CMP_UEQ_D:
31099 case R6_OPC_CMP_LT_D:
31100 case R6_OPC_CMP_ULT_D:
31101 case R6_OPC_CMP_LE_D:
31102 case R6_OPC_CMP_ULE_D:
31103 case R6_OPC_CMP_SAF_D:
31104 case R6_OPC_CMP_SUN_D:
31105 case R6_OPC_CMP_SEQ_D:
31106 case R6_OPC_CMP_SEUQ_D:
31107 case R6_OPC_CMP_SLT_D:
31108 case R6_OPC_CMP_SULT_D:
31109 case R6_OPC_CMP_SLE_D:
31110 case R6_OPC_CMP_SULE_D:
31111 case R6_OPC_CMP_OR_D:
31112 case R6_OPC_CMP_UNE_D:
31113 case R6_OPC_CMP_NE_D:
31114 case R6_OPC_CMP_SOR_D:
31115 case R6_OPC_CMP_SUNE_D:
31116 case R6_OPC_CMP_SNE_D:
31117 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31118 break;
31119 default:
31120 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
31121 rt, rd, sa, (imm >> 8) & 0x7);
31123 break;
31125 } else {
31126 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31127 (imm >> 8) & 0x7);
31129 break;
31131 case OPC_BZ_V:
31132 case OPC_BNZ_V:
31133 case OPC_BZ_B:
31134 case OPC_BZ_H:
31135 case OPC_BZ_W:
31136 case OPC_BZ_D:
31137 case OPC_BNZ_B:
31138 case OPC_BNZ_H:
31139 case OPC_BNZ_W:
31140 case OPC_BNZ_D:
31141 check_insn(ctx, ASE_MSA);
31142 gen_msa_branch(env, ctx, op1);
31143 break;
31144 default:
31145 MIPS_INVAL("cp1");
31146 gen_reserved_instruction(ctx);
31147 break;
31149 break;
31151 /* Compact branches [R6] and COP2 [non-R6] */
31152 case OPC_BC: /* OPC_LWC2 */
31153 case OPC_BALC: /* OPC_SWC2 */
31154 if (ctx->insn_flags & ISA_MIPS_R6) {
31155 /* OPC_BC, OPC_BALC */
31156 gen_compute_compact_branch(ctx, op, 0, 0,
31157 sextract32(ctx->opcode << 2, 0, 28));
31158 } else if (ctx->insn_flags & ASE_LEXT) {
31159 gen_loongson_lswc2(ctx, rt, rs, rd);
31160 } else {
31161 /* OPC_LWC2, OPC_SWC2 */
31162 /* COP2: Not implemented. */
31163 generate_exception_err(ctx, EXCP_CpU, 2);
31165 break;
31166 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
31167 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
31168 if (ctx->insn_flags & ISA_MIPS_R6) {
31169 if (rs != 0) {
31170 /* OPC_BEQZC, OPC_BNEZC */
31171 gen_compute_compact_branch(ctx, op, rs, 0,
31172 sextract32(ctx->opcode << 2, 0, 23));
31173 } else {
31174 /* OPC_JIC, OPC_JIALC */
31175 gen_compute_compact_branch(ctx, op, 0, rt, imm);
31177 } else if (ctx->insn_flags & ASE_LEXT) {
31178 gen_loongson_lsdc2(ctx, rt, rs, rd);
31179 } else {
31180 /* OPC_LWC2, OPC_SWC2 */
31181 /* COP2: Not implemented. */
31182 generate_exception_err(ctx, EXCP_CpU, 2);
31184 break;
31185 case OPC_CP2:
31186 check_insn(ctx, ASE_LMMI);
31187 /* Note that these instructions use different fields. */
31188 gen_loongson_multimedia(ctx, sa, rd, rt);
31189 break;
31191 case OPC_CP3:
31192 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31193 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
31194 check_cp1_enabled(ctx);
31195 op1 = MASK_CP3(ctx->opcode);
31196 switch (op1) {
31197 case OPC_LUXC1:
31198 case OPC_SUXC1:
31199 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
31200 /* Fallthrough */
31201 case OPC_LWXC1:
31202 case OPC_LDXC1:
31203 case OPC_SWXC1:
31204 case OPC_SDXC1:
31205 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31206 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
31207 break;
31208 case OPC_PREFX:
31209 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31210 /* Treat as NOP. */
31211 break;
31212 case OPC_ALNV_PS:
31213 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
31214 /* Fallthrough */
31215 case OPC_MADD_S:
31216 case OPC_MADD_D:
31217 case OPC_MADD_PS:
31218 case OPC_MSUB_S:
31219 case OPC_MSUB_D:
31220 case OPC_MSUB_PS:
31221 case OPC_NMADD_S:
31222 case OPC_NMADD_D:
31223 case OPC_NMADD_PS:
31224 case OPC_NMSUB_S:
31225 case OPC_NMSUB_D:
31226 case OPC_NMSUB_PS:
31227 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31228 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
31229 break;
31230 default:
31231 MIPS_INVAL("cp3");
31232 gen_reserved_instruction(ctx);
31233 break;
31235 } else {
31236 generate_exception_err(ctx, EXCP_CpU, 1);
31238 break;
31240 #if defined(TARGET_MIPS64)
31241 /* MIPS64 opcodes */
31242 case OPC_LLD:
31243 if (ctx->insn_flags & INSN_R5900) {
31244 check_insn_opc_user_only(ctx, INSN_R5900);
31246 /* fall through */
31247 case OPC_LDL:
31248 case OPC_LDR:
31249 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31250 /* fall through */
31251 case OPC_LWU:
31252 case OPC_LD:
31253 check_insn(ctx, ISA_MIPS3);
31254 check_mips_64(ctx);
31255 gen_ld(ctx, op, rt, rs, imm);
31256 break;
31257 case OPC_SDL:
31258 case OPC_SDR:
31259 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31260 /* fall through */
31261 case OPC_SD:
31262 check_insn(ctx, ISA_MIPS3);
31263 check_mips_64(ctx);
31264 gen_st(ctx, op, rt, rs, imm);
31265 break;
31266 case OPC_SCD:
31267 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31268 check_insn(ctx, ISA_MIPS3);
31269 if (ctx->insn_flags & INSN_R5900) {
31270 check_insn_opc_user_only(ctx, INSN_R5900);
31272 check_mips_64(ctx);
31273 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
31274 break;
31275 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
31276 if (ctx->insn_flags & ISA_MIPS_R6) {
31277 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
31278 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31279 } else {
31280 /* OPC_DADDI */
31281 check_insn(ctx, ISA_MIPS3);
31282 check_mips_64(ctx);
31283 gen_arith_imm(ctx, op, rt, rs, imm);
31285 break;
31286 case OPC_DADDIU:
31287 check_insn(ctx, ISA_MIPS3);
31288 check_mips_64(ctx);
31289 gen_arith_imm(ctx, op, rt, rs, imm);
31290 break;
31291 #else
31292 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
31293 if (ctx->insn_flags & ISA_MIPS_R6) {
31294 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31295 } else {
31296 MIPS_INVAL("major opcode");
31297 gen_reserved_instruction(ctx);
31299 break;
31300 #endif
31301 case OPC_DAUI: /* OPC_JALX */
31302 if (ctx->insn_flags & ISA_MIPS_R6) {
31303 #if defined(TARGET_MIPS64)
31304 /* OPC_DAUI */
31305 check_mips_64(ctx);
31306 if (rs == 0) {
31307 generate_exception(ctx, EXCP_RI);
31308 } else if (rt != 0) {
31309 TCGv t0 = tcg_temp_new();
31310 gen_load_gpr(t0, rs);
31311 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
31312 tcg_temp_free(t0);
31314 #else
31315 gen_reserved_instruction(ctx);
31316 MIPS_INVAL("major opcode");
31317 #endif
31318 } else {
31319 /* OPC_JALX */
31320 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
31321 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
31322 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
31324 break;
31325 case OPC_MSA: /* OPC_MDMX */
31326 if (ctx->insn_flags & INSN_R5900) {
31327 #if defined(TARGET_MIPS64)
31328 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
31329 #endif
31330 } else {
31331 /* MDMX: Not implemented. */
31332 gen_msa(env, ctx);
31334 break;
31335 case OPC_PCREL:
31336 check_insn(ctx, ISA_MIPS_R6);
31337 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
31338 break;
31339 default: /* Invalid */
31340 MIPS_INVAL("major opcode");
31341 gen_reserved_instruction(ctx);
31342 break;
31346 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
31348 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31349 CPUMIPSState *env = cs->env_ptr;
31351 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
31352 ctx->saved_pc = -1;
31353 ctx->insn_flags = env->insn_flags;
31354 ctx->CP0_Config1 = env->CP0_Config1;
31355 ctx->CP0_Config2 = env->CP0_Config2;
31356 ctx->CP0_Config3 = env->CP0_Config3;
31357 ctx->CP0_Config5 = env->CP0_Config5;
31358 ctx->btarget = 0;
31359 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
31360 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
31361 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
31362 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
31363 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
31364 ctx->PAMask = env->PAMask;
31365 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
31366 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
31367 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
31368 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
31369 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
31370 /* Restore delay slot state from the tb context. */
31371 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
31372 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
31373 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
31374 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
31375 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
31376 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31377 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31378 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
31379 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
31380 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
31381 restore_cpu_state(env, ctx);
31382 #ifdef CONFIG_USER_ONLY
31383 ctx->mem_idx = MIPS_HFLAG_UM;
31384 #else
31385 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
31386 #endif
31387 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
31388 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
31390 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31391 ctx->hflags);
31394 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31398 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31400 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31402 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31403 ctx->btarget);
31406 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31407 const CPUBreakpoint *bp)
31409 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31411 save_cpu_state(ctx, 1);
31412 ctx->base.is_jmp = DISAS_NORETURN;
31413 gen_helper_raise_exception_debug(cpu_env);
31415 * The address covered by the breakpoint must be included in
31416 * [tb->pc, tb->pc + tb->size) in order to for it to be
31417 * properly cleared -- thus we increment the PC here so that
31418 * the logic setting tb->size below does the right thing.
31420 ctx->base.pc_next += 4;
31421 return true;
31424 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31426 CPUMIPSState *env = cs->env_ptr;
31427 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31428 int insn_bytes;
31429 int is_slot;
31431 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
31432 if (ctx->insn_flags & ISA_NANOMIPS32) {
31433 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31434 insn_bytes = decode_nanomips_opc(env, ctx);
31435 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
31436 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31437 insn_bytes = 4;
31438 decode_opc(env, ctx);
31439 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31440 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31441 insn_bytes = decode_micromips_opc(env, ctx);
31442 } else if (ctx->insn_flags & ASE_MIPS16) {
31443 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31444 insn_bytes = decode_mips16_opc(env, ctx);
31445 } else {
31446 gen_reserved_instruction(ctx);
31447 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31448 return;
31451 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31452 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31453 MIPS_HFLAG_FBNSLOT))) {
31455 * Force to generate branch as there is neither delay nor
31456 * forbidden slot.
31458 is_slot = 1;
31460 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31461 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
31463 * Force to generate branch as microMIPS R6 doesn't restrict
31464 * branches in the forbidden slot.
31466 is_slot = 1;
31469 if (is_slot) {
31470 gen_branch(ctx, insn_bytes);
31472 ctx->base.pc_next += insn_bytes;
31474 if (ctx->base.is_jmp != DISAS_NEXT) {
31475 return;
31478 * Execute a branch and its delay slot as a single instruction.
31479 * This is what GDB expects and is consistent with what the
31480 * hardware does (e.g. if a delay slot instruction faults, the
31481 * reported PC is the PC of the branch).
31483 if (ctx->base.singlestep_enabled &&
31484 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31485 ctx->base.is_jmp = DISAS_TOO_MANY;
31487 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31488 ctx->base.is_jmp = DISAS_TOO_MANY;
31492 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31494 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31496 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31497 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
31498 gen_helper_raise_exception_debug(cpu_env);
31499 } else {
31500 switch (ctx->base.is_jmp) {
31501 case DISAS_STOP:
31502 gen_save_pc(ctx->base.pc_next);
31503 tcg_gen_lookup_and_goto_ptr();
31504 break;
31505 case DISAS_NEXT:
31506 case DISAS_TOO_MANY:
31507 save_cpu_state(ctx, 0);
31508 gen_goto_tb(ctx, 0, ctx->base.pc_next);
31509 break;
31510 case DISAS_EXIT:
31511 tcg_gen_exit_tb(NULL, 0);
31512 break;
31513 case DISAS_NORETURN:
31514 break;
31515 default:
31516 g_assert_not_reached();
31521 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31523 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31524 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31527 static const TranslatorOps mips_tr_ops = {
31528 .init_disas_context = mips_tr_init_disas_context,
31529 .tb_start = mips_tr_tb_start,
31530 .insn_start = mips_tr_insn_start,
31531 .breakpoint_check = mips_tr_breakpoint_check,
31532 .translate_insn = mips_tr_translate_insn,
31533 .tb_stop = mips_tr_tb_stop,
31534 .disas_log = mips_tr_disas_log,
31537 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31539 DisasContext ctx;
31541 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31544 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31546 int i;
31547 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31549 #define printfpr(fp) \
31550 do { \
31551 if (is_fpu64) \
31552 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31553 " fd:%13g fs:%13g psu: %13g\n", \
31554 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31555 (double)(fp)->fd, \
31556 (double)(fp)->fs[FP_ENDIAN_IDX], \
31557 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31558 else { \
31559 fpr_t tmp; \
31560 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31561 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31562 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31563 " fd:%13g fs:%13g psu:%13g\n", \
31564 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31565 (double)tmp.fd, \
31566 (double)tmp.fs[FP_ENDIAN_IDX], \
31567 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31569 } while (0)
31572 qemu_fprintf(f,
31573 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31574 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31575 get_float_exception_flags(&env->active_fpu.fp_status));
31576 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31577 qemu_fprintf(f, "%3s: ", fregnames[i]);
31578 printfpr(&env->active_fpu.fpr[i]);
31581 #undef printfpr
31584 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31586 MIPSCPU *cpu = MIPS_CPU(cs);
31587 CPUMIPSState *env = &cpu->env;
31588 int i;
31590 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31591 " LO=0x" TARGET_FMT_lx " ds %04x "
31592 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31593 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31594 env->hflags, env->btarget, env->bcond);
31595 for (i = 0; i < 32; i++) {
31596 if ((i & 3) == 0) {
31597 qemu_fprintf(f, "GPR%02d:", i);
31599 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31600 regnames[i], env->active_tc.gpr[i]);
31601 if ((i & 3) == 3) {
31602 qemu_fprintf(f, "\n");
31606 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31607 TARGET_FMT_lx "\n",
31608 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31609 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31610 PRIx64 "\n",
31611 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31612 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31613 env->CP0_Config2, env->CP0_Config3);
31614 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31615 env->CP0_Config4, env->CP0_Config5);
31616 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31617 fpu_dump_state(env, f, flags);
31621 void mips_tcg_init(void)
31623 int i;
31625 cpu_gpr[0] = NULL;
31626 for (i = 1; i < 32; i++)
31627 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31628 offsetof(CPUMIPSState,
31629 active_tc.gpr[i]),
31630 regnames[i]);
31632 for (i = 0; i < 32; i++) {
31633 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31634 msa_wr_d[i * 2] =
31635 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31637 * The scalar floating-point unit (FPU) registers are mapped on
31638 * the MSA vector registers.
31640 fpu_f64[i] = msa_wr_d[i * 2];
31641 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31642 msa_wr_d[i * 2 + 1] =
31643 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31646 cpu_PC = tcg_global_mem_new(cpu_env,
31647 offsetof(CPUMIPSState, active_tc.PC), "PC");
31648 for (i = 0; i < MIPS_DSP_ACC; i++) {
31649 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31650 offsetof(CPUMIPSState, active_tc.HI[i]),
31651 regnames_HI[i]);
31652 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31653 offsetof(CPUMIPSState, active_tc.LO[i]),
31654 regnames_LO[i]);
31656 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31657 offsetof(CPUMIPSState,
31658 active_tc.DSPControl),
31659 "DSPControl");
31660 bcond = tcg_global_mem_new(cpu_env,
31661 offsetof(CPUMIPSState, bcond), "bcond");
31662 btarget = tcg_global_mem_new(cpu_env,
31663 offsetof(CPUMIPSState, btarget), "btarget");
31664 hflags = tcg_global_mem_new_i32(cpu_env,
31665 offsetof(CPUMIPSState, hflags), "hflags");
31667 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31668 offsetof(CPUMIPSState, active_fpu.fcr0),
31669 "fcr0");
31670 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31671 offsetof(CPUMIPSState, active_fpu.fcr31),
31672 "fcr31");
31673 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31674 "lladdr");
31675 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31676 "llval");
31678 #if defined(TARGET_MIPS64)
31679 cpu_mmr[0] = NULL;
31680 for (i = 1; i < 32; i++) {
31681 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31682 offsetof(CPUMIPSState,
31683 active_tc.mmr[i]),
31684 regnames[i]);
31686 #endif
31688 #if !defined(TARGET_MIPS64)
31689 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31690 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31691 offsetof(CPUMIPSState,
31692 active_tc.mxu_gpr[i]),
31693 mxuregnames[i]);
31696 mxu_CR = tcg_global_mem_new(cpu_env,
31697 offsetof(CPUMIPSState, active_tc.mxu_cr),
31698 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31699 #endif
31702 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31703 target_ulong *data)
31705 env->active_tc.PC = data[0];
31706 env->hflags &= ~MIPS_HFLAG_BMASK;
31707 env->hflags |= data[1];
31708 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31709 case MIPS_HFLAG_BR:
31710 break;
31711 case MIPS_HFLAG_BC:
31712 case MIPS_HFLAG_BL:
31713 case MIPS_HFLAG_B:
31714 env->btarget = data[2];
31715 break;